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