提交 6a9a0533 编写于 作者: Y Yinan Xu

dispatch1: block valid when blockBackward or noSpecExec

上级 5e33e227
......@@ -43,10 +43,11 @@ class DecodeBuffer extends XSModule {
if(i > 0 ){
io.out(i).valid := validVec(i) &&
!flush &&
Mux(r.ctrl.noSpecExec,
!ParallelOR(validVec.take(i)),
!ParallelOR(io.out.zip(validVec).take(i).map(x => x._2 && x._1.bits.ctrl.noSpecExec))
) && !io.isWalking
// Mux(r.ctrl.noSpecExec,
!ParallelOR(validVec.take(i))//,
// !ParallelOR(io.out.zip(validVec).take(i).map(x => x._2 && x._1.bits.ctrl.noSpecExec))
//) &&
!io.isWalking
} else {
require( i == 0)
io.out(i).valid := validVec(i) && !flush && !io.isWalking
......
......@@ -31,6 +31,7 @@ class Dispatch extends XSModule {
// 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))
......
......@@ -17,6 +17,7 @@ class Dispatch1 extends XSModule {
// 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))
......@@ -41,10 +42,12 @@ class Dispatch1 extends XSModule {
* Part 1: choose the target dispatch queue and the corresponding write ports
*/
// valid bits for different dispatch queues
val isInt = WireInit(VecInit(io.fromRename.map(uop => FuType.isIntExu(uop.bits.ctrl.fuType))))
val isFp = WireInit(VecInit(io.fromRename.map(uop => FuType.isFpExu (uop.bits.ctrl.fuType))))
val isLs = WireInit(VecInit(io.fromRename.map(uop => FuType.isMemExu(uop.bits.ctrl.fuType))))
val isStore = WireInit(VecInit(io.fromRename.map(uop => FuType.isStoreExu(uop.bits.ctrl.fuType))))
val isInt = VecInit(io.fromRename.map(req => FuType.isIntExu(req.bits.ctrl.fuType)))
val isFp = VecInit(io.fromRename.map(req => FuType.isFpExu (req.bits.ctrl.fuType)))
val isLs = VecInit(io.fromRename.map(req => FuType.isMemExu(req.bits.ctrl.fuType)))
val isStore = VecInit(io.fromRename.map(req => FuType.isStoreExu(req.bits.ctrl.fuType)))
val isBlockBackward = VecInit(io.fromRename.map(_.bits.ctrl.blockBackward))
val isNoSpecExec = VecInit(io.fromRename.map(_.bits.ctrl.noSpecExec))
// generate index mapping
val intIndex = Module(new IndexMapping(RenameWidth, dpParams.DqEnqWidth, false))
......@@ -79,24 +82,30 @@ class Dispatch1 extends XSModule {
// Thus, for i >= dpParams.DqEnqWidth, we have to check whether it's previous instructions (and the instruction itself) can enqueue.
// However, since, for instructions with indices less than dpParams.DqEnqWidth,
// they can always enter dispatch queue when ROB and LSQ are ready, we don't need to check whether they can enqueue.
// prevCanOut: previous instructions can enqueue
// thisIsBlocked: this instruction is blocked by itself
// thisCanOut: this instruction can enqueue
val thisCanOut = (0 until RenameWidth).map(i =>
// nextCanOut: next instructions can out
// notBlockedByPrevious: previous instructions can enqueue
val thisIsBlocked = VecInit((0 until RenameWidth).map(i =>
isNoSpecExec(i) && !io.enqRoq.isEmpty
))
val thisCanOut = VecInit((0 until RenameWidth).map(i => {
// For i in [0, DqEnqWidth), they can always enqueue when ROB and LSQ are ready
if (i < dpParams.DqEnqWidth) true.B
else Cat(Seq(intIndex, fpIndex, lsIndex).map(_.io.reverseMapping(i).valid)).orR
)
val prevCanOut = VecInit((0 until RenameWidth).map(i =>
// For i in [0, DqEnqWidth], previous instructions can always enqueue when ROB and LSQ are ready
if (i <= dpParams.DqEnqWidth) true.B
// They need to check their previous ones
else Cat((dpParams.DqEnqWidth until i).map(j => thisCanOut(j) || !io.fromRename(j).valid)).andR
if (i < dpParams.DqEnqWidth) !thisIsBlocked(i)
else Cat(Seq(intIndex, fpIndex, lsIndex).map(_.io.reverseMapping(i).valid)).orR && !thisIsBlocked(i)
}))
val nextCanOut = VecInit((0 until RenameWidth).map(i =>
(thisCanOut(i) && !isBlockBackward(i)) || !io.fromRename(i).valid
))
val notBlockedByPrevious = VecInit((0 until RenameWidth).map(i =>
if (i == 0) true.B
else Cat((0 until i).map(j => nextCanOut(j))).andR
))
// this instruction can actually dequeue: 3 conditions
// (1) resources are ready
// (2) previous instructions are ready
val thisCanActualOut = (0 until RenameWidth).map(i => allResourceReady && thisCanOut(i) && prevCanOut(i))
val thisCanActualOut = (0 until RenameWidth).map(i => allResourceReady && thisCanOut(i) && notBlockedByPrevious(i))
val uopWithIndex = Wire(Vec(RenameWidth, new MicroOp))
......@@ -129,17 +138,22 @@ class Dispatch1 extends XSModule {
// send uops with correct indexes to dispatch queues
// Note that if one of their previous instructions cannot enqueue, they should not enter dispatch queue.
// We use prevCanOut here since mapping(i).valid implies there's a valid instruction that can enqueue,
// We use notBlockedByPrevious here since mapping(i).valid implies there's a valid instruction that can enqueue,
// thus we don't need to check thisCanOut.
for (i <- 0 until dpParams.DqEnqWidth) {
io.toIntDq(i).bits := uopWithIndex(intIndex.io.mapping(i).bits)
io.toIntDq(i).valid := intIndex.io.mapping(i).valid && allResourceReady && prevCanOut(intIndex.io.mapping(i).bits)
io.toFpDq(i).bits := uopWithIndex(fpIndex.io.mapping(i).bits)
io.toFpDq(i).valid := fpIndex.io.mapping(i).valid && allResourceReady && prevCanOut(fpIndex.io.mapping(i).bits)
io.toLsDq(i).bits := uopWithIndex(lsIndex.io.mapping(i).bits)
io.toLsDq(i).valid := lsIndex.io.mapping(i).valid && allResourceReady && prevCanOut(lsIndex.io.mapping(i).bits)
io.toIntDq(i).bits := uopWithIndex(intIndex.io.mapping(i).bits)
io.toIntDq(i).valid := intIndex.io.mapping(i).valid && allResourceReady &&
!thisIsBlocked(intIndex.io.mapping(i).bits) && notBlockedByPrevious(intIndex.io.mapping(i).bits)
// NOTE: floating point instructions are not noSpecExec currently
// remove commit /**/ when fp instructions are possible to be noSpecExec
io.toFpDq(i).bits := uopWithIndex(fpIndex.io.mapping(i).bits)
io.toFpDq(i).valid := fpIndex.io.mapping(i).valid && allResourceReady &&
/*!thisIsBlocked(fpIndex.io.mapping(i).bits) && */notBlockedByPrevious(fpIndex.io.mapping(i).bits)
io.toLsDq(i).bits := uopWithIndex(lsIndex.io.mapping(i).bits)
io.toLsDq(i).valid := lsIndex.io.mapping(i).valid && allResourceReady &&
!thisIsBlocked(lsIndex.io.mapping(i).bits) && notBlockedByPrevious(lsIndex.io.mapping(i).bits)
XSDebug(io.toIntDq(i).valid, p"pc 0x${Hexadecimal(io.toIntDq(i).bits.cf.pc)} int index $i\n")
XSDebug(io.toFpDq(i).valid , p"pc 0x${Hexadecimal(io.toFpDq(i).bits.cf.pc )} fp index $i\n")
......
......@@ -44,6 +44,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
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))
......@@ -85,14 +86,13 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
io.roqDeqPtr := deqPtrExt
// Dispatch
val validEntries = distanceBetween(enqPtrExt, deqPtrExt)
val firedDispatch = Cat(io.enq.req.map(_.valid))
io.enq.canAccept := validEntries <= (RoqSize - RenameWidth).U
XSDebug(p"(ready, valid): ${io.enq.canAccept}, ${Binary(firedDispatch)}\n")
val hasBlockBackward = RegInit(false.B)
val hasNoSpecExec = RegInit(false.B)
val blockBackwardCommit = Cat(io.commits.map(c => c.valid && !c.bits.isWalk && c.bits.uop.ctrl.blockBackward)).orR
val noSpecExecCommit = Cat(io.commits.map(c => c.valid && !c.bits.isWalk && c.bits.uop.ctrl.noSpecExec)).orR
when(blockBackwardCommit){ hasBlockBackward:= false.B }
when(noSpecExecCommit){ hasNoSpecExec:= false.B }
val noSpecEnq = io.enq.req.map(i => i.bits.ctrl.blockBackward)
val hasNoSpec = RegInit(false.B)
when(isEmpty){ hasNoSpec:= false.B }
val validDispatch = io.enq.req.map(_.valid)
XSDebug("(ready, valid): ")
for (i <- 0 until RenameWidth) {
......@@ -100,19 +100,30 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val roqIdxExt = enqPtrExt + offset
val roqIdx = roqIdxExt.value
when(io.enq.req(i).valid){
when(io.enq.req(i).valid) {
microOp(roqIdx) := io.enq.req(i).bits
valid(roqIdx) := true.B
flag(roqIdx) := roqIdxExt.flag
writebacked(roqIdx) := false.B
when(noSpecEnq(i)){ hasNoSpec := true.B }
when(io.enq.req(i).bits.ctrl.blockBackward) {
hasBlockBackward := true.B
}
when(io.enq.req(i).bits.ctrl.noSpecExec) {
hasNoSpecExec := true.B
}
}
io.enq.resp(i) := roqIdxExt
}
val validEntries = distanceBetween(enqPtrExt, deqPtrExt)
val firedDispatch = Cat(io.enq.req.map(_.valid))
io.enq.canAccept := (validEntries <= (RoqSize - RenameWidth).U) && !hasBlockBackward
io.enq.isEmpty := isEmpty
XSDebug(p"(ready, valid): ${io.enq.canAccept}, ${Binary(firedDispatch)}\n")
val dispatchCnt = PopCount(firedDispatch)
enqPtrExt := enqPtrExt + PopCount(firedDispatch)
when (firedDispatch.orR) {
enqPtrExt := enqPtrExt + dispatchCnt
XSInfo("dispatched %d insts\n", dispatchCnt)
}
......@@ -144,7 +155,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val deqUop = microOp(deqPtr)
val deqPtrWritebacked = writebacked(deqPtr) && valid(deqPtr)
val intrEnable = io.csr.intrBitSet && !isEmpty && !hasNoSpec &&
val intrEnable = io.csr.intrBitSet && !isEmpty && !hasNoSpecExec &&
deqUop.ctrl.commitType =/= CommitType.STORE && deqUop.ctrl.commitType =/= CommitType.LOAD// TODO: wanna check why has hasCsr(hasNoSpec)
val exceptionEnable = deqPtrWritebacked && Cat(deqUop.cf.exceptionVec).orR()
val isFlushPipe = deqPtrWritebacked && deqUop.ctrl.flushPipe
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册