1 from __future__
import print_function
5 * Copyright 2015 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.
35 A class for collecting multiple strings in a single larger string that is
36 used by indexing (to avoid relocations in the resulting binary)
42 def add(self
, string
):
43 # We might get lucky with string being a suffix of a previously added string
45 if te
[0].endswith(string
):
46 idx
= te
[1] + len(te
[0]) - len(string
)
51 self
.table
.append((string
, idx
, set((idx
,))))
52 self
.length
+= len(string
) + 1
56 def emit(self
, filp
, name
, static
=True):
59 [static] const char name[] = "...";
63 '"%s\\0" /* %s */' % (
64 te
[0].encode('unicode_escape').decode(),
65 ', '.join(str(idx
) for idx
in te
[2])
69 filp
.write('%sconst char %s[] =\n%s;\n' % (
70 'static ' if static
else '',
72 '\n'.join('\t' + fragment
for fragment
in fragments
)
77 A class for collecting multiple arrays of integers in a single big array
78 that is used by indexing (to avoid relocations in the resulting binary)
80 def __init__(self
, typename
):
81 self
.typename
= typename
86 # We might get lucky and find the array somewhere in the existing data
90 idx
= self
.table
.index(array
[0], idx
, len(self
.table
) - len(array
) + 1)
92 for i
in range(1, len(array
)):
93 if array
[i
] != self
.table
[idx
+ i
]:
103 idx
= len(self
.table
)
108 def emit(self
, filp
, name
, static
=True):
111 [static] const typename name[] = { ... };
114 idxs
= sorted(self
.idxs
) + [len(self
.table
)]
119 ' '.join((str(elt
) + ',') for elt
in self
.table
[idxs
[i
]:idxs
[i
+1]])
121 for i
in range(len(idxs
) - 1)
124 filp
.write('%sconst %s %s[] = {\n%s\n};\n' % (
125 'static ' if static
else '',
131 def __init__(self
, reg
, s_name
):
133 self
.name
= strip_prefix(s_name
)
135 self
.varname_values
= '%s__%s__values' % (reg
.r_name
.lower(), self
.name
.lower())
138 def __init__(self
, r_name
):
140 self
.name
= strip_prefix(r_name
)
142 self
.own_fields
= True
146 '''Strip prefix in the form ._.*_, e.g. R_001234_'''
147 return s
[s
[2:].find('_')+3:]
149 def parse(filename
, regs
, packets
):
150 stream
= open(filename
)
153 if not line
.startswith('#define '):
156 line
= line
[8:].strip()
158 if line
.startswith('R_'):
159 name
= line
.split()[0]
162 if it
.r_name
== name
:
169 elif line
.startswith('S_'):
170 name
= line
[:line
.find('(')]
172 for it
in reg
.fields
:
173 if it
.s_name
== name
:
177 field
= Field(reg
, name
)
178 reg
.fields
.append(field
)
180 elif line
.startswith('V_'):
183 value
= int(split
[1], 0)
185 for (n
,v
) in field
.values
:
188 sys
.exit('Value mismatch: name = ' + name
)
190 field
.values
.append((name
, value
))
192 elif line
.startswith('PKT3_') and line
.find('0x') != -1 and line
.find('(') == -1:
193 packets
.append(line
.split()[0])
195 # Copy fields to indexed registers which have their fields only defined
196 # at register index 0.
197 # For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 0.
198 match_number
= re
.compile('[0-9]+')
201 # Create a dict of registers with fields and '0' in their name
203 if len(reg
.fields
) and reg
.name
.find('0') != -1:
204 reg_dict
[reg
.name
] = reg
208 if not len(reg
.fields
):
209 reg0
= reg_dict
.get(match_number
.sub('0', reg
.name
))
211 reg
.fields
= reg0
.fields
212 reg
.fields_owner
= reg0
213 reg
.own_fields
= False
216 def write_tables(regs
, packets
):
218 strings
= StringTable()
219 strings_offsets
= IntTable("int")
221 print('/* This file is autogenerated by egd_tables.py from evergreend.h. Do not edit directly. */')
223 print(CopyRight
.strip())
229 unsigned name_offset;
232 unsigned values_offset; /* offset into eg_strings_offsets */
236 unsigned name_offset;
239 unsigned fields_offset;
243 unsigned name_offset;
248 print('static const struct eg_packet3 packet3_table[] = {')
250 print('\t{%s, %s},' % (strings
.add(pkt
[5:]), pkt
))
254 print('static const struct eg_field egd_fields_table[] = {')
258 if len(reg
.fields
) and reg
.own_fields
:
259 print('\t/* %s */' % (fields_idx
))
261 reg
.fields_idx
= fields_idx
263 for field
in reg
.fields
:
264 if len(field
.values
):
266 for value
in field
.values
:
267 while value
[1] >= len(values_offsets
):
268 values_offsets
.append(-1)
269 values_offsets
[value
[1]] = strings
.add(strip_prefix(value
[0]))
270 print('\t{%s, %s(~0u), %s, %s},' % (
271 strings
.add(field
.name
), field
.s_name
,
272 len(values_offsets
), strings_offsets
.add(values_offsets
)))
274 print('\t{%s, %s(~0u)},' % (strings
.add(field
.name
), field
.s_name
))
280 print('static const struct eg_reg egd_reg_table[] = {')
283 print('\t{%s, %s, %s, %s},' % (strings
.add(reg
.name
), reg
.r_name
,
284 len(reg
.fields
), reg
.fields_idx
if reg
.own_fields
else reg
.fields_owner
.fields_idx
))
286 print('\t{%s, %s},' % (strings
.add(reg
.name
), reg
.r_name
))
290 strings
.emit(sys
.stdout
, "egd_strings")
294 strings_offsets
.emit(sys
.stdout
, "egd_strings_offsets")
303 for arg
in sys
.argv
[1:]:
304 parse(arg
, regs
, packets
)
305 write_tables(regs
, packets
)
308 if __name__
== '__main__':
311 # kate: space-indent on; indent-width 4; replace-tabs on;