Skip to content

Commit 5ee2491

Browse files
committed
RequestArb: restrict concurrent number of Acquires with same set
Consider a deadlock situation: given 4 ways in each slice, MSHR 0~3 are accessing separate ways, which makes all the ways occupied. At the same time, MSHR 4 already got CompData from HN, and is waiting for a free way to replace and to echo data through channel D to L1. Therefore MSHR 4 selects replacement way but fails repeatedly. If there is an incoming snoop that has the same address with MSHR 4, the snoop will be blocked because Grant message of MSHR 4 is blocked. Then CompData(s) corresponding to MSHR 0~3 could not be returned due to the blocked snoop. There goes the deadlock.
1 parent 5c3f826 commit 5ee2491

File tree

6 files changed

+18
-2
lines changed

6 files changed

+18
-2
lines changed

src/main/scala/coupledL2/Common.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class MSHRRequest(implicit p: Parameters) extends L2Bundle {
173173
}
174174

175175
// MSHR info to ReqBuf and SinkB
176-
class MSHRInfo(implicit p: Parameters) extends L2Bundle {
176+
class MSHRInfo(implicit p: Parameters) extends L2Bundle with HasTLChannelBits {
177177
val set = UInt(setBits.W)
178178
val way = UInt(wayBits.W)
179179
val reqTag = UInt(tagBits.W)

src/main/scala/coupledL2/RequestArb.scala

+13-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ class RequestArb(implicit p: Parameters) extends L2Module {
7070
val fromTXDAT = if (enableCHI) Some(Input(new TXDATBlockBundle)) else None
7171
val fromTXRSP = if (enableCHI) Some(Input(new TXRSPBlockBundle)) else None
7272
val fromTXREQ = if (enableCHI) Some(Input(new TXBlockBundle)) else None
73+
74+
/* MSHR Status */
75+
val msInfo = Vec(mshrsAll, Flipped(ValidIO(new MSHRInfo())))
7376
})
7477

7578
/* ======== Reset ======== */
@@ -137,7 +140,9 @@ class RequestArb(implicit p: Parameters) extends L2Module {
137140

138141
val sink_ready_basic = io.dirRead_s1.ready && resetFinish && !mshr_task_s1.valid && s2_ready
139142

140-
io.sinkA.ready := sink_ready_basic && !block_A && !sinkValids(1) && !sinkValids(0) // SinkC prior to SinkA & SinkB
143+
val noFreeWay = Wire(Bool())
144+
145+
io.sinkA.ready := sink_ready_basic && !block_A && !sinkValids(1) && !sinkValids(0) && !noFreeWay // SinkC prior to SinkA & SinkB
141146
io.sinkB.ready := sink_ready_basic && !block_B && !sinkValids(0) // SinkB prior to SinkA
142147
io.sinkC.ready := sink_ready_basic && !block_C
143148

@@ -189,6 +194,13 @@ class RequestArb(implicit p: Parameters) extends L2Module {
189194
task_s2.valid := s1_fire
190195
when(s1_fire) { task_s2.bits := task_s1.bits }
191196

197+
val sameSet_s2 = task_s2.valid && task_s2.bits.fromA && !task_s2.bits.mshrTask && task_s2.bits.set === A_task.set
198+
val sameSet_s3 = RegNext(task_s2.valid && task_s2.bits.fromA && !task_s2.bits.mshrTask) &&
199+
RegEnable(task_s2.bits.set, task_s2.valid) === A_task.set
200+
val sameSetCnt = PopCount(VecInit(io.msInfo.map(s => s.valid && s.bits.set === A_task.set && s.bits.fromA) :+
201+
sameSet_s2 :+ sameSet_s3).asUInt)
202+
noFreeWay := sameSetCnt >= cacheParams.ways.U
203+
192204
io.taskToPipe_s2 := task_s2
193205

194206
// MSHR task

src/main/scala/coupledL2/tl2chi/MSHR.scala

+1
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,7 @@ class MSHR(implicit p: Parameters) extends TL2CHIL2Module {
958958
io.msInfo.bits.w_replResp := state.w_replResp
959959
io.msInfo.bits.w_rprobeacklast := state.w_rprobeacklast
960960
io.msInfo.bits.replaceData := isT(meta.state) && meta.dirty || probeDirty
961+
io.msInfo.bits.channel := req.channel
961962

962963
assert(!(c_resp.valid && !io.status.bits.w_c_resp))
963964
assert(!(rxrsp.valid && !io.status.bits.w_d_resp))

src/main/scala/coupledL2/tl2chi/Slice.scala

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class Slice()(implicit p: Parameters) extends TL2CHIL2Module {
102102
reqArb.io.fromTXDAT.foreach(_ := txdat.io.toReqArb)
103103
reqArb.io.fromTXRSP.foreach(_ := txrsp.io.toReqArb)
104104
reqArb.io.fromTXREQ.foreach(_ := txreq.io.toReqArb)
105+
reqArb.io.msInfo := mshrCtl.io.msInfo
105106

106107
reqBuf.io.in <> sinkA.io.task
107108
reqBuf.io.mshrInfo := mshrCtl.io.msInfo

src/main/scala/coupledL2/tl2tl/MSHR.scala

+1
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@ class MSHR(implicit p: Parameters) extends L2Module {
553553
io.msInfo.bits.w_releaseack := state.w_releaseack
554554
io.msInfo.bits.w_replResp := state.w_replResp
555555
io.msInfo.bits.w_rprobeacklast := state.w_rprobeacklast
556+
io.msInfo.bits.channel := req.channel
556557

557558
assert(!(c_resp.valid && !io.status.bits.w_c_resp))
558559
assert(!(d_resp.valid && !io.status.bits.w_d_resp))

src/main/scala/coupledL2/tl2tl/Slice.scala

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class Slice()(implicit p: Parameters) extends L2Module {
8181
reqArb.io.fromMainPipe := mainPipe.io.toReqArb
8282
reqArb.io.fromGrantBuffer := grantBuf.io.toReqArb
8383
reqArb.io.fromSourceC.foreach(_ := sourceC.io.toReqArb)
84+
reqArb.io.msInfo := mshrCtl.io.msInfo
8485

8586
mshrCtl.io.fromReqArb.status_s1 := reqArb.io.status_s1
8687
mshrCtl.io.resps.sinkC := sinkC.io.resp

0 commit comments

Comments
 (0)