diff options
author | Nicolai Hähnle <[email protected]> | 2017-09-04 10:02:36 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2017-09-06 09:59:14 +0200 |
commit | 925ad7d2f62c680ffef5d72db8cedd273dc26625 (patch) | |
tree | 5d6dff8102a5f572ed1905644327673114699390 /src/amd/common | |
parent | 981335b704dc5a8984d30d656eeed1c59b05315a (diff) |
ac/sid_tables: add FieldTable object
Automatically re-use table entries like StringTable and IntTable do.
This allows us to get rid of the "fields_owner" logic, and simplifies
the next change.
Acked-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/amd/common')
-rw-r--r-- | src/amd/common/sid_tables.py | 115 |
1 files changed, 85 insertions, 30 deletions
diff --git a/src/amd/common/sid_tables.py b/src/amd/common/sid_tables.py index 01970caa7be..808a96f834f 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 |