comb += regfile.ren.eq(1<<regnum)
# ... but on a 1-clock delay
with m.If(res_ok_delay):
- comb += res.eq(regfile.data_o)
+ comb += res.eq(regfile.o_data)
return res
def get_predint(m, mask, name):
# one cycle later, msr/sv read arrives. valid only once.
with m.If(~msr_read):
sync += msr_read.eq(1) # yeah don't read it again
- sync += cur_state.msr.eq(self.state_r_msr.data_o)
+ sync += cur_state.msr.eq(self.state_r_msr.o_data)
with m.If(self.imem.f_busy_o): # zzz...
# busy: stay in wait-read
comb += self.imem.a_i_valid.eq(1)
with m.If(dunary):
# set selected mask bit for 1<<r3 mode
dst_shift = Signal(range(64))
- comb += dst_shift.eq(self.int_pred.data_o & 0b111111)
+ comb += dst_shift.eq(self.int_pred.o_data & 0b111111)
sync += new_dstmask.eq(1 << dst_shift)
with m.Else():
# invert mask if requested
- sync += new_dstmask.eq(self.int_pred.data_o ^ inv)
+ sync += new_dstmask.eq(self.int_pred.o_data ^ inv)
# skip fetching source mask register, when zero
with m.If(sall1s):
sync += new_srcmask.eq(-1)
with m.If(sunary):
# set selected mask bit for 1<<r3 mode
src_shift = Signal(range(64))
- comb += src_shift.eq(self.int_pred.data_o & 0b111111)
+ comb += src_shift.eq(self.int_pred.o_data & 0b111111)
sync += new_srcmask.eq(1 << src_shift)
with m.Else():
# invert mask if requested
- sync += new_srcmask.eq(self.int_pred.data_o ^ inv)
+ sync += new_srcmask.eq(self.int_pred.o_data ^ inv)
m.next = "FETCH_PRED_SHIFT_MASK"
# fetch masks from the CR register file
cr_field = Signal(4)
scr_bit = Signal()
dcr_bit = Signal()
- comb += cr_field.eq(cr_pred.data_o)
+ comb += cr_field.eq(cr_pred.o_data)
comb += scr_bit.eq(cr_field.bit_select(sidx, 1) ^ scrinvert)
comb += dcr_bit.eq(cr_field.bit_select(didx, 1) ^ dcrinvert)
# set the corresponding mask bit
# note if an exception happened. in a pipelined or OoO design
# this needs to be accompanied by "shadowing" (or stalling)
- el = []
- for exc in core.fus.excs.values():
- el.append(exc.happened)
- exc_happened = Signal()
- if len(el) > 0: # at least one exception
- comb += exc_happened.eq(Cat(*el).bool())
+ exc_happened = self.core.o.exc_happened
with m.FSM(name="issue_fsm"):
# while stopped, allow updating the PC and SVSTATE
with m.If(self.pc_i.ok):
comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
- comb += self.state_w_pc.data_i.eq(self.pc_i.data)
+ comb += self.state_w_pc.i_data.eq(self.pc_i.data)
sync += pc_changed.eq(1)
with m.If(self.svstate_i.ok):
comb += new_svstate.eq(self.svstate_i.data)
# since we are in a VL==0 loop, no instruction was
# executed that we could be overwriting
comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
- comb += self.state_w_pc.data_i.eq(nia)
+ comb += self.state_w_pc.i_data.eq(nia)
comb += self.insn_done.eq(1)
m.next = "ISSUE_START"
with m.Else():
(skip_dststep >= cur_vl)):
# end of VL loop. Update PC and reset src/dst step
comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
- comb += self.state_w_pc.data_i.eq(nia)
+ comb += self.state_w_pc.i_data.eq(nia)
comb += new_svstate.srcstep.eq(0)
comb += new_svstate.dststep.eq(0)
comb += update_svstate.eq(1)
# pass predicate mask bits through to satellite decoders
# TODO: for SIMD this will be *multiple* bits
- sync += core.sv_pred_sm.eq(self.srcmask[0])
- sync += core.sv_pred_dm.eq(self.dstmask[0])
+ sync += core.i.sv_pred_sm.eq(self.srcmask[0])
+ sync += core.i.sv_pred_dm.eq(self.dstmask[0])
# after src/dst step have been updated, we are ready
# to decode the instruction
with m.State("DECODE_SV"):
# decode the instruction
- sync += core.e.eq(pdecode2.e)
- sync += core.state.eq(cur_state)
- sync += core.raw_insn_i.eq(dec_opcode_i)
- sync += core.bigendian_i.eq(self.core_bigendian_i)
+ sync += core.i.e.eq(pdecode2.e)
+ sync += core.i.state.eq(cur_state)
+ sync += core.i.raw_insn_i.eq(dec_opcode_i)
+ sync += core.i.bigendian_i.eq(self.core_bigendian_i)
if self.svp64_en:
- sync += core.sv_rm.eq(pdecode2.sv_rm)
+ sync += core.i.sv_rm.eq(pdecode2.sv_rm)
# set RA_OR_ZERO detection in satellite decoders
- sync += core.sv_a_nz.eq(pdecode2.sv_a_nz)
+ sync += core.i.sv_a_nz.eq(pdecode2.sv_a_nz)
# and svp64 detection
- sync += core.is_svp64_mode.eq(is_svp64_mode)
+ sync += core.i.is_svp64_mode.eq(is_svp64_mode)
# and svp64 bit-rev'd ldst mode
ldst_dec = pdecode2.use_svp64_ldst_dec
- sync += core.use_svp64_ldst_dec.eq(ldst_dec)
+ sync += core.i.use_svp64_ldst_dec.eq(ldst_dec)
+ # after decoding, reset any previous exception condition,
+ # allowing it to be set again during the next execution
+ sync += pdecode2.ldst_exc.eq(0)
m.next = "INSN_EXECUTE" # move to "execute"
with m.If(~dbg.core_stop_o & ~core_rst):
comb += exec_pc_i_ready.eq(1)
# see https://bugs.libre-soc.org/show_bug.cgi?id=636
- #with m.If(exec_pc_o_valid & exc_happened):
- # probably something like this:
- # sync += pdecode2.ldst_exc.eq(core.fus.get_exc("ldst0")
- # TODO: the exception info needs to be blatted
- # into pdecode.ldst_exc, and the instruction "re-run".
+ # the exception info needs to be blatted into
+ # pdecode.ldst_exc, and the instruction "re-run".
# when ldst_exc.happened is set, the PowerDecoder2
# reacts very differently: it re-writes the instruction
# with a "trap" (calls PowerDecoder2.trap()) which
# PC to the exception address, as well as alter MSR.
# nothing else needs to be done other than to note
# the change of PC and MSR (and, later, SVSTATE)
- #with m.Elif(exec_pc_o_valid):
- with m.If(exec_pc_o_valid): # replace with Elif (above)
+ with m.If(exc_happened):
+ sync += pdecode2.ldst_exc.eq(core.fus.get_exc("ldst0"))
+
+ with m.If(exec_pc_o_valid):
# was this the last loop iteration?
is_last = Signal()
cur_vl = cur_state.svstate.vl
comb += is_last.eq(next_srcstep == cur_vl)
+ # return directly to Decode if Execute generated an
+ # exception.
+ with m.If(pdecode2.ldst_exc.happened):
+ m.next = "DECODE_SV"
+
# if either PC or SVSTATE were changed by the previous
# instruction, go directly back to Fetch, without
# updating either PC or SVSTATE
- with m.If(pc_changed | sv_changed):
+ with m.Elif(pc_changed | sv_changed):
m.next = "ISSUE_START"
# also return to Fetch, when no output was a vector
# TODO: this just blithely overwrites whatever
# pipeline updated the PC
comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
- comb += self.state_w_pc.data_i.eq(nia)
+ comb += self.state_w_pc.i_data.eq(nia)
# reset SRCSTEP before returning to Fetch
if self.svp64_en:
with m.If(pdecode2.loop_continue):
# while stopped, allow updating the PC and SVSTATE
with m.If(self.pc_i.ok):
comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
- comb += self.state_w_pc.data_i.eq(self.pc_i.data)
+ comb += self.state_w_pc.i_data.eq(self.pc_i.data)
sync += pc_changed.eq(1)
with m.If(self.svstate_i.ok):
comb += new_svstate.eq(self.svstate_i.data)
# check if svstate needs updating: if so, write it to State Regfile
with m.If(update_svstate):
comb += self.state_w_sv.wen.eq(1<<StateRegs.SVSTATE)
- comb += self.state_w_sv.data_i.eq(new_svstate)
+ comb += self.state_w_sv.i_data.eq(new_svstate)
sync += cur_state.svstate.eq(new_svstate) # for next clock
def execute_fsm(self, m, core, pc_changed, sv_changed,
pdecode2 = self.pdecode2
# temporaries
- core_busy_o = core.busy_o # core is busy
- core_ii_valid = core.ii_valid # instruction is valid
- core_issue_i = core.issue_i # instruction is issued
- insn_type = core.e.do.insn_type # instruction MicroOp type
+ core_busy_o = ~core.p.o_ready | core.n.o_data.busy_o # core is busy
+ core_ivalid_i = core.p.i_valid # instruction is valid
with m.FSM(name="exec_fsm"):
with m.State("INSN_START"):
comb += exec_insn_o_ready.eq(1)
with m.If(exec_insn_i_valid):
- comb += core_ii_valid.eq(1) # instruction is valid
- comb += core_issue_i.eq(1) # and issued
+ comb += core_ivalid_i.eq(1) # instruction is valid/issued
sync += sv_changed.eq(0)
sync += pc_changed.eq(0)
m.next = "INSN_ACTIVE" # move to "wait completion"
# instruction started: must wait till it finishes
with m.State("INSN_ACTIVE"):
- with m.If(insn_type != MicrOp.OP_NOP):
- comb += core_ii_valid.eq(1) # instruction is valid
# note changes to PC and SVSTATE
with m.If(self.state_nia.wen & (1<<StateRegs.SVSTATE)):
sync += sv_changed.eq(1)
with m.If(~core_busy_o): # instruction done!
comb += exec_pc_o_valid.eq(1)
with m.If(exec_pc_i_ready):
- comb += self.insn_done.eq(1)
+ # when finished, indicate "done".
+ # however, if there was an exception, the instruction
+ # is *not* yet done. this is an implementation
+ # detail: we choose to implement exceptions by
+ # taking the exception information from the LDST
+ # unit, putting that *back* into the PowerDecoder2,
+ # and *re-running the entire instruction*.
+ # if we erroneously indicate "done" here, it is as if
+ # there were *TWO* instructions:
+ # 1) the failed LDST 2) a TRAP.
+ with m.If(~pdecode2.ldst_exc.happened):
+ comb += self.insn_done.eq(1)
m.next = "INSN_START" # back to fetch
def setup_peripherals(self, m):
comb += dbg_rst.eq(ResetSignal())
# busy/halted signals from core
- comb += self.busy_o.eq(core.busy_o)
+ core_busy_o = ~core.p.o_ready | core.n.o_data.busy_o # core is busy
+ comb += self.busy_o.eq(core_busy_o)
comb += pdecode2.dec.bigendian.eq(self.core_bigendian_i)
# temporary hack: says "go" immediately for both address gen and ST
# don't write pc every cycle
comb += self.state_w_pc.wen.eq(0)
- comb += self.state_w_pc.data_i.eq(0)
+ comb += self.state_w_pc.i_data.eq(0)
# don't read msr every cycle
comb += self.state_r_msr.ren.eq(0)
# connect up debug signals
# TODO comb += core.icache_rst_i.eq(dbg.icache_rst_o)
- comb += dbg.terminate_i.eq(core.core_terminate_o)
+ comb += dbg.terminate_i.eq(core.o.core_terminate_o)
comb += dbg.state.pc.eq(pc)
comb += dbg.state.svstate.eq(svstate)
comb += dbg.state.msr.eq(cur_state.msr)
sync += d_reg_delay.eq(d_reg.req)
with m.If(d_reg_delay):
# data arrives one clock later
- comb += d_reg.data.eq(self.int_r.data_o)
+ comb += d_reg.data.eq(self.int_r.o_data)
comb += d_reg.ack.eq(1)
# sigh same thing for CR debug
sync += d_cr_delay.eq(d_cr.req)
with m.If(d_cr_delay):
# data arrives one clock later
- comb += d_cr.data.eq(self.cr_r.data_o)
+ comb += d_cr.data.eq(self.cr_r.o_data)
comb += d_cr.ack.eq(1)
# aaand XER...
sync += d_xer_delay.eq(d_xer.req)
with m.If(d_xer_delay):
# data arrives one clock later
- comb += d_xer.data.eq(self.xer_r.data_o)
+ comb += d_xer.data.eq(self.xer_r.o_data)
comb += d_xer.ack.eq(1)
def tb_dec_fsm(self, m, spr_dec):
with m.State("DEC_WRITE"):
new_dec = Signal(64)
# TODO: MSR.LPCR 32-bit decrement mode
- comb += new_dec.eq(fast_r_dectb.data_o - 1)
+ comb += new_dec.eq(fast_r_dectb.o_data - 1)
comb += fast_w_dectb.addr.eq(FastRegs.DEC)
comb += fast_w_dectb.wen.eq(1)
- comb += fast_w_dectb.data_i.eq(new_dec)
+ comb += fast_w_dectb.i_data.eq(new_dec)
sync += spr_dec.eq(new_dec) # copy into cur_state for decoder
m.next = "TB_READ"
# waits for read TB to arrive, initiates write of current TB
with m.State("TB_WRITE"):
new_tb = Signal(64)
- comb += new_tb.eq(fast_r_dectb.data_o + 1)
+ comb += new_tb.eq(fast_r_dectb.o_data + 1)
comb += fast_w_dectb.addr.eq(FastRegs.TB)
comb += fast_w_dectb.wen.eq(1)
- comb += fast_w_dectb.data_i.eq(new_tb)
+ comb += fast_w_dectb.i_data.eq(new_tb)
m.next = "DEC_READ"
return m