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