add data-dependent fail-first mode, Rc=1 variant not RC1 yet
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 23 Sep 2022 21:44:14 +0000 (22:44 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 23 Sep 2022 21:44:14 +0000 (22:44 +0100)
first unit test passes, not Vertical-First Mode

src/openpower/decoder/isa/caller.py
src/openpower/decoder/isa/test_caller_svp64_dd_ffirst.py [new file with mode: 0644]
src/openpower/decoder/power_svp64_rm.py

index 74a63a18f5edfa65cd94ad24bca0f3f6bf6fa53e..8a8a3f6ef0e3c693b68b5d9f7cbb9c22a50e9ec5 100644 (file)
@@ -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 (file)
index 0000000..af51be5
--- /dev/null
@@ -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()
index 781868e041ab1890fe8b1a918d515a023c6eb5c7..04bccc684dc3c3d24d127dbacb1c97790e8af7ef 100644 (file)
@@ -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):