101e04c3fSmrgCopyRight = ''' 201e04c3fSmrg/* 301e04c3fSmrg * Copyright 2015 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 2701e04c3fSmrgimport sys 2801e04c3fSmrgimport re 2901e04c3fSmrg 3001e04c3fSmrg 3101e04c3fSmrgclass StringTable: 3201e04c3fSmrg """ 3301e04c3fSmrg A class for collecting multiple strings in a single larger string that is 3401e04c3fSmrg used by indexing (to avoid relocations in the resulting binary) 3501e04c3fSmrg """ 3601e04c3fSmrg def __init__(self): 3701e04c3fSmrg self.table = [] 3801e04c3fSmrg self.length = 0 3901e04c3fSmrg 4001e04c3fSmrg def add(self, string): 4101e04c3fSmrg # We might get lucky with string being a suffix of a previously added string 4201e04c3fSmrg for te in self.table: 4301e04c3fSmrg if te[0].endswith(string): 4401e04c3fSmrg idx = te[1] + len(te[0]) - len(string) 4501e04c3fSmrg te[2].add(idx) 4601e04c3fSmrg return idx 4701e04c3fSmrg 4801e04c3fSmrg idx = self.length 4901e04c3fSmrg self.table.append((string, idx, set((idx,)))) 5001e04c3fSmrg self.length += len(string) + 1 5101e04c3fSmrg 5201e04c3fSmrg return idx 5301e04c3fSmrg 5401e04c3fSmrg def emit(self, filp, name, static=True): 5501e04c3fSmrg """ 5601e04c3fSmrg Write 5701e04c3fSmrg [static] const char name[] = "..."; 5801e04c3fSmrg to filp. 5901e04c3fSmrg """ 6001e04c3fSmrg fragments = [ 6101e04c3fSmrg '"%s\\0" /* %s */' % ( 6201e04c3fSmrg te[0].encode('unicode_escape').decode(), 6301e04c3fSmrg ', '.join(str(idx) for idx in te[2]) 6401e04c3fSmrg ) 6501e04c3fSmrg for te in self.table 6601e04c3fSmrg ] 6701e04c3fSmrg filp.write('%sconst char %s[] =\n%s;\n' % ( 6801e04c3fSmrg 'static ' if static else '', 6901e04c3fSmrg name, 7001e04c3fSmrg '\n'.join('\t' + fragment for fragment in fragments) 7101e04c3fSmrg )) 7201e04c3fSmrg 7301e04c3fSmrgclass IntTable: 7401e04c3fSmrg """ 7501e04c3fSmrg A class for collecting multiple arrays of integers in a single big array 7601e04c3fSmrg that is used by indexing (to avoid relocations in the resulting binary) 7701e04c3fSmrg """ 7801e04c3fSmrg def __init__(self, typename): 7901e04c3fSmrg self.typename = typename 8001e04c3fSmrg self.table = [] 8101e04c3fSmrg self.idxs = set() 8201e04c3fSmrg 8301e04c3fSmrg def add(self, array): 8401e04c3fSmrg # We might get lucky and find the array somewhere in the existing data 8501e04c3fSmrg try: 8601e04c3fSmrg idx = 0 8701e04c3fSmrg while True: 8801e04c3fSmrg idx = self.table.index(array[0], idx, len(self.table) - len(array) + 1) 8901e04c3fSmrg 9001e04c3fSmrg for i in range(1, len(array)): 9101e04c3fSmrg if array[i] != self.table[idx + i]: 9201e04c3fSmrg break 9301e04c3fSmrg else: 9401e04c3fSmrg self.idxs.add(idx) 9501e04c3fSmrg return idx 9601e04c3fSmrg 9701e04c3fSmrg idx += 1 9801e04c3fSmrg except ValueError: 9901e04c3fSmrg pass 10001e04c3fSmrg 10101e04c3fSmrg idx = len(self.table) 10201e04c3fSmrg self.table += array 10301e04c3fSmrg self.idxs.add(idx) 10401e04c3fSmrg return idx 10501e04c3fSmrg 10601e04c3fSmrg def emit(self, filp, name, static=True): 10701e04c3fSmrg """ 10801e04c3fSmrg Write 10901e04c3fSmrg [static] const typename name[] = { ... }; 11001e04c3fSmrg to filp. 11101e04c3fSmrg """ 11201e04c3fSmrg idxs = sorted(self.idxs) + [len(self.table)] 11301e04c3fSmrg 11401e04c3fSmrg fragments = [ 11501e04c3fSmrg ('\t/* %s */ %s' % ( 11601e04c3fSmrg idxs[i], 11701e04c3fSmrg ' '.join((str(elt) + ',') for elt in self.table[idxs[i]:idxs[i+1]]) 11801e04c3fSmrg )) 11901e04c3fSmrg for i in range(len(idxs) - 1) 12001e04c3fSmrg ] 12101e04c3fSmrg 12201e04c3fSmrg filp.write('%sconst %s %s[] = {\n%s\n};\n' % ( 12301e04c3fSmrg 'static ' if static else '', 12401e04c3fSmrg self.typename, name, 12501e04c3fSmrg '\n'.join(fragments) 12601e04c3fSmrg )) 12701e04c3fSmrg 12801e04c3fSmrgclass Field: 12901e04c3fSmrg def __init__(self, reg, s_name): 13001e04c3fSmrg self.s_name = s_name 13101e04c3fSmrg self.name = strip_prefix(s_name) 13201e04c3fSmrg self.values = [] 13301e04c3fSmrg self.varname_values = '%s__%s__values' % (reg.r_name.lower(), self.name.lower()) 13401e04c3fSmrg 13501e04c3fSmrgclass Reg: 13601e04c3fSmrg def __init__(self, r_name): 13701e04c3fSmrg self.r_name = r_name 13801e04c3fSmrg self.name = strip_prefix(r_name) 13901e04c3fSmrg self.fields = [] 14001e04c3fSmrg self.own_fields = True 14101e04c3fSmrg 14201e04c3fSmrg 14301e04c3fSmrgdef strip_prefix(s): 14401e04c3fSmrg '''Strip prefix in the form ._.*_, e.g. R_001234_''' 14501e04c3fSmrg return s[s[2:].find('_')+3:] 14601e04c3fSmrg 14701e04c3fSmrgdef parse(filename, regs, packets): 14801e04c3fSmrg stream = open(filename) 14901e04c3fSmrg 15001e04c3fSmrg for line in stream: 15101e04c3fSmrg if not line.startswith('#define '): 15201e04c3fSmrg continue 15301e04c3fSmrg 15401e04c3fSmrg line = line[8:].strip() 15501e04c3fSmrg 15601e04c3fSmrg if line.startswith('R_'): 15701e04c3fSmrg name = line.split()[0] 15801e04c3fSmrg 15901e04c3fSmrg for it in regs: 16001e04c3fSmrg if it.r_name == name: 16101e04c3fSmrg reg = it 16201e04c3fSmrg break 16301e04c3fSmrg else: 16401e04c3fSmrg reg = Reg(name) 16501e04c3fSmrg regs.append(reg) 16601e04c3fSmrg 16701e04c3fSmrg elif line.startswith('S_'): 16801e04c3fSmrg name = line[:line.find('(')] 16901e04c3fSmrg 17001e04c3fSmrg for it in reg.fields: 17101e04c3fSmrg if it.s_name == name: 17201e04c3fSmrg field = it 17301e04c3fSmrg break 17401e04c3fSmrg else: 17501e04c3fSmrg field = Field(reg, name) 17601e04c3fSmrg reg.fields.append(field) 17701e04c3fSmrg 17801e04c3fSmrg elif line.startswith('V_'): 17901e04c3fSmrg split = line.split() 18001e04c3fSmrg name = split[0] 18101e04c3fSmrg value = int(split[1], 0) 18201e04c3fSmrg 18301e04c3fSmrg for (n,v) in field.values: 18401e04c3fSmrg if n == name: 18501e04c3fSmrg if v != value: 18601e04c3fSmrg sys.exit('Value mismatch: name = ' + name) 18701e04c3fSmrg 18801e04c3fSmrg field.values.append((name, value)) 18901e04c3fSmrg 19001e04c3fSmrg elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1: 19101e04c3fSmrg packets.append(line.split()[0]) 19201e04c3fSmrg 19301e04c3fSmrg # Copy fields to indexed registers which have their fields only defined 19401e04c3fSmrg # at register index 0. 19501e04c3fSmrg # For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 0. 19601e04c3fSmrg match_number = re.compile('[0-9]+') 19701e04c3fSmrg reg_dict = dict() 19801e04c3fSmrg 19901e04c3fSmrg # Create a dict of registers with fields and '0' in their name 20001e04c3fSmrg for reg in regs: 20101e04c3fSmrg if len(reg.fields) and reg.name.find('0') != -1: 20201e04c3fSmrg reg_dict[reg.name] = reg 20301e04c3fSmrg 20401e04c3fSmrg # Assign fields 20501e04c3fSmrg for reg in regs: 20601e04c3fSmrg if not len(reg.fields): 20701e04c3fSmrg reg0 = reg_dict.get(match_number.sub('0', reg.name)) 20801e04c3fSmrg if reg0 != None: 20901e04c3fSmrg reg.fields = reg0.fields 21001e04c3fSmrg reg.fields_owner = reg0 21101e04c3fSmrg reg.own_fields = False 21201e04c3fSmrg 21301e04c3fSmrg 21401e04c3fSmrgdef write_tables(regs, packets): 21501e04c3fSmrg 21601e04c3fSmrg strings = StringTable() 21701e04c3fSmrg strings_offsets = IntTable("int") 21801e04c3fSmrg 21901e04c3fSmrg print('/* This file is autogenerated by egd_tables.py from evergreend.h. Do not edit directly. */') 22001e04c3fSmrg print() 22101e04c3fSmrg print(CopyRight.strip()) 22201e04c3fSmrg print(''' 22301e04c3fSmrg#ifndef EG_TABLES_H 22401e04c3fSmrg#define EG_TABLES_H 22501e04c3fSmrg 22601e04c3fSmrgstruct eg_field { 22701e04c3fSmrg unsigned name_offset; 22801e04c3fSmrg unsigned mask; 22901e04c3fSmrg unsigned num_values; 23001e04c3fSmrg unsigned values_offset; /* offset into eg_strings_offsets */ 23101e04c3fSmrg}; 23201e04c3fSmrg 23301e04c3fSmrgstruct eg_reg { 23401e04c3fSmrg unsigned name_offset; 23501e04c3fSmrg unsigned offset; 23601e04c3fSmrg unsigned num_fields; 23701e04c3fSmrg unsigned fields_offset; 23801e04c3fSmrg}; 23901e04c3fSmrg 24001e04c3fSmrgstruct eg_packet3 { 24101e04c3fSmrg unsigned name_offset; 24201e04c3fSmrg unsigned op; 24301e04c3fSmrg}; 24401e04c3fSmrg''') 24501e04c3fSmrg 24601e04c3fSmrg print('static const struct eg_packet3 packet3_table[] = {') 24701e04c3fSmrg for pkt in packets: 24801e04c3fSmrg print('\t{%s, %s},' % (strings.add(pkt[5:]), pkt)) 24901e04c3fSmrg print('};') 25001e04c3fSmrg print() 25101e04c3fSmrg 25201e04c3fSmrg print('static const struct eg_field egd_fields_table[] = {') 25301e04c3fSmrg 25401e04c3fSmrg fields_idx = 0 25501e04c3fSmrg for reg in regs: 25601e04c3fSmrg if len(reg.fields) and reg.own_fields: 25701e04c3fSmrg print('\t/* %s */' % (fields_idx)) 25801e04c3fSmrg 25901e04c3fSmrg reg.fields_idx = fields_idx 26001e04c3fSmrg 26101e04c3fSmrg for field in reg.fields: 26201e04c3fSmrg if len(field.values): 26301e04c3fSmrg values_offsets = [] 26401e04c3fSmrg for value in field.values: 26501e04c3fSmrg while value[1] >= len(values_offsets): 26601e04c3fSmrg values_offsets.append(-1) 26701e04c3fSmrg values_offsets[value[1]] = strings.add(strip_prefix(value[0])) 26801e04c3fSmrg print('\t{%s, %s(~0u), %s, %s},' % ( 26901e04c3fSmrg strings.add(field.name), field.s_name, 27001e04c3fSmrg len(values_offsets), strings_offsets.add(values_offsets))) 27101e04c3fSmrg else: 27201e04c3fSmrg print('\t{%s, %s(~0u)},' % (strings.add(field.name), field.s_name)) 27301e04c3fSmrg fields_idx += 1 27401e04c3fSmrg 27501e04c3fSmrg print('};') 27601e04c3fSmrg print() 27701e04c3fSmrg 27801e04c3fSmrg print('static const struct eg_reg egd_reg_table[] = {') 27901e04c3fSmrg for reg in regs: 28001e04c3fSmrg if len(reg.fields): 28101e04c3fSmrg print('\t{%s, %s, %s, %s},' % (strings.add(reg.name), reg.r_name, 28201e04c3fSmrg len(reg.fields), reg.fields_idx if reg.own_fields else reg.fields_owner.fields_idx)) 28301e04c3fSmrg else: 28401e04c3fSmrg print('\t{%s, %s},' % (strings.add(reg.name), reg.r_name)) 28501e04c3fSmrg print('};') 28601e04c3fSmrg print() 28701e04c3fSmrg 28801e04c3fSmrg strings.emit(sys.stdout, "egd_strings") 28901e04c3fSmrg 29001e04c3fSmrg print() 29101e04c3fSmrg 29201e04c3fSmrg strings_offsets.emit(sys.stdout, "egd_strings_offsets") 29301e04c3fSmrg 29401e04c3fSmrg print() 29501e04c3fSmrg print('#endif') 29601e04c3fSmrg 29701e04c3fSmrg 29801e04c3fSmrgdef main(): 29901e04c3fSmrg regs = [] 30001e04c3fSmrg packets = [] 30101e04c3fSmrg for arg in sys.argv[1:]: 30201e04c3fSmrg parse(arg, regs, packets) 30301e04c3fSmrg write_tables(regs, packets) 30401e04c3fSmrg 30501e04c3fSmrg 30601e04c3fSmrgif __name__ == '__main__': 30701e04c3fSmrg main() 30801e04c3fSmrg 30901e04c3fSmrg# kate: space-indent on; indent-width 4; replace-tabs on; 310