xref: /aosp_15_r20/external/mesa3d/src/amd/registers/makeregheader.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard WorkerCOPYRIGHT = '''
2*61046927SAndroid Build Coastguard Worker/*
3*61046927SAndroid Build Coastguard Worker * Copyright 2015-2019 Advanced Micro Devices, Inc.
4*61046927SAndroid Build Coastguard Worker *
5*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
6*61046927SAndroid Build Coastguard Worker */
7*61046927SAndroid Build Coastguard Worker'''
8*61046927SAndroid Build Coastguard Worker"""
9*61046927SAndroid Build Coastguard WorkerCreate the (combined) register header from register JSON. Use --help for usage.
10*61046927SAndroid Build Coastguard Worker"""
11*61046927SAndroid Build Coastguard Worker
12*61046927SAndroid Build Coastguard Workerimport argparse
13*61046927SAndroid Build Coastguard Workerfrom collections import defaultdict
14*61046927SAndroid Build Coastguard Workerimport itertools
15*61046927SAndroid Build Coastguard Workerimport json
16*61046927SAndroid Build Coastguard Workerimport re
17*61046927SAndroid Build Coastguard Workerimport sys
18*61046927SAndroid Build Coastguard Worker
19*61046927SAndroid Build Coastguard Workerfrom regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types
20*61046927SAndroid Build Coastguard Worker
21*61046927SAndroid Build Coastguard Worker
22*61046927SAndroid Build Coastguard Worker######### BEGIN HARDCODED CONFIGURATION
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker# Chips are sorted chronologically
25*61046927SAndroid Build Coastguard WorkerCHIPS = [
26*61046927SAndroid Build Coastguard Worker    Object(name='gfx6', disambiguation='GFX6'),
27*61046927SAndroid Build Coastguard Worker    Object(name='gfx7', disambiguation='GFX7'),
28*61046927SAndroid Build Coastguard Worker    Object(name='gfx8', disambiguation='GFX8'),
29*61046927SAndroid Build Coastguard Worker    Object(name='gfx81', disambiguation='GFX81'),
30*61046927SAndroid Build Coastguard Worker    Object(name='gfx9', disambiguation='GFX9'),
31*61046927SAndroid Build Coastguard Worker    Object(name='gfx940', disambiguation='GFX940'),
32*61046927SAndroid Build Coastguard Worker    Object(name='gfx10', disambiguation='GFX10'),
33*61046927SAndroid Build Coastguard Worker    Object(name='gfx103', disambiguation='GFX103'),
34*61046927SAndroid Build Coastguard Worker    Object(name='gfx11', disambiguation='GFX11'),
35*61046927SAndroid Build Coastguard Worker    Object(name='gfx115', disambiguation='GFX115'),
36*61046927SAndroid Build Coastguard Worker    Object(name='gfx12', disambiguation='GFX12'),
37*61046927SAndroid Build Coastguard Worker]
38*61046927SAndroid Build Coastguard Worker
39*61046927SAndroid Build Coastguard Worker######### END HARDCODED CONFIGURATION
40*61046927SAndroid Build Coastguard Worker
41*61046927SAndroid Build Coastguard Workerdef get_chip_index(chip):
42*61046927SAndroid Build Coastguard Worker    """
43*61046927SAndroid Build Coastguard Worker    Given a chip name, return its index in the global CHIPS list.
44*61046927SAndroid Build Coastguard Worker    """
45*61046927SAndroid Build Coastguard Worker    return next(idx for idx, obj in enumerate(CHIPS) if obj.name == chip)
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Workerdef get_disambiguation_suffix(chips):
48*61046927SAndroid Build Coastguard Worker    """
49*61046927SAndroid Build Coastguard Worker    Disambiguation suffix to be used for an enum entry or field name that
50*61046927SAndroid Build Coastguard Worker    is supported in the given set of chips.
51*61046927SAndroid Build Coastguard Worker    """
52*61046927SAndroid Build Coastguard Worker    oldest_chip_index = min([get_chip_index(chip) for chip in chips])
53*61046927SAndroid Build Coastguard Worker    return CHIPS[oldest_chip_index].disambiguation
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard Workerdef get_chips_comment(chips, parent=None):
56*61046927SAndroid Build Coastguard Worker    """
57*61046927SAndroid Build Coastguard Worker    Generate a user-friendly comment describing the given set of chips.
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker    The return value may be None, if such a comment is deemed unnecessary.
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker    parent is an optional set of chips supporting a parent structure, e.g.
62*61046927SAndroid Build Coastguard Worker    where chips may be the set of chips supporting a specific enum value,
63*61046927SAndroid Build Coastguard Worker    parent would be the set of chips supporting the field containing the enum,
64*61046927SAndroid Build Coastguard Worker    the idea being that no comment is necessary if all chips that support the
65*61046927SAndroid Build Coastguard Worker    parent also support the child.
66*61046927SAndroid Build Coastguard Worker    """
67*61046927SAndroid Build Coastguard Worker    chipflags = [chip.name in chips for chip in CHIPS]
68*61046927SAndroid Build Coastguard Worker    if all(chipflags):
69*61046927SAndroid Build Coastguard Worker        return None
70*61046927SAndroid Build Coastguard Worker
71*61046927SAndroid Build Coastguard Worker    if parent is not None:
72*61046927SAndroid Build Coastguard Worker        parentflags = [chip.name in parent for chip in CHIPS]
73*61046927SAndroid Build Coastguard Worker        if all(childflag or not parentflag for childflag, parentflag in zip(chipflags, parentflags)):
74*61046927SAndroid Build Coastguard Worker            return None
75*61046927SAndroid Build Coastguard Worker
76*61046927SAndroid Build Coastguard Worker    prefix = 0
77*61046927SAndroid Build Coastguard Worker    for idx, chip, flag in zip(itertools.count(), CHIPS, chipflags):
78*61046927SAndroid Build Coastguard Worker        if not flag:
79*61046927SAndroid Build Coastguard Worker            break
80*61046927SAndroid Build Coastguard Worker        prefix = idx + 1
81*61046927SAndroid Build Coastguard Worker
82*61046927SAndroid Build Coastguard Worker    suffix = len(CHIPS)
83*61046927SAndroid Build Coastguard Worker    for idx, chip, flag in zip(itertools.count(), reversed(CHIPS), reversed(chipflags)):
84*61046927SAndroid Build Coastguard Worker        if not flag:
85*61046927SAndroid Build Coastguard Worker            break
86*61046927SAndroid Build Coastguard Worker        suffix = len(CHIPS) - idx - 1
87*61046927SAndroid Build Coastguard Worker
88*61046927SAndroid Build Coastguard Worker    comment = []
89*61046927SAndroid Build Coastguard Worker    if prefix > 0:
90*61046927SAndroid Build Coastguard Worker        comment.append('<= {0}'.format(CHIPS[prefix - 1].name))
91*61046927SAndroid Build Coastguard Worker    for chip, flag in zip(CHIPS[prefix:suffix], chipflags[prefix:suffix]):
92*61046927SAndroid Build Coastguard Worker        if flag:
93*61046927SAndroid Build Coastguard Worker            comment.append(chip.name)
94*61046927SAndroid Build Coastguard Worker    if suffix < len(CHIPS):
95*61046927SAndroid Build Coastguard Worker        comment.append('>= {0}'.format(CHIPS[suffix].name))
96*61046927SAndroid Build Coastguard Worker
97*61046927SAndroid Build Coastguard Worker    return ', '.join(comment)
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Workerdef detect_conflict(regdb, field_in_type1, field_in_type2):
100*61046927SAndroid Build Coastguard Worker    """
101*61046927SAndroid Build Coastguard Worker    Returns False if field_in_type1 and field_in_type2 can be merged
102*61046927SAndroid Build Coastguard Worker    into a single field = if writing to field_in_type1 bits won't
103*61046927SAndroid Build Coastguard Worker    overwrite adjacent fields in type2, and the other way around.
104*61046927SAndroid Build Coastguard Worker    """
105*61046927SAndroid Build Coastguard Worker    for idx, type_refs in enumerate([field_in_type1.type_refs, field_in_type2.type_refs]):
106*61046927SAndroid Build Coastguard Worker        ref = field_in_type2 if idx == 0 else field_in_type1
107*61046927SAndroid Build Coastguard Worker        for type_ref in type_refs:
108*61046927SAndroid Build Coastguard Worker            for field in regdb.register_type(type_ref).fields:
109*61046927SAndroid Build Coastguard Worker                # If a different field in the other type starts in
110*61046927SAndroid Build Coastguard Worker                # the tested field's bits[0, 1] interval
111*61046927SAndroid Build Coastguard Worker                if (field.bits[0] > ref.bits[0] and
112*61046927SAndroid Build Coastguard Worker                    field.bits[0] <= ref.bits[1]):
113*61046927SAndroid Build Coastguard Worker                    return True
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker    return False
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Workerclass HeaderWriter(object):
118*61046927SAndroid Build Coastguard Worker    def __init__(self, regdb, guard=None):
119*61046927SAndroid Build Coastguard Worker        self.guard = guard
120*61046927SAndroid Build Coastguard Worker
121*61046927SAndroid Build Coastguard Worker        # The following contain: Object(address, chips, name, regmap/field/enumentry)
122*61046927SAndroid Build Coastguard Worker        self.register_lines = []
123*61046927SAndroid Build Coastguard Worker        self.field_lines = []
124*61046927SAndroid Build Coastguard Worker        self.value_lines = []
125*61046927SAndroid Build Coastguard Worker
126*61046927SAndroid Build Coastguard Worker        regtype_emit = defaultdict(set)
127*61046927SAndroid Build Coastguard Worker        enum_emit = defaultdict(set)
128*61046927SAndroid Build Coastguard Worker
129*61046927SAndroid Build Coastguard Worker        for regmap in regdb.register_mappings():
130*61046927SAndroid Build Coastguard Worker            type_ref = getattr(regmap, 'type_ref', None)
131*61046927SAndroid Build Coastguard Worker            self.register_lines.append(Object(
132*61046927SAndroid Build Coastguard Worker                address=regmap.map.at,
133*61046927SAndroid Build Coastguard Worker                chips=set(regmap.chips),
134*61046927SAndroid Build Coastguard Worker                name=regmap.name,
135*61046927SAndroid Build Coastguard Worker                regmap=regmap,
136*61046927SAndroid Build Coastguard Worker                type_refs=set([type_ref]) if type_ref else set(),
137*61046927SAndroid Build Coastguard Worker            ))
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker            basename = re.sub(r'[0-9]+', '', regmap.name)
140*61046927SAndroid Build Coastguard Worker            key = '{type_ref}::{basename}'.format(**locals())
141*61046927SAndroid Build Coastguard Worker            if type_ref is not None and regtype_emit[key].isdisjoint(regmap.chips):
142*61046927SAndroid Build Coastguard Worker                regtype_emit[key].update(regmap.chips)
143*61046927SAndroid Build Coastguard Worker
144*61046927SAndroid Build Coastguard Worker                regtype = regdb.register_type(type_ref)
145*61046927SAndroid Build Coastguard Worker                for field in regtype.fields:
146*61046927SAndroid Build Coastguard Worker                    if field.name == 'RESERVED':
147*61046927SAndroid Build Coastguard Worker                        continue
148*61046927SAndroid Build Coastguard Worker
149*61046927SAndroid Build Coastguard Worker                    enum_ref = getattr(field, 'enum_ref', None)
150*61046927SAndroid Build Coastguard Worker                    self.field_lines.append(Object(
151*61046927SAndroid Build Coastguard Worker                        address=regmap.map.at,
152*61046927SAndroid Build Coastguard Worker                        chips=set(regmap.chips),
153*61046927SAndroid Build Coastguard Worker                        name=field.name,
154*61046927SAndroid Build Coastguard Worker                        field=field,
155*61046927SAndroid Build Coastguard Worker                        bits=field.bits[:],
156*61046927SAndroid Build Coastguard Worker                        type_refs=set([type_ref]) if type_ref else set(),
157*61046927SAndroid Build Coastguard Worker                        enum_refs=set([enum_ref]) if enum_ref else set(),
158*61046927SAndroid Build Coastguard Worker                    ))
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker                    key = '{type_ref}::{basename}::{enum_ref}'.format(**locals())
161*61046927SAndroid Build Coastguard Worker                    if enum_ref is not None and enum_emit[key].isdisjoint(regmap.chips):
162*61046927SAndroid Build Coastguard Worker                        enum_emit[key].update(regmap.chips)
163*61046927SAndroid Build Coastguard Worker
164*61046927SAndroid Build Coastguard Worker                        enum = regdb.enum(enum_ref)
165*61046927SAndroid Build Coastguard Worker                        for entry in enum.entries:
166*61046927SAndroid Build Coastguard Worker                            self.value_lines.append(Object(
167*61046927SAndroid Build Coastguard Worker                                address=regmap.map.at,
168*61046927SAndroid Build Coastguard Worker                                chips=set(regmap.chips),
169*61046927SAndroid Build Coastguard Worker                                name=entry.name,
170*61046927SAndroid Build Coastguard Worker                                enumentry=entry,
171*61046927SAndroid Build Coastguard Worker                                enum_refs=set([enum_ref]) if enum_ref else set(),
172*61046927SAndroid Build Coastguard Worker                            ))
173*61046927SAndroid Build Coastguard Worker
174*61046927SAndroid Build Coastguard Worker        # Merge register lines
175*61046927SAndroid Build Coastguard Worker        lines = self.register_lines
176*61046927SAndroid Build Coastguard Worker        lines.sort(key=lambda line: (line.address, line.name))
177*61046927SAndroid Build Coastguard Worker
178*61046927SAndroid Build Coastguard Worker        self.register_lines = []
179*61046927SAndroid Build Coastguard Worker        for line in lines:
180*61046927SAndroid Build Coastguard Worker            prev = self.register_lines[-1] if self.register_lines else None
181*61046927SAndroid Build Coastguard Worker            if prev and prev.address == line.address and prev.name == line.name:
182*61046927SAndroid Build Coastguard Worker                prev.chips.update(line.chips)
183*61046927SAndroid Build Coastguard Worker                prev.type_refs.update(line.type_refs)
184*61046927SAndroid Build Coastguard Worker                continue
185*61046927SAndroid Build Coastguard Worker            self.register_lines.append(line)
186*61046927SAndroid Build Coastguard Worker
187*61046927SAndroid Build Coastguard Worker        # Merge field lines
188*61046927SAndroid Build Coastguard Worker        lines = self.field_lines
189*61046927SAndroid Build Coastguard Worker        lines.sort(key=lambda line: (line.address, line.name))
190*61046927SAndroid Build Coastguard Worker
191*61046927SAndroid Build Coastguard Worker        self.field_lines = []
192*61046927SAndroid Build Coastguard Worker        for line in lines:
193*61046927SAndroid Build Coastguard Worker            merged = False
194*61046927SAndroid Build Coastguard Worker            for prev in reversed(self.field_lines):
195*61046927SAndroid Build Coastguard Worker                if prev.address != line.address or prev.name != line.name:
196*61046927SAndroid Build Coastguard Worker                    break
197*61046927SAndroid Build Coastguard Worker
198*61046927SAndroid Build Coastguard Worker                # Can merge fields if they have the same starting bit and the
199*61046927SAndroid Build Coastguard Worker                # range of the field as intended by the current line does not
200*61046927SAndroid Build Coastguard Worker                # conflict with any of the regtypes covered by prev.
201*61046927SAndroid Build Coastguard Worker                if prev.bits[0] != line.bits[0]:
202*61046927SAndroid Build Coastguard Worker                    continue
203*61046927SAndroid Build Coastguard Worker
204*61046927SAndroid Build Coastguard Worker                if prev.bits[1] != line.bits[1]:
205*61046927SAndroid Build Coastguard Worker                    # Current line's field extends beyond the range of prev.
206*61046927SAndroid Build Coastguard Worker                    # Need to check for conflicts
207*61046927SAndroid Build Coastguard Worker                    if detect_conflict(regdb, prev, line):
208*61046927SAndroid Build Coastguard Worker                        continue
209*61046927SAndroid Build Coastguard Worker
210*61046927SAndroid Build Coastguard Worker                prev.bits[1] = max(prev.bits[1], line.bits[1])
211*61046927SAndroid Build Coastguard Worker                prev.chips.update(line.chips)
212*61046927SAndroid Build Coastguard Worker                prev.type_refs.update(line.type_refs)
213*61046927SAndroid Build Coastguard Worker                prev.enum_refs.update(line.enum_refs)
214*61046927SAndroid Build Coastguard Worker                merged = True
215*61046927SAndroid Build Coastguard Worker                break
216*61046927SAndroid Build Coastguard Worker            if not merged:
217*61046927SAndroid Build Coastguard Worker                self.field_lines.append(line)
218*61046927SAndroid Build Coastguard Worker
219*61046927SAndroid Build Coastguard Worker        # Merge value lines
220*61046927SAndroid Build Coastguard Worker        lines = self.value_lines
221*61046927SAndroid Build Coastguard Worker        lines.sort(key=lambda line: (line.address, line.name))
222*61046927SAndroid Build Coastguard Worker
223*61046927SAndroid Build Coastguard Worker        self.value_lines = []
224*61046927SAndroid Build Coastguard Worker        for line in lines:
225*61046927SAndroid Build Coastguard Worker            for prev in reversed(self.value_lines):
226*61046927SAndroid Build Coastguard Worker                if prev.address == line.address and prev.name == line.name and\
227*61046927SAndroid Build Coastguard Worker                   prev.enumentry.value == line.enumentry.value:
228*61046927SAndroid Build Coastguard Worker                    prev.chips.update(line.chips)
229*61046927SAndroid Build Coastguard Worker                    prev.enum_refs.update(line.enum_refs)
230*61046927SAndroid Build Coastguard Worker                    break
231*61046927SAndroid Build Coastguard Worker            else:
232*61046927SAndroid Build Coastguard Worker                self.value_lines.append(line)
233*61046927SAndroid Build Coastguard Worker
234*61046927SAndroid Build Coastguard Worker        # Disambiguate field and value lines
235*61046927SAndroid Build Coastguard Worker        for idx, line in enumerate(self.field_lines):
236*61046927SAndroid Build Coastguard Worker            prev = self.field_lines[idx - 1] if idx > 0 else None
237*61046927SAndroid Build Coastguard Worker            next = self.field_lines[idx + 1] if idx + 1 < len(self.field_lines) else None
238*61046927SAndroid Build Coastguard Worker            if (prev and prev.address == line.address and prev.field.name == line.field.name) or\
239*61046927SAndroid Build Coastguard Worker               (next and next.address == line.address and next.field.name == line.field.name):
240*61046927SAndroid Build Coastguard Worker                line.name += '_' + get_disambiguation_suffix(line.chips)
241*61046927SAndroid Build Coastguard Worker
242*61046927SAndroid Build Coastguard Worker        for idx, line in enumerate(self.value_lines):
243*61046927SAndroid Build Coastguard Worker            prev = self.value_lines[idx - 1] if idx > 0 else None
244*61046927SAndroid Build Coastguard Worker            next = self.value_lines[idx + 1] if idx + 1 < len(self.value_lines) else None
245*61046927SAndroid Build Coastguard Worker            if (prev and prev.address == line.address and prev.enumentry.name == line.enumentry.name) or\
246*61046927SAndroid Build Coastguard Worker               (next and next.address == line.address and next.enumentry.name == line.enumentry.name):
247*61046927SAndroid Build Coastguard Worker                line.name += '_' + get_disambiguation_suffix(line.chips)
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker    def print(self, filp, sort='address'):
250*61046927SAndroid Build Coastguard Worker        """
251*61046927SAndroid Build Coastguard Worker        Print out the entire register header.
252*61046927SAndroid Build Coastguard Worker        """
253*61046927SAndroid Build Coastguard Worker        if sort == 'address':
254*61046927SAndroid Build Coastguard Worker            self.register_lines.sort(key=lambda line: (line.address, line.name))
255*61046927SAndroid Build Coastguard Worker        else:
256*61046927SAndroid Build Coastguard Worker            assert sort == 'name'
257*61046927SAndroid Build Coastguard Worker            self.register_lines.sort(key=lambda line: (line.name, line.address))
258*61046927SAndroid Build Coastguard Worker
259*61046927SAndroid Build Coastguard Worker        # Collect and sort field lines by address
260*61046927SAndroid Build Coastguard Worker        field_lines_by_address = defaultdict(list)
261*61046927SAndroid Build Coastguard Worker        for line in self.field_lines:
262*61046927SAndroid Build Coastguard Worker            field_lines_by_address[line.address].append(line)
263*61046927SAndroid Build Coastguard Worker        for field_lines in field_lines_by_address.values():
264*61046927SAndroid Build Coastguard Worker            if sort == 'address':
265*61046927SAndroid Build Coastguard Worker                field_lines.sort(key=lambda line: (line.bits[0], line.name))
266*61046927SAndroid Build Coastguard Worker            else:
267*61046927SAndroid Build Coastguard Worker                field_lines.sort(key=lambda line: (line.name, line.bits[0]))
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker        # Collect and sort value lines by address
270*61046927SAndroid Build Coastguard Worker        value_lines_by_address = defaultdict(list)
271*61046927SAndroid Build Coastguard Worker        for line in self.value_lines:
272*61046927SAndroid Build Coastguard Worker            value_lines_by_address[line.address].append(line)
273*61046927SAndroid Build Coastguard Worker        for value_lines in value_lines_by_address.values():
274*61046927SAndroid Build Coastguard Worker            if sort == 'address':
275*61046927SAndroid Build Coastguard Worker                value_lines.sort(key=lambda line: (line.enumentry.value, line.name))
276*61046927SAndroid Build Coastguard Worker            else:
277*61046927SAndroid Build Coastguard Worker                value_lines.sort(key=lambda line: (line.name, line.enumentry.value))
278*61046927SAndroid Build Coastguard Worker
279*61046927SAndroid Build Coastguard Worker        print('/* Automatically generated by amd/registers/makeregheader.py */\n', file=filp)
280*61046927SAndroid Build Coastguard Worker        print(file=filp)
281*61046927SAndroid Build Coastguard Worker        print(COPYRIGHT.strip(), file=filp)
282*61046927SAndroid Build Coastguard Worker        print(file=filp)
283*61046927SAndroid Build Coastguard Worker
284*61046927SAndroid Build Coastguard Worker        if self.guard:
285*61046927SAndroid Build Coastguard Worker            print('#ifndef {self.guard}'.format(**locals()), file=filp)
286*61046927SAndroid Build Coastguard Worker            print('#define {self.guard}\n'.format(**locals()), file=filp)
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker        for register_line in self.register_lines:
289*61046927SAndroid Build Coastguard Worker            comment = get_chips_comment(register_line.chips)
290*61046927SAndroid Build Coastguard Worker
291*61046927SAndroid Build Coastguard Worker            address = '{0:X}'.format(register_line.address)
292*61046927SAndroid Build Coastguard Worker            address = address.rjust(3 if register_line.regmap.map.to == 'pkt3' else 6, '0')
293*61046927SAndroid Build Coastguard Worker
294*61046927SAndroid Build Coastguard Worker            define_name = 'R_{address}_{register_line.name}'.format(**locals()).ljust(63)
295*61046927SAndroid Build Coastguard Worker            comment = ' /* {0} */'.format(comment) if comment else ''
296*61046927SAndroid Build Coastguard Worker            print('#define {define_name} 0x{address}{comment}'.format(**locals()), file=filp)
297*61046927SAndroid Build Coastguard Worker
298*61046927SAndroid Build Coastguard Worker            field_lines = field_lines_by_address[register_line.address]
299*61046927SAndroid Build Coastguard Worker            field_idx = 0
300*61046927SAndroid Build Coastguard Worker            while field_idx < len(field_lines):
301*61046927SAndroid Build Coastguard Worker                field_line = field_lines[field_idx]
302*61046927SAndroid Build Coastguard Worker
303*61046927SAndroid Build Coastguard Worker                if field_line.type_refs.isdisjoint(register_line.type_refs):
304*61046927SAndroid Build Coastguard Worker                    field_idx += 1
305*61046927SAndroid Build Coastguard Worker                    continue
306*61046927SAndroid Build Coastguard Worker                del field_lines[field_idx]
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker                comment = get_chips_comment(field_line.chips, register_line.chips)
309*61046927SAndroid Build Coastguard Worker
310*61046927SAndroid Build Coastguard Worker                mask = (1 << (field_line.bits[1] - field_line.bits[0] + 1)) - 1
311*61046927SAndroid Build Coastguard Worker                define_name = '_{address}_{field_line.name}(x)'.format(**locals()).ljust(58)
312*61046927SAndroid Build Coastguard Worker                comment = ' /* {0} */'.format(comment) if comment else ''
313*61046927SAndroid Build Coastguard Worker                print(
314*61046927SAndroid Build Coastguard Worker                    '#define   S{define_name} (((unsigned)(x) & 0x{mask:X}) << {field_line.bits[0]}){comment}'
315*61046927SAndroid Build Coastguard Worker                    .format(**locals()), file=filp)
316*61046927SAndroid Build Coastguard Worker                print('#define   G{define_name} (((x) >> {field_line.bits[0]}) & 0x{mask:X})'
317*61046927SAndroid Build Coastguard Worker                         .format(**locals()), file=filp)
318*61046927SAndroid Build Coastguard Worker
319*61046927SAndroid Build Coastguard Worker                complement = ((1 << 32) - 1) ^ (mask << field_line.bits[0])
320*61046927SAndroid Build Coastguard Worker                define_name = '_{address}_{field_line.name}'.format(**locals()).ljust(58)
321*61046927SAndroid Build Coastguard Worker                print('#define   C{define_name} 0x{complement:08X}'
322*61046927SAndroid Build Coastguard Worker                         .format(**locals()), file=filp)
323*61046927SAndroid Build Coastguard Worker
324*61046927SAndroid Build Coastguard Worker                value_lines = value_lines_by_address[register_line.address]
325*61046927SAndroid Build Coastguard Worker                value_idx = 0
326*61046927SAndroid Build Coastguard Worker                while value_idx < len(value_lines):
327*61046927SAndroid Build Coastguard Worker                    value_line = value_lines[value_idx]
328*61046927SAndroid Build Coastguard Worker
329*61046927SAndroid Build Coastguard Worker                    if value_line.enum_refs.isdisjoint(field_line.enum_refs):
330*61046927SAndroid Build Coastguard Worker                        value_idx += 1
331*61046927SAndroid Build Coastguard Worker                        continue
332*61046927SAndroid Build Coastguard Worker                    del value_lines[value_idx]
333*61046927SAndroid Build Coastguard Worker
334*61046927SAndroid Build Coastguard Worker                    comment = get_chips_comment(value_line.chips, field_line.chips)
335*61046927SAndroid Build Coastguard Worker
336*61046927SAndroid Build Coastguard Worker                    define_name = 'V_{address}_{value_line.name}'.format(**locals()).ljust(55)
337*61046927SAndroid Build Coastguard Worker                    comment = ' /* {0} */'.format(comment) if comment else ''
338*61046927SAndroid Build Coastguard Worker                    print('#define     {define_name} {value_line.enumentry.value}{comment}'
339*61046927SAndroid Build Coastguard Worker                          .format(**locals()), file=filp)
340*61046927SAndroid Build Coastguard Worker
341*61046927SAndroid Build Coastguard Worker        if self.guard:
342*61046927SAndroid Build Coastguard Worker            print('\n#endif // {self.guard}'.format(**locals()), file=filp)
343*61046927SAndroid Build Coastguard Worker
344*61046927SAndroid Build Coastguard Worker
345*61046927SAndroid Build Coastguard Workerdef main():
346*61046927SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser()
347*61046927SAndroid Build Coastguard Worker    parser.add_argument('--chip', dest='chips', type=str, nargs='*',
348*61046927SAndroid Build Coastguard Worker                        help='Chip for which to generate the header (all chips if unspecified)')
349*61046927SAndroid Build Coastguard Worker    parser.add_argument('--sort', choices=['name', 'address'], default='address',
350*61046927SAndroid Build Coastguard Worker                        help='Sort key for registers, fields, and enum values')
351*61046927SAndroid Build Coastguard Worker    parser.add_argument('--guard', type=str, help='Name of the #include guard')
352*61046927SAndroid Build Coastguard Worker    parser.add_argument('files', metavar='FILE', type=str, nargs='+',
353*61046927SAndroid Build Coastguard Worker                        help='Register database file')
354*61046927SAndroid Build Coastguard Worker    args = parser.parse_args()
355*61046927SAndroid Build Coastguard Worker
356*61046927SAndroid Build Coastguard Worker    regdb = None
357*61046927SAndroid Build Coastguard Worker    for filename in args.files:
358*61046927SAndroid Build Coastguard Worker        with open(filename, 'r') as filp:
359*61046927SAndroid Build Coastguard Worker            db = RegisterDatabase.from_json(json.load(filp))
360*61046927SAndroid Build Coastguard Worker            if regdb is None:
361*61046927SAndroid Build Coastguard Worker                regdb = db
362*61046927SAndroid Build Coastguard Worker            else:
363*61046927SAndroid Build Coastguard Worker                regdb.update(db)
364*61046927SAndroid Build Coastguard Worker
365*61046927SAndroid Build Coastguard Worker    deduplicate_enums(regdb)
366*61046927SAndroid Build Coastguard Worker    deduplicate_register_types(regdb)
367*61046927SAndroid Build Coastguard Worker
368*61046927SAndroid Build Coastguard Worker    w = HeaderWriter(regdb, guard=args.guard)
369*61046927SAndroid Build Coastguard Worker    w.print(sys.stdout, sort=args.sort)
370*61046927SAndroid Build Coastguard Worker
371*61046927SAndroid Build Coastguard Worker
372*61046927SAndroid Build Coastguard Workerif __name__ == '__main__':
373*61046927SAndroid Build Coastguard Worker    main()
374*61046927SAndroid Build Coastguard Worker
375*61046927SAndroid Build Coastguard Worker# kate: space-indent on; indent-width 4; replace-tabs on;
376