Skip to content

Commit 071c63e

Browse files
authored
StoreQueue: Commit storequeue entry by judging robidx (#3020)
In the previous design, for scalar store commands, commits were made based on the `scommit` passed in by rob. That is, after rob commits n store commands in one cycle, it sets scommit to n, and the storequeue needs to commit n entries based on the value of scommit. Due to the special nature of vector instructions, a vector store instruction may correspond to a maximum of 128 items, and it is not possible to use `scommit` commits, which are similar to scalar commits. In this modification, both vector and scalar directives are compared against `robidx`, and the storequeue entry is committed when the `uop` stored in `uop` is equal to or older than the `pendingptr` passed in by rob. This has some improvement on timing. Also, additional processing is currently required for vector instructions. When an exception occurs on an item, it needs to be handled with an out-of-queue, but not write sbuffer.
1 parent 6b742a1 commit 071c63e

File tree

1 file changed

+23
-31
lines changed

1 file changed

+23
-31
lines changed

src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ class StoreQueue(implicit p: Parameters) extends XSModule
244244
//val vec_lastuop = Reg(Vec(StoreQueueSize, Bool())) // last uop of vector store instruction
245245
val vecMbCommit = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // vector store committed from merge buffer to rob
246246
val vecDataValid = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // vector store need write to sbuffer
247+
val hasException = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // store has exception, should deq but not write sbuffer
248+
val waitStoreS2 = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // wait for mmio and exception result until store_s2
247249
// val vec_robCommit = Reg(Vec(StoreQueueSize, Bool())) // vector store committed by rob
248250
// val vec_secondInv = RegInit(VecInit(List.fill(StoreQueueSize)(false.B))) // Vector unit-stride, second entry is invalid
249251

@@ -265,15 +267,9 @@ class StoreQueue(implicit p: Parameters) extends XSModule
265267
val deqMask = UIntToMask(deqPtr, StoreQueueSize)
266268
val enqMask = UIntToMask(enqPtr, StoreQueueSize)
267269

268-
// TODO: count commit numbers for scalar / vector store separately
269-
val scalarCommitCount = RegInit(0.U(log2Ceil(StoreQueueSize + 1).W))
270-
val scalarCommitted = WireInit(0.U(log2Ceil(CommitWidth + 1).W))
271-
val vecCommitted = WireInit(0.U(log2Ceil(CommitWidth + 1).W))
272270
val commitCount = WireInit(0.U(log2Ceil(CommitWidth + 1).W))
273271
val scommit = GatedRegNext(io.rob.scommit)
274272

275-
scalarCommitCount := scalarCommitCount + scommit - scalarCommitted
276-
277273
// store can be committed by ROB
278274
io.rob.mmio := DontCare
279275
io.rob.uop := DontCare
@@ -348,6 +344,8 @@ class StoreQueue(implicit p: Parameters) extends XSModule
348344
isVec((index + j.U).value) := enqInstr.isVecStore // check vector store by the encoding of inst
349345
vecMbCommit((index + j.U).value) := false.B
350346
vecDataValid((index + j.U).value) := false.B
347+
hasException((index + j.U).value) := false.B
348+
waitStoreS2((index + j.U).value) := true.B
351349
XSError(!io.enq.canAccept || !io.enq.lqCanAccept, s"must accept $i\n")
352350
XSError(index.value =/= sqIdx.value, s"must be the same entry $i\n")
353351
}
@@ -484,6 +482,8 @@ class StoreQueue(implicit p: Parameters) extends XSModule
484482
pending(stWbIndexReg) := io.storeAddrInRe(i).mmio
485483
mmio(stWbIndexReg) := io.storeAddrInRe(i).mmio
486484
atomic(stWbIndexReg) := io.storeAddrInRe(i).atomic
485+
hasException(stWbIndexReg) := ExceptionNO.selectByFu(uop(stWbIndexReg).exceptionVec, StaCfg).asUInt.orR || io.storeAddrInRe(i).af
486+
waitStoreS2(stWbIndexReg) := false.B
487487
}
488488
// dcache miss info (one cycle later than storeIn)
489489
// if dcache report a miss in sta pipeline, this store will trigger a prefetch when committing to sbuffer (if EnableAtCommitMissTrigger)
@@ -851,39 +851,30 @@ class StoreQueue(implicit p: Parameters) extends XSModule
851851
XSError(uncacheState =/= s_idle && uncacheState =/= s_wait && commitCount > 0.U,
852852
"should not commit instruction when MMIO has not been finished\n")
853853

