don't flush pipeline on writes to side-effect-free PCRs
notably, K0, K1, and EPC
This commit is contained in:
		| @@ -6,6 +6,7 @@ import Constants._ | ||||
| import Instructions._ | ||||
| import hwacha._ | ||||
| import ALU._ | ||||
| import Util._ | ||||
|  | ||||
| class CtrlDpathIO extends Bundle() | ||||
| { | ||||
| @@ -174,13 +175,13 @@ object XDecode extends DecodeConstants | ||||
|     REMUW->     List(xpr64,N,N,BR_N,  N,Y,Y,A2_RTYPE,DW_32, FN_REMU,  N,M_X,      MT_X, N,Y,Y,WA_RD,WB_X,  PCR.N,N,N,N,N,N), | ||||
|                                          | ||||
|     SYSCALL->   List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_X,  FN_X,     N,M_X,      MT_X, N,N,N,WA_X, WB_X,  PCR.N,N,N,Y,N,N), | ||||
|     SETPCR->    List(Y,    N,N,BR_N,  N,N,N,A2_ITYPE,DW_XPR,FN_OP2,   N,M_X,      MT_X, N,N,Y,WA_RD,WB_ALU,PCR.S,N,N,N,Y,Y), | ||||
|     CLEARPCR->  List(Y,    N,N,BR_N,  N,N,N,A2_ITYPE,DW_XPR,FN_OP2,   N,M_X,      MT_X, N,N,Y,WA_RD,WB_ALU,PCR.C,N,N,N,Y,Y), | ||||
|     SETPCR->    List(Y,    N,N,BR_N,  N,N,N,A2_ITYPE,DW_XPR,FN_OP2,   N,M_X,      MT_X, N,N,Y,WA_RD,WB_ALU,PCR.S,N,N,N,Y,N), | ||||
|     CLEARPCR->  List(Y,    N,N,BR_N,  N,N,N,A2_ITYPE,DW_XPR,FN_OP2,   N,M_X,      MT_X, N,N,Y,WA_RD,WB_ALU,PCR.C,N,N,N,Y,N), | ||||
|     ERET->      List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_X,  FN_X,     N,M_X,      MT_X, N,N,N,WA_X, WB_X,  PCR.N,N,Y,N,Y,N), | ||||
|     FENCE->     List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_X,  FN_X,     Y,M_FENCE,  MT_X, N,N,N,WA_X, WB_X,  PCR.N,N,N,N,N,N), | ||||
|     FENCE_I->   List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_X,  FN_X,     Y,M_FENCE,  MT_X, N,N,N,WA_X, WB_X,  PCR.N,Y,N,N,N,Y), | ||||
|     MFPCR->     List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_X,  FN_X,     N,M_X,      MT_X, N,N,Y,WA_RD,WB_X,  PCR.F,N,N,N,Y,Y), | ||||
|     MTPCR->     List(Y,    N,N,BR_N,  N,Y,N,A2_RTYPE,DW_XPR,FN_OP2,   N,M_X,      MT_X, N,N,Y,WA_RD,WB_ALU,PCR.T,N,N,N,Y,Y), | ||||
|     MFPCR->     List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_X,  FN_X,     N,M_X,      MT_X, N,N,Y,WA_RD,WB_X,  PCR.F,N,N,N,Y,N), | ||||
|     MTPCR->     List(Y,    N,N,BR_N,  N,Y,N,A2_RTYPE,DW_XPR,FN_OP2,   N,M_X,      MT_X, N,N,Y,WA_RD,WB_ALU,PCR.T,N,N,N,Y,N), | ||||
|     RDTIME->    List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_XPR,FN_X,     N,M_X,      MT_X, N,N,Y,WA_RD,WB_TSC,PCR.N,N,N,N,N,N), | ||||
|     RDCYCLE->   List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_XPR,FN_X,     N,M_X,      MT_X, N,N,Y,WA_RD,WB_TSC,PCR.N,N,N,N,N,N), | ||||
|     RDINSTRET-> List(Y,    N,N,BR_N,  N,N,N,A2_X,    DW_XPR,FN_X,     N,M_X,      MT_X, N,N,Y,WA_RD,WB_IRT,PCR.N,N,N,N,N,N)) | ||||
| @@ -393,7 +394,6 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|   val wb_reg_eret            = Reg(resetVal = Bool(false)) | ||||
|   val wb_reg_xcpt            = Reg(resetVal = Bool(false)) | ||||
|   val wb_reg_replay          = Reg(resetVal = Bool(false)) | ||||
|   val wb_reg_replay_next     = Reg(resetVal = Bool(false)) | ||||
|   val wb_reg_cause           = Reg(){UFix()} | ||||
|   val wb_reg_fp_val          = Reg(resetVal = Bool(false)) | ||||
|   val wb_reg_div_mul_val = Reg(resetVal = Bool(false)) | ||||
| @@ -453,6 +453,9 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|  | ||||
|   // executing ERET when traps are enabled causes an illegal instruction exception | ||||
|   val illegal_inst = !id_int_val.toBool || (id_eret.toBool && io.dpath.status.et) | ||||
|   // flush pipeline on PCR writes that may have side effects | ||||
|   val id_pcr_flush = id_pcr != PCR.N && id_pcr != PCR.F && | ||||
|     id_raddr1 != PCR.K0 && id_raddr1 != PCR.K1 && id_raddr1 != PCR.EPC | ||||
|  | ||||
|   val (id_xcpt, id_cause) = checkExceptions(List( | ||||
|     (id_interrupt,                            id_interrupt_cause), | ||||
| @@ -499,7 +502,7 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|     ex_reg_flush_inst  := id_fence_i | ||||
|     ex_reg_fp_val           := id_fp_val | ||||
|     ex_reg_vec_val          := id_vec_val.toBool | ||||
|     ex_reg_replay_next      := id_replay_next | ||||
|     ex_reg_replay_next      := id_replay_next || id_pcr_flush | ||||
|     ex_reg_load_use         := id_load_use; | ||||
|     ex_reg_mem_cmd := id_mem_cmd | ||||
|     ex_reg_mem_type := id_mem_type.toUFix | ||||
| @@ -567,7 +570,7 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|   ctrl_killm := killm_common || mem_xcpt || fpu_kill_mem | ||||
|  | ||||
|   wb_reg_replay := replay_mem && !take_pc_wb | ||||
|   wb_reg_xcpt := mem_xcpt && !take_pc_wb && !wb_reg_replay_next | ||||
|   wb_reg_xcpt := mem_xcpt && !take_pc_wb | ||||
|   when (mem_xcpt) { wb_reg_cause := mem_cause } | ||||
|  | ||||
|   when (ctrl_killm) { | ||||
| @@ -580,7 +583,6 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|     wb_reg_mem_val     := Bool(false) | ||||
|     wb_reg_div_mul_val := Bool(false); | ||||
|     wb_reg_fp_val      := Bool(false) | ||||
|     wb_reg_replay_next := Bool(false) | ||||
|   } | ||||
|   .otherwise { | ||||
|     wb_reg_valid       := mem_reg_valid | ||||
| @@ -592,7 +594,6 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|     wb_reg_mem_val     := mem_reg_mem_val | ||||
|     wb_reg_div_mul_val := mem_reg_div_mul_val | ||||
|     wb_reg_fp_val      := mem_reg_fp_val | ||||
|     wb_reg_replay_next := mem_reg_replay_next | ||||
|   } | ||||
|  | ||||
|   val replay_wb = io.dmem.resp.bits.nack || wb_reg_replay || vec_replay || io.dpath.pcr_replay | ||||
| @@ -651,7 +652,7 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|   io.imem.req.bits.taken := !ex_reg_btb_hit || ex_reg_jalr | ||||
|   io.imem.req.valid  := take_pc | ||||
|  | ||||
|   // stall for RAW/WAW hazards on loads, AMOs, and mul/div in execute stage. | ||||
|   // stall for RAW/WAW hazards on PCRs, loads, AMOs, and mul/div in execute stage. | ||||
|   val data_hazard_ex = ex_reg_wen && | ||||
|     (id_renx1.toBool && id_raddr1 === io.dpath.ex_waddr || | ||||
|      id_renx2.toBool && id_raddr2 === io.dpath.ex_waddr || | ||||
| @@ -661,10 +662,10 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|      io.fpu.dec.ren2 && id_raddr2 === io.dpath.ex_waddr || | ||||
|      io.fpu.dec.ren3 && id_raddr3 === io.dpath.ex_waddr || | ||||
|      io.fpu.dec.wen  && id_waddr  === io.dpath.ex_waddr) | ||||
|   val id_ex_hazard = data_hazard_ex && (ex_reg_mem_val || ex_reg_div_mul_val || ex_reg_fp_val) || | ||||
|   val id_ex_hazard = data_hazard_ex && (ex_reg_pcr != PCR.N || ex_reg_mem_val || ex_reg_div_mul_val || ex_reg_fp_val) || | ||||
|                      fp_data_hazard_ex && (ex_reg_mem_val || ex_reg_fp_val) | ||||
|      | ||||
|   // stall for RAW/WAW hazards on LB/LH and mul/div in memory stage. | ||||
|   // stall for RAW/WAW hazards on PCRs, LB/LH, and mul/div in memory stage. | ||||
|   val mem_mem_cmd_bh = | ||||
|     if (!conf.fastLoadWord) Bool(true) | ||||
|     else if (conf.fastLoadByte) Bool(false) | ||||
| @@ -678,7 +679,7 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|      io.fpu.dec.ren2 && id_raddr2 === io.dpath.mem_waddr || | ||||
|      io.fpu.dec.ren3 && id_raddr3 === io.dpath.mem_waddr || | ||||
|      io.fpu.dec.wen  && id_waddr  === io.dpath.mem_waddr) | ||||
|   val id_mem_hazard = data_hazard_mem && (mem_reg_mem_val && mem_mem_cmd_bh || mem_reg_div_mul_val || mem_reg_fp_val) || | ||||
|   val id_mem_hazard = data_hazard_mem && (mem_reg_pcr != PCR.N || mem_reg_mem_val && mem_mem_cmd_bh || mem_reg_div_mul_val || mem_reg_fp_val) || | ||||
|                       fp_data_hazard_mem && mem_reg_fp_val | ||||
|   id_load_use := mem_reg_mem_val && (data_hazard_mem || fp_data_hazard_mem) | ||||
|  | ||||
| @@ -705,10 +706,11 @@ class Control(implicit conf: RocketConfiguration) extends Component | ||||
|     id_fp_val && id_stall_fpu || | ||||
|     id_mem_val && !io.dmem.req.ready || | ||||
|     vec_stalld | ||||
|   ctrl_killd := !io.imem.resp.valid || take_pc || ctrl_stalld || id_interrupt | ||||
|   val ctrl_draind = id_interrupt || ex_reg_replay_next | ||||
|   ctrl_killd := !io.imem.resp.valid || take_pc || ctrl_stalld || ctrl_draind | ||||
|  | ||||
|   io.dpath.killd := take_pc || ctrl_stalld && !id_interrupt | ||||
|   io.imem.resp.ready := pc_taken || !ctrl_stalld | ||||
|   io.dpath.killd := take_pc || ctrl_stalld && !ctrl_draind | ||||
|   io.imem.resp.ready := pc_taken || !ctrl_stalld || ctrl_draind | ||||
|   io.imem.invalidate := wb_reg_flush_inst | ||||
|  | ||||
|   io.dpath.mem_load := mem_reg_mem_val && mem_reg_wen | ||||
|   | ||||
		Reference in New Issue
	
	Block a user