CRInSel, CROutSel,
LdstLen, In1Sel, In2Sel, In3Sel,
OutSel, SPRfull, SPRreduced,
- RC, SVP64LDSTmode, LDSTMode,
+ RCOE, SVP64LDSTmode, LDSTMode,
SVEXTRA, SVEtype, SVPtype)
from openpower.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
Decode2ToOperand)
def __init__(self, dec):
self.dec = dec
- self.sel_in = Signal(RC, reset_less=True)
+ self.sel_in = Signal(RCOE, reset_less=True)
self.insn_in = Signal(32, reset_less=True)
self.rc_out = Data(1, "rc")
# select Record bit out field
with m.Switch(self.sel_in):
- with m.Case(RC.RC):
+ with m.Case(RCOE.RC, RCOE.RC_ONLY):
comb += self.rc_out.data.eq(self.dec.Rc)
comb += self.rc_out.ok.eq(1)
- with m.Case(RC.ONE):
+ with m.Case(RCOE.ONE):
comb += self.rc_out.data.eq(1)
comb += self.rc_out.ok.eq(1)
- with m.Case(RC.NONE):
+ with m.Case(RCOE.NONE):
comb += self.rc_out.data.eq(0)
comb += self.rc_out.ok.eq(1)
class DecodeOE(Elaboratable):
"""DecodeOE from instruction
- decodes OE field: uses RC decode detection which might not be good
-
- -- For now, use "rc" in the decode table to decide whether oe exists.
- -- This is not entirely correct architecturally: For mulhd and
- -- mulhdu, the OE field is reserved. It remains to be seen what an
- -- actual POWER9 does if we set it on those instructions, for now we
- -- test that further down when assigning to the multiplier oe input.
+ decodes OE field: uses RC decode detection which has now been
+ updated to separate out RC_ONLY. all cases RC_ONLY are *NOT*
+ listening to the OE field, here.
"""
def __init__(self, dec, op):
self.dec = dec
self.op = op
- self.sel_in = Signal(RC, reset_less=True)
+ self.sel_in = Signal(RCOE, reset_less=True)
self.insn_in = Signal(32, reset_less=True)
self.oe_out = Data(1, "oe")
def elaborate(self, platform):
m = Module()
comb = m.d.comb
- op = self.op
- with m.Switch(op.internal_op):
-
- # mulhw, mulhwu, mulhd, mulhdu - these *ignore* OE
- # also rotate
- # XXX ARGH! ignoring OE causes incompatibility with microwatt
- # http://lists.libre-soc.org/pipermail/libre-soc-dev/2020-August/000302.html
- with m.Case(MicrOp.OP_MUL_H64, MicrOp.OP_MUL_H32,
- MicrOp.OP_EXTS, MicrOp.OP_CNTZ,
- MicrOp.OP_SHL, MicrOp.OP_SHR, MicrOp.OP_RLC,
- MicrOp.OP_LOAD, MicrOp.OP_STORE,
- MicrOp.OP_RLCL, MicrOp.OP_RLCR,
- MicrOp.OP_EXTSWSLI, MicrOp.OP_GREV, MicrOp.OP_TERNLOG):
- pass
-
- # all other ops decode OE field
+ with m.Switch(self.sel_in):
+ with m.Case(RCOE.RC):
+ comb += self.oe_out.data.eq(self.dec.OE)
+ comb += self.oe_out.ok.eq(1)
with m.Default():
- # select OE bit out field
- with m.Switch(self.sel_in):
- with m.Case(RC.RC):
- comb += self.oe_out.data.eq(self.dec.OE)
- comb += self.oe_out.ok.eq(1)
+ # default: clear OE.
+ comb += self.oe_out.data.eq(0)
+ comb += self.oe_out.ok.eq(0)
return m
self.regreduce_en = regreduce_en
if svp64_en:
self.is_svp64_mode = Signal() # mark decoding as SVP64 Mode
- self.use_svp64_ldst_dec = Signal() # must use LDST decoder
self.use_svp64_fft = Signal() # FFT Mode
self.sv_rm = SVP64Rec(name="dec_svp64") # SVP64 RM field
self.rm_dec = SVP64RMModeDecode("svp64_rm_dec")
# alternatives. useful for PCR (Program Compatibility Register)
# amongst other things
if svp64_en:
- conditions = {'SVP64BREV': self.use_svp64_ldst_dec,
- 'SVP64FFT': self.use_svp64_fft,
+ conditions = {
+ # XXX NO 'SVP64FFT': self.use_svp64_fft,
}
else:
conditions = None
if self.svp64_en:
ports += self.sv_rm.ports()
ports.append(self.is_svp64_mode)
- ports.append(self.use_svp64_ldst_dec)
ports.append(self.use_svp64_fft)
return ports
# the alternative decoder, svdecldst. what a mess... *sigh*
sv_ptype = self.op_get("SV_Ptype")
fn = self.op_get("function_unit")
- # detect major opcode for LDs: include 58 here. from CSV files.
- # BLECH! TODO: these should be done using "mini decoders",
- # using row and column subsets
- is_major_ld = Signal()
- # bits... errr... MSB0 0..5 which is 26:32 python
- major = Signal(6)
- comb += major.eq(self.dec.opcode_in[26:32])
- comb += is_major_ld.eq((major == 34) | (major == 35) |
- (major == 50) | (major == 51) |
- (major == 48) | (major == 49) |
- (major == 42) | (major == 43) |
- (major == 40) | (major == 41) |
- (major == 32) | (major == 33) |
- (major == 58))
- with m.If(self.is_svp64_mode & is_major_ld):
- # straight-up: "it's a LD". this gives enough info
- # for SVP64 RM Mode decoding to detect LD/ST, and
- # consequently detect the SHIFT mode. sigh
- comb += rm_dec.fn_in.eq(Function.LDST)
- with m.Else():
- comb += rm_dec.fn_in.eq(fn) # decode needs to know Fn type
+ comb += rm_dec.fn_in.eq(fn) # decode needs to know Fn type
comb += rm_dec.ptype_in.eq(sv_ptype) # Single/Twin predicated
comb += rm_dec.rc_in.eq(rc_out) # Rc=1
comb += rm_dec.rm_in.eq(self.sv_rm) # SVP64 RM mode
comb += rm_dec.ldst_imz_in.eq(bzero) # B immediate is zero
# main PowerDecoder2 determines if different SVP64 modes enabled
- if not self.final:
- # if shift mode requested
- shiftmode = rm_dec.ldstmode == SVP64LDSTmode.SHIFT
- comb += self.use_svp64_ldst_dec.eq(shiftmode)
# detect if SVP64 FFT mode enabled (really bad hack),
# exclude fcfids and others
# XXX this is a REALLY bad hack, REALLY has to be done better.
# likely with a sub-decoder.
- xo5 = Signal(1) # 1 bit from Minor 59 XO field == 0b0XXXX
- comb += xo5.eq(self.dec.opcode_in[5])
- xo = Signal(5) # 5 bits from Minor 59 fcfids == 0b01110
- comb += xo.eq(self.dec.opcode_in[1:6])
- comb += self.use_svp64_fft.eq((major == 59) & (xo5 == 0b0) &
- (xo != 0b01110))
+ # what this ultimately does is enable the 2nd implicit register
+ # (FRS) for SVP64-decoding. all of these instructions are
+ # 3-in 2-out but there is not enough room either in the
+ # opcode *or* EXTRA2/3 to specify a 5th operand.
+ major = Signal(6)
+ comb += major.eq(self.dec.opcode_in[26:32])
+ xo = Signal(10)
+ comb += xo.eq(self.dec.opcode_in[1:11])
+ comb += self.use_svp64_fft.eq((major == 59) & xo.matches(
+ '-----00100', # ffmsubs
+ '-----00101', # ffmadds
+ '-----00110', # ffnmsubs
+ '-----00111', # ffnmadds
+ '1111100000', # ffadds
+ '-----11011', # fdmadds
+ ))
# decoded/selected instruction flags
comb += self.do_copy("data_len", self.op_get("ldst_len"))
# get SVSTATE srcstep (TODO: elwidth etc.) needed below
vl = Signal.like(self.state.svstate.vl)
- subvl = Signal.like(self.state.svstate.subvl)
+ maxvl = Signal.like(self.state.svstate.maxvl)
+ subvl = Signal.like(self.rm_dec.rm_in.subvl)
srcstep = Signal.like(self.state.svstate.srcstep)
dststep = Signal.like(self.state.svstate.dststep)
- substep = Signal.like(self.state.svstate.substep)
+ ssubstep = Signal.like(self.state.svstate.ssubstep)
+ dsubstep = Signal.like(self.state.svstate.ssubstep)
comb += vl.eq(self.state.svstate.vl)
+ comb += maxvl.eq(self.state.svstate.maxvl)
comb += subvl.eq(self.rm_dec.rm_in.subvl)
comb += srcstep.eq(self.state.svstate.srcstep)
comb += dststep.eq(self.state.svstate.dststep)
- comb += substep.eq(self.state.svstate.substep)
+ comb += ssubstep.eq(self.state.svstate.ssubstep)
+ comb += dsubstep.eq(self.state.svstate.dsubstep)
in1_step, in2_step = self.in1_step, self.in2_step
in3_step = self.in3_step
with m.If(dec_o2.reg_out.ok & dec_o2.fp_madd_en):
with m.If(~self.remap_active[i]):
with m.If(svdec.isvec):
- comb += offs.eq(vl) # VL for Vectors
+ comb += offs.eq(maxvl) # MAXVL for Vectors
# detect if Vectorised: add srcstep/dststep if yes.
# to_reg is 7-bits, outs get dststep added, ins get srcstep
with m.If(svdec.isvec):
selectstep = dststep if out else srcstep
+ subselect = dsubstep if out else ssubstep
step = Signal(7, name="step_%s" % rname.lower())
with m.If(self.remap_active[i]):
- comb += step.eq((remapstep*(subvl+1))+substep)
+ comb += step.eq((remapstep*(subvl+1))+subselect)
with m.Else():
- comb += step.eq((selectstep*(subvl+1))+substep)
+ comb += step.eq((selectstep*(subvl+1))+subselect)
# reverse gear goes the opposite way
with m.If(self.rm_dec.reverse_gear):
comb += to_reg.data.eq(offs+svdec.reg_out+(vmax-1-step))