from dataclasses import dataclass from fnmatch import fnmatch from sys import argv from lxml.etree import XML # List of . patterns to mark as unsafe. UNSAFE: list[str] = [ "SIO.SPINLOCK[0-9]*", "ADC.FIFO", "SSI.*CR", "SIO.DIV_QUOTIENT", "SIO.DIV_REMAINDER", "SIO.FIFO_RD", "M0PLUS.SYST_CSR", "I2C*.IC_CLR*", "TIMER.TIME[HL]R", "PIO*.RXF*", "PPB.*", "XIP.*", ] def is_unsafe(peri: str, reg: str) -> bool: for pattern in UNSAFE: if fnmatch(f"{peri}.{reg}", pattern): return True return False with open(argv[1], "rb") as fp: xml = XML(fp.read()) @dataclass class Register: name: str offset: int reset: int read: bool write: bool @dataclass class Peripheral: name: str base: int regs: list[Register] peripherals: dict[str, Peripheral] = {} for peri in xml.cssselect("peripheral"): if "derivedFrom" in peri.attrib: orig = peripherals[peri.attrib["derivedFrom"]] names = peri.cssselect("peripheral > name") assert len(names) == 1 peripheral = Peripheral(name=names[0].text, base=orig.base, regs=orig.regs) continue names = peri.cssselect("peripheral > name") assert len(names) == 1 bases = peri.cssselect("peripheral > baseAddress") assert len(bases) == 1 base = int(bases[0].text, 16) peripheral = Peripheral(name=names[0].text, base=base, regs=[]) for reg in peri.cssselect("peripheral > registers > register"): names = reg.cssselect("register > name") assert len(names) == 1 offsets = reg.cssselect("register > addressOffset") assert len(offsets) == 1 resets = reg.cssselect("register > resetValue") assert len(resets) == 1 accesses = reg.cssselect("access") assert len(accesses) > 0 write = read = False for access in accesses: match access.text: case "read-only": read = True case "read-write": write = read = True case "write-only": write = True case mode: assert False, f"unknown access mode {mode!r}" offset = int(offsets[0].text, 16) reset = int(resets[0].text, 16) register = Register( name=names[0].text, offset=offset, reset=reset, write=write, read=read, ) peripheral.regs.append(register) peripherals[peripheral.name] = peripheral print( """ #include "regmap.h" struct reg_info regmap[] = { """.strip() ) for peripheral in peripherals.values(): for register in peripheral.regs: print("{ ", end="") print(f"{hex(peripheral.base + register.offset)}, ", end="") print(f"{hex(register.reset)}, ", end="") print(f"{hex(register.reset)}, ", end="") print(f'"{peripheral.name}", ', end="") print(f'"{register.name}", ', end="") if register.read: print("1, ", end="") else: print("0, ", end="") if register.write: print("1, ", end="") else: print("0, ", end="") if is_unsafe(peripheral.name, register.name): print("1", end="") else: print("0", end="") print(" },") print("{ 0, 0, 0, NULL, NULL, 0, 0, 0 },") print("};")