split PowerDecodeSubset do_copy into do_copy and do_get
[openpower-isa.git] / src / openpower / decoder / power_decoder2.py
index c0d523d680352d1aa782d45e43ebbec7321f0e45..cb5d6719c22847fdfd76b7b15aceb03d1131a178 100644 (file)
@@ -10,36 +10,35 @@ from nmigen import Module, Elaboratable, Signal, Mux, Const, Cat, Repl, Record
 from nmigen.cli import rtlil
 from nmutil.util import sel
 
-from soc.regfile.regfiles import XERRegs
-
 from nmutil.picker import PriorityPicker
 from nmutil.iocontrol import RecordObject
 from nmutil.extend import exts
 
-from soc.experiment.mem_types import LDSTException
+from openpower.exceptions import LDSTException
+
+from openpower.decoder.power_svp64_prefix import SVP64PrefixDecoder
+from openpower.decoder.power_svp64_extra import SVP64CRExtra, SVP64RegExtra
+from openpower.decoder.power_svp64_rm import (SVP64RMModeDecode,
+                                              sv_input_record_layout)
+from openpower.sv.svp64 import SVP64Rec
 
-from soc.decoder.power_svp64_prefix import SVP64PrefixDecoder
-from soc.decoder.power_svp64_extra import SVP64CRExtra, SVP64RegExtra
-from soc.decoder.power_svp64_rm import SVP64RMModeDecode
-from soc.decoder.power_regspec_map import regspec_decode_read
-from soc.decoder.power_regspec_map import regspec_decode_write
-from soc.decoder.power_decoder import create_pdecode
-from soc.decoder.power_enums import (MicrOp, CryIn, Function,
+from openpower.decoder.power_regspec_map import regspec_decode_read
+from openpower.decoder.power_decoder import create_pdecode
+from openpower.decoder.power_enums import (MicrOp, CryIn, Function,
                                      CRInSel, CROutSel,
                                      LdstLen, In1Sel, In2Sel, In3Sel,
                                      OutSel, SPRfull, SPRreduced,
                                      RC, LDSTMode,
                                      SVEXTRA, SVEtype, SVPtype)
-from soc.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
-                                         Decode2ToOperand)
-from soc.sv.svp64 import SVP64Rec
-from soc.consts import (MSR, SPEC, EXTRA2, EXTRA3, SVP64P, field,
-                        SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs)
+from openpower.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
+                                               Decode2ToOperand)
+
+from openpower.consts import (MSR, SPEC, EXTRA2, EXTRA3, SVP64P, field,
+                              SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs,
+                              FastRegsEnum, XERRegsEnum, TT)
 
-from soc.regfile.regfiles import FastRegs
-from soc.consts import TT
-from soc.config.state import CoreState
-from soc.regfile.util import spr_to_fast
+from openpower.state import CoreState
+from openpower.util import spr_to_fast
 
 
 def decode_spr_num(spr):
@@ -146,14 +145,14 @@ class DecodeA(Elaboratable):
             with m.Case(MicrOp.OP_BC):
                 with m.If(~self.dec.BO[2]):  # 3.0B p38 BO2=0, use CTR reg
                     # constant: CTR
-                    comb += self.fast_out.data.eq(FastRegs.CTR)
+                    comb += self.fast_out.data.eq(FastRegsEnum.CTR)
                     comb += self.fast_out.ok.eq(1)
             with m.Case(MicrOp.OP_BCREG):
                 xo9 = self.dec.FormXL.XO[9]  # 3.0B p38 top bit of XO
                 xo5 = self.dec.FormXL.XO[5]  # 3.0B p38
                 with m.If(xo9 & ~xo5):
                     # constant: CTR
-                    comb += self.fast_out.data.eq(FastRegs.CTR)
+                    comb += self.fast_out.data.eq(FastRegsEnum.CTR)
                     comb += self.fast_out.ok.eq(1)
 
             # MFSPR move from SPRs
