101e04c3fSmrg#encoding=utf-8 201e04c3fSmrg 39f464c52Smayaimport argparse 401e04c3fSmrgimport ast 501e04c3fSmrgimport xml.parsers.expat 601e04c3fSmrgimport re 701e04c3fSmrgimport sys 801e04c3fSmrgimport copy 901e04c3fSmrgimport textwrap 107ec681f3Smrgfrom util import * 1101e04c3fSmrg 1201e04c3fSmrglicense = """/* 1301e04c3fSmrg * Copyright (C) 2016 Intel Corporation 1401e04c3fSmrg * 1501e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 1601e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 1701e04c3fSmrg * to deal in the Software without restriction, including without limitation 1801e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1901e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 2001e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 2101e04c3fSmrg * 2201e04c3fSmrg * The above copyright notice and this permission notice (including the next 2301e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 2401e04c3fSmrg * Software. 2501e04c3fSmrg * 2601e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2701e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2801e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2901e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 3001e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 3101e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 3201e04c3fSmrg * IN THE SOFTWARE. 3301e04c3fSmrg */ 3401e04c3fSmrg""" 3501e04c3fSmrg 3601e04c3fSmrgpack_header = """%(license)s 3701e04c3fSmrg 3801e04c3fSmrg/* Instructions, enums and structures for %(platform)s. 3901e04c3fSmrg * 4001e04c3fSmrg * This file has been generated, do not hand edit. 4101e04c3fSmrg */ 4201e04c3fSmrg 4301e04c3fSmrg#ifndef %(guard)s 4401e04c3fSmrg#define %(guard)s 4501e04c3fSmrg 4601e04c3fSmrg#include <stdio.h> 4701e04c3fSmrg#include <stdint.h> 4801e04c3fSmrg#include <stdbool.h> 4901e04c3fSmrg#include <assert.h> 5001e04c3fSmrg#include <math.h> 5101e04c3fSmrg 5201e04c3fSmrg#ifndef __gen_validate_value 5301e04c3fSmrg#define __gen_validate_value(x) 5401e04c3fSmrg#endif 5501e04c3fSmrg 567ec681f3Smrg#ifndef __intel_field_functions 577ec681f3Smrg#define __intel_field_functions 5801e04c3fSmrg 5901e04c3fSmrg#ifdef NDEBUG 6001e04c3fSmrg#define NDEBUG_UNUSED __attribute__((unused)) 6101e04c3fSmrg#else 6201e04c3fSmrg#define NDEBUG_UNUSED 6301e04c3fSmrg#endif 6401e04c3fSmrg 657ec681f3Smrgunion __intel_value { 6601e04c3fSmrg float f; 6701e04c3fSmrg uint32_t dw; 6801e04c3fSmrg}; 6901e04c3fSmrg 707ec681f3Smrgstatic inline __attribute__((always_inline)) uint64_t 7101e04c3fSmrg__gen_mbo(uint32_t start, uint32_t end) 7201e04c3fSmrg{ 7301e04c3fSmrg return (~0ull >> (64 - (end - start + 1))) << start; 7401e04c3fSmrg} 7501e04c3fSmrg 767ec681f3Smrgstatic inline __attribute__((always_inline)) uint64_t 7701e04c3fSmrg__gen_uint(uint64_t v, uint32_t start, NDEBUG_UNUSED uint32_t end) 7801e04c3fSmrg{ 7901e04c3fSmrg __gen_validate_value(v); 8001e04c3fSmrg 8101e04c3fSmrg#ifndef NDEBUG 8201e04c3fSmrg const int width = end - start + 1; 8301e04c3fSmrg if (width < 64) { 8401e04c3fSmrg const uint64_t max = (1ull << width) - 1; 8501e04c3fSmrg assert(v <= max); 8601e04c3fSmrg } 8701e04c3fSmrg#endif 8801e04c3fSmrg 8901e04c3fSmrg return v << start; 9001e04c3fSmrg} 9101e04c3fSmrg 927ec681f3Smrgstatic inline __attribute__((always_inline)) uint64_t 9301e04c3fSmrg__gen_sint(int64_t v, uint32_t start, uint32_t end) 9401e04c3fSmrg{ 9501e04c3fSmrg const int width = end - start + 1; 9601e04c3fSmrg 9701e04c3fSmrg __gen_validate_value(v); 9801e04c3fSmrg 9901e04c3fSmrg#ifndef NDEBUG 10001e04c3fSmrg if (width < 64) { 10101e04c3fSmrg const int64_t max = (1ll << (width - 1)) - 1; 10201e04c3fSmrg const int64_t min = -(1ll << (width - 1)); 10301e04c3fSmrg assert(min <= v && v <= max); 10401e04c3fSmrg } 10501e04c3fSmrg#endif 10601e04c3fSmrg 10701e04c3fSmrg const uint64_t mask = ~0ull >> (64 - width); 10801e04c3fSmrg 10901e04c3fSmrg return (v & mask) << start; 11001e04c3fSmrg} 11101e04c3fSmrg 1127ec681f3Smrgstatic inline __attribute__((always_inline)) uint64_t 11301e04c3fSmrg__gen_offset(uint64_t v, NDEBUG_UNUSED uint32_t start, NDEBUG_UNUSED uint32_t end) 11401e04c3fSmrg{ 11501e04c3fSmrg __gen_validate_value(v); 11601e04c3fSmrg#ifndef NDEBUG 11701e04c3fSmrg uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; 11801e04c3fSmrg 11901e04c3fSmrg assert((v & ~mask) == 0); 12001e04c3fSmrg#endif 12101e04c3fSmrg 12201e04c3fSmrg return v; 12301e04c3fSmrg} 12401e04c3fSmrg 1257ec681f3Smrgstatic inline __attribute__((always_inline)) uint64_t 1267ec681f3Smrg__gen_address(__gen_user_data *data, void *location, 1277ec681f3Smrg __gen_address_type address, uint32_t delta, 1287ec681f3Smrg __attribute__((unused)) uint32_t start, uint32_t end) 1297ec681f3Smrg{ 1307ec681f3Smrg uint64_t addr_u64 = __gen_combine_address(data, location, address, delta); 1317ec681f3Smrg if (end == 31) { 1327ec681f3Smrg return addr_u64; 1337ec681f3Smrg } else if (end < 63) { 1347ec681f3Smrg const unsigned shift = 63 - end; 1357ec681f3Smrg return (addr_u64 << shift) >> shift; 1367ec681f3Smrg } else { 1377ec681f3Smrg return addr_u64; 1387ec681f3Smrg } 1397ec681f3Smrg} 1407ec681f3Smrg 1417ec681f3Smrgstatic inline __attribute__((always_inline)) uint32_t 14201e04c3fSmrg__gen_float(float v) 14301e04c3fSmrg{ 14401e04c3fSmrg __gen_validate_value(v); 1457ec681f3Smrg return ((union __intel_value) { .f = (v) }).dw; 14601e04c3fSmrg} 14701e04c3fSmrg 1487ec681f3Smrgstatic inline __attribute__((always_inline)) uint64_t 14901e04c3fSmrg__gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) 15001e04c3fSmrg{ 15101e04c3fSmrg __gen_validate_value(v); 15201e04c3fSmrg 15301e04c3fSmrg const float factor = (1 << fract_bits); 15401e04c3fSmrg 15501e04c3fSmrg#ifndef NDEBUG 15601e04c3fSmrg const float max = ((1 << (end - start)) - 1) / factor; 15701e04c3fSmrg const float min = -(1 << (end - start)) / factor; 15801e04c3fSmrg assert(min <= v && v <= max); 15901e04c3fSmrg#endif 16001e04c3fSmrg 16101e04c3fSmrg const int64_t int_val = llroundf(v * factor); 16201e04c3fSmrg const uint64_t mask = ~0ull >> (64 - (end - start + 1)); 16301e04c3fSmrg 16401e04c3fSmrg return (int_val & mask) << start; 16501e04c3fSmrg} 16601e04c3fSmrg 1677ec681f3Smrgstatic inline __attribute__((always_inline)) uint64_t 16801e04c3fSmrg__gen_ufixed(float v, uint32_t start, NDEBUG_UNUSED uint32_t end, uint32_t fract_bits) 16901e04c3fSmrg{ 17001e04c3fSmrg __gen_validate_value(v); 17101e04c3fSmrg 17201e04c3fSmrg const float factor = (1 << fract_bits); 17301e04c3fSmrg 17401e04c3fSmrg#ifndef NDEBUG 17501e04c3fSmrg const float max = ((1 << (end - start + 1)) - 1) / factor; 17601e04c3fSmrg const float min = 0.0f; 17701e04c3fSmrg assert(min <= v && v <= max); 17801e04c3fSmrg#endif 17901e04c3fSmrg 18001e04c3fSmrg const uint64_t uint_val = llroundf(v * factor); 18101e04c3fSmrg 18201e04c3fSmrg return uint_val << start; 18301e04c3fSmrg} 18401e04c3fSmrg 18501e04c3fSmrg#ifndef __gen_address_type 18601e04c3fSmrg#error #define __gen_address_type before including this file 18701e04c3fSmrg#endif 18801e04c3fSmrg 18901e04c3fSmrg#ifndef __gen_user_data 19001e04c3fSmrg#error #define __gen_combine_address before including this file 19101e04c3fSmrg#endif 19201e04c3fSmrg 19301e04c3fSmrg#undef NDEBUG_UNUSED 19401e04c3fSmrg 19501e04c3fSmrg#endif 19601e04c3fSmrg 19701e04c3fSmrg""" 19801e04c3fSmrg 19901e04c3fSmrgdef num_from_str(num_str): 20001e04c3fSmrg if num_str.lower().startswith('0x'): 20101e04c3fSmrg return int(num_str, base=16) 20201e04c3fSmrg 20301e04c3fSmrg assert not num_str.startswith('0'), 'octals numbers not allowed' 20401e04c3fSmrg return int(num_str) 20501e04c3fSmrg 20601e04c3fSmrgclass Field(object): 20701e04c3fSmrg ufixed_pattern = re.compile(r"u(\d+)\.(\d+)") 20801e04c3fSmrg sfixed_pattern = re.compile(r"s(\d+)\.(\d+)") 20901e04c3fSmrg 21001e04c3fSmrg def __init__(self, parser, attrs): 21101e04c3fSmrg self.parser = parser 21201e04c3fSmrg if "name" in attrs: 21301e04c3fSmrg self.name = safe_name(attrs["name"]) 21401e04c3fSmrg self.start = int(attrs["start"]) 21501e04c3fSmrg self.end = int(attrs["end"]) 21601e04c3fSmrg self.type = attrs["type"] 21701e04c3fSmrg 21801e04c3fSmrg assert self.start <= self.end, \ 21901e04c3fSmrg 'field {} has end ({}) < start ({})'.format(self.name, self.end, 22001e04c3fSmrg self.start) 22101e04c3fSmrg if self.type == 'bool': 22201e04c3fSmrg assert self.end == self.start, \ 22301e04c3fSmrg 'bool field ({}) is too wide'.format(self.name) 22401e04c3fSmrg 22501e04c3fSmrg if "prefix" in attrs: 22601e04c3fSmrg self.prefix = attrs["prefix"] 22701e04c3fSmrg else: 22801e04c3fSmrg self.prefix = None 22901e04c3fSmrg 23001e04c3fSmrg if "default" in attrs: 23101e04c3fSmrg # Base 0 recognizes 0x, 0o, 0b prefixes in addition to decimal ints. 23201e04c3fSmrg self.default = int(attrs["default"], base=0) 23301e04c3fSmrg else: 23401e04c3fSmrg self.default = None 23501e04c3fSmrg 23601e04c3fSmrg ufixed_match = Field.ufixed_pattern.match(self.type) 23701e04c3fSmrg if ufixed_match: 23801e04c3fSmrg self.type = 'ufixed' 23901e04c3fSmrg self.fractional_size = int(ufixed_match.group(2)) 24001e04c3fSmrg 24101e04c3fSmrg sfixed_match = Field.sfixed_pattern.match(self.type) 24201e04c3fSmrg if sfixed_match: 24301e04c3fSmrg self.type = 'sfixed' 24401e04c3fSmrg self.fractional_size = int(sfixed_match.group(2)) 24501e04c3fSmrg 24601e04c3fSmrg def is_builtin_type(self): 24701e04c3fSmrg builtins = [ 'address', 'bool', 'float', 'ufixed', 24801e04c3fSmrg 'offset', 'sfixed', 'offset', 'int', 'uint', 'mbo' ] 24901e04c3fSmrg return self.type in builtins 25001e04c3fSmrg 25101e04c3fSmrg def is_struct_type(self): 25201e04c3fSmrg return self.type in self.parser.structs 25301e04c3fSmrg 25401e04c3fSmrg def is_enum_type(self): 25501e04c3fSmrg return self.type in self.parser.enums 25601e04c3fSmrg 25701e04c3fSmrg def emit_template_struct(self, dim): 25801e04c3fSmrg if self.type == 'address': 25901e04c3fSmrg type = '__gen_address_type' 26001e04c3fSmrg elif self.type == 'bool': 26101e04c3fSmrg type = 'bool' 26201e04c3fSmrg elif self.type == 'float': 26301e04c3fSmrg type = 'float' 26401e04c3fSmrg elif self.type == 'ufixed': 26501e04c3fSmrg type = 'float' 26601e04c3fSmrg elif self.type == 'sfixed': 26701e04c3fSmrg type = 'float' 26801e04c3fSmrg elif self.type == 'uint' and self.end - self.start > 32: 26901e04c3fSmrg type = 'uint64_t' 27001e04c3fSmrg elif self.type == 'offset': 27101e04c3fSmrg type = 'uint64_t' 27201e04c3fSmrg elif self.type == 'int': 27301e04c3fSmrg type = 'int32_t' 27401e04c3fSmrg elif self.type == 'uint': 27501e04c3fSmrg type = 'uint32_t' 27601e04c3fSmrg elif self.is_struct_type(): 27701e04c3fSmrg type = 'struct ' + self.parser.gen_prefix(safe_name(self.type)) 27801e04c3fSmrg elif self.is_enum_type(): 27901e04c3fSmrg type = 'enum ' + self.parser.gen_prefix(safe_name(self.type)) 28001e04c3fSmrg elif self.type == 'mbo': 28101e04c3fSmrg return 28201e04c3fSmrg else: 28301e04c3fSmrg print("#error unhandled type: %s" % self.type) 28401e04c3fSmrg return 28501e04c3fSmrg 28601e04c3fSmrg print(" %-36s %s%s;" % (type, self.name, dim)) 28701e04c3fSmrg 28801e04c3fSmrg prefix = "" 28901e04c3fSmrg if self.values and self.default is None: 29001e04c3fSmrg if self.prefix: 29101e04c3fSmrg prefix = self.prefix + "_" 29201e04c3fSmrg 29301e04c3fSmrg for value in self.values: 29401e04c3fSmrg print("#define %-40s %d" % (prefix + value.name, value.value)) 29501e04c3fSmrg 29601e04c3fSmrgclass Group(object): 29701e04c3fSmrg def __init__(self, parser, parent, start, count, size): 29801e04c3fSmrg self.parser = parser 29901e04c3fSmrg self.parent = parent 30001e04c3fSmrg self.start = start 30101e04c3fSmrg self.count = count 30201e04c3fSmrg self.size = size 30301e04c3fSmrg self.fields = [] 30401e04c3fSmrg 30501e04c3fSmrg def emit_template_struct(self, dim): 30601e04c3fSmrg if self.count == 0: 30701e04c3fSmrg print(" /* variable length fields follow */") 30801e04c3fSmrg else: 30901e04c3fSmrg if self.count > 1: 31001e04c3fSmrg dim = "%s[%d]" % (dim, self.count) 31101e04c3fSmrg 31201e04c3fSmrg for field in self.fields: 31301e04c3fSmrg field.emit_template_struct(dim) 31401e04c3fSmrg 31501e04c3fSmrg class DWord: 31601e04c3fSmrg def __init__(self): 31701e04c3fSmrg self.size = 32 31801e04c3fSmrg self.fields = [] 31901e04c3fSmrg self.address = None 32001e04c3fSmrg 32101e04c3fSmrg def collect_dwords(self, dwords, start, dim): 32201e04c3fSmrg for field in self.fields: 32301e04c3fSmrg if isinstance(field, Group): 32401e04c3fSmrg if field.count == 1: 32501e04c3fSmrg field.collect_dwords(dwords, start + field.start, dim) 32601e04c3fSmrg else: 32701e04c3fSmrg for i in range(field.count): 32801e04c3fSmrg field.collect_dwords(dwords, 32901e04c3fSmrg start + field.start + i * field.size, 33001e04c3fSmrg "%s[%d]" % (dim, i)) 33101e04c3fSmrg continue 33201e04c3fSmrg 33301e04c3fSmrg index = (start + field.start) // 32 33401e04c3fSmrg if not index in dwords: 33501e04c3fSmrg dwords[index] = self.DWord() 33601e04c3fSmrg 33701e04c3fSmrg clone = copy.copy(field) 33801e04c3fSmrg clone.start = clone.start + start 33901e04c3fSmrg clone.end = clone.end + start 34001e04c3fSmrg clone.dim = dim 34101e04c3fSmrg dwords[index].fields.append(clone) 34201e04c3fSmrg 34301e04c3fSmrg if field.type == "address": 34401e04c3fSmrg # assert dwords[index].address == None 3457ec681f3Smrg dwords[index].address = clone 34601e04c3fSmrg 34701e04c3fSmrg # Coalesce all the dwords covered by this field. The two cases we 34801e04c3fSmrg # handle are where multiple fields are in a 64 bit word (typically 34901e04c3fSmrg # and address and a few bits) or where a single struct field 35001e04c3fSmrg # completely covers multiple dwords. 35101e04c3fSmrg while index < (start + field.end) // 32: 35201e04c3fSmrg if index + 1 in dwords and not dwords[index] == dwords[index + 1]: 35301e04c3fSmrg dwords[index].fields.extend(dwords[index + 1].fields) 35401e04c3fSmrg dwords[index].size = 64 35501e04c3fSmrg dwords[index + 1] = dwords[index] 35601e04c3fSmrg index = index + 1 35701e04c3fSmrg 35801e04c3fSmrg def collect_dwords_and_length(self): 35901e04c3fSmrg dwords = {} 36001e04c3fSmrg self.collect_dwords(dwords, 0, "") 36101e04c3fSmrg 36201e04c3fSmrg # Determine number of dwords in this group. If we have a size, use 36301e04c3fSmrg # that, since that'll account for MBZ dwords at the end of a group 36401e04c3fSmrg # (like dword 8 on BDW+ 3DSTATE_HS). Otherwise, use the largest dword 36501e04c3fSmrg # index we've seen plus one. 36601e04c3fSmrg if self.size > 0: 36701e04c3fSmrg length = self.size // 32 36801e04c3fSmrg elif dwords: 36901e04c3fSmrg length = max(dwords.keys()) + 1 37001e04c3fSmrg else: 37101e04c3fSmrg length = 0 37201e04c3fSmrg 37301e04c3fSmrg return (dwords, length) 37401e04c3fSmrg 37501e04c3fSmrg def emit_pack_function(self, dwords, length): 37601e04c3fSmrg for index in range(length): 37701e04c3fSmrg # Handle MBZ dwords 37801e04c3fSmrg if not index in dwords: 37901e04c3fSmrg print("") 38001e04c3fSmrg print(" dw[%d] = 0;" % index) 38101e04c3fSmrg continue 38201e04c3fSmrg 38301e04c3fSmrg # For 64 bit dwords, we aliased the two dword entries in the dword 38401e04c3fSmrg # dict it occupies. Now that we're emitting the pack function, 38501e04c3fSmrg # skip the duplicate entries. 38601e04c3fSmrg dw = dwords[index] 38701e04c3fSmrg if index > 0 and index - 1 in dwords and dw == dwords[index - 1]: 38801e04c3fSmrg continue 38901e04c3fSmrg 39001e04c3fSmrg # Special case: only one field and it's a struct at the beginning 39101e04c3fSmrg # of the dword. In this case we pack directly into the 39201e04c3fSmrg # destination. This is the only way we handle embedded structs 39301e04c3fSmrg # larger than 32 bits. 39401e04c3fSmrg if len(dw.fields) == 1: 39501e04c3fSmrg field = dw.fields[0] 39601e04c3fSmrg name = field.name + field.dim 39701e04c3fSmrg if field.is_struct_type() and field.start % 32 == 0: 39801e04c3fSmrg print("") 39901e04c3fSmrg print(" %s_pack(data, &dw[%d], &values->%s);" % 40001e04c3fSmrg (self.parser.gen_prefix(safe_name(field.type)), index, name)) 40101e04c3fSmrg continue 40201e04c3fSmrg 40301e04c3fSmrg # Pack any fields of struct type first so we have integer values 40401e04c3fSmrg # to the dword for those fields. 40501e04c3fSmrg field_index = 0 40601e04c3fSmrg for field in dw.fields: 40701e04c3fSmrg if isinstance(field, Field) and field.is_struct_type(): 40801e04c3fSmrg name = field.name + field.dim 40901e04c3fSmrg print("") 41001e04c3fSmrg print(" uint32_t v%d_%d;" % (index, field_index)) 41101e04c3fSmrg print(" %s_pack(data, &v%d_%d, &values->%s);" % 41201e04c3fSmrg (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name)) 41301e04c3fSmrg field_index = field_index + 1 41401e04c3fSmrg 41501e04c3fSmrg print("") 41601e04c3fSmrg dword_start = index * 32 41701e04c3fSmrg if dw.address == None: 41801e04c3fSmrg address_count = 0 41901e04c3fSmrg else: 42001e04c3fSmrg address_count = 1 42101e04c3fSmrg 42201e04c3fSmrg if dw.size == 32 and dw.address == None: 42301e04c3fSmrg v = None 42401e04c3fSmrg print(" dw[%d] =" % index) 42501e04c3fSmrg elif len(dw.fields) > address_count: 42601e04c3fSmrg v = "v%d" % index 42701e04c3fSmrg print(" const uint%d_t %s =" % (dw.size, v)) 42801e04c3fSmrg else: 42901e04c3fSmrg v = "0" 43001e04c3fSmrg 43101e04c3fSmrg field_index = 0 43201e04c3fSmrg non_address_fields = [] 43301e04c3fSmrg for field in dw.fields: 43401e04c3fSmrg if field.type != "mbo": 43501e04c3fSmrg name = field.name + field.dim 43601e04c3fSmrg 43701e04c3fSmrg if field.type == "mbo": 43801e04c3fSmrg non_address_fields.append("__gen_mbo(%d, %d)" % \ 43901e04c3fSmrg (field.start - dword_start, field.end - dword_start)) 44001e04c3fSmrg elif field.type == "address": 44101e04c3fSmrg pass 44201e04c3fSmrg elif field.type == "uint": 44301e04c3fSmrg non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ 44401e04c3fSmrg (name, field.start - dword_start, field.end - dword_start)) 44501e04c3fSmrg elif field.is_enum_type(): 44601e04c3fSmrg non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ 44701e04c3fSmrg (name, field.start - dword_start, field.end - dword_start)) 44801e04c3fSmrg elif field.type == "int": 44901e04c3fSmrg non_address_fields.append("__gen_sint(values->%s, %d, %d)" % \ 45001e04c3fSmrg (name, field.start - dword_start, field.end - dword_start)) 45101e04c3fSmrg elif field.type == "bool": 45201e04c3fSmrg non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ 45301e04c3fSmrg (name, field.start - dword_start, field.end - dword_start)) 45401e04c3fSmrg elif field.type == "float": 45501e04c3fSmrg non_address_fields.append("__gen_float(values->%s)" % name) 45601e04c3fSmrg elif field.type == "offset": 45701e04c3fSmrg non_address_fields.append("__gen_offset(values->%s, %d, %d)" % \ 45801e04c3fSmrg (name, field.start - dword_start, field.end - dword_start)) 45901e04c3fSmrg elif field.type == 'ufixed': 46001e04c3fSmrg non_address_fields.append("__gen_ufixed(values->%s, %d, %d, %d)" % \ 46101e04c3fSmrg (name, field.start - dword_start, field.end - dword_start, field.fractional_size)) 46201e04c3fSmrg elif field.type == 'sfixed': 46301e04c3fSmrg non_address_fields.append("__gen_sfixed(values->%s, %d, %d, %d)" % \ 46401e04c3fSmrg (name, field.start - dword_start, field.end - dword_start, field.fractional_size)) 46501e04c3fSmrg elif field.is_struct_type(): 46601e04c3fSmrg non_address_fields.append("__gen_uint(v%d_%d, %d, %d)" % \ 46701e04c3fSmrg (index, field_index, field.start - dword_start, field.end - dword_start)) 46801e04c3fSmrg field_index = field_index + 1 46901e04c3fSmrg else: 47001e04c3fSmrg non_address_fields.append("/* unhandled field %s, type %s */\n" % \ 47101e04c3fSmrg (name, field.type)) 47201e04c3fSmrg 47301e04c3fSmrg if non_address_fields: 47401e04c3fSmrg print(" |\n".join(" " + f for f in non_address_fields) + ";") 47501e04c3fSmrg 47601e04c3fSmrg if dw.size == 32: 47701e04c3fSmrg if dw.address: 4787ec681f3Smrg print(" dw[%d] = __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % 4797ec681f3Smrg (index, index, dw.address.name + field.dim, v, 4807ec681f3Smrg dw.address.start - dword_start, dw.address.end - dword_start)) 48101e04c3fSmrg continue 48201e04c3fSmrg 48301e04c3fSmrg if dw.address: 48401e04c3fSmrg v_address = "v%d_address" % index 4857ec681f3Smrg print(" const uint64_t %s =\n __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % 4867ec681f3Smrg (v_address, index, dw.address.name + field.dim, v, 4877ec681f3Smrg dw.address.start - dword_start, dw.address.end - dword_start)) 48801e04c3fSmrg if len(dw.fields) > address_count: 48901e04c3fSmrg print(" dw[%d] = %s;" % (index, v_address)) 49001e04c3fSmrg print(" dw[%d] = (%s >> 32) | (%s >> 32);" % (index + 1, v_address, v)) 49101e04c3fSmrg continue 49201e04c3fSmrg else: 49301e04c3fSmrg v = v_address 49401e04c3fSmrg print(" dw[%d] = %s;" % (index, v)) 49501e04c3fSmrg print(" dw[%d] = %s >> 32;" % (index + 1, v)) 49601e04c3fSmrg 49701e04c3fSmrgclass Value(object): 49801e04c3fSmrg def __init__(self, attrs): 49901e04c3fSmrg self.name = safe_name(attrs["name"]) 50001e04c3fSmrg self.value = ast.literal_eval(attrs["value"]) 50101e04c3fSmrg 50201e04c3fSmrgclass Parser(object): 50301e04c3fSmrg def __init__(self): 50401e04c3fSmrg self.parser = xml.parsers.expat.ParserCreate() 50501e04c3fSmrg self.parser.StartElementHandler = self.start_element 50601e04c3fSmrg self.parser.EndElementHandler = self.end_element 50701e04c3fSmrg 50801e04c3fSmrg self.instruction = None 50901e04c3fSmrg self.structs = {} 51001e04c3fSmrg # Set of enum names we've seen. 51101e04c3fSmrg self.enums = set() 51201e04c3fSmrg self.registers = {} 51301e04c3fSmrg 51401e04c3fSmrg def gen_prefix(self, name): 51501e04c3fSmrg if name[0] == "_": 5167ec681f3Smrg return 'GFX%s%s' % (self.gen, name) 5177ec681f3Smrg return 'GFX%s_%s' % (self.gen, name) 51801e04c3fSmrg 51901e04c3fSmrg def gen_guard(self): 52001e04c3fSmrg return self.gen_prefix("PACK_H") 52101e04c3fSmrg 52201e04c3fSmrg def start_element(self, name, attrs): 52301e04c3fSmrg if name == "genxml": 52401e04c3fSmrg self.platform = attrs["name"] 52501e04c3fSmrg self.gen = attrs["gen"].replace('.', '') 52601e04c3fSmrg print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()}) 52701e04c3fSmrg elif name in ("instruction", "struct", "register"): 52801e04c3fSmrg if name == "instruction": 52901e04c3fSmrg self.instruction = safe_name(attrs["name"]) 53001e04c3fSmrg self.length_bias = int(attrs["bias"]) 5319f464c52Smaya if "engine" in attrs: 5329f464c52Smaya self.instruction_engines = set(attrs["engine"].split('|')) 5339f464c52Smaya else: 5349f464c52Smaya # When an instruction doesn't have the engine specified, 5359f464c52Smaya # it is considered to be for all engines, so 'None' is used 5369f464c52Smaya # to signify that the instruction belongs to all engines. 5379f464c52Smaya self.instruction_engines = None 53801e04c3fSmrg elif name == "struct": 53901e04c3fSmrg self.struct = safe_name(attrs["name"]) 54001e04c3fSmrg self.structs[attrs["name"]] = 1 54101e04c3fSmrg elif name == "register": 54201e04c3fSmrg self.register = safe_name(attrs["name"]) 54301e04c3fSmrg self.reg_num = num_from_str(attrs["num"]) 54401e04c3fSmrg self.registers[attrs["name"]] = 1 54501e04c3fSmrg if "length" in attrs: 54601e04c3fSmrg self.length = int(attrs["length"]) 54701e04c3fSmrg size = self.length * 32 54801e04c3fSmrg else: 54901e04c3fSmrg self.length = None 55001e04c3fSmrg size = 0 55101e04c3fSmrg self.group = Group(self, None, 0, 1, size) 55201e04c3fSmrg 55301e04c3fSmrg elif name == "group": 55401e04c3fSmrg group = Group(self, self.group, 55501e04c3fSmrg int(attrs["start"]), int(attrs["count"]), int(attrs["size"])) 55601e04c3fSmrg self.group.fields.append(group) 55701e04c3fSmrg self.group = group 55801e04c3fSmrg elif name == "field": 55901e04c3fSmrg self.group.fields.append(Field(self, attrs)) 56001e04c3fSmrg self.values = [] 56101e04c3fSmrg elif name == "enum": 56201e04c3fSmrg self.values = [] 56301e04c3fSmrg self.enum = safe_name(attrs["name"]) 56401e04c3fSmrg self.enums.add(attrs["name"]) 56501e04c3fSmrg if "prefix" in attrs: 56601e04c3fSmrg self.prefix = safe_name(attrs["prefix"]) 56701e04c3fSmrg else: 56801e04c3fSmrg self.prefix= None 56901e04c3fSmrg elif name == "value": 57001e04c3fSmrg self.values.append(Value(attrs)) 57101e04c3fSmrg 57201e04c3fSmrg def end_element(self, name): 57301e04c3fSmrg if name == "instruction": 57401e04c3fSmrg self.emit_instruction() 57501e04c3fSmrg self.instruction = None 57601e04c3fSmrg self.group = None 57701e04c3fSmrg elif name == "struct": 57801e04c3fSmrg self.emit_struct() 57901e04c3fSmrg self.struct = None 58001e04c3fSmrg self.group = None 58101e04c3fSmrg elif name == "register": 58201e04c3fSmrg self.emit_register() 58301e04c3fSmrg self.register = None 58401e04c3fSmrg self.reg_num = None 58501e04c3fSmrg self.group = None 58601e04c3fSmrg elif name == "group": 58701e04c3fSmrg self.group = self.group.parent 58801e04c3fSmrg elif name == "field": 58901e04c3fSmrg self.group.fields[-1].values = self.values 59001e04c3fSmrg elif name == "enum": 59101e04c3fSmrg self.emit_enum() 59201e04c3fSmrg self.enum = None 59301e04c3fSmrg elif name == "genxml": 59401e04c3fSmrg print('#endif /* %s */' % self.gen_guard()) 59501e04c3fSmrg 59601e04c3fSmrg def emit_template_struct(self, name, group): 59701e04c3fSmrg print("struct %s {" % self.gen_prefix(name)) 59801e04c3fSmrg group.emit_template_struct("") 59901e04c3fSmrg print("};\n") 60001e04c3fSmrg 60101e04c3fSmrg def emit_pack_function(self, name, group): 60201e04c3fSmrg name = self.gen_prefix(name) 60301e04c3fSmrg print(textwrap.dedent("""\ 6047ec681f3Smrg static inline __attribute__((always_inline)) void 60501e04c3fSmrg %s_pack(__attribute__((unused)) __gen_user_data *data, 60601e04c3fSmrg %s__attribute__((unused)) void * restrict dst, 60701e04c3fSmrg %s__attribute__((unused)) const struct %s * restrict values) 60801e04c3fSmrg {""") % (name, ' ' * len(name), ' ' * len(name), name)) 60901e04c3fSmrg 61001e04c3fSmrg (dwords, length) = group.collect_dwords_and_length() 61101e04c3fSmrg if length: 61201e04c3fSmrg # Cast dst to make header C++ friendly 61301e04c3fSmrg print(" uint32_t * restrict dw = (uint32_t * restrict) dst;") 61401e04c3fSmrg 61501e04c3fSmrg group.emit_pack_function(dwords, length) 61601e04c3fSmrg 61701e04c3fSmrg print("}\n") 61801e04c3fSmrg 61901e04c3fSmrg def emit_instruction(self): 62001e04c3fSmrg name = self.instruction 6219f464c52Smaya if self.instruction_engines and not self.instruction_engines & self.engines: 6229f464c52Smaya return 6239f464c52Smaya 62401e04c3fSmrg if not self.length is None: 62501e04c3fSmrg print('#define %-33s %6d' % 62601e04c3fSmrg (self.gen_prefix(name + "_length"), self.length)) 62701e04c3fSmrg print('#define %-33s %6d' % 62801e04c3fSmrg (self.gen_prefix(name + "_length_bias"), self.length_bias)) 62901e04c3fSmrg 63001e04c3fSmrg default_fields = [] 63101e04c3fSmrg for field in self.group.fields: 63201e04c3fSmrg if not isinstance(field, Field): 63301e04c3fSmrg continue 63401e04c3fSmrg if field.default is None: 63501e04c3fSmrg continue 6367ec681f3Smrg 6377ec681f3Smrg if field.is_builtin_type(): 6387ec681f3Smrg default_fields.append(" .%-35s = %6d" % (field.name, field.default)) 6397ec681f3Smrg else: 6407ec681f3Smrg # Default values should not apply to structures 6417ec681f3Smrg assert field.is_enum_type() 6427ec681f3Smrg default_fields.append(" .%-35s = (enum %s) %6d" % (field.name, self.gen_prefix(safe_name(field.type)), field.default)) 64301e04c3fSmrg 64401e04c3fSmrg if default_fields: 64501e04c3fSmrg print('#define %-40s\\' % (self.gen_prefix(name + '_header'))) 64601e04c3fSmrg print(", \\\n".join(default_fields)) 64701e04c3fSmrg print('') 64801e04c3fSmrg 64901e04c3fSmrg self.emit_template_struct(self.instruction, self.group) 65001e04c3fSmrg 65101e04c3fSmrg self.emit_pack_function(self.instruction, self.group) 65201e04c3fSmrg 65301e04c3fSmrg def emit_register(self): 65401e04c3fSmrg name = self.register 65501e04c3fSmrg if not self.reg_num is None: 65601e04c3fSmrg print('#define %-33s 0x%04x' % 65701e04c3fSmrg (self.gen_prefix(name + "_num"), self.reg_num)) 65801e04c3fSmrg 65901e04c3fSmrg if not self.length is None: 66001e04c3fSmrg print('#define %-33s %6d' % 66101e04c3fSmrg (self.gen_prefix(name + "_length"), self.length)) 66201e04c3fSmrg 66301e04c3fSmrg self.emit_template_struct(self.register, self.group) 66401e04c3fSmrg self.emit_pack_function(self.register, self.group) 66501e04c3fSmrg 66601e04c3fSmrg def emit_struct(self): 66701e04c3fSmrg name = self.struct 66801e04c3fSmrg if not self.length is None: 66901e04c3fSmrg print('#define %-33s %6d' % 67001e04c3fSmrg (self.gen_prefix(name + "_length"), self.length)) 67101e04c3fSmrg 67201e04c3fSmrg self.emit_template_struct(self.struct, self.group) 67301e04c3fSmrg self.emit_pack_function(self.struct, self.group) 67401e04c3fSmrg 67501e04c3fSmrg def emit_enum(self): 67601e04c3fSmrg print('enum %s {' % self.gen_prefix(self.enum)) 67701e04c3fSmrg for value in self.values: 67801e04c3fSmrg if self.prefix: 67901e04c3fSmrg name = self.prefix + "_" + value.name 68001e04c3fSmrg else: 68101e04c3fSmrg name = value.name 68201e04c3fSmrg print(' %-36s = %6d,' % (name.upper(), value.value)) 68301e04c3fSmrg print('};\n') 68401e04c3fSmrg 68501e04c3fSmrg def parse(self, filename): 68601e04c3fSmrg file = open(filename, "rb") 68701e04c3fSmrg self.parser.ParseFile(file) 68801e04c3fSmrg file.close() 68901e04c3fSmrg 6909f464c52Smayadef parse_args(): 6919f464c52Smaya p = argparse.ArgumentParser() 6929f464c52Smaya p.add_argument('xml_source', metavar='XML_SOURCE', 6939f464c52Smaya help="Input xml file") 6949f464c52Smaya p.add_argument('--engines', nargs='?', type=str, default='render', 6959f464c52Smaya help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)") 6969f464c52Smaya 6979f464c52Smaya pargs = p.parse_args() 6989f464c52Smaya 6999f464c52Smaya if pargs.engines is None: 7009f464c52Smaya print("No engines specified") 7019f464c52Smaya sys.exit(1) 7029f464c52Smaya 7039f464c52Smaya return pargs 7049f464c52Smaya 7059f464c52Smayadef main(): 7069f464c52Smaya pargs = parse_args() 7079f464c52Smaya 7089f464c52Smaya input_file = pargs.xml_source 7099f464c52Smaya engines = pargs.engines.split(',') 7109f464c52Smaya valid_engines = [ 'render', 'blitter', 'video' ] 7119f464c52Smaya if set(engines) - set(valid_engines): 7129f464c52Smaya print("Invalid engine specified, valid engines are:\n") 7139f464c52Smaya for e in valid_engines: 7149f464c52Smaya print("\t%s" % e) 7159f464c52Smaya sys.exit(1) 71601e04c3fSmrg 7179f464c52Smaya p = Parser() 7189f464c52Smaya p.engines = set(engines) 7199f464c52Smaya p.parse(input_file) 72001e04c3fSmrg 7219f464c52Smayaif __name__ == '__main__': 7229f464c52Smaya main() 723