add setvl unit tests for overflow condition.
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 26 Aug 2022 14:40:01 +0000 (15:40 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 26 Aug 2022 14:40:01 +0000 (15:40 +0100)
TODO, update spec to match: when VL attempted to be set > MAXVL

openpower/isa/simplev.mdwn
src/openpower/decoder/isa/caller.py
src/openpower/decoder/isa/test_caller_setvl.py

index 6169c2e313da36cbf08447d62a8f20f9da681e97..b19e3af6046b6ca61b48d61a8a07036217770dd3 100644 (file)
@@ -31,6 +31,7 @@ Pseudo-code:
         if _RT != 0 then
            RT <- [0]*57 || step
     else
+        overflow <- 0b0
         VLimm <- SVi + 1
         # set or get MVL
         if ms = 1 then MVL <- VLimm[0:6]
@@ -38,14 +39,19 @@ Pseudo-code:
         # set or get VL
         if vs = 0                then VL <- SVSTATE[7:13]
         else if _RA != 0         then
-            if (RA) >u 0b1111111 then VL <- 0b1111111
+            if (RA) >u 0b1111111 then
+                VL <- 0b1111111
+                overflow <- 0b1
             else                      VL <- (RA)[57:63]
         else if _RA != 0         then VL <- (RA)[57:63]
         else if _RT = 0          then VL <- VLimm[0:6]
-        else if CTR >u 0b1111111 then VL <- 0b1111111
+        else if CTR >u 0b1111111 then
+            VL <- 0b1111111
+            overflow <- 0b1
         else                          VL <- CTR[57:63]
         # limit VL to within MVL
         if VL >u MVL then
+            overflow <- 0b1
             VL <- MVL
         SVSTATE[0:6] <- MVL
         SVSTATE[7:13] <- VL
index 854d784994e9516b898d1712f0453fb42023f4b6..bb928aba1c5e5f21a1c6fe6a692ee5fe12fbb758 100644 (file)
@@ -935,7 +935,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers):
         so = so | ov
         self.spr['XER'][XER_bits['SO']] = so
 
-    def handle_comparison(self, outputs, cr_idx=0):
+    def handle_comparison(self, outputs, cr_idx=0, overflow=None):
         out = outputs[0]
         assert isinstance(out, SelectableInt), \
             "out zero not a SelectableInt %s" % repr(outputs)
@@ -951,7 +951,9 @@ class ISACaller(ISACallerHelper, ISAFPHelpers):
         positive = SelectableInt(out > 0, 1)
         negative = SelectableInt(out < 0, 1)
         SO = self.spr['XER'][XER_bits['SO']]
-        log("handle_comparison SO", SO)
+        log("handle_comparison SO overflow", SO, overflow)
+        if overflow is not None and overflow == 1:
+            SO = SelectableInt(1, 1)
         cr_field = selectconcat(negative, positive, zero, SO)
         log("handle_comparison cr_field", self.cr, cr_idx, cr_field)
         self.crl[cr_idx].eq(cr_field)
@@ -1412,14 +1414,15 @@ class ISACaller(ISACallerHelper, ISAFPHelpers):
         if carry_en:
             yield from self.handle_carry_(inputs, results, already_done)
 
+        # check if one of the regs was named "overflow"
+        overflow = None
+        if info.write_regs:
+            for name, output in zip(output_names, results):
+                if name == 'overflow':
+                    overflow = output
+
         if not self.is_svp64_mode:  # yeah just no. not in parallel processing
             # detect if overflow was in return result
-            overflow = None
-            if info.write_regs:
-                for name, output in zip(output_names, results):
-                    if name == 'overflow':
-                        overflow = output
-
             if hasattr(self.dec2.e.do, "oe"):
                 ov_en = yield self.dec2.e.do.oe.oe
                 ov_ok = yield self.dec2.e.do.oe.ok
@@ -1437,7 +1440,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers):
                 rc_en = yield self.dec2.e.do.rc.rc
         if rc_en and ins_name not in ['svstep']:
             regnum, is_vec = yield from get_pdecode_cr_out(self.dec2, "CR0")
-            self.handle_comparison(results, regnum)
+            self.handle_comparison(results, regnum, overflow)
 
         # any modified return results?
         if info.write_regs:
index 45ff35784bc029a28923629bb2f2c9625e1bc1cc..3b2097cfc3bc45c9db31ed70e8aa9475ec7e0fa9 100644 (file)
@@ -97,6 +97,129 @@ class DecoderTestCase(FHDLTestCase):
             self.assertEqual(CR0[CRFields.GT], 1)
             self.assertEqual(CR0[CRFields.SO], 0)
 