@@ -235,10 +234,10 @@ class DecodeB(Elaboratable):
             xo9 = self.dec.FormXL.XO[9]  # 3.0B p38 top bit of XO
             xo5 = self.dec.FormXL.XO[5]  # 3.0B p38
             with m.If(~xo9):
-                comb += self.fast_out.data.eq(FastRegs.LR)
+                comb += self.fast_out.data.eq(FastRegsEnum.LR)
                 comb += self.fast_out.ok.eq(1)
             with m.Elif(xo5):
-                comb += self.fast_out.data.eq(FastRegs.TAR)
+                comb += self.fast_out.data.eq(FastRegsEnum.TAR)
                 comb += self.fast_out.ok.eq(1)
 
         return m
@@ -385,12 +384,12 @@ class DecodeOut(Elaboratable):
             with m.Case(MicrOp.OP_BC, MicrOp.OP_BCREG):
                 with m.If(~self.dec.BO[2]):  # 3.0B p38 BO2=0, use CTR reg
                     # constant: CTR
-                    comb += self.fast_out.data.eq(FastRegs.CTR)
+                    comb += self.fast_out.data.eq(FastRegsEnum.CTR)
                     comb += self.fast_out.ok.eq(1)
 
             # RFID 1st spr (fast)
             with m.Case(MicrOp.OP_RFID):
-                comb += self.fast_out.data.eq(FastRegs.SRR0)  # constant: SRR0
+                comb += self.fast_out.data.eq(FastRegsEnum.SRR0)  # SRR0
                 comb += self.fast_out.ok.eq(1)
 
         return m
@@ -417,6 +416,7 @@ class DecodeOut2(Elaboratable):
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(5, "reg_o2")
         self.fast_out = Data(3, "fast_o2")
+        self.fast_out3 = Data(3, "fast_o3")
 
     def elaborate(self, platform):
         m = Module()
@@ -440,13 +440,15 @@ class DecodeOut2(Elaboratable):
             # BC* implicit register (LR)
             with m.Case(MicrOp.OP_BC, MicrOp.OP_B, MicrOp.OP_BCREG):
                 with m.If(self.lk):  # "link" mode
-                    comb += self.fast_out.data.eq(FastRegs.LR)  # constant: LR
+                    comb += self.fast_out.data.eq(FastRegsEnum.LR)  # LR
                     comb += self.fast_out.ok.eq(1)
 
-            # RFID 2nd spr (fast)
+            # RFID 2nd and 3rd spr (fast)
             with m.Case(MicrOp.OP_RFID):
-                comb += self.fast_out.data.eq(FastRegs.SRR1)  # constant: SRR1
+                comb += self.fast_out.data.eq(FastRegsEnum.SRR1)  # SRR1
                 comb += self.fast_out.ok.eq(1)
+                comb += self.fast_out3.data.eq(FastRegsEnum.SVSRR0) # SVSRR0
+                comb += self.fast_out3.ok.eq(1)
 
         return m
 
