# set priv / virt mode on I-Cache, sigh
if isinstance(self.imem, ICache):
comb += self.imem.i_in.priv_mode.eq(~msr[MSR.PR])
- comb += self.imem.i_in.virt_mode.eq(msr[MSR.DR])
+ comb += self.imem.i_in.virt_mode.eq(msr[MSR.IR]) # Instr. Redir (VM)
with m.FSM(name='fetch_fsm'):
# waiting (zzz)
with m.State("IDLE"):
- with m.If(~dbg.stopping_o & ~fetch_failed & ~dbg.core_stop_o):
+ # fetch allowed if not failed and stopped but not stepping
+ # (see dmi.py for how core_stop_o is generated)
+ with m.If(~fetch_failed & ~dbg.core_stop_o):
comb += fetch_pc_o_ready.eq(1)
with m.If(fetch_pc_i_valid & ~pdecode2.instr_fault
& ~dbg.core_stop_o):
# dummy pause to find out why simulation is not keeping up
with m.State("INSN_READ"):
- if self.allow_overlap:
- stopping = dbg.stopping_o
- else:
- stopping = Const(0)
+ # when using "single-step" mode, checking dbg.stopping_o
+ # prevents progress. allow fetch to proceed once started
+ stopping = Const(0)
+ #if self.allow_overlap:
+ # stopping = dbg.stopping_o
with m.If(stopping):
# stopping: jump back to idle
m.next = "IDLE"
with m.If(self.imem.f_busy_o &
~pdecode2.instr_fault): # zzz...
# busy but not fetch failed: stay in wait-read
+ comb += self.imem.a_pc_i.eq(pc)
comb += self.imem.a_i_valid.eq(1)
comb += self.imem.f_i_valid.eq(1)
with m.Else():
comb += self.imem.f_i_valid.eq(1)
with m.Else():
# not busy: instruction fetched
- insn = get_insn(self.imem.f_instr_o, cur_state.pc+4)
+ if hasattr(core, "icache"):
+ # blech, icache returns actual instruction
+ insn = self.imem.f_instr_o
+ else:
+ insn = get_insn(self.imem.f_instr_o, cur_state.pc+4)
sync += dec_opcode_o.eq(insn)
m.next = "INSN_READY"
# TODO: probably can start looking at pdecode2.rm_dec
# wait for an instruction to arrive from Fetch
with m.State("INSN_WAIT"):
- if self.allow_overlap:
- stopping = dbg.stopping_o
- else:
- stopping = Const(0)
+ # when using "single-step" mode, checking dbg.stopping_o
+ # prevents progress. allow issue to proceed once started
+ stopping = Const(0)
+ #if self.allow_overlap:
+ # stopping = dbg.stopping_o
with m.If(stopping):
# stopping: jump back to idle
m.next = "ISSUE_START"
# handshake with execution FSM, move to "wait" once acknowledged
with m.State("INSN_EXECUTE"):
- comb += exec_insn_i_valid.eq(1) # trigger execute
- with m.If(exec_insn_o_ready): # execute acknowledged us
- m.next = "EXECUTE_WAIT"
+ # when using "single-step" mode, checking dbg.stopping_o
+ # prevents progress. allow execute to proceed once started
+ stopping = Const(0)
+ #if self.allow_overlap:
+ # stopping = dbg.stopping_o
+ with m.If(stopping):
+ # stopping: jump back to idle
+ m.next = "ISSUE_START"
+ if flush_needed:
+ # request the icache to stop asserting "failed"
+ comb += core.icache.flush_in.eq(1)
+ # stop instruction fault
+ sync += pdecode2.instr_fault.eq(0)
+ with m.Else():
+ comb += exec_insn_i_valid.eq(1) # trigger execute
+ with m.If(exec_insn_o_ready): # execute acknowledged us
+ m.next = "EXECUTE_WAIT"
with m.State("EXECUTE_WAIT"):
# wait on "core stop" release, at instruction end
comb += core.icache.flush_in.eq(1)
# stop instruction fault
sync += pdecode2.instr_fault.eq(0)
+ # if terminated return to idle
+ with m.If(dbg.terminate_i):
+ m.next = "ISSUE_START"
# check if svstate needs updating: if so, write it to State Regfile
with m.If(self.update_svstate):
comb = m.d.comb
sync = m.d.sync
+ dbg = self.dbg
pdecode2 = self.pdecode2
# temporaries
~pdecode2.instr_fault):
comb += self.insn_done.eq(1)
m.next = "INSN_START" # back to fetch
+ # terminate returns directly to INSN_START
+ with m.If(dbg.terminate_i):
+ # comb += self.insn_done.eq(1) - no because it's not
+ m.next = "INSN_START" # back to fetch
def elaborate(self, platform):
m = super().elaborate(platform)