1bf215546Sopenharmony_ci#
2bf215546Sopenharmony_ci# Copyright 2017-2019 Advanced Micro Devices, Inc.
3bf215546Sopenharmony_ci#
4bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci# copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci# to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci# on the rights to use, copy, modify, merge, publish, distribute, sub
8bf215546Sopenharmony_ci# license, and/or sell copies of the Software, and to permit persons to whom
9bf215546Sopenharmony_ci# the Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci#
11bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci# paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci# Software.
14bf215546Sopenharmony_ci#
15bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19bf215546Sopenharmony_ci# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20bf215546Sopenharmony_ci# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21bf215546Sopenharmony_ci# USE OR OTHER DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci#
23bf215546Sopenharmony_ci"""
24bf215546Sopenharmony_ciHelper script that parses a register header and produces a register database
25bf215546Sopenharmony_cias output. Use as:
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci  python3 parseheader.py ADDRESS_SPACE < header.h
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ciThis script is included for reference -- we should be able to remove this in
30bf215546Sopenharmony_cithe future.
31bf215546Sopenharmony_ci"""
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ciimport json
34bf215546Sopenharmony_ciimport math
35bf215546Sopenharmony_ciimport re
36bf215546Sopenharmony_ciimport sys
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cifrom regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ciRE_comment = re.compile(r'(/\*(.*)\*/)$|(//(.*))$')
42bf215546Sopenharmony_ciRE_prefix = re.compile(r'([RSV])_([0-9a-fA-F]+)_')
43bf215546Sopenharmony_ciRE_set_value = re.compile(r'\(\(\(unsigned\)\(x\) & ([0-9a-fA-Fx]+)\) << ([0-9]+)\)')
44bf215546Sopenharmony_ciRE_set_value_no_shift = re.compile(r'\((\(unsigned\))?\(x\) & ([0-9a-fA-Fx]+)\)')
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ciclass HeaderParser(object):
47bf215546Sopenharmony_ci    def __init__(self, address_space):
48bf215546Sopenharmony_ci        self.regdb = RegisterDatabase()
49bf215546Sopenharmony_ci        self.chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9']
50bf215546Sopenharmony_ci        self.address_space = address_space
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci    def __fini_field(self):
53bf215546Sopenharmony_ci        if self.__field is None:
54bf215546Sopenharmony_ci            return
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci        if self.__enumentries:
57bf215546Sopenharmony_ci            self.__field.enum_ref = self.__regmap.name + '__' + self.__field.name
58bf215546Sopenharmony_ci            self.regdb.add_enum(self.__field.enum_ref, Object(
59bf215546Sopenharmony_ci                entries=self.__enumentries
60bf215546Sopenharmony_ci            ))
61bf215546Sopenharmony_ci        self.__fields.append(self.__field)
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci        self.__enumentries = None
64bf215546Sopenharmony_ci        self.__field = None
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci    def __fini_register(self):
67bf215546Sopenharmony_ci        if self.__regmap is None:
68bf215546Sopenharmony_ci            return
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci        if self.__fields:
71bf215546Sopenharmony_ci            self.regdb.add_register_type(self.__regmap.name, Object(
72bf215546Sopenharmony_ci                fields=self.__fields
73bf215546Sopenharmony_ci            ))
74bf215546Sopenharmony_ci            self.__regmap.type_ref = self.__regmap.name
75bf215546Sopenharmony_ci        self.regdb.add_register_mapping(self.__regmap)
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci        self.__regmap = None
78bf215546Sopenharmony_ci        self.__fields = None
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci    def parse_header(self, filp):
81bf215546Sopenharmony_ci        regdb = RegisterDatabase()
82bf215546Sopenharmony_ci        chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9']
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci        self.__regmap = None
85bf215546Sopenharmony_ci        self.__fields = None
86bf215546Sopenharmony_ci        self.__field = None
87bf215546Sopenharmony_ci        self.__enumentries = None
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci        for line in filp:
90bf215546Sopenharmony_ci            if not line.startswith('#define '):
91bf215546Sopenharmony_ci                continue
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci            line = line[8:].strip()
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci            comment = None
96bf215546Sopenharmony_ci            m = RE_comment.search(line)
97bf215546Sopenharmony_ci            if m is not None:
98bf215546Sopenharmony_ci                comment = m.group(2) or m.group(4)
99bf215546Sopenharmony_ci                comment = comment.strip()
100bf215546Sopenharmony_ci                line = line[:m.span()[0]].strip()
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci            split = line.split(None, 1)
103bf215546Sopenharmony_ci            name = split[0]
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci            m = RE_prefix.match(name)
106bf215546Sopenharmony_ci            if m is None:
107bf215546Sopenharmony_ci                continue
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci            prefix = m.group(1)
110bf215546Sopenharmony_ci            prefix_address = int(m.group(2), 16)
111bf215546Sopenharmony_ci            name = name[m.span()[1]:]
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci            if prefix == 'V':
114bf215546Sopenharmony_ci                value = int(split[1], 0)
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci                for entry in self.__enumentries:
117bf215546Sopenharmony_ci                    if name == entry.name:
118bf215546Sopenharmony_ci                        sys.exit('Duplicate value define: name = {0}'.format(name))
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci                entry = Object(name=name, value=value)
121bf215546Sopenharmony_ci                if comment is not None:
122bf215546Sopenharmony_ci                    entry.comment = comment
123bf215546Sopenharmony_ci                self.__enumentries.append(entry)
124bf215546Sopenharmony_ci                continue
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci            if prefix == 'S':
127bf215546Sopenharmony_ci                self.__fini_field()
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci                if not name.endswith('(x)'):
130bf215546Sopenharmony_ci                    sys.exit('Missing (x) in S line: {0}'.line)
131bf215546Sopenharmony_ci                name = name[:-3]
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci                for field in self.__fields:
134bf215546Sopenharmony_ci                    if name == field.name:
135bf215546Sopenharmony_ci                        sys.exit('Duplicate field define: {0}'.format(name))
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci                m = RE_set_value.match(split[1])
138bf215546Sopenharmony_ci                if m is not None:
139bf215546Sopenharmony_ci                    unshifted_mask = int(m.group(1), 0)
140bf215546Sopenharmony_ci                    shift = int(m.group(2), 0)
141bf215546Sopenharmony_ci                else:
142bf215546Sopenharmony_ci                    m = RE_set_value_no_shift.match(split[1])
143bf215546Sopenharmony_ci                    if m is not None:
144bf215546Sopenharmony_ci                        unshifted_mask = int(m.group(2), 0)
145bf215546Sopenharmony_ci                        shift = 0
146bf215546Sopenharmony_ci                    else:
147bf215546Sopenharmony_ci                        sys.exit('Bad S_xxx_xxx define: {0}'.format(line))
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci                num_bits = int(math.log2(unshifted_mask + 1))
150bf215546Sopenharmony_ci                if unshifted_mask != (1 << num_bits) - 1:
151bf215546Sopenharmony_ci                    sys.exit('Bad unshifted mask in {0}'.format(line))
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci                self.__field = Object(
154bf215546Sopenharmony_ci                    name=name,
155bf215546Sopenharmony_ci                    bits=[shift, shift + num_bits - 1],
156bf215546Sopenharmony_ci                )
157bf215546Sopenharmony_ci                if comment is not None:
158bf215546Sopenharmony_ci                    self.__field.comment = comment
159bf215546Sopenharmony_ci                self.__enumentries = []
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci            if prefix == 'R':
162bf215546Sopenharmony_ci                self.__fini_field()
163bf215546Sopenharmony_ci                self.__fini_register()
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci                if regdb.register_mappings_by_name(name):
166bf215546Sopenharmony_ci                    sys.exit('Duplicate register define: {0}'.format(name))
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci                address = int(split[1], 0)
169bf215546Sopenharmony_ci                if address != prefix_address:
170bf215546Sopenharmony_ci                    sys.exit('Inconsistent register address: {0}'.format(line))
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci                self.__regmap = Object(
173bf215546Sopenharmony_ci                    name=name,
174bf215546Sopenharmony_ci                    chips=self.chips,
175bf215546Sopenharmony_ci                    map=Object(to=self.address_space, at=address),
176bf215546Sopenharmony_ci                )
177bf215546Sopenharmony_ci                self.__fields = []
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci        self.__fini_field()
180bf215546Sopenharmony_ci        self.__fini_register()
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_cidef main():
183bf215546Sopenharmony_ci    map_to = sys.argv[1]
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci    parser = HeaderParser(map_to)
186bf215546Sopenharmony_ci    parser.parse_header(sys.stdin)
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci    deduplicate_enums(parser.regdb)
189bf215546Sopenharmony_ci    deduplicate_register_types(parser.regdb)
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci    print(parser.regdb.encode_json_pretty())
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ciif __name__ == '__main__':
195bf215546Sopenharmony_ci    main()
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci# kate: space-indent on; indent-width 4; replace-tabs on;
198