提交 8ba1aec3 编写于 作者: Y Yinan Xu

roq: optimize enq timing

上级 c348ab30
......@@ -6,7 +6,7 @@ import xiangshan._
import utils._
import xiangshan.backend.regfile.RfReadPort
import chisel3.ExcitingUtils._
import xiangshan.backend.roq.RoqPtr
import xiangshan.backend.roq.{RoqPtr, RoqEnqIO}
import xiangshan.backend.rename.RenameBypassInfo
case class DispatchParameters
......@@ -29,13 +29,7 @@ class Dispatch extends XSModule {
// to busytable: set pdest to busy (not ready) when they are dispatched
val allocPregs = Vec(RenameWidth, Output(new ReplayPregReq))
// enq Roq
val enqRoq = new Bundle {
val canAccept = Input(Bool())
val isEmpty = Input(Bool())
val extraWalk = Vec(RenameWidth, Output(Bool()))
val req = Vec(RenameWidth, ValidIO(new MicroOp))
val resp = Vec(RenameWidth, Input(new RoqPtr))
}
val enqRoq = Flipped(new RoqEnqIO)
// enq Lsq
val enqLsq = new Bundle() {
val canAccept = Input(Bool())
......
......@@ -5,7 +5,7 @@ import chisel3.util._
import chisel3.ExcitingUtils._
import xiangshan._
import utils.{XSDebug, XSError, XSInfo}
import xiangshan.backend.roq.RoqPtr
import xiangshan.backend.roq.{RoqPtr, RoqEnqIO}
import xiangshan.backend.rename.RenameBypassInfo
// read rob and enqueue
......@@ -16,14 +16,7 @@ class Dispatch1 extends XSModule {
val renameBypass = Input(new RenameBypassInfo)
val recv = Output(Vec(RenameWidth, Bool()))
// enq Roq
val enqRoq = new Bundle {
val canAccept = Input(Bool())
val isEmpty = Input(Bool())
// if set, Roq needs extra walk
val extraWalk = Vec(RenameWidth, Output(Bool()))
val req = Vec(RenameWidth, ValidIO(new MicroOp))
val resp = Vec(RenameWidth, Input(new RoqPtr))
}
val enqRoq = Flipped(new RoqEnqIO)
// enq Lsq
val enqLsq = new Bundle() {
val canAccept = Input(Bool())
......@@ -132,33 +125,24 @@ class Dispatch1 extends XSModule {
// this instruction can actually dequeue: 3 conditions
// (1) resources are ready
// (2) previous instructions are ready
val thisCanActualOut = (0 until RenameWidth).map(i => allResourceReady && !thisIsBlocked(i) && notBlockedByPrevious(i))
val thisCanActualOut = (0 until RenameWidth).map(i => !thisIsBlocked(i) && notBlockedByPrevious(i))
// input for ROQ and LSQ
// note that LSQ needs roqIdx
// (1) LSQ needs roqIdx; (2) DPQ needs roqIdx and lsIdx
val updateUopWithIndex = Wire(Vec(RenameWidth, new MicroOp))
for (i <- 0 until RenameWidth) {
io.enqRoq.extraWalk(i) := io.fromRename(i).valid && !thisCanActualOut(i)
io.enqRoq.req(i).valid := io.fromRename(i).valid && thisCanActualOut(i)
io.enqRoq.needAlloc(i) := io.fromRename(i).valid
io.enqRoq.req(i).valid := io.fromRename(i).valid && thisCanActualOut(i) && io.enqLsq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
io.enqRoq.req(i).bits := updatedUop(i)
XSDebug(io.enqRoq.req(i).valid, p"pc 0x${Hexadecimal(io.fromRename(i).bits.cf.pc)} receives nroq ${io.enqRoq.resp(i)}\n")
val shouldEnqLsq = isLs(i) && io.fromRename(i).bits.ctrl.fuType =/= FuType.mou
io.enqLsq.req(i).valid := io.fromRename(i).valid && shouldEnqLsq && thisCanActualOut(i)
io.enqLsq.req(i).valid := io.fromRename(i).valid && shouldEnqLsq && thisCanActualOut(i) && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
io.enqLsq.req(i).bits := updatedUop(i)
io.enqLsq.req(i).bits.roqIdx := io.enqRoq.resp(i)
XSDebug(io.enqLsq.req(i).valid,
p"pc 0x${Hexadecimal(io.fromRename(i).bits.cf.pc)} receives lq ${io.enqLsq.resp(i).lqIdx} sq ${io.enqLsq.resp(i).sqIdx}\n")
XSDebug(io.enqRoq.req(i).valid, p"pc 0x${Hexadecimal(io.fromRename(i).bits.cf.pc)} receives nroq ${io.enqRoq.resp(i)}\n")
}
/**
* Part 4:
* append ROQ and LSQ indexed to uop, and send them to dispatch queue
*/
val updateUopWithIndex = Wire(Vec(RenameWidth, new MicroOp))
for (i <- 0 until RenameWidth) {
updateUopWithIndex(i) := updatedUop(i)
updateUopWithIndex(i).roqIdx := io.enqRoq.resp(i)
updateUopWithIndex(i).lqIdx := io.enqLsq.resp(i).lqIdx
......@@ -168,18 +152,16 @@ class Dispatch1 extends XSModule {
// Note that if one of their previous instructions cannot enqueue, they should not enter dispatch queue.
// We use notBlockedByPrevious here.
io.toIntDq.req(i).bits := updateUopWithIndex(i)
io.toIntDq.req(i).valid := io.fromRename(i).valid && isInt(i) && allResourceReady &&
!thisIsBlocked(i) && notBlockedByPrevious(i)
io.toIntDq.req(i).valid := io.fromRename(i).valid && isInt(i) && thisCanActualOut(i) &&
io.enqLsq.canAccept && io.enqRoq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
// NOTE: floating point instructions are not noSpecExec currently
// remove commit /**/ when fp instructions are possible to be noSpecExec
io.toFpDq.req(i).bits := updateUopWithIndex(i)
io.toFpDq.req(i).valid := io.fromRename(i).valid && isFp(i) && allResourceReady &&
/*!thisIsBlocked(i) && */notBlockedByPrevious(i)
io.toFpDq.req(i).valid := io.fromRename(i).valid && isFp(i) && thisCanActualOut(i) &&
io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toLsDq.canAccept
io.toLsDq.req(i).bits := updateUopWithIndex(i)
io.toLsDq.req(i).valid := io.fromRename(i).valid && isLs(i) && allResourceReady &&
!thisIsBlocked(i) && notBlockedByPrevious(i)
io.toLsDq.req(i).valid := io.fromRename(i).valid && isLs(i) && thisCanActualOut(i) &&
io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept
XSDebug(io.toIntDq.req(i).valid, p"pc 0x${Hexadecimal(io.toIntDq.req(i).bits.cf.pc)} int index $i\n")
XSDebug(io.toFpDq.req(i).valid , p"pc 0x${Hexadecimal(io.toFpDq.req(i).bits.cf.pc )} fp index $i\n")
......@@ -187,12 +169,12 @@ class Dispatch1 extends XSModule {
}
/**
* Part 3: send response to rename when dispatch queue accepts the uop
* Part 4: send response to rename when dispatch queue accepts the uop
*/
val readyVector = (0 until RenameWidth).map(i => !io.fromRename(i).valid || io.recv(i))
val hasSpecialInstr = Cat((0 until RenameWidth).map(i => io.fromRename(i).valid && (isBlockBackward(i) || isNoSpecExec(i)))).orR
for (i <- 0 until RenameWidth) {
io.recv(i) := thisCanActualOut(i)
io.fromRename(i).ready := Cat(readyVector).andR()
io.recv(i) := thisCanActualOut(i) && io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
io.fromRename(i).ready := !hasSpecialInstr && io.enqLsq.canAccept && io.enqRoq.canAccept && io.toIntDq.canAccept && io.toFpDq.canAccept && io.toLsDq.canAccept
XSInfo(io.recv(i) && io.fromRename(i).valid,
p"pc 0x${Hexadecimal(io.fromRename(i).bits.cf.pc)}, type(${isInt(i)}, ${isFp(i)}, ${isLs(i)}), " +
......
......@@ -38,17 +38,20 @@ class RoqCSRIO extends XSBundle {
val dirty_fs = Output(Bool())
}
class RoqEnqIO extends XSBundle {
val canAccept = Output(Bool())
val isEmpty = Output(Bool())
// valid vector, for roqIdx gen and walk
val needAlloc = Vec(RenameWidth, Input(Bool()))
val req = Vec(RenameWidth, Flipped(ValidIO(new MicroOp)))
val resp = Vec(RenameWidth, Output(new RoqPtr))
}
class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val io = IO(new Bundle() {
val brqRedirect = Input(Valid(new Redirect))
val memRedirect = Input(Valid(new Redirect))
val enq = new Bundle {
val canAccept = Output(Bool())
val isEmpty = Output(Bool())
val extraWalk = Vec(RenameWidth, Input(Bool()))
val req = Vec(RenameWidth, Flipped(ValidIO(new MicroOp)))
val resp = Vec(RenameWidth, Output(new RoqPtr))
}
val enq = new RoqEnqIO
val redirect = Output(Valid(new Redirect))
val exception = Output(new MicroOp)
// exu + brq
......@@ -108,14 +111,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
io.roqDeqPtr := deqPtrExt
// common signal
val enqPtrValPlus = Wire(Vec(RenameWidth, UInt(log2Up(RoqSize).W)))
val enqPtrFlagPlus = Wire(Vec(RenameWidth, Bool()))
for (i <- 0 until RenameWidth) {
val offset = PopCount(io.enq.req.map(_.valid).take(i))
val roqIdxExt = enqPtrExt + offset
enqPtrValPlus(i) := roqIdxExt.value
enqPtrFlagPlus(i) := roqIdxExt.flag
}
val enqPtrVec = WireInit(VecInit((0 until RenameWidth).map(i => enqPtrExt + PopCount(io.enq.needAlloc.take(i)))))
val deqPtrExtPlus = Wire(Vec(RenameWidth, UInt(log2Up(RoqSize).W)))
for(i <- 0 until CommitWidth){
......@@ -138,14 +134,9 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val walkNoSpecExec = io.commits.isWalk && Cat((0 until CommitWidth).map(i => io.commits.valid(i) && io.commits.uop(i).ctrl.noSpecExec)).orR
XSError(state =/= s_extrawalk && walkNoSpecExec, "noSpecExec should not walk\n")
val validDispatch = io.enq.req.map(_.valid)
for (i <- 0 until RenameWidth) {
val offset = PopCount(validDispatch.take(i))
val roqIdxExt = enqPtrExt + offset
val roqIdx = roqIdxExt.value
when(io.enq.req(i).valid) {
microOp(roqIdx) := io.enq.req(i).bits
when(io.enq.req(i).valid && io.enq.canAccept) {
microOp(enqPtrVec(i).value) := io.enq.req(i).bits
when(io.enq.req(i).bits.ctrl.blockBackward) {
hasBlockBackward := true.B
}
......@@ -153,19 +144,18 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
hasNoSpecExec := true.B
}
}
io.enq.resp(i) := roqIdxExt
io.enq.resp(i) := enqPtrVec(i)
}
val validEntries = distanceBetween(enqPtrExt, deqPtrExt)
val firedDispatch = Cat(io.enq.req.map(_.valid))
val firedDispatch = Mux(io.enq.canAccept, PopCount(Cat(io.enq.req.map(_.valid))), 0.U)
io.enq.canAccept := (validEntries <= (RoqSize - RenameWidth).U) && !hasBlockBackward
io.enq.isEmpty := isEmpty
XSDebug(p"(ready, valid): ${io.enq.canAccept}, ${Binary(firedDispatch)}\n")
XSDebug(p"(ready, valid): ${io.enq.canAccept}, ${Binary(Cat(io.enq.req.map(_.valid)))}\n")
val dispatchCnt = PopCount(firedDispatch)
enqPtrExt := enqPtrExt + dispatchCnt
when (firedDispatch.orR) {
XSInfo("dispatched %d insts\n", dispatchCnt)
enqPtrExt := enqPtrExt + firedDispatch
when (firedDispatch =/= 0.U) {
XSInfo("dispatched %d insts\n", firedDispatch)
}
// Writeback
......@@ -224,7 +214,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// extra space is used weh roq has no enough space, but mispredict recovery needs such info to walk regmap
val needExtraSpaceForMPR = WireInit(VecInit(
List.tabulate(RenameWidth)(i => io.brqRedirect.valid && io.enq.extraWalk(i))
List.tabulate(RenameWidth)(i => io.brqRedirect.valid && io.enq.needAlloc(i))
))
val extraSpaceForMPR = Reg(Vec(RenameWidth, new MicroOp))
val usedSpaceForMPR = Reg(Vec(RenameWidth, Bool()))
......@@ -345,12 +335,12 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// when redirect, walk back roq entries
when(io.brqRedirect.valid){ // TODO: need check if consider exception redirect?
state := s_walk
val nextEnqPtr = (enqPtrExt - 1.U) + dispatchCnt
val walkPtrStart = enqPtrExt - 1.U
walkPtrExt := Mux(state === s_walk,
walkPtrExt - Mux(walkFinished, walkCounter, CommitWidth.U),
Mux(state === s_extrawalk, walkPtrExt, nextEnqPtr))
Mux(state === s_extrawalk, walkPtrExt, walkPtrStart))
// walkTgtExt := io.brqRedirect.bits.roqIdx
val currentWalkPtr = Mux(state === s_walk || state === s_extrawalk, walkPtrExt, nextEnqPtr)
val currentWalkPtr = Mux(state === s_walk || state === s_extrawalk, walkPtrExt, walkPtrStart)
walkCounter := distanceBetween(currentWalkPtr, io.brqRedirect.bits.roqIdx) - Mux(state === s_walk, commitCnt, 0.U)
enqPtrExt := io.brqRedirect.bits.roqIdx + 1.U
}
......@@ -375,8 +365,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// write
// enqueue logic writes 6 valid
for (i <- 0 until RenameWidth) {
when(io.enq.req(i).fire()){
valid(enqPtrValPlus(i)) := true.B
when(io.enq.req(i).valid && io.enq.canAccept && !io.brqRedirect.valid){
valid(enqPtrVec(i).value) := true.B
}
}
// dequeue/walk logic writes 6 valid, dequeue and walk will not happen at the same time
......@@ -412,8 +402,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// write
// enqueue logic set 6 writebacked to false
for (i <- 0 until RenameWidth) {
when(io.enq.req(i).fire()){
writebacked(enqPtrValPlus(i)) := false.B
when(io.enq.req(i).valid && io.enq.canAccept && !io.brqRedirect.valid){
writebacked(enqPtrVec(i).value) := false.B
}
}
// writeback logic set numWbPorts writebacked to true
......@@ -443,8 +433,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// write: update when enqueue
// enqueue logic set 6 flagBkup at most
for (i <- 0 until RenameWidth) {
when(io.enq.req(i).fire()){
flagBkup(enqPtrValPlus(i)) := enqPtrFlagPlus(i)
when(io.enq.req(i).valid && io.enq.canAccept && !io.brqRedirect.valid){
flagBkup(enqPtrVec(i).value) := enqPtrVec(i).flag
}
}
// read: used in rollback logic
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册