From 7259b4a5cd600619956814123a4f8c5d34382680 Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Wed, 1 Jan 2025 14:20:42 +0000 Subject: [PATCH] pco: pygen: add control-flow and branch ops Signed-off-by: Simon Perretta Acked-by: Erik Faye-Lund Part-of: --- src/imagination/pco/pco_internal.h | 16 +++++ src/imagination/pco/pco_map.py | 109 +++++++++++++++++++++++++++-- src/imagination/pco/pco_ops.py | 13 ++++ 3 files changed, 133 insertions(+), 5 deletions(-) diff --git a/src/imagination/pco/pco_internal.h b/src/imagination/pco/pco_internal.h index 4055efc5090..0533f4c0f5d 100644 --- a/src/imagination/pco/pco_internal.h +++ b/src/imagination/pco/pco_internal.h @@ -2604,6 +2604,22 @@ static inline pco_instr *find_parent_instr_from(pco_ref src, pco_instr *from) return NULL; } +static inline unsigned pco_igrp_offset(pco_igrp *igrp) +{ + return igrp->enc.offset; +} + +static inline unsigned pco_cf_node_offset(pco_cf_node *cf_node) +{ + pco_block *block = pco_cf_node_as_block(cf_node); + return pco_igrp_offset(pco_first_igrp(block)); +} + +static inline unsigned pco_branch_rel_offset(pco_igrp *br, pco_cf_node *cf_node) +{ + return pco_cf_node_offset(cf_node) - pco_igrp_offset(br); +} + static inline bool pco_should_skip_pass(const char *pass) { return comma_separated_list_contains(pco_skip_passes, pass); diff --git a/src/imagination/pco/pco_map.py b/src/imagination/pco/pco_map.py index ce1d35313bc..e919810ad18 100644 --- a/src/imagination/pco/pco_map.py +++ b/src/imagination/pco/pco_map.py @@ -264,6 +264,19 @@ enum_map(RM_ELEM.t, F_MASKW0, [ ('e3', 'e3'), ], pass_zero=['e0', 'e1', 'e2', 'e3']) +enum_map(OM_CND.t, F_PCND, [ + ('always', 'always'), + ('p0_true', 'p0_true'), + ('never', 'never'), + ('p0_false', 'p0_false'), +]) + +enum_map(OM_BRANCH_CND.t, F_BPRED, [ + ('exec_cond', 'cc'), + ('allinst', 'allp'), + ('anyinst', 'anyp'), +]) + class OpRef(object): def __init__(self, ref_type, index, mods): self.type = ref_type @@ -311,13 +324,19 @@ def encode_map(op, encodings, op_ref_maps): elif isinstance(val_spec, int): encode_variant += str(val_spec) elif isinstance(val_spec, str): - assert struct_field.type.base_type == BaseType.enum + # Special case + if val_spec == 'target_cf_node': + assert op.has_target_cf_node - enum = struct_field.type.enum - assert enum.parent is None - assert val_spec in enum.elems.keys(), f'Invalid enum element "{val_spec}" in field "{isa_op_field}" in isa op "{isa_op.bsname}" mapping for op "{op.name}".' + encode_variant += f'pco_branch_rel_offset({{1}}->parent_igrp, {{1}}->target_cf_node)' + else: + assert struct_field.type.base_type == BaseType.enum - encode_variant += enum.elems[val_spec].cname + enum = struct_field.type.enum + assert enum.parent is None + assert val_spec in enum.elems.keys(), f'Invalid enum element "{val_spec}" in field "{isa_op_field}" in isa op "{isa_op.bsname}" mapping for op "{op.name}".' + + encode_variant += enum.elems[val_spec].cname elif isinstance(val_spec, OpMod): assert val_spec in op.op_mods, f'Op mod "{val_spec.t.tname}" was specified but not valid in isa op "{isa_op.bsname}" mapping for op "{op.name}".' @@ -1269,6 +1288,40 @@ encode_map(O_DITRP, op_ref_maps=[('ctrl', ['temp'], ['drc', 'coeff', 'coeff', 'imm'])] ) +encode_map(O_CNDST, + encodings=[ + (I_CND, [ + ('adjust', ('pco_ref_get_imm', SRC(1))), + ('pcnd', OM_CND), + ('cndinst', 'st') + ]) + ], + op_ref_maps=[('ctrl', ['pe', 'w0'], ['s0', 'imm'])] +) + +encode_map(O_CNDEND, + encodings=[ + (I_CND, [ + ('adjust', ('pco_ref_get_imm', SRC(1))), + ('pcnd', 0), + ('cndinst', 'end') + ]) + ], + op_ref_maps=[('ctrl', ['pe', 'w0'], ['s0', 'imm'])] +) + +encode_map(O_BR, + encodings=[ + (I_BRANCH, [ + ('link', OM_LINK), + ('bpred', OM_BRANCH_CND), + ('abs', False), + ('offset', 'target_cf_node') + ]) + ], + op_ref_maps=[('ctrl', [], [])] +) + # Group mappings. group_map(O_FADD, hdr=(I_IGRP_HDR_MAIN, [ @@ -2031,3 +2084,49 @@ group_map(O_DITRP, ]), enc_ops=[('ctrl', O_DITRP)] ) + +group_map(O_CNDST, + hdr=(I_IGRP_HDR_CONTROL, [ + ('olchk', False), + ('w1p', False), + ('w0p', True), + ('cc', OM_EXEC_CND), + ('miscctl', False), + ('ctrlop', 'cnd') + ]), + enc_ops=[('ctrl', O_CNDST)], + srcs=[ + ('s[0]', ('ctrl', SRC(0)), 's0'), + ('s[3]', 'pco_zero') + ], + dests=[('w[0]', ('ctrl', DEST(1)), 'w0')] +) + +group_map(O_CNDEND, + hdr=(I_IGRP_HDR_CONTROL, [ + ('olchk', False), + ('w1p', False), + ('w0p', True), + ('cc', OM_EXEC_CND), + ('miscctl', False), + ('ctrlop', 'cnd') + ]), + enc_ops=[('ctrl', O_CNDEND)], + srcs=[ + ('s[0]', ('ctrl', SRC(0)), 's0'), + ('s[3]', 'pco_zero') + ], + dests=[('w[0]', ('ctrl', DEST(1)), 'w0')] +) + +group_map(O_BR, + hdr=(I_IGRP_HDR_CONTROL, [ + ('olchk', False), + ('w1p', False), + ('w0p', False), + ('cc', OM_EXEC_CND), + ('miscctl', False), + ('ctrlop', 'b') + ]), + enc_ops=[('ctrl', O_BR)] +) diff --git a/src/imagination/pco/pco_ops.py b/src/imagination/pco/pco_ops.py index ac6ebb62d80..114a36ecfcf 100644 --- a/src/imagination/pco/pco_ops.py +++ b/src/imagination/pco/pco_ops.py @@ -293,6 +293,13 @@ OM_SHIFTOP = op_mod_enum('shiftop', [ 'asr', ]) +OM_CND = op_mod_enum('cnd', [ + ('always', 'if(1)'), + ('p0_true', 'if(p0)'), + ('never', 'if(0)'), + ('p0_false', 'if(!p0)'), +]) + # Ops. OM_ALU = [OM_OLCHK, OM_EXEC_CND, OM_END, OM_ATOM, OM_RPT] @@ -356,6 +363,12 @@ O_DITRP = hw_op('ditrp', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1 O_DITRP_WRITE = hw_op('ditrp.write', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1, 4) O_DITRP_READ = hw_op('ditrp.read', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1, 3) +O_CNDST = hw_op('cndst', [OM_EXEC_CND, OM_CND], 2, 2) +O_CNDEF = hw_op('cndef', [OM_EXEC_CND, OM_CND], 2, 2) +O_CNDEND = hw_op('cndend', [OM_EXEC_CND], 2, 2) + +O_BR = hw_op('br', [OM_EXEC_CND, OM_BRANCH_CND, OM_LINK], has_target_cf_node=True) + # Combination (> 1 instructions per group). O_SCMP = hw_op('scmp', OM_ALU + [OM_TST_OP_MAIN], 1, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]]) O_BCMP = hw_op('bcmp', OM_ALU + [OM_TST_OP_MAIN, OM_TST_TYPE_MAIN], 1, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])