xref: /aosp_15_r20/external/mesa3d/src/panfrost/compiler/bi_builder.h.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1# Copyright (C) 2020 Collabora, Ltd.
2#
3# Permission is hereby granted, free of charge, to any person obtaining a
4# copy of this software and associated documentation files (the "Software"),
5# to deal in the Software without restriction, including without limitation
6# the rights to use, copy, modify, merge, publish, distribute, sublicense,
7# and/or sell copies of the Software, and to permit persons to whom the
8# Software is furnished to do so, subject to the following conditions:
9#
10# The above copyright notice and this permission notice (including the next
11# paragraph) shall be included in all copies or substantial portions of the
12# Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20# IN THE SOFTWARE.
21
22SKIP = set(["lane", "lane_dest", "lanes", "lanes", "replicate", "swz", "widen",
23    "swap", "neg", "abs", "not", "sign", "extend", "divzero", "clamp", "sem",
24    "not_result", "skip", "round", "ftz"])
25
26TEMPLATE = """
27#ifndef _BI_BUILDER_H_
28#define _BI_BUILDER_H_
29
30#include "compiler.h"
31
32<%
33# For <32-bit loads/stores, the default extend `none` with a natural sized
34# input is not encodeable! To avoid a footgun, swap the default to `zext` which
35# will work as expected
36ZEXT_DEFAULT = set(["LOAD.i8", "LOAD.i16", "LOAD.i24", "STORE.i8", "STORE.i16", "STORE.i24"])
37
38def nirtypes(opcode):
39    split = opcode.split('.', 1)
40    if len(split) < 2:
41        split = opcode.split('_')
42
43    if len(split) <= 1:
44        return None
45
46    assert len(split) > 1
47
48    type = split[1]
49    if type[0] == 'v':
50        type = type[2:]
51
52    if type[0] == 'f':
53        return ['nir_type_float']
54    elif type[0] == 's':
55        return ['nir_type_int']
56    elif type[0] == 'u':
57        return ['nir_type_uint']
58    elif type[0] == 'i':
59        return ['nir_type_uint', 'nir_type_int']
60    else:
61        return None
62
63def condition(opcode, typecheck, sizecheck):
64    cond = ''
65    if typecheck == True:
66        cond += '('
67        types = nirtypes(opcode)
68        assert types != None
69        for T in types:
70            cond += "{}type == {}".format(' || ' if cond[-1] != '(' else '', T)
71        cond += ')'
72
73    if sizecheck == True:
74        cond += "{}bitsize == {}".format(' && ' if cond != '' else '', typesize(opcode))
75
76    cmpf_mods = ops[opcode]["modifiers"]["cmpf"] if "cmpf" in ops[opcode]["modifiers"] else None
77    if "cmpf" in ops[opcode]["modifiers"]:
78        cond += "{}(".format(' && ' if cond != '' else '')
79        for cmpf in ops[opcode]["modifiers"]["cmpf"]:
80            if cmpf != 'reserved':
81                cond += "{}cmpf == BI_CMPF_{}".format(' || ' if cond[-1] != '(' else '', cmpf.upper())
82        cond += ')'
83
84    return 'true' if cond == '' else cond
85
86def to_suffix(op):
87    return "_to" if op["dests"] > 0 else ""
88
89%>
90
91% for opcode in ops:
92static inline
93bi_instr * bi_${opcode.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${signature(ops[opcode], modifiers)})
94{
95<%
96    op = ops[opcode]
97    nr_dests = "nr_dests" if op["variable_dests"] else op["dests"]
98    nr_srcs = "nr_srcs" if op["variable_srcs"] else src_count(op)
99%>
100    size_t size = sizeof(bi_instr) + sizeof(bi_index) * (${nr_dests} + ${nr_srcs});
101    bi_instr *I = (bi_instr *) rzalloc_size(b->shader, size);
102
103    I->op = BI_OPCODE_${opcode.replace('.', '_').upper()};
104    I->nr_dests = ${nr_dests};
105    I->nr_srcs = ${nr_srcs};
106    I->dest = (bi_index *) (&I[1]);
107    I->src = I->dest + ${nr_dests};
108
109% if not op["variable_dests"]:
110% for dest in range(op["dests"]):
111    I->dest[${dest}] = dest${dest};
112% endfor
113%endif
114
115% if not op["variable_srcs"]:
116% for src in range(src_count(op)):
117    I->src[${src}] = src${src};
118% endfor
119% endif
120
121% for mod in ops[opcode]["modifiers"]:
122% if not should_skip(mod, opcode):
123    I->${mod} = ${mod};
124% endif
125% endfor
126% if ops[opcode]["rtz"]:
127    I->round = BI_ROUND_RTZ;
128% endif
129% for imm in ops[opcode]["immediates"]:
130    I->${imm} = ${imm};
131% endfor
132% if opcode in ZEXT_DEFAULT:
133    I->extend = BI_EXTEND_ZEXT;
134% endif
135    bi_builder_insert(&b->cursor, I);
136    return I;
137}
138
139% if ops[opcode]["dests"] == 1 and not ops[opcode]["variable_dests"]:
140static inline
141bi_index bi_${opcode.replace('.', '_').lower()}(${signature(ops[opcode], modifiers, no_dests=True)})
142{
143    return (bi_${opcode.replace('.', '_').lower()}_to(${arguments(ops[opcode])}))->dest[0];
144}
145
146%endif
147<%
148    common_op = opcode.split('.')[0]
149    variants = [a for a in ops.keys() if a.split('.')[0] == common_op]
150    signatures = [signature(ops[op], modifiers, no_dests=True) for op in variants]
151    homogenous = all([sig == signatures[0] for sig in signatures])
152    types = [nirtypes(x) for x in variants]
153    typeful = False
154    for t in types:
155        if t != types[0]:
156            typeful = True
157
158    sizes = [typesize(x) for x in variants]
159    sized = False
160    for size in sizes:
161        if size != sizes[0]:
162            sized = True
163
164    last = opcode == variants[-1]
165%>
166% if homogenous and len(variants) > 1 and last:
167% for (suffix, temp, dests, ret) in (('_to', False, 1, 'instr *'), ('', True, 0, 'index')):
168% if not temp or ops[opcode]["dests"] > 0:
169static inline
170bi_${ret} bi_${common_op.replace('.', '_').lower()}${suffix if ops[opcode]['dests'] > 0 else ''}(${signature(ops[opcode], modifiers, typeful=typeful, sized=sized, no_dests=not dests)})
171{
172% for i, variant in enumerate(variants):
173    ${"{}if ({})".format("else " if i > 0 else "", condition(variant, typeful, sized))}
174        return (bi_${variant.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${arguments(ops[opcode], temp_dest = temp)}))${"->dest[0]" if temp else ""};
175% endfor
176    else
177        unreachable("Invalid parameters for ${common_op}");
178}
179
180%endif
181%endfor
182%endif
183%endfor
184#endif"""
185
186import sys
187from bifrost_isa import *
188from mako.template import Template
189
190instructions = {}
191for arg in sys.argv[1:]:
192    new_instructions = parse_instructions(arg, include_pseudo = True)
193    instructions.update(new_instructions)
194
195ir_instructions = partition_mnemonics(instructions)
196modifier_lists = order_modifiers(ir_instructions)
197
198# Generate type signature for a builder routine
199
200def should_skip(mod, op):
201    # FROUND and HADD only make sense in context of a round mode, so override
202    # the usual skip
203    if mod == "round" and ("FROUND" in op or "HADD" in op):
204        return False
205
206    return mod in SKIP or mod[0:-1] in SKIP
207
208def modifier_signature(op):
209    return sorted([m for m in op["modifiers"].keys() if not should_skip(m, op["key"])])
210
211def signature(op, modifiers, typeful = False, sized = False, no_dests = False):
212    return ", ".join(
213        ["bi_builder *b"] +
214        (["nir_alu_type type"] if typeful == True else []) +
215        (["unsigned bitsize"] if sized == True else []) +
216        (["unsigned nr_dests"] if op["variable_dests"] else
217            ["bi_index dest{}".format(i) for i in range(0 if no_dests else op["dests"])]) +
218        (["unsigned nr_srcs"] if op["variable_srcs"] else
219            ["bi_index src{}".format(i) for i in range(src_count(op))]) +
220        ["{} {}".format(
221        "bool" if len(modifiers[T[0:-1]] if T[-1] in "0123" else modifiers[T]) == 2 else
222        "enum bi_" + T[0:-1] if T[-1] in "0123" else
223        "enum bi_" + T,
224        T) for T in modifier_signature(op)] +
225        ["uint32_t {}".format(imm) for imm in op["immediates"]])
226
227def arguments(op, temp_dest = True):
228    dest_pattern = "bi_temp(b->shader)" if temp_dest else 'dest{}'
229    dests = [dest_pattern.format(i) for i in range(op["dests"])]
230    srcs = ["src{}".format(i) for i in range(src_count(op))]
231
232    # Variable source/destinations just pass in the count
233    if op["variable_dests"]:
234        dests = ["nr_dests"]
235
236    if op["variable_srcs"]:
237        srcs = ["nr_srcs"]
238
239    return ", ".join(["b"] + dests + srcs + modifier_signature(op) + op["immediates"])
240
241print(Template(COPYRIGHT + TEMPLATE).render(ops = ir_instructions, modifiers =
242    modifier_lists, signature = signature, arguments = arguments, src_count =
243    src_count, typesize = typesize, should_skip = should_skip))
244