add RC1 support to ISACaller.
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 24 Sep 2022 16:17:55 +0000 (17:17 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 24 Sep 2022 16:17:55 +0000 (17:17 +0100)
this involves:
* reading Rc=0 and substituting RC1 in its place OR
* for non-Rc instructions just putting RC1 in place of Rc
* reading VLi flag and adding it to srcstep to put into VL on ffirst hit
* setting the cr-bit to test to EQ in RC1 mode

src/openpower/consts.py
src/openpower/decoder/isa/caller.py
src/openpower/decoder/isa/test_caller_svp64_dd_ffirst.py
src/openpower/decoder/power_decoder2.py
src/openpower/decoder/power_svp64_rm.py

index 86c4bdb716e9f9f4bf4c6a9b343af117cc8fcf46..2abae0c09a0456652c43a2196ba94136a07c0a19 100644 (file)
@@ -261,6 +261,7 @@ class SVP64MODEb(_Const):
     INV = 2  # invert CR sense 0=set 1=unset
     CR_MSB = 3  # CR bit to update (with Rc=1)
     CR_LSB = 4
+    VLI = 3
     RC1 = 4  # update CR as if Rc=1 (when Rc=0)
     # LD immediate els (element-stride) locations, depending on mode
     ELS_NORMAL = 4
index 8a8a3f6ef0e3c693b68b5d9f7cbb9c22a50e9ec5..5b8bfb2081ae480b2f2dd702eaf7f15beeab2432 100644 (file)
@@ -1352,6 +1352,11 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         else:
             rc_en = False
             rc_ok = False
+        # annoying: ignore rc_ok if RC1 is set (for creating *assembly name*)
+        RC1 = yield self.dec2.rm_dec.RC1
+        if RC1:
+            rc_en = False
+            rc_ok = False
         # grrrr have to special-case MUL op (see DecodeOE)
         log("ov %d en %d rc %d en %d op %d" %
             (ov_ok, ov_en, rc_ok, rc_en, int_op))
@@ -1705,8 +1710,12 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         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
+        RC1 = yield self.dec2.rm_dec.RC1
+        vli = yield self.dec2.rm_dec.vli # VL inclusive if truncated
         log(" ff rm_mode", rc_en, rm_mode, SVP64RMMode.FFIRST.value)
         log("        inv", ff_inv)
+        log("        RC1", RC1)
+        log("        vli", vli)
         log("     cr_bit", cr_bit)
         ffirst_hit = False
         if rc_en and rm_mode == SVP64RMMode.FFIRST.value:
@@ -1716,7 +1725,8 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             log("cr test", regnum, int(crtest), crtest, cr_bit, ff_inv)
             log("cr test?", ffirst_hit)
             if ffirst_hit:
-                self.svstate.vl = srcstep
+                vli = SelectableInt(int(vli), 7)
+                self.svstate.vl = srcstep + vli
                 yield self.dec2.state.svstate.eq(self.svstate.value)
                 yield Settle()  # let decoder update
 
index 297cccdcb615ffbf4a10a7366430595fca48c7cf..f03cb7f7d494c8b97ecb30ad83fc164fe22ce62c 100644 (file)
@@ -66,8 +66,8 @@ class DecoderTestCase(FHDLTestCase):
             self.assertEqual(sim.svstate.srcstep, 0)
             self.assertEqual(sim.svstate.dststep, 0)
 
-    def tst_sv_addi_ffirst_vli(self):
-        lst = SVP64Asm([ "sv.subf/ff=~RC1/vli *0,8,*0"
+    def test_sv_addi_ffirst_vli(self):
+        lst = SVP64Asm([ "sv.subf/ff=RC1/vli *0,8,*0"
                         ])
         lst = list(lst)
 
index dfa6f8f60a9f91a8603e0f5c412fdd690b042e57..22793db8c7a5921ef236dccfbca7e69a4c2324a6 100644 (file)
@@ -983,15 +983,6 @@ class PowerDecodeSubset(Elaboratable):
             comb += dec_bi.sel_in.eq(self.op_get("in2_sel"))
             comb += self.do_copy("imm_data", dec_bi.imm_out)  # imm in RB
 
-        # rc and oe out
-        comb += self.do_copy("rc", dec_rc.rc_out)
-        if self.svp64_en:
-            # OE only enabled when SVP64 not active
-            with m.If(~self.is_svp64_mode):
-                comb += self.do_copy("oe", dec_oe.oe_out)
-        else:
-            comb += self.do_copy("oe", dec_oe.oe_out)
-
         # CR in/out - note: these MUST match with what happens in
         # DecodeCROut!
         rc_out = self.dec_rc.rc_out.data
@@ -1049,6 +1040,26 @@ class PowerDecodeSubset(Elaboratable):
                 )):
                 comb += self.implicit_rs.eq(1)
 
+        # rc and oe out
+        comb += self.do_copy("rc", dec_rc.rc_out)
+        if self.svp64_en:
+            # OE only enabled when SVP64 not active
+            with m.If(~self.is_svp64_mode):
+                comb += self.do_copy("oe", dec_oe.oe_out)
+            # RC1 overrides Rc if rc type is NONE or ONE or Rc=0, in svp64_mode
+            # for instructions with a forced-Rc=1 (stbcx., pcdec.)
+            # the RC1 RM bit *becomes* Rc=0/1, but for instructions
+            # that have Rc=0/1 then when Rc=0 RC1 *becomes* (replaces) Rc.
+            with m.Elif((dec_rc.sel_in.matches(RCOE.RC, RCOE.RC_ONLY) &
+                         dec_rc.rc_out.data == 0) |
+                         (dec_rc.sel_in == RCOE.ONE)):
+                RC1 = Data(1, "RC1")
+                comb += RC1.ok.eq(rm_dec.RC1)
+                comb += RC1.RC1.eq(rm_dec.RC1)
+                comb += self.do_copy("rc", RC1)
+        else:
+            comb += self.do_copy("oe", dec_oe.oe_out)
+
         # decoded/selected instruction flags
         comb += self.do_copy("data_len", self.op_get("ldst_len"))
         comb += self.do_copy("invert_in", self.op_get("inv_a"))
index 04bccc684dc3c3d24d127dbacb1c97790e8af7ef..155905a4b9a15c2272fa512ceed14749c04715b6 100644 (file)
@@ -129,6 +129,7 @@ class SVP64RMModeDecode(Elaboratable):
         self.subvl= Signal(2) # subvl
         self.saturate = Signal(SVP64sat)
         self.RC1 = Signal()
+        self.vli = Signal()
         self.cr_sel = Signal(2)  # bit of CR to test (index 0-3)
         self.inv = Signal(1)     # and whether it's inverted (like branch BO)
         self.map_evm = Signal(1)
@@ -218,9 +219,14 @@ class SVP64RMModeDecode(Elaboratable):
 
             # extract failfirst
             with m.If(self.mode == SVP64RMMode.FFIRST): # fail-first
+                comb += self.inv.eq(mode[SVP64MODE.INV])
                 with m.If(self.rc_in):
-                    comb += self.inv.eq(mode[SVP64MODE.INV])
                     comb += self.cr_sel.eq(cr)
+                with m.Else():
+                    # only when Rc=0
+                    comb += self.RC1.eq(mode[SVP64MODE.RC1])
+                    comb += self.vli.eq(mode[SVP64MODE.VLI])
+                    comb += self.cr_sel.eq(0b10) # EQ bit index is implicit
 
             # extract saturate
             with m.Switch(mode2):