Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/amd/registers/parseheader.py
7081 views
1
#
2
# Copyright 2017-2019 Advanced Micro Devices, Inc.
3
#
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:
10
#
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
13
# Software.
14
#
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.
22
#
23
"""
24
Helper script that parses a register header and produces a register database
25
as output. Use as:
26
27
python3 parseheader.py ADDRESS_SPACE < header.h
28
29
This script is included for reference -- we should be able to remove this in
30
the future.
31
"""
32
33
from __future__ import absolute_import, division, print_function, unicode_literals
34
35
import json
36
import math
37
import re
38
import sys
39
40
from regdb import Object, RegisterDatabase, deduplicate_enums, deduplicate_register_types
41
42
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]+)\)')
47
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
53
54
def __fini_field(self):
55
if self.__field is None:
56
return
57
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
62
))
63
self.__fields.append(self.__field)
64
65
self.__enumentries = None
66
self.__field = None
67
68
def __fini_register(self):
69
if self.__regmap is None:
70
return
71
72
if self.__fields:
73
self.regdb.add_register_type(self.__regmap.name, Object(
74
fields=self.__fields
75
))
76
self.__regmap.type_ref = self.__regmap.name
77
self.regdb.add_register_mapping(self.__regmap)
78
79
self.__regmap = None
80
self.__fields = None
81
82
def parse_header(self, filp):
83
regdb = RegisterDatabase()
84
chips = ['gfx6', 'gfx7', 'gfx8', 'fiji', 'stoney', 'gfx9']
85
86
self.__regmap = None
87
self.__fields = None
88
self.__field = None
89
self.__enumentries = None
90
91
for line in filp:
92
if not line.startswith('#define '):
93
continue
94
95
line = line[8:].strip()
96
97
comment = None
98
m = RE_comment.search(line)
99
if m is not None:
100
comment = m.group(2) or m.group(4)
101
comment = comment.strip()
102
line = line[:m.span()[0]].strip()
103
104
split = line.split(None, 1)
105
name = split[0]
106
107
m = RE_prefix.match(name)
108
if m is None:
109
continue
110
111
prefix = m.group(1)
112
prefix_address = int(m.group(2), 16)
113
name = name[m.span()[1]:]
114
115
if prefix == 'V':
116
value = int(split[1], 0)
117
118
for entry in self.__enumentries:
119
if name == entry.name:
120
sys.exit('Duplicate value define: name = {0}'.format(name))
121
122
entry = Object(name=name, value=value)
123
if comment is not None:
124
entry.comment = comment
125
self.__enumentries.append(entry)
126
continue
127
128
if prefix == 'S':
129
self.__fini_field()
130
131
if not name.endswith('(x)'):
132
sys.exit('Missing (x) in S line: {0}'.line)
133
name = name[:-3]
134
135
for field in self.__fields:
136
if name == field.name:
137
sys.exit('Duplicate field define: {0}'.format(name))
138
139
m = RE_set_value.match(split[1])
140
if m is not None:
141
unshifted_mask = int(m.group(1), 0)
142
shift = int(m.group(2), 0)
143
else:
144
m = RE_set_value_no_shift.match(split[1])
145
if m is not None:
146
unshifted_mask = int(m.group(2), 0)
147
shift = 0
148
else:
149
sys.exit('Bad S_xxx_xxx define: {0}'.format(line))
150
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))
154
155
self.__field = Object(
156
name=name,
157
bits=[shift, shift + num_bits - 1],
158
)
159
if comment is not None:
160
self.__field.comment = comment
161
self.__enumentries = []
162
163
if prefix == 'R':
164
self.__fini_field()
165
self.__fini_register()
166
167
if regdb.register_mappings_by_name(name):
168
sys.exit('Duplicate register define: {0}'.format(name))
169
170
address = int(split[1], 0)
171
if address != prefix_address:
172
sys.exit('Inconsistent register address: {0}'.format(line))
173
174
self.__regmap = Object(
175
name=name,
176
chips=self.chips,
177
map=Object(to=self.address_space, at=address),
178
)
179
self.__fields = []
180
181
self.__fini_field()
182
self.__fini_register()
183
184
def main():
185
map_to = sys.argv[1]
186
187
parser = HeaderParser(map_to)
188
parser.parse_header(sys.stdin)
189
190
deduplicate_enums(parser.regdb)
191
deduplicate_register_types(parser.regdb)
192
193
print(parser.regdb.encode_json_pretty())
194
195
196
if __name__ == '__main__':
197
main()
198
199
# kate: space-indent on; indent-width 4; replace-tabs on;
200
201