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