From 9e6b86fe85c60f0f275ca28c157562bc84cffff7 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 24 Jan 2012 03:40:01 -0800 Subject: [PATCH] Fix a nasty replay bug If a mispredicted branch was followed by an instruction dependent on a load that missed in the cache, the mispredicted path would be executed rather than the correct path. Fail. Example broken code: lw x2, 0(x2) # cache miss beq x3, x0, somewhere # mispredicted branch move x4, x2 # wrong-path instruction dependent on load miss --- rocket/src/main/scala/ctrl.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rocket/src/main/scala/ctrl.scala b/rocket/src/main/scala/ctrl.scala index 2386fbf1..1546597d 100644 --- a/rocket/src/main/scala/ctrl.scala +++ b/rocket/src/main/scala/ctrl.scala @@ -345,6 +345,7 @@ class rocketCtrl extends Component val ex_reg_xcpt_fpu = Reg(resetVal = Bool(false)); val ex_reg_xcpt_syscall = Reg(resetVal = Bool(false)); val ex_reg_replay = Reg(resetVal = Bool(false)); + val ex_reg_lu_bypass = Reg(resetVal = Bool(false)); val mem_reg_inst_di = Reg(resetVal = Bool(false)); val mem_reg_inst_ei = Reg(resetVal = Bool(false)); @@ -404,6 +405,7 @@ class rocketCtrl extends Component ex_reg_xcpt_fpu <== Bool(false); ex_reg_xcpt_syscall <== Bool(false); ex_reg_replay <== Bool(false); + ex_reg_lu_bypass <== Bool(false); } otherwise { ex_reg_br_type <== id_br_type; @@ -423,6 +425,7 @@ class rocketCtrl extends Component ex_reg_xcpt_fpu <== Bool(false); ex_reg_xcpt_syscall <== id_syscall.toBool; ex_reg_replay <== id_reg_replay; + ex_reg_lu_bypass <== io.dpath.mem_lu_bypass; } ex_reg_mem_cmd <== id_mem_cmd; ex_reg_mem_type <== id_mem_type; @@ -567,7 +570,7 @@ class rocketCtrl extends Component // replay execute stage PC when the D$ is blocked, when the D$ misses, // for privileged instructions, and for fence.i instructions - val replay_ex = dcache_miss && Reg(io.dpath.mem_lu_bypass) || mem_reg_privileged || mem_reg_flush_inst || + val replay_ex = dcache_miss && ex_reg_lu_bypass || mem_reg_privileged || mem_reg_flush_inst || ex_reg_replay || ex_reg_mem_val && !(io.dmem.req_rdy && io.dtlb_rdy) val kill_ex = take_pc_wb || replay_ex