diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 62a1d1e0..6c2e5960 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,8 +27,6 @@ jobs: fetch-depth: '0' - name: check rocket-chip run: cd rocket-chip && git fetch --all && git merge-base --is-ancestor `git rev-parse HEAD` origin/master - - name: check HuanCun - run: cd HuanCun && git fetch --all && git merge-base --is-ancestor `git rev-parse HEAD` origin/master - name: check utility run: cd utility && git fetch --all && git merge-base --is-ancestor `git rev-parse HEAD` origin/master @@ -87,15 +85,14 @@ jobs: run: tar -zcf ${{ env.VERILATOR_ARCHIVE }} verilator # This workflow contains a single job called "build" - tl-test_L2: + chi-test_L2: # The type of runner that the job will run on runs-on: ubuntu-22.04 # Environments env: - RUN_ARCHIVE: coupledL2-tl-test-new-run-${{ github.sha }} - RUN_ARCHIVE_TL: coupledL2-tl-test-new-run-${{ github.sha }}-tilelink.tar.gz - RUN_ARCHIVE_CHI: coupledL2-tl-test-new-run-${{ github.sha }}-chi.tar.gz + RUN_ARCHIVE: xscache-chi-test-run-${{ github.sha }} + RUN_ARCHIVE_CHI: xscache-chi-test-run-${{ github.sha }}.tar.gz VERILATOR_ARCHIVE: verilator-ubuntu-22.04-clang-17.tar.gz # Steps represent a sequence of tasks that will be executed as part of the job @@ -187,24 +184,6 @@ jobs: test -d ./tl-test-new/run || mkdir -p ./tl-test-new/run tar -zcf ${{ env.RUN_ARCHIVE_CHI }} ./tl-test-new/run - # Clean artifacts folder (./tl-test-new/run) after successful run - - name: Unit Test for TileLink version - run: | - rm -rf tl-test-new - git clone https://github.com/OpenXiangShan/tl-test-new - cd ./tl-test-new - git checkout ${{ env.TL_TEST_NEW_COMMIT }} - sed -i 's/ari.target.*/ari.target = 240/g' ./configs/user.tltest.ini - rm -rf ./dut/XSCache && ln -s ../.. ./dut/XSCache - make coupledL2-test-l2l3l2 run THREADS_BUILD=4 CXX_COMPILER=clang++-17 - rm -rf run/*.vcd run/*.fst run/*.log run/*.db - - - name: Tar up artifacts of Unit Test for TileLink version - if: always() - run: | - test -d ./tl-test-new/run || mkdir -p ./tl-test-new/run - tar -zcf ${{ env.RUN_ARCHIVE_TL }} ./tl-test-new/run - - name: Upload artifacts of Unit Test if: always() uses: actions/upload-artifact@v4 diff --git a/.gitmodules b/.gitmodules index c3db17f7..38cebebe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "utility"] path = utility url = https://github.com/OpenXiangShan/utility -[submodule "HuanCun"] - path = HuanCun - url = https://github.com/OpenXiangShan/HuanCun.git [submodule "OpenNCB"] path = OpenNCB url = https://github.com/OpenXiangShan/OpenNCB.git diff --git a/HuanCun b/HuanCun deleted file mode 160000 index 65ef0773..00000000 --- a/HuanCun +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 65ef077373ecf398b4cecdea06b65ef9b8d79044 diff --git a/Makefile b/Makefile index 4bf8e69b..03062cf6 100644 --- a/Makefile +++ b/Makefile @@ -34,27 +34,12 @@ MEM_GEN = ./scripts/vlsi_mem_gen MEM_GEN_SEP = ./scripts/gen_sep_mem.sh gen-test-top: - mill -i XSCache.test.runMain coupledL2.$(TOP)_$(SYSTEM) -td $(BUILD_DIR_L2) --target systemverilog --split-verilog - $(MEM_GEN_SEP) "$(MEM_GEN)" "$(TOP_V_L2).conf" "$(BUILD_DIR_L2)" + mill -i XSCache.test.runMain xscache.coupledL2.$(TOP)_$(SYSTEM) -td $(BUILD_DIR_L2) --target systemverilog --split-verilog + if [ -f "$(TOP_V_L2).conf" ]; then $(MEM_GEN_SEP) "$(MEM_GEN)" "$(TOP_V_L2).conf" "$(BUILD_DIR_L2)"; fi gen-test-top-chi: - mill -i XSCache.test.runMain coupledL2.$(TOP)_$(SYSTEM) -td $(BUILD_DIR_L2) $(CHI_TOP_ARGS) --target systemverilog --split-verilog - $(MEM_GEN_SEP) "$(MEM_GEN)" "$(TOP_V_L2).conf" "$(BUILD_DIR_L2)" - -test-top-l2: - $(MAKE) gen-test-top SYSTEM=L2 - -test-top-l2standalone: - $(MAKE) gen-test-top SYSTEM=L2_Standalone - -test-top-l2l3-huancun: - $(MAKE) gen-test-top SYSTEM=L2L3 - -test-top-l2l3l2-huancun: - $(MAKE) gen-test-top SYSTEM=L2L3L2 - -test-top-fullsys-huancun: - $(MAKE) gen-test-top SYSTEM=fullSys + mill -i XSCache.test.runMain xscache.coupledL2.$(TOP)_$(SYSTEM) -td $(BUILD_DIR_L2) $(CHI_TOP_ARGS) --target systemverilog --split-verilog + if [ -f "$(TOP_V_L2).conf" ]; then $(MEM_GEN_SEP) "$(MEM_GEN)" "$(TOP_V_L2).conf" "$(BUILD_DIR_L2)"; fi test-top-chi: $(MAKE) gen-test-top-chi SYSTEM=CHIL2 $(CHI_PASS_ARGS) @@ -72,13 +57,13 @@ test-top-chi-quadcore-2ul: $(MAKE) gen-test-top-chi SYSTEM=CHIL2 $(CHI_PASS_ARGS) NUM_CORE=4 NUM_TL_UL=2 test-top-l3-openllc: - mill -i XSCache.test.runMain openLLC.TestTop_L3 -td build --target systemverilog --split-verilog + mill -i XSCache.test.runMain xscache.openLLC.TestTop_L3 -td build --target systemverilog --split-verilog test-top-l2l3-openllc: - mill -i XSCache.test.runMain openLLC.TestTopSoC_SingleCore -td $(BUILD_DIR_LLC) --target systemverilog --split-verilog + mill -i XSCache.test.runMain xscache.openLLC.TestTopSoC_SingleCore -td $(BUILD_DIR_LLC) --target systemverilog --split-verilog test-top-l2l3l2-openllc: - mill -i XSCache.test.runMain openLLC.TestTopSoC_DualCore -td $(BUILD_DIR_LLC) --target systemverilog --split-verilog + mill -i XSCache.test.runMain xscache.openLLC.TestTopSoC_DualCore -td $(BUILD_DIR_LLC) --target systemverilog --split-verilog clean: rm -rf ./build @@ -95,4 +80,4 @@ reformat: checkformat: mill -i __.checkFormat -.PHONY: init bsp checkformat clean compile-coupledl2 compile-openllc idea reformat \ No newline at end of file +.PHONY: init bsp checkformat clean compile-coupledl2 compile-openllc idea reformat diff --git a/README.md b/README.md index a4d52be3..eb2dadb1 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,18 @@ -# CoupledL2 +# XSCache -![Build Status](https://github.com/RISCVERS/HuanCun/actions/workflows/main.yml/badge.svg) +CHI-only cache subsystem built from `CoupledL2 (tl2chi)` and `OpenLLC`. ## Compile source code -``` +``` make init make compile ``` +## Generate CHI test tops + +``` +make test-top-chi +make test-top-l2l3-openllc +make test-top-l2l3l2-openllc +``` diff --git a/build.sc b/build.sc index bdb0be74..9b4b4128 100644 --- a/build.sc +++ b/build.sc @@ -81,13 +81,6 @@ object utility extends HasChisel { ) } -object huancun extends HasChisel { - override def millSourcePath = pwd / "HuanCun" - override def moduleDeps = super.moduleDeps ++ Seq( - rocketchip, utility - ) -} - object openNCB extends HasChisel { override def millSourcePath = pwd / "OpenNCB" override def moduleDeps = super.moduleDeps ++ Seq(rocketchip) @@ -101,12 +94,10 @@ object XSCache extends HasChisel with $file.common.XSCacheModule { def utilityModule: ScalaModule = utility - def huancunModule: ScalaModule = huancun - def openNCBModule: ScalaModule = openNCB object test extends SbtTests with TestModule.ScalaTest override def scalacOptions = super.scalacOptions() ++ Agg("-deprecation", "-feature") -} \ No newline at end of file +} diff --git a/common.sc b/common.sc index d7ab5606..8cca8930 100644 --- a/common.sc +++ b/common.sc @@ -7,9 +7,7 @@ trait XSCacheModule extends ScalaModule { def utilityModule: ScalaModule - def huancunModule: ScalaModule - def openNCBModule: ScalaModule - override def moduleDeps = super.moduleDeps ++ Seq(rocketModule, utilityModule, huancunModule, openNCBModule) -} \ No newline at end of file + override def moduleDeps = super.moduleDeps ++ Seq(rocketModule, utilityModule, openNCBModule) +} diff --git a/src/main/scala/coupledL2/BaseSlice.scala b/src/main/scala/coupledL2/BaseSlice.scala index 456b1fc2..b28a3924 100644 --- a/src/main/scala/coupledL2/BaseSlice.scala +++ b/src/main/scala/coupledL2/BaseSlice.scala @@ -15,14 +15,14 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink.TLBundle import utility._ -import coupledL2.prefetch._ +import xscache.coupledL2.prefetch._ trait BaseOuterBundle diff --git a/src/main/scala/coupledL2/tl2chi/Bundle.scala b/src/main/scala/coupledL2/Bundle.scala similarity index 84% rename from src/main/scala/coupledL2/tl2chi/Bundle.scala rename to src/main/scala/coupledL2/Bundle.scala index 74547f4c..6098c566 100644 --- a/src/main/scala/coupledL2/tl2chi/Bundle.scala +++ b/src/main/scala/coupledL2/Bundle.scala @@ -15,20 +15,15 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink.TLPermissions._ import utility.MemReqSource -import coupledL2.{HasTLChannelBits, DirResult, PipeStatus} - -object CHIChannel { - def TXREQ = "b001".U - def TXRSP = "b010".U - def TXDAT = "b100".U -} +import xscache.coupledL2.{HasTLChannelBits, DirResult, PipeStatus} +import xscache.chi.HasCHIOpcodes trait HasCHIChannelBits { this: Bundle => val txChannel = UInt(3.W) @@ -42,10 +37,10 @@ class PipeStatusWithCHI(implicit p: Parameters) extends PipeStatus val mshrTask = Bool() } -class PCrdQueryBundle(implicit p: Parameters) extends TL2CHIL2Bundle with HasCHIOpcodes { +class PCrdQueryBundle(implicit p: Parameters) extends CoupledL2Bundle with HasCHIOpcodes { val query = Output(ValidIO(new Bundle() { val pCrdType = UInt(PCRDTYPE_WIDTH.W) val srcID = UInt(SRCID_WIDTH.W) })) val grant = Input(Bool()) -} \ No newline at end of file +} diff --git a/src/main/scala/coupledL2/Common.scala b/src/main/scala/coupledL2/Common.scala index 74bef0cb..660e4726 100644 --- a/src/main/scala/coupledL2/Common.scala +++ b/src/main/scala/coupledL2/Common.scala @@ -15,14 +15,14 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink.TLPermissions._ import utility.MemReqSource -import tl2chi.{HasCHIMsgParameters, HasCHIChannelBits, CHIREQ, MemAttr, OrderEncodings, MPAM} +import xscache.chi.{CHIREQ, HasCHIMsgParameters, MemAttr, MPAM, OrderEncodings} abstract class L2Module(implicit val p: Parameters) extends Module with HasCoupledL2Parameters abstract class L2Bundle(implicit val p: Parameters) extends Bundle with HasCoupledL2Parameters @@ -91,7 +91,6 @@ class TaskBundle(implicit p: Parameters) extends L2Bundle // If true, MSHR should send an ack to L2 prefetcher. val needHint = prefetchOpt.map(_ => Bool()) - // For DirtyKey in Release val dirty = Bool() // if this is an mshr task and it needs to write dir diff --git a/src/main/scala/coupledL2/Consts.scala b/src/main/scala/coupledL2/Consts.scala index d4cbce9f..5764eb97 100644 --- a/src/main/scala/coupledL2/Consts.scala +++ b/src/main/scala/coupledL2/Consts.scala @@ -17,7 +17,7 @@ // See LICENSE.SiFive for license details. -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/CoupledL2.scala b/src/main/scala/coupledL2/CoupledL2.scala index cad47c93..c85a767a 100644 --- a/src/main/scala/coupledL2/CoupledL2.scala +++ b/src/main/scala/coupledL2/CoupledL2.scala @@ -17,7 +17,7 @@ // See LICENSE.SiFive for license details. -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ @@ -30,16 +30,17 @@ import freechips.rocketchip.util._ import org.chipsalliance.cde.config.{Field, Parameters} import scala.math.max -import coupledL2.prefetch._ -import huancun.{BankBitsKey, TPmetaReq, TPmetaResp} +import xscache.coupledL2.prefetch._ +import xscache.coupledL2.prefetch.{TPmetaReq, TPmetaResp} import utility.mbist.{MbistInterface, MbistPipeline} import utility.sram.{SramBroadcastBundle, SramHelper} import freechips.rocketchip.tilelink.TLArbiter +import xscache.coupledL2.utils._ +import xscache.common.BankBitsKey +import xscache.chi._ trait HasCoupledL2Parameters { val p: Parameters - // val tl2tlParams: HasTLL2Parameters = p(L2ParamKey) - def enableCHI = p(EnableCHI) def enableClockGate = p(EnableL2ClockGate) def cacheParams = p(L2ParamKey) def PrivateClintRange = cacheParams.PrivateClintRange @@ -56,7 +57,6 @@ trait HasCoupledL2Parameters { def offsetBits = log2Ceil(blockBytes) def beatBits = offsetBits - log2Ceil(beatBytes) def stateBits = MetaData.stateBits - def chiOpt = if (enableCHI) Some(true) else None def aliasBitsOpt = if(cacheParams.clientCaches.isEmpty) None else cacheParams.clientCaches.head.aliasBitsOpt // vaddr without offset bits @@ -111,6 +111,7 @@ trait HasCoupledL2Parameters { def hasNLPrefetcher = prefetchers.exists(_.isInstanceOf[NLParameters]) def hasPrefetchBit = prefetchers.exists(_.hasPrefetchBit) // !! TODO.test this def hasPrefetchSrc = prefetchers.exists(_.hasPrefetchSrc) + def chiOpt = Some(true) def topDownOpt = if(cacheParams.elaboratedTopDown) Some(true) else None def enableHintGuidedGrant = true @@ -260,7 +261,15 @@ trait HasCoupledL2Parameters { } } -abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with HasCoupledL2Parameters { +abstract class CoupledL2Bundle(implicit val p: Parameters) extends Bundle + with HasCoupledL2Parameters + with HasCHIMsgParameters + +abstract class CoupledL2Module(implicit val p: Parameters) extends Module + with HasCoupledL2Parameters + with HasCHIMsgParameters + +class CoupledL2(implicit p: Parameters) extends LazyModule with HasCoupledL2Parameters { val xfer = TransferSizes(blockBytes, blockBytes) val atom = TransferSizes(1, cacheParams.channelBytes.d.get) @@ -269,6 +278,32 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has val pf_recv_node: Option[BundleBridgeSink[PrefetchRecv]] = if(hasReceiver) Some(BundleBridgeSink(Some(() => new PrefetchRecv))) else None + val addressRange = Seq(AddressSet(0x00000000L, 0xffffffffffffL)) // TODO: parameterize this + val managerParameters = TLSlavePortParameters.v1( + managers = Seq(TLSlaveParameters.v1( + address = addressRange, + regionType = RegionType.CACHED, + supportsAcquireT = xfer, + supportsAcquireB = xfer, + supportsArithmetic = atom, + supportsLogical = atom, + supportsGet = access, + supportsPutFull = access, + supportsPutPartial = access, + supportsHint = access, + fifoId = None + )), + beatBytes = 32, + minLatency = 2, + responseFields = cacheParams.respField, + requestKeys = cacheParams.reqKey, + endSinkId = idsAll * (1 << bankBits) + ) + val managerNode = TLManagerNode(Seq(managerParameters)) + + val mmioBridge = LazyModule(new MMIOBridge) + val mmioNode = mmioBridge.mmioNode + val managerPortParams = (m: TLSlavePortParameters) => TLSlavePortParameters.v1( m.managers.map { m => m.v2copy( @@ -318,7 +353,7 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has val tpmeta_source_node = if(hasTPPrefetcher) Some(BundleBridgeSource(() => DecoupledIO(new TPmetaReq(hartIdLen, node.in.head._2.bundle.addressBits, offsetBits)))) else None val tpmeta_sink_node = if(hasTPPrefetcher) Some(BundleBridgeSink(Some(() => ValidIO(new TPmetaResp(hartIdLen, node.in.head._2.bundle.addressBits, offsetBits))))) else None - abstract class BaseCoupledL2Imp(wrapper: LazyModule) extends LazyModuleImp(wrapper) with HasPerfEvents { + class CoupledL2Imp(wrapper: LazyModule) extends LazyModuleImp(wrapper) with HasPerfEvents with HasCHIOpcodes { val banks = node.in.size val bankBits = log2Ceil(banks) val l2TlbParams: Parameters = p.alterPartial { @@ -351,12 +386,15 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has val l2FlushDone = Option.when(cacheParams.enableL2Flush) (Output(Bool())) val dft = Option.when(cacheParams.hasDFT)(Input(new SramBroadcastBundle)) val dft_reset = Option.when(cacheParams.hasMbist)(Input(new DFTResetSignals())) + val chi = new PortIO + val nodeID = Input(UInt()) + val cpu_wfi = Option.when(cacheParams.enableL2Flush)(Input(Bool())) }) // Display info val sizeBytes = cacheParams.toCacheParams.capacity.toDouble val sizeStr = sizeBytesToStr(sizeBytes) - println(s"====== Inclusive TL-${if (enableCHI) "CHI" else "TL"} ${cacheParams.name} ($sizeStr * $banks-bank) ======") + println(s"====== Inclusive CHI ${cacheParams.name} ($sizeStr * $banks-bank) ======") println(s"prefetch: ${cacheParams.prefetch}") println(s"bankBits: ${bankBits}") println(s"replacement: ${cacheParams.replacement}") @@ -365,6 +403,16 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has print_bundle_fields(node.in.head._2.bundle.requestFields, "usr") print_bundle_fields(node.in.head._2.bundle.echoFields, "echo") + require(io.chi.tx.rsp.getWidth == io.chi.rx.rsp.getWidth) + require(io.chi.tx.dat.getWidth == io.chi.rx.dat.getWidth) + + println(s"CHI Issue Version: ${p(CHIIssue)}") + println(s"CHI REQ Flit Width: ${io.chi.tx.req.flit.getWidth}") + println(s"CHI RSP Flit Width: ${io.chi.tx.rsp.flit.getWidth}") + println(s"CHI SNP Flit Width: ${io.chi.rx.snp.flit.getWidth}") + println(s"CHI DAT Flit Width: ${io.chi.rx.dat.flit.getWidth}") + println(s"CHI Port Width: ${io.chi.getWidth}") + println(s"Cacheable:") node.edges.in.headOption.foreach { n => n.client.clients.zipWithIndex.foreach { @@ -374,6 +422,17 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has } } + println(s"MMIO:") + mmioNode.edges.in.headOption.foreach { n => + n.client.clients.zipWithIndex.foreach { + case (c, i) => + println(s"\t${i} <= ${c.name};" + + s"\tsourceRange: ${c.sourceId.start}~${c.sourceId.end}") + } + } + + val mmio = mmioBridge.module + // Connection between prefetcher and the slices val pftParams: Parameters = p.alterPartial { case EdgeInKey => node.in.head._2 @@ -427,6 +486,23 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has val hasData = Bool() }))) + def setSliceID(txnID: UInt, sliceID: UInt, mmioReq: Bool): UInt = { + Mux( + mmioReq, + Cat(1.U(1.W), txnID.tail(1)), + Cat(0.U(1.W), if (banks <= 1) txnID.tail(1) else Cat(sliceID(bankBits - 1, 0), txnID.tail(bankBits + 1))) + ) + } + def getSliceID(txnID: UInt): UInt = if (banks <= 1) 0.U else txnID.tail(1).head(bankBits) + def restoreTXNID(txnID: UInt): UInt = { + val mmioReq = txnID.head(1).asBool + Mux( + mmioReq || (banks <= 1).B, + Cat(0.U(1.W), txnID.tail(1)), + Cat(0.U(1.W), 0.U(bankBits.W), txnID.tail(bankBits + 1)) + ) + } + // if Hint indicates that this slice should fireD, yet no D resp comes out of this slice // then we releaseSourceD, enabling io.d.ready for other slices // TODO: if Hint for single slice is 100% accurate, may consider remove this @@ -441,21 +517,12 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has require(in.params.dataBits == out.params.dataBits) val rst_L2 = reset val slice = withReset(rst_L2) { - if (enableCHI) { - Module(new tl2chi.Slice()(p.alterPartial { - case EdgeInKey => edgeIn - case EdgeOutKey => edgeOut - case BankBitsKey => bankBits - case SliceIdKey => i - })) - } else { - Module(new tl2tl.Slice()(p.alterPartial { - case EdgeInKey => edgeIn - case EdgeOutKey => edgeOut - case BankBitsKey => bankBits - case SliceIdKey => i - })) - } + Module(new Slice()(p.alterPartial { + case EdgeInKey => edgeIn + case EdgeOutKey => edgeOut + case BankBitsKey => bankBits + case SliceIdKey => i + })) } slice.io.in <> in if (enableHintGuidedGrant) { @@ -511,6 +578,130 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has slice } + val txreq_arb = Module(new TwoLevelRRArbiter(new CHIREQ, slices.size + 1)) + ArbPerf(txreq_arb, "txreq_arb") + val txreq = Wire(DecoupledIO(new CHIREQ)) + slices.zip(txreq_arb.io.in.init).foreach { case (s, in) => in <> s.io.out.tx.req } + txreq_arb.io.in.last <> mmio.io.tx.req + txreq <> txreq_arb.io.out + txreq.bits.txnID := setSliceID(txreq_arb.io.out.bits.txnID, txreq_arb.io.chosen, mmio.io.tx.req.fire) + + val txrsp = Wire(DecoupledIO(new CHIRSP)) + fastArb(slices.map(_.io.out.tx.rsp), txrsp, Some("txrsp")) + + val txdat = Wire(DecoupledIO(new CHIDAT)) + fastArb(slices.map(_.io.out.tx.dat) :+ mmio.io.tx.dat, txdat, Some("txdat")) + + val rxsnp = Wire(DecoupledIO(new CHISNP)) + val rxsnpSliceID = if (banks <= 1) 0.U else (rxsnp.bits.addr >> (offsetBits - 3))(bankBits - 1, 0) + slices.zipWithIndex.foreach { case (s, i) => + s.io.out.rx.snp.valid := rxsnp.valid && rxsnpSliceID === i.U + s.io.out.rx.snp.bits := rxsnp.bits + } + rxsnp.ready := Cat(slices.zipWithIndex.map { case (s, i) => s.io.out.rx.snp.ready && rxsnpSliceID === i.U }).orR + + val rxrsp = Wire(DecoupledIO(new CHIRSP)) + val rxrspIsMMIO = rxrsp.bits.txnID.head(1).asBool + val isPCrdGrant = rxrsp.valid && rxrsp.bits.opcode === PCrdGrant + + class EmptyBundle extends Bundle + class PCrdGranted extends Bundle { + val pCrdType = UInt(PCRDTYPE_WIDTH.W) + val srcID = UInt(SRCID_WIDTH.W) + } + + val (mmioQuerys, mmioGrants) = mmio.io_pCrd.map { case x => (x.query, x.grant) }.unzip + val (slicesQuerys, slicesGrants) = slices.map { case s => + (s.io_pCrd.map(_.query), s.io_pCrd.map(_.grant)) + }.unzip + val mshrPCrdQuerys = mmioQuerys ++ slicesQuerys.flatten + val mshrPCrdGrants = mmioGrants ++ slicesGrants.flatten + val mshrEntryCount = mshrPCrdQuerys.length + + val pCrdQueue_s2 = Module(new Queue(new PCrdGranted, entries = mshrEntryCount - 2)) + val pCrdQueue_s3 = Module(new Queue(new PCrdGranted, entries = 2)) + pCrdQueue_s3.io.enq <> pCrdQueue_s2.io.deq + + val mshrPCrdHits = mshrPCrdQuerys.map((_, pCrdQueue_s3.io.deq)).map { case (q, h) => + q.valid && h.valid && q.bits.pCrdType === h.bits.pCrdType && q.bits.srcID === h.bits.srcID + } + val mshrPCrdArbGrants = Wire(Vec(mshrEntryCount, Bool())) + val mshrPCrdArbIn = mshrPCrdHits.zip(mshrPCrdArbGrants).map { case (hit, grant) => + val arbPort = Wire(Decoupled(new EmptyBundle)) + arbPort.valid := hit + grant := arbPort.ready + arbPort + } + val mshrPCrdArbOut = { + val arbPort = Wire(Decoupled(new EmptyBundle)) + arbPort.ready := true.B + pCrdQueue_s3.io.deq.ready := arbPort.valid + arbPort + } + ArbPerf(twoLevelArb(mshrPCrdArbIn, mshrPCrdArbOut, Some("pcrdgrant")), "pcrdgrant_arb") + mshrPCrdGrants.zip(mshrPCrdArbGrants).foreach { case (grant, arb) => grant := arb } + + val pCrdGrantValid_s1 = RegNext(isPCrdGrant) + val pCrdGrantType_s1 = RegNext(rxrsp.bits.pCrdType) + val pCrdGrantSrcID_s1 = RegNext(rxrsp.bits.srcID) + pCrdQueue_s2.io.enq.valid := pCrdGrantValid_s1 + pCrdQueue_s2.io.enq.bits.pCrdType := pCrdGrantType_s1 + pCrdQueue_s2.io.enq.bits.srcID := pCrdGrantSrcID_s1 + val grantCnt = RegInit(0.U(64.W)) + when (pCrdQueue_s3.io.deq.ready) { + grantCnt := grantCnt + 1.U + } + dontTouch(grantCnt) + + val rxrspSliceID = getSliceID(rxrsp.bits.txnID) + slices.zipWithIndex.foreach { case (s, i) => + s.io.out.rx.rsp.valid := rxrsp.valid && rxrspSliceID === i.U && !rxrspIsMMIO && !isPCrdGrant + s.io.out.rx.rsp.bits := rxrsp.bits + s.io.out.rx.rsp.bits.txnID := restoreTXNID(rxrsp.bits.txnID) + } + mmio.io.rx.rsp.valid := rxrsp.valid && rxrspIsMMIO && !isPCrdGrant + mmio.io.rx.rsp.bits := rxrsp.bits + mmio.io.rx.rsp.bits.txnID := restoreTXNID(rxrsp.bits.txnID) + rxrsp.ready := rxrsp.bits.opcode === PCrdGrant || Mux( + rxrspIsMMIO, + mmio.io.rx.rsp.ready, + Cat(slices.zipWithIndex.map { case (s, i) => s.io.out.rx.rsp.ready && rxrspSliceID === i.U }).orR + ) + + val rxdat = Wire(DecoupledIO(new CHIDAT)) + val rxdatIsMMIO = rxdat.bits.txnID.head(1).asBool + val rxdatSliceID = getSliceID(rxdat.bits.txnID) + slices.zipWithIndex.foreach { case (s, i) => + s.io.out.rx.dat.valid := rxdat.valid && rxdatSliceID === i.U && !rxdatIsMMIO + s.io.out.rx.dat.bits := rxdat.bits + s.io.out.rx.dat.bits.txnID := restoreTXNID(rxdat.bits.txnID) + } + mmio.io.rx.dat.valid := rxdat.valid && rxdatIsMMIO + mmio.io.rx.dat.bits := rxdat.bits + mmio.io.rx.dat.bits.txnID := restoreTXNID(rxdat.bits.txnID) + rxdat.ready := Mux( + rxdatIsMMIO, + mmio.io.rx.dat.ready, + Cat(slices.zipWithIndex.map { case (s, i) => s.io.out.rx.dat.ready && rxdatSliceID === i.U }).orR + ) + + val linkMonitor = Module(new LinkMonitor) + val rxdatPipe = Pipeline(linkMonitor.io.in.rx.dat) + val rxrspPipe = Pipeline(linkMonitor.io.in.rx.rsp) + linkMonitor.io.in.tx.req <> txreq + linkMonitor.io.in.tx.rsp <> txrsp + linkMonitor.io.in.tx.dat <> txdat + rxsnp <> linkMonitor.io.in.rx.snp + rxrsp <> rxrspPipe + rxdat <> rxdatPipe + io.chi <> linkMonitor.io.out + linkMonitor.io.nodeID := io.nodeID + linkMonitor.io.exitco.foreach { _ := + Cat(slices.zipWithIndex.map { case (s, i) => s.io.l2FlushDone.getOrElse(false.B)}).andR && io.cpu_wfi.getOrElse(false.B) + } + + XSPerfAccumulate("pcrd_count", pCrdQueue_s2.io.enq.fire) + val perfEvents = Seq(("noEvent", 0.U)) ++ slices.zipWithIndex.map { case (slide, slide_idx) => slide.getPerfEvents.map{case (str, idx) => ("Slice" + slide_idx.toString + "_" + str, idx)} @@ -574,18 +765,6 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has } } - // Outer interface connection - slices.zip(node.out).zipWithIndex.foreach { - case ((slice, (out, _)), i) => - slice match { - case slice: tl2tl.Slice => - out <> slice.io.out - out.a.bits.address := restoreAddress(slice.io.out.a.bits.address, i) - out.c.bits.address := restoreAddress(slice.io.out.c.bits.address, i) - case slice: tl2chi.Slice => - } - } - // ==================== TopDown ==================== val topDown = topDownOpt.map(_ => Module(new TopDownMonitor()(p.alterPartial { case EdgeInKey => node.in.head._2 @@ -655,4 +834,6 @@ abstract class CoupledL2Base(implicit p: Parameters) extends LazyModule with Has None } } + + lazy val module = new CoupledL2Imp(this) } diff --git a/src/main/scala/coupledL2/CustomL1Hint.scala b/src/main/scala/coupledL2/CustomL1Hint.scala index 8116d12e..db5e78b6 100644 --- a/src/main/scala/coupledL2/CustomL1Hint.scala +++ b/src/main/scala/coupledL2/CustomL1Hint.scala @@ -15,14 +15,14 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink.TLMessages._ -import coupledL2.utils._ +import xscache.coupledL2.utils._ class HintQueueEntry(implicit p: Parameters) extends L2Bundle { val source = UInt(sourceIdBits.W) diff --git a/src/main/scala/coupledL2/DataStorage.scala b/src/main/scala/coupledL2/DataStorage.scala index de7015f8..8c5e5f5f 100644 --- a/src/main/scala/coupledL2/DataStorage.scala +++ b/src/main/scala/coupledL2/DataStorage.scala @@ -15,11 +15,11 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ -import coupledL2.utils.GatedSplittedSRAM +import xscache.coupledL2.utils.GatedSplittedSRAM import org.chipsalliance.cde.config.Parameters import utility.mbist.MbistPipeline diff --git a/src/main/scala/coupledL2/Directory.scala b/src/main/scala/coupledL2/Directory.scala index acb2b919..3abd18b4 100644 --- a/src/main/scala/coupledL2/Directory.scala +++ b/src/main/scala/coupledL2/Directory.scala @@ -15,16 +15,16 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility.mbist.MbistPipeline -import coupledL2.utils._ +import xscache.coupledL2.utils._ import utility.{ChiselDB, Code, MemReqSource, ParallelPriorityMux, RegNextN, XSPerfAccumulate, MaskToOH} import utility.sram.SRAMTemplate import org.chipsalliance.cde.config.Parameters -import coupledL2.prefetch.PfSource +import xscache.coupledL2.prefetch.PfSource import freechips.rocketchip.tilelink.TLMessages._ import freechips.rocketchip.util.SeqToAugmentedSeq diff --git a/src/main/scala/coupledL2/GrantBuffer.scala b/src/main/scala/coupledL2/GrantBuffer.scala index 0d9d1b23..cb480ba1 100644 --- a/src/main/scala/coupledL2/GrantBuffer.scala +++ b/src/main/scala/coupledL2/GrantBuffer.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ @@ -23,7 +23,7 @@ import utility._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ -import coupledL2.prefetch.PrefetchResp +import xscache.coupledL2.prefetch.PrefetchResp // record info of those with Grant sent, yet GrantAck not received // used to block Probe upwards diff --git a/src/main/scala/coupledL2/L2Param.scala b/src/main/scala/coupledL2/L2Param.scala index 16806343..cff6030e 100644 --- a/src/main/scala/coupledL2/L2Param.scala +++ b/src/main/scala/coupledL2/L2Param.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util.log2Ceil @@ -23,11 +23,10 @@ import freechips.rocketchip.diplomacy.{AddressSet, BufferParams} import freechips.rocketchip.tilelink._ import freechips.rocketchip.util._ import org.chipsalliance.cde.config.Field -import huancun.{AliasKey, CacheParameters, IsHitKey, PrefetchKey} -import coupledL2.prefetch._ +import xscache.coupledL2.prefetch._ import utility.{Code, MemReqSource, ReqSourceKey} +import xscache.common.{AliasKey, CacheParameters, IsHitKey, PrefetchKey, BankBitsKey} -case object EnableCHI extends Field[Boolean](false) case object EnableL2ClockGate extends Field[Boolean](true) // L1 Cache Params, used for TestTop generation @@ -161,8 +160,6 @@ case object EdgeInKey extends Field[TLEdgeIn] case object EdgeOutKey extends Field[TLEdgeOut] -case object BankBitsKey extends Field[Int] - case object L2NBanksKey extends Field[Int] case object SliceIdKey extends Field[Int] diff --git a/src/main/scala/coupledL2/LinkMonitor.scala b/src/main/scala/coupledL2/LinkMonitor.scala new file mode 100644 index 00000000..f8b416bb --- /dev/null +++ b/src/main/scala/coupledL2/LinkMonitor.scala @@ -0,0 +1,88 @@ +/** ************************************************************************************* + * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences + * Copyright (c) 2020-2021 Peng Cheng Laboratory + * + * XiangShan is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * + * See the Mulan PSL v2 for more details. + * ************************************************************************************* + */ + +package xscache.coupledL2 + +import chisel3._ +import chisel3.util._ +import org.chipsalliance.cde.config.Parameters +import xscache.chi.{Decoupled2LCredit, DecoupledPortIO, HasCHIOpcodes, LCredit2Decoupled, LinkState, LinkStates, PortIO} + +class LinkMonitor(implicit p: Parameters) extends L2Module with HasCHIOpcodes { + val io = IO(new Bundle() { + val in = Flipped(new DecoupledPortIO()) + val out = new PortIO + val nodeID = Input(UInt(NODEID_WIDTH.W)) + val exitco = Option.when(cacheParams.enableL2Flush)(Input(Bool())) + }) + + val txState = RegInit(LinkStates.STOP) + val rxState = RegInit(LinkStates.STOP) + + Seq(txState, rxState).zip(MixedVecInit(Seq(io.out.tx, io.out.rx))).foreach { case (state, link) => + state := MuxLookup(Cat(link.linkactivereq, link.linkactiveack), LinkStates.STOP)(Seq( + Cat(true.B, false.B) -> LinkStates.ACTIVATE, + Cat(true.B, true.B) -> LinkStates.RUN, + Cat(false.B, true.B) -> LinkStates.DEACTIVATE, + Cat(false.B, false.B) -> LinkStates.STOP + )) + } + + val rxsnpDeact, rxrspDeact, rxdatDeact = Wire(Bool()) + val rxDeact = rxsnpDeact && rxrspDeact && rxdatDeact + Decoupled2LCredit(setSrcID(io.in.tx.req, io.nodeID), io.out.tx.req, LinkState(txState), Some("txreq"), Some(8), enableOverCredit = cacheParams.enableCHIAsyncBridge.getOrElse(false)) + Decoupled2LCredit(setSrcID(io.in.tx.rsp, io.nodeID), io.out.tx.rsp, LinkState(txState), Some("txrsp"), Some(8), enableOverCredit = cacheParams.enableCHIAsyncBridge.getOrElse(false)) + Decoupled2LCredit(setSrcID(io.in.tx.dat, io.nodeID), io.out.tx.dat, LinkState(txState), Some("txdat"), Some(8), enableOverCredit = cacheParams.enableCHIAsyncBridge.getOrElse(false)) + LCredit2Decoupled(io.out.rx.snp, io.in.rx.snp, LinkState(rxState), rxsnpDeact, Some("rxsnp")) + LCredit2Decoupled(io.out.rx.rsp, io.in.rx.rsp, LinkState(rxState), rxrspDeact, Some("rxrsp"), 15, false) + LCredit2Decoupled(io.out.rx.dat, io.in.rx.dat, LinkState(rxState), rxdatDeact, Some("rxdat"), 15, false) + + val exitco = io.exitco.getOrElse(false.B) + val exitcoDone = !io.out.syscoreq && !io.out.syscoack && RegNext(true.B, init = false.B) + + io.out.tx.linkactivereq := RegNext(!exitcoDone, init = false.B) + io.out.rx.linkactiveack := RegNext(RegNext(io.out.rx.linkactivereq) || !rxDeact, init = false.B) + + io.out.syscoreq := RegNext(!exitco, init = false.B) + io.out.txsactive := RegNext(!exitcoDone, init = false.B) + + val retryAckCnt = RegInit(0.U(64.W)) + val pCrdGrantCnt = RegInit(0.U(64.W)) + val noAllowRetryCnt = RegInit(0.U(64.W)) + + when(io.in.rx.rsp.fire && io.in.rx.rsp.bits.opcode === RetryAck) { + retryAckCnt := retryAckCnt + 1.U + } + when(io.in.rx.rsp.fire && io.in.rx.rsp.bits.opcode === PCrdGrant) { + pCrdGrantCnt := pCrdGrantCnt + 1.U + } + when(io.in.tx.req.fire && !io.in.tx.req.bits.allowRetry) { + noAllowRetryCnt := noAllowRetryCnt + 1.U + } + + dontTouch(io.out) + dontTouch(retryAckCnt) + dontTouch(pCrdGrantCnt) + dontTouch(noAllowRetryCnt) + + def setSrcID[T <: Bundle](in: DecoupledIO[T], srcID: UInt = 0.U): DecoupledIO[T] = { + val out = Wire(in.cloneType) + out <> in + out.bits.elements.filter(_._1 == "srcID").head._2 := srcID + out + } +} diff --git a/src/main/scala/coupledL2/tl2chi/MMIOBridge.scala b/src/main/scala/coupledL2/MMIOBridge.scala similarity index 97% rename from src/main/scala/coupledL2/tl2chi/MMIOBridge.scala rename to src/main/scala/coupledL2/MMIOBridge.scala index fece0af4..774960bf 100644 --- a/src/main/scala/coupledL2/tl2chi/MMIOBridge.scala +++ b/src/main/scala/coupledL2/MMIOBridge.scala @@ -16,7 +16,7 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ @@ -25,9 +25,10 @@ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.diplomacy._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ -import coupledL2.HasCoupledL2Parameters -import coupledL2.{MemBackTypeMM, MemPageTypeNC} -import coupledL2.utils._ +import xscache.coupledL2.HasCoupledL2Parameters +import xscache.coupledL2.{MemBackTypeMM, MemPageTypeNC} +import xscache.coupledL2.utils._ +import xscache.chi.{CHIDAT, CHIIssue, CHIREQ, CHIRSP, DecoupledNoSnpPortIO, HasCHIMsgParameters, HasCHIOpcodes, MPAM, MemAttr, OrderEncodings, RespErrEncodings, SAM} class MMIOBridge()(implicit p: Parameters) extends LazyModule with HasCoupledL2Parameters @@ -65,7 +66,7 @@ class MMIOBridge()(implicit p: Parameters) extends LazyModule } -class MMIOBridgeEntry(edge: TLEdgeIn)(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes { +class MMIOBridgeEntry(edge: TLEdgeIn)(implicit p: Parameters) extends CoupledL2Module with HasCHIOpcodes { val needRR = true diff --git a/src/main/scala/coupledL2/tl2chi/MSHR.scala b/src/main/scala/coupledL2/MSHR.scala similarity index 98% rename from src/main/scala/coupledL2/tl2chi/MSHR.scala rename to src/main/scala/coupledL2/MSHR.scala index 11cd7f1b..1de16a3e 100644 --- a/src/main/scala/coupledL2/tl2chi/MSHR.scala +++ b/src/main/scala/coupledL2/MSHR.scala @@ -15,25 +15,25 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ -import coupledL2.MetaData._ +import xscache.coupledL2.MetaData._ import utility.{MemReqSource, ParallelLookUp, ParallelMux, ParallelPriorityMux, XSPerfAccumulate} import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ import freechips.rocketchip.tilelink.TLPermissions._ import org.chipsalliance.cde.config.Parameters -import coupledL2.prefetch.{PfSource, PrefetchTrain} -import coupledL2.tl2chi.CHICohStates._ -import coupledL2.tl2chi.CHIChannel -import coupledL2.tl2chi.RespErrEncodings._ -import coupledL2.MetaData._ -import coupledL2._ +import xscache.coupledL2.prefetch.{PfSource, PrefetchTrain} +import xscache.coupledL2.MetaData._ +import xscache.coupledL2._ +import xscache.chi.CHICohStates._ +import xscache.chi.{CHIChannel, CHICohStateFwdedTransSet, CHICohStateTransSet, CHIDAT, CHIREQ, CHIRSP, HasCHIOpcodes, MPAM, MemAttr, OrderEncodings} +import xscache.chi.RespErrEncodings._ -class MSHRTasks(implicit p: Parameters) extends TL2CHIL2Bundle { +class MSHRTasks(implicit p: Parameters) extends CoupledL2Bundle { // outer val txreq = DecoupledIO(new CHIREQ) //TODO: no need to use decoupled Shandshake val txrsp = DecoupledIO(new CHIRSP) //TODO: no need to use decoupled handshake @@ -42,13 +42,13 @@ class MSHRTasks(implicit p: Parameters) extends TL2CHIL2Bundle { // val prefetchTrain = prefetchOpt.map(_ => DecoupledIO(new PrefetchTrain)) // To prefetcher } -class MSHRResps(implicit p: Parameters) extends TL2CHIL2Bundle { +class MSHRResps(implicit p: Parameters) extends CoupledL2Bundle { val sinkC = Flipped(ValidIO(new RespInfoBundle)) val rxrsp = Flipped(ValidIO(new RespInfoBundle)) val rxdat = Flipped(ValidIO(new RespInfoBundle)) } -class MSHR(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes { +class MSHR(implicit p: Parameters) extends CoupledL2Module with HasCHIOpcodes { val io = IO(new Bundle() { val id = Input(UInt(mshrBits.W)) val status = ValidIO(new MSHRStatus) diff --git a/src/main/scala/coupledL2/MSHRBuffer.scala b/src/main/scala/coupledL2/MSHRBuffer.scala index b181935d..b02aab95 100644 --- a/src/main/scala/coupledL2/MSHRBuffer.scala +++ b/src/main/scala/coupledL2/MSHRBuffer.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.utils._ +import xscache.coupledL2.utils._ class MSHRBufRead(implicit p: Parameters) extends L2Bundle { val id = Output(UInt(mshrBits.W)) diff --git a/src/main/scala/coupledL2/tl2chi/MSHRCtl.scala b/src/main/scala/coupledL2/MSHRCtl.scala similarity index 97% rename from src/main/scala/coupledL2/tl2chi/MSHRCtl.scala rename to src/main/scala/coupledL2/MSHRCtl.scala index 8513101a..8d10b707 100644 --- a/src/main/scala/coupledL2/tl2chi/MSHRCtl.scala +++ b/src/main/scala/coupledL2/MSHRCtl.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ @@ -24,11 +24,12 @@ import utility._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ -import coupledL2.prefetch.PrefetchTrain -import coupledL2._ -import coupledL2.utils._ +import xscache.coupledL2.prefetch.PrefetchTrain +import xscache.coupledL2._ +import xscache.coupledL2.utils._ +import xscache.chi.{CHIREQ, CHIRSP, HasCHIOpcodes} -class MSHRCtl(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes with HasPerfEvents { +class MSHRCtl(implicit p: Parameters) extends CoupledL2Module with HasCHIOpcodes with HasPerfEvents { val io = IO(new Bundle() { /* interact with req arb */ val fromReqArb = Input(new Bundle() { @@ -268,4 +269,3 @@ class MSHRCtl(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes ) generatePerfEvent() } - diff --git a/src/main/scala/coupledL2/tl2chi/MainPipe.scala b/src/main/scala/coupledL2/MainPipe.scala similarity index 99% rename from src/main/scala/coupledL2/tl2chi/MainPipe.scala rename to src/main/scala/coupledL2/MainPipe.scala index 215a8ec8..f01aecb4 100644 --- a/src/main/scala/coupledL2/tl2chi/MainPipe.scala +++ b/src/main/scala/coupledL2/MainPipe.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ @@ -24,12 +24,13 @@ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ import freechips.rocketchip.tilelink.TLPermissions._ import org.chipsalliance.cde.config.Parameters -import coupledL2._ -import coupledL2.prefetch.{PrefetchTrain, PfSource} -import coupledL2.tl2chi.CHICohStates._ -import coupledL2.MetaData._ +import xscache.coupledL2._ +import xscache.coupledL2.prefetch.{PrefetchTrain, PfSource} +import xscache.coupledL2.MetaData._ +import xscache.chi.{CHIREQ, HasCHIOpcodes} +import xscache.chi.CHICohStates._ -class MainPipe(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes with HasPerfEvents { +class MainPipe(implicit p: Parameters) extends CoupledL2Module with HasCHIOpcodes with HasPerfEvents { val io = IO(new Bundle() { /* receive task from arbiter at stage 2 */ val taskFromArb_s2 = Flipped(ValidIO(new TaskBundle())) diff --git a/src/main/scala/coupledL2/tl2chi/RXDAT.scala b/src/main/scala/coupledL2/RXDAT.scala similarity index 94% rename from src/main/scala/coupledL2/tl2chi/RXDAT.scala rename to src/main/scala/coupledL2/RXDAT.scala index 45c23670..f739eb49 100644 --- a/src/main/scala/coupledL2/tl2chi/RXDAT.scala +++ b/src/main/scala/coupledL2/RXDAT.scala @@ -15,15 +15,16 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility._ import org.chipsalliance.cde.config.Parameters -import coupledL2.{RespBundle, MSHRBufWrite} +import xscache.coupledL2.{RespBundle, MSHRBufWrite} +import xscache.chi.{CHIDAT, RespErrEncodings} -class RXDAT(implicit p: Parameters) extends TL2CHIL2Module { +class RXDAT(implicit p: Parameters) extends CoupledL2Module { val io = IO(new Bundle() { val out = Flipped(DecoupledIO(new CHIDAT())) val in = Output(new RespBundle()) diff --git a/src/main/scala/coupledL2/tl2chi/RXRSP.scala b/src/main/scala/coupledL2/RXRSP.scala similarity index 92% rename from src/main/scala/coupledL2/tl2chi/RXRSP.scala rename to src/main/scala/coupledL2/RXRSP.scala index ef3e7031..88e2e5c3 100644 --- a/src/main/scala/coupledL2/tl2chi/RXRSP.scala +++ b/src/main/scala/coupledL2/RXRSP.scala @@ -15,15 +15,16 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility._ import org.chipsalliance.cde.config.Parameters -import coupledL2.RespBundle +import xscache.coupledL2.RespBundle +import xscache.chi.CHIRSP -class RXRSP(implicit p: Parameters) extends TL2CHIL2Module { +class RXRSP(implicit p: Parameters) extends CoupledL2Module { val io = IO(new Bundle() { val out = Flipped(DecoupledIO(new CHIRSP())) val in = Output(new RespBundle()) diff --git a/src/main/scala/coupledL2/tl2chi/RXSNP.scala b/src/main/scala/coupledL2/RXSNP.scala similarity index 97% rename from src/main/scala/coupledL2/tl2chi/RXSNP.scala rename to src/main/scala/coupledL2/RXSNP.scala index 1cda0661..78415f1c 100644 --- a/src/main/scala/coupledL2/tl2chi/RXSNP.scala +++ b/src/main/scala/coupledL2/RXSNP.scala @@ -15,19 +15,20 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility._ import org.chipsalliance.cde.config.Parameters import scala.collection.View.Fill -import coupledL2.{TaskBundle, MSHRInfo, MetaEntry, MergeTaskBundle} -import coupledL2.MetaData._ +import xscache.coupledL2.{TaskBundle, MSHRInfo, MetaEntry, MergeTaskBundle} +import xscache.coupledL2.MetaData._ +import xscache.chi.CHISNP class RXSNP( lCreditNum: Int = 4 // the number of L-Credits that a receiver can provide -)(implicit p: Parameters) extends TL2CHIL2Module { +)(implicit p: Parameters) extends CoupledL2Module { val io = IO(new Bundle() { val rxsnp = Flipped(DecoupledIO(new CHISNP())) val task = DecoupledIO(new TaskBundle()) diff --git a/src/main/scala/coupledL2/RequestArb.scala b/src/main/scala/coupledL2/RequestArb.scala index fa166d8b..ac9fd520 100644 --- a/src/main/scala/coupledL2/RequestArb.scala +++ b/src/main/scala/coupledL2/RequestArb.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ @@ -23,8 +23,8 @@ import utility._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2tl._ -import coupledL2.tl2chi._ +import xscache.coupledL2._ +import xscache.chi.HasCHIOpcodes class RequestArb(implicit p: Parameters) extends L2Module with HasCHIOpcodes { @@ -58,7 +58,7 @@ class RequestArb(implicit p: Parameters) extends L2Module /* status of each pipeline stage */ val status_s1 = Output(new PipeEntranceStatus) // set & tag of entrance status val status_vec = Vec(2, ValidIO(new PipeStatus)) - val status_vec_toTX = if (enableCHI) Some(Vec(2, ValidIO(new PipeStatusWithCHI))) else None + val status_vec_toTX = Vec(2, ValidIO(new PipeStatusWithCHI)) /* handle set conflict, capacity conflict */ val fromMSHRCtl = Input(new BlockInfo()) @@ -67,10 +67,9 @@ class RequestArb(implicit p: Parameters) extends L2Module val blockSinkReqEntrance = new BlockInfo() val blockMSHRReqEntrance = Bool() }) - val fromSourceC = if (!enableCHI) Some(Input(new SourceCBlockBundle)) else None - val fromTXDAT = if (enableCHI) Some(Input(new TXDATBlockBundle)) else None - val fromTXRSP = if (enableCHI) Some(Input(new TXRSPBlockBundle)) else None - val fromTXREQ = if (enableCHI) Some(Input(new TXBlockBundle)) else None + val fromTXDAT = Input(new TXDATBlockBundle) + val fromTXRSP = Input(new TXRSPBlockBundle) + val fromTXREQ = Input(new TXBlockBundle) /* MSHR Status */ val msInfo = Vec(mshrsAll, Flipped(ValidIO(new MSHRInfo()))) @@ -113,10 +112,9 @@ class RequestArb(implicit p: Parameters) extends L2Module // if mshr_task_s1 is replRead, it might stall and wait for dirRead.ready, so we block new mshrTask from entering // TODO: will cause msTask path vacant for one-cycle after replRead, since not use Flow so as to avoid ready propagation io.mshrTask.ready := !io.fromGrantBuffer.blockMSHRReqEntrance && !s1_needs_replRead && !(mshr_task_s1.valid && !s2_ready) && - (if (io.fromSourceC.isDefined) !io.fromSourceC.get.blockMSHRReqEntrance else true.B) && - (if (io.fromTXDAT.isDefined) !io.fromTXDAT.get.blockMSHRReqEntrance else true.B) && - (if (io.fromTXRSP.isDefined) !io.fromTXRSP.get.blockMSHRReqEntrance else true.B) && - (if (io.fromTXREQ.isDefined) !io.fromTXREQ.get.blockMSHRReqEntrance else true.B) + !io.fromTXDAT.blockMSHRReqEntrance && + !io.fromTXRSP.blockMSHRReqEntrance && + !io.fromTXREQ.blockMSHRReqEntrance s0_fire := io.mshrTask.valid && io.mshrTask.ready @@ -136,9 +134,8 @@ class RequestArb(implicit p: Parameters) extends L2Module val C_task = io.sinkC.bits val block_A = io.fromMSHRCtl.blockA_s1 || io.fromMainPipe.blockA_s1 || io.fromGrantBuffer.blockSinkReqEntrance.blockA_s1 val block_B = io.fromMSHRCtl.blockB_s1 || io.fromMainPipe.blockB_s1 || io.fromGrantBuffer.blockSinkReqEntrance.blockB_s1 || - (if (io.fromSourceC.isDefined) io.fromSourceC.get.blockSinkBReqEntrance else false.B) || - (if (io.fromTXDAT.isDefined) io.fromTXDAT.get.blockSinkBReqEntrance else false.B) || - (if (io.fromTXRSP.isDefined) io.fromTXRSP.get.blockSinkBReqEntrance else false.B) + io.fromTXDAT.blockSinkBReqEntrance || + io.fromTXRSP.blockSinkBReqEntrance val block_C = io.fromMSHRCtl.blockC_s1 || io.fromMainPipe.blockC_s1 || io.fromGrantBuffer.blockSinkReqEntrance.blockC_s1 // val noFreeWay = Wire(Bool()) @@ -227,17 +224,14 @@ class RequestArb(implicit p: Parameters) extends L2Module // For GrantData, read refillBuffer // Caution: GrantData-alias may read DataStorage or ReleaseBuf instead // Release-replTask also read refillBuf and then write to DS - val releaseRefillData = task_s2.bits.replTask && (if (enableCHI) { + val releaseRefillData = task_s2.bits.replTask && ( task_s2.bits.toTXREQ && ( task_s2.bits.chiOpcode.get === WriteBackFull || task_s2.bits.chiOpcode.get === WriteEvictFull || afterIssueEbOrElse(task_s2.bits.chiOpcode.get === WriteEvictOrEvict, false.B) || task_s2.bits.chiOpcode.get === Evict ) - } else { - task_s2.bits.opcode === Release || - task_s2.bits.opcode === ReleaseData - }) + ) io.refillBufRead_s2.valid := mshrTask_s2 && ( releaseRefillData || mshrTask_s2_a_upwards && !task_s2.bits.useProbeData) @@ -245,26 +239,14 @@ class RequestArb(implicit p: Parameters) extends L2Module // ReleaseData and ProbeAckData read releaseBuffer // channel is used to differentiate GrantData and ProbeAckData - val snoopNeedData = if (enableCHI) { - task_s2.bits.fromB && task_s2.bits.toTXDAT && isSnpRespDataX(task_s2.bits.chiOpcode.get) - } else { - task_s2.bits.fromB && task_s2.bits.opcode === ProbeAckData - } - val releaseNeedData = if (enableCHI) { - task_s2.bits.toTXDAT && task_s2.bits.chiOpcode.get === CopyBackWrData - } else task_s2.bits.opcode === ReleaseData - val dctNeedData = if (enableCHI) { - task_s2.bits.toTXDAT && task_s2.bits.chiOpcode.get === CompData - } else false.B - val cmoNeedData = if (enableCHI) { - task_s2.bits.toTXREQ && task_s2.bits.cmoTask && ( - task_s2.bits.chiOpcode.get === WriteCleanFull || - task_s2.bits.chiOpcode.get === WriteBackFull - ) - } else false.B - val snpHitReleaseNeedData = if (enableCHI) { - !mshrTask_s2 && task_s2.bits.fromB && task_s2.bits.snpHitReleaseWithData - } else false.B + val snoopNeedData = task_s2.bits.fromB && task_s2.bits.toTXDAT && isSnpRespDataX(task_s2.bits.chiOpcode.get) + val releaseNeedData = task_s2.bits.toTXDAT && task_s2.bits.chiOpcode.get === CopyBackWrData + val dctNeedData = task_s2.bits.toTXDAT && task_s2.bits.chiOpcode.get === CompData + val cmoNeedData = task_s2.bits.toTXREQ && task_s2.bits.cmoTask && ( + task_s2.bits.chiOpcode.get === WriteCleanFull || + task_s2.bits.chiOpcode.get === WriteBackFull + ) + val snpHitReleaseNeedData = !mshrTask_s2 && task_s2.bits.fromB && task_s2.bits.snpHitReleaseWithData io.releaseBufRead_s2.valid := task_s2.valid && Mux( mshrTask_s2, task_s2.bits.readProbeDataDown || mshrTask_s2_a_upwards && task_s2.bits.useProbeData, @@ -290,15 +272,13 @@ class RequestArb(implicit p: Parameters) extends L2Module status.bits.channel := task.bits.channel } - if (enableCHI) { - require(io.status_vec_toTX.get.size == 2) - io.status_vec_toTX.get.zip(Seq(task_s1, task_s2)).foreach { - case (status, task) => - status.valid := task.valid - status.bits.channel := task.bits.channel - status.bits.txChannel := task.bits.txChannel - status.bits.mshrTask := task.bits.mshrTask - } + require(io.status_vec_toTX.size == 2) + io.status_vec_toTX.zip(Seq(task_s1, task_s2)).foreach { + case (status, task) => + status.valid := task.valid + status.bits.channel := task.bits.channel + status.bits.txChannel := task.bits.txChannel + status.bits.mshrTask := task.bits.mshrTask } dontTouch(io) @@ -338,12 +318,12 @@ class RequestArb(implicit p: Parameters) extends L2Module XSPerfAccumulate("sinkB_stall_by_TXDAT", io.sinkB.valid && !io.fromMSHRCtl.blockB_s1 && !io.fromMainPipe.blockB_s1 && !io.fromGrantBuffer.blockSinkReqEntrance.blockB_s1 && - (if (io.fromTXDAT.isDefined) io.fromTXDAT.get.blockSinkBReqEntrance else false.B)) + io.fromTXDAT.blockSinkBReqEntrance) XSPerfAccumulate("sinkB_stall_by_TXRSP", io.sinkB.valid && !io.fromMSHRCtl.blockB_s1 && !io.fromMainPipe.blockB_s1 && !io.fromGrantBuffer.blockSinkReqEntrance.blockB_s1 && - !(if (io.fromTXDAT.isDefined) io.fromTXDAT.get.blockSinkBReqEntrance else false.B) && - (if (io.fromTXRSP.isDefined) io.fromTXRSP.get.blockSinkBReqEntrance else false.B)) + !io.fromTXDAT.blockSinkBReqEntrance && + io.fromTXRSP.blockSinkBReqEntrance) XSPerfAccumulate("sinkA_stall_by_dir", io.sinkA.valid && !block_A && !io.dirRead_s1.ready) XSPerfAccumulate("sinkB_stall_by_dir", io.sinkB.valid && !block_B && !io.dirRead_s1.ready) diff --git a/src/main/scala/coupledL2/RequestBuffer.scala b/src/main/scala/coupledL2/RequestBuffer.scala index af7d982f..1727fbc2 100644 --- a/src/main/scala/coupledL2/RequestBuffer.scala +++ b/src/main/scala/coupledL2/RequestBuffer.scala @@ -15,16 +15,16 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink.TLMessages._ import freechips.rocketchip.tilelink.TLPermissions._ import chisel3._ import chisel3.util._ -import coupledL2._ -import coupledL2.prefetch._ -import coupledL2.utils._ +import xscache.coupledL2._ +import xscache.coupledL2.prefetch._ +import xscache.coupledL2.utils._ import utility._ class ReqEntry(entries: Int = 4)(implicit p: Parameters) extends L2Bundle() { diff --git a/src/main/scala/coupledL2/SinkA.scala b/src/main/scala/coupledL2/SinkA.scala index 9a7bf188..07f034e5 100644 --- a/src/main/scala/coupledL2/SinkA.scala +++ b/src/main/scala/coupledL2/SinkA.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ @@ -23,9 +23,9 @@ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ import freechips.rocketchip.tilelink.TLHints._ -import coupledL2.prefetch.PrefetchReq -import huancun.{AliasKey, PrefetchKey} +import xscache.coupledL2.prefetch.PrefetchReq import utility.{MemReqSource, XSPerfAccumulate} +import xscache.common.{AliasKey, PrefetchKey} class SinkA(implicit p: Parameters) extends L2Module { val io = IO(new Bundle() { @@ -158,7 +158,7 @@ class SinkA(implicit p: Parameters) extends L2Module { 4. if cacheline is VALID, after cmo flush, Mainpipe send back resp | io.cmoAll.cmoLineDone 5. if cacheline is INVALID, MainPipe drop it and send back resp | io.cmoAll.cmoLineDone 6. after all slices is flushed, inform Core | io.cmoAll.l2FlushDone - 7. after all slices is flushed, exit coherency | TL2CHICoupledL2.io_chi.syscoreq + 7. after all slices is flushed, exit coherency | CoupledL2.io_chi.syscoreq ---------------------------------------------------------------------------------------------------------*/ val l2Flush = io.cmoAll.map(_.l2Flush).getOrElse(false.B) val mshrValid = io.cmoAll.map(_.mshrValid).getOrElse(false.B) diff --git a/src/main/scala/coupledL2/SinkC.scala b/src/main/scala/coupledL2/SinkC.scala index b88f0e33..60bae71e 100644 --- a/src/main/scala/coupledL2/SinkC.scala +++ b/src/main/scala/coupledL2/SinkC.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ @@ -23,7 +23,7 @@ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ import org.chipsalliance.cde.config.Parameters import utility.{MemReqSource, XSPerfAccumulate, TwoLevelRRArbiter, ArbPerf} -import coupledL2.utils._ +import xscache.coupledL2.utils._ class PipeBufferResp(implicit p: Parameters) extends L2Bundle { val data = Vec(beatSize, UInt((beatBytes * 8).W)) diff --git a/src/main/scala/coupledL2/tl2chi/Slice.scala b/src/main/scala/coupledL2/Slice.scala similarity index 96% rename from src/main/scala/coupledL2/tl2chi/Slice.scala rename to src/main/scala/coupledL2/Slice.scala index dfddcce8..34734db4 100644 --- a/src/main/scala/coupledL2/tl2chi/Slice.scala +++ b/src/main/scala/coupledL2/Slice.scala @@ -15,15 +15,16 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility.mbist.MbistPipeline import org.chipsalliance.cde.config.Parameters -import coupledL2._ -import coupledL2.prefetch.PrefetchIO +import xscache.coupledL2._ +import xscache.coupledL2.prefetch.PrefetchIO import utility.MemReqSource +import xscache.chi.{DecoupledPortIO, HasCHIMsgParameters} class OuterBundle(implicit p: Parameters) extends DecoupledPortIO with BaseOuterBundle @@ -66,7 +67,7 @@ class Slice()(implicit p: Parameters) extends BaseSlice[OuterBundle] grantBuf.io.fromReqArb.status_s1 := reqArb.io.status_s1 grantBuf.io.pipeStatusVec := reqArb.io.status_vec ++ mainPipe.io.status_vec_toD - val status_vec_toTX = reqArb.io.status_vec_toTX.get ++ mainPipe.io.status_vec_toTX + val status_vec_toTX = reqArb.io.status_vec_toTX ++ mainPipe.io.status_vec_toTX txreq.io.pipeReq <> mainPipe.io.toTXREQ txreq.io.mshrReq <> mshrCtl.io.toTXREQ txreq.io.pipeStatusVec := status_vec_toTX @@ -99,9 +100,9 @@ class Slice()(implicit p: Parameters) extends BaseSlice[OuterBundle] reqArb.io.fromMSHRCtl := mshrCtl.io.toReqArb reqArb.io.fromMainPipe := mainPipe.io.toReqArb reqArb.io.fromGrantBuffer := grantBuf.io.toReqArb - reqArb.io.fromTXDAT.foreach(_ := txdat.io.toReqArb) - reqArb.io.fromTXRSP.foreach(_ := txrsp.io.toReqArb) - reqArb.io.fromTXREQ.foreach(_ := txreq.io.toReqArb) + reqArb.io.fromTXDAT := txdat.io.toReqArb + reqArb.io.fromTXRSP := txrsp.io.toReqArb + reqArb.io.fromTXREQ := txreq.io.toReqArb reqArb.io.msInfo := mshrCtl.io.msInfo reqBuf.io.in <> sinkA.io.task @@ -199,7 +200,6 @@ class Slice()(implicit p: Parameters) extends BaseSlice[OuterBundle] /* Connect upwards channels */ val inBuf = cacheParams.innerBuf - // val outBuf = tl2tlParams.outerBuf sinkA.io.a <> inBuf.a(io.in.a) io.in.b <> inBuf.b(mshrCtl.io.toSourceB) sinkC.io.c <> inBuf.c(io.in.c) diff --git a/src/main/scala/coupledL2/SourceB.scala b/src/main/scala/coupledL2/SourceB.scala index 713036f5..c5f4726b 100644 --- a/src/main/scala/coupledL2/SourceB.scala +++ b/src/main/scala/coupledL2/SourceB.scala @@ -16,11 +16,11 @@ * ************************************************************************************* */ -package coupledL2 +package xscache.coupledL2 import chisel3._ import chisel3.util._ -import coupledL2.utils._ +import xscache.coupledL2.utils._ import freechips.rocketchip.tilelink._ import org.chipsalliance.cde.config.Parameters import utility._ @@ -59,7 +59,7 @@ class SourceB(implicit p: Parameters) extends L2Module { b.source := dcacheSourceIdStart b.address := Cat(task.tag, task.set, 0.U(offsetBits.W)) b.mask := Fill(beatBytes, 1.U(1.W)) - b.data := Cat(task.alias.getOrElse(0.U), 0.U(1.W)) // this is the same as HuanCun + b.data := Cat(task.alias.getOrElse(0.U), 0.U(1.W)) b.corrupt := false.B b } diff --git a/src/main/scala/coupledL2/tl2chi/TXDAT.scala b/src/main/scala/coupledL2/TXDAT.scala similarity index 96% rename from src/main/scala/coupledL2/tl2chi/TXDAT.scala rename to src/main/scala/coupledL2/TXDAT.scala index 1b71a9da..8c9a78b8 100644 --- a/src/main/scala/coupledL2/tl2chi/TXDAT.scala +++ b/src/main/scala/coupledL2/TXDAT.scala @@ -15,14 +15,15 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility._ import org.chipsalliance.cde.config.Parameters -import coupledL2.{TaskWithData, TaskBundle, DSBlock, DSBeat} -import coupledL2.tl2chi.CHICohStates._ +import xscache.coupledL2.{TaskWithData, TaskBundle, DSBlock, DSBeat} +import xscache.chi.{CHIDAT, HasCHIOpcodes, RespErrEncodings} +import xscache.chi.CHICohStates._ class TXDATBlockBundle(implicit p: Parameters) extends TXBlockBundle { val blockSinkBReqEntrance = Bool() @@ -30,7 +31,7 @@ class TXDATBlockBundle(implicit p: Parameters) extends TXBlockBundle { override def apply() = 0.U.asTypeOf(this) } -class TXDAT(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes { +class TXDAT(implicit p: Parameters) extends CoupledL2Module with HasCHIOpcodes { val io = IO(new Bundle() { val in = Flipped(DecoupledIO(new TaskWithData())) val out = DecoupledIO(new CHIDAT()) @@ -182,4 +183,4 @@ class TXDAT(implicit p: Parameters) extends TL2CHIL2Module with HasCHIOpcodes { dat } -} \ No newline at end of file +} diff --git a/src/main/scala/coupledL2/tl2chi/TXREQ.scala b/src/main/scala/coupledL2/TXREQ.scala similarity index 94% rename from src/main/scala/coupledL2/tl2chi/TXREQ.scala rename to src/main/scala/coupledL2/TXREQ.scala index 7c3cb4db..e33730f7 100644 --- a/src/main/scala/coupledL2/tl2chi/TXREQ.scala +++ b/src/main/scala/coupledL2/TXREQ.scala @@ -15,21 +15,22 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility._ import org.chipsalliance.cde.config.Parameters +import xscache.chi.{CHIREQ, SAM} -class TXBlockBundle(implicit p: Parameters) extends TL2CHIL2Bundle { +class TXBlockBundle(implicit p: Parameters) extends CoupledL2Bundle { // val blockSinkBReqEntrance = Bool() val blockMSHRReqEntrance = Bool() def apply() = 0.U.asTypeOf(this) } -class TXREQ(implicit p: Parameters) extends TL2CHIL2Module { +class TXREQ(implicit p: Parameters) extends CoupledL2Module { val io = IO(new Bundle() { val pipeReq = Flipped(DecoupledIO(new CHIREQ())) val mshrReq = Flipped(DecoupledIO(new CHIREQ())) diff --git a/src/main/scala/coupledL2/tl2chi/TXRSP.scala b/src/main/scala/coupledL2/TXRSP.scala similarity index 95% rename from src/main/scala/coupledL2/tl2chi/TXRSP.scala rename to src/main/scala/coupledL2/TXRSP.scala index 1a136b9b..34843131 100644 --- a/src/main/scala/coupledL2/tl2chi/TXRSP.scala +++ b/src/main/scala/coupledL2/TXRSP.scala @@ -15,13 +15,14 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.coupledL2 import chisel3._ import chisel3.util._ import utility._ import org.chipsalliance.cde.config.Parameters -import coupledL2.TaskBundle +import xscache.coupledL2.TaskBundle +import xscache.chi.{CHIRSP, RespErrEncodings} class TXRSPBlockBundle(implicit p: Parameters) extends TXBlockBundle { val blockSinkBReqEntrance = Bool() @@ -29,7 +30,7 @@ class TXRSPBlockBundle(implicit p: Parameters) extends TXBlockBundle { override def apply() = 0.U.asTypeOf(this) } -class TXRSP(implicit p: Parameters) extends TL2CHIL2Module { +class TXRSP(implicit p: Parameters) extends CoupledL2Module { val io = IO(new Bundle() { // val in = Flipped(DecoupledIO(new TaskBundle())) val pipeRsp = Flipped(DecoupledIO(new TaskBundle)) diff --git a/src/main/scala/coupledL2/TopDownMonitor.scala b/src/main/scala/coupledL2/TopDownMonitor.scala index 46f5c15c..16ed2b0a 100644 --- a/src/main/scala/coupledL2/TopDownMonitor.scala +++ b/src/main/scala/coupledL2/TopDownMonitor.scala @@ -14,13 +14,13 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ -package coupledL2 +package xscache.coupledL2 import org.chipsalliance.cde.config.Parameters import chisel3._ import chisel3.util._ -import coupledL2.prefetch.PfSource -import coupledL2.utils._ +import xscache.coupledL2.prefetch.PfSource +import xscache.coupledL2.utils._ import utility._ class PfStatInMSHRBundle()(implicit p: Parameters) extends L2Bundle { diff --git a/src/main/scala/coupledL2/debug/Monitor.scala b/src/main/scala/coupledL2/debug/Monitor.scala index ae8dec8f..955f5293 100644 --- a/src/main/scala/coupledL2/debug/Monitor.scala +++ b/src/main/scala/coupledL2/debug/Monitor.scala @@ -1,4 +1,4 @@ -package coupledL2.debug +package xscache.coupledL2.debug import chisel3._ import chisel3.util._ @@ -6,8 +6,8 @@ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink.TLMessages._ import freechips.rocketchip.tilelink.TLPermissions._ -import coupledL2._ -import coupledL2.MetaData._ +import xscache.coupledL2._ +import xscache.coupledL2.MetaData._ import utility._ class MainpipeMoni(implicit p: Parameters) extends L2Bundle { diff --git a/src/main/scala/coupledL2/prefetch/BestOffsetPrefetch.scala b/src/main/scala/coupledL2/prefetch/BestOffsetPrefetch.scala index d3c97102..b0819664 100644 --- a/src/main/scala/coupledL2/prefetch/BestOffsetPrefetch.scala +++ b/src/main/scala/coupledL2/prefetch/BestOffsetPrefetch.scala @@ -24,7 +24,7 @@ * ************************************************************************************* */ -package coupledL2.prefetch +package xscache.coupledL2.prefetch import utility.{ChiselDB, Constantin, MemReqSource, ParallelPriorityMux, XSPerfAccumulate, TwoLevelRRArbiter, ArbPerf} import utility.sram.SRAMTemplate @@ -32,11 +32,11 @@ import org.chipsalliance.cde.config.Parameters import chisel3.DontCare.:= import chisel3._ import chisel3.util._ -import coupledL2.{HasCoupledL2Parameters, L2TlbReq, L2ToL1TlbIO, TlbCmd, Pbmt} -import coupledL2.utils.ReplacementPolicy +import xscache.coupledL2.{HasCoupledL2Parameters, L2TlbReq, L2ToL1TlbIO, TlbCmd, Pbmt} +import xscache.coupledL2.utils.ReplacementPolicy import scopt.Read import freechips.rocketchip.util.SeqToAugmentedSeq -import coupledL2.utils._ +import xscache.coupledL2.utils._ case class BOPParameters( virtualTrain: Boolean = true, diff --git a/src/main/scala/coupledL2/prefetch/NextLinePrefetch.scala b/src/main/scala/coupledL2/prefetch/NextLinePrefetch.scala index 0e461181..1c59db96 100644 --- a/src/main/scala/coupledL2/prefetch/NextLinePrefetch.scala +++ b/src/main/scala/coupledL2/prefetch/NextLinePrefetch.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package coupledL2.prefetch +package xscache.coupledL2.prefetch import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.HasCoupledL2Parameters -import coupledL2.utils.{OverwriteQueue, ReplacementPolicy, SetAssocReplacer} +import xscache.coupledL2.HasCoupledL2Parameters +import xscache.coupledL2.utils.{OverwriteQueue, ReplacementPolicy, SetAssocReplacer} import utility.{ChiselDB, MemReqSource, XSPerfAccumulate, XSPerfHistogram} // Next-Line Prefetcher base parameters @@ -69,7 +69,7 @@ trait HasNLParams extends HasCoupledL2Parameters { }.get.asInstanceOf[NLParameters] def L2SliceNum: Int = { try { - val nb = p(coupledL2.L2NBanksKey) + val nb = p(xscache.coupledL2.L2NBanksKey) if (nb > 0) nb else nlParams.L2SliceNum } catch { case _: Throwable => nlParams.L2SliceNum diff --git a/src/main/scala/coupledL2/prefetch/PrefetchParameters.scala b/src/main/scala/coupledL2/prefetch/PrefetchParameters.scala index b9817de8..9e9fa61c 100644 --- a/src/main/scala/coupledL2/prefetch/PrefetchParameters.scala +++ b/src/main/scala/coupledL2/prefetch/PrefetchParameters.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package coupledL2.prefetch +package xscache.coupledL2.prefetch import org.chipsalliance.cde.config.Parameters import chisel3._ import chisel3.util._ -import coupledL2._ +import xscache.coupledL2._ import utility.MemReqSource trait PrefetchParameters { diff --git a/src/main/scala/coupledL2/prefetch/PrefetchReceiver.scala b/src/main/scala/coupledL2/prefetch/PrefetchReceiver.scala index aea1a800..59de1254 100644 --- a/src/main/scala/coupledL2/prefetch/PrefetchReceiver.scala +++ b/src/main/scala/coupledL2/prefetch/PrefetchReceiver.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package coupledL2.prefetch +package xscache.coupledL2.prefetch import org.chipsalliance.cde.config.Parameters import chisel3._ import chisel3.util._ import freechips.rocketchip.tilelink._ -import coupledL2._ +import xscache.coupledL2._ import utility.{Constantin, RegNextN} // TODO: PrefetchReceiver is temporarily used since L1&L2 do not support Hint. diff --git a/src/main/scala/coupledL2/prefetch/Prefetcher.scala b/src/main/scala/coupledL2/prefetch/Prefetcher.scala index 1cfaab50..ccad4e12 100644 --- a/src/main/scala/coupledL2/prefetch/Prefetcher.scala +++ b/src/main/scala/coupledL2/prefetch/Prefetcher.scala @@ -15,15 +15,15 @@ * ************************************************************************************* */ -package coupledL2.prefetch +package xscache.coupledL2.prefetch import chisel3._ import chisel3.util._ import utility._ import org.chipsalliance.cde.config.Parameters import utility.mbist.MbistPipeline -import coupledL2._ -import coupledL2.utils.OverwriteQueue +import xscache.coupledL2._ +import xscache.coupledL2.utils.OverwriteQueue /* virtual address */ trait HasPrefetcherHelper extends HasCircularQueuePtrHelper with HasCoupledL2Parameters { diff --git a/src/main/scala/coupledL2/prefetch/TemporalPrefetch.scala b/src/main/scala/coupledL2/prefetch/TemporalPrefetch.scala index 6183fcba..eca18b3c 100644 --- a/src/main/scala/coupledL2/prefetch/TemporalPrefetch.scala +++ b/src/main/scala/coupledL2/prefetch/TemporalPrefetch.scala @@ -26,16 +26,15 @@ * ************************************************************************************* */ -package coupledL2.prefetch +package xscache.coupledL2.prefetch import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import utility.{ChiselDB, Constantin, MemReqSource} import utility.sram.SRAMTemplate -import coupledL2.HasCoupledL2Parameters -import coupledL2.utils.ReplacementPolicy -import huancun.{TPmetaReq, TPmetaResp} +import xscache.coupledL2.HasCoupledL2Parameters +import xscache.coupledL2.utils.ReplacementPolicy case class TPParameters( tpTableEntries: Int = 16384, @@ -80,6 +79,19 @@ trait HasTPParams extends HasCoupledL2Parameters { abstract class TPBundle(implicit val p: Parameters) extends Bundle with HasTPParams abstract class TPModule(implicit val p: Parameters) extends Module with HasTPParams +class TPmetaReq(hartIdLen: Int, fullAddressBits: Int, offsetBits: Int) extends Bundle { + val hartid = UInt(hartIdLen.W) + val set = UInt(10.W) + val way = UInt(4.W) + val wmode = Bool() + val rawData = Vec(512 / (fullAddressBits - offsetBits), UInt((fullAddressBits - offsetBits).W)) +} + +class TPmetaResp(hartIdLen: Int, fullAddressBits: Int, offsetBits: Int) extends Bundle { + val hartid = UInt(hartIdLen.W) + val rawData = Vec(512 / (fullAddressBits - offsetBits), UInt((fullAddressBits - offsetBits).W)) +} + class tpMetaEntry(implicit p:Parameters) extends TPBundle { val valid = Bool() val triggerTag = UInt((fullAddressBits - blockOffBits - tpTableSetBits).W) diff --git a/src/main/scala/coupledL2/tl2chi/TL2CHICoupledL2.scala b/src/main/scala/coupledL2/tl2chi/TL2CHICoupledL2.scala deleted file mode 100644 index e5f03b8d..00000000 --- a/src/main/scala/coupledL2/tl2chi/TL2CHICoupledL2.scala +++ /dev/null @@ -1,281 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2chi - -import chisel3._ -import chisel3.util._ -import utility.{Pipeline, ParallelPriorityMux, RegNextN, XSPerfAccumulate, TwoLevelRRArbiter, ArbPerf} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import freechips.rocketchip.util._ -import org.chipsalliance.cde.config.{Parameters, Field} -import scala.math.max -import coupledL2._ -import coupledL2.prefetch._ -import coupledL2.utils._ - -abstract class TL2CHIL2Bundle(implicit val p: Parameters) extends Bundle - with HasCoupledL2Parameters - with HasCHIMsgParameters -abstract class TL2CHIL2Module(implicit val p: Parameters) extends Module - with HasCoupledL2Parameters - with HasCHIMsgParameters - - -class TL2CHICoupledL2(implicit p: Parameters) extends CoupledL2Base { - - val addressRange = Seq(AddressSet(0x00000000L, 0xffffffffffffL)) // TODO: parameterize this - val managerParameters = TLSlavePortParameters.v1( - managers = Seq(TLSlaveParameters.v1( - address = addressRange, - regionType = RegionType.CACHED, - supportsAcquireT = xfer, - supportsAcquireB = xfer, - supportsArithmetic = atom, - supportsLogical = atom, - supportsGet = access, - supportsPutFull = access, - supportsPutPartial = access, - supportsHint = access, - fifoId = None - )), - beatBytes = 32, - minLatency = 2, - responseFields = cacheParams.respField, - requestKeys = cacheParams.reqKey, - endSinkId = idsAll * (1 << bankBits) - ) - val managerNode = TLManagerNode(Seq(managerParameters)) - - val mmioBridge = LazyModule(new MMIOBridge) - val mmioNode = mmioBridge.mmioNode - - class CoupledL2Imp(wrapper: LazyModule) extends BaseCoupledL2Imp(wrapper) - with HasCHIOpcodes { - - val io_chi = IO(new PortIO) - val io_nodeID = IO(Input(UInt())) - val io_cpu_wfi = Option.when(cacheParams.enableL2Flush) (IO(Input(Bool()))) - - // Check port width - require(io_chi.tx.rsp.getWidth == io_chi.rx.rsp.getWidth); - require(io_chi.tx.dat.getWidth == io_chi.rx.dat.getWidth); - - // Display info - println(s"CHI Issue Version: ${p(CHIIssue)}") - println(s"CHI REQ Flit Width: ${io_chi.tx.req.flit.getWidth}") - println(s"CHI RSP Flit Width: ${io_chi.tx.rsp.flit.getWidth}") - println(s"CHI SNP Flit Width: ${io_chi.rx.snp.flit.getWidth}") - println(s"CHI DAT Flit Width: ${io_chi.rx.dat.flit.getWidth}") - println(s"CHI Port Width: ${io_chi.getWidth}") - - println(s"MMIO:") - mmioNode.edges.in.headOption.foreach { n => - n.client.clients.zipWithIndex.foreach { - case (c, i) => - println(s"\t${i} <= ${c.name};" + - s"\tsourceRange: ${c.sourceId.start}~${c.sourceId.end}") - } - } - - val mmio = mmioBridge.module - - // Outer interface connection - /** - * TxnID space arrangement: - * If this is a cacheable request: - * +----------------+-----------+---------------+ - * | 0.U(1.W) | SliceID | Inner TxnID | - * +----------------+-----------+---------------+ - * Otherwise this is an MMIO request: - * +----------------+-----------+---------------+ - * | 1.U(1.W) | Inner TxnID | - * +----------------+---------------------------+ - * - */ - def setSliceID(txnID: UInt, sliceID: UInt, mmio: Bool): UInt = { - Mux( - mmio, - Cat(1.U(1.W), txnID.tail(1)), - Cat(0.U(1.W), if (banks <= 1) txnID.tail(1) else Cat(sliceID(bankBits - 1, 0), txnID.tail(bankBits + 1))) - ) - } - def getSliceID(txnID: UInt): UInt = if (banks <= 1) 0.U else txnID.tail(1).head(bankBits) - def restoreTXNID(txnID: UInt): UInt = { - val mmio = txnID.head(1).asBool - Mux( - mmio || (banks <= 1).B, - Cat(0.U(1.W), txnID.tail(1)), - Cat(0.U(1.W), 0.U(bankBits.W), txnID.tail(bankBits + 1)) - ) - } - - slices match { - case slices: Seq[Slice] => - // TXREQ - val txreq_arb = Module(new TwoLevelRRArbiter(new CHIREQ, slices.size + 1)) // plus 1 for MMIO - ArbPerf(txreq_arb, "txreq_arb") - val txreq = Wire(DecoupledIO(new CHIREQ)) - slices.zip(txreq_arb.io.in.init).foreach { case (s, in) => in <> s.io.out.tx.req } - txreq_arb.io.in.last <> mmio.io.tx.req - txreq <> txreq_arb.io.out - txreq.bits.txnID := setSliceID(txreq_arb.io.out.bits.txnID, txreq_arb.io.chosen, mmio.io.tx.req.fire) - - // TXRSP - val txrsp = Wire(DecoupledIO(new CHIRSP)) - fastArb(slices.map(_.io.out.tx.rsp), txrsp, Some("txrsp")) - - // TXDAT - val txdat = Wire(DecoupledIO(new CHIDAT)) - fastArb(slices.map(_.io.out.tx.dat) :+ mmio.io.tx.dat, txdat, Some("txdat")) - - // RXSNP - val rxsnp = Wire(DecoupledIO(new CHISNP)) - val rxsnpSliceID = if (banks <= 1) 0.U else (rxsnp.bits.addr >> (offsetBits - 3))(bankBits - 1, 0) - slices.zipWithIndex.foreach { case (s, i) => - s.io.out.rx.snp.valid := rxsnp.valid && rxsnpSliceID === i.U - s.io.out.rx.snp.bits := rxsnp.bits - } - rxsnp.ready := Cat(slices.zipWithIndex.map { case (s, i) => s.io.out.rx.snp.ready && rxsnpSliceID === i.U }).orR - - // RXRSP - val rxrsp = Wire(DecoupledIO(new CHIRSP)) - val rxrspIsMMIO = rxrsp.bits.txnID.head(1).asBool - val isPCrdGrant = rxrsp.valid && rxrsp.bits.opcode === PCrdGrant - - // PCredit queue - class EmptyBundle extends Bundle - - class PCrdGranted extends Bundle { - val pCrdType = UInt(PCRDTYPE_WIDTH.W) - val srcID = UInt(SRCID_WIDTH.W) - } - - val (mmioQuerys, mmioGrants) = mmio.io_pCrd.map { case x => (x.query, x.grant) }.unzip - val (slicesQuerys, slicesGrants) = slices.map { case s => - (s.io_pCrd.map(_.query), s.io_pCrd.map(_.grant)) - }.unzip - val mshrPCrdQuerys = mmioQuerys ++ slicesQuerys.flatten - val mshrPCrdGrants = mmioGrants ++ slicesGrants.flatten - - val mshrEntryCount = mshrPCrdQuerys.length - - val pCrdQueue_s2 = Module(new Queue(new PCrdGranted, entries = mshrEntryCount - 2)) - val pCrdQueue_s3 = Module(new Queue(new PCrdGranted, entries = 2)) - - pCrdQueue_s3.io.enq <> pCrdQueue_s2.io.deq - - // PCredit hit by MSHRs - val mshrPCrdHits = mshrPCrdQuerys.map((_, pCrdQueue_s3.io.deq)).map { case (q, h) => { - q.valid && h.valid && q.bits.pCrdType === h.bits.pCrdType && q.bits.srcID === h.bits.srcID - }} - - // PCredit dispatch arbitration - val mshrPCrdArbGrants = Wire(Vec(mshrEntryCount, Bool())) - val mshrPCrdArbIn = mshrPCrdHits.zip(mshrPCrdArbGrants).map { case (hit, grant) => { - val arbPort = Wire(Decoupled(new EmptyBundle)) - arbPort.valid := hit - grant := arbPort.ready - arbPort - }} - - val mshrPCrdArbOut = { - val arbPort = Wire(Decoupled(new EmptyBundle)) - arbPort.ready := true.B - pCrdQueue_s3.io.deq.ready := arbPort.valid - arbPort - } - - ArbPerf(twoLevelArb(mshrPCrdArbIn, mshrPCrdArbOut, Some("pcrdgrant")), "pcrdgrant_arb") - - mshrPCrdGrants.zip(mshrPCrdArbGrants).foreach { case (grant, arb) => grant := arb } - - // PCredit receive - val pCrdGrantValid_s1 = RegNext(isPCrdGrant) - val pCrdGrantType_s1 = RegNext(rxrsp.bits.pCrdType) - val pCrdGrantSrcID_s1 = RegNext(rxrsp.bits.srcID) - - pCrdQueue_s2.io.enq.valid := pCrdGrantValid_s1 - pCrdQueue_s2.io.enq.bits.pCrdType := pCrdGrantType_s1 - pCrdQueue_s2.io.enq.bits.srcID := pCrdGrantSrcID_s1 - - val grantCnt = RegInit(0.U(64.W)) - when (pCrdQueue_s3.io.deq.ready) { - grantCnt := grantCnt + 1.U - } - dontTouch(grantCnt) - - val rxrspSliceID = getSliceID(rxrsp.bits.txnID) - slices.zipWithIndex.foreach { case (s, i) => - s.io.out.rx.rsp.valid := rxrsp.valid && rxrspSliceID === i.U && !rxrspIsMMIO && !isPCrdGrant - s.io.out.rx.rsp.bits := rxrsp.bits - s.io.out.rx.rsp.bits.txnID := restoreTXNID(rxrsp.bits.txnID) - } - mmio.io.rx.rsp.valid := rxrsp.valid && rxrspIsMMIO && !isPCrdGrant - mmio.io.rx.rsp.bits := rxrsp.bits - mmio.io.rx.rsp.bits.txnID := restoreTXNID(rxrsp.bits.txnID) - rxrsp.ready := rxrsp.bits.opcode === PCrdGrant || Mux( - rxrspIsMMIO, - mmio.io.rx.rsp.ready, - Cat(slices.zipWithIndex.map { case (s, i) => s.io.out.rx.rsp.ready && rxrspSliceID === i.U }).orR - ) - - // RXDAT - val rxdat = Wire(DecoupledIO(new CHIDAT)) - val rxdatIsMMIO = rxdat.bits.txnID.head(1).asBool - val rxdatSliceID = getSliceID(rxdat.bits.txnID) - slices.zipWithIndex.foreach { case (s, i) => - s.io.out.rx.dat.valid := rxdat.valid && rxdatSliceID === i.U && !rxdatIsMMIO - s.io.out.rx.dat.bits := rxdat.bits - s.io.out.rx.dat.bits.txnID := restoreTXNID(rxdat.bits.txnID) - } - mmio.io.rx.dat.valid := rxdat.valid && rxdatIsMMIO - mmio.io.rx.dat.bits := rxdat.bits - mmio.io.rx.dat.bits.txnID := restoreTXNID(rxdat.bits.txnID) - rxdat.ready := Mux( - rxdatIsMMIO, - mmio.io.rx.dat.ready, - Cat(slices.zipWithIndex.map { case (s, i) => s.io.out.rx.dat.ready && rxdatSliceID === i.U}).orR - ) - - val linkMonitor = Module(new LinkMonitor) - val rxdatPipe = Pipeline(linkMonitor.io.in.rx.dat) - val rxrspPipe = Pipeline(linkMonitor.io.in.rx.rsp) - linkMonitor.io.in.tx.req <> txreq - linkMonitor.io.in.tx.rsp <> txrsp - linkMonitor.io.in.tx.dat <> txdat - rxsnp <> linkMonitor.io.in.rx.snp - rxrsp <> rxrspPipe - rxdat <> rxdatPipe - io_chi <> linkMonitor.io.out - linkMonitor.io.nodeID := io_nodeID - /* exit coherency when: l2 flush of all slices is done and core is in WFI state */ - linkMonitor.io.exitco.foreach { _ := - Cat(slices.zipWithIndex.map { case (s, i) => s.io.l2FlushDone.getOrElse(false.B)}).andR && io_cpu_wfi.getOrElse(false.B) - } - - /** - * performance counters - */ - XSPerfAccumulate("pcrd_count", pCrdQueue_s2.io.enq.fire) - } - } - - lazy val module = new CoupledL2Imp(this) -} diff --git a/src/main/scala/coupledL2/tl2tl/AcquireUnit.scala b/src/main/scala/coupledL2/tl2tl/AcquireUnit.scala deleted file mode 100644 index 6726c9be..00000000 --- a/src/main/scala/coupledL2/tl2tl/AcquireUnit.scala +++ /dev/null @@ -1,54 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import utility._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import org.chipsalliance.cde.config.Parameters -import huancun.{DirtyKey, PreferCacheKey} -import coupledL2._ - -class AcquireUnit(implicit p: Parameters) extends L2Module { - val io = IO(new Bundle() { - val sourceA = DecoupledIO(new TLBundleA(edgeOut.bundle)) - val task = Flipped(DecoupledIO(new SourceAReq)) - }) - - val a = io.sourceA - val task = io.task.bits - - a.bits.opcode := task.opcode - a.bits.param := task.param - a.bits.size := offsetBits.U - a.bits.source := task.source - a.bits.address := Cat(task.tag, task.set, 0.U(offsetBits.W)) - a.bits.mask := Fill(edgeOut.manager.beatBytes, 1.U(1.W)) - a.bits.data := DontCare - a.bits.echo.lift(DirtyKey).foreach(_ := true.B) - a.bits.user.lift(PreferCacheKey).foreach(_ := false.B) - a.bits.user.lift(utility.ReqSourceKey).foreach(_ := task.reqSource) - a.bits.corrupt := false.B - - a.valid := io.task.valid - io.task.ready := a.ready - - dontTouch(io) -} diff --git a/src/main/scala/coupledL2/tl2tl/MSHR.scala b/src/main/scala/coupledL2/tl2tl/MSHR.scala deleted file mode 100644 index 36f11c9b..00000000 --- a/src/main/scala/coupledL2/tl2tl/MSHR.scala +++ /dev/null @@ -1,624 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import coupledL2.MetaData._ -import utility.{MemReqSource, ParallelLookUp, ParallelPriorityMux} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import freechips.rocketchip.tilelink.TLPermissions._ -import org.chipsalliance.cde.config.Parameters -import coupledL2._ -import coupledL2.prefetch.{PfSource, PrefetchTrain} - -class MSHRTasks(implicit p: Parameters) extends L2Bundle { - // outer - val source_a = DecoupledIO(new SourceAReq) // To AcquireUnit // TODO: no need to use decoupled handshake - val source_b = DecoupledIO(new SourceBReq) - val mainpipe = DecoupledIO(new TaskBundle) // To Mainpipe (SourceC or SourceD) - // val prefetchTrain = prefetchOpt.map(_ => DecoupledIO(new PrefetchTrain)) // To prefetcher -} - -class MSHRResps(implicit p: Parameters) extends L2Bundle { - val sink_c = Flipped(ValidIO(new RespInfoBundle)) - val sink_d = Flipped(ValidIO(new RespInfoBundle)) - // make sure that Acquire is sent after Release, - // so resp from SourceC is needed to initiate Acquire - val source_c = Flipped(ValidIO(new RespInfoBundle)) -} - -class MSHR(implicit p: Parameters) extends L2Module { - val io = IO(new Bundle() { - val id = Input(UInt(mshrBits.W)) - val status = ValidIO(new MSHRStatus) - val statAlloc = ValidIO(new MSHRAllocStatus) - val msInfo = ValidIO(new MSHRInfo) - val alloc = Flipped(ValidIO(new MSHRRequest)) - val tasks = new MSHRTasks() - val resps = new MSHRResps() - val nestedwb = Input(new NestedWriteback) - val nestedwbData = Output(Bool()) - val aMergeTask = Flipped(ValidIO(new TaskBundle)) - val replResp = Flipped(ValidIO(new ReplacerResult)) - }) - - val gotT = RegInit(false.B) // L3 might return T even though L2 wants B - val gotDirty = RegInit(false.B) - val gotGrantData = RegInit(false.B) - val probeDirty = RegInit(false.B) - val probeGotN = RegInit(false.B) - - val denied = RegInit(false.B) - val corrupt = RegInit(false.B) - - val timer = RegInit(0.U(64.W)) // for performance analysis - - /* MSHR Allocation */ - val req_valid = RegInit(false.B) - val req = RegInit(0.U.asTypeOf(new TaskBundle())) - val dirResult = RegInit(0.U.asTypeOf(new DirResult())) - val meta = dirResult.meta - val initState = Wire(new FSMState()) - initState.elements.foreach(_._2 := true.B) - val state = RegInit(new FSMState(), initState) - - when(io.alloc.valid) { - req_valid := true.B - state := io.alloc.bits.state - dirResult := io.alloc.bits.dirResult - req := io.alloc.bits.task - gotT := false.B - gotDirty := false.B - gotGrantData := false.B - probeDirty := false.B - probeGotN := false.B - denied := false.B - corrupt := false.B - timer := 1.U - } - - /* ======== Enchantment ======== */ - val meta_pft = meta.prefetch.getOrElse(false.B) - val meta_no_client = !meta.clients.orR - - val req_needT = needT(req.opcode, req.param) - val req_acquire = req.opcode === AcquireBlock && req.fromA || req.opcode === AcquirePerm // AcquireBlock and Probe share the same opcode - val req_acquirePerm = req.opcode === AcquirePerm - val req_get = req.opcode === Get - val req_prefetch = req.opcode === Hint - - val promoteT_normal = dirResult.hit && meta_no_client && meta.state === TIP - val promoteT_L3 = !dirResult.hit && gotT - val promoteT_alias = dirResult.hit && req.aliasTask.getOrElse(false.B) && (meta.state === TRUNK || meta.state === TIP) - // under above circumstances, we grant T to L1 even if it wants B - val req_promoteT = (req_acquire || req_get || req_prefetch) && (promoteT_normal || promoteT_L3 || promoteT_alias) - - assert(!(req_valid && req_prefetch && dirResult.hit), "MSHR can not receive prefetch hit req") - - /* ======== Task allocation ======== */ - // Theoretically, data to be released is saved in ReleaseBuffer, so Acquire can be sent as soon as req enters mshr - io.tasks.source_a.valid := !state.s_acquire - io.tasks.source_b.valid := !state.s_pprobe || !state.s_rprobe - val mp_release_valid = !state.s_release && state.w_rprobeacklast && state.w_grantlast && - state.w_replResp // release after Grant to L1 sent and replRead returns - - val mp_probeack_valid = !state.s_probeack && state.w_pprobeacklast - val mp_grant_valid = !state.s_refill && state.w_grantlast && state.w_rprobeacklast // [Alias] grant after rprobe done - io.tasks.mainpipe.valid := mp_release_valid || mp_probeack_valid || mp_grant_valid - // io.tasks.prefetchTrain.foreach(t => t.valid := !state.s_triggerprefetch.getOrElse(true.B)) - - val a_task = { - val oa = io.tasks.source_a.bits - oa.tag := req.tag - oa.set := req.set - oa.off := req.off - oa.source := io.id - oa.opcode := Mux( - req_acquirePerm && dirResult.hit, - req.opcode, - // Get or AcquireBlock - AcquireBlock - ) - oa.param := Mux( - req_needT, - Mux(dirResult.hit, BtoT, NtoT), - NtoB - ) - oa.size := req.size - oa.reqSource := req.reqSource - oa - } - - val b_task = { - val ob = io.tasks.source_b.bits - ob.tag := dirResult.tag - ob.set := dirResult.set - ob.off := 0.U - ob.opcode := Probe - ob.param := Mux( - !state.s_pprobe, - req.param, - Mux( - req_get && dirResult.hit && meta.state === TRUNK, - toB, - toN - ) - ) - ob.alias.foreach(_ := meta.alias.getOrElse(0.U)) - ob - } - val mp_release, mp_probeack, mp_grant = Wire(new TaskBundle) - val mp_release_task = { - mp_release := 0.U.asTypeOf(new TaskBundle) - mp_release.channel := req.channel - mp_release.tag := dirResult.tag - mp_release.set := req.set - mp_release.off := 0.U - mp_release.alias.foreach(_ := 0.U) - mp_release.vaddr.foreach(_ := req.vaddr.getOrElse(0.U)) - mp_release.isKeyword.foreach(_ := false.B) - // if dirty, we must ReleaseData - // if accessed, we ReleaseData to keep the data in L3, for future access to be faster - // [Access] TODO: consider use a counter - mp_release.opcode := { - cacheParams.releaseData match { - case 0 => Mux(meta.dirty && meta.state =/= INVALID || probeDirty, ReleaseData, Release) - case 1 => Mux(meta.dirty && meta.state =/= INVALID || probeDirty || meta.accessed, ReleaseData, Release) - case 2 => Mux(meta.prefetch.getOrElse(false.B) && !meta.accessed, Release, ReleaseData) //TODO: has problem with this - case 3 => ReleaseData // best performance with HuanCun-L3 - } - } - mp_release.param := Mux(isT(meta.state), TtoN, BtoN) - mp_release.size := 0.U(msgSizeBits.W) - mp_release.sourceId := 0.U(sourceIdBits.W) - mp_release.corrupt := false.B - mp_release.bufIdx := 0.U(bufIdxBits.W) - mp_release.needProbeAckData := false.B - mp_release.mshrTask := true.B - mp_release.mshrId := io.id - mp_release.aliasTask.foreach(_ := false.B) - // mp_release definitely read releaseBuf and refillBuf at ReqArb - // and it needs to write refillData to DS, so useProbeData is set false according to DS.wdata logic - mp_release.useProbeData := false.B - mp_release.readProbeDataDown := mp_release.opcode === ReleaseData - mp_release.mshrRetry := false.B - mp_release.way := dirResult.way - mp_release.fromL2pft.foreach(_ := false.B) - mp_release.needHint.foreach(_ := false.B) - mp_release.dirty := meta.dirty && meta.state =/= INVALID || probeDirty - mp_release.metaWen := false.B - mp_release.meta := MetaEntry() - mp_release.tagWen := false.B - mp_release.dsWen := true.B // write refillData to DS - mp_release.replTask := true.B - mp_release.wayMask := 0.U(cacheParams.ways.W) - mp_release.reqSource := 0.U(MemReqSource.reqSourceBits.W) - mp_release.mergeA := false.B - mp_release.aMergeTask := 0.U.asTypeOf(new MergeTaskBundle) - mp_release.txChannel := 0.U - mp_release - } - - val mp_probeack_task = { - mp_probeack := 0.U.asTypeOf(new TaskBundle) - mp_probeack.channel := req.channel - mp_probeack.tag := req.tag - mp_probeack.set := req.set - mp_probeack.off := req.off - mp_probeack.alias.foreach(_ := 0.U) - mp_probeack.vaddr.foreach(_ := req.vaddr.getOrElse(0.U)) - mp_probeack.isKeyword.foreach(_ := false.B) - mp_probeack.opcode := Mux( - meta.dirty && isT(meta.state) || probeDirty || req.needProbeAckData, - ProbeAckData, - ProbeAck - ) - mp_probeack.param := ParallelLookUp( - Cat(isT(meta.state), req.param(bdWidth - 1, 0)), - Seq( - Cat(false.B, toN) -> BtoN, - Cat(true.B, toN) -> TtoN, - Cat(true.B, toB) -> TtoB - ) - ) - mp_probeack.size := 0.U(msgSizeBits.W) - mp_probeack.sourceId := 0.U(sourceIdBits.W) - mp_probeack.corrupt := false.B - mp_probeack.bufIdx := 0.U(bufIdxBits.W) - mp_probeack.needProbeAckData := false.B - mp_probeack.mshrTask := true.B - mp_probeack.mshrId := io.id - mp_probeack.aliasTask.foreach(_ := false.B) - mp_probeack.useProbeData := true.B // write [probeAckData] to DS, if not probed toN - mp_probeack.readProbeDataDown := mp_probeack.opcode === ProbeAckData - mp_probeack.mshrRetry := false.B - mp_probeack.way := dirResult.way - mp_probeack.fromL2pft.foreach(_ := false.B) - mp_probeack.needHint.foreach(_ := false.B) - mp_probeack.dirty := meta.dirty && meta.state =/= INVALID || probeDirty - mp_probeack.meta := MetaEntry( - dirty = false.B, - state = Mux( - req.param === toN, - INVALID, - Mux( - req.param === toB, - BRANCH, - meta.state - ) - ), - clients = Fill(clientBits, !probeGotN), - alias = meta.alias, //[Alias] Keep alias bits unchanged - prefetch = req.param =/= toN && meta_pft, - accessed = req.param =/= toN && meta.accessed - ) - mp_probeack.metaWen := true.B - mp_probeack.tagWen := false.B - mp_probeack.dsWen := req.param =/= toN && probeDirty - mp_probeack.wayMask := 0.U(cacheParams.ways.W) - mp_probeack.reqSource := 0.U(MemReqSource.reqSourceBits.W) - mp_probeack.replTask := false.B - mp_probeack.mergeA := false.B - mp_probeack.aMergeTask := 0.U.asTypeOf(new MergeTaskBundle) - mp_probeack.txChannel := 0.U - mp_probeack - } - - - val mergeA = RegInit(false.B) - when(io.aMergeTask.valid) { - mergeA := true.B - }.elsewhen(io.alloc.valid) { - mergeA := false.B - } - val mp_grant_task = { - mp_grant := 0.U.asTypeOf(new TaskBundle) - mp_grant.channel := req.channel - mp_grant.tag := req.tag - mp_grant.set := req.set - mp_grant.off := req.off - mp_grant.sourceId := req.sourceId - mp_grant.alias.foreach(_ := 0.U) - mp_grant.vaddr.foreach(_ := req.vaddr.getOrElse(0.U)) - mp_grant.isKeyword.foreach(_ := req.isKeyword.getOrElse(false.B)) - mp_grant.opcode := odOpGen(req.opcode) - mp_grant.param := Mux( - req_get || req_prefetch, - 0.U, // Get -> AccessAckData - MuxLookup( // Acquire -> Grant - req.param, - req.param)( - Seq( - NtoB -> Mux(req_promoteT, toT, toB), - BtoT -> toT, - NtoT -> toT - ) - ) - ) - mp_grant.size := 0.U(msgSizeBits.W) - mp_grant.bufIdx := 0.U(bufIdxBits.W) - mp_grant.needProbeAckData := false.B - mp_grant.mshrTask := true.B - mp_grant.mshrId := io.id - mp_grant.way := dirResult.way - // if it is a Get or Prefetch, then we must keep alias bits unchanged - // in case future probes gets the wrong alias bits - val aliasFinal = Mux(req_get || req_prefetch, meta.alias.getOrElse(0.U), req.alias.getOrElse(0.U)) - mp_grant.alias.foreach(_ := aliasFinal) - mp_grant.aliasTask.foreach(_ := req.aliasTask.getOrElse(false.B)) - // [Alias] write probeData into DS for alias-caused Probe, but not replacement-caused Probe - // Exception case when multi-core: if aliasTask is AcquireBlock NtoT and self_state is Branch, - // and there is a nested Probe toN from L3 (means the data Granted from L3 in the future may be a new data), - // useProbeData will be set false to use data in RefillBuffer - mp_grant.useProbeData := (dirResult.hit && req_get) || - (req.aliasTask.getOrElse(false.B) && - !(dirResult.meta.state === BRANCH && req_needT) - ) - mp_grant.readProbeDataDown := false.B - mp_grant.dirty := false.B - - mp_grant.meta := MetaEntry( - dirty = gotDirty || dirResult.hit && (meta.dirty || probeDirty), - state = Mux( - req_get, - Mux( // Get - dirResult.hit, - Mux(isT(meta.state), TIP, BRANCH), - Mux(req_promoteT, TIP, BRANCH) - ), - Mux( // Acquire - req_promoteT || req_needT, - Mux(req_prefetch, TIP, TRUNK), - BRANCH - ) - ), - clients = Mux( - req_prefetch, - Mux(dirResult.hit, meta.clients, Fill(clientBits, false.B)), - Fill(clientBits, !(req_get && (!dirResult.hit || meta_no_client || probeGotN))) - ), - alias = Some(aliasFinal), - prefetch = req_prefetch || dirResult.hit && meta_pft, - pfsrc = PfSource.fromMemReqSource(req.reqSource), - accessed = req_acquire || req_get - ) - mp_grant.metaWen := true.B - mp_grant.tagWen := !dirResult.hit - mp_grant.dsWen := gotGrantData || probeDirty && (req_get || req.aliasTask.getOrElse(false.B)) - mp_grant.fromL2pft.foreach(_ := req.fromL2pft.get) - mp_grant.needHint.foreach(_ := false.B) - mp_grant.replTask := !dirResult.hit // Get and Alias are hit that does not need replacement - mp_grant.wayMask := 0.U(cacheParams.ways.W) - mp_grant.mshrRetry := !state.s_retry - mp_grant.reqSource := 0.U(MemReqSource.reqSourceBits.W) - mp_grant.denied := denied - mp_grant.corrupt := corrupt - - // Add merge grant task for Acquire and late Prefetch - mp_grant.mergeA := mergeA - - val merge_task = RegEnable(io.aMergeTask.bits, 0.U.asTypeOf(new TaskBundle), io.aMergeTask.valid) - - mp_grant.aMergeTask.off := merge_task.off - mp_grant.aMergeTask.alias.foreach(_ := merge_task.alias.getOrElse(0.U)) - mp_grant.aMergeTask.vaddr.foreach(_ := merge_task.vaddr.getOrElse(0.U)) - mp_grant.aMergeTask.isKeyword.foreach(_ := merge_task.isKeyword.getOrElse(false.B)) - mp_grant.aMergeTask.opcode := odOpGen(merge_task.opcode) - mp_grant.aMergeTask.param := MuxLookup( // Acquire -> Grant - merge_task.param, - merge_task.param)( - Seq( - NtoB -> Mux(req_promoteT, toT, toB), - BtoT -> toT, - NtoT -> toT - ) - ) - mp_grant.aMergeTask.sourceId := merge_task.sourceId - mp_grant.aMergeTask.meta := MetaEntry( - dirty = gotDirty || dirResult.hit && (meta.dirty || probeDirty), - state = Mux( // Acquire - req_promoteT || needT(merge_task.opcode, merge_task.param), - TRUNK, - BRANCH - ), - clients = Fill(clientBits, true.B), - alias = Some(merge_task.alias.getOrElse(0.U)), - prefetch = false.B, - accessed = true.B - ) - mp_grant.txChannel := 0.U - mp_grant.aMergeTask.pc.foreach(_ := merge_task.pc.getOrElse(0.U)) - - mp_grant - } - io.tasks.mainpipe.bits := ParallelPriorityMux( - Seq( - mp_grant_valid -> mp_grant, - mp_release_valid -> mp_release, - mp_probeack_valid -> mp_probeack - ) - ) - io.tasks.mainpipe.bits.reqSource := req.reqSource - io.tasks.mainpipe.bits.isKeyword.foreach(_:= req.isKeyword.getOrElse(false.B)) - // io.tasks.prefetchTrain.foreach { - // train => - // train.bits.tag := req.tag - // train.bits.set := req.set - // train.bits.needT := req_needT - // train.bits.source := req.source - // } - - /* ======== Task update ======== */ - when (io.tasks.source_a.fire) { - state.s_acquire := true.B - } - when (io.tasks.source_b.fire) { - state.s_pprobe := true.B - state.s_rprobe := true.B - } - when (io.tasks.mainpipe.ready) { - when (mp_grant_valid) { - state.s_refill := true.B - state.s_retry := true.B - }.elsewhen (mp_release_valid) { - state.s_release := true.B - meta.state := INVALID - }.elsewhen (mp_probeack_valid) { - state.s_probeack := true.B - } - } - // prefetchOpt.foreach { - // _ => - // when (io.tasks.prefetchTrain.get.fire) { - // state.s_triggerprefetch.get := true.B - // } - // } - - /* ======== Handling response ======== */ - val c_resp = io.resps.sink_c - val d_resp = io.resps.sink_d - when (c_resp.valid) { - when (c_resp.bits.opcode === ProbeAck || c_resp.bits.opcode === ProbeAckData) { - state.w_rprobeackfirst := true.B - state.w_rprobeacklast := state.w_rprobeacklast || c_resp.bits.last - state.w_pprobeackfirst := true.B - state.w_pprobeacklast := state.w_pprobeacklast || c_resp.bits.last - } - when (c_resp.bits.opcode === ProbeAckData) { - probeDirty := true.B - } - when (isToN(c_resp.bits.param)) { - probeGotN := true.B - } - } - - when (d_resp.valid) { - when(d_resp.bits.opcode === Grant || d_resp.bits.opcode === GrantData || d_resp.bits.opcode === AccessAck) { - state.w_grantfirst := true.B - state.w_grantlast := d_resp.bits.last - state.w_grant := req.off === 0.U || d_resp.bits.last // TODO? why offset? - } - when(d_resp.bits.opcode === Grant || d_resp.bits.opcode === GrantData) { - gotT := d_resp.bits.param === toT - gotDirty := gotDirty || d_resp.bits.dirty - } - when(d_resp.bits.opcode === GrantData) { - gotGrantData := true.B - corrupt := d_resp.bits.corrupt - } - when(d_resp.bits.opcode === ReleaseAck) { - state.w_releaseack := true.B - } - } - - val replResp = io.replResp.bits - when (io.replResp.valid && replResp.retry) { - state.s_refill := false.B - state.s_retry := false.B - dirResult.way := replResp.way - } - when (io.replResp.valid && !replResp.retry) { - state.w_replResp := true.B - - // update meta (no need to update hit/set/error/replacerInfo of dirResult) - dirResult.tag := replResp.tag - dirResult.way := replResp.way - dirResult.meta := replResp.meta - - // replacer choosing: - // 1. an invalid way, release no longer needed - // 2. the same way, just release as normal (only now we set s_release) - // 3. differet way, we need to update meta and release that way - // if meta has client, rprobe client - when (replResp.meta.state =/= INVALID) { - // set release flags - state.s_release := false.B - state.w_releaseack := false.B - // rprobe clients if any - when(replResp.meta.clients.orR) { - state.s_rprobe := false.B - state.w_rprobeackfirst := false.B - state.w_rprobeacklast := false.B - } - } - } - - when (req_valid) { - timer := timer + 1.U - } - - val no_schedule = state.s_refill && state.s_probeack && state.s_release // && state.s_triggerprefetch.getOrElse(true.B) - val no_wait = state.w_rprobeacklast && state.w_pprobeacklast && state.w_grantlast && state.w_releaseack && state.w_replResp - val will_free = no_schedule && no_wait - when (will_free && req_valid) { - req_valid := false.B - timer := 0.U - } - - // alias: should protect meta from being accessed or occupied - val releaseNotSent = !state.s_release - io.status.valid := req_valid - io.status.bits.channel := req.channel - io.status.bits.txChannel := DontCare // this signal is for chi - io.status.bits.set := req.set - io.status.bits.reqTag := req.tag - io.status.bits.metaTag := dirResult.tag - io.status.bits.needsRepl := releaseNotSent - // wait for resps, high as valid - io.status.bits.w_c_resp := !state.w_rprobeacklast || !state.w_pprobeacklast - io.status.bits.w_d_resp := !state.w_grantlast || !state.w_grant || !state.w_releaseack - io.status.bits.will_free := will_free - io.status.bits.is_miss := !dirResult.hit - io.status.bits.is_prefetch := req_prefetch - io.status.bits.reqSource := req.reqSource - - io.statAlloc.valid := io.alloc.valid - io.statAlloc.bits.is_miss := !io.alloc.bits.dirResult.hit - io.statAlloc.bits.is_prefetch := io.alloc.bits.task.opcode === Hint - io.statAlloc.bits.channel := io.alloc.bits.task.channel - - io.msInfo.valid := req_valid - io.msInfo.bits.set := req.set - io.msInfo.bits.way := dirResult.way - io.msInfo.bits.reqTag := req.tag - io.msInfo.bits.reqSource := req.reqSource - io.msInfo.bits.aliasTask.foreach(_ := req.aliasTask.getOrElse(false.B)) - io.msInfo.bits.needRelease := !state.w_releaseack - // if releaseTask is already in mainpipe_s1/s2, while a refillTask in mainpipe_s3, the refill should also be blocked and retry - io.msInfo.bits.blockRefill := releaseNotSent || RegNext(releaseNotSent,false.B) || RegNext(RegNext(releaseNotSent,false.B),false.B) - io.msInfo.bits.dirHit := dirResult.hit - io.msInfo.bits.metaTag := dirResult.tag - io.msInfo.bits.willFree := will_free - io.msInfo.bits.isAcqOrPrefetch := req_acquire || req_prefetch - io.msInfo.bits.isPrefetch := req_prefetch - io.msInfo.bits.param := req.param - io.msInfo.bits.mergeA := mergeA - io.msInfo.bits.w_grantfirst := state.w_grantfirst - io.msInfo.bits.w_grantlast := state.w_grantlast - io.msInfo.bits.w_grant := state.w_grant - io.msInfo.bits.s_refill := state.s_refill - io.msInfo.bits.s_release := state.s_release - io.msInfo.bits.s_cmoresp := true.B - io.msInfo.bits.s_cmometaw := true.B - io.msInfo.bits.w_releaseack := state.w_releaseack - io.msInfo.bits.w_replResp := state.w_replResp - io.msInfo.bits.w_rprobeacklast := state.w_rprobeacklast - io.msInfo.bits.replaceData := mp_release.opcode === ReleaseData - io.msInfo.bits.releaseToClean := false.B - io.msInfo.bits.meta := meta - io.msInfo.bits.meta.dirty := meta.dirty || probeDirty - io.msInfo.bits.channel := req.channel - - assert(!(c_resp.valid && !io.status.bits.w_c_resp)) - assert(!(d_resp.valid && !io.status.bits.w_d_resp)) - - /* ======== Handling Nested C ======== */ - // for A miss, only when replResp do we finally choose a way, allowing nested C - // for A-alias, always allowing nested C (state.w_replResp === true.B) - val nestedwb_match = req_valid && meta.state =/= INVALID && - dirResult.set === io.nestedwb.set && - dirResult.tag === io.nestedwb.tag && - state.w_replResp - - when (nestedwb_match) { - when (io.nestedwb.c_set_dirty) { - meta.dirty := true.B - } - } - // let nested C write ReleaseData to the MSHRBuffer entry of this MSHR id - // This is the VALID signal for releaseBuf.io.w(2) - io.nestedwbData := nestedwb_match && io.nestedwb.c_set_dirty - - dontTouch(state) - - /* ======== Performance counters ======== */ - // time stamp - // if (cacheParams.enablePerf) { - val acquire_ts = RegEnable(timer, false.B, io.tasks.source_a.fire) - val probe_ts = RegEnable(timer, false.B, io.tasks.source_b.fire) - val release_ts = RegEnable(timer, false.B, !mp_grant_valid && mp_release_valid && io.tasks.mainpipe.ready) - val acquire_period = IO(Output(UInt(64.W))) - val probe_period = IO(Output(UInt(64.W))) - val release_period = IO(Output(UInt(64.W))) - acquire_period := timer - acquire_ts - probe_period := timer - probe_ts - release_period := timer - release_ts - // } -} diff --git a/src/main/scala/coupledL2/tl2tl/MSHRCtl.scala b/src/main/scala/coupledL2/tl2tl/MSHRCtl.scala deleted file mode 100644 index 7202d67e..00000000 --- a/src/main/scala/coupledL2/tl2tl/MSHRCtl.scala +++ /dev/null @@ -1,255 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import utility._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import coupledL2._ -import coupledL2.prefetch.PrefetchTrain - -class MSHRSelector(implicit p: Parameters) extends L2Module { - val io = IO(new Bundle() { - val idle = Input(Vec(mshrsAll, Bool())) - val out = ValidIO(UInt(mshrsAll.W)) - }) - io.out.valid := ParallelOR(io.idle) - io.out.bits := ParallelPriorityMux(io.idle.zipWithIndex.map { - case (b, i) => (b, (1 << i).U) - }) -} - -class MSHRCtl(implicit p: Parameters) extends L2Module with HasPerfEvents { - val io = IO(new Bundle() { - /* interact with req arb */ - val fromReqArb = Input(new Bundle() { - val status_s1 = new PipeEntranceStatus - }) - val toReqArb = Output(new BlockInfo()) - - /* interact with mainpipe */ - val fromMainPipe = new Bundle() { - val mshr_alloc_s3 = Flipped(ValidIO(new MSHRRequest)) - } - val toMainPipe = new Bundle() { - val mshr_alloc_ptr = Output(UInt(mshrBits.W)) - } - - /* to request arbiter */ - // val mshrFull = Output(Bool()) - val mshrTask = DecoupledIO(new TaskBundle()) - - /* send reqs */ - val sourceA = DecoupledIO(new TLBundleA(edgeOut.bundle)) - val sourceB = DecoupledIO(new TLBundleB(edgeIn.bundle)) - // val prefetchTrain = prefetchOpt.map(_ => DecoupledIO(new PrefetchTrain)) - val grantStatus = Input(Vec(grantBufInflightSize, new GrantStatus)) - - /* receive resps */ - val resps = Input(new Bundle() { - val sinkC = new RespBundle - val sinkD = new RespBundle - val sourceC = new RespBundle - }) - - val releaseBufWriteId = Output(UInt(mshrBits.W)) - - /* nested writeback */ - val nestedwb = Input(new NestedWriteback) - val nestedwbDataId = Output(ValidIO(UInt(mshrBits.W))) - - /* status of s2 and s3 */ - val pipeStatusVec = Flipped(Vec(2, ValidIO(new PipeStatus))) - - /* MSHR info to Sinks */ - /* to ReqBuffer, to calculate conflict */ - /* to SinkB, to merge nested B req */ - val msInfo = Vec(mshrsAll, ValidIO(new MSHRInfo)) - val aMergeTask = Flipped(ValidIO(new AMergeTask)) - - /* refill read replacer result */ - val replResp = Flipped(ValidIO(new ReplacerResult)) - - /* for TopDown Monitor */ - val msStatus = topDownOpt.map(_ => Vec(mshrsAll, ValidIO(new MSHRStatus))) - val msAlloc = topDownOpt.map(_ => Vec(mshrsAll, ValidIO(new MSHRAllocStatus))) - - /* for TopDown */ - val l2Miss = Output(Bool()) - }) - - val mshrs = Seq.fill(mshrsAll) { Module(new MSHR()) } - val mshrValids = VecInit(mshrs.map(m => m.io.status.valid)) - - val pipeReqCount = PopCount(Cat(io.pipeStatusVec.map(_.valid))) // TODO: consider add !mshrTask to optimize - val mshrCount = PopCount(Cat(mshrs.map(_.io.status.valid))) - val mshrFull = pipeReqCount + mshrCount >= mshrsAll.U - val a_mshrFull = pipeReqCount + mshrCount >= (mshrsAll-1).U // the last idle mshr should not be allocated for channel A req - val mshrSelector = Module(new MSHRSelector()) - mshrSelector.io.idle := mshrs.map(m => !m.io.status.valid) - val selectedMSHROH = mshrSelector.io.out.bits - io.toMainPipe.mshr_alloc_ptr := OHToUInt(selectedMSHROH) - io.l2Miss := Cat(mshrs.map { m => - m.io.status.valid && m.io.status.bits.channel(0) && ( - m.io.status.bits.reqSource === MemReqSource.CPULoadData.id.U || - m.io.status.bits.reqSource === MemReqSource.CPUStoreData.id.U - ) - }).orR - - val resp_sinkC_match_vec = mshrs.map { mshr => - val status = mshr.io.status.bits - val tag = Mux(status.needsRepl, status.metaTag, status.reqTag) - mshr.io.status.valid && status.w_c_resp && io.resps.sinkC.set === status.set && io.resps.sinkC.tag === tag - } - - mshrs.zipWithIndex.foreach { - case (m, i) => - m.io.id := i.U - m.io.alloc.valid := selectedMSHROH(i) && io.fromMainPipe.mshr_alloc_s3.valid - m.io.alloc.bits := io.fromMainPipe.mshr_alloc_s3.bits - m.io.alloc.bits.task.isKeyword.foreach(_:= io.fromMainPipe.mshr_alloc_s3.bits.task.isKeyword.getOrElse(false.B)) - - m.io.resps.sink_c.valid := io.resps.sinkC.valid && resp_sinkC_match_vec(i) - m.io.resps.sink_c.bits := io.resps.sinkC.respInfo - m.io.resps.sink_d.valid := m.io.status.valid && io.resps.sinkD.valid && io.resps.sinkD.mshrId === i.U - m.io.resps.sink_d.bits := io.resps.sinkD.respInfo - m.io.resps.source_c.valid := m.io.status.valid && io.resps.sourceC.valid && io.resps.sourceC.mshrId === i.U - m.io.resps.source_c.bits := io.resps.sourceC.respInfo - m.io.replResp.valid := io.replResp.valid && io.replResp.bits.mshrId === i.U - m.io.replResp.bits := io.replResp.bits - - io.msInfo(i) := m.io.msInfo - m.io.nestedwb := io.nestedwb - m.io.aMergeTask.valid := io.aMergeTask.valid && io.aMergeTask.bits.idOH(i) - m.io.aMergeTask.bits := io.aMergeTask.bits.task - } - - io.toReqArb.blockC_s1 := false.B - io.toReqArb.blockB_s1 := mshrFull // conflict logic in SinkB - io.toReqArb.blockA_s1 := a_mshrFull // conflict logic in ReqBuf - io.toReqArb.blockG_s1 := false.B - - /* Acquire downwards */ - val acquireUnit = Module(new AcquireUnit()) - ArbPerf(twoLevelArb(mshrs.map(_.io.tasks.source_a), acquireUnit.io.task, Some("source_a")), "source_a_arb") - io.sourceA <> acquireUnit.io.sourceA - - /* Probe upwards */ - val sourceB = Module(new SourceB()) - ArbPerf(twoLevelArb(mshrs.map(_.io.tasks.source_b), sourceB.io.task, Some("source_b")), "source_b_arb") - sourceB.io.grantStatus := io.grantStatus - io.sourceB <> sourceB.io.sourceB - - /* Arbitrate MSHR task to RequestArbiter */ - ArbPerf(twoLevelArb(mshrs.map(_.io.tasks.mainpipe), io.mshrTask, Some("mshr_task")), "mshr_task_arb") - - /* Arbitrate prefetchTrains to Prefetcher */ - // prefetchOpt.foreach { - // _ => - // fastArb(mshrs.map(_.io.tasks.prefetchTrain.get), io.prefetchTrain.get, Some("prefetch_train")) - // } - - io.releaseBufWriteId := ParallelPriorityMux(resp_sinkC_match_vec, (0 until mshrsAll).map(i => i.U)) - - io.nestedwbDataId.valid := Cat(mshrs.map(_.io.nestedwbData)).orR - io.nestedwbDataId.bits := ParallelPriorityMux(mshrs.zipWithIndex.map { - case (mshr, i) => (mshr.io.nestedwbData, i.U) - }) - assert(RegNext(PopCount(mshrs.map(_.io.nestedwbData)) <= 1.U), "should only be one nestedwbData") - - dontTouch(io.sourceA) - - topDownOpt.foreach { _ => - io.msStatus.get.zip(io.msAlloc.get).zip(mshrs).foreach { - case ((statusOut, allocOut), mshr) => - // status - statusOut := mshr.io.status - // alloc - allocOut := mshr.io.statAlloc - } - } - - // Performance counters - XSPerfAccumulate("capacity_conflict_to_sinkA", a_mshrFull) - XSPerfAccumulate("capacity_conflict_to_sinkB", mshrFull) - XSPerfHistogram("mshr_alloc", io.toMainPipe.mshr_alloc_ptr, - enable = io.fromMainPipe.mshr_alloc_s3.valid, - start = 0, stop = mshrsAll, step = 1) - // prefetchOpt.foreach { - // _ => - // XSPerfAccumulate("prefetch_trains", io.prefetchTrain.get.fire) - // } - - if (cacheParams.enablePerf) { - val start = 0 - val stop = 100 - val step = 5 - val acquire_period = ParallelMux(mshrs.map { case m => m.io.resps.sink_d.valid -> m.acquire_period }) - val release_period = ParallelMux(mshrs.map { case m => m.io.resps.sink_d.valid -> m.release_period }) - val probe_period = ParallelMux(mshrs.map { case m => m.io.resps.sink_c.valid -> m.probe_period }) - val acquire_period_en = io.resps.sinkD.valid && - (io.resps.sinkD.respInfo.opcode === Grant || io.resps.sinkD.respInfo.opcode === GrantData) - val release_period_en = io.resps.sinkD.valid && io.resps.sinkD.respInfo.opcode === ReleaseAck - val probe_period_en = io.resps.sinkC.valid && - (io.resps.sinkC.respInfo.opcode === ProbeAck || io.resps.sinkC.respInfo.opcode === ProbeAckData) - XSPerfHistogram("acquire_period", acquire_period, acquire_period_en, start, stop, step) - XSPerfHistogram("release_period", release_period, release_period_en, start, stop, step) - XSPerfHistogram("probe_period", probe_period, probe_period_en, start, stop, step) - - val timers = RegInit(VecInit(Seq.fill(mshrsAll)(0.U(64.W)))) - for (((timer, m), i) <- timers.zip(mshrs).zipWithIndex) { - when (m.io.alloc.valid) { - timer := 1.U - }.otherwise { - timer := timer + 1.U - } - val enable = m.io.status.valid && m.io.status.bits.will_free - XSPerfHistogram("mshr_latency_" + Integer.toString(i, 10), - timer, enable, 0, 300, 10) - XSPerfMax("mshr_latency", timer, enable) - } - } - - val hpm_timers = RegInit(VecInit(Seq.fill(mshrsAll)(0.U(10.W)))) - // TODO: Is the width(4.W) proper here? - val lmiss = Wire(Vec(mshrsAll, UInt(4.W))) - for (((hpm_timer, m), i) <- hpm_timers.zip(mshrs).zipWithIndex) { - when (m.io.alloc.valid) { - hpm_timer := 1.U - }.otherwise { - hpm_timer := hpm_timer + 1.U - } - val enable = m.io.status.valid && m.io.status.bits.will_free - when (enable && hpm_timer > 200.U) { - lmiss(i) := 1.U - }.otherwise { - lmiss(i) := 0.U - } - } - - val perfEvents = Seq( - ("l2_cache_refill", acquireUnit.io.sourceA.fire && acquireUnit.io.task.bits.opcode === AcquireBlock), - ("l2_cache_rd_refill", acquireUnit.io.sourceA.fire && acquireUnit.io.task.bits.opcode === AcquireBlock), - ("l2_cache_wr_refill", false.B), - ("l2_cache_long_miss", lmiss.reduce(_ + _)) - ) - generatePerfEvent() -} diff --git a/src/main/scala/coupledL2/tl2tl/MainPipe.scala b/src/main/scala/coupledL2/tl2tl/MainPipe.scala deleted file mode 100644 index b316f259..00000000 --- a/src/main/scala/coupledL2/tl2tl/MainPipe.scala +++ /dev/null @@ -1,779 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import utility._ -import coupledL2.MetaData._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import freechips.rocketchip.tilelink.TLPermissions._ -import coupledL2._ -import coupledL2.utils._ -import coupledL2.debug._ -import coupledL2.prefetch.{PfSource, PrefetchTrain} - -class MainPipe(implicit p: Parameters) extends L2Module with HasPerfEvents { - val io = IO(new Bundle() { - /* receive task from arbiter at stage 2 */ - val taskFromArb_s2 = Flipped(ValidIO(new TaskBundle())) - /* receive s1 info for Hint */ - val mshrHintQInfo = Flipped(ValidIO(new TaskBundle)) - val sinkCHintQInfo = Flipped(ValidIO(new TaskBundle)) - - /* handle set conflict in req arb */ - val fromReqArb = Input(new Bundle() { - val status_s1 = new PipeEntranceStatus - }) - /* block B and C at Entrance */ - val toReqArb = Output(new BlockInfo()) - - /* block A at Entrance */ - val toReqBuf = Output(Vec(2, Bool())) - - /* handle capacity conflict of GrantBuffer */ - val status_vec_toD = Vec(3, ValidIO(new PipeStatus)) - /* handle capacity conflict of SourceC */ - val status_vec_toC = Vec(3, ValidIO(new PipeStatus)) - - /* get dir result at stage 3 */ - val dirResp_s3 = Input(new DirResult) - val replResp = Flipped(ValidIO(new ReplacerResult)) - val retryFastFwd_s2 = Input(Bool()) - - /* send task to MSHRCtl at stage 3 */ - val toMSHRCtl = new Bundle() { - val mshr_alloc_s3 = ValidIO(new MSHRRequest()) - } - - val fromMSHRCtl = new Bundle() { - val mshr_alloc_ptr = Input(UInt(mshrBits.W)) - } - - /* read C-channel Release Data and write into DS */ - val bufResp = Input(new PipeBufferResp) - - /* get ReleaseBuffer and RefillBuffer read result */ - val refillBufResp_s3 = Flipped(ValidIO(new DSBlock)) - val releaseBufResp_s3 = Flipped(ValidIO(new DSBlock)) - - /* read or write data storage */ - val toDS = new Bundle() { - val en_s3 = Output(Bool()) - val req_s3 = ValidIO(new DSRequest) - val rdata_s5 = Input(new DSBlock) - val wdata_s3 = Output(new DSBlock) - val error_s5 = Input(Bool()) - } - - /* send Release/Grant/ProbeAck via SourceC/D channels */ - val toSourceC, toSourceD = DecoupledIO(new Bundle() { - val task = new TaskBundle - val data = new DSBlock - }) - - /* write dir, including reset dir */ - val metaWReq = ValidIO(new MetaWrite) - val tagWReq = ValidIO(new TagWrite) - - /* read DS and write data into ReleaseBuf when the task needs to replace */ - val releaseBufWrite = ValidIO(new MSHRBufWrite()) - - val nestedwb = Output(new NestedWriteback) - val nestedwbData = Output(new DSBlock) - - /* send Hint to L1 */ - val l1Hint = DecoupledIO(new L2ToL1HintInsideL2()) - - /* send prefetchTrain to Prefetch to trigger a prefetch req */ - val prefetchTrain = prefetchOpt.map(_ => DecoupledIO(new PrefetchTrain)) - - val toMonitor = Output(new MainpipeMoni()) - - /* ECC error*/ - val error = ValidIO(new L2CacheErrorInfo) - }) - - val resetFinish = RegInit(false.B) - val resetIdx = RegInit((cacheParams.sets - 1).U) - /* block reqs when reset */ - when(!resetFinish) { - resetIdx := resetIdx - 1.U - } - when(resetIdx === 0.U) { - resetFinish := true.B - } - - val c_s3, c_s4, c_s5 = Wire(io.toSourceC.cloneType) - val d_s3, d_s4, d_s5 = Wire(io.toSourceD.cloneType) - - /* ======== Stage 2 ======== */ - // send out MSHR task if data is not needed - val task_s2 = io.taskFromArb_s2 - val hasData_s2 = task_s2.bits.opcode(0) - - /* ======== Stage 3 ======== */ - val task_s3 = RegInit(0.U.asTypeOf(Valid(new TaskBundle()))) - task_s3.valid := task_s2.valid - when(task_s2.valid) { - task_s3.bits := task_s2.bits - } - - /* ======== Enchantment ======== */ - val dirResult_s3 = io.dirResp_s3 - val meta_s3 = dirResult_s3.meta - val req_s3 = task_s3.bits - - val tagError_s3 = io.dirResp_s3.error || meta_s3.tagErr - val dataError_s3 = meta_s3.dataErr - val l2Error_s3 = io.dirResp_s3.error - - val mshr_req_s3 = req_s3.mshrTask - val sink_req_s3 = !mshr_req_s3 - val sinkA_req_s3 = !mshr_req_s3 && req_s3.fromA - val sinkB_req_s3 = !mshr_req_s3 && req_s3.fromB - val sinkC_req_s3 = !mshr_req_s3 && req_s3.fromC - - val req_acquire_s3 = sinkA_req_s3 && (req_s3.opcode === AcquireBlock || req_s3.opcode === AcquirePerm) - val req_acquireBlock_s3 = sinkA_req_s3 && req_s3.opcode === AcquireBlock - val req_prefetch_s3 = sinkA_req_s3 && req_s3.opcode === Hint - val req_get_s3 = sinkA_req_s3 && req_s3.opcode === Get - - val mshr_grant_s3 = mshr_req_s3 && req_s3.fromA && (req_s3.opcode === Grant || req_s3.opcode === GrantData) // Grant or GrantData from mshr - val mshr_grantdata_s3 = mshr_req_s3 && req_s3.fromA && req_s3.opcode === GrantData - val mshr_accessackdata_s3 = mshr_req_s3 && req_s3.fromA && req_s3.opcode === AccessAckData - val mshr_hintack_s3 = mshr_req_s3 && req_s3.fromA && req_s3.opcode === HintAck - val mshr_probeack_s3 = mshr_req_s3 && req_s3.fromB && (req_s3.opcode === ProbeAck || req_s3.opcode === ProbeAckData) // ProbeAck or ProbeAckData from mshr - val mshr_probeackdata_s3 = mshr_req_s3 && req_s3.fromB && req_s3.opcode === ProbeAckData - val mshr_release_s3 = mshr_req_s3 && (req_s3.opcode === Release || req_s3.opcode === ReleaseData) // voluntary Release or ReleaseData from mshr - val mshr_releasedata_s3 = mshr_req_s3 && req_s3.opcode === ReleaseData - - val meta_has_clients_s3 = meta_s3.clients.orR - val req_needT_s3 = needT(req_s3.opcode, req_s3.param) // require T status to handle req -// val a_need_replacement = sinkA_req_s3 && !dirResult_s3.hit && meta_s3.state =/= INVALID // b and c do not need replacement - - //[Alias] TODO: consider 1 client for now - val cache_alias = req_acquire_s3 && dirResult_s3.hit && meta_s3.clients(0) && - meta_s3.alias.getOrElse(0.U) =/= req_s3.alias.getOrElse(0.U) - - val mshr_refill_s3 = (mshr_accessackdata_s3 || mshr_hintack_s3 || mshr_grant_s3) // needs refill to L2 DS - val retry = io.replResp.bits.retry - val need_repl = io.replResp.bits.meta.state =/= INVALID && req_s3.replTask // Grant needs replacement - - /* ======== Interact with MSHR ======== */ - val acquire_on_miss_s3 = req_acquire_s3 || req_prefetch_s3 || req_get_s3 // TODO: remove this cause always acquire on miss? - val acquire_on_hit_s3 = meta_s3.state === BRANCH && req_needT_s3 && !req_prefetch_s3 - // For channel A reqs, alloc mshr when: acquire downwards is needed || alias - val need_acquire_s3_a = req_s3.fromA && Mux( - dirResult_s3.hit, - acquire_on_hit_s3, - acquire_on_miss_s3 - ) - val need_probe_s3_a = req_get_s3 && dirResult_s3.hit && meta_s3.state === TRUNK - - val need_mshr_s3_a = need_acquire_s3_a || need_probe_s3_a || cache_alias - // For channel B reqs, alloc mshr when Probe hits in both self and client dir - val need_mshr_s3_b = dirResult_s3.hit && req_s3.fromB && - !((meta_s3.state === BRANCH || meta_s3.state === TIP) && req_s3.param === toB) && - meta_has_clients_s3 - - // For channel C reqs, Release will always hit on MainPipe, no need for MSHR - val need_mshr_s3 = need_mshr_s3_a || need_mshr_s3_b - - /* Signals to MSHR Ctl */ - // Allocation of MSHR: new request only - val alloc_state = WireInit(0.U.asTypeOf(new FSMState())) - alloc_state.elements.foreach(_._2 := true.B) - io.toMSHRCtl.mshr_alloc_s3.valid := task_s3.valid && !mshr_req_s3 && need_mshr_s3 - io.toMSHRCtl.mshr_alloc_s3.bits.dirResult := dirResult_s3 - io.toMSHRCtl.mshr_alloc_s3.bits.state := alloc_state - - val ms_task = io.toMSHRCtl.mshr_alloc_s3.bits.task - ms_task.channel := req_s3.channel - ms_task.set := req_s3.set - ms_task.tag := req_s3.tag - ms_task.off := req_s3.off - ms_task.alias.foreach(_ := req_s3.alias.getOrElse(0.U)) - ms_task.vaddr.foreach(_ := req_s3.vaddr.getOrElse(0.U)) - ms_task.isKeyword.foreach(_ := req_s3.isKeyword.get) //OrElse(false.B)) - ms_task.pc.foreach(_ := req_s3.pc.getOrElse(0.U)) - ms_task.opcode := req_s3.opcode - ms_task.param := req_s3.param - ms_task.size := req_s3.size - ms_task.sourceId := req_s3.sourceId - ms_task.bufIdx := 0.U(bufIdxBits.W) - ms_task.needProbeAckData := req_s3.needProbeAckData - ms_task.mshrTask := false.B - ms_task.mshrId := 0.U(mshrBits.W) - ms_task.aliasTask.foreach(_ := cache_alias) - ms_task.useProbeData := false.B - ms_task.readProbeDataDown := false.B - ms_task.mshrRetry := false.B - ms_task.fromL2pft.foreach(_ := req_s3.fromL2pft.get) - ms_task.needHint.foreach(_ := req_s3.needHint.get) - ms_task.dirty := false.B - ms_task.way := req_s3.way - ms_task.meta := 0.U.asTypeOf(new MetaEntry) - ms_task.metaWen := false.B - ms_task.tagWen := false.B - ms_task.dsWen := false.B - ms_task.wayMask := 0.U(cacheParams.ways.W) - ms_task.replTask := false.B - ms_task.cmoTask := false.B - ms_task.reqSource := req_s3.reqSource - ms_task.mergeA := req_s3.mergeA - ms_task.aMergeTask := req_s3.aMergeTask - ms_task.txChannel := 0.U - ms_task.snpHitRelease := false.B - ms_task.snpHitReleaseToInval := false.B - ms_task.snpHitReleaseToClean := false.B - ms_task.snpHitReleaseWithData := false.B - ms_task.snpHitReleaseIdx := 0.U - ms_task.snpHitReleaseMeta := MetaEntry() - ms_task.denied := false.B - ms_task.corrupt := false.B - ms_task.cmoAll := false.B - /* ======== Resps to SinkA/B/C Reqs ======== */ - val sink_resp_s3 = WireInit(0.U.asTypeOf(Valid(new TaskBundle))) // resp for sinkA/B/C request that does not need to alloc mshr - val sink_resp_s3_a_promoteT = dirResult_s3.hit && isT(meta_s3.state) - - sink_resp_s3.valid := task_s3.valid && !mshr_req_s3 && !need_mshr_s3 - sink_resp_s3.bits := task_s3.bits - sink_resp_s3.bits.mshrId := (1 << (mshrBits-1)).U + sink_resp_s3.bits.sourceId // extra id for reqs that do not enter mshr - - when(req_s3.fromA) { - sink_resp_s3.bits.opcode := odOpGen(req_s3.opcode) - sink_resp_s3.bits.param := Mux( - req_acquire_s3, - Mux(req_s3.param === NtoB && !sink_resp_s3_a_promoteT, toB, toT), - 0.U // reserved - ) - }.elsewhen(req_s3.fromB) { - sink_resp_s3.bits.opcode := Mux( - dirResult_s3.hit && (meta_s3.state === TIP && meta_s3.dirty || req_s3.needProbeAckData), - ProbeAckData, - ProbeAck - ) - sink_resp_s3.bits.param := Mux(!dirResult_s3.hit, NtoN, - MuxLookup(Cat(req_s3.param, meta_s3.state), BtoB)(Seq( - Cat(toN, BRANCH) -> BtoN, - Cat(toN, TIP) -> TtoN, - Cat(toB, TIP) -> TtoB, - Cat(toT, TIP) -> TtoT - )) // other combinations should miss or have mshr allocated - ) - }.otherwise { // req_s3.fromC - sink_resp_s3.bits.opcode := ReleaseAck - sink_resp_s3.bits.param := 0.U // param of ReleaseAck must be 0 - } - - val source_req_s3 = Wire(new TaskBundle) - source_req_s3 := Mux(sink_resp_s3.valid, sink_resp_s3.bits, req_s3) - source_req_s3.isKeyword.foreach(_ := req_s3.isKeyword.getOrElse(false.B)) - /* ======== Interact with DS ======== */ - val data_s3 = Mux(io.releaseBufResp_s3.valid, io.releaseBufResp_s3.bits.data, io.refillBufResp_s3.bits.data) // releaseBuf prior - val c_releaseData_s3 = io.bufResp.data.asUInt - val hasData_s3 = source_req_s3.opcode(0) - - val need_data_a = dirResult_s3.hit && (req_get_s3 || req_acquireBlock_s3) - val need_data_b = sinkB_req_s3 && dirResult_s3.hit && - (meta_s3.state === TRUNK || meta_s3.state === TIP && meta_s3.dirty || req_s3.needProbeAckData) - val need_data_mshr_repl = mshr_refill_s3 && need_repl && !retry - val ren = need_data_a || need_data_b || need_data_mshr_repl - - val wen_c = sinkC_req_s3 && isParamFromT(req_s3.param) && req_s3.opcode(0) && dirResult_s3.hit - val wen_mshr = req_s3.dsWen && ( - mshr_probeack_s3 || mshr_release_s3 || - mshr_refill_s3 && !need_repl && !retry - ) - val wen = wen_c || wen_mshr - - // This is to let io.toDS.req_s3.valid hold for 2 cycles (see DataStorage for details) - val task_s3_valid_hold2 = RegEnable(task_s2.valid, false.B, !RegNext(task_s2.valid, false.B)) - - io.toDS.en_s3 := task_s3.valid && (ren || wen) - io.toDS.req_s3.valid := task_s3_valid_hold2 && (ren || wen) - io.toDS.req_s3.bits.way := Mux(mshr_refill_s3 && req_s3.replTask, io.replResp.bits.way, - Mux(mshr_req_s3, req_s3.way, dirResult_s3.way)) - io.toDS.req_s3.bits.set := Mux(mshr_req_s3, req_s3.set, dirResult_s3.set) - io.toDS.req_s3.bits.wen := wen - io.toDS.wdata_s3.data := Mux( - !mshr_req_s3, - c_releaseData_s3, // Among all sinkTasks, only C-Release writes DS - Mux( - req_s3.useProbeData, - io.releaseBufResp_s3.bits.data, - io.refillBufResp_s3.bits.data - ) - ) - - /* ======== 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: - // inner clients' data is needed, but whether the client will ack data is uncertain, so DS data is also needed, or - val need_write_releaseBuf = need_probe_s3_a || - cache_alias || - need_data_b && need_mshr_s3_b || - need_data_mshr_repl - // B: need_write_refillBuf indicates that DS should be read and the data will be written into RefillBuffer - // when L1 AcquireBlock but L2 AcquirePerm to L3, we need to prepare data for L1 - // but this will no longer happen, cuz we always AcquireBlock for L1 AcquireBlock - val need_write_refillBuf = false.B - - /* ======== Write Directory ======== */ - val metaW_valid_s3_a = sinkA_req_s3 && !need_mshr_s3_a && !req_get_s3 && !req_prefetch_s3 // get & prefetch that hit will not write meta - val metaW_valid_s3_b = sinkB_req_s3 && !need_mshr_s3_b && dirResult_s3.hit && (meta_s3.state === TIP || meta_s3.state === BRANCH && req_s3.param === toN) - val metaW_valid_s3_c = sinkC_req_s3 && dirResult_s3.hit - val metaW_valid_s3_mshr = mshr_req_s3 && req_s3.metaWen && !(mshr_refill_s3 && retry) - require(clientBits == 1) - - // Get and Prefetch should not change alias bit - val metaW_s3_a_alias = Mux( - req_get_s3 || req_prefetch_s3, - meta_s3.alias.getOrElse(0.U), - req_s3.alias.getOrElse(0.U) - ) - val metaW_s3_a = MetaEntry( - dirty = meta_s3.dirty, - state = Mux(req_needT_s3 || sink_resp_s3_a_promoteT, TRUNK, meta_s3.state), - clients = Fill(clientBits, true.B), - alias = Some(metaW_s3_a_alias), - accessed = true.B, - tagErr = meta_s3.tagErr, - dataErr = meta_s3.dataErr - ) - val metaW_s3_b = Mux(req_s3.param === toN, MetaEntry(), - MetaEntry( - dirty = false.B, - state = BRANCH, - clients = meta_s3.clients, - alias = meta_s3.alias, - tagErr = meta_s3.tagErr, - dataErr = meta_s3.dataErr - ) - ) - - val metaW_s3_c = MetaEntry( - dirty = meta_s3.dirty || wen_c, - state = Mux(isParamFromT(req_s3.param), TIP, meta_s3.state), - clients = Fill(clientBits, !isToN(req_s3.param)), - alias = meta_s3.alias, - accessed = meta_s3.accessed, - tagErr = Mux(wen_c, req_s3.denied, meta_s3.tagErr), - dataErr = Mux(wen_c, req_s3.corrupt, meta_s3.dataErr) // update error when write DS - ) - // use merge_meta if mergeA - val metaW_s3_mshr = WireInit(Mux(req_s3.mergeA, req_s3.aMergeTask.meta, req_s3.meta)) - metaW_s3_mshr.tagErr := req_s3.denied - metaW_s3_mshr.dataErr := req_s3.corrupt - - val metaW_way = Mux(mshr_refill_s3 && req_s3.replTask, io.replResp.bits.way, // grant always use replResp way - Mux(mshr_req_s3, req_s3.way, dirResult_s3.way)) - - io.metaWReq.valid := !resetFinish || task_s3.valid && (metaW_valid_s3_a || metaW_valid_s3_b || metaW_valid_s3_c || metaW_valid_s3_mshr) - io.metaWReq.bits.set := Mux(resetFinish, req_s3.set, resetIdx) - io.metaWReq.bits.wayOH := Mux(resetFinish, UIntToOH(metaW_way, cacheParams.ways), Fill(cacheParams.ways, true.B)) - io.metaWReq.bits.wmeta := Mux( - resetFinish, - ParallelPriorityMux( - Seq(metaW_valid_s3_a, metaW_valid_s3_b, metaW_valid_s3_c, metaW_valid_s3_mshr), - Seq(metaW_s3_a, metaW_s3_b, metaW_s3_c, metaW_s3_mshr) - ), - MetaEntry() - ) - - io.tagWReq.valid := task_s3.valid && req_s3.tagWen && mshr_refill_s3 && !retry - io.tagWReq.bits.set := req_s3.set - io.tagWReq.bits.wayOH := UIntToOH(Mux(mshr_refill_s3 && req_s3.replTask, io.replResp.bits.way, req_s3.way), cacheParams.ways) - io.tagWReq.bits.wtag := req_s3.tag - - /* ======== Interact with Channels (C & D) ======== */ - // do not need s4 & s5 - val chnl_fire_s3 = c_s3.fire || d_s3.fire - val req_drop_s3 = !need_write_releaseBuf && ( - !mshr_req_s3 && need_mshr_s3 || chnl_fire_s3 - ) || (mshr_refill_s3 && retry) - - val data_unready_s3 = hasData_s3 && !mshr_req_s3 - val isC_s3 = Mux( - mshr_req_s3, - mshr_release_s3 || mshr_probeack_s3, - req_s3.fromB && !need_mshr_s3 && !data_unready_s3 - ) - val isD_s3 = Mux( - mshr_req_s3, - mshr_refill_s3 && !retry, - req_s3.fromC || req_s3.fromA && !need_mshr_s3 && !data_unready_s3 && req_s3.opcode =/= Hint - ) // prefetch-hit will not generate response - c_s3.valid := task_s3.valid && isC_s3 - d_s3.valid := task_s3.valid && isD_s3 - c_s3.bits.task := source_req_s3 - c_s3.bits.data.data := data_s3 - d_s3.bits.task := source_req_s3 - d_s3.bits.data.data := data_s3 - - /* ======== nested & prefetch ======== */ - io.nestedwb.set := req_s3.set - io.nestedwb.tag := req_s3.tag - // This serves as VALID signal - // c_set_dirty is true iff Release has Data - io.nestedwb.c_set_dirty := task_s3.valid && task_s3.bits.fromC && task_s3.bits.opcode === ReleaseData - io.nestedwb.c_set_tip := false.B - io.nestedwb.b_inv_dirty := false.B - - io.nestedwbData := c_releaseData_s3.asTypeOf(new DSBlock) - - io.prefetchTrain.foreach { - train => - // train on request(with needHint flag) miss or hit on prefetched block - // trigger train also in a_merge here - train.valid := task_s3.valid && (((req_acquire_s3 || req_get_s3) && req_s3.needHint.getOrElse(false.B) && - (!dirResult_s3.hit || meta_s3.prefetch.get)) || req_s3.mergeA) - train.bits.tag := req_s3.tag - train.bits.set := req_s3.set - train.bits.needT := Mux(req_s3.mergeA, needT(req_s3.aMergeTask.opcode, req_s3.aMergeTask.param),req_needT_s3) - train.bits.source := Mux(req_s3.mergeA, req_s3.aMergeTask.sourceId, req_s3.sourceId) - train.bits.vaddr.foreach(_ := Mux(req_s3.mergeA, req_s3.aMergeTask.vaddr.getOrElse(0.U), req_s3.vaddr.getOrElse(0.U))) - train.bits.pc.foreach { pc => - pc := Mux(req_s3.mergeA, req_s3.aMergeTask.pc.getOrElse(0.U), req_s3.pc.getOrElse(0.U)) - } - train.bits.hit := Mux(req_s3.mergeA, true.B, dirResult_s3.hit) - train.bits.prefetched := Mux(req_s3.mergeA, true.B, meta_s3.prefetch.getOrElse(false.B)) - train.bits.pfsource := meta_s3.prefetchSrc.getOrElse(PfSource.NoWhere.id.U) // TODO - train.bits.reqsource := req_s3.reqSource - } - - /* ======== Stage 4 ======== */ - val task_s4 = RegInit(0.U.asTypeOf(Valid(new TaskBundle()))) - val data_unready_s4 = RegInit(false.B) - val data_s4 = Reg(UInt((blockBytes * 8).W)) - val ren_s4 = RegInit(false.B) - val need_write_releaseBuf_s4 = RegInit(false.B) - val isC_s4, isD_s4 = RegInit(false.B) - val tagError_s4 = RegInit(false.B) - val dataError_s4 = RegInit(false.B) - val l2Error_s4 = RegInit(false.B) - task_s4.valid := task_s3.valid && !req_drop_s3 - when (task_s3.valid && !req_drop_s3) { - task_s4.bits := source_req_s3 - task_s4.bits.mshrId := Mux(!task_s3.bits.mshrTask && need_mshr_s3, io.fromMSHRCtl.mshr_alloc_ptr, source_req_s3.mshrId) - // task_s4.bits.isKeyword.foreach(_ :=source_req_s3.isKeyword.getOrElse(false.B)) - data_unready_s4 := data_unready_s3 - data_s4 := data_s3 - ren_s4 := ren - need_write_releaseBuf_s4 := need_write_releaseBuf - isC_s4 := isC_s3 - isD_s4 := isD_s3 - tagError_s4 := tagError_s3 - dataError_s4 := dataError_s3 - l2Error_s4 := l2Error_s3 - } - - // A-alias-Acquire should send neither C nor D -// val isC_s4 = task_s4.bits.opcode(2, 1) === Release(2, 1) && task_s4.bits.fromA && !RegNext(cache_alias, false.B) || -// task_s4.bits.opcode(2, 1) === ProbeAck(2, 1) && task_s4.bits.fromB -// val isD_s4 = task_s4.bits.fromC || task_s4.bits.fromA && ( -// task_s4.bits.opcode(2, 1) === Grant(2, 1) || -// task_s4.bits.opcode(2, 1) === AccessAck(2, 1) || -// task_s4.bits.opcode === HintAck) - - // for reqs that CANNOT give response in MainPipe, but needs to write releaseBuf/refillBuf - // we cannot drop them at s3, we must let them go to s4/s5 - val chnl_fire_s4 = c_s4.fire || d_s4.fire - val req_drop_s4 = !need_write_releaseBuf_s4 && chnl_fire_s4 - - val c_d_valid_s4 = task_s4.valid && !RegNext(chnl_fire_s3, false.B) - c_s4.valid := c_d_valid_s4 && isC_s4 - d_s4.valid := c_d_valid_s4 && isD_s4 - c_s4.bits.task := task_s4.bits - c_s4.bits.data.data := data_s4 - d_s4.bits.task := task_s4.bits - d_s4.bits.task.isKeyword.foreach(_ := task_s4.bits.isKeyword.getOrElse(false.B)) - d_s4.bits.data.data := data_s4 - - /* ======== Stage 5 ======== */ - val task_s5 = RegInit(0.U.asTypeOf(Valid(new TaskBundle()))) - val ren_s5 = RegInit(false.B) - val data_s5 = Reg(UInt((blockBytes * 8).W)) - val need_write_releaseBuf_s5 = RegInit(false.B) - val isC_s5, isD_s5 = RegInit(false.B) - val tagError_s5 = RegInit(false.B) - val dataMetaError_s5 = RegInit(false.B) - val l2TagError_s5 = RegInit(false.B) - // those hit@s3 and ready to fire@s5, and Now wait@s4 - val pendingC_s4 = task_s4.bits.fromB && !task_s4.bits.mshrTask && task_s4.bits.opcode === ProbeAckData - val pendingD_s4 = task_s4.bits.fromA && !task_s4.bits.mshrTask && - (task_s4.bits.opcode === GrantData || task_s4.bits.opcode === AccessAckData) - - task_s5.valid := task_s4.valid && !req_drop_s4 - when (task_s4.valid && !req_drop_s4) { - task_s5.bits := task_s4.bits - task_s5.bits.isKeyword.foreach(_ :=task_s4.bits.isKeyword.getOrElse(false.B)) - ren_s5 := ren_s4 - data_s5 := data_s4 - need_write_releaseBuf_s5 := need_write_releaseBuf_s4 - // except for those ready at s3/s4 (isC/D_s4), sink resps are also ready to fire at s5 - isC_s5 := isC_s4 || pendingC_s4 - isD_s5 := isD_s4 || pendingD_s4 - tagError_s5 := tagError_s4 - dataMetaError_s5 := dataError_s4 - l2TagError_s5 := l2Error_s4 - } - val rdata_s5 = io.toDS.rdata_s5.data - val dataError_s5 = io.toDS.error_s5 || dataMetaError_s5 - val l2Error_s5 = l2TagError_s5 || io.toDS.error_s5 - val out_data_s5 = Mux(!task_s5.bits.mshrTask, rdata_s5, data_s5) - val chnl_fire_s5 = c_s5.fire || d_s5.fire - - val customL1Hint = Module(new CustomL1Hint) - - customL1Hint.io.mshrHintQInfo := io.mshrHintQInfo - customL1Hint.io.sinkCHintQInfo := io.sinkCHintQInfo - customL1Hint.io.retry_s2 := io.retryFastFwd_s2 - - customL1Hint.io.s3.task := task_s3 - // overwrite opcode: if sinkReq can respond, use sink_resp_s3.bits.opcode = Grant/GrantData - customL1Hint.io.s3.task.bits.opcode := Mux(sink_resp_s3.valid, sink_resp_s3.bits.opcode, task_s3.bits.opcode) - customL1Hint.io.s3.need_mshr := need_mshr_s3 - - customL1Hint.io.l1Hint <> io.l1Hint - - io.releaseBufWrite.valid := task_s5.valid && need_write_releaseBuf_s5 - io.releaseBufWrite.bits.id := task_s5.bits.mshrId - io.releaseBufWrite.bits.data.data := rdata_s5 - io.releaseBufWrite.bits.beatMask := Fill(beatSize, true.B) - - val c_d_valid_s5 = task_s5.valid && !RegNext(chnl_fire_s4, false.B) && !RegNextN(chnl_fire_s3, 2, Some(false.B)) - c_s5.valid := c_d_valid_s5 && isC_s5 - d_s5.valid := c_d_valid_s5 && isD_s5 - c_s5.bits.task := task_s5.bits - c_s5.bits.task.denied := Mux(!task_s5.bits.mshrTask, tagError_s5, task_s5.bits.denied) - c_s5.bits.task.corrupt := Mux(!task_s5.bits.mshrTask, dataError_s5, task_s5.bits.corrupt) - c_s5.bits.data.data := out_data_s5 - d_s5.bits.task := task_s5.bits - d_s5.bits.task.denied := Mux(!task_s5.bits.mshrTask, tagError_s5, task_s5.bits.denied) - d_s5.bits.task.corrupt := Mux(!task_s5.bits.mshrTask, dataError_s5, task_s5.bits.corrupt) - d_s5.bits.data.data := out_data_s5 - - /* ======== BlockInfo ======== */ - // if s2/s3 might write Dir, we must block s1 sink entrance - // TODO:[Check] it seems that s3 Dir write will naturally block all s1 by dirRead.ready - // (an even stronger blocking than set blocking) - // so we might not need s3 blocking here - def s23Block(chn: Char, s: TaskBundle): Bool = { - val s1 = io.fromReqArb.status_s1 - val s1_set = chn match { - case 'a' => s1.a_set - case 'b' => s1.b_set - case 'c' => s1.c_set - case 'g' => s1.g_set - } - s.set === s1_set && !(s.mshrTask && !s.metaWen) // if guaranteed not to write meta, no blocking needed - } - def bBlock(s: TaskBundle, tag: Boolean = false): Bool = { - val s1 = io.fromReqArb.status_s1 - // tag true: compare tag + set - s.set === s1.b_set && (if(tag) s.tag === s1.b_tag else true.B) - } - - io.toReqBuf(0) := task_s2.valid && s23Block('a', task_s2.bits) - io.toReqBuf(1) := task_s3.valid && s23Block('a', task_s3.bits) - - io.toReqArb.blockC_s1 := task_s2.valid && s23Block('c', task_s2.bits) - - io.toReqArb.blockB_s1 := - task_s2.valid && bBlock(task_s2.bits) || - task_s3.valid && bBlock(task_s3.bits) || - task_s4.valid && bBlock(task_s4.bits, tag = true) || - task_s5.valid && bBlock(task_s5.bits, tag = true) - - io.toReqArb.blockA_s1 := false.B - - io.toReqArb.blockG_s1 := task_s2.valid && s23Block('g', task_s2.bits) - /* ======== Pipeline Status ======== */ - require(io.status_vec_toD.size == 3) - io.status_vec_toD(0).valid := task_s3.valid && Mux( - mshr_req_s3, - mshr_refill_s3 && !retry, - true.B - // TODO: - // To consider grantBuffer capacity conflict, only " req_s3.fromC || req_s3.fromA && !need_mshr_s3 " is needed - // But to consider mshrFull, all channel_reqs are needed - // so maybe it is excessive for grantBuf capacity conflict - ) - - io.status_vec_toD(0).bits.channel := task_s3.bits.channel - io.status_vec_toD(1).valid := task_s4.valid && (isD_s4 || pendingD_s4) - io.status_vec_toD(1).bits.channel := task_s4.bits.channel - io.status_vec_toD(2).valid := d_s5.valid - io.status_vec_toD(2).bits.channel := task_s5.bits.channel - - require(io.status_vec_toC.size == 3) - io.status_vec_toC(0).valid := task_s3.valid && Mux(mshr_req_s3, mshr_release_s3 || mshr_probeack_s3, true.B) - io.status_vec_toC(0).bits.channel := task_s3.bits.channel - io.status_vec_toC(1).valid := task_s4.valid && (isC_s4 || pendingC_s4) - io.status_vec_toC(1).bits.channel := task_s4.bits.channel - io.status_vec_toC(2).valid := c_s5.valid - io.status_vec_toC(2).bits.channel := task_s5.bits.channel - - /* ======== Other Signals Assignment ======== */ - // Initial state assignment - // ! Caution: s_ and w_ are false-as-valid - when(req_s3.fromA) { - alloc_state.s_refill := false.B - alloc_state.w_replResp := dirResult_s3.hit // need replRead when NOT dirHit - // need Acquire downwards - when(need_acquire_s3_a) { - alloc_state.s_acquire := false.B - alloc_state.w_grantfirst := false.B - alloc_state.w_grantlast := false.B - alloc_state.w_grant := false.B - } - // need Probe for alias - // need Probe when Get hits on a TRUNK block - when(cache_alias || need_probe_s3_a) { - alloc_state.s_rprobe := false.B - alloc_state.w_rprobeackfirst := false.B - alloc_state.w_rprobeacklast := false.B - } - // need trigger a prefetch, send PrefetchTrain msg to Prefetcher - // prefetchOpt.foreach {_ => - // when (req_s3.fromA && req_s3.needHint.getOrElse(false.B) && (!dirResult_s3.hit || meta_s3.prefetch.get)) { - // alloc_state.s_triggerprefetch.foreach(_ := false.B) - // } - // } - } - when(req_s3.fromB) { - // Only consider the situation when mshr needs to be allocated - alloc_state.s_pprobe := false.B - alloc_state.w_pprobeackfirst := false.B - alloc_state.w_pprobeacklast := false.B - alloc_state.s_probeack := false.B - } - - val c = Seq(c_s5, c_s4, c_s3) - val d = Seq(d_s5, d_s4, d_s3) - val c_arb = Module(new Arbiter(io.toSourceC.bits.cloneType, c.size)) - val d_arb = Module(new Arbiter(io.toSourceD.bits.cloneType, d.size)) - c_arb.io.in <> c - d_arb.io.in <> d - - io.toSourceC <> c_arb.io.out - io.toSourceD <> d_arb.io.out - - io.error.valid := task_s5.valid - io.error.bits.valid := l2Error_s5 // if not enableECC, should be false - io.error.bits.address := Cat(task_s5.bits.tag, task_s5.bits.set, task_s5.bits.off) - - /* ===== Performance counters ===== */ - // num of mshr req - XSPerfAccumulate("mshr_grant_req", task_s3.valid && mshr_grant_s3 && !retry) - XSPerfAccumulate("mshr_grantdata_req", task_s3.valid && mshr_grantdata_s3 && !retry) - XSPerfAccumulate("mshr_accessackdata_req", task_s3.valid && mshr_accessackdata_s3 && !retry) - XSPerfAccumulate("mshr_hintack_req", task_s3.valid && mshr_hintack_s3 && !retry) - XSPerfAccumulate("mshr_probeack_req", task_s3.valid && mshr_probeack_s3) - XSPerfAccumulate("mshr_probeackdata_req", task_s3.valid && mshr_probeackdata_s3) - XSPerfAccumulate("mshr_release_req", task_s3.valid && mshr_release_s3) - - // directory access result - val hit_s3 = task_s3.valid && !mshr_req_s3 && dirResult_s3.hit - val miss_s3 = task_s3.valid && !mshr_req_s3 && !dirResult_s3.hit - XSPerfAccumulate("a_req_hit", hit_s3 && req_s3.fromA) - XSPerfAccumulate("acquire_hit", hit_s3 && req_s3.fromA && - (req_s3.opcode === AcquireBlock || req_s3.opcode === AcquirePerm)) - XSPerfAccumulate("get_hit", hit_s3 && req_s3.fromA && req_s3.opcode === Get) - XSPerfAccumulate("retry", mshr_refill_s3 && retry) - - XSPerfAccumulate("a_req_miss", miss_s3 && req_s3.fromA) - XSPerfAccumulate("acquire_miss", miss_s3 && req_s3.fromA && - (req_s3.opcode === AcquireBlock || req_s3.opcode === AcquirePerm)) - XSPerfAccumulate("get_miss", miss_s3 && req_s3.fromA && req_s3.opcode === Get) - - XSPerfAccumulate("b_req_hit", hit_s3 && req_s3.fromB) - XSPerfAccumulate("b_req_miss", miss_s3 && req_s3.fromB) - - XSPerfHistogram("a_req_access_way", perfCnt = dirResult_s3.way, - enable = task_s3.valid && !mshr_req_s3 && req_s3.fromA, start = 0, stop = cacheParams.ways, step = 1) - XSPerfHistogram("a_req_hit_way", perfCnt = dirResult_s3.way, - enable = hit_s3 && req_s3.fromA, start = 0, stop = cacheParams.ways, step = 1) - XSPerfHistogram("a_req_miss_way_choice", perfCnt = dirResult_s3.way, - enable = miss_s3 && req_s3.fromA, start = 0, stop = cacheParams.ways, step = 1) - - // pipeline stages for sourceC and sourceD reqs - val sourceC_pipe_len = ParallelMux(Seq( - c_s5.fire -> 5.U, - c_s4.fire -> 4.U, - c_s3.fire -> 3.U - )) - val sourceD_pipe_len = ParallelMux(Seq( - d_s5.fire -> 5.U, - d_s4.fire -> 4.U, - d_s3.fire -> 3.U - )) - XSPerfHistogram("sourceC_pipeline_stages", sourceC_pipe_len, - enable = io.toSourceC.fire, start = 3, stop = 5+1, step = 1) - XSPerfHistogram("sourceD_pipeline_stages", sourceD_pipe_len, - enable = io.toSourceD.fire, start = 3, stop = 5+1, step = 1) - - // XSPerfAccumulate("a_req_tigger_prefetch", io.prefetchTrain.) - prefetchOpt.foreach { - _ => - XSPerfAccumulate("a_req_trigger_prefetch", io.prefetchTrain.get.fire) - XSPerfAccumulate("a_req_trigger_prefetch_not_ready", io.prefetchTrain.get.valid && !io.prefetchTrain.get.ready) - XSPerfAccumulate("acquire_trigger_prefetch_on_miss", io.prefetchTrain.get.fire && req_acquire_s3 && !dirResult_s3.hit) - XSPerfAccumulate("acquire_trigger_prefetch_on_hit_pft", io.prefetchTrain.get.fire && req_acquire_s3 && dirResult_s3.hit && meta_s3.prefetch.get) - XSPerfAccumulate("release_all", mshr_release_s3) - XSPerfAccumulate("release_prefetch_accessed", mshr_release_s3 && meta_s3.prefetch.get && meta_s3.accessed) - XSPerfAccumulate("release_prefetch_not_accessed", mshr_release_s3 && meta_s3.prefetch.get && !meta_s3.accessed) - XSPerfAccumulate("get_trigger_prefetch_on_miss", io.prefetchTrain.get.fire && req_get_s3 && !dirResult_s3.hit) - XSPerfAccumulate("get_trigger_prefetch_on_hit_pft", io.prefetchTrain.get.fire && req_get_s3 && dirResult_s3.hit && meta_s3.prefetch.get) - } - - XSPerfAccumulate("early_prefetch", meta_s3.prefetch.getOrElse(false.B) && !meta_s3.accessed && !dirResult_s3.hit && task_s3.valid) - - /* ===== Monitor ===== */ - io.toMonitor.task_s2 := task_s2 - io.toMonitor.task_s3 := task_s3 - io.toMonitor.task_s4 := task_s4 - io.toMonitor.task_s5 := task_s5 - io.toMonitor.dirResult_s3 := dirResult_s3 - io.toMonitor.allocMSHR_s3.valid := io.toMSHRCtl.mshr_alloc_s3.valid - io.toMonitor.allocMSHR_s3.bits := io.fromMSHRCtl.mshr_alloc_ptr - io.toMonitor.metaW_s3 := io.metaWReq - - /* ===== Hardware Performance Monitor ===== */ - val perfEvents = Seq( - ("l2_cache_hit", hit_s3 && req_s3.fromA), - ("l2_cache_miss", miss_s3 && req_s3.fromA), - ("l2_cache_access", task_s3.valid && (sinkA_req_s3 && !req_prefetch_s3 || sinkC_req_s3)), - ("l2_cache_l2wb", task_s3.valid && (mshr_releasedata_s3 || mshr_probeackdata_s3)), - ("l2_cache_l1wb", task_s3.valid && sinkC_req_s3 && (req_s3.opcode === ReleaseData)), - ("l2_cache_wb_victim", task_s3.valid && mshr_releasedata_s3), - ("l2_cache_wb_cleaning_coh", task_s3.valid && mshr_probeackdata_s3), - ("l2_cache_prefetch_access", task_s3.valid && sinkA_req_s3 && req_prefetch_s3), - ("l2_cache_prefetch_miss", task_s3.valid && sinkA_req_s3 && req_prefetch_s3 && miss_s3), - ("l2_cache_access_rd", task_s3.valid && sinkA_req_s3 && !req_prefetch_s3), - ("l2_cache_access_wr", task_s3.valid && sinkC_req_s3), - ("l2_cache_miss_rd", task_s3.valid && sinkA_req_s3 && !req_prefetch_s3 && miss_s3), - // ("l2_cache_miss_wr", Inclusive L2 always hit), - ("l2_cache_inv", task_s3.valid && sinkB_req_s3 && (req_s3.param === toN)) - ) - generatePerfEvent() -} diff --git a/src/main/scala/coupledL2/tl2tl/ProbeQueue.scala b/src/main/scala/coupledL2/tl2tl/ProbeQueue.scala deleted file mode 100644 index e8dce881..00000000 --- a/src/main/scala/coupledL2/tl2tl/ProbeQueue.scala +++ /dev/null @@ -1,99 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import coupledL2._ -import coupledL2.utils._ -import freechips.rocketchip.tilelink._ -import org.chipsalliance.cde.config.Parameters - -class ProbeQueue(implicit p: Parameters) extends L2Module { - val io = IO(new Bundle() { - val sinkB = Flipped(DecoupledIO(new TLBundleB(edgeIn.bundle))) - val arb_busy_s0 = Input(Bool()) - val prb_bits_s0 = Valid(new TLBundleB(edgeIn.bundle)) - }) - - val prbqSize = 5 - - val prb_bits_init = 0.U.asTypeOf(new TLBundleB(edgeIn.bundle)) - val prbq_valid_reg = RegInit(VecInit(Seq.fill(prbqSize)(false.B))) - val prbq_bits_reg = RegInit(VecInit(Seq.fill(prbqSize)(prb_bits_init))) - val prb_valid_s0_reg = RegInit(false.B) - val prb_bits_s0_reg = RegInit(prb_bits_init) - - val prbq_older_arr = RegInit(VecInit(Seq.fill(prbqSize)(0.U(prbqSize.W)))) - - val prbq_in_sel = Wire(Vec(prbqSize, Bool())) - val prbq_out_sel = Wire(Vec(prbqSize, Bool())) - val prbq_alloc = Wire(Vec(prbqSize, Bool())) - val prbq_free = Wire(Vec(prbqSize, Bool())) - - for (i <- 0 until prbqSize) { - //********************************** - // alloc a entry of probe queue - if (i == 0) { - prbq_in_sel(i) := ~prbq_valid_reg(i) - } else { - prbq_in_sel(i) := ~prbq_valid_reg(i) & prbq_valid_reg.asUInt(i - 1, 0).andR - } - prbq_alloc(i) := io.sinkB.valid & prbq_in_sel(i) - - // free a entry of probe queue - prbq_out_sel(i) := ~(prbq_valid_reg.asUInt & prbq_older_arr(i)).orR - prbq_free(i) := prbq_valid_reg(i) & prbq_out_sel(i) & (~io.arb_busy_s0 | ~prb_valid_s0_reg) - - when(prbq_alloc(i)) { - prbq_valid_reg(i) := io.sinkB.valid - prbq_bits_reg(i) := io.sinkB.bits - } - .elsewhen(prbq_free(i)) { - prbq_valid_reg(i) := false.B - } - - // update the older array by LRU Algorithm - when(prbq_alloc(i)) { - prbq_older_arr(i) := ~prbq_alloc.asUInt - } - .elsewhen(prbq_alloc.asUInt.orR) { - prbq_older_arr(i) := prbq_older_arr(i) & ~prbq_alloc.asUInt - } - } - - val prb_valid_s0_en = (~prb_valid_s0_reg & prbq_valid_reg.asUInt.orR) | - (prb_valid_s0_reg & ~prbq_valid_reg.asUInt.orR & ~io.arb_busy_s0) - val prb_valid_s0_in = ~prb_valid_s0_reg & prbq_valid_reg.asUInt.orR - when(prb_valid_s0_en) { - prb_valid_s0_reg := prb_valid_s0_in - } - - val prb_bits_s0_en = (prbq_valid_reg.asUInt.orR & ~prb_valid_s0_reg) | - (prbq_valid_reg.asUInt.orR & ~io.arb_busy_s0) - val prbBitsWidth = prb_bits_s0_reg.asUInt.getWidth - val prb_bits_s0_in = prbq_bits_reg.zipWithIndex.map { case (x, i) => x.asUInt & Fill(prbBitsWidth, prbq_free(i)) }.reduce((x, y) => x | y) - when(prb_bits_s0_en) { - prb_bits_s0_reg := prb_bits_s0_in.asTypeOf(prb_bits_s0_reg) - } - - io.sinkB.ready := ~prbq_valid_reg.asUInt.andR - - io.prb_bits_s0.valid := prb_valid_s0_reg - io.prb_bits_s0.bits := prb_bits_s0_reg -} \ No newline at end of file diff --git a/src/main/scala/coupledL2/tl2tl/RefillUnit.scala b/src/main/scala/coupledL2/tl2tl/RefillUnit.scala deleted file mode 100644 index 3f7fef38..00000000 --- a/src/main/scala/coupledL2/tl2tl/RefillUnit.scala +++ /dev/null @@ -1,93 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import org.chipsalliance.cde.config.Parameters -import coupledL2._ -import utility.XSPerfAccumulate -import huancun.{DirtyKey, IsHitKey} - -class grantAckQEntry(implicit p: Parameters) extends L2Bundle { - val source = UInt(sourceIdBits.W) - val sink = UInt(outerSinkBits.W) -} - -// Communicate with L3 -// Receive Grant/GrantData/ReleaseAck from d and -// Send GrantAck through e -class RefillUnit(implicit p: Parameters) extends L2Module { - val io = IO(new Bundle() { - val sinkD = Flipped(DecoupledIO(new TLBundleD(edgeOut.bundle))) - val sourceE = DecoupledIO(new TLBundleE(edgeOut.bundle)) - val refillBufWrite = ValidIO(new MSHRBufWrite) - val resp = Output(new RespBundle) - }) - - val (first, last, _, beat) = edgeOut.count(io.sinkD) - val hasData = io.sinkD.bits.opcode(0) - val isGrant = io.sinkD.bits.opcode === Grant || io.sinkD.bits.opcode === GrantData - - val grantAckQ = Module(new Queue(new grantAckQEntry, entries=mshrsAll, pipe=false, flow=false)) - - grantAckQ.io.enq.valid := isGrant && io.sinkD.valid && first - grantAckQ.io.enq.bits.source := io.sinkD.bits.source - grantAckQ.io.enq.bits.sink := io.sinkD.bits.sink - - grantAckQ.io.deq.ready := io.sourceE.ready - io.sourceE.bits.sink := grantAckQ.io.deq.bits.sink - io.sourceE.valid := grantAckQ.io.deq.valid - - val grantDataBuf = RegEnable(io.sinkD.bits.data, 0.U((beatBytes * 8).W), io.sinkD.valid && hasData && first) - - io.refillBufWrite.valid := io.sinkD.valid && hasData && last - io.refillBufWrite.bits.id := io.sinkD.bits.source - io.refillBufWrite.bits.data.data := Cat(io.sinkD.bits.data, grantDataBuf) - io.refillBufWrite.bits.beatMask := Fill(beatSize, true.B) - - io.resp.valid := (first || last) && io.sinkD.valid - io.resp.mshrId := io.sinkD.bits.source - io.resp.set := 0.U(setBits.W) - io.resp.tag := 0.U(tagBits.W) - io.resp.respInfo.opcode := io.sinkD.bits.opcode - io.resp.respInfo.param := io.sinkD.bits.param - io.resp.respInfo.last := last - io.resp.respInfo.dirty := io.sinkD.bits.echo.lift(DirtyKey).getOrElse(false.B) - io.resp.respInfo.isHit := io.sinkD.bits.user.lift(IsHitKey).getOrElse(true.B) - io.resp.respInfo.denied := io.sinkD.bits.denied - io.resp.respInfo.corrupt := io.sinkD.bits.corrupt - dontTouch(io.resp.respInfo.isHit) - - io.sinkD.ready := true.B - - // count refillData all zero - // (assume beat0 and beat1 of the same block always come continuously, no intersection) - val zero = RegInit(true.B) - when (io.refillBufWrite.valid) { - when (beat === beatSize.U) { - zero := true.B // init as true - } .otherwise { - zero := zero & io.sinkD.bits.data === 0.U // if beat not 0.U, clear 'zero' - } - } - XSPerfAccumulate("sinkD_from_L3_zero", io.refillBufWrite.valid && beat === beatSize.U && zero && io.sinkD.bits.data === 0.U) - XSPerfAccumulate("sinkD_from_L3_all", io.refillBufWrite.valid && beat === beatSize.U) -} diff --git a/src/main/scala/coupledL2/tl2tl/SinkB.scala b/src/main/scala/coupledL2/tl2tl/SinkB.scala deleted file mode 100644 index eae73160..00000000 --- a/src/main/scala/coupledL2/tl2tl/SinkB.scala +++ /dev/null @@ -1,77 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import freechips.rocketchip.tilelink.TLPermissions._ -import coupledL2._ -import utility.MemReqSource - -class SinkB(implicit p: Parameters) extends L2Module { - val io = IO(new Bundle() { - val b = Flipped(DecoupledIO(new TLBundleB(edgeIn.bundle))) - val task = DecoupledIO(new TaskBundle) - val msInfo = Vec(mshrsAll, Flipped(ValidIO(new MSHRInfo))) - }) - - def fromTLBtoTaskBundle(b: TLBundleB): TaskBundle = { - val task = Wire(new TaskBundle) - task := 0.U.asTypeOf(new TaskBundle) - task.channel := "b010".U - task.txChannel := 0.U - task.tag := parseAddress(b.address)._1 - task.set := parseAddress(b.address)._2 - task.off := parseAddress(b.address)._3 - task.opcode := b.opcode - task.param := b.param - task.size := b.size - task.needProbeAckData := b.data(0) // TODO: parameterize this - task.mshrTask := false.B - task.aliasTask.foreach(_ := false.B) - task.wayMask := Fill(cacheParams.ways, "b1".U) - task.reqSource := MemReqSource.NoWhere.id.U // Ignore - task.snpHitRelease := false.B - task.snpHitReleaseToInval := false.B - task.snpHitReleaseToClean := false.B - task.snpHitReleaseWithData := false.B - task.snpHitReleaseIdx := 0.U - task.snpHitReleaseMeta := MetaEntry() - task - } - val task = fromTLBtoTaskBundle(io.b.bits) - - // unable to accept incoming B req because same-addr as some MSHR REQ - val addrConflict = VecInit(io.msInfo.map(s => - s.valid && s.bits.set === task.set && s.bits.reqTag === task.tag && !s.bits.willFree && s.bits.w_grantfirst - )).asUInt.orR - - // unable to accept incoming B req because same-addr Release to L3 and have not received ReleaseAck, and some MSHR replaced block and cannot nest - val replaceConflictMask = VecInit(io.msInfo.map(s => - s.valid && s.bits.set === task.set && s.bits.metaTag === task.tag && (s.bits.blockRefill || !s.bits.w_releaseack) - )).asUInt - val replaceConflict = replaceConflictMask.orR - - // when conflict, we block B req from entering SinkB - io.task.valid := io.b.valid && !addrConflict && !replaceConflict - io.task.bits := task - io.b.ready := io.task.ready && !addrConflict && !replaceConflict -} diff --git a/src/main/scala/coupledL2/tl2tl/Slice.scala b/src/main/scala/coupledL2/tl2tl/Slice.scala deleted file mode 100644 index 2f85a02d..00000000 --- a/src/main/scala/coupledL2/tl2tl/Slice.scala +++ /dev/null @@ -1,221 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import freechips.rocketchip.util.leftOR -import org.chipsalliance.cde.config.Parameters -import coupledL2._ -import coupledL2.utils._ -import coupledL2.debug._ -import coupledL2.prefetch.PrefetchIO -import utility.{MemReqSource, RegNextN, XSPerfHistogram} - -class OuterBundle(params: TLBundleParameters) extends TLBundle(params) with BaseOuterBundle - -class Slice()(implicit p: Parameters) extends BaseSlice[OuterBundle] { - val io = IO(new BaseSliceIO[OuterBundle] { - override val out: OuterBundle = new OuterBundle(edgeOut.bundle) - }) - - val reqArb = Module(new RequestArb()) - val a_reqBuf = Module(new RequestBuffer) - val mainPipe = Module(new MainPipe()) - val mshrCtl = Module(new MSHRCtl()) - val directory = Module(new Directory()) - val dataStorage = Module(new DataStorage()) - val refillUnit = Module(new RefillUnit()) - val sinkA = Module(new SinkA) - val sinkB = Module(new SinkB) - val sinkC = Module(new SinkC) - val sourceC = Module(new SourceC) - val grantBuf = Module(new GrantBuffer) - val refillBuf = Module(new MSHRBuffer(wPorts = 2)) - val releaseBuf = Module(new MSHRBuffer(wPorts = 3)) - - val prbq = Module(new ProbeQueue()) - prbq.io <> DontCare // @XiaBin TODO - - a_reqBuf.io.in <> sinkA.io.task - a_reqBuf.io.mshrInfo := mshrCtl.io.msInfo - a_reqBuf.io.mainPipeBlock := mainPipe.io.toReqBuf - a_reqBuf.io.s1Entrance := reqArb.io.s1Entrance - a_reqBuf.io.taskFromArb_s2 := reqArb.io.taskToPipe_s2 - - sinkB.io.msInfo := mshrCtl.io.msInfo - sinkC.io.msInfo := mshrCtl.io.msInfo - - reqArb.io.sinkA <> a_reqBuf.io.out - reqArb.io.ATag := a_reqBuf.io.ATag - reqArb.io.ASet := a_reqBuf.io.ASet - - reqArb.io.sinkB <> sinkB.io.task - reqArb.io.sinkC <> sinkC.io.task - reqArb.io.dirRead_s1 <> directory.io.read - reqArb.io.taskToPipe_s2 <> mainPipe.io.taskFromArb_s2 - reqArb.io.mshrTask <> mshrCtl.io.mshrTask - reqArb.io.refillBufRead_s2 <> refillBuf.io.r - reqArb.io.releaseBufRead_s2 <> releaseBuf.io.r - reqArb.io.fromMSHRCtl := mshrCtl.io.toReqArb - reqArb.io.fromMainPipe := mainPipe.io.toReqArb - reqArb.io.fromGrantBuffer := grantBuf.io.toReqArb - reqArb.io.fromSourceC.foreach(_ := sourceC.io.toReqArb) - reqArb.io.msInfo := mshrCtl.io.msInfo - - mshrCtl.io.fromReqArb.status_s1 := reqArb.io.status_s1 - mshrCtl.io.resps.sinkC := sinkC.io.resp - mshrCtl.io.resps.sinkD := refillUnit.io.resp - mshrCtl.io.resps.sourceC := sourceC.io.resp - mshrCtl.io.nestedwb := mainPipe.io.nestedwb - mshrCtl.io.aMergeTask := a_reqBuf.io.aMergeTask - mshrCtl.io.replResp <> directory.io.replResp - mainPipe.io.replResp <> directory.io.replResp - - directory.io.resp.bits <> mainPipe.io.dirResp_s3 - directory.io.metaWReq <> mainPipe.io.metaWReq - directory.io.tagWReq <> mainPipe.io.tagWReq - directory.io.msInfo <> mshrCtl.io.msInfo - - dataStorage.io.en := mainPipe.io.toDS.en_s3 - dataStorage.io.req <> mainPipe.io.toDS.req_s3 - dataStorage.io.wdata := mainPipe.io.toDS.wdata_s3 - - mainPipe.io.toMSHRCtl <> mshrCtl.io.fromMainPipe - mainPipe.io.fromMSHRCtl <> mshrCtl.io.toMainPipe - mainPipe.io.bufResp <> sinkC.io.bufResp - mainPipe.io.toDS.rdata_s5 := dataStorage.io.rdata - mainPipe.io.toDS.error_s5 := dataStorage.io.error - mainPipe.io.refillBufResp_s3.valid := RegNext(refillBuf.io.r.valid, false.B) - mainPipe.io.refillBufResp_s3.bits := refillBuf.io.resp.data - mainPipe.io.releaseBufResp_s3.valid := RegNext(releaseBuf.io.r.valid, false.B) - mainPipe.io.releaseBufResp_s3.bits := releaseBuf.io.resp.data - mainPipe.io.fromReqArb.status_s1 := reqArb.io.status_s1 - mainPipe.io.mshrHintQInfo := reqArb.io.mshrHintQInfo - mainPipe.io.sinkCHintQInfo := reqArb.io.sinkCHintQInfo - mainPipe.io.retryFastFwd_s2 := directory.io.retryFastFwd - - // priority: nested-ReleaseData / probeAckData [NEW] > mainPipe DS rdata [OLD] - // 0/1 might happen at the same cycle with 2 - releaseBuf.io.w(0).valid := mshrCtl.io.nestedwbDataId.valid - releaseBuf.io.w(0).bits.data := mainPipe.io.nestedwbData - releaseBuf.io.w(0).bits.id := mshrCtl.io.nestedwbDataId.bits - releaseBuf.io.w(0).bits.beatMask := Fill(beatSize, true.B) - releaseBuf.io.w(1) <> sinkC.io.releaseBufWrite - releaseBuf.io.w(1).bits.id := mshrCtl.io.releaseBufWriteId - releaseBuf.io.w(2) <> mainPipe.io.releaseBufWrite - - refillBuf.io.w(0) <> refillUnit.io.refillBufWrite - refillBuf.io.w(1) <> sinkC.io.refillBufWrite - - sourceC.io.in <> mainPipe.io.toSourceC - sourceC.io.pipeStatusVec := reqArb.io.status_vec ++ mainPipe.io.status_vec_toC - - io.l1Hint <> mainPipe.io.l1Hint - mshrCtl.io.grantStatus := grantBuf.io.grantStatus - - grantBuf.io.d_task <> mainPipe.io.toSourceD - grantBuf.io.fromReqArb.status_s1 := reqArb.io.status_s1 - grantBuf.io.pipeStatusVec := reqArb.io.status_vec ++ mainPipe.io.status_vec_toD - mshrCtl.io.pipeStatusVec(0) := (reqArb.io.status_vec)(1) // s2 status - mshrCtl.io.pipeStatusVec(1) := mainPipe.io.status_vec_toD(0) // s3 status - - io.prefetch.foreach { - p => - p.train <> mainPipe.io.prefetchTrain.get - sinkA.io.prefetchReq.get <> p.req - p.resp <> grantBuf.io.prefetchResp.get - p.tlb_req.req.ready := true.B - p.tlb_req.resp.valid := false.B - p.tlb_req.resp.bits := DontCare - p.tlb_req.pmp_resp := DontCare - p.recv_addr := 0.U.asTypeOf(p.recv_addr) - } - - /* input & output signals */ - val inBuf = cacheParams.innerBuf - val outBuf = cacheParams.outerBuf - - /* connect upward channels */ - sinkA.io.a <> inBuf.a(io.in.a) - io.in.b <> inBuf.b(mshrCtl.io.sourceB) - sinkC.io.c <> inBuf.c(io.in.c) - io.in.d <> inBuf.d(grantBuf.io.d) - grantBuf.io.e <> inBuf.e(io.in.e) - io.error.valid := RegNext(mainPipe.io.error.valid, false.B) - io.error.bits := RegNext(mainPipe.io.error.bits) - - /* connect downward channels */ - io.out.a <> outBuf.a(mshrCtl.io.sourceA) - sinkB.io.b <> outBuf.b(io.out.b) - io.out.c <> outBuf.c(sourceC.io.out) - refillUnit.io.sinkD <> outBuf.d(io.out.d) - io.out.e <> outBuf.e(refillUnit.io.sourceE) - - /* tie cmo All channels */ - sinkA.io.cmoAll.foreach {cmoAll => cmoAll.mshrValid := false.B} - sinkA.io.cmoAll.foreach {cmoAll => cmoAll.cmoLineDone := false.B} - sinkA.io.cmoAll.foreach {cmoAll => cmoAll.l2Flush := false.B} - - io.l2FlushDone.foreach {_ := false.B} - - dontTouch(io.in) - dontTouch(io.out) - - topDownOpt.foreach ( - _ => { - io.msStatus.get := mshrCtl.io.msStatus.get - io.msAlloc.get := mshrCtl.io.msAlloc.get - io.dirResult.get.valid := directory.io.resp.valid && !directory.io.replResp.valid // exclude MSHR-Grant read-dir - io.dirResult.get.bits := directory.io.resp.bits - io.pfStatInMSHR.get := a_reqBuf.io.pfStatInMSHR - io.pfSent.get.valid := io.prefetch.fold(false.B)(_.req.fire) - io.pfSent.get.bits := io.prefetch.fold(MemReqSource.NoWhere.id.U)(p => p.req.bits.pfSource) - } - ) - io.l2Miss := mshrCtl.io.l2Miss - - if (cacheParams.enablePerf) { - val a_begin_times = RegInit(VecInit(Seq.fill(sourceIdAll)(0.U(64.W)))) - val timer = RegInit(0.U(64.W)) - timer := timer + 1.U - a_begin_times.zipWithIndex.foreach { - case (r, i) => - when (sinkA.io.a.fire && sinkA.io.a.bits.source === i.U) { - r := timer - } - } - val d_source = grantBuf.io.d.bits.source - val delay = timer - a_begin_times(d_source) - val (first, _, _, _) = edgeIn.count(grantBuf.io.d) - val delay_sample = grantBuf.io.d.fire && grantBuf.io.d.bits.opcode =/= ReleaseAck && first - XSPerfHistogram("a_to_d_delay", delay, delay_sample, 0, 20, 1, true, true) - XSPerfHistogram("a_to_d_delay", delay, delay_sample, 20, 300, 10, true, true) - XSPerfHistogram("a_to_d_delay", delay, delay_sample, 300, 500, 20, true, true) - XSPerfHistogram("a_to_d_delay", delay, delay_sample, 500, 1000, 100, true, false) - } - - val monitor = Module(new Monitor()) - monitor.io.fromMainPipe <> mainPipe.io.toMonitor - - /* ===== Hardware Performance Monitor ===== */ - val perfEvents = Seq(mshrCtl, mainPipe).flatMap(_.getPerfEvents) - generatePerfEvent() -} diff --git a/src/main/scala/coupledL2/tl2tl/SourceC.scala b/src/main/scala/coupledL2/tl2tl/SourceC.scala deleted file mode 100644 index 1c816ddd..00000000 --- a/src/main/scala/coupledL2/tl2tl/SourceC.scala +++ /dev/null @@ -1,239 +0,0 @@ -/** ************************************************************************************* - * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences - * Copyright (c) 2020-2021 Peng Cheng Laboratory - * - * XiangShan is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * - * See the Mulan PSL v2 for more details. - * ************************************************************************************* - */ - -package coupledL2.tl2tl - -import chisel3._ -import chisel3.util._ -import utility._ -import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.tilelink._ -import coupledL2._ -import huancun.DirtyKey - -//class SourceC(implicit p: Parameters) extends L2Module { -// val io = IO(new Bundle() { -// val in = Flipped(DecoupledIO(new Bundle() { -// val task = new TaskBundle() -// val data = new DSBlock() -// })) -// val out = DecoupledIO(new TLBundleC(edgeOut.bundle)) -// val resp = Output(new RespBundle) -// }) -// -// val beat_valids = RegInit(VecInit(Seq.fill(mshrsAll) { // TODO: make sure there are enough entries -// VecInit(Seq.fill(beatSize)(false.B)) -// })) -// val block_valids = VecInit(beat_valids.map(_.asUInt.orR)).asUInt -// val tasks = Reg(Vec(mshrsAll, new TaskBundle)) -// val datas = Reg(Vec(mshrsAll, new DSBlock)) -// val full = block_valids.andR -// val selectOH = ParallelPriorityMux(~block_valids, (0 until mshrsAll).map(i => (1 << i).U)) -// -// selectOH.asBools.zipWithIndex.foreach { -// case (sel, i) => -// when (sel && io.in.fire()) { -// beat_valids(i).foreach(_ := true.B) -// tasks(i) := io.in.bits.task -// datas(i) := io.in.bits.data -// } -// } -// -// def toTLBundleC(task: TaskBundle, data: UInt = 0.U) = { -// val c = Wire(new TLBundleC(edgeOut.bundle)) -// c.opcode := task.opcode -// c.param := task.param -// c.size := offsetBits.U -// c.source := task.mshrId -// c.address := Cat(task.tag, task.set, task.off) -// c.data := data -// c.corrupt := false.B -// c.user.lift(utility.ReqSourceKey).foreach(_ := task.reqSource) -// c.echo.lift(DirtyKey).foreach(_ := task.dirty) -// c -// } -// -// def getBeat(data: UInt, beatsOH: UInt): (UInt, UInt) = { -// // get one beat from data according to beatsOH -// require(data.getWidth == (blockBytes * 8)) -// require(beatsOH.getWidth == beatSize) -// // next beat -// val next_beat = ParallelPriorityMux(beatsOH, data.asTypeOf(Vec(beatSize, UInt((beatBytes * 8).W)))) -// val selOH = PriorityEncoderOH(beatsOH) -// // remaining beats that haven't been sent out -// val next_beatsOH = beatsOH & ~selOH -// (next_beat, next_beatsOH) -// } -// -// val out_bundles = Wire(Vec(mshrsAll, io.out.cloneType)) -// out_bundles.zipWithIndex.foreach { -// case (out, i) => -// out.valid := block_valids(i) -// val data = datas(i).data -// val beatsOH = beat_valids(i).asUInt -// val (beat, next_beatsOH) = getBeat(data, beatsOH) -// out.bits := toTLBundleC(tasks(i), beat) -// val hasData = out.bits.opcode(0) -// -// when (out.fire()) { -// when (hasData) { -// beat_valids(i) := VecInit(next_beatsOH.asBools) -// }.otherwise { -// beat_valids(i).foreach(_ := false.B) -// } -// } -// } -// -// TLArbiter.robin(edgeIn, io.out, out_bundles:_*) -// -// io.in.ready := !full -// assert(!full, "SourceC should never be full") -// -// val (first, last, done, count) = edgeOut.count(io.out) -// val isRelease = io.out.bits.opcode === TLMessages.Release -// val isReleaseData = io.out.bits.opcode === TLMessages.ReleaseData -// // [LRelease] TODO: resp from SourceC indicating w_release_sent may be deprecated -// io.resp.valid := io.out.fire() && first && (isRelease || isReleaseData) -// io.resp.mshrId := io.out.bits.source -// io.resp.set := parseFullAddress(io.out.bits.address)._2 -// io.resp.tag := parseFullAddress(io.out.bits.address)._1 -// io.resp.respInfo := 0.U.asTypeOf(new RespInfoBundle) -// -// XSPerfAccumulate("sourceC_full", full) -//} - -class SourceCBlockBundle(implicit p: Parameters) extends L2Bundle { - val blockSinkBReqEntrance = Bool() - val blockMSHRReqEntrance = Bool() - - def apply() = 0.U.asTypeOf(this) -} - -class SourceC(implicit p: Parameters) extends L2Module { - val io = IO(new Bundle() { - val in = Flipped(DecoupledIO(new Bundle() { - val task = new TaskBundle() - val data = new DSBlock() - })) - val out = DecoupledIO(new TLBundleC(edgeOut.bundle)) - val resp = Output(new RespBundle) - val pipeStatusVec = Flipped(Vec(5, ValidIO(new PipeStatus))) - val toReqArb = Output(new SourceCBlockBundle) - }) - - // We must keep SourceC FIFO, so a queue is used - // Use customized SRAM: dual_port, max 256bits: - val queue = Module(new Queue(new TaskBundle(), entries = mshrsAll, flow = true)) - val queueData0 = Module(new Queue(new DSBeat(), entries = mshrsAll, flow = true)) - val queueData1 = Module(new Queue(new DSBeat(), entries = mshrsAll, flow = true)) - queue.io.enq.valid := io.in.valid - queue.io.enq.bits := io.in.bits.task - io.in.ready := queue.io.enq.ready - val enqData = io.in.bits.data.asTypeOf(Vec(beatSize, new DSBeat)) - queueData0.io.enq.valid := io.in.valid - queueData0.io.enq.bits := enqData(0) - queueData1.io.enq.valid := io.in.valid - queueData1.io.enq.bits := enqData(1) - // Add back pressure logic from SourceC - // refer to GrantBuffer - val sourceCQueueCnt = queue.io.count - val noSpaceForSinkBReq = PopCount(VecInit(io.pipeStatusVec.tail.map { case s => - s.valid && (s.bits.fromA || s.bits.fromB) - }).asUInt) + sourceCQueueCnt >= mshrsAll.U - val noSpaceForMSHRReq = PopCount(VecInit(io.pipeStatusVec.tail.map { case s => - s.valid && (s.bits.fromA || s.bits.fromB) - }).asUInt) + sourceCQueueCnt >= (mshrsAll-1).U - - io.toReqArb.blockSinkBReqEntrance := noSpaceForSinkBReq - io.toReqArb.blockMSHRReqEntrance := noSpaceForMSHRReq - - // dequeued task, the only, ready to fire - // WARNING: !it will reduce Release bandwidth to half!!! - // TODO: change it the same way as GrantBuf - val beatValids = RegInit(VecInit(Seq.fill(beatSize)(false.B))) - val taskValid = beatValids.asUInt.orR - val taskR = RegInit(0.U.asTypeOf(new Bundle() { - val task = new TaskBundle() - val data = new DSBlock() - })) - - val dequeueReady = !taskValid - queue.io.deq.ready := dequeueReady - queueData0.io.deq.ready := dequeueReady - queueData1.io.deq.ready := dequeueReady - when(queue.io.deq.valid && dequeueReady) { - beatValids.foreach(_ := true.B) - taskR.task := queue.io.deq.bits - taskR.data := Cat(queueData1.io.deq.bits.data, queueData0.io.deq.bits.data).asTypeOf(new DSBlock) - } - - def toTLBundleC(task: TaskBundle, data: UInt = 0.U) = { - val c = Wire(new TLBundleC(edgeOut.bundle)) - c.opcode := task.opcode - c.param := task.param - c.size := offsetBits.U - c.source := task.mshrId - c.address := Cat(task.tag, task.set, task.off) - c.data := data - c.corrupt := false.B - c.user.lift(utility.ReqSourceKey).foreach(_ := task.reqSource) - c.echo.lift(DirtyKey).foreach(_ := task.dirty) - c - } - - def getBeat(data: UInt, beatsOH: UInt): (UInt, UInt) = { - // get one beat from data according to beatsOH - require(data.getWidth == (blockBytes * 8)) - require(beatsOH.getWidth == beatSize) - // next beat - val next_beat = ParallelPriorityMux(beatsOH, data.asTypeOf(Vec(beatSize, UInt((beatBytes * 8).W)))) - val selOH = PriorityEncoderOH(beatsOH) - // remaining beats that haven't been sent out - val next_beatsOH = beatsOH & ~selOH - (next_beat, next_beatsOH) - } - - val data = taskR.data.data - val beatsOH = beatValids.asUInt - val (beat, next_beatsOH) = getBeat(data, beatsOH) - - io.out.valid := taskValid - io.out.bits := toTLBundleC(taskR.task, beat) - - val hasData = io.out.bits.opcode(0) - when (io.out.fire) { - when (hasData) { - beatValids := VecInit(next_beatsOH.asBools) - }.otherwise { - beatValids.foreach(_ := false.B) - } - } - - assert(io.in.ready, "SourceC should never be full") // WARNING - - // ========== Misc ============ - val (first, last, done, count) = edgeOut.count(io.out) - val isRelease = io.out.bits.opcode === TLMessages.Release - val isReleaseData = io.out.bits.opcode === TLMessages.ReleaseData - - // TODO: resp from SourceC indicating w_release_sent is deprecated, unused in MSHR - io.resp.valid := io.out.fire && first && (isRelease || isReleaseData) - io.resp.mshrId := io.out.bits.source - io.resp.set := parseFullAddress(io.out.bits.address)._2 - io.resp.tag := parseFullAddress(io.out.bits.address)._1 - io.resp.respInfo := 0.U.asTypeOf(new RespInfoBundle) -} \ No newline at end of file diff --git a/src/main/scala/coupledL2/utils/BankedSRAM.scala b/src/main/scala/coupledL2/utils/BankedSRAM.scala index 2540a779..e7776bd7 100644 --- a/src/main/scala/coupledL2/utils/BankedSRAM.scala +++ b/src/main/scala/coupledL2/utils/BankedSRAM.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/utils/GatedSplittedSRAM.scala b/src/main/scala/coupledL2/utils/GatedSplittedSRAM.scala index 9271c6ff..3c4987cc 100644 --- a/src/main/scala/coupledL2/utils/GatedSplittedSRAM.scala +++ b/src/main/scala/coupledL2/utils/GatedSplittedSRAM.scala @@ -1,4 +1,4 @@ -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/utils/OverwriteQueue.scala b/src/main/scala/coupledL2/utils/OverwriteQueue.scala index ed5e58a9..2f2dd89f 100644 --- a/src/main/scala/coupledL2/utils/OverwriteQueue.scala +++ b/src/main/scala/coupledL2/utils/OverwriteQueue.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/utils/Queue_SRAM.scala b/src/main/scala/coupledL2/utils/Queue_SRAM.scala index fa0e5746..4866f78a 100644 --- a/src/main/scala/coupledL2/utils/Queue_SRAM.scala +++ b/src/main/scala/coupledL2/utils/Queue_SRAM.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/utils/Replacer.scala b/src/main/scala/coupledL2/utils/Replacer.scala index 01fc40a2..e0911ef4 100644 --- a/src/main/scala/coupledL2/utils/Replacer.scala +++ b/src/main/scala/coupledL2/utils/Replacer.scala @@ -25,7 +25,7 @@ // See LICENSE.SiFive for license details. -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/utils/SRAMTemplate.scala b/src/main/scala/coupledL2/utils/SRAMTemplate.scala index ef8b43cb..92033e35 100644 --- a/src/main/scala/coupledL2/utils/SRAMTemplate.scala +++ b/src/main/scala/coupledL2/utils/SRAMTemplate.scala @@ -18,12 +18,12 @@ // See LICENSE.SiFive for license details. -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ import freechips.rocketchip.tilelink.LFSR64 -import huancun.utils.CustomAnnotations +import xscache.common.CustomAnnotations object HoldUnless { def apply[T <: Data](x: T, en: Bool): T = Mux(en, x, RegEnable(x, 0.U.asTypeOf(x), en)) diff --git a/src/main/scala/coupledL2/utils/SRAMWrapper.scala b/src/main/scala/coupledL2/utils/SRAMWrapper.scala index 5a91fe9e..cb00ebd7 100644 --- a/src/main/scala/coupledL2/utils/SRAMWrapper.scala +++ b/src/main/scala/coupledL2/utils/SRAMWrapper.scala @@ -1,4 +1,4 @@ -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/utils/SplittedSRAM.scala b/src/main/scala/coupledL2/utils/SplittedSRAM.scala index 85a84b34..19088a4c 100644 --- a/src/main/scala/coupledL2/utils/SplittedSRAM.scala +++ b/src/main/scala/coupledL2/utils/SplittedSRAM.scala @@ -1,4 +1,4 @@ -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/utils/Throttle.scala b/src/main/scala/coupledL2/utils/Throttle.scala index 1309b612..a397358a 100644 --- a/src/main/scala/coupledL2/utils/Throttle.scala +++ b/src/main/scala/coupledL2/utils/Throttle.scala @@ -1,4 +1,4 @@ -package coupledL2.utils +package xscache.coupledL2.utils import chisel3._ import chisel3.util._ diff --git a/src/main/scala/openLLC/Common.scala b/src/main/scala/openLLC/Common.scala index bc03cdc6..f32d584c 100644 --- a/src/main/scala/openLLC/Common.scala +++ b/src/main/scala/openLLC/Common.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi._ +import xscache.chi._ abstract class LLCModule(implicit val p: Parameters) extends Module with HasOpenLLCParameters diff --git a/src/main/scala/openLLC/DataStorage.scala b/src/main/scala/openLLC/DataStorage.scala index 27db6a03..47fc1ebb 100644 --- a/src/main/scala/openLLC/DataStorage.scala +++ b/src/main/scala/openLLC/DataStorage.scala @@ -15,11 +15,11 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ -import coupledL2.utils.SRAMTemplate +import xscache.coupledL2.utils.SRAMTemplate import org.chipsalliance.cde.config.Parameters class DSRequest(implicit p: Parameters) extends LLCBundle { diff --git a/src/main/scala/openLLC/Directory.scala b/src/main/scala/openLLC/Directory.scala index 6845881d..6ecedd5e 100644 --- a/src/main/scala/openLLC/Directory.scala +++ b/src/main/scala/openLLC/Directory.scala @@ -15,14 +15,14 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.utils.{SRAMTemplate, ReplacementPolicy} -import coupledL2.tl2chi.HasCHIOpcodes +import xscache.coupledL2.utils.{SRAMTemplate, ReplacementPolicy} import utility.{ParallelPriorityMux} +import xscache.chi.HasCHIOpcodes trait HasClientInfo { this: HasOpenLLCParameters => def clientCacheParams = cacheParams.clientCaches diff --git a/src/main/scala/openLLC/DummyLLC.scala b/src/main/scala/openLLC/DummyLLC.scala index f5a3366e..e4b63e70 100644 --- a/src/main/scala/openLLC/DummyLLC.scala +++ b/src/main/scala/openLLC/DummyLLC.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ @@ -23,9 +23,9 @@ import freechips.rocketchip.amba.axi4._ import freechips.rocketchip.amba.axi4.AXI4Parameters._ import freechips.rocketchip.diplomacy._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi._ -import coupledL2.tl2chi.CHICohStates._ import utility._ +import xscache.chi._ +import xscache.chi.CHICohStates._ class DummyLLC(numRNs: Int = 1)(implicit p: Parameters) extends LazyModule with HasOpenLLCParameters { val axi4node = AXI4MasterNode(Seq(AXI4MasterPortParameters( @@ -404,4 +404,4 @@ class ReceiverLinkMonitor(implicit p: Parameters) extends LLCModule with HasCHIM io.in.syscoack := RegNext(io.in.syscoreq) dontTouch(io.in) -} \ No newline at end of file +} diff --git a/src/main/scala/openLLC/LLCParam.scala b/src/main/scala/openLLC/LLCParam.scala index f4c3c1df..d6e6361c 100644 --- a/src/main/scala/openLLC/LLCParam.scala +++ b/src/main/scala/openLLC/LLCParam.scala @@ -15,15 +15,15 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import freechips.rocketchip.diplomacy._ import org.chipsalliance.cde.config.{Field, Parameters} -import coupledL2.L2Param -import huancun.CacheParameters +import xscache.coupledL2.L2Param import utility.ZeroExt +import xscache.common.CacheParameters case class ResourceConfig(refill: Int, response: Int, snoop: Int, memory: Int) diff --git a/src/main/scala/openLLC/MainPipe.scala b/src/main/scala/openLLC/MainPipe.scala index 54312055..e5ca5503 100644 --- a/src/main/scala/openLLC/MainPipe.scala +++ b/src/main/scala/openLLC/MainPipe.scala @@ -15,14 +15,14 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi._ -import coupledL2.tl2chi.CHICohStates._ import utility._ +import xscache.chi._ +import xscache.chi.CHICohStates._ class MainPipe(implicit p: Parameters) extends LLCModule with HasCHIOpcodes { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/MemUnit.scala b/src/main/scala/openLLC/MemUnit.scala index c62c31d8..c9f41d9a 100644 --- a/src/main/scala/openLLC/MemUnit.scala +++ b/src/main/scala/openLLC/MemUnit.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.HasCHIOpcodes import utility.{FastArbiter} +import xscache.chi.HasCHIOpcodes class MemState(implicit p: Parameters) extends LLCBundle { val s_issueReq = Bool() diff --git a/src/main/scala/openLLC/OpenLLC.scala b/src/main/scala/openLLC/OpenLLC.scala index 338d1276..d8f41f1e 100644 --- a/src/main/scala/openLLC/OpenLLC.scala +++ b/src/main/scala/openLLC/OpenLLC.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import freechips.rocketchip.diplomacy._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.{PortIO, CHIIssue} +import xscache.chi._ class OpenLLC(implicit p: Parameters) extends LLCModule with HasClientInfo { private val sizeBytes = cacheParams.toCacheParams.capacity.toDouble diff --git a/src/main/scala/openLLC/RefillUnit.scala b/src/main/scala/openLLC/RefillUnit.scala index f2031877..ec645753 100644 --- a/src/main/scala/openLLC/RefillUnit.scala +++ b/src/main/scala/openLLC/RefillUnit.scala @@ -15,14 +15,14 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi._ -import coupledL2.tl2chi.CHICohStates._ import utility.{FastArbiter} +import xscache.chi._ +import xscache.chi.CHICohStates._ class RefillBufRead(implicit p: Parameters) extends LLCBundle { val id = Output(UInt(log2Ceil(mshrs.refill).W)) diff --git a/src/main/scala/openLLC/RequestArb.scala b/src/main/scala/openLLC/RequestArb.scala index eba6972a..b51ddfdc 100644 --- a/src/main/scala/openLLC/RequestArb.scala +++ b/src/main/scala/openLLC/RequestArb.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.HasCHIOpcodes import scala.math.min +import xscache.chi.HasCHIOpcodes class RequestArb(implicit p: Parameters) extends LLCModule with HasClientInfo with HasCHIOpcodes { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/RequestBuffer.scala b/src/main/scala/openLLC/RequestBuffer.scala index 9320e3bb..5b473113 100644 --- a/src/main/scala/openLLC/RequestBuffer.scala +++ b/src/main/scala/openLLC/RequestBuffer.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.HasCHIOpcodes import utility.{FastArbiter} +import xscache.chi.HasCHIOpcodes class RequestBuffer(entries: Int = 8)(implicit p: Parameters) extends LLCModule with HasCHIOpcodes { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/ResponseUnit.scala b/src/main/scala/openLLC/ResponseUnit.scala index bdb0f23f..d595c637 100644 --- a/src/main/scala/openLLC/ResponseUnit.scala +++ b/src/main/scala/openLLC/ResponseUnit.scala @@ -15,14 +15,14 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi._ -import coupledL2.tl2chi.CHICohStates._ import utility.{FastArbiter} +import xscache.chi._ +import xscache.chi.CHICohStates._ class ResponseState(implicit p: Parameters) extends LLCBundle { val s_comp = Bool() diff --git a/src/main/scala/openLLC/Slice.scala b/src/main/scala/openLLC/Slice.scala index e1e13ebc..71ceb139 100644 --- a/src/main/scala/openLLC/Slice.scala +++ b/src/main/scala/openLLC/Slice.scala @@ -15,14 +15,14 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import freechips.rocketchip.amba.axi4._ import freechips.rocketchip.diplomacy._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.{DecoupledPortIO, DecoupledNoSnpPortIO} +import xscache.chi._ class Slice()(implicit p: Parameters) extends LLCModule { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/SnoopUnit.scala b/src/main/scala/openLLC/SnoopUnit.scala index be3e4dfd..5958fd30 100644 --- a/src/main/scala/openLLC/SnoopUnit.scala +++ b/src/main/scala/openLLC/SnoopUnit.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import utility.{FastArbiter} -import coupledL2.tl2chi.HasCHIOpcodes +import xscache.chi.HasCHIOpcodes class SnoopEntry(implicit p: Parameters) extends TaskEntry { val ready = Bool() diff --git a/src/main/scala/openLLC/TopDownMonitor.scala b/src/main/scala/openLLC/TopDownMonitor.scala index 717ae7ab..a7cdb6b3 100644 --- a/src/main/scala/openLLC/TopDownMonitor.scala +++ b/src/main/scala/openLLC/TopDownMonitor.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import org.chipsalliance.cde.config.Parameters import chisel3._ import chisel3.util._ -import coupledL2.tl2chi._ import utility.{XSPerfAccumulate} +import xscache.chi.HasCHIOpcodes class TopDownMonitor()(implicit p: Parameters) extends LLCModule with HasCHIOpcodes { val io = IO(new Bundle() { @@ -53,4 +53,3 @@ class TopDownMonitor()(implicit p: Parameters) extends LLCModule with HasCHIOpco XSPerfAccumulate(s"${cacheParams.name}MissMatch_${hartId}", addrMatch) } } - diff --git a/src/main/scala/openLLC/chi/LinkLayer.scala b/src/main/scala/openLLC/chi/LinkLayer.scala index bd3d0b84..48d30d2b 100644 --- a/src/main/scala/openLLC/chi/LinkLayer.scala +++ b/src/main/scala/openLLC/chi/LinkLayer.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi._ +import xscache.chi._ class DownwardsNoSnpLinkIO(implicit p: Parameters) extends Bundle with HasLinkSwitch { val req = ChannelIO(new CHIREQ) diff --git a/src/main/scala/openLLC/chi/RXDAT.scala b/src/main/scala/openLLC/chi/RXDAT.scala index 40fad1cc..3e92fbb3 100644 --- a/src/main/scala/openLLC/chi/RXDAT.scala +++ b/src/main/scala/openLLC/chi/RXDAT.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.CHIDAT +import xscache.chi.CHIDAT class RXDAT (implicit p: Parameters) extends LLCModule { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/chi/RXREQ.scala b/src/main/scala/openLLC/chi/RXREQ.scala index a1747e2e..ce5ca529 100644 --- a/src/main/scala/openLLC/chi/RXREQ.scala +++ b/src/main/scala/openLLC/chi/RXREQ.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.CHIREQ +import xscache.chi.CHIREQ // receive task from upwards and convert to inner task class RXREQ (implicit p: Parameters) extends LLCModule { @@ -61,7 +61,7 @@ class RXREQ (implicit p: Parameters) extends LLCModule { task.size := r.size task.refillTask := false.B task.reqID := Cat(0.U(1.W), bank, id_pool) - // this follows coupledL2.tl2chi.TaskBundle.toCHIReqBundle + // this follows TaskBundle.toCHIReqBundle task.tgtID := r.tgtID task.srcID := r.srcID task.txnID := r.txnID diff --git a/src/main/scala/openLLC/chi/RXRSP.scala b/src/main/scala/openLLC/chi/RXRSP.scala index a4bbf0a6..d5068351 100644 --- a/src/main/scala/openLLC/chi/RXRSP.scala +++ b/src/main/scala/openLLC/chi/RXRSP.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.CHIRSP +import xscache.chi.CHIRSP class RXRSP (implicit p: Parameters) extends LLCModule { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/chi/TXDAT.scala b/src/main/scala/openLLC/chi/TXDAT.scala index 6cb544b3..10fd8052 100644 --- a/src/main/scala/openLLC/chi/TXDAT.scala +++ b/src/main/scala/openLLC/chi/TXDAT.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.CHIDAT +import xscache.chi.CHIDAT class TXDAT (implicit p: Parameters) extends LLCModule { val io = IO(new Bundle() { @@ -51,4 +51,4 @@ class TXDAT (implicit p: Parameters) extends LLCModule { } io.task.ready := !bufferValid || last_beat && io.dat.fire -} \ No newline at end of file +} diff --git a/src/main/scala/openLLC/chi/TXREQ.scala b/src/main/scala/openLLC/chi/TXREQ.scala index bc63ed90..2164b9c0 100644 --- a/src/main/scala/openLLC/chi/TXREQ.scala +++ b/src/main/scala/openLLC/chi/TXREQ.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.CHIREQ +import xscache.chi.CHIREQ class TXREQ (implicit p: Parameters) extends LLCModule { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/chi/TXRSP.scala b/src/main/scala/openLLC/chi/TXRSP.scala index 6a9a07aa..ba39ed35 100644 --- a/src/main/scala/openLLC/chi/TXRSP.scala +++ b/src/main/scala/openLLC/chi/TXRSP.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.CHIRSP +import xscache.chi.CHIRSP class TXRSP (implicit p: Parameters) extends LLCModule { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/chi/TXSNP.scala b/src/main/scala/openLLC/chi/TXSNP.scala index fb51a638..e2046c30 100644 --- a/src/main/scala/openLLC/chi/TXSNP.scala +++ b/src/main/scala/openLLC/chi/TXSNP.scala @@ -15,12 +15,12 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi.CHISNP +import xscache.chi.CHISNP // receive inner task and send Snoop upwards class TXSNP (implicit p: Parameters) extends LLCModule { diff --git a/src/main/scala/openLLC/utils/CHIXbar.scala b/src/main/scala/openLLC/utils/CHIXbar.scala index 6f186c28..be6a4479 100644 --- a/src/main/scala/openLLC/utils/CHIXbar.scala +++ b/src/main/scala/openLLC/utils/CHIXbar.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi._ import utility.{FastArbiter} +import xscache.chi._ class RNXbar(implicit p: Parameters) extends LLCModule { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/utils/MMIOBridge.scala b/src/main/scala/openLLC/utils/MMIOBridge.scala index be90c760..b20c1d81 100644 --- a/src/main/scala/openLLC/utils/MMIOBridge.scala +++ b/src/main/scala/openLLC/utils/MMIOBridge.scala @@ -15,13 +15,13 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import coupledL2.tl2chi._ import utility.{FastArbiter} +import xscache.chi._ class MMIODiverger(implicit p: Parameters) extends LLCModule with HasCHIOpcodes { val io = IO(new Bundle() { diff --git a/src/main/scala/openLLC/utils/OpenNCB.scala b/src/main/scala/openLLC/utils/OpenNCB.scala index 4f3716e5..132bc4a1 100644 --- a/src/main/scala/openLLC/utils/OpenNCB.scala +++ b/src/main/scala/openLLC/utils/OpenNCB.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ @@ -23,11 +23,11 @@ import freechips.rocketchip.amba.axi4._ import freechips.rocketchip.amba.axi4.AXI4Parameters._ import freechips.rocketchip.diplomacy._ import org.chipsalliance.cde.config._ -import coupledL2.L2ParamKey -import coupledL2.tl2chi._ +import xscache.coupledL2.L2ParamKey import cc.xiangshan.openncb._ import cc.xiangshan.openncb.axi._ import cc.xiangshan.openncb.chi._ +import xscache.chi._ class OpenNCB(implicit p: Parameters) extends LazyModule with HasOpenLLCParameters { val ncbParams = p(NCBParametersKey) diff --git a/src/main/scala/openLLC/utils/TargetBinder.scala b/src/main/scala/openLLC/utils/TargetBinder.scala index 207fc642..759f9ad1 100644 --- a/src/main/scala/openLLC/utils/TargetBinder.scala +++ b/src/main/scala/openLLC/utils/TargetBinder.scala @@ -15,15 +15,15 @@ * ************************************************************************************* */ -package openLLC +package xscache.openLLC import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.diplomacy.AddressSet -import coupledL2.tl2chi._ import scala.collection.mutable.{Map} import utility.{FastArbiter} +import xscache.chi._ object TargetBinder { def route(in: PortIO, map: Map[AddressSet, Int])(implicit p: Parameters): Map[Int, PortIO] = { diff --git a/src/main/scala/coupledL2/tl2chi/chi/AsyncBridge.scala b/src/main/scala/xscache/chi/AsyncBridge.scala similarity index 99% rename from src/main/scala/coupledL2/tl2chi/chi/AsyncBridge.scala rename to src/main/scala/xscache/chi/AsyncBridge.scala index 675a68b3..e3618af2 100644 --- a/src/main/scala/coupledL2/tl2chi/chi/AsyncBridge.scala +++ b/src/main/scala/xscache/chi/AsyncBridge.scala @@ -14,7 +14,7 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ -package coupledL2.tl2chi +package xscache.chi import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/tl2tl/Bundle.scala b/src/main/scala/xscache/chi/CHIChannel.scala similarity index 86% rename from src/main/scala/coupledL2/tl2tl/Bundle.scala rename to src/main/scala/xscache/chi/CHIChannel.scala index d5654b56..aa4bf059 100644 --- a/src/main/scala/coupledL2/tl2tl/Bundle.scala +++ b/src/main/scala/xscache/chi/CHIChannel.scala @@ -15,4 +15,12 @@ * ************************************************************************************* */ -package coupledL2.tl2tl +package xscache.chi + +import chisel3._ + +object CHIChannel { + def TXREQ = "b001".U + def TXRSP = "b010".U + def TXDAT = "b100".U +} diff --git a/src/main/scala/coupledL2/tl2chi/chi/CHILogger.scala b/src/main/scala/xscache/chi/CHILogger.scala similarity index 99% rename from src/main/scala/coupledL2/tl2chi/chi/CHILogger.scala rename to src/main/scala/xscache/chi/CHILogger.scala index 87265aeb..b7b2749e 100644 --- a/src/main/scala/coupledL2/tl2chi/chi/CHILogger.scala +++ b/src/main/scala/xscache/chi/CHILogger.scala @@ -14,7 +14,7 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ -package coupledL2.tl2chi +package xscache.chi import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/tl2chi/chi/LinkLayer.scala b/src/main/scala/xscache/chi/LinkLayer.scala similarity index 74% rename from src/main/scala/coupledL2/tl2chi/chi/LinkLayer.scala rename to src/main/scala/xscache/chi/LinkLayer.scala index b939cfd4..5b4de106 100644 --- a/src/main/scala/coupledL2/tl2chi/chi/LinkLayer.scala +++ b/src/main/scala/xscache/chi/LinkLayer.scala @@ -15,14 +15,12 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.chi import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import utility._ -import coupledL2.L2Module -import coupledL2.HasCoupledL2Parameters class ChannelIO[+T <: Data](gen: T) extends Bundle { // Flit Pending. Early indication that a flit might be transmitted in the following cycle @@ -258,7 +256,8 @@ object LCredit2Decoupled { class Decoupled2LCredit[T <: Bundle]( gen: T, overlcreditNum: Option[Int] = None, -)(implicit val p: Parameters) extends Module with HasCoupledL2Parameters { + enableOverCredit: Boolean = false +)(implicit val p: Parameters) extends Module { val io = IO(new Bundle() { val in = Flipped(DecoupledIO(gen.cloneType)) val out = ChannelIO(gen.cloneType) @@ -274,8 +273,7 @@ class Decoupled2LCredit[T <: Bundle]( // The maximum number of L-Credits that a receiver can provide is 15. val lcreditsMax = 15 - val enableCHIAsync = cacheParams.enableCHIAsyncBridge.getOrElse(false) - val overlcreditVal = if(enableCHIAsync) overlcreditNum.getOrElse(0) else 0 + val overlcreditVal = if (enableOverCredit) overlcreditNum.getOrElse(0) else 0 val lcreditsMaxAll = lcreditsMax + overlcreditVal val lcreditPool = RegInit(overlcreditVal.U(log2Up(lcreditsMaxAll+1).W)) @@ -312,9 +310,10 @@ object Decoupled2LCredit { right: ChannelIO[T], state: LinkState, suggestName: Option[String] = None, - overlcreditNum: Option[Int] = None + overlcreditNum: Option[Int] = None, + enableOverCredit: Boolean = false )(implicit p: Parameters): Unit = { - val mod = Module(new Decoupled2LCredit(left.bits.cloneType, overlcreditNum)) + val mod = Module(new Decoupled2LCredit(left.bits.cloneType, overlcreditNum, enableOverCredit)) suggestName.foreach(name => mod.suggestName(s"Decoupled2LCredit_${name}")) mod.io.in <> left @@ -322,74 +321,3 @@ object Decoupled2LCredit { mod.io.state := state } } - -class LinkMonitor(implicit p: Parameters) extends L2Module with HasCHIOpcodes { - val io = IO(new Bundle() { - val in = Flipped(new DecoupledPortIO()) - val out = new PortIO - val nodeID = Input(UInt(NODEID_WIDTH.W)) - val exitco = Option.when(cacheParams.enableL2Flush) (Input(Bool())) - }) - // val s_stop :: s_activate :: s_run :: s_deactivate :: Nil = Enum(4) - - val txState = RegInit(LinkStates.STOP) - val rxState = RegInit(LinkStates.STOP) - - Seq(txState, rxState).zip(MixedVecInit(Seq(io.out.tx, io.out.rx))).foreach { case (state, link) => - state := MuxLookup(Cat(link.linkactivereq, link.linkactiveack), LinkStates.STOP)(Seq( - Cat(true.B, false.B) -> LinkStates.ACTIVATE, - Cat(true.B, true.B) -> LinkStates.RUN, - Cat(false.B, true.B) -> LinkStates.DEACTIVATE, - Cat(false.B, false.B) -> LinkStates.STOP - )) - } - - /* IO assignment */ - val rxsnpDeact, rxrspDeact, rxdatDeact = Wire(Bool()) - val rxDeact = rxsnpDeact && rxrspDeact && rxdatDeact - Decoupled2LCredit(setSrcID(io.in.tx.req, io.nodeID), io.out.tx.req, LinkState(txState), Some("txreq"), Some(8)) - Decoupled2LCredit(setSrcID(io.in.tx.rsp, io.nodeID), io.out.tx.rsp, LinkState(txState), Some("txrsp"), Some(8)) - Decoupled2LCredit(setSrcID(io.in.tx.dat, io.nodeID), io.out.tx.dat, LinkState(txState), Some("txdat"), Some(8)) - LCredit2Decoupled(io.out.rx.snp, io.in.rx.snp, LinkState(rxState), rxsnpDeact, Some("rxsnp")) - LCredit2Decoupled(io.out.rx.rsp, io.in.rx.rsp, LinkState(rxState), rxrspDeact, Some("rxrsp"), 15, false) - LCredit2Decoupled(io.out.rx.dat, io.in.rx.dat, LinkState(rxState), rxdatDeact, Some("rxdat"), 15, false) - - //exit coherecy + deactive tx/rx when l2 flush done - val exitco = io.exitco.getOrElse(false.B) - val exitcoDone = !io.out.syscoreq && !io.out.syscoack && RegNext(true.B, init = false.B) - - io.out.tx.linkactivereq := RegNext(!exitcoDone, init = false.B) - io.out.rx.linkactiveack := RegNext( - next = RegNext(io.out.rx.linkactivereq) || !rxDeact, - init = false.B - ) - - io.out.syscoreq := RegNext(!exitco, init = false.B) - io.out.txsactive := RegNext(!exitcoDone, init = false.B) - - val retryAckCnt = RegInit(0.U(64.W)) - val pCrdGrantCnt = RegInit(0.U(64.W)) - val noAllowRetryCnt = RegInit(0.U(64.W)) - - when (io.in.rx.rsp.fire && io.in.rx.rsp.bits.opcode === RetryAck) { - retryAckCnt := retryAckCnt + 1.U - } - when (io.in.rx.rsp.fire && io.in.rx.rsp.bits.opcode === PCrdGrant) { - pCrdGrantCnt := pCrdGrantCnt + 1.U - } - when (io.in.tx.req.fire && !io.in.tx.req.bits.allowRetry) { - noAllowRetryCnt := noAllowRetryCnt + 1.U - } - - dontTouch(io.out) - dontTouch(retryAckCnt) - dontTouch(pCrdGrantCnt) - dontTouch(noAllowRetryCnt) - - def setSrcID[T <: Bundle](in: DecoupledIO[T], srcID: UInt = 0.U): DecoupledIO[T] = { - val out = Wire(in.cloneType) - out <> in - out.bits.elements.filter(_._1 == "srcID").head._2 := srcID - out - } -} diff --git a/src/main/scala/coupledL2/tl2chi/chi/Message.scala b/src/main/scala/xscache/chi/Message.scala similarity index 98% rename from src/main/scala/coupledL2/tl2chi/chi/Message.scala rename to src/main/scala/xscache/chi/Message.scala index e091da4d..356ebc3f 100644 --- a/src/main/scala/coupledL2/tl2chi/chi/Message.scala +++ b/src/main/scala/xscache/chi/Message.scala @@ -15,17 +15,16 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.chi import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.cde.config.Field import scala.math.max -import coupledL2.{L2ParamKey, TaskBundle} -import coupledL2.tl2chi.CHICohStates._ -import coupledL2.tl2chi.CHICohStateTrans._ -import coupledL2.tl2chi.CHICohStateFwdedTrans._ +import xscache.chi.CHICohStates._ +import xscache.chi.CHICohStateTrans._ +import xscache.chi.CHICohStateFwdedTrans._ case object CHIIssue extends Field[String](Issue.B) @@ -33,6 +32,10 @@ case object NonSecureKey extends Field[Boolean](false) case object CHIAddrWidthKey extends Field[Int](48) +case object CHIDataCheckKey extends Field[String]("oddparity") + +case object CHIPoisonKey extends Field[Boolean](true) + object CHICohStates { val width = 3 @@ -223,7 +226,6 @@ trait HasCHIMsgParameters { implicit val p: Parameters val issue = p(CHIIssue) - val l2CacheParams = p(L2ParamKey) val DEFAULT_CONFIG = Map( "QOS_WIDTH" -> 4, @@ -296,14 +298,14 @@ trait HasCHIMsgParameters { // def Ea_FIELD[T <: Data](x: T): Option[T] = if (after(issue, Issue.Ea)) Some(x) else None def Eb_FIELD[T <: Data](x: T): Option[T] = if (after(issue, Issue.Eb)) Some(x) else None - def dataCheckMethod : Int = l2CacheParams.dataCheck.getOrElse("none").toLowerCase match { + def dataCheckMethod : Int = p(CHIDataCheckKey).toLowerCase match { case "none" => 0 case "oddparity" => 1 case "secded" => 2 case _ => 0 } def enableDataCheck = dataCheckMethod != 0 - def enablePoison = l2CacheParams.enablePoison + def enablePoison = p(CHIPoisonKey) def NODEID_WIDTH = CONFIG("NODEID_WIDTH") diff --git a/src/main/scala/coupledL2/tl2chi/chi/NetworkLayer.scala b/src/main/scala/xscache/chi/NetworkLayer.scala similarity index 98% rename from src/main/scala/coupledL2/tl2chi/chi/NetworkLayer.scala rename to src/main/scala/xscache/chi/NetworkLayer.scala index 18b75616..aa210ac0 100644 --- a/src/main/scala/coupledL2/tl2chi/chi/NetworkLayer.scala +++ b/src/main/scala/xscache/chi/NetworkLayer.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.chi import chisel3._ import chisel3.util._ diff --git a/src/main/scala/coupledL2/tl2chi/chi/Opcode.scala b/src/main/scala/xscache/chi/Opcode.scala similarity index 99% rename from src/main/scala/coupledL2/tl2chi/chi/Opcode.scala rename to src/main/scala/xscache/chi/Opcode.scala index 1aece66f..3a2a019b 100644 --- a/src/main/scala/coupledL2/tl2chi/chi/Opcode.scala +++ b/src/main/scala/xscache/chi/Opcode.scala @@ -15,7 +15,7 @@ * ************************************************************************************* */ -package coupledL2.tl2chi +package xscache.chi import chisel3._ import chisel3.util._ diff --git a/src/main/scala/xscache/common/BundleFields.scala b/src/main/scala/xscache/common/BundleFields.scala new file mode 100644 index 00000000..3877d47f --- /dev/null +++ b/src/main/scala/xscache/common/BundleFields.scala @@ -0,0 +1,37 @@ +/** ************************************************************************************* + * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences + * Copyright (c) 2020-2021 Peng Cheng Laboratory + * + * XiangShan is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * + * See the Mulan PSL v2 for more details. + * ************************************************************************************* + */ + +package xscache.common + +import chisel3._ +import freechips.rocketchip.util.{BundleField, ControlKey} + +case object PrefetchKey extends ControlKey[Bool](name = "needHint") + +case class PrefetchField() extends BundleField[Bool](PrefetchKey, Output(Bool()), _ := false.B) + +case object DirtyKey extends ControlKey[Bool](name = "dirty") + +case class DirtyField() extends BundleField[Bool](DirtyKey, Output(Bool()), _ := false.B) + +case object AliasKey extends ControlKey[UInt]("alias") + +case class AliasField(width: Int) extends BundleField[UInt](AliasKey, Output(UInt(width.W)), _ := 0.U(width.W)) + +case object IsHitKey extends ControlKey[Bool](name = "isHitInL3") + +case class IsHitField() extends BundleField[Bool](IsHitKey, Output(Bool()), _ := true.B) diff --git a/src/main/scala/coupledL2/tl2tl/TL2TLCoupledL2.scala b/src/main/scala/xscache/common/CacheCommon.scala similarity index 52% rename from src/main/scala/coupledL2/tl2tl/TL2TLCoupledL2.scala rename to src/main/scala/xscache/common/CacheCommon.scala index 26d3d964..3678f3f4 100644 --- a/src/main/scala/coupledL2/tl2tl/TL2TLCoupledL2.scala +++ b/src/main/scala/xscache/common/CacheCommon.scala @@ -5,7 +5,7 @@ * XiangShan is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 + * http://license.coscl.org.cn/MulanPSL2 * * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, @@ -15,24 +15,24 @@ * ************************************************************************************* */ -package coupledL2.tl2tl +package xscache.common -import chisel3._ -import chisel3.util._ -import utility.{FastArbiter, Pipeline, ParallelPriorityMux, RegNextN} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.tilelink.TLMessages._ -import freechips.rocketchip.util._ -import org.chipsalliance.cde.config.{Parameters, Field} -import scala.math.max -import coupledL2._ -import coupledL2.prefetch._ -import huancun.{TPmetaReq, TPmetaResp} +import chisel3.util.log2Ceil +import org.chipsalliance.cde.config.Field -class TL2TLCoupledL2(implicit p: Parameters) extends CoupledL2Base { +case class CacheParameters( + name: String, + sets: Int, + ways: Int, + blockGranularity: Int, + blockBytes: Int = 64, + aliasBitsOpt: Option[Int] = None, + inner: Seq[CacheParameters] = Nil +) { + val capacity = sets * ways * blockBytes + val setBits = log2Ceil(sets) + val offsetBits = log2Ceil(blockBytes) + val needResolveAlias = aliasBitsOpt.nonEmpty +} - class CoupledL2Imp(wrapper: LazyModule) extends BaseCoupledL2Imp(wrapper) - - lazy val module = new CoupledL2Imp(this) -} \ No newline at end of file +case object BankBitsKey extends Field[Int] diff --git a/src/main/scala/xscache/common/CustomAnnotations.scala b/src/main/scala/xscache/common/CustomAnnotations.scala new file mode 100644 index 00000000..25179d23 --- /dev/null +++ b/src/main/scala/xscache/common/CustomAnnotations.scala @@ -0,0 +1,44 @@ +/** ************************************************************************************* + * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences + * Copyright (c) 2020-2021 Peng Cheng Laboratory + * + * XiangShan is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * + * See the Mulan PSL v2 for more details. + * ************************************************************************************* + */ + +package xscache.common + +import chisel3.Module + +case class SRAMClkDivBy2Annotation(mod: firrtl.annotations.ModuleName) + extends firrtl.annotations.SingleTargetAnnotation[firrtl.annotations.ModuleName] { + override val target: firrtl.annotations.ModuleName = mod + + override def duplicate(n: firrtl.annotations.ModuleName): firrtl.annotations.Annotation = this.copy(n) +} + +case class SRAMSpecialDepthAnnotation(mod: firrtl.annotations.ModuleName) + extends firrtl.annotations.SingleTargetAnnotation[firrtl.annotations.ModuleName] { + override val target: firrtl.annotations.ModuleName = mod + + override def duplicate(n: firrtl.annotations.ModuleName): firrtl.annotations.Annotation = this.copy(n) +} + +object CustomAnnotations { + def annotateClkDivBy2(mod: Module): Unit = { + chisel3.experimental.annotate(mod)(Seq(SRAMClkDivBy2Annotation(mod.toNamed))) + } + + def annotateSpecialDepth(mod: Module): Unit = { + chisel3.experimental.annotate(mod)(Seq(SRAMSpecialDepthAnnotation(mod.toNamed))) + } +} diff --git a/src/test/scala/ReplacementPolicyTest.scala b/src/test/scala/ReplacementPolicyTest.scala index 7acdf954..3923621c 100644 --- a/src/test/scala/ReplacementPolicyTest.scala +++ b/src/test/scala/ReplacementPolicyTest.scala @@ -1,6 +1,6 @@ package cache -import coupledL2.utils._ +import xscache.coupledL2.utils._ import chisel3._ import chisel3.util._ import chisel3.experimental._ @@ -9,7 +9,7 @@ import chisel3.simulator.HasSimulator import svsim.verilator.Backend.CompilationSettings.TraceStyle import svsim.verilator.Backend.CompilationSettings.TraceKind -import coupledL2.utils.PseudoLRU +import xscache.coupledL2.utils.PseudoLRU import freechips.rocketchip.util.UIntToAugmentedUInt class PLRU(way: Int) extends Module { diff --git a/src/test/scala/TestProbeQueue.scala b/src/test/scala/TestProbeQueue.scala deleted file mode 100644 index 3a07a8ef..00000000 --- a/src/test/scala/TestProbeQueue.scala +++ /dev/null @@ -1,46 +0,0 @@ -package coupledL2 - -import freechips.rocketchip.diplomacy.LazyModule - - -import chisel3._ -import circt.stage.ChiselStage -import chisel3.util._ -import org.chipsalliance.cde.config._ -import chisel3.stage.ChiselGeneratorAnnotation -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tilelink._ -import scala.collection.mutable.ArrayBuffer -import huancun.DirtyField -import coupledL2.tl2tl._ - - - - -object TestProbeQueue extends App { - val config = new Config((_, _, _) => { - case L2ParamKey => L2Param( - echoField = Seq(DirtyField()) - ) - }) - - val top_coupledl2 = DisableMonitors(p => LazyModule(new TestTop_L2()(p)) )(config) - ChiselStage.elaborate(top_coupledl2.module) - - val arb_args = chisel3.aop.Select.collectDeep[ProbeQueue](top_coupledl2.module){ - case ds: ProbeQueue => - ds - }.head - - ChiselStage.emitSystemVerilog(new ProbeQueue()(arb_args.p)) -} - - - -/* -# To build a signle test Module @XiaBin -mill: - mill -i CoupledL2.test.runMain coupledL2.TestProbeQueue - -@mv *.v vsrc/ProbeQueue - -@rm *.json *.fir -*/ \ No newline at end of file diff --git a/src/test/scala/TestSplittedSRAM.scala b/src/test/scala/TestSplittedSRAM.scala index 3b1b99c6..55613c05 100644 --- a/src/test/scala/TestSplittedSRAM.scala +++ b/src/test/scala/TestSplittedSRAM.scala @@ -1,6 +1,6 @@ -package coupledL2 +package xscache.coupledL2 -import coupledL2.utils._ +import xscache.coupledL2.utils._ import chisel3._ import chisel3.util._ import chisel3.experimental._ @@ -79,5 +79,5 @@ object TestSplittedSRAM extends App with ChiselSim { /* # To build a signle test Module mill: - mill -i CoupledL2.test.runMain coupledL2.TestSplittedSRAM + mill -i CoupledL2.test.runMain xscache.coupledL2.TestSplittedSRAM */ \ No newline at end of file diff --git a/src/test/scala/TestTop_L2.scala b/src/test/scala/TestTop_L2.scala deleted file mode 100644 index 3dd6eba0..00000000 --- a/src/test/scala/TestTop_L2.scala +++ /dev/null @@ -1,777 +0,0 @@ -package coupledL2 - -import chisel3._ -import circt.stage.{ChiselStage, FirtoolOption} -import chisel3.util._ -import org.chipsalliance.cde.config._ -import chisel3.stage.ChiselGeneratorAnnotation -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.tile.MaxHartIdBits -import freechips.rocketchip.tilelink._ -import huancun._ -import coupledL2.prefetch._ -import coupledL2.tl2tl._ -import utility._ - - -import scala.collection.mutable.ArrayBuffer - -object baseConfig { - def apply(maxHartIdBits: Int) = { - new Config((_, _, _) => { - case MaxHartIdBits => maxHartIdBits - }) - } -} - -class TestTop_L2()(implicit p: Parameters) extends LazyModule { - - /* L1D - * | - * L2 - */ - - override lazy val desiredName: String = "TestTop" - val delayFactor = 0.5 - val cacheParams = p(L2ParamKey) - - def createClientNode(name: String, sources: Int) = { - val masterNode = TLClientNode(Seq( - TLMasterPortParameters.v2( - masters = Seq( - TLMasterParameters.v1( - name = name, - sourceId = IdRange(0, sources), - supportsProbe = TransferSizes(cacheParams.blockBytes) - ) - ), - channelBytes = TLChannelBeatBytes(cacheParams.blockBytes), - minLatency = 1, - echoFields = Nil, - requestFields = Seq(AliasField(2)), - responseKeys = cacheParams.respKey - ) - )) - masterNode - } - - val l1d_nodes = (0 until 1) map( i => createClientNode(s"l1d$i", 32)) - val master_nodes = l1d_nodes - - val l2 = LazyModule(new TL2TLCoupledL2()((baseConfig(1).alter((site, here, up) => { - case BankBitsKey => 0 - case LogUtilsOptionsKey => LogUtilsOptions( - false, - here(L2ParamKey).enablePerf, - here(L2ParamKey).FPGAPlatform - ) - case PerfCounterOptionsKey => PerfCounterOptions( - here(L2ParamKey).enablePerf && !here(L2ParamKey).FPGAPlatform, - here(L2ParamKey).enableRollingDB && !here(L2ParamKey).FPGAPlatform, - XSPerfLevel.withName("VERBOSE"), - 0 - ) - })))) - val xbar = TLXbar() - val ram = LazyModule(new TLRAM(AddressSet(0, 0xff_ffffL), beatBytes = 32)) - - for (l1d <- l1d_nodes) { - xbar := TLBuffer() := l1d - } - - ram.node := - TLXbar() :=* - TLFragmenter(32, 64) :=* - TLCacheCork() :=* - TLDelayer(delayFactor) :=* - l2.node :=* xbar - - lazy val module = new LazyModuleImp(this){ - val timer = WireDefault(0.U(64.W)) - val logEnable = WireDefault(false.B) - val clean = WireDefault(false.B) - val dump = WireDefault(false.B) - - dontTouch(timer) - dontTouch(logEnable) - dontTouch(clean) - dontTouch(dump) - - master_nodes.zipWithIndex.foreach{ - case (node, i) => - node.makeIOs()(ValName(s"master_port_$i")) - } - - l2.module.io.hartId := DontCare - l2.module.io.pfCtrlFromCore := DontCare - l2.module.io.debugTopDown <> DontCare - l2.module.io.l2_tlb_req <> DontCare - } - -} - -class TestTop_L2L3()(implicit p: Parameters) extends LazyModule { - /* L1I L1D - * \ / - * L2 - * | - * L3 - */ - - override lazy val desiredName: String = "TestTop" - val delayFactor = 0.2 - val cacheParams = p(L2ParamKey) - - def createClientNode(name: String, sources: Int) = { - val masterNode = TLClientNode(Seq( - TLMasterPortParameters.v2( - masters = Seq( - TLMasterParameters.v1( - name = name, - sourceId = IdRange(0, sources), - supportsProbe = TransferSizes(cacheParams.blockBytes) - ) - ), - channelBytes = TLChannelBeatBytes(cacheParams.blockBytes), - minLatency = 1, - echoFields = Nil, - requestFields = Seq(AliasField(2), PrefetchField()), - responseKeys = cacheParams.respKey - ) - )) - masterNode - } - - val l1d = createClientNode(s"l1d", 32) - val l1i = TLClientNode(Seq( - TLMasterPortParameters.v1( - clients = Seq(TLMasterParameters.v1( - name = s"l1i", - sourceId = IdRange(0, 32) - )) - ) - )) - val master_nodes = Seq(l1d, l1i) - - val l2 = LazyModule(new TL2TLCoupledL2()(baseConfig(1).alter((site, here, up) => { - case L2ParamKey => L2Param( - name = s"l2", - ways = 4, - sets = 128, - clientCaches = Seq(L1Param(aliasBitsOpt = Some(2), vaddrBitsOpt = Some(16))), - echoField = Seq(DirtyField()), - prefetch = Seq(BOPParameters( - rrTableEntries = 16, - rrTagBits = 6 - )), - tagECC = Some("secded"), - dataECC = Some("secded"), - enableTagECC = true, - enableDataECC = true, - dataCheck = Some("oddparity"), - enablePoison = true, - ) - case BankBitsKey => 0 - case LogUtilsOptionsKey => LogUtilsOptions( - false, - here(L2ParamKey).enablePerf, - here(L2ParamKey).FPGAPlatform - ) - case PerfCounterOptionsKey => PerfCounterOptions( - here(L2ParamKey).enablePerf && !here(L2ParamKey).FPGAPlatform, - here(L2ParamKey).enableRollingDB && !here(L2ParamKey).FPGAPlatform, - XSPerfLevel.withName("VERBOSE"), - 0 - ) - }))) - - val l3 = LazyModule(new HuanCun()(baseConfig(1).alter((site, here, up) => { - case HCCacheParamsKey => HCCacheParameters( - name = "l3", - level = 3, - ways = 4, - sets = 128, - inclusive = false, - clientCaches = Seq( - CacheParameters( - name = s"l2", - sets = 128, - ways = 4 + 2, - blockGranularity = log2Ceil(128) - ), - ), - echoField = Seq(DirtyField()), - simulation = true - ) - case LogUtilsOptionsKey => LogUtilsOptions( - here(HCCacheParamsKey).enableDebug, - here(HCCacheParamsKey).enablePerf, - here(HCCacheParamsKey).FPGAPlatform - ) - case PerfCounterOptionsKey => PerfCounterOptions( - here(HCCacheParamsKey).enablePerf && !here(HCCacheParamsKey).FPGAPlatform, - false, - XSPerfLevel.withName("VERBOSE"), - 0 - ) - }))) - - val xbar = TLXbar() - val ram = LazyModule(new TLRAM(AddressSet(0, 0xff_ffffL), beatBytes = 32)) - - xbar := TLBuffer() := l1i - xbar := TLBuffer() := l1d - - ram.node := - TLXbar() :=* - TLFragmenter(32, 64) :=* - TLCacheCork() :=* - TLDelayer(delayFactor) :=* - l3.node :=* - TLBuffer() := - l2.node :=* xbar - - lazy val module = new LazyModuleImp(this) { - val timer = WireDefault(0.U(64.W)) - val logEnable = WireDefault(false.B) - val clean = WireDefault(false.B) - val dump = WireDefault(false.B) - - dontTouch(timer) - dontTouch(logEnable) - dontTouch(clean) - dontTouch(dump) - - master_nodes.zipWithIndex.foreach { - case (node, i) => - node.makeIOs()(ValName(s"master_port_$i")) - } - - l2.module.io.hartId := DontCare - l2.module.io.pfCtrlFromCore := DontCare - l2.module.io.debugTopDown <> DontCare - l2.module.io.l2_tlb_req <> DontCare - } - -} - -class TestTop_L2_Standalone()(implicit p: Parameters) extends LazyModule { - - /* L1D L1D (fake) - * \ / - * L2 - * | - * L3 (fake, used for tl-test with salve) - */ - - override lazy val desiredName: String = "TestTop" - val delayFactor = 0.5 - val cacheParams = p(L2ParamKey) - - def createClientNode(name: String, sources: Int) = { - val masterNode = TLClientNode(Seq( - TLMasterPortParameters.v2( - masters = Seq( - TLMasterParameters.v1( - name = name, - sourceId = IdRange(0, sources), - supportsProbe = TransferSizes(cacheParams.blockBytes) - ) - ), - channelBytes = TLChannelBeatBytes(cacheParams.blockBytes), - minLatency = 1, - echoFields = Nil, - requestFields = Seq(AliasField(2)), - responseKeys = cacheParams.respKey - ) - )) - masterNode - } - - def createManagerNode(name: String, sources: Int) = { - val xfer = TransferSizes(cacheParams.blockBytes, cacheParams.blockBytes) - val slaveNode = TLManagerNode(Seq( - TLSlavePortParameters.v1(Seq( - TLSlaveParameters.v1( - address = Seq(AddressSet(0, 0xff_ffffL)), - regionType = RegionType.CACHED, - executable = true, - supportsAcquireT = xfer, - supportsAcquireB = xfer, - fifoId = None - )), - beatBytes = 32, - minLatency = 2, - responseFields = cacheParams.respField, - requestKeys = cacheParams.reqKey, - endSinkId = sources - )) - ) - slaveNode - } - - val l1d_nodes = (0 until 1) map( i => createClientNode(s"l1d$i", 32)) - val master_nodes = l1d_nodes - - val l2 = LazyModule(new TL2TLCoupledL2()(new Config((site, here, up) => { - case BankBitsKey => 0 - case LogUtilsOptionsKey => LogUtilsOptions( - false, - here(L2ParamKey).enablePerf, - here(L2ParamKey).FPGAPlatform - ) - case PerfCounterOptionsKey => PerfCounterOptions( - here(L2ParamKey).enablePerf && !here(L2ParamKey).FPGAPlatform, - here(L2ParamKey).enableRollingDB && !here(L2ParamKey).FPGAPlatform, - XSPerfLevel.withName("VERBOSE"), - 0 - ) - }))) - val xbar = TLXbar() - val l3 = createManagerNode("Fake_L3", 16) - - for(i <- 0 until 1) { - xbar :=* TLBuffer() := l1d_nodes(i) - } - - l3 := - TLBuffer() := - TLXbar() :=* - TLDelayer(delayFactor) :=* - l2.node :=* xbar - - lazy val module = new LazyModuleImp(this){ - val timer = WireDefault(0.U(64.W)) - val logEnable = WireDefault(false.B) - val clean = WireDefault(false.B) - val dump = WireDefault(false.B) - - dontTouch(timer) - dontTouch(logEnable) - dontTouch(clean) - dontTouch(dump) - - master_nodes.zipWithIndex.foreach{ - case (node, i) => - node.makeIOs()(ValName(s"master_port_$i")) - } - l3.makeIOs()(ValName(s"slave_port")) - l2.module.io.hartId := DontCare - l2.module.io.pfCtrlFromCore := DontCare - l2.module.io.debugTopDown <> DontCare - l2.module.io.l2_tlb_req <> DontCare - } -} - -class TestTop_L2L3L2()(implicit p: Parameters) extends LazyModule { - - /* L1D L1D - * | | - * L2 L2 - * \ / - * L3 - */ - - override lazy val desiredName: String = "TestTop" - val delayFactor = 0.2 - val cacheParams = p(L2ParamKey) - - val nrL2 = 2 - - def createClientNode(name: String, sources: Int) = { - val masterNode = TLClientNode(Seq( - TLMasterPortParameters.v2( - masters = Seq( - TLMasterParameters.v1( - name = name, - sourceId = IdRange(0, sources), - supportsProbe = TransferSizes(cacheParams.blockBytes) - ) - ), - channelBytes = TLChannelBeatBytes(cacheParams.blockBytes), - minLatency = 1, - echoFields = Nil, - requestFields = Seq(AliasField(2)), - responseKeys = cacheParams.respKey - ) - )) - masterNode - } - - val l1d_nodes = (0 until nrL2).map(i => createClientNode(s"l1d$i", 32)) - val master_nodes = l1d_nodes - - val coupledL2 = (0 until nrL2).map(i => LazyModule(new TL2TLCoupledL2()(baseConfig(1).alter((site, here, up) => { - case L2ParamKey => L2Param( - name = s"l2$i", - ways = 4, - sets = 128, - clientCaches = Seq(L1Param(aliasBitsOpt = Some(2))), - echoField = Seq(DirtyField()), - hartId = i, - tagECC = Some("secded"), - dataECC = Some("secded"), - enableTagECC = true, - enableDataECC = true, - dataCheck = Some("oddparity"), - enablePoison = true, - ) - case BankBitsKey => 0 - case LogUtilsOptionsKey => LogUtilsOptions( - false, - here(L2ParamKey).enablePerf, - here(L2ParamKey).FPGAPlatform - ) - case PerfCounterOptionsKey => PerfCounterOptions( - here(L2ParamKey).enablePerf && !here(L2ParamKey).FPGAPlatform, - here(L2ParamKey).enableRollingDB && !here(L2ParamKey).FPGAPlatform, - XSPerfLevel.withName("VERBOSE"), - i - ) - })))) - val l2_nodes = coupledL2.map(_.node) - - val l3 = LazyModule(new HuanCun()(baseConfig(1).alter((site, here, up) => { - case HCCacheParamsKey => HCCacheParameters( - name = "L3", - level = 3, - ways = 4, - sets = 128, - inclusive = false, - clientCaches = (0 until nrL2).map(i => - CacheParameters( - name = s"l2", - sets = 128, - ways = 4 + 2, - blockGranularity = log2Ceil(128) - ), - ), - echoField = Seq(DirtyField()), - simulation = true - ) - case LogUtilsOptionsKey => LogUtilsOptions( - here(HCCacheParamsKey).enableDebug, - here(HCCacheParamsKey).enablePerf, - here(HCCacheParamsKey).FPGAPlatform - ) - case PerfCounterOptionsKey => PerfCounterOptions( - here(HCCacheParamsKey).enablePerf && !here(HCCacheParamsKey).FPGAPlatform, - false, - XSPerfLevel.withName("VERBOSE"), - 0 - ) - }))) - - val xbar = TLXbar() - val ram = LazyModule(new TLRAM(AddressSet(0, 0xff_ffffL), beatBytes = 32)) - - l1d_nodes.zip(l2_nodes).zipWithIndex map { - case ((l1d, l2), i) => l2 := - TLLogger(s"L2_L1[${i}].C[0]", !cacheParams.FPGAPlatform && cacheParams.enableTLLog) := - TLBuffer() := l1d - } - - l2_nodes.zipWithIndex map { - case(l2, i) => xbar := - TLLogger(s"L3_L2[${i}]", !cacheParams.FPGAPlatform && cacheParams.enableTLLog) := - TLBuffer() := l2 - } - - ram.node := - TLXbar() :=* - TLFragmenter(32, 64) :=* - TLCacheCork() :=* - TLDelayer(delayFactor) :=* - TLLogger(s"MEM_L3", !cacheParams.FPGAPlatform && cacheParams.enableTLLog) :=* - l3.node :=* xbar - - lazy val module = new LazyModuleImp(this) { - val timer = WireDefault(0.U(64.W)) - val logEnable = WireDefault(false.B) - val clean = WireDefault(false.B) - val dump = WireDefault(false.B) - - dontTouch(timer) - dontTouch(logEnable) - dontTouch(clean) - dontTouch(dump) - - coupledL2.foreach { - case l2 => { - l2.module.io.debugTopDown <> DontCare - l2.module.io.hartId := DontCare - l2.module.io.pfCtrlFromCore := DontCare - l2.module.io.l2_tlb_req <> DontCare - } - } - - master_nodes.zipWithIndex.foreach { - case (node, i) => - node.makeIOs()(ValName(s"master_port_$i")) - } - } -} - -// This is not yet applicable, just reference -class TestTop_fullSys()(implicit p: Parameters) extends LazyModule { - - /* L1D L1I L1D L1I (L1I sends Get) - * \ / \ / - * L2 L2 - * \ / - * L3 - */ - - override lazy val desiredName: String = "TestTop" - val delayFactor = 0.2 - val cacheParams = p(L2ParamKey) - - val nrL2 = 2 - - def createClientNode(name: String, sources: Int) = { - val masterNode = TLClientNode(Seq( - TLMasterPortParameters.v2( - masters = Seq( - TLMasterParameters.v1( - name = name, - sourceId = IdRange(0, sources), - supportsProbe = TransferSizes(cacheParams.blockBytes) - ) - ), - channelBytes = TLChannelBeatBytes(cacheParams.blockBytes), - minLatency = 1, - echoFields = Nil, - requestFields = Seq(AliasField(2)), - responseKeys = cacheParams.respKey - ) - )) - masterNode - } - - val l2xbar = TLXbar() - val ram = LazyModule(new TLRAM(AddressSet(0, 0xff_ffffL), beatBytes = 32)) - var master_nodes: Seq[TLClientNode] = Seq() // TODO - - (0 until nrL2).map{i => - val l1d = createClientNode(s"l1d$i", 32) - val l1i = TLClientNode(Seq( - TLMasterPortParameters.v1( - clients = Seq(TLMasterParameters.v1( - name = s"l1i$i", - sourceId = IdRange(0, 32) - )) - ) - )) - master_nodes = master_nodes ++ Seq(l1d, l1i) // TODO - - val l1xbar = TLXbar() - val l2 = LazyModule(new TL2TLCoupledL2()(baseConfig(1).alter((site, here, up) => { - case L2ParamKey => L2Param( - name = s"l2$i", - ways = 4, - sets = 128, - clientCaches = Seq(L1Param(aliasBitsOpt = Some(2))), - echoField = Seq(DirtyField()), - prefetch = Seq(BOPParameters( - rrTableEntries = 16, - rrTagBits = 6 - )), - tagECC = Some("secded"), - dataECC = Some("secded"), - enableTagECC = true, - enableDataECC = true, - dataCheck = Some("oddparity"), - enablePoison = true, - ) - case BankBitsKey => 0 - case LogUtilsOptionsKey => LogUtilsOptions( - false, - here(L2ParamKey).enablePerf, - here(L2ParamKey).FPGAPlatform - ) - case PerfCounterOptionsKey => PerfCounterOptions( - here(L2ParamKey).enablePerf && !here(L2ParamKey).FPGAPlatform, - here(L2ParamKey).enableRollingDB && !here(L2ParamKey).FPGAPlatform, - XSPerfLevel.withName("VERBOSE"), - i - ) - }))) - - l1xbar := TLBuffer() := l1i - l1xbar := TLBuffer() := l1d - - l2xbar := TLBuffer() := l2.node := l1xbar - - InModuleBody { - l2.module.io.hartId := DontCare - l2.module.io.pfCtrlFromCore := DontCare - } - } - - val l3 = LazyModule(new HuanCun()(baseConfig(1).alter((site, here, up) => { - case HCCacheParamsKey => HCCacheParameters( - name = "L3", - level = 3, - ways = 4, - sets = 128, - inclusive = false, - clientCaches = (0 until nrL2).map(i => - CacheParameters( - name = s"l2", - sets = 128, - ways = 4 + 2, - blockGranularity = log2Ceil(128) - ), - ), - echoField = Seq(DirtyField()), - simulation = true - ) - case LogUtilsOptionsKey => LogUtilsOptions( - here(HCCacheParamsKey).enableDebug, - here(HCCacheParamsKey).enablePerf, - here(HCCacheParamsKey).FPGAPlatform - ) - case PerfCounterOptionsKey => PerfCounterOptions( - here(HCCacheParamsKey).enablePerf && !here(HCCacheParamsKey).FPGAPlatform, - false, - XSPerfLevel.withName("VERBOSE"), - 0 - ) - }))) - - ram.node := - TLXbar() :=* - TLFragmenter(32, 64) :=* - TLCacheCork() :=* - TLDelayer(delayFactor) :=* - l3.node :=* l2xbar - - lazy val module = new LazyModuleImp(this) { - val timer = WireDefault(0.U(64.W)) - val logEnable = WireDefault(false.B) - val clean = WireDefault(false.B) - val dump = WireDefault(false.B) - - dontTouch(timer) - dontTouch(logEnable) - dontTouch(clean) - dontTouch(dump) - - master_nodes.zipWithIndex.foreach { - case (node, i) => - node.makeIOs()(ValName(s"master_port_$i")) - } - } -} - -private[coupledL2] object TestTopFirtoolOptions { - def apply() = Seq( - FirtoolOption("--disable-annotation-unknown"), - FirtoolOption("--repl-seq-mem"), - FirtoolOption("--repl-seq-mem-file=TestTop.sv.conf"), - FirtoolOption("--lowering-options=explicitBitcast") - ) -} - -object TestTop_L2 extends App { - val config = baseConfig(1).alterPartial({ - case L2ParamKey => L2Param( - clientCaches = Seq(L1Param(aliasBitsOpt = Some(2))), - echoField = Seq(DirtyField()) - ) - }) - ChiselDB.init(false) - - val top = DisableMonitors(p => LazyModule(new TestTop_L2()(p)) )(config) - (new ChiselStage).execute(args, - ChiselGeneratorAnnotation(() => top.module) +: TestTopFirtoolOptions() - ) - - ChiselDB.addToFileRegisters - FileRegisters.write("./build") -} - -object TestTop_L2_Standalone extends App { - val config = baseConfig(1).alterPartial({ - case L2ParamKey => L2Param( - clientCaches = Seq(L1Param(aliasBitsOpt = Some(2))), - echoField = Seq(DirtyField()) - ) - }) - ChiselDB.init(false) - - val top = DisableMonitors(p => LazyModule(new TestTop_L2_Standalone()(p)) )(config) - (new ChiselStage).execute(args, - ChiselGeneratorAnnotation(() => top.module) +: TestTopFirtoolOptions() - ) - - ChiselDB.addToFileRegisters - FileRegisters.write("./build") -} - -object TestTop_L2L3 extends App { - val config = baseConfig(1).alterPartial({ - case L2ParamKey => L2Param( - clientCaches = Seq(L1Param(aliasBitsOpt = Some(2))), - echoField = Seq(DirtyField()) - ) - case HCCacheParamsKey => HCCacheParameters( - echoField = Seq(DirtyField()) - ) - }) - ChiselDB.init(true) - Constantin.init(false) - - val top = DisableMonitors(p => LazyModule(new TestTop_L2L3()(p)) )(config) - (new ChiselStage).execute(args, - ChiselGeneratorAnnotation(() => top.module) +: TestTopFirtoolOptions() - ) - - ChiselDB.addToFileRegisters - Constantin.addToFileRegisters - FileRegisters.write("./build") -} - -object TestTop_L2L3L2 extends App { - val config = baseConfig(1).alterPartial({ - case L2ParamKey => L2Param( - clientCaches = Seq(L1Param(aliasBitsOpt = Some(2))), - // echoField = Seq(DirtyField()) - ) - case HCCacheParamsKey => HCCacheParameters( - echoField = Seq(DirtyField()) - ) - }) - ChiselDB.init(true) - Constantin.init(false) - - val top = DisableMonitors(p => LazyModule(new TestTop_L2L3L2()(p)))(config) - (new ChiselStage).execute(args, - ChiselGeneratorAnnotation(() => top.module) +: TestTopFirtoolOptions() - ) - - ChiselDB.addToFileRegisters - Constantin.addToFileRegisters - FileRegisters.write("./build") -} - -object TestTop_fullSys extends App { - val config = baseConfig(1).alterPartial({ - case L2ParamKey => L2Param( - clientCaches = Seq(L1Param(aliasBitsOpt = Some(2))), - echoField = Seq(DirtyField()) - ) - case HCCacheParamsKey => HCCacheParameters( - echoField = Seq(DirtyField()) - ) - }) - ChiselDB.init(false) - - val top = DisableMonitors(p => LazyModule(new TestTop_fullSys()(p)))(config) - (new ChiselStage).execute(args, - ChiselGeneratorAnnotation(() => top.module) +: TestTopFirtoolOptions() - ) - - ChiselDB.addToFileRegisters - FileRegisters.write("./build") -} diff --git a/src/test/scala/TestTop_LLC.scala b/src/test/scala/TestTop_LLC.scala index 3bf2ef72..8f062158 100644 --- a/src/test/scala/TestTop_LLC.scala +++ b/src/test/scala/TestTop_LLC.scala @@ -1,4 +1,4 @@ -package openLLC +package xscache.openLLC import chisel3._ import circt.stage.{ChiselStage, FirtoolOption} @@ -10,12 +10,13 @@ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tile.MaxHartIdBits import freechips.rocketchip.tilelink._ import org.chipsalliance.cde.config._ -import coupledL2._ -import coupledL2.tl2chi._ +import xscache.coupledL2.{CoupledL2, EdgeInKey, L1Param, L2Param, L2ParamKey, L2ToL1Hint} import cc.xiangshan.openncb._ import cc.xiangshan.openncb.chi._ import utility._ import utility.chiron._ +import xscache.common.{AliasField, BankBitsKey} +import xscache.chi._ class TestTop_L3()(implicit p: Parameters) extends LazyModule with HasCHIMsgParameters { override lazy val desiredName: String = "TestTop_L3" @@ -90,7 +91,7 @@ class TestTopSoC(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, issue: channelBytes = TLChannelBeatBytes(l2Params.blockBytes), minLatency = 1, echoFields = Nil, - requestFields = Seq(huancun.AliasField(2)), + requestFields = Seq(AliasField(2)), responseKeys = l2Params.respKey ) )) @@ -111,15 +112,13 @@ class TestTopSoC(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, issue: } } - // val l2 = LazyModule(new TL2CHICoupledL2()) - val l2_nodes = (0 until numCores).map(i => LazyModule(new TL2CHICoupledL2()(new Config((site, here, up) => { + val l2_nodes = (0 until numCores).map(i => LazyModule(new CoupledL2()(new Config((site, here, up) => { case L2ParamKey => l2Params.copy( name = s"L2_$i", hartId = i, ) - case EnableCHI => true case CHIIssue => issue - case huancun.BankBitsKey => log2Ceil(banks) + case BankBitsKey => log2Ceil(banks) case MaxHartIdBits => log2Up(numCores) case LogUtilsOptionsKey => LogUtilsOptions( false, @@ -270,25 +269,25 @@ class TestTopSoC(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, issue: vTime = false, clock = l2.module.clock, reset = l2.module.reset, - rnId = l2.module.io_nodeID, - txreqflit = l2.module.io_chi.tx.req.flit, txreqflitv = l2.module.io_chi.tx.req.flitv, - rxrspflit = l2.module.io_chi.rx.rsp.flit, rxrspflitv = l2.module.io_chi.rx.rsp.flitv, - rxdatflit = l2.module.io_chi.rx.dat.flit, rxdatflitv = l2.module.io_chi.rx.dat.flitv, - rxsnpflit = l2.module.io_chi.rx.snp.flit, rxsnpflitv = l2.module.io_chi.rx.snp.flitv, - txrspflit = l2.module.io_chi.tx.rsp.flit, txrspflitv = l2.module.io_chi.tx.rsp.flitv, - txdatflit = l2.module.io_chi.tx.dat.flit, txdatflitv = l2.module.io_chi.tx.dat.flitv, + rnId = l2.module.io.nodeID, + txreqflit = l2.module.io.chi.tx.req.flit, txreqflitv = l2.module.io.chi.tx.req.flitv, + rxrspflit = l2.module.io.chi.rx.rsp.flit, rxrspflitv = l2.module.io.chi.rx.rsp.flitv, + rxdatflit = l2.module.io.chi.rx.dat.flit, rxdatflitv = l2.module.io.chi.rx.dat.flitv, + rxsnpflit = l2.module.io.chi.rx.snp.flit, rxsnpflitv = l2.module.io.chi.rx.snp.flitv, + txrspflit = l2.module.io.chi.tx.rsp.flit, txrspflitv = l2.module.io.chi.tx.rsp.flitv, + txdatflit = l2.module.io.chi.tx.dat.flit, txdatflitv = l2.module.io.chi.tx.dat.flitv, time = time_sim, timev = extTime.B ) } - l2.module.io_chi <> l3.io.rn(i) + l2.module.io.chi <> l3.io.rn(i) dontTouch(l2.module.io) l2.module.io.l2_hint <> io_l1(i).l2Hint l2.module.io.hartId := i.U l2.module.io.pfCtrlFromCore := DontCare - l2.module.io_nodeID := i.U(NODEID_WIDTH.W) + l2.module.io.nodeID := i.U(NODEID_WIDTH.W) l2.module.io.debugTopDown := DontCare l2.module.io.l2_tlb_req <> DontCare } diff --git a/src/test/scala/TestWritebackQueue.scala b/src/test/scala/TestWritebackQueue.scala deleted file mode 100644 index faf0991c..00000000 --- a/src/test/scala/TestWritebackQueue.scala +++ /dev/null @@ -1,43 +0,0 @@ -// package coupledL2 - -// import freechips.rocketchip.diplomacy.LazyModule - - -// import chisel3._ -// import chisel3.util._ -// import org.chipsalliance.cde.config._ -// import freechips.rocketchip.diplomacy._ -// import freechips.rocketchip.tilelink._ -// import scala.collection.mutable.ArrayBuffer - - - - - -// object TestWritebackQueue extends App { -// val config = new Config((_, _, _) => { -// case L2ParamKey => L2Param( -// echoField = Seq(DirtyField()) -// ) -// }) - -// val top_coupledl2 = DisableMonitors(p => LazyModule(new TestTop_L2()(p)) )(config) -// chisel3.stage.ChiselStage.elaborate(top_coupledl2.module) - -// val arb_args = chisel3.aop.Select.collectDeep[WritebackQueue](top_coupledl2.module){ -// case ds: WritebackQueue => -// ds -// }.head - -// (new chisel3.stage.ChiselStage).emitVerilog(new WritebackQueue()(arb_args.p)) -// } - - - -/* -# To build a signle test Module @XiaBin -mill: - mill -i CoupledL2.test.runMain coupledL2.TestWritebackQueue - -@mv *.v vsrc/WritebackQueue - -@rm *.json *.fir -*/ \ No newline at end of file diff --git a/src/test/scala/chi/TestTop.scala b/src/test/scala/chi/TestTop.scala index 53e4aaf7..a8ea43ba 100644 --- a/src/test/scala/chi/TestTop.scala +++ b/src/test/scala/chi/TestTop.scala @@ -1,19 +1,21 @@ -package coupledL2 +package xscache.coupledL2 import chisel3._ import circt.stage.ChiselStage +import circt.stage.FirtoolOption import chisel3.util._ import org.chipsalliance.cde.config._ import chisel3.stage.ChiselGeneratorAnnotation import freechips.rocketchip.diplomacy._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tile.MaxHartIdBits -import huancun._ -import coupledL2.prefetch._ -import coupledL2.tl2chi._ +import xscache.coupledL2.prefetch._ +import xscache.coupledL2._ import utility._ import utility.chiron._ +import xscache.common.{AliasField, BankBitsKey, PrefetchField} import scala.collection.mutable.ArrayBuffer +import xscache.chi._ class TestTop_CHIL2(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, extTime: Boolean = false, vTime: Boolean = false)(implicit p: Parameters) extends LazyModule with HasCHIMsgParameters { @@ -70,14 +72,12 @@ class TestTop_CHIL2(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, ext } } - // val l2 = LazyModule(new TL2CHICoupledL2()) - val l2_nodes = (0 until numCores).map(i => LazyModule(new TL2CHICoupledL2()(new Config((site, here, up) => { + val l2_nodes = (0 until numCores).map(i => LazyModule(new CoupledL2()(new Config((site, here, up) => { case L2ParamKey => cacheParams.copy( name = s"L2_$i", hartId = i, ) case CHIIssue => p(CHIIssue) - case EnableCHI => p(EnableCHI) case BankBitsKey => log2Ceil(banks) case MaxHartIdBits => log2Up(numCores) case LogUtilsOptionsKey => LogUtilsOptions( @@ -180,18 +180,18 @@ class TestTop_CHIL2(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, ext vTime = vTime, clock = l2.module.clock, reset = l2.module.reset, - rnId = l2.module.io_nodeID, - txreqflit = l2.module.io_chi.tx.req.flit, txreqflitv = l2.module.io_chi.tx.req.flitv, - rxrspflit = l2.module.io_chi.rx.rsp.flit, rxrspflitv = l2.module.io_chi.rx.rsp.flitv, - rxdatflit = l2.module.io_chi.rx.dat.flit, rxdatflitv = l2.module.io_chi.rx.dat.flitv, - rxsnpflit = l2.module.io_chi.rx.snp.flit, rxsnpflitv = l2.module.io_chi.rx.snp.flitv, - txrspflit = l2.module.io_chi.tx.rsp.flit, txrspflitv = l2.module.io_chi.tx.rsp.flitv, - txdatflit = l2.module.io_chi.tx.dat.flit, txdatflitv = l2.module.io_chi.tx.dat.flitv, + rnId = l2.module.io.nodeID, + txreqflit = l2.module.io.chi.tx.req.flit, txreqflitv = l2.module.io.chi.tx.req.flitv, + rxrspflit = l2.module.io.chi.rx.rsp.flit, rxrspflitv = l2.module.io.chi.rx.rsp.flitv, + rxdatflit = l2.module.io.chi.rx.dat.flit, rxdatflitv = l2.module.io.chi.rx.dat.flitv, + rxsnpflit = l2.module.io.chi.rx.snp.flit, rxsnpflitv = l2.module.io.chi.rx.snp.flitv, + txrspflit = l2.module.io.chi.tx.rsp.flit, txrspflitv = l2.module.io.chi.tx.rsp.flitv, + txdatflit = l2.module.io.chi.tx.dat.flit, txdatflitv = l2.module.io.chi.tx.dat.flitv, time = time_sim, timev = extTime.B ) } - l2.module.io_chi <> io(i).chi + l2.module.io.chi <> io(i).chi l2.module.io.l2_hint <> io_l1(i).l2Hint @@ -199,7 +199,7 @@ class TestTop_CHIL2(numCores: Int = 1, numULAgents: Int = 0, banks: Int = 1, ext l2.module.io.hartId := i.U l2.module.io.pfCtrlFromCore := DontCare - l2.module.io_nodeID := io(i).nodeId + l2.module.io.nodeID := io(i).nodeId l2.module.io.debugTopDown := DontCare l2.module.io.l2_tlb_req <> DontCare } @@ -246,7 +246,6 @@ object TestTopCHIHelper { sam = Seq(AddressSet.everything -> 0) ) case CHIIssue => issue - case EnableCHI => true }) CLogB.init(true) @@ -255,9 +254,11 @@ object TestTopCHIHelper { val top = DisableMonitors(p => LazyModule(fTop(p)))(config) - (new ChiselStage).execute(args, - ChiselGeneratorAnnotation(() => top.module) +: TestTopFirtoolOptions() - ) + (new ChiselStage).execute(args, Seq( + ChiselGeneratorAnnotation(() => top.module), + FirtoolOption("--disable-annotation-unknown"), + FirtoolOption("--default-layer-specialization=enable") + )) ChiselDB.addToFileRegisters FileRegisters.write("./build") diff --git a/src/test/scala/tltest/BigIntUtils.scala b/src/test/scala/tltest/BigIntUtils.scala deleted file mode 100644 index 799cbb41..00000000 --- a/src/test/scala/tltest/BigIntUtils.scala +++ /dev/null @@ -1,56 +0,0 @@ -package tltest - -import scala.collection.mutable.ListBuffer - -object BigIntUtils { - val prefix: Array[Byte] = Array(0.toByte) - - def extract256Bit(n: BigInt, index: Int): BigInt = { - val mask256 = BigInt(prefix ++ Array.fill(32)(0xff.toByte)) - (n >> (index * 256)) & mask256 - } - - def replaceNBytes(n: BigInt, in: BigInt, start: Int, len: Int): BigInt = { - val inArray = in.toByteArray.dropWhile(_ == 0) - val nArray = n.toByteArray.dropWhile(_ == 0) - require( - inArray.length <= len, - s"given insert value:$in, inArray: ${inArray.mkString("Array(", ", ", ")")} longer than len: $len" - ) - if (nArray.length <= start) { - BigInt(prefix ++ inArray ++ Array.fill(start - nArray.length)(0.toByte) ++ nArray) - } else { - BigInt( - prefix ++ nArray.dropRight(start + len) ++ Array.fill(len - inArray.length)(0.toByte) ++ inArray ++ nArray - .takeRight(start) - ) - } - } - - def extractByte(n: BigInt, start: Int, len: Int): BigInt = { - val mask = BigInt(prefix ++ Array.fill(len)(0xff.toByte)) - (n >> (start * 8)) & mask - } - - def writeMaskedData(old: BigInt, in: BigInt, mask: BigInt): BigInt = { - val mask8_buffer = ListBuffer[Byte]() - var tmp_mask = mask - while (tmp_mask != 0) { - mask8_buffer.prepend( - if ((tmp_mask & 1) == 1) { - 0xff.toByte - } else { - 0.toByte - } - ) - tmp_mask >>= 1 - } - val tmp = mask8_buffer.toArray - val mask8 = BigInt(prefix ++ tmp) - ((old | mask8) ^ mask8) | (in & mask8) - } - - def cleanMask(old: BigInt, off: BigInt): BigInt = { - (old | off) ^ off - } -} diff --git a/src/test/scala/tltest/TLCAgent.scala b/src/test/scala/tltest/TLCAgent.scala deleted file mode 100644 index 41d0f9d9..00000000 --- a/src/test/scala/tltest/TLCAgent.scala +++ /dev/null @@ -1,1323 +0,0 @@ -package tltest - -import scala.collection.mutable -import scala.collection.mutable.{ArrayBuffer, ListBuffer} - -import scala.util.Random -import chisel3.util._ -import BigIntUtils._ -import TLMessagesBigInt._ - -class ScoreboardData { - var mainData: BigInt = 0 - var mainVersion: BigInt = 0 - val dataMap: mutable.Map[BigInt, BigInt] = mutable.Map[BigInt, BigInt]() - val refCntMap: mutable.Map[BigInt, Int] = mutable.Map[BigInt, Int]() - - def writeNewData(in: BigInt): Unit = { - mainData = in - mainVersion = 0 - } - - def getReadDataVersion(): BigInt = { - if (!refCntMap.contains(mainVersion)) { - val freeSlot = (1 to 7).map(BigInt(_)).find(!refCntMap.contains(_)) - mainVersion = freeSlot.get - refCntMap(mainVersion) = 1 - dataMap(mainVersion) = mainData - } else { - refCntMap(mainVersion) = refCntMap(mainVersion) + 1 - } - mainVersion - } - - def peekMatchVersion(ver: BigInt): BigInt = { - val cnt = refCntMap(ver) - assert(cnt >= 1, "SB has more consumer than reference") - val data = dataMap(ver) - if (cnt == 1) { - refCntMap.remove(ver) - dataMap.remove(ver) - } else { - refCntMap(ver) = cnt - 1 - } - data - } -} - -class AddrState { - val callerTrans: ListBuffer[TLCCallerTrans] = ListBuffer() - val calleeTrans: ListBuffer[TLCCalleeTrans] = ListBuffer() - var masterPerm: BigInt = nothing - var myPerm: BigInt = nothing - var data: BigInt = 0 - var dirty: Boolean = false - - var pendingGrant = false - var pendingGrantAck = false - var pendingReleaseAck = false - var pendingProbeAck = false - - def masterUpdatePendingGrant(): Unit = { - pendingGrant = callerTrans.foldLeft(false)((res, caller) => { - res || { - caller match { - case acq: AcquireCallerTrans => acq.grantPending.getOrElse(false) - case _ => false - } - } - }) - } - - def slaveUpdatePendingGrantAck(): Unit = { - pendingGrantAck = calleeTrans.foldLeft(false)((res, callee) => { - res || { - callee match { - case acq: AcquireCalleeTrans => acq.grantAckPending.getOrElse(false) - case _ => false - } - } - }) - } - - def masterUpdatePendingReleaseAck(): Unit = { - pendingReleaseAck = callerTrans.foldLeft(false)((res, caller) => { - res || { - caller match { - case rel: ReleaseCallerTrans => rel.releaseAckPending.getOrElse(false) - case _ => false - } - } - }) - } - - def slaveUpdatePendingProbeAck(): Unit = { - pendingProbeAck = callerTrans.foldLeft(false)((res, caller) => { - res || { - caller match { - case pro: ProbeCallerTrans => pro.probeAckPending.getOrElse(false) - case _ => false - } - } - }) - } - - def blockInnerAcquire(): Boolean = { - pendingGrantAck || pendingProbeAck || pendingGrant || pendingReleaseAck - } - - def blockOuterProbe(): Boolean = { - pendingGrantAck || pendingProbeAck || pendingReleaseAck - } - - def blockInnerRelease(): Boolean = { - pendingReleaseAck - } - -} - -class FireQueue[T <: TLCScalaMessage]() { - val q: mutable.Queue[(T, Int)] = mutable.Queue[(T, Int)]() - var headCnt = 0 - var beatCnt = 0 - - def enqMessage(message: T, cnt: Int = 1): Unit = { - q.enqueue((message, cnt)) - if (q.size == 1) { - headCnt = cnt - beatCnt = 0 - } - } - - def fireHead(): Unit = { - beatCnt += 1 - if (beatCnt == headCnt) { - val m = q.dequeue() - if (m._1.trans.isDefined) - m._1.trans.get.startTimer() - beatCnt = 0 - if (q.nonEmpty) { - headCnt = q.head._2 - } - } - } -} - -class TLCAgent( - ID: Int, - name: String = "", - addrStateMap: mutable.Map[BigInt, AddrState], - serialList: ArrayBuffer[(Int, TLCTrans)], - scoreboard: mutable.Map[BigInt, ScoreboardData], - blockBytes: Int, - beatBytes: Int) - extends PermissionTransition { - val beatNum = blockBytes / beatBytes - val beatBits = beatBytes * 8 - val blockWords = blockBytes / 8 - - val wordBits = 64 - val wordBytes = 8 - val wordAddrBits = 3 - val blockAddrBits = log2Up(blockBytes) - val beatAddrBits = log2Up(beatBytes) - val fullBeatMask = BigInt(prefix ++ Array.fill(beatBytes)(0xff.toByte)) - val fullBlockMask = BigInt(prefix ++ Array.fill(blockBytes)(0xff.toByte)) - val offsetMask: Long = (1L << log2Up(blockBytes)) - 1 - - val rand = new Random(0xdad) - - var clock = 0 - - def transStep(): Unit = { - () - } - - def step(): Unit = { - transStep() - clock += 1 - } - - def debugPrefix(): String = { - f"[DEBUG][time= $clock%19d] TLAgent$ID-$name: " - } - - def debugPrintln(ins: String): Unit = { - println(debugPrefix() ++ ins) - } - - def getState(addr: BigInt): AddrState = { - val state = addrStateMap.getOrElse(addr, new AddrState()) - if (!addrStateMap.contains(addr)) { //alloc new state if need - addrStateMap += (addr -> state) - if (!scoreboard.contains(addr)) { //alloc scoreboard if needed - scoreboard += (addr -> new ScoreboardData()) - } - } - state - } - - def countBeats(size: BigInt): Int = { - if ((1 << size.toInt) <= beatBytes) - 1 - else - ((1 << size.toInt) / beatBytes) - } - - def addrAlignBlock(addr: BigInt): BigInt = { - (addr >> blockAddrBits) << blockAddrBits - } - - def dataConcatBeat(oldData: BigInt, inData: BigInt, cnt: Int): BigInt = { - oldData | (inData << (cnt * beatBits)) - } - - def dataConcatWord(oldData: BigInt, inData: BigInt, cnt: Int): BigInt = { - oldData | (inData << (cnt * wordBits)) - } - - def dataOutOfBeat(inData: BigInt, cnt: Int): BigInt = { - inData >> (cnt * beatBits) - } - - def dataOutOfWord(inData: BigInt, cnt: Int): BigInt = { - inData >> (cnt * wordBits) - } - - def maskConcatBeat(oldMask: BigInt, inMask: BigInt, cnt: Int): BigInt = { - oldMask | (inMask << (cnt * beatBytes)) - } - - def maskConcatWord(oldMask: BigInt, inMask: BigInt, cnt: Int): BigInt = { - oldMask | (inMask << (cnt * wordBytes)) - } - - def maskOutOfWord(mask: BigInt, cnt: Int): BigInt = { - mask >> (cnt * wordBytes) - } - - def beatInBlock(addr: BigInt): Int = { - ((addr & offsetMask) >> beatAddrBits).toInt - } - - def wordInBlock(addr: BigInt): Int = { - ((addr & offsetMask) >> wordAddrBits).toInt - } - - def genWordMaskInBlock(addr: BigInt, wordMask: BigInt): BigInt = { - maskConcatWord(0, wordMask, wordInBlock(addr)) - } - - def randomBlockData(): BigInt = { - (0 until blockWords).foldLeft(BigInt(0))((d, _) => (d << 64) | (rand.nextLong() & 0x7fffffffffffffffL)) - } - - def appendSerial(t: TLCTrans): Unit = { - /*serialList.synchronized { - serialList.append((ID, t)) - }*/ - } - - //only for master Get - def insertVersionRead(addr: BigInt, ver: BigInt): BigInt = { - val alignAddr = addrAlignBlock(addr) - if (ver == 0) //from l2, just read scoreboard - scoreboardRead(alignAddr) - else //from l3, need match version - scoreboardPeekMatchData(alignAddr, ver) - } - - def insertMaskedReadSnap(addr: BigInt, readData: BigInt, snapData: BigInt, byteMask: BigInt): Unit = { - //addr and mask must be aligned to block - val alignAddr = addrAlignBlock(addr) - val start_beat = beatInBlock(addr) - val alignData = dataConcatBeat(0, readData, start_beat) - val alignMask = maskConcatBeat(0, byteMask, start_beat) - val addrState = getState(alignAddr) - addrState.data = writeMaskedData(addrState.data, alignData, alignMask) - val sbData = snapData - val checkWriteData = writeMaskedData(sbData, alignData, alignMask) - debugPrintln(f"MaskedRead, Addr: $alignAddr%x , own data: $alignData%x , sbData:$sbData%x , mask:$alignMask%x") - assert( - sbData == checkWriteData, - f"agent $ID data has been changed, Addr: $alignAddr%x, " + - f"own data: $alignData%x , scoreboard data: $sbData%x , mask:$alignMask%x" - ) - } - - //core Agent always read latest version - def insertMaskedWordRead(addr: BigInt, readWordData: BigInt, wordByteMask: BigInt): Unit = { - //addr and mask must be aligned to block - val alignAddr = addrAlignBlock(addr) - val start_word = wordInBlock(addr) - val alignData = dataConcatWord(0, readWordData, start_word) - val alignMask = maskConcatWord(0, wordByteMask, start_word) - val addrState = getState(alignAddr) - addrState.data = writeMaskedData(addrState.data, alignData, alignMask) - val sbData = insertVersionRead(addr, 0) - val checkWriteData = writeMaskedData(sbData, alignData, alignMask) - debugPrintln(f"MaskedRead, Addr: $alignAddr%x , own data: $alignData%x , sbData:$sbData%x , mask:$alignMask%x") - assert( - sbData == checkWriteData, - f"agent $ID data has been changed, Addr: $alignAddr%x, " + - f"own data: $alignData%x , scoreboard data: $sbData%x , mask:$alignMask%x" - ) - } - - //for Put - def insertMaskedWrite(addr: BigInt, newData: BigInt, byteMask: BigInt): Unit = { - //addr and mask must be aligned to block - val alignAddr = addrAlignBlock(addr) - val start_beat = beatInBlock(addr) - val alignData = dataConcatBeat(0, newData, start_beat) - val alignMask = maskConcatBeat(0, byteMask, start_beat) - val addrState = getState(alignAddr) - //new data - val oldData = scoreboardRead(alignAddr) - val res = writeMaskedData(oldData, alignData, alignMask) - addrState.dirty = true - addrState.data = res - scoreboardWrite(alignAddr, res) - debugPrintln(f"MaskedWrite, Addr: $alignAddr%x ,old sbData:$oldData%x , new sbData: $res%x , mask:$alignMask%x") - } - - def insertMaskedWordWrite(addr: BigInt, newWordData: BigInt, wordByteMask: BigInt): Unit = { - //addr and mask must be aligned to block - val alignAddr = addrAlignBlock(addr) - val start_word = wordInBlock(addr) - val alignData = dataConcatWord(0, newWordData, start_word) - val alignMask = maskConcatWord(0, wordByteMask, start_word) - val addrState = getState(alignAddr) - //new data - val oldData = scoreboardRead(alignAddr) - val res = writeMaskedData(oldData, alignData, alignMask) - addrState.dirty = true - addrState.data = res - scoreboardWrite(alignAddr, res) - debugPrintln(f"MaskedWrite, Addr: $alignAddr%x ,old sbData:$oldData%x , new sbData: $res%x , mask:$alignMask%x") - } - - //full block read - def insertRead(addr: BigInt, readData: BigInt): Unit = { - //Do not call masked read for performance - val addrState = getState(addr) - addrState.data = readData - val sbData = scoreboardRead(addr) - debugPrintln(f"insertFullBlockRead, Addr: $addr%x ,own data: $readData%x") - assert( - readData == sbData, - f"agent $ID data has been changed, Addr: $addr%x, " + - f"own data: $readData%x , scoreboard data: $sbData%x , with full mask" - ) - } - - //read block with snapshot - def insertReadSnap(addr: BigInt, readData: BigInt, snapData: BigInt): Unit = { - val addrState = getState(addr) - addrState.data = readData - val sbData = snapData - debugPrintln(f"insertFullBlockRead, Addr: $addr%x ,own data: $readData%x") - assert( - readData == sbData, - f"agent $ID data has been changed, Addr: $addr%x, " + - f"own data: $readData%x , scoreboard data: $sbData%x , with full mask" - ) - } - - //full block write, only write new data - def insertFullWrite(addr: BigInt, newData: BigInt): Unit = { - //Do not call masked write for performance - val addrState = getState(addr) - //new data - addrState.dirty = true - addrState.data = newData - scoreboardWrite(addr, newData) - debugPrintln(f"insertFullBlockWrite, Addr: $addr%x ,new sbData: $newData%x") - } - - //full block read & write, check old data before write new data - def insertReadWrite(addr: BigInt, readData: BigInt, newData: BigInt): Unit = { - //check old data - insertRead(addr, readData) - //new data - insertFullWrite(addr, newData) - } - - def insertReadSnapWrite(addr: BigInt, readData: BigInt, snapData: BigInt, newData: BigInt): Unit = { - //check old data - insertReadSnap(addr, readData, snapData) - //new data - insertFullWrite(addr, newData) - } - - def scoreboardRead(addr: BigInt): BigInt = { - scoreboard.synchronized { - if (!scoreboard.contains(addr)) - scoreboard(addr) = new ScoreboardData() - scoreboard(addr).mainData - } - } - - //for master checking read data with version - def scoreboardPeekMatchData(addr: BigInt, ver: BigInt): BigInt = { - scoreboard.synchronized { - scoreboard(addr).peekMatchVersion(ver) - } - } - - def scoreboardGetVer(addr: BigInt): BigInt = { - scoreboard.synchronized { - scoreboard(addr).getReadDataVersion() - } - } - - def scoreboardWrite(addr: BigInt, data: BigInt): Unit = { - scoreboard.synchronized { - scoreboard(addr).writeNewData(data) - } - } - -} - -class TLCSlaveAgent( - ID: Int, - name: String = "", - val maxSink: Int, - addrStateMap: mutable.Map[BigInt, AddrState], - serialList: ArrayBuffer[(Int, TLCTrans)], - scoreboard: mutable.Map[BigInt, ScoreboardData], - blockBytes: Int, - beatBytes: Int) - extends TLCAgent(ID, name, addrStateMap, serialList, scoreboard, blockBytes, beatBytes) { - val innerAcquire = ListBuffer[AcquireCalleeTrans]() - val innerRelease = ListBuffer[ReleaseCalleeTrans]() - val innerProbe = ListBuffer[ProbeCallerTrans]() - - val innerGet: mutable.Queue[GetCalleeTrans] = mutable.Queue[GetCalleeTrans]() - val innerPut: mutable.Queue[PutCalleeTrans] = mutable.Queue[PutCalleeTrans]() - - val sinkIdMap = mutable.Map[BigInt, AcquireCalleeTrans]() - val sinkFreeQueue = mutable.Queue[BigInt]() - - def freeSink(): Unit = { - sinkFreeQueue.dequeueAll { ID => - sinkIdMap.remove(ID) - true - } - } - - override def transStep(): Unit = { - innerAcquire.foreach(_.step()) - innerRelease.foreach(_.step()) - innerProbe.foreach(_.step()) - innerPut.foreach(_.step()) - innerGet.foreach(_.step()) - } - - override def getState(addr: BigInt): AddrState = { - val state = addrStateMap.getOrElse(addr, new AddrState()) - if (!addrStateMap.contains(addr)) { //alloc new state if need - state.myPerm = trunk - addrStateMap += (addr -> state) - if (!scoreboard.contains(addr)) { //alloc scoreboard if needed - scoreboard += (addr -> new ScoreboardData()) - } - } - state - } - - def permAgainstMaster(masterPerm: BigInt): BigInt = { - if (masterPerm == trunk) - nothing - else if (masterPerm == branch) - branch - else - trunk - } - - var tmpA = new TLCScalaA() - var a_cnt = 0 - var a_cnt_end = 0 - - val aList = ListBuffer[TLCScalaA]() - val cList = ListBuffer[TLCScalaC]() - var tmpC = new TLCScalaC() - var c_cnt = 0 - //E will never block - val bQueue = new FireQueue[TLCScalaB]() - val dQueue = new FireQueue[TLCScalaD]() - - def banIssueGrant(addr: BigInt): Boolean = { - val addrState = getState(addr) - addrState.pendingProbeAck - } - - def banIssueProbe(addr: BigInt): Boolean = { - val addrState = getState(addr) - addrState.pendingGrantAck || addrState.pendingProbeAck - } - - //Due to no backup pressure in channel E, the handle function is integrated into fire function - def fireE(inE: TLCScalaE): Unit = { - require(sinkIdMap.contains(inE.sink), "no sinkId for GrantAck") - val acq = sinkIdMap(inE.sink) - acq.pairGrantAck(inE) - val addr = acq.a.get.address - val state = getState(addr) - //update state - state.slaveUpdatePendingGrantAck() - //free sinkId - // sinkIdMap.remove(inE.sink) - sinkFreeQueue.enqueue(inE.sink) - //remove from addrList and agentList - state.calleeTrans -= acq - innerAcquire -= acq - } - - def issueD(): Unit = { - //serach AccessAck(Data) to issue - innerGet.dequeueAll { g => - val addr = g.a.get.address - val alignAddr = addrAlignBlock(addr) - val state = getState(alignAddr) - if (state.myPerm == nothing) { - debugPrintln(f"can't handle Get at $addr%x") - false - } else { - val ver = scoreboardGetVer(alignAddr) - val start_beat = beatInBlock(addr) - val targetData = dataOutOfBeat(state.data, start_beat) - // println(f"issue AccessAckData, addr:$addr%x, data:$targetData, size:${g.a.get.size}, " + - // f"beats:${countBeats(g.a.get.size)}, ver:$ver") - dQueue.enqMessage(g.issueAccessAckData(targetData, ver), countBeats(g.a.get.size)) - true - } - } - innerPut.dequeueAll { p => - val addr = p.a.get.address - val alignAddr = addrAlignBlock(addr) - val state = getState(alignAddr) - if (state.myPerm != trunk) { - debugPrintln(f"can't handle Put at $addr%x") - false - } else { - insertMaskedWrite(p.a.get.address, p.a.get.data, p.a.get.mask) - dQueue.enqMessage(p.issueAccessAck()) - true - } - } - //search ReleaseAck to issue - innerRelease --= innerRelease.filter { r => - if (r.releaseAckIssued.getOrElse(true)) { - false - } else { - dQueue.enqMessage(r.issueReleaseAck()) - //when releaseAck is issued, the meta & data will be changed - val addr = r.c.get.address - val state = getState(addr) - val c = r.c.get - assert( - permCmp(shrinkFrom(c.param), state.masterPerm) <= 0, - f"addr: $addr%x, recorded master perm: ${state.masterPerm}, param:${c.param} , shrink from ${shrinkFrom(c.param)}" - ) - state.masterPerm = shrinkTarget(r.c.get.param) - state.myPerm = permAgainstMaster(state.masterPerm) - if (r.c.get.opcode == ReleaseData) { - state.data = r.c.get.data - if (state.masterPerm == nothing) { - insertReadWrite(addr, r.c.get.data, randomBlockData()) //modify data when master is invalid - } else { - insertRead(addr, r.c.get.data) - } - } else { - if (state.masterPerm == nothing) { - insertReadWrite(addr, state.data, randomBlockData()) //modify data when master is invalid - } - } - //serialization point - appendSerial(r) - //remove from addrList and agentList - state.calleeTrans -= r - true //condition to remove from agent list safely - } - } - if (sinkIdMap.size < maxSink) { //fast check available ID - val sinkQ = mutable.Queue() ++ List.tabulate(maxSink)(a => BigInt(a)).filterNot(k => sinkIdMap.contains(k)) - //search Grant to issue - innerAcquire.foreach { acq => - //TODO:check recursive trans completion before issue - if (!acq.grantIssued.getOrElse(true)) { //need issue - val a_acq = acq.a.get - val addr = a_acq.address - val state = getState(addr) - if (sinkQ.nonEmpty && !banIssueGrant(addr)) { //has empty sinkid and ok to issue - val allocId = sinkQ.dequeue() - if (a_acq.opcode == AcquirePerm) { - dQueue.enqMessage(acq.issueGrant(allocId)) - } else { //is AcquireBlock - if (state.masterPerm == branch && growFrom(a_acq.param) == branch) { //grow from branch - dQueue.enqMessage(acq.issueGrant(allocId)) - } else { - dQueue.enqMessage(acq.issueGrantData(allocId, state.data), cnt = beatNum) - } - } - //update state - state.masterPerm = growTarget(a_acq.param) - state.myPerm = permAgainstMaster(state.masterPerm) - state.slaveUpdatePendingGrantAck() - //mark Id allocated - sinkIdMap(allocId) = acq - } - } - } - } - } - - //Check if there is any message to fire - def peekD(): Option[TLCScalaD] = { - if (dQueue.q.isEmpty) { - None - } else { - val headD = dQueue.q.head._1 - Some(headD.copy(newData = extract256Bit(headD.data, dQueue.beatCnt))) - } - } - - //Notify the agent this channel has been fired - def fireD(): Unit = { - dQueue.fireHead() - } - - var sbDataSnapshot: BigInt = 0 - - def fireC(inC: TLCScalaC): Unit = { - if (inC.opcode == ReleaseData || inC.opcode == ProbeAckData) { - if (c_cnt == 0) { //start burst - sbDataSnapshot = scoreboardRead(inC.address) - tmpC = inC.copy() - c_cnt += 1 - } else { //burst beat - tmpC.data = tmpC.data | inC.data << (beatBits * c_cnt) - c_cnt += 1 - if (c_cnt == beatNum) { - handleC(tmpC) - c_cnt = 0 - } - } - } else { - handleC(inC) - } - } - - def handleC(c: TLCScalaC): Unit = { - c.opcode match { - case ProbeAck => { - val addr = c.address - val state = getState(addr) - //TODO: only one master for now, so no need to check source - val probeT = - innerProbe.filter(p => p.probeAckPending.getOrElse(false)).filter(p => p.b.get.address == addr).head - //pair ProbeAck - probeT.pairProbeAck(c) - //update state - assert( - permCmp(shrinkFrom(c.param), state.masterPerm) <= 0, - f"addr: $addr%x, recorded master perm: ${state.masterPerm}, param:${c.param} , shrink from ${shrinkFrom(c.param)}" - ) - state.masterPerm = shrinkTarget(c.param) - state.myPerm = permAgainstMaster(state.masterPerm) - state.slaveUpdatePendingProbeAck() - if (state.myPerm == trunk) { - insertReadWrite(addr, state.data, randomBlockData()) //modify data when master is invalid - } else if (state.myPerm == branch) { - insertRead(addr, state.data) - } - //serialization point - appendSerial(probeT) - //remove from addrList and agentList - state.callerTrans -= probeT - innerProbe -= probeT - //TODO:update father trans call list after completion - } - case ProbeAckData => { - val addr = c.address - val state = getState(addr) - //TODO: only one master for now, so no need to check source - val probeT = innerProbe - .filter(p => p.probeAckPending.getOrElse(false)) - .filter(p => p.b.get.address == addr) - .head //pair ProbeAck - //pair ProbeAck - probeT.pairProbeAck(c) - //update state - assert( - permCmp(shrinkFrom(c.param), state.masterPerm) <= 0, - f"addr: $addr%x, recorded master perm: ${state.masterPerm}, param:${c.param} , shrink from ${shrinkFrom(c.param)}" - ) - state.masterPerm = shrinkTarget(c.param) - state.myPerm = permAgainstMaster(state.masterPerm) - state.data = c.data - state.slaveUpdatePendingProbeAck() - if (state.myPerm == trunk) { - insertReadSnapWrite(addr, c.data, sbDataSnapshot, randomBlockData()) //modify data when master is invalid - } else if (state.myPerm == branch) { - insertReadSnap(addr, c.data, sbDataSnapshot) - } - //serialization point - appendSerial(probeT) - //remove from addrList and agentList - state.callerTrans -= probeT - innerProbe -= probeT - //TODO:update father trans call list after completion - } - case Release => { - val addr = c.address - val state = getState(addr) - val acq_list = state.calleeTrans.filter(_.isInstanceOf[AcquireCalleeTrans]) - assert( - acq_list.forall(a => a.asInstanceOf[AcquireCalleeTrans].grantIssued.getOrElse(true)), - "Detect master issue Release when pending Grant" - ) - //TODO:only support one master for now - cList.append(c) - } - case ReleaseData => { - val addr = c.address - val state = getState(addr) - val acq_list = state.calleeTrans.filter(_.isInstanceOf[AcquireCalleeTrans]) - assert( - acq_list.forall(a => a.asInstanceOf[AcquireCalleeTrans].grantIssued.getOrElse(true)), - "Detect master issue Release when pending Grant" - ) - //TODO:only support one master for now - cList.append(c) - } - } - } - - def tickC(): Unit = { - cList --= cList.filter { c => - val addr = c.address - val state = getState(addr) - if (state.blockInnerRelease()) { - false - } else { - val rel = new ReleaseCalleeTrans() - rel.pairRelease(c) - //add to addr list and agent list - innerRelease.append(rel) - state.calleeTrans.append(rel) - true //condition to remove from cList - } - } - } - - def issueB(): Unit = { - innerProbe.foreach { p => - if (!p.probeIssued.getOrElse(true)) { - val addr = p.b.get.address - val state = getState(addr) - //TODO:check recursive trans completion before issue - if (!banIssueProbe(addr)) { //ok to issue - bQueue.enqMessage(p.issueProbe()) - //append to addr caller list - state.callerTrans.append(p) - //update state - state.slaveUpdatePendingProbeAck() - } - } - } - } - - def peekB(): Option[TLCScalaB] = { - if (bQueue.q.isEmpty) { - None - } else { - Some(bQueue.q.head._1.copy(newData = extract256Bit(bQueue.q.head._1.data, bQueue.beatCnt))) - } - } - - def fireB(): Unit = { - bQueue.fireHead() - } - - def fireA(inA: TLCScalaA): Unit = { - if (inA.opcode == PutFullData || inA.opcode == PutPartialData) { - if (a_cnt == 0) { //start burst - a_cnt_end = countBeats(inA.size) - tmpA = inA.copy() - a_cnt += 1 - } else { - tmpA.mask = maskConcatBeat(tmpA.mask, inA.mask, a_cnt) - tmpA.data = dataConcatBeat(tmpA.data, inA.data, a_cnt) - a_cnt += 1 - } - if (a_cnt == a_cnt_end) { - a_cnt = 0 - aList.append(tmpA) - } - } else - aList.append(inA) - } - - def tickA(): Unit = { - aList --= aList.filter { a => - if (a.opcode == Get) { - val getT = new GetCalleeTrans() - val beats = countBeats(a.size) - if (beats > 1) { //fill n mask if there are n beats - a.mask = (0 until beats).foldLeft(BigInt(0))((cmask, i) => maskConcatBeat(cmask, a.mask, i)) - } - getT.pairGet(a) - innerGet.enqueue(getT) - true - } else if (a.opcode == PutFullData || a.opcode == PutPartialData) { - val putT = new PutCalleeTrans() - putT.pairPut(a) - innerPut.enqueue(putT) - true - } else { - val addr = a.address - val state = getState(addr) - if (state.blockInnerAcquire()) { //blocking - false - } else { //not blocking - val transA = new AcquireCalleeTrans() - transA.pairAcquire(a) - //serialization point - appendSerial(transA) - //add to addr list and agent list - innerAcquire.append(transA) - state.calleeTrans.append(transA) - true - } - } - } - } - - def addProbe(addr: BigInt, targetPerm: BigInt): Unit = { - val pro = new ProbeCallerTrans() - pro.prepareProbe(addr, targetPerm) - innerProbe.append(pro) - } - - override def step(): Unit = { - freeSink() - super.step() - } -} - -class TLCMasterAgent( - ID: Int, - name: String = "", - val maxSource: Int, - addrStateMap: mutable.Map[BigInt, AddrState], - serialList: ArrayBuffer[(Int, TLCTrans)], - scoreboard: mutable.Map[BigInt, ScoreboardData], - blockBytes: Int, - beatBytes: Int) - extends TLCAgent(ID, name, addrStateMap, serialList, scoreboard, blockBytes, beatBytes) { - val outerAcquire: ListBuffer[AcquireCallerTrans] = ListBuffer() - val outerRelease: ListBuffer[ReleaseCallerTrans] = ListBuffer() - val outerProbe: ListBuffer[ProbeCalleeTrans] = ListBuffer() - - val sourceAMap = mutable.Map[BigInt, AcquireCallerTrans]() - val sourceCMap = mutable.Map[BigInt, ReleaseCallerTrans]() - val sourceAFreeQueue = mutable.Queue[BigInt]() - val sourceCFreeQueue = mutable.Queue[BigInt]() - - def freeSource(): Unit = { - sourceAFreeQueue.dequeueAll { id => - sourceAMap.remove(id) - true - } - sourceCFreeQueue.dequeueAll { id => - sourceCMap.remove(id) - true - } - } - - override def transStep(): Unit = { - outerAcquire.foreach(_.step()) - outerRelease.foreach(_.step()) - outerProbe.foreach(_.step()) - } - - val bList = ListBuffer[TLCScalaB]() - - var tmpD = new TLCScalaD() - var d_cnt = 0 - - val aQueue = new FireQueue[TLCScalaA]() - val cQueue = new FireQueue[TLCScalaC]() - val eQueue = new FireQueue[TLCScalaE]() - - def banIssueAcquire(addr: BigInt): Boolean = { - val addrState = getState(addr) - addrState.pendingGrant || addrState.pendingReleaseAck - } - - def banIssueRelease(addr: BigInt): Boolean = { - val addrState = getState(addr) - addrState.pendingGrant || addrState.pendingReleaseAck - } - - def banIssueProbeAck(addr: BigInt): Boolean = { - val addrState = getState(addr) - addrState.pendingReleaseAck - } - - //issue GrantAck in responding to grant, thus no need to define issueE - def peekE(): Option[TLCScalaE] = { - if (eQueue.q.isEmpty) { - None - } else { - Some(eQueue.q.head._1) - } - } - - def fireE(): Unit = { - eQueue.fireHead() - } - - def fireD(inD: TLCScalaD): Unit = { - if (inD.opcode == GrantData) { - if (d_cnt == 0) { //start burst - tmpD = inD.copy() - d_cnt += 1 - } else { - tmpD.data = tmpD.data | inD.data << (beatBits * d_cnt) - d_cnt += 1 - if (d_cnt == beatNum) { - handleD(tmpD) - d_cnt = 0 - } - } - } else { - handleD(inD) - } - } - - def handleD(d: TLCScalaD): Unit = { - d.opcode match { - case ReleaseAck => { - require(sourceCMap.contains(d.source), "no sourceID for ReleaseAck") - val rel = sourceCMap(d.source) - rel.pairReleaseAck(d) - //handle meta - val addr = rel.c.get.address - val state = getState(addr) - state.myPerm = rel.targetPerm - //update state - state.masterUpdatePendingReleaseAck() - //free sourceID - // sourceCMap.remove(d.source) - sourceCFreeQueue.enqueue(d.source) - //remove from addrList and agentList - state.callerTrans -= rel - outerRelease -= rel - //TODO: notify father transaction here - } - case Grant => { - if(!sourceAMap.contains(d.source)){ - println(s"source id [${d.source}] not found") - println(sourceAMap.keys.mkString(" ")) - } - require(sourceAMap.contains(d.source), "no sourceID for Grant") - val acq = sourceAMap(d.source) - acq.pairGrant(d) - //handle meta - val addr = acq.a.get.address - val state = getState(addr) - if (!d.denied) { - state.myPerm = d.param - if (acq.a.get.opcode == AcquireBlock) { - if (state.myPerm == trunk) { - insertReadWrite(addr, state.data, randomBlockData()) //modify data when trunk - } else if (state.myPerm == branch) { - insertRead(addr, state.data) - } - } else { //acquire permssion, used for full write - if (state.myPerm == trunk) { - insertFullWrite(addr, randomBlockData()) //modify data when trunk - } - } - } - //issue GrantAck - eQueue.enqMessage(acq.issueGrantAck()) - //update state - state.masterUpdatePendingGrant() - //free sourceID - // sourceAMap.remove(d.source) - sourceAFreeQueue.enqueue(d.source) - //serialization point - appendSerial(acq) - //remove from addrList and agentList - state.callerTrans -= acq - outerAcquire -= acq - } - case GrantData => { - require(sourceAMap.contains(d.source), "no sourceID for Grant") - val acq = sourceAMap(d.source) - acq.pairGrant(d) - //handle meta & data - val addr = acq.a.get.address - val state = getState(addr) - if (!d.denied) { - state.myPerm = d.param - state.data = d.data - if (state.myPerm == trunk) { - insertReadWrite(addr, d.data, randomBlockData()) //modify data when trunk - } else { - insertRead(addr, d.data) - } - } - //issue GrantAck - eQueue.enqMessage(acq.issueGrantAck()) - //update state - state.masterUpdatePendingGrant() - //free sourceID - // sourceAMap.remove(d.source) - sourceAFreeQueue.enqueue(d.source) - //serialization point - appendSerial(acq) - //remove from addrList and agentList - state.callerTrans -= acq - outerAcquire -= acq - } - } - } - - //Because D messages won't be blocked, there is no tickD() - - def issueC(): Unit = { - //search ProbeAck to issue - outerProbe --= outerProbe.filter { p => - if (p.probeAckIssued.getOrElse(true)) { - false - } else { - //TODO: check recursive call here - val addr = p.b.get.address - val state = getState(addr) - if (banIssueProbeAck(addr)) { - false - } else { //ok to issue - val myperm = state.myPerm - var targetPerm = p.b.get.param - if (targetPerm < myperm) { //if target is higher than me - targetPerm = myperm - } - //assume all probe is ProbeBlock - if (state.dirty) { //need write back - cQueue.enqMessage(p.issueProbeAckData(myperm, targetPerm, state.data), cnt = beatNum) - if (targetPerm != trunk) { - state.dirty = false - } - } else { - cQueue.enqMessage(p.issueProbeAck(myperm, targetPerm)) - } - //change state permission - state.myPerm = targetPerm - //remove from addr list and agent list - state.calleeTrans -= p - true //condition to remove from agent list - } - } - } - - //search Release here - val abandonList = ListBuffer[ReleaseCallerTrans]() - if (sourceCMap.size < maxSource) { //fast check available ID - val sourceQ = mutable.Queue() ++ List.tabulate(maxSource)(a => BigInt(a)).filterNot(k => sourceCMap.contains(k)) - outerRelease.foreach { r => - if (!r.releaseIssued.getOrElse(true)) { //haven't issue release - val addr = r.c.get.address - val state = getState(addr) - if (state.myPerm != nothing) { //have some thing to report - if (sourceQ.nonEmpty && !banIssueRelease(addr)) { //has empty source ID and ok to issue - val allocId = sourceQ.dequeue() - //TODO: random decide to report or not when target perm is higher than me - if (r.targetPerm < state.myPerm) { //if target is higher - r.targetPerm = state.myPerm - } - if (state.dirty) { - cQueue.enqMessage(r.issueReleaseData(allocId, state.myPerm, state.data), cnt = beatNum) - state.dirty = false - } else { - cQueue.enqMessage(r.issueRelease(allocId, state.myPerm)) - } - //serialization point - appendSerial(r) - //append to addr caller list - state.callerTrans.append(r) - //update state - state.masterUpdatePendingReleaseAck() - //mark ID allocated - sourceCMap(allocId) = r - } - } else { // no need to report/shrink. Delete from release trans list - abandonList += r - //TODO: check father here - } - } - } - outerRelease --= abandonList - } - } - - def peekC(): Option[TLCScalaC] = { - if (cQueue.q.isEmpty) { - None - } else { - val headC = cQueue.q.head._1 - Some(headC.copy(newData = extract256Bit(headC.data, cQueue.beatCnt))) - } - } - - def fireC(): Unit = { - cQueue.fireHead() - } - - def fireB(inB: TLCScalaB): Unit = { - bList.append(inB) - } - - def tickB(): Unit = { - bList --= bList.filter { b => - val addr = b.address - val state = getState(addr) - //assume all of B message is probe - require(b.opcode == Probe, "Only support probe message") - if (state.blockOuterProbe()) { - false - } else { - val pro = ProbeCalleeTrans() - pro.pairProbe(b) - //serialization point - appendSerial(pro) - //TODO: add recursive call when probed - //add to addr list and agent list - outerProbe.append(pro) - state.calleeTrans.append(pro) - true //condition to remove from bList - } - } - } - - def issueA(): Unit = { - val abandonList = ListBuffer[AcquireCallerTrans]() - if (sourceAMap.size < maxSource) { //fast check available ID - val sourceQ = mutable.Queue() ++ List.tabulate(maxSource)(a => BigInt(a)).filterNot(k => sourceAMap.contains(k)) - outerAcquire.foreach { acq => - if (!acq.acquireIssued.getOrElse(true)) { //haven't issue acquire - val addr = acq.a.get.address - val state = getState(addr) - if (acq.checkNeedGrow(state.myPerm)) { //really need grow - if (sourceQ.nonEmpty && !banIssueAcquire(addr)) { //has empty sourceid and ok to issue - //TODO:decide to make full write here, use acqblock for now - val allocId = sourceQ.dequeue() - aQueue.enqMessage(acq.issueAcquireBlock(allocId, state.myPerm)) - //serialization point - appendSerial(acq) - //append to addr caller list - state.callerTrans.append(acq) - //update state - state.masterUpdatePendingGrant() - //mark ID allocated - sourceAMap(allocId) = acq - } - } else { //no need to grow. Delete from acquire trans list - abandonList += acq - //TODO:check father here - } - } - } - outerAcquire --= abandonList - } - } - - def peekA(): Option[TLCScalaA] = { - if (aQueue.q.isEmpty) { - None - } else { - Some(aQueue.q.head._1) - } - } - - def fireA(): Unit = { - aQueue.fireHead() - } - - def addAcquire(addr: BigInt, targetPerm: BigInt): Unit = { - val acq = new AcquireCallerTrans() - acq.prepareAcquire(addr, targetPerm) - outerAcquire.append(acq) - } - - def addRelease(addr: BigInt, targetPerm: BigInt): Unit = { - val rel = new ReleaseCallerTrans() - rel.prepareRelease(addr, targetPerm) - outerRelease.append(rel) - } - - override def step(): Unit = { - freeSource() - super.step() - } - -} - -class TLULMasterAgent( - ID: Int, - name: String = "", - val maxSource: Int, - addrStateMap: mutable.Map[BigInt, AddrState], - serialList: ArrayBuffer[(Int, TLCTrans)], - scoreboard: mutable.Map[BigInt, ScoreboardData], - blockBytes: Int, - beatBytes: Int) - extends TLCAgent(ID, name, addrStateMap, serialList, scoreboard, blockBytes, beatBytes) { - val outerGet: ListBuffer[GetCallerTrans] = ListBuffer() - val outerPut: ListBuffer[PutCallerTrans] = ListBuffer() - - val getMap: mutable.Map[BigInt, GetCallerTrans] = mutable.Map[BigInt, GetCallerTrans]() - val putMap: mutable.Map[BigInt, PutCallerTrans] = mutable.Map[BigInt, PutCallerTrans]() - - val getQueue = new FireQueue[TLCScalaA]() - val putQueue = new FireQueue[TLCScalaA]() - - val sourceAFreeIdQueue = mutable.Queue[BigInt]() // TODO: handle Put in exactly one id queue? - - def freeSource(): Unit = { - sourceAFreeIdQueue.dequeueAll { id => - getMap.remove(id) - true - } - } - - override def transStep(): Unit = { - outerGet.foreach(_.step()) -// outerPut.foreach(_.step()) - } - - var tmpA = new TLCScalaA() - var a_cnt = 0 - var a_cnt_end = 0 - var tmpD = new TLCScalaD() - var d_cnt = 0 - var d_cnt_end = 0 - var snapData: BigInt = 0 - - def fireD(inD: TLCScalaD): Unit = { - if (inD.opcode == AccessAckData) { - if (d_cnt == 0) { // Start burst - val getT = getMap(inD.source) - // if Get from L2, version = 0 - // if Get from L3, version is carefully assigned - snapData = insertVersionRead(getT.a.get.address, inD.param) - tmpD = inD.copy() - d_cnt += 1 - } - else { - tmpD.data = dataConcatBeat(tmpD.data, inD.data, d_cnt) - d_cnt += 1 - if (d_cnt == beatNum) { - d_cnt = 0 - val getT = getMap(inD.source) - getT.pairAccessAckData(tmpD) - // insertMaskedReadSnap(getT.a.get.address, tmpD.data, snapData, getT.a.get.mask) - if (!tmpD.denied) { - // insertRead(getT.a.get.address, tmpD.data) - // TODO: verify correctness of data - } - sourceAFreeIdQueue.enqueue(inD.source) - outerGet -= getT - } - } - // TODO: do FireD - debugPrintln(f"AccessAckData, Source: ${inD.source}%x, Data: ${inD.data}%x") - } else { - assert(false, "Put test is not implemented yet") - } - } - - def fireAGet(): Unit = { - getQueue.fireHead() - } - - def issueA(): Unit = { - if (getMap.size < maxSource) { - val sourceQ = mutable.Queue() ++ List.tabulate(maxSource)(a => BigInt(a)).filterNot(k => getMap.contains(k)) - outerGet.foreach { acq => - if (!acq.getIssued.getOrElse(true)) { // Haven't issue get - val addr = acq.a.get.address - if (sourceQ.nonEmpty) { - val allocId = sourceQ.dequeue() - getQueue.enqMessage(acq.issueGet(allocId)) - appendSerial(acq) - getMap(allocId) = acq - } - } - } - } - } - - def peekA(): Option[TLCScalaA] = { - if (getQueue.q.isEmpty) { - None - } else { - Some(getQueue.q.head._1) - } - } - - def addGet(addr: BigInt): Unit = { - val acq = new GetCallerTrans() - acq.prepareGet(addr) - outerGet.append(acq) - } - - override def step(): Unit = { - freeSource() - super.step() - } -} \ No newline at end of file diff --git a/src/test/scala/tltest/TLCScalaMessage.scala b/src/test/scala/tltest/TLCScalaMessage.scala deleted file mode 100644 index 45c72408..00000000 --- a/src/test/scala/tltest/TLCScalaMessage.scala +++ /dev/null @@ -1,718 +0,0 @@ -package tltest - -import freechips.rocketchip.tilelink.TLMessages -import BigIntUtils._ -import TLMessagesBigInt._ - -import scala.collection.mutable.ListBuffer - -object TLMessagesBigInt { - val PutFullData = TLMessages.PutFullData.litValue - val PutPartialData = TLMessages.PutPartialData.litValue - val ArithmeticData = TLMessages.ArithmeticData.litValue - val LogicalData = TLMessages.LogicalData.litValue - val Get = TLMessages.Get.litValue - val Hint = TLMessages.Hint.litValue - val AcquireBlock = TLMessages.AcquireBlock.litValue - val AcquirePerm = TLMessages.AcquirePerm.litValue - val Probe = TLMessages.Probe.litValue - val AccessAck = TLMessages.AccessAck.litValue - val AccessAckData = TLMessages.AccessAckData.litValue - val HintAck = TLMessages.HintAck.litValue - val ProbeAck = TLMessages.ProbeAck.litValue - val ProbeAckData = TLMessages.ProbeAckData.litValue - val Release = TLMessages.Release.litValue - val ReleaseData = TLMessages.ReleaseData.litValue - val Grant = TLMessages.Grant.litValue - val GrantData = TLMessages.GrantData.litValue - val ReleaseAck = TLMessages.ReleaseAck.litValue - val GrantAck = TLMessages.GrantAck.litValue - - val toT = BigInt(0) - val toB = BigInt(1) - val toN = BigInt(2) - - val NtoB = BigInt(0) - val NtoT = BigInt(1) - val BtoT = BigInt(2) - - val TtoB = BigInt(0) - val TtoN = BigInt(1) - val BtoN = BigInt(2) - - val TtoT = BigInt(3) - val BtoB = BigInt(4) - val NtoN = BigInt(5) - - val trunk = toT - val branch = toB - val nothing = toN -} - -class TLCScalaMessage { - var trans: Option[TLCTrans] = None -} - -class TLCScalaA -( - var opcode: BigInt = 0, - var param: BigInt = 0, - var size: BigInt = 0, - var source: BigInt = 0, - var address: BigInt = 0, - var mask: BigInt = 0, - var data: BigInt = 0, -) extends TLCScalaMessage { - def copy( - newOpcode: BigInt = opcode, - newParam: BigInt = param, - newSize: BigInt = size, - newSource: BigInt = source, - newAddress: BigInt = address, - newMask: BigInt = mask, - newData: BigInt = data, - ): TLCScalaA = new TLCScalaA( - opcode = newOpcode, - param = newParam, - size = newSize, - source = newSource, - address = newAddress, - mask = newMask, - data = newData, - ) -} - -class TLCScalaC -( - var opcode: BigInt = 0, - var param: BigInt = 0, - var size: BigInt = 0, - var source: BigInt = 0, - var address: BigInt = 0, - var data: BigInt = 0, -) extends TLCScalaMessage { - def copy( - newOpcode: BigInt = opcode, - newParam: BigInt = param, - newSize: BigInt = size, - newSource: BigInt = source, - newAddress: BigInt = address, - newData: BigInt = data, - ): TLCScalaC = new TLCScalaC( - opcode = newOpcode, - param = newParam, - size = newSize, - source = newSource, - address = newAddress, - data = newData, - ) -} - -class TLCScalaE -( - var sink: BigInt = 0, -) extends TLCScalaMessage { - def copy( - newSink: BigInt = sink - ): TLCScalaE = new TLCScalaE( - sink = newSink - ) -} - -class TLCScalaB -( - var opcode: BigInt = 0, - var param: BigInt = 0, - var size: BigInt = 0, - var source: BigInt = 0, - var address: BigInt = 0, - var mask: BigInt = 0, - var data: BigInt = 0, -) extends TLCScalaMessage { - def copy( - newOpcode: BigInt = opcode, - newParam: BigInt = param, - newSize: BigInt = size, - newSource: BigInt = source, - newAddress: BigInt = address, - newMask: BigInt = mask, - newData: BigInt = data, - ): TLCScalaB = new TLCScalaB( - opcode = newOpcode, - param = newParam, - size = newSize, - source = newSource, - address = newAddress, - mask = newMask, - data = newData, - ) -} - -class TLCScalaD -( - var opcode: BigInt = 0, - var param: BigInt = 0, - var size: BigInt = 0, - var source: BigInt = 0, - var sink: BigInt = 0, - var denied: Boolean = false, - var data: BigInt = 0, -) extends TLCScalaMessage { - def copy( - newOpcode: BigInt = opcode, - newParam: BigInt = param, - newSize: BigInt = size, - newSource: BigInt = source, - newSink: BigInt = sink, - newDenied: Boolean = denied, - newData: BigInt = data, - ): TLCScalaD = new TLCScalaD( - opcode = newOpcode, - param = newParam, - size = newSize, - source = newSource, - sink = newSink, - denied = newDenied, - data = newData, - ) -} - - -trait PermissionTransition { - def growTarget(param: BigInt): BigInt = { - param match { - case NtoB => toB - case NtoT => toT - case BtoT => toT - } - } - - def growFrom(param: BigInt): BigInt = { - param match { - case NtoB => nothing - case NtoT => nothing - case BtoT => branch - } - } - - def needGrow(from: BigInt, to: BigInt): Boolean = { - from > to - } - - def growParam(from: BigInt, to: BigInt): BigInt = { - assert(from > to, "no need to grow") - if (from == nothing) { - if (to == branch) - NtoB - else - NtoT - } - else - BtoT - } - - def shrinkTarget(param: BigInt): BigInt = { - param match { - case TtoB => toB - case TtoN => toN - case BtoN => toN - case TtoT => toT - case BtoB => toB - case NtoN => toN - } - } - - def shrinkFrom(param: BigInt): BigInt = { - param match { - case TtoB => trunk - case TtoN => trunk - case BtoN => branch - case TtoT => trunk - case BtoB => branch - case NtoN => nothing - } - } - - def shrinkParam(from: BigInt, to: BigInt): BigInt = { - assert(from <= to, "shrink to higher permission") - if (from == trunk) { - if (to == trunk) - TtoT - else if (to == branch) - TtoB - else - TtoN - } else if (from == branch) { - if (to == branch) - BtoB - else - BtoN - } - else - NtoN - } - - //0 if same perm, -1 if b is higher, 1 if a is higer - def permCmp(aPerm: BigInt, bPerm: BigInt): Int = { - if (aPerm == bPerm) - 0 - else if (aPerm > bPerm) - -1 - else - 1 - } -} - -//Transaction meta data will hide in start message -abstract class TLCTrans extends PermissionTransition { - val blockSizeL2 = BigInt(6) - val beatFullMask = BigInt(prefix ++ Array.fill(4)(0xff.toByte)) - - private var timer = 0 - private var timerRunning = false - - override def toString: String = { - "not implemented toString for TLCTrans" - } - - def step(): Unit = { - if (timerRunning) { - timer += 1 - assert(timer <= 1000, s"transaction time out: [${this.toString}]") - } - } - - def startTimer(): Unit = { - timer = 0 - timerRunning = true - } - - def resetTimer(): Unit = { - timer = 0 - timerRunning = false - } -} - -trait TLCCallerTrans extends TLCTrans { - var transDepend: Option[TLCTrans] = None -} - -trait TLCCalleeTrans extends TLCTrans { - var recursiveTrans: Option[ListBuffer[TLCTrans]] = None -} - -//Acquire -class AcquireTrans extends TLCTrans { - var a: Option[TLCScalaA] = None - var d: Option[TLCScalaD] = None - var e: Option[TLCScalaE] = None - -} - -class AcquireCallerTrans() extends AcquireTrans with TLCCallerTrans { - var acquireIssued: Option[Boolean] = None - var grantPending: Option[Boolean] = None - var grantAckIssued: Option[Boolean] = None - - var targetPerm: BigInt = nothing - - override def toString: String = { - if(a.nonEmpty){ - val addr = a.get.address - val op = a.get.opcode - val param = a.get.param - val source = a.get.source - s"address: ${addr.toString(16)} op: $op param: $param source:$source " + - s"acquire issued: ${acquireIssued.getOrElse(false)} " + - s"grant pending: ${grantPending.getOrElse(false)} " + - s"grant ack issued: ${grantAckIssued.getOrElse(false)}" - } else "" - } - - //record metaData in Acquire Message - def prepareAcquire(reqAddr: BigInt, reqTargetPerm: BigInt): Unit = { - val genA = new TLCScalaA( - size = blockSizeL2, - address = reqAddr, - mask = beatFullMask, - ) - a = Some(genA) - acquireIssued = Some(false) - targetPerm = reqTargetPerm - } - - def checkNeedGrow(nowPerm: BigInt): Boolean = { - needGrow(nowPerm, targetPerm) - } - - def issueAcquirePerm(sourceMapId: BigInt, nowPerm: BigInt): TLCScalaA = { - a.get.opcode = AcquirePerm - a.get.source = sourceMapId - a.get.param = growParam(nowPerm, targetPerm) - acquireIssued = Some(true) - grantPending = Some(true) - a.get.trans = Some(this) - a.get - } - - def issueAcquireBlock(sourceMapId: BigInt, nowPerm: BigInt): TLCScalaA = { - a.get.opcode = AcquireBlock - a.get.source = sourceMapId - a.get.param = growParam(nowPerm, targetPerm) - acquireIssued = Some(true) - grantPending = Some(true) - a.get.trans = Some(this) - a.get - } - - def pairGrant(inD: TLCScalaD): Unit = { - d = Some(inD) - grantPending = Some(false) - grantAckIssued = Some(false) - resetTimer() - } - - def issueGrantAck(): TLCScalaE = { - assert(d.isDefined, "miss grant in AcquireTransaction") - val genE = new TLCScalaE(sink = d.get.sink) - e = Some(genE) - grantAckIssued = Some(true) - e.get - } - -} - -class AcquireCalleeTrans() extends AcquireTrans with TLCCalleeTrans { - var grantIssued: Option[Boolean] = None - var grantAckPending: Option[Boolean] = None - - def pairAcquire(aIn: TLCScalaA): Unit = { - a = Some(aIn) - grantIssued = Some(false) - } - - def issueGrant(sinkMapId: BigInt): TLCScalaD = { - assert(a.isDefined, "miss acquire in AcquireTransaction") - val genD = new TLCScalaD( - opcode = Grant, - param = growTarget(a.get.param), - size = a.get.size, - source = a.get.source, - sink = sinkMapId, - denied = false, - ) - d = Some(genD) - grantIssued = Some(true) - grantAckPending = Some(true) - d.get.trans = Some(this) - d.get - } - - def issueGrantData(sinkMapId: BigInt, inData: BigInt): TLCScalaD = { - assert(a.isDefined, "miss acquire in AcquireTransaction") - val genD = new TLCScalaD( - opcode = GrantData, - param = growTarget(a.get.param), - size = a.get.size, - source = a.get.source, - sink = sinkMapId, - denied = false, - data = inData, - ) - d = Some(genD) - grantIssued = Some(true) - grantAckPending = Some(true) - d.get.trans = Some(this) - d.get - } - - def pairGrantAck(inE: TLCScalaE): Unit = { - e = Some(inE) - grantAckPending = Some(false) - resetTimer() - } - -} - -//probe -class ProbeTrans extends TLCTrans with PermissionTransition { - var b: Option[TLCScalaB] = None - var c: Option[TLCScalaC] = None -} - -class ProbeCallerTrans() extends ProbeTrans with TLCCallerTrans { - var probeIssued: Option[Boolean] = None - var probeAckPending: Option[Boolean] = None - - //record metaData in Probe Message - def prepareProbe(reqAddr: BigInt, reqTargetPerm: BigInt, targetSource: BigInt = 0): Unit = { - val genB = new TLCScalaB( - opcode = Probe, - param = reqTargetPerm, - size = blockSizeL2, - source = targetSource, - address = reqAddr, - mask = beatFullMask, - ) - b = Some(genB) - probeIssued = Some(false) - } - - def issueProbe(): TLCScalaB = { - probeIssued = Some(true) - probeAckPending = Some(true) - b.get.trans = Some(this) - b.get - } - - def pairProbeAck(inC: TLCScalaC): Unit = { - c = Some(inC) - probeAckPending = Some(false) - resetTimer() - } - -} - -case class ProbeCalleeTrans() extends ProbeTrans with TLCCalleeTrans { - var probeAckIssued: Option[Boolean] = None - - def pairProbe(bIn: TLCScalaB): Unit = { - b = Some(bIn) - probeAckIssued = Some(false) - } - - def issueProbeAck(from: BigInt, to: BigInt): TLCScalaC = { - assert(b.isDefined, "miss probe in ProbeTransaction") - val genC = new TLCScalaC( - opcode = ProbeAck, - param = shrinkParam(from, to), - size = b.get.size, - source = b.get.source, - address = b.get.address - ) - c = Some(genC) - probeAckIssued = Some(true) - c.get - } - - def issueProbeAckData(from: BigInt, to: BigInt, inData: BigInt): TLCScalaC = { - assert(b.isDefined, "miss probe in ProbeTransaction") - val genC = new TLCScalaC( - opcode = ProbeAckData, - param = shrinkParam(from, to), - size = b.get.size, - source = b.get.source, - address = b.get.address, - data = inData, - ) - c = Some(genC) - probeAckIssued = Some(true) - c.get - } -} - - -class ReleaseTrans extends TLCTrans with PermissionTransition { - var c: Option[TLCScalaC] = None - var d: Option[TLCScalaD] = None -} - -class ReleaseCallerTrans() extends ReleaseTrans with TLCCallerTrans { - var releaseIssued: Option[Boolean] = None - var releaseAckPending: Option[Boolean] = None - - var targetPerm: BigInt = nothing - - //record metaData in Release Message - def prepareRelease(reqAddr: BigInt, reqTargetPerm: BigInt): Unit = { - val genC = new TLCScalaC( - size = blockSizeL2, - address = reqAddr, - ) - c = Some(genC) - releaseIssued = Some(false) - targetPerm = reqTargetPerm - } - - def issueRelease(sourceMapId: BigInt, nowPerm: BigInt): TLCScalaC = { - c.get.opcode = Release - c.get.param = shrinkParam(nowPerm, targetPerm) - c.get.source = sourceMapId - releaseIssued = Some(true) - releaseAckPending = Some(true) - c.get.trans = Some(this) - c.get - } - - def issueReleaseData(sourceMapId: BigInt, nowPerm: BigInt, inData: BigInt): TLCScalaC = { - c.get.opcode = ReleaseData - c.get.param = shrinkParam(nowPerm, targetPerm) - c.get.source = sourceMapId - c.get.data = inData - releaseIssued = Some(true) - releaseAckPending = Some(true) - c.get.trans = Some(this) - c.get - } - - def pairReleaseAck(inD: TLCScalaD): Unit = { - d = Some(inD) - releaseAckPending = Some(false) - resetTimer() - } - - override def toString: String = { - if(c.nonEmpty){ - val addr = c.get.address - val op = c.get.opcode - val param = c.get.param - val source = c.get.source - s"address: ${addr.toString(16)} op: $op param: $param source:$source " - } else "" - } - -} - -class ReleaseCalleeTrans() extends ReleaseTrans with TLCCalleeTrans { - var releaseAckIssued: Option[Boolean] = None - - def pairRelease(inC: TLCScalaC): Unit = { - c = Some(inC) - releaseAckIssued = Some(false) - } - - def issueReleaseAck(): TLCScalaD = { - assert(c.isDefined, "miss release in ReleaseTransaction") - d = Some(new TLCScalaD( - opcode = ReleaseAck, - param = 0, - size = c.get.size, - source = c.get.source, - denied = false, - )) - releaseAckIssued = Some(true) - d.get - } -} - -class GetTrans() extends TLCTrans { - var a: Option[TLCScalaA] = None - var d: Option[TLCScalaD] = None -} - -class GetCallerTrans() extends GetTrans with TLCCallerTrans { - var getIssued: Option[Boolean] = None - var accessAckDataPending: Option[Boolean] = None - - override def toString: String = { - if (a.nonEmpty) { - val addr = a.get.address - val op = a.get.opcode - val param = a.get.param - val source = a.get.source - s"address: ${addr.toString(16)} op: $op param: $param source:$source " + - s"get issued: ${getIssued.getOrElse(false)} " + - s"accessAck pending: ${accessAckDataPending.getOrElse(false)} " - } else "" - } - - def prepareGet(reqAddr: BigInt): Unit = { - val genA = new TLCScalaA( - size = blockSizeL2, - address = reqAddr, - mask = beatFullMask, - ) - a = Some(genA) - getIssued = Some(false) - } - - def issueGet(sourceMapId: BigInt): TLCScalaA = { - a.get.opcode = Get - a.get.source = sourceMapId - a.get.param = 0 - getIssued = Some(true) - accessAckDataPending = Some(true) - a.get.trans = Some(this) - a.get - } - - def pairGet(inA: TLCScalaA): Unit = { - a = Some(inA) - accessAckDataPending = Some(true) - startTimer() - } - - def pairAccessAckData(inD: TLCScalaD): Unit = { - d = Some(inD) - accessAckDataPending = Some(false) - resetTimer() - } -} - -class GetCalleeTrans() extends GetTrans with TLCCalleeTrans { - var accessAckDataIssued: Option[Boolean] = None - - def pairGet(inA: TLCScalaA): Unit = { - a = Some(inA) - accessAckDataIssued = Some(false) - } - - //outD is concated - def issueAccessAckData(inData: BigInt, param: BigInt): TLCScalaD = { - d = Some(new TLCScalaD( - opcode = AccessAckData, - param = param, - size = a.get.size, - source = a.get.source, - sink = 0, - data = inData - )) - accessAckDataIssued = Some(true) - d.get - } -} - -class PutTrans() extends TLCTrans { - var a: Option[TLCScalaA] = None - var d: Option[TLCScalaD] = None -} - -class PutCallerTrans() extends GetTrans with TLCCallerTrans { - var accessAckPending: Option[Boolean] = None - - //inA will be concat in fireQueue - def pairPut(inA: TLCScalaA): Unit = { - a = Some(inA) - accessAckPending = Some(true) - startTimer() - } - - def pairAccessAck(inD: TLCScalaD): Unit = { - d = Some(inD) - accessAckPending = Some(false) - resetTimer() - } -} - -class PutCalleeTrans() extends GetTrans with TLCCalleeTrans { - var accessAckIssued: Option[Boolean] = None - - //inA will be concat in fireQueue - def pairPut(inA: TLCScalaA): Unit = { - a = Some(inA) - accessAckIssued = Some(false) - } - - def issueAccessAck(): TLCScalaD = { - d = Some(new TLCScalaD( - opcode = AccessAck, - param = 1, - size = a.get.size, - source = a.get.source, - sink = 0, - data = 0, - )) - accessAckIssued = Some(true) - d.get - } -} \ No newline at end of file