1*4882a593Smuzhiyun#!/usr/bin/env python2 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun# Script to create enums from datasheet register tables 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# Usage: 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# First, create a text file from the datasheet: 8*4882a593Smuzhiyun# pdftotext -layout /path/to/rockchip-3288-trm.pdf /tmp/asc 9*4882a593Smuzhiyun# 10*4882a593Smuzhiyun# Then use this script to output the #defines for a particular register: 11*4882a593Smuzhiyun# ./tools/rkmux.py GRF_GPIO4C_IOMUX 12*4882a593Smuzhiyun# 13*4882a593Smuzhiyun# It will create output suitable for putting in a header file, with SHIFT and 14*4882a593Smuzhiyun# MASK values for each bitfield in the register. 15*4882a593Smuzhiyun# 16*4882a593Smuzhiyun# Note: this tool is not perfect and you may need to edit the resulting code. 17*4882a593Smuzhiyun# But it should speed up the process. 18*4882a593Smuzhiyun 19*4882a593Smuzhiyunimport csv 20*4882a593Smuzhiyunimport re 21*4882a593Smuzhiyunimport sys 22*4882a593Smuzhiyun 23*4882a593Smuzhiyuntab_to_col = 3 24*4882a593Smuzhiyun 25*4882a593Smuzhiyunclass RegField: 26*4882a593Smuzhiyun def __init__(self, cols=None): 27*4882a593Smuzhiyun if cols: 28*4882a593Smuzhiyun self.bits, self.attr, self.reset_val, self.desc = ( 29*4882a593Smuzhiyun [x.strip() for x in cols]) 30*4882a593Smuzhiyun self.desc = [self.desc] 31*4882a593Smuzhiyun else: 32*4882a593Smuzhiyun self.bits = '' 33*4882a593Smuzhiyun self.attr = '' 34*4882a593Smuzhiyun self.reset_val = '' 35*4882a593Smuzhiyun self.desc = [] 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun def Setup(self, cols): 38*4882a593Smuzhiyun self.bits, self.attr, self.reset_val = cols[0:3] 39*4882a593Smuzhiyun if len(cols) > 3: 40*4882a593Smuzhiyun self.desc.append(cols[3]) 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun def AddDesc(self, desc): 43*4882a593Smuzhiyun self.desc.append(desc) 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun def Show(self): 46*4882a593Smuzhiyun print self 47*4882a593Smuzhiyun print 48*4882a593Smuzhiyun self.__init__() 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun def __str__(self): 51*4882a593Smuzhiyun return '%s,%s,%s,%s' % (self.bits, self.attr, self.reset_val, 52*4882a593Smuzhiyun '\n'.join(self.desc)) 53*4882a593Smuzhiyun 54*4882a593Smuzhiyunclass Printer: 55*4882a593Smuzhiyun def __init__(self, name): 56*4882a593Smuzhiyun self.first = True 57*4882a593Smuzhiyun self.name = name 58*4882a593Smuzhiyun self.re_sel = re.compile("[1-9]'b([01]+): (.*)") 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun def __enter__(self): 61*4882a593Smuzhiyun return self 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun def __exit__(self, type, value, traceback): 64*4882a593Smuzhiyun if not self.first: 65*4882a593Smuzhiyun self.output_footer() 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun def output_header(self): 68*4882a593Smuzhiyun print '/* %s */' % self.name 69*4882a593Smuzhiyun print 'enum {' 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun def output_footer(self): 72*4882a593Smuzhiyun print '};'; 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun def output_regfield(self, regfield): 75*4882a593Smuzhiyun lines = regfield.desc 76*4882a593Smuzhiyun field = lines[0] 77*4882a593Smuzhiyun #print 'field:', field 78*4882a593Smuzhiyun if field in ['reserved', 'reserve', 'write_enable', 'write_mask']: 79*4882a593Smuzhiyun return 80*4882a593Smuzhiyun if field.endswith('_sel') or field.endswith('_con'): 81*4882a593Smuzhiyun field = field[:-4] 82*4882a593Smuzhiyun elif field.endswith(' iomux'): 83*4882a593Smuzhiyun field = field[:-6] 84*4882a593Smuzhiyun elif field.endswith('_mode') or field.endswith('_mask'): 85*4882a593Smuzhiyun field = field[:-5] 86*4882a593Smuzhiyun #else: 87*4882a593Smuzhiyun #print 'bad field %s' % field 88*4882a593Smuzhiyun #return 89*4882a593Smuzhiyun field = field.upper() 90*4882a593Smuzhiyun if ':' in regfield.bits: 91*4882a593Smuzhiyun bit_high, bit_low = [int(x) for x in regfield.bits.split(':')] 92*4882a593Smuzhiyun else: 93*4882a593Smuzhiyun bit_high = bit_low = int(regfield.bits) 94*4882a593Smuzhiyun bit_width = bit_high - bit_low + 1 95*4882a593Smuzhiyun mask = (1 << bit_width) - 1 96*4882a593Smuzhiyun if self.first: 97*4882a593Smuzhiyun self.first = False 98*4882a593Smuzhiyun self.output_header() 99*4882a593Smuzhiyun else: 100*4882a593Smuzhiyun print 101*4882a593Smuzhiyun out_enum(field, 'shift', bit_low) 102*4882a593Smuzhiyun out_enum(field, 'mask', mask) 103*4882a593Smuzhiyun next_val = -1 104*4882a593Smuzhiyun #print 'lines: %s', lines 105*4882a593Smuzhiyun for line in lines: 106*4882a593Smuzhiyun m = self.re_sel.match(line) 107*4882a593Smuzhiyun if m: 108*4882a593Smuzhiyun val, enum = int(m.group(1), 2), m.group(2) 109*4882a593Smuzhiyun if enum not in ['reserved', 'reserve']: 110*4882a593Smuzhiyun out_enum(field, enum, val, val == next_val) 111*4882a593Smuzhiyun next_val = val + 1 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun 114*4882a593Smuzhiyundef process_file(name, fd): 115*4882a593Smuzhiyun field = RegField() 116*4882a593Smuzhiyun reg = '' 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun fields = [] 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun def add_it(field): 121*4882a593Smuzhiyun if field.bits: 122*4882a593Smuzhiyun if reg == name: 123*4882a593Smuzhiyun fields.append(field) 124*4882a593Smuzhiyun field = RegField() 125*4882a593Smuzhiyun return field 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun def is_field_start(line): 128*4882a593Smuzhiyun if '=' in line or '+' in line: 129*4882a593Smuzhiyun return False 130*4882a593Smuzhiyun if (line.startswith('gpio') or line.startswith('peri_') or 131*4882a593Smuzhiyun line.endswith('_sel') or line.endswith('_con')): 132*4882a593Smuzhiyun return True 133*4882a593Smuzhiyun if not ' ' in line: # and '_' in line: 134*4882a593Smuzhiyun return True 135*4882a593Smuzhiyun return False 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun for line in fd: 138*4882a593Smuzhiyun line = line.rstrip() 139*4882a593Smuzhiyun if line[:4] in ['GRF_', 'PMU_', 'CRU_']: 140*4882a593Smuzhiyun field = add_it(field) 141*4882a593Smuzhiyun reg = line 142*4882a593Smuzhiyun do_this = name == reg 143*4882a593Smuzhiyun elif not line or not line.startswith(' '): 144*4882a593Smuzhiyun continue 145*4882a593Smuzhiyun line = line.replace('\xe2\x80\x99', "'") 146*4882a593Smuzhiyun leading = len(line) - len(line.lstrip()) 147*4882a593Smuzhiyun line = line.lstrip() 148*4882a593Smuzhiyun cols = re.split(' *', line, 3) 149*4882a593Smuzhiyun if leading > 15 or (len(cols) > 3 and is_field_start(cols[3])): 150*4882a593Smuzhiyun if is_field_start(line): 151*4882a593Smuzhiyun field = add_it(field) 152*4882a593Smuzhiyun field.AddDesc(line) 153*4882a593Smuzhiyun else: 154*4882a593Smuzhiyun if cols[0] == 'Bit' or len(cols) < 3: 155*4882a593Smuzhiyun continue 156*4882a593Smuzhiyun #print 157*4882a593Smuzhiyun #print field 158*4882a593Smuzhiyun field = add_it(field) 159*4882a593Smuzhiyun field.Setup(cols) 160*4882a593Smuzhiyun field = add_it(field) 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun with Printer(name) as printer: 163*4882a593Smuzhiyun for field in fields: 164*4882a593Smuzhiyun #print field 165*4882a593Smuzhiyun printer.output_regfield(field) 166*4882a593Smuzhiyun #print 167*4882a593Smuzhiyun 168*4882a593Smuzhiyundef out_enum(field, suffix, value, skip_val=False): 169*4882a593Smuzhiyun str = '%s_%s' % (field.upper(), suffix.upper()) 170*4882a593Smuzhiyun if not skip_val: 171*4882a593Smuzhiyun tabs = tab_to_col - len(str) / 8 172*4882a593Smuzhiyun if value > 9: 173*4882a593Smuzhiyun val_str = '%#x' % value 174*4882a593Smuzhiyun else: 175*4882a593Smuzhiyun val_str = '%d' % value 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun str += '%s= %s' % ('\t' * tabs, val_str) 178*4882a593Smuzhiyun print '\t%s,' % str 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun# Process a CSV file, e.g. from tabula 181*4882a593Smuzhiyundef process_csv(name, fd): 182*4882a593Smuzhiyun reader = csv.reader(fd) 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun rows = [] 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun field = RegField() 187*4882a593Smuzhiyun for row in reader: 188*4882a593Smuzhiyun #print field.desc 189*4882a593Smuzhiyun if not row[0]: 190*4882a593Smuzhiyun field.desc.append(row[3]) 191*4882a593Smuzhiyun continue 192*4882a593Smuzhiyun if field.bits: 193*4882a593Smuzhiyun if field.bits != 'Bit': 194*4882a593Smuzhiyun rows.append(field) 195*4882a593Smuzhiyun #print row 196*4882a593Smuzhiyun field = RegField(row) 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun with Printer(name) as printer: 199*4882a593Smuzhiyun for row in rows: 200*4882a593Smuzhiyun #print field 201*4882a593Smuzhiyun printer.output_regfield(row) 202*4882a593Smuzhiyun #print 203*4882a593Smuzhiyun 204*4882a593Smuzhiyunfname = sys.argv[1] 205*4882a593Smuzhiyunname = sys.argv[2] 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun# Read output from pdftotext -layout 208*4882a593Smuzhiyunif 1: 209*4882a593Smuzhiyun with open(fname, 'r') as fd: 210*4882a593Smuzhiyun process_file(name, fd) 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun# Use tabula 213*4882a593Smuzhiyun# It seems to be better at outputting text for an entire cell in one cell. 214*4882a593Smuzhiyun# But it does not always work. E.g. GRF_GPIO7CH_IOMUX. 215*4882a593Smuzhiyun# So there is no point in using it. 216*4882a593Smuzhiyunif 0: 217*4882a593Smuzhiyun with open(fname, 'r') as fd: 218*4882a593Smuzhiyun process_csv(name, fd) 219