diff options
Diffstat (limited to 'src/gallium/drivers/radeonsi/sid_tables.py')
-rwxr-xr-x | src/gallium/drivers/radeonsi/sid_tables.py | 147 |
1 files changed, 128 insertions, 19 deletions
diff --git a/src/gallium/drivers/radeonsi/sid_tables.py b/src/gallium/drivers/radeonsi/sid_tables.py index 1fe5d3c589a..59954c55dfb 100755 --- a/src/gallium/drivers/radeonsi/sid_tables.py +++ b/src/gallium/drivers/radeonsi/sid_tables.py @@ -30,6 +30,103 @@ import sys import re +class StringTable: + """ + A class for collecting multiple strings in a single larger string that is + used by indexing (to avoid relocations in the resulting binary) + """ + def __init__(self): + self.table = [] + self.length = 0 + + def add(self, string): + # We might get lucky with string being a suffix of a previously added string + for te in self.table: + if te[0].endswith(string): + idx = te[1] + len(te[0]) - len(string) + te[2].add(idx) + return idx + + idx = self.length + self.table.append((string, idx, set((idx,)))) + self.length += len(string) + 1 + + return idx + + def emit(self, filp, name, static=True): + """ + Write + [static] const char name[] = "..."; + to filp. + """ + fragments = [ + '"%s\\0" /* %s */' % ( + te[0].encode('string_escape'), + ', '.join(str(idx) for idx in te[2]) + ) + for te in self.table + ] + filp.write('%sconst char %s[] =\n%s;\n' % ( + 'static ' if static else '', + name, + '\n'.join('\t' + fragment for fragment in fragments) + )) + +class IntTable: + """ + A class for collecting multiple arrays of integers in a single big array + that is used by indexing (to avoid relocations in the resulting binary) + """ + def __init__(self, typename): + self.typename = typename + self.table = [] + self.idxs = set() + + def add(self, array): + # We might get lucky and find the array somewhere in the existing data + try: + idx = 0 + while True: + idx = self.table.index(array[0], idx, len(self.table) - len(array) + 1) + + for i in range(1, len(array)): + if array[i] != self.table[idx + i]: + break + else: + self.idxs.add(idx) + return idx + + idx += 1 + except ValueError: + pass + + idx = len(self.table) + self.table += array + self.idxs.add(idx) + return idx + + def emit(self, filp, name, static=True): + """ + Write + [static] const typename name[] = { ... }; + to filp. + """ + idxs = sorted(self.idxs) + [-1] + + fragments = [ + ('\t/* %s */ %s' % ( + idxs[i], + ' '.join((str(elt) + ',') for elt in self.table[idxs[i]:idxs[i+1]]) + )) + for i in range(len(idxs) - 1) + ] + + filp.write('%sconst %s %s[] = {\n%s\n};\n' % ( + 'static ' if static else '', + self.typename, name, + '\n'.join(fragments) + )) + class Field: def __init__(self, reg, s_name): self.s_name = s_name @@ -71,7 +168,8 @@ def parse(filename): reg.fields.append(field) elif line.startswith('V_'): - field.values.append(line.split()[0]) + split = line.split() + field.values.append((split[0], int(split[1], 0))) elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1: packets.append(line.split()[0]) @@ -103,6 +201,9 @@ def write_tables(tables): regs = tables[0] packets = tables[1] + strings = StringTable() + strings_offsets = IntTable("int") + print '/* This file is autogenerated by sid_tables.py from sid.h. Do not edit directly. */' print print CopyRight.strip() @@ -111,60 +212,66 @@ def write_tables(tables): #define SID_TABLES_H struct si_field { - const char *name; + unsigned name_offset; unsigned mask; unsigned num_values; - const char **values; + unsigned values_offset; /* offset into sid_strings_offsets */ }; struct si_reg { - const char *name; + unsigned name_offset; unsigned offset; unsigned num_fields; const struct si_field *fields; }; struct si_packet3 { - const char *name; + unsigned name_offset; unsigned op; }; ''' print 'static const struct si_packet3 packet3_table[] = {' for pkt in packets: - print '\t{"%s", %s},' % (pkt[5:], pkt) + print '\t{%s, %s},' % (strings.add(pkt[5:]), pkt) print '};' print for reg in regs: if len(reg.fields) and reg.own_fields: - for field in reg.fields: - if len(field.values): - print 'static const char *%s[] = {' % (field.varname_values) - for value in field.values: - print '\t[%s] = "%s",' % (value, strip_prefix(value)) - print '};' - print - print 'static const struct si_field %s[] = {' % (reg.varname_fields) for field in reg.fields: if len(field.values): - print '\t{"%s", %s(~0u), ARRAY_SIZE(%s), %s},' % (field.name, - field.s_name, field.varname_values, field.varname_values) + values_offsets = [] + for value in field.values: + while value[1] >= len(values_offsets): + values_offsets.append(-1) + values_offsets[value[1]] = strings.add(strip_prefix(value[0])) + print '\t{%s, %s(~0u), %s, %s},' % ( + strings.add(field.name), field.s_name, + len(values_offsets), strings_offsets.add(values_offsets)) else: - print '\t{"%s", %s(~0u)},' % (field.name, field.s_name) + print '\t{%s, %s(~0u)},' % (strings.add(field.name), field.s_name) print '};' print print 'static const struct si_reg reg_table[] = {' for reg in regs: if len(reg.fields): - print '\t{"%s", %s, ARRAY_SIZE(%s), %s},' % (reg.name, reg.r_name, + print '\t{%s, %s, ARRAY_SIZE(%s), %s},' % (strings.add(reg.name), reg.r_name, reg.varname_fields, reg.varname_fields) else: - print '\t{"%s", %s},' % (reg.name, reg.r_name) + print '\t{%s, %s},' % (strings.add(reg.name), reg.r_name) print '};' print + + strings.emit(sys.stdout, "sid_strings") + + print + + strings_offsets.emit(sys.stdout, "sid_strings_offsets") + + print print '#endif' @@ -177,3 +284,5 @@ def main(): if __name__ == '__main__': main() + +# kate: space-indent on; indent-width 4; replace-tabs on; |