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_di = Reg(resetVal = Bool(false));
|
||||||
val ex_reg_inst_ei = 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_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_ma_inst = Reg(resetVal = Bool(false));
|
||||||
val ex_reg_xcpt_itlb = Reg(resetVal = Bool(false));
|
val ex_reg_xcpt_itlb = Reg(resetVal = Bool(false));
|
||||||
val ex_reg_xcpt_illegal = 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_di = Reg(resetVal = Bool(false));
|
||||||
val mem_reg_inst_ei = 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_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_ma_inst = Reg(resetVal = Bool(false));
|
||||||
val mem_reg_xcpt_itlb = Reg(resetVal = Bool(false));
|
val mem_reg_xcpt_itlb = Reg(resetVal = Bool(false));
|
||||||
val mem_reg_xcpt_illegal = 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_val = Reg(resetVal = Bool(false));
|
||||||
val wb_reg_fp_sboard_set = 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.stalld) {
|
||||||
when (io.dpath.killf) {
|
when (io.dpath.killf) {
|
||||||
@ -421,12 +426,47 @@ class rocketCtrl extends Component
|
|||||||
}
|
}
|
||||||
id_reg_icmiss := !io.imem.resp_val;
|
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)
|
// executing ERET when traps are enabled causes an illegal instruction exception (as per ISA sim)
|
||||||
val illegal_inst =
|
val illegal_inst =
|
||||||
!(id_int_val.toBool || io.fpu.dec.valid || id_vec_val.toBool) ||
|
!(id_int_val.toBool || io.fpu.dec.valid || id_vec_val.toBool) ||
|
||||||
(id_eret.toBool && io.dpath.status(SR_ET).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) {
|
when (reset.toBool || io.dpath.killd) {
|
||||||
ex_reg_br_type := BR_N;
|
ex_reg_br_type := BR_N;
|
||||||
ex_reg_btb_hit := Bool(false);
|
ex_reg_btb_hit := Bool(false);
|
||||||
@ -479,6 +519,8 @@ class rocketCtrl extends Component
|
|||||||
}
|
}
|
||||||
ex_reg_mem_cmd := id_mem_cmd
|
ex_reg_mem_cmd := id_mem_cmd
|
||||||
ex_reg_mem_type := id_mem_type.toUFix
|
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 beq = io.dpath.br_eq;
|
||||||
val bne = ~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_cmd := ex_reg_mem_cmd;
|
||||||
mem_reg_mem_type := ex_reg_mem_type;
|
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) {
|
when (io.dpath.killm) {
|
||||||
wb_reg_valid := Bool(false)
|
wb_reg_valid := Bool(false)
|
||||||
@ -619,82 +663,44 @@ class rocketCtrl extends Component
|
|||||||
io.fpu.dec.wen && fp_sboard.io.r(3).data
|
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
|
// 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_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_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_ld = io.xcpt_dtlb_ld && !mem_reg_kill
|
||||||
val mem_xcpt_dtlb_st = io.xcpt_dtlb_st && !mem_reg_kill
|
val mem_xcpt_dtlb_st = io.xcpt_dtlb_st && !mem_reg_kill
|
||||||
|
|
||||||
val mem_exception =
|
val mem_exception =
|
||||||
interrupt ||
|
mem_reg_xcpt_interrupt ||
|
||||||
mem_xcpt_ma_ld ||
|
mem_xcpt_ma_ld ||
|
||||||
mem_xcpt_ma_st ||
|
mem_xcpt_ma_st ||
|
||||||
mem_xcpt_dtlb_ld ||
|
mem_xcpt_dtlb_ld ||
|
||||||
mem_xcpt_dtlb_st ||
|
mem_xcpt_dtlb_st ||
|
||||||
mem_reg_xcpt_illegal ||
|
mem_reg_xcpt_illegal ||
|
||||||
mem_reg_xcpt_privileged ||
|
mem_reg_xcpt_privileged ||
|
||||||
mem_reg_xcpt_fpu ||
|
mem_reg_xcpt_fpu ||
|
||||||
mem_reg_xcpt_vec ||
|
mem_reg_xcpt_vec ||
|
||||||
mem_reg_xcpt_syscall ||
|
mem_reg_xcpt_syscall ||
|
||||||
mem_reg_xcpt_itlb ||
|
mem_reg_xcpt_itlb ||
|
||||||
mem_reg_xcpt_ma_inst;
|
mem_reg_xcpt_ma_inst;
|
||||||
|
|
||||||
val mem_cause =
|
val mem_cause =
|
||||||
Mux(interrupt, interrupt_cause, // asynchronous interrupt
|
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_itlb, UFix(1,5), // instruction access fault
|
||||||
Mux(mem_reg_xcpt_illegal, UFix(2,5), // illegal instruction
|
Mux(mem_reg_xcpt_illegal, UFix(2,5), // illegal instruction
|
||||||
Mux(mem_reg_xcpt_privileged, UFix(3,5), // privileged 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_fpu, UFix(4,5), // FPU disabled
|
||||||
Mux(mem_reg_xcpt_syscall, UFix(6,5), // system call
|
Mux(mem_reg_xcpt_syscall, UFix(6,5), // system call
|
||||||
// breakpoint
|
// breakpoint
|
||||||
Mux(mem_xcpt_ma_ld, UFix(8,5), // misaligned load
|
Mux(mem_xcpt_ma_ld, UFix(8,5), // misaligned load
|
||||||
Mux(mem_xcpt_ma_st, UFix(9,5), // misaligned store
|
Mux(mem_xcpt_ma_st, UFix(9,5), // misaligned store
|
||||||
Mux(mem_xcpt_dtlb_ld, UFix(10,5), // load fault
|
Mux(mem_xcpt_dtlb_ld, UFix(10,5), // load fault
|
||||||
Mux(mem_xcpt_dtlb_st, UFix(11,5), // store fault
|
Mux(mem_xcpt_dtlb_st, UFix(11,5), // store fault
|
||||||
Mux(mem_reg_xcpt_vec, UFix(12,5), // vector disabled
|
Mux(mem_reg_xcpt_vec, UFix(12,5), // vector disabled
|
||||||
UFix(0,5)))))))))))); // instruction address misaligned
|
UFix(0,5)))))))))))); // instruction address misaligned
|
||||||
|
|
||||||
// control transfer from ex/mem
|
// control transfer from ex/mem
|
||||||
val take_pc_ex = ex_reg_btb_hit != br_taken || jr_taken
|
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;
|
take_pc := take_pc_ex || take_pc_wb;
|
||||||
|
|
||||||
// replay mem stage PC on a DTLB miss or a long-latency writeback
|
// replay mem stage PC on a DTLB miss or a long-latency writeback
|
||||||
@ -703,7 +709,7 @@ class rocketCtrl extends Component
|
|||||||
val replay_mem = dmem_kill_mem || mem_reg_wen && mem_ll_wb || mem_reg_replay
|
val replay_mem = dmem_kill_mem || mem_reg_wen && mem_ll_wb || mem_reg_replay
|
||||||
val kill_mem = dmem_kill_mem || mem_reg_wen && mem_ll_wb || take_pc_wb || mem_exception || mem_reg_kill
|
val kill_mem = dmem_kill_mem || mem_reg_wen && mem_ll_wb || take_pc_wb || mem_exception || mem_reg_kill
|
||||||
val kill_dcache = io.dtlb_miss || mem_reg_wen && mem_ll_wb || take_pc_wb || mem_exception || mem_reg_kill
|
val kill_dcache = io.dtlb_miss || mem_reg_wen && mem_ll_wb || take_pc_wb || mem_exception || mem_reg_kill
|
||||||
|
|
||||||
// replay execute stage PC when the D$ is blocked, when the D$ misses,
|
// replay execute stage PC when the D$ is blocked, when the D$ misses,
|
||||||
// for privileged instructions, and for fence.i instructions
|
// for privileged instructions, and for fence.i instructions
|
||||||
val replay_ex = wb_reg_dcache_miss && ex_reg_load_use || mem_reg_flush_inst ||
|
val replay_ex = wb_reg_dcache_miss && ex_reg_load_use || mem_reg_flush_inst ||
|
||||||
|
Loading…
Reference in New Issue
Block a user