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