only add svdecldst in PowerDecoder2 or LDST PowerDecodeSubset
[openpower-isa.git] / src / openpower / decoder / power_decoder2.py
index 81279ca5ec6918400f2b03848b520ebedd36dd24..5c2b259abce79e6770f60553c9abebbb91c9f8fe 100644 (file)
@@ -25,12 +25,13 @@ from openpower.sv.svp64 import SVP64Rec
 
 from openpower.decoder.power_regspec_map import regspec_decode_read
 from openpower.decoder.power_decoder import (create_pdecode,
-                                             create_pdecode_svp64,)
+                                             create_pdecode_svp64_ldst,
+                                             PowerOp)
 from openpower.decoder.power_enums import (MicrOp, CryIn, Function,
                                      CRInSel, CROutSel,
                                      LdstLen, In1Sel, In2Sel, In3Sel,
                                      OutSel, SPRfull, SPRreduced,
-                                     RC, LDSTMode,
+                                     RC, SVP64LDSTmode, LDSTMode,
                                      SVEXTRA, SVEtype, SVPtype)
 from openpower.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
                                                Decode2ToOperand)
@@ -752,6 +753,8 @@ class PowerDecodeSubset(Elaboratable):
         self.svp64_en = svp64_en
         self.regreduce_en = regreduce_en
         if svp64_en:
+            self.is_svp64_mode = Signal() # mark decoding as SVP64 Mode
+            self.use_svp64_ldst_dec = Signal() # must use LDST decoder
             self.sv_rm = SVP64Rec(name="dec_svp64") # SVP64 RM field
             self.rm_dec = SVP64RMModeDecode("svp64_rm_dec")
             # set these to the predicate mask bits needed for the ALU
@@ -776,16 +779,22 @@ class PowerDecodeSubset(Elaboratable):
             dec = create_pdecode(name=fn_name, col_subset=col_subset,
                                       row_subset=self.rowsubsetfn)
         self.dec = dec
-        # create SVP64 decoder
-        if svp64_en:
+
+        # create SVP64 LDST decoder
+        if svp64_en and (not final or fn_name.lower().startswith("ldst")):
             if fn_name:
                 name = "sv_"+fn_name
             else:
                 name = "svdec"
-            svdec = create_pdecode(name=name,
-                                      col_subset=col_subset,
-                                      row_subset=self.rowsubsetfn)
-            self.svdec = svdec
+            svdecldst = create_pdecode_svp64_ldst(name=name,
+                                              col_subset=col_subset,
+                                              row_subset=self.rowsubsetfn)
+            self.svdecldst = svdecldst
+        else:
+            self.svdecldst = None
+
+        # set up a copy of the PowerOp
+        self.op = PowerOp.like(self.dec.op)
 
         # state information needed by the Decoder
         if state is None:
@@ -823,7 +832,8 @@ class PowerDecodeSubset(Elaboratable):
         ports = self.dec.ports() + self.e.ports()
         if self.svp64_en:
             ports += self.sv_rm.ports()
-            ports += self.svdec.ports()
+        if self.svdecldst:
+            ports += self.svdecldst.ports()
         return ports
 
     def needs_field(self, field, op_field):
@@ -847,7 +857,7 @@ class PowerDecodeSubset(Elaboratable):
         return []
 
     def op_get(self, op_field):
-        return getattr(self.dec.op, op_field, None)
+        return getattr(self.op, op_field, None)
 
     def elaborate(self, platform):
         if self.regreduce_en:
@@ -874,11 +884,16 @@ class PowerDecodeSubset(Elaboratable):
         m.submodules.dec_rc = self.dec_rc = dec_rc = DecodeRC(self.dec)
         m.submodules.dec_oe = dec_oe = DecodeOE(self.dec, op)
 
+        # use op from first decoder (self.dec.op) if not in SVP64-LDST mode
+        # (TODO)
+        comb += self.op.eq(self.dec.op)
+
         if self.svp64_en:
             # and SVP64 RM mode decoder
             m.submodules.sv_rm_dec = rm_dec = self.rm_dec
+        if self.svdecldst:
             # and SVP64 decoder
