xref: /aosp_15_r20/external/mesa3d/src/panfrost/compiler/valhall/valhall.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker#encoding=utf-8
2*61046927SAndroid Build Coastguard Worker
3*61046927SAndroid Build Coastguard Worker# Copyright (C) 2016 Intel Corporation
4*61046927SAndroid Build Coastguard Worker# Copyright (C) 2016 Broadcom
5*61046927SAndroid Build Coastguard Worker# Copyright (C) 2020 Collabora, Ltd.
6*61046927SAndroid Build Coastguard Worker#
7*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"),
9*61046927SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation
10*61046927SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*61046927SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the
12*61046927SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker#
14*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next
15*61046927SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the
16*61046927SAndroid Build Coastguard Worker# Software.
17*61046927SAndroid Build Coastguard Worker#
18*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*61046927SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*61046927SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21*61046927SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*61046927SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23*61046927SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24*61046927SAndroid Build Coastguard Worker# IN THE SOFTWARE.
25*61046927SAndroid Build Coastguard Worker
26*61046927SAndroid Build Coastguard Workerimport os
27*61046927SAndroid Build Coastguard Workerimport textwrap
28*61046927SAndroid Build Coastguard Workerimport xml.etree.ElementTree as ET
29*61046927SAndroid Build Coastguard Workerimport sys
30*61046927SAndroid Build Coastguard Worker
31*61046927SAndroid Build Coastguard Worker# All instructions in the ISA
32*61046927SAndroid Build Coastguard Workerinstructions = []
33*61046927SAndroid Build Coastguard Worker
34*61046927SAndroid Build Coastguard WorkerMODIFIERS = {}
35*61046927SAndroid Build Coastguard Workerenums = {}
36*61046927SAndroid Build Coastguard Workerimmediates = []
37*61046927SAndroid Build Coastguard Worker
38*61046927SAndroid Build Coastguard Workerdef xmlbool(s):
39*61046927SAndroid Build Coastguard Worker    assert(s.lower() in ["false", "true"])
40*61046927SAndroid Build Coastguard Worker    return False if s.lower() == "false" else True
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Workerclass EnumValue:
43*61046927SAndroid Build Coastguard Worker    def __init__(self, value, default):
44*61046927SAndroid Build Coastguard Worker        self.value = value
45*61046927SAndroid Build Coastguard Worker        self.default = default
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Workerclass Enum:
48*61046927SAndroid Build Coastguard Worker    def __init__(self, name, values):
49*61046927SAndroid Build Coastguard Worker        self.name = name
50*61046927SAndroid Build Coastguard Worker        self.values = values
51*61046927SAndroid Build Coastguard Worker        self.bare_values = [x.value for x in values]
52*61046927SAndroid Build Coastguard Worker
53*61046927SAndroid Build Coastguard Worker        defaults = [x.value for x in values if x.default]
54*61046927SAndroid Build Coastguard Worker        if len(defaults) > 0:
55*61046927SAndroid Build Coastguard Worker            assert(len(defaults) == 1)
56*61046927SAndroid Build Coastguard Worker            self.default = defaults[0]
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard Workerdef build_enum(el):
59*61046927SAndroid Build Coastguard Worker    values = []
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker    for child in el:
62*61046927SAndroid Build Coastguard Worker        if child.tag == 'value':
63*61046927SAndroid Build Coastguard Worker            is_default = child.attrib.get('default', False)
64*61046927SAndroid Build Coastguard Worker            values.append(EnumValue(child.text, is_default))
65*61046927SAndroid Build Coastguard Worker        elif child.tag == 'reserved':
66*61046927SAndroid Build Coastguard Worker            values.append(EnumValue("reserved", False))
67*61046927SAndroid Build Coastguard Worker
68*61046927SAndroid Build Coastguard Worker    return Enum(el.attrib['name'], values)
69*61046927SAndroid Build Coastguard Worker
70*61046927SAndroid Build Coastguard Workerclass Modifier:
71*61046927SAndroid Build Coastguard Worker    def __init__(self, name, start, size, implied = False, force_enum = None):
72*61046927SAndroid Build Coastguard Worker        self.name = name
73*61046927SAndroid Build Coastguard Worker        self.start = start
74*61046927SAndroid Build Coastguard Worker        self.size = size
75*61046927SAndroid Build Coastguard Worker        self.implied = implied
76*61046927SAndroid Build Coastguard Worker        self.is_enum = (force_enum is not None) or size > 1
77*61046927SAndroid Build Coastguard Worker        self.enum = force_enum or name
78*61046927SAndroid Build Coastguard Worker
79*61046927SAndroid Build Coastguard Worker        if not self.is_enum:
80*61046927SAndroid Build Coastguard Worker            self.bare_values = ['', name]
81*61046927SAndroid Build Coastguard Worker            self.default = 0
82*61046927SAndroid Build Coastguard Worker        else:
83*61046927SAndroid Build Coastguard Worker            self.bare_values = [x.value for x in enums[self.enum].values]
84*61046927SAndroid Build Coastguard Worker            defaults = [x for x in enums[self.enum].values if x.default]
85*61046927SAndroid Build Coastguard Worker            assert(len(defaults) <= 1)
86*61046927SAndroid Build Coastguard Worker
87*61046927SAndroid Build Coastguard Worker            if len(defaults) > 0:
88*61046927SAndroid Build Coastguard Worker                self.default = self.bare_values.index(defaults[0].value)
89*61046927SAndroid Build Coastguard Worker            else:
90*61046927SAndroid Build Coastguard Worker                self.default = None
91*61046927SAndroid Build Coastguard Worker
92*61046927SAndroid Build Coastguard Workerdef Flag(name, start):
93*61046927SAndroid Build Coastguard Worker    return Modifier(name, start, 1)
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker# Model a single instruction
96*61046927SAndroid Build Coastguard Workerclass Source:
97*61046927SAndroid Build Coastguard Worker    def __init__(self, index, size, is_float = False, swizzle = False,
98*61046927SAndroid Build Coastguard Worker            halfswizzle = False, widen = False, lanes = False, combine = False, lane = None, absneg = False, notted = False, name = ""):
99*61046927SAndroid Build Coastguard Worker        self.is_float = is_float or absneg
100*61046927SAndroid Build Coastguard Worker        self.start = (index * 8)
101*61046927SAndroid Build Coastguard Worker        self.size = size
102*61046927SAndroid Build Coastguard Worker        self.absneg = absneg
103*61046927SAndroid Build Coastguard Worker        self.notted = notted
104*61046927SAndroid Build Coastguard Worker        self.swizzle = swizzle
105*61046927SAndroid Build Coastguard Worker        self.halfswizzle = halfswizzle
106*61046927SAndroid Build Coastguard Worker        self.widen = widen
107*61046927SAndroid Build Coastguard Worker        self.lanes = lanes
108*61046927SAndroid Build Coastguard Worker        self.lane = lane
109*61046927SAndroid Build Coastguard Worker        self.combine = combine
110*61046927SAndroid Build Coastguard Worker        self.name = name
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker        self.offset = {}
113*61046927SAndroid Build Coastguard Worker        self.bits = {}
114*61046927SAndroid Build Coastguard Worker        if absneg:
115*61046927SAndroid Build Coastguard Worker            self.offset['neg'] = 32 + 2 + ((2 - index) * 2)
116*61046927SAndroid Build Coastguard Worker            self.offset['abs'] = 33 + 2 + ((2 - index) * 2)
117*61046927SAndroid Build Coastguard Worker            self.bits['neg'] = 1
118*61046927SAndroid Build Coastguard Worker            self.bits['abs'] = 1
119*61046927SAndroid Build Coastguard Worker        if notted:
120*61046927SAndroid Build Coastguard Worker            self.offset['not'] = 35
121*61046927SAndroid Build Coastguard Worker            self.bits['not'] = 1
122*61046927SAndroid Build Coastguard Worker        if widen or lanes or halfswizzle:
123*61046927SAndroid Build Coastguard Worker            self.offset['widen'] = 26 if index == 1 else 36
124*61046927SAndroid Build Coastguard Worker            self.bits['widen'] = 4 # XXX: too much?
125*61046927SAndroid Build Coastguard Worker        if lane:
126*61046927SAndroid Build Coastguard Worker            self.offset['lane'] = self.lane
127*61046927SAndroid Build Coastguard Worker            self.bits['lane'] = 2 if size in (8, 32) else 1
128*61046927SAndroid Build Coastguard Worker        if swizzle:
129*61046927SAndroid Build Coastguard Worker            assert(size in [16, 32])
130*61046927SAndroid Build Coastguard Worker            self.offset['swizzle'] = 24 + ((2 - index) * 2)
131*61046927SAndroid Build Coastguard Worker            self.bits['swizzle'] = 2
132*61046927SAndroid Build Coastguard Worker        if combine:
133*61046927SAndroid Build Coastguard Worker            self.offset['combine'] = 37
134*61046927SAndroid Build Coastguard Worker            self.bits['combine'] = 3
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Workerclass Dest:
137*61046927SAndroid Build Coastguard Worker    def __init__(self, name = ""):
138*61046927SAndroid Build Coastguard Worker        self.name = name
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Workerclass Staging:
141*61046927SAndroid Build Coastguard Worker    def __init__(self, read = False, write = False, count = 0, flags = 'true', name = ""):
142*61046927SAndroid Build Coastguard Worker        self.name = name
143*61046927SAndroid Build Coastguard Worker        self.read = read
144*61046927SAndroid Build Coastguard Worker        self.write = write
145*61046927SAndroid Build Coastguard Worker        self.count = count
146*61046927SAndroid Build Coastguard Worker        self.flags = (flags != 'false')
147*61046927SAndroid Build Coastguard Worker        self.start = 40
148*61046927SAndroid Build Coastguard Worker
149*61046927SAndroid Build Coastguard Worker        if write and not self.flags:
150*61046927SAndroid Build Coastguard Worker            self.start = 16
151*61046927SAndroid Build Coastguard Worker
152*61046927SAndroid Build Coastguard Worker        # For compatibility
153*61046927SAndroid Build Coastguard Worker        self.absneg = False
154*61046927SAndroid Build Coastguard Worker        self.swizzle = False
155*61046927SAndroid Build Coastguard Worker        self.notted = False
156*61046927SAndroid Build Coastguard Worker        self.widen = False
157*61046927SAndroid Build Coastguard Worker        self.lanes = False
158*61046927SAndroid Build Coastguard Worker        self.lane = False
159*61046927SAndroid Build Coastguard Worker        self.halfswizzle = False
160*61046927SAndroid Build Coastguard Worker        self.combine = False
161*61046927SAndroid Build Coastguard Worker        self.size = 32
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker        if not self.flags:
164*61046927SAndroid Build Coastguard Worker            self.encoded_flags = 0
165*61046927SAndroid Build Coastguard Worker        elif flags == 'rw':
166*61046927SAndroid Build Coastguard Worker            self.encoded_flags = 0xc0
167*61046927SAndroid Build Coastguard Worker        else:
168*61046927SAndroid Build Coastguard Worker            assert(flags == 'true')
169*61046927SAndroid Build Coastguard Worker            self.encoded_flags = (0x80 if write else 0) | (0x40 if read else 0)
170*61046927SAndroid Build Coastguard Worker
171*61046927SAndroid Build Coastguard Workerclass Immediate:
172*61046927SAndroid Build Coastguard Worker    def __init__(self, name, start, size, signed):
173*61046927SAndroid Build Coastguard Worker        self.name = name
174*61046927SAndroid Build Coastguard Worker        self.start = start
175*61046927SAndroid Build Coastguard Worker        self.size = size
176*61046927SAndroid Build Coastguard Worker        self.signed = signed
177*61046927SAndroid Build Coastguard Worker
178*61046927SAndroid Build Coastguard Workerclass Instruction:
179*61046927SAndroid Build Coastguard Worker    def __init__(self, name, opcode, opcode2, srcs = [], dests = [], immediates = [], modifiers = [], staging = None, unit = None):
180*61046927SAndroid Build Coastguard Worker        self.name = name
181*61046927SAndroid Build Coastguard Worker        self.srcs = srcs
182*61046927SAndroid Build Coastguard Worker        self.dests = dests
183*61046927SAndroid Build Coastguard Worker        self.opcode = opcode
184*61046927SAndroid Build Coastguard Worker        self.opcode2 = opcode2 or 0
185*61046927SAndroid Build Coastguard Worker        self.immediates = immediates
186*61046927SAndroid Build Coastguard Worker        self.modifiers = modifiers
187*61046927SAndroid Build Coastguard Worker        self.staging = staging
188*61046927SAndroid Build Coastguard Worker        self.unit = unit
189*61046927SAndroid Build Coastguard Worker        self.is_signed = len(name.split(".")) > 1 and ('s' in name.split(".")[1])
190*61046927SAndroid Build Coastguard Worker
191*61046927SAndroid Build Coastguard Worker        # Message-passing instruction <===> not ALU instruction
192*61046927SAndroid Build Coastguard Worker        self.message = unit not in ["FMA", "CVT", "SFU"]
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker        self.secondary_shift = max(len(self.srcs) * 8, 16)
195*61046927SAndroid Build Coastguard Worker        self.secondary_mask = 0xF if opcode2 is not None else 0x0
196*61046927SAndroid Build Coastguard Worker        if "left" in [x.name for x in self.modifiers]:
197*61046927SAndroid Build Coastguard Worker            self.secondary_mask |= 0x100
198*61046927SAndroid Build Coastguard Worker        if len(srcs) == 3 and (srcs[1].widen or srcs[1].lanes or srcs[1].swizzle):
199*61046927SAndroid Build Coastguard Worker            self.secondary_mask &= ~0xC # conflicts
200*61046927SAndroid Build Coastguard Worker        if opcode == 0x90:
201*61046927SAndroid Build Coastguard Worker            # XXX: XMLify this, but disambiguates sign of conversions
202*61046927SAndroid Build Coastguard Worker            self.secondary_mask |= 0x10
203*61046927SAndroid Build Coastguard Worker        if name.startswith("LOAD.i") or name.startswith("STORE.i") or name.startswith("LD_BUFFER.i"):
204*61046927SAndroid Build Coastguard Worker            self.secondary_shift = 27 # Alias with memory_size
205*61046927SAndroid Build Coastguard Worker            self.secondary_mask = 0x7
206*61046927SAndroid Build Coastguard Worker        if "descriptor_type" in [x.name for x in self.modifiers]:
207*61046927SAndroid Build Coastguard Worker            self.secondary_mask = 0x3
208*61046927SAndroid Build Coastguard Worker            self.secondary_shift = 37
209*61046927SAndroid Build Coastguard Worker        elif "memory_width" in [x.name for x in self.modifiers]:
210*61046927SAndroid Build Coastguard Worker            self.secondary_mask = 0x7
211*61046927SAndroid Build Coastguard Worker            self.secondary_shift = 27
212*61046927SAndroid Build Coastguard Worker
213*61046927SAndroid Build Coastguard Worker        assert(len(dests) == 0 or not staging)
214*61046927SAndroid Build Coastguard Worker        assert(not opcode2 or (opcode2 & self.secondary_mask) == opcode2)
215*61046927SAndroid Build Coastguard Worker
216*61046927SAndroid Build Coastguard Worker    def __str__(self):
217*61046927SAndroid Build Coastguard Worker        return self.name
218*61046927SAndroid Build Coastguard Worker
219*61046927SAndroid Build Coastguard Worker# Build a single source from XML
220*61046927SAndroid Build Coastguard Workerdef build_source(el, i, size):
221*61046927SAndroid Build Coastguard Worker    lane = el.get('lane', None)
222*61046927SAndroid Build Coastguard Worker    if lane == "true":
223*61046927SAndroid Build Coastguard Worker        lane = 38 if i == 0 else 36
224*61046927SAndroid Build Coastguard Worker    elif lane is not None:
225*61046927SAndroid Build Coastguard Worker        lane = int(lane)
226*61046927SAndroid Build Coastguard Worker
227*61046927SAndroid Build Coastguard Worker    return Source(i, int(el.get('size', size)),
228*61046927SAndroid Build Coastguard Worker            absneg = el.get('absneg', False),
229*61046927SAndroid Build Coastguard Worker            is_float = el.get('float', False),
230*61046927SAndroid Build Coastguard Worker            swizzle = el.get('swizzle', False),
231*61046927SAndroid Build Coastguard Worker            halfswizzle = el.get('halfswizzle', False),
232*61046927SAndroid Build Coastguard Worker            widen = el.get('widen', False),
233*61046927SAndroid Build Coastguard Worker            lanes = el.get('lanes', False),
234*61046927SAndroid Build Coastguard Worker            combine = el.get('combine', False),
235*61046927SAndroid Build Coastguard Worker            lane = lane,
236*61046927SAndroid Build Coastguard Worker            notted = el.get('not', False),
237*61046927SAndroid Build Coastguard Worker            name = el.text or "")
238*61046927SAndroid Build Coastguard Worker
239*61046927SAndroid Build Coastguard Workerdef build_imm(el):
240*61046927SAndroid Build Coastguard Worker    return Immediate(el.attrib['name'], int(el.attrib['start']),
241*61046927SAndroid Build Coastguard Worker            int(el.attrib['size']), bool(el.attrib.get('signed', False)))
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Workerdef build_staging(i, el):
244*61046927SAndroid Build Coastguard Worker    r = xmlbool(el.attrib.get('read', 'false'))
245*61046927SAndroid Build Coastguard Worker    w = xmlbool(el.attrib.get('write', 'false'))
246*61046927SAndroid Build Coastguard Worker    count = int(el.attrib.get('count', '0'))
247*61046927SAndroid Build Coastguard Worker    flags = el.attrib.get('flags', 'true')
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker    return Staging(r, w, count, flags, el.text or '')
250*61046927SAndroid Build Coastguard Worker
251*61046927SAndroid Build Coastguard Workerdef build_modifier(el):
252*61046927SAndroid Build Coastguard Worker    name = el.attrib['name']
253*61046927SAndroid Build Coastguard Worker    start = int(el.attrib['start'])
254*61046927SAndroid Build Coastguard Worker    size = int(el.attrib['size'])
255*61046927SAndroid Build Coastguard Worker    implied = xmlbool(el.get('implied', 'false'))
256*61046927SAndroid Build Coastguard Worker
257*61046927SAndroid Build Coastguard Worker    return Modifier(name, start, size, implied)
258*61046927SAndroid Build Coastguard Worker
259*61046927SAndroid Build Coastguard Worker# Build a single instruction from XML and group based overrides
260*61046927SAndroid Build Coastguard Workerdef build_instr(el, overrides = {}):
261*61046927SAndroid Build Coastguard Worker    # Get overridables
262*61046927SAndroid Build Coastguard Worker    name = overrides.get('name') or el.attrib.get('name')
263*61046927SAndroid Build Coastguard Worker    opcode = overrides.get('opcode') or el.attrib.get('opcode')
264*61046927SAndroid Build Coastguard Worker    opcode2 = overrides.get('opcode2') or el.attrib.get('opcode2')
265*61046927SAndroid Build Coastguard Worker    unit = overrides.get('unit') or el.attrib.get('unit')
266*61046927SAndroid Build Coastguard Worker    opcode = int(opcode, base=0)
267*61046927SAndroid Build Coastguard Worker    opcode2 = int(opcode2, base=0) if opcode2 else None
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker    # Get explicit sources/dests
270*61046927SAndroid Build Coastguard Worker    tsize = typesize(name)
271*61046927SAndroid Build Coastguard Worker    sources = []
272*61046927SAndroid Build Coastguard Worker    i = 0
273*61046927SAndroid Build Coastguard Worker
274*61046927SAndroid Build Coastguard Worker    for src in el.findall('src'):
275*61046927SAndroid Build Coastguard Worker        if (src.attrib.get('pseudo', False)):
276*61046927SAndroid Build Coastguard Worker            continue
277*61046927SAndroid Build Coastguard Worker        built = build_source(src, i, tsize)
278*61046927SAndroid Build Coastguard Worker        sources += [built]
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker        # 64-bit sources in a 32-bit (message) instruction count as two slots
281*61046927SAndroid Build Coastguard Worker        # Affects BLEND, ST_CVT
282*61046927SAndroid Build Coastguard Worker        if tsize != 64 and built.size == 64:
283*61046927SAndroid Build Coastguard Worker            i = i + 2
284*61046927SAndroid Build Coastguard Worker        else:
285*61046927SAndroid Build Coastguard Worker            i = i + 1
286*61046927SAndroid Build Coastguard Worker
287*61046927SAndroid Build Coastguard Worker    dests = [Dest(dest.text or '') for dest in el.findall('dest')]
288*61046927SAndroid Build Coastguard Worker
289*61046927SAndroid Build Coastguard Worker    # Get implicit ones
290*61046927SAndroid Build Coastguard Worker    sources = sources + ([Source(i, int(tsize)) for i in range(int(el.attrib.get('srcs', 0)))])
291*61046927SAndroid Build Coastguard Worker    dests = dests + ([Dest()] * int(el.attrib.get('dests', 0)))
292*61046927SAndroid Build Coastguard Worker
293*61046927SAndroid Build Coastguard Worker    # Get staging registers
294*61046927SAndroid Build Coastguard Worker    staging = [build_staging(i, el) for i, el in enumerate(el.findall('sr'))]
295*61046927SAndroid Build Coastguard Worker
296*61046927SAndroid Build Coastguard Worker    # Get immediates
297*61046927SAndroid Build Coastguard Worker    imms = [build_imm(imm) for imm in el.findall('imm')]
298*61046927SAndroid Build Coastguard Worker
299*61046927SAndroid Build Coastguard Worker    modifiers = []
300*61046927SAndroid Build Coastguard Worker    for mod in el:
301*61046927SAndroid Build Coastguard Worker        if (mod.tag in MODIFIERS) and not (mod.attrib.get('pseudo', False)):
302*61046927SAndroid Build Coastguard Worker            modifiers.append(MODIFIERS[mod.tag])
303*61046927SAndroid Build Coastguard Worker        elif mod.tag =='va_mod':
304*61046927SAndroid Build Coastguard Worker            modifiers.append(build_modifier(mod))
305*61046927SAndroid Build Coastguard Worker
306*61046927SAndroid Build Coastguard Worker    instr = Instruction(name, opcode, opcode2, srcs = sources, dests = dests, immediates = imms, modifiers = modifiers, staging = staging, unit = unit)
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker    instructions.append(instr)
309*61046927SAndroid Build Coastguard Worker
310*61046927SAndroid Build Coastguard Worker# Build all the instructions in a group by duplicating the group itself with
311*61046927SAndroid Build Coastguard Worker# overrides for each distinct instruction
312*61046927SAndroid Build Coastguard Workerdef build_group(el):
313*61046927SAndroid Build Coastguard Worker    for ins in el.findall('ins'):
314*61046927SAndroid Build Coastguard Worker        build_instr(el, overrides = {
315*61046927SAndroid Build Coastguard Worker            'name': ins.attrib['name'],
316*61046927SAndroid Build Coastguard Worker            'opcode': ins.attrib.get('opcode'),
317*61046927SAndroid Build Coastguard Worker            'opcode2': ins.attrib.get('opcode2'),
318*61046927SAndroid Build Coastguard Worker            'unit': ins.attrib.get('unit'),
319*61046927SAndroid Build Coastguard Worker        })
320*61046927SAndroid Build Coastguard Worker
321*61046927SAndroid Build Coastguard Workerdef to_alphanum(name):
322*61046927SAndroid Build Coastguard Worker    substitutions = {
323*61046927SAndroid Build Coastguard Worker        ' ': '_',
324*61046927SAndroid Build Coastguard Worker        '/': '_',
325*61046927SAndroid Build Coastguard Worker        '[': '',
326*61046927SAndroid Build Coastguard Worker        ']': '',
327*61046927SAndroid Build Coastguard Worker        '(': '',
328*61046927SAndroid Build Coastguard Worker        ')': '',
329*61046927SAndroid Build Coastguard Worker        '-': '_',
330*61046927SAndroid Build Coastguard Worker        ':': '',
331*61046927SAndroid Build Coastguard Worker        '.': '',
332*61046927SAndroid Build Coastguard Worker        ',': '',
333*61046927SAndroid Build Coastguard Worker        '=': '',
334*61046927SAndroid Build Coastguard Worker        '>': '',
335*61046927SAndroid Build Coastguard Worker        '#': '',
336*61046927SAndroid Build Coastguard Worker        '&': '',
337*61046927SAndroid Build Coastguard Worker        '*': '',
338*61046927SAndroid Build Coastguard Worker        '"': '',
339*61046927SAndroid Build Coastguard Worker        '+': '',
340*61046927SAndroid Build Coastguard Worker        '\'': '',
341*61046927SAndroid Build Coastguard Worker    }
342*61046927SAndroid Build Coastguard Worker
343*61046927SAndroid Build Coastguard Worker    for i, j in substitutions.items():
344*61046927SAndroid Build Coastguard Worker        name = name.replace(i, j)
345*61046927SAndroid Build Coastguard Worker
346*61046927SAndroid Build Coastguard Worker    return name
347*61046927SAndroid Build Coastguard Worker
348*61046927SAndroid Build Coastguard Workerdef safe_name(name):
349*61046927SAndroid Build Coastguard Worker    name = to_alphanum(name)
350*61046927SAndroid Build Coastguard Worker    if not name[0].isalpha():
351*61046927SAndroid Build Coastguard Worker        name = '_' + name
352*61046927SAndroid Build Coastguard Worker
353*61046927SAndroid Build Coastguard Worker    return name.lower()
354*61046927SAndroid Build Coastguard Worker
355*61046927SAndroid Build Coastguard Worker# Parses out the size part of an opcode name
356*61046927SAndroid Build Coastguard Workerdef typesize(opcode):
357*61046927SAndroid Build Coastguard Worker    if opcode[-3:] == '128':
358*61046927SAndroid Build Coastguard Worker        return 128
359*61046927SAndroid Build Coastguard Worker    if opcode[-2:] == '48':
360*61046927SAndroid Build Coastguard Worker        return 48
361*61046927SAndroid Build Coastguard Worker    elif opcode[-1] == '8':
362*61046927SAndroid Build Coastguard Worker        return 8
363*61046927SAndroid Build Coastguard Worker    else:
364*61046927SAndroid Build Coastguard Worker        try:
365*61046927SAndroid Build Coastguard Worker            return int(opcode[-2:])
366*61046927SAndroid Build Coastguard Worker        except:
367*61046927SAndroid Build Coastguard Worker            return 32
368*61046927SAndroid Build Coastguard Worker
369*61046927SAndroid Build Coastguard Worker# Parse the ISA
370*61046927SAndroid Build Coastguard Workerdef valhall_parse_isa(xmlfile = False):
371*61046927SAndroid Build Coastguard Worker    global MODIFIERS
372*61046927SAndroid Build Coastguard Worker    global enums
373*61046927SAndroid Build Coastguard Worker    global immediates
374*61046927SAndroid Build Coastguard Worker    global root
375*61046927SAndroid Build Coastguard Worker
376*61046927SAndroid Build Coastguard Worker    xmlfile = os.path.join(os.path.dirname(__file__), 'ISA.xml')
377*61046927SAndroid Build Coastguard Worker    tree = ET.parse(xmlfile)
378*61046927SAndroid Build Coastguard Worker    root = tree.getroot()
379*61046927SAndroid Build Coastguard Worker
380*61046927SAndroid Build Coastguard Worker    # All immediates in the ISA
381*61046927SAndroid Build Coastguard Worker    ilut = root.findall('lut')[0]
382*61046927SAndroid Build Coastguard Worker    assert(ilut.attrib['name'] == "Immediates")
383*61046927SAndroid Build Coastguard Worker    immediates = [int(imm.text, base=0) for imm in ilut.findall('constant')]
384*61046927SAndroid Build Coastguard Worker
385*61046927SAndroid Build Coastguard Worker    for child in root.findall('enum'):
386*61046927SAndroid Build Coastguard Worker        enums[safe_name(child.attrib['name'])] = build_enum(child)
387*61046927SAndroid Build Coastguard Worker
388*61046927SAndroid Build Coastguard Worker    MODIFIERS = {
389*61046927SAndroid Build Coastguard Worker        # Texture instructions share a common encoding
390*61046927SAndroid Build Coastguard Worker        "wide_indices": Flag("wide_indices", 8),
391*61046927SAndroid Build Coastguard Worker        "array_enable": Flag("array_enable", 10),
392*61046927SAndroid Build Coastguard Worker        "texel_offset": Flag("texel_offset", 11),
393*61046927SAndroid Build Coastguard Worker        "shadow": Flag("shadow", 12),
394*61046927SAndroid Build Coastguard Worker        "integer_coordinates": Flag("integer_coordinates", 13),
395*61046927SAndroid Build Coastguard Worker        "fetch_component": Modifier("fetch_component", 14, 2),
396*61046927SAndroid Build Coastguard Worker        "lod_mode": Modifier("lod_mode", 13, 3),
397*61046927SAndroid Build Coastguard Worker        "lod_bias_disable": Modifier("lod_mode", 13, 1),
398*61046927SAndroid Build Coastguard Worker        "lod_clamp_disable": Modifier("lod_mode", 14, 1),
399*61046927SAndroid Build Coastguard Worker        "write_mask": Modifier("write_mask", 22, 4),
400*61046927SAndroid Build Coastguard Worker        "register_type": Modifier("register_type", 26, 2),
401*61046927SAndroid Build Coastguard Worker        "dimension": Modifier("dimension", 28, 2),
402*61046927SAndroid Build Coastguard Worker        "skip": Flag("skip", 39),
403*61046927SAndroid Build Coastguard Worker        "register_width": Modifier("register_width", 46, 1, force_enum = "register_width"),
404*61046927SAndroid Build Coastguard Worker        "secondary_register_width": Modifier("secondary_register_width", 47, 1, force_enum = "register_width"),
405*61046927SAndroid Build Coastguard Worker        "vartex_register_width": Modifier("varying_texture_register_width", 24, 2),
406*61046927SAndroid Build Coastguard Worker
407*61046927SAndroid Build Coastguard Worker        "atom_opc": Modifier("atomic_operation", 22, 4),
408*61046927SAndroid Build Coastguard Worker        "atom_opc_1": Modifier("atomic_operation_with_1", 22, 4),
409*61046927SAndroid Build Coastguard Worker        "inactive_result": Modifier("inactive_result", 22, 4),
410*61046927SAndroid Build Coastguard Worker        "memory_access": Modifier("memory_access", 24, 2),
411*61046927SAndroid Build Coastguard Worker        "regfmt": Modifier("register_format", 24, 3),
412*61046927SAndroid Build Coastguard Worker        "source_format": Modifier("source_format", 24, 4),
413*61046927SAndroid Build Coastguard Worker        "vecsize": Modifier("vector_size", 28, 2),
414*61046927SAndroid Build Coastguard Worker
415*61046927SAndroid Build Coastguard Worker        "slot": Modifier("slot", 30, 3),
416*61046927SAndroid Build Coastguard Worker        "roundmode": Modifier("round_mode", 30, 2),
417*61046927SAndroid Build Coastguard Worker        "result_type": Modifier("result_type", 30, 2),
418*61046927SAndroid Build Coastguard Worker        "saturate": Flag("saturate", 30),
419*61046927SAndroid Build Coastguard Worker        "not_result": Flag("not_result", 30),
420*61046927SAndroid Build Coastguard Worker
421*61046927SAndroid Build Coastguard Worker        "lane_op": Modifier("lane_operation", 32, 2),
422*61046927SAndroid Build Coastguard Worker        "cmp": Modifier("condition", 32, 3),
423*61046927SAndroid Build Coastguard Worker        "clamp": Modifier("clamp", 32, 2),
424*61046927SAndroid Build Coastguard Worker        "sr_count": Modifier("staging_register_count", 33, 3, implied = True),
425*61046927SAndroid Build Coastguard Worker        "sample_and_update": Modifier("sample_and_update_mode", 33, 3),
426*61046927SAndroid Build Coastguard Worker        "sr_write_count": Modifier("staging_register_write_count", 36, 3, implied = True),
427*61046927SAndroid Build Coastguard Worker
428*61046927SAndroid Build Coastguard Worker        "conservative": Flag("conservative", 35),
429*61046927SAndroid Build Coastguard Worker        "subgroup": Modifier("subgroup_size", 36, 4),
430*61046927SAndroid Build Coastguard Worker        "update": Modifier("update_mode", 36, 2),
431*61046927SAndroid Build Coastguard Worker        "sample": Modifier("sample_mode", 38, 2),
432*61046927SAndroid Build Coastguard Worker    }
433*61046927SAndroid Build Coastguard Worker
434*61046927SAndroid Build Coastguard Worker    for child in root:
435*61046927SAndroid Build Coastguard Worker        if child.tag == 'group':
436*61046927SAndroid Build Coastguard Worker            build_group(child)
437*61046927SAndroid Build Coastguard Worker        elif child.tag == 'ins':
438*61046927SAndroid Build Coastguard Worker            build_instr(child)
439*61046927SAndroid Build Coastguard Worker
440*61046927SAndroid Build Coastguard Worker    instruction_dict = { ins.name: ins for ins in instructions }
441*61046927SAndroid Build Coastguard Worker
442*61046927SAndroid Build Coastguard Worker    # Validate there are no duplicated instructions
443*61046927SAndroid Build Coastguard Worker    if len(instruction_dict) != len(instructions):
444*61046927SAndroid Build Coastguard Worker        import collections
445*61046927SAndroid Build Coastguard Worker        counts = collections.Counter([i.name for i in instructions])
446*61046927SAndroid Build Coastguard Worker        for c in counts:
447*61046927SAndroid Build Coastguard Worker            if counts[c] != 1:
448*61046927SAndroid Build Coastguard Worker                print(f'{c} appeared {counts[c]} times.')
449*61046927SAndroid Build Coastguard Worker
450*61046927SAndroid Build Coastguard Worker    assert(len(instruction_dict) == len(instructions))
451*61046927SAndroid Build Coastguard Worker
452*61046927SAndroid Build Coastguard Worker    return (instructions, immediates, enums, typesize, safe_name)
453