1 from __future__
import print_function
, division
, unicode_literals
5 * Copyright 2015-2019 Advanced Micro Devices, Inc.
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:
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
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.
29 from collections
import defaultdict
37 AMD_REGISTERS
= os
.path
.abspath(os
.path
.join(os
.path
.dirname(sys
.argv
[0]), "../registers"))
38 sys
.path
.append(AMD_REGISTERS
)
40 from regdb
import Object
, RegisterDatabase
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)
52 def add(self
, string
):
53 # We might get lucky with string being a suffix of a previously added string
55 if te
[0].endswith(string
):
56 idx
= te
[1] + len(te
[0]) - len(string
)
61 self
.table
.append((string
, idx
, set((idx
,))))
62 self
.length
+= len(string
) + 1
66 def emit(self
, filp
, name
, static
=True):
69 [static] const char name[] = "...";
73 '"%s\\0" /* %s */' % (
74 te
[0].encode('unicode_escape').decode(),
75 ', '.join(str(idx
) for idx
in sorted(te
[2]))
79 filp
.write('%sconst char %s[] =\n%s;\n' % (
80 'static ' if static
else '',
82 '\n'.join('\t' + fragment
for fragment
in fragments
)
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)
90 def __init__(self
, typename
):
91 self
.typename
= typename
96 # We might get lucky and find the array somewhere in the existing data
100 idx
= self
.table
.index(array
[0], idx
, len(self
.table
) - len(array
) + 1)
102 for i
in range(1, len(array
)):
103 if array
[i
] != self
.table
[idx
+ i
]:
113 idx
= len(self
.table
)
118 def emit(self
, filp
, name
, static
=True):
121 [static] const typename name[] = { ... };
124 idxs
= sorted(self
.idxs
) + [len(self
.table
)]
129 ' '.join((str(elt
) + ',') for elt
in self
.table
[idxs
[i
]:idxs
[i
+1]])
131 for i
in range(len(idxs
) - 1)
134 filp
.write('%sconst %s %s[] = {\n%s\n};\n' % (
135 'static ' if static
else '',
141 def __init__(self
, name
, bits
):
143 self
.bits
= bits
# [first, last]
144 self
.values
= [] # [(name, value), ...]
146 def format(self
, string_table
, idx_table
):
147 mask
= ((1 << (self
.bits
[1] - self
.bits
[0] + 1)) - 1) << self
.bits
[0]
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
),
160 return '{{{0}, 0x{mask:X}}}'.format(string_table
.add(self
.name
), **locals())
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
)))
168 def __ne__(self
, other
):
169 return not (self
== other
)
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)
180 self
.name_to_idx
= defaultdict(lambda: [])
182 def add(self
, array
):
184 Add an array of Field objects, and return the index of where to find
185 the array in the table.
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
):
192 for i
, a
in enumerate(array
):
193 b
= self
.table
[base_idx
+ i
]
199 base_idx
= len(self
.table
)
200 self
.idxs
.add(base_idx
)
203 self
.name_to_idx
[field
.name
].append(len(self
.table
))
204 self
.table
.append(field
)
208 def emit(self
, filp
, string_table
, idx_table
):
211 static const struct si_field sid_fields_table[] = { ... };
214 idxs
= sorted(self
.idxs
) + [len(self
.table
)]
216 filp
.write('static const struct si_field sid_fields_table[] = {\n')
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
)))
226 def parse_packet3(filp
):
228 Parse PKT3 commands from the given header file.
232 if not line
.startswith('#define '):
235 line
= line
[8:].strip()
237 if line
.startswith('PKT3_') and line
.find('0x') != -1 and line
.find('(') == -1:
238 packets
.append(line
.split()[0])
242 class TableWriter(object):
244 self
.__strings
= StringTable()
245 self
.__strings
_offsets
= IntTable('int')
246 self
.__fields
= FieldTable()
248 def write(self
, regdb
, packets
, file=sys
.stdout
):
250 print(*args
, file=file)
252 out('/* This file is autogenerated by sid_tables.py from sid.h. Do not edit directly. */')
254 out(CopyRight
.strip())
260 unsigned name_offset;
263 unsigned values_offset; /* offset into sid_strings_offsets */
267 unsigned name_offset;
270 unsigned fields_offset;
274 unsigned name_offset;
279 out('static const struct si_packet3 packet3_table[] = {')
281 out('\t{%s, %s},' % (self
.__strings
.add(pkt
[5:]), pkt
))
285 regmaps_by_chip
= defaultdict(list)
287 for regmap
in regdb
.register_mappings():
288 for chip
in regmap
.chips
:
289 regmaps_by_chip
[chip
].append(regmap
)
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
))
298 out('static const struct si_reg {chip}_reg_table[] = {{'.format(**locals()))
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
)
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
))
313 num_fields
= len(regtype
.fields
)
314 fields_offset
= self
.__fields
.add(fields
)
315 regtypes
[regmap
.type_ref
] = (num_fields
, fields_offset
)
317 num_fields
, fields_offset
= regtypes
[regmap
.type_ref
]
319 print('\t{{{0}, {regmap.map.at}, {num_fields}, {fields_offset}}},'
320 .format(self
.__strings
.add(regmap
.name
), **locals()))
322 print('\t{{{0}, {regmap.map.at}}},'
323 .format(self
.__strings
.add(regmap
.name
), **locals()))
327 self
.__fields
.emit(file, self
.__strings
, self
.__strings
_offsets
)
331 self
.__strings
.emit(file, "sid_strings")
335 self
.__strings
_offsets
.emit(file, "sid_strings_offsets")
343 with
open(sys
.argv
[1], 'r') as filp
:
344 packets
= parse_packet3(filp
)
346 # Register database parse
348 for filename
in sys
.argv
[2:]:
349 with
open(filename
, 'r') as filp
:
351 db
= RegisterDatabase
.from_json(json
.load(filp
))
356 except json
.JSONDecodeError
as e
:
357 print('Error reading {}'.format(sys
.argv
[1]), file=sys
.stderr
)
360 # The ac_debug code only distinguishes by chip_class
361 regdb
.merge_chips(['gfx8', 'fiji', 'stoney'], 'gfx8')
365 w
.write(regdb
, packets
)
367 if __name__
== '__main__':
370 # kate: space-indent on; indent-width 4; replace-tabs on;