import sys from generate import renderer import string with open(sys.argv[1], 'r') as f: buf = f.read() def split_line(line): register_name = line[0:21] addr = line[21:44] bits = line[44:53] description = line[53:] return ( register_name.strip(), addr.strip(), bits.strip(), description.strip() ) def parse_addr(addr): base10, base16 = addr.split() base16 = base16.removeprefix('(').removesuffix(')') assert int(base10, 10) == int(base16, 16) return int(base16, 16) def parse_bits(bits): high, low = bits.split(":") return int(high, 10), int(low, 10) def parse_lines(buf): it = map(split_line, buf.strip().split('\n')) header = next(it) assert header == ('Register Name', 'Addr', 'Bits', 'Description') for register_name, addr, bits, description in it: if register_name.lower() == "reserved": continue addr = parse_addr(addr) bits = parse_bits(bits) yield register_name, addr, bits, description def bits_length(bits): high, low = bits assert (high + 1) % 8 == 0 and low == 0 length = (high + 1) // 8 return length def reg_type(length): if length == 1: return "reg8" if length == 2: return "reg16" if length == 3: return "reg8" if length == 4: return "reg32" assert False, length def format_name(s): def do(): prev_lower = False for i, c in enumerate(s): if prev_lower and i > 0 and c in string.ascii_uppercase: yield "_" prev_lower = c in string.ascii_lowercase yield c.upper() return "".join(do()) def render_struct(buf): next_address = 0 reserved_ix = 0 yield "struct voodoo2_config {" lines = list(parse_lines(buf)) for register_name, addr, bits, description in lines: if addr != next_address: yield f"reg8 _reserved{reserved_ix}[{addr - next_address}];" reserved_ix += 1 length = bits_length(bits) arr = "" if length != 3 else "[3]" yield f"{reg_type(length)} {format_name(register_name)}{arr};" next_address = addr + length yield "};" yield "" for register_name, addr, bits, description in lines: length = bits_length(bits) arr = "" if length != 3 else "[0]" yield f"static_assert((offsetof (struct voodoo2_config, {format_name(register_name)}{arr})) == 0x{addr:02x});" def render_macros(buf): lines = list(parse_lines(buf)) for register_name, addr, bits, description in lines: yield f"#define PCI__CONFIG__{format_name(register_name)} (0x{addr:02x})" def render_all(buf): yield "#pragma once" yield "" yield "#include " yield "#include " yield "" yield '#include "reg.h"' yield "" yield from render_macros(buf) yield "" yield "typedef struct voodoo2_config voodoo2_config;" with open(sys.argv[1], 'r') as f: buf = f.read() lines = buf.split('\n') render, out = renderer() render(render_all(buf)) sys.stdout.write(out.getvalue())