import csv import sys from dataclasses import dataclass from generate import renderer @dataclass class RegisterBitDef: name: str bits: tuple[int, int] bit_prefix: str bit_name: str enum_name: str enum_value: str description: str def parse_bit(s): if ':' in s: a, b = s.split(':') return int(a, 10), int(b, 10) else: return int(s, 10), int(s, 10) last_def = None def parse_value(s): if not s: return None elif s.startswith("0x"): return int(s.removeprefix("0x"), 16) else: return int(s.removeprefix("0x"), 10) def parse_csv_row(row): global last_def name, bits, bit_prefix, bit_name, enum_name, enum_value, description = row if not name: assert last_def is not None assert not bits assert not bit_prefix assert not bit_name assert enum_name assert enum_value != '' assert not description assert last_def.enum_name assert last_def.enum_value is not None name = last_def.name bits = last_def.bits bit_prefix = last_def.bit_prefix bit_name = last_def.bit_name description = last_def.description else: bits = parse_bit(bits) assert name, name assert bit_name, bit_name if enum_name: assert enum_value, (enum_name, enum_value) assert description, description bit_def = RegisterBitDef( name, bits, bit_prefix or None, bit_name, enum_name or None, parse_value(enum_value), description ) last_def = bit_def return bit_def def filter_row(row): if row == ['', '', '', '', '', '', '']: return False name, bits, bit_prefix, bit_name, enum_name, enum_value, description = row return description != 'reserved' and (bit_name or enum_name) def bit_mask(d): high, low = d.bits return (1 << ((high - low) + 1)) - 1 def format_value(d): if d.enum_name is not None: assert d.enum_value is not None assert d.enum_value <= bit_mask(d) return f"({d.enum_value} << {d.bits[1]})" elif bit_mask(d) == 1: return f"(1 << {d.bits[1]})" else: return f"(((n) & {hex(bit_mask(d))}) << {d.bits[1]})" def format_macro(d): macro = f"{d.name.upper()}" if d.bit_prefix is not None: macro += f"__{d.bit_prefix.upper()}" macro += f"__{d.bit_name.upper()}" if d.enum_name is not None: macro += f"__{d.enum_name.upper()}" elif bit_mask(d) != 1: macro += "(n)" return macro def format_def(d): return f"#define {format_macro(d)} {format_value(d)}" def render_defs(defs): last_name = None for d in defs: if last_name is not None and d.name != last_name: yield "" yield format_def(d) last_name = d.name with open(sys.argv[1], 'r') as f: reader = csv.reader(f) defs = list(map(parse_csv_row, filter(filter_row, reader))) render, out = renderer() render(render_defs(defs)) sys.stdout.write(out.getvalue())