提交 38a7fe59 编写于 作者: L Lingrui98

frontend: send load replay redirect to bpu

上级 351914a5
......@@ -10,7 +10,6 @@ class FetchRequestBundle(implicit p: Parameters) extends XSBundle {
val startAddr = UInt(VAddrBits.W)
val fallThruAddr = UInt(VAddrBits.W)
val ftqIdx = new FtqPtr
val ldReplayOffset = ValidUndirectioned(UInt(log2Ceil(PredictWidth).W))
val ftqOffset = ValidUndirectioned(UInt(log2Ceil(PredictWidth).W))
val target = UInt(VAddrBits.W)
val oversize = Bool()
......
......@@ -64,7 +64,6 @@ class IfuToPreDecode(implicit p: Parameters) extends XSBundle {
val instValid = Bool()
val lastHalfMatch = Bool()
val oversize = Bool()
val startRange = Vec(PredictWidth, Bool())
}
class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
......@@ -184,8 +183,6 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
val f2_ftq_req = RegEnable(next = f1_ftq_req, enable = f1_fire)
val f2_situation = RegEnable(next = f1_situation, enable=f1_fire)
val f2_doubleLine = RegEnable(next = f1_doubleLine, enable=f1_fire)
val f2_isLoadReplay = f2_ftq_req.ldReplayOffset.valid
val f2_ldReplayIdx = f2_ftq_req.ldReplayOffset.bits
val f2_fire = io.toIbuffer.fire()
f1_ready := f2_ready || !f1_valid
......@@ -316,7 +313,6 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
else bank := Mux(f2_bank_hit(i), f2_hit_datas(i),Mux(sec_miss_reg(3),reservedRefillData(1),Mux(sec_miss_reg(1),reservedRefillData(0), f2_mq_datas(i))))
}
val f2_ldreplay_valids = Fill(PredictWidth, !f2_ftq_req.ldReplayOffset.valid) | Fill(PredictWidth, 1.U(1.W)) << (f2_ftq_req.ldReplayOffset.bits)
val f2_jump_valids = Fill(PredictWidth, !preDecoderOut.cfiOffset.valid) | Fill(PredictWidth, 1.U(1.W)) >> (~preDecoderOut.cfiOffset.bits)
val f2_predecode_valids = VecInit(preDecoderOut.pd.map(instr => instr.valid)).asUInt & f2_jump_valids
......@@ -352,7 +348,6 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
preDecoderIn.target := f2_ftq_req.target
preDecoderIn.oversize := f2_ftq_req.oversize
preDecoderIn.lastHalfMatch := f2_lastHalfMatch
preDecoderIn.startRange := f2_ldreplay_valids.asTypeOf(Vec(PredictWidth, Bool()))
predecodeOutValid := (f2_valid && f2_hit) || miss_all_fix
......
......@@ -354,11 +354,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
val allowBpuIn, allowToIfu = WireInit(false.B)
val flushToIfu = !allowToIfu
// all redirect except load replay
allowBpuIn := !ifuFlush && !roqFlush.valid &&
!(stage2Redirect.valid && !isLoadReplay(stage2Redirect)) &&
!(stage3Redirect.valid && !isLoadReplay(stage3Redirect))
allowBpuIn := !ifuFlush && !roqFlush.valid && !stage2Redirect.valid && !stage3Redirect.valid
allowToIfu := !ifuFlush && !roqFlush.valid && !stage2Redirect.valid && !stage3Redirect.valid
val bpuPtr, ifuPtr, ifuWbPtr, commPtr = RegInit(FtqPtr(false.B, 0.U))
......@@ -420,9 +416,6 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
val f_to_send :: f_sent :: Nil = Enum(2)
val entry_fetch_status = RegInit(VecInit(Seq.fill(FtqSize)(f_sent)))
val l_invalid :: l_replaying :: Nil = Enum(2)
val entry_replay_status = RegInit(VecInit(Seq.fill(FtqSize)(l_invalid)))
val h_not_hit :: h_false_hit :: h_hit :: Nil = Enum(3)
val entry_hit_status = RegInit(VecInit(Seq.fill(FtqSize)(h_not_hit)))
......@@ -441,7 +434,6 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
}
val set_fetch_status_between = set_status_between(entry_fetch_status)(_, _, _)
val set_commit_status_between = set_status_between(commitStateQueue)(_, _, _)
val set_replay_status_between = set_status_between(entry_replay_status)(_, _, _)
when (enq_fire) {
val enqIdx = bpuPtr.value
......@@ -450,7 +442,6 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
val enq_cfiIndex = WireInit(0.U.asTypeOf(new ValidUndirectioned(UInt(log2Ceil(PredictWidth).W))))
entry_fetch_status(enqIdx) := f_to_send
commitStateQueue(enqIdx) := VecInit(Seq.fill(PredictWidth)(c_invalid))
entry_replay_status(enqIdx) := l_invalid // may be useless
entry_hit_status(enqIdx) := Mux(io.fromBpu.resp.bits.hit, h_hit, h_not_hit) // pd may change it to h_false_hit
enq_cfiIndex.valid := preds.real_taken_mask.asUInt.orR
// when no takens, set cfiIndex to PredictWidth-1
......@@ -472,12 +463,11 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
val ifu_wb_idx = pdWb.bits.ftqIdx.value
// read ports: commit update
val ftq_pd_mem = Module(new SyncDataModuleTemplate(new Ftq_pd_Entry, FtqSize, 1, 1))
ftq_pd_mem.io.wen(0) := ifu_wb_valid && entry_replay_status(ifu_wb_idx) =/= l_replaying
ftq_pd_mem.io.wen(0) := ifu_wb_valid
ftq_pd_mem.io.waddr(0) := pdWb.bits.ftqIdx.value
ftq_pd_mem.io.wdata(0).fromPdWb(pdWb.bits)
val hit_pd_valid = entry_hit_status(ifu_wb_idx) === h_hit &&
entry_replay_status(ifu_wb_idx) =/= l_replaying &&
ifu_wb_valid
val hit_pd_mispred = hit_pd_valid && pdWb.bits.misOffset.valid
val hit_pd_mispred_reg = RegNext(hit_pd_mispred, init=false.B)
......@@ -492,7 +482,6 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
(commitStateQueue(ifu_wb_idx) zip comm_stq_wen).map{
case (qe, v) => when (v) { qe := c_valid }
}
entry_replay_status(ifu_wb_idx) := l_invalid
}
ifuWbPtr := ifuWbPtr + ifu_wb_valid
......@@ -523,10 +512,6 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
entry_hit_status(wb_idx_reg) := h_false_hit
}
XSError(ifu_wb_valid && pdWb.bits.misOffset.valid && entry_replay_status(ifu_wb_idx) === l_replaying,
p"unexpected predecode mispredict detected at idx: ${ifu_wb_idx} startAddr: ${Hexadecimal(pdWb.bits.pc(0))} " +
p"misOffset: ${pdWb.bits.misOffset.bits}\n")
// ****************************************************************
// **************************** to ifu ****************************
......@@ -551,15 +536,10 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
// read pc and target
ftq_pc_mem.io.raddr.init.last := ifuPtr.value
val loadReplayOffset = RegInit(0.U.asTypeOf(Valid(UInt(log2Ceil(PredictWidth).W))))
when (to_buf_fire) {
ifu_req_buf.bits.ftqIdx := ifuPtr
ifu_req_buf.bits.ldReplayOffset := loadReplayOffset
ifu_req_buf.bits.target := update_target(ifuPtr.value)
ifu_req_buf.bits.ftqOffset := cfiIndex_vec(ifuPtr.value)
when (loadReplayOffset.valid) {
loadReplayOffset.valid := false.B
}
}
when (RegNext(to_buf_fire)) {
......@@ -722,52 +702,23 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
)
// when redirect, we should reset ptrs and status queues
// For normal redirects, the inst casusing redirect itself
// should not be flushed (called flushAfter), we should reset
// both bpuPtr and ifuPtr, and send redirect request to both module.
// However, for load replays, the load instruction itself should be
// re-fetched and re-executed. In this case we only send another
// fetch request to ifu, fetching instructions starting from this load,
// resetting ifuPtr. We do not trigger a redirect for bpu, and we reuse
// previously predicted results to provide the following fetch stream
when(redirectVec.map(r => r.valid).reduce(_||_)){
val r = PriorityMux(redirectVec.map(r => (r.valid -> r)))
val notIfu = redirectVec.dropRight(1).map(r => r.valid).reduce(_||_)
val (idx, offset, flushItSelf) = (r.ftqIdx, r.ftqOffset, r.flushItSelf)
val next = idx + 1.U
when (!flushItSelf) {
bpuPtr := next
ifuPtr := next
ifuWbPtr := next
when (notIfu) {
commitStateQueue(idx.value).zipWithIndex.foreach({ case (s, i) =>
when(i.U > offset){
s := c_invalid
}
})
when(next.value =/= commPtr.value){ // if next.value === commPtr.value, ftq is full
commitStateQueue(next.value).foreach(_ := c_invalid)
bpuPtr := next
ifuPtr := next
ifuWbPtr := next
when (notIfu) {
commitStateQueue(idx.value).zipWithIndex.foreach({ case (s, i) =>
when(i.U > offset || i.U === offset && flushItSelf){
s := c_invalid
}
})
when(next.value =/= commPtr.value){ // if next.value === commPtr.value, ftq is full
commitStateQueue(next.value).foreach(_ := c_invalid)
}
set_replay_status_between(ifuPtr, FtqPtr.inverse(ifuPtr), l_invalid) // set all to invalid
loadReplayOffset.valid := false.B
// load replay
}.otherwise {
ifuPtr := idx
ifuWbPtr := idx
// set fetch status of entries between ifuPtr and bpuPtr to f_to_send
set_fetch_status_between(idx, ifuPtr, f_to_send)
// set commit state of entries between ifuWbPtr and bpuPtr to c_invalid
set_commit_status_between(idx+1.U, ifuWbPtr, VecInit(Seq.fill(PredictWidth)(c_invalid)))
// set replay status
set_replay_status_between(idx, ifuWbPtr, l_replaying)
// set load replay offset
loadReplayOffset.valid := true.B
loadReplayOffset.bits := offset
}
}
......@@ -786,11 +737,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
// **************************** to bpu ****************************
// ****************************************************************
// do not send redirect to bpu when load replay
io.toBpu.redirect <>
Mux(fromBackendRedirect.valid && !fromBackendRedirect.bits.flushItself,
fromBackendRedirect,
ifuRedirectToBpu)
io.toBpu.redirect <> Mux(fromBackendRedirect.valid, fromBackendRedirect, ifuRedirectToBpu)
val do_commit = Wire(Bool())
val canCommit = commPtr =/= ifuWbPtr && !do_commit &&
......
......@@ -85,7 +85,6 @@ class PreDecode(implicit p: Parameters) extends XSModule with HasPdConst{
})
val instValid = io.in.instValid
val startRange = io.in.startRange
val data = io.in.data
val pcStart = io.in.startAddr
val pcEnd = io.in.fallThruAddr
......@@ -122,7 +121,7 @@ class PreDecode(implicit p: Parameters) extends XSModule with HasPdConst{
val lastIsValidEnd = if (i == 0) { !io.in.lastHalfMatch } else { validEnd(i-1) || isFirstInBlock || !HasCExtension.B }
validStart(i) := (lastIsValidEnd || !HasCExtension.B) && startRange(i)
validStart(i) := (lastIsValidEnd || !HasCExtension.B)
validEnd(i) := validStart(i) && currentIsRVC || !validStart(i) || !HasCExtension.B
val brType::isCall::isRet::Nil = brInfo(inst)
......@@ -176,7 +175,7 @@ class PreDecode(implicit p: Parameters) extends XSModule with HasPdConst{
val endRange = ((Fill(PredictWidth, 1.U(1.W)) >> (~getBasicBlockIdx(realEndPC, pcStart))) | (Fill(PredictWidth, oversize)))
val takeRange = Fill(PredictWidth, !ParallelOR(takens)) | Fill(PredictWidth, 1.U(1.W)) >> (~PriorityEncoder(takens))
instRange := VecInit((0 until PredictWidth).map(i => endRange(i) & startRange(i) && takeRange(i)))
instRange := VecInit((0 until PredictWidth).map(i => endRange(i) && takeRange(i)))
realEndPC := Mux(hasFalseHit, Mux(hasJump, jumpNextPC, pcStart + (PredictWidth * 2).U), pcEnd)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册