-            m.submodules.svdec = svdec = self.svdec
+            m.submodules.svdecldst = svdecldst = self.svdecldst
 
         # copy instruction through...
         for i in [do.insn, dec_rc.insn_in, dec_oe.insn_in, ]:
@@ -954,16 +969,39 @@ class PowerDecodeSubset(Elaboratable):
         comb += self.do_copy("output_cr", self.op_get("cr_out"))  # CR out
 
         if self.svp64_en:
-            # connect up SVP64 RM Mode decoding
+            # connect up SVP64 RM Mode decoding.  however... we need a shorter
+            # path, for the LDST bit-reverse detection.  so perform partial
+            # decode when SVP64 is detected.  then, bit-reverse mode can be
+            # quickly determined, and the Decoder result MUXed over to
+            # the alternative decoder, svdecldst. what a mess... *sigh*
             sv_ptype = self.op_get("SV_Ptype")
             fn = self.op_get("function_unit")
-            comb += rm_dec.fn_in.eq(fn) # decode needs to know if LD/ST type
+            # detect major opcode for LDs: include 58 here. from CSV files.
+            is_major_ld = Signal()
+            major = Signal(6) # bits... errr... MSB0 0..5 which is 26:32 python
+            comb += major.eq(self.dec.opcode_in[26:32])
+            comb += is_major_ld.eq((major == 34) | (major == 35) |
+                                   (major == 50) | (major == 51) |
+                                   (major == 48) | (major == 49) |
+                                   (major == 42) | (major == 43) |
+                                   (major == 40) | (major == 41) |
+                                   (major == 32) | (major == 33) |
+                                   (major == 58))
+            with m.If(self.is_svp64_mode & is_major_ld):
+                # straight-up: "it's a LD"
+                comb += rm_dec.fn_in.eq(Function.LDST)
+            with m.Else():
+                comb += rm_dec.fn_in.eq(fn) # decode needs to know Fn type
             comb += rm_dec.ptype_in.eq(sv_ptype) # Single/Twin predicated
             comb += rm_dec.rc_in.eq(rc_out) # Rc=1
             comb += rm_dec.rm_in.eq(self.sv_rm) # SVP64 RM mode
             if self.needs_field("imm_data", "in2_sel"):
                 bzero = dec_bi.imm_out.ok & ~dec_bi.imm_out.data.bool()
                 comb += rm_dec.ldst_imz_in.eq(bzero) # B immediate is zero
+            # main PowerDecoder2 determines if bit-reverse mode requested
+            if not self.final:
+                bitrev = rm_dec.ldstmode == SVP64LDSTmode.BITREVERSE
+                comb += self.use_svp64_ldst_dec.eq(bitrev)
 
         # decoded/selected instruction flags
         comb += self.do_copy("data_len", self.op_get("ldst_len"))
@@ -1084,7 +1122,7 @@ class PowerDecode2(PowerDecodeSubset):
         m = super().elaborate(platform)
         comb = m.d.comb
         state = self.state
-        e_out, op, do_out = self.e, self.dec.op, self.e.do
+        op, e_out, do_out = self.op, self.e, self.e.do
         dec_spr, msr, cia, ext_irq = state.dec, state.msr, state.pc, state.eint
         rc_out = self.dec_rc.rc_out.data
         e = self.e_tmp
@@ -1317,11 +1355,12 @@ class PowerDecode2(PowerDecodeSubset):
         # sigh this is exactly the sort of thing for which the
         # decoder is designed to not need.  MTSPR, MFSPR and others need
         # access to the XER bits.  however setting e.oe is not appropriate
-        with m.If(op.internal_op == MicrOp.OP_MFSPR):
+        internal_op = self.op_get("internal_op")
+        with m.If(internal_op == MicrOp.OP_MFSPR):
             comb += e.xer_in.eq(0b111) # SO, CA, OV
-        with m.If(op.internal_op == MicrOp.OP_CMP):
+        with m.If(internal_op == MicrOp.OP_CMP):
             comb += e.xer_in.eq(1<<XERRegsEnum.SO) # SO
-        with m.If(op.internal_op == MicrOp.OP_MTSPR):
+        with m.If(internal_op == MicrOp.OP_MTSPR):
             comb += e.xer_out.eq(1)
 
         # set the trapaddr to 0x700 for a td/tw/tdi/twi operation