From 649dcb8c8e28da39098fdb43fdd5800f637b0c67 Mon Sep 17 00:00:00 2001 From: Kumonda221 Date: Wed, 26 Nov 2025 23:40:51 +0800 Subject: [PATCH 1/4] fix(CustomL1Hint): sync with AccessAckData for hint accuracy --- src/main/scala/coupledL2/CustomL1Hint.scala | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/scala/coupledL2/CustomL1Hint.scala b/src/main/scala/coupledL2/CustomL1Hint.scala index 3cd350f31..4000b9ca6 100644 --- a/src/main/scala/coupledL2/CustomL1Hint.scala +++ b/src/main/scala/coupledL2/CustomL1Hint.scala @@ -60,14 +60,16 @@ class CustomL1Hint(implicit p: Parameters) extends L2Module { def isRelease(t: TaskBundle): Bool = t.fromC && (t.opcode === Release || t.opcode === ReleaseData) def isMergeGrantData(t: TaskBundle): Bool = t.fromA && t.mergeA && t.aMergeTask.opcode === GrantData def isMergeGrant(t: TaskBundle): Bool = t.fromA && t.mergeA && t.aMergeTask.opcode === Grant + def isAccessAckData(t: TaskBundle): Bool = t.fromA && t.opcode === AccessAckData // ==================== Hint Generation ==================== // Hint for "MSHRTask and ReleaseAck" will fire@s1 val mshr_GrantData_s1 = task_s1.valid && mshrReq_s1 && (isGrantData(task_s1.bits) || isMergeGrantData(task_s1.bits)) val mshr_Grant_s1 = task_s1.valid && mshrReq_s1 && (isGrant(task_s1.bits) || isMergeGrant(task_s1.bits)) val chn_Release_s1 = task_s1.valid && !mshrReq_s1 && isRelease(task_s1.bits) + val chn_AccessAckData_s1 = task_s1.valid && mshrReq_s1 && isAccessAckData(task_s1.bits) - val enqValid_s1 = mshr_GrantData_s1 || mshr_Grant_s1 || chn_Release_s1 + val enqValid_s1 = mshr_GrantData_s1 || mshr_Grant_s1 || chn_Release_s1 || chn_AccessAckData_s1 val enqSource_s1 = Mux(task_s1.bits.mergeA, task_s1.bits.aMergeTask.sourceId, task_s1.bits.sourceId) val enqKeyWord_s1 = Mux(task_s1.bits.mergeA, task_s1.bits.aMergeTask.isKeyword.getOrElse(false.B), @@ -77,20 +79,23 @@ class CustomL1Hint(implicit p: Parameters) extends L2Module { Seq( mshr_Grant_s1 -> Grant, mshr_GrantData_s1 -> GrantData, - chn_Release_s1 -> ReleaseAck + chn_Release_s1 -> ReleaseAck, + chn_AccessAckData_s1 -> AccessAckData ) ) // Hint for "chnTask Hit" will fire@s3 val chn_Grant_s3 = task_s3.valid && !mshrReq_s3 && !need_mshr_s3 && isGrant(task_s3.bits) val chn_GrantData_s3 = task_s3.valid && !mshrReq_s3 && !need_mshr_s3 && isGrantData(task_s3.bits) - val enqValid_s3 = chn_Grant_s3 || chn_GrantData_s3 + val chn_AccessAckData_s3 = task_s3.valid && !mshrReq_s3 && !need_mshr_s3 && isAccessAckData(task_s3.bits) + val enqValid_s3 = chn_Grant_s3 || chn_GrantData_s3 || chn_AccessAckData_s3 val enqSource_s3 = task_s3.bits.sourceId val enqKeyWord_s3 = task_s3.bits.isKeyword.getOrElse(false.B) val enqOpcode_s3 = ParallelPriorityMux( Seq( chn_Grant_s3 -> Grant, - chn_GrantData_s3 -> GrantData + chn_GrantData_s3 -> GrantData, + chn_AccessAckData_s3 -> AccessAckData ) ) @@ -110,13 +115,17 @@ class CustomL1Hint(implicit p: Parameters) extends L2Module { assert(hint_s1Queue.io.enq.ready, "hint_s1Queue should never be full") assert(hintQueue.io.enq.ready, "hintQueue should never be full") + // For AccessAckData that would never go to LSU, insert a dequing bubble for channel delay accuracy + val lastDeque_AccessAckData = RegNext(hintQueue.io.deq.fire && hintQueue.io.deq.bits.opcode === AccessAckData) + val lastDequeBubble = lastDeque_AccessAckData + hintQueue.io.enq.valid := enqValid_s3 || hint_s1Queue.io.deq.valid hintQueue.io.enq.bits.opcode := Mux(enqValid_s3, enqOpcode_s3, hint_s1Queue.io.deq.bits.opcode) hintQueue.io.enq.bits.source := Mux(enqValid_s3, enqSource_s3, hint_s1Queue.io.deq.bits.source) hintQueue.io.enq.bits.isKeyword := Mux(enqValid_s3, enqKeyWord_s3, hint_s1Queue.io.deq.bits.isKeyword) - hintQueue.io.deq.ready := io.l1Hint.ready + hintQueue.io.deq.ready := !lastDequeBubble && io.l1Hint.ready - io.l1Hint.valid := hintQueue.io.deq.valid && hintQueue.io.deq.bits.opcode === GrantData + io.l1Hint.valid := !lastDequeBubble && hintQueue.io.deq.valid && hintQueue.io.deq.bits.opcode === GrantData io.l1Hint.bits.sourceId := hintQueue.io.deq.bits.source io.l1Hint.bits.isKeyword := hintQueue.io.deq.bits.isKeyword } \ No newline at end of file From fb377d04791862fab0d854a8fc6bc5abbf730e21 Mon Sep 17 00:00:00 2001 From: Kumonda221 Date: Thu, 27 Nov 2025 16:11:49 +0800 Subject: [PATCH 2/4] fix(CustomL1Hint): signal naming of AccessAckData from MSHR --- src/main/scala/coupledL2/CustomL1Hint.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/coupledL2/CustomL1Hint.scala b/src/main/scala/coupledL2/CustomL1Hint.scala index 4000b9ca6..bf9a47eba 100644 --- a/src/main/scala/coupledL2/CustomL1Hint.scala +++ b/src/main/scala/coupledL2/CustomL1Hint.scala @@ -66,10 +66,10 @@ class CustomL1Hint(implicit p: Parameters) extends L2Module { // Hint for "MSHRTask and ReleaseAck" will fire@s1 val mshr_GrantData_s1 = task_s1.valid && mshrReq_s1 && (isGrantData(task_s1.bits) || isMergeGrantData(task_s1.bits)) val mshr_Grant_s1 = task_s1.valid && mshrReq_s1 && (isGrant(task_s1.bits) || isMergeGrant(task_s1.bits)) + val mshr_AccessAckData_s1 = task_s1.valid && mshrReq_s1 && isAccessAckData(task_s1.bits) val chn_Release_s1 = task_s1.valid && !mshrReq_s1 && isRelease(task_s1.bits) - val chn_AccessAckData_s1 = task_s1.valid && mshrReq_s1 && isAccessAckData(task_s1.bits) - val enqValid_s1 = mshr_GrantData_s1 || mshr_Grant_s1 || chn_Release_s1 || chn_AccessAckData_s1 + val enqValid_s1 = mshr_GrantData_s1 || mshr_Grant_s1 || mshr_AccessAckData_s1 || chn_Release_s1 val enqSource_s1 = Mux(task_s1.bits.mergeA, task_s1.bits.aMergeTask.sourceId, task_s1.bits.sourceId) val enqKeyWord_s1 = Mux(task_s1.bits.mergeA, task_s1.bits.aMergeTask.isKeyword.getOrElse(false.B), @@ -80,7 +80,7 @@ class CustomL1Hint(implicit p: Parameters) extends L2Module { mshr_Grant_s1 -> Grant, mshr_GrantData_s1 -> GrantData, chn_Release_s1 -> ReleaseAck, - chn_AccessAckData_s1 -> AccessAckData + mshr_AccessAckData_s1 -> AccessAckData ) ) From 81c805d1d2f22018e080447fdc5a4be0df513cce Mon Sep 17 00:00:00 2001 From: Kumonda221 Date: Thu, 27 Nov 2025 17:35:37 +0800 Subject: [PATCH 3/4] feat(TestTop): export L2ToL1Hint for CHI TestTop --- src/test/scala/chi/TestTop.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/scala/chi/TestTop.scala b/src/test/scala/chi/TestTop.scala index 3aefb1ed8..7e53f8a34 100644 --- a/src/test/scala/chi/TestTop.scala +++ b/src/test/scala/chi/TestTop.scala @@ -166,6 +166,7 @@ class TestTop_CHIL2(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, ext val io = IO(Vec(numCores, new Bundle() { val chi = new PortIO val nodeId = Input(UInt(NODEID_WIDTH.W)) + val l2Hint = Valid(new L2ToL1Hint) })) l2_nodes.zipWithIndex.foreach { case (l2, i) => @@ -189,6 +190,8 @@ class TestTop_CHIL2(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, ext l2.module.io_chi <> io(i).chi + l2.module.io.l2_hint <> io(i).l2Hint + dontTouch(l2.module.io) l2.module.io.hartId := i.U From 80d2c728500f5c25075080bfa6edf98374918091 Mon Sep 17 00:00:00 2001 From: Kumonda221 Date: Fri, 28 Nov 2025 12:13:31 +0800 Subject: [PATCH 4/4] chore(TestTop): naming of l1 signal port --- src/test/scala/chi/TestTop.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/scala/chi/TestTop.scala b/src/test/scala/chi/TestTop.scala index 7e53f8a34..53e4aaf73 100644 --- a/src/test/scala/chi/TestTop.scala +++ b/src/test/scala/chi/TestTop.scala @@ -166,6 +166,9 @@ class TestTop_CHIL2(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, ext val io = IO(Vec(numCores, new Bundle() { val chi = new PortIO val nodeId = Input(UInt(NODEID_WIDTH.W)) + })) + + val io_l1 = IO(Vec(numCores, new Bundle() { val l2Hint = Valid(new L2ToL1Hint) })) @@ -190,7 +193,7 @@ class TestTop_CHIL2(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, ext l2.module.io_chi <> io(i).chi - l2.module.io.l2_hint <> io(i).l2Hint + l2.module.io.l2_hint <> io_l1(i).l2Hint dontTouch(l2.module.io)