[Mesa-dev] [PATCH 2/4] ac/sid_tables: add FieldTable object
Nicolai Hähnle
nhaehnle at gmail.com
Mon Sep 4 12:11:05 UTC 2017
From: Nicolai Hähnle <nicolai.haehnle at amd.com>
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.
---
src/amd/common/sid_tables.py | 115 ++++++++++++++++++++++++++++++++-----------
1 file 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
@@ -18,20 +18,22 @@ CopyRight = '''
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
'''
+import collections
+import functools
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):
@@ -125,26 +127,102 @@ class IntTable:
self.typename, name,
'\n'.join(fragments)
))
class Field:
def __init__(self, reg, s_name):
self.s_name = s_name
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):
'''Strip prefix in the form ._.*_, e.g. R_001234_'''
return s[s[2:].find('_')+3:]
def parse(filename, regs, packets):
stream = open(filename)
for line in stream:
@@ -200,28 +278,27 @@ def parse(filename, regs, packets):
for reg in regs:
if len(reg.fields) and reg.name.find('0') != -1:
reg_dict[reg.name] = reg
# Assign fields
for reg in regs:
if not len(reg.fields):
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
print CopyRight.strip()
print '''
#ifndef SID_TABLES_H
#define SID_TABLES_H
struct si_field {
unsigned name_offset;
@@ -242,56 +319,34 @@ struct si_packet3 {
unsigned op;
};
'''
print 'static const struct si_packet3 packet3_table[] = {'
for pkt in packets:
print '\t{%s, %s},' % (strings.add(pkt[5:]), pkt)
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
strings_offsets.emit(sys.stdout, "sid_strings_offsets")
print
print '#endif'
--
2.11.0
More information about the mesa-dev
mailing list