2 # Copyright 2017-2019 Advanced Micro Devices, Inc.
4 # Permission is hereby granted, free of charge, to any person obtaining a
5 # copy of this software and associated documentation files (the "Software"),
6 # to deal in the Software without restriction, including without limitation
7 # on the rights to use, copy, modify, merge, publish, distribute, sub
8 # license, and/or sell copies of the Software, and to permit persons to whom
9 # the Software is furnished to do so, subject to the following conditions:
11 # The above copyright notice and this permission notice (including the next
12 # paragraph) shall be included in all copies or substantial portions of the
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 # THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 # USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Helper script that parses a register header and produces a register database
27 python3 parseheader.py ADDRESS_SPACE < header.h
29 This script is included for reference -- we should be able to remove this in
33 from __future__
import absolute_import
, division
, print_function
, unicode_literals
40 from regdb
import Object
, RegisterDatabase
, deduplicate_enums
, deduplicate_register_types
43 RE_comment
= re
.compile(r
'(/\*(.*)\*/)$|(//(.*))$')
44 RE_prefix
= re
.compile(r
'([RSV])_([0-9a-fA-F]+)_')
45 RE_set_value
= re
.compile(r
'\(\(\(unsigned\)\(x\) & ([0-9a-fA-Fx]+)\) << ([0-9]+)\)')
46 RE_set_value_no_shift
= re
.compile(r
'\((\(unsigned\))?\(x\) & ([0-9a-fA-Fx]+)\)')
48 class HeaderParser(object):
49 def __init__(self
, address_space
):
50 self
.regdb
= RegisterDatabase()
51 self
.chips
= ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9']
52 self
.address_space
= address_space
54 def __fini_field(self
):
55 if self
.__field
is None:
58 if self
.__enumentries
:
59 self
.__field
.enum_ref
= self
.__regmap
.name
+ '__' + self
.__field
.name
60 self
.regdb
.add_enum(self
.__field
.enum_ref
, Object(
61 entries
=self
.__enumentries
63 self
.__fields
.append(self
.__field
)
65 self
.__enumentries
= None
68 def __fini_register(self
):
69 if self
.__regmap
is None:
73 self
.regdb
.add_register_type(self
.__regmap
.name
, Object(
76 self
.__regmap
.type_ref
= self
.__regmap
.name
77 self
.regdb
.add_register_mapping(self
.__regmap
)
82 def parse_header(self
, filp
):
83 regdb
= RegisterDatabase()
84 chips
= ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9']
89 self
.__enumentries
= None
92 if not line
.startswith('#define '):
95 line
= line
[8:].strip()
98 m
= RE_comment
.search(line
)
100 comment
= m
.group(2) or m
.group(4)
101 comment
= comment
.strip()
102 line
= line
[:m
.span()[0]].strip()
104 split
= line
.split(None, 1)
107 m
= RE_prefix
.match(name
)
112 prefix_address
= int(m
.group(2), 16)
113 name
= name
[m
.span()[1]:]
116 value
= int(split
[1], 0)
118 for entry
in self
.__enumentries
:
119 if name
== entry
.name
:
120 sys
.exit('Duplicate value define: name = {0}'.format(name
))
122 entry
= Object(name
=name
, value
=value
)
123 if comment
is not None:
124 entry
.comment
= comment
125 self
.__enumentries
.append(entry
)
131 if not name
.endswith('(x)'):
132 sys
.exit('Missing (x) in S line: {0}'.line
)
135 for field
in self
.__fields
:
136 if name
== field
.name
:
137 sys
.exit('Duplicate field define: {0}'.format(name
))
139 m
= RE_set_value
.match(split
[1])
141 unshifted_mask
= int(m
.group(1), 0)
142 shift
= int(m
.group(2), 0)
144 m
= RE_set_value_no_shift
.match(split
[1])
146 unshifted_mask
= int(m
.group(2), 0)
149 sys
.exit('Bad S_xxx_xxx define: {0}'.format(line
))
151 num_bits
= int(math
.log2(unshifted_mask
+ 1))
152 if unshifted_mask
!= (1 << num_bits
) - 1:
153 sys
.exit('Bad unshifted mask in {0}'.format(line
))
155 self
.__field
= Object(
157 bits
=[shift
, shift
+ num_bits
- 1],
159 if comment
is not None:
160 self
.__field
.comment
= comment
161 self
.__enumentries
= []
165 self
.__fini
_register
()
167 if regdb
.register_mappings_by_name(name
):
168 sys
.exit('Duplicate register define: {0}'.format(name
))
170 address
= int(split
[1], 0)
171 if address
!= prefix_address
:
172 sys
.exit('Inconsistent register address: {0}'.format(line
))
174 self
.__regmap
= Object(
177 map=Object(to
=self
.address_space
, at
=address
),
182 self
.__fini
_register
()
187 parser
= HeaderParser(map_to
)
188 parser
.parse_header(sys
.stdin
)
190 deduplicate_enums(parser
.regdb
)
191 deduplicate_register_types(parser
.regdb
)
193 print(parser
.regdb
.encode_json_pretty())
196 if __name__
== '__main__':
199 # kate: space-indent on; indent-width 4; replace-tabs on;