summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/amd/common/sid_tables.py115
1 files changed, 85 insertions, 30 deletions
diff --git a/src/amd/common/sid_tables.py b/src/amd/common/sid_tables.py
index 01970caa7b..808a96f834 100644
--- a/src/amd/common/sid_tables.py
+++ b/src/amd/common/sid_tables.py
@@ -25,6 +25,8 @@ CopyRight = '''
*/
'''
+import collections
+import functools
import sys
import re
@@ -132,12 +134,88 @@ class Field:
self.name = strip_prefix(s_name)
self.values = []
+ def format(self, string_table, idx_table):
+ if len(self.values):
+ values_offsets = []
+ for value in self.values:
+ while value[1] >= len(values_offsets):
+ values_offsets.append(-1)
+ values_offsets[value[1]] = string_table.add(strip_prefix(value[0]))
+ return '{%s, %s(~0u), %s, %s}' % (
+ string_table.add(self.name), self.s_name,
+ len(values_offsets), idx_table.add(values_offsets))
+ else:
+ return '{%s, %s(~0u)}' % (string_table.add(self.name), self.s_name)
+
+ def __eq__(self, other):
+ return (self.s_name == other.s_name and
+ self.name == other.name and
+ len(self.values) == len(other.values) and
+ all(a[0] == b[0] and a[1] == b[1] for a, b, in zip(self.values, other.values)))
+
+ def __ne__(self, other):
+ return not (self == other)
+
+
+class FieldTable:
+ """
+ A class for collecting multiple arrays of register fields in a single big
+ array that is used by indexing (to avoid relocations in the resulting binary)
+ """
+ def __init__(self):
+ self.table = []
+ self.idxs = set()
+ self.name_to_idx = collections.defaultdict(lambda: [])
+
+ def add(self, array):
+ """
+ Add an array of Field objects, and return the index of where to find
+ the array in the table.
+ """
+ # Check if we can find the array in the table already
+ for base_idx in self.name_to_idx.get(array[0].name, []):
+ if base_idx + len(array) > len(self.table):
+ continue
+
+ for i, a in enumerate(array):
+ b = self.table[base_idx + i]
+ if a != b:
+ break
+ else:
+ return base_idx
+
+ base_idx = len(self.table)
+ self.idxs.add(base_idx)
+
+ for field in array:
+ self.name_to_idx[field.name].append(len(self.table))
+ self.table.append(field)
+
+ return base_idx
+
+ def emit(self, filp, string_table, idx_table):
+ """
+ Write
+ static const struct si_field sid_fields_table[] = { ... };
+ to filp.
+ """
+ idxs = sorted(self.idxs) + [len(self.table)]
+
+ filp.write('static const struct si_field sid_fields_table[] = {\n')
+
+ for start, end in zip(idxs, idxs[1:]):
+ filp.write('\t/* %s */\n' % (start))
+ for field in self.table[start:end]:
+ filp.write('\t%s,\n' % (field.format(string_table, idx_table)))
+
+ filp.write('};\n')
+
+
class Reg:
def __init__(self, r_name):
self.r_name = r_name
self.name = strip_prefix(r_name)
self.fields = []
- self.own_fields = True
def strip_prefix(s):
@@ -207,14 +285,13 @@ def parse(filename, regs, packets):
reg0 = reg_dict.get(match_number.sub('0', reg.name))
if reg0 != None:
reg.fields = reg0.fields
- reg.fields_owner = reg0
- reg.own_fields = False
def write_tables(regs, packets):
strings = StringTable()
strings_offsets = IntTable("int")
+ fields = FieldTable()
print '/* This file is autogenerated by sid_tables.py from sid.h. Do not edit directly. */'
print
@@ -249,42 +326,20 @@ struct si_packet3 {
print '};'
print
- print 'static const struct si_field sid_fields_table[] = {'
-
- fields_idx = 0
- for reg in regs:
- if len(reg.fields) and reg.own_fields:
- print '\t/* %s */' % (fields_idx)
-
- reg.fields_idx = fields_idx
-
- for field in reg.fields:
- if len(field.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)},' % (strings.add(field.name), field.s_name)
- fields_idx += 1
-
- print '};'
- print
-
print 'static const struct si_reg sid_reg_table[] = {'
for reg in regs:
if len(reg.fields):
print '\t{%s, %s, %s, %s},' % (strings.add(reg.name), reg.r_name,
- len(reg.fields), reg.fields_idx if reg.own_fields else reg.fields_owner.fields_idx)
+ len(reg.fields), fields.add(reg.fields))
else:
print '\t{%s, %s},' % (strings.add(reg.name), reg.r_name)
print '};'
print
+ fields.emit(sys.stdout, strings, strings_offsets)
+
+ print
+
strings.emit(sys.stdout, "sid_strings")
print