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 <marek.olsak@amd.com>
This commit is contained in:
Nicolai Hähnle 2017-09-04 10:02:36 +02:00
parent 981335b704
commit 925ad7d2f6

View file

@ -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