@@ -679,6 +681,7 @@ class DecodeCROut(Elaboratable):
 # to be decoded (this includes the single bit names)
 record_names = {'insn_type': 'internal_op',
                 'fn_unit': 'function_unit',
+                'SV_Ptype': 'SV_Ptype',
                 'rc': 'rc_sel',
                 'oe': 'rc_sel',
                 'zero_a': 'in1_sel',
@@ -711,6 +714,7 @@ class PowerDecodeSubset(Elaboratable):
         self.regreduce_en = regreduce_en
         if svp64_en:
             self.sv_rm = SVP64Rec(name="dec_svp64") # SVP64 RM field
+            self.rm_dec = SVP64RMModeDecode("svp64_rm_dec")
         self.sv_a_nz = Signal(1)
         self.final = final
         self.opkls = opkls
@@ -776,13 +780,17 @@ class PowerDecodeSubset(Elaboratable):
             do = self.e_tmp.do
         return hasattr(do, field) and self.op_get(op_field) is not None
 
-    def do_copy(self, field, val, final=False):
+    def do_get(self, field, final=False):
         if final or self.final:
             do = self.do
         else:
             do = self.e_tmp.do
-        if hasattr(do, field) and val is not None:
-            return getattr(do, field).eq(val)
+        return getattr(do, field, None)
+
+    def do_copy(self, field, val, final=False):
+        df = self.do_get(field, final)
+        if df is not None and val is not None:
+            return df.eq(val)
         return []
 
     def op_get(self, op_field):
@@ -797,7 +805,7 @@ class PowerDecodeSubset(Elaboratable):
         comb = m.d.comb
         state = self.state
         op, do = self.dec.op, self.do
-        msr, cia = state.msr, state.pc
+        msr, cia, svstate = state.msr, state.pc, state.svstate
         # fill in for a normal instruction (not an exception)
         # copy over if non-exception, non-privileged etc. is detected
         if not self.final:
@@ -813,6 +821,10 @@ class PowerDecodeSubset(Elaboratable):
         m.submodules.dec_rc = self.dec_rc = dec_rc = DecodeRC(self.dec)
         m.submodules.dec_oe = dec_oe = DecodeOE(self.dec)
 
+        if self.svp64_en:
+            # and SVP64 RM mode decoder
+            m.submodules.sv_rm_dec = rm_dec = self.rm_dec
+
         # copy instruction through...
         for i in [do.insn, dec_rc.insn_in, dec_oe.insn_in, ]:
             comb += i.eq(self.dec.opcode_in)
@@ -824,6 +836,7 @@ class PowerDecodeSubset(Elaboratable):
         # copy "state" over
         comb += self.do_copy("msr", msr)
         comb += self.do_copy("cia", cia)
+        comb += self.do_copy("svstate", svstate)
 
         # set up instruction type
         # no op: defaults to OP_ILLEGAL
@@ -885,6 +898,14 @@ class PowerDecodeSubset(Elaboratable):
         comb += self.do_copy("input_cr", self.op_get("cr_in"))   # CR in
         comb += self.do_copy("output_cr", self.op_get("cr_out"))  # CR out
 
+        if self.svp64_en:
+            # connect up SVP64 RM Mode decoding
+            fn = self.op_get("function_unit")
+            comb += rm_dec.fn_in.eq(fn) # decode needs to know if LD/ST type
+            comb += rm_dec.ptype_in.eq(op.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
+
         # 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"))
@@ -902,6 +923,15 @@ class PowerDecodeSubset(Elaboratable):
         comb += self.do_copy("sign_extend", self.op_get("sgn_ext"))
         comb += self.do_copy("ldst_mode", self.op_get("upd"))  # LD/ST mode
 
+        # copy over SVP64 input record fields (if they exist)
+        if self.svp64_en:
+            # TODO, really do we have to do these explicitly?? sigh
+            #for (field, _) in sv_input_record_layout:
+            #    comb += self.do_copy(field, self.rm_dec.op_get(field))
+            comb += self.do_copy("sv_pred_sz", self.rm_dec.pred_sz)
+            comb += self.do_copy("sv_pred_dz", self.rm_dec.pred_dz)
+            comb += self.do_copy("sv_saturate", self.rm_dec.saturate)
+            comb += self.do_copy("sv_Ptype", self.rm_dec.ptype_in)
         return m
 
 
@@ -940,7 +970,7 @@ class PowerDecode2(PowerDecodeSubset):
                             state=None, svp64_en=True, regreduce_en=False):
         super().__init__(dec, opkls, fn_name, final, state, svp64_en,
                          regreduce_en=False)
-        self.exc = LDSTException("dec2_exc")
+        self.ldst_exc = LDSTException("dec2_exc")
 
         if self.svp64_en:
             self.cr_out_isvec = Signal(1, name="cr_out_isvec")
@@ -955,7 +985,6 @@ class PowerDecode2(PowerDecodeSubset):
             self.no_in_vec = Signal(1, name="no_in_vec") # no inputs vector
             self.no_out_vec = Signal(1, name="no_out_vec") # no outputs vector
             self.loop_continue = Signal(1, name="loop_continue")
-            self.rm_dec = SVP64RMModeDecode("svp64_rm_dec")
         else:
             self.no_in_vec = Const(1, 1)
             self.no_out_vec = Const(1, 1)
@@ -978,6 +1007,9 @@ class PowerDecode2(PowerDecodeSubset):
             subset.add("sv_cr_out")
             subset.add("SV_Etype")
             subset.add("SV_Ptype")
+            # from SVP64RMModeDecode
+            for (field, _) in sv_input_record_layout:
+                subset.add(field)
         subset.add("lk")
         subset.add("internal_op")
         subset.add("form")
@@ -1021,9 +1053,6 @@ class PowerDecode2(PowerDecodeSubset):
             # debug access to crout_svdec (used in get_pdecode_cr_out)
             self.crout_svdec = crout_svdec
 
-            # and SVP64 RM mode decoder
-            m.submodules.sv_rm_dec = rm_dec = self.rm_dec
-
         # get the 5-bit reg data before svp64-munging it into 7-bit plus isvec
         reg = Signal(5, reset_less=True)
 
@@ -1198,19 +1227,12 @@ class PowerDecode2(PowerDecodeSubset):
         comb += e.read_spr1.eq(dec_a.spr_out)
         comb += e.write_spr.eq(dec_o.spr_out)
 
-        # Fast regs out
+        # Fast regs out including SRR0/1/SVSRR0
         comb += e.read_fast1.eq(dec_a.fast_out)
         comb += e.read_fast2.eq(dec_b.fast_out)
-        comb += e.write_fast1.eq(dec_o.fast_out)
-        comb += e.write_fast2.eq(dec_o2.fast_out)
-
-        if self.svp64_en:
-            # connect up SVP64 RM Mode decoding
-            fn = self.op_get("function_unit")
-            comb += rm_dec.fn_in.eq(fn) # decode needs to know if LD/ST type
-            comb += rm_dec.ptype_in.eq(op.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
+        comb += e.write_fast1.eq(dec_o.fast_out)   # SRR0 (OP_RFID)
+        comb += e.write_fast2.eq(dec_o2.fast_out)  # SRR1 (ditto)
+        comb += e.write_fast3.eq(dec_o2.fast_out3) # SVSRR0 (ditto)
 
         # sigh this is exactly the sort of thing for which the
         # decoder is designed to not need.  MTSPR, MFSPR and others need
@@ -1218,7 +1240,7 @@ class PowerDecode2(PowerDecodeSubset):
         with m.If(op.internal_op == MicrOp.OP_MFSPR):
             comb += e.xer_in.eq(0b111) # SO, CA, OV
         with m.If(op.internal_op == MicrOp.OP_CMP):
-            comb += e.xer_in.eq(1<<XERRegs.SO) # SO
+            comb += e.xer_in.eq(1<<XERRegsEnum.SO) # SO
         with m.If(op.internal_op == MicrOp.OP_MTSPR):
             comb += e.xer_out.eq(1)
 
@@ -1244,7 +1266,7 @@ class PowerDecode2(PowerDecodeSubset):
         dec_irq_ok = Signal()
         priv_ok = Signal()
         illeg_ok = Signal()
-        exc = self.exc
+        ldst_exc = self.ldst_exc
 
         comb += ext_irq_ok.eq(ext_irq & msr[MSR.EE]) # v3.0B p944 (MSR.EE)
         comb += dec_irq_ok.eq(dec_spr[63] & msr[MSR.EE]) # 6.5.11 p1076
@@ -1253,17 +1275,17 @@ class PowerDecode2(PowerDecodeSubset):
 
         # LD/ST exceptions.  TestIssuer copies the exception info at us
         # after a failed LD/ST.
-        with m.If(exc.happened):
-            with m.If(exc.alignment):
+        with m.If(ldst_exc.happened):
+            with m.If(ldst_exc.alignment):
                 self.trap(m, TT.PRIV, 0x600)
-            with m.Elif(exc.instr_fault):
-                with m.If(exc.segment_fault):
+            with m.Elif(ldst_exc.instr_fault):
+                with m.If(ldst_exc.segment_fault):
                     self.trap(m, TT.PRIV, 0x480)
                 with m.Else():
                     # pass exception info to trap to create SRR1
-                    self.trap(m, TT.MEMEXC, 0x400, exc)
+                    self.trap(m, TT.MEMEXC, 0x400, ldst_exc)
             with m.Else():
-                with m.If(exc.segment_fault):
+                with m.If(ldst_exc.segment_fault):
                     self.trap(m, TT.PRIV, 0x380)
                 with m.Else():
                     self.trap(m, TT.PRIV, 0x300)
@@ -1300,20 +1322,26 @@ class PowerDecode2(PowerDecodeSubset):
         with m.If((do_out.insn_type == MicrOp.OP_TRAP) |
                   (do_out.insn_type == MicrOp.OP_SC)):
             # TRAP write fast1 = SRR0
-            comb += e_out.write_fast1.data.eq(FastRegs.SRR0)  # constant: SRR0
+            comb += e_out.write_fast1.data.eq(FastRegsEnum.SRR0)  # SRR0
             comb += e_out.write_fast1.ok.eq(1)
             # TRAP write fast2 = SRR1
-            comb += e_out.write_fast2.data.eq(FastRegs.SRR1)  # constant: SRR1
+            comb += e_out.write_fast2.data.eq(FastRegsEnum.SRR1)  # SRR1
             comb += e_out.write_fast2.ok.eq(1)
+            # TRAP write fast2 = SRR1
+            comb += e_out.write_fast3.data.eq(FastRegsEnum.SVSRR0)  # SVSRR0
+            comb += e_out.write_fast3.ok.eq(1)
 
         # RFID: needs to read SRR0/1
         with m.If(do_out.insn_type == MicrOp.OP_RFID):
             # TRAP read fast1 = SRR0
-            comb += e_out.read_fast1.data.eq(FastRegs.SRR0)  # constant: SRR0
+            comb += e_out.read_fast1.data.eq(FastRegsEnum.SRR0)  # SRR0
             comb += e_out.read_fast1.ok.eq(1)
             # TRAP read fast2 = SRR1
-            comb += e_out.read_fast2.data.eq(FastRegs.SRR1)  # constant: SRR1
+            comb += e_out.read_fast2.data.eq(FastRegsEnum.SRR1)  # SRR1
             comb += e_out.read_fast2.ok.eq(1)
+            # TRAP read fast2 = SVSRR0
+            comb += e_out.read_fast3.data.eq(FastRegsEnum.SVSRR0)  # SVSRR0
+            comb += e_out.read_fast3.ok.eq(1)
 
         # annoying simulator bug
         if hasattr(e_out, "asmcode") and hasattr(self.dec.op, "asmcode"):
@@ -1321,7 +1349,7 @@ class PowerDecode2(PowerDecodeSubset):
 
         return m
 
-    def trap(self, m, traptype, trapaddr, exc=None):
+    def trap(self, m, traptype, trapaddr, ldst_exc=None):
         """trap: this basically "rewrites" the decoded instruction as a trap
         """
         comb = m.d.comb
@@ -1334,9 +1362,10 @@ class PowerDecode2(PowerDecodeSubset):
         comb += self.do_copy("fn_unit", Function.TRAP, True)
         comb += self.do_copy("trapaddr", trapaddr >> 4, True) # bottom 4 bits
         comb += self.do_copy("traptype", traptype, True)  # request type
-        comb += self.do_copy("ldst_exc", exc, True)  # request type
+        comb += self.do_copy("ldst_exc", ldst_exc, True)  # request type
         comb += self.do_copy("msr", self.state.msr, True) # copy of MSR "state"
         comb += self.do_copy("cia", self.state.pc, True)  # copy of PC "state"
+        comb += self.do_copy("svstate", self.state.svstate, True)  # SVSTATE