Path: blob/21.2-virgl/src/panfrost/lib/gen_pack.py
4560 views
#encoding=utf-812# Copyright (C) 2016 Intel Corporation3# Copyright (C) 2016 Broadcom4# Copyright (C) 2020 Collabora, Ltd.5#6# Permission is hereby granted, free of charge, to any person obtaining a7# copy of this software and associated documentation files (the "Software"),8# to deal in the Software without restriction, including without limitation9# the rights to use, copy, modify, merge, publish, distribute, sublicense,10# and/or sell copies of the Software, and to permit persons to whom the11# Software is furnished to do so, subject to the following conditions:12#13# The above copyright notice and this permission notice (including the next14# paragraph) shall be included in all copies or substantial portions of the15# Software.16#17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL20# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS23# IN THE SOFTWARE.2425import xml.parsers.expat26import sys27import operator28from functools import reduce2930global_prefix = "mali"3132pack_header = """33/* Generated code, see midgard.xml and gen_pack_header.py34*35* Packets, enums and structures for Panfrost.36*37* This file has been generated, do not hand edit.38*/3940#ifndef PAN_PACK_H41#define PAN_PACK_H4243#include <stdio.h>44#include <stdint.h>45#include <stdbool.h>46#include <assert.h>47#include <math.h>48#include <inttypes.h>49#include "util/macros.h"50#include "util/u_math.h"5152#define __gen_unpack_float(x, y, z) uif(__gen_unpack_uint(x, y, z))5354static inline uint64_t55__gen_uint(uint64_t v, uint32_t start, uint32_t end)56{57#ifndef NDEBUG58const int width = end - start + 1;59if (width < 64) {60const uint64_t max = (1ull << width) - 1;61assert(v <= max);62}63#endif6465return v << start;66}6768static inline uint32_t69__gen_sint(int32_t v, uint32_t start, uint32_t end)70{71#ifndef NDEBUG72const int width = end - start + 1;73if (width < 64) {74const int64_t max = (1ll << (width - 1)) - 1;75const int64_t min = -(1ll << (width - 1));76assert(min <= v && v <= max);77}78#endif7980return (((uint32_t) v) << start) & ((2ll << end) - 1);81}8283static inline uint32_t84__gen_padded(uint32_t v, uint32_t start, uint32_t end)85{86unsigned shift = __builtin_ctz(v);87unsigned odd = v >> (shift + 1);8889#ifndef NDEBUG90assert((v >> shift) & 1);91assert(shift <= 31);92assert(odd <= 7);93assert((end - start + 1) == 8);94#endif9596return __gen_uint(shift | (odd << 5), start, end);97}9899100static inline uint64_t101__gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end)102{103uint64_t val = 0;104const int width = end - start + 1;105const uint64_t mask = (width == 64 ? ~0 : (1ull << width) - 1 );106107for (uint32_t byte = start / 8; byte <= end / 8; byte++) {108val |= ((uint64_t) cl[byte]) << ((byte - start / 8) * 8);109}110111return (val >> (start % 8)) & mask;112}113114static inline uint64_t115__gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end)116{117int size = end - start + 1;118int64_t val = __gen_unpack_uint(cl, start, end);119120/* Get the sign bit extended. */121return (val << (64 - size)) >> (64 - size);122}123124static inline uint64_t125__gen_unpack_padded(const uint8_t *restrict cl, uint32_t start, uint32_t end)126{127unsigned val = __gen_unpack_uint(cl, start, end);128unsigned shift = val & 0b11111;129unsigned odd = val >> 5;130131return (2*odd + 1) << shift;132}133134#define pan_prepare(dst, T) \\135*(dst) = (struct MALI_ ## T){ MALI_ ## T ## _header }136137#define pan_pack(dst, T, name) \\138for (struct MALI_ ## T name = { MALI_ ## T ## _header }, \\139*_loop_terminate = (void *) (dst); \\140__builtin_expect(_loop_terminate != NULL, 1); \\141({ MALI_ ## T ## _pack((uint32_t *) (dst), &name); \\142_loop_terminate = NULL; }))143144#define pan_unpack(src, T, name) \\145struct MALI_ ## T name; \\146MALI_ ## T ## _unpack((uint8_t *)(src), &name)147148#define pan_print(fp, T, var, indent) \\149MALI_ ## T ## _print(fp, &(var), indent)150151#define pan_section_offset(A, S) \\152MALI_ ## A ## _SECTION_ ## S ## _OFFSET153154#define pan_section_ptr(base, A, S) \\155((void *)((uint8_t *)(base) + pan_section_offset(A, S)))156157#define pan_section_pack(dst, A, S, name) \\158for (MALI_ ## A ## _SECTION_ ## S ## _TYPE name = { MALI_ ## A ## _SECTION_ ## S ## _header }, \\159*_loop_terminate = (void *) (dst); \\160__builtin_expect(_loop_terminate != NULL, 1); \\161({ MALI_ ## A ## _SECTION_ ## S ## _pack(pan_section_ptr(dst, A, S), &name); \\162_loop_terminate = NULL; }))163164#define pan_section_unpack(src, A, S, name) \\165MALI_ ## A ## _SECTION_ ## S ## _TYPE name; \\166MALI_ ## A ## _SECTION_ ## S ## _unpack(pan_section_ptr(src, A, S), &name)167168#define pan_section_print(fp, A, S, var, indent) \\169MALI_ ## A ## _SECTION_ ## S ## _print(fp, &(var), indent)170171#define pan_merge(packed1, packed2, type) \172do { \173for (unsigned i = 0; i < (MALI_ ## type ## _LENGTH / 4); ++i) \174packed1.opaque[i] |= packed2.opaque[i]; \175} while(0)176177#define mali_pixel_format_print_v6(fp, format) \\178fprintf(fp, "%*sFormat (v6): %s%s%s %s%s%s%s\\n", indent, "", \\179mali_format_as_str((enum mali_format)((format >> 12) & 0xFF)), \\180(format & (1 << 20)) ? " sRGB" : "", \\181(format & (1 << 21)) ? " big-endian" : "", \\182mali_channel_as_str((enum mali_channel)((format >> 0) & 0x7)), \\183mali_channel_as_str((enum mali_channel)((format >> 3) & 0x7)), \\184mali_channel_as_str((enum mali_channel)((format >> 6) & 0x7)), \\185mali_channel_as_str((enum mali_channel)((format >> 9) & 0x7)));186187#define mali_pixel_format_print_v7(fp, format) \\188fprintf(fp, "%*sFormat (v7): %s%s %s%s\\n", indent, "", \\189mali_format_as_str((enum mali_format)((format >> 12) & 0xFF)), \\190(format & (1 << 20)) ? " sRGB" : "", \\191mali_rgb_component_order_as_str((enum mali_rgb_component_order)(format & ((1 << 12) - 1))), \\192(format & (1 << 21)) ? " XXX BAD BIT" : "");193194195/* From presentations, 16x16 tiles externally. Use shift for fast computation196* of tile numbers. */197198#define MALI_TILE_SHIFT 4199#define MALI_TILE_LENGTH (1 << MALI_TILE_SHIFT)200201"""202203def to_alphanum(name):204substitutions = {205' ': '_',206'/': '_',207'[': '',208']': '',209'(': '',210')': '',211'-': '_',212':': '',213'.': '',214',': '',215'=': '',216'>': '',217'#': '',218'&': '',219'*': '',220'"': '',221'+': '',222'\'': '',223}224225for i, j in substitutions.items():226name = name.replace(i, j)227228return name229230def safe_name(name):231name = to_alphanum(name)232if not name[0].isalpha():233name = '_' + name234235return name236237def prefixed_upper_name(prefix, name):238if prefix:239name = prefix + "_" + name240return safe_name(name).upper()241242def enum_name(name):243return "{}_{}".format(global_prefix, safe_name(name)).lower()244245def num_from_str(num_str):246if num_str.lower().startswith('0x'):247return int(num_str, base=16)248else:249assert(not num_str.startswith('0') and 'octals numbers not allowed')250return int(num_str)251252MODIFIERS = ["shr", "minus", "align", "log2"]253254def parse_modifier(modifier):255if modifier is None:256return None257258for mod in MODIFIERS:259if modifier[0:len(mod)] == mod:260if mod == "log2":261assert(len(mod) == len(modifier))262return [mod]263264if modifier[len(mod)] == '(' and modifier[-1] == ')':265ret = [mod, int(modifier[(len(mod) + 1):-1])]266if ret[0] == 'align':267align = ret[1]268# Make sure the alignment is a power of 2269assert(align > 0 and not(align & (align - 1)));270271return ret272273print("Invalid modifier")274assert(False)275276class Aggregate(object):277def __init__(self, parser, name, attrs):278self.parser = parser279self.sections = []280self.name = name281self.explicit_size = int(attrs["size"]) if "size" in attrs else 0282self.size = 0283self.align = int(attrs["align"]) if "align" in attrs else None284285class Section:286def __init__(self, name):287self.name = name288289def get_size(self):290if self.size > 0:291return self.size292293size = 0294for section in self.sections:295size = max(size, section.offset + section.type.get_length())296297if self.explicit_size > 0:298assert(self.explicit_size >= size)299self.size = self.explicit_size300else:301self.size = size302return self.size303304def add_section(self, type_name, attrs):305assert("name" in attrs)306section = self.Section(safe_name(attrs["name"]).lower())307section.human_name = attrs["name"]308section.offset = int(attrs["offset"])309assert(section.offset % 4 == 0)310section.type = self.parser.structs[attrs["type"]]311section.type_name = type_name312self.sections.append(section)313314class Field(object):315def __init__(self, parser, attrs):316self.parser = parser317if "name" in attrs:318self.name = safe_name(attrs["name"]).lower()319self.human_name = attrs["name"]320321if ":" in str(attrs["start"]):322(word, bit) = attrs["start"].split(":")323self.start = (int(word) * 32) + int(bit)324else:325self.start = int(attrs["start"])326327self.end = self.start + int(attrs["size"]) - 1328self.type = attrs["type"]329330if self.type == 'bool' and self.start != self.end:331print("#error Field {} has bool type but more than one bit of size".format(self.name));332333if "prefix" in attrs:334self.prefix = safe_name(attrs["prefix"]).upper()335else:336self.prefix = None337338if "exact" in attrs:339self.exact = int(attrs["exact"])340else:341self.exact = None342343self.default = attrs.get("default")344345# Map enum values346if self.type in self.parser.enums and self.default is not None:347self.default = safe_name('{}_{}_{}'.format(global_prefix, self.type, self.default)).upper()348349self.modifier = parse_modifier(attrs.get("modifier"))350351def emit_template_struct(self, dim):352if self.type == 'address':353type = 'uint64_t'354elif self.type == 'bool':355type = 'bool'356elif self.type == 'float':357type = 'float'358elif self.type == 'uint' and self.end - self.start > 32:359type = 'uint64_t'360elif self.type == 'int':361type = 'int32_t'362elif self.type in ['uint', 'uint/float', 'padded', 'Pixel Format']:363type = 'uint32_t'364elif self.type in self.parser.structs:365type = 'struct ' + self.parser.gen_prefix(safe_name(self.type.upper()))366elif self.type in self.parser.enums:367type = 'enum ' + enum_name(self.type)368else:369print("#error unhandled type: %s" % self.type)370type = "uint32_t"371372print(" %-36s %s%s;" % (type, self.name, dim))373374for value in self.values:375name = prefixed_upper_name(self.prefix, value.name)376print("#define %-40s %d" % (name, value.value))377378def overlaps(self, field):379return self != field and max(self.start, field.start) <= min(self.end, field.end)380381class Group(object):382def __init__(self, parser, parent, start, count, label):383self.parser = parser384self.parent = parent385self.start = start386self.count = count387self.label = label388self.size = 0389self.length = 0390self.fields = []391392def get_length(self):393# Determine number of bytes in this group.394calculated = max(field.end // 8 for field in self.fields) + 1 if len(self.fields) > 0 else 0395if self.length > 0:396assert(self.length >= calculated)397else:398self.length = calculated399return self.length400401402def emit_template_struct(self, dim):403if self.count == 0:404print(" /* variable length fields follow */")405else:406if self.count > 1:407dim = "%s[%d]" % (dim, self.count)408409if len(self.fields) == 0:410print(" int dummy;")411412for field in self.fields:413if field.exact is not None:414continue415416field.emit_template_struct(dim)417418class Word:419def __init__(self):420self.size = 32421self.contributors = []422423class FieldRef:424def __init__(self, field, path, start, end):425self.field = field426self.path = path427self.start = start428self.end = end429430def collect_fields(self, fields, offset, path, all_fields):431for field in fields:432field_path = '{}{}'.format(path, field.name)433field_offset = offset + field.start434435if field.type in self.parser.structs:436sub_struct = self.parser.structs[field.type]437self.collect_fields(sub_struct.fields, field_offset, field_path + '.', all_fields)438continue439440start = field_offset441end = offset + field.end442all_fields.append(self.FieldRef(field, field_path, start, end))443444def collect_words(self, fields, offset, path, words):445for field in fields:446field_path = '{}{}'.format(path, field.name)447start = offset + field.start448449if field.type in self.parser.structs:450sub_fields = self.parser.structs[field.type].fields451self.collect_words(sub_fields, start, field_path + '.', words)452continue453454end = offset + field.end455contributor = self.FieldRef(field, field_path, start, end)456first_word = contributor.start // 32457last_word = contributor.end // 32458for b in range(first_word, last_word + 1):459if not b in words:460words[b] = self.Word()461words[b].contributors.append(contributor)462463def emit_pack_function(self):464self.get_length()465466words = {}467self.collect_words(self.fields, 0, '', words)468469# Validate the modifier is lossless470for field in self.fields:471if field.modifier is None:472continue473474assert(field.exact is None)475476if field.modifier[0] == "shr":477shift = field.modifier[1]478mask = hex((1 << shift) - 1)479print(" assert((values->{} & {}) == 0);".format(field.name, mask))480elif field.modifier[0] == "minus":481print(" assert(values->{} >= {});".format(field.name, field.modifier[1]))482elif field.modifier[0] == "log2":483print(" assert(util_is_power_of_two_nonzero(values->{}));".format(field.name))484485for index in range(self.length // 4):486# Handle MBZ words487if not index in words:488print(" cl[%2d] = 0;" % index)489continue490491word = words[index]492493word_start = index * 32494495v = None496prefix = " cl[%2d] =" % index497498for contributor in word.contributors:499field = contributor.field500name = field.name501start = contributor.start502end = contributor.end503contrib_word_start = (start // 32) * 32504start -= contrib_word_start505end -= contrib_word_start506507value = str(field.exact) if field.exact is not None else "values->{}".format(contributor.path)508if field.modifier is not None:509if field.modifier[0] == "shr":510value = "{} >> {}".format(value, field.modifier[1])511elif field.modifier[0] == "minus":512value = "{} - {}".format(value, field.modifier[1])513elif field.modifier[0] == "align":514value = "ALIGN_POT({}, {})".format(value, field.modifier[1])515elif field.modifier[0] == "log2":516value = "util_logbase2({})".format(value)517518if field.type in ["uint", "uint/float", "address", "Pixel Format"]:519s = "__gen_uint(%s, %d, %d)" % \520(value, start, end)521elif field.type == "padded":522s = "__gen_padded(%s, %d, %d)" % \523(value, start, end)524elif field.type in self.parser.enums:525s = "__gen_uint(%s, %d, %d)" % \526(value, start, end)527elif field.type == "int":528s = "__gen_sint(%s, %d, %d)" % \529(value, start, end)530elif field.type == "bool":531s = "__gen_uint(%s, %d, %d)" % \532(value, start, end)533elif field.type == "float":534assert(start == 0 and end == 31)535s = "__gen_uint(fui({}), 0, 32)".format(value)536else:537s = "#error unhandled field {}, type {}".format(contributor.path, field.type)538539if not s == None:540shift = word_start - contrib_word_start541if shift:542s = "%s >> %d" % (s, shift)543544if contributor == word.contributors[-1]:545print("%s %s;" % (prefix, s))546else:547print("%s %s |" % (prefix, s))548prefix = " "549550continue551552# Given a field (start, end) contained in word `index`, generate the 32-bit553# mask of present bits relative to the word554def mask_for_word(self, index, start, end):555field_word_start = index * 32556start -= field_word_start557end -= field_word_start558# Cap multiword at one word559start = max(start, 0)560end = min(end, 32 - 1)561count = (end - start + 1)562return (((1 << count) - 1) << start)563564def emit_unpack_function(self):565# First, verify there is no garbage in unused bits566words = {}567self.collect_words(self.fields, 0, '', words)568569for index in range(self.length // 4):570base = index * 32571word = words.get(index, self.Word())572masks = [self.mask_for_word(index, c.start, c.end) for c in word.contributors]573mask = reduce(lambda x,y: x | y, masks, 0)574575ALL_ONES = 0xffffffff576577if mask != ALL_ONES:578TMPL = ' if (((const uint32_t *) cl)[{}] & {}) fprintf(stderr, "XXX: Invalid field of {} unpacked at word {}\\n");'579print(TMPL.format(index, hex(mask ^ ALL_ONES), self.label, index))580581fieldrefs = []582self.collect_fields(self.fields, 0, '', fieldrefs)583for fieldref in fieldrefs:584field = fieldref.field585convert = None586587args = []588args.append('cl')589args.append(str(fieldref.start))590args.append(str(fieldref.end))591592if field.type in set(["uint", "uint/float", "address", "Pixel Format"]):593convert = "__gen_unpack_uint"594elif field.type in self.parser.enums:595convert = "(enum %s)__gen_unpack_uint" % enum_name(field.type)596elif field.type == "int":597convert = "__gen_unpack_sint"598elif field.type == "padded":599convert = "__gen_unpack_padded"600elif field.type == "bool":601convert = "__gen_unpack_uint"602elif field.type == "float":603convert = "__gen_unpack_float"604else:605s = "/* unhandled field %s, type %s */\n" % (field.name, field.type)606607suffix = ""608prefix = ""609if field.modifier:610if field.modifier[0] == "minus":611suffix = " + {}".format(field.modifier[1])612elif field.modifier[0] == "shr":613suffix = " << {}".format(field.modifier[1])614if field.modifier[0] == "log2":615prefix = "1 << "616617decoded = '{}{}({}){}'.format(prefix, convert, ', '.join(args), suffix)618619print(' values->{} = {};'.format(fieldref.path, decoded))620if field.modifier and field.modifier[0] == "align":621mask = hex(field.modifier[1] - 1)622print(' assert(!(values->{} & {}));'.format(fieldref.path, mask))623624def emit_print_function(self):625for field in self.fields:626convert = None627name, val = field.human_name, 'values->{}'.format(field.name)628629if field.type in self.parser.structs:630pack_name = self.parser.gen_prefix(safe_name(field.type)).upper()631print(' fprintf(fp, "%*s{}:\\n", indent, "");'.format(field.human_name))632print(" {}_print(fp, &values->{}, indent + 2);".format(pack_name, field.name))633elif field.type == "address":634# TODO resolve to name635print(' fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val))636elif field.type in self.parser.enums:637print(' fprintf(fp, "%*s{}: %s\\n", indent, "", {}_as_str({}));'.format(name, enum_name(field.type), val))638elif field.type == "int":639print(' fprintf(fp, "%*s{}: %d\\n", indent, "", {});'.format(name, val))640elif field.type == "bool":641print(' fprintf(fp, "%*s{}: %s\\n", indent, "", {} ? "true" : "false");'.format(name, val))642elif field.type == "float":643print(' fprintf(fp, "%*s{}: %f\\n", indent, "", {});'.format(name, val))644elif field.type == "uint" and (field.end - field.start) >= 32:645print(' fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val))646elif field.type == "uint/float":647print(' fprintf(fp, "%*s{}: 0x%X (%f)\\n", indent, "", {}, uif({}));'.format(name, val, val))648elif field.type == "Pixel Format":649print(' mali_pixel_format_print_v6(fp, {});'.format(val))650print(' mali_pixel_format_print_v7(fp, {});'.format(val))651else:652print(' fprintf(fp, "%*s{}: %u\\n", indent, "", {});'.format(name, val))653654class Value(object):655def __init__(self, attrs):656self.name = attrs["name"]657self.value = int(attrs["value"], 0)658659class Parser(object):660def __init__(self):661self.parser = xml.parsers.expat.ParserCreate()662self.parser.StartElementHandler = self.start_element663self.parser.EndElementHandler = self.end_element664665self.struct = None666self.structs = {}667# Set of enum names we've seen.668self.enums = set()669self.aggregate = None670self.aggregates = {}671672def gen_prefix(self, name):673return '{}_{}'.format(global_prefix.upper(), name)674675def start_element(self, name, attrs):676if name == "panxml":677print(pack_header)678elif name == "struct":679name = attrs["name"]680self.no_direct_packing = attrs.get("no-direct-packing", False)681object_name = self.gen_prefix(safe_name(name.upper()))682self.struct = object_name683684self.group = Group(self, None, 0, 1, name)685if "size" in attrs:686self.group.length = int(attrs["size"]) * 4687self.group.align = int(attrs["align"]) if "align" in attrs else None688self.structs[attrs["name"]] = self.group689elif name == "field":690self.group.fields.append(Field(self, attrs))691self.values = []692elif name == "enum":693self.values = []694self.enum = safe_name(attrs["name"])695self.enums.add(attrs["name"])696if "prefix" in attrs:697self.prefix = attrs["prefix"]698else:699self.prefix= None700elif name == "value":701self.values.append(Value(attrs))702elif name == "aggregate":703aggregate_name = self.gen_prefix(safe_name(attrs["name"].upper()))704self.aggregate = Aggregate(self, aggregate_name, attrs)705self.aggregates[attrs['name']] = self.aggregate706elif name == "section":707type_name = self.gen_prefix(safe_name(attrs["type"].upper()))708self.aggregate.add_section(type_name, attrs)709710def end_element(self, name):711if name == "struct":712self.emit_struct()713self.struct = None714self.group = None715elif name == "field":716self.group.fields[-1].values = self.values717elif name == "enum":718self.emit_enum()719self.enum = None720elif name == "aggregate":721self.emit_aggregate()722self.aggregate = None723elif name == "panxml":724# Include at the end so it can depend on us but not the converse725print('#include "panfrost-job.h"')726print('#endif')727728def emit_header(self, name):729default_fields = []730for field in self.group.fields:731if not type(field) is Field:732continue733if field.default is not None:734default_fields.append(" .{} = {}".format(field.name, field.default))735elif field.type in self.structs:736default_fields.append(" .{} = {{ {}_header }}".format(field.name, self.gen_prefix(safe_name(field.type.upper()))))737738print('#define %-40s\\' % (name + '_header'))739if default_fields:740print(", \\\n".join(default_fields))741else:742print(' 0')743print('')744745def emit_template_struct(self, name, group):746print("struct %s {" % name)747group.emit_template_struct("")748print("};\n")749750def emit_aggregate(self):751aggregate = self.aggregate752print("struct %s_packed {" % aggregate.name.lower())753print(" uint32_t opaque[{}];".format(aggregate.get_size() // 4))754print("};\n")755print('#define {}_LENGTH {}'.format(aggregate.name.upper(), aggregate.size))756if aggregate.align != None:757print('#define {}_ALIGN {}'.format(aggregate.name.upper(), aggregate.align))758for section in aggregate.sections:759print('#define {}_SECTION_{}_TYPE struct {}'.format(aggregate.name.upper(), section.name.upper(), section.type_name))760print('#define {}_SECTION_{}_header {}_header'.format(aggregate.name.upper(), section.name.upper(), section.type_name))761print('#define {}_SECTION_{}_pack {}_pack'.format(aggregate.name.upper(), section.name.upper(), section.type_name))762print('#define {}_SECTION_{}_unpack {}_unpack'.format(aggregate.name.upper(), section.name.upper(), section.type_name))763print('#define {}_SECTION_{}_print {}_print'.format(aggregate.name.upper(), section.name.upper(), section.type_name))764print('#define {}_SECTION_{}_OFFSET {}'.format(aggregate.name.upper(), section.name.upper(), section.offset))765print("")766767def emit_pack_function(self, name, group):768print("static inline void\n%s_pack(uint32_t * restrict cl,\n%sconst struct %s * restrict values)\n{" %769(name, ' ' * (len(name) + 6), name))770771group.emit_pack_function()772773print("}\n\n")774775# Should be a whole number of words776assert((self.group.length % 4) == 0)777778print('#define {} {}'.format (name + "_LENGTH", self.group.length))779if self.group.align != None:780print('#define {} {}'.format (name + "_ALIGN", self.group.align))781print('struct {}_packed {{ uint32_t opaque[{}]; }};'.format(name.lower(), self.group.length // 4))782783def emit_unpack_function(self, name, group):784print("static inline void")785print("%s_unpack(const uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" %786(name.upper(), ' ' * (len(name) + 8), name))787788group.emit_unpack_function()789790print("}\n")791792def emit_print_function(self, name, group):793print("static inline void")794print("{}_print(FILE *fp, const struct {} * values, unsigned indent)\n{{".format(name.upper(), name))795796group.emit_print_function()797798print("}\n")799800def emit_struct(self):801name = self.struct802803self.emit_template_struct(self.struct, self.group)804self.emit_header(name)805if self.no_direct_packing == False:806self.emit_pack_function(self.struct, self.group)807self.emit_unpack_function(self.struct, self.group)808self.emit_print_function(self.struct, self.group)809810def enum_prefix(self, name):811return812813def emit_enum(self):814e_name = enum_name(self.enum)815prefix = e_name if self.enum != 'Format' else global_prefix816print('enum {} {{'.format(e_name))817818for value in self.values:819name = '{}_{}'.format(prefix, value.name)820name = safe_name(name).upper()821print(' % -36s = %6d,' % (name, value.value))822print('};\n')823824print("static inline const char *")825print("{}_as_str(enum {} imm)\n{{".format(e_name.lower(), e_name))826print(" switch (imm) {")827for value in self.values:828name = '{}_{}'.format(prefix, value.name)829name = safe_name(name).upper()830print(' case {}: return "{}";'.format(name, value.name))831print(' default: return "XXX: INVALID";')832print(" }")833print("}\n")834835def parse(self, filename):836file = open(filename, "rb")837self.parser.ParseFile(file)838file.close()839840if len(sys.argv) < 2:841print("No input xml file specified")842sys.exit(1)843844input_file = sys.argv[1]845846p = Parser()847p.parse(input_file)848849850