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

rob: optimize timing for commit and walk (#1644)

* rob: separate walk and commit valid bits

* rob: optimize instrCnt timing

* rob: fix blockCommit condition when flushPipe

When flushPipe is enabled, it will block commits in ROB. However,
in the deqPtrModule, the commit is not blocked. This commit fixes
the issue.
上级 53b8f1a7
......@@ -371,15 +371,17 @@ class RobCommitInfo(implicit p: Parameters) extends XSBundle {
}
class RobCommitIO(implicit p: Parameters) extends XSBundle {
val isCommit = Output(Bool())
val commitValid = Vec(CommitWidth, Output(Bool()))
val isWalk = Output(Bool())
val valid = Vec(CommitWidth, Output(Bool()))
// valid bits optimized for walk
val walkValid = Vec(CommitWidth, Output(Bool()))
val info = Vec(CommitWidth, Output(new RobCommitInfo))
def hasWalkInstr = isWalk && valid.asUInt.orR
val info = Vec(CommitWidth, Output(new RobCommitInfo))
def hasCommitInstr = !isWalk && valid.asUInt.orR
def hasWalkInstr: Bool = isWalk && walkValid.asUInt.orR
def hasCommitInstr: Bool = isCommit && commitValid.asUInt.orR
}
class RSFeedback(implicit p: Parameters) extends XSBundle {
......
......@@ -342,7 +342,9 @@ class CtrlBlockImp(outer: CtrlBlock)(implicit p: Parameters) extends LazyModuleI
// 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.
for (i <- 0 until CommitWidth) {
val is_commit = rob.io.commits.valid(i) && !rob.io.commits.isWalk && !rob.io.flushOut.valid
// why flushOut: instructions with flushPipe are not commited to frontend
// If we commit them to frontend, it will cause flush after commit, which is not acceptable by frontend.
val is_commit = rob.io.commits.commitValid(i) && rob.io.commits.isCommit && !rob.io.flushOut.valid
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)
}
......
......@@ -253,12 +253,10 @@ class Rename(implicit p: Parameters) extends XSModule with HasPerfEvents {
* Instructions commit: update freelist and rename table
*/
for (i <- 0 until CommitWidth) {
val commitValid = io.robCommits.isCommit && io.robCommits.commitValid(i)
val walkValid = io.robCommits.isWalk && io.robCommits.walkValid(i)
Seq((io.intRenamePorts, false), (io.fpRenamePorts, true)) foreach { case (rat, fp) =>
// is valid commit req and given instruction has destination register
val commitDestValid = io.robCommits.valid(i) && needDestRegCommit(fp, io.robCommits.info(i))
XSDebug(p"isFp[${fp}]index[$i]-commitDestValid:$commitDestValid,isWalk:${io.robCommits.isWalk}\n")
/*
I. RAT Update
*/
......@@ -279,14 +277,15 @@ class Rename(implicit p: Parameters) extends XSModule with HasPerfEvents {
II. Free List Update
*/
if (fp) { // Float Point free list
fpFreeList.io.freeReq(i) := commitDestValid && !io.robCommits.isWalk
fpFreeList.io.freeReq(i) := commitValid && needDestRegCommit(fp, io.robCommits.info(i))
fpFreeList.io.freePhyReg(i) := io.robCommits.info(i).old_pdest
} else { // Integer free list
intFreeList.io.freeReq(i) := intRefCounter.io.freeRegs(i).valid
intFreeList.io.freePhyReg(i) := intRefCounter.io.freeRegs(i).bits
}
}
intRefCounter.io.deallocate(i).valid := io.robCommits.valid(i) && needDestRegCommit(false, io.robCommits.info(i))
intRefCounter.io.deallocate(i).valid := (commitValid || walkValid) && needDestRegCommit(false, io.robCommits.info(i))
intRefCounter.io.deallocate(i).bits := Mux(io.robCommits.isWalk, io.robCommits.info(i).pdest, io.robCommits.info(i).old_pdest)
}
......@@ -308,10 +307,10 @@ class Rename(implicit p: Parameters) extends XSModule with HasPerfEvents {
}
XSDebug(io.robCommits.isWalk, p"Walk Recovery Enabled\n")
XSDebug(io.robCommits.isWalk, p"validVec:${Binary(io.robCommits.valid.asUInt)}\n")
XSDebug(io.robCommits.isWalk, p"validVec:${Binary(io.robCommits.walkValid.asUInt)}\n")
for (i <- 0 until CommitWidth) {
val info = io.robCommits.info(i)
XSDebug(io.robCommits.isWalk && io.robCommits.valid(i), p"[#$i walk info] pc:${Hexadecimal(info.pc)} " +
XSDebug(io.robCommits.isWalk && io.robCommits.walkValid(i), p"[#$i walk info] pc:${Hexadecimal(info.pc)} " +
p"ldest:${info.ldest} rfWen:${info.rfWen} fpWen:${info.fpWen} " +
p"pdest:${info.pdest} old_pdest:${info.old_pdest}\n")
}
......
......@@ -105,13 +105,13 @@ class RenameTableWrapper(implicit p: Parameters) extends XSModule {
intRat.io.readPorts <> io.intReadPorts.flatten
val intDestValid = io.robCommits.info.map(_.rfWen)
for ((arch, i) <- intRat.io.archWritePorts.zipWithIndex) {
arch.wen := !io.robCommits.isWalk && io.robCommits.valid(i) && intDestValid(i)
arch.wen := io.robCommits.isCommit && io.robCommits.commitValid(i) && intDestValid(i)
arch.addr := io.robCommits.info(i).ldest
arch.data := io.robCommits.info(i).pdest
XSError(arch.wen && arch.addr === 0.U && arch.data =/= 0.U, "pdest for $0 should be 0\n")
}
for ((spec, i) <- intRat.io.specWritePorts.zipWithIndex) {
spec.wen := io.robCommits.isWalk && io.robCommits.valid(i) && intDestValid(i)
spec.wen := io.robCommits.isWalk && io.robCommits.walkValid(i) && intDestValid(i)
spec.addr := io.robCommits.info(i).ldest
spec.data := io.robCommits.info(i).old_pdest
XSError(spec.wen && spec.addr === 0.U && spec.data =/= 0.U, "pdest for $0 should be 0\n")
......@@ -128,12 +128,12 @@ class RenameTableWrapper(implicit p: Parameters) extends XSModule {
fpRat.io.debug_rdata <> io.debug_fp_rat
fpRat.io.readPorts <> io.fpReadPorts.flatten
for ((arch, i) <- fpRat.io.archWritePorts.zipWithIndex) {
arch.wen := !io.robCommits.isWalk && io.robCommits.valid(i) && io.robCommits.info(i).fpWen
arch.wen := io.robCommits.isCommit && io.robCommits.commitValid(i) && io.robCommits.info(i).fpWen
arch.addr := io.robCommits.info(i).ldest
arch.data := io.robCommits.info(i).pdest
}
for ((spec, i) <- fpRat.io.specWritePorts.zipWithIndex) {
spec.wen := io.robCommits.isWalk && io.robCommits.valid(i) && io.robCommits.info(i).fpWen
spec.wen := io.robCommits.isWalk && io.robCommits.walkValid(i) && io.robCommits.info(i).fpWen
spec.addr := io.robCommits.info(i).ldest
spec.data := io.robCommits.info(i).old_pdest
}
......
......@@ -90,9 +90,7 @@ class RobDeqPtrWrapper(implicit p: Parameters) extends XSModule with HasCircular
val intrBitSetReg = Input(Bool())
val hasNoSpecExec = Input(Bool())
val interrupt_safe = Input(Bool())
val misPredBlock = Input(Bool())
val isReplaying = Input(Bool())
val hasWFI = Input(Bool())
val blockCommit = Input(Bool())
// output: the CommitWidth deqPtr
val out = Vec(CommitWidth, Output(new RobPtr))
val next_out = Vec(CommitWidth, Output(new RobPtr))
......@@ -109,7 +107,7 @@ class RobDeqPtrWrapper(implicit p: Parameters) extends XSModule with HasCircular
// for normal commits: only to consider when there're no exceptions
// we don't need to consider whether the first instruction has exceptions since it wil trigger exceptions.
val commit_exception = io.exception_state.valid && !isAfter(io.exception_state.bits.robIdx, deqPtrVec.last)
val canCommit = VecInit((0 until CommitWidth).map(i => io.deq_v(i) && io.deq_w(i) && !io.misPredBlock && !io.isReplaying && !io.hasWFI))
val canCommit = VecInit((0 until CommitWidth).map(i => io.deq_v(i) && io.deq_w(i)))
val normalCommitCnt = PriorityEncoder(canCommit.map(c => !c) :+ true.B)
// when io.intrBitSetReg or there're possible exceptions in these instructions,
// only one instruction is allowed to commit
......@@ -117,7 +115,7 @@ class RobDeqPtrWrapper(implicit p: Parameters) extends XSModule with HasCircular
val commitCnt = Mux(allowOnlyOne, canCommit(0), normalCommitCnt)
val commitDeqPtrVec = VecInit(deqPtrVec.map(_ + commitCnt))
val deqPtrVec_next = Mux(io.state === 0.U && !redirectOutValid, commitDeqPtrVec, deqPtrVec)
val deqPtrVec_next = Mux(io.state === 0.U && !redirectOutValid && !io.blockCommit, commitDeqPtrVec, deqPtrVec)
deqPtrVec := deqPtrVec_next
......@@ -138,22 +136,24 @@ class RobEnqPtrWrapper(implicit p: Parameters) extends XSModule with HasCircular
val allowEnqueue = Input(Bool())
val hasBlockBackward = Input(Bool())
val enq = Vec(RenameWidth, Input(Bool()))
val out = Output(new RobPtr)
val out = Output(Vec(RenameWidth, new RobPtr))
})
val enqPtr = RegInit(0.U.asTypeOf(new RobPtr))
val enqPtrVec = RegInit(VecInit.tabulate(RenameWidth)(_.U.asTypeOf(new RobPtr)))
// enqueue
val canAccept = io.allowEnqueue && !io.hasBlockBackward
val dispatchNum = Mux(canAccept, PopCount(io.enq), 0.U)
when (io.redirect.valid) {
enqPtr := io.redirect.bits.robIdx + Mux(io.redirect.bits.flushItself(), 0.U, 1.U)
for ((ptr, i) <- enqPtrVec.zipWithIndex) {
when(io.redirect.valid) {
ptr := Mux(io.redirect.bits.flushItself(), io.redirect.bits.robIdx + i.U, io.redirect.bits.robIdx + (i + 1).U)
}.otherwise {
enqPtr := enqPtr + dispatchNum
ptr := ptr + dispatchNum
}
}
io.out := enqPtr
io.out := enqPtrVec
}
......@@ -348,14 +348,14 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// pointers
// For enqueue ptr, we don't duplicate it since only enqueue needs it.
val enqPtr = Wire(new RobPtr)
val enqPtrVec = Wire(Vec(RenameWidth, new RobPtr))
val deqPtrVec = Wire(Vec(CommitWidth, new RobPtr))
val walkPtrVec = Reg(Vec(CommitWidth, new RobPtr))
val validCounter = RegInit(0.U(log2Ceil(RobSize + 1).W))
val allowEnqueue = RegInit(true.B)
val enqPtrVec = VecInit((0 until RenameWidth).map(i => enqPtr + PopCount(io.enq.needAlloc.take(i))))
val enqPtr = enqPtrVec.head
val deqPtr = deqPtrVec(0)
val walkPtr = walkPtrVec(0)
......@@ -399,7 +399,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// To reduce registers usage, for hasBlockBackward cases, we allow enqueue after ROB is empty.
when (isEmpty) { hasBlockBackward:= false.B }
// When any instruction commits, hasNoSpecExec should be set to false.B
when (io.commits.valid.asUInt.orR && state =/= s_extrawalk) { hasNoSpecExec:= false.B }
when ((io.commits.hasWalkInstr && state =/= s_extrawalk) || io.commits.hasCommitInstr) { hasNoSpecExec:= false.B }
// The wait-for-interrupt (WFI) instruction waits in the ROB until an interrupt might need servicing.
// io.csr.wfiEvent will be asserted if the WFI can resume execution, and we change the state to s_wfi_idle.
......@@ -410,21 +410,23 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
hasWFI := false.B
}
val allocatePtrVec = VecInit((0 until RenameWidth).map(i => enqPtrVec(PopCount(io.enq.needAlloc.take(i)))))
io.enq.canAccept := allowEnqueue && !hasBlockBackward
io.enq.resp := enqPtrVec
io.enq.resp := allocatePtrVec
val canEnqueue = VecInit(io.enq.req.map(_.valid && io.enq.canAccept))
val timer = GTimer()
for (i <- 0 until RenameWidth) {
// we don't check whether io.redirect is valid here since redirect has higher priority
when (canEnqueue(i)) {
val enqUop = io.enq.req(i).bits
val enqIndex = allocatePtrVec(i).value
// store uop in data module and debug_microOp Vec
debug_microOp(enqPtrVec(i).value) := enqUop
debug_microOp(enqPtrVec(i).value).debugInfo.dispatchTime := timer
debug_microOp(enqPtrVec(i).value).debugInfo.enqRsTime := timer
debug_microOp(enqPtrVec(i).value).debugInfo.selectTime := timer
debug_microOp(enqPtrVec(i).value).debugInfo.issueTime := timer
debug_microOp(enqPtrVec(i).value).debugInfo.writebackTime := timer
debug_microOp(enqIndex) := enqUop
debug_microOp(enqIndex).debugInfo.dispatchTime := timer
debug_microOp(enqIndex).debugInfo.enqRsTime := timer
debug_microOp(enqIndex).debugInfo.selectTime := timer
debug_microOp(enqIndex).debugInfo.issueTime := timer
debug_microOp(enqIndex).debugInfo.writebackTime := timer
when (enqUop.ctrl.blockBackward) {
hasBlockBackward := true.B
}
......@@ -557,16 +559,16 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// wiring to csr
val (wflags, fpWen) = (0 until CommitWidth).map(i => {
val v = io.commits.valid(i)
val v = io.commits.commitValid(i)
val info = io.commits.info(i)
(v & info.wflags, v & info.fpWen)
}).unzip
val fflags = Wire(Valid(UInt(5.W)))
fflags.valid := Mux(io.commits.isWalk, false.B, Cat(wflags).orR)
fflags.valid := io.commits.isCommit && VecInit(wflags).asUInt.orR
fflags.bits := wflags.zip(fflagsDataRead).map({
case (w, f) => Mux(w, f, 0.U)
}).reduce(_|_)
val dirty_fs = Mux(io.commits.isWalk, false.B, Cat(fpWen).orR)
val dirty_fs = io.commits.isCommit && VecInit(fpWen).asUInt.orR
// when mispredict branches writeback, stop commit in the next 2 cycles
// TODO: don't check all exu write back
......@@ -579,9 +581,12 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
misPredBlockCounter >> 1.U
)
val misPredBlock = misPredBlockCounter(0)
val blockCommit = misPredBlock || isReplaying || lastCycleFlush || hasWFI
io.commits.isWalk := state =/= s_idle
val commit_v = Mux(state === s_idle, VecInit(deqPtrVec.map(ptr => valid(ptr.value))), VecInit(walkPtrVec.map(ptr => valid(ptr.value))))
io.commits.isCommit := state === s_idle && !blockCommit
val walk_v = VecInit(walkPtrVec.map(ptr => valid(ptr.value)))
val commit_v = VecInit(deqPtrVec.map(ptr => valid(ptr.value)))
// store will be commited iff both sta & std have been writebacked
val commit_w = VecInit(deqPtrVec.map(ptr => writebacked(ptr.value) && store_data_writebacked(ptr.value)))
val commit_exception = exceptionDataRead.valid && !isAfter(exceptionDataRead.bits.robIdx, deqPtrVec.last)
......@@ -592,20 +597,24 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// defaults: state === s_idle and instructions commit
// when intrBitSetReg, allow only one instruction to commit at each clock cycle
val isBlocked = if (i != 0) Cat(commit_block.take(i)).orR || allowOnlyOneCommit else intrEnable || deqHasException || deqHasReplayInst
io.commits.valid(i) := commit_v(i) && commit_w(i) && !isBlocked && !misPredBlock && !isReplaying && !lastCycleFlush && !hasWFI
io.commits.walkValid(i) := DontCare
io.commits.commitValid(i) := commit_v(i) && commit_w(i) && !isBlocked
io.commits.info(i) := dispatchDataRead(i)
when (state === s_walk) {
io.commits.valid(i) := commit_v(i) && shouldWalkVec(i)
io.commits.walkValid(i) := commit_v(i) && shouldWalkVec(i)
}.elsewhen(state === s_extrawalk) {
io.commits.valid(i) := (if (i < RenameWidth) usedSpaceForMPR(RenameWidth-i-1) else false.B)
io.commits.walkValid(i) := (if (i < RenameWidth) usedSpaceForMPR(RenameWidth-i-1) else false.B)
io.commits.info(i) := (if (i < RenameWidth) extraSpaceForMPR(RenameWidth-i-1) else DontCare)
io.commits.walkValid(i) := shouldWalkVec(i)
when (io.commits.isWalk && state === s_walk && shouldWalkVec(i)) {
XSError(!walk_v(i), s"why not $i???\n")
}
when (state === s_extrawalk) {
if (i < RenameWidth) {
io.commits.walkValid(i) := usedSpaceForMPR(RenameWidth - i - 1)
io.commits.info(i) := extraSpaceForMPR(RenameWidth - i - 1)
}
else {
io.commits.walkValid(i) := false.B
}
}
XSInfo(state === s_idle && io.commits.valid(i),
XSInfo(io.commits.isCommit && io.commits.commitValid(i),
"retired pc %x wen %d ldest %d pdest %x old_pdest %x data %x fflags: %b\n",
debug_microOp(deqPtrVec(i).value).cf.pc,
io.commits.info(i).rfWen,
......@@ -615,13 +624,13 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
debug_exuData(deqPtrVec(i).value),
fflagsDataRead(i)
)
XSInfo(state === s_walk && io.commits.valid(i), "walked pc %x wen %d ldst %d data %x\n",
XSInfo(state === s_walk && io.commits.walkValid(i), "walked pc %x wen %d ldst %d data %x\n",
debug_microOp(walkPtrVec(i).value).cf.pc,
io.commits.info(i).rfWen,
io.commits.info(i).ldest,
debug_exuData(walkPtrVec(i).value)
)
XSInfo(state === s_extrawalk && io.commits.valid(i), "use extra space walked wen %d ldst %d\n",
XSInfo(state === s_extrawalk && io.commits.walkValid(i), "use extra space walked wen %d ldst %d\n",
io.commits.info(i).rfWen,
io.commits.info(i).ldest
)
......@@ -635,13 +644,14 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
io.csr.dirty_fs := RegNext(dirty_fs)
// commit load/store to lsq
val ldCommitVec = VecInit((0 until CommitWidth).map(i => io.commits.valid(i) && io.commits.info(i).commitType === CommitType.LOAD))
val stCommitVec = VecInit((0 until CommitWidth).map(i => io.commits.valid(i) && io.commits.info(i).commitType === CommitType.STORE))
io.lsq.lcommit := RegNext(Mux(io.commits.isWalk, 0.U, PopCount(ldCommitVec)))
io.lsq.scommit := RegNext(Mux(io.commits.isWalk, 0.U, PopCount(stCommitVec)))
io.lsq.pendingld := RegNext(!io.commits.isWalk && io.commits.info(0).commitType === CommitType.LOAD && valid(deqPtr.value))
io.lsq.pendingst := RegNext(!io.commits.isWalk && io.commits.info(0).commitType === CommitType.STORE && valid(deqPtr.value))
io.lsq.commit := RegNext(!io.commits.isWalk && io.commits.valid(0))
val ldCommitVec = VecInit((0 until CommitWidth).map(i => io.commits.commitValid(i) && io.commits.info(i).commitType === CommitType.LOAD))
val stCommitVec = VecInit((0 until CommitWidth).map(i => io.commits.commitValid(i) && io.commits.info(i).commitType === CommitType.STORE))
io.lsq.lcommit := RegNext(Mux(io.commits.isCommit, PopCount(ldCommitVec), 0.U))
io.lsq.scommit := RegNext(Mux(io.commits.isCommit, PopCount(stCommitVec), 0.U))
// indicate a pending load or store
io.lsq.pendingld := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.LOAD && valid(deqPtr.value))
io.lsq.pendingst := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.STORE && valid(deqPtr.value))
io.lsq.commit := RegNext(io.commits.isCommit && io.commits.commitValid(0))
/**
* state changes
......@@ -650,11 +660,24 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
* (3) walk: when walking comes to the end, switch to s_walk
* (4) s_extrawalk to s_walk
*/
// state === s_idle: don't change when walk_no_need
// state === s_walk: don't change when walk_no_need && walkFinished
// state === s_extrawalk: always continue to walk (because it's not possible for walk_no_need)
val zeroWalkDistance = enqPtr - 1.U === io.redirect.bits.robIdx && !io.redirect.bits.flushItself()
val noNeedToWalk = zeroWalkDistance && (state === s_idle || (state === s_walk && walkFinished))
// update the state depending on whether there is a redirect
val state_next = Mux(io.redirect.valid,
Mux(io.enq.needAlloc.asUInt.orR, s_extrawalk, s_walk),
Mux(io.enq.needAlloc.asUInt.orR,
s_extrawalk,
Mux(noNeedToWalk, s_idle, s_walk)
),
Mux(state === s_walk && walkFinished,
s_idle,
Mux(state === s_extrawalk, s_walk, state)
Mux(state === s_extrawalk,
// if no more walk, switch to s_idle
Mux(walkCounter === 0.U, s_idle, s_walk),
state
)
)
)
state := state_next
......@@ -670,9 +693,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
deqPtrGenModule.io.intrBitSetReg := intrBitSetReg
deqPtrGenModule.io.hasNoSpecExec := hasNoSpecExec
deqPtrGenModule.io.interrupt_safe := interrupt_safe(deqPtr.value)
deqPtrGenModule.io.misPredBlock := misPredBlock
deqPtrGenModule.io.isReplaying := isReplaying
deqPtrGenModule.io.hasWFI := hasWFI
deqPtrGenModule.io.blockCommit := blockCommit
deqPtrVec := deqPtrGenModule.io.out
val deqPtrVec_next = deqPtrGenModule.io.next_out
......@@ -681,7 +702,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
enqPtrGenModule.io.allowEnqueue := allowEnqueue
enqPtrGenModule.io.hasBlockBackward := hasBlockBackward
enqPtrGenModule.io.enq := VecInit(io.enq.req.map(_.valid))
enqPtr := enqPtrGenModule.io.out
enqPtrVec := enqPtrGenModule.io.out
val thisCycleWalkCount = Mux(walkFinished, walkCounter, CommitWidth.U)
// next walkPtrVec:
......@@ -698,13 +719,13 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
val lastCycleRedirect = RegNext(io.redirect.valid)
val trueValidCounter = Mux(lastCycleRedirect, distanceBetween(enqPtr, deqPtr), validCounter)
val commitCnt = PopCount(io.commits.valid)
validCounter := Mux(state === s_idle,
val commitCnt = PopCount(io.commits.commitValid)
validCounter := Mux(io.commits.isCommit,
(validCounter - commitCnt) + dispatchNum,
trueValidCounter
)
allowEnqueue := Mux(state === s_idle,
allowEnqueue := Mux(io.commits.isCommit,
validCounter + dispatchNum <= (RobSize - RenameWidth).U,
trueValidCounter <= (RobSize - RenameWidth).U
)
......@@ -721,11 +742,13 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// Previously we use `+` to count the walk distance and it causes overflows
// when RobSize is power of 2. We change it to `+&` to allow walkCounter to be RobSize.
// The width of walkCounter also needs to be changed.
redirectWalkDistance +& io.redirect.bits.flushItself() - commitCnt,
redirectWalkDistance +& io.redirect.bits.flushItself()
redirectWalkDistance - (thisCycleWalkCount - io.redirect.bits.flushItself()),
redirectWalkDistance + io.redirect.bits.flushItself()
)
XSError(state === s_walk && thisCycleWalkCount < io.redirect.bits.flushItself(),
p"walk distance error ($thisCycleWalkCount < ${io.redirect.bits.flushItself()}\n")
}.elsewhen (state === s_walk) {
walkCounter := walkCounter - commitCnt
walkCounter := walkCounter - thisCycleWalkCount
XSInfo(p"rolling back: $enqPtr $deqPtr walk $walkPtr walkcnt $walkCounter\n")
}
......@@ -742,12 +765,14 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// enqueue logic writes 6 valid
for (i <- 0 until RenameWidth) {
when (canEnqueue(i) && !io.redirect.valid) {
valid(enqPtrVec(i).value) := true.B
valid(allocatePtrVec(i).value) := true.B
}
}
// dequeue/walk logic writes 6 valid, dequeue and walk will not happen at the same time
for (i <- 0 until CommitWidth) {
when (io.commits.valid(i) && state =/= s_extrawalk) {
val commitValid = io.commits.isCommit && io.commits.commitValid(i)
val walkValid = io.commits.isWalk && io.commits.walkValid(i) && state =/= s_extrawalk
when (commitValid || walkValid) {
valid(commitReadAddr(i)) := false.B
}
}
......@@ -765,9 +790,9 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
val enqHasException = ExceptionNO.selectFrontend(io.enq.req(i).bits.cf.exceptionVec).asUInt.orR
val enqHasTriggerHit = io.enq.req(i).bits.cf.trigger.getHitFrontend
val enqIsWritebacked = io.enq.req(i).bits.eliminatedMove
writebacked(enqPtrVec(i).value) := enqIsWritebacked && !enqHasException && !enqHasTriggerHit
writebacked(allocatePtrVec(i).value) := enqIsWritebacked && !enqHasException && !enqHasTriggerHit
val isStu = io.enq.req(i).bits.ctrl.fuType === FuType.stu
store_data_writebacked(enqPtrVec(i).value) := !isStu
store_data_writebacked(allocatePtrVec(i).value) := !isStu
}
}
when (exceptionGen.io.out.valid) {
......@@ -798,7 +823,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// enqueue logic set 6 flagBkup at most
for (i <- 0 until RenameWidth) {
when (canEnqueue(i)) {
flagBkup(enqPtrVec(i).value) := enqPtrVec(i).flag
flagBkup(allocatePtrVec(i).value) := allocatePtrVec(i).flag
}
}
......@@ -814,7 +839,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// Thus, we don't allow load/store instructions to trigger an interrupt.
// TODO: support non-MMIO load-store instructions to trigger interrupts
val allow_interrupts = !CommitType.isLoadStore(io.enq.req(i).bits.ctrl.commitType)
interrupt_safe(RegNext(enqPtrVec(i).value)) := RegNext(allow_interrupts)
interrupt_safe(RegNext(allocatePtrVec(i).value)) := RegNext(allow_interrupts)
}
}
......@@ -826,7 +851,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
VecInit(walkPtrVec_next.map(_.value))
)
dispatchData.io.wen := canEnqueue
dispatchData.io.waddr := enqPtrVec.map(_.value)
dispatchData.io.waddr := allocatePtrVec.map(_.value)
dispatchData.io.wdata.zip(io.enq.req.map(_.bits)).foreach{ case (wdata, req) =>
wdata.ldest := req.ctrl.ldest
wdata.rfWen := req.ctrl.rfWen
......@@ -888,12 +913,13 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
fflagsDataRead := fflagsDataModule.io.rdata
val instrCnt = RegInit(0.U(64.W))
val fuseCommitCnt = PopCount(io.commits.valid.zip(io.commits.info).map{ case (v, i) => v && CommitType.isFused(i.commitType) })
val trueCommitCnt = commitCnt +& fuseCommitCnt
val retireCounter = Mux(state === s_idle, trueCommitCnt, 0.U)
instrCnt := instrCnt + retireCounter
io.csr.perfinfo.retiredInstr := RegNext(retireCounter)
val instrCntReg = RegInit(0.U(64.W))
val fuseCommitCnt = PopCount(io.commits.commitValid.zip(io.commits.info).map{ case (v, i) => RegNext(v && CommitType.isFused(i.commitType)) })
val trueCommitCnt = RegNext(commitCnt) +& fuseCommitCnt
val retireCounter = Mux(RegNext(io.commits.isCommit), trueCommitCnt, 0.U)
val instrCnt = instrCntReg + retireCounter
instrCntReg := instrCnt
io.csr.perfinfo.retiredInstr := retireCounter
io.robFull := !allowEnqueue
/**
......@@ -917,7 +943,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
if(i % 4 == 3) XSDebug(false, true.B, "\n")
}
def ifCommit(counter: UInt): UInt = Mux(io.commits.isWalk, 0.U, counter)
def ifCommit(counter: UInt): UInt = Mux(io.commits.isCommit, counter, 0.U)
val commitDebugUop = deqPtrVec.map(_.value).map(debug_microOp(_))
XSPerfAccumulate("clock_cycle", 1.U)
......@@ -925,24 +951,24 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
XSPerfAccumulate("commitUop", ifCommit(commitCnt))
XSPerfAccumulate("commitInstr", ifCommit(trueCommitCnt))
val commitIsMove = commitDebugUop.map(_.ctrl.isMove)
XSPerfAccumulate("commitInstrMove", ifCommit(PopCount(io.commits.valid.zip(commitIsMove).map{ case (v, m) => v && m })))
XSPerfAccumulate("commitInstrMove", ifCommit(PopCount(io.commits.commitValid.zip(commitIsMove).map{ case (v, m) => v && m })))
val commitMoveElim = commitDebugUop.map(_.debugInfo.eliminatedMove)
XSPerfAccumulate("commitInstrMoveElim", ifCommit(PopCount(io.commits.valid zip commitMoveElim map { case (v, e) => v && e })))
XSPerfAccumulate("commitInstrMoveElim", ifCommit(PopCount(io.commits.commitValid zip commitMoveElim map { case (v, e) => v && e })))
XSPerfAccumulate("commitInstrFused", ifCommit(fuseCommitCnt))
val commitIsLoad = io.commits.info.map(_.commitType).map(_ === CommitType.LOAD)
val commitLoadValid = io.commits.valid.zip(commitIsLoad).map{ case (v, t) => v && t }
val commitLoadValid = io.commits.commitValid.zip(commitIsLoad).map{ case (v, t) => v && t }
XSPerfAccumulate("commitInstrLoad", ifCommit(PopCount(commitLoadValid)))
val commitIsBranch = io.commits.info.map(_.commitType).map(_ === CommitType.BRANCH)
val commitBranchValid = io.commits.valid.zip(commitIsBranch).map{ case (v, t) => v && t }
val commitBranchValid = io.commits.commitValid.zip(commitIsBranch).map{ case (v, t) => v && t }
XSPerfAccumulate("commitInstrBranch", ifCommit(PopCount(commitBranchValid)))
val commitLoadWaitBit = commitDebugUop.map(_.cf.loadWaitBit)
XSPerfAccumulate("commitInstrLoadWait", ifCommit(PopCount(commitLoadValid.zip(commitLoadWaitBit).map{ case (v, w) => v && w })))
val commitIsStore = io.commits.info.map(_.commitType).map(_ === CommitType.STORE)
XSPerfAccumulate("commitInstrStore", ifCommit(PopCount(io.commits.valid.zip(commitIsStore).map{ case (v, t) => v && t })))
XSPerfAccumulate("commitInstrStore", ifCommit(PopCount(io.commits.commitValid.zip(commitIsStore).map{ case (v, t) => v && t })))
XSPerfAccumulate("writeback", PopCount((0 until RobSize).map(i => valid(i) && writebacked(i))))
// XSPerfAccumulate("enqInstr", PopCount(io.dp1Req.map(_.fire)))
// XSPerfAccumulate("d2rVnR", PopCount(io.dp1Req.map(p => p.valid && !p.ready)))
XSPerfAccumulate("walkInstr", Mux(io.commits.isWalk, PopCount(io.commits.valid), 0.U))
XSPerfAccumulate("walkInstr", Mux(io.commits.isWalk, PopCount(io.commits.walkValid), 0.U))
XSPerfAccumulate("walkCycle", state === s_walk || state === s_extrawalk)
val deqNotWritebacked = valid(deqPtr.value) && !writebacked(deqPtr.value)
val deqUopCommitType = io.commits.info(0).commitType
......@@ -963,7 +989,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
}
for (fuType <- FuType.functionNameMap.keys) {
val fuName = FuType.functionNameMap(fuType)
val commitIsFuType = io.commits.valid.zip(commitDebugUop).map(x => x._1 && x._2.ctrl.fuType === fuType.U )
val commitIsFuType = io.commits.commitValid.zip(commitDebugUop).map(x => x._1 && x._2.ctrl.fuType === fuType.U )
XSPerfAccumulate(s"${fuName}_instr_cnt", ifCommit(PopCount(commitIsFuType)))
XSPerfAccumulate(s"${fuName}_latency_dispatch", ifCommit(latencySum(commitIsFuType, dispatchLatency)))
XSPerfAccumulate(s"${fuName}_latency_enq_rs", ifCommit(latencySum(commitIsFuType, enqRsLatency)))
......@@ -981,7 +1007,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
}
//difftest signals
val firstValidCommit = (deqPtr + PriorityMux(io.commits.valid, VecInit(List.tabulate(CommitWidth)(_.U)))).value
val firstValidCommit = (deqPtr + PriorityMux(io.commits.commitValid, VecInit(List.tabulate(CommitWidth)(_.U)))).value
val wdata = Wire(Vec(CommitWidth, UInt(XLEN.W)))
val wpc = Wire(Vec(CommitWidth, UInt(XLEN.W)))
......@@ -991,9 +1017,6 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
wdata(i) := debug_exuData(idx)
wpc(i) := SignExt(commitDebugUop(i).cf.pc, XLEN)
}
val retireCounterFix = Mux(io.exception.valid, 1.U, retireCounter)
val retirePCFix = SignExt(Mux(io.exception.valid, io.exception.bits.uop.cf.pc, debug_microOp(firstValidCommit).cf.pc), XLEN)
val retireInstFix = Mux(io.exception.valid, io.exception.bits.uop.cf.instr, debug_microOp(firstValidCommit).cf.instr)
if (env.EnableDifftest) {
for (i <- 0 until CommitWidth) {
......@@ -1006,7 +1029,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
val uop = commitDebugUop(i)
val exuOut = debug_exuDebug(ptr)
val exuData = debug_exuData(ptr)
difftest.io.valid := RegNext(RegNext(RegNext(io.commits.valid(i) && !io.commits.isWalk)))
difftest.io.valid := RegNext(RegNext(RegNext(io.commits.commitValid(i) && io.commits.isCommit)))
difftest.io.pc := RegNext(RegNext(RegNext(SignExt(uop.cf.pc, XLEN))))
difftest.io.instr := RegNext(RegNext(RegNext(uop.cf.instr)))
difftest.io.special := RegNext(RegNext(RegNext(CommitType.isFused(io.commits.info(i).commitType))))
......@@ -1014,8 +1037,8 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
// we must make sure that skip is properly set to false (output from EXU is random value)
difftest.io.skip := RegNext(RegNext(RegNext(Mux(uop.eliminatedMove, false.B, exuOut.isMMIO || exuOut.isPerfCnt))))
difftest.io.isRVC := RegNext(RegNext(RegNext(uop.cf.pd.isRVC)))
difftest.io.rfwen := RegNext(RegNext(RegNext(io.commits.valid(i) && io.commits.info(i).rfWen && io.commits.info(i).ldest =/= 0.U)))
difftest.io.fpwen := RegNext(RegNext(RegNext(io.commits.valid(i) && io.commits.info(i).fpWen)))
difftest.io.rfwen := RegNext(RegNext(RegNext(io.commits.commitValid(i) && io.commits.info(i).rfWen && io.commits.info(i).ldest =/= 0.U)))
difftest.io.fpwen := RegNext(RegNext(RegNext(io.commits.commitValid(i) && io.commits.info(i).fpWen)))
difftest.io.wpdest := RegNext(RegNext(RegNext(io.commits.info(i).pdest)))
difftest.io.wdest := RegNext(RegNext(RegNext(io.commits.info(i).ldest)))
......@@ -1037,8 +1060,8 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
val dt_exuDebug = Reg(Vec(RobSize, new DebugBundle))
for (i <- 0 until RenameWidth) {
when (canEnqueue(i)) {
dt_eliminatedMove(enqPtrVec(i).value) := io.enq.req(i).bits.eliminatedMove
dt_isRVC(enqPtrVec(i).value) := io.enq.req(i).bits.cf.pd.isRVC
dt_eliminatedMove(allocatePtrVec(i).value) := io.enq.req(i).bits.eliminatedMove
dt_isRVC(allocatePtrVec(i).value) := io.enq.req(i).bits.cf.pd.isRVC
}
}
for (wb <- exuWriteback) {
......@@ -1059,12 +1082,12 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
difftest.io.clock := clock
difftest.io.coreid := io.hartId
difftest.io.index := i.U
difftest.io.valid := RegNext(RegNext(RegNext(io.commits.valid(i) && !io.commits.isWalk)))
difftest.io.valid := RegNext(RegNext(RegNext(io.commits.commitValid(i) && io.commits.isCommit)))
difftest.io.special := RegNext(RegNext(RegNext(CommitType.isFused(commitInfo.commitType))))
difftest.io.skip := RegNext(RegNext(RegNext(Mux(eliminatedMove, false.B, exuOut.isMMIO || exuOut.isPerfCnt))))
difftest.io.isRVC := RegNext(RegNext(RegNext(isRVC)))
difftest.io.rfwen := RegNext(RegNext(RegNext(io.commits.valid(i) && commitInfo.rfWen && commitInfo.ldest =/= 0.U)))
difftest.io.fpwen := RegNext(RegNext(RegNext(io.commits.valid(i) && commitInfo.fpWen)))
difftest.io.rfwen := RegNext(RegNext(RegNext(io.commits.commitValid(i) && commitInfo.rfWen && commitInfo.ldest =/= 0.U)))
difftest.io.fpwen := RegNext(RegNext(RegNext(io.commits.commitValid(i) && commitInfo.fpWen)))
difftest.io.wpdest := RegNext(RegNext(RegNext(commitInfo.pdest)))
difftest.io.wdest := RegNext(RegNext(RegNext(commitInfo.ldest)))
}
......@@ -1080,7 +1103,7 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
val ptr = deqPtrVec(i).value
val uop = commitDebugUop(i)
val exuOut = debug_exuDebug(ptr)
difftest.io.valid := RegNext(RegNext(RegNext(io.commits.valid(i) && !io.commits.isWalk)))
difftest.io.valid := RegNext(RegNext(RegNext(io.commits.commitValid(i) && io.commits.isCommit)))
difftest.io.paddr := RegNext(RegNext(RegNext(exuOut.paddr)))
difftest.io.opType := RegNext(RegNext(RegNext(uop.ctrl.fuOpType)))
difftest.io.fuType := RegNext(RegNext(RegNext(uop.ctrl.fuType)))
......@@ -1092,10 +1115,10 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
val dt_isXSTrap = Mem(RobSize, Bool())
for (i <- 0 until RenameWidth) {
when (canEnqueue(i)) {
dt_isXSTrap(enqPtrVec(i).value) := io.enq.req(i).bits.ctrl.isXSTrap
dt_isXSTrap(allocatePtrVec(i).value) := io.enq.req(i).bits.ctrl.isXSTrap
}
}
val trapVec = io.commits.valid.zip(deqPtrVec).map{ case (v, d) => state === s_idle && v && dt_isXSTrap(d.value) }
val trapVec = io.commits.commitValid.zip(deqPtrVec).map{ case (v, d) => io.commits.isCommit && v && dt_isXSTrap(d.value) }
val hitTrap = trapVec.reduce(_||_)
val trapCode = PriorityMux(wdata.zip(trapVec).map(x => x._2 -> x._1))
val trapPC = SignExt(PriorityMux(wpc.zip(trapVec).map(x => x._2 ->x._1)), XLEN)
......@@ -1113,10 +1136,10 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
val dt_isXSTrap = Mem(RobSize, Bool())
for (i <- 0 until RenameWidth) {
when (canEnqueue(i)) {
dt_isXSTrap(enqPtrVec(i).value) := io.enq.req(i).bits.ctrl.isXSTrap
dt_isXSTrap(allocatePtrVec(i).value) := io.enq.req(i).bits.ctrl.isXSTrap
}
}
val trapVec = io.commits.valid.zip(deqPtrVec).map{ case (v, d) => state === s_idle && v && dt_isXSTrap(d.value) }
val trapVec = io.commits.commitValid.zip(deqPtrVec).map{ case (v, d) => io.commits.isCommit && v && dt_isXSTrap(d.value) }
val hitTrap = trapVec.reduce(_||_)
val difftest = Module(new DifftestBasicTrapEvent)
difftest.io.clock := clock
......@@ -1133,13 +1156,13 @@ class RobImp(outer: Rob)(implicit p: Parameters) extends LazyModuleImp(outer)
("rob_replay_inst_num ", io.flushOut.valid && isFlushPipe && deqHasReplayInst ),
("rob_commitUop ", ifCommit(commitCnt) ),
("rob_commitInstr ", ifCommit(trueCommitCnt) ),
("rob_commitInstrMove ", ifCommit(PopCount(io.commits.valid.zip(commitIsMove).map{ case (v, m) => v && m })) ),
("rob_commitInstrMove ", ifCommit(PopCount(io.commits.commitValid.zip(commitIsMove).map{ case (v, m) => v && m })) ),
("rob_commitInstrFused ", ifCommit(fuseCommitCnt) ),
("rob_commitInstrLoad ", ifCommit(PopCount(commitLoadValid)) ),
("rob_commitInstrLoad ", ifCommit(PopCount(commitBranchValid)) ),
("rob_commitInstrLoadWait ", ifCommit(PopCount(commitLoadValid.zip(commitLoadWaitBit).map{ case (v, w) => v && w })) ),
("rob_commitInstrStore ", ifCommit(PopCount(io.commits.valid.zip(commitIsStore).map{ case (v, t) => v && t })) ),
("rob_walkInstr ", Mux(io.commits.isWalk, PopCount(io.commits.valid), 0.U) ),
("rob_commitInstrStore ", ifCommit(PopCount(io.commits.commitValid.zip(commitIsStore).map{ case (v, t) => v && t })) ),
("rob_walkInstr ", Mux(io.commits.isWalk, PopCount(io.commits.walkValid), 0.U) ),
("rob_walkCycle ", (state === s_walk || state === s_extrawalk) ),
("rob_1_4_valid ", (PopCount((0 until RobSize).map(valid(_))) < (RobSize.U/4.U)) ),
("rob_2_4_valid ", (PopCount((0 until RobSize).map(valid(_))) > (RobSize.U/4.U)) & (PopCount((0 until RobSize).map(valid(_))) <= (RobSize.U/2.U)) ),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册