from openpower.decoder.power_regspec_map import regspec_decode_read
from openpower.decoder.power_decoder import (create_pdecode,
- create_pdecode_svp64,)
+ create_pdecode_svp64_ldst,
+ PowerOp)
from openpower.decoder.power_enums import (MicrOp, CryIn, Function,
CRInSel, CROutSel,
LdstLen, In1Sel, In2Sel, In3Sel,
OutSel, SPRfull, SPRreduced,
- RC, LDSTMode,
+ RC, SVP64LDSTmode, LDSTMode,
SVEXTRA, SVEtype, SVPtype)
from openpower.decoder.decode2execute1 import (Decode2ToExecute1Type, Data,
Decode2ToOperand)
self.svp64_en = svp64_en
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.sv_rm = SVP64Rec(name="dec_svp64") # SVP64 RM field
self.rm_dec = SVP64RMModeDecode("svp64_rm_dec")
# set these to the predicate mask bits needed for the ALU
dec = create_pdecode(name=fn_name, col_subset=col_subset,
row_subset=self.rowsubsetfn)
self.dec = dec
- # create SVP64 decoder
- if svp64_en:
+
+ # create SVP64 LDST decoder
+ if svp64_en and (not final or fn_name.lower().startswith("ldst")):
if fn_name:
name = "sv_"+fn_name
else:
name = "svdec"
- svdec = create_pdecode(name=name,
- col_subset=col_subset,
- row_subset=self.rowsubsetfn)
- self.svdec = svdec
+ svdecldst = create_pdecode_svp64_ldst(name=name,
+ col_subset=col_subset,
+ row_subset=self.rowsubsetfn)
+ self.svdecldst = svdecldst
+ else:
+ self.svdecldst = None
+
+ # set up a copy of the PowerOp
+ self.op = PowerOp.like(self.dec.op)
# state information needed by the Decoder
if state is None:
ports = self.dec.ports() + self.e.ports()
if self.svp64_en:
ports += self.sv_rm.ports()
- ports += self.svdec.ports()
+ if self.svdecldst:
+ ports += self.svdecldst.ports()
return ports
def needs_field(self, field, op_field):
return []
def op_get(self, op_field):
- return getattr(self.dec.op, op_field, None)
+ return getattr(self.op, op_field, None)
def elaborate(self, platform):
if self.regreduce_en:
m.submodules.dec_rc = self.dec_rc = dec_rc = DecodeRC(self.dec)
m.submodules.dec_oe = dec_oe = DecodeOE(self.dec, op)
+ # use op from first decoder (self.dec.op) if not in SVP64-LDST mode
+ # (TODO)
+ comb += self.op.eq(self.dec.op)
+
if self.svp64_en:
# and SVP64 RM mode decoder
m.submodules.sv_rm_dec = rm_dec = self.rm_dec
+ if self.svdecldst:
# and SVP64 decoder
- m.submodules.svdec = svdec = self.svdec
+ m.submodules.svdecldst = svdecldst = self.svdecldst
# copy instruction through...
for i in [do.insn, dec_rc.insn_in, dec_oe.insn_in, ]:
comb += self.do_copy("output_cr", self.op_get("cr_out")) # CR out
if self.svp64_en:
- # connect up SVP64 RM Mode decoding
+ # connect up SVP64 RM Mode decoding. however... we need a shorter
+ # path, for the LDST bit-reverse detection. so perform partial
+ # decode when SVP64 is detected. then, bit-reverse mode can be
+ # quickly determined, and the Decoder result MUXed over to
+ # the alternative decoder, svdecldst. what a mess... *sigh*
sv_ptype = self.op_get("SV_Ptype")
fn = self.op_get("function_unit")
- comb += rm_dec.fn_in.eq(fn) # decode needs to know if LD/ST type
+ # detect major opcode for LDs: include 58 here. from CSV files.
+ is_major_ld = Signal()
+ major = Signal(6) # bits... errr... MSB0 0..5 which is 26:32 python
+ 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"
+ 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.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
if self.needs_field("imm_data", "in2_sel"):
bzero = dec_bi.imm_out.ok & ~dec_bi.imm_out.data.bool()
comb += rm_dec.ldst_imz_in.eq(bzero) # B immediate is zero
+ # main PowerDecoder2 determines if bit-reverse mode requested
+ if not self.final:
+ bitrev = rm_dec.ldstmode == SVP64LDSTmode.BITREVERSE
+ comb += self.use_svp64_ldst_dec.eq(bitrev)
# decoded/selected instruction flags
comb += self.do_copy("data_len", self.op_get("ldst_len"))
m = super().elaborate(platform)
comb = m.d.comb
state = self.state
- e_out, op, do_out = self.e, self.dec.op, self.e.do
+ op, e_out, do_out = self.op, self.e, self.e.do
dec_spr, msr, cia, ext_irq = state.dec, state.msr, state.pc, state.eint
rc_out = self.dec_rc.rc_out.data
e = self.e_tmp
# sigh this is exactly the sort of thing for which the
# decoder is designed to not need. MTSPR, MFSPR and others need
# access to the XER bits. however setting e.oe is not appropriate
- with m.If(op.internal_op == MicrOp.OP_MFSPR):
+ internal_op = self.op_get("internal_op")
+ with m.If(internal_op == MicrOp.OP_MFSPR):
comb += e.xer_in.eq(0b111) # SO, CA, OV
- with m.If(op.internal_op == MicrOp.OP_CMP):
+ with m.If(internal_op == MicrOp.OP_CMP):
comb += e.xer_in.eq(1<<XERRegsEnum.SO) # SO
- with m.If(op.internal_op == MicrOp.OP_MTSPR):
+ with m.If(internal_op == MicrOp.OP_MTSPR):
comb += e.xer_out.eq(1)
# set the trapaddr to 0x700 for a td/tw/tdi/twi operation