pan/bi: Add helpers for manipulating the ISA

These will be used to generate various files for the IR.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8213>
This commit is contained in:
Alyssa Rosenzweig 2020-12-23 11:38:06 -05:00 committed by Marge Bot
parent 46584f2d46
commit 93af193eeb

View file

@ -52,6 +52,8 @@ COPYRIGHT = """/*
import xml.etree.ElementTree as ET
import copy
import itertools
from collections import OrderedDict
def parse_cond(cond, aliased = False):
if cond.tag == 'reserved':
@ -226,3 +228,92 @@ def expand_states(instructions):
out[name] = (ins, test if test is not None else [], desc)
return out
# Drop keys used for packing to simplify IR representation, so we can check for
# equivalence easier
def simplify_to_ir(ins):
return {
'staging': ins['staging'],
'srcs': len(ins['srcs']),
'modifiers': [[m[0][0], m[2]] for m in ins['modifiers']],
'immediates': [m[0] for m in ins['immediates']]
}
def combine_ir_variants(instructions, v):
variants = sum([[simplify_to_ir(Q[1]) for Q in instructions[x]] for x in v], [])
# Accumulate modifiers across variants
modifiers = {}
for s in variants:
# Check consistency
assert(s['srcs'] == variants[0]['srcs'])
assert(s['immediates'] == variants[0]['immediates'])
assert(s['staging'] == variants[0]['staging'])
for name, opts in s['modifiers']:
if name not in modifiers:
modifiers[name] = copy.deepcopy(opts)
else:
modifiers[name] += opts
# Great, we've checked srcs/immediates are consistent and we've summed over
# modifiers
return {
'srcs': variants[0]['srcs'],
'staging': variants[0]['staging'],
'immediates': sorted(variants[0]['immediates']),
'modifiers': { k: modifiers[k] for k in modifiers }
}
# Partition instructions to mnemonics, considering units and variants
# equivalent.
def partition_mnemonics(instructions):
partitions = itertools.groupby(instructions, lambda x: x[1:])
return { k: combine_ir_variants(instructions, v) for (k, v) in partitions }
# Generate modifier lists, by accumulating all the possible modifiers, and
# deduplicating thus assigning canonical enum values. We don't try _too_ hard
# to be clever, but by preserving as much of the original orderings as
# possible, later instruction encoding is simplified a bit. Probably a micro
# optimization but we have to pick _some_ ordering, might as well choose the
# most convenient.
#
# THIS MUST BE DETERMINISTIC
def order_modifiers(ir_instructions):
out = {}
# modifier name -> (list of option strings)
modifier_lists = {}
for ins in sorted(ir_instructions):
modifiers = ir_instructions[ins]["modifiers"]
for name in modifiers:
name_ = name[0:-1] if name[-1] in "0123" else name
if name_ not in modifier_lists:
modifier_lists[name_] = copy.deepcopy(modifiers[name])
else:
modifier_lists[name_] += modifiers[name]
for mod in modifier_lists:
lst = list(OrderedDict.fromkeys(modifier_lists[mod]))
# Ensure none is false for booleans so the builder makes sense
if len(lst) == 2 and lst[1] == "none":
lst.reverse()
out[mod] = lst
return out
# Count sources for a simplified (IR) instruction, including a source for a
# staging register if necessary
def src_count(op):
staging = 1 if (op["staging"] in ["r", "rw"]) else 0
return op["srcs"] + staging