Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/broadcom/cle/gen_pack_header.py
4560 views
1
#encoding=utf-8
2
3
# Copyright (C) 2016 Intel Corporation
4
# Copyright (C) 2016 Broadcom
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining a
7
# copy of this software and associated documentation files (the "Software"),
8
# to deal in the Software without restriction, including without limitation
9
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
# and/or sell copies of the Software, and to permit persons to whom the
11
# Software is furnished to do so, subject to the following conditions:
12
#
13
# The above copyright notice and this permission notice (including the next
14
# paragraph) shall be included in all copies or substantial portions of the
15
# Software.
16
#
17
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
# IN THE SOFTWARE.
24
25
from __future__ import (
26
absolute_import, division, print_function, unicode_literals
27
)
28
import xml.parsers.expat
29
import re
30
import sys
31
import copy
32
33
license = """/* Generated code, see v3d_packet_v21.xml, v3d_packet_v33.xml and gen_pack_header.py */
34
"""
35
36
pack_header = """%(license)s
37
38
/* Packets, enums and structures for %(platform)s.
39
*
40
* This file has been generated, do not hand edit.
41
*/
42
43
#ifndef %(guard)s
44
#define %(guard)s
45
46
#include "cle/v3d_packet_helpers.h"
47
48
"""
49
50
def to_alphanum(name):
51
substitutions = {
52
' ': '_',
53
'/': '_',
54
'[': '',
55
']': '',
56
'(': '',
57
')': '',
58
'-': '_',
59
':': '',
60
'.': '',
61
',': '',
62
'=': '',
63
'>': '',
64
'#': '',
65
'&': '',
66
'*': '',
67
'"': '',
68
'+': '',
69
'\'': '',
70
}
71
72
for i, j in substitutions.items():
73
name = name.replace(i, j)
74
75
return name
76
77
def safe_name(name):
78
name = to_alphanum(name)
79
if not name[0].isalpha():
80
name = '_' + name
81
82
return name
83
84
def prefixed_upper_name(prefix, name):
85
if prefix:
86
name = prefix + "_" + name
87
return safe_name(name).upper()
88
89
def num_from_str(num_str):
90
if num_str.lower().startswith('0x'):
91
return int(num_str, base=16)
92
else:
93
assert(not num_str.startswith('0') and 'octals numbers not allowed')
94
return int(num_str)
95
96
class Field(object):
97
ufixed_pattern = re.compile(r"u(\d+)\.(\d+)")
98
sfixed_pattern = re.compile(r"s(\d+)\.(\d+)")
99
100
def __init__(self, parser, attrs):
101
self.parser = parser
102
if "name" in attrs:
103
self.name = safe_name(attrs["name"]).lower()
104
105
if str(attrs["start"]).endswith("b"):
106
self.start = int(attrs["start"][:-1]) * 8
107
else:
108
self.start = int(attrs["start"])
109
# packet <field> entries in XML start from the bit after the
110
# opcode, so shift everything up by 8 since we'll also have a
111
# Field for the opcode.
112
if not parser.struct:
113
self.start += 8
114
115
self.end = self.start + int(attrs["size"]) - 1
116
self.type = attrs["type"]
117
118
if self.type == 'bool' and self.start != self.end:
119
print("#error Field {} has bool type but more than one bit of size".format(self.name));
120
121
if "prefix" in attrs:
122
self.prefix = safe_name(attrs["prefix"]).upper()
123
else:
124
self.prefix = None
125
126
if "default" in attrs:
127
self.default = int(attrs["default"])
128
else:
129
self.default = None
130
131
if "minus_one" in attrs:
132
assert(attrs["minus_one"] == "true")
133
self.minus_one = True
134
else:
135
self.minus_one = False
136
137
ufixed_match = Field.ufixed_pattern.match(self.type)
138
if ufixed_match:
139
self.type = 'ufixed'
140
self.fractional_size = int(ufixed_match.group(2))
141
142
sfixed_match = Field.sfixed_pattern.match(self.type)
143
if sfixed_match:
144
self.type = 'sfixed'
145
self.fractional_size = int(sfixed_match.group(2))
146
147
def emit_template_struct(self, dim):
148
if self.type == 'address':
149
type = '__gen_address_type'
150
elif self.type == 'bool':
151
type = 'bool'
152
elif self.type == 'float':
153
type = 'float'
154
elif self.type == 'f187':
155
type = 'float'
156
elif self.type == 'ufixed':
157
type = 'float'
158
elif self.type == 'sfixed':
159
type = 'float'
160
elif self.type == 'uint' and self.end - self.start > 32:
161
type = 'uint64_t'
162
elif self.type == 'offset':
163
type = 'uint64_t'
164
elif self.type == 'int':
165
type = 'int32_t'
166
elif self.type == 'uint':
167
type = 'uint32_t'
168
elif self.type in self.parser.structs:
169
type = 'struct ' + self.parser.gen_prefix(safe_name(self.type))
170
elif self.type in self.parser.enums:
171
type = 'enum ' + self.parser.gen_prefix(safe_name(self.type))
172
elif self.type == 'mbo':
173
return
174
else:
175
print("#error unhandled type: %s" % self.type)
176
type = "uint32_t"
177
178
print(" %-36s %s%s;" % (type, self.name, dim))
179
180
for value in self.values:
181
name = prefixed_upper_name(self.prefix, value.name)
182
print("#define %-40s %d" % (name, value.value))
183
184
def overlaps(self, field):
185
return self != field and max(self.start, field.start) <= min(self.end, field.end)
186
187
188
class Group(object):
189
def __init__(self, parser, parent, start, count):
190
self.parser = parser
191
self.parent = parent
192
self.start = start
193
self.count = count
194
self.size = 0
195
self.fields = []
196
self.min_ver = 0
197
self.max_ver = 0
198
199
def emit_template_struct(self, dim):
200
if self.count == 0:
201
print(" /* variable length fields follow */")
202
else:
203
if self.count > 1:
204
dim = "%s[%d]" % (dim, self.count)
205
206
for field in self.fields:
207
field.emit_template_struct(dim)
208
209
class Byte:
210
def __init__(self):
211
self.size = 8
212
self.fields = []
213
self.address = None
214
215
def collect_bytes(self, bytes):
216
for field in self.fields:
217
first_byte = field.start // 8
218
last_byte = field.end // 8
219
220
for b in range(first_byte, last_byte + 1):
221
if not b in bytes:
222
bytes[b] = self.Byte()
223
224
bytes[b].fields.append(field)
225
226
if field.type == "address":
227
# assert bytes[index].address == None
228
bytes[b].address = field
229
230
def emit_pack_function(self, start):
231
# Determine number of bytes in this group.
232
self.length = max(field.end // 8 for field in self.fields) + 1
233
234
bytes = {}
235
self.collect_bytes(bytes)
236
237
relocs_emitted = set()
238
memcpy_fields = set()
239
240
for field in self.fields:
241
if field.minus_one:
242
print(" assert(values->%s >= 1);" % field.name)
243
244
for index in range(self.length):
245
# Handle MBZ bytes
246
if not index in bytes:
247
print(" cl[%2d] = 0;" % index)
248
continue
249
byte = bytes[index]
250
251
# Call out to the driver to note our relocations. Inside of the
252
# packet we only store offsets within the BOs, and we store the
253
# handle to the packet outside. Unlike Intel genxml, we don't
254
# need to have the other bits that will be stored together with
255
# the address during the reloc process, so there's no need for the
256
# complicated combine_address() function.
257
if byte.address and byte.address not in relocs_emitted:
258
print(" __gen_emit_reloc(data, &values->%s);" % byte.address.name)
259
relocs_emitted.add(byte.address)
260
261
# Special case: floats can't have any other fields packed into
262
# them (since they'd change the meaning of the float), and the
263
# per-byte bitshifting math below bloats the pack code for floats,
264
# so just copy them directly here. Also handle 16/32-bit
265
# uints/ints with no merged fields.
266
if len(byte.fields) == 1:
267
field = byte.fields[0]
268
if field.type in ["float", "uint", "int"] and field.start % 8 == 0 and field.end - field.start == 31 and not field.minus_one:
269
if field in memcpy_fields:
270
continue
271
272
if not any(field.overlaps(scan_field) for scan_field in self.fields):
273
assert(field.start == index * 8)
274
print("")
275
print(" memcpy(&cl[%d], &values->%s, sizeof(values->%s));" %
276
(index, field.name, field.name))
277
memcpy_fields.add(field)
278
continue
279
280
byte_start = index * 8
281
282
v = None
283
prefix = " cl[%2d] =" % index
284
285
field_index = 0
286
for field in byte.fields:
287
if field.type != "mbo":
288
name = field.name
289
290
start = field.start
291
end = field.end
292
field_byte_start = (field.start // 8) * 8
293
start -= field_byte_start
294
end -= field_byte_start
295
extra_shift = 0
296
297
value = "values->%s" % name
298
if field.minus_one:
299
value = "%s - 1" % value
300
301
if field.type == "mbo":
302
s = "__gen_mbo(%d, %d)" % \
303
(start, end)
304
elif field.type == "address":
305
extra_shift = (31 - (end - start)) // 8 * 8
306
s = "__gen_address_offset(&values->%s)" % byte.address.name
307
elif field.type == "uint":
308
s = "__gen_uint(%s, %d, %d)" % \
309
(value, start, end)
310
elif field.type in self.parser.enums:
311
s = "__gen_uint(%s, %d, %d)" % \
312
(value, start, end)
313
elif field.type == "int":
314
s = "__gen_sint(%s, %d, %d)" % \
315
(value, start, end)
316
elif field.type == "bool":
317
s = "__gen_uint(%s, %d, %d)" % \
318
(value, start, end)
319
elif field.type == "float":
320
s = "#error %s float value mixed in with other fields" % name
321
elif field.type == "f187":
322
s = "__gen_uint(fui(%s) >> 16, %d, %d)" % \
323
(value, start, end)
324
elif field.type == "offset":
325
s = "__gen_offset(%s, %d, %d)" % \
326
(value, start, end)
327
elif field.type == 'ufixed':
328
s = "__gen_ufixed(%s, %d, %d, %d)" % \
329
(value, start, end, field.fractional_size)
330
elif field.type == 'sfixed':
331
s = "__gen_sfixed(%s, %d, %d, %d)" % \
332
(value, start, end, field.fractional_size)
333
elif field.type in self.parser.structs:
334
s = "__gen_uint(v%d_%d, %d, %d)" % \
335
(index, field_index, start, end)
336
field_index = field_index + 1
337
else:
338
print("/* unhandled field %s, type %s */\n" % (name, field.type))
339
s = None
340
341
if not s == None:
342
shift = byte_start - field_byte_start + extra_shift
343
if shift:
344
s = "%s >> %d" % (s, shift)
345
346
if field == byte.fields[-1]:
347
print("%s %s;" % (prefix, s))
348
else:
349
print("%s %s |" % (prefix, s))
350
prefix = " "
351
352
print("")
353
continue
354
355
def emit_unpack_function(self, start):
356
for field in self.fields:
357
if field.type != "mbo":
358
convert = None
359
360
args = []
361
args.append('cl')
362
args.append(str(start + field.start))
363
args.append(str(start + field.end))
364
365
if field.type == "address":
366
convert = "__gen_unpack_address"
367
elif field.type == "uint":
368
convert = "__gen_unpack_uint"
369
elif field.type in self.parser.enums:
370
convert = "__gen_unpack_uint"
371
elif field.type == "int":
372
convert = "__gen_unpack_sint"
373
elif field.type == "bool":
374
convert = "__gen_unpack_uint"
375
elif field.type == "float":
376
convert = "__gen_unpack_float"
377
elif field.type == "f187":
378
convert = "__gen_unpack_f187"
379
elif field.type == "offset":
380
convert = "__gen_unpack_offset"
381
elif field.type == 'ufixed':
382
args.append(str(field.fractional_size))
383
convert = "__gen_unpack_ufixed"
384
elif field.type == 'sfixed':
385
args.append(str(field.fractional_size))
386
convert = "__gen_unpack_sfixed"
387
else:
388
print("/* unhandled field %s, type %s */\n" % (field.name, field.type))
389
s = None
390
391
plusone = ""
392
if field.minus_one:
393
plusone = " + 1"
394
print(" values->%s = %s(%s)%s;" % \
395
(field.name, convert, ', '.join(args), plusone))
396
397
class Value(object):
398
def __init__(self, attrs):
399
self.name = attrs["name"]
400
self.value = int(attrs["value"])
401
402
class Parser(object):
403
def __init__(self, ver):
404
self.parser = xml.parsers.expat.ParserCreate()
405
self.parser.StartElementHandler = self.start_element
406
self.parser.EndElementHandler = self.end_element
407
408
self.packet = None
409
self.struct = None
410
self.structs = {}
411
# Set of enum names we've seen.
412
self.enums = set()
413
self.registers = {}
414
self.ver = ver
415
416
def gen_prefix(self, name):
417
if name[0] == "_":
418
return 'V3D%s%s' % (self.ver, name)
419
else:
420
return 'V3D%s_%s' % (self.ver, name)
421
422
def gen_guard(self):
423
return self.gen_prefix("PACK_H")
424
425
def attrs_version_valid(self, attrs):
426
if "min_ver" in attrs and self.ver < attrs["min_ver"]:
427
return False
428
429
if "max_ver" in attrs and self.ver > attrs["max_ver"]:
430
return False
431
432
return True
433
434
def group_enabled(self):
435
if self.group.min_ver != 0 and self.ver < self.group.min_ver:
436
return False
437
438
if self.group.max_ver != 0 and self.ver > self.group.max_ver:
439
return False
440
441
return True
442
443
def start_element(self, name, attrs):
444
if name == "vcxml":
445
self.platform = "V3D {}.{}".format(self.ver[0], self.ver[1])
446
print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()})
447
elif name in ("packet", "struct", "register"):
448
default_field = None
449
450
object_name = self.gen_prefix(safe_name(attrs["name"].upper()))
451
if name == "packet":
452
self.packet = object_name
453
454
# Add a fixed Field for the opcode. We only make <field>s in
455
# the XML for the fields listed in the spec, and all of those
456
# start from bit 0 after of the opcode.
457
default_field = {
458
"name" : "opcode",
459
"default" : attrs["code"],
460
"type" : "uint",
461
"start" : -8,
462
"size" : 8,
463
}
464
elif name == "struct":
465
self.struct = object_name
466
self.structs[attrs["name"]] = 1
467
elif name == "register":
468
self.register = object_name
469
self.reg_num = num_from_str(attrs["num"])
470
self.registers[attrs["name"]] = 1
471
472
self.group = Group(self, None, 0, 1)
473
if default_field:
474
field = Field(self, default_field)
475
field.values = []
476
self.group.fields.append(field)
477
478
if "min_ver" in attrs:
479
self.group.min_ver = attrs["min_ver"]
480
if "max_ver" in attrs:
481
self.group.max_ver = attrs["max_ver"]
482
483
elif name == "field":
484
self.group.fields.append(Field(self, attrs))
485
self.values = []
486
elif name == "enum":
487
self.values = []
488
self.enum = safe_name(attrs["name"])
489
self.enums.add(attrs["name"])
490
self.enum_enabled = self.attrs_version_valid(attrs)
491
if "prefix" in attrs:
492
self.prefix = attrs["prefix"]
493
else:
494
self.prefix= None
495
elif name == "value":
496
if self.attrs_version_valid(attrs):
497
self.values.append(Value(attrs))
498
499
def end_element(self, name):
500
if name == "packet":
501
self.emit_packet()
502
self.packet = None
503
self.group = None
504
elif name == "struct":
505
self.emit_struct()
506
self.struct = None
507
self.group = None
508
elif name == "register":
509
self.emit_register()
510
self.register = None
511
self.reg_num = None
512
self.group = None
513
elif name == "field":
514
self.group.fields[-1].values = self.values
515
elif name == "enum":
516
if self.enum_enabled:
517
self.emit_enum()
518
self.enum = None
519
elif name == "vcxml":
520
print('#endif /* %s */' % self.gen_guard())
521
522
def emit_template_struct(self, name, group):
523
print("struct %s {" % name)
524
group.emit_template_struct("")
525
print("};\n")
526
527
def emit_pack_function(self, name, group):
528
print("static inline void\n%s_pack(__gen_user_data *data, uint8_t * restrict cl,\n%sconst struct %s * restrict values)\n{" %
529
(name, ' ' * (len(name) + 6), name))
530
531
group.emit_pack_function(0)
532
533
print("}\n")
534
535
print('#define %-33s %6d' %
536
(name + "_length", self.group.length))
537
538
def emit_unpack_function(self, name, group):
539
print("#ifdef __gen_unpack_address")
540
print("static inline void")
541
print("%s_unpack(const uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" %
542
(name, ' ' * (len(name) + 8), name))
543
544
group.emit_unpack_function(0)
545
546
print("}\n#endif\n")
547
548
def emit_header(self, name):
549
default_fields = []
550
for field in self.group.fields:
551
if not type(field) is Field:
552
continue
553
if field.default == None:
554
continue
555
default_fields.append(" .%-35s = %6d" % (field.name, field.default))
556
557
print('#define %-40s\\' % (name + '_header'))
558
print(", \\\n".join(default_fields))
559
print('')
560
561
def emit_packet(self):
562
if not self.group_enabled():
563
return
564
565
name = self.packet
566
567
assert(self.group.fields[0].name == "opcode")
568
print('#define %-33s %6d' %
569
(name + "_opcode", self.group.fields[0].default))
570
571
self.emit_header(name)
572
self.emit_template_struct(self.packet, self.group)
573
self.emit_pack_function(self.packet, self.group)
574
self.emit_unpack_function(self.packet, self.group)
575
576
print('')
577
578
def emit_register(self):
579
if not self.group_enabled():
580
return
581
582
name = self.register
583
if not self.reg_num == None:
584
print('#define %-33s 0x%04x' %
585
(self.gen_prefix(name + "_num"), self.reg_num))
586
587
self.emit_template_struct(self.register, self.group)
588
self.emit_pack_function(self.register, self.group)
589
self.emit_unpack_function(self.register, self.group)
590
591
def emit_struct(self):
592
if not self.group_enabled():
593
return
594
595
name = self.struct
596
597
self.emit_header(name)
598
self.emit_template_struct(self.struct, self.group)
599
self.emit_pack_function(self.struct, self.group)
600
self.emit_unpack_function(self.struct, self.group)
601
602
print('')
603
604
def emit_enum(self):
605
print('enum %s {' % self.gen_prefix(self.enum))
606
for value in self.values:
607
name = value.name
608
if self.prefix:
609
name = self.prefix + "_" + name
610
name = safe_name(name).upper()
611
print(' % -36s = %6d,' % (name, value.value))
612
print('};\n')
613
614
def parse(self, filename):
615
file = open(filename, "rb")
616
self.parser.ParseFile(file)
617
file.close()
618
619
if len(sys.argv) < 2:
620
print("No input xml file specified")
621
sys.exit(1)
622
623
input_file = sys.argv[1]
624
625
p = Parser(sys.argv[2])
626
p.parse(input_file)
627
628