From c7308b19a012d17203a03e134a0986009f905d4d Mon Sep 17 00:00:00 2001 From: "Eric R. Smith" Date: Thu, 4 Jul 2024 20:51:53 +0000 Subject: [PATCH] panfrost: Update bifrost_isa.py to handle some Valhall constructs Updates the ISA.xml parser to be able to handle some of the constructs from the Valhall ISA.xml (which differs in significant ways from the Bifrost ISA.xml). The eventual intent is to avoid duplicating instructions in the two files, although that isn't enabled in this patch. The new features aren't used yet, that will be in a future commit. Reviewed-by: Mary Guillemard Acked-by: Boris Brezillon Part-of: --- src/panfrost/compiler/bifrost_isa.py | 102 +++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/src/panfrost/compiler/bifrost_isa.py b/src/panfrost/compiler/bifrost_isa.py index 4be004c3417..6f317e64331 100644 --- a/src/panfrost/compiler/bifrost_isa.py +++ b/src/panfrost/compiler/bifrost_isa.py @@ -102,8 +102,8 @@ def parse_modifiers(obj, include_pseudo): opts = [x.text if x.tag == 'opt' else x.tag for x in mod.findall('*')] if len(opts) == 0: - assert('opt' in mod.attrib) - opts = ['none', mod.attrib['opt']] + if 'opt' in mod.attrib: + opts = ['none', mod.attrib['opt']] # Find suitable default default = mod.attrib.get('default', 'none' if 'none' in opts else None) @@ -122,6 +122,33 @@ def parse_copy(enc, existing): if ex[0][0] == name: ex[0][1] = node.get('start') +mod_names = { + 'cmp' : [['cmpf', None, None], None, ['eq', 'gt', 'ge', 'ne', 'lt', 'le', 'gtlt', 'total']], + # FIXME: Valhall can accept any integer comparision, but the old IR generator only generated + # gt and ge, and left out lt and le. For now follow the old way so we can compare generated files, + # but we should switch over to the proper way once everything is working +# 'cmpfi' : [['cmpf', None, None], None, ['eq', 'ne', 'gt', 'ge', 'lt', 'le']], + 'cmpfi' : [['cmpf', None, None], None, ['eq', 'ne', 'gt', 'ge']], + 'eq' : [['cmpf', None, None], 'ne', ['eq', 'ne']], + 'dimension' : [['dimension', None, None], None, ['1d', '2d', '3d', 'cube']], + 'fetch_component' : [['fetch_component', None, None], None, ['gather4_r', 'gather4_g', 'gather4_b', 'gather4_a']], + 'lod_mode': [['va_lod_mode', None, None], 'zero_lod', ['zero_lod', 'computed_lod', 'explicit', 'computed_bias', 'grdesc']], + 'regfmt' : [['register_format', None, None], None, ['f16', 'f32', 's32', 'u32', 's16', 'u16', 'f64', 'i64', 'auto']], + 'result_type' : [['result_type', None, None], None, ['i1', 'f1', 'm1']], + 'sample' : [['sample', None, None], 'none', ['center', 'centroid', 'sample', 'explicit', 'none']], + 'update' : [['update', None, None], None, ['store', 'retrieve', 'conditional', 'clobber']], + 'vecsize' : [['vecsize', None, None], 'none', ['none', 'v2', 'v3', 'v4']], + 'source_format' : [['source_format', None, None], None, ['flat32', 'flat16', 'f32', 'f16']], + + 'array_enable': [['array_enable', None, None], 'none', ['none', 'array_enable']], + 'integer_coordinates': [['integer_coordinates', None, None], 'none', ['none', 'integer_coordinates']], + 'shadow' : [['shadow', None, None], 'none', ['none', 'shadow']], + 'skip' : [['skip', None, None], 'none', ['none', 'skip']], + 'texel_offset': [['texel_offset', None, None], 'none', ['none', 'texel_offset']], + 'wide_indices': [['wide_indices', None, None], 'none', ['none', 'wide_indices']], + 'write_mask' : [['write_mask', None, None], 'none', ['none', 'r', 'g', 'rg', 'b', 'rb', 'gb', 'rgb', 'a', 'ra', 'ga', 'rga', 'ba', 'rba', 'gba', 'rgba']] + } + def parse_instruction(ins, include_pseudo): common = { 'srcs': [], @@ -144,12 +171,21 @@ def parse_instruction(ins, include_pseudo): if 'exact' in ins.attrib: common['exact'] = parse_exact(ins) + extra_modifiers=[] + src_num = 0 for src in ins.findall('src'): if src.attrib.get('pseudo', False) and not include_pseudo: continue mask = int(src.attrib['mask'], 0) if ('mask' in src.attrib) else 0xFF - common['srcs'].append([int(src.attrib['start'], 0), mask]) + if src.attrib.get('start') is not None: + common['srcs'].append([int(src.attrib['start'], 0), mask]) + else: + common['srcs'].append([src_num*3, mask]) + if src.attrib.get('absneg', False): + extra_modifiers.append([['neg'+str(src_num), '0', '1'], 'neg',['none', 'neg']]) + extra_modifiers.append([['abs'+str(src_num), '0', '1'], 'abs',['none', 'abs']]) + src_num += 1 for imm in ins.findall('immediate'): if imm.attrib.get('pseudo', False) and not include_pseudo: @@ -158,8 +194,49 @@ def parse_instruction(ins, include_pseudo): start = int(imm.attrib['start']) if 'start' in imm.attrib else None common['immediates'].append([imm.attrib['name'], start, int(imm.attrib['size'])]) + # FIXME valhall ISA.xml uses instead of + for imm in ins.findall('imm'): + if imm.attrib.get('pseudo', False) and not include_pseudo: + continue + + base_name = imm.attrib['name'] + name = imm.attrib.get('ir_name', base_name) + if not name: + continue + + start = int(imm.attrib['start']) if 'start' in imm.attrib else None + common['immediates'].append([name, start, int(imm.attrib['size'])]) + + staging_read = False + staging_write = False + for sr in ins.findall('sr'): + if sr.attrib.get('read', False): + staging_read = True + if sr.attrib.get('write', False): + staging_write = True + + if staging_read: + common['staging'] = 'r' + if staging_write: + common['staging'] += 'w' + for sr in ins.findall('sr_count'): + size = sr.attrib.get('count', 'sr_count') + common['staging_count'] = size + + for m in ins.findall('*'): + name = m.tag + if name == 'cmp': + if m.attrib.get('int_only', False): + name = 'cmpfi' + elif m.attrib.get('eqne_only', False): + name = 'cmpfeq' + if name == 'va_mod': + name = m.attrib.get('name', '') + if name in mod_names: + extra_modifiers.append(mod_names[name]) + common['derived'] = parse_derived(ins) - common['modifiers'] = parse_modifiers(ins, include_pseudo) + common['modifiers'] = parse_modifiers(ins, include_pseudo) + extra_modifiers for swap in ins.findall('swap'): lr = [int(swap.get('left')), int(swap.get('right'))] @@ -206,14 +283,27 @@ def ins_name(ins, group = False): base_name = ins.attrib['name'] if group.attrib['unit'] == 'fma': tagged_name = '*' + base_name - elif group.attrib.get('ir_unit', '') == 'fma': - tagged_name = '*' + base_name else: tagged_name = '+' + base_name return tagged_name def parse_instructions(xml, include_unused = False, include_pseudo = False): final = {} + + # look at groups of instructions + groups = ET.parse(xml).getroot().findall('group') + for gr in groups: + if gr.attrib.get('unused', False) and not include_unused: + continue + if gr.attrib.get('pseudo', False) and not include_pseudo: + continue + group_base = parse_instruction(gr, include_pseudo) + for ins in gr.findall('ins'): + parsed = copy.deepcopy(group_base) + tagged_name = ins_name(ins, gr) + final[tagged_name] = parsed + + # now look at individual instructions instructions = ET.parse(xml).getroot().findall('ins') for ins in instructions: