xref: /aosp_15_r20/external/mesa3d/src/asahi/genxml/gen_pack.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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