Begin to rework player operation generation

This commit is contained in:
kris 2022-07-02 10:05:21 +01:00
parent 695ddb2c10
commit efb66e03d8
3 changed files with 580 additions and 726 deletions

View File

@ -5,6 +5,23 @@ from typing import Iterable, List, Tuple
import opcodes_6502
def audio_opcodes() -> Iterable[Tuple[opcodes_6502.Opcode]]:
# These two basic sequences let us chain together STA $C030 with any number
# >= 10 of intervening cycles (except 11). We don't need to explicitly
# include 6 or more cycles of NOP because those can be obtained by chaining
# together JMP (WDATA) to itself
#
# XXX support 11 cycles explicitly?
yield tuple(
[nop for nop in opcodes_6502.nops(4)] + [
opcodes_6502.STA_C030, opcodes_6502.JMP_WDATA])
yield tuple(
[nop for nop in opcodes_6502.nops(4)] + [
opcodes_6502.Opcode(3, 2, "STA zpdummy"),
opcodes_6502.STA_C030, opcodes_6502.JMP_WDATA])
def duty_cycle_range():
cycles = []
for i in range(4, 42):
@ -172,11 +189,9 @@ def _duty_cycles(duty_cycles):
for c in sorted(list(res.keys())):
pair = sorted(res[c], reverse=False)[0][1:]
cycles.append(pair)
print(c, pair)
# print(c, pair)
print(len(cycles))
return sorted(cycles, key=lambda p: p[0] + p[1])
return sorted(cycles)
EOF_DUTY_CYCLES = _duty_cycles(duty_cycle_range())
@ -315,25 +330,7 @@ def _make_end_of_frame_voltages2(cycles) -> numpy.ndarray:
return numpy.array(c, dtype=numpy.float32)
def audio_opcodes() -> Iterable[opcodes_6502.Opcode]:
# These two basic sequences let us chain together STA $C030 with any number
# >= 10 of intervening cycles (except 11). We don't need to explicitly
# include 6 or more cycles of NOP because those can be obtained by chaining
# together JMP (WDATA) to itself
#
# XXX support 11 cycles explicitly?
yield tuple(
[nop for nop in opcodes_6502.nops(4)] + [
opcodes_6502.STA_C030, opcodes_6502.JMP_WDATA])
yield tuple(
[nop for nop in opcodes_6502.nops(4)] + [
opcodes_6502.Opcode(3, 2, "STA zpdummy"),
opcodes_6502.STA_C030, opcodes_6502.JMP_WDATA])
def generate_player(
player_ops: Iterable[opcodes_6502.Opcode],
opcode_filename: str,
player_stage1_filename: str,
player_stage2_filename: str
@ -344,9 +341,12 @@ def generate_player(
unique_entrypoints = {}
toggles = {}
# Write out page 3 operations
with open(player_stage1_filename, "w+") as f:
for i, ops in enumerate(player_ops):
# Audio operations
for i, ops in enumerate(audio_opcodes()):
player_op = []
# Generate unique entrypoints
for j, op in enumerate(ops):
op_suffix_toggles = opcodes_6502.toggles(ops[j:])
if op_suffix_toggles not in seen_op_suffix_toggles:
@ -371,7 +371,9 @@ def generate_player(
num_bytes += player_op_len
f.write("\n")
# stage 1 EOF trampoline operations
duty_cycle_first = sorted(list(set(dc[0] for dc in EOF_DUTY_CYCLES)))
stage_1_offsets = {}
for eof_stage1_cycles in duty_cycle_first:
eof_stage1_ops = EOF_TRAMPOLINE_STAGE1[eof_stage1_cycles]
if not eof_stage1_ops:
@ -382,10 +384,12 @@ def generate_player(
f.write("\n")
num_bytes += opcodes_6502.total_bytes(eof_stage1_ops)
stage_1_offsets[eof_stage1_cycles] = num_bytes
f.write("; %d entrypoints, %d bytes\n" % (
len(unique_entrypoints), num_bytes))
# Write out stage 2 EOF trampoline operations
with open(player_stage2_filename, "w+") as f:
for eof_stage1_cycles in duty_cycle_first:
@ -404,9 +408,10 @@ def generate_player(
opcodes_6502.STA_C030, opcodes_6502.padding(b - 4)]
)
stage_3_ops = [
opcodes_6502.Literal("eof_stage_3_%d_%d:" % (a, b), indent=0)
] + list(opcodes_6502.interleave_opcodes(
stage_3_tick_ops, EOF_STAGE_3_BASE))
opcodes_6502.Literal(
"eof_stage_3_%d_%d:" % (a, b), indent=0)
] + list(opcodes_6502.interleave_opcodes(
stage_3_tick_ops, EOF_STAGE_3_BASE))
for op in stage_3_ops:
f.write("%s\n" % str(op))
f.write("\n")
@ -423,32 +428,56 @@ def generate_player(
# eof_trampoline_7_stage3_page:
# ; ...
with open(opcode_filename, "w") as f:
f.write("import enum\nimport numpy\n\n\n")
f.write("class Opcode(enum.Enum):\n")
f.write("""
import numpy
class PlayerOp:
def __init__(self, byte: int):
self.byte = byte
class PlayerOps:
""")
for o in unique_entrypoints.keys():
f.write(" TICK_%02x = 0x%02x\n" % (o, o))
f.write(" EXIT = 0x%02x\n" % num_bytes)
# f.write(" END_OF_FRAME = 0x%02x\n" % (num_bytes + 3))
for i, _ in enumerate(EOF_DUTY_CYCLES):
f.write(" TICK_%02x = PlayerOp(0x%02x)\n" % (o, o))
# XXX EXIT operation
# f.write(" EXIT = PlayerOp(0x%02x)\n" % num_bytes)
f.write("\n")
eof_stage1_names = []
for first in duty_cycle_first:
eof_stage1_name = "END_OF_FRAME_%d_STAGE1" % first
eof_stage1_names.append(eof_stage1_name)
f.write(
" END_OF_FRAME_%d = 0x%02x\n" % (i, num_bytes + 4 + i))
f.write("\n\nVOLTAGE_SCHEDULE = {\n")
for o, v in unique_entrypoints.items():
" %s = PlayerOp(0x%02x)\n" % (
eof_stage1_name, stage_1_offsets[first]))
f.write("\n")
eof_stage2_names = []
for first, second in EOF_DUTY_CYCLES:
eof_stage2_name = "END_OF_FRAME_%d_%d_STAGE2_3" % (first, second)
eof_stage2_names.append(eof_stage2_name)
f.write(
" Opcode.TICK_%02x: numpy.array(%s, dtype=numpy.float32),"
"\n" % (o, v))
for i, skip_cycles in enumerate(EOF_DUTY_CYCLES):
f.write(" Opcode.END_OF_FRAME_%d: numpy.array([%s], "
"dtype=numpy.float32), # %s\n" % (i, ", ".join(
str(f) for f in _make_end_of_frame_voltages2(
skip_cycles)), skip_cycles))
f.write("}\n")
#
" %s = PlayerOp(0x%02x)\n" % (eof_stage2_name,
EOF_TRAMPOLINE_STAGE3_PAGE_OFFSETS[
first, second][1]))
f.write("\n")
# f.write("\n\nVOLTAGE_SCHEDULE = {\n")
# for o, v in unique_entrypoints.items():
# f.write(
# " Opcode.TICK_%02x: numpy.array(%s, dtype=numpy.float32),"
# "\n" % (o, v))
# for i, skip_cycles in enumerate(EOF_DUTY_CYCLES):
# f.write(" Opcode.END_OF_FRAME_%d: numpy.array([%s], "
# "dtype=numpy.float32), # %s\n" % (i, ", ".join(
# str(f) for f in _make_end_of_frame_voltages2(
# skip_cycles)), skip_cycles))
# f.write("}\n")
# f.write("\n\nTOGGLES = {\n")
# for o, v in toggles.items():
# f.write(
@ -456,16 +485,19 @@ def generate_player(
# )
# f.write("}\n")
#
f.write("\n\nEOF_OPCODES = (\n")
for i in range(len(EOF_DUTY_CYCLES)):
f.write(" Opcode.END_OF_FRAME_%d,\n" % i)
f.write("\nEOF_STAGE_1_OPS = (\n")
for n in eof_stage1_names:
f.write(" PlayerOps.%s,\n" % n)
f.write(")\n")
f.write("\n\nEOF_STAGE_2_3_OPS = (\n")
for n in eof_stage2_names:
f.write(" PlayerOps.%s,\n" % n)
f.write(")\n")
def main():
player_ops = audio_opcodes()
generate_player(
player_ops,
opcode_filename="opcodes_generated.py",
player_stage1_filename="player/player_generated.s",
player_stage2_filename="player/player_stage2_generated.s"

View File

@ -4,6 +4,8 @@ import opcodes_generated
import numpy
from typing import Dict, List, Tuple, Iterable
#
# def _make_end_of_frame_voltages(bits) -> numpy.ndarray:
# """Voltage sequence for end-of-frame TCP processing."""
@ -23,6 +25,8 @@ from typing import Dict, List, Tuple, Iterable
Opcode = opcodes_generated.Opcode
# TOGGLES = opcodes_generated.TOGGLES
_VOLTAGE_SCHEDULE = opcodes_generated.VOLTAGE_SCHEDULE
# _VOLTAGE_SCHEDULE[Opcode.END_OF_FRAME], TOGGLES[Opcode.END_OF_FRAME] = (
# _make_end_of_frame_voltages())

File diff suppressed because it is too large Load Diff