#!/usr/bin/python # Script to create enums from datasheet register tables # # Usage: # # First, create a text file from the datasheet: # pdftotext -layout /path/to/rockchip-3288-trm.pdf /tmp/asc # # Then use this script to output the #defines for a particular register: # ./tools/rkmux.py GRF_GPIO4C_IOMUX # # It will create output suitable for putting in a header file, with SHIFT and # MASK values for each bitfield in the register. # # Note: this tool is not perfect and you may need to edit the resulting code. # But it should speed up the process. import csv import re import sys tab_to_col = 3 class RegField: def __init__(self, cols=None): if cols: self.bits, self.attr, self.reset_val, self.desc = ( [x.strip() for x in cols]) self.desc = [self.desc] else: self.bits = '' self.attr = '' self.reset_val = '' self.desc = [] def Setup(self, cols): self.bits, self.attr, self.reset_val = cols[0:3] if len(cols) > 3: self.desc.append(cols[3]) def AddDesc(self, desc): self.desc.append(desc) def Show(self): print self print self.__init__() def __str__(self): return '%s,%s,%s,%s' % (self.bits, self.attr, self.reset_val, '\n'.join(self.desc)) class Printer: def __init__(self, name): self.first = True self.name = name self.re_sel = re.compile("[1-9]'b([01]+): (.*)") def __enter__(self): return self def __exit__(self, type, value, traceback): if not self.first: self.output_footer() def output_header(self): print '/* %s */' % self.name print 'enum {' def output_footer(self): print '};'; def output_regfield(self, regfield): lines = regfield.desc field = lines[0] #print 'field:', field if field in ['reserved', 'reserve', 'write_enable', 'write_mask']: return if field.endswith('_sel') or field.endswith('_con'): field = field[:-4] elif field.endswith(' iomux'): field = field[:-6] elif field.endswith('_mode') or field.endswith('_mask'): field = field[:-5] #else: #print 'bad field %s' % field #return field = field.upper() if ':' in regfield.bits: bit_high, bit_low = [int(x) for x in regfield.bits.split(':')] else: bit_high = bit_low = int(regfield.bits) bit_width = bit_high - bit_low + 1 mask = (1 << bit_width) - 1 if self.first: self.first = False self.output_header() else: print out_enum(field, 'shift', bit_low) out_enum(field, 'mask', mask) next_val = -1 #print 'lines: %s', lines for line in lines: m = self.re_sel.match(line) if m: val, enum = int(m.group(1), 2), m.group(2) if enum not in ['reserved', 'reserve']: out_enum(field, enum, val, val == next_val) next_val = val + 1 def process_file(name, fd): field = RegField() reg = '' fields = [] def add_it(field): if field.bits: if reg == name: fields.append(field) field = RegField() return field def is_field_start(line): if '=' in line or '+' in line: return False if (line.startswith('gpio') or line.startswith('peri_') or line.endswith('_sel') or line.endswith('_con')): return True if not ' ' in line: # and '_' in line: return True return False for line in fd: line = line.rstrip() if line[:4] in ['GRF_', 'PMU_', 'CRU_']: field = add_it(field) reg = line do_this = name == reg elif not line or not line.startswith(' '): continue line = line.replace('\xe2\x80\x99', "'") leading = len(line) - len(line.lstrip()) line = line.lstrip() cols = re.split(' *', line, 3) if leading > 15 or (len(cols) > 3 and is_field_start(cols[3])): if is_field_start(line): field = add_it(field) field.AddDesc(line) else: if cols[0] == 'Bit' or len(cols) < 3: continue #print #print field field = add_it(field) field.Setup(cols) field = add_it(field) with Printer(name) as printer: for field in fields: #print field printer.output_regfield(field) #print def out_enum(field, suffix, value, skip_val=False): str = '%s_%s' % (field.upper(), suffix.upper()) if not skip_val: tabs = tab_to_col - len(str) / 8 if value > 9: val_str = '%#x' % value else: val_str = '%d' % value str += '%s= %s' % ('\t' * tabs, val_str) print '\t%s,' % str # Process a CSV file, e.g. from tabula def process_csv(name, fd): reader = csv.reader(fd) rows = [] field = RegField() for row in reader: #print field.desc if not row[0]: field.desc.append(row[3]) continue if field.bits: if field.bits != 'Bit': rows.append(field) #print row field = RegField(row) with Printer(name) as printer: for row in rows: #print field printer.output_regfield(row) #print fname = sys.argv[1] name = sys.argv[2] # Read output from pdftotext -layout if 1: with open(fname, 'r') as fd: process_file(name, fd) # Use tabula # It seems to be better at outputting text for an entire cell in one cell. # But it does not always work. E.g. GRF_GPIO7CH_IOMUX. # So there is no point in using it. if 0: with open(fname, 'r') as fd: process_csv(name, fd)