voodoo/gen/voodoo2_config.py

113 lines
3.1 KiB
Python

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 <stddef.h>"
yield "#include <stdint.h>"
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())