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 25from __future__ import ( 26 absolute_import, division, print_function, unicode_literals 27) 28import xml.parsers.expat 29import re 30import sys 31import copy 32 33license = """/* Generated code, see v3d_packet_v21.xml, v3d_packet_v33.xml and gen_pack_header.py */ 34""" 35 36pack_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 50def 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 77def safe_name(name): 78 name = to_alphanum(name) 79 if not name[0].isalpha(): 80 name = '_' + name 81 82 return name 83 84def prefixed_upper_name(prefix, name): 85 if prefix: 86 name = prefix + "_" + name 87 return safe_name(name).upper() 88 89def 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 96class 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 188class 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 397class Value(object): 398 def __init__(self, attrs): 399 self.name = attrs["name"] 400 self.value = int(attrs["value"]) 401 402class 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 619if len(sys.argv) < 2: 620 print("No input xml file specified") 621 sys.exit(1) 622 623input_file = sys.argv[1] 624 625p = Parser(sys.argv[2]) 626p.parse(input_file) 627