1from __future__ import print_function 2 3CopyRight = ''' 4/* 5 * Copyright 2015 Advanced Micro Devices, Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * on the rights to use, copy, modify, merge, publish, distribute, sub 11 * license, and/or sell copies of the Software, and to permit persons to whom 12 * the Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the next 15 * paragraph) shall be included in all copies or substantial portions of the 16 * Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 * USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 */ 27''' 28 29import sys 30import re 31 32 33class StringTable: 34 """ 35 A class for collecting multiple strings in a single larger string that is 36 used by indexing (to avoid relocations in the resulting binary) 37 """ 38 def __init__(self): 39 self.table = [] 40 self.length = 0 41 42 def add(self, string): 43 # We might get lucky with string being a suffix of a previously added string 44 for te in self.table: 45 if te[0].endswith(string): 46 idx = te[1] + len(te[0]) - len(string) 47 te[2].add(idx) 48 return idx 49 50 idx = self.length 51 self.table.append((string, idx, set((idx,)))) 52 self.length += len(string) + 1 53 54 return idx 55 56 def emit(self, filp, name, static=True): 57 """ 58 Write 59 [static] const char name[] = "..."; 60 to filp. 61 """ 62 fragments = [ 63 '"%s\\0" /* %s */' % ( 64 te[0].encode('unicode_escape').decode(), 65 ', '.join(str(idx) for idx in te[2]) 66 ) 67 for te in self.table 68 ] 69 filp.write('%sconst char %s[] =\n%s;\n' % ( 70 'static ' if static else '', 71 name, 72 '\n'.join('\t' + fragment for fragment in fragments) 73 )) 74 75class IntTable: 76 """ 77 A class for collecting multiple arrays of integers in a single big array 78 that is used by indexing (to avoid relocations in the resulting binary) 79 """ 80 def __init__(self, typename): 81 self.typename = typename 82 self.table = [] 83 self.idxs = set() 84 85 def add(self, array): 86 # We might get lucky and find the array somewhere in the existing data 87 try: 88 idx = 0 89 while True: 90 idx = self.table.index(array[0], idx, len(self.table) - len(array) + 1) 91 92 for i in range(1, len(array)): 93 if array[i] != self.table[idx + i]: 94 break 95 else: 96 self.idxs.add(idx) 97 return idx 98 99 idx += 1 100 except ValueError: 101 pass 102 103 idx = len(self.table) 104 self.table += array 105 self.idxs.add(idx) 106 return idx 107 108 def emit(self, filp, name, static=True): 109 """ 110 Write 111 [static] const typename name[] = { ... }; 112 to filp. 113 """ 114 idxs = sorted(self.idxs) + [len(self.table)] 115 116 fragments = [ 117 ('\t/* %s */ %s' % ( 118 idxs[i], 119 ' '.join((str(elt) + ',') for elt in self.table[idxs[i]:idxs[i+1]]) 120 )) 121 for i in range(len(idxs) - 1) 122 ] 123 124 filp.write('%sconst %s %s[] = {\n%s\n};\n' % ( 125 'static ' if static else '', 126 self.typename, name, 127 '\n'.join(fragments) 128 )) 129 130class Field: 131 def __init__(self, reg, s_name): 132 self.s_name = s_name 133 self.name = strip_prefix(s_name) 134 self.values = [] 135 self.varname_values = '%s__%s__values' % (reg.r_name.lower(), self.name.lower()) 136 137class Reg: 138 def __init__(self, r_name): 139 self.r_name = r_name 140 self.name = strip_prefix(r_name) 141 self.fields = [] 142 self.own_fields = True 143 144 145def strip_prefix(s): 146 '''Strip prefix in the form ._.*_, e.g. R_001234_''' 147 return s[s[2:].find('_')+3:] 148 149def parse(filename, regs, packets): 150 stream = open(filename) 151 152 for line in stream: 153 if not line.startswith('#define '): 154 continue 155 156 line = line[8:].strip() 157 158 if line.startswith('R_'): 159 name = line.split()[0] 160 161 for it in regs: 162 if it.r_name == name: 163 reg = it 164 break 165 else: 166 reg = Reg(name) 167 regs.append(reg) 168 169 elif line.startswith('S_'): 170 name = line[:line.find('(')] 171 172 for it in reg.fields: 173 if it.s_name == name: 174 field = it 175 break 176 else: 177 field = Field(reg, name) 178 reg.fields.append(field) 179 180 elif line.startswith('V_'): 181 split = line.split() 182 name = split[0] 183 value = int(split[1], 0) 184 185 for (n,v) in field.values: 186 if n == name: 187 if v != value: 188 sys.exit('Value mismatch: name = ' + name) 189 190 field.values.append((name, value)) 191 192 elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1: 193 packets.append(line.split()[0]) 194 195 # Copy fields to indexed registers which have their fields only defined 196 # at register index 0. 197 # For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 0. 198 match_number = re.compile('[0-9]+') 199 reg_dict = dict() 200 201 # Create a dict of registers with fields and '0' in their name 202 for reg in regs: 203 if len(reg.fields) and reg.name.find('0') != -1: 204 reg_dict[reg.name] = reg 205 206 # Assign fields 207 for reg in regs: 208 if not len(reg.fields): 209 reg0 = reg_dict.get(match_number.sub('0', reg.name)) 210 if reg0 != None: 211 reg.fields = reg0.fields 212 reg.fields_owner = reg0 213 reg.own_fields = False 214 215 216def write_tables(regs, packets): 217 218 strings = StringTable() 219 strings_offsets = IntTable("int") 220 221 print('/* This file is autogenerated by egd_tables.py from evergreend.h. Do not edit directly. */') 222 print() 223 print(CopyRight.strip()) 224 print(''' 225#ifndef EG_TABLES_H 226#define EG_TABLES_H 227 228struct eg_field { 229 unsigned name_offset; 230 unsigned mask; 231 unsigned num_values; 232 unsigned values_offset; /* offset into eg_strings_offsets */ 233}; 234 235struct eg_reg { 236 unsigned name_offset; 237 unsigned offset; 238 unsigned num_fields; 239 unsigned fields_offset; 240}; 241 242struct eg_packet3 { 243 unsigned name_offset; 244 unsigned op; 245}; 246''') 247 248 print('static const struct eg_packet3 packet3_table[] = {') 249 for pkt in packets: 250 print('\t{%s, %s},' % (strings.add(pkt[5:]), pkt)) 251 print('};') 252 print() 253 254 print('static const struct eg_field egd_fields_table[] = {') 255 256 fields_idx = 0 257 for reg in regs: 258 if len(reg.fields) and reg.own_fields: 259 print('\t/* %s */' % (fields_idx)) 260 261 reg.fields_idx = fields_idx 262 263 for field in reg.fields: 264 if len(field.values): 265 values_offsets = [] 266 for value in field.values: 267 while value[1] >= len(values_offsets): 268 values_offsets.append(-1) 269 values_offsets[value[1]] = strings.add(strip_prefix(value[0])) 270 print('\t{%s, %s(~0u), %s, %s},' % ( 271 strings.add(field.name), field.s_name, 272 len(values_offsets), strings_offsets.add(values_offsets))) 273 else: 274 print('\t{%s, %s(~0u)},' % (strings.add(field.name), field.s_name)) 275 fields_idx += 1 276 277 print('};') 278 print() 279 280 print('static const struct eg_reg egd_reg_table[] = {') 281 for reg in regs: 282 if len(reg.fields): 283 print('\t{%s, %s, %s, %s},' % (strings.add(reg.name), reg.r_name, 284 len(reg.fields), reg.fields_idx if reg.own_fields else reg.fields_owner.fields_idx)) 285 else: 286 print('\t{%s, %s},' % (strings.add(reg.name), reg.r_name)) 287 print('};') 288 print() 289 290 strings.emit(sys.stdout, "egd_strings") 291 292 print() 293 294 strings_offsets.emit(sys.stdout, "egd_strings_offsets") 295 296 print() 297 print('#endif') 298 299 300def main(): 301 regs = [] 302 packets = [] 303 for arg in sys.argv[1:]: 304 parse(arg, regs, packets) 305 write_tables(regs, packets) 306 307 308if __name__ == '__main__': 309 main() 310 311# kate: space-indent on; indent-width 4; replace-tabs on; 312