move SVP64 Extra reg decoding into main PowerDecoder module
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 31 Jan 2021 15:28:02 +0000 (15:28 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 31 Jan 2021 15:28:02 +0000 (15:28 +0000)
src/soc/decoder/power_decoder2.py

index 7c435ca2e05fd44fb9737056ff0eb1249472c1ca..b8b35285f79596c15993e8a808da462aa07d40e9 100644 (file)
@@ -221,11 +221,9 @@ class DecodeA(Elaboratable):
 
     def __init__(self, dec):
         self.dec = dec
-        self.sv_rm = SVP64Rec() # SVP64 RM field
         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.reg_out = Data(5, name="reg_a")
         self.spr_out = Data(SPR, "spr_a")
         self.fast_out = Data(3, "fast_a")
 
@@ -233,11 +231,8 @@ class DecodeA(Elaboratable):
         m = Module()
         comb = m.d.comb
         op = self.dec.op
+        reg = self.reg_out
         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)
@@ -245,30 +240,16 @@ class DecodeA(Elaboratable):
         with m.If((self.sel_in == In1Sel.RA) |
                   ((self.sel_in == In1Sel.RA_OR_ZERO) &
                    (ra != Const(0, 5)))):
-            comb += reg.eq(ra)
-            comb += self.reg_out.ok.eq(1)
+            comb += reg.data.eq(ra)
+            comb += reg.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 += 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)
+            comb += reg.data.eq(rs)
+            comb += reg.ok.eq(1)
 
         # decode Fast-SPR based on instruction type
         with m.Switch(op.internal_op):
@@ -334,7 +315,6 @@ class DecodeB(Elaboratable):
 
     def __init__(self, dec):
         self.dec = dec
-        self.sv_rm = SVP64Rec() # SVP64 RM field
         self.sel_in = Signal(In2Sel, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
         self.reg_out = Data(7, "reg_b")
@@ -345,32 +325,17 @@ class DecodeB(Elaboratable):
         m = Module()
         comb = m.d.comb
         op = self.dec.op
-        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)
+        reg = self.reg_out
 
         # select Register B field
         with m.Switch(self.sel_in):
             with m.Case(In2Sel.RB):
-                comb += reg.eq(self.dec.RB)
-                comb += self.reg_out.ok.eq(1)
+                comb += reg.data.eq(self.dec.RB)
+                comb += reg.ok.eq(1)
             with m.Case(In2Sel.RS):
                 # for M-Form shiftrot
-                comb += reg.eq(self.dec.RS)
-                comb += self.reg_out.ok.eq(1)
-
-        # now do the SVP64 munging.  different from DecodeA only by sv_in2
-
-        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_in2)     # SVP64 reg #2 (matches in2_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)
+                comb += reg.data.eq(self.dec.RS)
+                comb += reg.ok.eq(1)
 
         # decode SPR2 based on instruction type
         # BCREG implicitly uses LR or TAR for 2nd reg
@@ -459,39 +424,23 @@ class DecodeC(Elaboratable):
         self.sv_rm = SVP64Rec() # SVP64 RM field
         self.sel_in = Signal(In3Sel, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
-        self.reg_out = Data(7, "reg_c")
-        self.reg_isvec = Signal(1, name="reg_c_isvec") # TODO: in reg_out
+        self.reg_out = Data(5, "reg_c")
 
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
         op = self.dec.op
-        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)
+        reg = self.reg_out
 
         # select Register C field
         with m.Switch(self.sel_in):
             with m.Case(In3Sel.RB):
                 # for M-Form shiftrot
-                comb += reg.eq(self.dec.RB)
-                comb += self.reg_out.ok.eq(1)
+                comb += reg.data.eq(self.dec.RB)
+                comb += reg.ok.eq(1)
             with m.Case(In3Sel.RS):
-                comb += reg.eq(self.dec.RS)
-                comb += self.reg_out.ok.eq(1)
-
-        # now do the SVP64 munging.  different from DecodeA only by sv_in3
-
-        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_in3)     # SVP64 reg #3 (matches in3_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)
+                comb += reg.data.eq(self.dec.RS)
+                comb += reg.ok.eq(1)
 
         return m
 
@@ -507,8 +456,7 @@ class DecodeOut(Elaboratable):
         self.sv_rm = SVP64Rec() # SVP64 RM field
         self.sel_in = Signal(OutSel, reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
-        self.reg_out = Data(7, "reg_o")
-        self.reg_isvec = Signal(1, name="reg_o_isvec") # TODO: in reg_out
+        self.reg_out = Data(5, "reg_o")
         self.spr_out = Data(SPR, "spr_o")
         self.fast_out = Data(3, "fast_o")
 
@@ -517,19 +465,16 @@ class DecodeOut(Elaboratable):
         comb = m.d.comb
         m.submodules.sprmap = sprmap = SPRMap()
         op = self.dec.op
-        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)
+        reg = self.reg_out
 
         # select Register out field
         with m.Switch(self.sel_in):
             with m.Case(OutSel.RT):
-                comb += reg.eq(self.dec.RT)
-                comb += self.reg_out.ok.eq(1)
+                comb += reg.data.eq(self.dec.RT)
+                comb += reg.ok.eq(1)
             with m.Case(OutSel.RA):
