fix Bug 607 - unnecessary code added related to MMU in PowerDecoder2
[soc.git] / src / soc / decoder / power_decoder2.py
index 27ce810acec850618c2bfd2c114c83f0cd334a50..4cee7ab7c903faeef3416db3f530ed2a10faed98 100644 (file)
@@ -8,6 +8,8 @@ over-riding the internal opcode when an exception is needed.
 
 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
@@ -27,7 +29,7 @@ from soc.decoder.power_enums import (MicrOp, CryIn, Function,
 from soc.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
                                          Decode2ToOperand)
 from soc.sv.svp64 import SVP64Rec
-from soc.consts import (MSR, sel, SPEC, EXTRA2, EXTRA3, SVP64P, field,
+from soc.consts import (MSR, SPEC, EXTRA2, EXTRA3, SVP64P, field,
                         SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs)
 
 from soc.regfile.regfiles import FastRegs
@@ -122,11 +124,14 @@ class SVP64ExtraSpec(Elaboratable):
             with m.Case(SVEtype.EXTRA3):
                 with m.Switch(self.idx):
                     with m.Case(SVEXTRA.Idx0):  # 1st 3 bits [0:2]
-                        comb += spec.eq(sel(extra, EXTRA3.IDX0))
+                        extra3_idx0 = sel(m, extra, EXTRA3.IDX0)
+                        comb += spec.eq(extra3_idx0)
                     with m.Case(SVEXTRA.Idx1):  # 2nd 3 bits [3:5]
-                        comb += spec.eq(sel(extra, EXTRA3.IDX1))
+                        extra3_idx1 = sel(m, extra, EXTRA3.IDX1)
+                        comb += spec.eq(extra3_idx1)
                     with m.Case(SVEXTRA.Idx2):  # 3rd 3 bits [6:8]
-                        comb += spec.eq(sel(extra, EXTRA3.IDX2))
+                        extra3_idx2 = sel(m, extra, EXTRA3.IDX2)
+                        comb += spec.eq(extra3_idx2)
                     # cannot fit more than 9 bits so there is no 4th thing
 
         return m
@@ -746,6 +751,12 @@ class DecodeCROut(Elaboratable):
         comb += self.whole_reg.ok.eq(0)
         comb += self.sv_override.eq(0)
 
+        # please note these MUST match (setting of cr_bitfield.ok) exactly
+        # with write_cr0 below in PowerDecoder2.  the reason it's separated
+        # is to avoid having duplicate copies of DecodeCROut in multiple
+        # PowerDecoderSubsets.  register decoding should be a one-off in
+        # PowerDecoder2.  see https://bugs.libre-soc.org/show_bug.cgi?id=606
+
         with m.Switch(self.sel_in):
             with m.Case(CROutSel.NONE):
                 pass  # No bitfield activated
@@ -878,7 +889,6 @@ class PowerDecodeSubset(Elaboratable):
         state = self.state
         op, do = self.dec.op, self.do
         msr, cia = state.msr, state.pc
-
         # fill in for a normal instruction (not an exception)
         # copy over if non-exception, non-privileged etc. is detected
         if not self.final:
@@ -890,23 +900,16 @@ class PowerDecodeSubset(Elaboratable):
 
         # set up submodule decoders
         m.submodules.dec = self.dec
-        m.submodules.dec_rc = dec_rc = DecodeRC(self.dec)
+        m.submodules.dec_rc = self.dec_rc = dec_rc = DecodeRC(self.dec)
         m.submodules.dec_oe = dec_oe = DecodeOE(self.dec)
-        m.submodules.dec_cr_in = self.dec_cr_in = DecodeCRIn(self.dec)
-        m.submodules.dec_cr_out = self.dec_cr_out = DecodeCROut(self.dec)
 
         # copy instruction through...
-        for i in [do.insn,
-                  dec_rc.insn_in, dec_oe.insn_in,
-                  self.dec_cr_in.insn_in, self.dec_cr_out.insn_in]:
+        for i in [do.insn, dec_rc.insn_in, dec_oe.insn_in, ]:
             comb += i.eq(self.dec.opcode_in)
 
         # ...and subdecoders' input fields
         comb += dec_rc.sel_in.eq(op.rc_sel)
         comb += dec_oe.sel_in.eq(op.rc_sel)  # XXX should be OE sel
-        comb += self.dec_cr_in.sel_in.eq(op.cr_in)
-        comb += self.dec_cr_out.sel_in.eq(op.cr_out)
-        comb += self.dec_cr_out.rc_in.eq(dec_rc.rc_out.data)
 
         # copy "state" over
         comb += self.do_copy("msr", msr)
@@ -914,16 +917,8 @@ class PowerDecodeSubset(Elaboratable):
 
         # set up instruction type
         # no op: defaults to OP_ILLEGAL
-        if self.fn_name=="MMU":
-            # mmu is special case: needs SPR opcode as well
-            mmu0 = self.mmu0_spr_dec
-            with m.If(((mmu0.dec.op.internal_op == MicrOp.OP_MTSPR) |
-                       (mmu0.dec.op.internal_op == MicrOp.OP_MFSPR))):
-                comb += self.do_copy("insn_type", mmu0.op_get("internal_op"))
-            with m.Else():
-                comb += self.do_copy("insn_type", self.op_get("internal_op"))
-        else:
-            comb += self.do_copy("insn_type", self.op_get("internal_op"))
+        # FIX https://bugs.libre-soc.org/show_bug.cgi?id=607
+        comb += self.do_copy("insn_type", self.op_get("internal_op"))
 
         # function unit for decoded instruction: requires minor redirect
         # for SPR set/get
@@ -931,18 +926,12 @@ class PowerDecodeSubset(Elaboratable):
         spr = Signal(10, reset_less=True)
         comb += spr.eq(decode_spr_num(self.dec.SPR)) # from XFX
 
-        # XXX BUG - don't use hardcoded magic constants.
-        # also use ".value" otherwise the test fails.  bit of a pain
-        # https://bugs.libre-soc.org/show_bug.cgi?id=603
-
-        SPR_PID   = 48  # TODO read docs for POWER9
         # Microwatt doesn't implement the partition table
-        # instead has PRTBL register (SPR) to point to process table
-        SPR_PRTBL = 720 # see common.vhdl in microwatt, not in POWER9
+        # instead has PRTBL(SVSRR0) register (SPR) to point to process table
         with m.If(((self.dec.op.internal_op == MicrOp.OP_MTSPR) |
                    (self.dec.op.internal_op == MicrOp.OP_MFSPR)) &
-                  ((spr == SPR.DSISR) | (spr == SPR.DAR)
-                   | (spr==SPR_PRTBL) | (spr==SPR_PID))):
+                   ((spr == SPR.DSISR.value) | (spr == SPR.DAR.value) |
+                     (spr==SPR.SVSRR0.value) | (spr==SPR.PIDR.value))):
             comb += self.do_copy("fn_unit", Function.MMU)
         with m.Else():
             comb += self.do_copy("fn_unit",fn)