+    def test_3_setvl_overflow_rc1(self):
+        lst = SVP64Asm(["setvl. 5, 4, 5, 0, 1, 1",
+                        ])
+        lst = list(lst)
+
+        # SVSTATE (in this case, MAXVL=5) which is going to get erased by setvl
+        # r4 (RA) is 4. and Rc=1. therefore, CR0 should be set to GT
+        svstate = SVP64State()
+        svstate.maxvl = 5 # MAXVL
+        print ("SVSTATE", bin(svstate.asint()))
+
+        initial_regs = [0] * 32
+        initial_regs[4] = 1000 # much greater than MAXVL
+
+        with Program(lst, bigendian=False) as program:
+            sim = self.run_tst_program(program, svstate=svstate,
+                                       initial_regs=initial_regs)
+            print ("SVSTATE after", bin(sim.svstate.asint()))
+            print ("        vl", bin(sim.svstate.vl))
+            print ("        mvl", bin(sim.svstate.maxvl))
+            print ("    srcstep", bin(sim.svstate.srcstep))
+            print ("    dststep", bin(sim.svstate.dststep))
+            print ("     vfirst", bin(sim.svstate.vfirst))
+            self.assertEqual(sim.svstate.vl, 5)
+            self.assertEqual(sim.svstate.maxvl, 5)
+            self.assertEqual(sim.svstate.srcstep, 0)
+            self.assertEqual(sim.svstate.dststep, 0)
+            self.assertEqual(sim.svstate.vfirst, 0)
+            print("      gpr4", sim.gpr(4))
+            self.assertEqual(sim.gpr(4), SelectableInt(1000, 64)) # unmodified
+            print("      gpr5", sim.gpr(5))
+            self.assertEqual(sim.gpr(5), SelectableInt(5, 64)) # equal to MAXVL
+            CR0 = sim.crl[0]
+            print("      CR0", bin(CR0.get_range().value))
+            self.assertEqual(CR0[CRFields.EQ], 0)
+            self.assertEqual(CR0[CRFields.LT], 0)
+            self.assertEqual(CR0[CRFields.GT], 1)
+            self.assertEqual(CR0[CRFields.SO], 1)
+
+    def test_4_setvl_max_overflow_rc1(self):
+        """this should set overflow even though VL gets set to MAXVL
+        at its limit of 127 (0b1111111)
+        """
+        lst = SVP64Asm(["setvl. 5, 4, 127, 0, 1, 1",
+                        ])
+        lst = list(lst)
+
+        # SVSTATE (in this case, MAXVL=5) which is going to get erased by setvl
+        # r4 (RA) is 4. and Rc=1. therefore, CR0 should be set to GT
+        svstate = SVP64State()
+        svstate.maxvl = 5 # MAXVL
+        print ("SVSTATE", bin(svstate.asint()))
+
+        initial_regs = [0] * 32
+        initial_regs[4] = 1000 # much greater than MAXVL
+
+        with Program(lst, bigendian=False) as program:
+            sim = self.run_tst_program(program, svstate=svstate,
+                                       initial_regs=initial_regs)
+            print ("SVSTATE after", bin(sim.svstate.asint()))
+            print ("        vl", bin(sim.svstate.vl))
+            print ("        mvl", bin(sim.svstate.maxvl))
+            print ("    srcstep", bin(sim.svstate.srcstep))
+            print ("    dststep", bin(sim.svstate.dststep))
+            print ("     vfirst", bin(sim.svstate.vfirst))
+            self.assertEqual(sim.svstate.vl, 127)
+            self.assertEqual(sim.svstate.maxvl, 127)
+            self.assertEqual(sim.svstate.srcstep, 0)
+            self.assertEqual(sim.svstate.dststep, 0)
+            self.assertEqual(sim.svstate.vfirst, 0)
+            print("      gpr4", sim.gpr(4))
+            self.assertEqual(sim.gpr(4), SelectableInt(1000, 64)) # unmodified
+            print("      gpr5", sim.gpr(5))
+            self.assertEqual(sim.gpr(5), SelectableInt(127, 64)) # eq. MAXVL
+            CR0 = sim.crl[0]
+            print("      CR0", bin(CR0.get_range().value))
+            self.assertEqual(CR0[CRFields.EQ], 0)
+            self.assertEqual(CR0[CRFields.LT], 0)
+            self.assertEqual(CR0[CRFields.GT], 1)
+            self.assertEqual(CR0[CRFields.SO], 1)
+
+    def test_5_setvl_max_rc1(self):
+        """this should not set when VL gets set to MAXVL
+        at its limit of 127 (0b1111111)
+        """
+        lst = SVP64Asm(["setvl. 5, 4, 127, 0, 1, 1",
+                        ])
+        lst = list(lst)
+
+        # SVSTATE (in this case, MAXVL=5) which is going to get erased by setvl
+        # r4 (RA) is 4. and Rc=1. therefore, CR0 should be set to GT
+        svstate = SVP64State()
+        svstate.maxvl = 5 # MAXVL
+        print ("SVSTATE", bin(svstate.asint()))
+
+        initial_regs = [0] * 32
+        initial_regs[4] = 127 # exactly equal to MAXVL
+
+        with Program(lst, bigendian=False) as program:
+            sim = self.run_tst_program(program, svstate=svstate,
+                                       initial_regs=initial_regs)
+            print ("SVSTATE after", bin(sim.svstate.asint()))
+            print ("        vl", bin(sim.svstate.vl))
+            print ("        mvl", bin(sim.svstate.maxvl))
+            print ("    srcstep", bin(sim.svstate.srcstep))
+            print ("    dststep", bin(sim.svstate.dststep))
+            print ("     vfirst", bin(sim.svstate.vfirst))
+            self.assertEqual(sim.svstate.vl, 127)
+            self.assertEqual(sim.svstate.maxvl, 127)
+            self.assertEqual(sim.svstate.srcstep, 0)
+            self.assertEqual(sim.svstate.dststep, 0)
+            self.assertEqual(sim.svstate.vfirst, 0)
+            print("      gpr4", sim.gpr(4))
+            self.assertEqual(sim.gpr(4), SelectableInt(127, 64)) # unmodified
+            print("      gpr5", sim.gpr(5))
+            self.assertEqual(sim.gpr(5), SelectableInt(127, 64)) # eq. MAXVL
+            CR0 = sim.crl[0]
+            print("      CR0", bin(CR0.get_range().value))
+            self.assertEqual(CR0[CRFields.EQ], 0)
+            self.assertEqual(CR0[CRFields.LT], 0)
+            self.assertEqual(CR0[CRFields.GT], 1)
+            self.assertEqual(CR0[CRFields.SO], 0)
+
     def test_svstep_1(self):
         lst = SVP64Asm(["setvl 0, 0, 10, 1, 1, 1", # actual setvl (VF mode)
                         "setvl 0, 0, 1, 1, 0, 0", # svstep