X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fopenpower%2Fdecoder%2Fpower_svp64_rm.py;h=c052924ddb1c2341b0c7384a0da04ecbb613dad9;hb=9277bd119931afcbda2d95f25ca957a94c8f74a5;hp=ac29159a914a5c121ce7d8100a2b33b468e173f0;hpb=28221555c092a1411ce417878f17d4b2598a5c16;p=openpower-isa.git diff --git a/src/openpower/decoder/power_svp64_rm.py b/src/openpower/decoder/power_svp64_rm.py index ac29159a..c052924d 100644 --- a/src/openpower/decoder/power_svp64_rm.py +++ b/src/openpower/decoder/power_svp64_rm.py @@ -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)