1#encoding=utf-8 2 3# Copyright 2016 Intel Corporation 4# Copyright 2016 Broadcom 5# Copyright 2020 Collabora, Ltd. 6# SPDX-License-Identifier: MIT 7 8import xml.parsers.expat 9import sys 10import operator 11import math 12from functools import reduce 13 14global_prefix = "agx" 15 16pack_header = """ 17/* Generated code, see midgard.xml and gen_pack_header.py 18 * 19 * Packets, enums and structures for Panfrost. 20 * 21 * This file has been generated, do not hand edit. 22 */ 23 24#ifndef AGX_PACK_H 25#define AGX_PACK_H 26 27#ifndef __OPENCL_VERSION__ 28#include <stdio.h> 29#include <inttypes.h> 30#include "util/bitpack_helpers.h" 31#include "util/half_float.h" 32#define FILE_TYPE FILE 33#define CONSTANT_ const 34#define GLOBAL_ 35#else 36 37#include "libagx.h" 38#define assert(x) 39#define FILE_TYPE void 40#define CONSTANT_ constant 41#define GLOBAL_ global 42 43static uint64_t 44util_bitpack_uint(uint64_t v, uint32_t start, uint32_t end) 45{ 46 return v << start; 47} 48 49static uint64_t 50util_bitpack_sint(int64_t v, uint32_t start, uint32_t end) 51{ 52 const int bits = end - start + 1; 53 const uint64_t mask = (bits == 64) ? ~((uint64_t)0) : (1ull << bits) - 1; 54 return (v & mask) << start; 55} 56 57static uint32_t 58util_bitpack_float(float v) 59{ 60 union { float f; uint32_t dw; } x; 61 x.f = v; 62 return x.dw; 63} 64 65static inline float 66uif(uint32_t ui) 67{ 68 union { float f; uint32_t dw; } fi; 69 fi.dw = ui; 70 return fi.f; 71} 72 73#define DIV_ROUND_UP( A, B ) ( ((A) + (B) - 1) / (B) ) 74#define CLAMP( X, MIN, MAX ) ( (X)>(MIN) ? ((X)>(MAX) ? (MAX) : (X)) : (MIN) ) 75#define ALIGN_POT(x, pot_align) (((x) + (pot_align) - 1) & ~((pot_align) - 1)) 76 77static inline unsigned 78util_logbase2(unsigned n) 79{ 80 return ((sizeof(unsigned) * 8 - 1) - __builtin_clz(n | 1)); 81} 82 83static inline int64_t 84util_sign_extend(uint64_t val, unsigned width) 85{ 86 unsigned shift = 64 - width; 87 return (int64_t)(val << shift) >> shift; 88} 89 90static inline uint16_t 91_mesa_float_to_half(float f) 92{ 93 union { half h; uint16_t w; } hi; 94 hi.h = convert_half(f); 95 return hi.w; 96} 97 98static inline float 99_mesa_half_to_float(uint16_t w) 100{ 101 union { half h; uint16_t w; } hi; 102 hi.w = w; 103 return convert_float(hi.h); 104} 105 106#endif 107 108#define __gen_unpack_float(x, y, z) uif(__gen_unpack_uint(x, y, z)) 109#define __gen_unpack_half(x, y, z) _mesa_half_to_float(__gen_unpack_uint(x, y, z)) 110 111static inline uint64_t 112__gen_unpack_uint(CONSTANT_ uint32_t *restrict cl, uint32_t start, uint32_t end) 113{ 114 uint64_t val = 0; 115 const int width = end - start + 1; 116 const uint64_t mask = (width == 64) ? ~((uint64_t)0) : ((uint64_t)1 << width) - 1; 117 118 for (unsigned word = start / 32; word < (end / 32) + 1; word++) { 119 val |= ((uint64_t) cl[word]) << ((word - start / 32) * 32); 120 } 121 122 return (val >> (start % 32)) & mask; 123} 124 125/* 126 * LODs are 4:6 fixed point. We must clamp before converting to integers to 127 * avoid undefined behaviour for out-of-bounds inputs like +/- infinity. 128 */ 129static inline uint32_t 130__gen_pack_lod(float f, uint32_t start, uint32_t end) 131{ 132 uint32_t fixed = CLAMP(f * (1 << 6), 0 /* 0.0 */, 0x380 /* 14.0 */); 133 return util_bitpack_uint(fixed, start, end); 134} 135 136static inline float 137__gen_unpack_lod(CONSTANT_ uint32_t *restrict cl, uint32_t start, uint32_t end) 138{ 139 return ((float) __gen_unpack_uint(cl, start, end)) / (1 << 6); 140} 141 142static inline uint64_t 143__gen_unpack_sint(CONSTANT_ uint32_t *restrict cl, uint32_t start, uint32_t end) 144{ 145 int size = end - start + 1; 146 int64_t val = __gen_unpack_uint(cl, start, end); 147 148 return util_sign_extend(val, size); 149} 150 151static inline uint64_t 152__gen_to_groups(uint32_t value, uint32_t group_size, uint32_t length) 153{ 154 /* Zero is not representable, clamp to minimum */ 155 if (value == 0) 156 return 1; 157 158 /* Round up to the nearest number of groups */ 159 uint32_t groups = DIV_ROUND_UP(value, group_size); 160 161 /* The 0 encoding means "all" */ 162 if (groups == (1ull << length)) 163 return 0; 164 165 /* Otherwise it's encoded as the identity */ 166 assert(groups < (1u << length) && "out of bounds"); 167 assert(groups >= 1 && "exhaustive"); 168 return groups; 169} 170 171static inline uint64_t 172__gen_from_groups(uint32_t value, uint32_t group_size, uint32_t length) 173{ 174 return group_size * (value ? value: (1 << length)); 175} 176 177#define agx_pack(dst, T, name) \\ 178 for (struct AGX_ ## T name = { AGX_ ## T ## _header }, \\ 179 *_loop_count = (GLOBAL_ void *) ((uintptr_t) 0); \\ 180 (uintptr_t)_loop_count < 1; \\ 181 ({ AGX_ ## T ## _pack((GLOBAL_ uint32_t *) (dst), &name); \\ 182 _loop_count = (GLOBAL_ void*)(((uintptr_t)_loop_count) + 1); })) 183 184#define agx_unpack(fp, src, T, name) \\ 185 struct AGX_ ## T name; \\ 186 AGX_ ## T ## _unpack(fp, (CONSTANT_ uint8_t *)(src), &name) 187 188#define agx_print(fp, T, var, indent) \\ 189 AGX_ ## T ## _print(fp, &(var), indent) 190 191static inline void agx_merge_helper(uint32_t *dst, const uint32_t *src, size_t bytes) 192{ 193 assert((bytes & 3) == 0); 194 195 for (unsigned i = 0; i < (bytes / 4); ++i) 196 dst[i] |= src[i]; 197} 198 199#define agx_merge(packed1, packed2, type) \ 200 agx_merge_helper((packed1).opaque, (packed2).opaque, AGX_##type##_LENGTH) 201""" 202 203def to_alphanum(name): 204 substitutions = { 205 ' ': '_', 206 '/': '_', 207 '[': '', 208 ']': '', 209 '(': '', 210 ')': '', 211 '-': '_', 212 ':': '', 213 '.': '', 214 ',': '', 215 '=': '', 216 '>': '', 217 '#': '', 218 '&': '', 219 '*': '', 220 '"': '', 221 '+': '', 222 '\'': '', 223 '?': '', 224 } 225 226 for i, j in substitutions.items(): 227 name = name.replace(i, j) 228 229 return name 230 231def safe_name(name): 232 name = to_alphanum(name) 233 if not name[0].isalpha(): 234 name = '_' + name 235 236 return name 237 238def prefixed_upper_name(prefix, name): 239 if prefix: 240 name = prefix + "_" + name 241 return safe_name(name).upper() 242 243def enum_name(name): 244 return "{}_{}".format(global_prefix, safe_name(name)).lower() 245 246MODIFIERS = ["shr", "minus", "align", "log2", "groups"] 247 248def parse_modifier(modifier): 249 if modifier is None: 250 return None 251 252 for mod in MODIFIERS: 253 if modifier[0:len(mod)] == mod: 254 if mod == "log2": 255 assert(len(mod) == len(modifier)) 256 return [mod] 257 258 if modifier[len(mod)] == '(' and modifier[-1] == ')': 259 ret = [mod, int(modifier[(len(mod) + 1):-1])] 260 if ret[0] == 'align': 261 align = ret[1] 262 # Make sure the alignment is a power of 2 263 assert(align > 0 and not(align & (align - 1))); 264 265 return ret 266 267 print("Invalid modifier") 268 assert(False) 269 270class Field(object): 271 def __init__(self, parser, attrs): 272 self.parser = parser 273 if "name" in attrs: 274 self.name = safe_name(attrs["name"]).lower() 275 self.human_name = attrs["name"] 276 277 if ":" in str(attrs["start"]): 278 (word, bit) = attrs["start"].split(":") 279 self.start = (int(word) * 32) + int(bit) 280 else: 281 self.start = int(attrs["start"]) 282 283 self.end = self.start + int(attrs["size"]) - 1 284 self.type = attrs["type"] 285 286 if self.type == 'bool' and self.start != self.end: 287 print("#error Field {} has bool type but more than one bit of size".format(self.name)); 288 289 if "prefix" in attrs: 290 self.prefix = safe_name(attrs["prefix"]).upper() 291 else: 292 self.prefix = None 293 294 self.default = attrs.get("default") 295 296 # Map enum values 297 if self.type in self.parser.enums and self.default is not None: 298 self.default = safe_name('{}_{}_{}'.format(global_prefix, self.type, self.default)).upper() 299 300 self.modifier = parse_modifier(attrs.get("modifier")) 301 302 def emit_template_struct(self, dim): 303 if self.type == 'address': 304 type = 'uint64_t' 305 elif self.type == 'bool': 306 type = 'bool' 307 elif self.type in ['float', 'half', 'lod']: 308 type = 'float' 309 elif self.type in ['uint', 'hex'] and self.end - self.start > 32: 310 type = 'uint64_t' 311 elif self.type == 'int': 312 type = 'int32_t' 313 elif self.type in ['uint', 'hex']: 314 type = 'uint32_t' 315 elif self.type in self.parser.structs: 316 type = 'struct ' + self.parser.gen_prefix(safe_name(self.type.upper())) 317 elif self.type in self.parser.enums: 318 type = 'enum ' + enum_name(self.type) 319 else: 320 print("#error unhandled type: %s" % self.type) 321 type = "uint32_t" 322 323 print(" %-36s %s%s;" % (type, self.name, dim)) 324 325 for value in self.values: 326 name = prefixed_upper_name(self.prefix, value.name) 327 print("#define %-40s %d" % (name, value.value)) 328 329 def overlaps(self, field): 330 return self != field and max(self.start, field.start) <= min(self.end, field.end) 331 332class Group(object): 333 def __init__(self, parser, parent, start, count, label): 334 self.parser = parser 335 self.parent = parent 336 self.start = start 337 self.count = count 338 self.label = label 339 self.size = 0 340 self.length = 0 341 self.fields = [] 342 343 def get_length(self): 344 # Determine number of bytes in this group. 345 calculated = max(field.end // 8 for field in self.fields) + 1 if len(self.fields) > 0 else 0 346 if self.length > 0: 347 assert(self.length >= calculated) 348 else: 349 self.length = calculated 350 return self.length 351 352 353 def emit_template_struct(self, dim): 354 if self.count == 0: 355 print(" /* variable length fields follow */") 356 else: 357 if self.count > 1: 358 dim = "%s[%d]" % (dim, self.count) 359 360 if len(self.fields) == 0: 361 print(" int dummy;") 362 363 for field in self.fields: 364 field.emit_template_struct(dim) 365 366 class Word: 367 def __init__(self): 368 self.size = 32 369 self.contributors = [] 370 371 class FieldRef: 372 def __init__(self, field, path, start, end): 373 self.field = field 374 self.path = path 375 self.start = start 376 self.end = end 377 378 def collect_fields(self, fields, offset, path, all_fields): 379 for field in fields: 380 field_path = '{}{}'.format(path, field.name) 381 field_offset = offset + field.start 382 383 if field.type in self.parser.structs: 384 sub_struct = self.parser.structs[field.type] 385 self.collect_fields(sub_struct.fields, field_offset, field_path + '.', all_fields) 386 continue 387 388 start = field_offset 389 end = offset + field.end 390 all_fields.append(self.FieldRef(field, field_path, start, end)) 391 392 def collect_words(self, fields, offset, path, words): 393 for field in fields: 394 field_path = '{}{}'.format(path, field.name) 395 start = offset + field.start 396 397 if field.type in self.parser.structs: 398 sub_fields = self.parser.structs[field.type].fields 399 self.collect_words(sub_fields, start, field_path + '.', words) 400 continue 401 402 end = offset + field.end 403 contributor = self.FieldRef(field, field_path, start, end) 404 first_word = contributor.start // 32 405 last_word = contributor.end // 32 406 for b in range(first_word, last_word + 1): 407 if not b in words: 408 words[b] = self.Word() 409 words[b].contributors.append(contributor) 410 411 def emit_pack_function(self): 412 self.get_length() 413 414 words = {} 415 self.collect_words(self.fields, 0, '', words) 416 417 # Validate the modifier is lossless 418 for field in self.fields: 419 if field.modifier is None: 420 continue 421 422 if field.modifier[0] == "shr": 423 shift = field.modifier[1] 424 mask = hex((1 << shift) - 1) 425 print(" assert((values->{} & {}) == 0);".format(field.name, mask)) 426 elif field.modifier[0] == "minus": 427 print(" assert(values->{} >= {});".format(field.name, field.modifier[1])) 428 elif field.modifier[0] == "log2": 429 print(" assert(IS_POT_NONZERO(values->{}));".format(field.name)) 430 431 for index in range(math.ceil(self.length / 4)): 432 # Handle MBZ words 433 if not index in words: 434 print(" cl[%2d] = 0;" % index) 435 continue 436 437 word = words[index] 438 439 word_start = index * 32 440 441 v = None 442 prefix = " cl[%2d] =" % index 443 444 for contributor in word.contributors: 445 field = contributor.field 446 name = field.name 447 start = contributor.start 448 end = contributor.end 449 contrib_word_start = (start // 32) * 32 450 start -= contrib_word_start 451 end -= contrib_word_start 452 453 value = "values->{}".format(contributor.path) 454 if field.modifier is not None: 455 if field.modifier[0] == "shr": 456 value = "{} >> {}".format(value, field.modifier[1]) 457 elif field.modifier[0] == "minus": 458 value = "{} - {}".format(value, field.modifier[1]) 459 elif field.modifier[0] == "align": 460 value = "ALIGN_POT({}, {})".format(value, field.modifier[1]) 461 elif field.modifier[0] == "log2": 462 value = "util_logbase2({})".format(value) 463 elif field.modifier[0] == "groups": 464 value = "__gen_to_groups({}, {}, {})".format(value, 465 field.modifier[1], end - start + 1) 466 467 if field.type in ["uint", "hex", "address"]: 468 s = "util_bitpack_uint(%s, %d, %d)" % \ 469 (value, start, end) 470 elif field.type in self.parser.enums: 471 s = "util_bitpack_uint(%s, %d, %d)" % \ 472 (value, start, end) 473 elif field.type == "int": 474 s = "util_bitpack_sint(%s, %d, %d)" % \ 475 (value, start, end) 476 elif field.type == "bool": 477 s = "util_bitpack_uint(%s, %d, %d)" % \ 478 (value, start, end) 479 elif field.type == "float": 480 assert(start == 0 and end == 31) 481 s = "util_bitpack_float({})".format(value) 482 elif field.type == "half": 483 assert(start == 0 and end == 15) 484 s = "_mesa_float_to_half({})".format(value) 485 elif field.type == "lod": 486 assert(end - start + 1 == 10) 487 s = "__gen_pack_lod(%s, %d, %d)" % (value, start, end) 488 else: 489 s = "#error unhandled field {}, type {}".format(contributor.path, field.type) 490 491 if not s == None: 492 shift = word_start - contrib_word_start 493 if shift: 494 s = "%s >> %d" % (s, shift) 495 496 if contributor == word.contributors[-1]: 497 print("%s %s;" % (prefix, s)) 498 else: 499 print("%s %s |" % (prefix, s)) 500 prefix = " " 501 502 continue 503 504 # Given a field (start, end) contained in word `index`, generate the 32-bit 505 # mask of present bits relative to the word 506 def mask_for_word(self, index, start, end): 507 field_word_start = index * 32 508 start -= field_word_start 509 end -= field_word_start 510 # Cap multiword at one word 511 start = max(start, 0) 512 end = min(end, 32 - 1) 513 count = (end - start + 1) 514 return (((1 << count) - 1) << start) 515 516 def emit_unpack_function(self): 517 # First, verify there is no garbage in unused bits 518 words = {} 519 self.collect_words(self.fields, 0, '', words) 520 print(' bool valid = true;') 521 522 print('#ifndef __OPENCL_VERSION__') 523 for index in range(self.length // 4): 524 base = index * 32 525 word = words.get(index, self.Word()) 526 masks = [self.mask_for_word(index, c.start, c.end) for c in word.contributors] 527 mask = reduce(lambda x,y: x | y, masks, 0) 528 529 ALL_ONES = 0xffffffff 530 531 if mask != ALL_ONES: 532 TMPL = ''' 533 if (((const uint32_t *) cl)[{}] & {}) {{ 534 valid = false; 535 536 if (fp != NULL) {{ 537 fprintf(fp, "XXX: Unknown field of {} unpacked at word {}: got %X, bad mask %X\\n", 538 ((const uint32_t *) cl)[{}], ((const uint32_t *) cl)[{}] & {}); 539 }} 540 }} 541 ''' 542 print(TMPL.format(index, hex(mask ^ ALL_ONES), self.label, index, index, index, hex(mask ^ ALL_ONES))) 543 print('#endif') 544 545 fieldrefs = [] 546 self.collect_fields(self.fields, 0, '', fieldrefs) 547 for fieldref in fieldrefs: 548 field = fieldref.field 549 convert = None 550 551 args = [] 552 args.append('(CONSTANT_ uint32_t *) cl') 553 args.append(str(fieldref.start)) 554 args.append(str(fieldref.end)) 555 556 if field.type in set(["uint", "address", "hex"]) | self.parser.enums: 557 convert = "__gen_unpack_uint" 558 elif field.type == "int": 559 convert = "__gen_unpack_sint" 560 elif field.type == "bool": 561 convert = "__gen_unpack_uint" 562 elif field.type == "float": 563 convert = "__gen_unpack_float" 564 elif field.type == "half": 565 convert = "__gen_unpack_half" 566 elif field.type == "lod": 567 convert = "__gen_unpack_lod" 568 else: 569 s = "/* unhandled field %s, type %s */\n" % (field.name, field.type) 570 571 suffix = "" 572 prefix = "" 573 if field.modifier: 574 if field.modifier[0] == "minus": 575 suffix = " + {}".format(field.modifier[1]) 576 elif field.modifier[0] == "shr": 577 suffix = " << {}".format(field.modifier[1]) 578 if field.modifier[0] == "log2": 579 prefix = "1 << " 580 elif field.modifier[0] == "groups": 581 prefix = "__gen_from_groups(" 582 suffix = ", {}, {})".format(field.modifier[1], 583 fieldref.end - fieldref.start + 1) 584 585 if field.type in self.parser.enums: 586 prefix = f"(enum {enum_name(field.type)}) {prefix}" 587 588 decoded = '{}{}({}){}'.format(prefix, convert, ', '.join(args), suffix) 589 590 print(' values->{} = {};'.format(fieldref.path, decoded)) 591 if field.modifier and field.modifier[0] == "align": 592 mask = hex(field.modifier[1] - 1) 593 print(' assert(!(values->{} & {}));'.format(fieldref.path, mask)) 594 595 def emit_print_function(self): 596 for field in self.fields: 597 convert = None 598 name, val = field.human_name, 'values->{}'.format(field.name) 599 600 if field.type in self.parser.structs: 601 pack_name = self.parser.gen_prefix(safe_name(field.type)).upper() 602 print(' fprintf(fp, "%*s{}:\\n", indent, "");'.format(field.human_name)) 603 print(" {}_print(fp, &values->{}, indent + 2);".format(pack_name, field.name)) 604 elif field.type == "address": 605 # TODO resolve to name 606 print(' fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val)) 607 elif field.type in self.parser.enums: 608 print(' if ({}_as_str({}))'.format(enum_name(field.type), val)) 609 print(' fprintf(fp, "%*s{}: %s\\n", indent, "", {}_as_str({}));'.format(name, enum_name(field.type), val)) 610 print(' else') 611 print(' fprintf(fp, "%*s{}: unknown %X (XXX)\\n", indent, "", {});'.format(name, val)) 612 elif field.type == "int": 613 print(' fprintf(fp, "%*s{}: %d\\n", indent, "", {});'.format(name, val)) 614 elif field.type == "bool": 615 print(' fprintf(fp, "%*s{}: %s\\n", indent, "", {} ? "true" : "false");'.format(name, val)) 616 elif field.type in ["float", "lod", "half"]: 617 print(' fprintf(fp, "%*s{}: %f\\n", indent, "", {});'.format(name, val)) 618 elif field.type in ["uint", "hex"] and (field.end - field.start) >= 32: 619 print(' fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val)) 620 elif field.type == "hex": 621 print(' fprintf(fp, "%*s{}: 0x%" PRIx32 "\\n", indent, "", {});'.format(name, val)) 622 else: 623 print(' fprintf(fp, "%*s{}: %u\\n", indent, "", {});'.format(name, val)) 624 625class Value(object): 626 def __init__(self, attrs): 627 self.name = attrs["name"] 628 self.value = int(attrs["value"], 0) 629 630class Parser(object): 631 def __init__(self): 632 self.parser = xml.parsers.expat.ParserCreate() 633 self.parser.StartElementHandler = self.start_element 634 self.parser.EndElementHandler = self.end_element 635 636 self.struct = None 637 self.structs = {} 638 # Set of enum names we've seen. 639 self.enums = set() 640 641 def gen_prefix(self, name): 642 return '{}_{}'.format(global_prefix.upper(), name) 643 644 def start_element(self, name, attrs): 645 if name == "genxml": 646 print(pack_header) 647 elif name == "struct": 648 name = attrs["name"] 649 object_name = self.gen_prefix(safe_name(name.upper())) 650 self.struct = object_name 651 652 self.group = Group(self, None, 0, 1, name) 653 if "size" in attrs: 654 self.group.length = int(attrs["size"]) 655 self.group.align = int(attrs["align"]) if "align" in attrs else None 656 self.structs[attrs["name"]] = self.group 657 elif name == "field": 658 self.group.fields.append(Field(self, attrs)) 659 self.values = [] 660 elif name == "enum": 661 self.values = [] 662 self.enum = safe_name(attrs["name"]) 663 self.enums.add(attrs["name"]) 664 if "prefix" in attrs: 665 self.prefix = attrs["prefix"] 666 else: 667 self.prefix= None 668 elif name == "value": 669 self.values.append(Value(attrs)) 670 671 def end_element(self, name): 672 if name == "struct": 673 self.emit_struct() 674 self.struct = None 675 self.group = None 676 elif name == "field": 677 self.group.fields[-1].values = self.values 678 elif name == "enum": 679 self.emit_enum() 680 self.enum = None 681 elif name == "genxml": 682 print('#endif') 683 684 def emit_header(self, name): 685 default_fields = [] 686 for field in self.group.fields: 687 if not type(field) is Field: 688 continue 689 if field.default is not None: 690 default_fields.append(" .{} = {}".format(field.name, field.default)) 691 elif field.type in self.structs: 692 default_fields.append(" .{} = {{ {}_header }}".format(field.name, self.gen_prefix(safe_name(field.type.upper())))) 693 694 print('#define %-40s\\' % (name + '_header')) 695 if default_fields: 696 print(", \\\n".join(default_fields)) 697 else: 698 print(' 0') 699 print('') 700 701 def emit_template_struct(self, name, group): 702 print("struct %s {" % name) 703 group.emit_template_struct("") 704 print("};\n") 705 706 def emit_pack_function(self, name, group): 707 print("static inline void\n%s_pack(GLOBAL_ uint32_t * restrict cl,\n%sconst struct %s * restrict values)\n{" % 708 (name, ' ' * (len(name) + 6), name)) 709 710 group.emit_pack_function() 711 712 print("}\n\n") 713 714 print('#define {} {}'.format (name + "_LENGTH", self.group.length)) 715 if self.group.align != None: 716 print('#define {} {}'.format (name + "_ALIGN", self.group.align)) 717 718 # round up to handle 6 half-word USC structures 719 words = (self.group.length + 4 - 1) // 4 720 print('struct {}_packed {{ uint32_t opaque[{}];}};'.format(name.lower(), 721 words)) 722 723 def emit_unpack_function(self, name, group): 724 print("static inline bool") 725 print("%s_unpack(FILE_TYPE *fp, CONSTANT_ uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" % 726 (name.upper(), ' ' * (len(name) + 8), name)) 727 728 group.emit_unpack_function() 729 730 print(" return valid;\n") 731 print("}\n") 732 733 def emit_print_function(self, name, group): 734 print("#ifndef __OPENCL_VERSION__") 735 print("static inline void") 736 print("{}_print(FILE *fp, const struct {} * values, unsigned indent)\n{{".format(name.upper(), name)) 737 738 group.emit_print_function() 739 740 print("}\n") 741 print("#endif") 742 743 def emit_struct(self): 744 name = self.struct 745 746 self.emit_template_struct(self.struct, self.group) 747 self.emit_header(name) 748 self.emit_pack_function(self.struct, self.group) 749 self.emit_unpack_function(self.struct, self.group) 750 self.emit_print_function(self.struct, self.group) 751 752 def enum_prefix(self, name): 753 return 754 755 def emit_enum(self): 756 e_name = enum_name(self.enum) 757 prefix = e_name if self.enum != 'Format' else global_prefix 758 print('enum {} {{'.format(e_name)) 759 760 for value in self.values: 761 name = '{}_{}'.format(prefix, value.name) 762 name = safe_name(name).upper() 763 print(' % -36s = %6d,' % (name, value.value)) 764 print('};\n') 765 766 print("#ifndef __OPENCL_VERSION__") 767 print("static inline const char *") 768 print("{}_as_str(enum {} imm)\n{{".format(e_name.lower(), e_name)) 769 print(" switch (imm) {") 770 for value in self.values: 771 name = '{}_{}'.format(prefix, value.name) 772 name = safe_name(name).upper() 773 print(' case {}: return "{}";'.format(name, value.name)) 774 print(' default: break;') 775 print(" }") 776 print(" return NULL;") 777 print("}\n") 778 print("#endif") 779 780 def parse(self, filename): 781 file = open(filename, "rb") 782 self.parser.ParseFile(file) 783 file.close() 784 785if len(sys.argv) < 2: 786 print("No input xml file specified") 787 sys.exit(1) 788 789input_file = sys.argv[1] 790 791p = Parser() 792p.parse(input_file) 793