854-
val scalarcommitVec = WireInit(VecInit(Seq.fill(CommitWidth)(false.B)))
855-
val veccommitVec = WireInit(VecInit(Seq.fill(CommitWidth)(false.B)))
854+
val commitVec = WireInit(VecInit(Seq.fill(CommitWidth)(false.B)))
855+
val needCancel = Wire(Vec(StoreQueueSize, Bool())) // Will be assigned later
856+
dontTouch(commitVec)
856857
// TODO: Deal with vector store mmio
857858
for (i <- 0 until CommitWidth) {
858-
val veccount = PopCount(veccommitVec.take(i))
859-
when (allocated(cmtPtrExt(i).value) && isVec(cmtPtrExt(i).value) && isNotAfter(uop(cmtPtrExt(i).value).robIdx, RegNext(io.rob.pendingPtr)) && vecMbCommit(cmtPtrExt(i).value)) {
859+
when (allocated(cmtPtrExt(i).value) && isNotAfter(uop(cmtPtrExt(i).value).robIdx, RegNext(io.rob.pendingPtr)) && !needCancel(cmtPtrExt(i).value) && !waitStoreS2(cmtPtrExt(i).value)) {
860860
if (i == 0){
861861
// TODO: fixme for vector mmio
862862
when ((uncacheState === s_idle) || (uncacheState === s_wait && scommit > 0.U)){
863-
committed(cmtPtrExt(0).value) := true.B
864-
veccommitVec(i) := true.B
863+
when ((isVec(cmtPtrExt(i).value) && vecMbCommit(cmtPtrExt(i).value)) || !isVec(cmtPtrExt(i).value)) {
864+
committed(cmtPtrExt(0).value) := true.B
865+
commitVec(0) := true.B
866+
}
865867
}
866868
} else {
867-
committed(cmtPtrExt(i).value) := true.B
868-
veccommitVec(i) := veccommitVec(i - 1) || scalarcommitVec(i - 1)
869-
}
870-
} .elsewhen (scalarCommitCount > i.U - veccount) {
871-
if (i == 0){
872-
when ((uncacheState === s_idle) || (uncacheState === s_wait && scommit > 0.U)){
873-
committed(cmtPtrExt(0).value) := true.B
874-
scalarcommitVec(i) := true.B
869+
when ((isVec(cmtPtrExt(i).value) && vecMbCommit(cmtPtrExt(i).value)) || !isVec(cmtPtrExt(i).value)) {
870+
committed(cmtPtrExt(i).value) := true.B
871+
commitVec(i) := commitVec(i - 1)
875872
}
876-
} else {
877-
committed(cmtPtrExt(i).value) := true.B
878-
scalarcommitVec(i) := veccommitVec(i - 1) || scalarcommitVec(i - 1)
879873
}
880874
}
881875
}
882876

883-
scalarCommitted := PopCount(scalarcommitVec)
884-
vecCommitted := PopCount(veccommitVec)
885-
commitCount := scalarCommitted + vecCommitted
886-
877+
commitCount := PopCount(commitVec)
887878
cmtPtrExt := cmtPtrExt.map(_ + commitCount)
888879

889880
// committed stores will not be cancelled and can be sent to lower level.
@@ -892,10 +883,10 @@ class StoreQueue(implicit p: Parameters) extends XSModule
892883
// Read data from data module
893884
// As store queue grows larger and larger, time needed to read data from data
894885
// module keeps growing higher. Now we give data read a whole cycle.
895-
val mmioStall = mmio(rdataPtrExt(0).value)
896886
for (i <- 0 until EnsbufferWidth) {
897887
val ptr = rdataPtrExt(i).value
898-
dataBuffer.io.enq(i).valid := allocated(ptr) && committed(ptr) && (!isVec(ptr) || vecMbCommit(ptr)) && !mmioStall
888+
val mmioStall = if(i == 0) mmio(rdataPtrExt(0).value) else (mmio(rdataPtrExt(i).value) || mmio(rdataPtrExt(i-1).value))
889+
dataBuffer.io.enq(i).valid := allocated(ptr) && committed(ptr) && ((!isVec(ptr) && allvalid(ptr)) || vecMbCommit(ptr)) && !mmioStall
899890
// Note that store data/addr should both be valid after store's commit
900891
assert(!dataBuffer.io.enq(i).valid || allvalid(ptr) || (allocated(ptr) && vecMbCommit(ptr)))
901892
dataBuffer.io.enq(i).bits.addr := paddrModule.io.rdata(i)
@@ -905,7 +896,8 @@ class StoreQueue(implicit p: Parameters) extends XSModule
905896
dataBuffer.io.enq(i).bits.wline := paddrModule.io.rlineflag(i)
906897
dataBuffer.io.enq(i).bits.sqPtr := rdataPtrExt(i)
907898
dataBuffer.io.enq(i).bits.prefetch := prefetch(ptr)
908-
dataBuffer.io.enq(i).bits.vecValid := !isVec(ptr) || vecDataValid(ptr) // scalar is always valid
899+
// when scalar has exception, will also not write into sbuffer
900+
dataBuffer.io.enq(i).bits.vecValid := (!isVec(ptr) || vecDataValid(ptr)) && !hasException(ptr)
909901
}
910902

911903
// Send data stored in sbufferReqBitsReg to sbuffer
@@ -944,6 +936,7 @@ class StoreQueue(implicit p: Parameters) extends XSModule
944936
if (env.EnableDifftest) {
945937
for (i <- 0 until EnsbufferWidth) {
946938
val ptr = rdataPtrExt(i).value
939+
val mmioStall = if(i == 0) mmio(rdataPtrExt(0).value) else (mmio(rdataPtrExt(i).value) || mmio(rdataPtrExt(i-1).value))
947940
difftestBuffer.get.io.enq(i).valid := allocated(ptr) && committed(ptr) && (!isVec(ptr) || vecMbCommit(ptr)) && !mmioStall
948941
difftestBuffer.get.io.enq(i).bits := uop(ptr)
949942
}
@@ -993,7 +986,6 @@ class StoreQueue(implicit p: Parameters) extends XSModule
993986

994987
// misprediction recovery / exception redirect
995988
// invalidate sq term using robIdx
996-
val needCancel = Wire(Vec(StoreQueueSize, Bool()))
997989
for (i <- 0 until StoreQueueSize) {
998990
needCancel(i) := uop(i).robIdx.needFlush(io.brqRedirect) && allocated(i) && !committed(i)
999991
when (needCancel(i)) {

0 commit comments

Comments
 (0)