1#encoding=utf-8 2 3import argparse 4import ast 5import xml.parsers.expat 6import re 7import sys 8import copy 9import textwrap 10from util import * 11 12license = """/* 13 * Copyright (C) 2016 Intel Corporation 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining a 16 * copy of this software and associated documentation files (the "Software"), 17 * to deal in the Software without restriction, including without limitation 18 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 19 * and/or sell copies of the Software, and to permit persons to whom the 20 * Software is furnished to do so, subject to the following conditions: 21 * 22 * The above copyright notice and this permission notice (including the next 23 * paragraph) shall be included in all copies or substantial portions of the 24 * Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 29 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 32 * IN THE SOFTWARE. 33 */ 34""" 35 36pack_header = """%(license)s 37 38/* Instructions, 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 <stdio.h> 47#include <stdint.h> 48#include <stdbool.h> 49#include <assert.h> 50#include <math.h> 51 52#ifndef __gen_validate_value 53#define __gen_validate_value(x) 54#endif 55 56#ifndef __intel_field_functions 57#define __intel_field_functions 58 59#ifdef NDEBUG 60#define NDEBUG_UNUSED __attribute__((unused)) 61#else 62#define NDEBUG_UNUSED 63#endif 64 65union __intel_value { 66 float f; 67 uint32_t dw; 68}; 69 70static inline __attribute__((always_inline)) uint64_t 71__gen_mbo(uint32_t start, uint32_t end) 72{ 73 return (~0ull >> (64 - (end - start + 1))) << start; 74} 75 76static inline __attribute__((always_inline)) uint64_t 77__gen_uint(uint64_t v, uint32_t start, NDEBUG_UNUSED uint32_t end) 78{ 79 __gen_validate_value(v); 80 81#ifndef NDEBUG 82 const int width = end - start + 1; 83 if (width < 64) { 84 const uint64_t max = (1ull << width) - 1; 85 assert(v <= max); 86 } 87#endif 88 89 return v << start; 90} 91 92static inline __attribute__((always_inline)) uint64_t 93__gen_uint_nonzero(uint64_t v, uint32_t start, uint32_t end) 94{ 95 assert(v != 0ull); 96 return __gen_uint(v, start, end); 97} 98 99static inline __attribute__((always_inline)) uint64_t 100__gen_sint(int64_t v, uint32_t start, uint32_t end) 101{ 102 const int width = end - start + 1; 103 104 __gen_validate_value(v); 105 106#ifndef NDEBUG 107 if (width < 64) { 108 const int64_t max = (1ll << (width - 1)) - 1; 109 const int64_t min = -(1ll << (width - 1)); 110 assert(min <= v && v <= max); 111 } 112#endif 113 114 const uint64_t mask = ~0ull >> (64 - width); 115 116 return (v & mask) << start; 117} 118 119static inline __attribute__((always_inline)) uint64_t 120__gen_sint_nonzero(int64_t v, uint32_t start, uint32_t end) 121{ 122 assert(v != 0ll); 123 return __gen_sint(v, start, end); 124} 125 126static inline __attribute__((always_inline)) uint64_t 127__gen_offset(uint64_t v, NDEBUG_UNUSED uint32_t start, NDEBUG_UNUSED uint32_t end) 128{ 129 __gen_validate_value(v); 130#ifndef NDEBUG 131 uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; 132 133 assert((v & ~mask) == 0); 134#endif 135 136 return v; 137} 138 139static inline __attribute__((always_inline)) uint64_t 140__gen_offset_nonzero(uint64_t v, uint32_t start, uint32_t end) 141{ 142 assert(v != 0ull); 143 return __gen_offset(v, start, end); 144} 145 146static inline __attribute__((always_inline)) uint64_t 147__gen_address(__gen_user_data *data, void *location, 148 __gen_address_type address, uint32_t delta, 149 __attribute__((unused)) uint32_t start, uint32_t end) 150{ 151 uint64_t addr_u64 = __gen_combine_address(data, location, address, delta); 152 if (end == 31) { 153 return addr_u64; 154 } else if (end < 63) { 155 const unsigned shift = 63 - end; 156 return (addr_u64 << shift) >> shift; 157 } else { 158 return addr_u64; 159 } 160} 161 162static inline __attribute__((always_inline)) uint32_t 163__gen_float(float v) 164{ 165 __gen_validate_value(v); 166 return ((union __intel_value) { .f = (v) }).dw; 167} 168 169static inline __attribute__((always_inline)) uint32_t 170__gen_float_nonzero(float v) 171{ 172 assert(v != 0.0f); 173 return __gen_float(v); 174} 175 176static inline __attribute__((always_inline)) uint64_t 177__gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) 178{ 179 __gen_validate_value(v); 180 181 const float factor = (1 << fract_bits); 182 183#ifndef NDEBUG 184 const float max = ((1 << (end - start)) - 1) / factor; 185 const float min = -(1 << (end - start)) / factor; 186 assert(min <= v && v <= max); 187#endif 188 189 const int64_t int_val = llroundf(v * factor); 190 const uint64_t mask = ~0ull >> (64 - (end - start + 1)); 191 192 return (int_val & mask) << start; 193} 194 195static inline __attribute__((always_inline)) uint64_t 196__gen_sfixed_nonzero(float v, uint32_t start, uint32_t end, uint32_t fract_bits) 197{ 198 assert(v != 0.0f); 199 return __gen_sfixed(v, start, end, fract_bits); 200} 201 202static inline __attribute__((always_inline)) uint64_t 203__gen_ufixed(float v, uint32_t start, NDEBUG_UNUSED uint32_t end, uint32_t fract_bits) 204{ 205 __gen_validate_value(v); 206 207 const float factor = (1 << fract_bits); 208 209#ifndef NDEBUG 210 const float max = ((1 << (end - start + 1)) - 1) / factor; 211 const float min = 0.0f; 212 assert(min <= v && v <= max); 213#endif 214 215 const uint64_t uint_val = llroundf(v * factor); 216 217 return uint_val << start; 218} 219 220static inline __attribute__((always_inline)) uint64_t 221__gen_ufixed_nonzero(float v, uint32_t start, uint32_t end, uint32_t fract_bits) 222{ 223 assert(v != 0.0f); 224 return __gen_ufixed(v, start, end, fract_bits); 225} 226 227#ifndef __gen_address_type 228#error #define __gen_address_type before including this file 229#endif 230 231#ifndef __gen_user_data 232#error #define __gen_combine_address before including this file 233#endif 234 235#undef NDEBUG_UNUSED 236 237#endif 238 239""" 240 241def num_from_str(num_str): 242 if num_str.lower().startswith('0x'): 243 return int(num_str, base=16) 244 245 assert not num_str.startswith('0'), 'octals numbers not allowed' 246 return int(num_str) 247 248def bool_from_str(bool_str): 249 options = { "true": True, "false": False } 250 return options[bool_str]; 251 252class Field(object): 253 ufixed_pattern = re.compile(r"u(\d+)\.(\d+)") 254 sfixed_pattern = re.compile(r"s(\d+)\.(\d+)") 255 256 def __init__(self, parser, attrs): 257 self.parser = parser 258 if "name" in attrs: 259 self.name = safe_name(attrs["name"]) 260 self.start = int(attrs["start"]) 261 self.end = int(attrs["end"]) 262 self.type = attrs["type"] 263 self.nonzero = bool_from_str(attrs.get("nonzero", "false")) 264 265 assert self.start <= self.end, \ 266 'field {} has end ({}) < start ({})'.format(self.name, self.end, 267 self.start) 268 if self.type == 'bool': 269 assert self.end == self.start, \ 270 'bool field ({}) is too wide'.format(self.name) 271 272 if "prefix" in attrs: 273 self.prefix = attrs["prefix"] 274 else: 275 self.prefix = None 276 277 if "default" in attrs: 278 # Base 0 recognizes 0x, 0o, 0b prefixes in addition to decimal ints. 279 self.default = int(attrs["default"], base=0) 280 else: 281 self.default = None 282 283 ufixed_match = Field.ufixed_pattern.match(self.type) 284 if ufixed_match: 285 self.type = 'ufixed' 286 self.fractional_size = int(ufixed_match.group(2)) 287 288 sfixed_match = Field.sfixed_pattern.match(self.type) 289 if sfixed_match: 290 self.type = 'sfixed' 291 self.fractional_size = int(sfixed_match.group(2)) 292 293 def is_builtin_type(self): 294 builtins = [ 'address', 'bool', 'float', 'ufixed', 295 'offset', 'sfixed', 'offset', 'int', 'uint', 296 'mbo', 'mbz' ] 297 return self.type in builtins 298 299 def is_struct_type(self): 300 return self.type in self.parser.structs 301 302 def is_enum_type(self): 303 return self.type in self.parser.enums 304 305 def emit_template_struct(self, dim): 306 if self.type == 'address': 307 type = '__gen_address_type' 308 elif self.type == 'bool': 309 type = 'bool' 310 elif self.type == 'float': 311 type = 'float' 312 elif self.type == 'ufixed': 313 type = 'float' 314 elif self.type == 'sfixed': 315 type = 'float' 316 elif self.type == 'uint' and self.end - self.start > 32: 317 type = 'uint64_t' 318 elif self.type == 'offset': 319 type = 'uint64_t' 320 elif self.type == 'int': 321 type = 'int32_t' 322 elif self.type == 'uint': 323 type = 'uint32_t' 324 elif self.is_struct_type(): 325 type = 'struct ' + self.parser.gen_prefix(safe_name(self.type)) 326 elif self.is_enum_type(): 327 type = 'enum ' + self.parser.gen_prefix(safe_name(self.type)) 328 elif self.type == 'mbo' or self.type == 'mbz': 329 return 330 else: 331 print("#error unhandled type: %s" % self.type) 332 return 333 334 print(" %-36s %s%s;" % (type, self.name, dim)) 335 336 prefix = self.prefix + '_' if self.prefix else '' 337 338 for value in self.values: 339 name = value.name 340 if self.prefix and value.name[0] == '_': 341 name = name[1:] 342 343 print("#define %-40s %d" % (prefix + name, value.value)) 344 345class Group(object): 346 def __init__(self, parser, parent, start, count, size): 347 self.parser = parser 348 self.parent = parent 349 self.start = start 350 self.count = count 351 self.size = size 352 self.fields = [] 353 354 def emit_template_struct(self, dim): 355 if self.count == 0: 356 print(" /* variable length fields follow */") 357 else: 358 if self.count > 1: 359 dim = "%s[%d]" % (dim, self.count) 360 361 for field in self.fields: 362 field.emit_template_struct(dim) 363 364 class DWord: 365 def __init__(self): 366 self.size = 32 367 self.fields = [] 368 self.address = None 369 370 def collect_dwords(self, dwords, start, dim): 371 for field in self.fields: 372 if isinstance(field, Group): 373 if field.count == 1: 374 field.collect_dwords(dwords, start + field.start, dim) 375 else: 376 for i in range(field.count): 377 field.collect_dwords(dwords, 378 start + field.start + i * field.size, 379 "%s[%d]" % (dim, i)) 380 continue 381 382 index = (start + field.start) // 32 383 if not index in dwords: 384 dwords[index] = self.DWord() 385 386 clone = copy.copy(field) 387 clone.start = clone.start + start 388 clone.end = clone.end + start 389 clone.dim = dim 390 dwords[index].fields.append(clone) 391 392 if field.type == "address": 393 # assert dwords[index].address == None 394 dwords[index].address = clone 395 396 # Coalesce all the dwords covered by this field. The two cases we 397 # handle are where multiple fields are in a 64 bit word (typically 398 # and address and a few bits) or where a single struct field 399 # completely covers multiple dwords. 400 while index < (start + field.end) // 32: 401 if index + 1 in dwords and not dwords[index] == dwords[index + 1]: 402 dwords[index].fields.extend(dwords[index + 1].fields) 403 dwords[index].size = 64 404 dwords[index + 1] = dwords[index] 405 index = index + 1 406 407 def collect_dwords_and_length(self): 408 dwords = {} 409 self.collect_dwords(dwords, 0, "") 410 411 # Determine number of dwords in this group. If we have a size, use 412 # that, since that'll account for MBZ dwords at the end of a group 413 # (like dword 8 on BDW+ 3DSTATE_HS). Otherwise, use the largest dword 414 # index we've seen plus one. 415 if self.size > 0: 416 length = self.size // 32 417 elif dwords: 418 length = max(dwords.keys()) + 1 419 else: 420 length = 0 421 422 return (dwords, length) 423 424 def emit_pack_function(self, dwords, length): 425 for index in range(length): 426 # Handle MBZ dwords 427 if not index in dwords: 428 print("") 429 print(" dw[%d] = 0;" % index) 430 continue 431 432 # For 64 bit dwords, we aliased the two dword entries in the dword 433 # dict it occupies. Now that we're emitting the pack function, 434 # skip the duplicate entries. 435 dw = dwords[index] 436 if index > 0 and index - 1 in dwords and dw == dwords[index - 1]: 437 continue 438 439 # Special case: only one field and it's a struct at the beginning 440 # of the dword. In this case we pack directly into the 441 # destination. This is the only way we handle embedded structs 442 # larger than 32 bits. 443 if len(dw.fields) == 1: 444 field = dw.fields[0] 445 name = field.name + field.dim 446 if field.is_struct_type() and field.start % 32 == 0: 447 print("") 448 print(" %s_pack(data, &dw[%d], &values->%s);" % 449 (self.parser.gen_prefix(safe_name(field.type)), index, name)) 450 continue 451 452 # Pack any fields of struct type first so we have integer values 453 # to the dword for those fields. 454 field_index = 0 455 for field in dw.fields: 456 if isinstance(field, Field) and field.is_struct_type(): 457 name = field.name + field.dim 458 print("") 459 print(" uint32_t v%d_%d;" % (index, field_index)) 460 print(" %s_pack(data, &v%d_%d, &values->%s);" % 461 (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name)) 462 field_index = field_index + 1 463 464 print("") 465 dword_start = index * 32 466 if dw.address == None: 467 address_count = 0 468 else: 469 address_count = 1 470 471 if dw.size == 32 and dw.address == None: 472 v = None 473 print(" dw[%d] =" % index) 474 elif len(dw.fields) > address_count: 475 v = "v%d" % index 476 print(" const uint%d_t %s =" % (dw.size, v)) 477 else: 478 v = "0" 479 480 field_index = 0 481 non_address_fields = [] 482 for field in dw.fields: 483 if field.type != "mbo" and field.type != "mbz": 484 name = field.name + field.dim 485 486 nz = "_nonzero" if field.nonzero else "" 487 488 if field.type == "mbo": 489 non_address_fields.append("__gen_mbo(%d, %d)" % \ 490 (field.start - dword_start, field.end - dword_start)) 491 elif field.type == "mbz": 492 assert not field.nonzero 493 elif field.type == "address": 494 pass 495 elif field.type == "uint": 496 non_address_fields.append("__gen_uint%s(values->%s, %d, %d)" % \ 497 (nz, name, field.start - dword_start, field.end - dword_start)) 498 elif field.is_enum_type(): 499 non_address_fields.append("__gen_uint%s(values->%s, %d, %d)" % \ 500 (nz, name, field.start - dword_start, field.end - dword_start)) 501 elif field.type == "int": 502 non_address_fields.append("__gen_sint%s(values->%s, %d, %d)" % \ 503 (nz, name, field.start - dword_start, field.end - dword_start)) 504 elif field.type == "bool": 505 non_address_fields.append("__gen_uint%s(values->%s, %d, %d)" % \ 506 (nz, name, field.start - dword_start, field.end - dword_start)) 507 elif field.type == "float": 508 non_address_fields.append("__gen_float%s(values->%s)" % (nz, name)) 509 elif field.type == "offset": 510 non_address_fields.append("__gen_offset%s(values->%s, %d, %d)" % \ 511 (nz, name, field.start - dword_start, field.end - dword_start)) 512 elif field.type == 'ufixed': 513 non_address_fields.append("__gen_ufixed%s(values->%s, %d, %d, %d)" % \ 514 (nz, name, field.start - dword_start, field.end - dword_start, field.fractional_size)) 515 elif field.type == 'sfixed': 516 non_address_fields.append("__gen_sfixed%s(values->%s, %d, %d, %d)" % \ 517 (nz, name, field.start - dword_start, field.end - dword_start, field.fractional_size)) 518 elif field.is_struct_type(): 519 non_address_fields.append("__gen_uint(v%d_%d, %d, %d)" % \ 520 (index, field_index, field.start - dword_start, field.end - dword_start)) 521 field_index = field_index + 1 522 else: 523 non_address_fields.append("/* unhandled field %s, type %s */\n" % \ 524 (name, field.type)) 525 526 if non_address_fields: 527 print(" |\n".join(" " + f for f in non_address_fields) + ";") 528 529 if dw.size == 32: 530 if dw.address: 531 print(" dw[%d] = __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % 532 (index, index, dw.address.name + field.dim, v, 533 dw.address.start - dword_start, dw.address.end - dword_start)) 534 continue 535 536 if dw.address: 537 v_address = "v%d_address" % index 538 print(" const uint64_t %s =\n __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % 539 (v_address, index, dw.address.name + field.dim, v, 540 dw.address.start - dword_start, dw.address.end - dword_start)) 541 if len(dw.fields) > address_count: 542 print(" dw[%d] = %s;" % (index, v_address)) 543 print(" dw[%d] = (%s >> 32) | (%s >> 32);" % (index + 1, v_address, v)) 544 continue 545 else: 546 v = v_address 547 print(" dw[%d] = %s;" % (index, v)) 548 print(" dw[%d] = %s >> 32;" % (index + 1, v)) 549 550class Value(object): 551 def __init__(self, attrs): 552 self.name = safe_name(attrs["name"]) 553 self.value = ast.literal_eval(attrs["value"]) 554 555class Parser(object): 556 def __init__(self): 557 self.parser = xml.parsers.expat.ParserCreate() 558 self.parser.StartElementHandler = self.start_element 559 self.parser.EndElementHandler = self.end_element 560 561 self.instruction = None 562 self.structs = {} 563 # Set of enum names we've seen. 564 self.enums = set() 565 self.registers = {} 566 567 def gen_prefix(self, name): 568 if name[0] == "_": 569 return 'GFX%s%s' % (self.gen, name) 570 return 'GFX%s_%s' % (self.gen, name) 571 572 def gen_guard(self): 573 return self.gen_prefix("PACK_H") 574 575 def start_element(self, name, attrs): 576 if name == "genxml": 577 self.platform = attrs["name"] 578 self.gen = attrs["gen"].replace('.', '') 579 print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()}) 580 elif name in ("instruction", "struct", "register"): 581 if name == "instruction": 582 self.instruction = safe_name(attrs["name"]) 583 self.length_bias = int(attrs["bias"]) 584 if "engine" in attrs: 585 self.instruction_engines = set(attrs["engine"].split('|')) 586 else: 587 # When an instruction doesn't have the engine specified, 588 # it is considered to be for all engines, so 'None' is used 589 # to signify that the instruction belongs to all engines. 590 self.instruction_engines = None 591 elif name == "struct": 592 self.struct = safe_name(attrs["name"]) 593 self.structs[attrs["name"]] = 1 594 elif name == "register": 595 self.register = safe_name(attrs["name"]) 596 self.reg_num = num_from_str(attrs["num"]) 597 self.registers[attrs["name"]] = 1 598 if "length" in attrs: 599 self.length = int(attrs["length"]) 600 size = self.length * 32 601 else: 602 self.length = None 603 size = 0 604 self.group = Group(self, None, 0, 1, size) 605 606 elif name == "group": 607 group = Group(self, self.group, 608 int(attrs["start"]), int(attrs["count"]), int(attrs["size"])) 609 self.group.fields.append(group) 610 self.group = group 611 elif name == "field": 612 self.group.fields.append(Field(self, attrs)) 613 self.values = [] 614 elif name == "enum": 615 self.values = [] 616 self.enum = safe_name(attrs["name"]) 617 self.enums.add(attrs["name"]) 618 if "prefix" in attrs: 619 self.prefix = safe_name(attrs["prefix"]) 620 else: 621 self.prefix= None 622 elif name == "value": 623 self.values.append(Value(attrs)) 624 625 def end_element(self, name): 626 if name == "instruction": 627 self.emit_instruction() 628 self.instruction = None 629 self.group = None 630 elif name == "struct": 631 self.emit_struct() 632 self.struct = None 633 self.group = None 634 elif name == "register": 635 self.emit_register() 636 self.register = None 637 self.reg_num = None 638 self.group = None 639 elif name == "group": 640 self.group = self.group.parent 641 elif name == "field": 642 self.group.fields[-1].values = self.values 643 elif name == "enum": 644 self.emit_enum() 645 self.enum = None 646 elif name == "genxml": 647 print('#endif /* %s */' % self.gen_guard()) 648 649 def emit_template_struct(self, name, group): 650 print("struct %s {" % self.gen_prefix(name)) 651 group.emit_template_struct("") 652 print("};\n") 653 654 def emit_pack_function(self, name, group): 655 name = self.gen_prefix(name) 656 print(textwrap.dedent("""\ 657 static inline __attribute__((always_inline)) void 658 %s_pack(__attribute__((unused)) __gen_user_data *data, 659 %s__attribute__((unused)) void * restrict dst, 660 %s__attribute__((unused)) const struct %s * restrict values) 661 {""") % (name, ' ' * len(name), ' ' * len(name), name)) 662 663 (dwords, length) = group.collect_dwords_and_length() 664 if length: 665 # Cast dst to make header C++ friendly 666 print(" uint32_t * restrict dw = (uint32_t * restrict) dst;") 667 668 group.emit_pack_function(dwords, length) 669 670 print("}\n") 671 672 def emit_instruction(self): 673 name = self.instruction 674 if self.instruction_engines and not self.instruction_engines & self.engines: 675 return 676 677 if not self.length is None: 678 print('#define %-33s %6d' % 679 (self.gen_prefix(name + "_length"), self.length)) 680 print('#define %-33s %6d' % 681 (self.gen_prefix(name + "_length_bias"), self.length_bias)) 682 683 default_fields = [] 684 for field in self.group.fields: 685 if not isinstance(field, Field): 686 continue 687 if field.default is None: 688 continue 689 690 if field.is_builtin_type(): 691 default_fields.append(" .%-35s = %6d" % (field.name, field.default)) 692 else: 693 # Default values should not apply to structures 694 assert field.is_enum_type() 695 default_fields.append(" .%-35s = (enum %s) %6d" % (field.name, self.gen_prefix(safe_name(field.type)), field.default)) 696 697 if default_fields: 698 print('#define %-40s\\' % (self.gen_prefix(name + '_header'))) 699 print(", \\\n".join(default_fields)) 700 print('') 701 702 self.emit_template_struct(self.instruction, self.group) 703 704 self.emit_pack_function(self.instruction, self.group) 705 706 def emit_register(self): 707 name = self.register 708 if not self.reg_num is None: 709 print('#define %-33s 0x%04x' % 710 (self.gen_prefix(name + "_num"), self.reg_num)) 711 712 if not self.length is None: 713 print('#define %-33s %6d' % 714 (self.gen_prefix(name + "_length"), self.length)) 715 716 self.emit_template_struct(self.register, self.group) 717 self.emit_pack_function(self.register, self.group) 718 719 def emit_struct(self): 720 name = self.struct 721 if not self.length is None: 722 print('#define %-33s %6d' % 723 (self.gen_prefix(name + "_length"), self.length)) 724 725 self.emit_template_struct(self.struct, self.group) 726 self.emit_pack_function(self.struct, self.group) 727 728 def emit_enum(self): 729 print('enum %s {' % self.gen_prefix(self.enum)) 730 for value in self.values: 731 if self.prefix: 732 name = self.prefix + "_" + value.name 733 else: 734 name = value.name 735 print(' %-36s = %6d,' % (name.upper(), value.value)) 736 print('};\n') 737 738 def parse(self, filename): 739 file = open(filename, "rb") 740 self.parser.ParseFile(file) 741 file.close() 742 743def parse_args(): 744 p = argparse.ArgumentParser() 745 p.add_argument('xml_source', metavar='XML_SOURCE', 746 help="Input xml file") 747 p.add_argument('--engines', nargs='?', type=str, default='render', 748 help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)") 749 750 pargs = p.parse_args() 751 752 if pargs.engines is None: 753 print("No engines specified") 754 sys.exit(1) 755 756 return pargs 757 758def main(): 759 pargs = parse_args() 760 761 input_file = pargs.xml_source 762 engines = pargs.engines.split(',') 763 valid_engines = [ 'render', 'blitter', 'video' ] 764 if set(engines) - set(valid_engines): 765 print("Invalid engine specified, valid engines are:\n") 766 for e in valid_engines: 767 print("\t%s" % e) 768 sys.exit(1) 769 770 p = Parser() 771 p.engines = set(engines) 772 p.parse(input_file) 773 774if __name__ == '__main__': 775 main() 776