create SVP64CROffs consts for when SVP64 Vector-of-CRs is active (Rc=1)
[soc.git] / src / soc / decoder / power_decoder2.py
index 63a6a82cbfb5b32f97c5e5525def53eb35d44556..27ce810acec850618c2bfd2c114c83f0cd334a50 100644 (file)
@@ -27,7 +27,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)
+from soc.consts import (MSR, sel, SPEC, EXTRA2, EXTRA3, SVP64P, field,
+                        SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs)
 
 from soc.regfile.regfiles import FastRegs
 from soc.consts import TT
@@ -156,19 +157,22 @@ 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
-        comb += self.isvec.eq(spec[2])
+        comb += self.isvec.eq(spec[SPEC.VEC])
+        # extra bits for register number augmentation
+        spec_aug = Signal(SPEC_AUG_SIZE)
+        comb += spec_aug.eq(field(spec, SPECb.MSB, SPECb.LSB, SPEC_SIZE))
 
         # decode vector differently from scalar
         with m.If(self.isvec):
-            # Vector: shifted up, extra in LSBs (RA << 2) | spec[0:1]
-            comb += self.reg_out.eq(Cat(spec[:2], self.reg_in))
+            # 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)
-            comb += self.reg_out.eq(Cat(self.reg_in, spec[:2]))
+            # 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
 
@@ -188,7 +192,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
 
@@ -200,19 +204,22 @@ 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
-        comb += self.isvec.eq(spec[2])
+        comb += self.isvec.eq(spec[SPEC.VEC])
+        # extra bits for register number augmentation
+        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)
-            comb += self.cr_out.eq(Cat(Const(0, 2), spec[:2], self.cr_in))
+            # 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)
-            comb += self.cr_out.eq(Cat(self.cr_in, spec[:2]))
+            # 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
 
@@ -653,6 +660,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()
@@ -666,6 +674,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):
@@ -674,6 +683,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)
@@ -719,6 +733,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()
@@ -729,6 +744,7 @@ class DecodeCROut(Elaboratable):
 
         comb += self.cr_bitfield.ok.eq(0)
         comb += self.whole_reg.ok.eq(0)
+        comb += self.sv_override.eq(0)
 
         with m.Switch(self.sel_in):
             with m.Case(CROutSel.NONE):
@@ -736,6 +752,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)
@@ -910,6 +931,10 @@ 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
@@ -1060,6 +1085,9 @@ 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)
 
@@ -1160,15 +1188,29 @@ 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)
-            comb += to_reg.data.eq(svdec.cr_out) # 7-bit output
+            with m.If(svdec.isvec):
+                # 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)
 
         # sigh this is exactly the sort of thing for which the
@@ -1312,6 +1354,7 @@ class SVP64PrefixDecoder(Elaboratable):
 
     def elaborate(self, platform):
         m = Module()
+        opcode_in = self.opcode_in
         comb = m.d.comb
         # sigh copied this from TopPowerDecoder
         # raw opcode in assumed to be in LE order: byte-reverse it to get BE
@@ -1321,25 +1364,23 @@ class SVP64PrefixDecoder(Elaboratable):
             l.append(raw_le[i:i+8])
         l.reverse()
         raw_be = Cat(*l)
-        comb += self.opcode_in.eq(Mux(self.bigendian, raw_be, raw_le))
+        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(self.opcode_in[26:32])
-        comb += self.is_svp64_mode.eq((major == Const(1, 6)) & # EXT01
-                                      self.opcode_in[31-7] & # identifier
-                                      self.opcode_in[31-9])  # bits
+        comb += major.eq(sel(opcode_in, SVP64P.OPC))
+        comb += ident.eq(sel(opcode_in, SVP64P.SVP64_7_9))
+
+        comb += self.is_svp64_mode.eq(
+            (major == Const(1, 6)) &   # EXT01
+            (ident == Const(0b11, 2))  # identifier bits
+        )
 
-        # now grab the 24-bit ReMap context bits,
-        rmfields = [6, 8] + list(range(10,32)) # SVP64 24-bit RM
-        l = []
-        for idx in rmfields:
-            l.append(self.opcode_in[31-idx])
-        # in nMigen, Cat begins at the LSB and proceeds upwards
-        l.reverse()  # put the LSB at the start of the list
         with m.If(self.is_svp64_mode):
-            comb += self.svp64_rm.eq(Cat(*l))
+            # now grab the 24-bit ReMap context bits,
+            comb += self.svp64_rm.eq(sel(opcode_in, SVP64P.RM))
 
         return m