From ac7074318e4354b940b4849c7251abf921138e4c Mon Sep 17 00:00:00 2001 From: XiChen Date: Tue, 24 Sep 2024 21:04:23 +0800 Subject: [PATCH] misc: an official version of MCP2 hold check --- src/main/scala/coupledL2/CoupledL2.scala | 1 + src/main/scala/coupledL2/Directory.scala | 7 +++++++ src/main/scala/coupledL2/L2Param.scala | 2 ++ src/main/scala/coupledL2/MSHRBuffer.scala | 10 +++++----- src/main/scala/coupledL2/SinkC.scala | 14 +++++++------- src/main/scala/coupledL2/tl2chi/MainPipe.scala | 14 -------------- src/main/scala/coupledL2/tl2chi/Slice.scala | 12 ++++++++++++ src/main/scala/coupledL2/tl2tl/MainPipe.scala | 14 -------------- src/main/scala/coupledL2/tl2tl/Slice.scala | 11 +++++++++++ src/main/scala/coupledL2/utils/HoldChecker.scala | 6 ++++++ 10 files changed, 51 insertions(+), 40 deletions(-) diff --git a/src/main/scala/coupledL2/CoupledL2.scala b/src/main/scala/coupledL2/CoupledL2.scala index 2bac7874..69d34c33 100644 --- a/src/main/scala/coupledL2/CoupledL2.scala +++ b/src/main/scala/coupledL2/CoupledL2.scala @@ -79,6 +79,7 @@ trait HasCoupledL2Parameters { def hasPrefetchSrc = prefetchers.exists(_.hasPrefetchSrc) def hasCMO = cacheParams.hasCMO def topDownOpt = if(cacheParams.elaboratedTopDown) Some(true) else None + def hasMPC2Check = cacheParams.MPC2Check def enableHintGuidedGrant = true diff --git a/src/main/scala/coupledL2/Directory.scala b/src/main/scala/coupledL2/Directory.scala index 377896ec..575d22ec 100644 --- a/src/main/scala/coupledL2/Directory.scala +++ b/src/main/scala/coupledL2/Directory.scala @@ -113,6 +113,7 @@ class Directory(implicit p: Parameters) extends L2Module { val replResp = ValidIO(new ReplacerResult) // used to count occWays for Grant to retry val msInfo = Vec(mshrsAll, Flipped(ValidIO(new MSHRInfo))) + val mcp2Check = if(hasMPC2Check) Some(Input(new MCP2CheckEn)) else None }) def invalid_way_sel(metaVec: Seq[MetaEntry], repl: UInt) = { @@ -373,4 +374,10 @@ class Directory(implicit p: Parameters) extends L2Module { XSPerfAccumulate("dirRead_cnt", io.read.fire) XSPerfAccumulate("choose_busy_way", reqValid_s3 && !req_s3.wayMask(chosenWay)) + + // ===== for MCP2 hold check ===== + if (hasMPC2Check) { + HoldChecker.check2(io.resp.bits, io.mcp2Check.get.en, "dirResp_s3") + HoldChecker.check2(io.replResp.bits, io.mcp2Check.get.en, "replResp_s3") + } } diff --git a/src/main/scala/coupledL2/L2Param.scala b/src/main/scala/coupledL2/L2Param.scala index 13f972eb..9cf79169 100644 --- a/src/main/scala/coupledL2/L2Param.scala +++ b/src/main/scala/coupledL2/L2Param.scala @@ -106,6 +106,8 @@ case class L2Param( FPGAPlatform: Boolean = false, // CMO hasCMO: Boolean = false, + // has DataStorage MCP2 Check + MPC2Check: Boolean = true, // Network layer SAM sam: Seq[(AddressSet, Int)] = Seq(AddressSet.everything -> 0) diff --git a/src/main/scala/coupledL2/MSHRBuffer.scala b/src/main/scala/coupledL2/MSHRBuffer.scala index 21c78465..fe3fc9cd 100644 --- a/src/main/scala/coupledL2/MSHRBuffer.scala +++ b/src/main/scala/coupledL2/MSHRBuffer.scala @@ -21,7 +21,6 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import coupledL2.utils._ -import chisel3.util.experimental.BoringUtils class MSHRBufRead(implicit p: Parameters) extends L2Bundle { val id = Output(UInt(mshrBits.W)) @@ -43,6 +42,7 @@ class MSHRBuffer(wPorts: Int = 1)(implicit p: Parameters) extends L2Module { val r = Flipped(ValidIO(new MSHRBufRead)) val resp = new MSHRBufResp val w = Vec(wPorts, Flipped(ValidIO(new MSHRBufWrite))) + val mcp2Check = if(hasMPC2Check) Some(Input(new MCP2CheckEn)) else None }) val buffer = Reg(Vec(mshrsAll, Vec(beatSize, UInt((beatBytes * 8).W)))) @@ -65,10 +65,10 @@ class MSHRBuffer(wPorts: Int = 1)(implicit p: Parameters) extends L2Module { val rdata = buffer(io.r.bits.id).asUInt io.resp.data.data := RegEnable(rdata, 0.U.asTypeOf(rdata), io.r.valid) - val ds_wen = WireInit(false.B) - BoringUtils.addSink(ds_wen, "ds_wen") - assert(!io.r.valid || !RegNext(io.r.valid), "No continuous read") - HoldChecker.check2(io.resp.data.data, ds_wen, "mshrBuf_r") + if (hasMPC2Check) { + assert(!io.r.valid || !RegNext(io.r.valid), "No continuous read") + HoldChecker.check2(io.resp.data.data, io.mcp2Check.get.wen, "mshrBuf_wdata") + } } // may consider just choose an empty entry to insert diff --git a/src/main/scala/coupledL2/SinkC.scala b/src/main/scala/coupledL2/SinkC.scala index 11aca9be..d501aef9 100644 --- a/src/main/scala/coupledL2/SinkC.scala +++ b/src/main/scala/coupledL2/SinkC.scala @@ -23,8 +23,7 @@ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ import org.chipsalliance.cde.config.Parameters import utility.{MemReqSource, XSPerfAccumulate, RRArbiterInit} -import chisel3.util.experimental.BoringUtils -import coupledL2.utils.HoldChecker +import coupledL2.utils._ class PipeBufferResp(implicit p: Parameters) extends L2Bundle { val data = Vec(beatSize, UInt((beatBytes * 8).W)) @@ -43,6 +42,7 @@ class SinkC(implicit p: Parameters) extends L2Module { val bufResp = Output(new PipeBufferResp) val refillBufWrite = ValidIO(new MSHRBufWrite) val msInfo = Vec(mshrsAll, Flipped(ValidIO(new MSHRInfo))) + val mcp2Check = if(hasMPC2Check) Some(Input(new MCP2CheckEn)) else None }) val (first, last, _, beat) = edgeIn.count(io.c) @@ -187,11 +187,6 @@ class SinkC(implicit p: Parameters) extends L2Module { when(RegNext(io.task.fire)) { beatValids(RegNext(io.task.bits.bufIdx)).foreach(_ := false.B) } - // ===== for MCP2 hold check ===== - val ds_wen = WireInit(false.B) - BoringUtils.addSink(ds_wen, "ds_wen") - assert(!io.task.fire || !RegNext(io.task.fire), "No continuous write @SinkC") - HoldChecker.check2(io.bufResp.data.asUInt, ds_wen, "sinkC_") // Performance counters val stall = io.c.valid && isRelease && !io.c.ready @@ -203,4 +198,9 @@ class SinkC(implicit p: Parameters) extends L2Module { XSPerfAccumulate("NewDataNestC", io.refillBufWrite.valid) //!!WARNING: TODO: if this is zero, that means fucntion [Release-new-data written into refillBuf] // is never tested, and may have flaws + // ===== for MCP2 hold check ===== + if (hasMPC2Check) { + assert(!io.task.fire || !RegNext(io.task.fire), "No continuous write @SinkC") + HoldChecker.check2(io.bufResp.data.asUInt, io.mcp2Check.get.wen, "sinkC_wdata") + } } diff --git a/src/main/scala/coupledL2/tl2chi/MainPipe.scala b/src/main/scala/coupledL2/tl2chi/MainPipe.scala index 8a4c048b..45968a84 100644 --- a/src/main/scala/coupledL2/tl2chi/MainPipe.scala +++ b/src/main/scala/coupledL2/tl2chi/MainPipe.scala @@ -29,7 +29,6 @@ import coupledL2.utils.HoldChecker import coupledL2.prefetch.{PrefetchTrain, PfSource} import coupledL2.tl2chi.CHICohStates._ import coupledL2.MetaData._ -import chisel3.util.experimental.BoringUtils class MainPipe(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes { val io = IO(new Bundle() { @@ -416,19 +415,6 @@ class MainPipe(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes ) ) - // ===== for MCP2 hold check ===== - val en = io.toDS.en_s3 - val w_en = io.toDS.en_s3 && io.toDS.req_s3.bits.wen - HoldChecker.check2(task_s3.bits, en, "task_s3.bits") - HoldChecker.check2(dirResult_s3, en, "dirResult_s3") - HoldChecker.check2(io.replResp.bits, en, "replResp_s3") - - HoldChecker.check2(io.bufResp.data.asUInt, w_en, "sinkC_data_s3") - HoldChecker.check2(io.refillBufResp_s3.bits, w_en, "refillBufResp_data_s3") - HoldChecker.check2(io.releaseBufResp_s3.bits, w_en, "releaseBufResp_data_s3") - - BoringUtils.addSource(w_en, "ds_wen") - /* ======== Read DS and store data in Buffer ======== */ // A: need_write_releaseBuf indicates that DS should be read and the data will be written into ReleaseBuffer // need_write_releaseBuf is assigned true when: diff --git a/src/main/scala/coupledL2/tl2chi/Slice.scala b/src/main/scala/coupledL2/tl2chi/Slice.scala index 7e4c1954..216532be 100644 --- a/src/main/scala/coupledL2/tl2chi/Slice.scala +++ b/src/main/scala/coupledL2/tl2chi/Slice.scala @@ -22,6 +22,7 @@ import chisel3.util._ import freechips.rocketchip.tilelink._ import org.chipsalliance.cde.config.Parameters import coupledL2._ +import coupledL2.utils._ import coupledL2.prefetch.PrefetchIO class OuterBundle(implicit p: Parameters) extends DecoupledPortIO with BaseOuterBundle @@ -209,4 +210,15 @@ class Slice()(implicit p: Parameters) extends BaseSlice[OuterBundle] rxrsp.io.out <> io.out.rx.rsp io_pCrd <> mshrCtl.io.pCrd + + if (hasMPC2Check) { + val dsEnable = WireInit(0.U.asTypeOf(new MCP2CheckEn)) + dsEnable.en := dataStorage.io.en + dsEnable.wen := dataStorage.io.en && dataStorage.io.req.bits.wen + + directory.io.mcp2Check.get := dsEnable + releaseBuf.io.mcp2Check.get := dsEnable + refillBuf.io.mcp2Check.get := dsEnable + sinkC.io.mcp2Check.get := dsEnable + } } diff --git a/src/main/scala/coupledL2/tl2tl/MainPipe.scala b/src/main/scala/coupledL2/tl2tl/MainPipe.scala index 8fba75c6..35ba0e16 100644 --- a/src/main/scala/coupledL2/tl2tl/MainPipe.scala +++ b/src/main/scala/coupledL2/tl2tl/MainPipe.scala @@ -19,7 +19,6 @@ package coupledL2.tl2tl import chisel3._ import chisel3.util._ -import chisel3.util.experimental.BoringUtils import utility._ import coupledL2.MetaData._ import org.chipsalliance.cde.config.Parameters @@ -315,19 +314,6 @@ class MainPipe(implicit p: Parameters) extends L2Module { ) ) - // ===== for MCP2 hold check ===== - val en = io.toDS.en_s3 - val w_en = io.toDS.en_s3 && io.toDS.req_s3.bits.wen - HoldChecker.check2(task_s3.bits, en, "task_s3.bits") - HoldChecker.check2(dirResult_s3, en, "dirResult_s3") - HoldChecker.check2(io.replResp.bits, en, "replResp_s3") - - HoldChecker.check2(io.bufResp.data.asUInt, w_en, "sinkC_data_s3") - HoldChecker.check2(io.refillBufResp_s3.bits, w_en, "refillBufResp_data_s3") - HoldChecker.check2(io.releaseBufResp_s3.bits, w_en, "releaseBufResp_data_s3") - - BoringUtils.addSource(w_en, "ds_wen") - /* ======== Read DS and store data in Buffer ======== */ // A: need_write_releaseBuf indicates that DS should be read and the data will be written into ReleaseBuffer // need_write_releaseBuf is assigned true when: diff --git a/src/main/scala/coupledL2/tl2tl/Slice.scala b/src/main/scala/coupledL2/tl2tl/Slice.scala index edaad502..301f61ff 100644 --- a/src/main/scala/coupledL2/tl2tl/Slice.scala +++ b/src/main/scala/coupledL2/tl2tl/Slice.scala @@ -205,4 +205,15 @@ class Slice()(implicit p: Parameters) extends BaseSlice[OuterBundle] { val monitor = Module(new Monitor()) monitor.io.fromMainPipe <> mainPipe.io.toMonitor + + if (hasMPC2Check) { + val dsEnable = WireInit(0.U.asTypeOf(new MCP2CheckEn)) + dsEnable.en := dataStorage.io.en + dsEnable.wen := dataStorage.io.en && dataStorage.io.req.bits.wen + + directory.io.mcp2Check.get := dsEnable + releaseBuf.io.mcp2Check.get := dsEnable + refillBuf.io.mcp2Check.get := dsEnable + sinkC.io.mcp2Check.get := dsEnable + } } diff --git a/src/main/scala/coupledL2/utils/HoldChecker.scala b/src/main/scala/coupledL2/utils/HoldChecker.scala index b94e4e45..248185ac 100644 --- a/src/main/scala/coupledL2/utils/HoldChecker.scala +++ b/src/main/scala/coupledL2/utils/HoldChecker.scala @@ -20,6 +20,12 @@ package coupledL2.utils import chisel3._ import chisel3.util._ +// enable signals, only used to check mcp2 hold condition of predecessor regs +class MCP2CheckEn extends Bundle { + val en = Bool() + val wen = Bool() +} + /** * Assert the signal must hold for certain cycles when enable is high */