From 0aac1f134c8cba997a39d9402fc3fcd8137b894b Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 21 May 2025 04:05:25 -0500 Subject: [PATCH] regs: add register_python --- regs/register_gen.py | 28 ++++++++++++------- regs/register_python.py | 59 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 regs/register_python.py diff --git a/regs/register_gen.py b/regs/register_gen.py index bdc327e..8bd1c24 100644 --- a/regs/register_gen.py +++ b/regs/register_gen.py @@ -1,20 +1,28 @@ from csv_input import read_input from generate import renderer from register import parse_row, group_by_block -from register_java import generate_classes +import register_java +import register_python import sys +generators = { + "java": register_java.generate_classes, + "python": register_python.generate_decoder, +} + if __name__ == "__main__": rows = read_input(sys.argv[1]) - block_name = sys.argv[2] - package_name = sys.argv[3] - class_name = sys.argv[4] - base_address = int(sys.argv[5], 16) + generator_type = sys.argv[2] + block_name = sys.argv[3] + package_name = sys.argv[4] + class_name = sys.argv[5] + base_address = int(sys.argv[6], 16) + generator = generators[generator_type] blocks = group_by_block(map(parse_row, rows)) render, out = renderer(indent_length=4) - render(generate_classes(block_name, - package_name, - class_name, - base_address, - blocks)) + render(generator(block_name, + package_name, + class_name, + base_address, + blocks)) sys.stdout.write(out.getvalue()) diff --git a/regs/register_python.py b/regs/register_python.py new file mode 100644 index 0000000..ad9b347 --- /dev/null +++ b/regs/register_python.py @@ -0,0 +1,59 @@ +def generate_dataclass(block_name, registers): + yield "@dataclass" + yield f"class {block_name.capitalize()}:" + for register in registers: + if register.size == 4: + yield f" {register.name}: int" + elif register.size > 4: + yield f" {register.name}: list[int]" + else: + assert False, register.size + yield "" + yield " def __init__(self):" + yield " pass" + yield "" + yield " def __repr__(self):" + yield ' return (f"{self.__class__.__qualname__}(" +' + yield ' ",\\n ".join([' + for register in registers: + if register.size == 4: + yield f' f"{register.name}={{self.{register.name}:08x}}",' + elif register.size > 4: + #yield f' (f"{register.name}=" + ",\\n".join([' + #yield f' f"{{i:08x}}" for i in self.{register.name}' + #yield " ]))," + pass + else: + assert False, register.size + yield ' ]) +' + yield ' ")")' + yield "" + +def generate_struct_decoder(block_name, registers): + yield f"def decode_{block_name.lower()}(buf: bytes) -> {block_name.capitalize()}:" + yield " mem = memoryview(buf)" + yield f" {block_name.lower()} = {block_name.capitalize()}()" + for register in registers: + lhs = f"{block_name.lower()}.{register.name}" + mem = f"{hex(register.address)}:{hex(register.address + register.size)}" + if register.size == 4: + yield f" {lhs}, = struct.unpack(' 4: + assert register.size % 4 == 0, register.size + length = register.size // 4 + fmt = f"('I' * {length})" + yield f" {lhs} = struct.unpack('<' + {fmt}, mem[{mem}])" + else: + assert False, register.size + yield f" return {block_name.lower()}" + yield "" + +def generate_decoder(block_name, package_name, class_name, base_address, blocks): + yield "from dataclasses import dataclass" + yield "import struct" + yield "" + for block, registers, in blocks: + if block.lower() != block_name.lower(): + continue + yield from generate_dataclass(block_name, registers) + yield from generate_struct_decoder(block_name, registers)