101e04c3fSmrgCopyRight = ''' 201e04c3fSmrg/* 37ec681f3Smrg * Copyright 2015-2019 Advanced Micro Devices, Inc. 401e04c3fSmrg * 501e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 601e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 701e04c3fSmrg * to deal in the Software without restriction, including without limitation 801e04c3fSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub 901e04c3fSmrg * license, and/or sell copies of the Software, and to permit persons to whom 1001e04c3fSmrg * the Software is furnished to do so, subject to the following conditions: 1101e04c3fSmrg * 1201e04c3fSmrg * The above copyright notice and this permission notice (including the next 1301e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1401e04c3fSmrg * Software. 1501e04c3fSmrg * 1601e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1701e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1801e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 1901e04c3fSmrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 2001e04c3fSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2101e04c3fSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2201e04c3fSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 2301e04c3fSmrg * 2401e04c3fSmrg */ 2501e04c3fSmrg''' 2601e04c3fSmrg 277ec681f3Smrgfrom collections import defaultdict 2801e04c3fSmrgimport functools 2901e04c3fSmrgimport itertools 307ec681f3Smrgimport json 3101e04c3fSmrgimport os.path 3201e04c3fSmrgimport re 3301e04c3fSmrgimport sys 3401e04c3fSmrg 357ec681f3SmrgAMD_REGISTERS = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../registers")) 367ec681f3Smrgsys.path.append(AMD_REGISTERS) 377ec681f3Smrg 387ec681f3Smrgfrom regdb import Object, RegisterDatabase 397ec681f3Smrg 407ec681f3Smrg 417ec681f3Smrgdef string_to_chars(string): 427ec681f3Smrg return "'" + "', '".join(string) + "', '\\0'," 437ec681f3Smrg 4401e04c3fSmrg 4501e04c3fSmrgclass StringTable: 4601e04c3fSmrg """ 4701e04c3fSmrg A class for collecting multiple strings in a single larger string that is 4801e04c3fSmrg used by indexing (to avoid relocations in the resulting binary) 4901e04c3fSmrg """ 5001e04c3fSmrg def __init__(self): 5101e04c3fSmrg self.table = [] 5201e04c3fSmrg self.length = 0 5301e04c3fSmrg 5401e04c3fSmrg def add(self, string): 5501e04c3fSmrg # We might get lucky with string being a suffix of a previously added string 5601e04c3fSmrg for te in self.table: 5701e04c3fSmrg if te[0].endswith(string): 5801e04c3fSmrg idx = te[1] + len(te[0]) - len(string) 5901e04c3fSmrg te[2].add(idx) 6001e04c3fSmrg return idx 6101e04c3fSmrg 6201e04c3fSmrg idx = self.length 6301e04c3fSmrg self.table.append((string, idx, set((idx,)))) 6401e04c3fSmrg self.length += len(string) + 1 6501e04c3fSmrg 6601e04c3fSmrg return idx 6701e04c3fSmrg 6801e04c3fSmrg def emit(self, filp, name, static=True): 6901e04c3fSmrg """ 7001e04c3fSmrg Write 7101e04c3fSmrg [static] const char name[] = "..."; 7201e04c3fSmrg to filp. 7301e04c3fSmrg """ 7401e04c3fSmrg fragments = [ 757ec681f3Smrg '%s /* %s (%s) */' % ( 767ec681f3Smrg string_to_chars(te[0].encode('unicode_escape').decode()), 7701e04c3fSmrg te[0].encode('unicode_escape').decode(), 7801e04c3fSmrg ', '.join(str(idx) for idx in sorted(te[2])) 7901e04c3fSmrg ) 8001e04c3fSmrg for te in self.table 8101e04c3fSmrg ] 827ec681f3Smrg filp.write('%sconst char %s[] = {\n%s\n};\n' % ( 8301e04c3fSmrg 'static ' if static else '', 8401e04c3fSmrg name, 8501e04c3fSmrg '\n'.join('\t' + fragment for fragment in fragments) 8601e04c3fSmrg )) 8701e04c3fSmrg 8801e04c3fSmrgclass IntTable: 8901e04c3fSmrg """ 9001e04c3fSmrg A class for collecting multiple arrays of integers in a single big array 9101e04c3fSmrg that is used by indexing (to avoid relocations in the resulting binary) 9201e04c3fSmrg """ 9301e04c3fSmrg def __init__(self, typename): 9401e04c3fSmrg self.typename = typename 9501e04c3fSmrg self.table = [] 9601e04c3fSmrg self.idxs = set() 9701e04c3fSmrg 9801e04c3fSmrg def add(self, array): 9901e04c3fSmrg # We might get lucky and find the array somewhere in the existing data 10001e04c3fSmrg try: 10101e04c3fSmrg idx = 0 10201e04c3fSmrg while True: 10301e04c3fSmrg idx = self.table.index(array[0], idx, len(self.table) - len(array) + 1) 10401e04c3fSmrg 10501e04c3fSmrg for i in range(1, len(array)): 10601e04c3fSmrg if array[i] != self.table[idx + i]: 10701e04c3fSmrg break 10801e04c3fSmrg else: 10901e04c3fSmrg self.idxs.add(idx) 11001e04c3fSmrg return idx 11101e04c3fSmrg 11201e04c3fSmrg idx += 1 11301e04c3fSmrg except ValueError: 11401e04c3fSmrg pass 11501e04c3fSmrg 11601e04c3fSmrg idx = len(self.table) 11701e04c3fSmrg self.table += array 11801e04c3fSmrg self.idxs.add(idx) 11901e04c3fSmrg return idx 12001e04c3fSmrg 12101e04c3fSmrg def emit(self, filp, name, static=True): 12201e04c3fSmrg """ 12301e04c3fSmrg Write 12401e04c3fSmrg [static] const typename name[] = { ... }; 12501e04c3fSmrg to filp. 12601e04c3fSmrg """ 12701e04c3fSmrg idxs = sorted(self.idxs) + [len(self.table)] 12801e04c3fSmrg 12901e04c3fSmrg fragments = [ 13001e04c3fSmrg ('\t/* %s */ %s' % ( 13101e04c3fSmrg idxs[i], 13201e04c3fSmrg ' '.join((str(elt) + ',') for elt in self.table[idxs[i]:idxs[i+1]]) 13301e04c3fSmrg )) 13401e04c3fSmrg for i in range(len(idxs) - 1) 13501e04c3fSmrg ] 13601e04c3fSmrg 13701e04c3fSmrg filp.write('%sconst %s %s[] = {\n%s\n};\n' % ( 13801e04c3fSmrg 'static ' if static else '', 13901e04c3fSmrg self.typename, name, 14001e04c3fSmrg '\n'.join(fragments) 14101e04c3fSmrg )) 14201e04c3fSmrg 14301e04c3fSmrgclass Field: 1447ec681f3Smrg def __init__(self, name, bits): 1457ec681f3Smrg self.name = name 1467ec681f3Smrg self.bits = bits # [first, last] 1477ec681f3Smrg self.values = [] # [(name, value), ...] 14801e04c3fSmrg 14901e04c3fSmrg def format(self, string_table, idx_table): 1507ec681f3Smrg mask = ((1 << (self.bits[1] - self.bits[0] + 1)) - 1) << self.bits[0] 15101e04c3fSmrg if len(self.values): 15201e04c3fSmrg values_offsets = [] 15301e04c3fSmrg for value in self.values: 15401e04c3fSmrg while value[1] >= len(values_offsets): 15501e04c3fSmrg values_offsets.append(-1) 1567ec681f3Smrg values_offsets[value[1]] = string_table.add(value[0]) 1577ec681f3Smrg return '{{{0}, 0x{mask:X}, {1}, {2}}}'.format( 1587ec681f3Smrg string_table.add(self.name), 1597ec681f3Smrg len(values_offsets), idx_table.add(values_offsets), 1607ec681f3Smrg **locals() 1617ec681f3Smrg ) 16201e04c3fSmrg else: 1637ec681f3Smrg return '{{{0}, 0x{mask:X}}}'.format(string_table.add(self.name), **locals()) 16401e04c3fSmrg 16501e04c3fSmrg def __eq__(self, other): 1667ec681f3Smrg return (self.name == other.name and 1677ec681f3Smrg self.bits[0] == other.bits[0] and self.bits[1] == other.bits[1] and 16801e04c3fSmrg len(self.values) == len(other.values) and 16901e04c3fSmrg all(a[0] == b[0] and a[1] == b[1] for a, b, in zip(self.values, other.values))) 17001e04c3fSmrg 17101e04c3fSmrg def __ne__(self, other): 17201e04c3fSmrg return not (self == other) 17301e04c3fSmrg 17401e04c3fSmrg 17501e04c3fSmrgclass FieldTable: 17601e04c3fSmrg """ 17701e04c3fSmrg A class for collecting multiple arrays of register fields in a single big 17801e04c3fSmrg array that is used by indexing (to avoid relocations in the resulting binary) 17901e04c3fSmrg """ 18001e04c3fSmrg def __init__(self): 18101e04c3fSmrg self.table = [] 18201e04c3fSmrg self.idxs = set() 1837ec681f3Smrg self.name_to_idx = defaultdict(lambda: []) 18401e04c3fSmrg 18501e04c3fSmrg def add(self, array): 18601e04c3fSmrg """ 18701e04c3fSmrg Add an array of Field objects, and return the index of where to find 18801e04c3fSmrg the array in the table. 18901e04c3fSmrg """ 19001e04c3fSmrg # Check if we can find the array in the table already 19101e04c3fSmrg for base_idx in self.name_to_idx.get(array[0].name, []): 19201e04c3fSmrg if base_idx + len(array) > len(self.table): 19301e04c3fSmrg continue 19401e04c3fSmrg 19501e04c3fSmrg for i, a in enumerate(array): 19601e04c3fSmrg b = self.table[base_idx + i] 19701e04c3fSmrg if a != b: 19801e04c3fSmrg break 19901e04c3fSmrg else: 20001e04c3fSmrg return base_idx 20101e04c3fSmrg 20201e04c3fSmrg base_idx = len(self.table) 20301e04c3fSmrg self.idxs.add(base_idx) 20401e04c3fSmrg 20501e04c3fSmrg for field in array: 20601e04c3fSmrg self.name_to_idx[field.name].append(len(self.table)) 20701e04c3fSmrg self.table.append(field) 20801e04c3fSmrg 20901e04c3fSmrg return base_idx 21001e04c3fSmrg 21101e04c3fSmrg def emit(self, filp, string_table, idx_table): 21201e04c3fSmrg """ 21301e04c3fSmrg Write 21401e04c3fSmrg static const struct si_field sid_fields_table[] = { ... }; 21501e04c3fSmrg to filp. 21601e04c3fSmrg """ 21701e04c3fSmrg idxs = sorted(self.idxs) + [len(self.table)] 21801e04c3fSmrg 21901e04c3fSmrg filp.write('static const struct si_field sid_fields_table[] = {\n') 22001e04c3fSmrg 22101e04c3fSmrg for start, end in zip(idxs, idxs[1:]): 22201e04c3fSmrg filp.write('\t/* %s */\n' % (start)) 22301e04c3fSmrg for field in self.table[start:end]: 22401e04c3fSmrg filp.write('\t%s,\n' % (field.format(string_table, idx_table))) 22501e04c3fSmrg 22601e04c3fSmrg filp.write('};\n') 22701e04c3fSmrg 22801e04c3fSmrg 2297ec681f3Smrgdef parse_packet3(filp): 23001e04c3fSmrg """ 2317ec681f3Smrg Parse PKT3 commands from the given header file. 23201e04c3fSmrg """ 2337ec681f3Smrg packets = [] 2347ec681f3Smrg for line in filp: 2357ec681f3Smrg if not line.startswith('#define '): 2367ec681f3Smrg continue 23701e04c3fSmrg 2387ec681f3Smrg line = line[8:].strip() 23901e04c3fSmrg 2407ec681f3Smrg if line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1: 2417ec681f3Smrg packets.append(line.split()[0]) 2427ec681f3Smrg return packets 24301e04c3fSmrg 24401e04c3fSmrg 2457ec681f3Smrgclass TableWriter(object): 2467ec681f3Smrg def __init__(self): 2477ec681f3Smrg self.__strings = StringTable() 2487ec681f3Smrg self.__strings_offsets = IntTable('int') 2497ec681f3Smrg self.__fields = FieldTable() 2507ec681f3Smrg 2517ec681f3Smrg def write(self, regdb, packets, file=sys.stdout): 2527ec681f3Smrg def out(*args): 2537ec681f3Smrg print(*args, file=file) 2547ec681f3Smrg 2557ec681f3Smrg out('/* This file is autogenerated by sid_tables.py from sid.h. Do not edit directly. */') 2567ec681f3Smrg out() 2577ec681f3Smrg out(CopyRight.strip()) 2587ec681f3Smrg out(''' 25901e04c3fSmrg#ifndef SID_TABLES_H 26001e04c3fSmrg#define SID_TABLES_H 26101e04c3fSmrg 26201e04c3fSmrgstruct si_field { 26301e04c3fSmrg unsigned name_offset; 26401e04c3fSmrg unsigned mask; 26501e04c3fSmrg unsigned num_values; 26601e04c3fSmrg unsigned values_offset; /* offset into sid_strings_offsets */ 26701e04c3fSmrg}; 26801e04c3fSmrg 26901e04c3fSmrgstruct si_reg { 27001e04c3fSmrg unsigned name_offset; 27101e04c3fSmrg unsigned offset; 27201e04c3fSmrg unsigned num_fields; 27301e04c3fSmrg unsigned fields_offset; 27401e04c3fSmrg}; 27501e04c3fSmrg 27601e04c3fSmrgstruct si_packet3 { 27701e04c3fSmrg unsigned name_offset; 27801e04c3fSmrg unsigned op; 27901e04c3fSmrg}; 28001e04c3fSmrg''') 28101e04c3fSmrg 2827ec681f3Smrg out('static const struct si_packet3 packet3_table[] = {') 2837ec681f3Smrg for pkt in packets: 2847ec681f3Smrg out('\t{%s, %s},' % (self.__strings.add(pkt[5:]), pkt)) 2857ec681f3Smrg out('};') 2867ec681f3Smrg out() 2877ec681f3Smrg 2887ec681f3Smrg regmaps_by_chip = defaultdict(list) 2897ec681f3Smrg 2907ec681f3Smrg for regmap in regdb.register_mappings(): 2917ec681f3Smrg for chip in regmap.chips: 2927ec681f3Smrg regmaps_by_chip[chip].append(regmap) 2937ec681f3Smrg 2947ec681f3Smrg regtypes = {} 2957ec681f3Smrg 2967ec681f3Smrg # Sorted iteration over chips for deterministic builds 2977ec681f3Smrg for chip in sorted(regmaps_by_chip.keys()): 2987ec681f3Smrg regmaps = regmaps_by_chip[chip] 2997ec681f3Smrg regmaps.sort(key=lambda regmap: (regmap.map.to, regmap.map.at)) 3007ec681f3Smrg 3017ec681f3Smrg out('static const struct si_reg {chip}_reg_table[] = {{'.format(**locals())) 3027ec681f3Smrg 3037ec681f3Smrg for regmap in regmaps: 3047ec681f3Smrg if hasattr(regmap, 'type_ref'): 3057ec681f3Smrg if not regmap.type_ref in regtypes: 3067ec681f3Smrg regtype = regdb.register_type(regmap.type_ref) 3077ec681f3Smrg fields = [] 3087ec681f3Smrg for dbfield in regtype.fields: 3097ec681f3Smrg field = Field(dbfield.name, dbfield.bits) 3107ec681f3Smrg if hasattr(dbfield, 'enum_ref'): 3117ec681f3Smrg enum = regdb.enum(dbfield.enum_ref) 3127ec681f3Smrg for entry in enum.entries: 3137ec681f3Smrg field.values.append((entry.name, entry.value)) 3147ec681f3Smrg fields.append(field) 3157ec681f3Smrg 3167ec681f3Smrg num_fields = len(regtype.fields) 3177ec681f3Smrg fields_offset = self.__fields.add(fields) 3187ec681f3Smrg regtypes[regmap.type_ref] = (num_fields, fields_offset) 3197ec681f3Smrg else: 3207ec681f3Smrg num_fields, fields_offset = regtypes[regmap.type_ref] 32101e04c3fSmrg 3227ec681f3Smrg print('\t{{{0}, {regmap.map.at}, {num_fields}, {fields_offset}}},' 3237ec681f3Smrg .format(self.__strings.add(regmap.name), **locals())) 3247ec681f3Smrg else: 3257ec681f3Smrg print('\t{{{0}, {regmap.map.at}}},' 3267ec681f3Smrg .format(self.__strings.add(regmap.name), **locals())) 32701e04c3fSmrg 3287ec681f3Smrg out('};\n') 32901e04c3fSmrg 3307ec681f3Smrg self.__fields.emit(file, self.__strings, self.__strings_offsets) 33101e04c3fSmrg 3327ec681f3Smrg out() 33301e04c3fSmrg 3347ec681f3Smrg self.__strings.emit(file, "sid_strings") 33501e04c3fSmrg 3367ec681f3Smrg out() 33701e04c3fSmrg 3387ec681f3Smrg self.__strings_offsets.emit(file, "sid_strings_offsets") 33901e04c3fSmrg 3407ec681f3Smrg out() 3417ec681f3Smrg out('#endif') 34201e04c3fSmrg 34301e04c3fSmrg 34401e04c3fSmrgdef main(): 3457ec681f3Smrg # Parse PKT3 types 3467ec681f3Smrg with open(sys.argv[1], 'r') as filp: 3477ec681f3Smrg packets = parse_packet3(filp) 3487ec681f3Smrg 3497ec681f3Smrg # Register database parse 3507ec681f3Smrg regdb = None 3517ec681f3Smrg for filename in sys.argv[2:]: 3527ec681f3Smrg with open(filename, 'r') as filp: 3537ec681f3Smrg try: 3547ec681f3Smrg db = RegisterDatabase.from_json(json.load(filp)) 3557ec681f3Smrg if regdb is None: 3567ec681f3Smrg regdb = db 3577ec681f3Smrg else: 3587ec681f3Smrg regdb.update(db) 3597ec681f3Smrg except json.JSONDecodeError as e: 3607ec681f3Smrg print('Error reading {}'.format(sys.argv[1]), file=sys.stderr) 3617ec681f3Smrg raise 3627ec681f3Smrg 3637ec681f3Smrg # The ac_debug code only distinguishes by chip_class 3647ec681f3Smrg regdb.merge_chips(['gfx8', 'fiji', 'stoney'], 'gfx8') 36501e04c3fSmrg 3667ec681f3Smrg # Write it all out 3677ec681f3Smrg w = TableWriter() 3687ec681f3Smrg w.write(regdb, packets) 36901e04c3fSmrg 37001e04c3fSmrgif __name__ == '__main__': 37101e04c3fSmrg main() 37201e04c3fSmrg 37301e04c3fSmrg# kate: space-indent on; indent-width 4; replace-tabs on; 374