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\w+)\s+' r'(?P
0x[0-9A-F]+)\s+' r'(?P\d+)\s+' r'(?P\w+)\s+' r'(?P0x[0-9A-F]+)\s+' r'(?P.+)$') 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; {padding // 4}],') else: code.append(f'unused{reserved_id}: [RO; {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}," 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)