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