未验证 提交 df5b4b8e 编写于 作者: Y Yinan Xu 提交者: GitHub

csr: optimize exception and trapTarget timing (#1372)

上级 5b7ef044
......@@ -33,7 +33,7 @@ import xiangshan.mem.mdp.{LFST, SSIT, WaitTable}
class CtrlToFtqIO(implicit p: Parameters) extends XSBundle {
val rob_commits = Vec(CommitWidth, Valid(new RobCommitInfo))
val stage2Redirect = Valid(new Redirect)
val redirect = Valid(new Redirect)
}
class RedirectGenerator(implicit p: Parameters) extends XSModule
......@@ -267,13 +267,6 @@ class CtrlBlockImp(outer: CtrlBlock)(implicit p: Parameters) extends LazyModuleI
val flushRedirect = Wire(Valid(new Redirect))
flushRedirect.valid := RegNext(rob.io.flushOut.valid)
flushRedirect.bits := RegEnable(rob.io.flushOut.bits, rob.io.flushOut.valid)
flushRedirect.bits.cfiUpdate.target := Mux(io.robio.toCSR.isXRet || rob.io.exception.valid,
io.robio.toCSR.trapTarget,
Mux(flushRedirect.bits.flushItself(),
flushPC, // replay inst
flushPC + 4.U // flush pipe
)
)
val flushRedirectReg = Wire(Valid(new Redirect))
flushRedirectReg.valid := RegNext(flushRedirect.valid, init = false.B)
......@@ -303,7 +296,8 @@ class CtrlBlockImp(outer: CtrlBlock)(implicit p: Parameters) extends LazyModuleI
redirectGen.io.loadReplay <> loadReplay
redirectGen.io.flush := flushRedirect.valid
val frontendFlush = DelayN(flushRedirect, 5)
val frontendFlushValid = DelayN(flushRedirect.valid, 5)
val frontendFlushBits = RegEnable(flushRedirect.bits, flushRedirect.valid)
// When ROB commits an instruction with a flush, we notify the frontend of the flush without the commit.
// Flushes to frontend may be delayed by some cycles and commit before flush causes errors.
// Thus, we make all flush reasons to behave the same as exceptions for frontend.
......@@ -312,14 +306,29 @@ class CtrlBlockImp(outer: CtrlBlock)(implicit p: Parameters) extends LazyModuleI
io.frontend.toFtq.rob_commits(i).valid := RegNext(is_commit)
io.frontend.toFtq.rob_commits(i).bits := RegEnable(rob.io.commits.info(i), is_commit)
}
io.frontend.toFtq.stage2Redirect := Mux(frontendFlush.valid, frontendFlush, redirectGen.io.stage2Redirect)
when (frontendFlush.valid) {
io.frontend.toFtq.stage2Redirect.bits.level := RedirectLevel.flush
io.frontend.toFtq.redirect.valid := frontendFlushValid || redirectGen.io.stage2Redirect.valid
io.frontend.toFtq.redirect.bits := Mux(frontendFlushValid, frontendFlushBits, redirectGen.io.stage2Redirect.bits)
when (frontendFlushValid) {
io.frontend.toFtq.redirect.bits.level := RedirectLevel.flush
// Be careful here:
// T0: flushRedirect.valid, exception.valid
// T1: csr.redirect.valid
// T2: csr.exception.valid
// T3: csr.trapTarget
// T4: ctrlBlock.trapTarget
// T5: io.frontend.toFtq.stage2Redirect.valid
val pc_from_csr = io.robio.toCSR.isXRet || DelayN(rob.io.exception.valid, 4)
val rob_flush_pc = RegEnable(Mux(flushRedirect.bits.flushItself(),
flushPC, // replay inst
flushPC + 4.U // flush pipe
), flushRedirect.valid)
val flushTarget = Mux(pc_from_csr, io.robio.toCSR.trapTarget, rob_flush_pc)
io.frontend.toFtq.redirect.bits.cfiUpdate.target := RegNext(flushTarget)
}
val pendingRedirect = RegInit(false.B)
when (stage2Redirect.valid) {
pendingRedirect := true.B
}.elsewhen (RegNext(io.frontend.toFtq.stage2Redirect.valid)) {
}.elsewhen (RegNext(io.frontend.toFtq.redirect.valid)) {
pendingRedirect := false.B
}
......
......@@ -53,6 +53,8 @@ class ExeUnit(config: ExuConfig)(implicit p: Parameters) extends Exu(config) {
csr.csrio <> csrio.get
csrio.get.tlb := DelayN(csr.csrio.tlb, 2)
csrio.get.customCtrl := DelayN(csr.csrio.customCtrl, 2)
csrio.get.trapTarget := RegNext(csr.csrio.trapTarget)
csr.csrio.exception := DelayN(csrio.get.exception, 2)
disableSfence := csr.csrio.disableSfence
csr_frm := csr.csrio.fpu.frm
// setup skip for hpm CSR read
......
......@@ -1001,17 +1001,20 @@ class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMP
// ctrl block will use theses later for flush
val isXRetFlag = RegInit(false.B)
val retTargetReg = Reg(retTarget.cloneType)
when (io.redirectIn.valid) {
when (DelayN(io.redirectIn.valid, 5)) {
isXRetFlag := false.B
}.elsewhen (isXRet) {
isXRetFlag := true.B
retTargetReg := retTarget
}
csrio.isXRet := isXRetFlag
val retTargetReg = RegEnable(retTarget, isXRet)
val tvec = Mux(delegS, stvec, mtvec)
val tvecBase = tvec(VAddrBits - 1, 2)
csrio.trapTarget := Mux(isXRetFlag,
// XRet sends redirect instead of Flush and isXRetFlag is true.B before redirect.valid.
// ROB sends exception at T0 while CSR receives at T2.
// We add a RegNext here and trapTarget is valid at T3.
csrio.trapTarget := RegEnable(Mux(isXRetFlag,
retTargetReg,
Mux(raiseDebugExceptionIntr || ebreakEnterParkLoop, debugTrapTarget,
// When MODE=Vectored, all synchronous exceptions into M/S mode
......@@ -1019,7 +1022,7 @@ class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMP
// interrupts cause the pc to be set to the address in the BASE field
// plus four times the interrupt cause number.
Cat(tvecBase + Mux(tvec(0) && raiseIntr, causeNO(3, 0), 0.U), 0.U(2.W))
))
)), isXRetFlag || csrio.exception.valid)
when (raiseExceptionIntr) {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
......
......@@ -93,7 +93,7 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)
icache.io.fencei := RegNext(io.fencei)
val needFlush = RegNext(io.backend.toFtq.stage2Redirect.valid)
val needFlush = RegNext(io.backend.toFtq.redirect.valid)
//IFU-Ftq
ifu.io.ftqInter.fromFtq <> ftq.io.toIfu
......
......@@ -458,10 +458,10 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
})
io.bpuInfo := DontCare
val stage2Redirect = io.fromBackend.stage2Redirect
val stage3Redirect = RegNext(io.fromBackend.stage2Redirect)
val backendRedirect = io.fromBackend.redirect
val backendRedirectReg = RegNext(io.fromBackend.redirect)
val stage2Flush = stage2Redirect.valid
val stage2Flush = backendRedirect.valid
val backendFlush = stage2Flush || RegNext(stage2Flush)
val ifuFlush = Wire(Bool())
......@@ -469,8 +469,8 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
val allowBpuIn, allowToIfu = WireInit(false.B)
val flushToIfu = !allowToIfu
allowBpuIn := !ifuFlush && !stage2Redirect.valid && !stage3Redirect.valid
allowToIfu := !ifuFlush && !stage2Redirect.valid && !stage3Redirect.valid
allowBpuIn := !ifuFlush && !backendRedirect.valid && !backendRedirectReg.valid
allowToIfu := !ifuFlush && !backendRedirect.valid && !backendRedirectReg.valid
val bpuPtr, ifuPtr, ifuWbPtr, commPtr = RegInit(FtqPtr(false.B, 0.U))
val validEntries = distanceBetween(bpuPtr, commPtr)
......@@ -673,7 +673,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
}.reduce(_||_) ||
(shareTailSlot.B && tailSlot.valid && pred_ftb_entry.tailSlot.sharing &&
!(pd_reg(tailSlot.offset).valid && pd_reg(tailSlot.offset).isBr))
val jmpOffset = tailSlot.offset
val jmp_pd = pd_reg(jmpOffset)
val jal_false_hit = pred_ftb_entry.jmpValid &&
......@@ -711,13 +711,13 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
// *******************************************************************************
// redirect read cfiInfo, couples to redirectGen s2
ftq_redirect_sram.io.ren.init.last := io.fromBackend.stage2Redirect.valid
ftq_redirect_sram.io.raddr.init.last := io.fromBackend.stage2Redirect.bits.ftqIdx.value
ftq_redirect_sram.io.ren.init.last := io.fromBackend.redirect.valid
ftq_redirect_sram.io.raddr.init.last := io.fromBackend.redirect.bits.ftqIdx.value
ftb_entry_mem.io.raddr.init.last := io.fromBackend.stage2Redirect.bits.ftqIdx.value
ftb_entry_mem.io.raddr.init.last := io.fromBackend.redirect.bits.ftqIdx.value
val stage3CfiInfo = ftq_redirect_sram.io.rdata.init.last
val fromBackendRedirect = WireInit(stage3Redirect)
val fromBackendRedirect = WireInit(backendRedirectReg)
val backendRedirectCfi = fromBackendRedirect.bits.cfiUpdate
backendRedirectCfi.fromFtqRedirectSram(stage3CfiInfo)
......@@ -783,7 +783,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
// fix mispredict entry
val lastIsMispredict = RegNext(
stage2Redirect.valid && stage2Redirect.bits.level === RedirectLevel.flushAfter, init = false.B
backendRedirect.valid && backendRedirect.bits.level === RedirectLevel.flushAfter, init = false.B
)
def updateCfiInfo(redirect: Valid[Redirect], isBackend: Boolean = true) = {
......@@ -802,8 +802,8 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
}
}
when(stage3Redirect.valid && lastIsMispredict) {
updateCfiInfo(stage3Redirect)
when(backendRedirectReg.valid && lastIsMispredict) {
updateCfiInfo(backendRedirectReg)
}.elsewhen (ifuRedirectToBpu.valid) {
updateCfiInfo(ifuRedirectToBpu, isBackend=false)
}
......@@ -812,7 +812,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
// **************************** flush ptr and state queue ****************************
// ***********************************************************************************
val redirectVec = VecInit(stage2Redirect, fromIfuRedirect)
val redirectVec = VecInit(backendRedirect, fromIfuRedirect)
// when redirect, we should reset ptrs and status queues
when(redirectVec.map(r => r.valid).reduce(_||_)){
......@@ -833,7 +833,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
}
// only the valid bit is actually needed
io.toIfu.redirect.bits := stage2Redirect.bits
io.toIfu.redirect.bits := backendRedirect.bits
io.toIfu.redirect.valid := stage2Flush
// commit
......@@ -976,7 +976,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe
}
val enq = io.fromBpu.resp
val perf_redirect = io.fromBackend.stage2Redirect
val perf_redirect = io.fromBackend.redirect
XSPerfAccumulate("entry", validEntries)
XSPerfAccumulate("bpu_to_ftq_stall", enq.valid && !enq.ready)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册