From bd27d0fab222cc9a291eac5756c1705e8a374851 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 19 Mar 2012 01:02:06 -0700 Subject: [PATCH] can now take interrupts on stalled instructions --- rocket/src/main/scala/ctrl.scala | 146 ++++++++++++++++--------------- 1 file changed, 76 insertions(+), 70 deletions(-) diff --git a/rocket/src/main/scala/ctrl.scala b/rocket/src/main/scala/ctrl.scala index cd99bce4..9af0c14d 100644 --- a/rocket/src/main/scala/ctrl.scala +++ b/rocket/src/main/scala/ctrl.scala @@ -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) { @@ -421,12 +426,47 @@ 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_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_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(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 @@ -703,7 +709,7 @@ class rocketCtrl extends Component 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_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, // for privileged instructions, and for fence.i instructions val replay_ex = wb_reg_dcache_miss && ex_reg_load_use || mem_reg_flush_inst ||