summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeonsi/sid_tables.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/radeonsi/sid_tables.py')
-rwxr-xr-xsrc/gallium/drivers/radeonsi/sid_tables.py147
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;