-                comb += reg.eq(self.dec.RA)
-                comb += self.reg_out.ok.eq(1)
+                comb += reg.data.eq(self.dec.RA)
+                comb += reg.ok.eq(1)
             with m.Case(OutSel.SPR):
                 spr = Signal(10, reset_less=True)
                 comb += spr.eq(decode_spr_num(self.dec.SPR))  # from XFX
@@ -539,18 +484,6 @@ class DecodeOut(Elaboratable):
                     comb += self.spr_out.eq(sprmap.spr_o)
                     comb += self.fast_out.eq(sprmap.fast_o)
 
-        # now do the SVP64 munging.  different from DecodeA only by sv_out
-
-        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_out)     # SVP64 reg out1 (matches out_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)
-
         # determine Fast Reg
         with m.Switch(op.internal_op):
 
@@ -589,8 +522,7 @@ class DecodeOut2(Elaboratable):
         self.sel_in = Signal(OutSel, reset_less=True)
         self.lk = Signal(reset_less=True)
         self.insn_in = Signal(32, reset_less=True)
-        self.reg_out = Data(7, "reg_o2")
-        #self.reg_isvec = Signal(1, name="reg_o2_isvec") # TODO: in reg_out
+        self.reg_out = Data(5, "reg_o2")
         self.fast_out = Data(3, "fast_o2")
 
     def elaborate(self, platform):
@@ -1059,6 +991,11 @@ class PowerDecode2(PowerDecodeSubset):
         self.cr_in_isvec = Signal(1, name="cr_in_isvec")
         self.cr_in_b_isvec = Signal(1, name="cr_in_b_isvec")
         self.cr_in_o_isvec = Signal(1, name="cr_in_o_isvec")
+        self.in1_isvec = Signal(1, name="reg_a_isvec")
+        self.in2_isvec = Signal(1, name="reg_b_isvec")
+        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")
 
     def get_col_subset(self, opkls):
         subset = super().get_col_subset(opkls)
@@ -1104,6 +1041,14 @@ class PowerDecode2(PowerDecodeSubset):
         m.submodules.crin_svdec = crin_svdec = SVP64CRExtra()
         m.submodules.crin_svdec_b = crin_svdec_b = SVP64CRExtra()
         m.submodules.crin_svdec_o = crin_svdec_o = SVP64CRExtra()
+        m.submodules.in1_svdec = in1_svdec = SVP64RegExtra()
+        m.submodules.in2_svdec = in2_svdec = SVP64RegExtra()
+        m.submodules.in3_svdec = in3_svdec = SVP64RegExtra()
+        m.submodules.o_svdec = o_svdec = SVP64RegExtra()
+        m.submodules.o2_svdec = o2_svdec = SVP64RegExtra()
+
+        # 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,
@@ -1115,7 +1060,9 @@ class PowerDecode2(PowerDecodeSubset):
                   dec_c.insn_in, dec_o.insn_in, dec_o2.insn_in]:
             comb += i.eq(self.sv_rm)
 
-        # now do the SVP64 munging.
+        # 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
 
         #######
@@ -1128,7 +1075,7 @@ class PowerDecode2(PowerDecodeSubset):
         cr_a_idx = Signal(SVEXTRA)
         cr_b_idx = Signal(SVEXTRA)
 
-        # these change slighly, when decoding BA/BB.  really should have
+        # these change slightly, when decoding BA/BB.  really should have
         # their own separate CSV column: sv_cr_in1 and sv_cr_in2, but hey
         comb += cr_a_idx.eq(op.sv_cr_in)
         comb += cr_b_idx.eq(SVEXTRA.NONE)
@@ -1155,15 +1102,33 @@ class PowerDecode2(PowerDecodeSubset):
             comb += dec_o2.lk.eq(do.lk)
 
         # registers a, b, c and out and out2 (LD/ST EA)
-        for to_reg, fromreg in (
-            (e.read_reg1, dec_a.reg_out),
-            (e.read_reg2, dec_b.reg_out),
-            (e.read_reg3, dec_c.reg_out),
-            (e.write_reg, dec_o.reg_out),
-            (e.write_ea, dec_o2.reg_out)):
-            comb += to_reg.data.eq(fromreg.data)
+        for to_reg, fromreg, svdec in (
+            (e.read_reg1, dec_a.reg_out, in1_svdec),
+            (e.read_reg2, dec_b.reg_out, in2_svdec),
+            (e.read_reg3, dec_c.reg_out, in3_svdec),
+            (e.write_reg, dec_o.reg_out, o_svdec),
+            (e.write_ea, dec_o2.reg_out, o2_svdec)):
+            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)
 
+        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)
+        comb += in3_svdec.idx.eq(op.sv_in3)  # SVP64 reg #3 (matches in3_sel)
+        comb += o_svdec.idx.eq(op.sv_out)    # SVP64 output (matches out_sel)
+        # XXX TODO - work out where this should come from.  the problem is
+        # that LD-with-update is implied (computed from "is instruction in
+        # "update mode" rather than specified cleanly as its own CSV column
+        #comb += o2_svdec.idx.eq(op.sv_out)    # SVP64 output (implicit)
+
+        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)
+
         # SPRs out
         comb += e.read_spr1.eq(dec_a.spr_out)
         comb += e.write_spr.eq(dec_o.spr_out)