can now take interrupts on stalled instructions
This commit is contained in:
parent
2ed0be65f9
commit
bd27d0fab2
@ -358,6 +358,8 @@ class rocketCtrl extends Component
|
||||
val ex_reg_inst_di = Reg(resetVal = Bool(false));
|
||||
val ex_reg_inst_ei = Reg(resetVal = Bool(false));
|
||||
val ex_reg_flush_inst = Reg(resetVal = Bool(false));
|
||||
val ex_reg_xcpt_interrupt = Reg(resetVal = Bool(false));
|
||||
val ex_reg_cause = Reg(){UFix()}
|
||||
val ex_reg_xcpt_ma_inst = Reg(resetVal = Bool(false));
|
||||
val ex_reg_xcpt_itlb = Reg(resetVal = Bool(false));
|
||||
val ex_reg_xcpt_illegal = Reg(resetVal = Bool(false));
|
||||
@ -376,6 +378,8 @@ class rocketCtrl extends Component
|
||||
val mem_reg_inst_di = Reg(resetVal = Bool(false));
|
||||
val mem_reg_inst_ei = Reg(resetVal = Bool(false));
|
||||
val mem_reg_flush_inst = Reg(resetVal = Bool(false));
|
||||
val mem_reg_xcpt_interrupt = Reg(resetVal = Bool(false));
|
||||
val mem_reg_cause = Reg(){UFix()}
|
||||
val mem_reg_xcpt_ma_inst = Reg(resetVal = Bool(false));
|
||||
val mem_reg_xcpt_itlb = Reg(resetVal = Bool(false));
|
||||
val mem_reg_xcpt_illegal = Reg(resetVal = Bool(false));
|
||||
@ -402,7 +406,8 @@ class rocketCtrl extends Component
|
||||
val wb_reg_fp_val = Reg(resetVal = Bool(false));
|
||||
val wb_reg_fp_sboard_set = Reg(resetVal = Bool(false));
|
||||
|
||||
val take_pc = Wire() { Bool() };
|
||||
val take_pc = Wire(){Bool()}
|
||||
val take_pc_wb = Wire(){Bool()}
|
||||
|
||||
when (!io.dpath.stalld) {
|
||||
when (io.dpath.killf) {
|
||||
@ -422,11 +427,46 @@ class rocketCtrl extends Component
|
||||
id_reg_icmiss := !io.imem.resp_val;
|
||||
}
|
||||
|
||||
var vec_replay = Bool(false)
|
||||
var vec_stalld = Bool(false)
|
||||
var vec_irq = Bool(false)
|
||||
var vec_irq_cause = UFix(23,5) // don't care
|
||||
if (HAVE_VEC)
|
||||
{
|
||||
// vector control
|
||||
val vec = new rocketCtrlVec()
|
||||
|
||||
io.vec_dpath <> vec.io.dpath
|
||||
io.vec_iface <> vec.io.iface
|
||||
|
||||
vec.io.s := io.dpath.status(SR_S)
|
||||
vec.io.sr_ev := io.dpath.status(SR_EV)
|
||||
vec.io.exception := wb_reg_exception
|
||||
vec.io.eret := wb_reg_eret
|
||||
|
||||
vec_replay = vec.io.replay
|
||||
vec_stalld = vec.io.stalld // || id_vfence_cv && !vec.io.vfence_ready
|
||||
vec_irq = vec.io.irq
|
||||
vec_irq_cause = vec.io.irq_cause
|
||||
}
|
||||
|
||||
// executing ERET when traps are enabled causes an illegal instruction exception (as per ISA sim)
|
||||
val illegal_inst =
|
||||
!(id_int_val.toBool || io.fpu.dec.valid || id_vec_val.toBool) ||
|
||||
(id_eret.toBool && io.dpath.status(SR_ET).toBool);
|
||||
|
||||
val p_irq_timer = (io.dpath.status(15).toBool && io.dpath.irq_timer);
|
||||
val p_irq_ipi = (io.dpath.status(13).toBool && io.dpath.irq_ipi);
|
||||
val id_interrupt =
|
||||
io.dpath.status(SR_ET).toBool && mem_reg_valid &&
|
||||
((io.dpath.status(15).toBool && io.dpath.irq_timer) ||
|
||||
(io.dpath.status(13).toBool && io.dpath.irq_ipi) ||
|
||||
vec_irq);
|
||||
val id_cause =
|
||||
Mux(p_irq_ipi, UFix(21,5),
|
||||
Mux(p_irq_timer, UFix(23,5),
|
||||
vec_irq_cause))
|
||||
|
||||
when (reset.toBool || io.dpath.killd) {
|
||||
ex_reg_br_type := BR_N;
|
||||
ex_reg_btb_hit := Bool(false);
|
||||
@ -479,6 +519,8 @@ class rocketCtrl extends Component
|
||||
}
|
||||
ex_reg_mem_cmd := id_mem_cmd
|
||||
ex_reg_mem_type := id_mem_type.toUFix
|
||||
ex_reg_xcpt_interrupt := id_reg_valid && id_interrupt && !take_pc
|
||||
ex_reg_cause := id_cause
|
||||
|
||||
val beq = io.dpath.br_eq;
|
||||
val bne = ~io.dpath.br_eq;
|
||||
@ -547,6 +589,8 @@ class rocketCtrl extends Component
|
||||
}
|
||||
mem_reg_mem_cmd := ex_reg_mem_cmd;
|
||||
mem_reg_mem_type := ex_reg_mem_type;
|
||||
mem_reg_xcpt_interrupt := ex_reg_xcpt_interrupt && !take_pc_wb
|
||||
mem_reg_cause := ex_reg_cause
|
||||
|
||||
when (io.dpath.killm) {
|
||||
wb_reg_valid := Bool(false)
|
||||
@ -619,82 +663,44 @@ class rocketCtrl extends Component
|
||||
io.fpu.dec.wen && fp_sboard.io.r(3).data
|
||||
}
|
||||
|
||||
var vec_replay = Bool(false)
|
||||
var vec_stalld = Bool(false)
|
||||
var vec_irq = Bool(false)
|
||||
var vec_irq_cause = UFix(0,5)
|
||||
if (HAVE_VEC)
|
||||
{
|
||||
// vector control
|
||||
val vec = new rocketCtrlVec()
|
||||
|
||||
io.vec_dpath <> vec.io.dpath
|
||||
io.vec_iface <> vec.io.iface
|
||||
|
||||
vec.io.s := io.dpath.status(SR_S)
|
||||
vec.io.sr_ev := io.dpath.status(SR_EV)
|
||||
vec.io.exception := wb_reg_exception
|
||||
vec.io.eret := wb_reg_eret
|
||||
|
||||
vec_replay = vec.io.replay
|
||||
vec_stalld = vec.io.stalld // || id_vfence_cv && !vec.io.vfence_ready
|
||||
vec_irq = vec.io.irq
|
||||
vec_irq_cause = vec.io.irq_cause
|
||||
}
|
||||
|
||||
// exception handling
|
||||
// FIXME: verify PC in MEM stage points to valid, restartable instruction
|
||||
val p_irq_timer = (io.dpath.status(15).toBool && io.dpath.irq_timer);
|
||||
val p_irq_ipi = (io.dpath.status(13).toBool && io.dpath.irq_ipi);
|
||||
val interrupt =
|
||||
io.dpath.status(SR_ET).toBool && mem_reg_valid &&
|
||||
((io.dpath.status(15).toBool && io.dpath.irq_timer) ||
|
||||
(io.dpath.status(13).toBool && io.dpath.irq_ipi) ||
|
||||
vec_irq);
|
||||
|
||||
val interrupt_cause =
|
||||
Mux(p_irq_ipi, UFix(21,5),
|
||||
Mux(p_irq_timer, UFix(23,5),
|
||||
Mux(vec_irq, vec_irq_cause,
|
||||
UFix(0,5))))
|
||||
|
||||
val mem_xcpt_ma_ld = io.dmem.xcpt_ma_ld && !mem_reg_kill
|
||||
val mem_xcpt_ma_st = io.dmem.xcpt_ma_st && !mem_reg_kill
|
||||
val mem_xcpt_dtlb_ld = io.xcpt_dtlb_ld && !mem_reg_kill
|
||||
val mem_xcpt_dtlb_st = io.xcpt_dtlb_st && !mem_reg_kill
|
||||
|
||||
val mem_exception =
|
||||
interrupt ||
|
||||
mem_xcpt_ma_ld ||
|
||||
mem_xcpt_ma_st ||
|
||||
mem_xcpt_dtlb_ld ||
|
||||
mem_xcpt_dtlb_st ||
|
||||
mem_reg_xcpt_illegal ||
|
||||
mem_reg_xcpt_privileged ||
|
||||
mem_reg_xcpt_fpu ||
|
||||
mem_reg_xcpt_vec ||
|
||||
mem_reg_xcpt_syscall ||
|
||||
mem_reg_xcpt_itlb ||
|
||||
mem_reg_xcpt_ma_inst;
|
||||
val mem_exception =
|
||||
mem_reg_xcpt_interrupt ||
|
||||
mem_xcpt_ma_ld ||
|
||||
mem_xcpt_ma_st ||
|
||||
mem_xcpt_dtlb_ld ||
|
||||
mem_xcpt_dtlb_st ||
|
||||
mem_reg_xcpt_illegal ||
|
||||
mem_reg_xcpt_privileged ||
|
||||
mem_reg_xcpt_fpu ||
|
||||
mem_reg_xcpt_vec ||
|
||||
mem_reg_xcpt_syscall ||
|
||||
mem_reg_xcpt_itlb ||
|
||||
mem_reg_xcpt_ma_inst;
|
||||
|
||||
val mem_cause =
|
||||
Mux(interrupt, interrupt_cause, // asynchronous interrupt
|
||||
Mux(mem_reg_xcpt_itlb, UFix(1,5), // instruction access fault
|
||||
Mux(mem_reg_xcpt_illegal, UFix(2,5), // illegal instruction
|
||||
Mux(mem_reg_xcpt_privileged, UFix(3,5), // privileged instruction
|
||||
Mux(mem_reg_xcpt_fpu, UFix(4,5), // FPU disabled
|
||||
Mux(mem_reg_xcpt_syscall, UFix(6,5), // system call
|
||||
// breakpoint
|
||||
Mux(mem_xcpt_ma_ld, UFix(8,5), // misaligned load
|
||||
Mux(mem_xcpt_ma_st, UFix(9,5), // misaligned store
|
||||
Mux(mem_xcpt_dtlb_ld, UFix(10,5), // load fault
|
||||
Mux(mem_xcpt_dtlb_st, UFix(11,5), // store fault
|
||||
Mux(mem_reg_xcpt_vec, UFix(12,5), // vector disabled
|
||||
UFix(0,5)))))))))))); // instruction address misaligned
|
||||
val mem_cause =
|
||||
Mux(mem_reg_xcpt_interrupt, mem_reg_cause, // asynchronous interrupt
|
||||
Mux(mem_reg_xcpt_itlb, UFix(1,5), // instruction access fault
|
||||
Mux(mem_reg_xcpt_illegal, UFix(2,5), // illegal instruction
|
||||
Mux(mem_reg_xcpt_privileged, UFix(3,5), // privileged instruction
|
||||
Mux(mem_reg_xcpt_fpu, UFix(4,5), // FPU disabled
|
||||
Mux(mem_reg_xcpt_syscall, UFix(6,5), // system call
|
||||
// breakpoint
|
||||
Mux(mem_xcpt_ma_ld, UFix(8,5), // misaligned load
|
||||
Mux(mem_xcpt_ma_st, UFix(9,5), // misaligned store
|
||||
Mux(mem_xcpt_dtlb_ld, UFix(10,5), // load fault
|
||||
Mux(mem_xcpt_dtlb_st, UFix(11,5), // store fault
|
||||
Mux(mem_reg_xcpt_vec, UFix(12,5), // vector disabled
|
||||
UFix(0,5)))))))))))); // instruction address misaligned
|
||||
|
||||
// control transfer from ex/mem
|
||||
val take_pc_ex = ex_reg_btb_hit != br_taken || jr_taken
|
||||
val take_pc_wb = wb_reg_replay || vec_replay || wb_reg_exception || wb_reg_eret
|
||||
take_pc_wb := wb_reg_replay || vec_replay || wb_reg_exception || wb_reg_eret
|
||||
take_pc := take_pc_ex || take_pc_wb;
|
||||
|
||||
// replay mem stage PC on a DTLB miss or a long-latency writeback
|
||||
|
Loading…
Reference in New Issue
Block a user