from nmigen import Elaboratable, Module, Signal, Const
from openpower.decoder.power_enums import (SVP64RMMode, Function, SVPtype,
- SVP64PredMode, SVP64sat)
+ SVP64PredMode, SVP64sat, SVP64LDSTmode)
from openpower.consts import EXTRA3, SVP64MODE
from openpower.sv.svp64 import SVP64Rec
from nmutil.util import sel
('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),
]
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)
self.inv = Signal(1)
self.map_evm = Signal(1)
self.map_crm = Signal(1)
+ self.ldstmode = Signal(SVP64LDSTmode) # LD/ST Mode (strided type)
def elaborate(self, platform):
m = Module()
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])
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])
+
+ # RA is vectorised
+ with m.If(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)