rkmux.py 6.0 KB

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