1
0

Get s2_nack off the critical path

We were using it to compute the next PC on flush vs. replay (which require
PC+4 and PC, respectively).  This fix gets rid of the adder altogether by
reusing the M-stage PC in the flush case, which by construction holds PC+4.
This commit is contained in:
Andrew Waterman 2017-08-05 00:30:36 -07:00
parent bc298bf146
commit b9b4142bb4

View File

@ -376,14 +376,18 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
val mem_cfi_taken = (mem_ctrl.branch && mem_br_taken) || mem_ctrl.jalr || mem_ctrl.jal
val mem_direction_misprediction = (Bool(coreParams.jumpInFrontend) || mem_reg_btb_hit) && mem_ctrl.branch && mem_br_taken =/= mem_reg_btb_resp.taken
val mem_misprediction = if (usingBTB) mem_wrong_npc else mem_cfi_taken
take_pc_mem := mem_reg_valid && (mem_misprediction || mem_reg_sfence || (mem_ctrl.jalr && csr.io.status.debug))
take_pc_mem := mem_reg_valid && (mem_misprediction || mem_reg_sfence)
mem_reg_valid := !ctrl_killx
mem_reg_replay := !take_pc_mem_wb && replay_ex
mem_reg_xcpt := !ctrl_killx && ex_xcpt
mem_reg_xcpt_interrupt := !take_pc_mem_wb && ex_reg_xcpt_interrupt
when (ex_pc_valid) {
// on pipeline flushes, cause mem_npc to hold the sequential npc, which
// will drive the W-stage npc mux
when (mem_reg_valid && mem_reg_flush_pipe) {
mem_reg_sfence := false
}.elsewhen (ex_pc_valid) {
mem_ctrl := ex_ctrl
mem_reg_rvc := ex_reg_rvc
mem_reg_load := ex_ctrl.mem && isRead(ex_ctrl.mem_cmd)
@ -398,10 +402,16 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
mem_reg_inst := ex_reg_inst
mem_reg_pc := ex_reg_pc
mem_reg_wdata := alu.io.out
when (ex_ctrl.rxs2 && (ex_ctrl.mem || ex_ctrl.rocc || ex_sfence)) {
val typ = Mux(ex_ctrl.rocc, log2Ceil(xLen/8).U, ex_ctrl.mem_type)
mem_reg_rs2 := new StoreGen(typ, 0.U, ex_rs(1), coreDataBytes).data
}
when (ex_ctrl.jalr && csr.io.status.debug) {
// flush I$ on D-mode JALR to effect uncached fetch without D$ flush
mem_ctrl.fence_i := true
mem_reg_flush_pipe := true
}
}
val mem_breakpoint = (mem_reg_load && bpu.io.xcpt_ld) || (mem_reg_store && bpu.io.xcpt_st)
@ -438,9 +448,6 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
wb_reg_cause := mem_cause
wb_reg_inst := mem_reg_inst
wb_reg_pc := mem_reg_pc
when (mem_ctrl.jalr && csr.io.status.debug) {
wb_ctrl.fence_i := true
}
}
val (wb_xcpt, wb_cause) = checkExceptions(List(
@ -458,7 +465,6 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
val replay_wb_common = io.dmem.s2_nack || wb_reg_replay
val replay_wb_rocc = wb_reg_valid && wb_ctrl.rocc && !io.rocc.cmd.ready
val replay_wb = replay_wb_common || replay_wb_rocc
val wb_npc = encodeVirtualAddress(wb_reg_pc, wb_reg_pc + Mux(replay_wb, 0.U, Mux(wb_reg_rvc, 2.U, 4.U)))
take_pc_wb := replay_wb || wb_xcpt || csr.io.eret || wb_reg_flush_pipe
// writeback arbitration
@ -586,8 +592,8 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
io.imem.req.bits.speculative := !take_pc_wb
io.imem.req.bits.pc :=
Mux(wb_xcpt || csr.io.eret, csr.io.evec, // exception or [m|s]ret
Mux(replay_wb || wb_reg_flush_pipe, wb_npc, // replay or flush
mem_npc)) // branch misprediction
Mux(replay_wb, wb_reg_pc, // replay
mem_npc)) // flush or branch misprediction
io.imem.flush_icache := wb_reg_valid && wb_ctrl.fence_i && !io.dmem.s2_nack
io.imem.sfence.valid := wb_reg_valid && wb_reg_sfence
io.imem.sfence.bits.rs1 := wb_ctrl.mem_type(0)