fix Bug 607 - unnecessary code added related to MMU in PowerDecoder2
[soc.git] / src / soc / decoder / power_decoder2.py
index 3e51512c67a04d2ca70c12c537c5d84d439417d3..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,8 +29,8 @@ 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,
-                        SPEC_SIZE, SPECb, SPEC_AUG_SIZE)
+from soc.consts import (MSR, SPEC, EXTRA2, EXTRA3, SVP64P, field,
+                        SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs)
 
 from soc.regfile.regfiles import FastRegs
 from soc.consts import TT
@@ -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
@@ -157,7 +162,7 @@ class SVP64RegExtra(SVP64ExtraSpec):
         # which is zero which is ok.
         spec = self.spec
 
-        # now decode it. bit 2 is "scalar/vector".  note that spec could be zero
+        # now decode it. bit 0 is "scalar/vector".  note that spec could be zero
         #  from above, which (by design) has the effect of "no change", below.
 
         # simple: isvec is top bit of spec
@@ -168,10 +173,10 @@ class SVP64RegExtra(SVP64ExtraSpec):
 
         # decode vector differently from scalar
         with m.If(self.isvec):
-            # Vector: shifted up, extra in LSBs (RA << 2) | spec[0:1]
+            # Vector: shifted up, extra in LSBs (RA << 2) | spec[1:2]
             comb += self.reg_out.eq(Cat(spec_aug, self.reg_in))
         with m.Else():
-            # Scalar: not shifted up, extra in MSBs RA | (spec[0:1] << 5)
+            # Scalar: not shifted up, extra in MSBs RA | (spec[1:2] << 5)
             comb += self.reg_out.eq(Cat(self.reg_in, spec_aug))
 
         return m
