Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/swr/rasterizer/codegen/gen_archrast.py
4574 views
1
# Copyright (C) 2014-2016 Intel Corporation. All Rights Reserved.
2
#
3
# Permission is hereby granted, free of charge, to any person obtaining a
4
# copy of this software and associated documentation files (the "Software"),
5
# to deal in the Software without restriction, including without limitation
6
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
# and/or sell copies of the Software, and to permit persons to whom the
8
# Software is furnished to do so, subject to the following conditions:
9
#
10
# The above copyright notice and this permission notice (including the next
11
# paragraph) shall be included in all copies or substantial portions of the
12
# Software.
13
#
14
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
# IN THE SOFTWARE.
21
22
# Python source
23
from __future__ import print_function
24
import os
25
import sys
26
import re
27
from gen_common import *
28
29
def parse_event_fields(lines, idx, event_dict):
30
"""
31
Parses lines from a proto file that contain an event definition and stores it in event_dict
32
"""
33
fields = []
34
end_of_event = False
35
36
# record all fields in event definition.
37
# note: we don't check if there's a leading brace.
38
while not end_of_event and idx < len(lines):
39
line = lines[idx].rstrip()
40
idx += 1
41
42
# ex 1: uint32_t numSampleCLZExecuted; // number of sample_cl_z instructions executed
43
# ex 2: char reason[256]; // size of reason
44
match = re.match(r'^(\s*)([\w\*]+)(\s+)([\w]+)(\[\d+\])*;\s*(\/\/.*)*$', line)
45
# group 1 -
46
# group 2 type
47
# group 3 -
48
# group 4 name
49
# group 5 [array size]
50
# group 6 //comment
51
52
if match:
53
field = {
54
"type": match.group(2),
55
"name": match.group(4),
56
"size": int(match.group(5)[1:-1]) if match.group(5) else 1,
57
"desc": match.group(6)[2:].strip() if match.group(6) else "",
58
}
59
fields.append(field)
60
61
end_of_event = re.match(r'(\s*)};', line)
62
63
event_dict['fields'] = fields
64
event_dict['num_fields'] = len(fields)
65
66
return idx
67
68
def parse_enums(lines, idx, event_dict):
69
"""
70
Parses lines from a proto file that contain an enum definition and stores it in event_dict
71
"""
72
enum_names = []
73
end_of_enum = False
74
75
# record all enum values in enumeration
76
# note: we don't check if there's a leading brace.
77
while not end_of_enum and idx < len(lines):
78
line = lines[idx].rstrip()
79
idx += 1
80
81
preprocessor = re.search(r'#if|#endif', line)
82
83
if not preprocessor:
84
enum = re.match(r'(\s*)(\w+)(\s*)', line)
85
86
if enum:
87
enum_names.append(line)
88
89
end_of_enum = re.match(r'(\s*)};', line)
90
91
event_dict['names'] = enum_names
92
return idx
93
94
def parse_protos(files, verbose=False):
95
"""
96
Parses a proto file and returns a dictionary of event definitions
97
"""
98
99
# Protos structure:
100
#
101
# {
102
# "events": {
103
# "defs": { // dict of event definitions where keys are 'group_name::event_name"
104
# ...,
105
# "ApiStat::DrawInfoEvent": {
106
# "id": 3,
107
# "group": "ApiStat",
108
# "name": "DrawInfoEvent", // name of event without 'group_name::' prefix
109
# "desc": "",
110
# "fields": [
111
# {
112
# "type": "uint32_t",
113
# "name": "drawId",
114
# "size": 1,
115
# "desc": "",
116
# },
117
# ...
118
# ]
119
# },
120
# ...
121
# },
122
# "groups": { // dict of groups with lists of event keys
123
# "ApiStat": [
124
# "ApiStat::DispatchEvent",
125
# "ApiStat::DrawInfoEvent",
126
# ...
127
# ],
128
# "Framework": [
129
# "Framework::ThreadStartApiEvent",
130
# "Framework::ThreadStartWorkerEvent",
131
# ...
132
# ],
133
# ...
134
# },
135
# "map": { // map of event ids to match archrast output to event key
136
# "1": "Framework::ThreadStartApiEvent",
137
# "2": "Framework::ThreadStartWorkerEvent",
138
# "3": "ApiStat::DrawInfoEvent",
139
# ...
140
# }
141
# },
142
# "enums": { ... } // enums follow similar defs, map (groups?) structure
143
# }
144
145
protos = {
146
'events': {
147
'defs': {}, # event dictionary containing events with their fields
148
'map': {}, # dictionary to map event ids to event names
149
'groups': {} # event keys stored by groups
150
},
151
'enums': {
152
'defs': {},
153
'map': {}
154
}
155
}
156
157
event_id = 0
158
enum_id = 0
159
160
if type(files) is not list:
161
files = [files]
162
163
for filename in files:
164
if verbose:
165
print("Parsing proto file: %s" % os.path.normpath(filename))
166
167
with open(filename, 'r') as f:
168
lines = f.readlines()
169
in_brief = False
170
brief = []
171
idx = 0
172
while idx < len(lines):
173
line = lines[idx].strip()
174
idx += 1
175
176
# If currently processing a brief, keep processing or change state
177
if in_brief:
178
match = re.match(r'^\s*\/\/\/\s*(.*)$', line) # i.e. "/// more event desc..."
179
if match:
180
brief.append(match.group(1).strip())
181
continue
182
else:
183
in_brief = False
184
185
# Match event/enum brief
186
match = re.match(r'^\s*\/\/\/\s*@(brief|breif)\s*(.*)$', line) # i.e. "///@brief My event desc..."
187
if match:
188
in_brief = True
189
brief.append(match.group(2).strip())
190
continue
191
192
# Match event definition
193
match = re.match(r'event(\s*)(((\w*)::){0,1}(\w+))', line) # i.e. "event SWTag::CounterEvent"
194
if match:
195
event_id += 1
196
197
# Parse event attributes
198
event_key = match.group(2) # i.e. SWTag::CounterEvent
199
event_group = match.group(4) if match.group(4) else "" # i.e. SWTag
200
event_name = match.group(5) # i.e. CounterEvent
201
202
# Define event attributes
203
event = {
204
'id': event_id,
205
'group': event_group,
206
'name': event_name,
207
'desc': ' '.join(brief)
208
}
209
# Add period at end of event desc if necessary
210
if event["desc"] and event["desc"][-1] != '.':
211
event["desc"] += '.'
212
213
# Reset brief
214
brief = []
215
216
# Now add event fields
217
idx = parse_event_fields(lines, idx, event)
218
219
# Register event and mapping
220
protos['events']['defs'][event_key] = event
221
protos['events']['map'][event_id] = event_key
222
223
continue
224
225
# Match enum definition
226
match = re.match(r'enum(\s*)(\w+)', line)
227
if match:
228
enum_id += 1
229
230
# Parse enum attributes
231
enum_name = match.group(2)
232
233
# Define enum attr
234
enum = {
235
'name': enum_name,
236
'desc': ' '.join(brief)
237
}
238
# Add period at end of event desc if necessary
239
if enum["desc"] and enum["desc"][-1] != '.':
240
enum["desc"] += '.'
241
242
# Reset brief
243
brief = []
244
245
# Now add enum fields
246
idx = parse_enums(lines, idx, enum)
247
248
# Register enum and mapping
249
protos['enums']['defs'][enum_name] = enum
250
protos['enums']['map'][enum_id] = enum_name
251
252
continue
253
254
# Sort and group events
255
event_groups = protos['events']['groups']
256
for key in sorted(protos['events']['defs']):
257
group = protos['events']['defs'][key]['group']
258
if group not in event_groups:
259
event_groups[group] = []
260
event_groups[group].append(key)
261
262
return protos
263
264
265
def main():
266
267
# Parse args...
268
parser = ArgumentParser()
269
parser.add_argument("--proto", "-p", dest="protos", nargs='+', help="Path to all proto file(s) to process. Accepts one or more paths (i.e. events.proto and events_private.proto)", required=True)
270
parser.add_argument("--output-dir", help="Output dir (defaults to ./codegen). Will create folder if it does not exist.", required=False, default="codegen")
271
parser.add_argument("--verbose", "-v", help="Verbose", action="store_true")
272
args = parser.parse_args()
273
274
if not os.path.exists(args.output_dir):
275
MakeDir(args.output_dir)
276
277
for f in args.protos:
278
if not os.path.exists(f):
279
print('Error: Could not find proto file %s' % f, file=sys.stderr)
280
return 1
281
282
# Parse each proto file and add to protos container
283
protos = parse_protos(args.protos, args.verbose)
284
285
files = [
286
["gen_ar_event.hpp", ""],
287
["gen_ar_event.cpp", ""],
288
["gen_ar_eventhandler.hpp", "gen_ar_event.hpp"],
289
["gen_ar_eventhandlerfile.hpp", "gen_ar_eventhandler.hpp"]
290
]
291
292
rval = 0
293
294
try:
295
# Delete existing files
296
for f in files:
297
filename = f[0]
298
output_fullpath = os.path.join(args.output_dir, filename)
299
if os.path.exists(output_fullpath):
300
if args.verbose:
301
print("Deleting existing file: %s" % output_fullpath)
302
os.remove(output_fullpath)
303
304
# Generate files from templates
305
print("Generating c++ from proto files...")
306
for f in files:
307
filename = f[0]
308
event_header = f[1]
309
curdir = os.path.dirname(os.path.abspath(__file__))
310
template_file = os.path.join(curdir, 'templates', filename)
311
output_fullpath = os.path.join(args.output_dir, filename)
312
313
if args.verbose:
314
print("Generating: %s" % output_fullpath)
315
MakoTemplateWriter.to_file(template_file, output_fullpath,
316
cmdline=sys.argv,
317
filename=filename,
318
protos=protos,
319
event_header=event_header)
320
321
except Exception as e:
322
print(e)
323
rval = 1
324
325
return rval
326
327
if __name__ == '__main__':
328
sys.exit(main())
329
330