1bf215546Sopenharmony_ciCopyRight = '''
2bf215546Sopenharmony_ci/*
3bf215546Sopenharmony_ci * Copyright 2015 Advanced Micro Devices, Inc.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci */
25bf215546Sopenharmony_ci'''
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ciimport sys
28bf215546Sopenharmony_ciimport re
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ciclass StringTable:
32bf215546Sopenharmony_ci    """
33bf215546Sopenharmony_ci    A class for collecting multiple strings in a single larger string that is
34bf215546Sopenharmony_ci    used by indexing (to avoid relocations in the resulting binary)
35bf215546Sopenharmony_ci    """
36bf215546Sopenharmony_ci    def __init__(self):
37bf215546Sopenharmony_ci        self.table = []
38bf215546Sopenharmony_ci        self.length = 0
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci    def add(self, string):
41bf215546Sopenharmony_ci        # We might get lucky with string being a suffix of a previously added string
42bf215546Sopenharmony_ci        for te in self.table:
43bf215546Sopenharmony_ci            if te[0].endswith(string):
44bf215546Sopenharmony_ci                idx = te[1] + len(te[0]) - len(string)
45bf215546Sopenharmony_ci                te[2].add(idx)
46bf215546Sopenharmony_ci                return idx
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci        idx = self.length
49bf215546Sopenharmony_ci        self.table.append((string, idx, set((idx,))))
50bf215546Sopenharmony_ci        self.length += len(string) + 1
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci        return idx
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci    def emit(self, filp, name, static=True):
55bf215546Sopenharmony_ci        """
56bf215546Sopenharmony_ci        Write
57bf215546Sopenharmony_ci        [static] const char name[] = "...";
58bf215546Sopenharmony_ci        to filp.
59bf215546Sopenharmony_ci        """
60bf215546Sopenharmony_ci        fragments = [
61bf215546Sopenharmony_ci            '"%s\\0" /* %s */' % (
62bf215546Sopenharmony_ci                te[0].encode('unicode_escape').decode(),
63bf215546Sopenharmony_ci                ', '.join(str(idx) for idx in te[2])
64bf215546Sopenharmony_ci            )
65bf215546Sopenharmony_ci            for te in self.table
66bf215546Sopenharmony_ci        ]
67bf215546Sopenharmony_ci        filp.write('%sconst char %s[] =\n%s;\n' % (
68bf215546Sopenharmony_ci            'static ' if static else '',
69bf215546Sopenharmony_ci            name,
70bf215546Sopenharmony_ci            '\n'.join('\t' + fragment for fragment in fragments)
71bf215546Sopenharmony_ci        ))
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ciclass IntTable:
74bf215546Sopenharmony_ci    """
75bf215546Sopenharmony_ci    A class for collecting multiple arrays of integers in a single big array
76bf215546Sopenharmony_ci    that is used by indexing (to avoid relocations in the resulting binary)
77bf215546Sopenharmony_ci    """
78bf215546Sopenharmony_ci    def __init__(self, typename):
79bf215546Sopenharmony_ci        self.typename = typename
80bf215546Sopenharmony_ci        self.table = []
81bf215546Sopenharmony_ci        self.idxs = set()
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci    def add(self, array):
84bf215546Sopenharmony_ci        # We might get lucky and find the array somewhere in the existing data
85bf215546Sopenharmony_ci        try:
86bf215546Sopenharmony_ci            idx = 0
87bf215546Sopenharmony_ci            while True:
88bf215546Sopenharmony_ci                idx = self.table.index(array[0], idx, len(self.table) - len(array) + 1)
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci                for i in range(1, len(array)):
91bf215546Sopenharmony_ci                    if array[i] != self.table[idx + i]:
92bf215546Sopenharmony_ci                        break
93bf215546Sopenharmony_ci                else:
94bf215546Sopenharmony_ci                    self.idxs.add(idx)
95bf215546Sopenharmony_ci                    return idx
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci                idx += 1
98bf215546Sopenharmony_ci        except ValueError:
99bf215546Sopenharmony_ci            pass
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci        idx = len(self.table)
102bf215546Sopenharmony_ci        self.table += array
103bf215546Sopenharmony_ci        self.idxs.add(idx)
104bf215546Sopenharmony_ci        return idx
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci    def emit(self, filp, name, static=True):
107bf215546Sopenharmony_ci        """
108bf215546Sopenharmony_ci        Write
109bf215546Sopenharmony_ci        [static] const typename name[] = { ... };
110bf215546Sopenharmony_ci        to filp.
111bf215546Sopenharmony_ci        """
112bf215546Sopenharmony_ci        idxs = sorted(self.idxs) + [len(self.table)]
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci        fragments = [
115bf215546Sopenharmony_ci            ('\t/* %s */ %s' % (
116bf215546Sopenharmony_ci                idxs[i],
117bf215546Sopenharmony_ci                ' '.join((str(elt) + ',') for elt in self.table[idxs[i]:idxs[i+1]])
118bf215546Sopenharmony_ci            ))
119bf215546Sopenharmony_ci            for i in range(len(idxs) - 1)
120bf215546Sopenharmony_ci        ]
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci        filp.write('%sconst %s %s[] = {\n%s\n};\n' % (
123bf215546Sopenharmony_ci            'static ' if static else '',
124bf215546Sopenharmony_ci            self.typename, name,
125bf215546Sopenharmony_ci            '\n'.join(fragments)
126bf215546Sopenharmony_ci        ))
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ciclass Field:
129bf215546Sopenharmony_ci    def __init__(self, reg, s_name):
130bf215546Sopenharmony_ci        self.s_name = s_name
131bf215546Sopenharmony_ci        self.name = strip_prefix(s_name)
132bf215546Sopenharmony_ci        self.values = []
133bf215546Sopenharmony_ci        self.varname_values = '%s__%s__values' % (reg.r_name.lower(), self.name.lower())
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ciclass Reg:
136bf215546Sopenharmony_ci    def __init__(self, r_name):
137bf215546Sopenharmony_ci        self.r_name = r_name
138bf215546Sopenharmony_ci        self.name = strip_prefix(r_name)
139bf215546Sopenharmony_ci        self.fields = []
140bf215546Sopenharmony_ci        self.own_fields = True
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_cidef strip_prefix(s):
144bf215546Sopenharmony_ci    '''Strip prefix in the form ._.*_, e.g. R_001234_'''
145bf215546Sopenharmony_ci    return s[s[2:].find('_')+3:]
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_cidef parse(filename, regs, packets):
148bf215546Sopenharmony_ci    stream = open(filename)
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci    for line in stream:
151bf215546Sopenharmony_ci        if not line.startswith('#define '):
152bf215546Sopenharmony_ci            continue
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci        line = line[8:].strip()
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci        if line.startswith('R_'):
157bf215546Sopenharmony_ci            name = line.split()[0]
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci            for it in regs:
160bf215546Sopenharmony_ci                if it.r_name == name:
161bf215546Sopenharmony_ci                    reg = it
162bf215546Sopenharmony_ci                    break
163bf215546Sopenharmony_ci            else:
164bf215546Sopenharmony_ci                reg = Reg(name)
165bf215546Sopenharmony_ci                regs.append(reg)
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci        elif line.startswith('S_'):
168bf215546Sopenharmony_ci            name = line[:line.find('(')]
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci            for it in reg.fields:
171bf215546Sopenharmony_ci                if it.s_name == name:
172bf215546Sopenharmony_ci                    field = it
173bf215546Sopenharmony_ci                    break
174bf215546Sopenharmony_ci            else:
175bf215546Sopenharmony_ci                field = Field(reg, name)
176bf215546Sopenharmony_ci                reg.fields.append(field)
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci        elif line.startswith('V_'):
179bf215546Sopenharmony_ci            split = line.split()
180bf215546Sopenharmony_ci            name = split[0]
181bf215546Sopenharmony_ci            value = int(split[1], 0)
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci            for (n,v) in field.values:
184bf215546Sopenharmony_ci                if n == name:
185bf215546Sopenharmony_ci                    if v != value:
186bf215546Sopenharmony_ci                        sys.exit('Value mismatch: name = ' + name)
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci            field.values.append((name, value))
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci        elif line.startswith('PKT3_') and line.find('0x') != -1 and line.find('(') == -1:
191bf215546Sopenharmony_ci            packets.append(line.split()[0])
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci    # Copy fields to indexed registers which have their fields only defined
194bf215546Sopenharmony_ci    # at register index 0.
195bf215546Sopenharmony_ci    # For example, copy fields from CB_COLOR0_INFO to CB_COLORn_INFO, n > 0.
196bf215546Sopenharmony_ci    match_number = re.compile('[0-9]+')
197bf215546Sopenharmony_ci    reg_dict = dict()
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci    # Create a dict of registers with fields and '0' in their name
200bf215546Sopenharmony_ci    for reg in regs:
201bf215546Sopenharmony_ci        if len(reg.fields) and reg.name.find('0') != -1:
202bf215546Sopenharmony_ci            reg_dict[reg.name] = reg
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci    # Assign fields
205bf215546Sopenharmony_ci    for reg in regs:
206bf215546Sopenharmony_ci        if not len(reg.fields):
207bf215546Sopenharmony_ci            reg0 = reg_dict.get(match_number.sub('0', reg.name))
208bf215546Sopenharmony_ci            if reg0 != None:
209bf215546Sopenharmony_ci                reg.fields = reg0.fields
210bf215546Sopenharmony_ci                reg.fields_owner = reg0
211bf215546Sopenharmony_ci                reg.own_fields = False
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_cidef write_tables(regs, packets):
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci    strings = StringTable()
217bf215546Sopenharmony_ci    strings_offsets = IntTable("int")
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci    print('/* This file is autogenerated by egd_tables.py from evergreend.h. Do not edit directly. */')
220bf215546Sopenharmony_ci    print()
221bf215546Sopenharmony_ci    print(CopyRight.strip())
222bf215546Sopenharmony_ci    print('''
223bf215546Sopenharmony_ci#ifndef EG_TABLES_H
224bf215546Sopenharmony_ci#define EG_TABLES_H
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_cistruct eg_field {
227bf215546Sopenharmony_ci        unsigned name_offset;
228bf215546Sopenharmony_ci        unsigned mask;
229bf215546Sopenharmony_ci        unsigned num_values;
230bf215546Sopenharmony_ci        unsigned values_offset; /* offset into eg_strings_offsets */
231bf215546Sopenharmony_ci};
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_cistruct eg_reg {
234bf215546Sopenharmony_ci        unsigned name_offset;
235bf215546Sopenharmony_ci        unsigned offset;
236bf215546Sopenharmony_ci        unsigned num_fields;
237bf215546Sopenharmony_ci        unsigned fields_offset;
238bf215546Sopenharmony_ci};
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_cistruct eg_packet3 {
241bf215546Sopenharmony_ci        unsigned name_offset;
242bf215546Sopenharmony_ci        unsigned op;
243bf215546Sopenharmony_ci};
244bf215546Sopenharmony_ci''')
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci    print('static const struct eg_packet3 packet3_table[] = {')
247bf215546Sopenharmony_ci    for pkt in packets:
248bf215546Sopenharmony_ci        print('\t{%s, %s},' % (strings.add(pkt[5:]), pkt))
249bf215546Sopenharmony_ci    print('};')
250bf215546Sopenharmony_ci    print()
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci    print('static const struct eg_field egd_fields_table[] = {')
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci    fields_idx = 0
255bf215546Sopenharmony_ci    for reg in regs:
256bf215546Sopenharmony_ci        if len(reg.fields) and reg.own_fields:
257bf215546Sopenharmony_ci            print('\t/* %s */' % (fields_idx))
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci            reg.fields_idx = fields_idx
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci            for field in reg.fields:
262bf215546Sopenharmony_ci                if len(field.values):
263bf215546Sopenharmony_ci                    values_offsets = []
264bf215546Sopenharmony_ci                    for value in field.values:
265bf215546Sopenharmony_ci                        while value[1] >= len(values_offsets):
266bf215546Sopenharmony_ci                            values_offsets.append(-1)
267bf215546Sopenharmony_ci                        values_offsets[value[1]] = strings.add(strip_prefix(value[0]))
268bf215546Sopenharmony_ci                    print('\t{%s, %s(~0u), %s, %s},' % (
269bf215546Sopenharmony_ci                        strings.add(field.name), field.s_name,
270bf215546Sopenharmony_ci                        len(values_offsets), strings_offsets.add(values_offsets)))
271bf215546Sopenharmony_ci                else:
272bf215546Sopenharmony_ci                    print('\t{%s, %s(~0u)},' % (strings.add(field.name), field.s_name))
273bf215546Sopenharmony_ci                fields_idx += 1
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci    print('};')
276bf215546Sopenharmony_ci    print()
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci    print('static const struct eg_reg egd_reg_table[] = {')
279bf215546Sopenharmony_ci    for reg in regs:
280bf215546Sopenharmony_ci        if len(reg.fields):
281bf215546Sopenharmony_ci            print('\t{%s, %s, %s, %s},' % (strings.add(reg.name), reg.r_name,
282bf215546Sopenharmony_ci                len(reg.fields), reg.fields_idx if reg.own_fields else reg.fields_owner.fields_idx))
283bf215546Sopenharmony_ci        else:
284bf215546Sopenharmony_ci            print('\t{%s, %s},' % (strings.add(reg.name), reg.r_name))
285bf215546Sopenharmony_ci    print('};')
286bf215546Sopenharmony_ci    print()
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci    strings.emit(sys.stdout, "egd_strings")
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_ci    print()
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci    strings_offsets.emit(sys.stdout, "egd_strings_offsets")
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci    print()
295bf215546Sopenharmony_ci    print('#endif')
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_cidef main():
299bf215546Sopenharmony_ci    regs = []
300bf215546Sopenharmony_ci    packets = []
301bf215546Sopenharmony_ci    for arg in sys.argv[1:]:
302bf215546Sopenharmony_ci        parse(arg, regs, packets)
303bf215546Sopenharmony_ci    write_tables(regs, packets)
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ciif __name__ == '__main__':
307bf215546Sopenharmony_ci    main()
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci# kate: space-indent on; indent-width 4; replace-tabs on;
310