@@ -961,10 +950,14 @@ class PowerDecodeSubset(Elaboratable):
         comb += self.do_copy("rc", dec_rc.rc_out)
         comb += self.do_copy("oe", dec_oe.oe_out)
 
-        # CR in/out
-        comb += self.do_copy("read_cr_whole", self.dec_cr_in.whole_reg)
-        comb += self.do_copy("write_cr_whole", self.dec_cr_out.whole_reg)
-        comb += self.do_copy("write_cr0", self.dec_cr_out.cr_bitfield.ok)
+        # CR in/out - note: these MUST match with what happens in
+        # DecodeCROut!
+        rc_out = self.dec_rc.rc_out.data
+        with m.Switch(op.cr_out):
+            with m.Case(CROutSel.CR0, CROutSel.CR1):
+                comb += self.do_copy("write_cr0", rc_out) # only when RC=1
+            with m.Case(CROutSel.BF, CROutSel.BT):
+                comb += self.do_copy("write_cr0", 1)
 
         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
@@ -1061,6 +1054,7 @@ class PowerDecode2(PowerDecodeSubset):
         state = self.state
         e_out, op, do_out = self.e, self.dec.op, 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
         do = e.do
 
@@ -1073,6 +1067,8 @@ class PowerDecode2(PowerDecodeSubset):
         m.submodules.dec_c = dec_c = DecodeC(self.dec)
         m.submodules.dec_o = dec_o = DecodeOut(self.dec)
         m.submodules.dec_o2 = dec_o2 = DecodeOut2(self.dec)
