1#encoding=utf-8 2 3# Copyright (C) 2016 Intel Corporation 4# Copyright (C) 2016 Broadcom 5# Copyright (C) 2020 Collabora, Ltd. 6# 7# Permission is hereby granted, free of charge, to any person obtaining a 8# copy of this software and associated documentation files (the "Software"), 9# to deal in the Software without restriction, including without limitation 10# the rights to use, copy, modify, merge, publish, distribute, sublicense, 11# and/or sell copies of the Software, and to permit persons to whom the 12# Software is furnished to do so, subject to the following conditions: 13# 14# The above copyright notice and this permission notice (including the next 15# paragraph) shall be included in all copies or substantial portions of the 16# Software. 17# 18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24# IN THE SOFTWARE. 25 26import xml.parsers.expat 27import sys 28import operator 29from functools import reduce 30 31global_prefix = "mali" 32 33pack_header = """ 34/* Generated code, see midgard.xml and gen_pack_header.py 35 * 36 * Packets, enums and structures for Panfrost. 37 * 38 * This file has been generated, do not hand edit. 39 */ 40 41#ifndef PAN_PACK_H 42#define PAN_PACK_H 43 44#include <stdio.h> 45#include <inttypes.h> 46 47#include "util/bitpack_helpers.h" 48 49#define __gen_unpack_float(x, y, z) uif(__gen_unpack_uint(x, y, z)) 50 51static inline uint32_t 52__gen_padded(uint32_t v, uint32_t start, uint32_t end) 53{ 54 unsigned shift = __builtin_ctz(v); 55 unsigned odd = v >> (shift + 1); 56 57#ifndef NDEBUG 58 assert((v >> shift) & 1); 59 assert(shift <= 31); 60 assert(odd <= 7); 61 assert((end - start + 1) == 8); 62#endif 63 64 return util_bitpack_uint(shift | (odd << 5), start, end); 65} 66 67 68static inline uint64_t 69__gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end) 70{ 71 uint64_t val = 0; 72 const int width = end - start + 1; 73 const uint64_t mask = (width == 64 ? ~0 : (1ull << width) - 1 ); 74 75 for (uint32_t byte = start / 8; byte <= end / 8; byte++) { 76 val |= ((uint64_t) cl[byte]) << ((byte - start / 8) * 8); 77 } 78 79 return (val >> (start % 8)) & mask; 80} 81 82static inline uint64_t 83__gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end) 84{ 85 int size = end - start + 1; 86 int64_t val = __gen_unpack_uint(cl, start, end); 87 88 return util_sign_extend(val, size); 89} 90 91static inline float 92__gen_unpack_ulod(const uint8_t *restrict cl, uint32_t start, uint32_t end) 93{ 94 uint32_t u = __gen_unpack_uint(cl, start, end); 95 96 return ((float)u) / 256.0; 97} 98 99static inline float 100__gen_unpack_slod(const uint8_t *restrict cl, uint32_t start, uint32_t end) 101{ 102 int32_t u = __gen_unpack_sint(cl, start, end); 103 104 return ((float)u) / 256.0; 105} 106 107static inline uint64_t 108__gen_unpack_padded(const uint8_t *restrict cl, uint32_t start, uint32_t end) 109{ 110 unsigned val = __gen_unpack_uint(cl, start, end); 111 unsigned shift = val & 0b11111; 112 unsigned odd = val >> 5; 113 114 return (2*odd + 1) << shift; 115} 116 117#define PREFIX1(A) MALI_ ## A 118#define PREFIX2(A, B) MALI_ ## A ## _ ## B 119#define PREFIX4(A, B, C, D) MALI_ ## A ## _ ## B ## _ ## C ## _ ## D 120 121#define pan_pack(dst, T, name) \\ 122 for (struct PREFIX1(T) name = { PREFIX2(T, header) }, \\ 123 *_loop_terminate = (void *) (dst); \\ 124 __builtin_expect(_loop_terminate != NULL, 1); \\ 125 ({ PREFIX2(T, pack)((uint32_t *) (dst), &name); \\ 126 _loop_terminate = NULL; })) 127 128#define pan_unpack(src, T, name) \\ 129 struct PREFIX1(T) name; \\ 130 PREFIX2(T, unpack)((uint8_t *)(src), &name) 131 132#define pan_print(fp, T, var, indent) \\ 133 PREFIX2(T, print)(fp, &(var), indent) 134 135#define pan_size(T) PREFIX2(T, LENGTH) 136#define pan_alignment(T) PREFIX2(T, ALIGN) 137 138#define pan_section_offset(A, S) \\ 139 PREFIX4(A, SECTION, S, OFFSET) 140 141#define pan_section_ptr(base, A, S) \\ 142 ((void *)((uint8_t *)(base) + pan_section_offset(A, S))) 143 144#define pan_section_pack(dst, A, S, name) \\ 145 for (PREFIX4(A, SECTION, S, TYPE) name = { PREFIX4(A, SECTION, S, header) }, \\ 146 *_loop_terminate = (void *) (dst); \\ 147 __builtin_expect(_loop_terminate != NULL, 1); \\ 148 ({ PREFIX4(A, SECTION, S, pack) (pan_section_ptr(dst, A, S), &name); \\ 149 _loop_terminate = NULL; })) 150 151#define pan_section_unpack(src, A, S, name) \\ 152 PREFIX4(A, SECTION, S, TYPE) name; \\ 153 PREFIX4(A, SECTION, S, unpack)(pan_section_ptr(src, A, S), &name) 154 155#define pan_section_print(fp, A, S, var, indent) \\ 156 PREFIX4(A, SECTION, S, print)(fp, &(var), indent) 157 158static inline void pan_merge_helper(uint32_t *dst, const uint32_t *src, size_t bytes) 159{ 160 assert((bytes & 3) == 0); 161 162 for (unsigned i = 0; i < (bytes / 4); ++i) 163 dst[i] |= src[i]; 164} 165 166#define pan_merge(packed1, packed2, type) \ 167 pan_merge_helper((packed1).opaque, (packed2).opaque, pan_size(type)) 168 169/* From presentations, 16x16 tiles externally. Use shift for fast computation 170 * of tile numbers. */ 171 172#define MALI_TILE_SHIFT 4 173#define MALI_TILE_LENGTH (1 << MALI_TILE_SHIFT) 174 175""" 176 177v6_format_printer = """ 178 179#define mali_pixel_format_print(fp, format) \\ 180 fprintf(fp, "%*sFormat (v6): %s%s%s %s%s%s%s\\n", indent, "", \\ 181 mali_format_as_str((enum mali_format)((format >> 12) & 0xFF)), \\ 182 (format & (1 << 20)) ? " sRGB" : "", \\ 183 (format & (1 << 21)) ? " big-endian" : "", \\ 184 mali_channel_as_str((enum mali_channel)((format >> 0) & 0x7)), \\ 185 mali_channel_as_str((enum mali_channel)((format >> 3) & 0x7)), \\ 186 mali_channel_as_str((enum mali_channel)((format >> 6) & 0x7)), \\ 187 mali_channel_as_str((enum mali_channel)((format >> 9) & 0x7))); 188 189""" 190 191v7_format_printer = """ 192 193#define mali_pixel_format_print(fp, format) \\ 194 fprintf(fp, "%*sFormat (v7): %s%s %s%s\\n", indent, "", \\ 195 mali_format_as_str((enum mali_format)((format >> 12) & 0xFF)), \\ 196 (format & (1 << 20)) ? " sRGB" : "", \\ 197 mali_rgb_component_order_as_str((enum mali_rgb_component_order)(format & ((1 << 12) - 1))), \\ 198 (format & (1 << 21)) ? " XXX BAD BIT" : ""); 199 200""" 201 202def to_alphanum(name): 203 substitutions = { 204 ' ': '_', 205 '/': '_', 206 '[': '', 207 ']': '', 208 '(': '', 209 ')': '', 210 '-': '_', 211 ':': '', 212 '.': '', 213 ',': '', 214 '=': '', 215 '>': '', 216 '#': '', 217 '&': '', 218 '%': '', 219 '*': '', 220 '"': '', 221 '+': '', 222 '\'': '', 223 } 224 225 for i, j in substitutions.items(): 226 name = name.replace(i, j) 227 228 return name 229 230def safe_name(name): 231 name = to_alphanum(name) 232 if not name[0].isalpha(): 233 name = '_' + name 234 235 return name 236 237def prefixed_upper_name(prefix, name): 238 if prefix: 239 name = prefix + "_" + name 240 return safe_name(name).upper() 241 242def enum_name(name): 243 return "{}_{}".format(global_prefix, safe_name(name)).lower() 244 245MODIFIERS = ["shr", "minus", "align", "log2"] 246 247def parse_modifier(modifier): 248 if modifier is None: 249 return None 250 251 for mod in MODIFIERS: 252 if modifier[0:len(mod)] == mod: 253 if mod == "log2": 254 assert(len(mod) == len(modifier)) 255 return [mod] 256 257 if modifier[len(mod)] == '(' and modifier[-1] == ')': 258 ret = [mod, int(modifier[(len(mod) + 1):-1])] 259 if ret[0] == 'align': 260 align = ret[1] 261 # Make sure the alignment is a power of 2 262 assert(align > 0 and not(align & (align - 1))); 263 264 return ret 265 266 print("Invalid modifier") 267 assert(False) 268 269class Aggregate(object): 270 def __init__(self, parser, name, attrs): 271 self.parser = parser 272 self.sections = [] 273 self.name = name 274 self.explicit_size = int(attrs["size"]) if "size" in attrs else 0 275 self.size = 0 276 self.align = int(attrs["align"]) if "align" in attrs else None 277 278 class Section: 279 def __init__(self, name): 280 self.name = name 281 282 def get_size(self): 283 if self.size > 0: 284 return self.size 285 286 size = 0 287 for section in self.sections: 288 size = max(size, section.offset + section.type.get_length()) 289 290 if self.explicit_size > 0: 291 assert(self.explicit_size >= size) 292 self.size = self.explicit_size 293 else: 294 self.size = size 295 return self.size 296 297 def add_section(self, type_name, attrs): 298 assert("name" in attrs) 299 section = self.Section(safe_name(attrs["name"]).lower()) 300 section.human_name = attrs["name"] 301 section.offset = int(attrs["offset"]) 302 assert(section.offset % 4 == 0) 303 section.type = self.parser.structs[attrs["type"]] 304 section.type_name = type_name 305 self.sections.append(section) 306 307class Field(object): 308 def __init__(self, parser, attrs): 309 self.parser = parser 310 if "name" in attrs: 311 self.name = safe_name(attrs["name"]).lower() 312 self.human_name = attrs["name"] 313 314 if ":" in str(attrs["start"]): 315 (word, bit) = attrs["start"].split(":") 316 self.start = (int(word) * 32) + int(bit) 317 else: 318 self.start = int(attrs["start"]) 319 320 self.end = self.start + int(attrs["size"]) - 1 321 self.type = attrs["type"] 322 323 if self.type == 'bool' and self.start != self.end: 324 print("#error Field {} has bool type but more than one bit of size".format(self.name)); 325 326 if "prefix" in attrs: 327 self.prefix = safe_name(attrs["prefix"]).upper() 328 else: 329 self.prefix = None 330 331 self.default = attrs.get("default") 332 333 # Map enum values 334 if self.type in self.parser.enums and self.default is not None: 335 self.default = safe_name('{}_{}_{}'.format(global_prefix, self.type, self.default)).upper() 336 337 self.modifier = parse_modifier(attrs.get("modifier")) 338 339 def emit_template_struct(self, dim): 340 if self.type == 'address': 341 type = 'uint64_t' 342 elif self.type == 'bool': 343 type = 'bool' 344 elif self.type in ['float', 'ulod', 'slod']: 345 type = 'float' 346 elif self.type in ['uint', 'hex'] and self.end - self.start > 32: 347 type = 'uint64_t' 348 elif self.type == 'int': 349 type = 'int32_t' 350 elif self.type in ['uint', 'hex', 'uint/float', 'padded', 'Pixel Format']: 351 type = 'uint32_t' 352 elif self.type in self.parser.structs: 353 type = 'struct ' + self.parser.gen_prefix(safe_name(self.type.upper())) 354 elif self.type in self.parser.enums: 355 type = 'enum ' + enum_name(self.type) 356 else: 357 print("#error unhandled type: %s" % self.type) 358 type = "uint32_t" 359 360 print(" %-36s %s%s;" % (type, self.name, dim)) 361 362 for value in self.values: 363 name = prefixed_upper_name(self.prefix, value.name) 364 print("#define %-40s %d" % (name, value.value)) 365 366 def overlaps(self, field): 367 return self != field and max(self.start, field.start) <= min(self.end, field.end) 368 369class Group(object): 370 def __init__(self, parser, parent, start, count, label): 371 self.parser = parser 372 self.parent = parent 373 self.start = start 374 self.count = count 375 self.label = label 376 self.size = 0 377 self.length = 0 378 self.fields = [] 379 380 def get_length(self): 381 # Determine number of bytes in this group. 382 calculated = max(field.end // 8 for field in self.fields) + 1 if len(self.fields) > 0 else 0 383 if self.length > 0: 384 assert(self.length >= calculated) 385 else: 386 self.length = calculated 387 return self.length 388 389 390 def emit_template_struct(self, dim): 391 if self.count == 0: 392 print(" /* variable length fields follow */") 393 else: 394 if self.count > 1: 395 dim = "%s[%d]" % (dim, self.count) 396 397 if len(self.fields) == 0: 398 print(" int dummy;") 399 400 for field in self.fields: 401 field.emit_template_struct(dim) 402 403 class Word: 404 def __init__(self): 405 self.size = 32 406 self.contributors = [] 407 408 class FieldRef: 409 def __init__(self, field, path, start, end): 410 self.field = field 411 self.path = path 412 self.start = start 413 self.end = end 414 415 def collect_fields(self, fields, offset, path, all_fields): 416 for field in fields: 417 field_path = '{}{}'.format(path, field.name) 418 field_offset = offset + field.start 419 420 if field.type in self.parser.structs: 421 sub_struct = self.parser.structs[field.type] 422 self.collect_fields(sub_struct.fields, field_offset, field_path + '.', all_fields) 423 continue 424 425 start = field_offset 426 end = offset + field.end 427 all_fields.append(self.FieldRef(field, field_path, start, end)) 428 429 def collect_words(self, fields, offset, path, words): 430 for field in fields: 431 field_path = '{}{}'.format(path, field.name) 432 start = offset + field.start 433 434 if field.type in self.parser.structs: 435 sub_fields = self.parser.structs[field.type].fields 436 self.collect_words(sub_fields, start, field_path + '.', words) 437 continue 438 439 end = offset + field.end 440 contributor = self.FieldRef(field, field_path, start, end) 441 first_word = contributor.start // 32 442 last_word = contributor.end // 32 443 for b in range(first_word, last_word + 1): 444 if not b in words: 445 words[b] = self.Word() 446 words[b].contributors.append(contributor) 447 448 def emit_pack_function(self): 449 self.get_length() 450 451 words = {} 452 self.collect_words(self.fields, 0, '', words) 453 454 # Validate the modifier is lossless 455 for field in self.fields: 456 if field.modifier is None: 457 continue 458 459 if field.modifier[0] == "shr": 460 shift = field.modifier[1] 461 mask = hex((1 << shift) - 1) 462 print(" assert((values->{} & {}) == 0);".format(field.name, mask)) 463 elif field.modifier[0] == "minus": 464 print(" assert(values->{} >= {});".format(field.name, field.modifier[1])) 465 elif field.modifier[0] == "log2": 466 print(" assert(IS_POT_NONZERO(values->{}));".format(field.name)) 467 468 for index in range(self.length // 4): 469 # Handle MBZ words 470 if not index in words: 471 print(" cl[%2d] = 0;" % index) 472 continue 473 474 word = words[index] 475 476 word_start = index * 32 477 478 v = None 479 prefix = " cl[%2d] =" % index 480 481 for contributor in word.contributors: 482 field = contributor.field 483 name = field.name 484 start = contributor.start 485 end = contributor.end 486 contrib_word_start = (start // 32) * 32 487 start -= contrib_word_start 488 end -= contrib_word_start 489 490 value = "values->{}".format(contributor.path) 491 if field.modifier is not None: 492 if field.modifier[0] == "shr": 493 value = "{} >> {}".format(value, field.modifier[1]) 494 elif field.modifier[0] == "minus": 495 value = "{} - {}".format(value, field.modifier[1]) 496 elif field.modifier[0] == "align": 497 value = "ALIGN_POT({}, {})".format(value, field.modifier[1]) 498 elif field.modifier[0] == "log2": 499 value = "util_logbase2({})".format(value) 500 501 if field.type in ["uint", "hex", "uint/float", "address", "Pixel Format"]: 502 s = "util_bitpack_uint(%s, %d, %d)" % \ 503 (value, start, end) 504 elif field.type == "padded": 505 s = "__gen_padded(%s, %d, %d)" % \ 506 (value, start, end) 507 elif field.type in self.parser.enums: 508 s = "util_bitpack_uint(%s, %d, %d)" % \ 509 (value, start, end) 510 elif field.type == "int": 511 s = "util_bitpack_sint(%s, %d, %d)" % \ 512 (value, start, end) 513 elif field.type == "bool": 514 s = "util_bitpack_uint(%s, %d, %d)" % \ 515 (value, start, end) 516 elif field.type == "float": 517 assert(start == 0 and end == 31) 518 s = "util_bitpack_float({})".format(value) 519 elif field.type == "ulod": 520 s = "util_bitpack_ufixed_clamp({}, {}, {}, 8)".format(value, 521 start, 522 end) 523 elif field.type == "slod": 524 s = "util_bitpack_sfixed_clamp({}, {}, {}, 8)".format(value, 525 start, 526 end) 527 else: 528 s = "#error unhandled field {}, type {}".format(contributor.path, field.type) 529 530 if not s == None: 531 shift = word_start - contrib_word_start 532 if shift: 533 s = "%s >> %d" % (s, shift) 534 535 if contributor == word.contributors[-1]: 536 print("%s %s;" % (prefix, s)) 537 else: 538 print("%s %s |" % (prefix, s)) 539 prefix = " " 540 541 continue 542 543 # Given a field (start, end) contained in word `index`, generate the 32-bit 544 # mask of present bits relative to the word 545 def mask_for_word(self, index, start, end): 546 field_word_start = index * 32 547 start -= field_word_start 548 end -= field_word_start 549 # Cap multiword at one word 550 start = max(start, 0) 551 end = min(end, 32 - 1) 552 count = (end - start + 1) 553 return (((1 << count) - 1) << start) 554 555 def emit_unpack_function(self): 556 # First, verify there is no garbage in unused bits 557 words = {} 558 self.collect_words(self.fields, 0, '', words) 559 560 for index in range(self.length // 4): 561 base = index * 32 562 word = words.get(index, self.Word()) 563 masks = [self.mask_for_word(index, c.start, c.end) for c in word.contributors] 564 mask = reduce(lambda x,y: x | y, masks, 0) 565 566 ALL_ONES = 0xffffffff 567 568 if mask != ALL_ONES: 569 TMPL = ' if (((const uint32_t *) cl)[{}] & {}) fprintf(stderr, "XXX: Invalid field of {} unpacked at word {}\\n");' 570 print(TMPL.format(index, hex(mask ^ ALL_ONES), self.label, index)) 571 572 fieldrefs = [] 573 self.collect_fields(self.fields, 0, '', fieldrefs) 574 for fieldref in fieldrefs: 575 field = fieldref.field 576 convert = None 577 578 args = [] 579 args.append('cl') 580 args.append(str(fieldref.start)) 581 args.append(str(fieldref.end)) 582 583 if field.type in set(["uint", "hex", "uint/float", "address", "Pixel Format"]): 584 convert = "__gen_unpack_uint" 585 elif field.type in self.parser.enums: 586 convert = "(enum %s)__gen_unpack_uint" % enum_name(field.type) 587 elif field.type == "int": 588 convert = "__gen_unpack_sint" 589 elif field.type == "padded": 590 convert = "__gen_unpack_padded" 591 elif field.type == "bool": 592 convert = "__gen_unpack_uint" 593 elif field.type == "float": 594 convert = "__gen_unpack_float" 595 elif field.type == "ulod": 596 convert = "__gen_unpack_ulod" 597 elif field.type == "slod": 598 convert = "__gen_unpack_slod" 599 else: 600 s = "/* unhandled field %s, type %s */\n" % (field.name, field.type) 601 602 suffix = "" 603 prefix = "" 604 if field.modifier: 605 if field.modifier[0] == "minus": 606 suffix = " + {}".format(field.modifier[1]) 607 elif field.modifier[0] == "shr": 608 suffix = " << {}".format(field.modifier[1]) 609 if field.modifier[0] == "log2": 610 prefix = "1U << " 611 612 decoded = '{}{}({}){}'.format(prefix, convert, ', '.join(args), suffix) 613 614 print(' values->{} = {};'.format(fieldref.path, decoded)) 615 if field.modifier and field.modifier[0] == "align": 616 mask = hex(field.modifier[1] - 1) 617 print(' assert(!(values->{} & {}));'.format(fieldref.path, mask)) 618 619 def emit_print_function(self): 620 for field in self.fields: 621 convert = None 622 name, val = field.human_name, 'values->{}'.format(field.name) 623 624 if field.type in self.parser.structs: 625 pack_name = self.parser.gen_prefix(safe_name(field.type)).upper() 626 print(' fprintf(fp, "%*s{}:\\n", indent, "");'.format(field.human_name)) 627 print(" {}_print(fp, &values->{}, indent + 2);".format(pack_name, field.name)) 628 elif field.type == "address": 629 # TODO resolve to name 630 print(' fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val)) 631 elif field.type in self.parser.enums: 632 print(' fprintf(fp, "%*s{}: %s\\n", indent, "", {}_as_str({}));'.format(name, enum_name(field.type), val)) 633 elif field.type == "int": 634 print(' fprintf(fp, "%*s{}: %d\\n", indent, "", {});'.format(name, val)) 635 elif field.type == "bool": 636 print(' fprintf(fp, "%*s{}: %s\\n", indent, "", {} ? "true" : "false");'.format(name, val)) 637 elif field.type in ["float", "ulod", "slod"]: 638 print(' fprintf(fp, "%*s{}: %f\\n", indent, "", {});'.format(name, val)) 639 elif field.type in ["uint", "hex"] and (field.end - field.start) >= 32: 640 print(' fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val)) 641 elif field.type == "hex": 642 print(' fprintf(fp, "%*s{}: 0x%x\\n", indent, "", {});'.format(name, val)) 643 elif field.type == "uint/float": 644 print(' fprintf(fp, "%*s{}: 0x%X (%f)\\n", indent, "", {}, uif({}));'.format(name, val, val)) 645 elif field.type == "Pixel Format": 646 print(' mali_pixel_format_print(fp, {});'.format(val)) 647 else: 648 print(' fprintf(fp, "%*s{}: %u\\n", indent, "", {});'.format(name, val)) 649 650class Value(object): 651 def __init__(self, attrs): 652 self.name = attrs["name"] 653 self.value = int(attrs["value"], 0) 654 655class Parser(object): 656 def __init__(self): 657 self.parser = xml.parsers.expat.ParserCreate() 658 self.parser.StartElementHandler = self.start_element 659 self.parser.EndElementHandler = self.end_element 660 661 self.struct = None 662 self.structs = {} 663 # Set of enum names we've seen. 664 self.enums = set() 665 self.aggregate = None 666 self.aggregates = {} 667 668 def gen_prefix(self, name): 669 return '{}_{}'.format(global_prefix.upper(), name) 670 671 def start_element(self, name, attrs): 672 if name == "panxml": 673 print(pack_header) 674 if "arch" in attrs: 675 arch = int(attrs["arch"]) 676 if arch <= 6: 677 print(v6_format_printer) 678 else: 679 print(v7_format_printer) 680 elif name == "struct": 681 name = attrs["name"] 682 self.no_direct_packing = attrs.get("no-direct-packing", False) 683 object_name = self.gen_prefix(safe_name(name.upper())) 684 self.struct = object_name 685 686 self.group = Group(self, None, 0, 1, name) 687 if "size" in attrs: 688 self.group.length = int(attrs["size"]) * 4 689 self.group.align = int(attrs["align"]) if "align" in attrs else None 690 self.structs[attrs["name"]] = self.group 691 elif name == "field": 692 self.group.fields.append(Field(self, attrs)) 693 self.values = [] 694 elif name == "enum": 695 self.values = [] 696 self.enum = safe_name(attrs["name"]) 697 self.enums.add(attrs["name"]) 698 if "prefix" in attrs: 699 self.prefix = attrs["prefix"] 700 else: 701 self.prefix= None 702 elif name == "value": 703 self.values.append(Value(attrs)) 704 elif name == "aggregate": 705 aggregate_name = self.gen_prefix(safe_name(attrs["name"].upper())) 706 self.aggregate = Aggregate(self, aggregate_name, attrs) 707 self.aggregates[attrs['name']] = self.aggregate 708 elif name == "section": 709 type_name = self.gen_prefix(safe_name(attrs["type"].upper())) 710 self.aggregate.add_section(type_name, attrs) 711 712 def end_element(self, name): 713 if name == "struct": 714 self.emit_struct() 715 self.struct = None 716 self.group = None 717 elif name == "field": 718 self.group.fields[-1].values = self.values 719 elif name == "enum": 720 self.emit_enum() 721 self.enum = None 722 elif name == "aggregate": 723 self.emit_aggregate() 724 self.aggregate = None 725 elif name == "panxml": 726 # Include at the end so it can depend on us but not the converse 727 print('#include "panfrost-job.h"') 728 print('#endif') 729 730 def emit_header(self, name): 731 default_fields = [] 732 for field in self.group.fields: 733 if not type(field) is Field: 734 continue 735 if field.default is not None: 736 default_fields.append(" .{} = {}".format(field.name, field.default)) 737 elif field.type in self.structs: 738 default_fields.append(" .{} = {{ {}_header }}".format(field.name, self.gen_prefix(safe_name(field.type.upper())))) 739 740 print('#define %-40s\\' % (name + '_header')) 741 if default_fields: 742 print(", \\\n".join(default_fields)) 743 else: 744 print(' 0') 745 print('') 746 747 def emit_template_struct(self, name, group): 748 print("struct %s {" % name) 749 group.emit_template_struct("") 750 print("};\n") 751 752 def emit_aggregate(self): 753 aggregate = self.aggregate 754 print("struct %s_packed {" % aggregate.name.lower()) 755 print(" uint32_t opaque[{}];".format(aggregate.get_size() // 4)) 756 print("};\n") 757 print('#define {}_LENGTH {}'.format(aggregate.name.upper(), aggregate.size)) 758 if aggregate.align != None: 759 print('#define {}_ALIGN {}'.format(aggregate.name.upper(), aggregate.align)) 760 for section in aggregate.sections: 761 print('#define {}_SECTION_{}_TYPE struct {}'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 762 print('#define {}_SECTION_{}_header {}_header'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 763 print('#define {}_SECTION_{}_pack {}_pack'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 764 print('#define {}_SECTION_{}_unpack {}_unpack'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 765 print('#define {}_SECTION_{}_print {}_print'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 766 print('#define {}_SECTION_{}_OFFSET {}'.format(aggregate.name.upper(), section.name.upper(), section.offset)) 767 print("") 768 769 def emit_pack_function(self, name, group): 770 print("static ALWAYS_INLINE void\n%s_pack(uint32_t * restrict cl,\n%sconst struct %s * restrict values)\n{" % 771 (name, ' ' * (len(name) + 6), name)) 772 773 group.emit_pack_function() 774 775 print("}\n\n") 776 777 # Should be a whole number of words 778 assert((self.group.length % 4) == 0) 779 780 print('#define {} {}'.format (name + "_LENGTH", self.group.length)) 781 if self.group.align != None: 782 print('#define {} {}'.format (name + "_ALIGN", self.group.align)) 783 print('struct {}_packed {{ uint32_t opaque[{}]; }};'.format(name.lower(), self.group.length // 4)) 784 785 def emit_unpack_function(self, name, group): 786 print("static inline void") 787 print("%s_unpack(const uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" % 788 (name.upper(), ' ' * (len(name) + 8), name)) 789 790 group.emit_unpack_function() 791 792 print("}\n") 793 794 def emit_print_function(self, name, group): 795 print("static inline void") 796 print("{}_print(FILE *fp, const struct {} * values, unsigned indent)\n{{".format(name.upper(), name)) 797 798 group.emit_print_function() 799 800 print("}\n") 801 802 def emit_struct(self): 803 name = self.struct 804 805 self.emit_template_struct(self.struct, self.group) 806 self.emit_header(name) 807 if self.no_direct_packing == False: 808 self.emit_pack_function(self.struct, self.group) 809 self.emit_unpack_function(self.struct, self.group) 810 self.emit_print_function(self.struct, self.group) 811 812 def enum_prefix(self, name): 813 return 814 815 def emit_enum(self): 816 e_name = enum_name(self.enum) 817 prefix = e_name if self.enum != 'Format' else global_prefix 818 print('enum {} {{'.format(e_name)) 819 820 for value in self.values: 821 name = '{}_{}'.format(prefix, value.name) 822 name = safe_name(name).upper() 823 print(' % -36s = %6d,' % (name, value.value)) 824 print('};\n') 825 826 print("static inline const char *") 827 print("{}_as_str(enum {} imm)\n{{".format(e_name.lower(), e_name)) 828 print(" switch (imm) {") 829 for value in self.values: 830 name = '{}_{}'.format(prefix, value.name) 831 name = safe_name(name).upper() 832 print(' case {}: return "{}";'.format(name, value.name)) 833 print(' default: return "XXX: INVALID";') 834 print(" }") 835 print("}\n") 836 837 def parse(self, filename): 838 file = open(filename, "rb") 839 self.parser.ParseFile(file) 840 file.close() 841 842if len(sys.argv) < 2: 843 print("No input xml file specified") 844 sys.exit(1) 845 846input_file = sys.argv[1] 847 848p = Parser() 849p.parse(input_file) 850