from collections import defaultdict from dataclasses import dataclass import sys from csv_input import read_input from sh7091 import size_to_type from sh7091 import headers from generate import renderer @dataclass class Register: address: int name: str size: int rw: set[str] def group_by_address(rows): _rw = defaultdict(set) _size = dict() _groups = defaultdict(list) def process_row(row): address = int(row["address"], 16) name = row["name"] size = int(row["size"], 10) rw = set(row["r/w"].upper()) if address not in _size: _size[address] = size assert _size[address] == size, row assert _rw[address].intersection(rw) == set(), row _groups[address].append(Register( address=address, name=name, size=size, rw=rw )) _ = list(map(process_row, rows)) return list(sorted(_groups.items(), key=lambda kv: kv[0])) def render_groups(groups): next_address = 0 reserved_num = 0 yield "struct gdrom_if_reg {" for address, group in groups: assert address >= next_address if address > next_address: padding = address - next_address type = size_to_type(1) yield f"const {type} _pad{reserved_num}[{padding}];" reserved_num += 1 if len(group) > 1: yield "union {" for reg in group: type = size_to_type(reg.size) const = "const " if reg.rw == {'R'} else "" yield f"{const}{type} {reg.name};" if len(group) > 1: yield "};" # end of union next_address = address + group[0].size yield "};" for address, group in groups: for reg in group: yield f"static_assert((offsetof (struct gdrom_if_reg, {reg.name})) == {reg.address});" yield "" yield 'extern struct gdrom_if_reg gdrom_if __asm("gdrom_if");' if __name__ == "__main__": input_file = sys.argv[1] rows = read_input(input_file) groups = group_by_address(rows) render, out = renderer() render(headers()) render(render_groups(groups)) sys.stdout.write(out.getvalue())