pico-pio-adc/etc/regmap.py

149 lines
3.4 KiB
Python

from dataclasses import dataclass
from fnmatch import fnmatch
from sys import argv
from lxml.etree import XML
# List of <peri>.<register> 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("};")