voodoo/gen/render_voodoo2_csv.py

128 lines
3.2 KiB
Python

import csv
import sys
from dataclasses import dataclass
from generate import renderer
import re
@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 is_function_bit(d):
infer_by_name = re.match("^.*_[0-9]$", d.bit_name) and "gpio_" not in d.bit_name.lower()
return bit_mask(d) != 1 or infer_by_name
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 is_function_bit(d):
return f"(((n) & {hex(bit_mask(d))}) << {d.bits[1]})"
else:
return f"(1 << {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 is_function_bit(d):
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())