From 86d1324aa726b91faa840f3a3b45342779579ffc Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 23 Sep 2022 22:44:14 +0100 Subject: [PATCH] add data-dependent fail-first mode, Rc=1 variant not RC1 yet first unit test passes, not Vertical-First Mode --- src/openpower/decoder/isa/caller.py | 45 ++++++++-- .../isa/test_caller_svp64_dd_ffirst.py | 85 +++++++++++++++++++ src/openpower/decoder/power_svp64_rm.py | 7 ++ 3 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 src/openpower/decoder/isa/test_caller_svp64_dd_ffirst.py diff --git a/src/openpower/decoder/isa/caller.py b/src/openpower/decoder/isa/caller.py index 74a63a18..8a8a3f6e 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -1701,10 +1701,29 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): if rc_en and ins_name not in ['svstep']: yield from self.do_rc_ov(ins_name, results, overflow, cr0) + # check failfirst + rm_mode = yield self.dec2.rm_dec.mode + ff_inv = yield self.dec2.rm_dec.inv + cr_bit = yield self.dec2.rm_dec.cr_sel + log(" ff rm_mode", rc_en, rm_mode, SVP64RMMode.FFIRST.value) + log(" inv", ff_inv) + log(" cr_bit", cr_bit) + ffirst_hit = False + if rc_en and rm_mode == SVP64RMMode.FFIRST.value: + regnum, is_vec = yield from get_pdecode_cr_out(self.dec2, "CR0") + crtest = self.crl[regnum] + ffirst_hit = crtest[cr_bit] != ff_inv + log("cr test", regnum, int(crtest), crtest, cr_bit, ff_inv) + log("cr test?", ffirst_hit) + if ffirst_hit: + self.svstate.vl = srcstep + yield self.dec2.state.svstate.eq(self.svstate.value) + yield Settle() # let decoder update + # any modified return results? yield from self.do_outregs_nia(asmop, ins_name, info, output_names, results, - carry_en, rc_en) + carry_en, rc_en, ffirst_hit) def do_rc_ov(self, ins_name, results, overflow, cr0): if ins_name.startswith("f"): @@ -1724,20 +1743,24 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): # if there was not an explicit CR0 in the pseudocode, do implicit Rc=1 if cr0 is None: self.handle_comparison(cmps, regnum, overflow, no_so=is_setvl) - return - # otherwise we just blat CR0 into the required regnum - log("explicit rc0", cr0) - self.crl[regnum].eq(cr0) + else: + # otherwise we just blat CR0 into the required regnum + log("explicit rc0", cr0) + self.crl[regnum].eq(cr0) def do_outregs_nia(self, asmop, ins_name, info, output_names, results, - carry_en, rc_en): + carry_en, rc_en, ffirst_hit): # write out any regs for this instruction if info.write_regs: for name, output in zip(output_names, results): yield from self.check_write(info, name, output, carry_en) - # check advancement of src/dst/sub-steps and if PC needs updating - nia_update = (yield from self.check_step_increment(results, rc_en, + if ffirst_hit: + self.svp64_reset_loop() + nia_update = True + else: + # check advancement of src/dst/sub-steps and if PC needs updating + nia_update = (yield from self.check_step_increment(results, rc_en, asmop, ins_name)) if nia_update: self.update_pc_next() @@ -2045,6 +2068,9 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): unpack = self.svstate.unpack vl = self.svstate.vl subvl = yield self.dec2.rm_dec.rm_in.subvl + rm_mode = yield self.dec2.rm_dec.mode + ff_inv = yield self.dec2.rm_dec.inv + cr_bit = yield self.dec2.rm_dec.cr_sel log(" srcstep", srcstep) log(" dststep", dststep) log(" pack", pack) @@ -2053,6 +2079,9 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop): log(" dsubstep", dsubstep) log(" vl", vl) log(" subvl", subvl) + log(" rm_mode", rm_mode) + log(" inv", ff_inv) + log(" cr_bit", cr_bit) # check if end reached (we let srcstep overrun, above) # nothing needs doing (TODO zeroing): just do next instruction diff --git a/src/openpower/decoder/isa/test_caller_svp64_dd_ffirst.py b/src/openpower/decoder/isa/test_caller_svp64_dd_ffirst.py new file mode 100644 index 00000000..af51be5b --- /dev/null +++ b/src/openpower/decoder/isa/test_caller_svp64_dd_ffirst.py @@ -0,0 +1,85 @@ +from nmigen import Module, Signal +from nmigen.sim import Simulator, Delay, Settle +from nmutil.formaltest import FHDLTestCase +import unittest +from openpower.decoder.isa.caller import ISACaller +from openpower.decoder.power_decoder import (create_pdecode) +from openpower.decoder.power_decoder2 import (PowerDecode2) +from openpower.simulator.program import Program +from openpower.decoder.isa.caller import ISACaller, SVP64State +from openpower.decoder.selectable_int import SelectableInt +from openpower.decoder.orderedset import OrderedSet +from openpower.decoder.isa.all import ISA +from openpower.decoder.isa.test_caller import Register, run_tst +from openpower.sv.trans.svp64 import SVP64Asm +from openpower.consts import SVP64CROffs +from copy import deepcopy +from openpower.decoder.helpers import fp64toselectable +from openpower.decoder.isa.remap_preduce_yield import preduce_y +from functools import reduce +import operator + + +class DecoderTestCase(FHDLTestCase): + + def _check_regs(self, sim, expected): + for i in range(32): + self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64)) + + def test_sv_addi_ffirst(self): + lst = SVP64Asm([ "sv.subf./ff=eq *0,8,*0" + ]) + lst = list(lst) + + # SVSTATE + svstate = SVP64State() + svstate.vl = 4 # VL + svstate.maxvl = 4 # MAXVL + print ("SVSTATE", bin(svstate.asint())) + + gprs = [0] * 64 + gprs[8] = 3 + vec = [9, 8, 3, 4] + + res = [] + # store GPRs + for i, x in enumerate(vec): + gprs[i] = x + + with Program(lst, bigendian=False) as program: + sim = self.run_tst_program(program, initial_regs=gprs, + svstate=svstate) + for i in range(4): + val = sim.gpr(i).value + res.append(val) + print ("i", i, val) + # confirm that the results are as expected + expected = deepcopy(vec) + for i in range(4): + expected[i] -= gprs[8] + if expected[i] == 0: + break + for i, v in enumerate(res): + self.assertEqual(v, expected[i]) + + + def run_tst_program(self, prog, initial_regs=None, + svstate=None, + initial_mem=None, + initial_fprs=None): + if initial_regs is None: + initial_regs = [0] * 32 + simulator = run_tst(prog, initial_regs, mem=initial_mem, + initial_fprs=initial_fprs, + svstate=svstate) + + print ("GPRs") + simulator.gpr.dump() + print ("FPRs") + simulator.fpr.dump() + + return simulator + + +if __name__ == "__main__": + unittest.main() diff --git a/src/openpower/decoder/power_svp64_rm.py b/src/openpower/decoder/power_svp64_rm.py index 781868e0..04bccc68 100644 --- a/src/openpower/decoder/power_svp64_rm.py +++ b/src/openpower/decoder/power_svp64_rm.py @@ -147,6 +147,7 @@ class SVP64RMModeDecode(Elaboratable): comb += is_ldst.eq(self.fn_in == Function.LDST) comb += is_bc.eq(self.fn_in == Function.BRANCH) mode2 = sel(m, mode, SVP64MODE.MOD2) + cr = sel(m, mode, SVP64MODE.CR) with m.If(is_bc): # Branch-Conditional is completely different @@ -215,6 +216,12 @@ class SVP64RMModeDecode(Elaboratable): comb += self.pred_sz.eq(mode[SVP64MODE.SZ]) comb += self.pred_dz.eq(mode[SVP64MODE.DZ]) + # extract failfirst + with m.If(self.mode == SVP64RMMode.FFIRST): # fail-first + with m.If(self.rc_in): + comb += self.inv.eq(mode[SVP64MODE.INV]) + comb += self.cr_sel.eq(cr) + # extract saturate with m.Switch(mode2): with m.Case(2): -- 2.30.2