1bf215546Sopenharmony_ciCopyRight = ''' 2bf215546Sopenharmony_ci/* 3bf215546Sopenharmony_ci * Copyright 2015-2019 Advanced Micro Devices, Inc. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci''' 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_cifrom collections import defaultdict 28bf215546Sopenharmony_ciimport functools 29bf215546Sopenharmony_ciimport itertools 30bf215546Sopenharmony_ciimport json 31bf215546Sopenharmony_ciimport os.path 32bf215546Sopenharmony_ciimport re 33bf215546Sopenharmony_ciimport sys 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ciAMD_REGISTERS = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../registers")) 36bf215546Sopenharmony_cisys.path.append(AMD_REGISTERS) 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cifrom regdb import Object, RegisterDatabase 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cidef string_to_chars(string): 42bf215546Sopenharmony_ci return "'" + "', '".join(string) + "', '\\0'," 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ciclass StringTable: 46bf215546Sopenharmony_ci """ 47bf215546Sopenharmony_ci A class for collecting multiple strings in a single larger string that is 48bf215546Sopenharmony_ci used by indexing (to avoid relocations in the resulting binary) 49bf215546Sopenharmony_ci """ 50bf215546Sopenharmony_ci def __init__(self): 51bf215546Sopenharmony_ci self.table = [] 52bf215546Sopenharmony_ci self.length = 0 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci def add(self, string): 55bf215546Sopenharmony_ci # We might get lucky with string being a suffix of a previously added string 56bf215546Sopenharmony_ci for te in self.table: 57bf215546Sopenharmony_ci if te[0].endswith(string): 58bf215546Sopenharmony_ci idx = te[1] + len(te[0]) - len(string) 59bf215546Sopenharmony_ci te[2].add(idx) 60bf215546Sopenharmony_ci return idx 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci idx = self.length 63bf215546Sopenharmony_ci self.table.append((string, idx, set((idx,)))) 64bf215546Sopenharmony_ci self.length += len(string) + 1 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci return idx 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci def emit(self, filp, name, static=True): 69bf215546Sopenharmony_ci """ 70bf215546Sopenharmony_ci Write 71bf215546Sopenharmony_ci [static] const char name[] = "..."; 72bf215546Sopenharmony_ci to filp. 73bf215546Sopenharmony_ci """ 74bf215546Sopenharmony_ci fragments = [ 75bf215546Sopenharmony_ci '%s /* %s (%s) */' % ( 76bf215546Sopenharmony_ci string_to_chars(te[0].encode('unicode_escape').decode()), 77bf215546Sopenharmony_ci te[0].encode('unicode_escape').decode(), 78bf215546Sopenharmony_ci ', '.join(str(idx) for idx in sorted(te[2])) 79bf215546Sopenharmony_ci ) 80bf215546Sopenharmony_ci for te in self.table 81bf215546Sopenharmony_ci ] 82bf215546Sopenharmony_ci filp.write('%sconst char %s[] = {\n%s\n};\n' % ( 83bf215546Sopenharmony_ci 'static ' if static else '', 84bf215546Sopenharmony_ci name, 85bf215546Sopenharmony_ci '\n'.join('\t' + fragment for fragment in fragments) 86bf215546Sopenharmony_ci )) 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ciclass IntTable: 89bf215546Sopenharmony_ci """ 90bf215546Sopenharmony_ci A class for collecting multiple arrays of integers in a single big array 91bf215546Sopenharmony_ci that is used by indexing (to avoid relocations in the resulting binary) 92bf215546Sopenharmony_ci """ 93bf215546Sopenharmony_ci def __init__(self, typename): 94bf215546Sopenharmony_ci self.typename = typename 95bf215546Sopenharmony_ci self.table = [] 96bf215546Sopenharmony_ci self.idxs = set() 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci def add(self, array): 99bf215546Sopenharmony_ci # We might get lucky and find the array somewhere in the existing data 100bf215546Sopenharmony_ci try: 101bf215546Sopenharmony_ci idx = 0 102bf215546Sopenharmony_ci while True: 103bf215546Sopenharmony_ci idx = self.table.index(array[0], idx, len(self.table) - len(array) + 1) 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci for i in range(1, len(array)): 106bf215546Sopenharmony_ci if array[i] != self.table[idx + i]: 107bf215546Sopenharmony_ci break 108bf215546Sopenharmony_ci else: 109bf215546Sopenharmony_ci self.idxs.add(idx) 110bf215546Sopenharmony_ci return idx 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci idx += 1 113bf215546Sopenharmony_ci except ValueError: 114bf215546Sopenharmony_ci pass 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci idx = len(self.table) 117bf215546Sopenharmony_ci self.table += array 118bf215546Sopenharmony_ci self.idxs.add(idx) 119bf215546Sopenharmony_ci return idx 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci def emit(self, filp, name, static=True): 122bf215546Sopenharmony_ci """ 123bf215546Sopenharmony_ci Write 124bf215546Sopenharmony_ci [static] const typename name[] = { ... }; 125bf215546Sopenharmony_ci to filp. 126bf215546Sopenharmony_ci """ 127bf215546Sopenharmony_ci idxs = sorted(self.idxs) + [len(self.table)] 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci fragments = [ 130bf215546Sopenharmony_ci ('\t/* %s */ %s' % ( 131bf215546Sopenharmony_ci idxs[i], 132bf215546Sopenharmony_ci ' '.join((str(elt) + ',') for elt in self.table[idxs[i]:idxs[i+1]]) 133bf215546Sopenharmony_ci )) 134bf215546Sopenharmony_ci for i in range(len(idxs) - 1) 135bf215546Sopenharmony_ci ] 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci filp.write('%sconst %s %s[] = {\n%s\n};\n' % ( 138bf215546Sopenharmony_ci 'static ' if static else '', 139bf215546Sopenharmony_ci self.typename, name, 140bf215546Sopenharmony_ci '\n'.join(fragments) 141bf215546Sopenharmony_ci )) 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ciclass Field: 144bf215546Sopenharmony_ci def __init__(self, name, bits): 145bf215546Sopenharmony_ci self.name = name 146bf215546Sopenharmony_ci self.bits = bits # [first, last] 147bf215546Sopenharmony_ci self.values = [] # [(name, value), ...] 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci def format(self, string_table, idx_table): 150bf215546Sopenharmony_ci mask = ((1 << (self.bits[1] - self.bits[0] + 1)) - 1) << self.bits[0] 151bf215546Sopenharmony_ci if len(self.values): 152bf215546Sopenharmony_ci values_offsets = [] 153bf215546Sopenharmony_ci for value in self.values: 154bf215546Sopenharmony_ci while value[1] >= len(values_offsets): 155bf215546Sopenharmony_ci values_offsets.append(-1) 156bf215546Sopenharmony_ci values_offsets[value[1]] = string_table.add(value[0]) 157bf215546Sopenharmony_ci return '{{{0}, 0x{mask:X}, {1}, {2}}}'.format( 158bf215546Sopenharmony_ci string_table.add(self.name), 159bf215546Sopenharmony_ci len(values_offsets), idx_table.add(values_offsets), 160bf215546Sopenharmony_ci **locals() 161bf215546Sopenharmony_ci ) 162bf215546Sopenharmony_ci else: 163bf215546Sopenharmony_ci return '{{{0}, 0x{mask:X}}}'.format(string_table.add(self.name), **locals()) 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci def __eq__(self, other): 166bf215546Sopenharmony_ci return (self.name == other.name and 167bf215546Sopenharmony_ci self.bits[0] == other.bits[0] and self.bits[1] == other.bits[1] and 168bf215546Sopenharmony_ci len(self.values) == len(other.values) and 169bf215546Sopenharmony_ci all(a[0] == b[0] and a[1] == b[1] for a, b, in zip(self.values, other.values))) 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci def __ne__(self, other): 172bf215546Sopenharmony_ci return not (self == other) 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ciclass FieldTable: 176bf215546Sopenharmony_ci """ 177bf215546Sopenharmony_ci A class for collecting multiple arrays of register fields in a single big 178bf215546Sopenharmony_ci array that is used by indexing (to avoid relocations in the resulting binary) 179bf215546Sopenharmony_ci """ 180bf215546Sopenharmony_ci def __init__(self): 181bf215546Sopenharmony_ci self.table = [] 182bf215546Sopenharmony_ci self.idxs = set() 183bf215546Sopenharmony_ci self.name_to_idx = defaultdict(lambda: []) 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci def add(self, array): 186bf215546Sopenharmony_ci """ 187bf215546Sopenharmony_ci Add an array of Field objects, and return the index of where to find 188bf215546Sopenharmony_ci the array in the table. 189bf215546Sopenharmony_ci """ 190bf215546Sopenharmony_ci # Check if we can find the array in the table already 191bf215546Sopenharmony_ci for base_idx in self.name_to_idx.get(array[0].name, []): 192bf215546Sopenharmony_ci if base_idx + len(array) > len(self.table): 193bf215546Sopenharmony_ci continue 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci for i, a in enumerate(array): 196bf215546Sopenharmony_ci b = self.table[base_idx + i] 197bf215546Sopenharmony_ci if a != b: 198bf215546Sopenharmony_ci break 199bf215546Sopenharmony_ci else: 200bf215546Sopenharmony_ci return base_idx 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci base_idx = len(self.table) 203bf215546Sopenharmony_ci self.idxs.add(base_idx) 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci for field in array: 206bf215546Sopenharmony_ci self.name_to_idx[field.name].append(len(self.table)) 207bf215546Sopenharmony_ci self.table.append(field) 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci return base_idx 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci def emit(self, filp, string_table, idx_table): 212bf215546Sopenharmony_ci """ 213bf215546Sopenharmony_ci Write 214bf215546Sopenharmony_ci static const struct si_field sid_fields_table[] = { ... }; 215bf215546Sopenharmony_ci to filp. 216bf215546Sopenharmony_ci """ 217bf215546Sopenharmony_ci idxs = sorted(self.idxs) + [len(self.table)] 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci filp.write('static const struct si_field sid_fields_table[] = {\n') 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci for start, end in zip(idxs, idxs[1:]): 222bf215546Sopenharmony_ci filp.write('\t/* %s */\n' % (start)) 223bf215546Sopenharmony_ci for field in self.table[start:end]: 224bf215546Sopenharmony_ci filp.write('\t%s,\n' % (field.format(string_table, idx_table))) 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci filp.write('};\n') 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_cidef parse_packet3(filp): 230bf215546Sopenharmony_ci """ 231bf215546Sopenharmony_ci Parse PKT3 commands from the given header file. 232bf215546Sopenharmony_ci """ 233bf215546Sopenharmony_ci packets = [] 234bf215546Sopenharmony_ci for line in filp: 235bf215546Sopenharmony_ci if not line.startswith('#define '): 236bf215546Sopenharmony_ci continue 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci line = line[8:].strip() 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci if line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1: 241bf215546Sopenharmony_ci packets.append(line.split()[0]) 242bf215546Sopenharmony_ci return packets 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ciclass TableWriter(object): 246bf215546Sopenharmony_ci def __init__(self): 247bf215546Sopenharmony_ci self.__strings = StringTable() 248bf215546Sopenharmony_ci self.__strings_offsets = IntTable('int') 249bf215546Sopenharmony_ci self.__fields = FieldTable() 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci def write(self, regdb, packets, file=sys.stdout): 252bf215546Sopenharmony_ci def out(*args): 253bf215546Sopenharmony_ci print(*args, file=file) 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci out('/* This file is autogenerated by sid_tables.py from sid.h. Do not edit directly. */') 256bf215546Sopenharmony_ci out() 257bf215546Sopenharmony_ci out(CopyRight.strip()) 258bf215546Sopenharmony_ci out(''' 259bf215546Sopenharmony_ci#ifndef SID_TABLES_H 260bf215546Sopenharmony_ci#define SID_TABLES_H 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_cistruct si_field { 263bf215546Sopenharmony_ci unsigned name_offset; 264bf215546Sopenharmony_ci unsigned mask; 265bf215546Sopenharmony_ci unsigned num_values; 266bf215546Sopenharmony_ci unsigned values_offset; /* offset into sid_strings_offsets */ 267bf215546Sopenharmony_ci}; 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_cistruct si_reg { 270bf215546Sopenharmony_ci unsigned name_offset; 271bf215546Sopenharmony_ci unsigned offset; 272bf215546Sopenharmony_ci unsigned num_fields; 273bf215546Sopenharmony_ci unsigned fields_offset; 274bf215546Sopenharmony_ci}; 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_cistruct si_packet3 { 277bf215546Sopenharmony_ci unsigned name_offset; 278bf215546Sopenharmony_ci unsigned op; 279bf215546Sopenharmony_ci}; 280bf215546Sopenharmony_ci''') 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci out('static const struct si_packet3 packet3_table[] = {') 283bf215546Sopenharmony_ci for pkt in packets: 284bf215546Sopenharmony_ci out('\t{%s, %s},' % (self.__strings.add(pkt[5:]), pkt)) 285bf215546Sopenharmony_ci out('};') 286bf215546Sopenharmony_ci out() 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci regmaps_by_chip = defaultdict(list) 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci for regmap in regdb.register_mappings(): 291bf215546Sopenharmony_ci for chip in regmap.chips: 292bf215546Sopenharmony_ci regmaps_by_chip[chip].append(regmap) 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci regtypes = {} 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci # Sorted iteration over chips for deterministic builds 297bf215546Sopenharmony_ci for chip in sorted(regmaps_by_chip.keys()): 298bf215546Sopenharmony_ci regmaps = regmaps_by_chip[chip] 299bf215546Sopenharmony_ci regmaps.sort(key=lambda regmap: (regmap.map.to, regmap.map.at)) 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci out('static const struct si_reg {chip}_reg_table[] = {{'.format(**locals())) 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci for regmap in regmaps: 304bf215546Sopenharmony_ci if hasattr(regmap, 'type_ref'): 305bf215546Sopenharmony_ci if not regmap.type_ref in regtypes: 306bf215546Sopenharmony_ci regtype = regdb.register_type(regmap.type_ref) 307bf215546Sopenharmony_ci fields = [] 308bf215546Sopenharmony_ci for dbfield in regtype.fields: 309bf215546Sopenharmony_ci field = Field(dbfield.name, dbfield.bits) 310bf215546Sopenharmony_ci if hasattr(dbfield, 'enum_ref'): 311bf215546Sopenharmony_ci enum = regdb.enum(dbfield.enum_ref) 312bf215546Sopenharmony_ci for entry in enum.entries: 313bf215546Sopenharmony_ci field.values.append((entry.name, entry.value)) 314bf215546Sopenharmony_ci fields.append(field) 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci num_fields = len(regtype.fields) 317bf215546Sopenharmony_ci fields_offset = self.__fields.add(fields) 318bf215546Sopenharmony_ci regtypes[regmap.type_ref] = (num_fields, fields_offset) 319bf215546Sopenharmony_ci else: 320bf215546Sopenharmony_ci num_fields, fields_offset = regtypes[regmap.type_ref] 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci print('\t{{{0}, {regmap.map.at}, {num_fields}, {fields_offset}}},' 323bf215546Sopenharmony_ci .format(self.__strings.add(regmap.name), **locals())) 324bf215546Sopenharmony_ci else: 325bf215546Sopenharmony_ci print('\t{{{0}, {regmap.map.at}}},' 326bf215546Sopenharmony_ci .format(self.__strings.add(regmap.name), **locals())) 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci out('};\n') 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci self.__fields.emit(file, self.__strings, self.__strings_offsets) 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci out() 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci self.__strings.emit(file, "sid_strings") 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci out() 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci self.__strings_offsets.emit(file, "sid_strings_offsets") 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci out() 341bf215546Sopenharmony_ci out('#endif') 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_cidef main(): 345bf215546Sopenharmony_ci # Parse PKT3 types 346bf215546Sopenharmony_ci with open(sys.argv[1], 'r') as filp: 347bf215546Sopenharmony_ci packets = parse_packet3(filp) 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci # Register database parse 350bf215546Sopenharmony_ci regdb = None 351bf215546Sopenharmony_ci for filename in sys.argv[2:]: 352bf215546Sopenharmony_ci with open(filename, 'r') as filp: 353bf215546Sopenharmony_ci try: 354bf215546Sopenharmony_ci db = RegisterDatabase.from_json(json.load(filp)) 355bf215546Sopenharmony_ci if regdb is None: 356bf215546Sopenharmony_ci regdb = db 357bf215546Sopenharmony_ci else: 358bf215546Sopenharmony_ci regdb.update(db) 359bf215546Sopenharmony_ci except json.JSONDecodeError as e: 360bf215546Sopenharmony_ci print('Error reading {}'.format(sys.argv[1]), file=sys.stderr) 361bf215546Sopenharmony_ci raise 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci # The ac_debug code only distinguishes by gfx_level 364bf215546Sopenharmony_ci regdb.merge_chips(['gfx8', 'fiji', 'stoney'], 'gfx8') 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci # Write it all out 367bf215546Sopenharmony_ci w = TableWriter() 368bf215546Sopenharmony_ci w.write(regdb, packets) 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ciif __name__ == '__main__': 371bf215546Sopenharmony_ci main() 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci# kate: space-indent on; indent-width 4; replace-tabs on; 374