add crossreference to bug #603
[soc.git] / src / soc / decoder / power_decoder2.py
index f99160781a71ad47b3456211637ebd774fb4d856..6cf06f34c677591e573d942d33272c30ded3ebf1 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
+from soc.consts import (MSR, sel, SPEC, EXTRA2, EXTRA3, SVP64P, field,
+                        SPEC_SIZE, SPECb, SPEC_AUG_SIZE)
 
 from soc.regfile.regfiles import FastRegs
 from soc.consts import TT
@@ -86,7 +87,7 @@ class SVP64ExtraSpec(Elaboratable):
     see https://libre-soc.org/openpower/sv/svp64/
     """
     def __init__(self):
-        self.extra   = Signal(10, reset_less=True)
+        self.extra   = Signal(9, reset_less=True)
         self.etype   = Signal(SVEtype, reset_less=True) # 2 or 3 bits
         self.idx     = Signal(SVEXTRA, reset_less=True) # which part of extra
         self.spec  = Signal(3) # EXTRA spec for the register
@@ -95,6 +96,7 @@ class SVP64ExtraSpec(Elaboratable):
         m = Module()
         comb = m.d.comb
         spec = self.spec
+        extra = self.extra
 
         # back in the LDSTRM-* and RM-* files generated by sv_analysis.py
         # we marked every op with an Etype: EXTRA2 or EXTRA3, and also said
@@ -104,23 +106,27 @@ class SVP64ExtraSpec(Elaboratable):
             # 2-bit index selection mode
             with m.Case(SVEtype.EXTRA2):
                 with m.Switch(self.idx):
-                    with m.Case(SVEXTRA.Idx0): # 1st 2 bits
-                        comb += spec[1:3].eq(self.extra[0:2])
-                    with m.Case(SVEXTRA.Idx1): # 2nd 2 bits
-                        comb += spec[1:3].eq(self.extra[2:4])
-                    with m.Case(SVEXTRA.Idx2): # 3rd 2 bits
-                        comb += spec[1:3].eq(self.extra[4:6])
-                    with m.Case(SVEXTRA.Idx3): # 4th 2 bits
-                        comb += spec[1:3].eq(self.extra[6:8])
+                    with m.Case(SVEXTRA.Idx0):  # 1st 2 bits [0:1]
+                        comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX0_VEC])
+                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX0_MSB])
+                    with m.Case(SVEXTRA.Idx1):  # 2nd 2 bits [2:3]
+                        comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX1_VEC])
+                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX1_MSB])
+                    with m.Case(SVEXTRA.Idx2):  # 3rd 2 bits [4:5]
+                        comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX2_VEC])
+                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX2_MSB])
+                    with m.Case(SVEXTRA.Idx3):  # 4th 2 bits [6:7]
+                        comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX3_VEC])
+                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX3_MSB])
             # 3-bit index selection mode
             with m.Case(SVEtype.EXTRA3):
                 with m.Switch(self.idx):
-                    with m.Case(SVEXTRA.Idx0): # 1st 3 bits
-                        comb += spec.eq(self.extra[0:3])
-                    with m.Case(SVEXTRA.Idx1): # 2nd 3 bits
-                        comb += spec.eq(self.extra[3:6])
-                    with m.Case(SVEXTRA.Idx2): # 3rd 3 bits
-                        comb += spec.eq(self.extra[6:9])
+                    with m.Case(SVEXTRA.Idx0):  # 1st 3 bits [0:2]
+                        comb += spec.eq(sel(extra, EXTRA3.IDX0))
+                    with m.Case(SVEXTRA.Idx1):  # 2nd 3 bits [3:5]
+                        comb += spec.eq(sel(extra, EXTRA3.IDX1))
+                    with m.Case(SVEXTRA.Idx2):  # 3rd 3 bits [6:8]
+                        comb += spec.eq(sel(extra, EXTRA3.IDX2))
                     # cannot fit more than 9 bits so there is no 4th thing
 
         return m
@@ -151,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
 
@@ -183,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
 
@@ -195,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
 
@@ -905,6 +917,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
@@ -1003,6 +1019,7 @@ class PowerDecode2(PowerDecodeSubset):
         self.in3_isvec = Signal(1, name="reg_c_isvec")
         self.o_isvec = Signal(1, name="reg_o_isvec")
         self.o2_isvec = Signal(1, name="reg_o2_isvec")
+        self.no_out_vec = Signal(1, name="no_out_vec") # no outputs are vectors
 
     def get_col_subset(self, opkls):
         subset = super().get_col_subset(opkls)
@@ -1103,6 +1120,10 @@ class PowerDecode2(PowerDecodeSubset):
         if hasattr(do, "lk"):
             comb += dec_o2.lk.eq(do.lk)
 
+        # get SVSTATE srcstep (TODO: elwidth, dststep etc.) needed below
+        srcstep = Signal.like(self.state.svstate.srcstep)
+        comb += srcstep.eq(self.state.svstate.srcstep)
+
         # registers a, b, c and out and out2 (LD/ST EA)
         for to_reg, fromreg, svdec in (
             (e.read_reg1, dec_a.reg_out, in1_svdec),
@@ -1113,8 +1134,13 @@ class PowerDecode2(PowerDecodeSubset):
             comb += svdec.extra.eq(extra)        # EXTRA field of SVP64 RM
             comb += svdec.etype.eq(op.SV_Etype)  # EXTRA2/3 for this insn
             comb += svdec.reg_in.eq(fromreg.data) # 3-bit (CR0/BC/BFA)
-            comb += to_reg.data.eq(svdec.reg_out) # 7-bit output
             comb += to_reg.ok.eq(fromreg.ok)
+            # detect if Vectorised: add srcstep if yes.  TODO: a LOT.
+            # this trick only holds when elwidth=default and in single-pred
+            with m.If(svdec.isvec):
+                comb += to_reg.data.eq(srcstep+svdec.reg_out) # 7-bit output
+            with m.Else():
+                comb += to_reg.data.eq(svdec.reg_out) # 7-bit output
 
         comb += in1_svdec.idx.eq(op.sv_in1)  # SVP64 reg #1 (matches in1_sel)
         comb += in2_svdec.idx.eq(op.sv_in2)  # SVP64 reg #2 (matches in2_sel)
@@ -1125,11 +1151,14 @@ class PowerDecode2(PowerDecodeSubset):
         # "update mode" rather than specified cleanly as its own CSV column
         #comb += o2_svdec.idx.eq(op.sv_out)    # SVP64 output (implicit)
 
+        # output reg-is-vectorised (and when no output is vectorised)
         comb += self.in1_isvec.eq(in1_svdec.isvec)
         comb += self.in2_isvec.eq(in2_svdec.isvec)
         comb += self.in3_isvec.eq(in3_svdec.isvec)
         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))
 
         # SPRs out
         comb += e.read_spr1.eq(dec_a.spr_out)
@@ -1150,7 +1179,10 @@ class PowerDecode2(PowerDecodeSubset):
             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):
+                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
@@ -1294,6 +1326,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
@@ -1303,23 +1336,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[32-idx])
         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