From: Nicolai Hähnle Date: Sun, 8 May 2016 23:37:12 +0000 (-0500) Subject: radeonsi/sid_tables: store strings by offset instead of by pointer X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=54ab39caafab98751cd8813963d8c2b31dc420b5;p=mesa.git radeonsi/sid_tables: store strings by offset instead of by pointer This saves some space and avoids the need for relocations. Acked-by: Marek Olšák Reviewed-by: Bas Nieuwenhuizen --- diff --git a/src/gallium/drivers/radeonsi/si_debug.c b/src/gallium/drivers/radeonsi/si_debug.c index f227e5a7b09..3f87fd35473 100644 --- a/src/gallium/drivers/radeonsi/si_debug.c +++ b/src/gallium/drivers/radeonsi/si_debug.c @@ -187,13 +187,14 @@ static void si_dump_reg(FILE *file, unsigned offset, uint32_t value, for (r = 0; r < ARRAY_SIZE(reg_table); r++) { const struct si_reg *reg = ®_table[r]; + const char *reg_name = sid_strings + reg->name_offset; if (reg->offset == offset) { bool first_field = true; print_spaces(file, INDENT_PKT); fprintf(file, COLOR_YELLOW "%s" COLOR_RESET " <- ", - reg->name); + reg_name); if (!reg->num_fields) { print_value(file, value, 32); @@ -202,6 +203,7 @@ static void si_dump_reg(FILE *file, unsigned offset, uint32_t value, for (f = 0; f < reg->num_fields; f++) { const struct si_field *field = ®->fields[f]; + const int *values_offsets = sid_strings_offsets + field->values_offset; uint32_t val = (value & field->mask) >> (ffs(field->mask) - 1); @@ -211,13 +213,13 @@ static void si_dump_reg(FILE *file, unsigned offset, uint32_t value, /* Indent the field. */ if (!first_field) print_spaces(file, - INDENT_PKT + strlen(reg->name) + 4); + INDENT_PKT + strlen(reg_name) + 4); /* Print the field. */ - fprintf(file, "%s = ", field->name); + fprintf(file, "%s = ", sid_strings + field->name_offset); - if (val < field->num_values && field->values[val]) - fprintf(file, "%s\n", field->values[val]); + if (val < field->num_values && values_offsets[val] >= 0) + fprintf(file, "%s\n", sid_strings + values_offsets[val]); else print_value(file, val, util_bitcount(field->mask)); @@ -254,17 +256,19 @@ static uint32_t *si_parse_packet3(FILE *f, uint32_t *ib, int *num_dw, if (packet3_table[i].op == op) break; - if (i < ARRAY_SIZE(packet3_table)) + if (i < ARRAY_SIZE(packet3_table)) { + const char *name = sid_strings + packet3_table[i].name_offset; + if (op == PKT3_SET_CONTEXT_REG || op == PKT3_SET_CONFIG_REG || op == PKT3_SET_UCONFIG_REG || op == PKT3_SET_SH_REG) fprintf(f, COLOR_CYAN "%s%s" COLOR_CYAN ":\n", - packet3_table[i].name, predicate); + name, predicate); else fprintf(f, COLOR_GREEN "%s%s" COLOR_RESET ":\n", - packet3_table[i].name, predicate); - else + name, predicate); + } else fprintf(f, COLOR_RED "PKT3_UNKNOWN 0x%x%s" COLOR_RESET ":\n", op, predicate); 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,59 +212,65 @@ 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;