8c2feebca830f6df24d8ddcb2b1abe5b294dad19
3 # Copyright (C) 2016 Intel Corporation
4 # Copyright (C) 2016 Broadcom
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:
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
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
25 from __future__
import (
26 absolute_import
, division
, print_function
, unicode_literals
28 import xml
.parsers
.expat
33 license
= """/* Generated code, see v3d_packet_v21.xml, v3d_packet_v33.xml and gen_pack_header.py */
36 pack_header
= """%(license)s
38 /* Packets, enums and structures for %(platform)s.
40 * This file has been generated, do not hand edit.
46 #include "cle/v3d_packet_helpers.h"
50 def to_alphanum(name
):
73 for i
, j
in substitutions
.items():
74 name
= name
.replace(i
, j
)
79 name
= to_alphanum(name
)
80 if not name
[0].isalpha():
85 def prefixed_upper_name(prefix
, name
):
87 name
= prefix
+ "_" + name
88 return safe_name(name
).upper()
90 def num_from_str(num_str
):
91 if num_str
.lower().startswith('0x'):
92 return int(num_str
, base
=16)
94 assert(not num_str
.startswith('0') and 'octals numbers not allowed')
98 ufixed_pattern
= re
.compile(r
"u(\d+)\.(\d+)")
99 sfixed_pattern
= re
.compile(r
"s(\d+)\.(\d+)")
101 def __init__(self
, parser
, attrs
):
104 self
.name
= safe_name(attrs
["name"]).lower()
106 if str(attrs
["start"]).endswith("b"):
107 self
.start
= int(attrs
["start"][:-1]) * 8
109 self
.start
= int(attrs
["start"])
110 # packet <field> entries in XML start from the bit after the
111 # opcode, so shift everything up by 8 since we'll also have a
112 # Field for the opcode.
113 if not parser
.struct
:
116 self
.end
= self
.start
+ int(attrs
["size"]) - 1
117 self
.type = attrs
["type"]
119 if self
.type == 'bool' and self
.start
!= self
.end
:
120 print("#error Field {} has bool type but more than one bit of size".format(self
.name
));
122 if "prefix" in attrs
:
123 self
.prefix
= safe_name(attrs
["prefix"]).upper()
127 if "default" in attrs
:
128 self
.default
= int(attrs
["default"])
132 if "minus_one" in attrs
:
133 assert(attrs
["minus_one"] == "true")
134 self
.minus_one
= True
136 self
.minus_one
= False
138 ufixed_match
= Field
.ufixed_pattern
.match(self
.type)
141 self
.fractional_size
= int(ufixed_match
.group(2))
143 sfixed_match
= Field
.sfixed_pattern
.match(self
.type)
146 self
.fractional_size
= int(sfixed_match
.group(2))
148 def emit_template_struct(self
, dim
):
149 if self
.type == 'address':
150 type = '__gen_address_type'
151 elif self
.type == 'bool':
153 elif self
.type == 'float':
155 elif self
.type == 'f187':
157 elif self
.type == 'ufixed':
159 elif self
.type == 'sfixed':
161 elif self
.type == 'uint' and self
.end
- self
.start
> 32:
163 elif self
.type == 'offset':
165 elif self
.type == 'int':
167 elif self
.type == 'uint':
169 elif self
.type in self
.parser
.structs
:
170 type = 'struct ' + self
.parser
.gen_prefix(safe_name(self
.type))
171 elif self
.type in self
.parser
.enums
:
172 type = 'enum ' + self
.parser
.gen_prefix(safe_name(self
.type))
173 elif self
.type == 'mbo':
176 print("#error unhandled type: %s" % self
.type)
179 print(" %-36s %s%s;" % (type, self
.name
, dim
))
181 for value
in self
.values
:
182 name
= prefixed_upper_name(self
.prefix
, value
.name
)
183 print("#define %-40s %d" % (name
, value
.value
))
185 def overlaps(self
, field
):
186 return self
!= field
and max(self
.start
, field
.start
) <= min(self
.end
, field
.end
)
190 def __init__(self
, parser
, parent
, start
, count
):
200 def emit_template_struct(self
, dim
):
202 print(" /* variable length fields follow */")
205 dim
= "%s[%d]" % (dim
, self
.count
)
207 for field
in self
.fields
:
208 field
.emit_template_struct(dim
)
216 def collect_bytes(self
, bytes
):
217 for field
in self
.fields
:
218 first_byte
= field
.start
// 8
219 last_byte
= field
.end
// 8
221 for b
in range(first_byte
, last_byte
+ 1):
223 bytes
[b
] = self
.Byte()
225 bytes
[b
].fields
.append(field
)
227 if field
.type == "address":
228 # assert bytes[index].address == None
229 bytes
[b
].address
= field
231 def emit_pack_function(self
, start
):
232 # Determine number of bytes in this group.
233 self
.length
= max(field
.end
// 8 for field
in self
.fields
) + 1
236 self
.collect_bytes(bytes
)
238 relocs_emitted
= set()
239 memcpy_fields
= set()
241 for field
in self
.fields
:
243 print(" assert(values->%s >= 1);" % field
.name
)
245 for index
in range(self
.length
):
247 if not index
in bytes
:
248 print(" cl[%2d] = 0;" % index
)
252 # Call out to the driver to note our relocations. Inside of the
253 # packet we only store offsets within the BOs, and we store the
254 # handle to the packet outside. Unlike Intel genxml, we don't
255 # need to have the other bits that will be stored together with
256 # the address during the reloc process, so there's no need for the
257 # complicated combine_address() function.
258 if byte
.address
and byte
.address
not in relocs_emitted
:
259 print(" __gen_emit_reloc(data, &values->%s);" % byte
.address
.name
)
260 relocs_emitted
.add(byte
.address
)
262 # Special case: floats can't have any other fields packed into
263 # them (since they'd change the meaning of the float), and the
264 # per-byte bitshifting math below bloats the pack code for floats,
265 # so just copy them directly here. Also handle 16/32-bit
266 # uints/ints with no merged fields.
267 if len(byte
.fields
) == 1:
268 field
= byte
.fields
[0]
269 if field
.type in ["float", "uint", "int"] and field
.start
% 8 == 0 and field
.end
- field
.start
== 31 and not field
.minus_one
:
270 if field
in memcpy_fields
:
273 if not any(field
.overlaps(scan_field
) for scan_field
in self
.fields
):
274 assert(field
.start
== index
* 8)
276 print(" memcpy(&cl[%d], &values->%s, sizeof(values->%s));" %
277 (index
, field
.name
, field
.name
))
278 memcpy_fields
.add(field
)
281 byte_start
= index
* 8
284 prefix
= " cl[%2d] =" % index
287 for field
in byte
.fields
:
288 if field
.type != "mbo":
293 field_byte_start
= (field
.start
// 8) * 8
294 start
-= field_byte_start
295 end
-= field_byte_start
298 value
= "values->%s" % name
300 value
= "%s - 1" % value
302 if field
.type == "mbo":
303 s
= "__gen_mbo(%d, %d)" % \
305 elif field
.type == "address":
306 extra_shift
= (31 - (end
- start
)) // 8 * 8
307 s
= "__gen_address_offset(&values->%s)" % byte
.address
.name
308 elif field
.type == "uint":
309 s
= "__gen_uint(%s, %d, %d)" % \
311 elif field
.type in self
.parser
.enums
:
312 s
= "__gen_uint(%s, %d, %d)" % \
314 elif field
.type == "int":
315 s
= "__gen_sint(%s, %d, %d)" % \
317 elif field
.type == "bool":
318 s
= "__gen_uint(%s, %d, %d)" % \
320 elif field
.type == "float":
321 s
= "#error %s float value mixed in with other fields" % name
322 elif field
.type == "f187":
323 s
= "__gen_uint(fui(%s) >> 16, %d, %d)" % \
325 elif field
.type == "offset":
326 s
= "__gen_offset(%s, %d, %d)" % \
328 elif field
.type == 'ufixed':
329 s
= "__gen_ufixed(%s, %d, %d, %d)" % \
330 (value
, start
, end
, field
.fractional_size
)
331 elif field
.type == 'sfixed':
332 s
= "__gen_sfixed(%s, %d, %d, %d)" % \
333 (value
, start
, end
, field
.fractional_size
)
334 elif field
.type in self
.parser
.structs
:
335 s
= "__gen_uint(v%d_%d, %d, %d)" % \
336 (index
, field_index
, start
, end
)
337 field_index
= field_index
+ 1
339 print("/* unhandled field %s, type %s */\n" % (name
, field
.type))
343 shift
= byte_start
- field_byte_start
+ extra_shift
345 s
= "%s >> %d" % (s
, shift
)
347 if field
== byte
.fields
[-1]:
348 print("%s %s;" % (prefix
, s
))
350 print("%s %s |" % (prefix
, s
))
356 def emit_unpack_function(self
, start
):
357 for field
in self
.fields
:
358 if field
.type != "mbo":
363 args
.append(str(start
+ field
.start
))
364 args
.append(str(start
+ field
.end
))
366 if field
.type == "address":
367 convert
= "__gen_unpack_address"
368 elif field
.type == "uint":
369 convert
= "__gen_unpack_uint"
370 elif field
.type in self
.parser
.enums
:
371 convert
= "__gen_unpack_uint"
372 elif field
.type == "int":
373 convert
= "__gen_unpack_sint"
374 elif field
.type == "bool":
375 convert
= "__gen_unpack_uint"
376 elif field
.type == "float":
377 convert
= "__gen_unpack_float"
378 elif field
.type == "f187":
379 convert
= "__gen_unpack_f187"
380 elif field
.type == "offset":
381 convert
= "__gen_unpack_offset"
382 elif field
.type == 'ufixed':
383 args
.append(str(field
.fractional_size
))
384 convert
= "__gen_unpack_ufixed"
385 elif field
.type == 'sfixed':
386 args
.append(str(field
.fractional_size
))
387 convert
= "__gen_unpack_sfixed"
389 print("/* unhandled field %s, type %s */\n" % (field
.name
, field
.type))
395 print(" values->%s = %s(%s)%s;" % \
396 (field
.name
, convert
, ', '.join(args
), plusone
))
399 def __init__(self
, attrs
):
400 self
.name
= attrs
["name"]
401 self
.value
= int(attrs
["value"])
403 class Parser(object):
404 def __init__(self
, ver
):
405 self
.parser
= xml
.parsers
.expat
.ParserCreate()
406 self
.parser
.StartElementHandler
= self
.start_element
407 self
.parser
.EndElementHandler
= self
.end_element
412 # Set of enum names we've seen.
417 def gen_prefix(self
, name
):
419 return 'V3D%s%s' % (self
.ver
, name
)
421 return 'V3D%s_%s' % (self
.ver
, name
)
424 return self
.gen_prefix("PACK_H")
426 def attrs_version_valid(self
, attrs
):
427 if "min_ver" in attrs
and self
.ver
< attrs
["min_ver"]:
430 if "max_ver" in attrs
and self
.ver
> attrs
["max_ver"]:
435 def group_enabled(self
):
436 if self
.group
.min_ver
!= 0 and self
.ver
< self
.group
.min_ver
:
439 if self
.group
.max_ver
!= 0 and self
.ver
> self
.group
.max_ver
:
444 def start_element(self
, name
, attrs
):
446 self
.platform
= "V3D {}.{}".format(self
.ver
[0], self
.ver
[1])
447 print(pack_header
% {'license': license
, 'platform': self
.platform
, 'guard': self
.gen_guard()})
448 elif name
in ("packet", "struct", "register"):
451 object_name
= self
.gen_prefix(safe_name(attrs
["name"].upper()))
453 self
.packet
= object_name
455 # Add a fixed Field for the opcode. We only make <field>s in
456 # the XML for the fields listed in the spec, and all of those
457 # start from bit 0 after of the opcode.
460 "default" : attrs
["code"],
465 elif name
== "struct":
466 self
.struct
= object_name
467 self
.structs
[attrs
["name"]] = 1
468 elif name
== "register":
469 self
.register
= object_name
470 self
.reg_num
= num_from_str(attrs
["num"])
471 self
.registers
[attrs
["name"]] = 1
473 self
.group
= Group(self
, None, 0, 1)
475 field
= Field(self
, default_field
)
477 self
.group
.fields
.append(field
)
479 if "min_ver" in attrs
:
480 self
.group
.min_ver
= attrs
["min_ver"]
481 if "max_ver" in attrs
:
482 self
.group
.max_ver
= attrs
["max_ver"]
484 elif name
== "field":
485 self
.group
.fields
.append(Field(self
, attrs
))
489 self
.enum
= safe_name(attrs
["name"])
490 self
.enums
.add(attrs
["name"])
491 self
.enum_enabled
= self
.attrs_version_valid(attrs
)
492 if "prefix" in attrs
:
493 self
.prefix
= attrs
["prefix"]
496 elif name
== "value":
497 if self
.attrs_version_valid(attrs
):
498 self
.values
.append(Value(attrs
))
500 def end_element(self
, name
):
505 elif name
== "struct":
509 elif name
== "register":
514 elif name
== "field":
515 self
.group
.fields
[-1].values
= self
.values
517 if self
.enum_enabled
:
520 elif name
== "vcxml":
521 print('#endif /* %s */' % self
.gen_guard())
523 def emit_template_struct(self
, name
, group
):
524 print("struct %s {" % name
)
525 group
.emit_template_struct("")
528 def emit_pack_function(self
, name
, group
):
529 print("static inline void\n%s_pack(__gen_user_data *data, uint8_t * restrict cl,\n%sconst struct %s * restrict values)\n{" %
530 (name
, ' ' * (len(name
) + 6), name
))
532 group
.emit_pack_function(0)
536 print('#define %-33s %6d' %
537 (name
+ "_length", self
.group
.length
))
539 def emit_unpack_function(self
, name
, group
):
540 print("#ifdef __gen_unpack_address")
541 print("static inline void")
542 print("%s_unpack(const uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" %
543 (name
, ' ' * (len(name
) + 8), name
))
545 group
.emit_unpack_function(0)
549 def emit_header(self
, name
):
551 for field
in self
.group
.fields
:
552 if not type(field
) is Field
:
554 if field
.default
== None:
556 default_fields
.append(" .%-35s = %6d" % (field
.name
, field
.default
))
558 print('#define %-40s\\' % (name
+ '_header'))
559 print(", \\\n".join(default_fields
))
562 def emit_packet(self
):
563 if not self
.group_enabled():
568 assert(self
.group
.fields
[0].name
== "opcode")
569 print('#define %-33s %6d' %
570 (name
+ "_opcode", self
.group
.fields
[0].default
))
572 self
.emit_header(name
)
573 self
.emit_template_struct(self
.packet
, self
.group
)
574 self
.emit_pack_function(self
.packet
, self
.group
)
575 self
.emit_unpack_function(self
.packet
, self
.group
)
579 def emit_register(self
):
580 if not self
.group_enabled():
584 if not self
.reg_num
== None:
585 print('#define %-33s 0x%04x' %
586 (self
.gen_prefix(name
+ "_num"), self
.reg_num
))
588 self
.emit_template_struct(self
.register
, self
.group
)
589 self
.emit_pack_function(self
.register
, self
.group
)
590 self
.emit_unpack_function(self
.register
, self
.group
)
592 def emit_struct(self
):
593 if not self
.group_enabled():
598 self
.emit_header(name
)
599 self
.emit_template_struct(self
.struct
, self
.group
)
600 self
.emit_pack_function(self
.struct
, self
.group
)
601 self
.emit_unpack_function(self
.struct
, self
.group
)
606 print('enum %s {' % self
.gen_prefix(self
.enum
))
607 for value
in self
.values
:
610 name
= self
.prefix
+ "_" + name
611 name
= safe_name(name
).upper()
612 print(' % -36s = %6d,' % (name
, value
.value
))
615 def parse(self
, filename
):
616 file = open(filename
, "rb")
617 self
.parser
.ParseFile(file)
620 if len(sys
.argv
) < 2:
621 print("No input xml file specified")
624 input_file
= sys
.argv
[1]
626 p
= Parser(sys
.argv
[2])