@@ -180,13 +180,18 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
180
180
181
181
val cmo_cbo = req_cboClean || req_cboFlush || req_cboInval
182
182
183
+ // *NOTICE: WriteBack/WriteClean(s) with nested snoops that passed dirty were not considered as
184
+ // a nested hit here, which would no longer pass latest data to lower tier memories.
183
185
val hitDirty = dirResult.hit && meta.dirty || probeDirty
184
- val hitWriteBack = req.snpHitRelease && req.snpHitReleaseWithData && req.snpHitReleaseDirty
186
+ val hitWriteBack = req.snpHitRelease && req.snpHitReleaseWithData && req.snpHitReleaseDirty && req.snpHitReleaseToInval
187
+ val hitWriteClean = req.snpHitRelease && req.snpHitReleaseWithData && req.snpHitReleaseDirty && req.snpHitReleaseToClean
185
188
val hitWriteEvict = req.snpHitRelease && req.snpHitReleaseWithData && ! req.snpHitReleaseDirty
186
- val hitWriteX = hitWriteBack || hitWriteEvict
187
- val hitDirtyOrWriteBack = hitDirty || hitWriteBack
188
189
189
- val releaseToB = req_cboClean
190
+ val hitWriteX = hitWriteBack || hitWriteClean || hitWriteEvict
191
+ val hitWriteDirty = hitWriteBack || hitWriteClean
192
+ val hitDirtyOrWriteDirty = hitDirty || hitWriteDirty
193
+
194
+ val releaseToClean = req_cboClean
190
195
191
196
/**
192
197
* About which snoop should echo SnpRespData[Fwded] instead of SnpResp[Fwded]:
@@ -197,7 +202,7 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
197
202
* 3. When the snoop opcode is non-forwarding non-stashing snoop, echo SnpRespData if RetToSrc = 1 as long as the
198
203
* cache line is Shared Clean and the snoopee retains a copy of the cache line.
199
204
*/
200
- val doRespData_dirty = hitDirtyOrWriteBack && (
205
+ val doRespData_dirty = hitDirtyOrWriteDirty && (
201
206
req_chiOpcode === SnpOnce ||
202
207
snpToB ||
203
208
req_chiOpcode === SnpUnique ||
@@ -216,8 +221,12 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
216
221
(isSnpToBNonFwd(req_chiOpcode) || isSnpToNNonFwd(req_chiOpcode) || isSnpOnce(req_chiOpcode)) ||
217
222
hitWriteEvict &&
218
223
isSnpOnce(req_chiOpcode))
219
- // doRespData_once includes SnpOnceFwd(nested) UD -> I and SnpOnce UC -> UC/I(non-nested/nested)
220
- val doRespData_once = hitWriteBack &&
224
+ // doRespData_once includes
225
+ // 1. SnpOnceFwd : UD -> I (nesting WriteBack)
226
+ // 2. SnpOnceFwd : UD -> SC (nesting WriteClean)
227
+ // 3. SnpOnce : UC -> UC (non-nesting)
228
+ // 4. SnpOnce : UC -> I (nesting WriteBack)
229
+ val doRespData_once = (hitWriteBack || hitWriteClean) &&
221
230
isSnpOnceFwd(req_chiOpcode) ||
222
231
(dirResult.hit && ! meta.dirty && meta.state =/= BRANCH || hitWriteEvict) &&
223
232
isSnpOnce(req_chiOpcode)
@@ -298,34 +307,35 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
298
307
}
299
308
300
309
// resp and fwdState
301
- val respCacheState = Mux (dirResult.hit, ParallelPriorityMux (Seq (
310
+ // *NOTICE: Snp*Fwd would enter MSHR on directory missing
311
+ val respCacheState = ParallelPriorityMux (Seq (
302
312
snpToN -> I ,
303
- snpToB -> SC ,
313
+ snpToB -> Mux ( ! dirResult.hit, I , SC ) ,
304
314
isSnpOnceX(req_chiOpcode) ->
305
- Mux (
306
- req.snpHitRelease ,
307
- I , // also see 'nestedwb.b_inv_dirty' in MainPipe
315
+ Mux (! dirResult.hit, I , Mux (
316
+ req.snpHitReleaseToClean ,
317
+ SC ,
308
318
Mux (probeDirty || meta.dirty, UD , metaChi)
309
- ),
319
+ )) ,
310
320
(isSnpStashX(req_chiOpcode) || isSnpQuery(req_chiOpcode)) ->
311
321
Mux (probeDirty || meta.dirty, UD , metaChi),
312
322
isSnpCleanShared(req_chiOpcode) ->
313
323
Mux (isT(meta.state), UC , metaChi)
314
- )), I )
315
- val respPassDirty = hitDirtyOrWriteBack && (
324
+ ))
325
+ val respPassDirty = hitDirtyOrWriteDirty && (
316
326
snpToB ||
317
327
req_chiOpcode === SnpUnique ||
318
328
req_chiOpcode === SnpUniqueStash ||
319
329
req_chiOpcode === SnpCleanShared ||
320
330
req_chiOpcode === SnpCleanInvalid ||
321
- isSnpOnceX(req_chiOpcode) && hitWriteBack
331
+ isSnpOnceX(req_chiOpcode) && hitWriteDirty
322
332
)
323
333
val fwdCacheState = Mux (
324
334
isSnpToBFwd(req_chiOpcode),
325
335
SC ,
326
336
Mux (isSnpToNFwd(req_chiOpcode), UC /* UC_UD*/ , I )
327
337
)
328
- val fwdPassDirty = isSnpToNFwd(req_chiOpcode) && hitDirtyOrWriteBack
338
+ val fwdPassDirty = isSnpToNFwd(req_chiOpcode) && hitDirtyOrWriteDirty
329
339
330
340
/* TXRSP for CompAck */
331
341
val orsp = io.tasks.txrsp.bits
@@ -630,21 +640,32 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
630
640
* 1. If the snoop belongs to SnpToN
631
641
* 2. If the snoop belongs to SnpToB
632
642
* 3. If the snoop is SnpCleanShared
643
+ * 4. If the snoop is SnpOnce/SnpOnceFwd and nesting WriteCleanFull
633
644
* Otherwise, the dirty bit should stay the same as before.
634
645
*/
635
- dirty = ! snpToN && ! snpToB && req_chiOpcode =/= SnpCleanShared && (dirResult.hit && meta.dirty) ||
636
- isSnpOnceX(req_chiOpcode) && probeDirty,
646
+ dirty = ! (
647
+ ! dirResult.hit || ! meta.dirty ||
648
+ snpToN ||
649
+ snpToB ||
650
+ isSnpCleanShared(req_chiOpcode) ||
651
+ isSnpOnceX(req_chiOpcode) && req.snpHitReleaseToClean
652
+ ) || isSnpOnceX(req_chiOpcode) && probeDirty,
653
+ // Directory would always be missing on nesting WriteBackFull/WriteEvict*/Evict
637
654
state = Mux (
638
655
snpToN,
639
656
INVALID ,
640
- Mux (snpToB, BRANCH , meta.state)
657
+ Mux (
658
+ // On SnpOnce/SnpOnceFwd nesting WriteCleanFull with UD, we went UD -> SC (T -> B here)
659
+ snpToB || isSnpOnceX(req_chiOpcode) && hitWriteClean,
660
+ BRANCH ,
661
+ meta.state)
641
662
),
642
663
clients = meta.clients & Fill (clientBits, ! probeGotN && ! snpToN),
643
664
alias = meta.alias, // [Alias] Keep alias bits unchanged
644
665
prefetch = ! snpToN && meta_pft,
645
666
accessed = ! snpToN && meta.accessed
646
667
)
647
- mp_probeack.metaWen := ! req.snpHitRelease || req.snpHitReleaseToB
668
+ mp_probeack.metaWen := ! req.snpHitReleaseToInval
648
669
mp_probeack.tagWen := false .B
649
670
mp_probeack.dsWen := ! snpToN && probeDirty && meta.clients.orR
650
671
mp_probeack.wayMask := 0 .U (cacheParams.ways.W )
@@ -679,7 +700,8 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
679
700
mp_probeack.expCompAck.get := false .B
680
701
mp_probeack.traceTag.get := req.traceTag.get
681
702
mp_probeack.snpHitRelease := req.snpHitRelease
682
- mp_probeack.snpHitReleaseToB := req.snpHitReleaseToB
703
+ mp_probeack.snpHitReleaseToInval := req.snpHitReleaseToInval
704
+ mp_probeack.snpHitReleaseToClean := req.snpHitReleaseToClean
683
705
mp_probeack.snpHitReleaseWithData := req.snpHitReleaseWithData
684
706
mp_probeack.snpHitReleaseIdx := req.snpHitReleaseIdx
685
707
@@ -867,7 +889,8 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
867
889
mp_dct.expCompAck.get := false .B // DontCare
868
890
mp_dct.traceTag.get := req.traceTag.get
869
891
mp_dct.snpHitRelease := req.snpHitRelease
870
- mp_dct.snpHitReleaseToB := req.snpHitReleaseToB
892
+ mp_dct.snpHitReleaseToInval := req.snpHitReleaseToInval
893
+ mp_dct.snpHitReleaseToClean := req.snpHitReleaseToClean
871
894
mp_dct.snpHitReleaseWithData := req.snpHitReleaseWithData
872
895
mp_dct.snpHitReleaseIdx := req.snpHitReleaseIdx
873
896
mp_dct.snpHitReleaseState := req.snpHitReleaseState
@@ -929,7 +952,8 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
929
952
mp_cmometaw.expCompAck.get := false .B // DontCare
930
953
mp_cmometaw.traceTag.get := 0 .U
931
954
mp_cmometaw.snpHitRelease := req.snpHitRelease
932
- mp_cmometaw.snpHitReleaseToB := req.snpHitReleaseToB
955
+ mp_cmometaw.snpHitReleaseToInval := req.snpHitReleaseToInval
956
+ mp_cmometaw.snpHitReleaseToClean := req.snpHitReleaseToClean
933
957
mp_cmometaw.snpHitReleaseWithData := req.snpHitReleaseWithData
934
958
mp_cmometaw.snpHitReleaseIdx := req.snpHitReleaseIdx
935
959
mp_cmometaw.snpHitReleaseState := req.snpHitReleaseState
@@ -1306,7 +1330,7 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes {
1306
1330
io.msInfo.bits.w_rprobeacklast := state.w_rprobeacklast
1307
1331
io.msInfo.bits.replaceData := isT(meta.state) && meta.dirty || probeDirty || // including WriteCleanFull
1308
1332
isWriteEvictFull || isWriteEvictOrEvict
1309
- io.msInfo.bits.releaseToB := releaseToB
1333
+ io.msInfo.bits.releaseToClean := releaseToClean
1310
1334
io.msInfo.bits.channel := req.channel
1311
1335
1312
1336
assert(! (c_resp.valid && ! io.status.bits.w_c_resp))
0 commit comments