@@ -192,7 +197,7 @@ class SVP64CRExtra(SVP64ExtraSpec):
     """
     def __init__(self):
         SVP64ExtraSpec.__init__(self)
-        self.cr_in  = Signal(3) # incoming CR number (3 bits, BA[2:5], BFA)
+        self.cr_in  = Signal(3) # incoming CR number (3 bits, BA[0:2], BFA)
         self.cr_out = Signal(7) # extra-augmented CR output (7 bits)
         self.isvec  = Signal(1) # reg is marked as vector if true
 
@@ -204,7 +209,7 @@ class SVP64CRExtra(SVP64ExtraSpec):
         # which is zero which is ok.
         spec = self.spec
 
-        # now decode it. bit 2 is "scalar/vector".  note that spec could be zero
+        # now decode it. bit 0 is "scalar/vector".  note that spec could be zero
         #  from above, which (by design) has the effect of "no change", below.
 
         # simple: isvec is top bit of spec
@@ -213,12 +218,12 @@ class SVP64CRExtra(SVP64ExtraSpec):
         spec_aug = Signal(SPEC_AUG_SIZE)
         comb += spec_aug.eq(field(spec, SPECb.MSB, SPECb.LSB, SPEC_SIZE))
 
-        # decode vector differently from scalar, insert bits 0 and 1 accordingly
+        # decode vector differently from scalar, insert bits 1 and 2 accordingly
         with m.If(self.isvec):
-            # Vector: shifted up, extra in LSBs (CR << 4) | (spec[0:1] << 2)
+            # Vector: shifted up, extra in LSBs (CR << 4) | (spec[1:2] << 2)
             comb += self.cr_out.eq(Cat(Const(0, 2), spec_aug, self.cr_in))
         with m.Else():
-            # Scalar: not shifted up, extra in MSBs CR | (spec[0:1] << 3)
+            # Scalar: not shifted up, extra in MSBs CR | (spec[1:2] << 3)
             comb += self.cr_out.eq(Cat(self.cr_in, spec_aug))
 
         return m
@@ -660,6 +665,7 @@ class DecodeCRIn(Elaboratable):
         self.cr_bitfield_b = Data(3, "cr_bitfield_b")
         self.cr_bitfield_o = Data(3, "cr_bitfield_o")
         self.whole_reg = Data(8,  "cr_fxm")
+        self.sv_override = Signal(2, reset_less=True) # do not do EXTRA spec
 
     def elaborate(self, platform):
         m = Module()
@@ -673,6 +679,7 @@ class DecodeCRIn(Elaboratable):
         comb += self.cr_bitfield_b.ok.eq(0)
         comb += self.cr_bitfield_o.ok.eq(0)
         comb += self.whole_reg.ok.eq(0)
+        comb += self.sv_override.eq(0)
 
         # select the relevant CR bitfields
         with m.Switch(self.sel_in):
@@ -681,6 +688,11 @@ class DecodeCRIn(Elaboratable):
             with m.Case(CRInSel.CR0):
                 comb += self.cr_bitfield.data.eq(0) # CR0 (MSB0 numbering)
                 comb += self.cr_bitfield.ok.eq(1)
+                comb += self.sv_override.eq(1)
+            with m.Case(CRInSel.CR1):
+                comb += self.cr_bitfield.data.eq(1) # CR1 (MSB0 numbering)
+                comb += self.cr_bitfield.ok.eq(1)
+                comb += self.sv_override.eq(2)
             with m.Case(CRInSel.BI):
                 comb += self.cr_bitfield.data.eq(self.dec.BI[2:5])
                 comb += self.cr_bitfield.ok.eq(1)
@@ -726,6 +738,7 @@ class DecodeCROut(Elaboratable):
         self.insn_in = Signal(32, reset_less=True)
         self.cr_bitfield = Data(3, "cr_bitfield")
         self.whole_reg = Data(8,  "cr_fxm")
+        self.sv_override = Signal(2, reset_less=True) # do not do EXTRA spec
 
     def elaborate(self, platform):
         m = Module()
@@ -736,6 +749,13 @@ class DecodeCROut(Elaboratable):
 
         comb += self.cr_bitfield.ok.eq(0)
         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):
@@ -743,6 +763,11 @@ class DecodeCROut(Elaboratable):
             with m.Case(CROutSel.CR0):
                 comb += self.cr_bitfield.data.eq(0) # CR0 (MSB0 numbering)
                 comb += self.cr_bitfield.ok.eq(self.rc_in)  # only when RC=1
+                comb += self.sv_override.eq(1)
+            with m.Case(CROutSel.CR1):
+                comb += self.cr_bitfield.data.eq(1) # CR1 (MSB0 numbering)
+                comb += self.cr_bitfield.ok.eq(self.rc_in)  # only when RC=1
+                comb += self.sv_override.eq(2)
             with m.Case(CROutSel.BF):
                 comb += self.cr_bitfield.data.eq(self.dec.FormX.BF)
                 comb += self.cr_bitfield.ok.eq(1)
@@ -864,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:
@@ -876,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)
@@ -900,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
@@ -917,14 +926,12 @@ class PowerDecodeSubset(Elaboratable):
         spr = Signal(10, reset_less=True)
         comb += spr.eq(decode_spr_num(self.dec.SPR)) # from XFX
 
-        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)
@@ -943,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
@@ -1043,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
 
@@ -1055,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()
@@ -1067,14 +1081,27 @@ class PowerDecode2(PowerDecodeSubset):
         m.submodules.o_svdec = o_svdec = SVP64RegExtra()
         m.submodules.o2_svdec = o2_svdec = SVP64RegExtra()
 
+        # debug access to crout_svdec (used in get_pdecode_cr_out)
+        self.crout_svdec = crout_svdec
+
         # get the 5-bit reg data before svp64-munging it into 7-bit plus isvec
         reg = Signal(5, reset_less=True)
 
         # 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
@@ -1154,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)
@@ -1167,16 +1195,27 @@ class PowerDecode2(PowerDecodeSubset):
         comb += e.write_fast2.eq(dec_o2.fast_out)
 
         # condition registers (CR)
-        for to_reg, fromreg, svdec in (
-            (e.read_cr1, self.dec_cr_in.cr_bitfield, crin_svdec),
-            (e.read_cr2, self.dec_cr_in.cr_bitfield_b, crin_svdec_b),
-            (e.read_cr3, self.dec_cr_in.cr_bitfield_o, crin_svdec_o),
-            (e.write_cr, self.dec_cr_out.cr_bitfield, crout_svdec)):
+        for to_reg, cr, name, svdec in (
+            (e.read_cr1, self.dec_cr_in, "cr_bitfield", crin_svdec),
+            (e.read_cr2, self.dec_cr_in, "cr_bitfield_b", crin_svdec_b),
+            (e.read_cr3, self.dec_cr_in, "cr_bitfield_o", crin_svdec_o),
+            (e.write_cr, self.dec_cr_out, "cr_bitfield", crout_svdec)):
+            fromreg = getattr(cr, name)
             comb += svdec.extra.eq(extra)        # EXTRA field of SVP64 RM
             comb += svdec.etype.eq(op.SV_Etype)  # EXTRA2/3 for this insn
             comb += svdec.cr_in.eq(fromreg.data) # 3-bit (CR0/BC/BFA)
             with m.If(svdec.isvec):
-                comb += to_reg.data.eq(srcstep+svdec.cr_out) # 7-bit output
+                # check if this is CR0 or CR1: treated differently
+                # (does not "listen" to EXTRA2/3 spec for a start)
+                # also: the CRs start from completely different locations
+                with m.If(cr.sv_override == 1): # CR0
+                    offs = SVP64CROffs.CR0
+                    comb += to_reg.data.eq(srcstep+offs)
+                with m.Elif(cr.sv_override == 2): # CR1
+                    offs = SVP64CROffs.CR1
+                    comb += to_reg.data.eq(srcstep+1)
+                with m.Else():
+                    comb += to_reg.data.eq(srcstep+svdec.cr_out) # 7-bit output
             with m.Else():
                 comb += to_reg.data.eq(svdec.cr_out) # 7-bit output
             comb += to_reg.ok.eq(fromreg.ok)
@@ -1335,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
@@ -1348,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