whoops, no ability to add comments in between functions in pseudocode
[openpower-isa.git] / src / openpower / decoder / power_svp64_rm.py
index ac29159a914a5c121ce7d8100a2b33b468e173f0..c052924ddb1c2341b0c7384a0da04ecbb613dad9 100644 (file)
@@ -17,12 +17,24 @@ https://libre-soc.org/openpower/sv/svp64/
 """
 
 from nmigen import Elaboratable, Module, Signal, Const
-from soc.decoder.power_enums import (SVP64RMMode, Function, SVPtype,
-                                    SVP64PredMode, SVP64sat)
-from soc.consts import EXTRA3, SVP64MODE
-from soc.sv.svp64 import SVP64Rec
+from openpower.decoder.power_enums import (SVP64RMMode, Function, SVPtype,
+                                    SVP64PredMode, SVP64sat, SVP64LDSTmode)
+from openpower.consts import EXTRA3, SVP64MODE
+from openpower.sv.svp64 import SVP64Rec
 from nmutil.util import sel
 
+# a list of fields which need to be added to input records in order
+# pass on vital information needed by each pipeline.
+# make sure to keep these the same as SVP64RMModeDecode, in fact,
+# TODO, make SVP64RMModeDecode *use* this as a Record!
+sv_input_record_layout = [
+        ('sv_pred_sz', 1), # predicate source zeroing
+        ('sv_pred_dz', 1), # predicate dest zeroing
+        ('sv_saturate', SVP64sat),
+        ('sv_ldstmode', SVP64LDSTmode),
+        ('SV_Ptype', SVPtype),
+        #('sv_RC1', 1),
+    ]
 
 """RM Mode
 there are three Mode variants, two for LD/ST and one for everything else
@@ -30,7 +42,8 @@ https://libre-soc.org/openpower/sv/svp64/
 https://libre-soc.org/openpower/sv/ldst/
 
 LD/ST immed:
-00     str     sz dz   normal mode
+00     0       dz els  normal mode (with element-stride)
+00     1       dz rsvd bit-reversed mode
 01     inv     CR-bit  Rc=1: ffirst CR sel
 01     inv     els RC1 Rc=0: ffirst z/nonz
 10     N       dz els  sat mode: N=0/1 u/s
@@ -59,11 +72,15 @@ Arithmetic:
 
 class SVP64RMModeDecode(Elaboratable):
     def __init__(self, name=None):
+        ##### inputs #####
         self.rm_in = SVP64Rec(name=name)
         self.fn_in = Signal(Function) # LD/ST is different
         self.ptype_in = Signal(SVPtype)
         self.rc_in = Signal()
-        self.ldst_idx = Signal()
+        self.ldst_ra_vec = Signal() # set when RA is vec, indicate Index mode
+        self.ldst_imz_in = Signal() # set when LD/ST immediate is zero
+
+        ##### outputs #####
 
         # main mode (normal, reduce, saturate, ffirst, pred-result)
         self.mode = Signal(SVP64RMMode)
@@ -74,13 +91,15 @@ class SVP64RMModeDecode(Elaboratable):
         self.dstpred = Signal(3) # destination predicate
         self.pred_sz = Signal(1) # predicate source zeroing
         self.pred_dz = Signal(1) # predicate dest zeroing
-        
+
         self.saturate = Signal(SVP64sat)
         self.RC1 = Signal()
-        self.cr_sel = Signal(2)
-        self.inv = Signal(1)
+        self.cr_sel = Signal(2)  # bit of CR to test (index 0-3)
+        self.inv = Signal(1)     # and whether it's inverted (like branch BO)
         self.map_evm = Signal(1)
         self.map_crm = Signal(1)
+        self.reverse_gear = Signal(1)  # elements to go VL-1..0
+        self.ldstmode = Signal(SVP64LDSTmode) # LD/ST Mode (strided type)
 
     def elaborate(self, platform):
         m = Module()
