Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / amd / common / sid_tables.py
1 from __future__ import print_function, division, unicode_literals
2
3 CopyRight = '''
4 /*
5 * Copyright 2015-2019 Advanced Micro Devices, Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27 '''
28
29 from collections import defaultdict
30 import functools
31 import itertools
32 import json
33 import os.path
34 import re
35 import sys
36
37 AMD_REGISTERS = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../registers"))
38 sys.path.append(AMD_REGISTERS)
39
40 from regdb import Object, RegisterDatabase
41
42
43 class StringTable:
44 """
45 A class for collecting multiple strings in a single larger string that is
46 used by indexing (to avoid relocations in the resulting binary)
47 """
48 def __init__(self):
49 self.table = []
50 self.length = 0
51
52 def add(self, string):
53 # We might get lucky with string being a suffix of a previously added string
54 for te in self.table:
55 if te[0].endswith(string):
56 idx = te[1] + len(te[0]) - len(string)
57 te[2].add(idx)
58 return idx
59
60 idx = self.length
61 self.table.append((string, idx, set((idx,))))
62 self.length += len(string) + 1
63
64 return idx
65
66 def emit(self, filp, name, static=True):
67 """
68 Write
69 [static] const char name[] = "...";
70 to filp.
71 """
72 fragments = [
73 '"%s\\0" /* %s */' % (
74 te[0].encode('unicode_escape').decode(),
75 ', '.join(str(idx) for idx in sorted(te[2]))
76 )
77 for te in self.table
78 ]
79 filp.write('%sconst char %s[] =\n%s;\n' % (
80 'static ' if static else '',
81 name,
82 '\n'.join('\t' + fragment for fragment in fragments)
83 ))
84
85 class IntTable:
86 """
87 A class for collecting multiple arrays of integers in a single big array
88 that is used by indexing (to avoid relocations in the resulting binary)
89 """
90 def __init__(self, typename):
91 self.typename = typename
92 self.table = []
93 self.idxs = set()
94
95 def add(self, array):
96 # We might get lucky and find the array somewhere in the existing data
97 try:
98 idx = 0
99 while True:
100 idx = self.table.index(array[0], idx, len(self.table) - len(array) + 1)
101
102 for i in range(1, len(array)):
103 if array[i] != self.table[idx + i]:
104 break
105 else:
106 self.idxs.add(idx)
107 return idx
108
109 idx += 1
110 except ValueError:
111 pass
112
113 idx = len(self.table)
114 self.table += array
115 self.idxs.add(idx)
116 return idx
117
118 def emit(self, filp, name, static=True):
119 """
120 Write
121 [static] const typename name[] = { ... };
122 to filp.
123 """
124 idxs = sorted(self.idxs) + [len(self.table)]
125
126 fragments = [
127 ('\t/* %s */ %s' % (
128 idxs[i],
129 ' '.join((str(elt) + ',') for elt in self.table[idxs[i]:idxs[i+1]])
130 ))
131 for i in range(len(idxs) - 1)
132 ]
133
134 filp.write('%sconst %s %s[] = {\n%s\n};\n' % (
135 'static ' if static else '',
136 self.typename, name,
137 '\n'.join(fragments)
138 ))
139
140 class Field:
141 def __init__(self, name, bits):
142 self.name = name
143 self.bits = bits # [first, last]
144 self.values = [] # [(name, value), ...]
145
146 def format(self, string_table, idx_table):
147 mask = ((1 << (self.bits[1] - self.bits[0] + 1)) - 1) << self.bits[0]
148 if len(self.values):
149 values_offsets = []
150 for value in self.values:
151 while value[1] >= len(values_offsets):
152 values_offsets.append(-1)
153 values_offsets[value[1]] = string_table.add(value[0])
154 return '{{{0}, 0x{mask:X}, {1}, {2}}}'.format(
155 string_table.add(self.name),
156 len(values_offsets), idx_table.add(values_offsets),
157 **locals()
158 )
159 else:
160 return '{{{0}, 0x{mask:X}}}'.format(string_table.add(self.name), **locals())
161
162 def __eq__(self, other):
163 return (self.name == other.name and
164 self.bits[0] == other.bits[0] and self.bits[1] == other.bits[1] and
165 len(self.values) == len(other.values) and
166 all(a[0] == b[0] and a[1] == b[1] for a, b, in zip(self.values, other.values)))
167
168 def __ne__(self, other):
169 return not (self == other)
170
171
172 class FieldTable:
173 """
174 A class for collecting multiple arrays of register fields in a single big
175 array that is used by indexing (to avoid relocations in the resulting binary)
176 """
177 def __init__(self):
178 self.table = []
179 self.idxs = set()
180 self.name_to_idx = defaultdict(lambda: [])
181
182 def add(self, array):
183 """
184 Add an array of Field objects, and return the index of where to find
185 the array in the table.
186 """
187 # Check if we can find the array in the table already
188 for base_idx in self.name_to_idx.get(array[0].name, []):
189 if base_idx + len(array) > len(self.table):
190 continue
191
192 for i, a in enumerate(array):
193 b = self.table[base_idx + i]
194 if a != b:
195 break
196 else:
197 return base_idx
198
199 base_idx = len(self.table)
200 self.idxs.add(base_idx)
201
202 for field in array:
203 self.name_to_idx[field.name].append(len(self.table))
204 self.table.append(field)
205
206 return base_idx
207
208 def emit(self, filp, string_table, idx_table):
209 """
210 Write
211 static const struct si_field sid_fields_table[] = { ... };
212 to filp.
213 """
214 idxs = sorted(self.idxs) + [len(self.table)]
215
216 filp.write('static const struct si_field sid_fields_table[] = {\n')
217
218 for start, end in zip(idxs, idxs[1:]):
219 filp.write('\t/* %s */\n' % (start))
220 for field in self.table[start:end]:
221 filp.write('\t%s,\n' % (field.format(string_table, idx_table)))
222
223 filp.write('};\n')
224
225
226 def parse_packet3(filp):
227 """
228 Parse PKT3 commands from the given header file.
229 """
230 packets = []
231 for line in filp:
232 if not line.startswith('#define '):
233 continue
234
235 line = line[8:].strip()
236
237 if line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1:
238 packets.append(line.split()[0])
239 return packets
240
241
242 class TableWriter(object):
243 def __init__(self):
244 self.__strings = StringTable()
245 self.__strings_offsets = IntTable('int')
246 self.__fields = FieldTable()
247
248 def write(self, regdb, packets, file=sys.stdout):
249 def out(*args):
250 print(*args, file=file)
251
252 out('/* This file is autogenerated by sid_tables.py from sid.h. Do not edit directly. */')
253 out()
254 out(CopyRight.strip())
255 out('''
256 #ifndef SID_TABLES_H
257 #define SID_TABLES_H
258
259 struct si_field {
260 unsigned name_offset;
261 unsigned mask;
262 unsigned num_values;
263 unsigned values_offset; /* offset into sid_strings_offsets */
264 };
265
266 struct si_reg {
267 unsigned name_offset;
268 unsigned offset;
269 unsigned num_fields;
270 unsigned fields_offset;
271 };
272
273 struct si_packet3 {
274 unsigned name_offset;
275 unsigned op;
276 };
277 ''')
278
279 out('static const struct si_packet3 packet3_table[] = {')
280 for pkt in packets:
281 out('\t{%s, %s},' % (self.__strings.add(pkt[5:]), pkt))
282 out('};')
283 out()
284
285 regmaps_by_chip = defaultdict(list)
286
287 for regmap in regdb.register_mappings():
288 for chip in regmap.chips:
289 regmaps_by_chip[chip].append(regmap)
290
291 regtypes = {}
292
293 # Sorted iteration over chips for deterministic builds
294 for chip in sorted(regmaps_by_chip.keys()):
295 regmaps = regmaps_by_chip[chip]
296 regmaps.sort(key=lambda regmap: (regmap.map.to, regmap.map.at))
297
298 out('static const struct si_reg {chip}_reg_table[] = {{'.format(**locals()))
299
300 for regmap in regmaps:
301 if hasattr(regmap, 'type_ref'):
302 if not regmap.type_ref in regtypes:
303 regtype = regdb.register_type(regmap.type_ref)
304 fields = []
305 for dbfield in regtype.fields:
306 field = Field(dbfield.name, dbfield.bits)
307 if hasattr(dbfield, 'enum_ref'):
308 enum = regdb.enum(dbfield.enum_ref)
309 for entry in enum.entries:
310 field.values.append((entry.name, entry.value))
311 fields.append(field)
312
313 num_fields = len(regtype.fields)
314 fields_offset = self.__fields.add(fields)
315 regtypes[regmap.type_ref] = (num_fields, fields_offset)
316 else:
317 num_fields, fields_offset = regtypes[regmap.type_ref]
318
319 print('\t{{{0}, {regmap.map.at}, {num_fields}, {fields_offset}}},'
320 .format(self.__strings.add(regmap.name), **locals()))
321 else:
322 print('\t{{{0}, {regmap.map.at}}},'
323 .format(self.__strings.add(regmap.name), **locals()))
324
325 out('};\n')
326
327 self.__fields.emit(file, self.__strings, self.__strings_offsets)
328
329 out()
330
331 self.__strings.emit(file, "sid_strings")
332
333 out()
334
335 self.__strings_offsets.emit(file, "sid_strings_offsets")
336
337 out()
338 out('#endif')
339
340
341 def main():
342 # Parse PKT3 types
343 with open(sys.argv[1], 'r') as filp:
344 packets = parse_packet3(filp)
345
346 # Register database parse
347 regdb = None
348 for filename in sys.argv[2:]:
349 with open(filename, 'r') as filp:
350 try:
351 db = RegisterDatabase.from_json(json.load(filp))
352 if regdb is None:
353 regdb = db
354 else:
355 regdb.update(db)
356 except json.JSONDecodeError as e:
357 print('Error reading {}'.format(sys.argv[1]), file=sys.stderr)
358 raise
359
360 # The ac_debug code only distinguishes by chip_class
361 regdb.merge_chips(['gfx8', 'fiji', 'stoney'], 'gfx8')
362
363 # Write it all out
364 w = TableWriter()
365 w.write(regdb, packets)
366
367 if __name__ == '__main__':
368 main()
369
370 # kate: space-indent on; indent-width 4; replace-tabs on;