1
0

can now take interrupts on stalled instructions

This commit is contained in:
Andrew Waterman 2012-03-19 01:02:06 -07:00
parent 2ed0be65f9
commit bd27d0fab2

View File

@ -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 ||