Skip to content

Commit 0e9a807

Browse files
Fix critical miss queue pushing
1 parent e7ff788 commit 0e9a807

12 files changed

+50
-32
lines changed

src/main/scala/caches/hardware/pipelined/stages/Rep.scala

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class Rep(nCores: Int, nSets: Int, nWays: Int, nMshrs: Int, reqIdWidth: Int, tag
8585
val updateStageValid = WireDefault(false.B)
8686
val updateStageIsHit = WireDefault(false.B)
8787
val updateStageIsCrit = WireDefault(false.B)
88+
val updateStageMshrIdx = WireDefault(0.U(log2Up(nWays).W))
8889

8990
def updateValidAndDirtyBits(inValid: Vec[Bool], inDirty: Vec[Bool], inTags: Vec[UInt], currIdx: UInt, useInvalidate: Boolean = true): (Vec[Bool], Vec[Bool], Vec[UInt]) = {
9091
val newValidBits = VecInit(Seq.fill(nWays)(false.B))
@@ -126,19 +127,28 @@ class Rep(nCores: Int, nSets: Int, nWays: Int, nMshrs: Int, reqIdWidth: Int, tag
126127
// We compute a half miss check here, since we do not need to know the replacement way either way
127128
val halfMissCheckInMissFifoNonCrit = halfMissCheck(io.rep.index, io.rep.tag, io.missNonCritInfo.currentIndexes, io.missNonCritInfo.currentTags, io.missNonCritInfo.validMSHRs)
128129
val halfMissCheckInMissFifoCrit = halfMissCheck(io.rep.index, io.rep.tag, io.missCritInfo.currentIndexes, io.missCritInfo.currentTags, io.missCritInfo.validMSHRs)
129-
val halfMissCheckInMissFifo = (halfMissCheckInMissFifoCrit._1 || halfMissCheckInMissFifoNonCrit._1, Mux(halfMissCheckInMissFifoCrit._1, halfMissCheckInMissFifoCrit._2, halfMissCheckInMissFifoNonCrit._2))
130130

131131
val halfMissCheckInUpdateStage = io.rep.index === updateStageIndex && io.rep.tag === updateStageTag && updateStageValid && !updateStageIsHit
132-
val halfMissIdxInUpdateStage = Mux(updateStageIsCrit, io.missCritInfo.wrPtr, io.missNonCritInfo.wrPtr)
133132

134-
val isHalfMiss = halfMissCheckInMissFifo._1 || halfMissCheckInUpdateStage
135-
val halfMissIdx = Mux(halfMissCheckInMissFifo._1, halfMissCheckInMissFifo._2, halfMissIdxInUpdateStage)
133+
val isHalfMiss = halfMissCheckInMissFifoNonCrit._1 || halfMissCheckInMissFifoCrit._1 || halfMissCheckInUpdateStage
134+
val halfMissIdx = WireDefault(0.U(log2Up(nMshrs).W))
135+
val isHalfMissInCrit = WireDefault(false.B)
136+
when(halfMissCheckInUpdateStage) {
137+
halfMissIdx := updateStageMshrIdx
138+
isHalfMissInCrit := updateStageIsCrit
139+
} .elsewhen (halfMissCheckInMissFifoCrit._1) {
140+
halfMissIdx := halfMissCheckInMissFifoCrit._2
141+
isHalfMissInCrit := true.B
142+
} .elsewhen (halfMissCheckInMissFifoNonCrit._1) {
143+
halfMissIdx := halfMissCheckInMissFifoNonCrit._2
144+
isHalfMissInCrit := false.B
145+
}
136146

137147
val coreIdReg = PipelineReg(io.rep.coreId, 0.U, !io.stall)
138148
val reqValidReg = PipelineReg(io.rep.reqValid, false.B, !io.stall)
139149
val isHalfMissReg = PipelineReg(isHalfMiss, false.B, !io.stall)
140150
val halfMissIdxReg = PipelineReg(halfMissIdx, 0.U, !io.stall)
141-
val halfMissInCritReg = PipelineReg(updateStageIsCrit || halfMissCheckInMissFifoCrit._1, false.B, !io.stall)
151+
val halfMissInCritReg = PipelineReg(isHalfMissInCrit, false.B, !io.stall)
142152
val reqIdReg = PipelineReg(io.rep.reqId, 0.U, !io.stall)
143153
val reqRwReg = PipelineReg(io.rep.reqRw, false.B, !io.stall)
144154
val wDataReg = PipelineReg(io.rep.wData, 0.U, !io.stall)
@@ -154,18 +164,14 @@ class Rep(nCores: Int, nSets: Int, nWays: Int, nMshrs: Int, reqIdWidth: Int, tag
154164

155165
val validAndDirtyBits2 = updateValidAndDirtyBits(validBitsReg, dirtyBitsReg, setTagsReg, indexReg, useInvalidate = false)
156166
val isHit = checkIfHit(validAndDirtyBits2._1, validAndDirtyBits2._3, tagReg) // Long combinational path // TODO: Move one pipeline register back instead
157-
158-
updateStageIndex := indexReg
159-
updateStageTag := tagReg
160-
updateStageValid := reqValidReg
161-
updateStageIsHit := isHit._1
167+
val isHalfMissInUpdateStage = isHalfMissReg && !(!halfMissInCritReg && io.repPol.updateCoreReachedLimit) // If the core has reached limit and there is already a request in the non-critical q then we turn it into a full new request
162168

163169
val repWay = io.repPol.replaceWay
164170
val repWayValid = io.repPol.isValid
165171
val isRepDirty = validAndDirtyBits2._2(repWay)
166172
val isRepLineValid = validAndDirtyBits2._1(repWay)
167173
val dirtyTag = validAndDirtyBits2._3(repWay)
168-
val evict = reqValidReg && (!isHit._1 && repWayValid && !isHalfMissReg) && !io.stall
174+
val evict = reqValidReg && (!isHit._1 && repWayValid && !isHalfMissInUpdateStage) && !io.stall
169175

170176
// Replacement policy connections
171177

@@ -184,7 +190,7 @@ class Rep(nCores: Int, nSets: Int, nWays: Int, nMshrs: Int, reqIdWidth: Int, tag
184190
io.repPol.nonCritWbEntryIsCrit := io.nonCritWbEntryIsCrit
185191

186192
// Push request or a command to the miss fifo
187-
io.isMissPushCrit := halfMissInCritReg || io.repPol.updateCoreReachedLimit
193+
io.isMissPushCrit := (isHalfMissInUpdateStage && halfMissInCritReg) || io.repPol.updateCoreReachedLimit
188194
updateStageIsCrit := io.repPol.updateCoreReachedLimit && reqValidReg
189195

190196
// Miss fifo connections
@@ -197,13 +203,13 @@ class Rep(nCores: Int, nSets: Int, nWays: Int, nMshrs: Int, reqIdWidth: Int, tag
197203
io.missFifoPush.pushReqEntry.incidentCoreId := coreIdReg
198204
io.missFifoPush.pushReqEntry.isCrit := io.repPol.updateCoreIsCrit
199205

200-
io.missFifoPush.pushCmd := isHalfMissReg && reqValidReg && !isHit._1 && !io.stall // Push a half miss command
206+
io.missFifoPush.pushCmd := isHalfMissInUpdateStage && reqValidReg && !isHit._1 && !io.stall // Push a half miss command
201207
io.missFifoPush.mshrIdx := halfMissIdxReg
202208
io.missFifoPush.pushCmdEntry.reqId := reqIdReg
203209
io.missFifoPush.pushCmdEntry.coreId := coreIdReg
204210
io.missFifoPush.pushCmdEntry.blockOffset := blockOffsetReg
205211

206-
io.missFifoPush.updateByteEn := (isHalfMissReg && reqValidReg && !isHit._1 && reqRwReg && !io.stall) // Update a byte mask if it is a write request and a half miss
212+
io.missFifoPush.updateByteEn := (isHalfMissInUpdateStage && reqValidReg && !isHit._1 && reqRwReg && !io.stall) // Update a byte mask if it is a write request and a half miss
207213
io.missFifoPush.updateByteEnVal := byteEnReg
208214
io.missFifoPush.updateByteEnCol := blockOffsetReg
209215
io.missFifoPush.updateByteEnRow := halfMissIdxReg
@@ -233,7 +239,7 @@ class Rep(nCores: Int, nSets: Int, nWays: Int, nMshrs: Int, reqIdWidth: Int, tag
233239
io.read.wData := wDataReg
234240
io.read.byteEn := blockByteMask((blockWidth / 8) -1, 0)
235241
io.read.repValid := repWayValid
236-
io.read.repWay := Mux(isHalfMissReg, Mux(halfMissInCritReg, io.missCritInfo.replacementWays(halfMissIdxReg), io.missNonCritInfo.replacementWays(halfMissIdxReg)), repWay) // If it is a half miss we give the replacement way of the full miss for a write request
242+
io.read.repWay := Mux(isHalfMissInUpdateStage, Mux(halfMissInCritReg, io.missCritInfo.replacementWays(halfMissIdxReg), io.missNonCritInfo.replacementWays(halfMissIdxReg)), repWay) // If it is a half miss we give the replacement way of the full miss for a write request
237243
io.read.isHit := isHit._1
238244
io.read.hitWay := isHit._2
239245
io.read.isRepDirty := isRepDirty
@@ -251,15 +257,22 @@ class Rep(nCores: Int, nSets: Int, nWays: Int, nMshrs: Int, reqIdWidth: Int, tag
251257
io.invalidate.way := invalidateWay
252258
io.invalidate.index := invalidateIndex
253259

260+
// Forwarding signals to the previous stage
261+
updateStageIndex := indexReg
262+
updateStageTag := tagReg
263+
updateStageValid := reqValidReg
264+
updateStageIsHit := isHit._1
265+
updateStageMshrIdx := Mux(evict, Mux(io.repPol.updateCoreReachedLimit, io.missCritInfo.wrPtr, io.missNonCritInfo.wrPtr), halfMissIdxReg)
266+
254267
// ---------------- Stalls due to hazards ----------------
255268

256269
// If the replacement way is dirty but the line is not valid---stall the pipeline
257270
val stallDueToDirtyInvalid = reqValidReg && (!isHit._1 && isRepDirty && !isRepLineValid)
258271
io.dirtyInvalidStall := stallDueToDirtyInvalid
259272

260273
// If a single mshr register is full of commands then we stall the pipeline until the line is brought in
261-
val cmdCapacityNonCrit = io.missNonCritInfo.fullCmds(halfMissIdxReg) && io.missNonCritInfo.validMSHRs(halfMissIdxReg) && isHalfMissReg && !isHit._1
262-
val cmdCapacityCrit = io.missCritInfo.fullCmds(halfMissIdxReg) && io.missCritInfo.validMSHRs(halfMissIdxReg) && isHalfMissReg && !isHit._1
274+
val cmdCapacityNonCrit = io.missNonCritInfo.fullCmds(halfMissIdxReg) && io.missNonCritInfo.validMSHRs(halfMissIdxReg) && isHalfMissInUpdateStage && !isHit._1
275+
val cmdCapacityCrit = io.missCritInfo.fullCmds(halfMissIdxReg) && io.missCritInfo.validMSHRs(halfMissIdxReg) && isHalfMissInUpdateStage && !isHit._1
263276
val halfMissCapacity = Mux(halfMissInCritReg, cmdCapacityCrit, cmdCapacityNonCrit)
264277
io.halfMissCapacity := halfMissCapacity
265278
}

src/main/scala/caches/hardware/reppol/TimeoutReplacementPolicy.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class TimeoutReplacementPolicy(nWays: Int, nSets: Int, nCores: Int, basePolicy:
117117
timeoutAlgo.io.decIdxTimers := timerMemory.io.rTimers1
118118
timeoutAlgo.io.updateIdxTimers := timerMemory.io.rTimers2
119119
decIdx := timeoutAlgo.io.decIdx
120-
timerMemWrEn := true.B // TODO: ???
120+
timerMemWrEn := true.B // TODO: Should write enable always be high since we are always decrementing something ???
121121
timerMemWrData := timeoutAlgo.io.wTimers
122122
timerMemWrIdx := timeoutAlgo.io.wIdx
123123

src/test/scala/caches/hardware/pipelined/OcpCacheWrapperTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class OcpCacheWrapperTest extends AnyFlatSpec with ChiselScalatestTester {
4444
memDataWidth = memDataWidth,
4545
memBurstLen = memBurstLen,
4646
l2Cache = l2CacheGen
47-
)).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut =>
47+
)).withAnnotations(Seq(WriteFstAnnotation, VerilatorBackendAnnotation)) { dut =>
4848
// Default assignments
4949
for (i <- 0 until nCores) {
5050
dut.io.cores(i).M.Cmd.poke(OcpCmd.IDLE)

src/test/scala/caches/hardware/pipelined/cache/SharedPipelinedCacheBitPlruTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class SharedPipelinedCacheBitPlruTest extends AnyFlatSpec with ChiselScalatestTe
88
"SharedPipelinedCache" should "process pipelined requests for 8 ways, 128 sets, with bit plru policy" in {
99
val cache = generateDut(CacheConfigs.config64BitPlru)
1010

11-
test(cache._1.apply()).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut =>
11+
test(cache._1.apply()).withAnnotations(Seq(WriteFstAnnotation, VerilatorBackendAnnotation)) { dut =>
1212
defaultAssignments(dut, cache._2)
1313

1414
performTestActions(
@@ -29,7 +29,7 @@ class SharedPipelinedCacheBitPlruTest extends AnyFlatSpec with ChiselScalatestTe
2929
"SharedPipelinedCache" should "work with mshr entries that are full of cmds" in {
3030
val cache = generateDut(CacheConfigs.config64BitPlru)
3131

32-
test(cache._1.apply()).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut =>
32+
test(cache._1.apply()).withAnnotations(Seq(WriteFstAnnotation, VerilatorBackendAnnotation)) { dut =>
3333
defaultAssignments(dut, cache._2)
3434

3535
// Issue the first set of requests

src/test/scala/caches/hardware/pipelined/cache/SharedPipelinedCacheContWithAllEvents.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class SharedPipelinedCacheContWithAllEvents extends AnyFlatSpec with ChiselScala
88
"SharedPipelinedCache" should "work with all contention events" in {
99
val cache = generateDut(CacheConfigs.config64ContMimPrecWb)
1010

11-
test(cache._1.apply()).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut =>
11+
test(cache._1.apply()).withAnnotations(Seq(WriteFstAnnotation, VerilatorBackendAnnotation)) { dut =>
1212
defaultAssignments(dut, cache._2)
1313

1414
// Issue the first set of requests
@@ -19,7 +19,7 @@ class SharedPipelinedCacheContWithAllEvents extends AnyFlatSpec with ChiselScala
1919
cache._3,
2020
cache._4,
2121
cache._5,
22-
600,
22+
1000,
2323
printResults = PRINT_RESULTS
2424
)
2525

src/test/scala/caches/hardware/pipelined/cache/SharedPipelinedCacheContentionTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class SharedPipelinedCacheContentionTest extends AnyFlatSpec with ChiselScalates
88
"SharedPipelinedCache" should "process pipelined requests for 8 ways, 128 sets, with contention policy" in {
99
val cache = generateDut(CacheConfigs.config64Cont)
1010

11-
test(cache._1.apply()).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut =>
11+
test(cache._1.apply()).withAnnotations(Seq(WriteFstAnnotation, VerilatorBackendAnnotation)) { dut =>
1212
defaultAssignments(dut, cache._2)
1313

1414
// Issue the first set of requests

src/test/scala/caches/hardware/pipelined/cache/SharedPipelinedCacheStressTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class SharedPipelinedCacheStressTest extends AnyFlatSpec with ChiselScalatestTes
88
"SharedPipelinedCache" should "handle stress test with bit plru policy" in {
99
val cache = generateDut(CacheConfigs.config64BitPlru)
1010

11-
test(cache._1.apply()).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut =>
11+
test(cache._1.apply()).withAnnotations(Seq(WriteFstAnnotation, VerilatorBackendAnnotation)) { dut =>
1212
defaultAssignments(dut, cache._2)
1313

1414
performTestActions(

src/test/scala/caches/hardware/pipelined/cache/SharedPipelinedCacheTest.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ case class CacheRequest(
2626
expectedData: Option[String] = None
2727
) extends TestAction
2828

29+
// TODO: Should add an optional parameter that says that a response for a request should be received after a response to some other request has been received
30+
2931
case class Stall(stallCycles: Int = 0) extends TestAction()
3032

3133
case class ExpectFinishedRejectedResponse(coreId: Int, reqId: Int, expectedData: String) extends TestAction()
@@ -379,10 +381,13 @@ object Tests {
379381
CacheRequest(coreId = 3, reqId = 13, tag = 39, index = 74, blockOffset = 3, rw = false, expectedData = Some("b638aaa4ef343eee6a4757cb65a2f78c")), // MISS, way: 3, contention event, critical wb, reach contention limit for core 1
380382
CacheRequest(coreId = 1, reqId = 14, tag = 57, index = 74, blockOffset = 2, rw = false, expectedData = Some("26f4756810b9c7b7fc87a234ac62fee6")), // MISS, way: 2,
381383
CacheRequest(coreId = 2, reqId = 15, tag = 41, index = 74, blockOffset = 1, rw = false, expectedData = Some("8f2a3009871c1b8fb22ed80f63229d0f")), // MISS, way: 3,
382-
CacheRequest(coreId = 0, reqId = 16, tag = 8, index = 74, blockOffset = 0, rw = false, expectedData = Some("e83fb23952953ff164bdb8d5685d2bd3"), rejected = true), // MISS, way: rejected
384+
CacheRequest(coreId = 0, reqId = 16, tag = 41, index = 72, blockOffset = 1, rw = false, expectedData = Some("abbd90af6dbb29366ec5bd141df45023")), // MISS, way: 0,
385+
CacheRequest(coreId = 1, reqId = 17, tag = 41, index = 72, blockOffset = 0, rw = false, expectedData = Some("a64a45812e63b4001eafac68edee5dd6")), // MISS, way: 1, not a half-miss since the core reached contention limit
386+
CacheRequest(coreId = 2, reqId = 18, tag = 41, index = 72, blockOffset = 2, rw = false, expectedData = Some("b1a10cf29e0b684ae2dd8277b34d19f1")), // MISS, way: 2, not a half-miss since the core reached contention limit
387+
CacheRequest(coreId = 0, reqId = 19, tag = 8, index = 74, blockOffset = 0, rw = false, expectedData = Some("e83fb23952953ff164bdb8d5685d2bd3"), rejected = true), // MISS, way: rejected
383388
Stall(300),
384389
PerformSchedulerOperation(2, false),
385-
ExpectFinishedRejectedResponse(coreId = 0, reqId = 16, expectedData = "e83fb23952953ff164bdb8d5685d2bd3")
390+
ExpectFinishedRejectedResponse(coreId = 0, reqId = 19, expectedData = "e83fb23952953ff164bdb8d5685d2bd3")
386391
)
387392
}
388393

src/test/scala/caches/hardware/pipelined/cache/SharedPipelinedCacheTestMissQ.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class SharedPipelinedCacheTestMissQ extends AnyFlatSpec with ChiselScalatestTest
88
"SharedPipelinedCache" should "work with miss-q and precedent events for 8 ways and 128 sets" in {
99
val cache = generateDut(CacheConfigs.config64ContMimPrec)
1010

11-
test(cache._1.apply()).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut =>
11+
test(cache._1.apply()).withAnnotations(Seq(WriteFstAnnotation, VerilatorBackendAnnotation)) { dut =>
1212
defaultAssignments(dut, cache._2)
1313

1414
// Issue the first set of requests

src/test/scala/caches/hardware/pipelined/cache/SharedPipelinedCacheTimeoutTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class SharedPipelinedCacheTimeoutTest extends AnyFlatSpec with ChiselScalatestTe
88
"SharedPipelinedCache" should "process pipelined requests for 8 ways, 128 sets, with timeout policy" in {
99
val cache = generateDut(CacheConfigs.config64TimeOut)
1010

11-
test(cache._1.apply()).withAnnotations(Seq(WriteVcdAnnotation, VerilatorBackendAnnotation)) { dut =>
11+
test(cache._1.apply()).withAnnotations(Seq(WriteFstAnnotation, VerilatorBackendAnnotation)) { dut =>
1212
defaultAssignments(dut, cache._2)
1313

1414
// Issue the first set of requests

0 commit comments

Comments
 (0)