+        m.submodules.dec_cr_in = self.dec_cr_in = DecodeCRIn(self.dec)
+        m.submodules.dec_cr_out = self.dec_cr_out = DecodeCROut(self.dec)
 
         # and SVP64 Extra decoders
         m.submodules.crout_svdec = crout_svdec = SVP64CRExtra()
@@ -1093,9 +1089,19 @@ class PowerDecode2(PowerDecodeSubset):
 
         # copy instruction through...
         for i in [do.insn, dec_a.insn_in, dec_b.insn_in,
+                  self.dec_cr_in.insn_in, self.dec_cr_out.insn_in,
                   dec_c.insn_in, dec_o.insn_in, dec_o2.insn_in]:
             comb += i.eq(self.dec.opcode_in)
 
+        # CR setup
+        comb += self.dec_cr_in.sel_in.eq(op.cr_in)
+        comb += self.dec_cr_out.sel_in.eq(op.cr_out)
+        comb += self.dec_cr_out.rc_in.eq(rc_out)
+
+        # CR register info
+        comb += self.do_copy("read_cr_whole", self.dec_cr_in.whole_reg)
+        comb += self.do_copy("write_cr_whole", self.dec_cr_out.whole_reg)
+
         # now do the SVP64 munging.  op.SV_Etype and op.sv_in1 comes from
         # PowerDecoder which in turn comes from LDST-RM*.csv and RM-*.csv
         # which in turn were auto-generated by sv_analysis.py
@@ -1175,7 +1181,8 @@ class PowerDecode2(PowerDecodeSubset):
         comb += self.o_isvec.eq(o_svdec.isvec)
         comb += self.o2_isvec.eq(o2_svdec.isvec)
         # TODO: include SPRs and CRs here!  must be True when *all* are scalar
-        comb += self.no_out_vec.eq((~o2_svdec.isvec) & (~o_svdec.isvec))
+        comb += self.no_out_vec.eq((~o2_svdec.isvec) & (~o_svdec.isvec) &
+                                   (~crout_svdec.isvec))
 
         # SPRs out
         comb += e.read_spr1.eq(dec_a.spr_out)
@@ -1367,11 +1374,8 @@ class SVP64PrefixDecoder(Elaboratable):
         comb += opcode_in.eq(Mux(self.bigendian, raw_be, raw_le))
 
         # start identifying if the incoming opcode is SVP64 prefix)
-        major = Signal(6, reset_less=True)
-        ident = Signal(2, reset_less=True)
-
-        comb += major.eq(sel(opcode_in, SVP64P.OPC))
-        comb += ident.eq(sel(opcode_in, SVP64P.SVP64_7_9))
+        major = sel(m, opcode_in, SVP64P.OPC)
+        ident = sel(m, opcode_in, SVP64P.SVP64_7_9)
 
         comb += self.is_svp64_mode.eq(
             (major == Const(1, 6)) &   # EXT01
@@ -1380,7 +1384,8 @@ class SVP64PrefixDecoder(Elaboratable):
 
         with m.If(self.is_svp64_mode):
             # now grab the 24-bit ReMap context bits,
-            comb += self.svp64_rm.eq(sel(opcode_in, SVP64P.RM))
+            rm = sel(m, opcode_in, SVP64P.RM)
+            comb += self.svp64_rm.eq(rm)
 
         return m