add first SVP64 7-bit register context decoder to PowerDecoder2
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 30 Jan 2021 00:17:20 +0000 (00:17 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 30 Jan 2021 00:17:20 +0000 (00:17 +0000)
src/soc/decoder/power_decoder.py
src/soc/decoder/power_decoder2.py

index 6712cd1d63fc5f518776423ecff2d3fbf1470270..bdad81ba701aecbf76be0e584a75d9c6ed0c9fb2 100644 (file)
@@ -152,6 +152,8 @@ power_op_csvmap = {'function_unit': 'unit',
                    'sv_out': 'sv_out',
                    'sv_cr_in': 'sv_cr_in',
                    'sv_cr_out': 'sv_cr_out',
+                   'SV_Etype': 'SV_Etype',
+                   'SV_Ptype': 'SV_Ptype',
                    'cr_in': 'CR in',
                    'cr_out': 'CR out',
                    'ldst_len': 'ldst len',
index 57d7e4fb0a912a2e5fa31663841e0993ada9f07e..220258e0a7e5e9faab40572e3ec842578b8e0603 100644 (file)
@@ -22,7 +22,8 @@ from soc.decoder.power_decoder import create_pdecode
 from soc.decoder.power_enums import (MicrOp, CryIn, Function,
                                      CRInSel, CROutSel,
                                      LdstLen, In1Sel, In2Sel, In3Sel,
-                                     OutSel, SPR, RC, LDSTMode)
+                                     OutSel, SPR, RC, LDSTMode,
+                                     SVEXTRA, SVEtype)
 from soc.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
                                          Decode2ToOperand)
 from soc.sv.svp64 import SVP64Rec
@@ -78,6 +79,77 @@ class SPRMap(Elaboratable):
         return m
 
 
+class SVP64RegExtra(Elaboratable):
+    """SVP64RegExtra - decodes SVP64 Extra fields to determine reg extension
+
+    incoming 5-bit GPR/FP is turned into a 7-bit and marked as scalar/vector
+    depending on info in one of the positions in the EXTRA field.
+
+    designed so that "no change" to the 5-bit register number occurs if
+    SV either does not apply or the relevant EXTRA2/3 field bits are zero.
+
+    see https://libre-soc.org/openpower/sv/svp64/
+    """
+    def __init__(self):
+        self.extra   = Signal(10, 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.reg_in  = Signal(5) # incoming reg number (5 bits, RA, RB)
+        self.reg_out = Signal(7) # extra-augmented output (7 bits)
+        self.isvec   = Signal(1) # reg is marked as vector if true
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+
+        # first get the spec.  if not changed it's "scalar identity behaviour"
+        # which is zero which is ok.
+        spec = Signal(3)
+
+        # 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
+        # which of the 4 (or 3 for EXTRA3) sub-fields of bits 10:18 contain
+        # the register-extension information.  extract those how
+        with m.Switch(self.etype):
+            # 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])
+            # 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])
+                    # cannot fit more than 9 bits so there is no 4th thing
+
+        # now decode it. bit 2 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])
+
+        # 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))
+        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]))
+
+        return m
+
+
 class DecodeA(Elaboratable):
     """DecodeA from instruction
 
@@ -90,13 +162,19 @@ class DecodeA(Elaboratable):
         self.sel_in = Signal(In1Sel, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(7, name="reg_a")
+        self.reg_isvec = Signal(1, name="reg_a_isvec") # TODO: in reg_out
         self.spr_out = Data(SPR, "spr_a")
         self.fast_out = Data(3, "fast_a")
 
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
+        op = self.dec.op
         m.submodules.sprmap = sprmap = SPRMap()
+        m.submodules.svdec = svdec = SVP64RegExtra()
+
+        # get the 5-bit reg data before svp64-munging it into 7-bit plus isvec
+        reg = Signal(5, reset_less=True)
 
         # select Register A field
         ra = Signal(5, reset_less=True)
@@ -104,16 +182,32 @@ class DecodeA(Elaboratable):
         with m.If((self.sel_in == In1Sel.RA) |
                   ((self.sel_in == In1Sel.RA_OR_ZERO) &
                    (ra != Const(0, 5)))):
-            comb += self.reg_out.data.eq(ra)
+            comb += reg.eq(ra)
             comb += self.reg_out.ok.eq(1)
 
         # some Logic/ALU ops have RS as the 3rd arg, but no "RA".
+        # moved it to 1st position (in1_sel)... because
+        rs = Signal(5, reset_less=True)
+        comb += rs.eq(self.dec.RS)
         with m.If(self.sel_in == In1Sel.RS):
-            comb += self.reg_out.data.eq(self.dec.RS)
+            comb += reg.eq(rs)
             comb += self.reg_out.ok.eq(1)
 
+        # 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
+
+        extra = self.sv_rm.extra            # SVP64 extra bits 10:18
+        comb += svdec.extra.eq(extra)       # EXTRA field of SVP64 RM
+        comb += svdec.etype.eq(op.SV_Etype) # EXTRA2/3 for this insn
+        comb += svdec.idx.eq(op.sv_in1)     # SVP64 reg #1 (matches in1_sel)
+        comb += svdec.reg_in.eq(reg)        # 5-bit (RA, RS)
+
+        # outputs: 7-bit reg number and whether it's vectorised
+        comb += self.reg_out.data.eq(svdec.reg_out)
+        comb += self.reg_isvec.eq(svdec.isvec)
+
         # decode Fast-SPR based on instruction type
-        op = self.dec.op
         with m.Switch(op.internal_op):
 
             # BC or BCREG: implicit register (CTR) NOTE: same in DecodeOut
@@ -833,11 +927,17 @@ class PowerDecode2(PowerDecodeSubset):
 
     def get_col_subset(self, opkls):
         subset = super().get_col_subset(opkls)
-        subset.add("in1_sel")
         subset.add("asmcode")
+        subset.add("in1_sel")
         subset.add("in2_sel")
         subset.add("in3_sel")
         subset.add("out_sel")
+        subset.add("sv_in1")
+        subset.add("sv_in2")
+        subset.add("sv_in3")
+        subset.add("sv_out")
+        subset.add("SV_Etype")
+        subset.add("SV_Ptype")
         subset.add("lk")
         subset.add("internal_op")
         subset.add("form")