regs-parser/main.py

99 lines
3.1 KiB
Python

from typing import Optional, Dict
import re
import sys
def parse_table_entries(fields, pattern, lines):
"""Parse aligned table entries"""
prev: Optional[Dict] = None
entries = []
def flush():
nonlocal prev
if prev is not None:
entries.append(prev['data'])
prev = None
for line in lines:
if len(line.strip()) == 0:
flush()
continue
match = pattern.search(line.strip())
if match is not None:
flush()
starts = [match.span(v)[0] for v in fields] + [len(line)]
prev = {
'data': {v: match.group(v) for v in fields},
'starts': starts
}
elif prev is not None:
for i, field in enumerate(fields):
v = line[prev['starts'][i]:prev['starts'][i + 1]].strip()
if len(v) == 0:
continue
if prev['data'][field][-1] not in ['-', '_']:
v = ' ' + v
prev['data'][field] += v
flush()
return entries
def parse_registers(lines):
"""Parse register entry from `pdftotext -layout output` from TRM table"""
fields = ['id', 'address', 'size', 'type', 'reset_value', 'description']
ENTRY_PATTERN = re.compile(r'^'
r'(?P<id>\w+)\s+'
r'(?P<address>0x[0-9A-F]+)\s+'
r'(?P<size>\d+)\s+'
r'(?P<type>\w+)\s+'
r'(?P<reset_value>0x[0-9A-F]+)\s+'
r'(?P<description>.+)$')
return parse_table_entries(fields, ENTRY_PATTERN, lines)
def emit_rust(base_addr, ending_addr, registers):
current_addr = base_addr
reserved_id = 0
code = []
for reg in registers:
addr = int(reg['address'], 16)
if addr > ending_addr:
break
if addr < base_addr:
continue
padding = addr - current_addr
if padding > 0:
if padding % 4 == 0:
code.append(f'unused{reserved_id}: [RO<u32>; {padding // 4}],')
else:
code.append(f'unused{reserved_id}: [RO<u8>; {padding}],')
reserved_id += 1
access = ''
unknown = False
if reg['type'] == 'ro':
access = 'RO'
elif reg['type'] == 'wo':
access = 'WO'
elif reg['type'] in ['rw', 'mixed']:
access = 'RW'
else:
access = reg['type']
unknown = True
size = int(reg['size'])
if size not in [8, 16, 32]:
unknown = True
current_addr += padding + size // 8
line = f"pub {reg['id'].lower()}: {access}<u{size}>,"
if unknown:
line = '// FIXME: ' + line
code.append(f"/// {reg['description']}")
code.append(line)
return code
if len(sys.argv) != 3:
print("Pipe pdftotext to stdin, and give starting and ending address"
"(inclusive) for the registers")
exit()
for line in emit_rust(int(sys.argv[1], 0), int(sys.argv[2], 0), parse_registers(sys.stdin)):
print(line)