sv.bc test jumping to wrong location (offset 0xc not 0x8)
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 15 Aug 2021 16:05:16 +0000 (17:05 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 15 Aug 2021 16:05:16 +0000 (17:05 +0100)
fix sv.bc/all test, and sv.bc pseudocode, to early-exit if one CR test
fails, but also not branch just because *one* test succeeds.

openpower/isa/svbranch.mdwn
src/openpower/decoder/isa/caller.py
src/openpower/decoder/isa/test_caller_svp64_bc.py
src/openpower/sv/trans/svp64.py

index 0c15a04d6725d57beabc734a32e922bc9d3a1ff8..bbc5aeda49de6e914179e2d1cd09b854fbccc8c0 100644 (file)
@@ -54,6 +54,7 @@ Pseudo-code:
             SVSTATE[7:13] <- (srcstep+1)
         else
             SVSTATE[7:13] <- srcstep+1
+        end_loop <- 0b1
     # XXX if svstep_mode then
     # XXX   SVSTATE.srcstep = new_srcstep
     # actual branch
@@ -61,8 +62,17 @@ Pseudo-code:
     else M <- 32
     if ¬BO[2] then CTR <- CTR - 1
     ctr_ok <- BO[2] | ((CTR[M:63] != 0) ^ BO[3])
+    test_branch <- 0b1
+    if ALL then
+        # in ALL mode only try branching at end of loop
+        if ¬end_loop then
+            test_branch <- 0b0
+        # test early-exit. ALL will exit if cond_ok fails
+        if ¬cond_ok then
+            end_loop <- 0b1
+            test_branch <- 0b0
     lr_ok <- LRu
-    if ctr_ok & cond_ok then
+    if test_branch & ctr_ok & cond_ok then
       if AA then NIA <-iea EXTS(BD || 0b00)
       else       NIA <-iea CIA + EXTS(BD || 0b00)
       lr_ok <- 0b1
index 157d4598dbca0ea5fcddd387a6c94b923703dfc0..0c1a873093fa2601030862026a5f915d15832531 100644 (file)
@@ -799,7 +799,9 @@ class ISACaller:
             bc_snz = (mode & SVP64MODE.BC_SNZ) != 0
             bc_vsb = yield self.dec2.rm_dec.bc_vsb
             bc_lru = yield self.dec2.rm_dec.bc_lru
+            bc_gate = yield self.dec2.rm_dec.bc_gate
             sz = yield self.dec2.rm_dec.pred_sz
+            self.namespace['ALL'] = SelectableInt(bc_gate, 1)
             self.namespace['VSb'] = SelectableInt(bc_vsb, 1)
             self.namespace['LRu'] = SelectableInt(bc_lru, 1)
             self.namespace['VLSET'] = SelectableInt(bc_vlset, 1)
@@ -1019,7 +1021,8 @@ class ISACaller:
         if not self.respect_pc:
             self.fake_pc += 4
 
-        log("execute one, CIA NIA", self.pc.CIA.value, self.pc.NIA.value)
+        log("execute one, CIA NIA", hex(self.pc.CIA.value),
+                                    hex(self.pc.NIA.value))
 
     def get_assembly_name(self):
         # TODO, asmregs is from the spec, e.g. add RT,RA,RB
@@ -1581,6 +1584,7 @@ class ISACaller:
         # this is our Sub-Program-Counter loop from 0 to VL-1
         pre = False
         post = False
+        nia_update = True
         if self.allow_next_step_inc:
             log("SVSTATE_NEXT: inc requested, mode",
                     self.svstate_next_mode, self.allow_next_step_inc)
@@ -1598,7 +1602,7 @@ class ISACaller:
             else:
                 if self.allow_next_step_inc == 2:
                     log ("SVSTATE_NEXT: read")
-                    yield from self.svstate_post_inc(ins_name)
+                    nia_update = (yield from self.svstate_post_inc(ins_name))
                 else:
                     log ("SVSTATE_NEXT: post-inc")
                 # use actual src/dst-step here to check end, do NOT
@@ -1638,7 +1642,7 @@ class ISACaller:
                     self.svstate.vfirst = 0
 
         elif self.is_svp64_mode:
-            yield from self.svstate_post_inc(ins_name)
+            nia_update = (yield from self.svstate_post_inc(ins_name))
         else:
             # XXX only in non-SVP64 mode!
             # record state of whether the current operation was an svshape,
@@ -1647,7 +1651,8 @@ class ISACaller:
             # to interrupt in between. sigh.
             self.last_op_svshape = asmop == 'svremap'
 
-        self.update_pc_next()
+        if nia_update:
+            self.update_pc_next()
 
     def SVSTATE_NEXT(self, mode, submode):
         """explicitly moves srcstep/dststep on to next element, for
@@ -1796,18 +1801,18 @@ class ISACaller:
             svp64_is_vector = (out_vec or in_vec)
         else:
             svp64_is_vector = out_vec
+        # check if this was an sv.bc* and if so did it succeed
+        if self.is_svp64_mode and insn_name.startswith("sv.bc"):
+            end_loop = self.namespace['end_loop']
+            log("branch %s end_loop" % insn_name, end_loop)
+            if end_loop.value:
+                self.svp64_reset_loop()
+                self.update_pc_next()
+                return False
         if svp64_is_vector and srcstep != vl-1 and dststep != vl-1:
             self.svstate.srcstep += SelectableInt(1, 7)
             self.svstate.dststep += SelectableInt(1, 7)
             self.namespace['SVSTATE'] = self.svstate
-            # check if this was an sv.bc* and if so did it succeed
-            if self.is_svp64_mode and insn_name.startswith("sv.bc"):
-                end_loop = self.namespace['end_loop']
-                log("branch %s end_loop" % insn_name, end_loop)
-                if end_loop.value:
-                    self.svp64_reset_loop()
-                    self.update_pc_next()
-                    return True
             # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
             # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
             # this way we keep repeating the same instruction (with new steps)
@@ -1871,6 +1876,8 @@ def inject():
             log("args[0]", args[0].namespace['CIA'],
                   args[0].namespace['NIA'],
                   args[0].namespace['SVSTATE'])
+            if 'end_loop' in func_globals:
+                log("args[0] end_loop", func_globals['end_loop'])
             args[0].namespace = func_globals
             #exec (func.__code__, func_globals)
 
index 65ba1b70b72c862d5df0d346f25f5b26e83f7d9b..5378040085995813070ccaa9cbe28a1add9a5e81 100644 (file)
@@ -51,13 +51,13 @@ class DecoderTestCase(FHDLTestCase):
             self.assertEqual(sim.gpr(10), SelectableInt(0x1235, 64))
 
     def test_sv_branch_cond(self):
-        for i in [0, 10]: #[0, 10]:
+        for i in [0, 10]: #, 10]: #[0, 10]:
             lst = SVP64Asm(
                 [f"addi 1, 0, {i}",  # set r1 to i
                  f"addi 2, 0, {i}",  # set r2 to i
                 "cmpi cr0, 1, 1, 10",  # compare r1 with 10 and store to cr0
                 "cmpi cr1, 1, 2, 10",  # compare r2 with 10 and store to cr1
-                "sv.bc 12, 2.v, 0x8",    # beq 0x8 -
+                "sv.bc 12, 2.v, 0xc",    # beq 0xc -
                                        # branch if r1 equals 10 to the nop below
                 "addi 3, 0, 0x1234",   # if r1 == 10 this shouldn't execute
                 "or 0, 0, 0"]          # branch target
@@ -77,6 +77,33 @@ class DecoderTestCase(FHDLTestCase):
                 else:
                     self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64))
 
+    def test_sv_branch_cond_all(self):
+        for i in [7, 8, 9]:
+            lst = SVP64Asm(
+                [f"addi 1, 0, {i+1}",  # set r1 to i
+                 f"addi 2, 0, {i}",  # set r2 to i
+                "cmpi cr0, 1, 1, 8",  # compare r1 with 10 and store to cr0
+                "cmpi cr1, 1, 2, 8",  # compare r2 with 10 and store to cr1
+                "sv.bc/all 12, 1.v, 0xc",    # bgt 0xc - branch if BOTH
+                                       # r1 AND r2 greater 8 to the nop below
+                "addi 3, 0, 0x1234",   # if tests fail this shouldn't execute
+                "or 0, 0, 0"]          # branch target
+                )
+            lst = list(lst)
+
+            # SVSTATE (in this case, VL=2)
+            svstate = SVP64State()
+            svstate.vl = 2 # VL
+            svstate.maxvl = 2 # MAXVL
+            print ("SVSTATE", bin(svstate.asint()))
+
+            with Program(lst, bigendian=False) as program:
+                sim = self.run_tst_program(program, svstate=svstate)
+                if i == 9:
+                    self.assertEqual(sim.gpr(3), SelectableInt(0, 64))
+                else:
+                    self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64))
+
     def tst_sv_add_cr(self):
         """>>> lst = ['sv.add. 1.v, 5.v, 9.v'
                        ]
index 96f9e71dce5b4246fd44f1db79cb6717a4eca260..45b292b4c4c32bbff548f2bf299235633d31db6c 100644 (file)
@@ -783,8 +783,8 @@ class SVP64Asm:
             sv_mode = ((bc_svstep << SVP64MODE.MOD2_MSB) |
                       (bc_vlset << SVP64MODE.MOD2_LSB) |
                       (bc_snz << SVP64MODE.BC_SNZ))
-            srcwid = (bc_brc << 1) | bc_vsb
-            destwid = (bc_all << 1) | bc_lru
+            srcwid = (bc_vsb << 1) | bc_lru
+            destwid = (bc_lru << 1) | bc_all
 
         else: