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 <marek.olsak@amd.com> Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user