mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-26 17:48:26 +00:00 
			
		
		
		
	Convert this tool to Python 3 and make it use that, to meet the 2020 deadline. Signed-off-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			219 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| # 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)
 |