@@ -106,11 +125,20 @@ class SVP64RMModeDecode(Elaboratable):
             with m.Case(3):
                 comb += self.mode.eq(SVP64RMMode.PREDRES) # predicate result
 
+        # extract "reverse gear" for mapreduce mode
+        with m.If((~is_ldst) &                     # not for LD/ST
+                    (mode2 == 0) &                 # first 2 bits == 0
+                    mode[SVP64MODE.REDUCE] &       # bit 2 == 1
+                   (~mode[SVP64MODE.PARALLEL])):   # not parallel mapreduce
+            comb += self.reverse_gear.eq(mode[SVP64MODE.RG]) # finally, whew
+
         # extract zeroing
         with m.Switch(mode2):
             with m.Case(0): # needs further decoding (LDST no mapreduce)
                 with m.If(is_ldst):
-                    comb += self.pred_sz.eq(mode[SVP64MODE.SZ])
+                    # XXX TODO, work out which of these is most appropriate
+                    # set both? or just the one? or one if LD, the other if ST?
+                    comb += self.pred_sz.eq(mode[SVP64MODE.DZ])
                     comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
                 with m.Elif(mode[SVP64MODE.REDUCE]):
                     with m.If(self.rm_in.subvl == Const(0, 2)): # no SUBVL
@@ -120,17 +148,54 @@ class SVP64RMModeDecode(Elaboratable):
                     comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
             with m.Case(1, 3):
                 with m.If(is_ldst):
-                    with m.If(~self.ldst_idx):
+                    with m.If(~self.ldst_ra_vec):
                         comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
                 with m.Elif(self.rc_in):
                     comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
             with m.Case(2):
-                with m.If(is_ldst & ~self.ldst_idx):
+                with m.If(is_ldst & ~self.ldst_ra_vec):
                     comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
                 with m.Else():
                     comb += self.pred_sz.eq(mode[SVP64MODE.SZ])
                     comb += self.pred_dz.eq(mode[SVP64MODE.DZ])
 
+        # extract saturate
+        with m.Switch(mode2):
+            with m.Case(2):
+                with m.If(mode[SVP64MODE.N]):
+                    comb += self.saturate.eq(SVP64sat.UNSIGNED)
+                with m.Else():
+                    comb += self.saturate.eq(SVP64sat.SIGNED)
+            with m.Default():
+                comb += self.saturate.eq(SVP64sat.NONE)
+
+        # extract els (element strided mode bit)
+        # see https://libre-soc.org/openpower/sv/ldst/
+        els = Signal()
+        with m.If(is_ldst):
+            with m.Switch(mode2):
+                with m.Case(0):
+                    comb += els.eq(mode[SVP64MODE.ELS_NORMAL])
+                with m.Case(2):
+                    comb += els.eq(mode[SVP64MODE.ELS_SAT])
+                with m.Case(1, 3):
+                    with m.If(self.rc_in):
+                        comb += els.eq(mode[SVP64MODE.ELS_FFIRST_PRED])
+
+            # Bit-reversed Mode
+            with m.If(mode[SVP64MODE.LDST_BITREV]):
+                comb += self.ldstmode.eq(SVP64LDSTmode.BITREVERSE)
+            # RA is vectorised
+            with m.Elif(self.ldst_ra_vec):
+                comb += self.ldstmode.eq(SVP64LDSTmode.INDEXED)
+            # not element-strided, therefore unit...
+            with m.Elif(~els):
+                comb += self.ldstmode.eq(SVP64LDSTmode.UNITSTRIDE)
+            # but if the LD/ST immediate is zero, allow cache-inhibited
+            # loads from same location, therefore don't do element-striding
+            with m.Elif(~self.ldst_imz_in):
+                comb += self.ldstmode.eq(SVP64LDSTmode.ELSTRIDE)
+
         # extract src/dest predicate.  use EXTRA3.MASK because EXTRA2.MASK
         # is in exactly the same bits
         srcmask = sel(m, self.rm_in.extra, EXTRA3.MASK)