selectconcat)
from openpower.decoder.power_enums import (spr_dict, spr_byname, XER_bits,
insns, MicrOp, In1Sel, In2Sel, In3Sel,
- OutSel, CROutSel, LDSTMode,
+ OutSel, CRInSel, CROutSel, LDSTMode,
SVP64RMMode, SVP64PredMode,
SVP64PredInt, SVP64PredCR,
SVP64LDSTmode)
from openpower.decoder.power_enums import SVPtype
-from openpower.decoder.helpers import (exts, gtu, ltu, undefined, bitrev)
+from openpower.decoder.helpers import (exts, gtu, ltu, undefined,
+ ISACallerHelper, ISAFPHelpers)
from openpower.consts import PIb, MSRb # big-endian (PowerISA versions)
-from openpower.consts import SVP64CROffs
+from openpower.consts import (SVP64MODE,
+ SVP64CROffs,
+ )
from openpower.decoder.power_svp64 import SVP64RM, decode_extra
from openpower.decoder.isa.radixmmu import RADIX
"RB": 0,
"RC": 0,
"RS": 0,
+ "BI": 0,
"CR": 0,
"LR": 0,
"CTR": 0,
return None, False
+# TODO, really should just be using PowerDecoder2
+def get_pdecode_cr_in(dec2, name):
+ op = dec2.dec.op
+ in_sel = yield op.cr_in
+ in_bitfield = yield dec2.dec_cr_in.cr_bitfield.data
+ sv_cr_in = yield op.sv_cr_in
+ spec = yield dec2.crin_svdec.spec
+ sv_override = yield dec2.dec_cr_in.sv_override
+ # get the IN1/2/3 from the decoder (includes SVP64 remap and isvec)
+ in1 = yield dec2.e.read_cr1.data
+ cr_isvec = yield dec2.cr_in_isvec
+ log ("get_pdecode_cr_in", in_sel, CROutSel.CR0.value, in1, cr_isvec)
+ log (" sv_cr_in", sv_cr_in)
+ log (" cr_bf", in_bitfield)
+ log (" spec", spec)
+ log (" override", sv_override)
+ # identify which regnames map to in / o2
+ if name == 'BI':
+ if in_sel == CRInSel.BI.value:
+ return in1, cr_isvec
+ log ("get_pdecode_cr_in not found", name)
+ return None, False
+
+
# TODO, really should just be using PowerDecoder2
def get_pdecode_cr_out(dec2, name):
op = dec2.dec.op
return None, False
-class ISACaller:
+class ISACaller(ISACallerHelper, ISAFPHelpers):
# decoder2 - an instance of power_decoder2
# regfile - a list of initial values for the registers
# initial_{etc} - initial values for SPRs, Condition Register, Mem, MSR
self.msr = SelectableInt(initial_msr, 64) # underlying reg
self.pc = PC()
# GPR FPR SPR registers
+ initial_sprs = copy(initial_sprs) # so as not to get modified
self.gpr = GPR(decoder2, self, self.svstate, regfile)
self.fpr = GPR(decoder2, self, self.svstate, fpregfile)
self.spr = SPR(decoder2, initial_sprs) # initialise SPRs before MMU
'MSR': self.msr,
'undefined': undefined,
'mode_is_64bit': True,
- 'SO': XER_bits['SO']
+ 'SO': XER_bits['SO'],
+ 'XLEN': 64 # elwidth overrides, later
})
# update pc to requested start point
def memassign(self, ea, sz, val):
self.mem.memassign(ea, sz, val)
- def prep_namespace(self, formname, op_fields):
+ def prep_namespace(self, insn_name, formname, op_fields):
# TODO: get field names from form in decoder*1* (not decoder2)
# decoder2 is hand-created, and decoder1.sigform is auto-generated
# from spec
fields = self.decoder.sigforms[formname]
log("prep_namespace", formname, op_fields)
for name in op_fields:
- if name == 'spr':
- sig = getattr(fields, name.upper())
- else:
+ # CR immediates. deal with separately. needs modifying
+ # pseudocode
+ if self.is_svp64_mode and name in ['BI']: # TODO, more CRs
+ # BI is a 5-bit, must reconstruct the value
+ regnum, is_vec = yield from get_pdecode_cr_in(self.dec2, name)
sig = getattr(fields, name)
- val = yield sig
+ val = yield sig
+ # low 2 LSBs (CR field selector) remain same, CR num extended
+ assert regnum <= 7, "sigh, TODO, 128 CR fields"
+ val = (val & 0b11) | (regnum<<2)
+ else:
+ if name == 'spr':
+ sig = getattr(fields, name.upper())
+ else:
+ sig = getattr(fields, name)
+ val = yield sig
# these are all opcode fields involved in index-selection of CR,
# and need to do "standard" arithmetic. CR[BA+32] for example
# would, if using SelectableInt, only be 5-bit.
self.namespace['VL'] = vl
self.namespace['srcstep'] = srcstep
+ # sv.bc* need some extra fields
+ if self.is_svp64_mode and insn_name.startswith("sv.bc"):
+ # blegh grab bits manually
+ mode = yield self.dec2.rm_dec.rm_in.mode
+ bc_vlset = (mode & SVP64MODE.BC_VLSET) != 0
+ bc_vli = (mode & SVP64MODE.BC_VLI) != 0
+ bc_snz = (mode & SVP64MODE.BC_SNZ) != 0
+ bc_vsb = yield self.dec2.rm_dec.bc_vsb
+ bc_lru = yield self.dec2.rm_dec.bc_lru
+ bc_gate = yield self.dec2.rm_dec.bc_gate
+ sz = yield self.dec2.rm_dec.pred_sz
+ self.namespace['ALL'] = SelectableInt(bc_gate, 1)
+ self.namespace['VSb'] = SelectableInt(bc_vsb, 1)
+ self.namespace['LRu'] = SelectableInt(bc_lru, 1)
+ self.namespace['VLSET'] = SelectableInt(bc_vlset, 1)
+ self.namespace['VLI'] = SelectableInt(bc_vli, 1)
+ self.namespace['sz'] = SelectableInt(sz, 1)
+ self.namespace['SNZ'] = SelectableInt(bc_snz, 1)
+
def handle_carry_(self, inputs, outputs, already_done):
inv_a = yield self.dec2.e.do.invert_in
if inv_a:
if not self.respect_pc:
self.fake_pc += 4
- log("execute one, CIA NIA", self.pc.CIA.value, self.pc.NIA.value)
+ log("execute one, CIA NIA", hex(self.pc.CIA.value),
+ hex(self.pc.NIA.value))
def get_assembly_name(self):
# TODO, asmregs is from the spec, e.g. add RT,RA,RB
return asmop
def get_remap_indices(self):
+ """WARNING, this function stores remap_idxs and remap_loopends
+ in the class for later use. this to avoid problems with yield
+ """
# go through all iterators in lock-step, advance to next remap_idx
- srcstep, dststep = self.new_srcstep, self.new_dststep
+ srcstep, dststep = self.get_src_dststeps()
# get four SVSHAPEs. here we are hard-coding
SVSHAPE0 = self.spr['SVSHAPE0']
SVSHAPE1 = self.spr['SVSHAPE1']
illegal = False
ins_name = 'ffadds'
+ # branch-conditional redirects to sv.bc
+ if asmop.startswith('bc') and self.is_svp64_mode:
+ ins_name = 'sv.%s' % ins_name
+
+ log(" post-processed name", ins_name, asmop)
+
+ # illegal instructions call TRAP at 0x700
if illegal:
print("illegal", ins_name, asmop)
self.call_trap(0x700, PIb.ILLEG)
self.update_pc_next()
return
+ # look up instruction in ISA.instrs, prepare namespace
info = self.instrs[ins_name]
- yield from self.prep_namespace(info.form, info.op_fields)
+ yield from self.prep_namespace(ins_name, info.form, info.op_fields)
# preserve order of register names
input_names = create_args(list(info.read_regs) +
# see if srcstep/dststep need skipping over masked-out predicate bits
if (self.is_svp64_mode or ins_name == 'setvl' or
- ins_name.startswith("sv")):
+ ins_name in ['svremap', 'svstate']):
yield from self.svstate_pre_inc()
if self.is_svp64_mode:
pre = yield from self.update_new_svstate_steps()
self.update_nia()
self.update_pc_next()
return
- srcstep, dststep = self.new_srcstep, self.new_dststep
+ srcstep, dststep = self.get_src_dststeps()
pred_dst_zero = self.pred_dst_zero
pred_src_zero = self.pred_src_zero
vl = self.svstate.vl
if not self.is_svp64_mode or not pred_src_zero:
log('reading reg %s %s' % (name, str(regnum)), is_vec)
if name in fregs:
- reg_val = self.fpr(regnum)
+ reg_val = SelectableInt(self.fpr(regnum))
elif name is not None:
- reg_val = self.gpr(regnum)
+ reg_val = SelectableInt(self.gpr(regnum))
else:
log('zero input reg %s %s' % (name, str(regnum)), is_vec)
reg_val = 0
replace_d = False # update / replace constant in pseudocode
if self.is_svp64_mode:
ldstmode = yield self.dec2.rm_dec.ldstmode
- # bitreverse mode reads SVD (or SVDS - TODO)
+ # shift mode reads SVD (or SVDS - TODO)
# *BUT*... because this is "overloading" of LD operations,
# it gets *STORED* into D (or DS, TODO)
- if ldstmode == SVP64LDSTmode.BITREVERSE.value:
+ if ldstmode == SVP64LDSTmode.SHIFT.value:
imm = yield self.dec2.dec.fields.FormSVD.SVD[0:11]
imm = exts(imm, 11) # sign-extend to integer
- log ("bitrev SVD", imm)
+ log ("shift SVD", imm)
replace_d = True
else:
if info.form == 'DS':
op = yield self.dec2.e.do.insn_type
offsmul = 0
if op == MicrOp.OP_LOAD.value:
- offsmul = srcstep
- log("D-field src", imm, offsmul)
+ if remap_active:
+ offsmul = yield self.dec2.in1_step
+ log("D-field REMAP src", imm, offsmul)
+ else:
+ offsmul = srcstep
+ log("D-field src", imm, offsmul)
elif op == MicrOp.OP_STORE.value:
+ # XXX NOTE! no bit-reversed STORE! this should not ever be used
offsmul = dststep
log("D-field dst", imm, offsmul)
- # bit-reverse mode
- if ldstmode == SVP64LDSTmode.BITREVERSE.value:
+ # bit-reverse mode, rev already done through get_src_dst_steps()
+ if ldstmode == SVP64LDSTmode.SHIFT.value:
# manually look up RC, sigh
RC = yield self.dec2.dec.RC[0:5]
RC = self.gpr(RC)
- log ("RC", RC.value, "imm", imm, "offs", bin(offsmul),
- "rev", bin(bitrev(offsmul, vl)))
- imm = SelectableInt((imm * bitrev(offsmul, vl)) << RC.value, 32)
+ log ("LD-SHIFT:", "VL", vl,
+ "RC", RC.value, "imm", imm,
+ "offs", bin(offsmul),
+ )
+ imm = SelectableInt((imm * offsmul) << RC.value, 32)
# Unit-Strided LD/ST adds offset*width to immediate
elif ldstmode == SVP64LDSTmode.UNITSTRIDE.value:
ldst_len = yield self.dec2.e.do.data_len
# clear trap (trap) NIA
self.trap_nia = None
+ # check if this was an sv.bc* and create an indicator that
+ # this is the last check to be made as a loop. combined with
+ # the ALL/ANY mode we can early-exit
+ if self.is_svp64_mode and ins_name.startswith("sv.bc"):
+ no_in_vec = yield self.dec2.no_in_vec # BI is scalar
+ end_loop = no_in_vec or srcstep == vl-1 or dststep == vl-1
+ self.namespace['end_loop'] = SelectableInt(end_loop, 1)
+
# execute actual instruction here (finally)
log("inputs", inputs)
results = info.func(self, *inputs)
# this is our Sub-Program-Counter loop from 0 to VL-1
pre = False
post = False
+ nia_update = True
if self.allow_next_step_inc:
log("SVSTATE_NEXT: inc requested, mode",
self.svstate_next_mode, self.allow_next_step_inc)
else:
if self.allow_next_step_inc == 2:
log ("SVSTATE_NEXT: read")
- yield from self.svstate_post_inc()
+ nia_update = (yield from self.svstate_post_inc(ins_name))
else:
log ("SVSTATE_NEXT: post-inc")
+ # use actual src/dst-step here to check end, do NOT
+ # use bit-reversed version
srcstep, dststep = self.new_srcstep, self.new_dststep
remaps = self.get_remap_indices()
remap_idxs = self.remap_idxs
self.svstate.vfirst = 0
elif self.is_svp64_mode:
- yield from self.svstate_post_inc()
+ nia_update = (yield from self.svstate_post_inc(ins_name))
else:
# XXX only in non-SVP64 mode!
# record state of whether the current operation was an svshape,
# to interrupt in between. sigh.
self.last_op_svshape = asmop == 'svremap'
- self.update_pc_next()
+ if nia_update:
+ self.update_pc_next()
def SVSTATE_NEXT(self, mode, submode):
"""explicitly moves srcstep/dststep on to next element, for
"Vertical-First" mode. this function is called from
setvl pseudo-code, as a pseudo-op "svstep"
+
+ WARNING: this function uses information that was created EARLIER
+ due to it being in the middle of a yield, but this function is
+ *NOT* called from yield (it's called from compiled pseudocode).
"""
self.allow_next_step_inc = submode.value + 1
log("SVSTATE_NEXT mode", mode, submode, self.allow_next_step_inc)
log (" new srcstep", srcstep)
log (" new dststep", dststep)
+ def get_src_dststeps(self):
+ """gets srcstep and dststep
+ """
+ return self.new_srcstep, self.new_dststep
+
def update_new_svstate_steps(self):
+ # note, do not get the bit-reversed srcstep here!
srcstep, dststep = self.new_srcstep, self.new_dststep
# update SVSTATE with new srcstep
# nothing needs doing (TODO zeroing): just do next instruction
return srcstep == vl or dststep == vl
- def svstate_post_inc(self, vf=0):
+ def svstate_post_inc(self, insn_name, vf=0):
# check if SV "Vertical First" mode is enabled
vfirst = self.svstate.vfirst
log (" SV Vertical First", vf, vfirst)
svp64_is_vector = (out_vec or in_vec)
else:
svp64_is_vector = out_vec
+ # check if this was an sv.bc* and if so did it succeed
+ if self.is_svp64_mode and insn_name.startswith("sv.bc"):
+ end_loop = self.namespace['end_loop']
+ log("branch %s end_loop" % insn_name, end_loop)
+ if end_loop.value:
+ self.svp64_reset_loop()
+ self.update_pc_next()
+ return False
if svp64_is_vector and srcstep != vl-1 and dststep != vl-1:
self.svstate.srcstep += SelectableInt(1, 7)
self.svstate.dststep += SelectableInt(1, 7)
+ self.namespace['SVSTATE'] = self.svstate
+ # not an SVP64 branch, so fix PC (NIA==CIA) for next loop
+ # (by default, NIA is CIA+4 if v3.0B or CIA+8 if SVP64)
+ # this way we keep repeating the same instruction (with new steps)
self.pc.NIA.value = self.pc.CIA.value
self.namespace['NIA'] = self.pc.NIA
- self.namespace['SVSTATE'] = self.svstate
log("end of sub-pc call", self.namespace['CIA'],
self.namespace['NIA'])
return False # DO NOT allow PC update whilst Sub-PC loop running
self.pc.update_nia(self.is_svp64_mode)
self.namespace['NIA'] = self.pc.NIA
+
def inject():
"""Decorator factory.
log("args[0]", args[0].namespace['CIA'],
args[0].namespace['NIA'],
args[0].namespace['SVSTATE'])
+ if 'end_loop' in func_globals:
+ log("args[0] end_loop", func_globals['end_loop'])
args[0].namespace = func_globals
#exec (func.__code__, func_globals)