1b8e80941Smrg#encoding=utf-8 2b8e80941Smrg 3b8e80941Smrgfrom __future__ import ( 4b8e80941Smrg absolute_import, division, print_function, unicode_literals 5b8e80941Smrg) 6b8e80941Smrgimport argparse 7b8e80941Smrgimport ast 8b8e80941Smrgimport xml.parsers.expat 9b8e80941Smrgimport re 10b8e80941Smrgimport sys 11b8e80941Smrgimport copy 12b8e80941Smrgimport textwrap 13b8e80941Smrg 14b8e80941Smrglicense = """/* 15b8e80941Smrg * Copyright (C) 2016 Intel Corporation 16b8e80941Smrg * 17b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 18b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 19b8e80941Smrg * to deal in the Software without restriction, including without limitation 20b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 21b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 22b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 23b8e80941Smrg * 24b8e80941Smrg * The above copyright notice and this permission notice (including the next 25b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 26b8e80941Smrg * Software. 27b8e80941Smrg * 28b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 31b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 33b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 34b8e80941Smrg * IN THE SOFTWARE. 35b8e80941Smrg */ 36b8e80941Smrg""" 37b8e80941Smrg 38b8e80941Smrgpack_header = """%(license)s 39b8e80941Smrg 40b8e80941Smrg/* Instructions, enums and structures for %(platform)s. 41b8e80941Smrg * 42b8e80941Smrg * This file has been generated, do not hand edit. 43b8e80941Smrg */ 44b8e80941Smrg 45b8e80941Smrg#ifndef %(guard)s 46b8e80941Smrg#define %(guard)s 47b8e80941Smrg 48b8e80941Smrg#include <stdio.h> 49b8e80941Smrg#include <stdint.h> 50b8e80941Smrg#include <stdbool.h> 51b8e80941Smrg#include <assert.h> 52b8e80941Smrg#include <math.h> 53b8e80941Smrg 54b8e80941Smrg#ifndef __gen_validate_value 55b8e80941Smrg#define __gen_validate_value(x) 56b8e80941Smrg#endif 57b8e80941Smrg 58b8e80941Smrg#ifndef __gen_field_functions 59b8e80941Smrg#define __gen_field_functions 60b8e80941Smrg 61b8e80941Smrg#ifdef NDEBUG 62b8e80941Smrg#define NDEBUG_UNUSED __attribute__((unused)) 63b8e80941Smrg#else 64b8e80941Smrg#define NDEBUG_UNUSED 65b8e80941Smrg#endif 66b8e80941Smrg 67b8e80941Smrgunion __gen_value { 68b8e80941Smrg float f; 69b8e80941Smrg uint32_t dw; 70b8e80941Smrg}; 71b8e80941Smrg 72b8e80941Smrgstatic inline uint64_t 73b8e80941Smrg__gen_mbo(uint32_t start, uint32_t end) 74b8e80941Smrg{ 75b8e80941Smrg return (~0ull >> (64 - (end - start + 1))) << start; 76b8e80941Smrg} 77b8e80941Smrg 78b8e80941Smrgstatic inline uint64_t 79b8e80941Smrg__gen_uint(uint64_t v, uint32_t start, NDEBUG_UNUSED uint32_t end) 80b8e80941Smrg{ 81b8e80941Smrg __gen_validate_value(v); 82b8e80941Smrg 83b8e80941Smrg#ifndef NDEBUG 84b8e80941Smrg const int width = end - start + 1; 85b8e80941Smrg if (width < 64) { 86b8e80941Smrg const uint64_t max = (1ull << width) - 1; 87b8e80941Smrg assert(v <= max); 88b8e80941Smrg } 89b8e80941Smrg#endif 90b8e80941Smrg 91b8e80941Smrg return v << start; 92b8e80941Smrg} 93b8e80941Smrg 94b8e80941Smrgstatic inline uint64_t 95b8e80941Smrg__gen_sint(int64_t v, uint32_t start, uint32_t end) 96b8e80941Smrg{ 97b8e80941Smrg const int width = end - start + 1; 98b8e80941Smrg 99b8e80941Smrg __gen_validate_value(v); 100b8e80941Smrg 101b8e80941Smrg#ifndef NDEBUG 102b8e80941Smrg if (width < 64) { 103b8e80941Smrg const int64_t max = (1ll << (width - 1)) - 1; 104b8e80941Smrg const int64_t min = -(1ll << (width - 1)); 105b8e80941Smrg assert(min <= v && v <= max); 106b8e80941Smrg } 107b8e80941Smrg#endif 108b8e80941Smrg 109b8e80941Smrg const uint64_t mask = ~0ull >> (64 - width); 110b8e80941Smrg 111b8e80941Smrg return (v & mask) << start; 112b8e80941Smrg} 113b8e80941Smrg 114b8e80941Smrgstatic inline uint64_t 115b8e80941Smrg__gen_offset(uint64_t v, NDEBUG_UNUSED uint32_t start, NDEBUG_UNUSED uint32_t end) 116b8e80941Smrg{ 117b8e80941Smrg __gen_validate_value(v); 118b8e80941Smrg#ifndef NDEBUG 119b8e80941Smrg uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; 120b8e80941Smrg 121b8e80941Smrg assert((v & ~mask) == 0); 122b8e80941Smrg#endif 123b8e80941Smrg 124b8e80941Smrg return v; 125b8e80941Smrg} 126b8e80941Smrg 127b8e80941Smrgstatic inline uint32_t 128b8e80941Smrg__gen_float(float v) 129b8e80941Smrg{ 130b8e80941Smrg __gen_validate_value(v); 131b8e80941Smrg return ((union __gen_value) { .f = (v) }).dw; 132b8e80941Smrg} 133b8e80941Smrg 134b8e80941Smrgstatic inline uint64_t 135b8e80941Smrg__gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) 136b8e80941Smrg{ 137b8e80941Smrg __gen_validate_value(v); 138b8e80941Smrg 139b8e80941Smrg const float factor = (1 << fract_bits); 140b8e80941Smrg 141b8e80941Smrg#ifndef NDEBUG 142b8e80941Smrg const float max = ((1 << (end - start)) - 1) / factor; 143b8e80941Smrg const float min = -(1 << (end - start)) / factor; 144b8e80941Smrg assert(min <= v && v <= max); 145b8e80941Smrg#endif 146b8e80941Smrg 147b8e80941Smrg const int64_t int_val = llroundf(v * factor); 148b8e80941Smrg const uint64_t mask = ~0ull >> (64 - (end - start + 1)); 149b8e80941Smrg 150b8e80941Smrg return (int_val & mask) << start; 151b8e80941Smrg} 152b8e80941Smrg 153b8e80941Smrgstatic inline uint64_t 154b8e80941Smrg__gen_ufixed(float v, uint32_t start, NDEBUG_UNUSED uint32_t end, uint32_t fract_bits) 155b8e80941Smrg{ 156b8e80941Smrg __gen_validate_value(v); 157b8e80941Smrg 158b8e80941Smrg const float factor = (1 << fract_bits); 159b8e80941Smrg 160b8e80941Smrg#ifndef NDEBUG 161b8e80941Smrg const float max = ((1 << (end - start + 1)) - 1) / factor; 162b8e80941Smrg const float min = 0.0f; 163b8e80941Smrg assert(min <= v && v <= max); 164b8e80941Smrg#endif 165b8e80941Smrg 166b8e80941Smrg const uint64_t uint_val = llroundf(v * factor); 167b8e80941Smrg 168b8e80941Smrg return uint_val << start; 169b8e80941Smrg} 170b8e80941Smrg 171b8e80941Smrg#ifndef __gen_address_type 172b8e80941Smrg#error #define __gen_address_type before including this file 173b8e80941Smrg#endif 174b8e80941Smrg 175b8e80941Smrg#ifndef __gen_user_data 176b8e80941Smrg#error #define __gen_combine_address before including this file 177b8e80941Smrg#endif 178b8e80941Smrg 179b8e80941Smrg#undef NDEBUG_UNUSED 180b8e80941Smrg 181b8e80941Smrg#endif 182b8e80941Smrg 183b8e80941Smrg""" 184b8e80941Smrg 185b8e80941Smrgdef to_alphanum(name): 186b8e80941Smrg substitutions = { 187b8e80941Smrg ' ': '', 188b8e80941Smrg '/': '', 189b8e80941Smrg '[': '', 190b8e80941Smrg ']': '', 191b8e80941Smrg '(': '', 192b8e80941Smrg ')': '', 193b8e80941Smrg '-': '', 194b8e80941Smrg ':': '', 195b8e80941Smrg '.': '', 196b8e80941Smrg ',': '', 197b8e80941Smrg '=': '', 198b8e80941Smrg '>': '', 199b8e80941Smrg '#': '', 200b8e80941Smrg 'α': 'alpha', 201b8e80941Smrg '&': '', 202b8e80941Smrg '*': '', 203b8e80941Smrg '"': '', 204b8e80941Smrg '+': '', 205b8e80941Smrg '\'': '', 206b8e80941Smrg } 207b8e80941Smrg 208b8e80941Smrg for i, j in substitutions.items(): 209b8e80941Smrg name = name.replace(i, j) 210b8e80941Smrg 211b8e80941Smrg return name 212b8e80941Smrg 213b8e80941Smrgdef safe_name(name): 214b8e80941Smrg name = to_alphanum(name) 215b8e80941Smrg if not name[0].isalpha(): 216b8e80941Smrg name = '_' + name 217b8e80941Smrg 218b8e80941Smrg return name 219b8e80941Smrg 220b8e80941Smrgdef num_from_str(num_str): 221b8e80941Smrg if num_str.lower().startswith('0x'): 222b8e80941Smrg return int(num_str, base=16) 223b8e80941Smrg 224b8e80941Smrg assert not num_str.startswith('0'), 'octals numbers not allowed' 225b8e80941Smrg return int(num_str) 226b8e80941Smrg 227b8e80941Smrgclass Field(object): 228b8e80941Smrg ufixed_pattern = re.compile(r"u(\d+)\.(\d+)") 229b8e80941Smrg sfixed_pattern = re.compile(r"s(\d+)\.(\d+)") 230b8e80941Smrg 231b8e80941Smrg def __init__(self, parser, attrs): 232b8e80941Smrg self.parser = parser 233b8e80941Smrg if "name" in attrs: 234b8e80941Smrg self.name = safe_name(attrs["name"]) 235b8e80941Smrg self.start = int(attrs["start"]) 236b8e80941Smrg self.end = int(attrs["end"]) 237b8e80941Smrg self.type = attrs["type"] 238b8e80941Smrg 239b8e80941Smrg assert self.start <= self.end, \ 240b8e80941Smrg 'field {} has end ({}) < start ({})'.format(self.name, self.end, 241b8e80941Smrg self.start) 242b8e80941Smrg if self.type == 'bool': 243b8e80941Smrg assert self.end == self.start, \ 244b8e80941Smrg 'bool field ({}) is too wide'.format(self.name) 245b8e80941Smrg 246b8e80941Smrg if "prefix" in attrs: 247b8e80941Smrg self.prefix = attrs["prefix"] 248b8e80941Smrg else: 249b8e80941Smrg self.prefix = None 250b8e80941Smrg 251b8e80941Smrg if "default" in attrs: 252b8e80941Smrg # Base 0 recognizes 0x, 0o, 0b prefixes in addition to decimal ints. 253b8e80941Smrg self.default = int(attrs["default"], base=0) 254b8e80941Smrg else: 255b8e80941Smrg self.default = None 256b8e80941Smrg 257b8e80941Smrg ufixed_match = Field.ufixed_pattern.match(self.type) 258b8e80941Smrg if ufixed_match: 259b8e80941Smrg self.type = 'ufixed' 260b8e80941Smrg self.fractional_size = int(ufixed_match.group(2)) 261b8e80941Smrg 262b8e80941Smrg sfixed_match = Field.sfixed_pattern.match(self.type) 263b8e80941Smrg if sfixed_match: 264b8e80941Smrg self.type = 'sfixed' 265b8e80941Smrg self.fractional_size = int(sfixed_match.group(2)) 266b8e80941Smrg 267b8e80941Smrg def is_builtin_type(self): 268b8e80941Smrg builtins = [ 'address', 'bool', 'float', 'ufixed', 269b8e80941Smrg 'offset', 'sfixed', 'offset', 'int', 'uint', 'mbo' ] 270b8e80941Smrg return self.type in builtins 271b8e80941Smrg 272b8e80941Smrg def is_struct_type(self): 273b8e80941Smrg return self.type in self.parser.structs 274b8e80941Smrg 275b8e80941Smrg def is_enum_type(self): 276b8e80941Smrg return self.type in self.parser.enums 277b8e80941Smrg 278b8e80941Smrg def emit_template_struct(self, dim): 279b8e80941Smrg if self.type == 'address': 280b8e80941Smrg type = '__gen_address_type' 281b8e80941Smrg elif self.type == 'bool': 282b8e80941Smrg type = 'bool' 283b8e80941Smrg elif self.type == 'float': 284b8e80941Smrg type = 'float' 285b8e80941Smrg elif self.type == 'ufixed': 286b8e80941Smrg type = 'float' 287b8e80941Smrg elif self.type == 'sfixed': 288b8e80941Smrg type = 'float' 289b8e80941Smrg elif self.type == 'uint' and self.end - self.start > 32: 290b8e80941Smrg type = 'uint64_t' 291b8e80941Smrg elif self.type == 'offset': 292b8e80941Smrg type = 'uint64_t' 293b8e80941Smrg elif self.type == 'int': 294b8e80941Smrg type = 'int32_t' 295b8e80941Smrg elif self.type == 'uint': 296b8e80941Smrg type = 'uint32_t' 297b8e80941Smrg elif self.is_struct_type(): 298b8e80941Smrg type = 'struct ' + self.parser.gen_prefix(safe_name(self.type)) 299b8e80941Smrg elif self.is_enum_type(): 300b8e80941Smrg type = 'enum ' + self.parser.gen_prefix(safe_name(self.type)) 301b8e80941Smrg elif self.type == 'mbo': 302b8e80941Smrg return 303b8e80941Smrg else: 304b8e80941Smrg print("#error unhandled type: %s" % self.type) 305b8e80941Smrg return 306b8e80941Smrg 307b8e80941Smrg print(" %-36s %s%s;" % (type, self.name, dim)) 308b8e80941Smrg 309b8e80941Smrg prefix = "" 310b8e80941Smrg if self.values and self.default is None: 311b8e80941Smrg if self.prefix: 312b8e80941Smrg prefix = self.prefix + "_" 313b8e80941Smrg 314b8e80941Smrg for value in self.values: 315b8e80941Smrg print("#define %-40s %d" % (prefix + value.name, value.value)) 316b8e80941Smrg 317b8e80941Smrgclass Group(object): 318b8e80941Smrg def __init__(self, parser, parent, start, count, size): 319b8e80941Smrg self.parser = parser 320b8e80941Smrg self.parent = parent 321b8e80941Smrg self.start = start 322b8e80941Smrg self.count = count 323b8e80941Smrg self.size = size 324b8e80941Smrg self.fields = [] 325b8e80941Smrg 326b8e80941Smrg def emit_template_struct(self, dim): 327b8e80941Smrg if self.count == 0: 328b8e80941Smrg print(" /* variable length fields follow */") 329b8e80941Smrg else: 330b8e80941Smrg if self.count > 1: 331b8e80941Smrg dim = "%s[%d]" % (dim, self.count) 332b8e80941Smrg 333b8e80941Smrg for field in self.fields: 334b8e80941Smrg field.emit_template_struct(dim) 335b8e80941Smrg 336b8e80941Smrg class DWord: 337b8e80941Smrg def __init__(self): 338b8e80941Smrg self.size = 32 339b8e80941Smrg self.fields = [] 340b8e80941Smrg self.address = None 341b8e80941Smrg 342b8e80941Smrg def collect_dwords(self, dwords, start, dim): 343b8e80941Smrg for field in self.fields: 344b8e80941Smrg if isinstance(field, Group): 345b8e80941Smrg if field.count == 1: 346b8e80941Smrg field.collect_dwords(dwords, start + field.start, dim) 347b8e80941Smrg else: 348b8e80941Smrg for i in range(field.count): 349b8e80941Smrg field.collect_dwords(dwords, 350b8e80941Smrg start + field.start + i * field.size, 351b8e80941Smrg "%s[%d]" % (dim, i)) 352b8e80941Smrg continue 353b8e80941Smrg 354b8e80941Smrg index = (start + field.start) // 32 355b8e80941Smrg if not index in dwords: 356b8e80941Smrg dwords[index] = self.DWord() 357b8e80941Smrg 358b8e80941Smrg clone = copy.copy(field) 359b8e80941Smrg clone.start = clone.start + start 360b8e80941Smrg clone.end = clone.end + start 361b8e80941Smrg clone.dim = dim 362b8e80941Smrg dwords[index].fields.append(clone) 363b8e80941Smrg 364b8e80941Smrg if field.type == "address": 365b8e80941Smrg # assert dwords[index].address == None 366b8e80941Smrg dwords[index].address = field 367b8e80941Smrg 368b8e80941Smrg # Coalesce all the dwords covered by this field. The two cases we 369b8e80941Smrg # handle are where multiple fields are in a 64 bit word (typically 370b8e80941Smrg # and address and a few bits) or where a single struct field 371b8e80941Smrg # completely covers multiple dwords. 372b8e80941Smrg while index < (start + field.end) // 32: 373b8e80941Smrg if index + 1 in dwords and not dwords[index] == dwords[index + 1]: 374b8e80941Smrg dwords[index].fields.extend(dwords[index + 1].fields) 375b8e80941Smrg dwords[index].size = 64 376b8e80941Smrg dwords[index + 1] = dwords[index] 377b8e80941Smrg index = index + 1 378b8e80941Smrg 379b8e80941Smrg def collect_dwords_and_length(self): 380b8e80941Smrg dwords = {} 381b8e80941Smrg self.collect_dwords(dwords, 0, "") 382b8e80941Smrg 383b8e80941Smrg # Determine number of dwords in this group. If we have a size, use 384b8e80941Smrg # that, since that'll account for MBZ dwords at the end of a group 385b8e80941Smrg # (like dword 8 on BDW+ 3DSTATE_HS). Otherwise, use the largest dword 386b8e80941Smrg # index we've seen plus one. 387b8e80941Smrg if self.size > 0: 388b8e80941Smrg length = self.size // 32 389b8e80941Smrg elif dwords: 390b8e80941Smrg length = max(dwords.keys()) + 1 391b8e80941Smrg else: 392b8e80941Smrg length = 0 393b8e80941Smrg 394b8e80941Smrg return (dwords, length) 395b8e80941Smrg 396b8e80941Smrg def emit_pack_function(self, dwords, length): 397b8e80941Smrg for index in range(length): 398b8e80941Smrg # Handle MBZ dwords 399b8e80941Smrg if not index in dwords: 400b8e80941Smrg print("") 401b8e80941Smrg print(" dw[%d] = 0;" % index) 402b8e80941Smrg continue 403b8e80941Smrg 404b8e80941Smrg # For 64 bit dwords, we aliased the two dword entries in the dword 405b8e80941Smrg # dict it occupies. Now that we're emitting the pack function, 406b8e80941Smrg # skip the duplicate entries. 407b8e80941Smrg dw = dwords[index] 408b8e80941Smrg if index > 0 and index - 1 in dwords and dw == dwords[index - 1]: 409b8e80941Smrg continue 410b8e80941Smrg 411b8e80941Smrg # Special case: only one field and it's a struct at the beginning 412b8e80941Smrg # of the dword. In this case we pack directly into the 413b8e80941Smrg # destination. This is the only way we handle embedded structs 414b8e80941Smrg # larger than 32 bits. 415b8e80941Smrg if len(dw.fields) == 1: 416b8e80941Smrg field = dw.fields[0] 417b8e80941Smrg name = field.name + field.dim 418b8e80941Smrg if field.is_struct_type() and field.start % 32 == 0: 419b8e80941Smrg print("") 420b8e80941Smrg print(" %s_pack(data, &dw[%d], &values->%s);" % 421b8e80941Smrg (self.parser.gen_prefix(safe_name(field.type)), index, name)) 422b8e80941Smrg continue 423b8e80941Smrg 424b8e80941Smrg # Pack any fields of struct type first so we have integer values 425b8e80941Smrg # to the dword for those fields. 426b8e80941Smrg field_index = 0 427b8e80941Smrg for field in dw.fields: 428b8e80941Smrg if isinstance(field, Field) and field.is_struct_type(): 429b8e80941Smrg name = field.name + field.dim 430b8e80941Smrg print("") 431b8e80941Smrg print(" uint32_t v%d_%d;" % (index, field_index)) 432b8e80941Smrg print(" %s_pack(data, &v%d_%d, &values->%s);" % 433b8e80941Smrg (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name)) 434b8e80941Smrg field_index = field_index + 1 435b8e80941Smrg 436b8e80941Smrg print("") 437b8e80941Smrg dword_start = index * 32 438b8e80941Smrg if dw.address == None: 439b8e80941Smrg address_count = 0 440b8e80941Smrg else: 441b8e80941Smrg address_count = 1 442b8e80941Smrg 443b8e80941Smrg if dw.size == 32 and dw.address == None: 444b8e80941Smrg v = None 445b8e80941Smrg print(" dw[%d] =" % index) 446b8e80941Smrg elif len(dw.fields) > address_count: 447b8e80941Smrg v = "v%d" % index 448b8e80941Smrg print(" const uint%d_t %s =" % (dw.size, v)) 449b8e80941Smrg else: 450b8e80941Smrg v = "0" 451b8e80941Smrg 452b8e80941Smrg field_index = 0 453b8e80941Smrg non_address_fields = [] 454b8e80941Smrg for field in dw.fields: 455b8e80941Smrg if field.type != "mbo": 456b8e80941Smrg name = field.name + field.dim 457b8e80941Smrg 458b8e80941Smrg if field.type == "mbo": 459b8e80941Smrg non_address_fields.append("__gen_mbo(%d, %d)" % \ 460b8e80941Smrg (field.start - dword_start, field.end - dword_start)) 461b8e80941Smrg elif field.type == "address": 462b8e80941Smrg pass 463b8e80941Smrg elif field.type == "uint": 464b8e80941Smrg non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ 465b8e80941Smrg (name, field.start - dword_start, field.end - dword_start)) 466b8e80941Smrg elif field.is_enum_type(): 467b8e80941Smrg non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ 468b8e80941Smrg (name, field.start - dword_start, field.end - dword_start)) 469b8e80941Smrg elif field.type == "int": 470b8e80941Smrg non_address_fields.append("__gen_sint(values->%s, %d, %d)" % \ 471b8e80941Smrg (name, field.start - dword_start, field.end - dword_start)) 472b8e80941Smrg elif field.type == "bool": 473b8e80941Smrg non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ 474b8e80941Smrg (name, field.start - dword_start, field.end - dword_start)) 475b8e80941Smrg elif field.type == "float": 476b8e80941Smrg non_address_fields.append("__gen_float(values->%s)" % name) 477b8e80941Smrg elif field.type == "offset": 478b8e80941Smrg non_address_fields.append("__gen_offset(values->%s, %d, %d)" % \ 479b8e80941Smrg (name, field.start - dword_start, field.end - dword_start)) 480b8e80941Smrg elif field.type == 'ufixed': 481b8e80941Smrg non_address_fields.append("__gen_ufixed(values->%s, %d, %d, %d)" % \ 482b8e80941Smrg (name, field.start - dword_start, field.end - dword_start, field.fractional_size)) 483b8e80941Smrg elif field.type == 'sfixed': 484b8e80941Smrg non_address_fields.append("__gen_sfixed(values->%s, %d, %d, %d)" % \ 485b8e80941Smrg (name, field.start - dword_start, field.end - dword_start, field.fractional_size)) 486b8e80941Smrg elif field.is_struct_type(): 487b8e80941Smrg non_address_fields.append("__gen_uint(v%d_%d, %d, %d)" % \ 488b8e80941Smrg (index, field_index, field.start - dword_start, field.end - dword_start)) 489b8e80941Smrg field_index = field_index + 1 490b8e80941Smrg else: 491b8e80941Smrg non_address_fields.append("/* unhandled field %s, type %s */\n" % \ 492b8e80941Smrg (name, field.type)) 493b8e80941Smrg 494b8e80941Smrg if non_address_fields: 495b8e80941Smrg print(" |\n".join(" " + f for f in non_address_fields) + ";") 496b8e80941Smrg 497b8e80941Smrg if dw.size == 32: 498b8e80941Smrg if dw.address: 499b8e80941Smrg print(" dw[%d] = __gen_combine_address(data, &dw[%d], values->%s, %s);" % (index, index, dw.address.name + field.dim, v)) 500b8e80941Smrg continue 501b8e80941Smrg 502b8e80941Smrg if dw.address: 503b8e80941Smrg v_address = "v%d_address" % index 504b8e80941Smrg print(" const uint64_t %s =\n __gen_combine_address(data, &dw[%d], values->%s, %s);" % 505b8e80941Smrg (v_address, index, dw.address.name + field.dim, v)) 506b8e80941Smrg if len(dw.fields) > address_count: 507b8e80941Smrg print(" dw[%d] = %s;" % (index, v_address)) 508b8e80941Smrg print(" dw[%d] = (%s >> 32) | (%s >> 32);" % (index + 1, v_address, v)) 509b8e80941Smrg continue 510b8e80941Smrg else: 511b8e80941Smrg v = v_address 512b8e80941Smrg print(" dw[%d] = %s;" % (index, v)) 513b8e80941Smrg print(" dw[%d] = %s >> 32;" % (index + 1, v)) 514b8e80941Smrg 515b8e80941Smrgclass Value(object): 516b8e80941Smrg def __init__(self, attrs): 517b8e80941Smrg self.name = safe_name(attrs["name"]) 518b8e80941Smrg self.value = ast.literal_eval(attrs["value"]) 519b8e80941Smrg 520b8e80941Smrgclass Parser(object): 521b8e80941Smrg def __init__(self): 522b8e80941Smrg self.parser = xml.parsers.expat.ParserCreate() 523b8e80941Smrg self.parser.StartElementHandler = self.start_element 524b8e80941Smrg self.parser.EndElementHandler = self.end_element 525b8e80941Smrg 526b8e80941Smrg self.instruction = None 527b8e80941Smrg self.structs = {} 528b8e80941Smrg # Set of enum names we've seen. 529b8e80941Smrg self.enums = set() 530b8e80941Smrg self.registers = {} 531b8e80941Smrg 532b8e80941Smrg def gen_prefix(self, name): 533b8e80941Smrg if name[0] == "_": 534b8e80941Smrg return 'GEN%s%s' % (self.gen, name) 535b8e80941Smrg return 'GEN%s_%s' % (self.gen, name) 536b8e80941Smrg 537b8e80941Smrg def gen_guard(self): 538b8e80941Smrg return self.gen_prefix("PACK_H") 539b8e80941Smrg 540b8e80941Smrg def start_element(self, name, attrs): 541b8e80941Smrg if name == "genxml": 542b8e80941Smrg self.platform = attrs["name"] 543b8e80941Smrg self.gen = attrs["gen"].replace('.', '') 544b8e80941Smrg print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()}) 545b8e80941Smrg elif name in ("instruction", "struct", "register"): 546b8e80941Smrg if name == "instruction": 547b8e80941Smrg self.instruction = safe_name(attrs["name"]) 548b8e80941Smrg self.length_bias = int(attrs["bias"]) 549b8e80941Smrg if "engine" in attrs: 550b8e80941Smrg self.instruction_engines = set(attrs["engine"].split('|')) 551b8e80941Smrg else: 552b8e80941Smrg # When an instruction doesn't have the engine specified, 553b8e80941Smrg # it is considered to be for all engines, so 'None' is used 554b8e80941Smrg # to signify that the instruction belongs to all engines. 555b8e80941Smrg self.instruction_engines = None 556b8e80941Smrg elif name == "struct": 557b8e80941Smrg self.struct = safe_name(attrs["name"]) 558b8e80941Smrg self.structs[attrs["name"]] = 1 559b8e80941Smrg elif name == "register": 560b8e80941Smrg self.register = safe_name(attrs["name"]) 561b8e80941Smrg self.reg_num = num_from_str(attrs["num"]) 562b8e80941Smrg self.registers[attrs["name"]] = 1 563b8e80941Smrg if "length" in attrs: 564b8e80941Smrg self.length = int(attrs["length"]) 565b8e80941Smrg size = self.length * 32 566b8e80941Smrg else: 567b8e80941Smrg self.length = None 568b8e80941Smrg size = 0 569b8e80941Smrg self.group = Group(self, None, 0, 1, size) 570b8e80941Smrg 571b8e80941Smrg elif name == "group": 572b8e80941Smrg group = Group(self, self.group, 573b8e80941Smrg int(attrs["start"]), int(attrs["count"]), int(attrs["size"])) 574b8e80941Smrg self.group.fields.append(group) 575b8e80941Smrg self.group = group 576b8e80941Smrg elif name == "field": 577b8e80941Smrg self.group.fields.append(Field(self, attrs)) 578b8e80941Smrg self.values = [] 579b8e80941Smrg elif name == "enum": 580b8e80941Smrg self.values = [] 581b8e80941Smrg self.enum = safe_name(attrs["name"]) 582b8e80941Smrg self.enums.add(attrs["name"]) 583b8e80941Smrg if "prefix" in attrs: 584b8e80941Smrg self.prefix = safe_name(attrs["prefix"]) 585b8e80941Smrg else: 586b8e80941Smrg self.prefix= None 587b8e80941Smrg elif name == "value": 588b8e80941Smrg self.values.append(Value(attrs)) 589b8e80941Smrg 590b8e80941Smrg def end_element(self, name): 591b8e80941Smrg if name == "instruction": 592b8e80941Smrg self.emit_instruction() 593b8e80941Smrg self.instruction = None 594b8e80941Smrg self.group = None 595b8e80941Smrg elif name == "struct": 596b8e80941Smrg self.emit_struct() 597b8e80941Smrg self.struct = None 598b8e80941Smrg self.group = None 599b8e80941Smrg elif name == "register": 600b8e80941Smrg self.emit_register() 601b8e80941Smrg self.register = None 602b8e80941Smrg self.reg_num = None 603b8e80941Smrg self.group = None 604b8e80941Smrg elif name == "group": 605b8e80941Smrg self.group = self.group.parent 606b8e80941Smrg elif name == "field": 607b8e80941Smrg self.group.fields[-1].values = self.values 608b8e80941Smrg elif name == "enum": 609b8e80941Smrg self.emit_enum() 610b8e80941Smrg self.enum = None 611b8e80941Smrg elif name == "genxml": 612b8e80941Smrg print('#endif /* %s */' % self.gen_guard()) 613b8e80941Smrg 614b8e80941Smrg def emit_template_struct(self, name, group): 615b8e80941Smrg print("struct %s {" % self.gen_prefix(name)) 616b8e80941Smrg group.emit_template_struct("") 617b8e80941Smrg print("};\n") 618b8e80941Smrg 619b8e80941Smrg def emit_pack_function(self, name, group): 620b8e80941Smrg name = self.gen_prefix(name) 621b8e80941Smrg print(textwrap.dedent("""\ 622b8e80941Smrg static inline void 623b8e80941Smrg %s_pack(__attribute__((unused)) __gen_user_data *data, 624b8e80941Smrg %s__attribute__((unused)) void * restrict dst, 625b8e80941Smrg %s__attribute__((unused)) const struct %s * restrict values) 626b8e80941Smrg {""") % (name, ' ' * len(name), ' ' * len(name), name)) 627b8e80941Smrg 628b8e80941Smrg (dwords, length) = group.collect_dwords_and_length() 629b8e80941Smrg if length: 630b8e80941Smrg # Cast dst to make header C++ friendly 631b8e80941Smrg print(" uint32_t * restrict dw = (uint32_t * restrict) dst;") 632b8e80941Smrg 633b8e80941Smrg group.emit_pack_function(dwords, length) 634b8e80941Smrg 635b8e80941Smrg print("}\n") 636b8e80941Smrg 637b8e80941Smrg def emit_instruction(self): 638b8e80941Smrg name = self.instruction 639b8e80941Smrg if self.instruction_engines and not self.instruction_engines & self.engines: 640b8e80941Smrg return 641b8e80941Smrg 642b8e80941Smrg if not self.length is None: 643b8e80941Smrg print('#define %-33s %6d' % 644b8e80941Smrg (self.gen_prefix(name + "_length"), self.length)) 645b8e80941Smrg print('#define %-33s %6d' % 646b8e80941Smrg (self.gen_prefix(name + "_length_bias"), self.length_bias)) 647b8e80941Smrg 648b8e80941Smrg default_fields = [] 649b8e80941Smrg for field in self.group.fields: 650b8e80941Smrg if not isinstance(field, Field): 651b8e80941Smrg continue 652b8e80941Smrg if field.default is None: 653b8e80941Smrg continue 654b8e80941Smrg default_fields.append(" .%-35s = %6d" % (field.name, field.default)) 655b8e80941Smrg 656b8e80941Smrg if default_fields: 657b8e80941Smrg print('#define %-40s\\' % (self.gen_prefix(name + '_header'))) 658b8e80941Smrg print(", \\\n".join(default_fields)) 659b8e80941Smrg print('') 660b8e80941Smrg 661b8e80941Smrg self.emit_template_struct(self.instruction, self.group) 662b8e80941Smrg 663b8e80941Smrg self.emit_pack_function(self.instruction, self.group) 664b8e80941Smrg 665b8e80941Smrg def emit_register(self): 666b8e80941Smrg name = self.register 667b8e80941Smrg if not self.reg_num is None: 668b8e80941Smrg print('#define %-33s 0x%04x' % 669b8e80941Smrg (self.gen_prefix(name + "_num"), self.reg_num)) 670b8e80941Smrg 671b8e80941Smrg if not self.length is None: 672b8e80941Smrg print('#define %-33s %6d' % 673b8e80941Smrg (self.gen_prefix(name + "_length"), self.length)) 674b8e80941Smrg 675b8e80941Smrg self.emit_template_struct(self.register, self.group) 676b8e80941Smrg self.emit_pack_function(self.register, self.group) 677b8e80941Smrg 678b8e80941Smrg def emit_struct(self): 679b8e80941Smrg name = self.struct 680b8e80941Smrg if not self.length is None: 681b8e80941Smrg print('#define %-33s %6d' % 682b8e80941Smrg (self.gen_prefix(name + "_length"), self.length)) 683b8e80941Smrg 684b8e80941Smrg self.emit_template_struct(self.struct, self.group) 685b8e80941Smrg self.emit_pack_function(self.struct, self.group) 686b8e80941Smrg 687b8e80941Smrg def emit_enum(self): 688b8e80941Smrg print('enum %s {' % self.gen_prefix(self.enum)) 689b8e80941Smrg for value in self.values: 690b8e80941Smrg if self.prefix: 691b8e80941Smrg name = self.prefix + "_" + value.name 692b8e80941Smrg else: 693b8e80941Smrg name = value.name 694b8e80941Smrg print(' %-36s = %6d,' % (name.upper(), value.value)) 695b8e80941Smrg print('};\n') 696b8e80941Smrg 697b8e80941Smrg def parse(self, filename): 698b8e80941Smrg file = open(filename, "rb") 699b8e80941Smrg self.parser.ParseFile(file) 700b8e80941Smrg file.close() 701b8e80941Smrg 702b8e80941Smrgdef parse_args(): 703b8e80941Smrg p = argparse.ArgumentParser() 704b8e80941Smrg p.add_argument('xml_source', metavar='XML_SOURCE', 705b8e80941Smrg help="Input xml file") 706b8e80941Smrg p.add_argument('--engines', nargs='?', type=str, default='render', 707b8e80941Smrg help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)") 708b8e80941Smrg 709b8e80941Smrg pargs = p.parse_args() 710b8e80941Smrg 711b8e80941Smrg if pargs.engines is None: 712b8e80941Smrg print("No engines specified") 713b8e80941Smrg sys.exit(1) 714b8e80941Smrg 715b8e80941Smrg return pargs 716b8e80941Smrg 717b8e80941Smrgdef main(): 718b8e80941Smrg pargs = parse_args() 719b8e80941Smrg 720b8e80941Smrg input_file = pargs.xml_source 721b8e80941Smrg engines = pargs.engines.split(',') 722b8e80941Smrg valid_engines = [ 'render', 'blitter', 'video' ] 723b8e80941Smrg if set(engines) - set(valid_engines): 724b8e80941Smrg print("Invalid engine specified, valid engines are:\n") 725b8e80941Smrg for e in valid_engines: 726b8e80941Smrg print("\t%s" % e) 727b8e80941Smrg sys.exit(1) 728b8e80941Smrg 729b8e80941Smrg p = Parser() 730b8e80941Smrg p.engines = set(engines) 731b8e80941Smrg p.parse(input_file) 732b8e80941Smrg 733b8e80941Smrgif __name__ == '__main__': 734b8e80941Smrg main() 735