diff --git a/.travis.yml b/.travis.yml index 5f0707f8..9f29b739 100644 --- a/.travis.yml +++ b/.travis.yml @@ -84,7 +84,3 @@ jobs: script: - travis_wait 80 make emulator-ndebug -C regression SUITE=RocketSuiteA JVM_MEMORY=3G - travis_wait 80 make emulator-regression-tests -C regression SUITE=RocketSuiteA JVM_MEMORY=3G - - <<: *test - script: - - travis_wait 80 make emulator-ndebug -C regression SUITE=GroundtestSuite JVM_MEMORY=3G - - travis_wait 80 make emulator-regression-tests -C regression SUITE=GroundtestSuite JVM_MEMORY=3G diff --git a/Makefrag b/Makefrag index 47400577..5b013e35 100644 --- a/Makefrag +++ b/Makefrag @@ -4,7 +4,7 @@ $(error Please set environment variable RISCV. Please take a look at README) endif MODEL ?= TestHarness -PROJECT ?= rocketchip +PROJECT ?= freechips.rocketchip.chip CFG_PROJECT ?= $(PROJECT) CONFIG ?= DefaultConfig # TODO: For now must match rocketchip.Generator diff --git a/README.md b/README.md index 8781436d..0492202b 100644 --- a/README.md +++ b/README.md @@ -154,13 +154,20 @@ Some of these packages provide Scala utilities for generator configuration, while other contain the actual Chisel RTL generators themselves. Here is a brief description of what can be found in each package: +* **amba** +This RTL package uses diplomacy to generate bus implementations of AMBA protocols, including AXI4, AHB-lite, and APB. +* **chip** +This top-level utility package invokes Chisel to elaborate a particular configuration of a coreplex, +along with the appropriate testing collateral. * **config** This utility package provides Scala interfaces for configuring a generator via a dynamically-scoped parameterization library. * **coreplex** -This RTL package generates a complete coreplex by gluing together a variety of other components, -including tiled Rocket cores, an L1-to-L2 network, L2 coherence agents, and internal devices -such as the debug unit and interrupt handlers. +This RTL package generates a complete coreplex by gluing together a variety of components from other packages, +including: tiled Rocket cores, a system bus network, coherence agents, debug devices, interrupt handlers, externally-facing peripherals, +clock-crossers and converters from TileLink to external bus protocols (e.g. AXI or AHB). +* **devices** +This RTL package contains implementations for peripheral devices, including the Debug module and various TL slaves. * **diplomacy** This utility package extends Chisel by allowing for two-phase hardware elaboration, in which certain parameters are dynamically negotiated between modules. @@ -176,16 +183,13 @@ This RTL package generates the Rocket in-order pipelined core, as well as the L1 instruction and data caches. This library is intended to be used by a chip generator that instantiates the core within a memory system and connects it to the outside world. -* **uncore** -This RTL package generates a variety of uncore logic and devices, such as -such as the L2 coherence hub and Debug modules, as well as defining their interfaces and protocols. -Contains implementations of both TileLink and AXI4. +* **tile** +This RTL package contains components that can be combined with cores to construct tiles, such as FPUs and accelerators. +* **tilelink** +This RTL package uses diplomacy to generate bus implementations of the TileLink protocol. It also contains a variety +of adapters and protocol converters. * **unittest** This utility package contains a framework for generateing synthesizeable hardware testers of individual modules. -* **rocketchip** -This top-level RTL package instantiates a coreplex and drops in any additional -externally-facing peripheral devices. It also includes clock-crossers and converters -from TileLink to external bus protocols (e.g. AXI or AHB). * **util** This utility package provides a variety of common Scala and Chisel constructs that are re-used across multiple other packages, diff --git a/regression/Makefile b/regression/Makefile index 6abb2794..82be8dd0 100644 --- a/regression/Makefile +++ b/regression/Makefile @@ -42,31 +42,23 @@ $(error Set SUITE to the regression suite you want to run) endif ifeq ($(SUITE),RocketSuiteA) -PROJECT=rocketchip +PROJECT=freechips.rocketchip.chip CONFIGS=DefaultConfig endif ifeq ($(SUITE),RocketSuiteB) -PROJECT=rocketchip +PROJECT=freechips.rocketchip.chip CONFIGS=DefaultBufferlessConfig endif ifeq ($(SUITE),RocketSuiteC) -PROJECT=rocketchip -CONFIGS=DefaultL2Config TinyConfig -endif - -ifeq ($(SUITE),GroundtestSuite) -PROJECT=groundtest -CONFIGS=MemtestConfig MemtestBufferlessConfig MemtestStatelessConfig \ - BroadcastRegressionTestConfig BufferlessRegressionTestConfig CacheRegressionTestConfig \ - ComparatorConfig ComparatorBufferlessConfig ComparatorStatelessConfig -# FancyMemtestConfig takes too long to compile +PROJECT=freechips.rocketchip.chip +CONFIGS=TinyConfig endif ifeq ($(SUITE),UnittestSuite) -PROJECT=unittest -CONFIGS=UncoreUnitTestConfig TLSimpleUnitTestConfig TLWidthUnitTestConfig +PROJECT=freechips.rocketchip.unittest +CONFIGS=AMBAUnitTestConfig TLSimpleUnitTestConfig TLWidthUnitTestConfig endif ifeq ($(SUITE), JtagDtmSuite) diff --git a/src/main/scala/uncore/ahb/Bundles.scala b/src/main/scala/amba/ahb/Bundles.scala similarity index 91% rename from src/main/scala/uncore/ahb/Bundles.scala rename to src/main/scala/amba/ahb/Bundles.scala index caf6d307..6ad7cce8 100644 --- a/src/main/scala/uncore/ahb/Bundles.scala +++ b/src/main/scala/amba/ahb/Bundles.scala @@ -1,9 +1,9 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ -import util.GenericParameterizedBundle +import freechips.rocketchip.util.GenericParameterizedBundle abstract class AHBBundleBase(params: AHBBundleParameters) extends GenericParameterizedBundle(params) diff --git a/src/main/scala/uncore/ahb/Nodes.scala b/src/main/scala/amba/ahb/Nodes.scala similarity index 97% rename from src/main/scala/uncore/ahb/Nodes.scala rename to src/main/scala/amba/ahb/Nodes.scala index d50d62f9..86671b45 100644 --- a/src/main/scala/uncore/ahb/Nodes.scala +++ b/src/main/scala/amba/ahb/Nodes.scala @@ -1,11 +1,10 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.diplomacy._ object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBEdgeParameters, AHBBundle] { diff --git a/src/main/scala/uncore/ahb/Parameters.scala b/src/main/scala/amba/ahb/Parameters.scala similarity index 97% rename from src/main/scala/uncore/ahb/Parameters.scala rename to src/main/scala/amba/ahb/Parameters.scala index e89b345d..30df7a40 100644 --- a/src/main/scala/uncore/ahb/Parameters.scala +++ b/src/main/scala/amba/ahb/Parameters.scala @@ -1,10 +1,9 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.diplomacy._ import scala.math.max case class AHBSlaveParameters( diff --git a/src/main/scala/uncore/ahb/Protocol.scala b/src/main/scala/amba/ahb/Protocol.scala similarity index 97% rename from src/main/scala/uncore/ahb/Protocol.scala rename to src/main/scala/amba/ahb/Protocol.scala index 502a363b..08c2adba 100644 --- a/src/main/scala/uncore/ahb/Protocol.scala +++ b/src/main/scala/amba/ahb/Protocol.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ diff --git a/src/main/scala/uncore/ahb/RegisterRouter.scala b/src/main/scala/amba/ahb/RegisterRouter.scala similarity index 88% rename from src/main/scala/uncore/ahb/RegisterRouter.scala rename to src/main/scala/amba/ahb/RegisterRouter.scala index 2621e41f..0b9b19ea 100644 --- a/src/main/scala/uncore/ahb/RegisterRouter.scala +++ b/src/main/scala/amba/ahb/RegisterRouter.scala @@ -1,11 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ -import config._ -import diplomacy._ -import regmapper._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple} +import freechips.rocketchip.util.{HeterogeneousBag, MaskGen} import scala.math.{min,max} class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) @@ -57,7 +59,7 @@ class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int d_taken := Bool(false) d_read := !ahb.hwrite d_index := ahb.haddr >> log2Ceil(beatBytes) - d_mask := uncore.tilelink2.maskGen(ahb.haddr, ahb.hsize, beatBytes) + d_mask := MaskGen(ahb.haddr, ahb.hsize, beatBytes) } out.ready := Bool(true) @@ -77,10 +79,10 @@ object AHBRegisterNode abstract class AHBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule { val node = AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) + val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) } -case class AHBRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[AHBBundle])(implicit val p: Parameters) +case class AHBRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[AHBBundle])(implicit val p: Parameters) class AHBRegBundleBase(arg: AHBRegBundleArg) extends Bundle { diff --git a/src/main/scala/uncore/ahb/SRAM.scala b/src/main/scala/amba/ahb/SRAM.scala similarity index 94% rename from src/main/scala/uncore/ahb/SRAM.scala rename to src/main/scala/amba/ahb/SRAM.scala index aa830511..74e546dc 100644 --- a/src/main/scala/uncore/ahb/SRAM.scala +++ b/src/main/scala/amba/ahb/SRAM.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, fuzzHreadyout: Boolean = false)(implicit p: Parameters) extends LazyModule { @@ -35,7 +35,7 @@ class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4 // The mask and address during the address phase val a_access = in.htrans === AHBParameters.TRANS_NONSEQ || in.htrans === AHBParameters.TRANS_SEQ val a_request = in.hready && in.hsel && a_access - val a_mask = uncore.tilelink2.maskGen(in.haddr, in.hsize, beatBytes) + val a_mask = MaskGen(in.haddr, in.hsize, beatBytes) val a_address = Cat((mask zip (in.haddr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse) val a_write = in.hwrite diff --git a/src/main/scala/uncore/ahb/Test.scala b/src/main/scala/amba/ahb/Test.scala similarity index 91% rename from src/main/scala/uncore/ahb/Test.scala rename to src/main/scala/amba/ahb/Test.scala index c294fca9..507c306e 100644 --- a/src/main/scala/uncore/ahb/Test.scala +++ b/src/main/scala/amba/ahb/Test.scala @@ -1,12 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ -import config._ -import diplomacy._ -import uncore.tilelink2._ -import unittest._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.devices.tilelink.TLTestRAM +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.unittest._ class RRTest0(address: BigInt)(implicit p: Parameters) extends AHBRegisterRouter(address, 0, 32, 0, 4)( new AHBRegBundle((), _) with RRTest0Bundle)( diff --git a/src/main/scala/uncore/ahb/ToTL.scala b/src/main/scala/amba/ahb/ToTL.scala similarity index 95% rename from src/main/scala/uncore/ahb/ToTL.scala rename to src/main/scala/amba/ahb/ToTL.scala index 6252cd00..d2aa84e7 100644 --- a/src/main/scala/uncore/ahb/ToTL.scala +++ b/src/main/scala/amba/ahb/ToTL.scala @@ -1,12 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import uncore.tilelink2._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util.MaskGen case class AHBToTLNode() extends MixedAdapterNode(AHBImp, TLImp)( dFn = { case AHBMasterPortParameters(masters) => @@ -108,7 +109,7 @@ class AHBToTL()(implicit p: Parameters) extends LazyModule out.a.bits.source := UInt(0) out.a.bits.address := d_addr out.a.bits.data := in.hwdata - out.a.bits.mask := maskGen(d_addr, d_size, beatBytes) + out.a.bits.mask := MaskGen(d_addr, d_size, beatBytes) out.d.ready := d_recv // backpressure AccessAckData arriving faster than AHB beats in.hrdata := out.d.bits.data diff --git a/src/main/scala/uncore/ahb/Xbar.scala b/src/main/scala/amba/ahb/Xbar.scala similarity index 89% rename from src/main/scala/uncore/ahb/Xbar.scala rename to src/main/scala/amba/ahb/Xbar.scala index 8e1378eb..a19837c5 100644 --- a/src/main/scala/uncore/ahb/Xbar.scala +++ b/src/main/scala/amba/ahb/Xbar.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.ahb +package freechips.rocketchip.amba.ahb import Chisel._ -import config._ -import diplomacy._ -import regmapper._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ import scala.math.{min,max} class AHBFanout()(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/ahb/package.scala b/src/main/scala/amba/ahb/package.scala similarity index 67% rename from src/main/scala/uncore/ahb/package.scala rename to src/main/scala/amba/ahb/package.scala index ed173388..c6ce626a 100644 --- a/src/main/scala/uncore/ahb/package.scala +++ b/src/main/scala/amba/ahb/package.scala @@ -1,9 +1,9 @@ // See LICENSE.SiFive for license details. -package uncore +package freechips.rocketchip.amba import Chisel._ -import diplomacy._ +import freechips.rocketchip.diplomacy.OutwardNodeHandle package object ahb { diff --git a/src/main/scala/uncore/apb/Bundles.scala b/src/main/scala/amba/apb/Bundles.scala similarity index 90% rename from src/main/scala/uncore/apb/Bundles.scala rename to src/main/scala/amba/apb/Bundles.scala index da40ce67..a86179dc 100644 --- a/src/main/scala/uncore/apb/Bundles.scala +++ b/src/main/scala/amba/apb/Bundles.scala @@ -1,9 +1,9 @@ // See LICENSE.SiFive for license details. -package uncore.apb +package freechips.rocketchip.amba.apb import Chisel._ -import util.GenericParameterizedBundle +import freechips.rocketchip.util.GenericParameterizedBundle abstract class APBBundleBase(params: APBBundleParameters) extends GenericParameterizedBundle(params) diff --git a/src/main/scala/uncore/apb/Nodes.scala b/src/main/scala/amba/apb/Nodes.scala similarity index 95% rename from src/main/scala/uncore/apb/Nodes.scala rename to src/main/scala/amba/apb/Nodes.scala index c7d5fa7d..a3618129 100644 --- a/src/main/scala/uncore/apb/Nodes.scala +++ b/src/main/scala/amba/apb/Nodes.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.apb +package freechips.rocketchip.amba.apb import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBEdgeParameters, APBBundle] { diff --git a/src/main/scala/uncore/apb/Parameters.scala b/src/main/scala/amba/apb/Parameters.scala similarity index 94% rename from src/main/scala/uncore/apb/Parameters.scala rename to src/main/scala/amba/apb/Parameters.scala index 96fdc5d9..e0d74cbf 100644 --- a/src/main/scala/uncore/apb/Parameters.scala +++ b/src/main/scala/amba/apb/Parameters.scala @@ -1,10 +1,10 @@ // See LICENSE.SiFive for license details. -package uncore.apb +package freechips.rocketchip.amba.apb import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.math.max case class APBSlaveParameters( diff --git a/src/main/scala/uncore/apb/Protocol.scala b/src/main/scala/amba/apb/Protocol.scala similarity index 90% rename from src/main/scala/uncore/apb/Protocol.scala rename to src/main/scala/amba/apb/Protocol.scala index f8c84356..b67b4890 100644 --- a/src/main/scala/uncore/apb/Protocol.scala +++ b/src/main/scala/amba/apb/Protocol.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package uncore.apb +package freechips.rocketchip.amba.apb import Chisel._ diff --git a/src/main/scala/uncore/apb/RegisterRouter.scala b/src/main/scala/amba/apb/RegisterRouter.scala similarity index 87% rename from src/main/scala/uncore/apb/RegisterRouter.scala rename to src/main/scala/amba/apb/RegisterRouter.scala index b8e3a9ae..1cd52a63 100644 --- a/src/main/scala/uncore/apb/RegisterRouter.scala +++ b/src/main/scala/amba/apb/RegisterRouter.scala @@ -1,11 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.apb +package freechips.rocketchip.amba.apb import Chisel._ -import config._ -import diplomacy._ -import regmapper._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple} +import freechips.rocketchip.util.HeterogeneousBag import scala.math.{min,max} class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) @@ -61,10 +63,10 @@ object APBRegisterNode abstract class APBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule { val node = APBRegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) + val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) } -case class APBRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[APBBundle])(implicit val p: Parameters) +case class APBRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[APBBundle])(implicit val p: Parameters) class APBRegBundleBase(arg: APBRegBundleArg) extends Bundle { diff --git a/src/main/scala/uncore/apb/SRAM.scala b/src/main/scala/amba/apb/SRAM.scala similarity index 90% rename from src/main/scala/uncore/apb/SRAM.scala rename to src/main/scala/amba/apb/SRAM.scala index b17520df..57babb9c 100644 --- a/src/main/scala/uncore/apb/SRAM.scala +++ b/src/main/scala/amba/apb/SRAM.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.apb +package freechips.rocketchip.amba.apb import Chisel._ -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ class APBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/apb/Test.scala b/src/main/scala/amba/apb/Test.scala similarity index 87% rename from src/main/scala/uncore/apb/Test.scala rename to src/main/scala/amba/apb/Test.scala index 2f359f42..948ab197 100644 --- a/src/main/scala/uncore/apb/Test.scala +++ b/src/main/scala/amba/apb/Test.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.apb +package freechips.rocketchip.amba.apb import Chisel._ -import config._ -import diplomacy._ -import uncore.tilelink2._ -import unittest._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.unittest._ class RRTest0(address: BigInt)(implicit p: Parameters) extends APBRegisterRouter(address, 0, 32, 0, 4)( new APBRegBundle((), _) with RRTest0Bundle)( diff --git a/src/main/scala/uncore/apb/Xbar.scala b/src/main/scala/amba/apb/Xbar.scala similarity index 89% rename from src/main/scala/uncore/apb/Xbar.scala rename to src/main/scala/amba/apb/Xbar.scala index c5b78f48..d7742f40 100644 --- a/src/main/scala/uncore/apb/Xbar.scala +++ b/src/main/scala/amba/apb/Xbar.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.apb +package freechips.rocketchip.amba.apb import Chisel._ -import config._ -import diplomacy._ -import regmapper._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ import scala.math.{min,max} class APBFanout()(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/apb/package.scala b/src/main/scala/amba/apb/package.scala similarity index 67% rename from src/main/scala/uncore/apb/package.scala rename to src/main/scala/amba/apb/package.scala index d6f9bd4d..c8fc21e5 100644 --- a/src/main/scala/uncore/apb/package.scala +++ b/src/main/scala/amba/apb/package.scala @@ -1,9 +1,9 @@ // See LICENSE.SiFive for license details. -package uncore +package freechips.rocketchip.amba import Chisel._ -import diplomacy._ +import freechips.rocketchip.diplomacy.OutwardNodeHandle package object apb { diff --git a/src/main/scala/uncore/axi4/Buffer.scala b/src/main/scala/amba/axi4/Buffer.scala similarity index 94% rename from src/main/scala/uncore/axi4/Buffer.scala rename to src/main/scala/amba/axi4/Buffer.scala index 1658e8b0..c7c5bfa8 100644 --- a/src/main/scala/uncore/axi4/Buffer.scala +++ b/src/main/scala/amba/axi4/Buffer.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.internal.sourceinfo.SourceInfo import chisel3.util.IrrevocableIO -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.math.{min,max} // pipe is only used if a queue has depth = 1 diff --git a/src/main/scala/uncore/axi4/Bundles.scala b/src/main/scala/amba/axi4/Bundles.scala similarity index 96% rename from src/main/scala/uncore/axi4/Bundles.scala rename to src/main/scala/amba/axi4/Bundles.scala index 75f43c66..d0a8d174 100644 --- a/src/main/scala/uncore/axi4/Bundles.scala +++ b/src/main/scala/amba/axi4/Bundles.scala @@ -1,10 +1,10 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.util.Irrevocable -import util.GenericParameterizedBundle +import freechips.rocketchip.util.GenericParameterizedBundle abstract class AXI4BundleBase(params: AXI4BundleParameters) extends GenericParameterizedBundle(params) diff --git a/src/main/scala/uncore/axi4/Deinterleaver.scala b/src/main/scala/amba/axi4/Deinterleaver.scala similarity index 95% rename from src/main/scala/uncore/axi4/Deinterleaver.scala rename to src/main/scala/amba/axi4/Deinterleaver.scala index 3778c91d..fc04866f 100644 --- a/src/main/scala/uncore/axi4/Deinterleaver.scala +++ b/src/main/scala/amba/axi4/Deinterleaver.scala @@ -1,14 +1,14 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.internal.sourceinfo.SourceInfo import chisel3.util.IrrevocableIO -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.{leftOR, rightOR, UIntToOH1, OH1ToOH} import scala.math.{min,max} -import uncore.tilelink2.{leftOR, rightOR, UIntToOH1, OH1ToOH} class AXI4Deinterleaver(maxReadBytes: Int)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/axi4/Fragmenter.scala b/src/main/scala/amba/axi4/Fragmenter.scala similarity index 97% rename from src/main/scala/uncore/axi4/Fragmenter.scala rename to src/main/scala/amba/axi4/Fragmenter.scala index 43aa38a9..9282a6a2 100644 --- a/src/main/scala/uncore/axi4/Fragmenter.scala +++ b/src/main/scala/amba/axi4/Fragmenter.scala @@ -1,14 +1,14 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.internal.sourceinfo.SourceInfo import chisel3.util.IrrevocableIO -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.{leftOR, rightOR, UIntToOH1, OH1ToOH} import scala.math.{min,max} -import uncore.tilelink2.{leftOR, rightOR, UIntToOH1, OH1ToOH} class AXI4Fragmenter()(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/axi4/IdIndexer.scala b/src/main/scala/amba/axi4/IdIndexer.scala similarity index 96% rename from src/main/scala/uncore/axi4/IdIndexer.scala rename to src/main/scala/amba/axi4/IdIndexer.scala index 1fa6aee9..5a4ddb34 100644 --- a/src/main/scala/uncore/axi4/IdIndexer.scala +++ b/src/main/scala/amba/axi4/IdIndexer.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.math.{min,max} class AXI4IdIndexer(idBits: Int)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/uncore/axi4/Nodes.scala b/src/main/scala/amba/axi4/Nodes.scala similarity index 95% rename from src/main/scala/uncore/axi4/Nodes.scala rename to src/main/scala/amba/axi4/Nodes.scala index a4e1ca00..dacbefcc 100644 --- a/src/main/scala/uncore/axi4/Nodes.scala +++ b/src/main/scala/amba/axi4/Nodes.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4EdgeParameters, AXI4Bundle] { diff --git a/src/main/scala/uncore/axi4/Parameters.scala b/src/main/scala/amba/axi4/Parameters.scala similarity index 97% rename from src/main/scala/uncore/axi4/Parameters.scala rename to src/main/scala/amba/axi4/Parameters.scala index c7107f91..19226fe5 100644 --- a/src/main/scala/uncore/axi4/Parameters.scala +++ b/src/main/scala/amba/axi4/Parameters.scala @@ -1,10 +1,10 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.math.max case class AXI4SlaveParameters( diff --git a/src/main/scala/uncore/axi4/Protocol.scala b/src/main/scala/amba/axi4/Protocol.scala similarity index 96% rename from src/main/scala/uncore/axi4/Protocol.scala rename to src/main/scala/amba/axi4/Protocol.scala index 70ad2bfa..4e621809 100644 --- a/src/main/scala/uncore/axi4/Protocol.scala +++ b/src/main/scala/amba/axi4/Protocol.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.util.{Irrevocable, IrrevocableIO} diff --git a/src/main/scala/uncore/axi4/RegisterRouter.scala b/src/main/scala/amba/axi4/RegisterRouter.scala similarity index 88% rename from src/main/scala/uncore/axi4/RegisterRouter.scala rename to src/main/scala/amba/axi4/RegisterRouter.scala index 7ac32fae..20d431b0 100644 --- a/src/main/scala/uncore/axi4/RegisterRouter.scala +++ b/src/main/scala/amba/axi4/RegisterRouter.scala @@ -1,11 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ -import config._ -import diplomacy._ -import regmapper._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple} +import freechips.rocketchip.util.{HeterogeneousBag, MaskGen} import scala.math.{min,max} class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) @@ -43,7 +45,7 @@ class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int val aw_extra = Cat(Seq(aw.bits.id) ++ aw.bits.user.toList) val in_extra = Mux(ar.valid, ar_extra, aw_extra) val addr = Mux(ar.valid, ar.bits.addr, aw.bits.addr) - val mask = uncore.tilelink2.maskGen(ar.bits.addr, ar.bits.size, beatBytes) + val mask = MaskGen(ar.bits.addr, ar.bits.size, beatBytes) in.bits.read := ar.valid in.bits.index := addr >> log2Ceil(beatBytes) @@ -87,10 +89,10 @@ object AXI4RegisterNode abstract class AXI4RegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule { val node = AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) + val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) } -case class AXI4RegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[AXI4Bundle])(implicit val p: Parameters) +case class AXI4RegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[AXI4Bundle])(implicit val p: Parameters) class AXI4RegBundleBase(arg: AXI4RegBundleArg) extends Bundle { diff --git a/src/main/scala/uncore/axi4/SRAM.scala b/src/main/scala/amba/axi4/SRAM.scala similarity index 94% rename from src/main/scala/uncore/axi4/SRAM.scala rename to src/main/scala/amba/axi4/SRAM.scala index 6c53cc02..38686f7e 100644 --- a/src/main/scala/uncore/axi4/SRAM.scala +++ b/src/main/scala/amba/axi4/SRAM.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/axi4/Test.scala b/src/main/scala/amba/axi4/Test.scala similarity index 94% rename from src/main/scala/uncore/axi4/Test.scala rename to src/main/scala/amba/axi4/Test.scala index 401036ff..5c926c39 100644 --- a/src/main/scala/uncore/axi4/Test.scala +++ b/src/main/scala/amba/axi4/Test.scala @@ -1,12 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ -import config._ -import diplomacy._ -import uncore.tilelink2._ -import unittest._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.devices.tilelink.TLError +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.unittest._ class RRTest0(address: BigInt)(implicit p: Parameters) extends AXI4RegisterRouter(address, 0, 32, 0, 4)( new AXI4RegBundle((), _) with RRTest0Bundle)( diff --git a/src/main/scala/uncore/axi4/ToTL.scala b/src/main/scala/amba/axi4/ToTL.scala similarity index 97% rename from src/main/scala/uncore/axi4/ToTL.scala rename to src/main/scala/amba/axi4/ToTL.scala index 7f219052..b9801855 100644 --- a/src/main/scala/uncore/axi4/ToTL.scala +++ b/src/main/scala/amba/axi4/ToTL.scala @@ -1,12 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import uncore.tilelink2._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ case class AXI4ToTLNode() extends MixedAdapterNode(AXI4Imp, TLImp)( dFn = { case AXI4MasterPortParameters(masters, userBits) => diff --git a/src/main/scala/uncore/axi4/UserYanker.scala b/src/main/scala/amba/axi4/UserYanker.scala similarity index 95% rename from src/main/scala/uncore/axi4/UserYanker.scala rename to src/main/scala/amba/axi4/UserYanker.scala index 72bd7bdc..f0c6efbc 100644 --- a/src/main/scala/uncore/axi4/UserYanker.scala +++ b/src/main/scala/amba/axi4/UserYanker.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.axi4 +package freechips.rocketchip.amba.axi4 import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import uncore.tilelink2.UIntToOH1 +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.UIntToOH1 class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/axi4/package.scala b/src/main/scala/amba/axi4/package.scala similarity index 68% rename from src/main/scala/uncore/axi4/package.scala rename to src/main/scala/amba/axi4/package.scala index cf730478..75fef97a 100644 --- a/src/main/scala/uncore/axi4/package.scala +++ b/src/main/scala/amba/axi4/package.scala @@ -1,9 +1,9 @@ // See LICENSE.SiFive for license details. -package uncore +package freechips.rocketchip.amba import Chisel._ -import diplomacy._ +import freechips.rocketchip.diplomacy.OutwardNodeHandle package object axi4 { diff --git a/src/main/scala/rocketchip/Configs.scala b/src/main/scala/chip/Configs.scala similarity index 81% rename from src/main/scala/rocketchip/Configs.scala rename to src/main/scala/chip/Configs.scala index 652be85b..ca24d164 100644 --- a/src/main/scala/rocketchip/Configs.scala +++ b/src/main/scala/chip/Configs.scala @@ -1,24 +1,24 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocketchip +package freechips.rocketchip.chip import Chisel._ -import junctions._ -import rocket._ -import diplomacy._ -import uncore.agents._ -import uncore.tilelink2._ -import uncore.devices._ -import uncore.converters._ -import util._ -import coreplex._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.devices._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tile.XLen +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ + import scala.math.max import scala.collection.mutable.{LinkedHashSet, ListBuffer} import scala.collection.immutable.HashMap + import DefaultTestSuites._ -import config._ -import tile.XLen class BasePlatformConfig extends Config((site, here, up) => { // DTS descriptive parameters @@ -49,33 +49,23 @@ class BasePlatformConfig extends Config((site, here, up) => { class BaseConfig extends Config(new BaseCoreplexConfig ++ new BasePlatformConfig) class DefaultConfig extends Config(new WithNBigCores(1) ++ new BaseConfig) -class DefaultL2Config extends Config(new WithL2Cache ++ new WithNBigCores(1) ++ new BaseConfig) class DefaultBufferlessConfig extends Config( new WithBufferlessBroadcastHub ++ new WithNBigCores(1) ++ new BaseConfig) class FPGAConfig extends Config(Parameters.empty) class DefaultFPGAConfig extends Config(new FPGAConfig ++ new BaseConfig) -class DefaultL2FPGAConfig extends Config( - new WithL2Capacity(64) ++ new WithL2Cache ++ new DefaultFPGAConfig) class DefaultSmallConfig extends Config(new WithNSmallCores(1) ++ new BaseConfig) class DefaultRV32Config extends Config(new WithRV32 ++ new DefaultConfig) class DualBankConfig extends Config( new WithNBanksPerMemChannel(2) ++ new BaseConfig) -class DualBankL2Config extends Config( - new WithNBanksPerMemChannel(2) ++ new WithL2Cache ++ new BaseConfig) class DualChannelConfig extends Config(new WithNMemoryChannels(2) ++ new BaseConfig) -class DualChannelL2Config extends Config( - new WithNMemoryChannels(2) ++ new WithL2Cache ++ new BaseConfig) class DualChannelDualBankConfig extends Config( new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(2) ++ new BaseConfig) -class DualChannelDualBankL2Config extends Config( - new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(2) ++ - new WithL2Cache ++ new BaseConfig) class RoccExampleConfig extends Config(new WithRoccExample ++ new DefaultConfig) @@ -84,11 +74,7 @@ class Edge128BitConfig extends Config( class Edge32BitConfig extends Config( new WithEdgeDataBits(32) ++ new BaseConfig) -class SmallL2Config extends Config( - new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++ - new WithL2Capacity(256) ++ new DefaultL2Config) - -class SingleChannelBenchmarkConfig extends Config(new WithL2Capacity(256) ++ new DefaultL2Config) +class SingleChannelBenchmarkConfig extends Config(new DefaultConfig) class DualChannelBenchmarkConfig extends Config(new WithNMemoryChannels(2) ++ new SingleChannelBenchmarkConfig) class QuadChannelBenchmarkConfig extends Config(new WithNMemoryChannels(4) ++ new SingleChannelBenchmarkConfig) class OctoChannelBenchmarkConfig extends Config(new WithNMemoryChannels(8) ++ new SingleChannelBenchmarkConfig) @@ -96,9 +82,9 @@ class OctoChannelBenchmarkConfig extends Config(new WithNMemoryChannels(8) ++ ne class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseConfig) class DualCoreConfig extends Config( - new WithNBigCores(2) ++ new WithL2Cache ++ new BaseConfig) + new WithNBigCores(2) ++ new BaseConfig) class HeterogeneousDualCoreConfig extends Config( - new WithNSmallCores(1) ++ new WithNBigCores(1) ++ new WithL2Cache ++ new BaseConfig) + new WithNSmallCores(1) ++ new WithNBigCores(1) ++ new BaseConfig) class TinyConfig extends Config( new WithNMemoryChannels(0) ++ diff --git a/src/main/scala/rocketchip/DebugTransport.scala b/src/main/scala/chip/DebugTransport.scala similarity index 97% rename from src/main/scala/rocketchip/DebugTransport.scala rename to src/main/scala/chip/DebugTransport.scala index 579672dc..30c11c94 100644 --- a/src/main/scala/rocketchip/DebugTransport.scala +++ b/src/main/scala/chip/DebugTransport.scala @@ -1,12 +1,13 @@ // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip import Chisel._ -import util._ -import config._ -import jtag._ -import uncore.devices.{DMIConsts, DMIIO, DMIReq, DMIResp} + +import freechips.rocketchip.config._ +import freechips.rocketchip.devices.debug.{DMIConsts, DMIIO, DMIReq, DMIResp} +import freechips.rocketchip.jtag._ +import freechips.rocketchip.util._ case object IncludeJtagDTM extends Field[Boolean] diff --git a/src/main/scala/rocketchip/ExampleTop.scala b/src/main/scala/chip/ExampleTop.scala similarity index 94% rename from src/main/scala/rocketchip/ExampleTop.scala rename to src/main/scala/chip/ExampleTop.scala index 2d146220..19e1cd4f 100644 --- a/src/main/scala/rocketchip/ExampleTop.scala +++ b/src/main/scala/chip/ExampleTop.scala @@ -1,11 +1,10 @@ // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip import Chisel._ -import config._ -import junctions._ -import rocketchip._ + +import freechips.rocketchip.config.Parameters /** Example system with periphery devices (w/o coreplex) */ abstract class ExampleSystem(implicit p: Parameters) extends BaseSystem diff --git a/src/main/scala/rocketchip/Generator.scala b/src/main/scala/chip/Generator.scala similarity index 93% rename from src/main/scala/rocketchip/Generator.scala rename to src/main/scala/chip/Generator.scala index 93c5961f..6a998276 100644 --- a/src/main/scala/rocketchip/Generator.scala +++ b/src/main/scala/chip/Generator.scala @@ -1,14 +1,15 @@ // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip -import tile.XLen -import coreplex.RocketTilesKey +import freechips.rocketchip.coreplex.RocketTilesKey +import freechips.rocketchip.tile.XLen +import freechips.rocketchip.util.GeneratorApp import scala.collection.mutable.LinkedHashSet /** A Generator for platforms containing Rocket Coreplexes */ -object Generator extends util.GeneratorApp { +object Generator extends GeneratorApp { val rv64RegrTestNames = LinkedHashSet( "rv64ud-v-fcvt", diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/chip/Periphery.scala similarity index 97% rename from src/main/scala/rocketchip/Periphery.scala rename to src/main/scala/chip/Periphery.scala index 031bea83..4ad3c45b 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/chip/Periphery.scala @@ -1,14 +1,17 @@ // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip import Chisel._ -import config._ -import coreplex._ -import diplomacy._ -import uncore.tilelink2._ -import uncore.axi4._ -import util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.util._ + import scala.math.{min,max} /** Specifies the size of external memory */ @@ -42,7 +45,7 @@ trait HasPeripheryParameters { def socBusBytes = socBusConfig.beatBytes def cacheBlockBytes = p(CacheBlockBytes) def peripheryBusArithmetic = p(PeripheryBusArithmetic) - def nMemoryChannels = p(coreplex.BankedL2Config).nMemoryChannels + def nMemoryChannels = p(BankedL2Config).nMemoryChannels def nExtInterrupts = p(NExtTopInterrupts) } diff --git a/src/main/scala/rocketchip/RISCVPlatform.scala b/src/main/scala/chip/RISCVPlatform.scala similarity index 90% rename from src/main/scala/rocketchip/RISCVPlatform.scala rename to src/main/scala/chip/RISCVPlatform.scala index 30d78f98..514f05cc 100644 --- a/src/main/scala/rocketchip/RISCVPlatform.scala +++ b/src/main/scala/chip/RISCVPlatform.scala @@ -1,15 +1,17 @@ // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip import Chisel._ -import config._ -import coreplex._ -import diplomacy._ -import jtag.JTAGIO -import uncore.tilelink2._ -import uncore.devices._ -import util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.devices.debug._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.jtag.JTAGIO +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ /** All the traits defined in this file assume that they are being mixed in * to a system that has a standard RISCV-based coreplex platform. @@ -89,7 +91,7 @@ trait HasPeripheryRTCCounter extends HasSystemNetworks with HasCoreplexRISCVPlat trait HasPeripheryRTCCounterModuleImp extends LazyMultiIOModuleImp { val outer: HasPeripheryRTCCounter - val period = p(rocketchip.RTCPeriod) + val period = p(RTCPeriod) val rtcCounter = RegInit(UInt(0, width = log2Up(period))) val rtcWrap = rtcCounter === UInt(period-1) diff --git a/src/main/scala/rocketchip/RocketPlexMaster.scala b/src/main/scala/chip/RocketPlexMaster.scala similarity index 82% rename from src/main/scala/rocketchip/RocketPlexMaster.scala rename to src/main/scala/chip/RocketPlexMaster.scala index 6af16081..8e5c4e2e 100644 --- a/src/main/scala/rocketchip/RocketPlexMaster.scala +++ b/src/main/scala/chip/RocketPlexMaster.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip import Chisel._ -import coreplex.RocketPlex -import diplomacy.{LazyModule, LazyMultiIOModuleImp} + +import freechips.rocketchip.coreplex.RocketPlex +import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp} /** Add a RocketPlex to the system */ trait HasRocketPlexMaster extends HasSystemNetworks with HasCoreplexRISCVPlatform { diff --git a/src/main/scala/rocketchip/RocketTestSuite.scala b/src/main/scala/chip/RocketTestSuite.scala similarity index 99% rename from src/main/scala/rocketchip/RocketTestSuite.scala rename to src/main/scala/chip/RocketTestSuite.scala index 32e7b664..ccd4d740 100644 --- a/src/main/scala/rocketchip/RocketTestSuite.scala +++ b/src/main/scala/chip/RocketTestSuite.scala @@ -1,9 +1,8 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip -import Chisel._ import scala.collection.mutable.LinkedHashSet abstract class RocketTestSuite { diff --git a/src/main/scala/rocketchip/System.scala b/src/main/scala/chip/System.scala similarity index 76% rename from src/main/scala/rocketchip/System.scala rename to src/main/scala/chip/System.scala index 2486f763..ddef55e4 100644 --- a/src/main/scala/rocketchip/System.scala +++ b/src/main/scala/chip/System.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip import Chisel._ -import config.Parameters -import diplomacy._ -import util._ + +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp} +import freechips.rocketchip.util.ElaborationArtefacts /** BareSystem is the root class for creating a top-level RTL module */ abstract class BareSystem(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/chip/TestHarness.scala similarity index 84% rename from src/main/scala/rocketchip/TestHarness.scala rename to src/main/scala/chip/TestHarness.scala index 751e6359..fe57443c 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/chip/TestHarness.scala @@ -1,14 +1,15 @@ // See LICENSE.SiFive for license details. -package rocketchip +package freechips.rocketchip.chip import Chisel._ -import config._ -import junctions._ -import diplomacy._ -import coreplex._ -import uncore.axi4._ -import jtag.JTAGIO + +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.devices.debug._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.jtag.JTAGIO class TestHarness()(implicit p: Parameters) extends Module { val io = new Bundle { @@ -52,11 +53,11 @@ class SimDTM(implicit p: Parameters) extends BlackBox { val io = new Bundle { val clk = Clock(INPUT) val reset = Bool(INPUT) - val debug = new uncore.devices.DMIIO + val debug = new DMIIO val exit = UInt(OUTPUT, 32) } - def connect(tbclk: Clock, tbreset: Bool, dutio: uncore.devices.ClockedDMIIO, tbsuccess: Bool) = { + def connect(tbclk: Clock, tbreset: Bool, dutio: ClockedDMIIO, tbsuccess: Bool) = { io.clk := tbclk io.reset := tbreset dutio.dmi <> io.debug diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/chip/Utils.scala similarity index 84% rename from src/main/scala/rocketchip/Utils.scala rename to src/main/scala/chip/Utils.scala index f6d039d8..bab78811 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/chip/Utils.scala @@ -1,18 +1,13 @@ // See LICENSE.SiFive for license details. -package rocketchip - -import config._ -import junctions._ -import diplomacy._ -import uncore.devices._ -import tile.XLen -import coreplex._ -import uncore.tilelink2._ -import util._ +package freechips.rocketchip.chip +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy.DTB +import freechips.rocketchip.coreplex.BootROMFile import java.nio.file.{Files, Paths} import java.nio.{ByteBuffer, ByteOrder} +import scala.collection.mutable.ArrayBuffer class RangeManager { private var finalized = false @@ -39,7 +34,7 @@ class RangeManager { class ResourceManager[T] { private var finalized = false - private val l = collection.mutable.ArrayBuffer[T]() + private val l = ArrayBuffer[T]() def add(element: T) = { require(!finalized); l += element } def add(list: Seq[T]) = { require(!finalized); l ++= list } def get: Seq[T] = { finalized = true; l } diff --git a/src/main/scala/config/Config.scala b/src/main/scala/config/Config.scala index 4e777ec5..c7930ee6 100644 --- a/src/main/scala/config/Config.scala +++ b/src/main/scala/config/Config.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package config +package freechips.rocketchip.config class Field[T] diff --git a/src/main/scala/coreplex/BaseCoreplex.scala b/src/main/scala/coreplex/BaseCoreplex.scala index d3062d83..eefaf011 100644 --- a/src/main/scala/coreplex/BaseCoreplex.scala +++ b/src/main/scala/coreplex/BaseCoreplex.scala @@ -1,14 +1,14 @@ // See LICENSE.SiFive for license details. -package coreplex +package freechips.rocketchip.coreplex import Chisel._ -import config._ -import diplomacy._ -import tile.XLen -import tile.TileInterrupts -import uncore.tilelink2._ -import util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tile.{ XLen, TileInterrupts} +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ /** Widths of various points in the SoC */ case class TLBusConfig(beatBytes: Int) diff --git a/src/main/scala/coreplex/Configs.scala b/src/main/scala/coreplex/Configs.scala index 8dea74a4..65bd8cd8 100644 --- a/src/main/scala/coreplex/Configs.scala +++ b/src/main/scala/coreplex/Configs.scala @@ -1,18 +1,18 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package coreplex +package freechips.rocketchip.coreplex import Chisel._ -import config._ -import diplomacy._ -import rocket._ -import tile._ -import uncore.converters._ -import uncore.devices._ -import uncore.tilelink2._ -import uncore.util._ -import util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.devices.debug._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ class BaseCoreplexConfig extends Config ((site, here, up) => { case PAddrBits => 32 @@ -20,14 +20,13 @@ class BaseCoreplexConfig extends Config ((site, here, up) => { case ASIdBits => 0 case XLen => 64 // Applies to all cores case ResetVectorBits => site(PAddrBits) - case MaxHartIdBits => log2Up(site(NTiles)) + case MaxHartIdBits => log2Up(site(RocketTilesKey).size) case BuildCore => (p: Parameters) => new Rocket()(p) case RocketCrossing => SynchronousCrossing() case RocketTilesKey => Nil case DMKey => DefaultDebugModuleConfig(site(XLen)) case PLICKey => PLICParams() case ClintKey => ClintParams() - case NTiles => site(RocketTilesKey).size case CBusConfig => TLBusConfig(beatBytes = site(XLen)/8) case L1toL2Config => TLBusConfig(beatBytes = site(XLen)/8) // increase for more PCIe bandwidth case BootROMFile => "./bootrom/bootrom.img" @@ -112,10 +111,6 @@ class WithCacheBlockBytes(linesize: Int) extends Config((site, here, up) => { case CacheBlockBytes => linesize }) -class WithL2Cache extends Config(Parameters.empty) // TODO: re-add L2 -class WithL2Capacity(size_kb: Int) extends Config(Parameters.empty) // TODO: re-add L2 -class WithNL2Ways(n: Int) extends Config(Parameters.empty) // TODO: re-add L2 - class WithBufferlessBroadcastHub extends Config((site, here, up) => { case BroadcastConfig => up(BroadcastConfig, site).copy(bufferless = true) }) diff --git a/src/main/scala/coreplex/CoreplexNetwork.scala b/src/main/scala/coreplex/CoreplexNetwork.scala index afe42ecb..7476b841 100644 --- a/src/main/scala/coreplex/CoreplexNetwork.scala +++ b/src/main/scala/coreplex/CoreplexNetwork.scala @@ -1,13 +1,14 @@ // See LICENSE.SiFive for license details. -package coreplex +package freechips.rocketchip.coreplex import Chisel._ -import config._ -import diplomacy._ -import uncore.tilelink2._ -import uncore.util._ -import util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.rocket.PAddrBits +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ trait CoreplexNetwork extends HasCoreplexParameters { val module: CoreplexNetworkModule @@ -112,7 +113,7 @@ trait CoreplexNetworkModule extends HasCoreplexParameters { val io: CoreplexNetworkBundle println("Generated Address Map") - private val aw = (outer.p(rocket.PAddrBits)-1)/4 + 1 + private val aw = (outer.p(PAddrBits)-1)/4 + 1 private val fmt = s"\t%${aw}x - %${aw}x %c%c%c%c %s" private def collect(path: List[String], value: ResourceValue): List[(String, ResourceAddress)] = { diff --git a/src/main/scala/coreplex/ISPPort.scala b/src/main/scala/coreplex/ISPPort.scala index eb60873f..70017536 100644 --- a/src/main/scala/coreplex/ISPPort.scala +++ b/src/main/scala/coreplex/ISPPort.scala @@ -1,14 +1,10 @@ // See LICENSE.SiFive for license details. -package coreplex +package freechips.rocketchip.coreplex import Chisel._ -import config._ -import diplomacy._ -import rocket._ -import tile._ -import uncore.tilelink2._ -import util._ +import freechips.rocketchip.diplomacy.LazyModule +import freechips.rocketchip.tilelink._ trait HasISPPort extends CoreplexNetwork { val module: HasISPPortModule diff --git a/src/main/scala/coreplex/RISCVPlatform.scala b/src/main/scala/coreplex/RISCVPlatform.scala index b42ed557..7eba3ef7 100644 --- a/src/main/scala/coreplex/RISCVPlatform.scala +++ b/src/main/scala/coreplex/RISCVPlatform.scala @@ -1,17 +1,17 @@ // See LICENSE.SiFive for license details. -package coreplex +package freechips.rocketchip.coreplex import Chisel._ -import config.Field -import diplomacy._ -import tile._ -import uncore.tilelink2._ -import uncore.devices._ -import util._ -/** Number of tiles */ -case object NTiles extends Field[Int] +import freechips.rocketchip.config.Field +import freechips.rocketchip.devices.debug._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ + case object PLICKey extends Field[PLICParams] case object ClintKey extends Field[ClintParams] diff --git a/src/main/scala/coreplex/RocketPlex.scala b/src/main/scala/coreplex/RocketPlex.scala index 25c25ca1..8d6a1829 100644 --- a/src/main/scala/coreplex/RocketPlex.scala +++ b/src/main/scala/coreplex/RocketPlex.scala @@ -1,9 +1,10 @@ // See LICENSE.SiFive for license details. -package coreplex +package freechips.rocketchip.coreplex import Chisel._ -import config.Parameters + +import freechips.rocketchip.config.Parameters class RocketPlex(implicit p: Parameters) extends BaseCoreplex with CoreplexRISCVPlatform diff --git a/src/main/scala/coreplex/RocketTiles.scala b/src/main/scala/coreplex/RocketTiles.scala index 4b619017..fbacc17b 100644 --- a/src/main/scala/coreplex/RocketTiles.scala +++ b/src/main/scala/coreplex/RocketTiles.scala @@ -1,22 +1,22 @@ // See LICENSE.SiFive for license details. -package coreplex +package freechips.rocketchip.coreplex import Chisel._ -import config._ -import diplomacy._ -import rocket._ -import tile._ -import uncore.tilelink2._ -import util._ +import freechips.rocketchip.config.Field +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ -sealed trait ClockCrossing -case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends ClockCrossing -case class RationalCrossing(direction: RationalDirection = FastToSlow) extends ClockCrossing -case class AsynchronousCrossing(depth: Int, sync: Int = 2) extends ClockCrossing +sealed trait CoreplexClockCrossing +case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends CoreplexClockCrossing +case class RationalCrossing(direction: RationalDirection = FastToSlow) extends CoreplexClockCrossing +case class AsynchronousCrossing(depth: Int, sync: Int = 2) extends CoreplexClockCrossing case object RocketTilesKey extends Field[Seq[RocketTileParams]] -case object RocketCrossing extends Field[ClockCrossing] +case object RocketCrossing extends Field[CoreplexClockCrossing] trait HasRocketTiles extends CoreplexRISCVPlatform { val module: HasRocketTilesModule diff --git a/src/main/scala/uncore/devices/debug/Debug.scala b/src/main/scala/devices/debug/Debug.scala similarity index 98% rename from src/main/scala/uncore/devices/debug/Debug.scala rename to src/main/scala/devices/debug/Debug.scala index 4f1381c1..30271488 100644 --- a/src/main/scala/uncore/devices/debug/Debug.scala +++ b/src/main/scala/devices/debug/Debug.scala @@ -1,16 +1,15 @@ // See LICENSE.SiFive for license details. -package uncore.devices +package freechips.rocketchip.devices.debug import Chisel._ -import junctions._ -import util._ -import regmapper._ -import tile.XLen -import uncore.tilelink2._ -import config._ -import diplomacy._ - +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.rocket.Instructions +import freechips.rocketchip.tile.XLen +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ /** Constant values used by both Debug Bus Response & Request */ @@ -756,7 +755,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p: val goReg = Reg(Bool()) val goAbstract = Wire(init = false.B) - val jalAbstract = Wire(init = (new GeneratedUJ()).fromBits(rocket.Instructions.JAL.value.U)) + val jalAbstract = Wire(init = (new GeneratedUJ()).fromBits(Instructions.JAL.value.U)) jalAbstract.setImm(ABSTRACT(cfg) - WHERETO) when (~io.dmactive){ @@ -838,20 +837,20 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p: val abstractGeneratedS = Wire(new GeneratedS()) val nop = Wire(new GeneratedI()) - abstractGeneratedI.opcode := ((new GeneratedI()).fromBits(rocket.Instructions.LW.value.U)).opcode + abstractGeneratedI.opcode := ((new GeneratedI()).fromBits(Instructions.LW.value.U)).opcode abstractGeneratedI.rd := (accessRegisterCommandReg.regno & 0x1F.U) abstractGeneratedI.funct3 := accessRegisterCommandReg.size abstractGeneratedI.rs1 := 0.U abstractGeneratedI.imm := DATA.U - abstractGeneratedS.opcode := ((new GeneratedS()).fromBits(rocket.Instructions.SW.value.U)).opcode + abstractGeneratedS.opcode := ((new GeneratedS()).fromBits(Instructions.SW.value.U)).opcode abstractGeneratedS.immlo := (DATA & 0x1F).U abstractGeneratedS.funct3 := accessRegisterCommandReg.size abstractGeneratedS.rs1 := 0.U abstractGeneratedS.rs2 := (accessRegisterCommandReg.regno & 0x1F.U) abstractGeneratedS.immhi := (DATA >> 5).U - nop := ((new GeneratedI()).fromBits(rocket.Instructions.ADDI.value.U)) + nop := ((new GeneratedI()).fromBits(Instructions.ADDI.value.U)) nop.rd := 0.U nop.rs1 := 0.U nop.imm := 0.U @@ -867,7 +866,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p: ) abstractGeneratedMem(1) := Mux(accessRegisterCommandReg.postexec, nop.asUInt(), - rocket.Instructions.EBREAK.value.U) + Instructions.EBREAK.value.U) } //-------------------------------------------------------------- diff --git a/src/main/scala/uncore/devices/debug/DebugRomContents.scala b/src/main/scala/devices/debug/DebugRomContents.scala similarity index 94% rename from src/main/scala/uncore/devices/debug/DebugRomContents.scala rename to src/main/scala/devices/debug/DebugRomContents.scala index a56d83af..e0419d03 100644 --- a/src/main/scala/uncore/devices/debug/DebugRomContents.scala +++ b/src/main/scala/devices/debug/DebugRomContents.scala @@ -1,6 +1,6 @@ // This file was auto-generated by 'make publish' in debug/ directory. -package uncore.devices +package freechips.rocketchip.devices.debug object DebugRomContents { diff --git a/src/main/scala/uncore/devices/debug/abstract_commands.scala b/src/main/scala/devices/debug/abstract_commands.scala similarity index 97% rename from src/main/scala/uncore/devices/debug/abstract_commands.scala rename to src/main/scala/devices/debug/abstract_commands.scala index da720282..5791908a 100644 --- a/src/main/scala/uncore/devices/debug/abstract_commands.scala +++ b/src/main/scala/devices/debug/abstract_commands.scala @@ -1,4 +1,4 @@ -package uncore.devices +package freechips.rocketchip.devices.debug import Chisel._ diff --git a/src/main/scala/uncore/devices/debug/dm_registers.scala b/src/main/scala/devices/debug/dm_registers.scala similarity index 99% rename from src/main/scala/uncore/devices/debug/dm_registers.scala rename to src/main/scala/devices/debug/dm_registers.scala index f2073307..34d7fdcd 100644 --- a/src/main/scala/uncore/devices/debug/dm_registers.scala +++ b/src/main/scala/devices/debug/dm_registers.scala @@ -1,4 +1,4 @@ -package uncore.devices +package freechips.rocketchip.devices.debug import Chisel._ diff --git a/src/main/scala/uncore/devices/Clint.scala b/src/main/scala/devices/tilelink/Clint.scala similarity index 89% rename from src/main/scala/uncore/devices/Clint.scala rename to src/main/scala/devices/tilelink/Clint.scala index 90e8aa13..ff3e1067 100644 --- a/src/main/scala/uncore/devices/Clint.scala +++ b/src/main/scala/devices/tilelink/Clint.scala @@ -1,18 +1,15 @@ // See LICENSE.SiFive for license details. -package uncore.devices +package freechips.rocketchip.devices.tilelink import Chisel._ -import junctions._ -import junctions.NastiConstants._ -import regmapper._ -import diplomacy._ -import uncore.tilelink2._ -import uncore.util._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.tile.XLen +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ import scala.math.{min,max} -import config._ -import tile.XLen object ClintConsts { diff --git a/src/main/scala/uncore/tilelink2/Error.scala b/src/main/scala/devices/tilelink/Error.scala similarity index 89% rename from src/main/scala/uncore/tilelink2/Error.scala rename to src/main/scala/devices/tilelink/Error.scala index 51a3f791..c3f2cac1 100644 --- a/src/main/scala/uncore/tilelink2/Error.scala +++ b/src/main/scala/devices/tilelink/Error.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.devices.tilelink import Chisel._ -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ class TLError(address: Seq[AddressSet], beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/devices/tilelink/Plic.scala similarity index 96% rename from src/main/scala/uncore/devices/Plic.scala rename to src/main/scala/devices/tilelink/Plic.scala index 9ecc8021..ab07e9f4 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/devices/tilelink/Plic.scala @@ -1,18 +1,16 @@ // See LICENSE.SiFive for license details. -package uncore.devices +package freechips.rocketchip.devices.tilelink import Chisel._ import Chisel.ImplicitConversions._ - -import junctions._ -import diplomacy._ -import regmapper._ -import uncore.tilelink2._ -import config._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.tile.XLen +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ import scala.math.min -import tile.XLen -import util._ class GatewayPLICIO extends Bundle { val valid = Bool(OUTPUT) diff --git a/src/main/scala/devices/tilelink/Rom.scala b/src/main/scala/devices/tilelink/Rom.scala new file mode 100644 index 00000000..7c57eb86 --- /dev/null +++ b/src/main/scala/devices/tilelink/Rom.scala @@ -0,0 +1,52 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package freechips.rocketchip.devices.tilelink + +import Chisel._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ + +class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4, + resources: Seq[Resource] = new SimpleDevice("rom", Seq("sifive,rom0")).reg("mem"))(implicit p: Parameters) extends LazyModule +{ + + val node = TLManagerNode(beatBytes, TLManagerParameters ( + address = List(AddressSet(base, size-1)), + resources = resources, + regionType = RegionType.UNCACHED, + executable = executable, + supportsGet = TransferSizes(1, beatBytes), + fifoId = Some(0))) + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val in = node.bundleIn + } + + val contents = contentsDelayed + val wrapSize = 1 << log2Ceil(contents.size) + require (wrapSize <= size) + + val in = io.in(0) + val edge = node.edgesIn(0) + + val words = (contents ++ Seq.fill(wrapSize-contents.size)(0.toByte)).grouped(beatBytes).toSeq + val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8}) + val rom = Vec(bigs.map(x => UInt(x, width = 8*beatBytes))) + + in.d.valid := in.a.valid + in.a.ready := in.d.ready + + val index = in.a.bits.address(log2Ceil(wrapSize)-1,log2Ceil(beatBytes)) + val high = if (wrapSize == size) UInt(0) else in.a.bits.address(log2Ceil(size)-1, log2Ceil(wrapSize)) + in.d.bits := edge.AccessAck(in.a.bits, UInt(0), Mux(high.orR, UInt(0), rom(index))) + + // Tie off unused channels + in.b.valid := Bool(false) + in.c.ready := Bool(true) + in.e.ready := Bool(true) + } +} diff --git a/src/main/scala/uncore/tilelink2/TestRAM.scala b/src/main/scala/devices/tilelink/TestRAM.scala similarity index 92% rename from src/main/scala/uncore/tilelink2/TestRAM.scala rename to src/main/scala/devices/tilelink/TestRAM.scala index c1b28f56..38a18260 100644 --- a/src/main/scala/uncore/tilelink2/TestRAM.scala +++ b/src/main/scala/devices/tilelink/TestRAM.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.devices.tilelink import Chisel._ -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ // Do not use this for synthesis! Only for simulation. class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule @@ -63,7 +64,7 @@ class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int } /** Synthesizeable unit testing */ -import unittest._ +import freechips.rocketchip.unittest._ class TLRAMZeroDelay(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule { val fuzz = LazyModule(new TLFuzzer(txns)) diff --git a/src/main/scala/uncore/tilelink2/Zero.scala b/src/main/scala/devices/tilelink/Zero.scala similarity index 89% rename from src/main/scala/uncore/tilelink2/Zero.scala rename to src/main/scala/devices/tilelink/Zero.scala index aaed3af7..9463d9cb 100644 --- a/src/main/scala/uncore/tilelink2/Zero.scala +++ b/src/main/scala/devices/tilelink/Zero.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.devices.tilelink import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ class TLZero(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/diplomacy/AddressDecoder.scala b/src/main/scala/diplomacy/AddressDecoder.scala index 02b039fb..1b2ed837 100644 --- a/src/main/scala/diplomacy/AddressDecoder.scala +++ b/src/main/scala/diplomacy/AddressDecoder.scala @@ -1,8 +1,8 @@ // See LICENSE.SiFive for license details. -package diplomacy +package freechips.rocketchip.diplomacy -import Chisel._ +import Chisel.log2Ceil import scala.math.{max,min} object AddressDecoder diff --git a/src/main/scala/diplomacy/DeviceTree.scala b/src/main/scala/diplomacy/DeviceTree.scala index 04c468f2..b27bb02f 100644 --- a/src/main/scala/diplomacy/DeviceTree.scala +++ b/src/main/scala/diplomacy/DeviceTree.scala @@ -1,9 +1,8 @@ // See LICENSE.SiFive for license details. -package diplomacy +package freechips.rocketchip.diplomacy -import Chisel._ -import config._ +import freechips.rocketchip.config.Field import sys.process._ import java.io.{ByteArrayInputStream, ByteArrayOutputStream} diff --git a/src/main/scala/diplomacy/JSON.scala b/src/main/scala/diplomacy/JSON.scala index 448e7b42..c8d2c42b 100644 --- a/src/main/scala/diplomacy/JSON.scala +++ b/src/main/scala/diplomacy/JSON.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package diplomacy +package freechips.rocketchip.diplomacy import scala.collection.immutable.SortedMap diff --git a/src/main/scala/diplomacy/LazyModule.scala b/src/main/scala/diplomacy/LazyModule.scala index 5fe14545..4823f98f 100644 --- a/src/main/scala/diplomacy/LazyModule.scala +++ b/src/main/scala/diplomacy/LazyModule.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package diplomacy +package freechips.rocketchip.diplomacy import Chisel._ -import config._ import chisel3.experimental.{BaseModule, RawModule, MultiIOModule} import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo} +import freechips.rocketchip.config.Parameters abstract class LazyModule()(implicit val p: Parameters) { diff --git a/src/main/scala/diplomacy/Monitor.scala b/src/main/scala/diplomacy/Monitor.scala index eacddb7b..5a499687 100644 --- a/src/main/scala/diplomacy/Monitor.scala +++ b/src/main/scala/diplomacy/Monitor.scala @@ -1,10 +1,9 @@ // See LICENSE.SiFive for license details. -package diplomacy +package freechips.rocketchip.diplomacy -import Chisel._ import chisel3.internal.sourceinfo.{SourceInfo, SourceLine} -import config._ +import freechips.rocketchip.config.Parameters abstract class MonitorBase(implicit sourceInfo: SourceInfo, p: Parameters) extends LazyModule()(p) { override val module: LazyModuleImp diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 4f4f957e..1a04d33f 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package diplomacy +package freechips.rocketchip.diplomacy import Chisel._ -import config._ -import util.HeterogeneousBag -import scala.collection.mutable.ListBuffer import chisel3.internal.sourceinfo.SourceInfo +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.util.HeterogeneousBag +import scala.collection.mutable.ListBuffer // DI = Downwards flowing Parameters received on the inner side of the node // UI = Upwards flowing Parameters generated by the inner side of the node diff --git a/src/main/scala/diplomacy/Parameters.scala b/src/main/scala/diplomacy/Parameters.scala index 21e7ef81..c641116c 100644 --- a/src/main/scala/diplomacy/Parameters.scala +++ b/src/main/scala/diplomacy/Parameters.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package diplomacy +package freechips.rocketchip.diplomacy import Chisel._ diff --git a/src/main/scala/diplomacy/Resources.scala b/src/main/scala/diplomacy/Resources.scala index cbccb1ff..6a48e667 100644 --- a/src/main/scala/diplomacy/Resources.scala +++ b/src/main/scala/diplomacy/Resources.scala @@ -1,9 +1,8 @@ // See LICENSE.SiFive for license details. -package diplomacy +package freechips.rocketchip.diplomacy -import Chisel._ -import config._ +import Chisel.log2Ceil import scala.collection.immutable.{ListMap,SortedMap} sealed trait ResourceValue diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index 5b9d4944..64219a1c 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -1,6 +1,7 @@ // See LICENSE.SiFive for license details. -import Chisel._ +package freechips.rocketchip + import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo} package object diplomacy diff --git a/src/main/scala/groundtest/BusMasterTest.scala b/src/main/scala/groundtest/BusMasterTest.scala deleted file mode 100644 index 998a9c32..00000000 --- a/src/main/scala/groundtest/BusMasterTest.scala +++ /dev/null @@ -1,116 +0,0 @@ -// See LICENSE.SiFive for license details. - -package groundtest - -import Chisel._ -import uncore.tilelink._ -import uncore.agents._ -import uncore.coherence.{InnerTLId, OuterTLId} -import util._ -import rocketchip._ -import config._ - -/** - * An example bus mastering devices that writes some preset data to memory. - * When it receives an MMIO put request, it starts writing out the data. - * When it receives an MMIO get request, it responds with the progress of - * the write. A grant data of 1 means it is still writing, grant data 0 - * means it has finished. - */ -class ExampleBusMaster(implicit val p: Parameters) extends Module - with HasTileLinkParameters { - val mmioParams = p.alterPartial({ case TLId => p(InnerTLId) }) - val memParams = p.alterPartial({ case TLId => p(OuterTLId) }) - val memStart = p(ExtMem).base - val memStartBlock = memStart >> p(CacheBlockOffsetBits) - - val io = new Bundle { - val mmio = new ClientUncachedTileLinkIO()(mmioParams).flip - val mem = new ClientUncachedTileLinkIO()(memParams) - } - - val s_idle :: s_put :: s_resp :: Nil = Enum(Bits(), 3) - val state = Reg(init = s_idle) - val send_resp = Reg(init = Bool(false)) - val r_acq = Reg(new AcquireMetadata) - - io.mmio.acquire.ready := !send_resp - io.mmio.grant.valid := send_resp - io.mmio.grant.bits := Grant( - is_builtin_type = Bool(true), - g_type = r_acq.getBuiltInGrantType(), - client_xact_id = r_acq.client_xact_id, - manager_xact_id = UInt(0), - addr_beat = r_acq.addr_beat, - data = Mux(state === s_idle, UInt(0), UInt(1))) - - when (io.mmio.acquire.fire()) { - send_resp := Bool(true) - r_acq := io.mmio.acquire.bits - when (state === s_idle && io.mmio.acquire.bits.hasData()) { state := s_put } - } - when (io.mmio.grant.fire()) { send_resp := Bool(false) } - - val (put_beat, put_done) = Counter(io.mem.acquire.fire(), tlDataBeats) - when (put_done) { state := s_resp } - when (io.mem.grant.fire()) { state := s_idle } - - io.mem.acquire.valid := state === s_put - io.mem.acquire.bits := PutBlock( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock), - addr_beat = put_beat, - data = put_beat) - io.mem.grant.ready := state === s_resp -} - -class BusMasterTest(implicit p: Parameters) extends GroundTest()(p) - with HasTileLinkParameters { - val (s_idle :: s_req_start :: s_resp_start :: s_req_poll :: s_resp_poll :: - s_req_check :: s_resp_check :: s_done :: Nil) = Enum(Bits(), 8) - val state = Reg(init = s_idle) - - val busMasterBlock = p(ExtBus).base >> p(CacheBlockOffsetBits) - val start_acq = Put( - client_xact_id = UInt(0), - addr_block = UInt(busMasterBlock), - addr_beat = UInt(0), - data = UInt(1)) - val poll_acq = Get( - client_xact_id = UInt(0), - addr_block = UInt(busMasterBlock), - addr_beat = UInt(0)) - val check_acq = GetBlock( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock)) - - val acq = io.mem.head.acquire - val gnt = io.mem.head.grant - - acq.valid := state.isOneOf(s_req_start, s_req_poll, s_req_check) - acq.bits := MuxLookup(state, check_acq, Seq( - s_req_start -> start_acq, - s_req_poll -> poll_acq)) - gnt.ready := state.isOneOf(s_resp_start, s_resp_poll, s_resp_check) - - val (get_beat, get_done) = Counter( - state === s_resp_check && gnt.valid, tlDataBeats) - - when (state === s_idle) { state := s_req_start } - when (state === s_req_start && acq.ready) { state := s_resp_start } - when (state === s_resp_start && gnt.valid) { state := s_req_poll } - when (state === s_req_poll && acq.ready) { state := s_resp_poll } - when (state === s_resp_poll && gnt.valid) { - when (gnt.bits.data === UInt(0)) { - state := s_req_check - } .otherwise { state := s_req_poll } - } - when (state === s_req_check && acq.ready) { state := s_resp_check } - when (get_done) { state := s_done } - - io.status.finished := state === s_done - - assert(state =/= s_resp_check || !gnt.valid || - gnt.bits.data === get_beat, - "BusMasterTest: data does not match") -} diff --git a/src/main/scala/groundtest/CacheFillTest.scala b/src/main/scala/groundtest/CacheFillTest.scala deleted file mode 100644 index 0ca70b7a..00000000 --- a/src/main/scala/groundtest/CacheFillTest.scala +++ /dev/null @@ -1,56 +0,0 @@ -// See LICENSE.SiFive for license details. -// See LICENSE.Berkeley for license details. - -package groundtest - -import Chisel._ -import coreplex.CacheBlockBytes -import uncore.tilelink._ -import uncore.constants._ -import uncore.util._ -import util._ -import config._ - -class CacheFillTest(implicit p: Parameters) extends GroundTest()(p) - with HasTileLinkParameters { - //val l2Config = p(CacheName("L2")) - //val capacityKb = l2Config.nSets * l2Config.nWays * l2Config.rowBits / (1024*8) - val capacityKb = 1024 // TODO - val nblocks = capacityKb * 1024 / p(CacheBlockBytes) - val s_start :: s_prefetch :: s_retrieve :: s_finished :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_start) - - val active = state.isOneOf(s_prefetch, s_retrieve) - - val xact_pending = Reg(init = UInt(0, tlMaxClientXacts)) - val xact_id = PriorityEncoder(~xact_pending) - - val (req_block, round_done) = Counter(io.mem.head.acquire.fire(), nblocks) - - io.mem.head.acquire.valid := active && !xact_pending.andR - io.mem.head.acquire.bits := Mux(state === s_prefetch, - GetPrefetch(xact_id, UInt(memStartBlock) + req_block), - GetBlock(xact_id, UInt(memStartBlock) + req_block)) - io.mem.head.grant.ready := xact_pending.orR - - def add_pending(acq: DecoupledIO[Acquire]): UInt = - Mux(acq.fire(), UIntToOH(acq.bits.client_xact_id), UInt(0)) - - def remove_pending(gnt: DecoupledIO[Grant]): UInt = { - val last_grant = !gnt.bits.hasMultibeatData() || - gnt.bits.addr_beat === UInt(tlDataBeats - 1) - ~Mux(gnt.fire() && last_grant, UIntToOH(gnt.bits.client_xact_id), UInt(0)) - } - - xact_pending := (xact_pending | - add_pending(io.mem.head.acquire)) & - remove_pending(io.mem.head.grant) - - when (state === s_start) { state := s_prefetch } - when (state === s_prefetch && round_done) { state := s_retrieve } - when (state === s_retrieve && round_done) { state := s_finished } - - io.status.finished := (state === s_finished) - io.status.timeout.valid := Bool(false) - io.status.error.valid := Bool(false) -} diff --git a/src/main/scala/groundtest/Comparator.scala b/src/main/scala/groundtest/Comparator.scala deleted file mode 100644 index 5f69b597..00000000 --- a/src/main/scala/groundtest/Comparator.scala +++ /dev/null @@ -1,394 +0,0 @@ -// See LICENSE.SiFive for license details. - -package groundtest - -import Chisel._ -import uncore.tilelink._ -import uncore.constants._ -import junctions._ -import rocket._ -import util.Timer -import scala.util.Random -import config._ -import util._ - -case class ComparatorParameters( - targets: Seq[Long], - width: Int, - operations: Int, - atomics: Boolean, - prefetches: Boolean) -case object ComparatorKey extends Field[ComparatorParameters] - -trait HasComparatorParameters { - implicit val p: Parameters - val comparatorParams = p(ComparatorKey) - val targets = comparatorParams.targets - val nTargets = targets.size - val targetWidth = comparatorParams.width - val nOperations = comparatorParams.operations - val atomics = comparatorParams.atomics - val prefetches = comparatorParams.prefetches -} - -object LFSR64 -{ - private var counter = 0 - private def next: Int = { - counter += 1 - counter - } - - def apply(increment: Bool = Bool(true), seed: Int = next): UInt = - { - val wide = 64 - val lfsr = RegInit(UInt((seed * 0xDEADBEEFCAFEBAB1L) >>> 1, width = wide)) - val xor = lfsr(0) ^ lfsr(1) ^ lfsr(3) ^ lfsr(4) - when (increment) { lfsr := Cat(xor, lfsr(wide-1,1)) } - lfsr - } -} - -object NoiseMaker -{ - def apply(wide: Int, increment: Bool = Bool(true)): UInt = { - val lfsrs = Seq.fill((wide+63)/64) { LFSR64(increment) } - Cat(lfsrs)(wide-1,0) - } -} - -object MaskMaker -{ - def apply(wide: Int, bits: UInt): UInt = - Vec.tabulate(wide) {UInt(_) < bits} .asUInt -} - -class ComparatorSource(implicit val p: Parameters) extends Module - with HasComparatorParameters - with HasTileLinkParameters -{ - val io = new Bundle { - val out = Decoupled(new Acquire) - val finished = Bool(OUTPUT) - } - - // Output exactly nOperations of Acquires - val finished = RegInit(Bool(false)) - val valid = RegInit(Bool(false)) - - valid := Bool(true) - - io.finished := finished - io.out.valid := !finished && valid - - // Generate random operand sizes - val inc = io.out.fire() - val raw_operand_size = NoiseMaker(2, inc) | UInt(0, M_SZ) - val max_operand_size = UInt(log2Up(tlDataBytes)) - val get_operand_size = Mux(raw_operand_size > max_operand_size, max_operand_size, raw_operand_size) - val atomic_operand_size = UInt(2) + NoiseMaker(1, inc) // word or dword - - // Generate random, but valid addr_bytes - val raw_addr_byte = NoiseMaker(tlByteAddrBits, inc) - val get_addr_byte = raw_addr_byte & ~MaskMaker(tlByteAddrBits, get_operand_size) - val atomic_addr_byte = raw_addr_byte & ~MaskMaker(tlByteAddrBits, atomic_operand_size) - - // Only allow some of the possible choices (M_XA_MAXU untested) - val atomic_opcode = MuxLookup(NoiseMaker(3, inc), M_XA_SWAP, Array( - UInt("b000") -> M_XA_ADD, - UInt("b001") -> M_XA_XOR, - UInt("b010") -> M_XA_OR, - UInt("b011") -> M_XA_AND, - UInt("b100") -> M_XA_MIN, - UInt("b101") -> M_XA_MAX, - UInt("b110") -> M_XA_MINU, - UInt("b111") -> M_XA_SWAP)) - - // Addr_block range - val addr_block_mask = MaskMaker(tlBlockAddrBits, UInt(targetWidth-tlBeatAddrBits-tlByteAddrBits)) - - // Generate some random values - val addr_block = NoiseMaker(tlBlockAddrBits, inc) & addr_block_mask - val addr_beat = NoiseMaker(tlBeatAddrBits, inc) - val wmask = NoiseMaker(tlDataBytes, inc) - val data = NoiseMaker(tlDataBits, inc) - val client_xact_id = UInt(0) // filled by Client - - // Random transactions - val get = Get(client_xact_id, addr_block, addr_beat, get_addr_byte, get_operand_size, Bool(false)) - val getBlock = GetBlock(client_xact_id, addr_block) - val put = Put(client_xact_id, addr_block, addr_beat, data, Some(wmask)) - val putBlock = PutBlock(client_xact_id, addr_block, UInt(0), data) - val putAtomic = if (atomics) - PutAtomic(client_xact_id, addr_block, addr_beat, - atomic_addr_byte, atomic_opcode, atomic_operand_size, data) - else put - val putPrefetch = if (prefetches) - PutPrefetch(client_xact_id, addr_block) - else put - val getPrefetch = if (prefetches) - GetPrefetch(client_xact_id, addr_block) - else get - val a_type_sel = NoiseMaker(3, inc) - - // We must initially putBlock all of memory to have a consistent starting state - val final_addr_block = addr_block_mask + UInt(1) - val wipe_addr_block = RegInit(UInt(0, width = tlBlockAddrBits)) - val done_wipe = wipe_addr_block === final_addr_block - - io.out.bits := Mux(!done_wipe, - // Override whatever else we were going to do if we are wiping - PutBlock(client_xact_id, wipe_addr_block, UInt(0), data), - // Generate a random a_type - MuxLookup(a_type_sel, get, Array( - UInt("b000") -> get, - UInt("b001") -> getBlock, - UInt("b010") -> put, - UInt("b011") -> putBlock, - UInt("b100") -> putAtomic, - UInt("b101") -> getPrefetch, - UInt("b110") -> putPrefetch))) - - val idx = Reg(init = UInt(0, log2Up(nOperations))) - when (io.out.fire()) { - when (idx === UInt(nOperations - 1)) { finished := Bool(true) } - when (!done_wipe) { - printf("[acq %d]: PutBlock(addr_block = %x, data = %x)\n", - idx, wipe_addr_block, data) - wipe_addr_block := wipe_addr_block + UInt(1) - } .otherwise { - switch (a_type_sel) { - is (UInt("b000")) { - printf("[acq %d]: Get(addr_block = %x, addr_beat = %x, addr_byte = %x, op_size = %x)\n", - idx, addr_block, addr_beat, get_addr_byte, get_operand_size) - } - is (UInt("b001")) { - printf("[acq %d]: GetBlock(addr_block = %x)\n", idx, addr_block) - } - is (UInt("b010")) { - printf("[acq %d]: Put(addr_block = %x, addr_beat = %x, data = %x, wmask = %x)\n", - idx, addr_block, addr_beat, data, wmask) - } - is (UInt("b011")) { - printf("[acq %d]: PutBlock(addr_block = %x, data = %x)\n", idx, addr_block, data) - } - is (UInt("b100")) { - if (atomics) { - printf("[acq %d]: PutAtomic(addr_block = %x, addr_beat = %x, addr_byte = %x, " + - "opcode = %x, op_size = %x, data = %x)\n", - idx, addr_block, addr_beat, atomic_addr_byte, - atomic_opcode, atomic_operand_size, data) - } else { - printf("[acq %d]: Put(addr_block = %x, addr_beat = %x, data = %x, wmask = %x)\n", - idx, addr_block, addr_beat, data, wmask) - } - } - is (UInt("b101")) { - if (prefetches) { - printf("[acq %d]: GetPrefetch(addr_block = %x)\n", idx, addr_block) - } else { - printf("[acq %d]: Get(addr_block = %x, addr_beat = %x, addr_byte = %x, op_size = %x)\n", - idx, addr_block, addr_beat, get_addr_byte, get_operand_size) - } - } - is (UInt("b110")) { - if (prefetches) { - printf("[acq %d]: PutPrefetch(addr_block = %x)\n", idx, addr_block) - } else { - printf("[acq %d]: Put(addr_block = %x, addr_beat = %x, data = %x, wmask = %x)\n", - idx, addr_block, addr_beat, data, wmask) - } - } - is (UInt("b111")) { - printf("[acq %d]: Get(addr_block = %x, addr_beat = %x, addr_byte = %x, op_size = %x)\n", - idx, addr_block, addr_beat, get_addr_byte, get_operand_size) - } - } - } - idx := idx + UInt(1) - } -} - -class ComparatorClient(val target: Long)(implicit val p: Parameters) extends Module - with HasComparatorParameters - with HasTileLinkParameters -{ - val io = new Bundle { - val in = Decoupled(new Acquire).flip - val tl = new ClientUncachedTileLinkIO() - val out = Decoupled(new Grant) - val finished = Bool(OUTPUT) - val timeout = Bool(OUTPUT) - } - - val xacts = tlMaxClientXacts - val offset = (UInt(target) >> UInt(tlBeatAddrBits+tlByteAddrBits)) - - // Track the status of inflight requests - val issued = RegInit(Vec.fill(xacts) {Bool(false)}) - val ready = RegInit(Vec.fill(xacts) {Bool(false)}) - val result = Reg(Vec(xacts, new Grant)) - - val buffer = Queue(io.in, xacts) - val queue = Module(new Queue(io.tl.acquire.bits.client_xact_id, xacts)) - - val isMultiOut = buffer.bits.hasMultibeatData() - val isMultiIn = io.tl.grant.bits.hasMultibeatData() - - val beatOut = RegInit(UInt(0, width = tlBeatAddrBits)) - val lastBeat = UInt(tlDataBeats-1) - val isFirstBeatOut= Mux(isMultiOut, beatOut === UInt(0), Bool(true)) - val isLastBeatOut = Mux(isMultiOut, beatOut === lastBeat, Bool(true)) - val isLastBeatIn = Mux(isMultiIn, io.tl.grant.bits.addr_beat === lastBeat, Bool(true)) - - // Potentially issue a request, using a free xact id - // NOTE: we may retract valid and change xact_id on a !ready (allowed by spec) - val allow_acq = NoiseMaker(1)(0) && issued.map(!_).reduce(_ || _) - val xact_id = PriorityEncoder(issued.map(!_)) holdUnless isFirstBeatOut - buffer.ready := allow_acq && io.tl.acquire.ready && isLastBeatOut - io.tl.acquire.valid := allow_acq && buffer.valid - io.tl.acquire.bits := buffer.bits - io.tl.acquire.bits.addr_block := buffer.bits.addr_block + offset - io.tl.acquire.bits.client_xact_id := xact_id - when (isMultiOut) { - val dataOut = (buffer.bits.data << beatOut) + buffer.bits.data // mix the data up a bit - io.tl.acquire.bits.addr_beat := beatOut - io.tl.acquire.bits.data := dataOut - } - - when (io.tl.acquire.fire()) { - issued(xact_id) := isLastBeatOut - when (isMultiOut) { beatOut := beatOut + UInt(1) } - } - - // Remember the xact ID so we can return results in-order - queue.io.enq.valid := io.tl.acquire.fire() && isLastBeatOut - queue.io.enq.bits := xact_id - assert (queue.io.enq.ready || !queue.io.enq.valid) // should be big enough - - // Capture the results from the manager - io.tl.grant.ready := NoiseMaker(1)(0) - when (io.tl.grant.fire()) { - val id = io.tl.grant.bits.client_xact_id - assert (!ready(id)) // got same xact_id twice? - ready(id) := isLastBeatIn - result(id) := io.tl.grant.bits - } - - // Bad xact_id returned if ready but not issued! - assert ((ready zip issued) map {case (r,i) => i || !r} reduce (_ && _)) - - // When we have the next grant result, send it to the sink - val next_id = queue.io.deq.bits - queue.io.deq.ready := io.out.ready && ready(next_id) // TODO: only compares last getBlock - io.out.valid := queue.io.deq.valid && ready(next_id) - io.out.bits := result(queue.io.deq.bits) - - when (io.out.fire()) { - ready(next_id) := Bool(false) - issued(next_id) := Bool(false) - } - - io.finished := !buffer.valid && !issued.reduce(_ || _) - - val (idx, acq_done) = Counter( - io.tl.acquire.fire() && io.tl.acquire.bits.last(), nOperations) - - val timer = Module(new Timer(8192, xacts)) - timer.io.start.valid := io.tl.acquire.fire() && io.tl.acquire.bits.first() - timer.io.start.bits := xact_id - timer.io.stop.valid := io.tl.grant.fire() && io.tl.grant.bits.first() - timer.io.stop.bits := io.tl.grant.bits.client_xact_id - assert(!timer.io.timeout.valid, "Comparator TL client timed out") - io.timeout := timer.io.timeout.valid -} - -class ComparatorSink(implicit val p: Parameters) extends Module - with HasComparatorParameters - with HasTileLinkParameters - with HasGroundTestConstants -{ - val io = new Bundle { - val in = Vec(nTargets, Decoupled(new Grant)).flip - val finished = Bool(OUTPUT) - val error = Valid(UInt(width = errorCodeBits)) - } - - // could use a smaller Queue here, but would couple targets flow controls together - val queues = io.in.map(Queue(_, nOperations)) - - io.finished := queues.map(!_.valid).reduce(_ && _) - val all_valid = queues.map(_.valid).reduce(_ && _) - queues.foreach(_.ready := all_valid) - - val base = queues(0).bits - val idx = Reg(init = UInt(0, log2Up(nOperations))) - - def check(g: Grant) = { - when (g.hasData() && base.data =/= g.data) { - printf("%d: %x =/= %x, g_type = %x\n", idx, base.data, g.data, g.g_type) - } - - val assert_conds = Seq( - g.is_builtin_type, - base.g_type === g.g_type, - base.addr_beat === g.addr_beat || !g.hasData(), - base.data === g.data || !g.hasData()) - - // TL1 likes to duplicate 32-bits into both halves of a 64-bit value - // TL2 doesn't do this, so they compare differently when they are the same - def isDupd(x: UInt) = if (tlDataBytes != 8) Bool(false) else x(31, 0) === x(63, 32) - def safeCompare(x: UInt, y: UInt) = - Mux(!isDupd(x) && !isDupd(y), x === y, x(63,32) === y(63,32) || x(31,0) === y(31,0)) - - assert (g.is_builtin_type, "grant not builtin") - assert (base.g_type === g.g_type, "g_type mismatch") - assert (base.addr_beat === g.addr_beat || !g.hasMultibeatData(), "addr_beat mismatch") - assert (base.data === g.data || !g.hasMultibeatData(), "multibeat data mismatch") - assert (safeCompare(base.data, g.data) || !g.hasData(), "singlebeat data mismatch") - - assert_conds.zipWithIndex.foreach { case (cond, i) => - when (!cond) { - io.error.valid := Bool(true) - io.error.bits := UInt(i) - } - } - } - when (all_valid) { - when (base.hasData()) { - printf("[gnt %d]: g_type = %x, addr_beat = %x, data = %x\n", - idx, base.g_type, base.addr_beat, base.data) - } .otherwise { - printf("[gnt %d]: g_type = %x\n", idx, base.g_type) - } - queues.drop(1).map(_.bits).foreach(check) - idx := idx + UInt(1) - } -} - -class ComparatorCore(implicit p: Parameters) extends GroundTest()(p) - with HasComparatorParameters - with HasTileLinkParameters { - - require (io.mem.size == nTargets) - - val source = Module(new ComparatorSource) - val sink = Module(new ComparatorSink) - val broadcast = Broadcaster(source.io.out, nTargets) - val clients = targets.zipWithIndex.map { case (target, index) => - val client = Module(new ComparatorClient(target)) - client.io.in <> broadcast(index) - io.mem(index) <> client.io.tl - sink.io.in(index) <> client.io.out - client - } - val client_timeouts = clients.map(_.io.timeout) - - io.status.finished := source.io.finished && sink.io.finished && clients.map(_.io.finished).reduce(_ && _) - io.status.timeout.valid := client_timeouts.reduce(_ || _) - io.status.timeout.bits := MuxCase(UInt(0), - client_timeouts.zipWithIndex.map { - case (timeout, i) => (timeout -> UInt(i)) - }) - io.status.error := sink.io.error -} diff --git a/src/main/scala/groundtest/Configs.scala b/src/main/scala/groundtest/Configs.scala index 05ad31e1..90d08e24 100644 --- a/src/main/scala/groundtest/Configs.scala +++ b/src/main/scala/groundtest/Configs.scala @@ -1,161 +1,40 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package groundtest +package freechips.rocketchip.groundtest import Chisel._ -import rocket._ -import diplomacy._ -import uncore.tilelink._ -import uncore.coherence._ -import uncore.agents._ -import uncore.util._ -import tile.TileKey -import junctions._ -import config._ -import coreplex._ -import rocketchip._ +import freechips.rocketchip.chip.{BaseConfig, ExtMem} +import freechips.rocketchip.config.Config +import freechips.rocketchip.coreplex.{CacheBlockBytes, L1toL2Config, WithBufferlessBroadcastHub} +import freechips.rocketchip.rocket.{DCacheParams, PAddrBits} +import freechips.rocketchip.tile.{MaxHartIdBits, XLen} /** Actual testing target Configs */ -class GroundTestConfig extends Config(new WithGroundTestTiles ++ new BaseConfig) +class TraceGenConfig extends Config(new WithTraceGen(List.fill(2){ DCacheParams(nSets = 16, nWays = 1) }) ++ new BaseConfig) -class ComparatorConfig extends Config( - new WithComparator(1) ++ new GroundTestConfig) -class ComparatorL2Config extends Config( - new WithAtomics ++ new WithPrefetches ++ - new WithL2Cache ++ new ComparatorConfig) -class ComparatorBufferlessConfig extends Config( - new WithBufferlessBroadcastHub ++ new ComparatorConfig) -class ComparatorStatelessConfig extends Config( - new WithStatelessBridge ++ new ComparatorConfig) - -class MemtestConfig extends Config(new WithMemtest(1) ++ new GroundTestConfig) -class MemtestL2Config extends Config( - new WithL2Cache ++ new MemtestConfig) -class MemtestBufferlessConfig extends Config( - new WithBufferlessBroadcastHub ++ new MemtestConfig) -class MemtestStatelessConfig extends Config( - new WithStatelessBridge ++ new MemtestConfig) -// Test ALL the things -class FancyMemtestConfig extends Config( - new WithMemtest(2) ++ - new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++ - new WithL2Cache ++ new GroundTestConfig) - -class CacheFillTestConfig extends Config( - new WithNL2Ways(4) ++ new WithL2Capacity(4) ++ - new WithCacheFillTest(1) ++ new WithL2Cache ++ new GroundTestConfig) - -class BroadcastRegressionTestConfig extends Config( - new WithBroadcastRegressionTest(1) ++ new GroundTestConfig) -class BufferlessRegressionTestConfig extends Config( - new WithBufferlessBroadcastHub ++ new BroadcastRegressionTestConfig) -class CacheRegressionTestConfig extends Config( - new WithCacheRegressionTest(1) ++ new WithL2Cache ++ new GroundTestConfig) - -class TraceGenConfig extends Config( - new WithTraceGen(2) ++ new GroundTestConfig) -class TraceGenBufferlessConfig extends Config( - new WithBufferlessBroadcastHub ++ new TraceGenConfig) -class TraceGenL2Config extends Config( - new WithNL2Ways(1) ++ new WithL2Capacity(32 * 64 / 1024) ++ - new WithL2Cache ++ new TraceGenConfig) - -class Edge128BitComparatorConfig extends Config( - new WithEdgeDataBits(128) ++ new ComparatorConfig) -class Edge128BitMemtestConfig extends Config( - new WithEdgeDataBits(128) ++ new MemtestConfig) - -class Edge32BitComparatorConfig extends Config( - new WithEdgeDataBits(32) ++ new ComparatorL2Config) -class Edge32BitMemtestConfig extends Config( - new WithEdgeDataBits(32) ++ new MemtestConfig) +class TraceGenBufferlessConfig extends Config(new WithBufferlessBroadcastHub ++ new TraceGenConfig) /* Composable Configs to set individual parameters */ -class WithGroundTestTiles extends Config((site, here, up) => { - case TileKey => site(GroundTestKey).head - case NTiles => site(GroundTestKey).size -}) - -class WithComparator(n: Int) extends Config((site, here, up) => { - case GroundTestKey => Seq.fill(n) { - GroundTestTileParams(uncached = 2, dcache = None) - } - case BuildGroundTest => - (p: Parameters) => Module(new ComparatorCore()(p)) - case ComparatorKey => ComparatorParameters( - targets = Seq(site(ExtMem).base, testRamAddr), - width = 8, - operations = 1000, - atomics = false, - prefetches = false) -}) - -class WithAtomics extends Config((site, here, up) => { - case ComparatorKey => up(ComparatorKey, site).copy(atomics = true) -}) - -class WithPrefetches extends Config((site, here, up) => { - case ComparatorKey => up(ComparatorKey, site).copy(prefetches = true) -}) - -class WithMemtest(n: Int) extends Config((site, here, up) => { - case GroundTestKey => Seq.fill(n) { - GroundTestTileParams(uncached = 1) - } - case GeneratorKey => TrafficGeneratorParameters( - maxRequests = 128, - startAddress = BigInt(site(ExtMem).base)) - case BuildGroundTest => - (p: Parameters) => Module(new GeneratorTest()(p)) -}) - -class WithCacheFillTest(n: Int) extends Config((site, here, up) => { - case GroundTestKey => Seq.fill(n) { - GroundTestTileParams(uncached = 1, dcache = None) - } - case BuildGroundTest => - (p: Parameters) => Module(new CacheFillTest()(p)) -}) - -class WithBroadcastRegressionTest(n: Int) extends Config((site, here, up) => { - case GroundTestKey => Seq.fill(n) { - GroundTestTileParams(uncached = 1, maxXacts = 3) - } - case BuildGroundTest => - (p: Parameters) => Module(new RegressionTest()(p)) - case GroundTestRegressions => - (p: Parameters) => RegressionTests.broadcastRegressions(p) -}) - -class WithCacheRegressionTest(n: Int) extends Config((site, here, up) => { - case GroundTestKey => Seq.fill(n) { - GroundTestTileParams(uncached = 1, maxXacts = 5) - } - case BuildGroundTest => - (p: Parameters) => Module(new RegressionTest()(p)) - case GroundTestRegressions => - (p: Parameters) => RegressionTests.cacheRegressions(p) -}) - -class WithTraceGen(n: Int) extends Config((site, here, up) => { - case GroundTestKey => Seq.fill(n) { - GroundTestTileParams(dcache = Some(DCacheParams(nSets = 16, nWays = 1))) - } - case BuildGroundTest => - (p: Parameters) => Module(new GroundTestTraceGenerator()(p)) - case GeneratorKey => TrafficGeneratorParameters( - maxRequests = 8192, - startAddress = 0) - case AddressBag => { - val nSets = 2 - val nWays = 1 - val blockOffset = site(CacheBlockOffsetBits) - val nBeats = site(CacheBlockBytes)/site(L1toL2Config).beatBytes - List.tabulate(4 * nWays) { i => - Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) } - }.flatten - } +class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) extends Config((site, here, up) => { + case GroundTestTilesKey => params.map { dcp => TraceGenParams( + dcache = Some(dcp), + wordBits = site(XLen), + addrBits = site(PAddrBits), + addrBag = { + val nSets = 2 + val nWays = 1 + val blockOffset = log2Up(site(CacheBlockBytes)) + val nBeats = site(CacheBlockBytes)/site(L1toL2Config).beatBytes + List.tabulate(4 * nWays) { i => + Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) } + }.flatten + }, + maxRequests = nReqs, + memStart = site(ExtMem).base, + numGens = params.size) + } + case MaxHartIdBits => log2Up(params.size) }) diff --git a/src/main/scala/groundtest/Coreplex.scala b/src/main/scala/groundtest/Coreplex.scala index bfd6d887..6ab78ca0 100644 --- a/src/main/scala/groundtest/Coreplex.scala +++ b/src/main/scala/groundtest/Coreplex.scala @@ -1,44 +1,27 @@ // See LICENSE.SiFive for license details. -package groundtest +package freechips.rocketchip.groundtest import Chisel._ -import config._ -import diplomacy._ -import coreplex._ -import rocket._ -import tile._ -import uncore.agents._ -import uncore.coherence._ -import uncore.devices._ -import uncore.tilelink._ -import uncore.tilelink2._ -import uncore.util._ + +import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.tile._ + import scala.math.max case object TileId extends Field[Int] class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex { - val tiles = List.tabulate(p(NTiles)) { i => - LazyModule(new GroundTestTile()(p.alter { (site, here, up) => { - case TileId => i - case CacheBlockOffsetBits => log2Up(site(CacheBlockBytes)) - case AmoAluOperandBits => site(XLen) + val tileParams = p(GroundTestTilesKey) + val tiles = tileParams.zipWithIndex.map { case(c, i) => LazyModule( + c.build(i, p.alterPartial { + case TileKey => c case SharedMemoryTLEdge => tile_splitter.node.edgesIn(0) - case TLId => "L1toL2" - case TLKey("L1toL2") => - TileLinkParameters( - coherencePolicy = new MESICoherence(new NullRepresentation(site(NTiles))), - nManagers = site(BankedL2Config).nBanks + 1, - nCachingClients = 1, - nCachelessClients = 1, - maxClientXacts = site(GroundTestKey).map(_.maxXacts).reduce(max(_, _)), - maxClientsPerPort = site(GroundTestKey).map(_.uncached).sum, - maxManagerXacts = 8, - dataBeats = (8 * site(CacheBlockBytes)) / site(XLen), - dataBits = site(CacheBlockBytes)*8) - }})) - } + }) + )} val fixer = LazyModule(new TLFIFOFixer) tile_splitter.node :=* fixer.node @@ -55,5 +38,9 @@ class GroundTestCoreplexBundle[+L <: GroundTestCoreplex](_outer: L) extends Base } class GroundTestCoreplexModule[+L <: GroundTestCoreplex, +B <: GroundTestCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) { - io.success := outer.tiles.map(_.module.io.success).reduce(_&&_) + + outer.tiles.zipWithIndex.map { case(t, i) => t.module.io.hartid := UInt(i) } + + val status = DebugCombiner(outer.tiles.map(_.module.io.status)) + io.success := status.finished } diff --git a/src/main/scala/groundtest/DummyPTW.scala b/src/main/scala/groundtest/DummyPTW.scala index 05b1532e..759a735e 100644 --- a/src/main/scala/groundtest/DummyPTW.scala +++ b/src/main/scala/groundtest/DummyPTW.scala @@ -1,13 +1,14 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package groundtest +package freechips.rocketchip.groundtest import Chisel._ -import config._ -import rocket._ -import tile._ -import util.ParameterizedBundle + +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tile.CoreModule +import freechips.rocketchip.util.ParameterizedBundle class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { val io = new Bundle { diff --git a/src/main/scala/groundtest/Generator.scala b/src/main/scala/groundtest/Generator.scala index ffd1c74c..f92910bc 100644 --- a/src/main/scala/groundtest/Generator.scala +++ b/src/main/scala/groundtest/Generator.scala @@ -1,8 +1,10 @@ // See LICENSE.SiFive for license details. -package groundtest +package freechips.rocketchip.groundtest -object Generator extends util.GeneratorApp { +import freechips.rocketchip.util.GeneratorApp + +object Generator extends GeneratorApp { val longName = names.topModuleProject + "." + names.configs generateFirrtl generateTestSuiteMakefrags // TODO: Needed only for legacy make targets diff --git a/src/main/scala/groundtest/Package.scala b/src/main/scala/groundtest/Package.scala index a5c79e12..c7f5f540 100644 --- a/src/main/scala/groundtest/Package.scala +++ b/src/main/scala/groundtest/Package.scala @@ -1,5 +1,9 @@ // See LICENSE.SiFive for license details. +package freechips.rocketchip + package object groundtest { val testRamAddr = 0x10000 + val timeoutCodeBits = 4 + val errorCodeBits = 4 } diff --git a/src/main/scala/groundtest/Regression.scala b/src/main/scala/groundtest/Regression.scala deleted file mode 100644 index 935da208..00000000 --- a/src/main/scala/groundtest/Regression.scala +++ /dev/null @@ -1,789 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package groundtest - -import Chisel._ -import uncore.tilelink._ -import uncore.constants._ -import uncore.util._ -import util._ -import rocket._ -import rocketchip._ -import config._ - -class RegressionIO(implicit val p: Parameters) extends ParameterizedBundle()(p) { - val start = Bool(INPUT) - val cache = new HellaCacheIO - val mem = new ClientUncachedTileLinkIO - val finished = Bool(OUTPUT) - val errored = Bool(OUTPUT) -} - -abstract class Regression(implicit val p: Parameters) - extends Module with HasTileLinkParameters { - val memStart = p(ExtMem).base - val memStartBlock = memStart >> p(CacheBlockOffsetBits) - val io = new RegressionIO - - def disableCache() { - io.cache.req.valid := Bool(false) - io.cache.req.bits.addr := UInt(memStart) - io.cache.req.bits.typ := UInt(0) - io.cache.req.bits.cmd := M_XRD - io.cache.req.bits.tag := UInt(0) - io.cache.req.bits.data := Bits(0) - io.cache.req.bits.phys := Bool(true) - io.cache.invalidate_lr := Bool(false) - } - - def disableMem() { - io.mem.acquire.valid := Bool(false) - io.mem.grant.ready := Bool(false) - } -} - -/** - * This was a bug in which the TileLinkIONarrower logic screwed up - * when a PutBlock request and a narrow Get request are sent to it at the - * same time. Repeating this sequence enough times will cause a queue to - * get filled up and deadlock the system. - */ -class IOGetAfterPutBlockRegression(implicit p: Parameters) extends Regression()(p) { - val nRuns = 7 - val run = Reg(init = UInt(0, log2Up(nRuns + 1))) - - val (put_beat, put_done) = Counter( - io.mem.acquire.fire() && io.mem.acquire.bits.hasData(), tlDataBeats) - - val started = Reg(init = Bool(false)) - val put_sent = Reg(init = Bool(false)) - val get_sent = Reg(init = Bool(false)) - val put_acked = Reg(init = Bool(false)) - val get_acked = Reg(init = Bool(false)) - val both_acked = put_acked && get_acked - - when (!started && io.start) { started := Bool(true) } - - io.mem.acquire.valid := !put_sent && started - io.mem.acquire.bits := PutBlock( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock), - addr_beat = put_beat, - data = UInt(0)) - io.mem.grant.ready := Bool(true) - - io.cache.req.valid := !get_sent && started - io.cache.req.bits.addr := UInt(testRamAddr) - io.cache.req.bits.typ := MT_WU - io.cache.req.bits.cmd := M_XRD - io.cache.req.bits.tag := UInt(0) - io.cache.invalidate_lr := Bool(false) - - when (put_done) { put_sent := Bool(true) } - when (io.cache.req.fire()) { get_sent := Bool(true) } - when (io.mem.grant.fire()) { put_acked := Bool(true) } - when (io.cache.resp.valid) { get_acked := Bool(true) } - - when (both_acked) { - when (run < UInt(nRuns - 1)) { - put_sent := Bool(false) - get_sent := Bool(false) - } - put_acked := Bool(false) - get_acked := Bool(false) - run := run + UInt(1) - } - - io.finished := (run === UInt(nRuns)) -} - -/* This was a bug with merging two PutBlocks to the same address in the L2. - * The transactor would start accepting beats of the second transaction but - * acknowledge both of them when the first one finished. - * This caused the state to go funky since the next time around it would - * start the put in the middle */ -class PutBlockMergeRegression(nSets: Int)(implicit p: Parameters) - extends Regression()(p) with HasTileLinkParameters { - val s_idle :: s_put :: s_wait :: s_done :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_idle) - - disableCache() - - val addr_blocks = Vec(Seq(0, 0, nSets).map(num => UInt(num + memStartBlock))) - val nSteps = addr_blocks.size - val (acq_beat, acq_done) = Counter(io.mem.acquire.fire(), tlDataBeats) - val (send_cnt, send_done) = Counter(acq_done, nSteps) - val (ack_cnt, ack_done) = Counter(io.mem.grant.fire(), nSteps) - - io.mem.acquire.valid := (state === s_put) - io.mem.acquire.bits := PutBlock( - client_xact_id = send_cnt, - addr_block = addr_blocks(send_cnt), - addr_beat = acq_beat, - data = Cat(send_cnt, acq_beat)) - io.mem.grant.ready := Bool(true) - - when (state === s_idle && io.start) { state := s_put } - when (send_done) { state := s_wait } - when (ack_done) { state := s_done } - - io.finished := (state === s_done) -} - -/* Make sure the L2 does "the right thing" when a put is sent no-alloc but - * the block is already in cache. It should just treat the request as a - * regular allocating put */ -class NoAllocPutHitRegression(implicit p: Parameters) extends Regression()(p) { - val (s_idle :: s_prefetch :: s_put :: s_get :: - s_wait :: s_done :: Nil) = Enum(Bits(), 6) - val state = Reg(init = s_idle) - - val acq = io.mem.acquire.bits - val gnt = io.mem.grant.bits - - val (put_beat, put_done) = Counter(io.mem.acquire.fire() && acq.hasData(), tlDataBeats) - val acked = Reg(init = UInt(0, tlDataBeats + 2)) - - val addr_block = UInt(memStartBlock + 2) - val test_data = UInt(0x3446) - - val prefetch_acq = GetPrefetch( - client_xact_id = UInt(0), - addr_block = addr_block) - val put_acq = PutBlock( - client_xact_id = UInt(1), - addr_block = addr_block, - addr_beat = put_beat, - data = test_data, - alloc = Bool(false)) - val get_acq = GetBlock( - client_xact_id = UInt(2), - addr_block = addr_block) - - io.mem.acquire.valid := state.isOneOf(s_prefetch, s_get, s_put) - io.mem.acquire.bits := MuxCase(get_acq, Seq( - (state === s_prefetch) -> prefetch_acq, - (state === s_put) -> put_acq)) - io.mem.grant.ready := Bool(true) - - when (state === s_idle && io.start) { state := s_prefetch } - when (state === s_prefetch && io.mem.acquire.ready) { state := s_put } - when (put_done) { state := s_get } - when (state === s_get && io.mem.acquire.ready) { state := s_wait } - when (state === s_wait && acked.andR) { state := s_done } - - when (io.mem.grant.fire()) { - switch (gnt.client_xact_id) { - is (UInt(0)) { acked := acked | UInt(1 << tlDataBeats) } - is (UInt(1)) { acked := acked | UInt(1 << (tlDataBeats + 1)) } - is (UInt(2)) { acked := acked | UIntToOH(gnt.addr_beat) } - } - } - - val data_mismatch = io.mem.grant.fire() && gnt.hasData() && gnt.data =/= test_data - assert(!data_mismatch, "NoAllocPutHitRegression: data does not match") - - io.finished := (state === s_done) - io.errored := data_mismatch - - disableCache() -} - -/** Make sure L2 does the right thing when multiple puts are sent for the - * same block, but only the first one has the alloc bit set. */ -class MixedAllocPutRegression(implicit p: Parameters) extends Regression()(p) { - val (s_idle :: s_pf_send :: s_pf_wait :: s_put_send :: s_put_wait :: - s_get_send :: s_get_wait :: s_done :: Nil) = Enum(Bits(), 8) - val state = Reg(init = s_idle) - - /** We have to test two cases: one when the block is already cached - * and one when the block is not yet cached. - * We use prefetching to assure the first case. */ - val test_data = Vec( - UInt("h2222222211111111"), - UInt("h3333333333333333"), - UInt("h4444444444444444"), - UInt("h5555555555555555")) - val test_alloc = Vec(Bool(false), Bool(false), Bool(true), Bool(false)) - val test_block = Vec( - Seq.fill(2) { UInt(memStartBlock + 15) } ++ - Seq.fill(2) { UInt(memStartBlock + 16) }) - val test_beat = Vec(UInt(0), UInt(2), UInt(1), UInt(2)) - - val (put_acq_id, put_acq_done) = Counter( - state === s_put_send && io.mem.acquire.ready, test_data.size) - val (put_gnt_cnt, put_gnt_done) = Counter( - state === s_put_wait && io.mem.grant.valid, test_data.size) - - val (get_acq_id, get_acq_done) = Counter( - state === s_get_send && io.mem.acquire.ready, test_data.size) - val (get_gnt_cnt, get_gnt_done) = Counter( - state === s_get_wait && io.mem.grant.valid, test_data.size) - - val pf_acquire = PutPrefetch( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock + 15)) - - val put_acquire = Put( - client_xact_id = put_acq_id, - addr_block = test_block(put_acq_id), - addr_beat = test_beat(put_acq_id), - data = test_data(put_acq_id), - alloc = test_alloc(put_acq_id)) - - val get_acquire = Get( - client_xact_id = get_acq_id, - addr_block = test_block(get_acq_id), - addr_beat = test_beat(get_acq_id)) - - io.mem.acquire.valid := state.isOneOf(s_pf_send, s_put_send, s_get_send) - io.mem.acquire.bits := MuxLookup(state, pf_acquire, Seq( - s_put_send -> put_acquire, - s_get_send -> get_acquire)) - io.mem.grant.ready := state.isOneOf(s_pf_wait, s_put_wait, s_get_wait) - - when (state === s_idle && io.start) { state := s_pf_send } - when (state === s_pf_send && io.mem.acquire.ready) { state := s_pf_wait } - when (state === s_pf_wait && io.mem.grant.valid) { state := s_put_send } - when (put_acq_done) { state := s_put_wait } - when (put_gnt_done) { state := s_get_send } - when (get_acq_done) { state := s_get_wait } - when (get_gnt_done) { state := s_done } - - io.finished := (state === s_done) - - val data_mismatch = state === s_get_wait && io.mem.grant.fire() && - io.mem.grant.bits.data =/= test_data(io.mem.grant.bits.client_xact_id) - assert(!data_mismatch, "MixedAllocPutRegression: data mismatch") - io.errored := data_mismatch - - disableCache() -} - -/* Make sure each no-alloc put triggers a request to outer memory. - * Unfortunately, there's no way to verify that this works except by looking - * at the waveform */ -class RepeatedNoAllocPutRegression(implicit p: Parameters) extends Regression()(p) { - disableCache() - - val nPuts = 2 - val (put_beat, put_done) = Counter(io.mem.acquire.fire(), tlDataBeats) - val (req_cnt, req_done) = Counter(put_done, nPuts) - - val sending = Reg(init = Bool(false)) - val acked = Reg(init = UInt(0, nPuts)) - - when (!sending && io.start) { sending := Bool(true) } - when (sending && req_done) { sending := Bool(false) } - - io.mem.acquire.valid := sending - io.mem.acquire.bits := PutBlock( - client_xact_id = req_cnt, - addr_block = UInt(memStartBlock + 5), - addr_beat = put_beat, - data = Cat(req_cnt, UInt(0, 8)), - alloc = Bool(false)) - io.mem.grant.ready := Bool(true) - - when (io.mem.grant.fire()) { - acked := acked | UIntToOH(io.mem.grant.bits.client_xact_id) - } - - io.finished := acked.andR -} - -/* Make sure write masking works properly by writing a block of data - * piece by piece */ -class WriteMaskedPutBlockRegression(implicit p: Parameters) extends Regression()(p) { - disableCache() - - val (s_idle :: s_put_send :: s_put_ack :: s_stall :: - s_get_send :: s_get_ack :: s_done :: Nil) = Enum(Bits(), 7) - val state = Reg(init = s_idle) - val post_stall_state = Reg(init = s_idle) - - val gnt = io.mem.grant.bits - val acq = io.mem.acquire.bits - - val stage = Reg(init = UInt(0, 1)) - - val (put_beat, put_block_done) = Counter( - io.mem.acquire.fire() && acq.hasData(), tlDataBeats) - val put_data = UInt(0x30010040, tlDataBits) + (put_beat << UInt(2)) - - val put_acq = PutBlock( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock + 7), - addr_beat = put_beat, - data = Mux(put_beat(0) === stage, put_data, UInt(0)), - wmask = Some(Mux(put_beat(0) === stage, Acquire.fullWriteMask, Bits(0)))) - - val get_acq = GetBlock( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock + 6) + stage) - - io.mem.acquire.valid := state.isOneOf(s_put_send, s_get_send) - io.mem.acquire.bits := Mux(state === s_get_send, get_acq, put_acq) - io.mem.grant.ready := state.isOneOf(s_put_ack, s_get_ack) - - val (get_cnt, get_done) = Counter( - io.mem.grant.fire() && gnt.hasData(), tlDataBeats) - val get_data = UInt(0x30010040, tlDataBits) + (get_cnt << UInt(2)) - - val (stall_cnt, stall_done) = Counter(state === s_stall, 16) - - when (state === s_idle && io.start) { state := s_put_send } - when (put_block_done) { state := s_put_ack } - when (state === s_put_ack && io.mem.grant.valid) { - post_stall_state := s_get_send - state := s_stall - } - when (stall_done) { state := post_stall_state } - when (state === s_get_send && io.mem.acquire.ready) { state := s_get_ack } - when (get_done) { - // do a read in-between the two put-blocks to overwrite the data buffer - when (stage === UInt(0)) { - stage := stage + UInt(1) - post_stall_state := s_put_send - state := s_stall - } .otherwise { state := s_done } - } - - io.finished := (state === s_done) - - val data_mismatch = io.mem.grant.fire() && io.mem.grant.bits.hasData() && - stage =/= UInt(0) && io.mem.grant.bits.data =/= get_data - assert(!data_mismatch, "WriteMaskedPutBlockRegression: data does not match") - io.errored := data_mismatch -} - -/* Make sure a prefetch that hits returns immediately. */ -class PrefetchHitRegression(implicit p: Parameters) extends Regression()(p) { - disableCache() - - val sending = Reg(init = Bool(false)) - val nPrefetches = 2 - val (pf_cnt, pf_done) = Counter(io.mem.acquire.fire(), nPrefetches) - val acked = Reg(init = UInt(0, nPrefetches)) - - val acq_bits = Vec( - PutPrefetch(client_xact_id = UInt(0), addr_block = UInt(memStartBlock + 12)), - GetPrefetch(client_xact_id = UInt(1), addr_block = UInt(memStartBlock + 12))) - - io.mem.acquire.valid := sending - io.mem.acquire.bits := acq_bits(pf_cnt) - io.mem.grant.ready := Bool(true) - - when (io.mem.grant.fire()) { - acked := acked | UIntToOH(io.mem.grant.bits.client_xact_id) - } - - when (!sending && io.start) { sending := Bool(true) } - when (sending && pf_done) { sending := Bool(false) } - - io.finished := acked.andR - io.errored := Bool(false) -} - -/* Test that a writeback will occur by writing nWays + 1 blocks to the same - * set. This assumes that there is only a single cache bank. If we want to - * test multibank configurations, we'll have to think of some other way to - * determine which banks are conflicting */ -class WritebackRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) { - disableCache() - - val addr_blocks = Vec.tabulate(nWays + 1) { i => UInt(memStartBlock + i * nSets) } - val data = Vec.tabulate(nWays + 1) { i => UInt((i + 1) * 1423) } - - val (put_beat, put_done) = Counter( - io.mem.acquire.fire() && io.mem.acquire.bits.hasData(), tlDataBeats) - val (get_beat, get_done) = Counter( - io.mem.grant.fire() && io.mem.grant.bits.hasData(), tlDataBeats) - val (put_cnt, _) = Counter(put_done, nWays + 1) - val (get_cnt, _) = Counter( - io.mem.acquire.fire() && !io.mem.acquire.bits.hasData(), nWays + 1) - val (ack_cnt, ack_done) = Counter( - io.mem.grant.fire() && !io.mem.grant.bits.hasData() || get_done, nWays + 1) - - val s_idle :: s_put :: s_get :: s_done :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_idle) - val sending = Reg(init = Bool(false)) - - io.mem.acquire.valid := sending - io.mem.acquire.bits := Mux(state === s_put, - PutBlock( - client_xact_id = UInt(0), - addr_block = addr_blocks(put_cnt), - addr_beat = put_beat, - data = data(put_cnt)), - GetBlock( - client_xact_id = UInt(0), - addr_block = addr_blocks(get_cnt))) - io.mem.grant.ready := !sending - - when (state === s_idle && io.start) { state := s_put; sending := Bool(true) } - when (put_done || state === s_get && io.mem.acquire.fire()) { - sending := Bool(false) - } - when (get_done && !ack_done || state === s_put && io.mem.grant.fire()) { - sending := Bool(true) - } - when (ack_done) { state := Mux(state === s_put, s_get, s_done) } - - io.finished := (state === s_done) - - val data_mismatch = io.mem.grant.fire() && io.mem.grant.bits.hasData() && - io.mem.grant.bits.data =/= data(ack_cnt) - assert(!data_mismatch, "WritebackRegression: incorrect data") - io.errored := data_mismatch -} - -class ReleaseRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) { - disableMem() - - val blockOffset = p(CacheBlockOffsetBits) - - val startBlock = memStartBlock + 10 - val addr_blocks = Vec.tabulate(nWays + 1) { i => UInt(startBlock + i * nSets) } - val data = Vec.tabulate(nWays + 1) { i => UInt((i + 1) * 1522) } - val (req_idx, req_done) = Counter(io.cache.req.fire(), nWays + 1) - val (resp_idx, resp_done) = Counter(io.cache.resp.valid, nWays + 1) - - val sending = Reg(init = Bool(false)) - val s_idle :: s_write :: s_read :: s_done :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_idle) - - io.cache.req.valid := sending && state.isOneOf(s_write, s_read) - io.cache.req.bits.addr := Cat(addr_blocks(req_idx), UInt(0, blockOffset)) - io.cache.req.bits.typ := MT_D - io.cache.req.bits.cmd := Mux(state === s_write, M_XWR, M_XRD) - io.cache.req.bits.tag := UInt(0) - io.cache.req.bits.data := data(req_idx) - io.cache.req.bits.phys := Bool(true) - io.cache.invalidate_lr := Bool(false) - - when (state === s_idle && io.start) { - sending := Bool(true) - state := s_write - } - - when (resp_done) { state := Mux(state === s_write, s_read, s_done) } - when (io.cache.req.fire()) { sending := Bool(false) } - when (io.cache.resp.valid) { sending := Bool(true) } - - io.finished := (state === s_done) - - val data_mismatch = io.cache.resp.valid && io.cache.resp.bits.has_data && - io.cache.resp.bits.data =/= data(resp_idx) - assert(!data_mismatch, "ReleaseRegression: data mismatch") - io.errored := data_mismatch -} - -class PutBeforePutBlockRegression(implicit p: Parameters) extends Regression()(p) { - val (s_idle :: s_put :: s_putblock :: s_wait :: - s_finished :: Nil) = Enum(Bits(), 5) - val state = Reg(init = s_idle) - - disableCache() - - val (put_block_beat, put_block_done) = Counter( - state === s_putblock && io.mem.acquire.ready, tlDataBeats) - - val put_acquire = Put( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock), - addr_beat = UInt(0), - data = UInt(0), - wmask = Some(UInt((1 << 8) - 1))) - - val put_block_acquire = PutBlock( - client_xact_id = UInt(1), - addr_block = UInt(memStartBlock + 1), - addr_beat = put_block_beat, - data = UInt(0)) - - val put_acked = Reg(init = UInt(0, 2)) - - val (ack_cnt, all_acked) = Counter(io.mem.grant.fire(), 2) - - io.mem.acquire.valid := state.isOneOf(s_put, s_putblock) - io.mem.acquire.bits := Mux(state === s_put, put_acquire, put_block_acquire) - io.mem.grant.ready := (state === s_wait) - - when (state === s_idle && io.start) { state := s_put } - when (state === s_put && io.mem.acquire.ready) { state := s_putblock } - when (put_block_done) { state := s_wait } - when (all_acked) { state := s_finished } - - io.finished := (state === s_finished) - io.errored := Bool(false) -} - -/** - * Make sure that multiple gets to the same line and beat are merged - * correctly, even if it is a cache miss. - */ -class MergedGetRegression(nSets: Int, nWays: Int)(implicit p: Parameters) extends Regression()(p) { - disableCache() - - val (s_idle :: s_put :: s_get :: s_done :: Nil) = Enum(Bits(), 4) - val state = Reg(init = s_idle) - - // Write NWays + 1 different conflicting lines to force an eviction of the first line - val (put_acq_cnt, put_acq_done) = Counter(state === s_put && io.mem.acquire.fire(), nWays + 1) - val (put_gnt_cnt, put_gnt_done) = Counter(state === s_put && io.mem.grant.fire(), nWays + 1) - val put_addr = UInt(memStartBlock) + Cat(put_acq_cnt, UInt(0, log2Up(nSets))) - - val (get_acq_cnt, get_acq_done) = Counter(state === s_get && io.mem.acquire.fire(), 2) - val (get_gnt_cnt, get_gnt_done) = Counter(state === s_get && io.mem.grant.fire(), 2) - val sending = Reg(init = Bool(false)) - - when (state === s_idle && io.start) { state := s_put; sending := Bool(true) } - when (state === s_put) { - when (io.mem.acquire.fire()) { sending := Bool(false) } - when (io.mem.grant.fire()) { sending := Bool(true) } - when (put_gnt_done) { state := s_get } - } - when (state === s_get) { - when (get_acq_done) { sending := Bool(false) } - when (get_gnt_done) { state := s_done } - } - - io.mem.acquire.valid := sending - io.mem.acquire.bits := Mux(state === s_put, - Put( - client_xact_id = UInt(0), - addr_block = put_addr, - addr_beat = UInt(3), - data = UInt("hdabb9321")), - Get( - client_xact_id = get_acq_cnt, - addr_block = UInt(memStartBlock), - addr_beat = UInt(3))) - io.mem.grant.ready := !sending - - val data_mismatch = io.mem.grant.valid && io.mem.grant.bits.hasData() && - io.mem.grant.bits.data =/= UInt("hdabb9321") - assert(!data_mismatch, "RepeatedGetRegression: wrong data back") - - io.finished := state === s_done - io.errored := data_mismatch -} - -/** - * Make sure that multiple puts to the same line and beat are merged - * correctly, even if there is a release from the L1 - */ -class MergedPutRegression(implicit p: Parameters) extends Regression()(p) - with HasTileLinkParameters { - val (s_idle :: s_cache_req :: s_cache_wait :: - s_put :: s_get :: s_done :: Nil) = Enum(Bits(), 6) - val state = Reg(init = s_idle) - - io.cache.req.valid := (state === s_cache_req) - io.cache.req.bits.cmd := M_XWR - io.cache.req.bits.typ := MT_D - io.cache.req.bits.addr := UInt(memStart) - io.cache.req.bits.data := UInt(1) - io.cache.req.bits.tag := UInt(0) - - val sending = Reg(init = Bool(false)) - val delaying = Reg(init = Bool(false)) - val (put_cnt, put_done) = Counter(io.mem.acquire.fire(), tlMaxClientXacts) - val (delay_cnt, delay_done) = Counter(delaying, 8) - val put_acked = Reg(UInt(width = tlMaxClientXacts), init = UInt(0)) - - io.mem.acquire.valid := sending && !delaying - io.mem.acquire.bits := Mux(state === s_put, - Put( - client_xact_id = put_cnt, - addr_block = UInt(memStartBlock), - addr_beat = UInt(0), - data = put_cnt + UInt(2)), - Get( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock), - addr_beat = UInt(0))) - io.mem.grant.ready := Bool(true) - - when (state === s_idle && io.start) { state := s_cache_req } - when (io.cache.req.fire()) { state := s_cache_wait } - when (io.cache.resp.valid) { state := s_put; sending := Bool(true) } - - when (io.mem.acquire.fire()) { - delaying := Bool(true) - when (put_done || state === s_get) { sending := Bool(false) } - } - when (delay_done) { delaying := Bool(false) } - - when (io.mem.grant.fire()) { - when (state === s_put) { - put_acked := put_acked | UIntToOH(io.mem.grant.bits.client_xact_id) - } - when (state === s_get) { state := s_done } - } - - when (state === s_put && put_acked.andR) { - state := s_get - sending := Bool(true) - } - - val expected_data = UInt(2 + tlMaxClientXacts - 1) - val data_mismatch = io.mem.grant.valid && io.mem.grant.bits.hasData() && - io.mem.grant.bits.data =/= expected_data - - assert(!data_mismatch, "MergedPutRegression: data mismatch") - - io.finished := (state === s_done) - io.errored := data_mismatch -} - -class PutAfterReleaseRegression(implicit p: Parameters) extends Regression()(p) { - val (s_idle :: s_cache_req :: s_cache_resp :: - s_write_first_req :: s_delay :: s_write_remaining_req :: s_write_resp :: - s_read_req :: s_read_resp :: s_finished :: Nil) = Enum(Bits(), 10) - val state = Reg(init = s_idle) - - val (delay_cnt, delay_done) = Counter(state === s_delay, 100) - val (write_cnt, write_done) = Counter( - io.mem.acquire.fire() && io.mem.acquire.bits.hasData(), tlDataBeats) - val (read_cnt, read_done) = Counter( - io.mem.grant.fire() && io.mem.grant.bits.hasData(), tlDataBeats) - - when (state === s_idle && io.start) { state := s_cache_req } - when (io.cache.req.fire()) { state := s_cache_resp } - when (state === s_cache_resp && io.cache.resp.valid) { state := s_write_first_req } - when (state === s_write_first_req && io.mem.acquire.ready) { state := s_delay } - when (delay_done) { state := s_write_remaining_req } - when (write_done) { state := s_write_resp } - when (state === s_write_resp && io.mem.grant.valid) { state := s_read_req } - when (state === s_read_req && io.mem.acquire.ready) { state := s_read_resp } - when (read_done) { state := s_finished } - - io.finished := state === s_finished - - io.cache.req.valid := state === s_cache_req - io.cache.req.bits.cmd := M_XWR - io.cache.req.bits.addr := UInt(memStart) - io.cache.req.bits.typ := MT_D - io.cache.req.bits.tag := UInt(0) - io.cache.req.bits.data := UInt(0) - - io.mem.acquire.valid := state.isOneOf(s_write_first_req, s_write_remaining_req, s_read_req) - io.mem.acquire.bits := Mux(state === s_read_req, - GetBlock( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock)), - PutBlock( - client_xact_id = UInt(0), - addr_block = UInt(memStartBlock), - addr_beat = write_cnt, - data = write_cnt + UInt(1))) - io.mem.grant.ready := state.isOneOf(s_write_resp, s_read_resp) - - assert(!io.mem.grant.valid || !io.mem.grant.bits.hasData() || - io.mem.grant.bits.data === read_cnt + UInt(1), - "PutAfterReleaseRegression: data mismatch") -} - -object RegressionTests { - val l1sets = 16 // TODO - val l1ways = 1 // TODO - val l2sets = 32 // TODO - val l2ways = 2 // TODO - def cacheRegressions(implicit p: Parameters) = Seq( - Module(new PutBlockMergeRegression(l2sets)), - Module(new NoAllocPutHitRegression), - Module(new RepeatedNoAllocPutRegression), - Module(new WriteMaskedPutBlockRegression), - Module(new PrefetchHitRegression), - Module(new WritebackRegression(l2sets, l2ways)), - Module(new PutBeforePutBlockRegression), - Module(new MixedAllocPutRegression), - Module(new ReleaseRegression(l1sets, l1ways)), - Module(new MergedGetRegression(l2sets, l2ways)), - Module(new MergedPutRegression)) - def broadcastRegressions(implicit p: Parameters) = Seq( - Module(new IOGetAfterPutBlockRegression), - Module(new WriteMaskedPutBlockRegression), - Module(new PutBeforePutBlockRegression), - Module(new ReleaseRegression(l1sets, l1ways)), - Module(new PutAfterReleaseRegression)) -} - -case object GroundTestRegressions extends Field[Parameters => Seq[Regression]] - -class RegressionTest(implicit p: Parameters) extends GroundTest()(p) { - val regressions = p(GroundTestRegressions)(p) - val regress_idx = Reg(init = UInt(0, log2Up(regressions.size + 1))) - val cur_finished = Wire(init = Bool(false)) - val all_done = (regress_idx === UInt(regressions.size)) - val start = Reg(init = Bool(true)) - - // Some tests randomly backpressure grant; make this safe: - val grant = Queue(io.mem.head.grant, 16) - - // default output values - io.mem.head.acquire.valid := Bool(false) - io.mem.head.acquire.bits := GetBlock( - client_xact_id = UInt(0), - addr_block = UInt(0)) - grant.ready := Bool(false) - io.cache.head.req.valid := Bool(false) - io.cache.head.req.bits.addr := UInt(0) - io.cache.head.req.bits.typ := UInt(log2Ceil(64 / 8)) - io.cache.head.req.bits.cmd := M_XRD - io.cache.head.req.bits.tag := UInt(0) - io.cache.head.req.bits.phys := Bool(true) - io.cache.head.req.bits.data := UInt(0) - io.cache.head.invalidate_lr := Bool(false) - - regressions.zipWithIndex.foreach { case (regress, i) => - val me = regress_idx === UInt(i) - regress.io.start := me && start - regress.io.mem.acquire.ready := io.mem.head.acquire.ready && me - regress.io.mem.grant.valid := grant.valid && me - regress.io.mem.grant.bits := grant.bits - regress.io.cache.req.ready := io.cache.head.req.ready && me - regress.io.cache.resp.valid := io.cache.head.resp.valid && me - regress.io.cache.resp.bits := io.cache.head.resp.bits - - when (me) { - io.mem.head.acquire.valid := regress.io.mem.acquire.valid - io.mem.head.acquire.bits := regress.io.mem.acquire.bits - grant.ready := regress.io.mem.grant.ready - io.cache.head.req.valid := regress.io.cache.req.valid - io.cache.head.req.bits := regress.io.cache.req.bits - io.cache.head.invalidate_lr := regress.io.cache.invalidate_lr - io.status.error.valid := regress.io.errored - io.status.error.bits := UInt(i) - cur_finished := regress.io.finished - } - - when (regress.io.start) { - printf(s"Starting regression ${regress.getClass.getSimpleName}\n") - } - } - - when (cur_finished && !all_done) { - start := Bool(true) - regress_idx := regress_idx + UInt(1) - } - when (start) { start := Bool(false) } - - val timeout = SimpleTimer(5000, start, cur_finished) - assert(!timeout, "Regression timed out") - - io.status.finished := all_done - io.status.timeout.valid := timeout - io.status.timeout.bits := UInt(0) - - assert(!(all_done && grant.valid), - "Getting grant after test completion") - - when (all_done) { - io.status.error.valid := grant.valid - io.status.error.bits := UInt(regressions.size) - } -} diff --git a/src/main/scala/groundtest/Status.scala b/src/main/scala/groundtest/Status.scala new file mode 100644 index 00000000..4601593a --- /dev/null +++ b/src/main/scala/groundtest/Status.scala @@ -0,0 +1,23 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.groundtest + +import Chisel._ +import freechips.rocketchip.util.ValidMux + +class GroundTestStatus extends Bundle { + val finished = Bool(OUTPUT) + val timeout = Valid(UInt(width = 4)) + val error = Valid(UInt(width = 4)) +} + +object DebugCombiner { + def apply(debugs: Seq[GroundTestStatus]): GroundTestStatus = { + val out = Wire(new GroundTestStatus) + out.finished := debugs.map(_.finished).reduce(_ && _) + out.timeout := ValidMux(debugs.map(_.timeout)) + out.error := ValidMux(debugs.map(_.error)) + out + } +} + diff --git a/src/main/scala/groundtest/TestHarness.scala b/src/main/scala/groundtest/TestHarness.scala index 23267af6..a7dd1ef3 100644 --- a/src/main/scala/groundtest/TestHarness.scala +++ b/src/main/scala/groundtest/TestHarness.scala @@ -1,12 +1,11 @@ // See LICENSE.SiFive for license details. -package groundtest +package freechips.rocketchip.groundtest import Chisel._ -import diplomacy._ -import config._ -import rocketchip._ -import util._ + +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy.LazyModule class TestHarness(implicit p: Parameters) extends Module { val io = new Bundle { val success = Bool(OUTPUT) } diff --git a/src/main/scala/groundtest/Tile.scala b/src/main/scala/groundtest/Tile.scala index 61c83c35..a41e8a5a 100644 --- a/src/main/scala/groundtest/Tile.scala +++ b/src/main/scala/groundtest/Tile.scala @@ -1,123 +1,51 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package groundtest +package freechips.rocketchip.groundtest import Chisel._ -import config._ -import coreplex._ -import rocket._ -import tile._ -import uncore.tilelink._ -import uncore.tilelink2._ -import rocketchip.ExtMem -import diplomacy._ -import util.ParameterizedBundle - +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.rocket._ +import freechips.rocketchip.chip._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ import scala.collection.mutable.ListBuffer -case object BuildGroundTest extends Field[Parameters => GroundTest] +trait GroundTestTileParams extends TileParams { + val memStart: BigInt + val maxRequests: Int + val numGens: Int -case class GroundTestTileParams( - uncached: Int = 0, - ptw: Int = 0, - maxXacts: Int = 1, - dcache: Option[DCacheParams] = Some(DCacheParams())) extends TileParams { + def build(i: Int, p: Parameters): GroundTestTile + val icache = None val btb = None val rocc = Nil - val core = rocket.RocketCoreParams(nPMPs = 0) //TODO remove this + val core = RocketCoreParams(nPMPs = 0) //TODO remove this val cached = if(dcache.isDefined) 1 else 0 val dataScratchpadBytes = 0 } -case object GroundTestKey extends Field[Seq[GroundTestTileParams]] -trait HasGroundTestConstants { - val timeoutCodeBits = 4 - val errorCodeBits = 4 +case object GroundTestTilesKey extends Field[Seq[GroundTestTileParams]] + +abstract class GroundTestTile(params: GroundTestTileParams)(implicit p: Parameters) extends BaseTile(params)(p) { + val slave = None + val dcacheOpt = params.dcache.map { dc => HellaCache(0, dc.nMSHRs == 0) } + dcacheOpt.foreach { tileBus.node := _.node } + + override lazy val module = new GroundTestTileModule(this, () => new GroundTestTileBundle(this)) } -trait HasGroundTestParameters { - implicit val p: Parameters - val tileParams = p(GroundTestKey)(p(TileId)) - val nUncached = tileParams.uncached - val nCached = tileParams.cached - val nPTW = tileParams.ptw - val memStart = p(ExtMem).base - val memStartBlock = memStart >> p(CacheBlockOffsetBits) -} - -class GroundTestStatus extends Bundle with HasGroundTestConstants { - val finished = Bool(OUTPUT) - val timeout = Valid(UInt(width = timeoutCodeBits)) - val error = Valid(UInt(width = errorCodeBits)) -} - -class GroundTestIO(implicit val p: Parameters) extends ParameterizedBundle()(p) - with HasGroundTestParameters { - val cache = Vec(nCached, new HellaCacheIO) - val mem = Vec(nUncached, new ClientUncachedTileLinkIO) - val ptw = Vec(nPTW, new TLBPTWIO) +class GroundTestTileBundle[+L <: GroundTestTile](_outer: L) extends BaseTileBundle(_outer) { val status = new GroundTestStatus } -abstract class GroundTest(implicit val p: Parameters) extends Module - with HasGroundTestParameters { - val io = new GroundTestIO -} +class GroundTestTileModule[+L <: GroundTestTile, +B <: GroundTestTileBundle[L]](_outer: L, _io: () => B) extends BaseTileModule(_outer, _io) { -class GroundTestTile(implicit p: Parameters) extends LazyModule - with HasGroundTestParameters { - val slave = None - val dcacheOpt = tileParams.dcache.map { dc => HellaCache(0, dc.nMSHRs == 0) } - val ucLegacy = LazyModule(new TLLegacy) - - val masterNode = TLOutputNode() - dcacheOpt.foreach { masterNode := _.node } - masterNode := TLHintHandler()(ucLegacy.node) - - lazy val module = new LazyModuleImp(this) { - val io = new Bundle { - val out = masterNode.bundleOut - val success = Bool(OUTPUT) - } - - val test = p(BuildGroundTest)(p) - - val ptwPorts = ListBuffer.empty ++= test.io.ptw - val uncachedArbPorts = ListBuffer.empty ++= test.io.mem - - dcacheOpt foreach { dcache => - val dcacheArb = Module(new HellaCacheArbiter(nCached)) - - dcacheArb.io.requestor.zip(test.io.cache).foreach { - case (requestor, cache) => - val dcacheIF = Module(new SimpleHellaCacheIF()) - dcacheIF.io.requestor <> cache - requestor <> dcacheIF.io.cache - } - dcache.module.io.cpu <> dcacheArb.io.mem - - // SimpleHellaCacheIF leaves invalidate_lr dangling, so we wire it to false - dcache.module.io.cpu.invalidate_lr := Bool(false) - - ptwPorts += dcache.module.io.ptw - } - - if (ptwPorts.size > 0) { - val ptw = Module(new DummyPTW(ptwPorts.size)) - ptw.io.requestors <> ptwPorts - } - - if (uncachedArbPorts.isEmpty) { - ucLegacy.module.io.legacy.acquire.valid := Bool(false) - ucLegacy.module.io.legacy.grant.ready := Bool(true) - } else { - val uncachedArb = Module(new ClientUncachedTileLinkIOArbiter(uncachedArbPorts.size)) - uncachedArb.io.in <> uncachedArbPorts - ucLegacy.module.io.legacy <> uncachedArb.io.out - } - - io.success := test.io.status.finished + outer.dcacheOpt foreach { dcache => + val ptw = Module(new DummyPTW(1)) + ptw.io.requestors.head <> dcache.module.io.ptw } } diff --git a/src/main/scala/groundtest/Top.scala b/src/main/scala/groundtest/Top.scala index fd2d65ad..9de7b6e3 100644 --- a/src/main/scala/groundtest/Top.scala +++ b/src/main/scala/groundtest/Top.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package groundtest +package freechips.rocketchip.groundtest import Chisel._ -import config.Parameters -import diplomacy.LazyModule -import rocketchip._ + +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy.LazyModule +import freechips.rocketchip.chip._ class GroundTestTop(implicit p: Parameters) extends BaseSystem with HasPeripheryMasterAXI4MemPort diff --git a/src/main/scala/groundtest/TraceGen.scala b/src/main/scala/groundtest/TraceGen.scala index d2e233bc..f9876c66 100644 --- a/src/main/scala/groundtest/TraceGen.scala +++ b/src/main/scala/groundtest/TraceGen.scala @@ -17,17 +17,14 @@ // Mainstream Systems (REMS) project, funded by EPSRC grant // EP/K008528/1. -package groundtest +package freechips.rocketchip.groundtest import Chisel._ -import uncore.tilelink._ -import uncore.constants._ -import coreplex.NTiles -import rocket._ -import tile._ -import util.{Timer, DynamicTimer} +import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.util._ import scala.util.Random -import config._ // ======= // Outline @@ -59,19 +56,29 @@ import config._ // (This is a way to generate a wider range of addresses without having // to repeatedly recompile with a different address bag.) -case object AddressBag extends Field[List[BigInt]] +case class TraceGenParams( + dcache: Option[DCacheParams] = Some(DCacheParams()), + wordBits: Int, // p(XLen) + addrBits: Int, // p(PAddrBits) + addrBag: List[BigInt], // p(AddressBag) + maxRequests: Int, + memStart: BigInt, //p(ExtMem).base + numGens: Int) extends GroundTestTileParams { + def build(i: Int, p: Parameters): GroundTestTile = new TraceGenTile(i, this)(p) +} trait HasTraceGenParams { implicit val p: Parameters - val pAddrBits = p(PAddrBits) - val numGens = p(NTiles) - val numBitsInId = log2Up(numGens) - val numReqsPerGen = p(GeneratorKey).maxRequests + val params: TraceGenParams + val pAddrBits = params.addrBits + val numGens = params.numGens + val numReqsPerGen = params.maxRequests + val memStart = params.memStart val memRespTimeout = 8192 - val numBitsInWord = p(XLen) + val numBitsInWord = params.wordBits val numBytesInWord = numBitsInWord / 8 val numBitsInWordOffset = log2Up(numBytesInWord) - val addressBag = p(AddressBag) + val addressBag = params.addrBag val addressBagLen = addressBag.length val logAddressBagLen = log2Up(addressBagLen) val genExtraAddrs = false @@ -179,14 +186,13 @@ class TagMan(val logNumTags : Int) extends Module { // Trace generator // =============== -class TraceGenerator(id: Int) - (implicit val p: Parameters) extends Module - with HasTraceGenParams - with HasGroundTestParameters { +class TraceGenerator(val params: TraceGenParams)(implicit val p: Parameters) extends Module + with HasTraceGenParams { val io = new Bundle { val finished = Bool(OUTPUT) val timeout = Bool(OUTPUT) val mem = new HellaCacheIO + val hartid = UInt(INPUT, log2Up(numGens)) } val totalNumAddrs = addressBag.size + numExtraAddrs @@ -199,8 +205,6 @@ class TraceGenerator(id: Int) reqTimer.io.stop.valid := io.mem.resp.valid reqTimer.io.stop.bits := io.mem.resp.bits.tag - assert(!reqTimer.io.timeout.valid, s"TraceGen core ${id}: request timed out") - // Random addresses // ---------------- @@ -327,7 +331,7 @@ class TraceGenerator(id: Int) // ------------------ // Hardware thread id - val tid = UInt(id, numBitsInId) + val tid = io.hartid // Request & response count val reqCount = Reg(init = UInt(0, 32)) @@ -345,7 +349,7 @@ class TraceGenerator(id: Int) sendFreshReq := Bool(false) // Used to generate unique data values - val nextData = Reg(init = UInt(1, numBitsInWord-numBitsInId)) + val nextData = Reg(init = UInt(1, numBitsInWord-tid.getWidth)) // Registers for all the interesting parts of a request val reqValid = Reg(init = Bool(false)) @@ -503,6 +507,7 @@ class TraceGenerator(id: Int) io.mem.req.bits.typ := UInt(log2Ceil(numBytesInWord)) io.mem.req.bits.cmd := reqCmd io.mem.req.bits.tag := reqTag + io.mem.invalidate_lr := Bool(false) // On cycle when request is actually sent, print it when (io.mem.req.fire()) { @@ -569,17 +574,25 @@ class TraceGenerator(id: Int) // Trace-generator wrapper // ======================= -class GroundTestTraceGenerator(implicit p: Parameters) - extends GroundTest()(p) with HasTraceGenParams { +class TraceGenTile(val id: Int, val params: TraceGenParams)(implicit p: Parameters) extends GroundTestTile(params) { + override lazy val module = new TraceGenTileModule(this) +} - require(io.mem.size <= 1) - require(io.cache.size == 1) +class TraceGenTileModule(outer: TraceGenTile) extends GroundTestTileModule(outer, () => new GroundTestTileBundle(outer)) { - val traceGen = Module(new TraceGenerator(p(TileId))) - io.cache.head <> traceGen.io.mem + val tracegen = Module(new TraceGenerator(outer.params)) + tracegen.io.hartid := io.hartid - io.status.finished := traceGen.io.finished - io.status.timeout.valid := traceGen.io.timeout + outer.dcacheOpt foreach { dcache => + val dcacheIF = Module(new SimpleHellaCacheIF()) + dcacheIF.io.requestor <> tracegen.io.mem + dcache.module.io.cpu <> dcacheIF.io.cache + } + + io.status.finished := tracegen.io.finished + io.status.timeout.valid := tracegen.io.timeout io.status.timeout.bits := UInt(0) io.status.error.valid := Bool(false) + + assert(!tracegen.io.timeout, s"TraceGen tile ${outer.id}: request timed out") } diff --git a/src/main/scala/groundtest/TrafficGenerator.scala b/src/main/scala/groundtest/TrafficGenerator.scala deleted file mode 100644 index 0eefcd29..00000000 --- a/src/main/scala/groundtest/TrafficGenerator.scala +++ /dev/null @@ -1,216 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package groundtest - -import Chisel._ -import uncore.tilelink._ -import coreplex.NTiles -import uncore.constants._ -import junctions._ -import rocket._ -import util.SimpleTimer -import scala.util.Random -import config._ - -case class TrafficGeneratorParameters( - maxRequests: Int, - startAddress: BigInt) -case object GeneratorKey extends Field[TrafficGeneratorParameters] - -trait HasTrafficGeneratorParameters extends HasGroundTestParameters { - implicit val p: Parameters - - val genParams = p(GeneratorKey) - val nGens = p(GroundTestKey).map( - cs => cs.uncached + cs.cached).reduce(_ + _) - val genTimeout = 8192 - val maxRequests = genParams.maxRequests - val startAddress = genParams.startAddress - - val genWordBits = 32 - val genWordBytes = genWordBits / 8 - val wordOffset = log2Ceil(genWordBytes) - val wordSize = UInt(log2Ceil(genWordBytes)) - - require(startAddress % BigInt(genWordBytes) == 0) -} - -class UncachedTileLinkGenerator(id: Int) - (implicit p: Parameters) extends TLModule()(p) with HasTrafficGeneratorParameters { - - private val tlBlockOffset = tlBeatAddrBits + tlByteAddrBits - - val io = new Bundle { - val mem = new ClientUncachedTileLinkIO - val status = new GroundTestStatus - } - - val (s_start :: s_put :: s_get :: s_finished :: Nil) = Enum(Bits(), 4) - val state = Reg(init = s_start) - - val (req_cnt, req_wrap) = Counter(io.mem.grant.fire(), maxRequests) - - val sending = Reg(init = Bool(false)) - - when (state === s_start) { - sending := Bool(true) - state := s_put - } - - when (io.mem.acquire.fire()) { sending := Bool(false) } - when (io.mem.grant.fire()) { sending := Bool(true) } - when (req_wrap) { state := Mux(state === s_put, s_get, s_finished) } - - val timeout = SimpleTimer(genTimeout, io.mem.acquire.fire(), io.mem.grant.fire()) - assert(!timeout, s"Uncached generator ${id} timed out waiting for grant") - - io.status.finished := (state === s_finished) - io.status.timeout.valid := timeout - io.status.timeout.bits := UInt(id) - - val part_of_full_addr = - if (log2Ceil(nGens) > 0) { - Cat(UInt(id, log2Ceil(nGens)), - UInt(0, wordOffset)) - } else { - UInt(0, wordOffset) - } - val full_addr = UInt(startAddress) + Cat(req_cnt, part_of_full_addr) - - val addr_block = full_addr >> UInt(tlBlockOffset) - val addr_beat = full_addr(tlBlockOffset - 1, tlByteAddrBits) - val addr_byte = full_addr(tlByteAddrBits - 1, 0) - - val data_prefix = Cat(UInt(id, log2Up(nGens)), req_cnt) - val word_data = Wire(UInt(width = genWordBits)) - word_data := Cat(data_prefix, part_of_full_addr) - val beat_data = Fill(tlDataBits / genWordBits, word_data) - val wshift = Cat(beatOffset(full_addr), UInt(0, wordOffset)) - val wmask = Fill(genWordBits / 8, Bits(1, 1)) << wshift - - val put_acquire = Put( - client_xact_id = UInt(0), - addr_block = addr_block, - addr_beat = addr_beat, - data = beat_data, - wmask = Some(wmask), - alloc = Bool(false)) - - val get_acquire = Get( - client_xact_id = UInt(0), - addr_block = addr_block, - addr_beat = addr_beat, - addr_byte = addr_byte, - operand_size = wordSize, - alloc = Bool(false)) - - io.mem.acquire.valid := sending && !io.status.finished - io.mem.acquire.bits := Mux(state === s_put, put_acquire, get_acquire) - io.mem.grant.ready := !sending && !io.status.finished - - def wordFromBeat(addr: UInt, dat: UInt) = { - val shift = Cat(beatOffset(addr), UInt(0, wordOffset + 3)) - (dat >> shift)(genWordBits - 1, 0) - } - - val data_mismatch = io.mem.grant.fire() && state === s_get && - wordFromBeat(full_addr, io.mem.grant.bits.data) =/= word_data - - io.status.error.valid := data_mismatch - io.status.error.bits := UInt(id) - - assert(!data_mismatch, - s"Get received incorrect data in uncached generator ${id}") - - def beatOffset(addr: UInt) = // TODO zero-width - if (tlByteAddrBits > wordOffset) addr(tlByteAddrBits - 1, wordOffset) - else UInt(0) -} - -class HellaCacheGenerator(id: Int) - (implicit val p: Parameters) extends Module with HasTrafficGeneratorParameters { - val io = new Bundle { - val mem = new HellaCacheIO - val status = new GroundTestStatus - } - - val timeout = SimpleTimer(genTimeout, io.mem.req.fire(), io.mem.resp.valid) - assert(!timeout, s"Cached generator ${id} timed out waiting for response") - io.status.timeout.valid := timeout - io.status.timeout.bits := UInt(id) - - val (s_start :: s_write :: s_read :: s_finished :: Nil) = Enum(Bits(), 4) - val state = Reg(init = s_start) - val sending = Reg(init = Bool(false)) - - val (req_cnt, req_wrap) = Counter(io.mem.resp.valid, maxRequests) - - val part_of_req_addr = - if (log2Ceil(nGens) > 0) { - Cat(UInt(id, log2Ceil(nGens)), - UInt(0, wordOffset)) - } else { - UInt(0, wordOffset) - } - val req_addr = UInt(startAddress) + Cat(req_cnt, part_of_req_addr) - val req_data = Cat(UInt(id, log2Up(nGens)), req_cnt, part_of_req_addr) - - io.mem.req.valid := sending && !io.status.finished - io.mem.req.bits.addr := req_addr - io.mem.req.bits.data := req_data - io.mem.req.bits.typ := wordSize - io.mem.req.bits.cmd := Mux(state === s_write, M_XWR, M_XRD) - io.mem.req.bits.tag := UInt(0) - - when (state === s_start) { sending := Bool(true); state := s_write } - - when (io.mem.req.fire()) { sending := Bool(false) } - when (io.mem.resp.valid) { sending := Bool(true) } - - when (req_wrap) { state := Mux(state === s_write, s_read, s_finished) } - - io.status.finished := (state === s_finished) - - def data_match(recv: Bits, expected: Bits): Bool = { - val recv_resized = Wire(Bits(width = genWordBits)) - val exp_resized = Wire(Bits(width = genWordBits)) - - recv_resized := recv - exp_resized := expected - recv_resized === exp_resized - } - - val data_mismatch = io.mem.resp.valid && io.mem.resp.bits.has_data && - !data_match(io.mem.resp.bits.data, req_data) - - io.status.error.valid := data_mismatch - io.status.error.bits := UInt(id) - - assert(!data_mismatch, - s"Received incorrect data in cached generator ${id}") -} - -class GeneratorTest(implicit p: Parameters) - extends GroundTest()(p) with HasTrafficGeneratorParameters { - - val idStart = p(GroundTestKey).take(p(TileId)) - .map(settings => settings.cached + settings.uncached) - .foldLeft(0)(_ + _) - - val cached = List.tabulate(nCached) { i => - val realId = idStart + i - Module(new HellaCacheGenerator(realId)) - } - - val uncached = List.tabulate(nUncached) { i => - val realId = idStart + nCached + i - Module(new UncachedTileLinkGenerator(realId)) - } - - io.cache <> cached.map(_.io.mem) - io.mem <> uncached.map(_.io.mem) - - val gen_debug = cached.map(_.io.status) ++ uncached.map(_.io.status) - io.status := DebugCombiner(gen_debug) -} diff --git a/src/main/scala/groundtest/Util.scala b/src/main/scala/groundtest/Util.scala deleted file mode 100644 index 60220d61..00000000 --- a/src/main/scala/groundtest/Util.scala +++ /dev/null @@ -1,168 +0,0 @@ -// See LICENSE.SiFive for license details. -// See LICENSE.Berkeley for license details. - -package groundtest - -import Chisel._ - -// ============ -// LCG16 module -// ============ - -// A 16-bit psuedo-random generator based on a linear conguential -// generator (LCG). The state is stored in an unitialised register. -// When using the C++ backend, it is straigtforward to arrange a -// random initial value for each uninitialised register, effectively -// seeding each LCG16 instance with a different seed. - -class LCG16 extends Module { - val io = new Bundle { - val out = UInt(OUTPUT, 16) - val inc = Bool(INPUT) - } - val state = Reg(UInt(width = 32)) - when (io.inc) { - state := state * UInt(1103515245, 32) + UInt(12345, 32) - } - io.out := state(30, 15) -} - -// ========== -// LCG module -// ========== - -// An n-bit psuedo-random generator made from many instances of a -// 16-bit LCG. Parameter 'width' must be larger than 0. - -class LCG(val w: Int) extends Module { - val io = new Bundle { - val out = UInt(OUTPUT, w) - val inc = Bool(INPUT) - } - require(w > 0) - val numLCG16s : Int = (w+15)/16 - val outs = Seq.fill(numLCG16s) { LCG16(io.inc) } - io.out := Cat(outs) -} - -object LCG16 { - def apply(inc: Bool = Bool(true)): UInt = { - val lcg = Module(new LCG16) - lcg.io.inc := inc - lcg.io.out - } -} - -object LCG { - def apply(w: Int, inc: Bool = Bool(true)): UInt = { - val lcg = Module(new LCG(w)) - lcg.io.inc := inc - lcg.io.out - } -} - -// ====================== -// Frequency distribution -// ====================== - -// Given a list of (frequency, value) pairs, return a random value -// according to the frequency distribution. The sum of the -// frequencies in the distribution must be a power of two. - -object Frequency { - def apply(dist : List[(Int, Bits)]) : Bits = { - // Distribution must be non-empty - require(dist.length > 0) - - // Require that the frequencies sum to a power of two - val (freqs, vals) = dist.unzip - val total = freqs.sum - require(isPow2(total)) - - // First item in the distribution - val (firstFreq, firstVal) = dist.head - - // Result wire - val result = Wire(Bits(width = firstVal.getWidth)) - result := UInt(0) - - // Random value - val randVal = LCG(log2Up(total)) - - // Pick return value - var count = firstFreq - var select = when (randVal < UInt(firstFreq)) { result := firstVal } - for (p <- dist.drop(1)) { - count = count + p._1 - select = select.elsewhen(randVal < UInt(count)) { result := p._2 } - } - - return result - } -} - -object ValidMux { - def apply[T <: Data](v1: ValidIO[T], v2: ValidIO[T]*): ValidIO[T] = { - apply(v1 +: v2.toSeq) - } - def apply[T <: Data](valids: Seq[ValidIO[T]]): ValidIO[T] = { - val out = Wire(Valid(valids.head.bits)) - out.valid := valids.map(_.valid).reduce(_ || _) - out.bits := MuxCase(valids.head.bits, - valids.map(v => (v.valid -> v.bits))) - out - } -} - -object DebugCombiner { - def apply(debugs: Seq[GroundTestStatus]): GroundTestStatus = { - val out = Wire(new GroundTestStatus) - out.finished := debugs.map(_.finished).reduce(_ && _) - out.timeout := ValidMux(debugs.map(_.timeout)) - out.error := ValidMux(debugs.map(_.error)) - out - } -} - -/** - * Takes in data on one decoupled interface and broadcasts it to - * N decoupled output interfaces - */ -class Broadcaster[T <: Data](typ: T, n: Int) extends Module { - val io = new Bundle { - val in = Decoupled(typ).flip - val out = Vec(n, Decoupled(typ)) - } - - require (n > 0) - - if (n == 1) { - io.out.head <> io.in - } else { - val idx = Reg(init = UInt(0, log2Up(n))) - val save = Reg(typ) - - io.out.head.valid := idx === UInt(0) && io.in.valid - io.out.head.bits := io.in.bits - for (i <- 1 until n) { - io.out(i).valid := idx === UInt(i) - io.out(i).bits := save - } - io.in.ready := io.out.head.ready && idx === UInt(0) - - when (io.in.fire()) { save := io.in.bits } - - when (io.out(idx).fire()) { - when (idx === UInt(n - 1)) { idx := UInt(0) } - .otherwise { idx := idx + UInt(1) } - } - } -} - -object Broadcaster { - def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = { - val split = Module(new Broadcaster(in.bits, n)) - split.io.in <> in - split.io.out - } -} diff --git a/src/main/scala/jtag/JtagShifter.scala b/src/main/scala/jtag/JtagShifter.scala index 686818c1..76633c43 100644 --- a/src/main/scala/jtag/JtagShifter.scala +++ b/src/main/scala/jtag/JtagShifter.scala @@ -1,6 +1,6 @@ // See LICENSE.jtag for license details. -package jtag +package freechips.rocketchip.jtag import chisel3._ import chisel3.core.DataMirror diff --git a/src/main/scala/jtag/JtagStateMachine.scala b/src/main/scala/jtag/JtagStateMachine.scala index 80f92437..240a946a 100644 --- a/src/main/scala/jtag/JtagStateMachine.scala +++ b/src/main/scala/jtag/JtagStateMachine.scala @@ -1,10 +1,10 @@ // See LICENSE.jtag for license details. -package jtag +package freechips.rocketchip.jtag -import util.{AsyncResetRegVec} import chisel3._ import chisel3.util._ +import freechips.rocketchip.util.{AsyncResetRegVec} object JtagState { sealed abstract class State(val id: Int) { diff --git a/src/main/scala/jtag/JtagTap.scala b/src/main/scala/jtag/JtagTap.scala index 50aee22c..c69fc638 100644 --- a/src/main/scala/jtag/JtagTap.scala +++ b/src/main/scala/jtag/JtagTap.scala @@ -1,6 +1,6 @@ // See LICENSE.jtag for license details. -package jtag +package freechips.rocketchip.jtag import chisel3._ import chisel3.util._ diff --git a/src/main/scala/jtag/JtagUtils.scala b/src/main/scala/jtag/JtagUtils.scala index 8c216a57..035ee9ea 100644 --- a/src/main/scala/jtag/JtagUtils.scala +++ b/src/main/scala/jtag/JtagUtils.scala @@ -1,6 +1,6 @@ // See LICENSE.jtag for license details. -package jtag +package freechips.rocketchip.jtag import chisel3._ import chisel3.util._ diff --git a/src/main/scala/jtag/Utils.scala b/src/main/scala/jtag/Utils.scala index 3b8644c5..491de8cf 100644 --- a/src/main/scala/jtag/Utils.scala +++ b/src/main/scala/jtag/Utils.scala @@ -1,6 +1,6 @@ // See LICENSE.jtag for license details. -package jtag +package freechips.rocketchip.jtag import chisel3._ import chisel3.util._ diff --git a/src/main/scala/jtag/package.scala b/src/main/scala/jtag/package.scala index 12f47c01..8ceceae5 100644 --- a/src/main/scala/jtag/package.scala +++ b/src/main/scala/jtag/package.scala @@ -1,5 +1,7 @@ // See LICENSE.jtag for license details +package freechips.rocketchip + import scala.language.implicitConversions package object jtag { diff --git a/src/main/scala/junctions/NastiDriver.scala b/src/main/scala/junctions/NastiDriver.scala deleted file mode 100644 index 236f0114..00000000 --- a/src/main/scala/junctions/NastiDriver.scala +++ /dev/null @@ -1,79 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package junctions - -import Chisel._ -import config._ - -class NastiDriver(dataWidth: Int, burstLen: Int, nBursts: Int) - (implicit p: Parameters) extends NastiModule { - val io = new Bundle { - val nasti = new NastiIO - val finished = Bool(OUTPUT) - val start = Bool(INPUT) - } - - val dataBytes = dataWidth / 8 - val nastiDataBytes = nastiXDataBits / 8 - - val (write_cnt, write_done) = Counter(io.nasti.w.fire(), burstLen) - val (read_cnt, read_done) = Counter(io.nasti.r.fire(), burstLen) - val (req_cnt, reqs_done) = Counter(read_done, nBursts) - - val req_addr = Cat(req_cnt, UInt(0, log2Up(burstLen * dataBytes))) - - val write_data = UInt(0x10000000L, dataWidth) | Cat(req_cnt, write_cnt) - val expected_data = UInt(0x10000000L, dataWidth) | Cat(req_cnt, read_cnt) - - val (s_idle :: s_write_addr :: s_write_data :: s_write_stall :: s_write_resp :: - s_read_addr :: s_read_data :: s_read_stall :: s_done :: Nil) = Enum(Bits(), 9) - val state = Reg(init = s_idle) - - val (stall_cnt, stall_done) = Counter(state === s_read_stall, 2) - - io.nasti.aw.valid := (state === s_write_addr) - io.nasti.aw.bits := NastiWriteAddressChannel( - id = UInt(0), - addr = req_addr, - size = UInt(log2Up(dataBytes)), - len = UInt(burstLen - 1)) - - io.nasti.w.valid := (state === s_write_data) - io.nasti.w.bits := NastiWriteDataChannel( - data = Cat(write_data, write_data), - last = (write_cnt === UInt(burstLen - 1))) - - io.nasti.b.ready := (state === s_write_resp) - - io.nasti.ar.valid := (state === s_read_addr) - io.nasti.ar.bits := NastiReadAddressChannel( - id = UInt(0), - addr = req_addr, - size = UInt(log2Up(dataBytes)), - len = UInt(burstLen - 1)) - - io.nasti.r.ready := (state === s_read_data) - - io.finished := (state === s_done) - - when (state === s_idle && io.start) { state := s_write_addr } - when (io.nasti.aw.fire()) { state := s_write_data } - when (io.nasti.w.fire()) { state := s_write_stall } - when (state === s_write_stall) { state := s_write_data } - when (write_done) { state := s_write_resp } - when (io.nasti.b.fire()) { state := s_read_addr } - when (io.nasti.ar.fire()) { state := s_read_data } - when (io.nasti.r.fire()) { state := s_read_stall } - when (stall_done) { state := s_read_data } - when (read_done) { state := s_write_addr } - when (reqs_done) { state := s_done } - - val full_addr = req_addr + (read_cnt << UInt(log2Up(dataBytes))) - val byteshift = full_addr(log2Up(nastiDataBytes) - 1, 0) - val bitshift = Cat(byteshift, UInt(0, 3)) - val read_data = (io.nasti.r.bits.data >> bitshift) & Fill(dataWidth, UInt(1, 1)) - - assert(!io.nasti.r.valid || read_data === expected_data, - s"NastiDriver got wrong data") -} diff --git a/src/main/scala/junctions/addrmap.scala b/src/main/scala/junctions/addrmap.scala deleted file mode 100644 index db2d9d11..00000000 --- a/src/main/scala/junctions/addrmap.scala +++ /dev/null @@ -1,148 +0,0 @@ -// See LICENSE.SiFive for license details. -// See LICENSE.Berkeley for license details. - -package junctions - -import Chisel._ -import config._ -import scala.collection.mutable.HashMap - -case class MemAttr(prot: Int, cacheable: Boolean = false) - -sealed abstract class MemRegion { - def start: BigInt - def size: BigInt - def numSlaves: Int - def attr: MemAttr - - def containsAddress(x: UInt) = UInt(start) <= x && x < UInt(start + size) -} - -case class MemSize(size: BigInt, attr: MemAttr) extends MemRegion { - def start = 0 - def numSlaves = 1 -} - -case class MemRange(start: BigInt, size: BigInt, attr: MemAttr) extends MemRegion { - def numSlaves = 1 -} - -object AddrMapProt { - val R = 0x1 - val W = 0x2 - val X = 0x4 - val RW = R | W - val RX = R | X - val RWX = R | W | X - val SZ = 3 -} - -class AddrMapProt extends Bundle { - val x = Bool() - val w = Bool() - val r = Bool() -} - -case class AddrMapEntry(name: String, region: MemRegion) - -object AddrMap { - def apply(elems: AddrMapEntry*): AddrMap = new AddrMap(elems) -} - -class AddrMap( - entriesIn: Seq[AddrMapEntry], - val start: BigInt = BigInt(0), - val collapse: Boolean = false) extends MemRegion { - private val slavePorts = HashMap[String, Int]() - private val mapping = HashMap[String, MemRegion]() - - def isEmpty = entries.isEmpty - def length = entries.size - def numSlaves = slavePorts.size - - val (size: BigInt, entries: Seq[AddrMapEntry], attr: MemAttr) = { - var ind = 0 - var base = start - var rebasedEntries = collection.mutable.ArrayBuffer[AddrMapEntry]() - var prot = 0 - var cacheable = true - for (AddrMapEntry(name, r) <- entriesIn) { - require (!mapping.contains(name)) - base = r.start - - r match { - case r: AddrMap => - val subMap = new AddrMap(r.entries, base, r.collapse) - rebasedEntries += AddrMapEntry(name, subMap) - mapping += name -> subMap - mapping ++= subMap.mapping.map { case (k, v) => s"$name:$k" -> v } - if (r.collapse) { - slavePorts += (name -> ind) - ind += 1 - } else { - slavePorts ++= subMap.slavePorts.map { - case (k, v) => s"$name:$k" -> (ind + v) - } - ind += r.numSlaves - } - case _ => - val e = MemRange(base, r.size, r.attr) - rebasedEntries += AddrMapEntry(name, e) - mapping += name -> e - slavePorts += name -> ind - ind += r.numSlaves - } - - base += r.size - prot |= r.attr.prot - cacheable &&= r.attr.cacheable - } - (base - start, rebasedEntries, MemAttr(prot, cacheable)) - } - - val flatten: Seq[AddrMapEntry] = { - mapping.toSeq.map { - case (name, range: MemRange) => Some(AddrMapEntry(name, range)) - case _ => None - }.flatten.sortBy(_.region.start) - } - - // checks to see whether any MemRange overlaps within this AddrMap - flatten.combinations(2) foreach { - case (Seq(AddrMapEntry(an, ar), AddrMapEntry(bn, br))) => - val arEnd = ar.start + ar.size - val brEnd = br.start + br.size - val abOverlaps = ar.start < brEnd && br.start < arEnd - require(!abOverlaps, - s"region $an@0x${ar.start.toString(16)} overlaps region $bn@0x${br.start.toString(16)}") - } - - def toRange: MemRange = MemRange(start, size, attr) - def apply(name: String): MemRegion = mapping(name) - def contains(name: String): Boolean = mapping.contains(name) - def port(name: String): Int = slavePorts(name) - def subMap(name: String): AddrMap = mapping(name).asInstanceOf[AddrMap] - def isInRegion(name: String, addr: UInt): Bool = mapping(name).containsAddress(addr) - - def isCacheable(addr: UInt): Bool = { - flatten.filter(_.region.attr.cacheable).map( - _.region.containsAddress(addr) - ).foldLeft(Bool(false))(_ || _) - } - - def isValid(addr: UInt): Bool = { - flatten.map(_.region.containsAddress(addr)).foldLeft(Bool(false))(_ || _) - } - - def getProt(addr: UInt): AddrMapProt = { - val protForRegion = flatten.map { entry => - Mux(entry.region.containsAddress(addr), - UInt(entry.region.attr.prot, AddrMapProt.SZ), UInt(0)) - } - new AddrMapProt().fromBits(protForRegion.reduce(_|_)) - } - - override def containsAddress(x: UInt) = { - flatten.map(_.region.containsAddress(x)).reduce(_||_) - } -} diff --git a/src/main/scala/junctions/hasti.scala b/src/main/scala/junctions/hasti.scala deleted file mode 100644 index 8a6e4142..00000000 --- a/src/main/scala/junctions/hasti.scala +++ /dev/null @@ -1,565 +0,0 @@ -// See LICENSE.SiFive for license details. -// See LICENSE.Berkeley for license details. - -package junctions - -import Chisel._ -import config._ -import unittest.UnitTest -import util._ - -object HastiConstants -{ - // Values for htrans - val SZ_HTRANS = 2 - def HTRANS_IDLE = UInt(0, SZ_HTRANS) // No transfer requested, not in a burst - def HTRANS_BUSY = UInt(1, SZ_HTRANS) // No transfer requested, in a burst - def HTRANS_NONSEQ = UInt(2, SZ_HTRANS) // First (potentially only) request in a burst - def HTRANS_SEQ = UInt(3, SZ_HTRANS) // Following requests in a burst - - // Values for hburst - val SZ_HBURST = 3 - def HBURST_SINGLE = UInt(0, SZ_HBURST) // Single access (no burst) - def HBURST_INCR = UInt(1, SZ_HBURST) // Incrementing burst of arbitrary length, not crossing 1KB - def HBURST_WRAP4 = UInt(2, SZ_HBURST) // 4-beat wrapping burst - def HBURST_INCR4 = UInt(3, SZ_HBURST) // 4-beat incrementing burst - def HBURST_WRAP8 = UInt(4, SZ_HBURST) // 8-beat wrapping burst - def HBURST_INCR8 = UInt(5, SZ_HBURST) // 8-beat incrementing burst - def HBURST_WRAP16 = UInt(6, SZ_HBURST) // 16-beat wrapping burst - def HBURST_INCR16 = UInt(7, SZ_HBURST) // 16-beat incrementing burst - - // Values for hresp - val SZ_HRESP = 1 - def HRESP_OKAY = UInt(0, SZ_HRESP) - def HRESP_ERROR = UInt(1, SZ_HRESP) - - // Values for hsize are identical to TileLink MT_SZ - // ie: 8*2^SZ_HSIZE bit transfers - val SZ_HSIZE = 3 - - // Values for hprot (a bitmask) - val SZ_HPROT = 4 - def HPROT_DATA = UInt("b0001") // Data access or Opcode fetch - def HPROT_PRIVILEGED = UInt("b0010") // Privileged or User access - def HPROT_BUFFERABLE = UInt("b0100") // Bufferable or non-bufferable - def HPROT_CACHEABLE = UInt("b1000") // Cacheable or non-cacheable - - def dgate(valid: Bool, b: UInt) = Fill(b.getWidth, valid) & b -} - -import HastiConstants._ - -case class HastiParameters(dataBits: Int, addrBits: Int) -case object HastiId extends Field[String] -case class HastiKey(id: String) extends Field[HastiParameters] - -trait HasHastiParameters { - implicit val p: Parameters - val hastiParams = p(HastiKey(p(HastiId))) - val hastiAddrBits = hastiParams.addrBits - val hastiDataBits = hastiParams.dataBits - val hastiDataBytes = hastiDataBits/8 - val hastiAlignment = log2Ceil(hastiDataBytes) -} - -abstract class HastiModule(implicit val p: Parameters) extends Module - with HasHastiParameters -abstract class HastiBundle(implicit val p: Parameters) extends ParameterizedBundle()(p) - with HasHastiParameters - -class HastiMasterIO(implicit p: Parameters) extends HastiBundle()(p) { - val htrans = UInt(OUTPUT, SZ_HTRANS) - val hmastlock = Bool(OUTPUT) - val haddr = UInt(OUTPUT, hastiAddrBits) - val hwrite = Bool(OUTPUT) - val hburst = UInt(OUTPUT, SZ_HBURST) - val hsize = UInt(OUTPUT, SZ_HSIZE) - val hprot = UInt(OUTPUT, SZ_HPROT) - - val hwdata = Bits(OUTPUT, hastiDataBits) - val hrdata = Bits(INPUT, hastiDataBits) - - val hready = Bool(INPUT) - val hresp = UInt(INPUT, SZ_HRESP) - - def isNSeq(dummy:Int=0) = htrans === HTRANS_NONSEQ // SEQ does not start a NEW request - def isHold(dummy:Int=0) = htrans === HTRANS_BUSY || htrans === HTRANS_SEQ - def isIdle(dummy:Int=0) = htrans === HTRANS_IDLE || htrans === HTRANS_BUSY -} - -class HastiSlaveIO(implicit p: Parameters) extends HastiBundle()(p) { - val htrans = UInt(INPUT, SZ_HTRANS) - val hmastlock = Bool(INPUT) - val haddr = UInt(INPUT, hastiAddrBits) - val hwrite = Bool(INPUT) - val hburst = UInt(INPUT, SZ_HBURST) - val hsize = UInt(INPUT, SZ_HSIZE) - val hprot = UInt(INPUT, SZ_HPROT) - - val hwdata = Bits(INPUT, hastiDataBits) - val hrdata = Bits(OUTPUT, hastiDataBits) - - val hsel = Bool(INPUT) - val hready = Bool(OUTPUT) - val hresp = UInt(OUTPUT, SZ_HRESP) -} - -/* A diverted master is told hready when his address phase goes nowhere. - * In this case, we buffer his address phase request and replay it later. - * NOTE: this must optimize to nothing when divert is constantly false. - */ -class MasterDiversion(implicit p: Parameters) extends HastiModule()(p) { - val io = new Bundle { - val in = (new HastiMasterIO).flip - val out = (new HastiMasterIO) - val divert = Bool(INPUT) - } - - val full = Reg(init = Bool(false)) - val buffer = Reg(new HastiMasterIO) - - when (io.out.hready) { - full := Bool(false) - } - when (io.divert) { - full := Bool(true) - buffer := io.in - } - - // If the master is diverted, he must also have been told hready - assert (!io.divert || io.in.hready, - "Diverted but not ready"); - - // Replay the request we diverted - io.out.htrans := Mux(full, buffer.htrans, io.in.htrans) - io.out.hmastlock := Mux(full, buffer.hmastlock, io.in.hmastlock) - io.out.haddr := Mux(full, buffer.haddr, io.in.haddr) - io.out.hwrite := Mux(full, buffer.hwrite, io.in.hwrite) - io.out.hburst := Mux(full, buffer.hburst, io.in.hburst) - io.out.hsize := Mux(full, buffer.hsize, io.in.hsize) - io.out.hprot := Mux(full, buffer.hprot, io.in.hprot) - io.out.hwdata := Mux(full, buffer.hwdata, io.in.hwdata) - - // Pass slave response back - io.in.hrdata := io.out.hrdata - io.in.hresp := io.out.hresp - io.in.hready := io.out.hready && !full // Block master while we steal his address phase -} - -/* Masters with lower index have priority over higher index masters. - * However, a lower priority master will retain control of a slave when EITHER: - * 1. a burst is in progress (switching slaves mid-burst violates AHB-lite at slave) - * 2. a transfer was waited (the standard forbids changing requests in this case) - * - * If a master raises hmastlock, it will be waited until no other master has inflight - * requests; then, it acquires exclusive control of the crossbar until hmastlock is low. - * - * To implement an AHB-lite crossbar, it is important to realize that requests and - * responses are coupled. Unlike modern bus protocols where the response data has flow - * control independent of the request data, in AHB-lite, both flow at the same time at - * the sole discretion of the slave via the hready signal. The address and data are - * delivered on two back-to-back cycles, the so-called address and data phases. - * - * Masters can only be connected to a single slave at a time. If a master had two different - * slave connections on the address and data phases, there would be two independent hready - * signals. An AHB-lite slave can assume that data flows when it asserts hready. If the data - * slave deasserts hready while the address slave asserts hready, the master is put in the - * impossible position of being in data phase on two slaves at once. For this reason, when - * a master issues back-to-back accesses to distinct slaves, we inject a pipeline bubble - * between the two requests to limit the master to just a single slave at a time. - * - * Conversely, a slave CAN have two masters attached to it. This is unproblematic, because - * the only signal which governs data flow is hready. Thus, both masters can be stalled - * safely by the single slave. - */ -class HastiXbar(nMasters: Int, addressMap: Seq[UInt=>Bool])(implicit p: Parameters) extends HastiModule()(p) { - val io = new Bundle { - val masters = Vec(nMasters, new HastiMasterIO).flip - val slaves = Vec(addressMap.size, new HastiSlaveIO).flip - } - - val nSlaves = addressMap.size - - // Setup diversions infront of each master - val diversions = Seq.tabulate(nMasters) { m => Module(new MasterDiversion) } - (io.masters zip diversions) foreach { case (m, d) => d.io.in <> m } - - // Handy short-hand - val masters = diversions map (_.io.out) - val slaves = io.slaves - - // Lock status of the crossbar - val lockedM = Reg(init = Vec.fill(nMasters)(Bool(false))) - val isLocked = lockedM.reduce(_ || _) - - // This matrix governs the master-slave connections in the address phase - // It is indexed by addressPhaseGrantSM(slave)(master) - // It is guaranteed to have at most one 'true' per column and per row - val addressPhaseGrantSM = Wire(Vec(nSlaves, Vec(nMasters, Bool()))) - // This matrix governs the master-slave connections in the data phase - // It is guaranteed to have at most one 'true' per column and per row - val dataPhaseGrantSM = Reg (init = Vec.fill(nSlaves)(Vec.fill(nMasters)(Bool(false)))) - // This matrix is the union of the address and data phases. - // It is transposed with respect to the two previous matrices. - // It is guaranteed to contain at most one 'true' per master row. - // However, two 'true's per slave column are permitted. - val unionGrantMS = Vec.tabulate(nMasters) { m => Vec.tabulate(nSlaves) { s => - addressPhaseGrantSM(s)(m) || dataPhaseGrantSM(s)(m) } } - - // Confirm the guarantees made above - def justOnce(v: Vec[Bool]) = v.fold(Bool(false)) { case (p, v) => - assert (!p || !v) - p || v - } - addressPhaseGrantSM foreach { s => justOnce(s) } - unionGrantMS foreach { s => justOnce(s) } - - // Data phase follows address phase whenever the slave is ready - (slaves zip (dataPhaseGrantSM zip addressPhaseGrantSM)) foreach { case (s, (d, a)) => - when (s.hready) { d := a } - } - - // Record the grant state from the previous cycle; needed in case we hold access - val priorAddressPhaseGrantSM = RegNext(addressPhaseGrantSM) - - // If a master says BUSY or SEQ, it is in the middle of a burst. - // In this case, it MUST stay attached to the same slave as before. - // Otherwise, it would violate the AHB-lite specification as seen by - // the slave, which is guaranteed a complete burst of the promised length. - // One case where this matters is preventing preemption of low-prio masters. - // NOTE: this exposes a slave to bad addresses when a master is buggy - val holdBurstM = Vec(masters map { _.isHold() }) - - // Transform the burst hold requirement from master indexing to slave indexing - // We use the previous cycle's binding because the master continues the prior burst - val holdBurstS = Vec(priorAddressPhaseGrantSM map { m => Mux1H(m, holdBurstM) }) - - // If a slave says !hready to a request, it must retain the same master next cycle. - // The AHB-lite specification requires that a waited transfer remain unchanged. - // If we preempted a waited master, the new master's request could potentially differ. - val holdBusyS = RegNext(Vec(slaves map { s => !s.hready && s.hsel })) - - // Combine the above two grounds to determine if the slave retains its prior master - val holdS = Vec((holdBurstS zip holdBusyS) map ({ case (a,b) => a||b })) - - // Determine which master addresses match which slaves - val matchMS = Vec(masters map { m => Vec(addressMap map { afn => afn(m.haddr) }) }) - // Detect requests to nowhere; we need to allow progress in this case - val nowhereM = Vec(matchMS map { s => !s.reduce(_ || _) }) - - // Detect if we need to inject a pipeline bubble between the master requests. - // Divert masters already granted a data phase different from next request. - // NOTE: if only one slave, matchMS is always true => bubble always false - // => the diversion registers are optimized away as they are unread - // NOTE: bubble => dataPhase => have an hready signal - val bubbleM = - Vec.tabulate(nMasters) { m => - Vec.tabulate(nSlaves) { s => dataPhaseGrantSM(s)(m) && !matchMS(m)(s) } - .reduce(_ || _) } - - // Block any request that requires bus ownership or conflicts with isLocked - val blockedM = - Vec((lockedM zip masters) map { case(l, m) => !l && (isLocked || m.hmastlock) }) - - // Requested access to slaves from masters (pre-arbitration) - // NOTE: isNSeq does NOT include SEQ; thus, masters who are midburst do not - // request access to a new slave. They stay tied to the old and do not get two. - // NOTE: if a master was waited, it must repeat the same request as last cycle; - // thus, it will request the same slave and not end up with two (unless buggy). - val NSeq = masters.map(_.isNSeq()) - val requestSM = Vec.tabulate(nSlaves) { s => Vec.tabulate(nMasters) { m => - matchMS(m)(s) && NSeq(m) && !bubbleM(m) && !blockedM(m) } } - - // Select at most one master request per slave (lowest index = highest priority) - val selectedRequestSM = Vec(requestSM map { m => Vec(PriorityEncoderOH(m)) }) - - // Calculate new crossbar interconnect state - addressPhaseGrantSM := Vec((holdS zip (priorAddressPhaseGrantSM zip selectedRequestSM)) - map { case (h, (p, r)) => Mux(h, p, r) }) - - for (m <- 0 until nMasters) { - // If the master is connected to a slave, the slave determines hready. - // However, if no slave is connected, for progress report ready anyway, if: - // bad address (swallow request) OR idle (permit stupid masters to move FSM) - val autoready = nowhereM(m) || masters(m).isIdle() - val hready = if (nSlaves == 1) - Mux(unionGrantMS(m)(0), slaves(0).hready ^ autoready, Bool(false)) ^ autoready - else - Mux1H(unionGrantMS(m), slaves.map(_.hready ^ autoready)) ^ autoready - masters(m).hready := hready - // If we diverted a master, we need to absorb his address phase to replay later - diversions(m).io.divert := (bubbleM(m) || blockedM(m)) && NSeq(m) && hready - } - - // Master muxes (address and data phase are the same) - (masters zip unionGrantMS) foreach { case (m, g) => { - m.hrdata := Mux1H(g, slaves.map(_.hrdata)) - m.hresp := Mux1H(g, slaves.map(_.hresp)) - } } - - // Slave address phase muxes - (slaves zip addressPhaseGrantSM) foreach { case (s, g) => { - s.htrans := Mux1H(g, masters.map(_.htrans)) - s.haddr := Mux1H(g, masters.map(_.haddr)) - s.hmastlock := isLocked - s.hwrite := Mux1H(g, masters.map(_.hwrite)) - s.hsize := Mux1H(g, masters.map(_.hsize)) - s.hburst := Mux1H(g, masters.map(_.hburst)) - s.hprot := Mux1H(g, masters.map(_.hprot)) - s.hsel := g.reduce(_ || _) - } } - - // Slave data phase muxes - (slaves zip dataPhaseGrantSM) foreach { case (s, g) => { - s.hwdata := Mux1H(g, masters.map(_.hwdata)) - } } - - // When no master-slave connections are active, a master can take-over the bus - val canLock = !addressPhaseGrantSM.map({ v => v.reduce(_ || _) }).reduce(_ || _) - - // Lowest index highest priority for lock arbitration - val reqLock = masters.map(_.hmastlock) - val winLock = PriorityEncoderOH(reqLock) - - // Lock arbitration - when (isLocked) { - lockedM := (lockedM zip reqLock) map { case (a,b) => a && b } - } .elsewhen (canLock) { - lockedM := winLock - } -} - -class HastiBus(amap: Seq[UInt=>Bool])(implicit p: Parameters) extends HastiModule()(p) { - val io = new Bundle { - val master = new HastiMasterIO().flip - val slaves = Vec(amap.size, new HastiSlaveIO).flip - } - - val bar = Module(new HastiXbar(1, amap)) - bar.io.masters(0) <> io.master - bar.io.slaves <> io.slaves -} - -class HastiSlaveMux(n: Int)(implicit p: Parameters) extends HastiModule()(p) { - val io = new Bundle { - val ins = Vec(n, new HastiSlaveIO) - val out = new HastiSlaveIO().flip - } - - val amap = Seq({ (_:UInt) => Bool(true)}) - val bar = Module(new HastiXbar(n, amap)) - io.ins <> bar.io.masters - io.out <> bar.io.slaves(0) -} - -class HastiSlaveToMaster(implicit p: Parameters) extends HastiModule()(p) { - val io = new Bundle { - val in = new HastiSlaveIO - val out = new HastiMasterIO - } - - io.out.htrans := Mux(io.in.hsel, io.in.htrans, HTRANS_IDLE) - io.out.hmastlock := io.in.hmastlock - io.out.haddr := io.in.haddr - io.out.hwrite := io.in.hwrite - io.out.hburst := io.in.hburst - io.out.hsize := io.in.hsize - io.out.hprot := io.in.hprot - io.out.hwdata := io.in.hwdata - io.in.hrdata := io.out.hrdata - io.in.hready := io.out.hready - io.in.hresp := io.out.hresp -} - -class HastiMasterIONastiIOConverter(implicit p: Parameters) extends HastiModule()(p) - with HasNastiParameters { - val io = new Bundle { - val nasti = new NastiIO().flip - val hasti = new HastiMasterIO - } - - require(hastiAddrBits == nastiXAddrBits) - require(hastiDataBits == nastiXDataBits) - - val r_queue = Module(new Queue(new NastiReadDataChannel, 2, pipe = true)) - - val s_idle :: s_read :: s_write :: s_write_resp :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_idle) - - val addr = Reg(UInt(width = hastiAddrBits)) - val id = Reg(UInt(width = nastiXIdBits)) - val size = Reg(UInt(width = nastiXSizeBits)) - val len = Reg(UInt(width = nastiXLenBits)) - val data = Reg(UInt(width = nastiXDataBits)) - val first = Reg(init = Bool(false)) - val is_rtrans = (state === s_read) && - (io.hasti.htrans === HTRANS_SEQ || - io.hasti.htrans === HTRANS_NONSEQ) - val rvalid = RegEnable(is_rtrans, Bool(false), io.hasti.hready) - - io.nasti.aw.ready := (state === s_idle) - io.nasti.ar.ready := (state === s_idle) && !io.nasti.aw.valid - io.nasti.w.ready := (state === s_write) && io.hasti.hready - io.nasti.b.valid := (state === s_write_resp) - io.nasti.b.bits := NastiWriteResponseChannel(id = id) - io.nasti.r <> r_queue.io.deq - - r_queue.io.enq.valid := io.hasti.hready && rvalid - r_queue.io.enq.bits := NastiReadDataChannel( - id = id, - data = io.hasti.hrdata, - last = (len === UInt(0))) - - assert(!r_queue.io.enq.valid || r_queue.io.enq.ready, - "NASTI -> HASTI converter queue overflow") - - // How many read requests have we not delivered a response for yet? - val pending_count = r_queue.io.count + rvalid - - io.hasti.haddr := addr - io.hasti.hsize := size - io.hasti.hwrite := (state === s_write) - io.hasti.hburst := HBURST_INCR - io.hasti.hprot := UInt(0) - io.hasti.hwdata := data - io.hasti.hmastlock := Bool(false) - io.hasti.htrans := MuxLookup(state, HTRANS_IDLE, Seq( - s_write -> Mux(io.nasti.w.valid, - Mux(first, HTRANS_NONSEQ, HTRANS_SEQ), - Mux(first, HTRANS_IDLE, HTRANS_BUSY)), - s_read -> MuxCase(HTRANS_BUSY, Seq( - first -> HTRANS_NONSEQ, - (pending_count <= UInt(1)) -> HTRANS_SEQ)))) - - when (io.nasti.aw.fire()) { - first := Bool(true) - addr := io.nasti.aw.bits.addr - id := io.nasti.aw.bits.id - size := io.nasti.aw.bits.size - state := s_write - } - - when (io.nasti.ar.fire()) { - first := Bool(true) - addr := io.nasti.ar.bits.addr - id := io.nasti.ar.bits.id - size := io.nasti.ar.bits.size - len := io.nasti.ar.bits.len - state := s_read - } - - when (io.nasti.w.fire()) { - first := Bool(false) - addr := addr + (UInt(1) << size) - data := io.nasti.w.bits.data - when (io.nasti.w.bits.last) { state := s_write_resp } - } - - when (io.nasti.b.fire()) { state := s_idle } - - when (is_rtrans && io.hasti.hready) { - first := Bool(false) - addr := addr + (UInt(1) << size) - len := len - UInt(1) - when (len === UInt(0)) { state := s_idle } - } -} - -class HastiTestSRAM(depth: Int)(implicit p: Parameters) extends HastiModule()(p) { - val io = new HastiSlaveIO - - // This is a test SRAM with random delays - val ready = LFSR16(Bool(true))(0) // Bool(true) - - // Calculate the bitmask of which bytes are being accessed - val mask_decode = Vec.tabulate(hastiAlignment+1) (UInt(_) <= io.hsize) - val mask_wide = Vec.tabulate(hastiDataBytes) { i => mask_decode(log2Ceil(i+1)) } - val mask_shift = if (hastiAlignment == 0) UInt(1) else - mask_wide.asUInt() << io.haddr(hastiAlignment-1,0) - - // The request had better have been aligned! (AHB-lite requires this) - if (hastiAlignment >= 1) { - assert (io.htrans === HTRANS_IDLE || io.htrans === HTRANS_BUSY || - (io.haddr & mask_decode.asUInt()(hastiAlignment,1)) === UInt(0), - "HASTI request not aligned") - } - - // The mask and address during the address phase - val a_request = io.hsel && (io.htrans === HTRANS_NONSEQ || io.htrans === HTRANS_SEQ) - val a_mask = Wire(UInt(width = hastiDataBytes)) - val a_address = io.haddr(depth-1, hastiAlignment) - val a_write = io.hwrite - - // for backwards compatibility with chisel2, we needed a static width in definition - a_mask := mask_shift(hastiDataBytes-1, 0) - - // The data phase signals - val d_read = RegEnable(a_request && !a_write, Bool(false), ready) - val d_mask = RegEnable(a_mask, ready && a_request) - val d_wdata = Vec.tabulate(hastiDataBytes) { i => io.hwdata(8*(i+1)-1, 8*i) } - - // AHB writes must occur during the data phase; this poses a structural - // hazard with reads which must occur during the address phase. To solve - // this problem, we delay the writes until there is a free cycle. - // - // The idea is to record the address information from address phase and - // then as soon as possible flush the pending write. This cannot be done - // on a cycle when there is an address phase read, but on any other cycle - // the write will execute. In the case of reads following a write, the - // result must bypass data from the pending write into the read if they - // happen to have matching address. - - // Pending write? - val p_valid = RegInit(Bool(false)) - val p_address = Reg(a_address) - val p_mask = Reg(a_mask) - val p_latch_d = RegNext(ready && a_request && a_write, Bool(false)) - val p_wdata = d_wdata holdUnless p_latch_d - - // Use single-ported memory with byte-write enable - val mem = SeqMem(1 << (depth-hastiAlignment), Vec(hastiDataBytes, Bits(width = 8))) - - // Decide is the SRAM port is used for reading or (potentially) writing - val read = ready && a_request && !a_write - // In case we are stalled, we need to hold the read data - val d_rdata = mem.readAndHold(a_address, read) - // Whenever the port is not needed for reading, execute pending writes - when (!read && p_valid) { mem.write(p_address, p_wdata, p_mask.toBools) } - when (!read) { p_valid := Bool(false) } - - // Record the request for later? - when (ready && a_request && a_write) { - p_valid := Bool(true) - p_address := a_address - p_mask := a_mask - } - - // Does the read need to be muxed with the previous write? - val a_bypass = a_address === p_address && p_valid - val d_bypass = RegEnable(a_bypass, ready && a_request) - - // Mux in data from the pending write - val muxdata = Vec((p_mask.toBools zip (p_wdata zip d_rdata)) - map { case (m, (p, r)) => Mux(d_bypass && m, p, r) }) - // Wipe out any data the master should not see (for testing) - val outdata = Vec((d_mask.toBools zip muxdata) - map { case (m, p) => Mux(d_read && ready && m, p, Bits(0)) }) - - // Finally, the outputs - io.hrdata := outdata.asUInt - io.hready := ready - io.hresp := HRESP_OKAY -} - -class HastiTest(implicit p: Parameters) extends UnitTest { - val sram = Module(new HastiTestSRAM(8)) - val bus = Module(new HastiBus(Seq(a => Bool(true)))) - val conv = Module(new HastiMasterIONastiIOConverter) - val driver = Module(new NastiDriver(32, 8, 2)) - - bus.io.slaves(0) <> sram.io - bus.io.master <> conv.io.hasti - conv.io.nasti <> driver.io.nasti - io.finished := driver.io.finished - driver.io.start := io.start -} diff --git a/src/main/scala/junctions/nasti.scala b/src/main/scala/junctions/nasti.scala deleted file mode 100644 index 0407cdc8..00000000 --- a/src/main/scala/junctions/nasti.scala +++ /dev/null @@ -1,532 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package junctions -import Chisel._ -import scala.math.max -import scala.collection.mutable.ArraySeq -import util._ -import config._ - -case object NastiKey extends Field[NastiParameters] - -case class NastiParameters(dataBits: Int, addrBits: Int, idBits: Int) - -trait HasNastiParameters { - implicit val p: Parameters - val nastiExternal = p(NastiKey) - val nastiXDataBits = nastiExternal.dataBits - val nastiWStrobeBits = nastiXDataBits / 8 - val nastiXAddrBits = nastiExternal.addrBits - val nastiWIdBits = nastiExternal.idBits - val nastiRIdBits = nastiExternal.idBits - val nastiXIdBits = max(nastiWIdBits, nastiRIdBits) - val nastiXUserBits = 1 - val nastiAWUserBits = nastiXUserBits - val nastiWUserBits = nastiXUserBits - val nastiBUserBits = nastiXUserBits - val nastiARUserBits = nastiXUserBits - val nastiRUserBits = nastiXUserBits - val nastiXLenBits = 8 - val nastiXSizeBits = 3 - val nastiXBurstBits = 2 - val nastiXCacheBits = 4 - val nastiXProtBits = 3 - val nastiXQosBits = 4 - val nastiXRegionBits = 4 - val nastiXRespBits = 2 - - def bytesToXSize(bytes: UInt) = MuxLookup(bytes, UInt("b111"), Array( - UInt(1) -> UInt(0), - UInt(2) -> UInt(1), - UInt(4) -> UInt(2), - UInt(8) -> UInt(3), - UInt(16) -> UInt(4), - UInt(32) -> UInt(5), - UInt(64) -> UInt(6), - UInt(128) -> UInt(7))) -} - -abstract class NastiModule(implicit val p: Parameters) extends Module - with HasNastiParameters -abstract class NastiBundle(implicit val p: Parameters) extends ParameterizedBundle()(p) - with HasNastiParameters - -abstract class NastiChannel(implicit p: Parameters) extends NastiBundle()(p) -abstract class NastiMasterToSlaveChannel(implicit p: Parameters) extends NastiChannel()(p) -abstract class NastiSlaveToMasterChannel(implicit p: Parameters) extends NastiChannel()(p) - -trait HasNastiMetadata extends HasNastiParameters { - val addr = UInt(width = nastiXAddrBits) - val len = UInt(width = nastiXLenBits) - val size = UInt(width = nastiXSizeBits) - val burst = UInt(width = nastiXBurstBits) - val lock = Bool() - val cache = UInt(width = nastiXCacheBits) - val prot = UInt(width = nastiXProtBits) - val qos = UInt(width = nastiXQosBits) - val region = UInt(width = nastiXRegionBits) -} - -trait HasNastiData extends HasNastiParameters { - val data = UInt(width = nastiXDataBits) - val last = Bool() -} - -class NastiReadIO(implicit val p: Parameters) extends ParameterizedBundle()(p) { - val ar = Decoupled(new NastiReadAddressChannel) - val r = Decoupled(new NastiReadDataChannel).flip -} - -class NastiWriteIO(implicit val p: Parameters) extends ParameterizedBundle()(p) { - val aw = Decoupled(new NastiWriteAddressChannel) - val w = Decoupled(new NastiWriteDataChannel) - val b = Decoupled(new NastiWriteResponseChannel).flip -} - -class NastiIO(implicit val p: Parameters) extends ParameterizedBundle()(p) { - val aw = Decoupled(new NastiWriteAddressChannel) - val w = Decoupled(new NastiWriteDataChannel) - val b = Decoupled(new NastiWriteResponseChannel).flip - val ar = Decoupled(new NastiReadAddressChannel) - val r = Decoupled(new NastiReadDataChannel).flip -} - -class NastiAddressChannel(implicit p: Parameters) extends NastiMasterToSlaveChannel()(p) - with HasNastiMetadata - -class NastiResponseChannel(implicit p: Parameters) extends NastiSlaveToMasterChannel()(p) { - val resp = UInt(width = nastiXRespBits) -} - -class NastiWriteAddressChannel(implicit p: Parameters) extends NastiAddressChannel()(p) { - val id = UInt(width = nastiWIdBits) - val user = UInt(width = nastiAWUserBits) -} - -class NastiWriteDataChannel(implicit p: Parameters) extends NastiMasterToSlaveChannel()(p) - with HasNastiData { - val id = UInt(width = nastiWIdBits) - val strb = UInt(width = nastiWStrobeBits) - val user = UInt(width = nastiWUserBits) -} - -class NastiWriteResponseChannel(implicit p: Parameters) extends NastiResponseChannel()(p) { - val id = UInt(width = nastiWIdBits) - val user = UInt(width = nastiBUserBits) -} - -class NastiReadAddressChannel(implicit p: Parameters) extends NastiAddressChannel()(p) { - val id = UInt(width = nastiRIdBits) - val user = UInt(width = nastiARUserBits) -} - -class NastiReadDataChannel(implicit p: Parameters) extends NastiResponseChannel()(p) - with HasNastiData { - val id = UInt(width = nastiRIdBits) - val user = UInt(width = nastiRUserBits) -} - -object NastiConstants { - def BURST_FIXED = UInt("b00") - def BURST_INCR = UInt("b01") - def BURST_WRAP = UInt("b10") - - def RESP_OKAY = UInt("b00") - def RESP_EXOKAY = UInt("b01") - def RESP_SLVERR = UInt("b10") - def RESP_DECERR = UInt("b11") - - def CACHE_DEVICE_NOBUF = UInt("b0000") - def CACHE_DEVICE_BUF = UInt("b0001") - def CACHE_NORMAL_NOCACHE_NOBUF = UInt("b0010") - def CACHE_NORMAL_NOCACHE_BUF = UInt("b0011") - - def AXPROT(instruction: Bool, nonsecure: Bool, privileged: Bool): UInt = - Cat(instruction, nonsecure, privileged) - - def AXPROT(instruction: Boolean, nonsecure: Boolean, privileged: Boolean): UInt = - AXPROT(Bool(instruction), Bool(nonsecure), Bool(privileged)) -} - -import NastiConstants._ - -object NastiWriteAddressChannel { - def apply(id: UInt, addr: UInt, size: UInt, - len: UInt = UInt(0), burst: UInt = BURST_INCR) - (implicit p: Parameters) = { - val aw = Wire(new NastiWriteAddressChannel) - aw.id := id - aw.addr := addr - aw.len := len - aw.size := size - aw.burst := burst - aw.lock := Bool(false) - aw.cache := CACHE_DEVICE_NOBUF - aw.prot := AXPROT(false, false, false) - aw.qos := UInt("b0000") - aw.region := UInt("b0000") - aw.user := UInt(0) - aw - } -} - -object NastiReadAddressChannel { - def apply(id: UInt, addr: UInt, size: UInt, - len: UInt = UInt(0), burst: UInt = BURST_INCR) - (implicit p: Parameters) = { - val ar = Wire(new NastiReadAddressChannel) - ar.id := id - ar.addr := addr - ar.len := len - ar.size := size - ar.burst := burst - ar.lock := Bool(false) - ar.cache := CACHE_DEVICE_NOBUF - ar.prot := AXPROT(false, false, false) - ar.qos := UInt(0) - ar.region := UInt(0) - ar.user := UInt(0) - ar - } -} - -object NastiWriteDataChannel { - def apply(data: UInt, strb: Option[UInt] = None, - last: Bool = Bool(true), id: UInt = UInt(0)) - (implicit p: Parameters): NastiWriteDataChannel = { - val w = Wire(new NastiWriteDataChannel) - w.strb := strb.getOrElse(Fill(w.nastiWStrobeBits, UInt(1, 1))) - w.data := data - w.last := last - w.id := id - w.user := UInt(0) - w - } -} - -object NastiReadDataChannel { - def apply(id: UInt, data: UInt, last: Bool = Bool(true), resp: UInt = UInt(0))( - implicit p: Parameters) = { - val r = Wire(new NastiReadDataChannel) - r.id := id - r.data := data - r.last := last - r.resp := resp - r.user := UInt(0) - r - } -} - -object NastiWriteResponseChannel { - def apply(id: UInt, resp: UInt = UInt(0))(implicit p: Parameters) = { - val b = Wire(new NastiWriteResponseChannel) - b.id := id - b.resp := resp - b.user := UInt(0) - b - } -} - -class NastiArbiterIO(arbN: Int)(implicit p: Parameters) extends Bundle { - val master = Vec(arbN, new NastiIO).flip - val slave = new NastiIO - override def cloneType = - new NastiArbiterIO(arbN).asInstanceOf[this.type] -} - -/** Arbitrate among arbN masters requesting to a single slave */ -class NastiArbiter(val arbN: Int)(implicit p: Parameters) extends NastiModule { - val io = new NastiArbiterIO(arbN) - - if (arbN > 1) { - val arbIdBits = log2Up(arbN) - - val ar_arb = Module(new RRArbiter(new NastiReadAddressChannel, arbN)) - val aw_arb = Module(new RRArbiter(new NastiWriteAddressChannel, arbN)) - - val slave_r_arb_id = io.slave.r.bits.id(arbIdBits - 1, 0) - val slave_b_arb_id = io.slave.b.bits.id(arbIdBits - 1, 0) - - val w_chosen = Reg(UInt(width = arbIdBits)) - val w_done = Reg(init = Bool(true)) - - when (aw_arb.io.out.fire()) { - w_chosen := aw_arb.io.chosen - w_done := Bool(false) - } - - when (io.slave.w.fire() && io.slave.w.bits.last) { - w_done := Bool(true) - } - - for (i <- 0 until arbN) { - val m_ar = io.master(i).ar - val m_aw = io.master(i).aw - val m_r = io.master(i).r - val m_b = io.master(i).b - val a_ar = ar_arb.io.in(i) - val a_aw = aw_arb.io.in(i) - val m_w = io.master(i).w - - a_ar <> m_ar - a_ar.bits.id := Cat(m_ar.bits.id, UInt(i, arbIdBits)) - - a_aw <> m_aw - a_aw.bits.id := Cat(m_aw.bits.id, UInt(i, arbIdBits)) - - m_r.valid := io.slave.r.valid && slave_r_arb_id === UInt(i) - m_r.bits := io.slave.r.bits - m_r.bits.id := io.slave.r.bits.id >> UInt(arbIdBits) - - m_b.valid := io.slave.b.valid && slave_b_arb_id === UInt(i) - m_b.bits := io.slave.b.bits - m_b.bits.id := io.slave.b.bits.id >> UInt(arbIdBits) - - m_w.ready := io.slave.w.ready && w_chosen === UInt(i) && !w_done - } - - io.slave.r.ready := io.master(slave_r_arb_id).r.ready - io.slave.b.ready := io.master(slave_b_arb_id).b.ready - - io.slave.w.bits := io.master(w_chosen).w.bits - io.slave.w.valid := io.master(w_chosen).w.valid && !w_done - - io.slave.ar <> ar_arb.io.out - - io.slave.aw.bits <> aw_arb.io.out.bits - io.slave.aw.valid := aw_arb.io.out.valid && w_done - aw_arb.io.out.ready := io.slave.aw.ready && w_done - - } else { io.slave <> io.master.head } -} - -/** A slave that send decode error for every request it receives */ -class NastiErrorSlave(implicit p: Parameters) extends NastiModule { - val io = (new NastiIO).flip - - when (io.ar.fire()) { printf("Invalid read address %x\n", io.ar.bits.addr) } - when (io.aw.fire()) { printf("Invalid write address %x\n", io.aw.bits.addr) } - - val r_queue = Module(new Queue(new NastiReadAddressChannel, 1)) - r_queue.io.enq <> io.ar - - val responding = Reg(init = Bool(false)) - val beats_left = Reg(init = UInt(0, nastiXLenBits)) - - when (!responding && r_queue.io.deq.valid) { - responding := Bool(true) - beats_left := r_queue.io.deq.bits.len - } - - io.r.valid := r_queue.io.deq.valid && responding - io.r.bits.id := r_queue.io.deq.bits.id - io.r.bits.data := UInt(0) - io.r.bits.resp := RESP_DECERR - io.r.bits.last := beats_left === UInt(0) - - r_queue.io.deq.ready := io.r.fire() && io.r.bits.last - - when (io.r.fire()) { - when (beats_left === UInt(0)) { - responding := Bool(false) - } .otherwise { - beats_left := beats_left - UInt(1) - } - } - - val draining = Reg(init = Bool(false)) - io.w.ready := draining - - when (io.aw.fire()) { draining := Bool(true) } - when (io.w.fire() && io.w.bits.last) { draining := Bool(false) } - - val b_queue = Module(new Queue(UInt(width = nastiWIdBits), 1)) - b_queue.io.enq.valid := io.aw.valid && !draining - b_queue.io.enq.bits := io.aw.bits.id - io.aw.ready := b_queue.io.enq.ready && !draining - io.b.valid := b_queue.io.deq.valid && !draining - io.b.bits.id := b_queue.io.deq.bits - io.b.bits.resp := RESP_DECERR - b_queue.io.deq.ready := io.b.ready && !draining -} - -class NastiRouterIO(nSlaves: Int)(implicit p: Parameters) extends Bundle { - val master = (new NastiIO).flip - val slave = Vec(nSlaves, new NastiIO) - override def cloneType = - new NastiRouterIO(nSlaves).asInstanceOf[this.type] -} - -/** Take a single Nasti master and route its requests to various slaves - * @param nSlaves the number of slaves - * @param routeSel a function which takes an address and produces - * a one-hot encoded selection of the slave to write to */ -class NastiRouter(nSlaves: Int, routeSel: UInt => UInt)(implicit p: Parameters) - extends NastiModule { - - val io = new NastiRouterIO(nSlaves) - - val ar_route = routeSel(io.master.ar.bits.addr) - val aw_route = routeSel(io.master.aw.bits.addr) - - var ar_ready = Bool(false) - var aw_ready = Bool(false) - var w_ready = Bool(false) - - io.slave.zipWithIndex.foreach { case (s, i) => - s.ar.valid := io.master.ar.valid && ar_route(i) - s.ar.bits := io.master.ar.bits - ar_ready = ar_ready || (s.ar.ready && ar_route(i)) - - s.aw.valid := io.master.aw.valid && aw_route(i) - s.aw.bits := io.master.aw.bits - aw_ready = aw_ready || (s.aw.ready && aw_route(i)) - - val chosen = Reg(init = Bool(false)) - when (s.w.fire() && s.w.bits.last) { chosen := Bool(false) } - when (s.aw.fire()) { chosen := Bool(true) } - - s.w.valid := io.master.w.valid && chosen - s.w.bits := io.master.w.bits - w_ready = w_ready || (s.w.ready && chosen) - } - - val r_invalid = !ar_route.orR - val w_invalid = !aw_route.orR - - val err_slave = Module(new NastiErrorSlave) - err_slave.io.ar.valid := r_invalid && io.master.ar.valid - err_slave.io.ar.bits := io.master.ar.bits - err_slave.io.aw.valid := w_invalid && io.master.aw.valid - err_slave.io.aw.bits := io.master.aw.bits - err_slave.io.w.valid := io.master.w.valid - err_slave.io.w.bits := io.master.w.bits - - io.master.ar.ready := ar_ready || (r_invalid && err_slave.io.ar.ready) - io.master.aw.ready := aw_ready || (w_invalid && err_slave.io.aw.ready) - io.master.w.ready := w_ready || err_slave.io.w.ready - - val b_arb = Module(new RRArbiter(new NastiWriteResponseChannel, nSlaves + 1)) - val r_arb = Module(new HellaPeekingArbiter( - new NastiReadDataChannel, nSlaves + 1, - // we can unlock if it's the last beat - (r: NastiReadDataChannel) => r.last)) - - for (i <- 0 until nSlaves) { - b_arb.io.in(i) <> io.slave(i).b - r_arb.io.in(i) <> io.slave(i).r - } - - b_arb.io.in(nSlaves) <> err_slave.io.b - r_arb.io.in(nSlaves) <> err_slave.io.r - - io.master.b <> b_arb.io.out - io.master.r <> r_arb.io.out -} - -/** Crossbar between multiple Nasti masters and slaves - * @param nMasters the number of Nasti masters - * @param nSlaves the number of Nasti slaves - * @param routeSel a function selecting the slave to route an address to */ -class NastiCrossbar(nMasters: Int, nSlaves: Int, routeSel: UInt => UInt) - (implicit p: Parameters) extends NastiModule { - val io = new Bundle { - val masters = Vec(nMasters, new NastiIO).flip - val slaves = Vec(nSlaves, new NastiIO) - } - - if (nMasters == 1) { - val router = Module(new NastiRouter(nSlaves, routeSel)) - router.io.master <> io.masters.head - io.slaves <> router.io.slave - } else { - val routers = Vec.fill(nMasters) { Module(new NastiRouter(nSlaves, routeSel)).io } - val arbiters = Vec.fill(nSlaves) { Module(new NastiArbiter(nMasters)).io } - - for (i <- 0 until nMasters) { - routers(i).master <> io.masters(i) - } - - for (i <- 0 until nSlaves) { - arbiters(i).master <> Vec(routers.map(r => r.slave(i))) - io.slaves(i) <> arbiters(i).slave - } - } -} - -class NastiInterconnectIO(val nMasters: Int, val nSlaves: Int) - (implicit p: Parameters) extends Bundle { - /* This is a bit confusing. The interconnect is a slave to the masters and - * a master to the slaves. Hence why the declarations seem to be backwards. */ - val masters = Vec(nMasters, new NastiIO).flip - val slaves = Vec(nSlaves, new NastiIO) - override def cloneType = - new NastiInterconnectIO(nMasters, nSlaves).asInstanceOf[this.type] -} - -abstract class NastiInterconnect(implicit p: Parameters) extends NastiModule()(p) { - val nMasters: Int - val nSlaves: Int - - lazy val io = new NastiInterconnectIO(nMasters, nSlaves) -} - -class NastiRecursiveInterconnect(val nMasters: Int, addrMap: AddrMap) - (implicit p: Parameters) extends NastiInterconnect()(p) { - def port(name: String) = io.slaves(addrMap.port(name)) - val nSlaves = addrMap.numSlaves - val routeSel = (addr: UInt) => - Cat(addrMap.entries.map(e => addrMap(e.name).containsAddress(addr)).reverse) - - val xbar = Module(new NastiCrossbar(nMasters, addrMap.length, routeSel)) - xbar.io.masters <> io.masters - - io.slaves <> addrMap.entries.zip(xbar.io.slaves).flatMap { - case (entry, xbarSlave) => { - entry.region match { - case submap: AddrMap if submap.entries.isEmpty => - val err_slave = Module(new NastiErrorSlave) - err_slave.io <> xbarSlave - None - case submap: AddrMap => - val ic = Module(new NastiRecursiveInterconnect(1, submap)) - ic.io.masters.head <> xbarSlave - ic.io.slaves - case r: MemRange => - Some(xbarSlave) - } - } - } -} - -object AsyncNastiCrossing { - // takes from_source from the 'from' clock domain to the 'to' clock domain - def apply(from_clock: Clock, from_reset: Bool, from_source: NastiIO, to_clock: Clock, to_reset: Bool, depth: Int = 8, sync: Int = 3) = { - val to_sink = Wire(new NastiIO()(from_source.p)) - - to_sink.aw <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.aw, to_clock, to_reset, depth, sync) - to_sink.ar <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.ar, to_clock, to_reset, depth, sync) - to_sink.w <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.w, to_clock, to_reset, depth, sync) - from_source.b <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.b, from_clock, from_reset, depth, sync) - from_source.r <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.r, from_clock, from_reset, depth, sync) - - to_sink // is now to_source - } -} - -object AsyncNastiTo { - // takes source from your clock domain and puts it into the 'to' clock domain - def apply(to_clock: Clock, to_reset: Bool, source: NastiIO, depth: Int = 8, sync: Int = 3): NastiIO = { - val scope = AsyncScope() - AsyncNastiCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) - } -} - -object AsyncNastiFrom { - // takes from_source from the 'from' clock domain and puts it into your clock domain - def apply(from_clock: Clock, from_reset: Bool, from_source: NastiIO, depth: Int = 8, sync: Int = 3): NastiIO = { - val scope = AsyncScope() - AsyncNastiCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) - } -} diff --git a/src/main/scala/junctions/package.scala b/src/main/scala/junctions/package.scala deleted file mode 100644 index 1c5762e9..00000000 --- a/src/main/scala/junctions/package.scala +++ /dev/null @@ -1,3 +0,0 @@ -// See LICENSE.SiFive for license details. - -package object junctions diff --git a/src/main/scala/junctions/poci.scala b/src/main/scala/junctions/poci.scala deleted file mode 100644 index f566e4dd..00000000 --- a/src/main/scala/junctions/poci.scala +++ /dev/null @@ -1,85 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package junctions - -import Chisel._ -import config._ - -class PociIO(implicit p: Parameters) extends HastiBundle()(p) -{ - val paddr = UInt(OUTPUT, hastiAddrBits) - val pwrite = Bool(OUTPUT) - val psel = Bool(OUTPUT) - val penable = Bool(OUTPUT) - val pwdata = UInt(OUTPUT, hastiDataBits) - val prdata = UInt(INPUT, hastiDataBits) - val pready = Bool(INPUT) - val pslverr = Bool(INPUT) -} - -class HastiToPociBridge(implicit p: Parameters) extends HastiModule()(p) { - val io = new Bundle { - val in = new HastiSlaveIO - val out = new PociIO - } - - val s_idle :: s_setup :: s_access :: Nil = Enum(UInt(), 3) - val state = Reg(init = s_idle) - val transfer = io.in.hsel & io.in.htrans(1) - - switch (state) { - is (s_idle) { - when (transfer) { state := s_setup } - } - is (s_setup) { - state := s_access - } - is (s_access) { - when (io.out.pready & ~transfer) { state := s_idle } - when (io.out.pready & transfer) { state := s_setup } - when (~io.out.pready) { state := s_access } - } - } - - val haddr_reg = Reg(UInt(width = hastiAddrBits)) - val hwrite_reg = Reg(UInt(width = 1)) - when (transfer) { - haddr_reg := io.in.haddr - hwrite_reg := io.in.hwrite - } - - io.out.paddr := haddr_reg - io.out.pwrite := hwrite_reg(0) - io.out.psel := (state =/= s_idle) - io.out.penable := (state === s_access) - io.out.pwdata := io.in.hwdata - io.in.hrdata := io.out.prdata - io.in.hready := ((state === s_access) & io.out.pready) | (state === s_idle) - io.in.hresp := io.out.pslverr -} - -class PociBus(amap: Seq[UInt=>Bool])(implicit p: Parameters) extends HastiModule()(p) -{ - val io = new Bundle { - val master = new PociIO().flip - val slaves = Vec(amap.size, new PociIO) - } - - val psels = PriorityEncoderOH( - (io.slaves zip amap) map { case (s, afn) => { - s.paddr := io.master.paddr - s.pwrite := io.master.pwrite - s.pwdata := io.master.pwdata - afn(io.master.paddr) && io.master.psel - }}) - - (io.slaves zip psels) foreach { case (s, psel) => { - s.psel := psel - s.penable := io.master.penable && psel - } } - - io.master.prdata := Mux1H(psels, io.slaves.map(_.prdata)) - io.master.pready := Mux1H(psels, io.slaves.map(_.pready)) - io.master.pslverr := Mux1H(psels, io.slaves.map(_.pslverr)) -} diff --git a/src/main/scala/junctions/slowio.scala b/src/main/scala/junctions/slowio.scala deleted file mode 100644 index 04c98a05..00000000 --- a/src/main/scala/junctions/slowio.scala +++ /dev/null @@ -1,65 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package junctions -import Chisel._ - -class SlowIO[T <: Data](val divisor_max: Int)(data: => T) extends Module -{ - val io = new Bundle { - val out_fast = Decoupled(data).flip - val out_slow = Decoupled(data) - val in_fast = Decoupled(data) - val in_slow = Decoupled(data).flip - val clk_slow = Bool(OUTPUT) - - val divisor = UInt(INPUT, log2Up(divisor_max)) - val hold = UInt(INPUT, log2Up(divisor_max)) - } - - require(divisor_max >= 8 && divisor_max <= 65536 && isPow2(divisor_max)) - - val divisor = Reg(init=UInt(divisor_max-1)) - val hold = Reg(init=UInt(divisor_max/4-1)) - - val count = Reg{UInt(width = log2Up(divisor_max))} - val myclock = Reg{Bool()} - count := count + UInt(1) - - val rising = count === (divisor >> 1) - val falling = count === divisor - val held = count === (divisor >> 1) + hold - - when (falling) { - divisor := io.divisor - hold := io.hold - count := UInt(0) - myclock := Bool(false) - } - when (rising) { - myclock := Bool(true) - } - - val in_slow_rdy = Reg(init=Bool(false)) - val out_slow_val = Reg(init=Bool(false)) - val out_slow_bits = Reg(data) - - val fromhost_q = Module(new Queue(data,1)) - fromhost_q.io.enq.valid := rising && (io.in_slow.valid && in_slow_rdy || this.reset) - fromhost_q.io.enq.bits := io.in_slow.bits - io.in_fast <> fromhost_q.io.deq - - val tohost_q = Module(new Queue(data,1)) - tohost_q.io.enq <> io.out_fast - tohost_q.io.deq.ready := rising && io.out_slow.ready && out_slow_val - - when (held) { - in_slow_rdy := fromhost_q.io.enq.ready - out_slow_val := tohost_q.io.deq.valid - out_slow_bits := Mux(this.reset, fromhost_q.io.deq.bits, tohost_q.io.deq.bits) - } - - io.in_slow.ready := in_slow_rdy - io.out_slow.valid := out_slow_val - io.out_slow.bits := out_slow_bits - io.clk_slow := myclock -} diff --git a/src/main/scala/junctions/stream.scala b/src/main/scala/junctions/stream.scala deleted file mode 100644 index 940b4217..00000000 --- a/src/main/scala/junctions/stream.scala +++ /dev/null @@ -1,192 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package junctions - -import Chisel._ -import NastiConstants._ -import config._ - -class StreamChannel(w: Int) extends Bundle { - val data = UInt(width = w) - val last = Bool() - - override def cloneType = new StreamChannel(w).asInstanceOf[this.type] -} - -class StreamIO(w: Int) extends Bundle { - val out = Decoupled(new StreamChannel(w)) - val in = Decoupled(new StreamChannel(w)).flip - - override def cloneType = new StreamIO(w).asInstanceOf[this.type] -} - -class NastiIOStreamIOConverter(w: Int)(implicit p: Parameters) extends Module { - val io = new Bundle { - val nasti = (new NastiIO).flip - val stream = new StreamIO(w) - } - - val streamSize = UInt(log2Up(w / 8)) - assert(!io.nasti.ar.valid || io.nasti.ar.bits.size === streamSize, - "read channel wrong size on stream") - assert(!io.nasti.ar.valid || io.nasti.ar.bits.len === UInt(0) || - io.nasti.ar.bits.burst === BURST_FIXED, - "read channel wrong burst type on stream") - assert(!io.nasti.aw.valid || io.nasti.aw.bits.size === streamSize, - "write channel wrong size on stream") - assert(!io.nasti.aw.valid || io.nasti.aw.bits.len === UInt(0) || - io.nasti.aw.bits.burst === BURST_FIXED, - "write channel wrong burst type on stream") - assert(!io.nasti.w.valid || io.nasti.w.bits.strb.andR, - "write channel cannot take partial writes") - - val read_id = Reg(io.nasti.ar.bits.id) - val read_cnt = Reg(io.nasti.ar.bits.len) - val reading = Reg(init = Bool(false)) - - io.nasti.ar.ready := !reading - io.nasti.r.valid := reading && io.stream.in.valid - io.nasti.r.bits := io.stream.in.bits - io.nasti.r.bits.resp := RESP_OKAY - io.nasti.r.bits.id := read_id - io.stream.in.ready := reading && io.nasti.r.ready - - when (io.nasti.ar.fire()) { - read_id := io.nasti.ar.bits.id - read_cnt := io.nasti.ar.bits.len - reading := Bool(true) - } - - when (io.nasti.r.fire()) { - when (read_cnt === UInt(0)) { - reading := Bool(false) - } .otherwise { - read_cnt := read_cnt - UInt(1) - } - } - - val write_id = Reg(io.nasti.aw.bits.id) - val writing = Reg(init = Bool(false)) - val write_resp = Reg(init = Bool(false)) - - io.nasti.aw.ready := !writing && !write_resp - io.nasti.w.ready := writing && io.stream.out.ready - io.stream.out.valid := writing && io.nasti.w.valid - io.stream.out.bits := io.nasti.w.bits - io.nasti.b.valid := write_resp - io.nasti.b.bits.resp := RESP_OKAY - io.nasti.b.bits.id := write_id - - when (io.nasti.aw.fire()) { - write_id := io.nasti.aw.bits.id - writing := Bool(true) - } - - when (io.nasti.w.fire() && io.nasti.w.bits.last) { - writing := Bool(false) - write_resp := Bool(true) - } - - when (io.nasti.b.fire()) { write_resp := Bool(false) } -} - -class StreamNarrower(win: Int, wout: Int) extends Module { - require(win > wout, "Stream narrower input width must be larger than input width") - require(win % wout == 0, "Stream narrower input width must be multiple of output width") - - val io = new Bundle { - val in = Decoupled(new StreamChannel(win)).flip - val out = Decoupled(new StreamChannel(wout)) - } - - val n_pieces = win / wout - val buffer = Reg(Bits(width = win)) - val (piece_idx, pkt_done) = Counter(io.out.fire(), n_pieces) - val pieces = Vec.tabulate(n_pieces) { i => buffer(wout * (i + 1) - 1, wout * i) } - val last_piece = (piece_idx === UInt(n_pieces - 1)) - val sending = Reg(init = Bool(false)) - val in_last = Reg(Bool()) - - when (io.in.fire()) { - buffer := io.in.bits.data - in_last := io.in.bits.last - sending := Bool(true) - } - when (pkt_done) { sending := Bool(false) } - - io.out.valid := sending - io.out.bits.data := pieces(piece_idx) - io.out.bits.last := in_last && last_piece - io.in.ready := !sending -} - -class StreamExpander(win: Int, wout: Int) extends Module { - require(win < wout, "Stream expander input width must be smaller than input width") - require(wout % win == 0, "Stream narrower output width must be multiple of input width") - - val io = new Bundle { - val in = Decoupled(new StreamChannel(win)).flip - val out = Decoupled(new StreamChannel(wout)) - } - - val n_pieces = wout / win - val buffer = Reg(Vec(n_pieces, UInt(width = win))) - val last = Reg(Bool()) - val collecting = Reg(init = Bool(true)) - val (piece_idx, pkt_done) = Counter(io.in.fire(), n_pieces) - - when (io.in.fire()) { buffer(piece_idx) := io.in.bits.data } - when (pkt_done) { last := io.in.bits.last; collecting := Bool(false) } - when (io.out.fire()) { collecting := Bool(true) } - - io.in.ready := collecting - io.out.valid := !collecting - io.out.bits.data := buffer.asUInt - io.out.bits.last := last -} - -object StreamUtils { - def connectStreams(a: StreamIO, b: StreamIO) { - a.in <> b.out - b.in <> a.out - } - def roundUp(n: Int, d: Int) = ((n - 1) / d + 1) * d -} - -class SerialIO(w: Int) extends Bundle { - val out = Decoupled(UInt(width = w)) - val in = Decoupled(UInt(width = w)).flip - override def cloneType = new SerialIO(w).asInstanceOf[this.type] -} - -class Serializer[T <: Data](w: Int, typ: T) extends Module { - val io = new Bundle { - val in = Decoupled(typ).flip - val out = Decoupled(Bits(width = w)) - } - - val narrower = Module(new StreamNarrower(StreamUtils.roundUp(typ.getWidth, w), w)) - narrower.io.in.bits.data := io.in.bits.asUInt - narrower.io.in.bits.last := Bool(true) - narrower.io.in.valid := io.in.valid - io.in.ready := narrower.io.in.ready - io.out.valid := narrower.io.out.valid - io.out.bits := narrower.io.out.bits.data - narrower.io.out.ready := io.out.ready -} - -class Deserializer[T <: Data](w: Int, typ: T) extends Module { - val io = new Bundle { - val in = Decoupled(Bits(width = w)).flip - val out = Decoupled(typ) - } - - val expander = Module(new StreamExpander(w, StreamUtils.roundUp(typ.getWidth, w))) - expander.io.in.valid := io.in.valid - expander.io.in.bits.data := io.in.bits - expander.io.in.bits.last := Bool(true) - io.in.ready := expander.io.in.ready - io.out.valid := expander.io.out.valid - io.out.bits := typ.fromBits(expander.io.out.bits.data) - expander.io.out.ready := io.out.ready -} diff --git a/src/main/scala/regmapper/RegField.scala b/src/main/scala/regmapper/RegField.scala index 597e6b18..b7bfa06d 100644 --- a/src/main/scala/regmapper/RegField.scala +++ b/src/main/scala/regmapper/RegField.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package regmapper +package freechips.rocketchip.regmapper import Chisel._ import chisel3.util.{ReadyValidIO} -import util.{SimpleRegIO} + +import freechips.rocketchip.util.{SimpleRegIO} case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt)) object RegReadFn diff --git a/src/main/scala/regmapper/RegMapper.scala b/src/main/scala/regmapper/RegMapper.scala index 862df684..d449c677 100644 --- a/src/main/scala/regmapper/RegMapper.scala +++ b/src/main/scala/regmapper/RegMapper.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package regmapper +package freechips.rocketchip.regmapper import Chisel._ -import diplomacy._ -import util.{GenericParameterizedBundle} + +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.{GenericParameterizedBundle, ReduceOthers} // A bus agnostic register interface to a register-based device @@ -154,7 +155,7 @@ object RegMapper def mux(valid: Bool, select: Seq[Bool], guard: Seq[Bool], flow: Seq[Seq[(Bool, Bool)]]): Vec[Bool] = Vec(((select zip guard) zip flow).map { case ((s, g), f) => val out = Wire(Bool()) - util.ReduceOthers((out, valid && s && g) +: f) + ReduceOthers((out, valid && s && g) +: f) out || !g }) diff --git a/src/main/scala/regmapper/RegisterCrossing.scala b/src/main/scala/regmapper/RegisterCrossing.scala index 5a59c4e4..212ecedc 100644 --- a/src/main/scala/regmapper/RegisterCrossing.scala +++ b/src/main/scala/regmapper/RegisterCrossing.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package regmapper +package freechips.rocketchip.regmapper import Chisel._ import chisel3.util.{Irrevocable} -import util.{AsyncQueue,AsyncResetRegVec} + +import freechips.rocketchip.util.{AsyncQueue,AsyncResetRegVec} // A very simple flow control state machine, run in the specified clock domain class BusyRegisterCrossing extends Module { diff --git a/src/main/scala/rocket/ALU.scala b/src/main/scala/rocket/ALU.scala index 79a42334..9636bbed 100644 --- a/src/main/scala/rocket/ALU.scala +++ b/src/main/scala/rocket/ALU.scala @@ -1,12 +1,11 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ -import config._ -import tile._ -import Instructions._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.tile.CoreModule object ALU { @@ -44,7 +43,9 @@ object ALU def cmpInverted(cmd: UInt) = cmd(0) def cmpEq(cmd: UInt) = !cmd(3) } + import ALU._ +import Instructions._ class ALU(implicit p: Parameters) extends CoreModule()(p) { val io = new Bundle { diff --git a/src/main/scala/uncore/util/AmoAlu.scala b/src/main/scala/rocket/AMOALU.scala similarity index 97% rename from src/main/scala/uncore/util/AmoAlu.scala rename to src/main/scala/rocket/AMOALU.scala index 703d059b..0364d250 100644 --- a/src/main/scala/uncore/util/AmoAlu.scala +++ b/src/main/scala/rocket/AMOALU.scala @@ -1,12 +1,10 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package uncore.util +package freechips.rocketchip.rocket import Chisel._ -import uncore.tilelink._ -import config._ -import uncore.constants._ +import freechips.rocketchip.config.Parameters class StoreGen(typ: UInt, addr: UInt, dat: UInt, maxSize: Int) { val size = typ(log2Up(log2Up(maxSize)+1)-1,0) diff --git a/src/main/scala/rocket/BTB.scala b/src/main/scala/rocket/BTB.scala index 1d9491bc..80371dd4 100644 --- a/src/main/scala/rocket/BTB.scala +++ b/src/main/scala/rocket/BTB.scala @@ -1,13 +1,14 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import tile.HasCoreParameters -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.coreplex.CacheBlockBytes +import freechips.rocketchip.tile.HasCoreParameters +import freechips.rocketchip.util._ case class BTBParams( nEntries: Int = 40, @@ -18,7 +19,7 @@ case class BTBParams( trait HasBtbParameters extends HasCoreParameters { val btbParams = tileParams.btb.getOrElse(BTBParams(nEntries = 0)) - val matchBits = btbParams.nMatchBits max log2Ceil(p(coreplex.CacheBlockBytes) * tileParams.icache.get.nSets) + val matchBits = btbParams.nMatchBits max log2Ceil(p(CacheBlockBytes) * tileParams.icache.get.nSets) val entries = btbParams.nEntries val nRAS = btbParams.nRAS val updatesOutOfOrder = btbParams.updatesOutOfOrder diff --git a/src/main/scala/rocket/Breakpoint.scala b/src/main/scala/rocket/Breakpoint.scala index 9d62502e..e0282793 100644 --- a/src/main/scala/rocket/Breakpoint.scala +++ b/src/main/scala/rocket/Breakpoint.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import tile._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.tile.{CoreModule, CoreBundle} +import freechips.rocketchip.util._ class BPControl(implicit p: Parameters) extends CoreBundle()(p) { val ttype = UInt(width = 4) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 82e417ac..08177c3e 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -1,17 +1,15 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocket - -import collection.mutable.LinkedHashMap +package freechips.rocketchip.rocket import Chisel._ -import Instructions._ -import config._ -import tile._ -import uncore.devices._ -import util._ import Chisel.ImplicitConversions._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.tile._ +import freechips.rocketchip.util._ +import scala.collection.mutable.LinkedHashMap +import Instructions._ class MStatus extends Bundle { // not truly part of mstatus, but convenient diff --git a/src/main/scala/rocket/Consts.scala b/src/main/scala/rocket/Consts.scala index 958b3294..bde6201d 100644 --- a/src/main/scala/rocket/Consts.scala +++ b/src/main/scala/rocket/Consts.scala @@ -1,9 +1,9 @@ // See LICENSE.Berkeley for license details. -package rocket -package constants +package freechips.rocketchip.rocket.constants import Chisel._ +import freechips.rocketchip.util._ import scala.math._ trait ScalarOpConstants { @@ -59,3 +59,38 @@ trait ScalarOpConstants { def DW_64 = Bool(true) def DW_XPR = DW_64 } + +trait MemoryOpConstants { + val NUM_XA_OPS = 9 + val M_SZ = 5 + def M_X = BitPat("b?????"); + def M_XRD = UInt("b00000"); // int load + def M_XWR = UInt("b00001"); // int store + def M_PFR = UInt("b00010"); // prefetch with intent to read + def M_PFW = UInt("b00011"); // prefetch with intent to write + def M_XA_SWAP = UInt("b00100"); + def M_FLUSH_ALL = UInt("b00101") // flush all lines + def M_XLR = UInt("b00110"); + def M_XSC = UInt("b00111"); + def M_XA_ADD = UInt("b01000"); + def M_XA_XOR = UInt("b01001"); + def M_XA_OR = UInt("b01010"); + def M_XA_AND = UInt("b01011"); + def M_XA_MIN = UInt("b01100"); + def M_XA_MAX = UInt("b01101"); + def M_XA_MINU = UInt("b01110"); + def M_XA_MAXU = UInt("b01111"); + def M_FLUSH = UInt("b10000") // write back dirty data and cede R/W permissions + def M_PWR = UInt("b10001") // partial (masked) store + def M_PRODUCE = UInt("b10010") // write back dirty data and cede W permissions + def M_CLEAN = UInt("b10011") // write back dirty data and retain R/W permissions + def M_SFENCE = UInt("b10100") // flush TLB + + def isAMOLogical(cmd: UInt) = cmd.isOneOf(M_XA_SWAP, M_XA_XOR, M_XA_OR, M_XA_AND) + def isAMOArithmetic(cmd: UInt) = cmd.isOneOf(M_XA_ADD, M_XA_MIN, M_XA_MAX, M_XA_MINU, M_XA_MAXU) + def isAMO(cmd: UInt) = isAMOLogical(cmd) || isAMOArithmetic(cmd) + def isPrefetch(cmd: UInt) = cmd === M_PFR || cmd === M_PFW + def isRead(cmd: UInt) = cmd === M_XRD || cmd === M_XLR || cmd === M_XSC || isAMO(cmd) + def isWrite(cmd: UInt) = cmd === M_XWR || cmd === M_PWR || cmd === M_XSC || isAMO(cmd) + def isWriteIntent(cmd: UInt) = isWrite(cmd) || cmd === M_PFW || cmd === M_XLR +} diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 8717774e..3106e18b 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -1,15 +1,14 @@ // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import diplomacy._ -import uncore.constants._ -import uncore.tilelink2._ -import uncore.util._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.coreplex.{RationalCrossing, RocketCrossing, RocketTilesKey} +import freechips.rocketchip.diplomacy.AddressSet +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ import TLMessages._ class DCacheDataReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) { @@ -83,8 +82,8 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { dataArb.io.out.ready := true metaArb.io.out.ready := true - val rational = p(coreplex.RocketCrossing) match { - case coreplex.RationalCrossing(_) => true + val rational = p(RocketCrossing) match { + case RationalCrossing(_) => true case _ => false } @@ -160,7 +159,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val s1_victim_way = Wire(init = replacer.way) val (s1_hit_way, s1_hit_state, s1_meta, s1_victim_meta) = if (usingDataScratchpad) { - val baseAddr = GetPropertyByHartId(p(coreplex.RocketTilesKey), _.dcache.flatMap(_.scratch.map(_.U)), io.hartid) + val baseAddr = GetPropertyByHartId(p(RocketTilesKey), _.dcache.flatMap(_.scratch.map(_.U)), io.hartid) val inScratchpad = s1_paddr >= baseAddr && s1_paddr < baseAddr + nSets * cacheBlockBytes val hitState = Mux(inScratchpad, ClientMetadata.maximum, ClientMetadata.onReset) val dummyMeta = L1Metadata(UInt(0), ClientMetadata.onReset) diff --git a/src/main/scala/rocket/Decode.scala b/src/main/scala/rocket/Decode.scala index feac4aad..5635f725 100644 --- a/src/main/scala/rocket/Decode.scala +++ b/src/main/scala/rocket/Decode.scala @@ -1,20 +1,21 @@ // See LICENSE.Berkeley for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ +import scala.collection.mutable.{ArrayBuffer, Map, Set} object DecodeLogic { def term(lit: BitPat) = new Term(lit.value, BigInt(2).pow(lit.getWidth)-(lit.mask+1)) - def logic(addr: UInt, addrWidth: Int, cache: scala.collection.mutable.Map[Term,Bool], terms: Seq[Term]) = { + def logic(addr: UInt, addrWidth: Int, cache: Map[Term,Bool], terms: Seq[Term]) = { terms.map { t => cache.getOrElseUpdate(t, (if (t.mask == 0) addr else addr & Bits(BigInt(2).pow(addrWidth)-(t.mask+1), addrWidth)) === Bits(t.value, addrWidth)) }.foldLeft(Bool(false))(_||_) } def apply(addr: UInt, default: BitPat, mapping: Iterable[(BitPat, BitPat)]): UInt = { - val cache = caches.getOrElseUpdate(addr, collection.mutable.Map[Term,Bool]()) + val cache = caches.getOrElseUpdate(addr, Map[Term,Bool]()) val dterm = term(default) val (keys, values) = mapping.unzip val addrWidth = keys.map(_.getWidth).max @@ -41,7 +42,7 @@ object DecodeLogic }).reverse) } def apply(addr: UInt, default: Seq[BitPat], mappingIn: Iterable[(BitPat, Seq[BitPat])]): Seq[UInt] = { - val mapping = collection.mutable.ArrayBuffer.fill(default.size)(collection.mutable.ArrayBuffer[(BitPat, BitPat)]()) + val mapping = ArrayBuffer.fill(default.size)(ArrayBuffer[(BitPat, BitPat)]()) for ((key, values) <- mappingIn) for ((value, i) <- values zipWithIndex) mapping(i) += key -> value @@ -52,7 +53,7 @@ object DecodeLogic apply(addr, default, mappingIn.map(m => (BitPat(m._1), m._2)).asInstanceOf[Iterable[(BitPat, Seq[BitPat])]]) def apply(addr: UInt, trues: Iterable[UInt], falses: Iterable[UInt]): Bool = apply(addr, BitPat.dontCare(1), trues.map(BitPat(_) -> BitPat("b1")) ++ falses.map(BitPat(_) -> BitPat("b0"))).toBool - private val caches = collection.mutable.Map[UInt,collection.mutable.Map[Term,Bool]]() + private val caches = Map[UInt,Map[Term,Bool]]() } class Term(val value: BigInt, val mask: BigInt = 0) @@ -87,7 +88,7 @@ object Simplify var prime = List[Term]() implicants.foreach(_.prime = true) val cols = (0 to bits).map(b => implicants.filter(b == _.mask.bitCount)) - val table = cols.map(c => (0 to bits).map(b => collection.mutable.Set(c.filter(b == _.value.bitCount):_*))) + val table = cols.map(c => (0 to bits).map(b => Set(c.filter(b == _.value.bitCount):_*))) for (i <- 0 to bits) { for (j <- 0 until bits-i) table(i)(j).foreach(a => table(i+1)(j) ++= table(i)(j+1).filter(_.similar(a)).map(_.merge(a))) @@ -127,7 +128,7 @@ object Simplify } def getCover(implicants: Seq[Term], minterms: Seq[Term], bits: Int) = { if (minterms.nonEmpty) { - val cover = minterms.map(m => implicants.filter(_.covers(m)).map(i => collection.mutable.Set(i))) + val cover = minterms.map(m => implicants.filter(_.covers(m)).map(i => Set(i))) val all = cover.reduceLeft((c0, c1) => c0.map(a => c1.map(_ ++ a)).reduceLeft(_++_)) all.map(_.toList).reduceLeft((a, b) => if (cheaper(a, b, bits)) a else b) } else @@ -164,7 +165,7 @@ object SimplifyDC minterms.foreach(_.prime = true) var mint = minterms.map(t => new Term(t.value, t.mask)) val cols = (0 to bits).map(b => mint.filter(b == _.mask.bitCount)) - val table = cols.map(c => (0 to bits).map(b => collection.mutable.Set(c.filter(b == _.value.bitCount):_*))) + val table = cols.map(c => (0 to bits).map(b => Set(c.filter(b == _.value.bitCount):_*))) for (i <- 0 to bits) { for (j <- 0 until bits-i) { diff --git a/src/main/scala/rocket/Events.scala b/src/main/scala/rocket/Events.scala index d4aeef76..2800f744 100644 --- a/src/main/scala/rocket/Events.scala +++ b/src/main/scala/rocket/Events.scala @@ -1,10 +1,10 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket -import util._ import Chisel._ +import freechips.rocketchip.util._ class EventSet(gate: (UInt, UInt) => Bool, events: Seq[(String, () => Bool)]) { def size = events.size diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index 7a341047..c72b7dc6 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -1,17 +1,17 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ import chisel3.core.withReset -import config._ -import coreplex._ -import diplomacy._ -import uncore.tilelink2._ -import tile._ -import util._ +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.util._ class FrontendReq(implicit p: Parameters) extends CoreBundle()(p) { val pc = UInt(width = vaddrBitsExtended) diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index 32da7c19..8adc2dd8 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -1,17 +1,15 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ -import config.{Parameters, Field} -import coreplex._ -import diplomacy._ -import tile._ -import uncore.constants._ -import uncore.tilelink2._ -import uncore.util.{Code, IdentityCode} -import util.{ParameterizedBundle, RandomReplacement} +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ import scala.collection.mutable.ListBuffer import scala.math.max diff --git a/src/main/scala/rocket/Arbiter.scala b/src/main/scala/rocket/HellaCacheArbiter.scala similarity index 55% rename from src/main/scala/rocket/Arbiter.scala rename to src/main/scala/rocket/HellaCacheArbiter.scala index e203bf97..ec3acef8 100644 --- a/src/main/scala/rocket/Arbiter.scala +++ b/src/main/scala/rocket/HellaCacheArbiter.scala @@ -1,11 +1,10 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ -import config._ -import util.{ParameterizedBundle, DecoupledHelper} +import freechips.rocketchip.config.Parameters class HellaCacheArbiter(n: Int)(implicit p: Parameters) extends Module { @@ -65,51 +64,3 @@ class HellaCacheArbiter(n: Int)(implicit p: Parameters) extends Module } } } - -class InOrderArbiter[T <: Data, U <: Data](reqTyp: T, respTyp: U, n: Int) - (implicit p: Parameters) extends Module { - val io = new Bundle { - val in_req = Vec(n, Decoupled(reqTyp)).flip - val in_resp = Vec(n, Decoupled(respTyp)) - val out_req = Decoupled(reqTyp) - val out_resp = Decoupled(respTyp).flip - } - - if (n > 1) { - val route_q = Module(new Queue(UInt(width = log2Up(n)), 2)) - val req_arb = Module(new RRArbiter(reqTyp, n)) - req_arb.io.in <> io.in_req - - val req_helper = DecoupledHelper( - req_arb.io.out.valid, - route_q.io.enq.ready, - io.out_req.ready) - - io.out_req.bits := req_arb.io.out.bits - io.out_req.valid := req_helper.fire(io.out_req.ready) - - route_q.io.enq.bits := req_arb.io.chosen - route_q.io.enq.valid := req_helper.fire(route_q.io.enq.ready) - - req_arb.io.out.ready := req_helper.fire(req_arb.io.out.valid) - - val resp_sel = route_q.io.deq.bits - val resp_ready = io.in_resp(resp_sel).ready - val resp_helper = DecoupledHelper( - resp_ready, - route_q.io.deq.valid, - io.out_resp.valid) - - val resp_valid = resp_helper.fire(resp_ready) - for (i <- 0 until n) { - io.in_resp(i).bits := io.out_resp.bits - io.in_resp(i).valid := resp_valid && resp_sel === UInt(i) - } - - route_q.io.deq.ready := resp_helper.fire(route_q.io.deq.valid) - io.out_resp.ready := resp_helper.fire(io.out_resp.valid) - } else { - io.out_req <> io.in_req.head - io.in_resp.head <> io.out_resp - } -} diff --git a/src/main/scala/rocket/IBuf.scala b/src/main/scala/rocket/IBuf.scala index eb94298a..399b394d 100644 --- a/src/main/scala/rocket/IBuf.scala +++ b/src/main/scala/rocket/IBuf.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import tile._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.tile._ +import freechips.rocketchip.util._ class Instruction(implicit val p: Parameters) extends ParameterizedBundle with HasCoreParameters { val xcpt0 = new FrontendExceptions // exceptions on first half of instruction diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index 5cb8c045..2532dee1 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -1,16 +1,16 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ -import config._ -import diplomacy._ -import tile._ -import uncore.tilelink2._ -import uncore.util._ -import util._ import Chisel.ImplicitConversions._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.coreplex.RocketTilesKey +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ case class ICacheParams( nSets: Int = 64, @@ -106,7 +106,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) val scratchpadMax = tl_in.map(tl => Reg(UInt(width = log2Ceil(nSets * (nWays - 1))))) def lineInScratchpad(line: UInt) = scratchpadMax.map(scratchpadOn && line <= _).getOrElse(false.B) def addrMaybeInScratchpad(addr: UInt) = if (outer.icacheParams.itimAddr.isEmpty) false.B else { - val base = GetPropertyByHartId(p(coreplex.RocketTilesKey), _.icache.flatMap(_.itimAddr.map(_.U)), io.hartid) + val base = GetPropertyByHartId(p(RocketTilesKey), _.icache.flatMap(_.itimAddr.map(_.U)), io.hartid) addr >= base && addr < base + outer.size } def addrInScratchpad(addr: UInt) = addrMaybeInScratchpad(addr) && lineInScratchpad(addr(untagBits+log2Ceil(nWays)-1, blockOffBits)) @@ -224,8 +224,8 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) // output signals outer.icacheParams.latency match { case 1 => - require(tECC.isInstanceOf[uncore.util.IdentityCode]) - require(dECC.isInstanceOf[uncore.util.IdentityCode]) + require(tECC.isInstanceOf[IdentityCode]) + require(dECC.isInstanceOf[IdentityCode]) require(outer.icacheParams.itimAddr.isEmpty) io.resp.bits.data := Mux1H(s1_tag_hit, s1_dout) io.resp.bits.ae := s1_tl_error.asUInt.orR diff --git a/src/main/scala/rocket/IDecode.scala b/src/main/scala/rocket/IDecode.scala index ca8ae4ac..bc88b9f8 100644 --- a/src/main/scala/rocket/IDecode.scala +++ b/src/main/scala/rocket/IDecode.scala @@ -1,16 +1,15 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.tile.HasCoreParameters +import freechips.rocketchip.util._ import Instructions._ -import uncore.constants.MemoryOpConstants._ import ALU._ -import config._ -import tile.HasCoreParameters -import util._ abstract trait DecodeConstants extends HasCoreParameters { diff --git a/src/main/scala/rocket/Instructions.scala b/src/main/scala/rocket/Instructions.scala index 81579f57..af61ea77 100644 --- a/src/main/scala/rocket/Instructions.scala +++ b/src/main/scala/rocket/Instructions.scala @@ -1,9 +1,10 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ +import scala.collection.mutable.ArrayBuffer /* Automatically generated by parse-opcodes */ object Instructions { @@ -231,7 +232,7 @@ object Causes { val load_page_fault = 0xd val store_page_fault = 0xf val all = { - val res = collection.mutable.ArrayBuffer[Int]() + val res = ArrayBuffer[Int]() res += misaligned_fetch res += fetch_access res += illegal_instruction @@ -463,7 +464,7 @@ object CSRs { val mhpmcounter30h = 0xb9e val mhpmcounter31h = 0xb9f val all = { - val res = collection.mutable.ArrayBuffer[Int]() + val res = ArrayBuffer[Int]() res += fflags res += frm res += fcsr @@ -615,7 +616,7 @@ object CSRs { res.toArray } val all32 = { - val res = collection.mutable.ArrayBuffer(all:_*) + val res = ArrayBuffer(all:_*) res += cycleh res += timeh res += instreth diff --git a/src/main/scala/rocket/Multiplier.scala b/src/main/scala/rocket/Multiplier.scala index f9ffb08a..2083ffb4 100644 --- a/src/main/scala/rocket/Multiplier.scala +++ b/src/main/scala/rocket/Multiplier.scala @@ -1,12 +1,12 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ -import ALU._ -import util._ import Chisel.ImplicitConversions._ +import freechips.rocketchip.util._ +import ALU._ class MultiplierReq(dataBits: Int, tagBits: Int) extends Bundle { val fn = Bits(width = SZ_ALU_FN) diff --git a/src/main/scala/rocket/NBDcache.scala b/src/main/scala/rocket/NBDcache.scala index 8d5612d3..fd96ec7f 100644 --- a/src/main/scala/rocket/NBDcache.scala +++ b/src/main/scala/rocket/NBDcache.scala @@ -1,16 +1,14 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import diplomacy._ -import uncore.constants._ -import uncore.tilelink2._ -import uncore.util._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ trait HasMissInfo extends HasL1HellaCacheParameters { val tag_match = Bool() diff --git a/src/main/scala/rocket/PMP.scala b/src/main/scala/rocket/PMP.scala index 3337da0a..1a55ed6c 100644 --- a/src/main/scala/rocket/PMP.scala +++ b/src/main/scala/rocket/PMP.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import tile._ -import util._ +import freechips.rocketchip.config._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.util._ class PMPConfig extends Bundle { val l = Bool() diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index 60484eca..89dc3d70 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -1,18 +1,15 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import tile._ -import coreplex.CacheBlockBytes -import uncore.constants._ -import uncore.tilelink2._ -import util._ -import uncore.util.ParityCode - +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.coreplex.CacheBlockBytes +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ import scala.collection.mutable.ListBuffer class PTWReq(implicit p: Parameters) extends CoreBundle()(p) { diff --git a/src/main/scala/rocket/RVC.scala b/src/main/scala/rocket/RVC.scala index 20a2f01a..43d795a9 100644 --- a/src/main/scala/rocket/RVC.scala +++ b/src/main/scala/rocket/RVC.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import tile._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.tile._ +import freechips.rocketchip.util._ class ExpandedInstruction extends Bundle { val bits = UInt(width = 32) diff --git a/src/main/scala/rocket/Rocket.scala b/src/main/scala/rocket/RocketCore.scala similarity index 98% rename from src/main/scala/rocket/Rocket.scala rename to src/main/scala/rocket/RocketCore.scala index 07362570..0940947c 100644 --- a/src/main/scala/rocket/Rocket.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -1,17 +1,16 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ -import chisel3.core.withReset -import config._ -import tile._ -import uncore.constants._ -import diplomacy._ -import util._ import Chisel.ImplicitConversions._ -import collection.immutable.ListMap +import chisel3.core.withReset +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.tile._ +import freechips.rocketchip.util._ +import scala.collection.immutable.ListMap +import scala.collection.mutable.ArrayBuffer case class RocketCoreParams( bootFreqHz: BigInt = 0, @@ -401,7 +400,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) mem_reg_wdata := alu.io.out when (ex_ctrl.rxs2 && (ex_ctrl.mem || ex_ctrl.rocc || ex_sfence)) { val typ = Mux(ex_ctrl.rocc, log2Ceil(xLen/8).U, ex_ctrl.mem_type) - mem_reg_rs2 := new uncore.util.StoreGen(typ, 0.U, ex_rs(1), coreDataBytes).data + mem_reg_rs2 := new StoreGen(typ, 0.U, ex_rs(1), coreDataBytes).data } } @@ -724,7 +723,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) class RegFile(n: Int, w: Int, zero: Boolean = false) { private val rf = Mem(n, UInt(width = w)) private def access(addr: UInt) = rf(~addr(log2Up(n)-1,0)) - private val reads = collection.mutable.ArrayBuffer[(UInt,UInt)]() + private val reads = ArrayBuffer[(UInt,UInt)]() private var canRead = true def read(addr: UInt) = { require(canRead) diff --git a/src/main/scala/rocket/RocketTiles.scala b/src/main/scala/rocket/RocketTile.scala similarity index 96% rename from src/main/scala/rocket/RocketTiles.scala rename to src/main/scala/rocket/RocketTile.scala index 4811199b..b7bb35b5 100644 --- a/src/main/scala/rocket/RocketTiles.scala +++ b/src/main/scala/rocket/RocketTile.scala @@ -1,16 +1,16 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ -import config._ -import coreplex._ -import diplomacy._ -import tile._ -import uncore.devices._ -import uncore.tilelink2._ -import util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ case class RocketTileParams( core: RocketCoreParams = RocketCoreParams(), @@ -24,6 +24,7 @@ case class RocketTileParams( } class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p: Parameters) extends BaseTile(rocketParams)(p) + with HasExternalInterrupts with HasLazyRoCC // implies CanHaveSharedFPU with CanHavePTW with HasHellaCache with CanHaveScratchpad { // implies CanHavePTW with HasHellaCache with HasICacheFrontend @@ -124,9 +125,11 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p } class RocketTileBundle(outer: RocketTile) extends BaseTileBundle(outer) + with HasExternalInterruptsBundle with CanHaveScratchpadBundle class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => new RocketTileBundle(outer)) + with HasExternalInterruptsModule with HasLazyRoCCModule with CanHaveScratchpadModule { @@ -257,7 +260,7 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet masterNode :=* source.node val slaveNode = new TLRationalInputNode() { override def reverse = true } - val sink = LazyModule(new TLRationalCrossingSink(util.SlowToFast)) + val sink = LazyModule(new TLRationalCrossingSink(SlowToFast)) rocket.slaveNode :*= sink.node sink.node :*= slaveNode diff --git a/src/main/scala/rocket/ScratchpadSlavePort.scala b/src/main/scala/rocket/ScratchpadSlavePort.scala index 667cc157..8fe3cad2 100644 --- a/src/main/scala/rocket/ScratchpadSlavePort.scala +++ b/src/main/scala/rocket/ScratchpadSlavePort.scala @@ -1,17 +1,16 @@ // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import coreplex.CacheBlockBytes -import diplomacy._ -import tile._ -import uncore.constants._ -import uncore.tilelink2._ -import uncore.util._ -import util._ + +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.coreplex.CacheBlockBytes +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ class ScratchpadSlavePort(address: AddressSet)(implicit p: Parameters) extends LazyModule with HasCoreParameters { diff --git a/src/main/scala/rocket/SimpleHellaCacheIF.scala b/src/main/scala/rocket/SimpleHellaCacheIF.scala index 1f821f99..1ee13e6a 100644 --- a/src/main/scala/rocket/SimpleHellaCacheIF.scala +++ b/src/main/scala/rocket/SimpleHellaCacheIF.scala @@ -1,12 +1,13 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import util._ + +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.util._ /** * This module buffers requests made by the SimpleHellaCacheIF in case they diff --git a/src/main/scala/rocket/TLB.scala b/src/main/scala/rocket/TLB.scala index 197b5f06..965c6f95 100644 --- a/src/main/scala/rocket/TLB.scala +++ b/src/main/scala/rocket/TLB.scala @@ -1,17 +1,17 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ import Chisel.ImplicitConversions._ -import config._ -import diplomacy._ -import coreplex.CacheBlockBytes -import tile.{XLen, CoreModule, CoreBundle} -import uncore.tilelink2._ -import uncore.constants._ -import util._ + +import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.coreplex.CacheBlockBytes +import freechips.rocketchip.diplomacy.RegionType +import freechips.rocketchip.tile.{XLen, CoreModule, CoreBundle} +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ case object PAddrBits extends Field[Int] case object PgLevels extends Field[Int] diff --git a/src/main/scala/rocket/TLBPermissions.scala b/src/main/scala/rocket/TLBPermissions.scala index 879680df..b9cfb430 100644 --- a/src/main/scala/rocket/TLBPermissions.scala +++ b/src/main/scala/rocket/TLBPermissions.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package rocket +package freechips.rocketchip.rocket import Chisel._ -import diplomacy._ -import uncore.tilelink2._ + +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ case class TLBPermissions( homogeneous: Bool, // if false, the below are undefined diff --git a/src/main/scala/rocket/Package.scala b/src/main/scala/rocket/package.scala similarity index 61% rename from src/main/scala/rocket/Package.scala rename to src/main/scala/rocket/package.scala index 40bb8ebf..a7615bce 100644 --- a/src/main/scala/rocket/Package.scala +++ b/src/main/scala/rocket/package.scala @@ -1,3 +1,5 @@ // See LICENSE.Berkeley for license details. -package object rocket extends rocket.constants.ScalarOpConstants +package freechips.rocketchip + +package object rocket extends rocket.constants.ScalarOpConstants with rocket.constants.MemoryOpConstants diff --git a/src/main/scala/tile/BaseTile.scala b/src/main/scala/tile/BaseTile.scala index 65f1ad2f..1de7834c 100644 --- a/src/main/scala/tile/BaseTile.scala +++ b/src/main/scala/tile/BaseTile.scala @@ -1,13 +1,14 @@ // See LICENSE.SiFive for license details. -package tile +package freechips.rocketchip.tile import Chisel._ -import config._ -import diplomacy._ -import rocket._ -import uncore.tilelink2._ -import util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util._ case object SharedMemoryTLEdge extends Field[TLEdgeOut] case object TileKey extends Field[TileParams] @@ -78,17 +79,14 @@ trait HasExternallyDrivenTileConstants extends Bundle { /** Base class for all Tiles that use TileLink */ abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends BareTile - with HasTileLinkMasterPort - with HasExternalInterrupts { + with HasTileParameters + with HasTileLinkMasterPort { override lazy val module = new BaseTileModule(this, () => new BaseTileBundle(this)) } class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer) - with HasTileParameters with HasTileLinkMasterPortBundle - with HasExternalInterruptsBundle with HasExternallyDrivenTileConstants class BaseTileModule[+L <: BaseTile, +B <: BaseTileBundle[L]](_outer: L, _io: () => B) extends BareTileModule(_outer, _io) with HasTileLinkMasterPortModule - with HasExternalInterruptsModule diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index 31279ae7..fd058f21 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package tile +package freechips.rocketchip.tile import Chisel._ -import config._ -import rocket._ -import util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.rocket._ +import freechips.rocketchip.util._ case object BuildCore extends Field[Parameters => CoreModule with HasCoreIO] case object XLen extends Field[Int] diff --git a/src/main/scala/tile/FPU.scala b/src/main/scala/tile/FPU.scala index 750bfc8d..69260500 100644 --- a/src/main/scala/tile/FPU.scala +++ b/src/main/scala/tile/FPU.scala @@ -1,16 +1,15 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package tile +package freechips.rocketchip.tile import Chisel._ import Chisel.ImplicitConversions._ -import FPConstants._ -import rocket.DecodeLogic -import rocket.Instructions._ -import uncore.constants.MemoryOpConstants._ -import config._ -import util._ + +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.rocket._ +import freechips.rocketchip.rocket.Instructions._ +import freechips.rocketchip.util._ case class FPUParams( divSqrt: Boolean = true, @@ -23,6 +22,7 @@ object FPConstants val RM_SZ = 3 val FLAGS_SZ = 5 } +import FPConstants._ trait HasFPUCtrlSigs { val ldst = Bool() diff --git a/src/main/scala/tile/Interrupts.scala b/src/main/scala/tile/Interrupts.scala index 82b4167c..7e438f97 100644 --- a/src/main/scala/tile/Interrupts.scala +++ b/src/main/scala/tile/Interrupts.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package tile +package freechips.rocketchip.tile import Chisel._ -import config.Parameters -import uncore.tilelink2.{IntSinkNode, IntSinkPortSimple} -import util._ + +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.tilelink.{IntSinkNode, IntSinkPortSimple} +import freechips.rocketchip.util._ class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) { val debug = Bool() diff --git a/src/main/scala/tile/L1Cache.scala b/src/main/scala/tile/L1Cache.scala index 8839a705..bffd1b7e 100644 --- a/src/main/scala/tile/L1Cache.scala +++ b/src/main/scala/tile/L1Cache.scala @@ -1,14 +1,14 @@ // See LICENSE.SiFive for license details. -package tile +package freechips.rocketchip.tile import Chisel._ -import config.{Parameters, Field} -import coreplex.CacheBlockBytes -import rocket.PAddrBits -import uncore.tilelink2.ClientMetadata -import uncore.util.{Code, IdentityCode} -import util.ParameterizedBundle + +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.coreplex.CacheBlockBytes +import freechips.rocketchip.rocket.PAddrBits +import freechips.rocketchip.tilelink.ClientMetadata +import freechips.rocketchip.util._ trait L1CacheParams { def nSets: Int diff --git a/src/main/scala/tile/LazyRoCC.scala b/src/main/scala/tile/LazyRoCC.scala index 32081d4d..5ce96169 100644 --- a/src/main/scala/tile/LazyRoCC.scala +++ b/src/main/scala/tile/LazyRoCC.scala @@ -1,14 +1,16 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package tile +package freechips.rocketchip.tile import Chisel._ -import config._ -import coreplex._ -import diplomacy._ -import rocket._ -import uncore.tilelink2._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util.InOrderArbiter case object RoccNPTWPorts extends Field[Int] case object BuildRoCC extends Field[Seq[RoCCParams]] @@ -206,7 +208,7 @@ class AccumulatorExampleModule(outer: AccumulatorExample, n: Int = 4)(implicit p io.mem.req.valid := cmd.valid && doLoad && !stallReg && !stallResp io.mem.req.bits.addr := addend io.mem.req.bits.tag := addr - io.mem.req.bits.cmd := uncore.constants.M_XRD // perform a load (M_XWR for stores) + io.mem.req.bits.cmd := M_XRD // perform a load (M_XWR for stores) io.mem.req.bits.typ := MT_D // D = 8 bytes, W = 4, H = 2, B = 1 io.mem.req.bits.data := Bits(0) // we're not performing any stores... io.mem.req.bits.phys := Bool(false) diff --git a/src/main/scala/tile/Package.scala b/src/main/scala/tile/Package.scala deleted file mode 100644 index 497ae8e1..00000000 --- a/src/main/scala/tile/Package.scala +++ /dev/null @@ -1,3 +0,0 @@ -// See LICENSE.SiFive for license details. - -package object tile extends rocket.constants.ScalarOpConstants diff --git a/src/main/scala/uncore/tilelink2/Arbiter.scala b/src/main/scala/tilelink/Arbiter.scala similarity index 95% rename from src/main/scala/uncore/tilelink2/Arbiter.scala rename to src/main/scala/tilelink/Arbiter.scala index a9a56009..7383a8be 100644 --- a/src/main/scala/uncore/tilelink2/Arbiter.scala +++ b/src/main/scala/tilelink/Arbiter.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ object TLArbiter { @@ -92,7 +93,7 @@ object TLArbiter } /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ class TestRobin(txns: Int = 128, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { val sources = Wire(Vec(6, DecoupledIO(UInt(width=3)))) diff --git a/src/main/scala/uncore/tilelink2/AsyncCrossing.scala b/src/main/scala/tilelink/AsyncCrossing.scala similarity index 95% rename from src/main/scala/uncore/tilelink2/AsyncCrossing.scala rename to src/main/scala/tilelink/AsyncCrossing.scala index 1159595b..df6214e0 100644 --- a/src/main/scala/uncore/tilelink2/AsyncCrossing.scala +++ b/src/main/scala/tilelink/AsyncCrossing.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ class TLAsyncCrossingSource(sync: Int = 3)(implicit p: Parameters) extends LazyModule { @@ -135,7 +135,7 @@ class TLAsyncCrossing(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) ext } /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule { val model = LazyModule(new TLRAMModel("AsyncCrossing")) @@ -151,7 +151,7 @@ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule { io.finished := fuzz.module.io.finished // Shove the RAM into another clock domain - val clocks = Module(new util.Pow2ClockDivider(2)) + val clocks = Module(new Pow2ClockDivider(2)) ram.module.clock := clocks.io.clock_out // ... and safely cross TL2 into it diff --git a/src/main/scala/uncore/tilelink2/AtomicAutomata.scala b/src/main/scala/tilelink/AtomicAutomata.scala similarity index 98% rename from src/main/scala/uncore/tilelink2/AtomicAutomata.scala rename to src/main/scala/tilelink/AtomicAutomata.scala index 02c3b1a5..e9bbd200 100644 --- a/src/main/scala/uncore/tilelink2/AtomicAutomata.scala +++ b/src/main/scala/tilelink/AtomicAutomata.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import util.GenericParameterizedBundle +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ import scala.math.{min,max} // Ensures that all downstream RW managers support Atomic operationss. @@ -284,7 +284,7 @@ object TLAtomicAutomata } /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ //TODO ensure handler will pass through operations to clients that can handle them themselves diff --git a/src/main/scala/uncore/tilelink2/Atomics.scala b/src/main/scala/tilelink/Atomics.scala similarity index 95% rename from src/main/scala/uncore/tilelink2/Atomics.scala rename to src/main/scala/tilelink/Atomics.scala index ccfc1a2d..5f412cc6 100644 --- a/src/main/scala/uncore/tilelink2/Atomics.scala +++ b/src/main/scala/tilelink/Atomics.scala @@ -1,11 +1,9 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ -import uncore.tilelink2._ + import TLMessages._ import TLPermissions._ diff --git a/src/main/scala/uncore/tilelink2/Broadcast.scala b/src/main/scala/tilelink/Broadcast.scala similarity index 98% rename from src/main/scala/uncore/tilelink2/Broadcast.scala rename to src/main/scala/tilelink/Broadcast.scala index 570a1ec2..204ec8ad 100644 --- a/src/main/scala/uncore/tilelink2/Broadcast.scala +++ b/src/main/scala/tilelink/Broadcast.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ import scala.math.{min,max} class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = false)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/uncore/tilelink2/Buffer.scala b/src/main/scala/tilelink/Buffer.scala similarity index 94% rename from src/main/scala/uncore/tilelink2/Buffer.scala rename to src/main/scala/tilelink/Buffer.scala index 2bc2c067..9a741ab3 100644 --- a/src/main/scala/uncore/tilelink2/Buffer.scala +++ b/src/main/scala/tilelink/Buffer.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.math.{min,max} class TLBuffer( diff --git a/src/main/scala/uncore/tilelink2/Bundles.scala b/src/main/scala/tilelink/Bundles.scala similarity index 98% rename from src/main/scala/uncore/tilelink2/Bundles.scala rename to src/main/scala/tilelink/Bundles.scala index 143e93ca..56816ffb 100644 --- a/src/main/scala/uncore/tilelink2/Bundles.scala +++ b/src/main/scala/tilelink/Bundles.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.util.{ReadyValidIO} -import diplomacy._ -import util._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ abstract class TLBundleBase(params: TLBundleParameters) extends GenericParameterizedBundle(params) diff --git a/src/main/scala/uncore/tilelink2/CacheCork.scala b/src/main/scala/tilelink/CacheCork.scala similarity index 97% rename from src/main/scala/uncore/tilelink2/CacheCork.scala rename to src/main/scala/tilelink/CacheCork.scala index d2714431..7fd421eb 100644 --- a/src/main/scala/uncore/tilelink2/CacheCork.scala +++ b/src/main/scala/tilelink/CacheCork.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.math.{min,max} import TLMessages._ diff --git a/src/main/scala/uncore/tilelink2/Delayer.scala b/src/main/scala/tilelink/Delayer.scala similarity index 96% rename from src/main/scala/uncore/tilelink2/Delayer.scala rename to src/main/scala/tilelink/Delayer.scala index 06c1be76..767bd7c1 100644 --- a/src/main/scala/uncore/tilelink2/Delayer.scala +++ b/src/main/scala/tilelink/Delayer.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ // q is the probability to delay a request class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/uncore/tilelink2/Edges.scala b/src/main/scala/tilelink/Edges.scala similarity index 99% rename from src/main/scala/uncore/tilelink2/Edges.scala rename to src/main/scala/tilelink/Edges.scala index 5b8a13cd..1455b419 100644 --- a/src/main/scala/uncore/tilelink2/Edges.scala +++ b/src/main/scala/tilelink/Edges.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import diplomacy._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ class TLEdge( client: TLClientPortParameters, @@ -19,7 +20,7 @@ class TLEdge( } def mask(address: UInt, lgSize: UInt): UInt = - maskGen(address, lgSize, manager.beatBytes) + MaskGen(address, lgSize, manager.beatBytes) def staticHasData(bundle: TLChannel): Option[Boolean] = { bundle match { diff --git a/src/main/scala/uncore/tilelink2/Example.scala b/src/main/scala/tilelink/Example.scala similarity index 87% rename from src/main/scala/uncore/tilelink2/Example.scala rename to src/main/scala/tilelink/Example.scala index 2cb9ce19..b9c41df4 100644 --- a/src/main/scala/uncore/tilelink2/Example.scala +++ b/src/main/scala/tilelink/Example.scala @@ -1,10 +1,10 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import regmapper._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.regmapper._ case class ExampleParams(num: Int, address: BigInt) diff --git a/src/main/scala/uncore/tilelink2/FIFOFixer.scala b/src/main/scala/tilelink/FIFOFixer.scala similarity index 95% rename from src/main/scala/uncore/tilelink2/FIFOFixer.scala rename to src/main/scala/tilelink/FIFOFixer.scala index 8b3943ea..9160acb2 100644 --- a/src/main/scala/uncore/tilelink2/FIFOFixer.scala +++ b/src/main/scala/tilelink/FIFOFixer.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.math.max class TLFIFOFixer(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/uncore/tilelink2/Filter.scala b/src/main/scala/tilelink/Filter.scala similarity index 93% rename from src/main/scala/uncore/tilelink2/Filter.scala rename to src/main/scala/tilelink/Filter.scala index 7c3899ff..80a4f1c7 100644 --- a/src/main/scala/uncore/tilelink2/Filter.scala +++ b/src/main/scala/tilelink/Filter.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.math.{min,max} class TLFilter(select: AddressSet)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/tilelink/Fragmenter.scala similarity index 98% rename from src/main/scala/uncore/tilelink2/Fragmenter.scala rename to src/main/scala/tilelink/Fragmenter.scala index 9b373ea5..13cb7dec 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/tilelink/Fragmenter.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ import scala.math.{min,max} // minSize: minimum size of transfers supported by all outward managers @@ -285,7 +286,7 @@ object TLFragmenter } /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ class TLRAMFragmenter(ramBeatBytes: Int, maxSize: Int, txns: Int)(implicit p: Parameters) extends LazyModule { val fuzz = LazyModule(new TLFuzzer(txns)) diff --git a/src/main/scala/uncore/tilelink2/Fuzzer.scala b/src/main/scala/tilelink/Fuzzer.scala similarity index 97% rename from src/main/scala/uncore/tilelink2/Fuzzer.scala rename to src/main/scala/tilelink/Fuzzer.scala index b4f48601..6493dc4e 100644 --- a/src/main/scala/uncore/tilelink2/Fuzzer.scala +++ b/src/main/scala/tilelink/Fuzzer.scala @@ -1,10 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ class IDMapGenerator(numIds: Int) extends Module { val w = log2Up(numIds) @@ -211,7 +212,7 @@ class TLFuzzer( } /** Synthesizeable integration test */ -import unittest._ +import freechips.rocketchip.unittest._ class TLFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule { @@ -236,7 +237,7 @@ class TLFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule io.finished := fuzz.module.io.finished // Shove the RAM into another clock domain - val clocks = Module(new util.Pow2ClockDivider(2)) + val clocks = Module(new Pow2ClockDivider(2)) ram.module.clock := clocks.io.clock_out // ... and safely cross TL2 into it diff --git a/src/main/scala/uncore/tilelink2/HintHandler.scala b/src/main/scala/tilelink/HintHandler.scala similarity index 96% rename from src/main/scala/uncore/tilelink2/HintHandler.scala rename to src/main/scala/tilelink/HintHandler.scala index fe13bbb3..56f35890 100644 --- a/src/main/scala/uncore/tilelink2/HintHandler.scala +++ b/src/main/scala/tilelink/HintHandler.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink -import scala.math.min import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import scala.math.min // Acks Hints for managers that don't support them or Acks all Hints if !passthrough class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(implicit p: Parameters) extends LazyModule @@ -106,7 +106,7 @@ object TLHintHandler } /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ //TODO ensure handler will pass through hints to clients that can handle them themselves diff --git a/src/main/scala/uncore/tilelink2/IntNodes.scala b/src/main/scala/tilelink/IntNodes.scala similarity index 97% rename from src/main/scala/uncore/tilelink2/IntNodes.scala rename to src/main/scala/tilelink/IntNodes.scala index 6459f341..aa910f5b 100644 --- a/src/main/scala/uncore/tilelink2/IntNodes.scala +++ b/src/main/scala/tilelink/IntNodes.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ import scala.collection.mutable.ListBuffer import scala.math.max diff --git a/src/main/scala/uncore/tilelink2/Isolation.scala b/src/main/scala/tilelink/Isolation.scala similarity index 94% rename from src/main/scala/uncore/tilelink2/Isolation.scala rename to src/main/scala/tilelink/Isolation.scala index 74eba192..78993586 100644 --- a/src/main/scala/uncore/tilelink2/Isolation.scala +++ b/src/main/scala/tilelink/Isolation.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import util.AsyncBundle +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.AsyncBundle // READ the comments in the TLIsolation object before you instantiate this module class TLIsolation(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/uncore/tilelink2/Metadata.scala b/src/main/scala/tilelink/Metadata.scala similarity index 97% rename from src/main/scala/uncore/tilelink2/Metadata.scala rename to src/main/scala/tilelink/Metadata.scala index 2fa57690..92d48c38 100644 --- a/src/main/scala/uncore/tilelink2/Metadata.scala +++ b/src/main/scala/tilelink/Metadata.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import util._ -import uncore.constants.MemoryOpConstants +import freechips.rocketchip.rocket.constants.MemoryOpConstants +import freechips.rocketchip.util._ object ClientStates { val width = 2 diff --git a/src/main/scala/uncore/tilelink2/Monitor.scala b/src/main/scala/tilelink/Monitor.scala similarity index 98% rename from src/main/scala/uncore/tilelink2/Monitor.scala rename to src/main/scala/tilelink/Monitor.scala index 1d5eb3db..86d43306 100644 --- a/src/main/scala/uncore/tilelink2/Monitor.scala +++ b/src/main/scala/tilelink/Monitor.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.{SourceInfo, SourceLine} -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.{HeterogeneousBag, PlusArg} case class TLMonitorArgs(edge: () => Seq[TLEdge], sourceInfo: SourceInfo, p: Parameters) @@ -16,7 +17,7 @@ abstract class TLMonitorBase(args: TLMonitorArgs) extends MonitorBase()(args.sou lazy val module = new LazyModuleImp(this) { val edges = args.edge() val io = new Bundle { - val in = util.HeterogeneousBag(edges.map(p => new TLBundleSnoop(p.bundle))).flip + val in = HeterogeneousBag(edges.map(p => new TLBundleSnoop(p.bundle))).flip } (edges zip io.in).foreach { case (e, in) => legalize(in, e, reset) } @@ -435,7 +436,7 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args) inflight := (inflight | a_set) & ~d_clr val watchdog = RegInit(UInt(0, width = 32)) - val limit = util.PlusArg("tilelink_timeout") + val limit = PlusArg("tilelink_timeout") assert (!inflight.orR || limit === UInt(0) || watchdog < limit, "TileLink timeout expired" + extra) watchdog := watchdog + UInt(1) diff --git a/src/main/scala/uncore/tilelink2/NodeNumberer.scala b/src/main/scala/tilelink/NodeNumberer.scala similarity index 95% rename from src/main/scala/uncore/tilelink2/NodeNumberer.scala rename to src/main/scala/tilelink/NodeNumberer.scala index 60242bb2..882350d8 100644 --- a/src/main/scala/uncore/tilelink2/NodeNumberer.scala +++ b/src/main/scala/tilelink/NodeNumberer.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ case class TLNodeNumbererNode(nodeAddressOffset: Option[Int] = None) extends TLCustomNode(0 to 999, 0 to 999) { diff --git a/src/main/scala/uncore/tilelink2/Nodes.scala b/src/main/scala/tilelink/Nodes.scala similarity index 97% rename from src/main/scala/uncore/tilelink2/Nodes.scala rename to src/main/scala/tilelink/Nodes.scala index a2281da3..513399ba 100644 --- a/src/main/scala/uncore/tilelink2/Nodes.scala +++ b/src/main/scala/tilelink/Nodes.scala @@ -1,13 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.RationalDirection import scala.collection.mutable.ListBuffer -import util.RationalDirection case object TLMonitorBuilder extends Field[TLMonitorArgs => Option[TLMonitorBase]] case object TLCombinationalCheck extends Field[Boolean] @@ -117,7 +117,7 @@ case class TLInternalOutputNode(portParams: Seq[TLManagerPortParameters]) extend case class TLInternalInputNode(portParams: Seq[TLClientPortParameters]) extends InternalInputNode(TLImp)(portParams) /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ class TLInputNodeTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { class Acceptor extends LazyModule { diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/tilelink/Parameters.scala similarity index 99% rename from src/main/scala/uncore/tilelink2/Parameters.scala rename to src/main/scala/tilelink/Parameters.scala index af2e8151..a33f4501 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/tilelink/Parameters.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import diplomacy._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util.RationalDirection import scala.math.max -import util.RationalDirection case class TLManagerParameters( address: Seq[AddressSet], diff --git a/src/main/scala/uncore/tilelink2/RAMModel.scala b/src/main/scala/tilelink/RAMModel.scala similarity index 98% rename from src/main/scala/uncore/tilelink2/RAMModel.scala rename to src/main/scala/tilelink/RAMModel.scala index 2befed32..6fb138a3 100644 --- a/src/main/scala/uncore/tilelink2/RAMModel.scala +++ b/src/main/scala/tilelink/RAMModel.scala @@ -1,11 +1,11 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ -import util.{GenericParameterizedBundle, CRC} +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ // We detect concurrent puts that put memory into an undefined state. // put0, put0Ack, put1, put1Ack => ok: defined diff --git a/src/main/scala/uncore/tilelink2/RationalCrossing.scala b/src/main/scala/tilelink/RationalCrossing.scala similarity index 95% rename from src/main/scala/uncore/tilelink2/RationalCrossing.scala rename to src/main/scala/tilelink/RationalCrossing.scala index 2d42c803..5603c0aa 100644 --- a/src/main/scala/uncore/tilelink2/RationalCrossing.scala +++ b/src/main/scala/tilelink/RationalCrossing.scala @@ -7,13 +7,13 @@ // - All outputs of TLRational are registers (bits, valid, and ready). // - It costs 3*bits registers as opposed to 2*bits in a TLBuffer(2) -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ class TLRationalCrossingSource(implicit p: Parameters) extends LazyModule { @@ -147,7 +147,7 @@ class TLRationalCrossing(direction: RationalDirection = Symmetric)(implicit p: P } /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ class TLRAMRationalCrossingSource(name: String, txns: Int)(implicit p: Parameters) extends LazyModule { val node = TLRationalOutputNode() @@ -204,18 +204,18 @@ class TLRAMRationalCrossing(txns: Int)(implicit p: Parameters) extends LazyModul fix_slow_source.module.io.finished // Generate faster clock (still divided so verilator approves) - val fast = Module(new util.Pow2ClockDivider(1)) + val fast = Module(new Pow2ClockDivider(1)) sym_fast_source.module.clock := fast.io.clock_out sym_fast_sink .module.clock := fast.io.clock_out fix_fast_source.module.clock := fast.io.clock_out fix_fast_sink .module.clock := fast.io.clock_out // Generate slower clock - val slow = Module(new util.Pow2ClockDivider(2)) + val slow = Module(new Pow2ClockDivider(2)) fix_slow_source.module.clock := slow.io.clock_out fix_slow_sink .module.clock := slow.io.clock_out - val odd = Module(new util.ClockDivider3) + val odd = Module(new ClockDivider3) odd.io.clk_in := clock sym_slow_source.module.clock := odd.io.clk_out sym_slow_sink .module.clock := odd.io.clk_out diff --git a/src/main/scala/uncore/tilelink2/RegisterRouter.scala b/src/main/scala/tilelink/RegisterRouter.scala similarity index 94% rename from src/main/scala/uncore/tilelink2/RegisterRouter.scala rename to src/main/scala/tilelink/RegisterRouter.scala index d2f255bf..ad598a28 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouter.scala +++ b/src/main/scala/tilelink/RegisterRouter.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ -import regmapper._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.util.HeterogeneousBag import scala.math.{min,max} class TLRegisterNode( @@ -107,7 +108,7 @@ abstract class TLRegisterRouterBase(devname: String, devcompat: Seq[String], val val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts, resources = Seq(Resource(device, "int")))) } -case class TLRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[TLBundle])(implicit val p: Parameters) +case class TLRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[TLBundle])(implicit val p: Parameters) class TLRegBundleBase(arg: TLRegBundleArg) extends Bundle { diff --git a/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala b/src/main/scala/tilelink/RegisterRouterTest.scala similarity index 97% rename from src/main/scala/uncore/tilelink2/RegisterRouterTest.scala rename to src/main/scala/tilelink/RegisterRouterTest.scala index 3dca68f2..ef70cf73 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala +++ b/src/main/scala/tilelink/RegisterRouterTest.scala @@ -1,13 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ -import regmapper._ -import unittest._ -import util.{Pow2ClockDivider} +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.unittest._ +import freechips.rocketchip.util.{Pow2ClockDivider} object LFSR16Seed { diff --git a/src/main/scala/uncore/tilelink2/SRAM.scala b/src/main/scala/tilelink/SRAM.scala similarity index 95% rename from src/main/scala/uncore/tilelink2/SRAM.scala rename to src/main/scala/tilelink/SRAM.scala index 3e7c2b75..310845b6 100644 --- a/src/main/scala/uncore/tilelink2/SRAM.scala +++ b/src/main/scala/tilelink/SRAM.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.experimental.chiselName -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, name: Option[String] = None)(implicit p: Parameters) extends LazyModule { @@ -90,7 +90,7 @@ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, } /** Synthesizeable unit testing */ -import unittest._ +import freechips.rocketchip.unittest._ class TLRAMSimple(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule { val fuzz = LazyModule(new TLFuzzer(txns)) diff --git a/src/main/scala/uncore/tilelink2/SourceShrinker.scala b/src/main/scala/tilelink/SourceShrinker.scala similarity index 94% rename from src/main/scala/uncore/tilelink2/SourceShrinker.scala rename to src/main/scala/tilelink/SourceShrinker.scala index df3f70e6..57558b42 100644 --- a/src/main/scala/uncore/tilelink2/SourceShrinker.scala +++ b/src/main/scala/tilelink/SourceShrinker.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import util._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ import scala.math.{min,max} class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/uncore/tilelink2/Splitter.scala b/src/main/scala/tilelink/Splitter.scala similarity index 97% rename from src/main/scala/uncore/tilelink2/Splitter.scala rename to src/main/scala/tilelink/Splitter.scala index 7dafc6dd..abebecc3 100644 --- a/src/main/scala/uncore/tilelink2/Splitter.scala +++ b/src/main/scala/tilelink/Splitter.scala @@ -1,10 +1,10 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ class TLSplitter(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/tilelink2/ToAHB.scala b/src/main/scala/tilelink/ToAHB.scala similarity index 96% rename from src/main/scala/uncore/tilelink2/ToAHB.scala rename to src/main/scala/tilelink/ToAHB.scala index 51a69927..ac5923da 100644 --- a/src/main/scala/uncore/tilelink2/ToAHB.scala +++ b/src/main/scala/tilelink/ToAHB.scala @@ -1,12 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import uncore.ahb._ +import freechips.rocketchip.amba.ahb._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ import scala.math.{min, max} import AHBParameters._ @@ -30,7 +31,7 @@ case class TLToAHBNode() extends MixedAdapterNode(TLImp, AHBImp)( TLManagerPortParameters(managers, beatBytes, 1, 1) }) -class AHBControlBundle(params: TLEdge) extends util.GenericParameterizedBundle(params) +class AHBControlBundle(params: TLEdge) extends GenericParameterizedBundle(params) { val full = Bool() val send = Bool() // => full+data diff --git a/src/main/scala/uncore/tilelink2/ToAPB.scala b/src/main/scala/tilelink/ToAPB.scala similarity index 95% rename from src/main/scala/uncore/tilelink2/ToAPB.scala rename to src/main/scala/tilelink/ToAPB.scala index 7aa51003..76dfe909 100644 --- a/src/main/scala/uncore/tilelink2/ToAPB.scala +++ b/src/main/scala/tilelink/ToAPB.scala @@ -1,12 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import uncore.apb._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.amba.apb._ import scala.math.{min, max} import APBParameters._ diff --git a/src/main/scala/uncore/tilelink2/ToAXI4.scala b/src/main/scala/tilelink/ToAXI4.scala similarity index 98% rename from src/main/scala/uncore/tilelink2/ToAXI4.scala rename to src/main/scala/tilelink/ToAXI4.scala index 3f0d1c7e..5bbf856c 100644 --- a/src/main/scala/uncore/tilelink2/ToAXI4.scala +++ b/src/main/scala/tilelink/ToAXI4.scala @@ -1,13 +1,13 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ -import util.ElaborationArtefacts -import uncore.axi4._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ +import freechips.rocketchip.amba.axi4._ import scala.math.{min, max} case class TLToAXI4Node(beatBytes: Int, stripBits: Int = 0) extends MixedAdapterNode(TLImp, AXI4Imp)( diff --git a/src/main/scala/uncore/tilelink2/WidthWidget.scala b/src/main/scala/tilelink/WidthWidget.scala similarity index 97% rename from src/main/scala/uncore/tilelink2/WidthWidget.scala rename to src/main/scala/tilelink/WidthWidget.scala index 8e27b822..b3b4eebf 100644 --- a/src/main/scala/uncore/tilelink2/WidthWidget.scala +++ b/src/main/scala/tilelink/WidthWidget.scala @@ -1,11 +1,12 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ import scala.math.{min,max} // innBeatBytes => the new client-facing bus width @@ -178,7 +179,7 @@ object TLWidthWidget } /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ class TLRAMWidthWidget(first: Int, second: Int, txns: Int)(implicit p: Parameters) extends LazyModule { val fuzz = LazyModule(new TLFuzzer(txns)) diff --git a/src/main/scala/uncore/tilelink2/Xbar.scala b/src/main/scala/tilelink/Xbar.scala similarity index 98% rename from src/main/scala/uncore/tilelink2/Xbar.scala rename to src/main/scala/tilelink/Xbar.scala index b75fd14a..5208bec0 100644 --- a/src/main/scala/uncore/tilelink2/Xbar.scala +++ b/src/main/scala/tilelink/Xbar.scala @@ -1,10 +1,10 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.tilelink import Chisel._ -import config._ -import diplomacy._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule { @@ -223,7 +223,7 @@ object TLXbar } /** Synthesizeable unit tests */ -import unittest._ +import freechips.rocketchip.unittest._ class TLRAMXbar(nManagers: Int, txns: Int)(implicit p: Parameters) extends LazyModule { val fuzz = LazyModule(new TLFuzzer(txns)) diff --git a/src/main/scala/tilelink/package.scala b/src/main/scala/tilelink/package.scala new file mode 100644 index 00000000..8a319b7e --- /dev/null +++ b/src/main/scala/tilelink/package.scala @@ -0,0 +1,17 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip + +import Chisel._ +import freechips.rocketchip.diplomacy._ + +package object tilelink +{ + type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] + type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] + type TLAsyncOutwardNode = OutwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle] + type TLRationalOutwardNode = OutwardNodeHandle[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle] + type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] + type TLMixedNode = MixedNode[TLClientPortParameters, TLManagerPortParameters, TLEdgeIn, TLBundle, + TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLBundle] +} diff --git a/src/main/scala/uncore/Consts.scala b/src/main/scala/uncore/Consts.scala deleted file mode 100644 index d1990625..00000000 --- a/src/main/scala/uncore/Consts.scala +++ /dev/null @@ -1,44 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package uncore -package constants - -import Chisel._ -import _root_.util._ - -object MemoryOpConstants extends MemoryOpConstants -trait MemoryOpConstants { - val NUM_XA_OPS = 9 - val M_SZ = 5 - def M_X = BitPat("b?????"); - def M_XRD = UInt("b00000"); // int load - def M_XWR = UInt("b00001"); // int store - def M_PFR = UInt("b00010"); // prefetch with intent to read - def M_PFW = UInt("b00011"); // prefetch with intent to write - def M_XA_SWAP = UInt("b00100"); - def M_FLUSH_ALL = UInt("b00101") // flush all lines - def M_XLR = UInt("b00110"); - def M_XSC = UInt("b00111"); - def M_XA_ADD = UInt("b01000"); - def M_XA_XOR = UInt("b01001"); - def M_XA_OR = UInt("b01010"); - def M_XA_AND = UInt("b01011"); - def M_XA_MIN = UInt("b01100"); - def M_XA_MAX = UInt("b01101"); - def M_XA_MINU = UInt("b01110"); - def M_XA_MAXU = UInt("b01111"); - def M_FLUSH = UInt("b10000") // write back dirty data and cede R/W permissions - def M_PWR = UInt("b10001") // partial (masked) store - def M_PRODUCE = UInt("b10010") // write back dirty data and cede W permissions - def M_CLEAN = UInt("b10011") // write back dirty data and retain R/W permissions - def M_SFENCE = UInt("b10100") // flush TLB - - def isAMOLogical(cmd: UInt) = cmd.isOneOf(M_XA_SWAP, M_XA_XOR, M_XA_OR, M_XA_AND) - def isAMOArithmetic(cmd: UInt) = cmd.isOneOf(M_XA_ADD, M_XA_MIN, M_XA_MAX, M_XA_MINU, M_XA_MAXU) - def isAMO(cmd: UInt) = isAMOLogical(cmd) || isAMOArithmetic(cmd) - def isPrefetch(cmd: UInt) = cmd === M_PFR || cmd === M_PFW - def isRead(cmd: UInt) = cmd === M_XRD || cmd === M_XLR || cmd === M_XSC || isAMO(cmd) - def isWrite(cmd: UInt) = cmd === M_XWR || cmd === M_PWR || cmd === M_XSC || isAMO(cmd) - def isWriteIntent(cmd: UInt) = isWrite(cmd) || cmd === M_PFW || cmd === M_XLR -} - diff --git a/src/main/scala/uncore/Package.scala b/src/main/scala/uncore/Package.scala deleted file mode 100644 index becd09df..00000000 --- a/src/main/scala/uncore/Package.scala +++ /dev/null @@ -1,5 +0,0 @@ -// See LICENSE.SiFive for license details. - -package uncore - -package object constants extends uncore.constants.MemoryOpConstants diff --git a/src/main/scala/uncore/agents/Agents.scala b/src/main/scala/uncore/agents/Agents.scala deleted file mode 100644 index 8f7f57c8..00000000 --- a/src/main/scala/uncore/agents/Agents.scala +++ /dev/null @@ -1,164 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.agents - -import Chisel._ -import config._ -import rocket.PAddrBits -import uncore.tilelink._ -import uncore.converters._ -import uncore.coherence._ -import uncore.util._ -import util._ - -case object NReleaseTransactors extends Field[Int] -case object NProbeTransactors extends Field[Int] -case object NAcquireTransactors extends Field[Int] - -trait HasCoherenceAgentParameters { - implicit val p: Parameters - val nReleaseTransactors = 1 - val nAcquireTransactors = p(NAcquireTransactors) - val nTransactors = nReleaseTransactors + nAcquireTransactors - val blockAddrBits = p(PAddrBits) - p(CacheBlockOffsetBits) - val outerTLId = p(OuterTLId) - val outerTLParams = p(TLKey(outerTLId)) - val outerDataBeats = outerTLParams.dataBeats - val outerDataBits = outerTLParams.dataBitsPerBeat - val outerBeatAddrBits = log2Up(outerDataBeats) - val outerByteAddrBits = log2Up(outerDataBits/8) - val outerWriteMaskBits = outerTLParams.writeMaskBits - val innerTLId = p(InnerTLId) - val innerTLParams = p(TLKey(innerTLId)) - val innerDataBeats = innerTLParams.dataBeats - val innerDataBits = innerTLParams.dataBitsPerBeat - val innerWriteMaskBits = innerTLParams.writeMaskBits - val innerBeatAddrBits = log2Up(innerDataBeats) - val innerByteAddrBits = log2Up(innerDataBits/8) - val innerNCachingClients = innerTLParams.nCachingClients - val maxManagerXacts = innerTLParams.maxManagerXacts - require(outerDataBeats == innerDataBeats) //TODO: fix all xact_data Vecs to remove this requirement -} - -abstract class CoherenceAgentModule(implicit val p: Parameters) extends Module - with HasCoherenceAgentParameters -abstract class CoherenceAgentBundle(implicit val p: Parameters) extends ParameterizedBundle()(p) - with HasCoherenceAgentParameters - -trait HasCoherenceAgentWiringHelpers { - def doOutputArbitration[T <: TileLinkChannel]( - out: DecoupledIO[T], - ins: Seq[DecoupledIO[T]]) { - def lock(o: T) = o.hasMultibeatData() - val arb = Module(new LockingRRArbiter(out.bits, ins.size, out.bits.tlDataBeats, Some(lock _))) - out <> arb.io.out - arb.io.in <> ins - } - - def doInputRouting[T <: Bundle with HasManagerTransactionId]( - in: DecoupledIO[T], - outs: Seq[DecoupledIO[T]]) { - val idx = in.bits.manager_xact_id - outs.map(_.bits := in.bits) - outs.zipWithIndex.map { case (o,i) => o.valid := in.valid && idx === UInt(i) } - in.ready := outs.map(_.ready).apply(idx) - } - - /** Broadcasts valid messages on this channel to all trackers, - * but includes logic to allocate a new tracker in the case where - * no previously allocated tracker matches the new req's addr. - * - * When a match is reported, if ready is high the new transaction - * is merged; when ready is low the transaction is being blocked. - * When no match is reported, any high idles are presumed to be - * from trackers that are available for allocation, and one is - * assigned via alloc based on priority; if no idles are high then - * all trackers are busy with other transactions. If idle is high - * but ready is low, the tracker will be allocated but does not - * have sufficient buffering for the data. - */ - def doInputRoutingWithAllocation[T <: TileLinkChannel with HasTileLinkData]( - in: DecoupledIO[T], - outs: Seq[DecoupledIO[T]], - allocs: Seq[TrackerAllocation], - dataOverrides: Option[Seq[UInt]] = None, - allocOverride: Option[Bool] = None, - matchOverride: Option[Bool] = None) { - val ready_bits = outs.map(_.ready).asUInt - val can_alloc_bits = allocs.map(_.can).asUInt - val should_alloc_bits = PriorityEncoderOH(can_alloc_bits) - val match_bits = allocs.map(_.matches).asUInt - val no_matches = !match_bits.orR - val alloc_ok = allocOverride.getOrElse(Bool(true)) - val match_ok = matchOverride.getOrElse(Bool(true)) - in.ready := (Mux(no_matches, can_alloc_bits, match_bits) & ready_bits).orR && alloc_ok && match_ok - outs.zip(allocs).zipWithIndex.foreach { case((out, alloc), i) => - out.valid := in.valid && match_ok && alloc_ok - out.bits := in.bits - dataOverrides foreach { d => out.bits.data := d(i) } - alloc.should := should_alloc_bits(i) && no_matches && alloc_ok - } - } -} - -trait HasInnerTLIO extends HasCoherenceAgentParameters { - val inner = new ManagerTileLinkIO()(p.alterPartial({case TLId => p(InnerTLId)})) - val incoherent = Vec(inner.tlNCachingClients, Bool()).asInput - def iacq(dummy: Int = 0) = inner.acquire.bits - def iprb(dummy: Int = 0) = inner.probe.bits - def irel(dummy: Int = 0) = inner.release.bits - def ignt(dummy: Int = 0) = inner.grant.bits - def ifin(dummy: Int = 0) = inner.finish.bits -} - -trait HasUncachedOuterTLIO extends HasCoherenceAgentParameters { - val outer = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => p(OuterTLId)})) - def oacq(dummy: Int = 0) = outer.acquire.bits - def ognt(dummy: Int = 0) = outer.grant.bits -} - -trait HasCachedOuterTLIO extends HasCoherenceAgentParameters { - val outer = new ClientTileLinkIO()(p.alterPartial({case TLId => p(OuterTLId)})) - def oacq(dummy: Int = 0) = outer.acquire.bits - def oprb(dummy: Int = 0) = outer.probe.bits - def orel(dummy: Int = 0) = outer.release.bits - def ognt(dummy: Int = 0) = outer.grant.bits -} - -class ManagerTLIO(implicit p: Parameters) extends CoherenceAgentBundle()(p) - with HasInnerTLIO - with HasUncachedOuterTLIO - -abstract class CoherenceAgent(implicit p: Parameters) extends CoherenceAgentModule()(p) { - def innerTL: ManagerTileLinkIO - def outerTL: ClientTileLinkIO - def incoherent: Vec[Bool] -} - -abstract class ManagerCoherenceAgent(implicit p: Parameters) extends CoherenceAgent()(p) - with HasCoherenceAgentWiringHelpers { - val io = new ManagerTLIO - def innerTL = io.inner - def outerTL = TileLinkIOWrapper(io.outer) - def incoherent = io.incoherent -} - -class HierarchicalTLIO(implicit p: Parameters) extends CoherenceAgentBundle()(p) - with HasInnerTLIO - with HasCachedOuterTLIO - -abstract class HierarchicalCoherenceAgent(implicit p: Parameters) extends CoherenceAgent()(p) - with HasCoherenceAgentWiringHelpers { - val io = new HierarchicalTLIO - def innerTL = io.inner - def outerTL = io.outer - def incoherent = io.incoherent - - // TODO: Remove this function (and all its calls) when we support probing the L2 - def disconnectOuterProbeAndFinish() { - io.outer.probe.ready := Bool(false) - io.outer.finish.valid := Bool(false) - assert(!io.outer.probe.valid, "L2 agent got illegal probe") - } -} diff --git a/src/main/scala/uncore/agents/Broadcast.scala b/src/main/scala/uncore/agents/Broadcast.scala deleted file mode 100644 index 599df317..00000000 --- a/src/main/scala/uncore/agents/Broadcast.scala +++ /dev/null @@ -1,207 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.agents - -import Chisel._ -import uncore.coherence._ -import uncore.tilelink._ -import uncore.constants._ -import uncore.util._ -import util._ -import config._ - -class L2BroadcastHub(implicit p: Parameters) extends HierarchicalCoherenceAgent()(p) { - - // Create TSHRs for outstanding transactions - val irelTrackerList = - (0 until nReleaseTransactors).map(id => - Module(new BufferedBroadcastVoluntaryReleaseTracker(id))) - val iacqTrackerList = - (nReleaseTransactors until nTransactors).map(id => - Module(new BufferedBroadcastAcquireTracker(id))) - val trackerList = irelTrackerList ++ iacqTrackerList - - // Propagate incoherence flags - trackerList.map(_.io.incoherent) foreach { _ := io.incoherent } - - // Create an arbiter for the one memory port - val outerList = trackerList.map(_.io.outer) - val outer_arb = Module(new ClientTileLinkIOArbiter(outerList.size) - (p.alterPartial({ case TLId => p(OuterTLId) }))) - outer_arb.io.in <> outerList - io.outer <> outer_arb.io.out - - // Handle acquire transaction initiation - val irel_vs_iacq_conflict = - io.inner.acquire.valid && - io.inner.release.valid && - io.irel().conflicts(io.iacq()) - - doInputRoutingWithAllocation( - in = io.inner.acquire, - outs = trackerList.map(_.io.inner.acquire), - allocs = trackerList.map(_.io.alloc.iacq), - allocOverride = Some(!irel_vs_iacq_conflict)) - - // Handle releases, which might be voluntary and might have data - doInputRoutingWithAllocation( - in = io.inner.release, - outs = trackerList.map(_.io.inner.release), - allocs = trackerList.map(_.io.alloc.irel)) - - // Wire probe requests and grant reply to clients, finish acks from clients - doOutputArbitration(io.inner.probe, trackerList.map(_.io.inner.probe)) - - doOutputArbitration(io.inner.grant, trackerList.map(_.io.inner.grant)) - - doInputRouting(io.inner.finish, trackerList.map(_.io.inner.finish)) - - disconnectOuterProbeAndFinish() -} - -class BroadcastXactTracker(implicit p: Parameters) extends XactTracker()(p) { - val io = new HierarchicalXactTrackerIO - pinAllReadyValidLow(io) -} - -trait BroadcastsToAllClients extends HasCoherenceAgentParameters { - val coh = HierarchicalMetadata.onReset - val inner_coh = coh.inner - val outer_coh = coh.outer - def full_representation = ~UInt(0, width = innerNCachingClients) -} - -abstract class BroadcastVoluntaryReleaseTracker(trackerId: Int)(implicit p: Parameters) - extends VoluntaryReleaseTracker(trackerId)(p) - with EmitsVoluntaryReleases - with BroadcastsToAllClients { - val io = new HierarchicalXactTrackerIO - pinAllReadyValidLow(io) - - // Checks for illegal behavior - assert(!(state === s_idle && io.inner.release.fire() && io.alloc.irel.should && !io.irel().isVoluntary()), - "VoluntaryReleaseTracker accepted Release that wasn't voluntary!") -} - -abstract class BroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters) - extends AcquireTracker(trackerId)(p) - with EmitsVoluntaryReleases - with BroadcastsToAllClients { - val io = new HierarchicalXactTrackerIO - pinAllReadyValidLow(io) - - val alwaysWriteFullBeat = false - val nSecondaryMisses = 1 - def iacq_can_merge = Bool(false) - - // Checks for illegal behavior - // TODO: this could be allowed, but is a useful check against allocation gone wild - assert(!(state === s_idle && io.inner.acquire.fire() && io.alloc.iacq.should && - io.iacq().hasMultibeatData() && !io.iacq().first()), - "AcquireTracker initialized with a tail data beat.") - - assert(!(state =/= s_idle && pending_ignt && xact_iacq.isPrefetch()), - "Broadcast Hub does not support Prefetches.") - - assert(!(state =/= s_idle && pending_ignt && xact_iacq.isAtomic()), - "Broadcast Hub does not support PutAtomics.") -} - -class BufferedBroadcastVoluntaryReleaseTracker(trackerId: Int)(implicit p: Parameters) - extends BroadcastVoluntaryReleaseTracker(trackerId)(p) - with HasDataBuffer { - - // Tell the parent if any incoming messages conflict with the ongoing transaction - routeInParent(irelCanAlloc = Bool(true)) - - // Start transaction by accepting inner release - innerRelease(block_vol_ignt = pending_orel || vol_ognt_counter.pending) - - // A release beat can be accepted if we are idle, if its a mergeable transaction, or if its a tail beat - io.inner.release.ready := state === s_idle || irel_can_merge || irel_same_xact - - when(io.inner.release.fire()) { data_buffer(io.irel().addr_beat) := io.irel().data } - - // Dispatch outer release - outerRelease( - coh = outer_coh.onHit(M_XWR), - data = data_buffer(vol_ognt_counter.up.idx), - add_pending_send_bit = irel_is_allocating) - - quiesce() {} -} - -class BufferedBroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters) - extends BroadcastAcquireTracker(trackerId)(p) - with HasByteWriteMaskBuffer { - - // Setup IOs used for routing in the parent - routeInParent(iacqCanAlloc = Bool(true)) - - // First, take care of accpeting new acquires or secondary misses - // Handling of primary and secondary misses' data and write mask merging - innerAcquire( - can_alloc = Bool(false), - next = s_inner_probe) - - io.inner.acquire.ready := state === s_idle || iacq_can_merge || iacq_same_xact_multibeat - - // Track which clients yet need to be probed and make Probe message - // If a writeback occurs, we can forward its data via the buffer, - // and skip having to go outwards - val skip_outer_acquire = pending_ignt_data.andR - - innerProbe( - inner_coh.makeProbe(curr_probe_dst, xact_iacq, xact_addr_block), - Mux(!skip_outer_acquire, s_outer_acquire, s_busy)) - - // Handle incoming releases from clients, which may reduce sharer counts - // and/or write back dirty data, and may be unexpected voluntary releases - def irel_can_merge = io.irel().conflicts(xact_addr_block) && - io.irel().isVoluntary() && - !state.isOneOf(s_idle, s_meta_write) && - !all_pending_done && - !io.outer.grant.fire() && - !io.inner.grant.fire() && - !vol_ignt_counter.pending && - !blockInnerRelease() - - innerRelease(block_vol_ignt = vol_ognt_counter.pending) - - //TODO: accept vol irels when state === s_idle, operate like the VolRelTracker - io.inner.release.ready := irel_can_merge || irel_same_xact - - mergeDataInner(io.inner.release) - - // If there was a writeback, forward it outwards - outerRelease( - block_orel = pending_put_data(vol_ognt_counter.up.idx), - coh = outer_coh.onHit(M_XWR), - data = data_buffer(vol_ognt_counter.up.idx)) - - // Send outer request for miss - outerAcquire( - caching = !xact_iacq.isBuiltInType(), - coh = outer_coh, - data = data_buffer(ognt_counter.up.idx), - wmask = wmask_buffer(ognt_counter.up.idx), - next = s_busy) - - // Handle the response from outer memory - mergeDataOuter(io.outer.grant) - - // Acknowledge or respond with data - innerGrant( - data = data_buffer(ignt_data_idx), - external_pending = pending_orel || ognt_counter.pending || vol_ognt_counter.pending) - - when(iacq_is_allocating) { - initializeProbes() - } - - initDataInner(io.inner.acquire, iacq_is_allocating || iacq_is_merging) - - // Wait for everything to quiesce - quiesce() { clearWmaskBuffer() } -} diff --git a/src/main/scala/uncore/agents/Bufferless.scala b/src/main/scala/uncore/agents/Bufferless.scala deleted file mode 100644 index a1c02318..00000000 --- a/src/main/scala/uncore/agents/Bufferless.scala +++ /dev/null @@ -1,163 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.agents - -import Chisel._ -import uncore.coherence._ -import uncore.tilelink._ -import uncore.constants._ -import config._ - - -class BufferlessBroadcastHub(implicit p: Parameters) extends HierarchicalCoherenceAgent()(p) { - - // Create TSHRs for outstanding transactions - val irelTrackerList = - (0 until nReleaseTransactors).map(id => - Module(new BufferlessBroadcastVoluntaryReleaseTracker(id))) - val iacqTrackerList = - (nReleaseTransactors until nTransactors).map(id => - Module(new BufferlessBroadcastAcquireTracker(id))) - val trackerList = irelTrackerList ++ iacqTrackerList - - // Propagate incoherence flags - trackerList.map(_.io.incoherent) foreach { _ := io.incoherent } - - // Create an arbiter for the one memory port - val outerList = trackerList.map(_.io.outer) - val outer_arb = Module(new ClientTileLinkIOArbiter(outerList.size) - (p.alterPartial({ case TLId => p(OuterTLId) }))) - outer_arb.io.in <> outerList - io.outer <> outer_arb.io.out - - val iacq = Queue(io.inner.acquire, 1, pipe=true) - val irel = Queue(io.inner.release, 1, pipe=true) - - // Handle acquire transaction initiation - val irel_vs_iacq_conflict = - iacq.valid && - irel.valid && - irel.bits.conflicts(iacq.bits) - - doInputRoutingWithAllocation( - in = iacq, - outs = trackerList.map(_.io.inner.acquire), - allocs = trackerList.map(_.io.alloc.iacq), - allocOverride = Some(!irel_vs_iacq_conflict)) - io.outer.acquire.bits.data := iacq.bits.data - when (io.oacq().hasData()) { - io.outer.acquire.bits.addr_beat := iacq.bits.addr_beat - } - - // Handle releases, which might be voluntary and might have data - doInputRoutingWithAllocation( - in = irel, - outs = trackerList.map(_.io.inner.release), - allocs = trackerList.map(_.io.alloc.irel)) - io.outer.release.bits.data := irel.bits.data - when (io.orel().hasData()) { - io.outer.release.bits.addr_beat := irel.bits.addr_beat - } - - // Wire probe requests and grant reply to clients, finish acks from clients - doOutputArbitration(io.inner.probe, trackerList.map(_.io.inner.probe)) - - doOutputArbitration(io.inner.grant, trackerList.map(_.io.inner.grant)) - io.inner.grant.bits.data := io.outer.grant.bits.data - io.inner.grant.bits.addr_beat := io.outer.grant.bits.addr_beat - - doInputRouting(io.inner.finish, trackerList.map(_.io.inner.finish)) - - disconnectOuterProbeAndFinish() -} - -class BufferlessBroadcastVoluntaryReleaseTracker(trackerId: Int)(implicit p: Parameters) - extends BroadcastVoluntaryReleaseTracker(trackerId)(p) { - - // Tell the parent if any incoming messages conflict with the ongoing transaction - routeInParent(irelCanAlloc = Bool(true)) - - // Start transaction by accepting inner release - innerRelease(block_vol_ignt = pending_orel || vol_ognt_counter.pending) - - // A release beat can be accepted if we are idle, if its a mergeable transaction, or if its a tail beat - // and if the outer relase path is clear - io.inner.release.ready := Mux(io.irel().hasData(), - (state =/= s_idle) && (irel_can_merge || irel_same_xact) && io.outer.release.ready, - (state === s_idle) || irel_can_merge || irel_same_xact) - - // Dispatch outer release - outerRelease(coh = outer_coh.onHit(M_XWR), buffering = Bool(false)) - - quiesce() {} -} - -class BufferlessBroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters) - extends BroadcastAcquireTracker(trackerId)(p) { - - // Setup IOs used for routing in the parent - routeInParent(iacqCanAlloc = Bool(true)) - - // First, take care of accpeting new acquires or secondary misses - // Handling of primary and secondary misses' data and write mask merging - innerAcquire( - can_alloc = Bool(false), - next = s_inner_probe) - - // We are never going to merge anything in the bufferless hub - // Therefore, we only need to concern ourselves with the allocated - // transaction and (in case of PutBlock) subsequent tail beats - val iacq_can_forward = iacq_same_xact && !vol_ognt_counter.pending - io.inner.acquire.ready := Mux(io.iacq().hasData(), - state === s_outer_acquire && iacq_can_forward && io.outer.acquire.ready, - state === s_idle && io.alloc.iacq.should) - - // Track which clients yet need to be probed and make Probe message - innerProbe( - inner_coh.makeProbe(curr_probe_dst, xact_iacq, xact_addr_block), - s_outer_acquire) - - // Handle incoming releases from clients, which may reduce sharer counts - // and/or write back dirty data, and may be unexpected voluntary releases - def irel_can_merge = io.irel().conflicts(xact_addr_block) && - io.irel().isVoluntary() && - !vol_ignt_counter.pending && - !(io.irel().hasData() && ognt_counter.pending) && - (state =/= s_idle) - - innerRelease(block_vol_ignt = vol_ognt_counter.pending) - - val irel_could_accept = irel_can_merge || irel_same_xact - io.inner.release.ready := irel_could_accept && - (!io.irel().hasData() || io.outer.release.ready) - - // If there was a writeback, forward it outwards - outerRelease( - coh = outer_coh.onHit(M_XWR), - buffering = Bool(false), - block_orel = !irel_could_accept) - - // Send outer request for miss - outerAcquire( - caching = !xact_iacq.isBuiltInType(), - block_outer_acquire = vol_ognt_counter.pending, - buffering = Bool(false), - coh = outer_coh, - next = s_busy) - - // Handle the response from outer memory - when (ognt_counter.pending && io.ognt().hasData()) { - io.outer.grant.ready := io.inner.grant.ready // bypass data - } - - // Acknowledge or respond with data - innerGrant( - external_pending = pending_orel || vol_ognt_counter.pending, - buffering = Bool(false)) - - when(iacq_is_allocating) { initializeProbes() } - - // Wait for everything to quiesce - quiesce() {} -} diff --git a/src/main/scala/uncore/agents/Mmio.scala b/src/main/scala/uncore/agents/Mmio.scala deleted file mode 100644 index e4c9a047..00000000 --- a/src/main/scala/uncore/agents/Mmio.scala +++ /dev/null @@ -1,75 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package uncore.agents - -import Chisel._ -import uncore.tilelink._ -import config._ - -class MMIOTileLinkManagerData(implicit p: Parameters) - extends TLBundle()(p) - with HasClientId - with HasClientTransactionId - -class MMIOTileLinkManager(implicit p: Parameters) - extends CoherenceAgentModule()(p) { - val io = new ManagerTLIO - - // MMIO requests should never need probe or release - io.inner.probe.valid := Bool(false) - io.inner.release.ready := Bool(false) - - val multibeat_fire = io.outer.acquire.fire() && io.oacq().hasMultibeatData() - val multibeat_start = multibeat_fire && io.oacq().addr_beat === UInt(0) - val multibeat_end = multibeat_fire && io.oacq().addr_beat === UInt(outerDataBeats - 1) - - // Acquire and Grant are basically passthru, - // except client_id and client_xact_id need to be converted. - // Associate the inner client_id and client_xact_id - // with the outer client_xact_id. - val xact_pending = Reg(init = UInt(0, maxManagerXacts)) - val xact_id_sel = PriorityEncoder(~xact_pending) - val xact_id_reg = RegEnable(xact_id_sel, multibeat_start) - val xact_multibeat = Reg(init = Bool(false)) - val outer_xact_id = Mux(xact_multibeat, xact_id_reg, xact_id_sel) - val xact_free = !xact_pending.andR - val xact_buffer = Reg(Vec(maxManagerXacts, new MMIOTileLinkManagerData)) - - io.inner.acquire.ready := io.outer.acquire.ready && xact_free - io.outer.acquire.valid := io.inner.acquire.valid && xact_free - io.outer.acquire.bits <> io.inner.acquire.bits - io.outer.acquire.bits.client_xact_id := outer_xact_id - - def isLastBeat[T <: TileLinkChannel with HasTileLinkBeatId](in: T): Bool = - !in.hasMultibeatData() || in.addr_beat === UInt(outerDataBeats - 1) - - def addPendingBitOnAcq[T <: AcquireMetadata](in: DecoupledIO[T]): UInt = - Mux(in.fire() && isLastBeat(in.bits), UIntToOH(in.bits.client_xact_id), UInt(0)) - - def clearPendingBitOnGnt[T <: GrantMetadata](in: DecoupledIO[T]): UInt = - ~Mux(in.fire() && isLastBeat(in.bits) && !in.bits.requiresAck(), - UIntToOH(in.bits.manager_xact_id), UInt(0)) - - def clearPendingBitOnFin(in: DecoupledIO[Finish]): UInt = - ~Mux(in.fire(), UIntToOH(in.bits.manager_xact_id), UInt(0)) - - xact_pending := (xact_pending | addPendingBitOnAcq(io.outer.acquire)) & - clearPendingBitOnFin(io.inner.finish) & - clearPendingBitOnGnt(io.inner.grant) - - when (io.outer.acquire.fire() && isLastBeat(io.outer.acquire.bits)) { - xact_buffer(outer_xact_id) <> io.iacq() - } - - when (multibeat_start) { xact_multibeat := Bool(true) } - when (multibeat_end) { xact_multibeat := Bool(false) } - - val gnt_xact = xact_buffer(io.ognt().client_xact_id) - io.outer.grant.ready := io.inner.grant.ready - io.inner.grant.valid := io.outer.grant.valid - io.inner.grant.bits <> io.outer.grant.bits - io.inner.grant.bits.client_id := gnt_xact.client_id - io.inner.grant.bits.client_xact_id := gnt_xact.client_xact_id - io.inner.grant.bits.manager_xact_id := io.ognt().client_xact_id - io.inner.finish.ready := Bool(true) -} diff --git a/src/main/scala/uncore/agents/StatelessBridge.scala b/src/main/scala/uncore/agents/StatelessBridge.scala deleted file mode 100644 index bc79b74d..00000000 --- a/src/main/scala/uncore/agents/StatelessBridge.scala +++ /dev/null @@ -1,69 +0,0 @@ -// See LICENSE.SiFive for license details. - -package uncore.agents - -import Chisel._ -import uncore.coherence._ -import uncore.tilelink._ -import uncore.constants._ -import uncore.devices._ -import config._ - -/** The ManagerToClientStateless Bridge does not maintain any state for the messages - * which pass through it. It simply passes the messages back and forth without any - * tracking or translation. - * - * This can reduce area and timing in very constrained situations: - * - The Manager and Client implement the same coherence protocol - * - There are no probe or finish messages. - * - The outer transaction ID is large enough to handle all possible inner - * transaction IDs, such that no remapping state must be maintained. - * - * This bridge DOES NOT keep the uncached channel coherent with the cached - * channel. Uncached requests to blocks cached by the L1 will not probe the L1. - * As a result, uncached reads to cached blocks will get stale data until - * the L1 performs a voluntary writeback, and uncached writes to cached blocks - * will get lost, as the voluntary writeback from the L1 will overwrite the - * changes. If your tile relies on probing the L1 data cache in order to - * share data between the instruction cache and data cache (e.g. you are using - * a non-blocking L1 D$) or if the tile has uncached channels capable of - * writes (e.g. Hwacha and other RoCC accelerators), DO NOT USE THIS BRIDGE. - */ - -class ManagerToClientStatelessBridge(implicit p: Parameters) extends HierarchicalCoherenceAgent()(p) { - val icid = io.inner.tlClientIdBits - val ixid = io.inner.tlClientXactIdBits - val oxid = io.outer.tlClientXactIdBits - - val innerCoh = io.inner.tlCoh.getClass - val outerCoh = io.outer.tlCoh.getClass - - // Stateless Bridge is only usable in certain constrained situations. - // Sanity check its usage here. - - require(io.inner.tlNCachingClients <= 1) - require(icid + ixid <= oxid) - require(innerCoh eq outerCoh, - s"Coherence policies do not match: inner is ${innerCoh.getSimpleName}, outer is ${outerCoh.getSimpleName}") - - io.outer.acquire.valid := io.inner.acquire.valid - io.inner.acquire.ready := io.outer.acquire.ready - io.outer.acquire.bits := io.inner.acquire.bits - io.outer.acquire.bits.client_xact_id := Cat(io.inner.acquire.bits.client_id, io.inner.acquire.bits.client_xact_id) - - io.outer.release.valid := io.inner.release.valid - io.inner.release.ready := io.outer.release.ready - io.outer.release.bits := io.inner.release.bits - io.outer.release.bits.client_xact_id := Cat(io.inner.release.bits.client_id, io.inner.release.bits.client_xact_id) - - io.inner.grant.valid := io.outer.grant.valid - io.outer.grant.ready := io.inner.grant.ready - io.inner.grant.bits := io.outer.grant.bits - io.inner.grant.bits.client_xact_id := io.outer.grant.bits.client_xact_id(ixid-1, 0) - io.inner.grant.bits.client_id := io.outer.grant.bits.client_xact_id(icid+ixid-1, ixid) - - io.inner.probe.valid := Bool(false) - io.inner.finish.ready := Bool(true) - - disconnectOuterProbeAndFinish() -} diff --git a/src/main/scala/uncore/agents/StoreDataQueue.scala b/src/main/scala/uncore/agents/StoreDataQueue.scala deleted file mode 100644 index 1a34b28c..00000000 --- a/src/main/scala/uncore/agents/StoreDataQueue.scala +++ /dev/null @@ -1,119 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package uncore.agents -import Chisel._ -import uncore.tilelink._ -import config._ - -case object L2StoreDataQueueDepth extends Field[Int] - -trait HasStoreDataQueueParameters extends HasCoherenceAgentParameters { - val sdqDepth = p(L2StoreDataQueueDepth)*innerDataBeats - val dqIdxBits = math.max(log2Up(nReleaseTransactors) + 1, log2Up(sdqDepth)) - val nDataQueueLocations = 3 //Stores, VoluntaryWBs, Releases -} - -class DataQueueLocation(implicit p: Parameters) extends CoherenceAgentBundle()(p) - with HasStoreDataQueueParameters { - val idx = UInt(width = dqIdxBits) - val loc = UInt(width = log2Ceil(nDataQueueLocations)) -} - -object DataQueueLocation { - def apply(idx: UInt, loc: UInt)(implicit p: Parameters) = { - val d = Wire(new DataQueueLocation) - d.idx := idx - d.loc := loc - d - } -} - -trait HasStoreDataQueue extends HasStoreDataQueueParameters { - val io: HierarchicalTLIO - val trackerIOsList: Seq[HierarchicalXactTrackerIO] - - val internalDataBits = new DataQueueLocation().getWidth - val inStoreQueue :: inVolWBQueue :: inClientReleaseQueue :: Nil = Enum(UInt(), nDataQueueLocations) - - val usingStoreDataQueue = p.alterPartial({ - case TLKey(`innerTLId`) => innerTLParams.copy(overrideDataBitsPerBeat = Some(internalDataBits)) - case TLKey(`outerTLId`) => outerTLParams.copy(overrideDataBitsPerBeat = Some(internalDataBits)) - }) - - // Queue to store impending Put data - lazy val sdq = Reg(Vec(sdqDepth, io.iacq().data)) - lazy val sdq_val = Reg(init=Bits(0, sdqDepth)) - lazy val sdq_alloc_id = PriorityEncoder(~sdq_val) - lazy val sdq_rdy = !sdq_val.andR - lazy val sdq_enq = trackerIOsList.map( t => - (t.alloc.iacq.should || t.alloc.iacq.matches) && - t.inner.acquire.fire() && - t.iacq().hasData() - ).reduce(_||_) - - lazy val sdqLoc = List.fill(nTransactors) { - DataQueueLocation(sdq_alloc_id, inStoreQueue).asUInt - } - - /* - doInputRoutingWithAllocation( - in = io.inner.acquire, - outs = trackerList.map(_.io.inner.acquire), - allocs = trackerList.map(_.io.alloc._iacq), - dataOverride = Some(sdqLoc), - allocOverride = Some(sdq_rdy && !irel_vs_iacq_conflict)) - */ - - // Queue to store impending Voluntary Release data - lazy val voluntary = io.irel().isVoluntary() - lazy val vwbdq_enq = io.inner.release.fire() && voluntary && io.irel().hasData() - lazy val (rel_data_cnt, rel_data_done) = Counter(vwbdq_enq, innerDataBeats) //TODO Zero width - lazy val vwbdq = Reg(Vec(innerDataBeats, io.irel().data)) //TODO Assumes nReleaseTransactors == 1 - - - lazy val vwbqLoc = (0 until nTransactors).map(i => - (DataQueueLocation(rel_data_cnt, - (if(i < nReleaseTransactors) inVolWBQueue - else inClientReleaseQueue)).asUInt)) - /* - doInputRoutingWithAllocation( - io.inner.release, - trackerList.map(_.io.inner.release), - trackerList.map(_.io.matches.irel), - trackerList.map(_.io.alloc.irel), - Some(vwbqLoc)) - */ - - val outer_arb: ClientTileLinkIOArbiter - lazy val outer_data_ptr = new DataQueueLocation().fromBits(outer_arb.io.out.acquire.bits.data) - /* - val outer_arb = Module(new ClientTileLinkIOArbiter(trackerList.size) - (usingStoreDataQueue.alterPartial({ case TLId => p(OuterTLId) }))) - outer_arb.io.in <> trackerList - */ - // Get the pending data out of the store data queue - lazy val is_in_sdq = outer_data_ptr.loc === inStoreQueue - lazy val free_sdq = io.outer.acquire.fire() && - io.outer.acquire.bits.hasData() && - outer_data_ptr.loc === inStoreQueue - /* - io.outer <> outer_arb.io.out - io.outer.acquire.bits.data := MuxLookup(outer_data_ptr.loc, io.irel().data, Array( - inStoreQueue -> sdq(outer_data_ptr.idx), - inVolWBQueue -> vwbdq(outer_data_ptr.idx))) - */ - - // Enqueue SDQ data - def sdqEnqueue() { - when (sdq_enq) { sdq(sdq_alloc_id) := io.iacq().data } - when(vwbdq_enq) { vwbdq(rel_data_cnt) := io.irel().data } - } - - // Update SDQ valid bits - def sdqUpdate() { - when (io.outer.acquire.valid || sdq_enq) { - sdq_val := sdq_val & ~(UIntToOH(outer_data_ptr.idx) & Fill(sdqDepth, free_sdq)) | - PriorityEncoderOH(~sdq_val(sdqDepth-1,0)) & Fill(sdqDepth, sdq_enq) - } - } -} diff --git a/src/main/scala/uncore/agents/Trackers.scala b/src/main/scala/uncore/agents/Trackers.scala deleted file mode 100644 index 75b81263..00000000 --- a/src/main/scala/uncore/agents/Trackers.scala +++ /dev/null @@ -1,654 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.agents - -import Chisel._ -import uncore.coherence._ -import uncore.tilelink._ -import uncore.util._ -import util._ -import config._ -import scala.math.max - -case object EnableL2Logging extends Field[Boolean] - -class TrackerAllocation extends Bundle { - val matches = Bool(OUTPUT) - val can = Bool(OUTPUT) - val should = Bool(INPUT) -} - -class TrackerAllocationIO(implicit val p: Parameters) - extends ParameterizedBundle()(p) - with HasCacheBlockAddress { - val iacq = new TrackerAllocation - val irel = new TrackerAllocation - val oprb = new TrackerAllocation - val idle = Bool(OUTPUT) - override val addr_block = UInt(OUTPUT, tlBlockAddrBits) -} - -trait HasTrackerAllocationIO extends Bundle { - implicit val p: Parameters - val alloc = new TrackerAllocationIO -} - -class ManagerXactTrackerIO(implicit p: Parameters) extends ManagerTLIO()(p) - with HasTrackerAllocationIO - -class HierarchicalXactTrackerIO(implicit p: Parameters) extends HierarchicalTLIO()(p) - with HasTrackerAllocationIO - -abstract class XactTracker(implicit p: Parameters) extends CoherenceAgentModule()(p) - with HasXactTrackerStates - with HasPendingBitHelpers { - override val s_idle :: s_meta_read :: s_meta_resp :: s_wb_req :: s_wb_resp :: s_inner_probe :: s_outer_acquire :: s_busy :: s_meta_write :: Nil = Enum(UInt(), 9) - val state = Reg(init=s_idle) - - def quiesce(next: UInt = s_idle)(restore: => Unit) { - all_pending_done := !scoreboard.foldLeft(Bool(false))(_||_) - when(state === s_busy && all_pending_done) { - state := next - restore - } - } - - def pinAllReadyValidLow[T <: Data](b: Bundle) { - b.elements.foreach { - _._2 match { - case d: DecoupledIO[_] => - if(d.ready.dir == OUTPUT) d.ready := Bool(false) - else if(d.valid.dir == OUTPUT) d.valid := Bool(false) - case v: ValidIO[_] => if(v.valid.dir == OUTPUT) v.valid := Bool(false) - case b: Bundle => pinAllReadyValidLow(b) - case _ => - } - } - } -} - -trait HasXactTrackerStates { - def state: UInt - def s_idle: UInt = UInt(0) - def s_meta_read: UInt - def s_meta_resp: UInt - def s_wb_req: UInt - def s_wb_resp: UInt - def s_inner_probe: UInt - def s_outer_acquire: UInt - def s_busy: UInt - def s_meta_write: UInt -} - -trait HasPendingBitHelpers extends HasDataBeatCounters { - val scoreboard = scala.collection.mutable.ListBuffer.empty[Bool] - val all_pending_done = Wire(Bool()) - - def addPendingBitWhenBeat[T <: HasBeat](inc: Bool, in: T): UInt = - Fill(in.tlDataBeats, inc) & UIntToOH(in.addr_beat) - - def dropPendingBitWhenBeat[T <: HasBeat](dec: Bool, in: T): UInt = - ~Fill(in.tlDataBeats, dec) | ~UIntToOH(in.addr_beat) - - def addPendingBitWhenId[T <: HasClientId](inc: Bool, in: T): UInt = - Fill(in.tlNCachingClients, inc) & UIntToOH(in.client_id) - - def dropPendingBitWhenId[T <: HasClientId](dec: Bool, in: T): UInt = - ~Fill(in.tlNCachingClients, dec) | ~UIntToOH(in.client_id) - - def addPendingBitWhenBeatHasData[T <: HasBeat](in: DecoupledIO[T], inc: Bool = Bool(true)): UInt = - addPendingBitWhenBeat(in.fire() && in.bits.hasData() && inc, in.bits) - - def addPendingBitWhenBeatHasDataAndAllocs( - in: DecoupledIO[AcquireFromSrc], - alloc_override: Bool = Bool(false)): UInt = - addPendingBitWhenBeatHasData(in, in.bits.allocate() || alloc_override) - - def addPendingBitWhenBeatNeedsRead(in: DecoupledIO[AcquireFromSrc], - always: Bool = Bool(true), unless: Bool = Bool(false)): UInt = { - val a = in.bits - val needs_read = !unless && (a.isGet() || a.isAtomic() || a.hasPartialWritemask()) || always - addPendingBitWhenBeat(in.fire() && needs_read, a) - } - - def addPendingBitWhenBeatHasPartialWritemask(in: DecoupledIO[AcquireFromSrc]): UInt = - addPendingBitWhenBeat(in.fire() && in.bits.hasPartialWritemask(), in.bits) - - def addPendingBitsFromAcquire(a: SecondaryMissInfo): UInt = - Mux(a.hasMultibeatData(), Fill(a.tlDataBeats, UInt(1, 1)), UIntToOH(a.addr_beat)) - - def dropPendingBitWhenBeatHasData[T <: HasBeat](in: DecoupledIO[T]): UInt = - dropPendingBitWhenBeat(in.fire() && in.bits.hasData(), in.bits) - - def dropPendingBitAtDest[T <: HasId](in: DecoupledIO[T]): UInt = - dropPendingBitWhenId(in.fire(), in.bits) - - def dropPendingBitAtDestWhenVoluntary[T <: HasId with MightBeVoluntary](in: DecoupledIO[T]): UInt = - dropPendingBitWhenId(in.fire() && in.bits.isVoluntary(), in.bits) - - def addPendingBitAtSrc[T <: HasId](in: DecoupledIO[T]): UInt = - addPendingBitWhenId(in.fire(), in.bits) - - def addPendingBitAtSrcWhenVoluntary[T <: HasId with MightBeVoluntary](in: DecoupledIO[T]): UInt = - addPendingBitWhenId(in.fire() && in.bits.isVoluntary(), in.bits) - - def addOtherBits(en: Bool, nBits: Int): UInt = - Mux(en, Cat(Fill(nBits - 1, UInt(1, 1)), UInt(0, 1)), UInt(0, nBits)) - - def addPendingBitsOnFirstBeat(in: DecoupledIO[Acquire]): UInt = - addOtherBits(in.fire() && - in.bits.hasMultibeatData() && - in.bits.addr_beat === UInt(0), - in.bits.tlDataBeats) - - def dropPendingBitsOnFirstBeat(in: DecoupledIO[Acquire]): UInt = - ~addPendingBitsOnFirstBeat(in) -} - -trait HasDataBuffer extends HasCoherenceAgentParameters { - val data_buffer = Reg(init=Vec.fill(innerDataBeats)(UInt(0, width = innerDataBits))) - - type TLDataBundle = TLBundle with HasTileLinkData with HasTileLinkBeatId - - def initDataInner[T <: Acquire](in: DecoupledIO[T], alloc: Bool) { - when(in.fire() && in.bits.hasData() && alloc) { - data_buffer(in.bits.addr_beat) := in.bits.data - } - } - - // TODO: provide func for accessing when innerDataBeats =/= outerDataBeats or internalDataBeats - def mergeData(dataBits: Int)(beat: UInt, incoming: UInt) { - data_buffer(beat) := incoming - } - - def mergeDataInner[T <: TLDataBundle](in: DecoupledIO[T]) { - when(in.fire() && in.bits.hasData()) { - mergeData(innerDataBits)(in.bits.addr_beat, in.bits.data) - } - } - - def mergeDataOuter[T <: TLDataBundle](in: DecoupledIO[T]) { - when(in.fire() && in.bits.hasData()) { - mergeData(outerDataBits)(in.bits.addr_beat, in.bits.data) - } - } -} - -trait HasByteWriteMaskBuffer extends HasDataBuffer { - val wmask_buffer = Reg(init=Vec.fill(innerDataBeats)(UInt(0, width = innerWriteMaskBits))) - val data_valid = Vec(wmask_buffer.map(wmask => wmask.andR)) - - override def initDataInner[T <: Acquire](in: DecoupledIO[T], alloc: Bool) { - when(in.fire() && in.bits.hasData() && alloc) { - val beat = in.bits.addr_beat - val full = FillInterleaved(8, in.bits.wmask()) - data_buffer(beat) := (~full & data_buffer(beat)) | (full & in.bits.data) - wmask_buffer(beat) := in.bits.wmask() | wmask_buffer(beat) // assumes wmask_buffer is zeroed - } - } - - override def mergeData(dataBits: Int)(beat: UInt, incoming: UInt) { - val old_data = incoming // Refilled, written back, or de-cached data - val new_data = data_buffer(beat) // Newly Put data is already in the buffer - val wmask = FillInterleaved(8, wmask_buffer(beat)) - data_buffer(beat) := (~wmask & old_data) | (wmask & new_data) - wmask_buffer(beat) := ~UInt(0, innerWriteMaskBits) - } - - def clearWmaskBuffer() { - wmask_buffer.foreach { w => w := UInt(0) } - } -} - -trait HasBlockAddressBuffer extends HasCoherenceAgentParameters { - val xact_addr_block = Reg(init = UInt(0, width = blockAddrBits)) -} - - -trait HasAcquireMetadataBuffer extends HasBlockAddressBuffer { - val xact_allocate = Reg{ Bool() } - val xact_amo_shift_bytes = Reg{ UInt() } - val xact_op_code = Reg{ UInt() } - val xact_addr_byte = Reg{ UInt() } - val xact_op_size = Reg{ UInt() } - val xact_addr_beat = Wire(UInt()) - val xact_iacq = Wire(new SecondaryMissInfo) -} - -trait HasVoluntaryReleaseMetadataBuffer extends HasBlockAddressBuffer - with HasPendingBitHelpers - with HasXactTrackerStates { - def io: HierarchicalXactTrackerIO - - val xact_vol_ir_r_type = Reg{ UInt() } - val xact_vol_ir_src = Reg{ UInt() } - val xact_vol_ir_client_xact_id = Reg{ UInt() } - - def xact_vol_irel = Release( - src = xact_vol_ir_src, - voluntary = Bool(true), - r_type = xact_vol_ir_r_type, - client_xact_id = xact_vol_ir_client_xact_id, - addr_block = xact_addr_block) - (p.alterPartial({ case TLId => p(InnerTLId) })) -} - -trait AcceptsVoluntaryReleases extends HasVoluntaryReleaseMetadataBuffer { - def inner_coh: ManagerMetadata - - val pending_irel_data = Reg(init=Bits(0, width = innerDataBeats)) - val vol_ignt_counter = Wire(new TwoWayBeatCounterStatus) - - def irel_can_merge: Bool - def irel_same_xact: Bool - def irel_is_allocating: Bool = state === s_idle && io.alloc.irel.should && io.inner.release.valid - def irel_is_merging: Bool = (irel_can_merge || irel_same_xact) && io.inner.release.valid - - def innerRelease(block_vol_ignt: Bool = Bool(false), next: UInt = s_busy) { - connectTwoWayBeatCounters( - status = vol_ignt_counter, - up = io.inner.release, - down = io.inner.grant, - trackUp = (r: Release) => { - Mux(state === s_idle, io.alloc.irel.should, io.alloc.irel.matches) && r.isVoluntary() && r.requiresAck() - }, - trackDown = (g: Grant) => (state =/= s_idle) && g.isVoluntary()) - - - when(irel_is_allocating) { - xact_addr_block := io.irel().addr_block - // Set all of them to pending in the beginning as a precaution - // If it turns out we don't need some or all of the beats, they will - // be overridden below - pending_irel_data := ~UInt(0, innerDataBeats) - state := next - } - - val irel_fire = (irel_is_allocating || irel_is_merging) && io.inner.release.ready - when (irel_fire) { - when (io.irel().first()) { - when (io.irel().isVoluntary()) { - xact_vol_ir_r_type := io.irel().r_type - xact_vol_ir_src := io.irel().client_id - xact_vol_ir_client_xact_id := io.irel().client_xact_id - } - // If this release has data, set all the pending bits except the first. - // Otherwise, clear all the pending bits - pending_irel_data := Mux(io.irel().hasMultibeatData(), - dropPendingBitWhenBeatHasData(io.inner.release), - UInt(0)) - } .otherwise { - pending_irel_data := (pending_irel_data & dropPendingBitWhenBeatHasData(io.inner.release)) - } - if (p(EnableL2Logging)) { - when (io.irel().hasData()) { - printf("[release] addr_block=%x addr_beat=%d data=%x\n", - io.irel().addr_block, io.irel().addr_beat, io.irel().data) - } - } - } - - io.inner.grant.valid := state.isOneOf(s_wb_req, s_wb_resp, s_inner_probe, s_busy) && - vol_ignt_counter.pending && - !(pending_irel_data.orR || block_vol_ignt) - - io.inner.grant.bits := inner_coh.makeGrant(xact_vol_irel) - - scoreboard += (pending_irel_data.orR, vol_ignt_counter.pending) - } - -} - -trait EmitsVoluntaryReleases extends HasVoluntaryReleaseMetadataBuffer { - val pending_orel_send = Reg(init=Bool(false)) - val pending_orel_data = Reg(init=Bits(0, width = innerDataBeats)) - val vol_ognt_counter = Wire(new TwoWayBeatCounterStatus) - val pending_orel = pending_orel_send || pending_orel_data.orR || vol_ognt_counter.pending - val sending_orel = Reg(init = Bool(false)) - - // Block acceptance of inner releases if we have already started sending - // outer releases, but have not yet sent out the beat corresponding to the - // inner release. This function must be included in io.inner.release.ready - // if it is possible to start accepting a new inner release as the previous - // outer release is still being sent. DO NOT include this in the - // io.inner.release.ready if the releases are not buffered - // (i.e. io.inner.release and io.outer.release combinationally linked). - def blockInnerRelease(rel: ReleaseMetadata = io.irel()): Bool = { - val waiting_to_send = sending_orel && pending_orel_data(rel.addr_beat) - val sending_now = io.outer.release.fire() && rel.addr_beat === io.orel().addr_beat - rel.hasData() && (waiting_to_send || sending_now) - } - - def outerRelease( - coh: ClientMetadata, - buffering: Bool = Bool(true), - data: UInt = io.irel().data, - add_pending_data_bits: UInt = UInt(0), - add_pending_send_bit: Bool = Bool(false), - block_orel: Bool = Bool(false)) { - - when (state =/= s_idle || io.alloc.irel.should) { - pending_orel_data := (pending_orel_data | - addPendingBitWhenBeatHasData(io.inner.release) | - add_pending_data_bits) & - dropPendingBitWhenBeatHasData(io.outer.release) - } - when (add_pending_send_bit) { pending_orel_send := Bool(true) } - when (io.outer.release.fire()) { - when (io.outer.release.bits.first()) { sending_orel := Bool(true) } - when (io.outer.release.bits.last()) { sending_orel := Bool(false) } - pending_orel_send := Bool(false) - } - - connectTwoWayBeatCounters( - status = vol_ognt_counter, - up = io.outer.release, - down = io.outer.grant, - trackUp = (r: Release) => r.isVoluntary() && r.requiresAck(), - trackDown = (g: Grant) => g.isVoluntary()) - - io.outer.release.valid := !block_orel && Mux(buffering, - (state === s_busy) && Mux(io.orel().hasData(), - pending_orel_data(vol_ognt_counter.up.idx), - pending_orel_send), - // only writebacks need to be forwarded to the outer interface - state =/= s_idle && io.alloc.irel.matches && - io.irel().hasData() && io.inner.release.valid) - - io.outer.release.bits := coh.makeVoluntaryWriteback( - client_xact_id = UInt(0), // TODO was tracker id, but not needed? - addr_block = xact_addr_block, - addr_beat = vol_ognt_counter.up.idx, - data = data) - - when (vol_ognt_counter.pending) { io.outer.grant.ready := Bool(true) } - - scoreboard += (pending_orel, vol_ognt_counter.pending) - } -} - -trait EmitsInnerProbes extends HasBlockAddressBuffer - with HasXactTrackerStates - with HasPendingBitHelpers { - def io: HierarchicalXactTrackerIO - - val needs_probes = (innerNCachingClients > 0) - val pending_iprbs = Reg(UInt(width = max(innerNCachingClients, 1))) - val curr_probe_dst = PriorityEncoder(pending_iprbs) - - def full_representation: UInt - def initializeProbes() { - if (needs_probes) - pending_iprbs := full_representation & ~io.incoherent.asUInt - else - pending_iprbs := UInt(0) - } - def irel_same_xact = io.irel().conflicts(xact_addr_block) && - !io.irel().isVoluntary() && - state === s_inner_probe - - def innerProbe(prb: Probe, next: UInt) { - if (needs_probes) { - val irel_counter = Wire(new TwoWayBeatCounterStatus) - - pending_iprbs := pending_iprbs & dropPendingBitAtDest(io.inner.probe) - io.inner.probe.valid := state === s_inner_probe && pending_iprbs.orR - io.inner.probe.bits := prb - - connectTwoWayBeatCounters( - status = irel_counter, - up = io.inner.probe, - down = io.inner.release, - max = innerNCachingClients, - trackDown = (r: Release) => (state =/= s_idle) && !r.isVoluntary()) - - when(state === s_inner_probe && !(pending_iprbs.orR || irel_counter.pending)) { - state := next - } - } else { - when (state === s_inner_probe) { state := next } - } - - //N.B. no pending bits added to scoreboard because all handled in s_inner_probe - } -} - -trait RoutesInParent extends HasBlockAddressBuffer - with HasXactTrackerStates { - def io: HierarchicalXactTrackerIO - type AddrComparison = HasCacheBlockAddress => Bool - def exactAddrMatch(a: HasCacheBlockAddress): Bool = a.conflicts(xact_addr_block) - def routeInParent(iacqMatches: AddrComparison = exactAddrMatch, - irelMatches: AddrComparison = exactAddrMatch, - oprbMatches: AddrComparison = exactAddrMatch, - iacqCanAlloc: Bool = Bool(false), - irelCanAlloc: Bool = Bool(false), - oprbCanAlloc: Bool = Bool(false)) { - io.alloc.iacq.matches := (state =/= s_idle) && iacqMatches(io.iacq()) - io.alloc.irel.matches := (state =/= s_idle) && irelMatches(io.irel()) - io.alloc.oprb.matches := (state =/= s_idle) && oprbMatches(io.oprb()) - io.alloc.iacq.can := state === s_idle && iacqCanAlloc - io.alloc.irel.can := state === s_idle && irelCanAlloc - io.alloc.oprb.can := state === s_idle && oprbCanAlloc - io.alloc.addr_block := xact_addr_block - io.alloc.idle := state === s_idle - } -} - -trait AcceptsInnerAcquires extends HasAcquireMetadataBuffer - with AcceptsVoluntaryReleases - with HasXactTrackerStates - with HasPendingBitHelpers { - def io: HierarchicalXactTrackerIO - def nSecondaryMisses: Int - def alwaysWriteFullBeat: Boolean - def inner_coh: ManagerMetadata - def trackerId: Int - - // Secondary miss queue holds transaction metadata used to make grants - lazy val ignt_q = Module(new Queue( - new SecondaryMissInfo()(p.alterPartial({ case TLId => p(InnerTLId) })), - 1 + nSecondaryMisses)) - - val pending_ignt = Wire(Bool()) - val ignt_data_idx = Wire(UInt()) - val ignt_data_done = Wire(Bool()) - val ifin_counter = Wire(new TwoWayBeatCounterStatus) - val pending_put_data = Reg(init=Bits(0, width = innerDataBeats)) - val pending_ignt_data = Reg(init=Bits(0, width = innerDataBeats)) - - def iacq_same_xact: Bool = - (xact_iacq.client_xact_id === io.iacq().client_xact_id) && - (xact_iacq.client_id === io.iacq().client_id) && - pending_ignt - def iacq_same_xact_multibeat = iacq_same_xact && io.iacq().hasMultibeatData() - def iacq_can_merge: Bool - def iacq_is_allocating: Bool = state === s_idle && io.alloc.iacq.should && io.inner.acquire.valid - def iacq_is_merging: Bool = (iacq_can_merge || iacq_same_xact) && io.inner.acquire.valid - - def innerAcquire(can_alloc: Bool, next: UInt) { - val iacq_matches_head = iacq_same_xact && xact_iacq.addr_beat === io.iacq().addr_beat - - // Enqueue some metadata information that we'll use to make coherence updates with later - ignt_q.io.enq.valid := iacq_is_allocating || - (!iacq_matches_head && pending_ignt && - io.inner.acquire.fire() && io.iacq().first()) - ignt_q.io.enq.bits := io.iacq() - - // Use the outputs of the queue to make further messages - xact_iacq := Mux(ignt_q.io.deq.valid, ignt_q.io.deq.bits, ignt_q.io.enq.bits) - xact_addr_beat := xact_iacq.addr_beat - pending_ignt := ignt_q.io.count > UInt(0) - - // Track whether any beats are missing from a PutBlock - when (state =/= s_idle || io.alloc.iacq.should) { - pending_put_data := (pending_put_data & - dropPendingBitWhenBeatHasData(io.inner.acquire)) | - addPendingBitsOnFirstBeat(io.inner.acquire) - } - - // Intialize transaction metadata for accepted Acquire - when(iacq_is_allocating) { - xact_addr_block := io.iacq().addr_block - xact_allocate := io.iacq().allocate() && can_alloc - xact_amo_shift_bytes := io.iacq().amo_shift_bytes() - xact_op_code := io.iacq().op_code() - xact_addr_byte := io.iacq().addr_byte() - xact_op_size := io.iacq().op_size() - // Make sure to collect all data from a PutBlock - pending_put_data := Mux( - io.iacq().isBuiltInType(Acquire.putBlockType), - dropPendingBitWhenBeatHasData(io.inner.acquire), - UInt(0)) - pending_ignt_data := UInt(0) - state := next - } - - scoreboard += (pending_put_data.orR) - } - - def innerGrant( - data: UInt = io.ognt().data, - external_pending: Bool = Bool(false), - buffering: Bool = Bool(true), - add_pending_bits: UInt = UInt(0)) { - // Track the number of outstanding inner.finishes - connectTwoWayBeatCounters( - status = ifin_counter, - up = io.inner.grant, - down = io.inner.finish, - max = nSecondaryMisses, - trackUp = (g: Grant) => g.requiresAck()) - - // Track which beats are ready for response - when(!iacq_is_allocating) { - pending_ignt_data := pending_ignt_data | - addPendingBitWhenBeatHasData(io.inner.release) | - addPendingBitWhenBeatHasData(io.outer.grant) | - add_pending_bits - } - - if (p(EnableL2Logging)) { - when (io.inner.grant.fire() && io.ignt().hasData()) { - printf("[get] addr_block=%x addr_beat=%d data=%x\n", - xact_addr_block, io.ignt().addr_beat, io.ignt().data) - } - } - - // Have we finished receiving the complete inner acquire transaction? - val iacq_finished = !(state === s_idle || - state === s_meta_read || - pending_put_data.orR) - - val ignt_from_iacq = inner_coh.makeGrant( - sec = ignt_q.io.deq.bits, - manager_xact_id = UInt(trackerId), - data = data) - - // Make the Grant message using the data stored in the secondary miss queue - val (cnt, done) = connectOutgoingDataBeatCounter(io.inner.grant, ignt_q.io.deq.bits.addr_beat) - ignt_data_idx := cnt - ignt_data_done := done - ignt_q.io.deq.ready := Bool(false) - when(!vol_ignt_counter.pending) { - ignt_q.io.deq.ready := ignt_data_done - io.inner.grant.bits := ignt_from_iacq - io.inner.grant.bits.addr_beat := ignt_data_idx // override based on outgoing counter - when (state === s_busy && pending_ignt) { - io.inner.grant.valid := !external_pending && - Mux(io.ignt().hasData(), - Mux(buffering, - pending_ignt_data(ignt_data_idx), - io.outer.grant.valid), - iacq_finished) - } - } - - // We must wait for as many Finishes as we sent Grants - io.inner.finish.ready := state === s_busy - - scoreboard += (pending_ignt, ifin_counter.pending) - } - -} - -trait EmitsOuterAcquires extends AcceptsInnerAcquires { - val ognt_counter = Wire(new TwoWayBeatCounterStatus) - - // Handle misses or coherence permission upgrades by initiating a new transaction in the outer memory: - // - // If we're allocating in this cache, we can use the current metadata - // to make an appropriate custom Acquire, otherwise we copy over the - // built-in Acquire from the inner TL to the outer TL - def outerAcquire( - caching: Bool, - coh: ClientMetadata, - block_outer_acquire: Bool = Bool(false), - buffering: Bool = Bool(true), - data: UInt = io.iacq().data, - wmask: UInt = io.iacq().wmask(), - next: UInt = s_busy) { - - // Tracks outstanding Acquires, waiting for their matching Grant. - connectTwoWayBeatCounters( - status = ognt_counter, - up = io.outer.acquire, - down = io.outer.grant, - beat = xact_addr_beat, - trackDown = (g: Grant) => !g.isVoluntary()) - - io.outer.acquire.valid := - state === s_outer_acquire && !block_outer_acquire && - (xact_allocate || - Mux(buffering, - !pending_put_data(ognt_counter.up.idx), - // If not buffering, we should only send an outer acquire if - // the ignt_q is not empty (pending_ignt) and the enqueued - // transaction does not have data or we are receiving the - // inner acquire and it is the same transaction as the one enqueued. - pending_ignt && (!xact_iacq.hasData() || - (io.inner.acquire.valid && iacq_same_xact)))) - - io.outer.acquire.bits := - Mux(caching, - coh.makeAcquire( - op_code = xact_op_code, - client_xact_id = UInt(0), - addr_block = xact_addr_block), - BuiltInAcquireBuilder( - a_type = xact_iacq.a_type, - client_xact_id = UInt(0), - addr_block = xact_addr_block, - addr_beat = ognt_counter.up.idx, - data = data, - addr_byte = xact_addr_byte, - operand_size = xact_op_size, - opcode = xact_op_code, - wmask = wmask, - alloc = Bool(false)) - (p.alterPartial({ case TLId => p(OuterTLId)}))) - - when(state === s_outer_acquire && ognt_counter.up.done) { state := next } - - when (ognt_counter.pending) { io.outer.grant.ready := Bool(true) } - - scoreboard += ognt_counter.pending - } -} - -abstract class VoluntaryReleaseTracker(val trackerId: Int)(implicit p: Parameters) extends XactTracker()(p) - with AcceptsVoluntaryReleases - with RoutesInParent { - def irel_can_merge = Bool(false) - def irel_same_xact = io.irel().conflicts(xact_addr_block) && - io.irel().isVoluntary() && - pending_irel_data.orR -} - -abstract class AcquireTracker(val trackerId: Int)(implicit p: Parameters) extends XactTracker()(p) - with AcceptsInnerAcquires - with EmitsOuterAcquires - with EmitsInnerProbes - with RoutesInParent { -} diff --git a/src/main/scala/uncore/coherence/Directory.scala b/src/main/scala/uncore/coherence/Directory.scala deleted file mode 100644 index 080bfe17..00000000 --- a/src/main/scala/uncore/coherence/Directory.scala +++ /dev/null @@ -1,43 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package uncore.coherence -import Chisel._ - -// This class encapsulates transformations on different directory information -// storage formats -abstract class DirectoryRepresentation(val width: Int) { - def pop(prev: UInt, id: UInt): UInt - def push(prev: UInt, id: UInt): UInt - def flush: UInt - def none(s: UInt): Bool - def one(s: UInt): Bool - def count(s: UInt): UInt - def next(s: UInt): UInt - def full(s: UInt): UInt -} - -abstract trait HasDirectoryRepresentation { - val dir: DirectoryRepresentation -} - -class NullRepresentation(nClients: Int) extends DirectoryRepresentation(1) { - def pop(prev: UInt, id: UInt) = UInt(0) - def push(prev: UInt, id: UInt) = UInt(0) - def flush = UInt(0) - def none(s: UInt) = Bool(false) - def one(s: UInt) = Bool(false) - def count(s: UInt) = UInt(nClients) - def next(s: UInt) = UInt(0) - def full(s: UInt) = SInt(-1, width = nClients).asUInt -} - -class FullRepresentation(nClients: Int) extends DirectoryRepresentation(nClients) { - def pop(prev: UInt, id: UInt) = prev & ~UIntToOH(id) - def push(prev: UInt, id: UInt) = prev | UIntToOH(id) - def flush = UInt(0, width = width) - def none(s: UInt) = s === UInt(0) - def one(s: UInt) = PopCount(s) === UInt(1) - def count(s: UInt) = PopCount(s) - def next(s: UInt) = PriorityEncoder(s) - def full(s: UInt) = s -} diff --git a/src/main/scala/uncore/coherence/Metadata.scala b/src/main/scala/uncore/coherence/Metadata.scala deleted file mode 100644 index e1d07964..00000000 --- a/src/main/scala/uncore/coherence/Metadata.scala +++ /dev/null @@ -1,344 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package uncore.coherence - -import Chisel._ -import uncore.tilelink._ -import uncore.constants._ -import config._ - -/** Identifies the TLId of the inner network in a hierarchical cache controller */ -case object InnerTLId extends Field[String] -/** Identifies the TLId of the outer network in a hierarchical cache controller */ -case object OuterTLId extends Field[String] - -/** Base class to represent coherence information in clients and managers */ -abstract class CoherenceMetadata(implicit p: Parameters) extends TLBundle()(p) { - val co = tlCoh -} - -/** Stores the client-side coherence information, - * such as permissions on the data and whether the data is dirty. - * Its API can be used to make TileLink messages in response to - * memory operations or [[uncore.Probe]] messages. - */ -class ClientMetadata(implicit p: Parameters) extends CoherenceMetadata()(p) { - /** Actual state information stored in this bundle */ - val state = UInt(width = co.clientStateWidth) - - /** Metadata equality */ - def ===(rhs: ClientMetadata): Bool = this.state === rhs.state - def =/=(rhs: ClientMetadata): Bool = !this.===(rhs) - - /** Is the block's data present in this cache */ - def isValid(dummy: Int = 0): Bool = co.isValid(this) - /** Does this cache have permissions on this block sufficient to perform op */ - def isHit(op_code: UInt): Bool = co.isHit(op_code, this) - /** Does this cache lack permissions on this block sufficient to perform op */ - def isMiss(op_code: UInt): Bool = !co.isHit(op_code, this) - /** Does a secondary miss on the block require another Acquire message */ - def requiresAcquireOnSecondaryMiss(first_op: UInt, second_op: UInt): Bool = - co.requiresAcquireOnSecondaryMiss(first_op, second_op, this) - /** Does op require a Release to be made to outer memory */ - def requiresReleaseOnCacheControl(op_code: UInt): Bool = - co.requiresReleaseOnCacheControl(op_code: UInt, this) - /** Does an eviction require a Release to be made to outer memory */ - def requiresVoluntaryWriteback(dummy: Int = 0): Bool = - co.requiresReleaseOnCacheControl(M_FLUSH, this) - - /** Constructs an Acquire message based on this metdata and a memory operation - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param op_code a memory operation from [[uncore.constants.MemoryOpConstants]] - */ - def makeAcquire( - op_code: UInt, - client_xact_id: UInt, - addr_block: UInt): Acquire = { - Acquire( - is_builtin_type = Bool(false), - a_type = co.getAcquireType(op_code, this), - client_xact_id = client_xact_id, - addr_block = addr_block, - union = Cat(op_code, Bool(true)))(p) - } - - /** Constructs a Release message based on this metadata on cache control op - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param addr_beat sub-block address (which beat) - * @param data data being written back - */ - def makeVoluntaryRelease( - op_code: UInt, - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt = UInt(0), - data: UInt = UInt(0)): Release = - Release( - voluntary = Bool(true), - r_type = co.getReleaseType(op_code, this), - client_xact_id = client_xact_id, - addr_block = addr_block, - addr_beat = addr_beat, - data = data)(p) - - /** Constructs a Release message based on this metadata on an eviction - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param addr_beat sub-block address (which beat) - * @param data data being written back - */ - def makeVoluntaryWriteback( - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt = UInt(0), - data: UInt = UInt(0)): Release = - makeVoluntaryRelease( - op_code = M_FLUSH, - client_xact_id = client_xact_id, - addr_block = addr_block, - addr_beat = addr_beat, - data = data) - - /** Constructs a Release message based on this metadata and a [[uncore.Probe]] - * - * @param the incoming [[uncore.Probe]] - * @param addr_beat sub-block address (which beat) - * @param data data being released - */ - def makeRelease( - prb: Probe, - addr_beat: UInt = UInt(0), - data: UInt = UInt(0)): Release = - Release( - voluntary = Bool(false), - r_type = co.getReleaseType(prb, this), - client_xact_id = UInt(0), - addr_block = prb.addr_block, - addr_beat = addr_beat, - data = data)(p) - - /** New metadata after receiving a [[uncore.Grant]] - * - * @param incoming the incoming [[uncore.Grant]] - * @param pending the mem op that triggered this transaction - */ - def onGrant(incoming: Grant, pending: UInt): ClientMetadata = - co.clientMetadataOnGrant(incoming, pending, this) - - /** New metadata after receiving a [[uncore.Probe]] - * - * @param incoming the incoming [[uncore.Probe]] - */ - def onProbe(incoming: Probe): ClientMetadata = - co.clientMetadataOnProbe(incoming, this) - - /** New metadata after a op_code hits this block - * - * @param op_code a memory operation from [[uncore.constants.MemoryOpConstants]] - */ - def onHit(op_code: UInt): ClientMetadata = - co.clientMetadataOnHit(op_code, this) - - /** New metadata after op_code releases permissions on this block - * - * @param op_code a memory operation from [[uncore.constants.MemoryOpConstants]] - */ - def onCacheControl(op_code: UInt): ClientMetadata = - co.clientMetadataOnCacheControl(op_code, this) -} - -/** Factories for ClientMetadata, including on reset */ -object ClientMetadata { - def apply(state: UInt)(implicit p: Parameters) = { - val meta = Wire(new ClientMetadata) - meta.state := state - meta - } - def onReset(implicit p: Parameters) = ClientMetadata(UInt(0))(p) // TODO: assumes clientInvalid === 0 -} - -/** Stores manager-side information about the status - * of a cache block, including whether it has any known sharers. - * - * Its API can be used to create [[uncore.Probe]] and [[uncore.Grant]] messages. - */ -class ManagerMetadata(implicit p: Parameters) extends CoherenceMetadata()(p) { - // Currently no coherence policies assume manager-side state information - // val state = UInt(width = co.masterStateWidth) TODO: Fix 0-width wires in Chisel - - /** The directory information for this block */ - val sharers = UInt(width = co.dir.width) - - /** Metadata equality */ - def ===(rhs: ManagerMetadata): Bool = //this.state === rhs.state && TODO: Fix 0-width wires in Chisel - this.sharers === rhs.sharers - def =/=(rhs: ManagerMetadata): Bool = !this.===(rhs) - - /** Converts the directory info into an N-hot sharer bitvector (i.e. full representation) */ - def full(dummy: Int = 0): UInt = co.dir.full(this.sharers) - - /** Does this [[uncore.Acquire]] require [[uncore.Probe Probes]] to be sent */ - def requiresProbes(acq: HasAcquireType): Bool = co.requiresProbes(acq, this) - /** Does this memory op require [[uncore.Probe Probes]] to be sent */ - def requiresProbes(op_code: UInt): Bool = co.requiresProbes(op_code, this) - /** Does an eviction require [[uncore.Probe Probes]] to be sent */ - def requiresProbesOnVoluntaryWriteback(dummy: Int = 0): Bool = - co.requiresProbes(M_FLUSH, this) - - /** Construct an appropriate [[uncore.ProbeToDst]] for a given [[uncore.Acquire]] - * - * @param dst Destination client id for this Probe - * @param acq Acquire message triggering this Probe - * @param addr_block address of the cache block being probed - */ - def makeProbe(dst: UInt, acq: HasAcquireType, addr_block: UInt): ProbeToDst = - Probe(dst, co.getProbeType(acq, this), addr_block)(p) - - /** Construct an appropriate [[uncore.ProbeToDst]] for a given [[uncore.Acquire]] - * - * @param dst Destination client id for this Probe - * @param acq Acquire message triggering this Probe - */ - def makeProbe(dst: UInt, acq: AcquireMetadata): ProbeToDst = - Probe(dst, co.getProbeType(acq, this), acq.addr_block)(p) - - /** Construct an appropriate [[uncore.ProbeToDst]] for a given mem op - * - * @param dst Destination client id for this Probe - * @param op_code memory operation triggering this Probe - * @param addr_block address of the cache block being probed - */ - def makeProbe(dst: UInt, op_code: UInt, addr_block: UInt): ProbeToDst = - Probe(dst, co.getProbeType(op_code, this), addr_block)(p) - - /** Construct an appropriate [[uncore.ProbeToDst]] for an eviction - * - * @param dst Destination client id for this Probe - * @param addr_block address of the cache block being probed prior to eviction - */ - def makeProbeForVoluntaryWriteback(dst: UInt, addr_block: UInt): ProbeToDst = - makeProbe(dst, M_FLUSH, addr_block) - - /** Construct an appropriate [[uncore.GrantToDst]] to acknowledge an [[uncore.Release]] - * - * @param rel Release message being acknowledged by this Grant - */ - def makeGrant(rel: ReleaseMetadata with HasClientId): GrantToDst = - Grant( - dst = rel.client_id, - is_builtin_type = Bool(true), - g_type = Grant.voluntaryAckType, - client_xact_id = rel.client_xact_id, - manager_xact_id = UInt(0))(p) - - /** Construct an appropriate [[uncore.GrantToDst]] to respond to an [[uncore.Acquire]] - * - * May contain single or multiple beats of data, or just be a permissions upgrade. - * - * @param acq Acquire message being responded to by this Grant - * @param manager_xact_id manager's transaction id - * @param addr_beat beat id of the data - * @param data data being refilled to the original requestor - */ - def makeGrant( - acq: AcquireMetadata with HasClientId, - manager_xact_id: UInt, - addr_beat: UInt = UInt(0), - data: UInt = UInt(0)): GrantToDst = - Grant( - dst = acq.client_id, - is_builtin_type = acq.isBuiltInType(), - g_type = co.getGrantType(acq, this), - client_xact_id = acq.client_xact_id, - manager_xact_id = manager_xact_id, - addr_beat = addr_beat, - data = data)(p) - - /** Construct an [[uncore.GrantToDst]] to respond to an [[uncore.Acquire]] with some overrides - * - * Used to respond to secondary misses merged into this transaction. - * May contain single or multiple beats of data. - * - * @param sec Secondary miss info - * @param manager_xact_id manager's transaction id - * @param data data being refilled to the original requestor - */ - def makeGrant( - sec: SecondaryMissInfo, - manager_xact_id: UInt, - data: UInt): GrantToDst = { - Grant( - dst = sec.client_id, - is_builtin_type = sec.isBuiltInType(), - g_type = co.getGrantType(sec, this), - client_xact_id = sec.client_xact_id, - manager_xact_id = manager_xact_id, - addr_beat = sec.addr_beat, - data = data)(p) - } - - /** New metadata after receiving a [[uncore.ReleaseFromSrc]] - * - * @param incoming the incoming [[uncore.ReleaseFromSrc]] - */ - def onRelease(incoming: ReleaseMetadata with HasClientId): ManagerMetadata = - co.managerMetadataOnRelease(incoming, incoming.client_id, this) - - /** New metadata after sending a [[uncore.GrantToDst]] - * - * @param outgoing the outgoing [[uncore.GrantToDst]] - */ - def onGrant(outgoing: GrantMetadata with HasClientId): ManagerMetadata = - co.managerMetadataOnGrant(outgoing, outgoing.client_id, this) -} - -/** Factories for ManagerMetadata, including on reset */ -object ManagerMetadata { - def apply(sharers: UInt, state: UInt = UInt(width = 0))(implicit p: Parameters) = { - val meta = Wire(new ManagerMetadata) - //meta.state := state TODO: Fix 0-width wires in Chisel - meta.sharers := sharers - meta - } - def apply(implicit p: Parameters) = { - val meta = Wire(new ManagerMetadata) - //meta.state := UInt(width = 0) TODO: Fix 0-width wires in Chisel - meta.sharers := meta.co.dir.flush - meta - } - def onReset(implicit p: Parameters) = ManagerMetadata(p) -} - -/** HierarchicalMetadata is used in a cache in a multi-level memory hierarchy - * that is a manager with respect to some inner caches and a client with - * respect to some outer cache. - * - * This class makes use of two different sets of TileLink parameters, which are - * applied by contextually mapping [[uncore.TLId]] to one of - * [[uncore.InnerTLId]] or [[uncore.OuterTLId]]. - */ -class HierarchicalMetadata(implicit p: Parameters) extends CoherenceMetadata()(p) { - val inner: ManagerMetadata = new ManagerMetadata()(p.alterPartial({case TLId => p(InnerTLId)})) - val outer: ClientMetadata = new ClientMetadata()(p.alterPartial({case TLId => p(OuterTLId)})) - def ===(rhs: HierarchicalMetadata): Bool = - this.inner === rhs.inner && this.outer === rhs.outer - def =/=(rhs: HierarchicalMetadata): Bool = !this.===(rhs) -} - -/** Factories for HierarchicalMetadata, including on reset */ -object HierarchicalMetadata { - def apply(inner: ManagerMetadata, outer: ClientMetadata) - (implicit p: Parameters): HierarchicalMetadata = { - val m = Wire(new HierarchicalMetadata) - m.inner := inner - m.outer := outer - m - } - def onReset(implicit p: Parameters): HierarchicalMetadata = - apply(ManagerMetadata.onReset, ClientMetadata.onReset) -} diff --git a/src/main/scala/uncore/coherence/Policies.scala b/src/main/scala/uncore/coherence/Policies.scala deleted file mode 100644 index cc86ebd1..00000000 --- a/src/main/scala/uncore/coherence/Policies.scala +++ /dev/null @@ -1,697 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.coherence - -import Chisel._ -import uncore.tilelink._ -import uncore.constants._ -import util._ - -/** The entire CoherencePolicy API consists of the following three traits: - * HasCustomTileLinkMessageTypes, used to define custom messages - * HasClientSideCoherencePolicy, for client coherence agents - * HasManagerSideCoherencePolicy, for manager coherence agents - */ -abstract class CoherencePolicy(val dir: DirectoryRepresentation) - extends HasCustomTileLinkMessageTypes - with HasClientSideCoherencePolicy - with HasManagerSideCoherencePolicy - -/** This API defines the custom, coherence-policy-defined message types, - * as opposed to the built-in ones found in tilelink.scala. - * Policies must enumerate the custom messages to be sent over each - * channel, as well as which of them have associated data. - */ -trait HasCustomTileLinkMessageTypes { - val nAcquireTypes: Int - def acquireTypeWidth = log2Up(nAcquireTypes) - val nProbeTypes: Int - def probeTypeWidth = log2Up(nProbeTypes) - val nReleaseTypes: Int - def releaseTypeWidth = log2Up(nReleaseTypes) - val nGrantTypes: Int - def grantTypeWidth = log2Up(nGrantTypes) - - val acquireTypesWithData = Nil // Only built-in Acquire types have data for now - def releaseTypesWithData: Seq[UInt] - def grantTypesWithData: Seq[UInt] -} - -/** This API contains all functions required for client coherence agents. - * Policies must enumerate the number of client states and define their - * permissions with respect to memory operations. Policies must fill in functions - * to control which messages are sent and how metadata is updated in response - * to coherence events. These funtions are generally called from within the - * ClientMetadata class in metadata.scala - */ -trait HasClientSideCoherencePolicy { - // Client coherence states and their permissions - val nClientStates: Int - def clientStateWidth = log2Ceil(nClientStates) - def clientStatesWithReadPermission: Seq[UInt] - def clientStatesWithWritePermission: Seq[UInt] - def clientStatesWithDirtyData: Seq[UInt] - - // Transaction initiation logic - def isValid(meta: ClientMetadata): Bool - def isHit(cmd: UInt, meta: ClientMetadata): Bool = { - Mux(isWriteIntent(cmd), - meta.state isOneOf clientStatesWithWritePermission, - meta.state isOneOf clientStatesWithReadPermission) - } - //TODO: Assumes all states with write permissions also have read permissions - def requiresAcquireOnSecondaryMiss( - first_cmd: UInt, - second_cmd: UInt, - meta: ClientMetadata): Bool = { - isWriteIntent(second_cmd) && !isWriteIntent(first_cmd) - } - //TODO: Assumes all cache ctrl ops writeback dirty data, and - // doesn't issue transaction when e.g. downgrading Exclusive to Shared: - def requiresReleaseOnCacheControl(cmd: UInt, meta: ClientMetadata): Bool = - meta.state isOneOf clientStatesWithDirtyData - - // Determine which custom message type to use - def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt - def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt - def getReleaseType(p: HasProbeType, meta: ClientMetadata): UInt - - // Mutate ClientMetadata based on messages or cmds - def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata): ClientMetadata - def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata): ClientMetadata - def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata): ClientMetadata - def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata): ClientMetadata -} - -/** This API contains all functions required for manager coherence agents. - * Policies must enumerate the number of manager states. Policies must fill - * in functions to control which Probe and Grant messages are sent and how - * metadata should be updated in response to coherence events. These funtions - * are generally called from within the ManagerMetadata class in metadata.scala - */ -trait HasManagerSideCoherencePolicy extends HasDirectoryRepresentation { - val nManagerStates: Int - def masterStateWidth = log2Ceil(nManagerStates) - - // Transaction probing logic - def requiresProbes(acq: HasAcquireType, meta: ManagerMetadata): Bool - def requiresProbes(cmd: UInt, meta: ManagerMetadata): Bool - - // Determine which custom message type to use in response - def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt - def getProbeType(acq: HasAcquireType, meta: ManagerMetadata): UInt - def getGrantType(acq: HasAcquireType, meta: ManagerMetadata): UInt - def getExclusiveGrantType(): UInt - - // Mutate ManagerMetadata based on messages or cmds - def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata): ManagerMetadata - def managerMetadataOnGrant(outgoing: HasGrantType, dst: UInt, meta: ManagerMetadata) = - ManagerMetadata(sharers=Mux(outgoing.isBuiltInType(), // Assumes all built-ins are uncached - meta.sharers, - dir.push(meta.sharers, dst)))(meta.p) - //state = meta.state) TODO: Fix 0-width wires in Chisel -} - -/** The following concrete implementations of CoherencePolicy each provide the - * functionality of one particular protocol. - */ - -/** A simple protocol with only two Client states. - * Data is always assumed to be dirty. - * Only a single client may ever have a copy of a block at a time. - */ -class MICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) { - // Message types - val nAcquireTypes = 1 - val nProbeTypes = 2 - val nReleaseTypes = 4 - val nGrantTypes = 1 - - val acquireExclusive :: Nil = Enum(UInt(), nAcquireTypes) - val probeInvalidate :: probeCopy :: Nil = Enum(UInt(), nProbeTypes) - val releaseInvalidateData :: releaseCopyData :: releaseInvalidateAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes) - val grantExclusive :: Nil = Enum(UInt(), nGrantTypes) - - def releaseTypesWithData = Seq(releaseInvalidateData, releaseCopyData) - def grantTypesWithData = Seq(grantExclusive) - - // Client states and functions - val nClientStates = 2 - val clientInvalid :: clientValid :: Nil = Enum(UInt(), nClientStates) - - def clientStatesWithReadPermission = Seq(clientValid) - def clientStatesWithWritePermission = Seq(clientValid) - def clientStatesWithDirtyData = Seq(clientValid) - - def isValid (meta: ClientMetadata): Bool = meta.state =/= clientInvalid - - def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt = acquireExclusive - - def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = { - val dirty = meta.state isOneOf clientStatesWithDirtyData - MuxLookup(cmd, releaseCopyAck, Array( - M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck), - M_PRODUCE -> Mux(dirty, releaseCopyData, releaseCopyAck), - M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck))) - } - - def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt = - MuxLookup(incoming.p_type, releaseInvalidateAck, Array( - probeInvalidate -> getReleaseType(M_FLUSH, meta), - probeCopy -> getReleaseType(M_FLUSH, meta))) - - def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) = meta - - def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) = - ClientMetadata(Mux(cmd === M_FLUSH, clientInvalid, meta.state))(meta.p) - - def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) = - ClientMetadata(Mux(incoming.isBuiltInType(), clientInvalid, clientValid))(meta.p) - - def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) = - ClientMetadata(Mux(incoming.p_type === probeInvalidate, - clientInvalid, meta.state))(meta.p) - - // Manager states and functions: - val nManagerStates = 0 // We don't actually need any states for this protocol - - def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) = !dir.none(meta.sharers) - - def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers) - - def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt = - MuxLookup(cmd, probeCopy, Array( - M_FLUSH -> probeInvalidate)) - - def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), - MuxLookup(a.a_type, probeCopy, Array( - Acquire.getBlockType -> probeCopy, - Acquire.putBlockType -> probeInvalidate, - Acquire.getType -> probeCopy, - Acquire.putType -> probeInvalidate, - Acquire.getPrefetchType -> probeCopy, - Acquire.putPrefetchType -> probeInvalidate, - Acquire.putAtomicType -> probeInvalidate)), - probeInvalidate) - - def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type), grantExclusive) - def getExclusiveGrantType(): UInt = grantExclusive - - def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = { - val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p) - MuxCase(meta, Array( - incoming.is(releaseInvalidateData) -> popped, - incoming.is(releaseInvalidateAck) -> popped)) - } -} - -/** A simple protocol with only three Client states. - * Data is marked as dirty when written. - * Only a single client may ever have a copy of a block at a time. - */ -class MEICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) { - // Message types - val nAcquireTypes = 2 - val nProbeTypes = 3 - val nReleaseTypes = 6 - val nGrantTypes = 1 - - val acquireExclusiveClean :: acquireExclusiveDirty :: Nil = Enum(UInt(), nAcquireTypes) - val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(UInt(), nProbeTypes) - val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes) - val grantExclusive :: Nil = Enum(UInt(), nGrantTypes) - - def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData) - def grantTypesWithData = Seq(grantExclusive) - - // Client states and functions - val nClientStates = 3 - val clientInvalid :: clientExclusiveClean :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates) - - def clientStatesWithReadPermission = Seq(clientExclusiveClean, clientExclusiveDirty) - def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty) - def clientStatesWithDirtyData = Seq(clientExclusiveDirty) - - def isValid (meta: ClientMetadata) = meta.state =/= clientInvalid - - def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt = - Mux(isWriteIntent(cmd), acquireExclusiveDirty, acquireExclusiveClean) - - def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = { - val dirty = meta.state isOneOf clientStatesWithDirtyData - MuxLookup(cmd, releaseCopyAck, Array( - M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck), - M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck), - M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck))) - } - - def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt = - MuxLookup(incoming.p_type, releaseInvalidateAck, Array( - probeInvalidate -> getReleaseType(M_FLUSH, meta), - probeDowngrade -> getReleaseType(M_FLUSH, meta), - probeCopy -> getReleaseType(M_FLUSH, meta))) - - def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) = - ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, meta.state))(meta.p) - - def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - MuxLookup(cmd, meta.state, Array( - M_FLUSH -> clientInvalid, - M_CLEAN -> Mux(meta.state === clientExclusiveDirty, clientExclusiveClean, meta.state))))(meta.p) - - def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - Mux(incoming.isBuiltInType(), clientInvalid, - Mux(isWrite(cmd), clientExclusiveDirty, clientExclusiveClean)))(meta.p) - - def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) = - ClientMetadata( - MuxLookup(incoming.p_type, meta.state, Array( - probeInvalidate -> clientInvalid, - probeDowngrade -> clientInvalid, - probeCopy -> clientInvalid)))(meta.p) - - // Manager states and functions: - val nManagerStates = 0 // We don't actually need any states for this protocol - - def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) = !dir.none(meta.sharers) - def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers) - - def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt = - MuxLookup(cmd, probeCopy, Array( - M_FLUSH -> probeInvalidate, - M_PRODUCE -> probeDowngrade)) - - def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), - MuxLookup(a.a_type, probeCopy, Array( - Acquire.getBlockType -> probeCopy, - Acquire.putBlockType -> probeInvalidate, - Acquire.getType -> probeCopy, - Acquire.putType -> probeInvalidate, - Acquire.getPrefetchType -> probeCopy, - Acquire.putPrefetchType -> probeInvalidate, - Acquire.putAtomicType -> probeInvalidate)), - probeInvalidate) - - def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type), grantExclusive) - def getExclusiveGrantType(): UInt = grantExclusive - - def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = { - val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p) - MuxCase(meta, Array( - incoming.is(releaseInvalidateData) -> popped, - incoming.is(releaseInvalidateAck) -> popped)) - } -} - -/** A protocol with only three Client states. - * Data is always assumed to be dirty. - * Multiple clients may share read permissions on a block at the same time. - */ -class MSICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) { - // Message types - val nAcquireTypes = 2 - val nProbeTypes = 3 - val nReleaseTypes = 6 - val nGrantTypes = 3 - - val acquireShared :: acquireExclusive :: Nil = Enum(UInt(), nAcquireTypes) - val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(UInt(), nProbeTypes) - val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes) - val grantShared :: grantExclusive :: grantExclusiveAck :: Nil = Enum(UInt(), nGrantTypes) - - def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData) - def grantTypesWithData = Seq(grantShared, grantExclusive) - - // Client states and functions - val nClientStates = 3 - val clientInvalid :: clientShared :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates) - - def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveDirty) - def clientStatesWithWritePermission = Seq(clientExclusiveDirty) - def clientStatesWithDirtyData = Seq(clientExclusiveDirty) - - def isValid(meta: ClientMetadata): Bool = meta.state =/= clientInvalid - - def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt = - Mux(isWriteIntent(cmd), acquireExclusive, acquireShared) - - def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = { - val dirty = meta.state isOneOf clientStatesWithDirtyData - MuxLookup(cmd, releaseCopyAck, Array( - M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck), - M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck), - M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck))) - } - - def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt = - MuxLookup(incoming.p_type, releaseInvalidateAck, Array( - probeInvalidate -> getReleaseType(M_FLUSH, meta), - probeDowngrade -> getReleaseType(M_PRODUCE, meta), - probeCopy -> getReleaseType(M_PRODUCE, meta))) - - def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) = - ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, meta.state))(meta.p) - - def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - MuxLookup(cmd, meta.state, Array( - M_FLUSH -> clientInvalid, - M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission, - clientShared, meta.state))))(meta.p) - - def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - Mux(incoming.isBuiltInType(), clientInvalid, - MuxLookup(incoming.g_type, clientInvalid, Array( - grantShared -> clientShared, - grantExclusive -> clientExclusiveDirty, - grantExclusiveAck -> clientExclusiveDirty))))(meta.p) - - def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) = - ClientMetadata( - MuxLookup(incoming.p_type, meta.state, Array( - probeInvalidate -> clientInvalid, - probeDowngrade -> clientShared, - probeCopy -> clientShared)))(meta.p) - - // Manager states and functions: - val nManagerStates = 0 // TODO: We could add a Shared state to avoid probing - // only a single sharer (also would need - // notification msg to track clean drops) - // Also could avoid probes on outer WBs. - - def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) = - Mux(dir.none(meta.sharers), Bool(false), - Mux(dir.one(meta.sharers), Bool(true), //TODO: for now we assume it's Exclusive - Mux(a.isBuiltInType(), a.hasData(), a.a_type =/= acquireShared))) - - def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers) - - def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt = - MuxLookup(cmd, probeCopy, Array( - M_FLUSH -> probeInvalidate, - M_PRODUCE -> probeDowngrade)) - - def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), - MuxLookup(a.a_type, probeCopy, Array( - Acquire.getBlockType -> probeCopy, - Acquire.putBlockType -> probeInvalidate, - Acquire.getType -> probeCopy, - Acquire.putType -> probeInvalidate, - Acquire.getPrefetchType -> probeCopy, - Acquire.putPrefetchType -> probeInvalidate, - Acquire.putAtomicType -> probeInvalidate)), - MuxLookup(a.a_type, probeCopy, Array( - acquireShared -> probeDowngrade, - acquireExclusive -> probeInvalidate))) - - def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type), - Mux(a.a_type === acquireShared, - Mux(!dir.none(meta.sharers), grantShared, grantExclusive), - grantExclusive)) - def getExclusiveGrantType(): UInt = grantExclusive - - def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = { - val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p) - MuxCase(meta, Array( - incoming.is(releaseInvalidateData) -> popped, - incoming.is(releaseInvalidateAck) -> popped)) - } -} - -/** A protocol with four Client states. - * Data is marked as dirty when written. - * Multiple clients may share read permissions on a block at the same time. - */ -class MESICoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) { - // Message types - val nAcquireTypes = 2 - val nProbeTypes = 3 - val nReleaseTypes = 6 - val nGrantTypes = 3 - - val acquireShared :: acquireExclusive :: Nil = Enum(UInt(), nAcquireTypes) - val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(UInt(), nProbeTypes) - val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: Nil = Enum(UInt(), nReleaseTypes) - val grantShared :: grantExclusive :: grantExclusiveAck :: Nil = Enum(UInt(), nGrantTypes) - - def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData) - def grantTypesWithData = Seq(grantShared, grantExclusive) - - // Client states and functions - val nClientStates = 4 - val clientInvalid :: clientShared :: clientExclusiveClean :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates) - - def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveClean, clientExclusiveDirty) - def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty) - def clientStatesWithDirtyData = Seq(clientExclusiveDirty) - - def isValid(meta: ClientMetadata): Bool = meta.state =/= clientInvalid - - def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt = - Mux(isWriteIntent(cmd), acquireExclusive, acquireShared) - - def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = { - val dirty = meta.state isOneOf clientStatesWithDirtyData - MuxLookup(cmd, releaseCopyAck, Array( - M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck), - M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck), - M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck))) - } - - def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt = - MuxLookup(incoming.p_type, releaseInvalidateAck, Array( - probeInvalidate -> getReleaseType(M_FLUSH, meta), - probeDowngrade -> getReleaseType(M_PRODUCE, meta), - probeCopy -> getReleaseType(M_PRODUCE, meta))) - - def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) = - ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, meta.state))(meta.p) - - def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - MuxLookup(cmd, meta.state, Array( - M_FLUSH -> clientInvalid, - M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission, - clientShared, meta.state), - M_CLEAN -> Mux(meta.state === clientExclusiveDirty, - clientExclusiveClean, meta.state))))(meta.p) - - def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - Mux(incoming.isBuiltInType(), clientInvalid, - MuxLookup(incoming.g_type, clientInvalid, Array( - grantShared -> clientShared, - grantExclusive -> Mux(isWrite(cmd), clientExclusiveDirty, clientExclusiveClean), - grantExclusiveAck -> clientExclusiveDirty))))(meta.p) - - def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) = - ClientMetadata( - MuxLookup(incoming.p_type, meta.state, Array( - probeInvalidate -> clientInvalid, - probeDowngrade -> clientShared, - probeCopy -> clientShared)))(meta.p) - - // Manager states and functions: - val nManagerStates = 0 // TODO: We could add a Shared state to avoid probing - // only a single sharer (also would need - // notification msg to track clean drops) - // Also could avoid probes on outer WBs. - - def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) = - Mux(dir.none(meta.sharers), Bool(false), - Mux(dir.one(meta.sharers), Bool(true), //TODO: for now we assume it's Exclusive - Mux(a.isBuiltInType(), a.hasData(), a.a_type =/= acquireShared))) - - def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers) - - def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt = - MuxLookup(cmd, probeCopy, Array( - M_FLUSH -> probeInvalidate, - M_PRODUCE -> probeDowngrade)) - - def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), - MuxLookup(a.a_type, probeCopy, Array( - Acquire.getBlockType -> probeCopy, - Acquire.putBlockType -> probeInvalidate, - Acquire.getType -> probeCopy, - Acquire.putType -> probeInvalidate, - Acquire.getPrefetchType -> probeCopy, - Acquire.putPrefetchType -> probeInvalidate, - Acquire.putAtomicType -> probeInvalidate)), - MuxLookup(a.a_type, probeCopy, Array( - acquireShared -> probeDowngrade, - acquireExclusive -> probeInvalidate))) - - def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type), - Mux(a.a_type === acquireShared, - Mux(!dir.none(meta.sharers), grantShared, grantExclusive), - grantExclusive)) - def getExclusiveGrantType(): UInt = grantExclusive - - def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = { - val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p) - MuxCase(meta, Array( - incoming.is(releaseInvalidateData) -> popped, - incoming.is(releaseInvalidateAck) -> popped)) - } -} - -class MigratoryCoherence(dir: DirectoryRepresentation) extends CoherencePolicy(dir) { - // Message types - val nAcquireTypes = 3 - val nProbeTypes = 4 - val nReleaseTypes = 10 - val nGrantTypes = 4 - - val acquireShared :: acquireExclusive :: acquireInvalidateOthers :: Nil = Enum(UInt(), nAcquireTypes) - val probeInvalidate :: probeDowngrade :: probeCopy :: probeInvalidateOthers :: Nil = Enum(UInt(), nProbeTypes) - val releaseInvalidateData :: releaseDowngradeData :: releaseCopyData :: releaseInvalidateAck :: releaseDowngradeAck :: releaseCopyAck :: releaseDowngradeDataMigratory :: releaseDowngradeAckHasCopy :: releaseInvalidateDataMigratory :: releaseInvalidateAckMigratory :: Nil = Enum(UInt(), nReleaseTypes) - val grantShared :: grantExclusive :: grantExclusiveAck :: grantReadMigratory :: Nil = Enum(UInt(), nGrantTypes) - - def releaseTypesWithData = Seq(releaseInvalidateData, releaseDowngradeData, releaseCopyData, releaseInvalidateDataMigratory, releaseDowngradeDataMigratory) - def grantTypesWithData = Seq(grantShared, grantExclusive, grantReadMigratory) - - // Client states and functions - val nClientStates = 7 - val clientInvalid :: clientShared :: clientExclusiveClean :: clientExclusiveDirty :: clientSharedByTwo :: clientMigratoryClean :: clientMigratoryDirty :: Nil = Enum(UInt(), nClientStates) - - def clientStatesWithReadPermission = Seq(clientShared, clientExclusiveClean, clientExclusiveDirty, clientSharedByTwo, clientMigratoryClean, clientMigratoryDirty) - def clientStatesWithWritePermission = Seq(clientExclusiveClean, clientExclusiveDirty, clientMigratoryClean, clientMigratoryDirty) - def clientStatesWithDirtyData = Seq(clientExclusiveDirty, clientMigratoryDirty) - - def isValid (meta: ClientMetadata): Bool = meta.state =/= clientInvalid - - def getAcquireType(cmd: UInt, meta: ClientMetadata): UInt = - Mux(isWriteIntent(cmd), - Mux(meta.state === clientInvalid, acquireExclusive, acquireInvalidateOthers), - acquireShared) - - def getReleaseType(cmd: UInt, meta: ClientMetadata): UInt = { - val dirty = meta.state isOneOf clientStatesWithDirtyData - MuxLookup(cmd, releaseCopyAck, Array( - M_FLUSH -> Mux(dirty, releaseInvalidateData, releaseInvalidateAck), - M_PRODUCE -> Mux(dirty, releaseDowngradeData, releaseDowngradeAck), - M_CLEAN -> Mux(dirty, releaseCopyData, releaseCopyAck))) - } - - def getReleaseType(incoming: HasProbeType, meta: ClientMetadata): UInt = { - val dirty = meta.state isOneOf clientStatesWithDirtyData - val with_data = MuxLookup(incoming.p_type, releaseInvalidateData, Array( - probeInvalidate -> Mux(meta.state isOneOf (clientExclusiveDirty, clientMigratoryDirty), - releaseInvalidateDataMigratory, releaseInvalidateData), - probeDowngrade -> Mux(meta.state === clientMigratoryDirty, - releaseDowngradeDataMigratory, releaseDowngradeData), - probeCopy -> releaseCopyData)) - val without_data = MuxLookup(incoming.p_type, releaseInvalidateAck, Array( - probeInvalidate -> Mux(clientExclusiveClean === meta.state, - releaseInvalidateAckMigratory, releaseInvalidateAck), - probeInvalidateOthers -> Mux(clientSharedByTwo === meta.state, - releaseInvalidateAckMigratory, releaseInvalidateAck), - probeDowngrade -> Mux(meta.state =/= clientInvalid, - releaseDowngradeAckHasCopy, releaseDowngradeAck), - probeCopy -> Mux(meta.state =/= clientInvalid, - releaseDowngradeAckHasCopy, releaseDowngradeAck))) - Mux(dirty, with_data, without_data) - } - - def clientMetadataOnHit(cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - Mux(isWrite(cmd), MuxLookup(meta.state, clientExclusiveDirty, Array( - clientExclusiveClean -> clientExclusiveDirty, - clientMigratoryClean -> clientMigratoryDirty)), - meta.state))(meta.p) - - def clientMetadataOnCacheControl(cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - MuxLookup(cmd, meta.state, Array( - M_FLUSH -> clientInvalid, - M_PRODUCE -> Mux(meta.state isOneOf clientStatesWithWritePermission, - clientShared, meta.state), - M_CLEAN -> MuxLookup(meta.state, meta.state, Array( - clientExclusiveDirty -> clientExclusiveClean, - clientMigratoryDirty -> clientMigratoryClean)))))(meta.p) - - def clientMetadataOnGrant(incoming: HasGrantType, cmd: UInt, meta: ClientMetadata) = - ClientMetadata( - Mux(incoming.isBuiltInType(), clientInvalid, - MuxLookup(incoming.g_type, clientInvalid, Array( - grantShared -> clientShared, - grantExclusive -> Mux(isWrite(cmd), clientExclusiveDirty, clientExclusiveClean), - grantExclusiveAck -> clientExclusiveDirty, - grantReadMigratory -> Mux(isWrite(cmd), - clientMigratoryDirty, clientMigratoryClean)))))(meta.p) - - def clientMetadataOnProbe(incoming: HasProbeType, meta: ClientMetadata) = { - val downgradeState = MuxLookup(meta.state, clientShared, Array( - clientExclusiveClean -> clientSharedByTwo, - clientExclusiveDirty -> clientSharedByTwo, - clientSharedByTwo -> clientShared, - clientMigratoryClean -> clientSharedByTwo, - clientMigratoryDirty -> clientInvalid)) - ClientMetadata( - MuxLookup(incoming.p_type, meta.state, Array( - probeInvalidate -> clientInvalid, - probeInvalidateOthers -> clientInvalid, - probeDowngrade -> downgradeState, - probeCopy -> downgradeState)))(meta.p) - } - - // Manager states and functions: - val nManagerStates = 0 // TODO: we could add some states to reduce the number of message types - - def requiresProbes(a: HasAcquireType, meta: ManagerMetadata) = - Mux(dir.none(meta.sharers), Bool(false), - Mux(dir.one(meta.sharers), Bool(true), //TODO: for now we assume it's Exclusive - Mux(a.isBuiltInType(), a.hasData(), a.a_type =/= acquireShared))) - - def requiresProbes(cmd: UInt, meta: ManagerMetadata) = !dir.none(meta.sharers) - - def getProbeType(cmd: UInt, meta: ManagerMetadata): UInt = - MuxLookup(cmd, probeCopy, Array( - M_FLUSH -> probeInvalidate, - M_PRODUCE -> probeDowngrade)) - - def getProbeType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), - MuxLookup(a.a_type, probeCopy, Array( - Acquire.getBlockType -> probeCopy, - Acquire.putBlockType -> probeInvalidate, - Acquire.getType -> probeCopy, - Acquire.putType -> probeInvalidate, - Acquire.getPrefetchType -> probeCopy, - Acquire.putPrefetchType -> probeInvalidate, - Acquire.putAtomicType -> probeInvalidate)), - MuxLookup(a.a_type, probeCopy, Array( - acquireShared -> probeDowngrade, - acquireExclusive -> probeInvalidate, - acquireInvalidateOthers -> probeInvalidateOthers))) - - def getGrantType(a: HasAcquireType, meta: ManagerMetadata): UInt = - Mux(a.isBuiltInType(), Acquire.getBuiltInGrantType(a.a_type), - MuxLookup(a.a_type, grantShared, Array( - acquireShared -> Mux(!dir.none(meta.sharers), grantShared, grantExclusive), - acquireExclusive -> grantExclusive, - acquireInvalidateOthers -> grantExclusiveAck))) //TODO: add this to MESI for broadcast? - def getExclusiveGrantType(): UInt = grantExclusive - - def managerMetadataOnRelease(incoming: HasReleaseType, src: UInt, meta: ManagerMetadata) = { - val popped = ManagerMetadata(sharers=dir.pop(meta.sharers, src))(meta.p) - MuxCase(meta, Array( - incoming.is(releaseInvalidateData) -> popped, - incoming.is(releaseInvalidateAck) -> popped, - incoming.is(releaseInvalidateDataMigratory) -> popped, - incoming.is(releaseInvalidateAckMigratory) -> popped)) - } -} diff --git a/src/main/scala/uncore/converters/Nasti.scala b/src/main/scala/uncore/converters/Nasti.scala deleted file mode 100644 index cce824b7..00000000 --- a/src/main/scala/uncore/converters/Nasti.scala +++ /dev/null @@ -1,388 +0,0 @@ -// See LICENSE.SiFive for license details. -// See LICENSE.Berkeley for license details. - -package uncore.converters - -import Chisel._ -import junctions._ -import util.{ReorderQueue, DecoupledHelper} -import junctions.NastiConstants._ -import uncore.tilelink._ -import uncore.constants._ -import config._ -import scala.math.min - -class IdMapper(val inIdBits: Int, val outIdBits: Int, - val forceMapping: Boolean = false) - (implicit val p: Parameters) extends Module { - - val io = new Bundle { - val req = new Bundle { - val valid = Bool(INPUT) - val ready = Bool(OUTPUT) - val in_id = UInt(INPUT, inIdBits) - val out_id = UInt(OUTPUT, outIdBits) - } - val resp = new Bundle { - val valid = Bool(INPUT) - val matches = Bool(OUTPUT) - val out_id = UInt(INPUT, outIdBits) - val in_id = UInt(OUTPUT, inIdBits) - } - } - val maxInXacts = 1 << inIdBits - - if (inIdBits <= outIdBits && !forceMapping) { - io.req.ready := Bool(true) - io.req.out_id := io.req.in_id - io.resp.matches := Bool(true) - io.resp.in_id := io.resp.out_id - } else { - val nInXacts = 1 << inIdBits - // No point in allowing more out xacts than in xacts - val nOutXacts = min(1 << outIdBits, nInXacts) - - val out_id_free = Reg(init = Vec.fill(nOutXacts){Bool(true)}) - val in_id_free = Reg(init = Vec.fill(nInXacts){Bool(true)}) - val next_out_id = PriorityEncoder(out_id_free) - val id_mapping = Reg(Vec(nOutXacts, UInt(0, inIdBits))) - - val req_fire = io.req.valid && io.req.ready - when (req_fire) { - out_id_free(io.req.out_id) := Bool(false) - in_id_free(io.req.in_id) := Bool(false) - id_mapping(io.req.out_id) := io.req.in_id - } - when (io.resp.valid) { - out_id_free(io.resp.out_id) := Bool(true) - in_id_free(io.resp.in_id) := Bool(true) - } - - io.req.ready := out_id_free.reduce(_ || _) && in_id_free(io.req.in_id) - io.req.out_id := next_out_id - - io.resp.in_id := id_mapping(io.resp.out_id) - io.resp.matches := !out_id_free(io.resp.out_id) - } -} - -class NastiIOTileLinkIOConverterInfo(implicit p: Parameters) extends TLBundle()(p) { - val addr_beat = UInt(width = tlBeatAddrBits) - val subblock = Bool() -} - -class NastiIOTileLinkIOConverter(implicit p: Parameters) extends TLModule()(p) - with HasNastiParameters { - val io = new Bundle { - val tl = new ClientUncachedTileLinkIO().flip - val nasti = new NastiIO - } - - val dataBits = tlDataBits*tlDataBeats - require(tlDataBits == nastiXDataBits, "Data sizes between LLC and MC don't agree") // TODO: remove this restriction - require(tlDataBeats < (1 << nastiXLenBits), "Can't have that many beats") - - val has_data = io.tl.acquire.bits.hasData() - - val is_subblock = io.tl.acquire.bits.isSubBlockType() - val is_multibeat = io.tl.acquire.bits.hasMultibeatData() - val (tl_cnt_out, tl_wrap_out) = Counter( - io.tl.acquire.fire() && is_multibeat, tlDataBeats) - - val get_valid = io.tl.acquire.valid && !has_data - val put_valid = io.tl.acquire.valid && has_data - - // Reorder queue saves extra information needed to send correct - // grant back to TL client - val roqIdBits = min(tlClientXactIdBits, nastiXIdBits) - val roq = Module(new ReorderQueue( - new NastiIOTileLinkIOConverterInfo, roqIdBits)) - - val get_id_mapper = Module(new IdMapper(tlClientXactIdBits, nastiXIdBits)) - val put_id_mapper = Module(new IdMapper(tlClientXactIdBits, nastiXIdBits)) - - val get_id_ready = get_id_mapper.io.req.ready - val put_id_mask = is_subblock || io.tl.acquire.bits.addr_beat === UInt(0) - val put_id_ready = put_id_mapper.io.req.ready || !put_id_mask - - // For Get/GetBlock, make sure Reorder queue can accept new entry - val get_helper = DecoupledHelper( - get_valid, - roq.io.enq.ready, - io.nasti.ar.ready, - get_id_ready) - - val w_inflight = Reg(init = Bool(false)) - val w_id_reg = Reg(init = UInt(0, nastiXIdBits)) - val w_id = Mux(w_inflight, w_id_reg, put_id_mapper.io.req.out_id) - - // For Put/PutBlock, make sure aw and w channel are both ready before - // we send the first beat - val aw_ready = w_inflight || io.nasti.aw.ready - val put_helper = DecoupledHelper( - put_valid, - aw_ready, - io.nasti.w.ready, - put_id_ready) - - val (nasti_cnt_out, nasti_wrap_out) = Counter( - io.nasti.r.fire() && !roq.io.deq.data.subblock, tlDataBeats) - - roq.io.enq.valid := get_helper.fire(roq.io.enq.ready) - roq.io.enq.bits.tag := io.nasti.ar.bits.id - roq.io.enq.bits.data.addr_beat := io.tl.acquire.bits.addr_beat - roq.io.enq.bits.data.subblock := is_subblock - roq.io.deq.valid := io.nasti.r.fire() && (nasti_wrap_out || roq.io.deq.data.subblock) - roq.io.deq.tag := io.nasti.r.bits.id - - get_id_mapper.io.req.valid := get_helper.fire(get_id_ready) - get_id_mapper.io.req.in_id := io.tl.acquire.bits.client_xact_id - get_id_mapper.io.resp.valid := io.nasti.r.fire() && io.nasti.r.bits.last - get_id_mapper.io.resp.out_id := io.nasti.r.bits.id - - put_id_mapper.io.req.valid := put_helper.fire(put_id_ready, put_id_mask) - put_id_mapper.io.req.in_id := io.tl.acquire.bits.client_xact_id - put_id_mapper.io.resp.valid := io.nasti.b.fire() - put_id_mapper.io.resp.out_id := io.nasti.b.bits.id - - // Decompose outgoing TL Acquires into Nasti address and data channels - io.nasti.ar.valid := get_helper.fire(io.nasti.ar.ready) - io.nasti.ar.bits := NastiReadAddressChannel( - id = get_id_mapper.io.req.out_id, - addr = io.tl.acquire.bits.full_addr(), - size = Mux(is_subblock, - io.tl.acquire.bits.op_size(), - UInt(log2Ceil(tlDataBytes))), - len = Mux(is_subblock, UInt(0), UInt(tlDataBeats - 1))) - - def mask_helper(all_inside_0: Seq[Bool], defsize: Int): (Seq[Bool], UInt, UInt) = { - val len = all_inside_0.size - if (len == 1) { - (Seq(Bool(true)), UInt(0), UInt(defsize)) - } else { - val sub_inside_0 = Seq.tabulate (len/2) { i => all_inside_0(2*i) && all_inside_0(2*i+1) } - val (sub_outside_0, sub_offset, sub_size) = mask_helper(sub_inside_0, defsize+1) - val all_outside_0 = Seq.tabulate (len) { i => sub_outside_0(i/2) && all_inside_0(i^1) } - val odd_outside_0 = Seq.tabulate (len/2) { i => all_outside_0(2*i+1) } - val odd_outside = odd_outside_0.reduce (_ || _) - val all_outside = all_outside_0.reduce (_ || _) - val offset = Cat(sub_offset, odd_outside) - val size = Mux(all_outside, UInt(defsize), sub_size) - (all_outside_0, offset, size) - } - } - - val all_inside_0 = (~io.tl.acquire.bits.wmask()).toBools - val (_, put_offset, put_size) = mask_helper(all_inside_0, 0) - - io.nasti.aw.valid := put_helper.fire(aw_ready, !w_inflight) - io.nasti.aw.bits := NastiWriteAddressChannel( - id = put_id_mapper.io.req.out_id, - addr = io.tl.acquire.bits.full_addr() | - Mux(is_multibeat, UInt(0), put_offset), - size = Mux(is_multibeat, UInt(log2Ceil(tlDataBytes)), put_size), - len = Mux(is_multibeat, UInt(tlDataBeats - 1), UInt(0))) - - io.nasti.w.valid := put_helper.fire(io.nasti.w.ready) - io.nasti.w.bits := NastiWriteDataChannel( - id = w_id, - data = io.tl.acquire.bits.data, - strb = Some(io.tl.acquire.bits.wmask()), - last = Mux(w_inflight, - tl_cnt_out === UInt(tlDataBeats - 1), !is_multibeat)) - - io.tl.acquire.ready := Mux(has_data, - put_helper.fire(put_valid), - get_helper.fire(get_valid)) - - when (!w_inflight && io.tl.acquire.fire() && is_multibeat) { - w_inflight := Bool(true) - w_id_reg := w_id - } - - when (w_inflight) { - when (tl_wrap_out) { w_inflight := Bool(false) } - } - - // Aggregate incoming NASTI responses into TL Grants - val (tl_cnt_in, tl_wrap_in) = Counter( - io.tl.grant.fire() && io.tl.grant.bits.hasMultibeatData(), tlDataBeats) - val gnt_arb = Module(new LockingArbiter(new GrantToDst, 2, - tlDataBeats, Some((gnt: GrantToDst) => gnt.hasMultibeatData()))) - io.tl.grant <> gnt_arb.io.out - - gnt_arb.io.in(0).valid := io.nasti.r.valid - io.nasti.r.ready := gnt_arb.io.in(0).ready - gnt_arb.io.in(0).bits := Grant( - is_builtin_type = Bool(true), - g_type = Mux(roq.io.deq.data.subblock, - Grant.getDataBeatType, Grant.getDataBlockType), - client_xact_id = get_id_mapper.io.resp.in_id, - manager_xact_id = UInt(0), - addr_beat = Mux(roq.io.deq.data.subblock, roq.io.deq.data.addr_beat, tl_cnt_in), - data = io.nasti.r.bits.data) - - assert(!roq.io.deq.valid || roq.io.deq.matches, - "TL -> NASTI converter ReorderQueue: NASTI tag error") - assert(!gnt_arb.io.in(0).valid || get_id_mapper.io.resp.matches, - "TL -> NASTI ID Mapper: NASTI tag error") - - gnt_arb.io.in(1).valid := io.nasti.b.valid - io.nasti.b.ready := gnt_arb.io.in(1).ready - gnt_arb.io.in(1).bits := Grant( - is_builtin_type = Bool(true), - g_type = Grant.putAckType, - client_xact_id = put_id_mapper.io.resp.in_id, - manager_xact_id = UInt(0), - addr_beat = UInt(0), - data = Bits(0)) - assert(!gnt_arb.io.in(1).valid || put_id_mapper.io.resp.matches, "NASTI tag error") - - assert(!io.nasti.r.valid || io.nasti.r.bits.resp === RESP_OKAY, "NASTI read error") - assert(!io.nasti.b.valid || io.nasti.b.bits.resp === RESP_OKAY, "NASTI write error") -} - -class TileLinkIONastiIOConverter(implicit p: Parameters) extends TLModule()(p) - with HasNastiParameters { - val io = new Bundle { - val nasti = (new NastiIO).flip - val tl = new ClientUncachedTileLinkIO - } - - val (s_idle :: s_put :: Nil) = Enum(Bits(), 2) - val state = Reg(init = s_idle) - - private val blockOffset = tlByteAddrBits + tlBeatAddrBits - - val aw_req = Reg(new NastiWriteAddressChannel) - val w_tl_id = Reg(io.tl.acquire.bits.client_xact_id) - - def is_singlebeat(chan: NastiAddressChannel): Bool = - chan.len === UInt(0) - - def is_multibeat(chan: NastiAddressChannel): Bool = - chan.len === UInt(tlDataBeats - 1) && chan.size === UInt(log2Up(tlDataBytes)) - - def nasti_addr_block(chan: NastiAddressChannel): UInt = - chan.addr(nastiXAddrBits - 1, blockOffset) - - def nasti_addr_beat(chan: NastiAddressChannel): UInt = - chan.addr(blockOffset - 1, tlByteAddrBits) - - def nasti_addr_byte(chan: NastiAddressChannel): UInt = - chan.addr(tlByteAddrBits - 1, 0) - - def size_mask(size: UInt): UInt = - (UInt(1) << (UInt(1) << size)) - UInt(1) - - def nasti_wmask(aw: NastiWriteAddressChannel, w: NastiWriteDataChannel): UInt = { - val base = w.strb & size_mask(aw.size) - val addr_byte = nasti_addr_byte(aw) - w.strb & (size_mask(aw.size) << addr_byte) - } - - def tl_last(gnt: GrantMetadata): Bool = - !gnt.hasMultibeatData() || gnt.addr_beat === UInt(tlDataBeats - 1) - - def tl_b_grant(gnt: GrantMetadata): Bool = - gnt.g_type === Grant.putAckType - - assert(!io.nasti.ar.valid || - is_singlebeat(io.nasti.ar.bits) || is_multibeat(io.nasti.ar.bits), - "NASTI read transaction cannot convert to TileLInk") - - assert(!io.nasti.aw.valid || - is_singlebeat(io.nasti.aw.bits) || is_multibeat(io.nasti.aw.bits), - "NASTI write transaction cannot convert to TileLInk") - - val put_count = Reg(init = UInt(0, tlBeatAddrBits)) - val get_id_mapper = Module(new IdMapper(nastiXIdBits, tlClientXactIdBits, true)) - val put_id_mapper = Module(new IdMapper(nastiXIdBits, tlClientXactIdBits, true)) - - when (io.nasti.aw.fire()) { - aw_req := io.nasti.aw.bits - w_tl_id := put_id_mapper.io.req.out_id - state := s_put - } - - when (io.nasti.w.fire()) { - put_count := put_count + UInt(1) - when (io.nasti.w.bits.last) { - put_count := UInt(0) - state := s_idle - } - } - - val get_acquire = Mux(is_multibeat(io.nasti.ar.bits), - GetBlock( - client_xact_id = get_id_mapper.io.req.out_id, - addr_block = nasti_addr_block(io.nasti.ar.bits)), - Get( - client_xact_id = get_id_mapper.io.req.out_id, - addr_block = nasti_addr_block(io.nasti.ar.bits), - addr_beat = nasti_addr_beat(io.nasti.ar.bits), - addr_byte = nasti_addr_byte(io.nasti.ar.bits), - operand_size = io.nasti.ar.bits.size, - alloc = Bool(false))) - - val put_acquire = Mux(is_multibeat(aw_req), - PutBlock( - client_xact_id = w_tl_id, - addr_block = nasti_addr_block(aw_req), - addr_beat = put_count, - data = io.nasti.w.bits.data, - wmask = Some(io.nasti.w.bits.strb)), - Put( - client_xact_id = w_tl_id, - addr_block = nasti_addr_block(aw_req), - addr_beat = nasti_addr_beat(aw_req), - data = io.nasti.w.bits.data, - wmask = Some(nasti_wmask(aw_req, io.nasti.w.bits)))) - - val get_helper = DecoupledHelper( - io.nasti.ar.valid, - get_id_mapper.io.req.ready, - io.tl.acquire.ready) - - get_id_mapper.io.req.valid := get_helper.fire( - get_id_mapper.io.req.ready, state === s_idle) - get_id_mapper.io.req.in_id := io.nasti.ar.bits.id - get_id_mapper.io.resp.out_id := io.tl.grant.bits.client_xact_id - get_id_mapper.io.resp.valid := io.nasti.r.fire() && io.nasti.r.bits.last - - val aw_ok = (state === s_idle && !io.nasti.ar.valid) - - put_id_mapper.io.req.valid := aw_ok && io.nasti.aw.valid - put_id_mapper.io.req.in_id := io.nasti.aw.bits.id - put_id_mapper.io.resp.out_id := io.tl.grant.bits.client_xact_id - put_id_mapper.io.resp.valid := io.nasti.b.fire() - - io.tl.acquire.bits := Mux(state === s_put, put_acquire, get_acquire) - io.tl.acquire.valid := get_helper.fire(io.tl.acquire.ready, state === s_idle) || - (state === s_put && io.nasti.w.valid) - - io.nasti.ar.ready := get_helper.fire(io.nasti.ar.valid, state === s_idle) - io.nasti.aw.ready := aw_ok && put_id_mapper.io.req.ready - io.nasti.w.ready := (state === s_put && io.tl.acquire.ready) - - val nXacts = tlMaxClientXacts * tlMaxClientsPerPort - - io.nasti.b.valid := io.tl.grant.valid && tl_b_grant(io.tl.grant.bits) - io.nasti.b.bits := NastiWriteResponseChannel( - id = put_id_mapper.io.resp.in_id) - - assert(!io.nasti.b.valid || put_id_mapper.io.resp.matches, - "Put ID does not match") - - io.nasti.r.valid := io.tl.grant.valid && !tl_b_grant(io.tl.grant.bits) - io.nasti.r.bits := NastiReadDataChannel( - id = get_id_mapper.io.resp.in_id, - data = io.tl.grant.bits.data, - last = tl_last(io.tl.grant.bits)) - - assert(!io.nasti.r.valid || get_id_mapper.io.resp.matches, - "Get ID does not match") - - io.tl.grant.ready := Mux(tl_b_grant(io.tl.grant.bits), - io.nasti.b.ready, io.nasti.r.ready) -} diff --git a/src/main/scala/uncore/converters/Tilelink.scala b/src/main/scala/uncore/converters/Tilelink.scala deleted file mode 100644 index a5572c91..00000000 --- a/src/main/scala/uncore/converters/Tilelink.scala +++ /dev/null @@ -1,605 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.converters - -import Chisel._ -import util.{ReorderQueue, DecoupledHelper} -import rocket.PAddrBits -import uncore.tilelink._ -import uncore.util._ -import uncore.constants._ -import unittest.UnitTest -import config._ - -/** Utilities for safely wrapping a *UncachedTileLink by pinning probe.ready and release.valid low */ -object TileLinkIOWrapper { - def apply(tl: ClientUncachedTileLinkIO): ClientTileLinkIO = { - val conv = Module(new ClientTileLinkIOWrapper()(tl.p)) - conv.io.in <> tl - conv.io.out - } - def apply(tl: UncachedTileLinkIO): TileLinkIO = { - val conv = Module(new TileLinkIOWrapper()(tl.p)) - conv.io.in <> tl - conv.io.out - } - def apply(tl: ClientTileLinkIO): ClientTileLinkIO = tl - def apply(tl: TileLinkIO): TileLinkIO = tl -} - -class TileLinkIOWrapper(implicit p: Parameters) extends TLModule()(p) { - val io = new Bundle { - val in = new UncachedTileLinkIO().flip - val out = new TileLinkIO - } - io.out.acquire <> io.in.acquire - io.in.grant <> io.out.grant - io.out.finish <> io.in.finish - io.out.probe.ready := Bool(true) - io.out.release.valid := Bool(false) -} - -class ClientTileLinkIOWrapper(implicit p: Parameters) extends TLModule()(p) { - val io = new Bundle { - val in = new ClientUncachedTileLinkIO().flip - val out = new ClientTileLinkIO - } - io.out.acquire <> io.in.acquire - io.in.grant <> io.out.grant - io.out.probe.ready := Bool(true) - io.out.release.valid := Bool(false) - io.out.finish.valid := Bool(false) -} - -class ClientTileLinkIOUnwrapper(implicit p: Parameters) extends TLModule()(p) { - val io = new Bundle { - val in = new ClientTileLinkIO().flip - val out = new ClientUncachedTileLinkIO - } - - val acqArb = Module(new LockingRRArbiter(new Acquire, 2, tlDataBeats, - Some((acq: Acquire) => acq.hasMultibeatData()))) - - val acqRoq = Module(new ReorderQueue(Bool(), tlClientXactIdBits)) - val relRoq = Module(new ReorderQueue(Bool(), tlClientXactIdBits)) - - val iacq = io.in.acquire.bits - val irel = io.in.release.bits - val ognt = io.out.grant.bits - - val acq_roq_enq = iacq.first() - val rel_roq_enq = irel.first() - - val acq_roq_ready = !acq_roq_enq || acqRoq.io.enq.ready - val rel_roq_ready = !rel_roq_enq || relRoq.io.enq.ready - - val acq_helper = DecoupledHelper( - io.in.acquire.valid, - acq_roq_ready, - acqArb.io.in(0).ready) - - val rel_helper = DecoupledHelper( - io.in.release.valid, - rel_roq_ready, - acqArb.io.in(1).ready) - - acqRoq.io.enq.valid := acq_helper.fire(acq_roq_ready, acq_roq_enq) - acqRoq.io.enq.bits.data := iacq.isBuiltInType() - acqRoq.io.enq.bits.tag := iacq.client_xact_id - - acqArb.io.in(0).valid := acq_helper.fire(acqArb.io.in(0).ready) - acqArb.io.in(0).bits := Acquire( - is_builtin_type = Bool(true), - a_type = Mux(iacq.isBuiltInType(), - iacq.a_type, Acquire.getBlockType), - client_xact_id = iacq.client_xact_id, - addr_block = iacq.addr_block, - addr_beat = iacq.addr_beat, - data = iacq.data, - union = iacq.union) - io.in.acquire.ready := acq_helper.fire(io.in.acquire.valid) - - relRoq.io.enq.valid := rel_helper.fire(rel_roq_ready, rel_roq_enq) - relRoq.io.enq.bits.data := irel.isVoluntary() - relRoq.io.enq.bits.tag := irel.client_xact_id - - acqArb.io.in(1).valid := rel_helper.fire(acqArb.io.in(1).ready) - acqArb.io.in(1).bits := PutBlock( - client_xact_id = irel.client_xact_id, - addr_block = irel.addr_block, - addr_beat = irel.addr_beat, - data = irel.data) - io.in.release.ready := rel_helper.fire(io.in.release.valid) - - io.out.acquire <> acqArb.io.out - - val grant_deq_roq = io.out.grant.fire() && ognt.last() - - acqRoq.io.deq.valid := acqRoq.io.deq.matches && grant_deq_roq - acqRoq.io.deq.tag := ognt.client_xact_id - - relRoq.io.deq.valid := !acqRoq.io.deq.matches && grant_deq_roq - relRoq.io.deq.tag := ognt.client_xact_id - - assert(!grant_deq_roq || acqRoq.io.deq.matches || relRoq.io.deq.matches, - "TileLink Unwrapper: client_xact_id mismatch") - - val gnt_builtin = acqRoq.io.deq.data - val gnt_voluntary = relRoq.io.deq.data - - val acq_grant = Grant( - is_builtin_type = gnt_builtin, - g_type = Mux(gnt_builtin, ognt.g_type, tlCoh.getExclusiveGrantType), - client_xact_id = ognt.client_xact_id, - manager_xact_id = ognt.manager_xact_id, - addr_beat = ognt.addr_beat, - data = ognt.data) - - assert(!io.in.release.valid || io.in.release.bits.isVoluntary(), "Unwrapper can only process voluntary releases.") - val rel_grant = Grant( - is_builtin_type = Bool(true), - g_type = Grant.voluntaryAckType, // We should only every be working with voluntary releases - client_xact_id = ognt.client_xact_id, - manager_xact_id = ognt.manager_xact_id, - addr_beat = ognt.addr_beat, - data = ognt.data) - - io.in.grant.valid := io.out.grant.valid - io.in.grant.bits := Mux(acqRoq.io.deq.matches, acq_grant, rel_grant) - io.out.grant.ready := io.in.grant.ready - - io.in.probe.valid := Bool(false) - io.in.finish.ready := Bool(false) -} - -object TileLinkIOUnwrapper { - def apply(in: ClientTileLinkIO): ClientUncachedTileLinkIO = { - val unwrapper = Module(new ClientTileLinkIOUnwrapper()(in.p)) - unwrapper.io.in <> in - unwrapper.io.out - } -} - -object TileLinkWidthAdapter { - def apply(in: ClientUncachedTileLinkIO, outerParams: Parameters) = { - val outerTLId = outerParams(TLId) - val outerDataBits = outerParams(TLKey(outerTLId)).dataBitsPerBeat - implicit val p = outerParams - if (outerDataBits > in.tlDataBits) { - val widener = Module(new TileLinkIOWidener(in.p(TLId), outerTLId)) - widener.io.in <> in - widener.io.out - } else if (outerDataBits < in.tlDataBits) { - val narrower = Module(new TileLinkIONarrower(in.p(TLId), outerTLId)) - narrower.io.in <> in - narrower.io.out - } else { in } - } - def apply(out: ClientUncachedTileLinkIO, in: ClientUncachedTileLinkIO): Unit = { - require(out.tlDataBits * out.tlDataBeats == in.tlDataBits * in.tlDataBeats) - out <> apply(in, out.p) - } -} - -class TileLinkIOWidener(innerTLId: String, outerTLId: String) - (implicit p: Parameters) extends TLModule()(p) { - - val paddrBits = p(PAddrBits) - val innerParams = p(TLKey(innerTLId)) - val outerParams = p(TLKey(outerTLId)) - val innerDataBeats = innerParams.dataBeats - val innerDataBits = innerParams.dataBitsPerBeat - val innerWriteMaskBits = innerParams.writeMaskBits - val innerByteAddrBits = log2Up(innerWriteMaskBits) - val innerMaxXacts = innerParams.maxClientXacts * innerParams.maxClientsPerPort - val innerXactIdBits = log2Up(innerMaxXacts) - val outerDataBeats = outerParams.dataBeats - val outerDataBits = outerParams.dataBitsPerBeat - val outerWriteMaskBits = outerParams.writeMaskBits - val outerByteAddrBits = log2Up(outerWriteMaskBits) - val outerBeatAddrBits = log2Up(outerDataBeats) - val outerBlockOffset = outerBeatAddrBits + outerByteAddrBits - val outerMaxClients = outerParams.maxClientsPerPort - val outerClientIdBits = log2Up(outerParams.maxClientXacts * outerMaxClients) - val outerManagerIdBits = log2Up(outerParams.maxManagerXacts) - val outerBlockAddrBits = paddrBits - outerBlockOffset - - require(outerDataBeats <= innerDataBeats) - require(outerDataBits >= innerDataBits) - require(outerDataBits % innerDataBits == 0) - require(outerDataBits * outerDataBeats == innerDataBits * innerDataBeats) - - val factor = innerDataBeats / outerDataBeats - - val io = new Bundle { - val in = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => innerTLId})).flip - val out = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => outerTLId})) - } - - val iacq = io.in.acquire.bits - val oacq = io.out.acquire.bits - val ognt = io.out.grant.bits - val ignt = io.in.grant.bits - - val shrink = iacq.a_type === Acquire.putBlockType - val stretch = ognt.g_type === Grant.getDataBlockType - val smallget = iacq.a_type === Acquire.getType - val smallput = iacq.a_type === Acquire.putType - val atomic = iacq.a_type === Acquire.putAtomicType - val wideget = iacq.a_type === Acquire.getBlockType - val smallgnt = ognt.g_type === Grant.getDataBeatType - - val sending_put = Reg(init = Bool(false)) - val collecting = Reg(init = Bool(false)) - val put_block = Reg(UInt(width = outerBlockAddrBits)) - val put_id = Reg(UInt(width = outerClientIdBits)) - val put_data = Reg(Vec(factor, UInt(width = innerDataBits))) - val put_wmask = Reg(Vec(factor, UInt(width = innerWriteMaskBits))) - val put_allocate = Reg(Bool()) - val (put_beat, put_done) = Counter(io.out.acquire.fire() && oacq.hasMultibeatData(), outerDataBeats) - val (recv_idx, recv_done) = Counter(io.in.acquire.fire() && iacq.hasMultibeatData(), factor) - - val in_addr = iacq.full_addr() - val out_addr_block = in_addr(paddrBits - 1, outerBlockOffset) - val out_addr_beat = in_addr(outerBlockOffset - 1, outerByteAddrBits) - val out_addr_byte = in_addr(outerByteAddrBits - 1, 0) - - val switch_addr = in_addr(outerByteAddrBits - 1, innerByteAddrBits) - val smallget_switch = Reg(Vec(innerMaxXacts, switch_addr)) - - def align_data(addr: UInt, data: UInt): UInt = - data << Cat(addr, UInt(0, log2Up(innerDataBits))) - - def align_wmask(addr: UInt, wmask: UInt): UInt = - wmask << Cat(addr, UInt(0, log2Up(innerWriteMaskBits))) - - val outerConfig = p.alterPartial({ case TLId => outerTLId }) - - val get_acquire = Get( - client_xact_id = iacq.client_xact_id, - addr_block = out_addr_block, - addr_beat = out_addr_beat, - addr_byte = out_addr_byte, - operand_size = iacq.op_size(), - alloc = iacq.allocate())(outerConfig) - - val get_block_acquire = GetBlock( - client_xact_id = iacq.client_xact_id, - addr_block = out_addr_block, - alloc = iacq.allocate())(outerConfig) - - val put_acquire = Put( - client_xact_id = iacq.client_xact_id, - addr_block = out_addr_block, - addr_beat = out_addr_beat, - data = align_data(switch_addr, iacq.data), - wmask = Some(align_wmask(switch_addr, iacq.wmask())), - alloc = iacq.allocate())(outerConfig) - - val put_block_acquire = PutBlock( - client_xact_id = put_id, - addr_block = put_block, - addr_beat = put_beat, - data = put_data.asUInt, - wmask = Some(put_wmask.asUInt))(outerConfig) - - val put_atomic_acquire = PutAtomic( - client_xact_id = iacq.client_xact_id, - addr_block = out_addr_block, - addr_beat = out_addr_beat, - addr_byte = out_addr_byte, - atomic_opcode = iacq.op_code(), - operand_size = iacq.op_size(), - data = align_data(switch_addr, iacq.data))(outerConfig) - - val default_acquire = Acquire( - is_builtin_type = Bool(true), - a_type = iacq.a_type, - client_xact_id = iacq.client_xact_id, - addr_block = iacq.addr_block)(outerConfig) - - io.out.acquire.valid := sending_put || (!shrink && io.in.acquire.valid) - io.out.acquire.bits := MuxCase(default_acquire, Seq( - sending_put -> put_block_acquire, - wideget -> get_block_acquire, - smallget -> get_acquire, - smallput -> put_acquire, - atomic -> put_atomic_acquire)) - io.in.acquire.ready := !sending_put && (shrink || io.out.acquire.ready) - - assert(!io.in.acquire.valid || iacq.isBuiltInType(), "Non-builtin acquires not supported by widener") - - when (io.in.acquire.fire() && shrink) { - when (!collecting) { - put_block := out_addr_block - put_id := iacq.client_xact_id - put_allocate := iacq.allocate() - collecting := Bool(true) - } - put_data(recv_idx) := iacq.data - put_wmask(recv_idx) := iacq.wmask() - } - - when (io.in.acquire.fire() && smallget) { - smallget_switch(iacq.client_xact_id) := switch_addr - } - - when (recv_done) { sending_put := Bool(true) } - when (sending_put && io.out.acquire.ready) { sending_put := Bool(false) } - when (put_done) { collecting := Bool(false) } - - val returning_data = Reg(init = Bool(false)) - val (send_idx, send_done) = Counter( - io.in.grant.ready && returning_data, factor) - - val gnt_beat = Reg(UInt(width = outerBeatAddrBits)) - val gnt_client_id = Reg(UInt(width = outerClientIdBits)) - val gnt_manager_id = Reg(UInt(width = outerManagerIdBits)) - val gnt_data = Reg(UInt(width = outerDataBits)) - - when (io.out.grant.fire() && stretch) { - gnt_data := ognt.data - gnt_client_id := ognt.client_xact_id - gnt_manager_id := ognt.manager_xact_id - gnt_beat := ognt.addr_beat - returning_data := Bool(true) - } - - when (send_done) { returning_data := Bool(false) } - - def select_data(data: UInt, sel: UInt): UInt = - data >> (sel << log2Up(innerDataBits)) - - val gnt_switch = smallget_switch(ognt.client_xact_id) - - val innerConfig = p.alterPartial({ case TLId => innerTLId }) - - val get_block_grant = Grant( - is_builtin_type = Bool(true), - g_type = Grant.getDataBlockType, - client_xact_id = gnt_client_id, - manager_xact_id = gnt_manager_id, - addr_beat = Cat(gnt_beat, send_idx), - data = select_data(gnt_data, send_idx))(innerConfig) - - val get_grant = Grant( - is_builtin_type = Bool(true), - g_type = Grant.getDataBeatType, - client_xact_id = ognt.client_xact_id, - manager_xact_id = ognt.manager_xact_id, - addr_beat = Cat(ognt.addr_beat, gnt_switch), - data = select_data(ognt.data, gnt_switch))(innerConfig) - - val default_grant = Grant( - is_builtin_type = Bool(true), - g_type = ognt.g_type, - client_xact_id = ognt.client_xact_id, - manager_xact_id = ognt.manager_xact_id, - addr_beat = UInt(0), - data = UInt(0))(innerConfig) - - io.in.grant.valid := returning_data || (!stretch && io.out.grant.valid) - io.in.grant.bits := MuxCase(default_grant, Seq( - returning_data -> get_block_grant, - smallgnt -> get_grant)) - io.out.grant.ready := !returning_data && (stretch || io.in.grant.ready) -} - -class TileLinkIONarrower(innerTLId: String, outerTLId: String) - (implicit p: Parameters) extends TLModule()(p) { - - val innerParams = p(TLKey(innerTLId)) - val outerParams = p(TLKey(outerTLId)) - val innerDataBeats = innerParams.dataBeats - val innerDataBits = innerParams.dataBitsPerBeat - val innerWriteMaskBits = innerParams.writeMaskBits - val innerByteAddrBits = log2Up(innerWriteMaskBits) - val outerDataBeats = outerParams.dataBeats - val outerDataBits = outerParams.dataBitsPerBeat - val outerWriteMaskBits = outerParams.writeMaskBits - val outerByteAddrBits = log2Up(outerWriteMaskBits) - val outerBeatAddrBits = log2Up(outerDataBeats) - val outerBlockOffset = outerBeatAddrBits + outerByteAddrBits - val outerMaxClients = outerParams.maxClientsPerPort - val outerIdBits = log2Up(outerParams.maxClientXacts * outerMaxClients) - - require(outerDataBeats > innerDataBeats) - require(outerDataBeats % innerDataBeats == 0) - require(outerDataBits < innerDataBits) - require(outerDataBits * outerDataBeats == innerDataBits * innerDataBeats) - - val factor = outerDataBeats / innerDataBeats - - val io = new Bundle { - val in = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => innerTLId})).flip - val out = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => outerTLId})) - } - - val iacq = io.in.acquire.bits - val ognt = io.out.grant.bits - - val stretch = iacq.a_type === Acquire.putBlockType - val wideget = iacq.a_type === Acquire.getBlockType - val smallput = iacq.a_type === Acquire.putType - val smallget = iacq.a_type === Acquire.getType - val atomic = iacq.a_type === Acquire.putAtomicType - - val acq_data_buffer = Reg(UInt(width = innerDataBits)) - val acq_wmask_buffer = Reg(UInt(width = innerWriteMaskBits)) - val acq_client_id = Reg(iacq.client_xact_id) - val acq_addr_block = Reg(iacq.addr_block) - val acq_addr_beat = Reg(iacq.addr_beat) - val oacq_ctr = Counter(factor) - - val outer_beat_addr = iacq.full_addr()(outerBlockOffset - 1, outerByteAddrBits) - val outer_byte_addr = iacq.full_addr()(outerByteAddrBits - 1, 0) - - val mask_chunks = Vec.tabulate(factor) { i => - val lsb = i * outerWriteMaskBits - val msb = (i + 1) * outerWriteMaskBits - 1 - iacq.wmask()(msb, lsb) - } - - val data_chunks = Vec.tabulate(factor) { i => - val lsb = i * outerDataBits - val msb = (i + 1) * outerDataBits - 1 - iacq.data(msb, lsb) - } - - val beat_sel = Cat(mask_chunks.map(mask => mask.orR).reverse) - - val smallput_data = Mux1H(beat_sel, data_chunks) - val smallput_wmask = Mux1H(beat_sel, mask_chunks) - val smallput_beat = Cat(iacq.addr_beat, PriorityEncoder(beat_sel)) - - assert(!io.in.acquire.valid || !smallput || PopCount(beat_sel) <= UInt(1), - "Can't perform Put wider than outer width") - - val read_size_ok = iacq.op_size() <= UInt(log2Ceil(outerDataBits / 8)) - assert(!io.in.acquire.valid || !smallget || read_size_ok, - "Can't perform Get wider than outer width") - - assert(!io.in.acquire.valid || !atomic || read_size_ok, - "Can't perform PutAtomic wider than outer width") - - val outerConfig = p.alterPartial({ case TLId => outerTLId }) - val innerConfig = p.alterPartial({ case TLId => innerTLId }) - - val get_block_acquire = GetBlock( - client_xact_id = iacq.client_xact_id, - addr_block = iacq.addr_block, - alloc = iacq.allocate())(outerConfig) - - val put_block_acquire = PutBlock( - client_xact_id = acq_client_id, - addr_block = acq_addr_block, - addr_beat = if (factor > 1) - Cat(acq_addr_beat, oacq_ctr.value) - else acq_addr_beat, - data = acq_data_buffer(outerDataBits - 1, 0), - wmask = Some(acq_wmask_buffer(outerWriteMaskBits - 1, 0)))(outerConfig) - - val get_acquire = Get( - client_xact_id = iacq.client_xact_id, - addr_block = iacq.addr_block, - addr_beat = outer_beat_addr, - addr_byte = outer_byte_addr, - operand_size = iacq.op_size(), - alloc = iacq.allocate())(outerConfig) - - val put_acquire = Put( - client_xact_id = iacq.client_xact_id, - addr_block = iacq.addr_block, - addr_beat = smallput_beat, - data = smallput_data, - wmask = Some(smallput_wmask))(outerConfig) - - val atomic_addr = iacq.full_addr() - val atomic_addr_beat = atomic_addr(outerBlockOffset - 1, outerByteAddrBits) - val atomic_addr_byte = atomic_addr(outerByteAddrBits - 1, 0) - val atomic_data_sel = atomic_addr(outerByteAddrBits + log2Up(factor) - 1, outerByteAddrBits) - val atomic_data_vec = Vec(Seq.tabulate(factor) { - i => iacq.data((i + 1) * outerDataBits - 1, i * outerDataBits) - }) - - val put_atomic_acquire = PutAtomic( - client_xact_id = iacq.client_xact_id, - addr_block = iacq.addr_block, - addr_beat = atomic_addr_beat, - addr_byte = atomic_addr_byte, - atomic_opcode = iacq.op_code(), - operand_size = iacq.op_size(), - data = atomic_data_vec(atomic_data_sel))(outerConfig) - - val default_acquire = Acquire( - is_builtin_type = Bool(true), - a_type = iacq.a_type, - client_xact_id = iacq.client_xact_id, - addr_block = iacq.addr_block)(outerConfig) - - val sending_put = Reg(init = Bool(false)) - val pass_valid = io.in.acquire.valid && !stretch - - io.out.acquire.bits := MuxCase(default_acquire, Seq( - sending_put -> put_block_acquire, - wideget -> get_block_acquire, - smallput -> put_acquire, - smallget -> get_acquire, - atomic -> put_atomic_acquire)) - io.out.acquire.valid := sending_put || pass_valid - io.in.acquire.ready := !sending_put && (stretch || io.out.acquire.ready) - - assert(!io.in.acquire.valid || iacq.isBuiltInType(), "Non-builtin acquires not supported by narrower") - - when (io.in.acquire.fire() && stretch) { - acq_data_buffer := iacq.data - acq_wmask_buffer := iacq.wmask() - acq_client_id := iacq.client_xact_id - acq_addr_block := iacq.addr_block - acq_addr_beat := iacq.addr_beat - sending_put := Bool(true) - } - - when (sending_put && io.out.acquire.ready) { - acq_data_buffer := acq_data_buffer >> outerDataBits - acq_wmask_buffer := acq_wmask_buffer >> outerWriteMaskBits - when (oacq_ctr.inc()) { sending_put := Bool(false) } - } - - val gnt_data_buffer = Reg(Vec(factor, UInt(width = outerDataBits))) - val gnt_client_id = Reg(ognt.client_xact_id) - val gnt_manager_id = Reg(ognt.manager_xact_id) - - val ignt_ctr = Counter(innerDataBeats) - val ognt_ctr = Counter(factor) - val sending_get = Reg(init = Bool(false)) - - val smallget_grant = ognt.g_type === Grant.getDataBeatType - val wideget_grant = ognt.hasMultibeatData() - - val get_block_grant = Grant( - is_builtin_type = Bool(true), - g_type = Grant.getDataBlockType, - client_xact_id = gnt_client_id, - manager_xact_id = gnt_manager_id, - addr_beat = ignt_ctr.value, - data = gnt_data_buffer.asUInt)(innerConfig) - - val get_grant = Grant( - is_builtin_type = Bool(true), - g_type = Grant.getDataBeatType, - client_xact_id = ognt.client_xact_id, - manager_xact_id = ognt.manager_xact_id, - addr_beat = ognt.addr_beat >> UInt(log2Up(factor)), - data = Fill(factor, ognt.data))(innerConfig) - - val default_grant = Grant( - is_builtin_type = Bool(true), - g_type = ognt.g_type, - client_xact_id = ognt.client_xact_id, - manager_xact_id = ognt.manager_xact_id, - addr_beat = UInt(0), - data = UInt(0))(innerConfig) - - io.in.grant.valid := sending_get || (io.out.grant.valid && !wideget_grant) - io.out.grant.ready := !sending_get && (wideget_grant || io.in.grant.ready) - - io.in.grant.bits := MuxCase(default_grant, Seq( - sending_get -> get_block_grant, - smallget_grant -> get_grant)) - - when (io.out.grant.valid && wideget_grant && !sending_get) { - gnt_data_buffer(ognt_ctr.value) := ognt.data - when (ognt_ctr.inc()) { - gnt_client_id := ognt.client_xact_id - gnt_manager_id := ognt.manager_xact_id - sending_get := Bool(true) - } - } - - when (io.in.grant.ready && sending_get) { - ignt_ctr.inc() - sending_get := Bool(false) - } -} diff --git a/src/main/scala/uncore/devices/Rom.scala b/src/main/scala/uncore/devices/Rom.scala deleted file mode 100644 index a676a6fe..00000000 --- a/src/main/scala/uncore/devices/Rom.scala +++ /dev/null @@ -1,132 +0,0 @@ -// See LICENSE.SiFive for license details. -// See LICENSE.Berkeley for license details. - -package uncore.devices - -import Chisel._ -import unittest.UnitTest -import junctions._ -import diplomacy._ -import uncore.tilelink._ -import uncore.tilelink2._ -import uncore.util._ -import config._ - -class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4, - resources: Seq[Resource] = new SimpleDevice("rom", Seq("sifive,rom0")).reg("mem"))(implicit p: Parameters) extends LazyModule -{ - - val node = TLManagerNode(beatBytes, TLManagerParameters ( - address = List(AddressSet(base, size-1)), - resources = resources, - regionType = RegionType.UNCACHED, - executable = executable, - supportsGet = TransferSizes(1, beatBytes), - fifoId = Some(0))) - - lazy val module = new LazyModuleImp(this) { - val io = new Bundle { - val in = node.bundleIn - } - - val contents = contentsDelayed - val wrapSize = 1 << log2Ceil(contents.size) - require (wrapSize <= size) - - val in = io.in(0) - val edge = node.edgesIn(0) - - val words = (contents ++ Seq.fill(wrapSize-contents.size)(0.toByte)).grouped(beatBytes).toSeq - val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8}) - val rom = Vec(bigs.map(x => UInt(x, width = 8*beatBytes))) - - in.d.valid := in.a.valid - in.a.ready := in.d.ready - - val index = in.a.bits.address(log2Ceil(wrapSize)-1,log2Ceil(beatBytes)) - val high = if (wrapSize == size) UInt(0) else in.a.bits.address(log2Ceil(size)-1, log2Ceil(wrapSize)) - in.d.bits := edge.AccessAck(in.a.bits, UInt(0), Mux(high.orR, UInt(0), rom(index))) - - // Tie off unused channels - in.b.valid := Bool(false) - in.c.ready := Bool(true) - in.e.ready := Bool(true) - } -} - -class ROMSlave(contents: Seq[Byte])(implicit val p: Parameters) extends Module - with HasTileLinkParameters { - val io = new ClientUncachedTileLinkIO().flip - - val acq = Queue(io.acquire, 1) - val single_beat = acq.bits.isBuiltInType(Acquire.getType) - val multi_beat = acq.bits.isBuiltInType(Acquire.getBlockType) - assert(!acq.valid || single_beat || multi_beat, "unsupported ROMSlave operation") - - val addr_beat = Reg(UInt()) - when (io.grant.fire()) { addr_beat := addr_beat + UInt(1) } - when (io.acquire.fire()) { addr_beat := io.acquire.bits.addr_beat } - - val byteWidth = tlDataBits / 8 - val rows = (contents.size + byteWidth - 1)/byteWidth - val rom = Vec.tabulate(rows) { i => - val slice = contents.slice(i*byteWidth, (i+1)*byteWidth) - UInt(slice.foldRight(BigInt(0)) { case (x,y) => (y << 8) + (x.toInt & 0xFF) }, byteWidth*8) - } - val raddr = Cat(acq.bits.addr_block, addr_beat) - val rdata = rom(if (rows == 1) UInt(0) else raddr(log2Up(rom.size)-1,0)) - - val last = !multi_beat || addr_beat === UInt(tlDataBeats-1) - io.grant.valid := acq.valid - acq.ready := io.grant.ready && last - io.grant.bits := Grant( - is_builtin_type = Bool(true), - g_type = acq.bits.getBuiltInGrantType(), - client_xact_id = acq.bits.client_xact_id, - manager_xact_id = UInt(0), - addr_beat = addr_beat, - data = rdata) -} - -class ROMSlaveTest(timeout: Int = 4096)(implicit p: Parameters) extends UnitTest(timeout) { - val romdata = Seq( - BigInt("01234567deadbeef", 16), - BigInt("ab32fee8d00dfeed", 16)) - val rombytes = romdata.map(_.toByteArray.reverse).flatten - val rom = Module(new ROMSlave(rombytes)) - val driver = Module(new DriverSet( - (driverParams: Parameters) => { - implicit val p = driverParams - Seq( - Module(new GetMultiWidthDriver), - Module(new GetSweepDriver(romdata)), - Module(new GetBlockSweepDriver(romdata))) - })) - rom.io <> driver.io.mem - driver.io.start := io.start - io.finished := driver.io.finished -} - -class NastiROM(contents: Seq[Byte])(implicit p: Parameters) extends Module { - val io = new NastiIO().flip - val ar = Queue(io.ar, 1) - - // This assumes ROMs are in read-only parts of the address map. - // Reuse b_queue code from NastiErrorSlave if this assumption is bad. - when (ar.valid) { assert(ar.bits.len === UInt(0), "Can't burst-read from NastiROM") } - assert(!(io.aw.valid || io.w.valid), "Can't write to NastiROM") - io.aw.ready := Bool(false) - io.w.ready := Bool(false) - io.b.valid := Bool(false) - - val byteWidth = io.r.bits.nastiXDataBits / 8 - val rows = (contents.size + byteWidth - 1)/byteWidth - val rom = Vec.tabulate(rows) { i => - val slice = contents.slice(i*byteWidth, (i+1)*byteWidth) - UInt(slice.foldRight(BigInt(0)) { case (x,y) => (y << 8) + (x.toInt & 0xFF) }, byteWidth*8) - } - val rdata = rom(if (rows == 1) UInt(0) else ar.bits.addr(log2Up(contents.size)-1,log2Up(byteWidth))) - - io.r <> ar - io.r.bits := NastiReadDataChannel(ar.bits.id, rdata) -} diff --git a/src/main/scala/uncore/tilelink/Arbiters.scala b/src/main/scala/uncore/tilelink/Arbiters.scala deleted file mode 100644 index a0728964..00000000 --- a/src/main/scala/uncore/tilelink/Arbiters.scala +++ /dev/null @@ -1,198 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package uncore.tilelink -import Chisel._ -import junctions._ -import config._ - -/** Utility functions for constructing TileLinkIO arbiters */ -trait TileLinkArbiterLike extends HasTileLinkParameters { - // Some shorthand type variables - type ManagerSourcedWithId = ManagerToClientChannel with HasClientTransactionId - type ClientSourcedWithId = ClientToManagerChannel with HasClientTransactionId - type ClientSourcedWithIdAndData = ClientToManagerChannel with HasClientTransactionId with HasTileLinkData - - val arbN: Int // The number of ports on the client side - - // These abstract funcs are filled in depending on whether the arbiter mucks with the - // outgoing client ids to track sourcing and then needs to revert them on the way back - def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int): Bits - def managerSourcedClientXactId(in: ManagerSourcedWithId): Bits - def arbIdx(in: ManagerSourcedWithId): UInt - - // The following functions are all wiring helpers for each of the different types of TileLink channels - - def hookupClientSource[M <: ClientSourcedWithIdAndData]( - clts: Seq[DecoupledIO[LogicalNetworkIO[M]]], - mngr: DecoupledIO[LogicalNetworkIO[M]]) { - def hasData(m: LogicalNetworkIO[M]) = m.payload.hasMultibeatData() - val arb = Module(new LockingRRArbiter(mngr.bits, arbN, tlDataBeats, Some(hasData _))) - clts.zipWithIndex.zip(arb.io.in).map{ case ((req, id), arb) => { - arb.valid := req.valid - arb.bits := req.bits - arb.bits.payload.client_xact_id := clientSourcedClientXactId(req.bits.payload, id) - req.ready := arb.ready - }} - mngr <> arb.io.out - } - - def hookupClientSourceHeaderless[M <: ClientSourcedWithIdAndData]( - clts: Seq[DecoupledIO[M]], - mngr: DecoupledIO[M]) { - def hasData(m: M) = m.hasMultibeatData() - val arb = Module(new LockingRRArbiter(mngr.bits, arbN, tlDataBeats, Some(hasData _))) - clts.zipWithIndex.zip(arb.io.in).map{ case ((req, id), arb) => { - arb.valid := req.valid - arb.bits := req.bits - arb.bits.client_xact_id := clientSourcedClientXactId(req.bits, id) - req.ready := arb.ready - }} - mngr <> arb.io.out - } - - def hookupManagerSourceWithHeader[M <: ManagerToClientChannel]( - clts: Seq[DecoupledIO[LogicalNetworkIO[M]]], - mngr: DecoupledIO[LogicalNetworkIO[M]]) { - mngr.ready := Bool(false) - for (i <- 0 until arbN) { - clts(i).valid := Bool(false) - when (mngr.bits.header.dst === UInt(i)) { - clts(i).valid := mngr.valid - mngr.ready := clts(i).ready - } - clts(i).bits := mngr.bits - } - } - - def hookupManagerSourceWithId[M <: ManagerSourcedWithId]( - clts: Seq[DecoupledIO[LogicalNetworkIO[M]]], - mngr: DecoupledIO[LogicalNetworkIO[M]]) { - mngr.ready := Bool(false) - for (i <- 0 until arbN) { - clts(i).valid := Bool(false) - when (arbIdx(mngr.bits.payload) === UInt(i)) { - clts(i).valid := mngr.valid - mngr.ready := clts(i).ready - } - clts(i).bits := mngr.bits - clts(i).bits.payload.client_xact_id := managerSourcedClientXactId(mngr.bits.payload) - } - } - - def hookupManagerSourceHeaderlessWithId[M <: ManagerSourcedWithId]( - clts: Seq[DecoupledIO[M]], - mngr: DecoupledIO[M]) { - mngr.ready := Bool(false) - for (i <- 0 until arbN) { - clts(i).valid := Bool(false) - when (arbIdx(mngr.bits) === UInt(i)) { - clts(i).valid := mngr.valid - mngr.ready := clts(i).ready - } - clts(i).bits := mngr.bits - clts(i).bits.client_xact_id := managerSourcedClientXactId(mngr.bits) - } - } - - def hookupManagerSourceBroadcast[M <: Data](clts: Seq[DecoupledIO[M]], mngr: DecoupledIO[M]) { - clts.map{ _.valid := mngr.valid } - clts.map{ _.bits := mngr.bits } - mngr.ready := clts.map(_.ready).reduce(_&&_) - } - - def hookupFinish[M <: LogicalNetworkIO[Finish]]( clts: Seq[DecoupledIO[M]], mngr: DecoupledIO[M]) { - val arb = Module(new RRArbiter(mngr.bits, arbN)) - arb.io.in <> clts - mngr <> arb.io.out - } -} - -/** Abstract base case for any Arbiters that have UncachedTileLinkIOs */ -abstract class UncachedTileLinkIOArbiter(val arbN: Int)(implicit val p: Parameters) extends Module - with TileLinkArbiterLike { - val io = new Bundle { - val in = Vec(arbN, new UncachedTileLinkIO).flip - val out = new UncachedTileLinkIO - } - hookupClientSource(io.in.map(_.acquire), io.out.acquire) - hookupFinish(io.in.map(_.finish), io.out.finish) - hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant) -} - -/** Abstract base case for any Arbiters that have cached TileLinkIOs */ -abstract class TileLinkIOArbiter(val arbN: Int)(implicit val p: Parameters) extends Module - with TileLinkArbiterLike { - val io = new Bundle { - val in = Vec(arbN, new TileLinkIO).flip - val out = new TileLinkIO - } - hookupClientSource(io.in.map(_.acquire), io.out.acquire) - hookupClientSource(io.in.map(_.release), io.out.release) - hookupFinish(io.in.map(_.finish), io.out.finish) - hookupManagerSourceBroadcast(io.in.map(_.probe), io.out.probe) - hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant) -} - -/** Appends the port index of the arbiter to the client_xact_id */ -trait AppendsArbiterId extends TileLinkArbiterLike { - def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = - Cat(in.client_xact_id, UInt(id, log2Up(arbN))) - def managerSourcedClientXactId(in: ManagerSourcedWithId) = { - /* This shouldn't be necessary, but Chisel3 doesn't emit correct Verilog - * when right shifting by too many bits. See - * https://github.com/ucb-bar/firrtl/issues/69 */ - if (in.client_xact_id.getWidth > log2Up(arbN)) - in.client_xact_id >> log2Up(arbN) - else - UInt(0) - } - def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id(log2Up(arbN)-1,0) -} - -/** Uses the client_xact_id as is (assumes it has been set to port index) */ -trait PassesId extends TileLinkArbiterLike { - def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = in.client_xact_id - def managerSourcedClientXactId(in: ManagerSourcedWithId) = in.client_xact_id - def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id -} - -/** Overwrites some default client_xact_id with the port idx */ -trait UsesNewId extends TileLinkArbiterLike { - def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = UInt(id, log2Up(arbN)) - def managerSourcedClientXactId(in: ManagerSourcedWithId) = UInt(0) - def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id -} - -// Now we can mix-in thevarious id-generation traits to make concrete arbiter classes -class UncachedTileLinkIOArbiterThatAppendsArbiterId(val n: Int)(implicit p: Parameters) extends UncachedTileLinkIOArbiter(n)(p) with AppendsArbiterId -class UncachedTileLinkIOArbiterThatPassesId(val n: Int)(implicit p: Parameters) extends UncachedTileLinkIOArbiter(n)(p) with PassesId -class UncachedTileLinkIOArbiterThatUsesNewId(val n: Int)(implicit p: Parameters) extends UncachedTileLinkIOArbiter(n)(p) with UsesNewId -class TileLinkIOArbiterThatAppendsArbiterId(val n: Int)(implicit p: Parameters) extends TileLinkIOArbiter(n)(p) with AppendsArbiterId -class TileLinkIOArbiterThatPassesId(val n: Int)(implicit p: Parameters) extends TileLinkIOArbiter(n)(p) with PassesId -class TileLinkIOArbiterThatUsesNewId(val n: Int)(implicit p: Parameters) extends TileLinkIOArbiter(n)(p) with UsesNewId - -/** Concrete uncached client-side arbiter that appends the arbiter's port id to client_xact_id */ -class ClientUncachedTileLinkIOArbiter(val arbN: Int)(implicit val p: Parameters) extends Module with TileLinkArbiterLike with AppendsArbiterId { - val io = new Bundle { - val in = Vec(arbN, new ClientUncachedTileLinkIO).flip - val out = new ClientUncachedTileLinkIO - } - if (arbN > 1) { - hookupClientSourceHeaderless(io.in.map(_.acquire), io.out.acquire) - hookupManagerSourceHeaderlessWithId(io.in.map(_.grant), io.out.grant) - } else { io.out <> io.in.head } -} - -/** Concrete client-side arbiter that appends the arbiter's port id to client_xact_id */ -class ClientTileLinkIOArbiter(val arbN: Int)(implicit val p: Parameters) extends Module with TileLinkArbiterLike with AppendsArbiterId { - val io = new Bundle { - val in = Vec(arbN, new ClientTileLinkIO).flip - val out = new ClientTileLinkIO - } - if (arbN > 1) { - hookupClientSourceHeaderless(io.in.map(_.acquire), io.out.acquire) - hookupClientSourceHeaderless(io.in.map(_.release), io.out.release) - hookupManagerSourceBroadcast(io.in.map(_.probe), io.out.probe) - hookupManagerSourceHeaderlessWithId(io.in.map(_.grant), io.out.grant) - } else { io.out <> io.in.head } -} diff --git a/src/main/scala/uncore/tilelink/Crossing.scala b/src/main/scala/uncore/tilelink/Crossing.scala deleted file mode 100644 index 49bc1cf2..00000000 --- a/src/main/scala/uncore/tilelink/Crossing.scala +++ /dev/null @@ -1,55 +0,0 @@ -// See LICENSE.SiFive for license details. - -package uncore.tilelink - -import Chisel._ -import util._ - -object AsyncClientUncachedTileLinkCrossing { - def apply(from_clock: Clock, from_reset: Bool, from_source: ClientUncachedTileLinkIO, to_clock: Clock, to_reset: Bool, depth: Int = 8, sync: Int = 3): ClientUncachedTileLinkIO = { - val to_sink = Wire(new ClientUncachedTileLinkIO()(from_source.p)) - to_sink.acquire <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.acquire, to_clock, to_reset, depth, sync) - from_source.grant <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.grant, from_clock, from_reset, depth, sync) - to_sink - } -} - -object AsyncClientTileLinkCrossing { - def apply(from_clock: Clock, from_reset: Bool, from_source: ClientTileLinkIO, to_clock: Clock, to_reset: Bool, depth: Int = 8, sync: Int = 3): ClientTileLinkIO = { - val to_sink = Wire(new ClientTileLinkIO()(from_source.p)) - to_sink.acquire <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.acquire, to_clock, to_reset, depth, sync) - to_sink.release <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.release, to_clock, to_reset, depth, sync) - to_sink.finish <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.finish, to_clock, to_reset, depth, sync) - from_source.grant <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.grant, from_clock, from_reset, depth, sync) - from_source.probe <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.probe, from_clock, from_reset, depth, sync) - to_sink - } -} - -object AsyncUTileLinkTo { - def apply(to_clock: Clock, to_reset: Bool, source: ClientUncachedTileLinkIO, depth: Int = 8, sync: Int = 3): ClientUncachedTileLinkIO = { - val scope = AsyncScope() - AsyncClientUncachedTileLinkCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) - } -} - -object AsyncUTileLinkFrom { - def apply(from_clock: Clock, from_reset: Bool, from_source: ClientUncachedTileLinkIO, depth: Int = 8, sync: Int = 3): ClientUncachedTileLinkIO = { - val scope = AsyncScope() - AsyncClientUncachedTileLinkCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) - } -} - -object AsyncTileLinkTo { - def apply(to_clock: Clock, to_reset: Bool, source: ClientTileLinkIO, depth: Int = 8, sync: Int = 3): ClientTileLinkIO = { - val scope = AsyncScope() - AsyncClientTileLinkCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) - } -} - -object AsyncTileLinkFrom { - def apply(from_clock: Clock, from_reset: Bool, from_source: ClientTileLinkIO, depth: Int = 8, sync: Int = 3): ClientTileLinkIO = { - val scope = AsyncScope() - AsyncClientTileLinkCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) - } -} diff --git a/src/main/scala/uncore/tilelink/Definitions.scala b/src/main/scala/uncore/tilelink/Definitions.scala deleted file mode 100644 index 5f854dc5..00000000 --- a/src/main/scala/uncore/tilelink/Definitions.scala +++ /dev/null @@ -1,972 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.tilelink -import Chisel._ -import junctions._ -import uncore.coherence.CoherencePolicy -import uncore.constants._ -import util._ -import scala.math.max -import config._ - -case object CacheBlockOffsetBits extends Field[Int] -case object AmoAluOperandBits extends Field[Int] - -case object TLId extends Field[String] -case class TLKey(id: String) extends Field[TileLinkParameters] - -/** Parameters exposed to the top-level design, set based on - * external requirements or design space exploration - * - * Coherency policy used to define custom mesage types - * Number of manager agents - * Number of client agents that cache data and use custom [[uncore.Acquire]] types - * Number of client agents that do not cache data and use built-in [[uncore.Acquire]] types - * Maximum number of unique outstanding transactions per client - * Maximum number of clients multiplexed onto a single port - * Maximum number of unique outstanding transactions per manager - * Width of cache block addresses - * Total amount of data per cache block - * Number of data beats per cache block - **/ - -case class TileLinkParameters( - coherencePolicy: CoherencePolicy, - nManagers: Int, - nCachingClients: Int, - nCachelessClients: Int, - maxClientXacts: Int, - maxClientsPerPort: Int, - maxManagerXacts: Int, - dataBits: Int, - dataBeats: Int = 4, - overrideDataBitsPerBeat: Option[Int] = None - ) { - val nClients = nCachingClients + nCachelessClients - val writeMaskBits: Int = ((dataBits / dataBeats) - 1) / 8 + 1 - val dataBitsPerBeat: Int = overrideDataBitsPerBeat.getOrElse(dataBits / dataBeats) -} - - -/** Utility trait for building Modules and Bundles that use TileLink parameters */ -trait HasTileLinkParameters { - implicit val p: Parameters - val tlExternal = p(TLKey(p(TLId))) - val tlCoh = tlExternal.coherencePolicy - val tlNManagers = tlExternal.nManagers - val tlNCachingClients = tlExternal.nCachingClients - val tlNCachelessClients = tlExternal.nCachelessClients - val tlNClients = tlExternal.nClients - val tlClientIdBits = log2Up(tlNClients) - val tlManagerIdBits = log2Up(tlNManagers) - val tlMaxClientXacts = tlExternal.maxClientXacts - val tlMaxClientsPerPort = tlExternal.maxClientsPerPort - val tlMaxManagerXacts = tlExternal.maxManagerXacts - val tlClientXactIdBits = log2Up(tlMaxClientXacts*tlMaxClientsPerPort) - val tlManagerXactIdBits = log2Up(tlMaxManagerXacts) - val tlBlockAddrBits = p(rocket.PAddrBits) - p(CacheBlockOffsetBits) - val tlDataBeats = tlExternal.dataBeats - val tlDataBits = tlExternal.dataBitsPerBeat - val tlDataBytes = tlDataBits/8 - val tlWriteMaskBits = tlExternal.writeMaskBits - val tlBeatAddrBits = log2Up(tlDataBeats) - val tlByteAddrBits = log2Up(tlWriteMaskBits) - val tlMemoryOpcodeBits = M_SZ - val tlMemoryOperandSizeBits = log2Ceil(log2Ceil(tlWriteMaskBits) + 1) - val tlAcquireTypeBits = max(log2Up(Acquire.nBuiltInTypes), - tlCoh.acquireTypeWidth) - val tlAcquireUnionBits = max(tlWriteMaskBits, - (tlByteAddrBits + - tlMemoryOperandSizeBits + - tlMemoryOpcodeBits)) + 1 - val tlGrantTypeBits = max(log2Up(Grant.nBuiltInTypes), - tlCoh.grantTypeWidth) + 1 -/** Whether the underlying physical network preserved point-to-point ordering of messages */ - val tlNetworkPreservesPointToPointOrdering = false - val tlNetworkDoesNotInterleaveBeats = true - val amoAluOperandBits = p(AmoAluOperandBits) - val amoAluOperandBytes = amoAluOperandBits/8 -} - -abstract class TLModule(implicit val p: Parameters) extends Module - with HasTileLinkParameters -abstract class TLBundle(implicit val p: Parameters) extends util.ParameterizedBundle()(p) - with HasTileLinkParameters - -/** Base trait for all TileLink channels */ -abstract class TileLinkChannel(implicit p: Parameters) extends TLBundle()(p) { - def hasData(dummy: Int = 0): Bool - def hasMultibeatData(dummy: Int = 0): Bool -} -/** Directionality of message channel. Used to hook up logical network ports to physical network ports */ -abstract class ClientToManagerChannel(implicit p: Parameters) extends TileLinkChannel()(p) -/** Directionality of message channel. Used to hook up logical network ports to physical network ports */ -abstract class ManagerToClientChannel(implicit p: Parameters) extends TileLinkChannel()(p) -/** Directionality of message channel. Used to hook up logical network ports to physical network ports */ -abstract class ClientToClientChannel(implicit p: Parameters) extends TileLinkChannel()(p) // Unused for now - -/** Common signals that are used in multiple channels. - * These traits are useful for type parameterizing bundle wiring functions. - */ - -/** Address of a cache block. */ -trait HasCacheBlockAddress extends HasTileLinkParameters { - val addr_block = UInt(width = tlBlockAddrBits) - - def conflicts(that: HasCacheBlockAddress) = this.addr_block === that.addr_block - def conflicts(addr: UInt) = this.addr_block === addr -} - -/** Sub-block address or beat id of multi-beat data */ -trait HasTileLinkBeatId extends HasTileLinkParameters { - val addr_beat = UInt(width = tlBeatAddrBits) -} - -/* Client-side transaction id. Usually Miss Status Handling Register File index */ -trait HasClientTransactionId extends HasTileLinkParameters { - val client_xact_id = Bits(width = tlClientXactIdBits) -} - -/** Manager-side transaction id. Usually Transaction Status Handling Register File index. */ -trait HasManagerTransactionId extends HasTileLinkParameters { - val manager_xact_id = Bits(width = tlManagerXactIdBits) -} - -/** A single beat of cache block data */ -trait HasTileLinkData extends HasTileLinkBeatId { - val data = UInt(width = tlDataBits) - - def hasData(dummy: Int = 0): Bool - def hasMultibeatData(dummy: Int = 0): Bool - def first(dummy: Int = 0): Bool = !hasMultibeatData() || addr_beat === UInt(0) - def last(dummy: Int = 0): Bool = !hasMultibeatData() || addr_beat === UInt(tlDataBeats-1) -} - -/** An entire cache block of data */ -trait HasTileLinkBlock extends HasTileLinkParameters { - val data_buffer = Vec(tlDataBeats, UInt(width = tlDataBits)) - val wmask_buffer = Vec(tlDataBeats, UInt(width = tlWriteMaskBits)) -} - -/** The id of a client source or destination. Used in managers. */ -trait HasClientId extends HasTileLinkParameters { - val client_id = UInt(width = tlClientIdBits) -} - -trait HasManagerId extends HasTileLinkParameters { - val manager_id = UInt(width = tlManagerIdBits) -} - -trait HasAcquireUnion extends HasTileLinkParameters { - val union = Bits(width = tlAcquireUnionBits) - - // Utility funcs for accessing subblock union: - def isBuiltInType(t: UInt): Bool - val opCodeOff = 1 - val opSizeOff = tlMemoryOpcodeBits + opCodeOff - val addrByteOff = tlMemoryOperandSizeBits + opSizeOff - val addrByteMSB = tlByteAddrBits + addrByteOff - /** Hint whether to allocate the block in any interveneing caches */ - def allocate(dummy: Int = 0) = union(0) - /** Op code for [[uncore.PutAtomic]] operations */ - def op_code(dummy: Int = 0) = Mux( - isBuiltInType(Acquire.putType) || isBuiltInType(Acquire.putBlockType), - M_XWR, union(opSizeOff-1, opCodeOff)) - /** Operand size for [[uncore.PutAtomic]] */ - def op_size(dummy: Int = 0) = union(addrByteOff-1, opSizeOff) - /** Byte address for [[uncore.PutAtomic]] operand */ - def addr_byte(dummy: Int = 0) = union(addrByteMSB-1, addrByteOff) - def amo_offset(dummy: Int = 0) = - if (tlByteAddrBits > log2Up(amoAluOperandBytes)) addr_byte()(tlByteAddrBits-1, log2Up(amoAluOperandBytes)) - else UInt(0) - /** Bit offset of [[uncore.PutAtomic]] operand */ - def amo_shift_bytes(dummy: Int = 0) = UInt(amoAluOperandBytes)*amo_offset() - /** Write mask for [[uncore.Put]], [[uncore.PutBlock]], [[uncore.PutAtomic]] */ - def wmask(dummy: Int = 0): UInt = { - val is_amo = isBuiltInType(Acquire.putAtomicType) - val amo_mask = if (tlByteAddrBits > log2Up(amoAluOperandBytes)) - FillInterleaved(amoAluOperandBytes, UIntToOH(amo_offset())) - else Acquire.fullWriteMask - val is_put = isBuiltInType(Acquire.putBlockType) || isBuiltInType(Acquire.putType) - val put_mask = union(tlWriteMaskBits, 1) - Mux(is_amo, amo_mask, Mux(is_put, put_mask, UInt(0))) - } - /** Full, beat-sized writemask */ - def full_wmask(dummy: Int = 0) = FillInterleaved(8, wmask()) - - /** Is this message a built-in read message */ - def hasPartialWritemask(dummy: Int = 0): Bool = wmask() =/= Acquire.fullWriteMask - -} - -trait HasAcquireType extends HasTileLinkParameters { - val is_builtin_type = Bool() - val a_type = UInt(width = tlAcquireTypeBits) - - /** Message type equality */ - def is(t: UInt) = a_type === t //TODO: make this more opaque; def ===? - - /** Is this message a built-in or custom type */ - def isBuiltInType(dummy: Int = 0): Bool = is_builtin_type - /** Is this message a particular built-in type */ - def isBuiltInType(t: UInt): Bool = is_builtin_type && a_type === t - - /** Does this message refer to subblock operands using info in the Acquire.union subbundle */ - def isSubBlockType(dummy: Int = 0): Bool = isBuiltInType() && a_type.isOneOf(Acquire.typesOnSubBlocks) - - /** Is this message a built-in prefetch message */ - def isPrefetch(dummy: Int = 0): Bool = isBuiltInType() && - (is(Acquire.getPrefetchType) || is(Acquire.putPrefetchType)) - - /** Is this message a built-in atomic message */ - def isAtomic(dummy: Int = 0): Bool = isBuiltInType() && is(Acquire.putAtomicType) - - /** Is this message a built-in read message */ - def isGet(dummy: Int = 0): Bool = isBuiltInType() && (is(Acquire.getType) || is(Acquire.getBlockType)) - - /** Does this message contain data? Assumes that no custom message types have data. */ - def hasData(dummy: Int = 0): Bool = isBuiltInType() && a_type.isOneOf(Acquire.typesWithData) - - /** Does this message contain multiple beats of data? Assumes that no custom message types have data. */ - def hasMultibeatData(dummy: Int = 0): Bool = Bool(tlDataBeats > 1) && isBuiltInType() && - a_type.isOneOf(Acquire.typesWithMultibeatData) - - /** Mapping between each built-in Acquire type and a built-in Grant type. */ - def getBuiltInGrantType(dummy: Int = 0): UInt = Acquire.getBuiltInGrantType(this.a_type) -} - -trait HasProbeType extends HasTileLinkParameters { - val p_type = UInt(width = tlCoh.probeTypeWidth) - - def is(t: UInt) = p_type === t - def hasData(dummy: Int = 0) = Bool(false) - def hasMultibeatData(dummy: Int = 0) = Bool(false) -} - -trait MightBeVoluntary { - def isVoluntary(dummy: Int = 0): Bool -} - -trait HasReleaseType extends HasTileLinkParameters with MightBeVoluntary { - val voluntary = Bool() - val r_type = UInt(width = tlCoh.releaseTypeWidth) - - def is(t: UInt) = r_type === t - def hasData(dummy: Int = 0) = r_type.isOneOf(tlCoh.releaseTypesWithData) - def hasMultibeatData(dummy: Int = 0) = Bool(tlDataBeats > 1) && - r_type.isOneOf(tlCoh.releaseTypesWithData) - def isVoluntary(dummy: Int = 0) = voluntary - def requiresAck(dummy: Int = 0) = !Bool(tlNetworkPreservesPointToPointOrdering) -} - -trait HasGrantType extends HasTileLinkParameters with MightBeVoluntary { - val is_builtin_type = Bool() - val g_type = UInt(width = tlGrantTypeBits) - - // Helper funcs - def isBuiltInType(dummy: Int = 0): Bool = is_builtin_type - def isBuiltInType(t: UInt): Bool = is_builtin_type && g_type === t - def is(t: UInt):Bool = g_type === t - def hasData(dummy: Int = 0): Bool = Mux(isBuiltInType(), - g_type.isOneOf(Grant.typesWithData), - g_type.isOneOf(tlCoh.grantTypesWithData)) - def hasMultibeatData(dummy: Int = 0): Bool = - Bool(tlDataBeats > 1) && Mux(isBuiltInType(), - g_type.isOneOf(Grant.typesWithMultibeatData), - g_type.isOneOf(tlCoh.grantTypesWithData)) - def isVoluntary(dummy: Int = 0): Bool = isBuiltInType() && (g_type === Grant.voluntaryAckType) - def requiresAck(dummy: Int = 0): Bool = !Bool(tlNetworkPreservesPointToPointOrdering) && !isVoluntary() -} - -/** TileLink channel bundle definitions */ - -/** The Acquire channel is used to intiate coherence protocol transactions in - * order to gain access to a cache block's data with certain permissions - * enabled. Messages sent over this channel may be custom types defined by - * a [[uncore.CoherencePolicy]] for cached data accesse or may be built-in types - * used for uncached data accesses. Acquires may contain data for Put or - * PutAtomic built-in types. After sending an Acquire, clients must - * wait for a manager to send them a [[uncore.Grant]] message in response. - */ -class AcquireMetadata(implicit p: Parameters) extends ClientToManagerChannel - with HasCacheBlockAddress - with HasClientTransactionId - with HasTileLinkBeatId - with HasAcquireType - with HasAcquireUnion { - /** Complete physical address for block, beat or operand */ - def full_addr(dummy: Int = 0) = - Cat(this.addr_block, this.addr_beat, - Mux(isBuiltInType() && this.a_type.isOneOf(Acquire.typesWithAddrByte), - this.addr_byte(), UInt(0, tlByteAddrBits))) -} - -/** [[uncore.AcquireMetadata]] with an extra field containing the data beat */ -class Acquire(implicit p: Parameters) extends AcquireMetadata - with HasTileLinkData - -/** [[uncore.AcquireMetadata]] with an extra field containing the entire cache block */ -class BufferedAcquire(implicit p: Parameters) extends AcquireMetadata - with HasTileLinkBlock - -/** [[uncore.Acquire]] with an extra field stating its source id */ -class AcquireFromSrc(implicit p: Parameters) extends Acquire - with HasClientId - -/** [[uncore.BufferedAcquire]] with an extra field stating its source id */ -class BufferedAcquireFromSrc(implicit p: Parameters) extends BufferedAcquire - with HasClientId - -/** Used to track metadata for transactions where multiple secondary misses have been merged - * and handled by a single transaction tracker. - */ -class SecondaryMissInfo(implicit p: Parameters) extends TLBundle - with HasClientTransactionId - with HasTileLinkBeatId - with HasClientId - with HasAcquireType - -/** Contains definitions of the the built-in Acquire types and a factory - * for [[uncore.Acquire]] - * - * In general you should avoid using this factory directly and use - * [[uncore.ClientMetadata.makeAcquire]] for custom cached Acquires and - * [[uncore.Get]], [[uncore.Put]], etc. for built-in uncached Acquires. - * - * @param is_builtin_type built-in or custom type message? - * @param a_type built-in type enum or custom type enum - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param addr_beat sub-block address (which beat) - * @param data data being put outwards - * @param union additional fields used for uncached types - */ -object Acquire { - val nBuiltInTypes = 7 - //TODO: Use Enum - def getType = UInt("b000") // Get a single beat of data - def getBlockType = UInt("b001") // Get a whole block of data - def putType = UInt("b010") // Put a single beat of data - def putBlockType = UInt("b011") // Put a whole block of data - def putAtomicType = UInt("b100") // Perform an atomic memory op - def getPrefetchType = UInt("b101") // Prefetch a whole block of data - def putPrefetchType = UInt("b110") // Prefetch a whole block of data, with intent to write - def typesWithData = Vec(putType, putBlockType, putAtomicType) - def typesWithMultibeatData = Vec(putBlockType) - def typesOnSubBlocks = Vec(putType, getType, putAtomicType) - def typesWithAddrByte = Vec(getType, putAtomicType) - - /** Mapping between each built-in Acquire type and a built-in Grant type. */ - def getBuiltInGrantType(a_type: UInt): UInt = { - MuxLookup(a_type, Grant.putAckType, Array( - Acquire.getType -> Grant.getDataBeatType, - Acquire.getBlockType -> Grant.getDataBlockType, - Acquire.putType -> Grant.putAckType, - Acquire.putBlockType -> Grant.putAckType, - Acquire.putAtomicType -> Grant.getDataBeatType, - Acquire.getPrefetchType -> Grant.prefetchAckType, - Acquire.putPrefetchType -> Grant.prefetchAckType)) - } - - def makeUnion( - a_type: UInt, - addr_byte: UInt, - operand_size: UInt, - opcode: UInt, - wmask: UInt, - alloc: Bool) - (implicit p: Parameters): UInt = { - - val tlExternal = p(TLKey(p(TLId))) - val tlWriteMaskBits = tlExternal.writeMaskBits - val tlByteAddrBits = log2Up(tlWriteMaskBits) - val tlMemoryOperandSizeBits = log2Ceil(log2Ceil(tlWriteMaskBits) + 1) - - // These had better be the right size when we cat them together! - val my_addr_byte = (UInt(0, tlByteAddrBits) | addr_byte)(tlByteAddrBits-1, 0) - val my_operand_size = (UInt(0, tlMemoryOperandSizeBits) | operand_size)(tlMemoryOperandSizeBits-1, 0) - val my_opcode = (UInt(0, M_SZ) | opcode)(M_SZ-1, 0) - val my_wmask = (UInt(0, tlWriteMaskBits) | wmask)(tlWriteMaskBits-1, 0) - - MuxLookup(a_type, UInt(0), Array( - Acquire.getType -> Cat(my_addr_byte, my_operand_size, my_opcode, alloc), - Acquire.getBlockType -> Cat(my_operand_size, my_opcode, alloc), - Acquire.putType -> Cat(my_wmask, alloc), - Acquire.putBlockType -> Cat(my_wmask, alloc), - Acquire.putAtomicType -> Cat(my_addr_byte, my_operand_size, my_opcode, alloc), - Acquire.getPrefetchType -> Cat(M_XRD, alloc), - Acquire.putPrefetchType -> Cat(M_XWR, alloc))) - } - - def fullWriteMask(implicit p: Parameters) = SInt(-1, width = p(TLKey(p(TLId))).writeMaskBits).asUInt - def fullOperandSize(implicit p: Parameters) = { - val dataBits = p(TLKey(p(TLId))).dataBitsPerBeat - UInt(log2Ceil(dataBits / 8)) - } - - // Most generic constructor - def apply( - is_builtin_type: Bool, - a_type: Bits, - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt = UInt(0), - data: UInt = UInt(0), - union: UInt = UInt(0)) - (implicit p: Parameters): Acquire = { - val acq = Wire(new Acquire) - acq.is_builtin_type := is_builtin_type - acq.a_type := a_type - acq.client_xact_id := client_xact_id - acq.addr_block := addr_block - acq.addr_beat := addr_beat - acq.data := data - acq.union := union - acq - } - - // Copy constructor - def apply(a: Acquire): Acquire = { - val acq = Wire(new Acquire()(a.p)) - acq := a - acq - } -} - -object BuiltInAcquireBuilder { - def apply( - a_type: UInt, - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt = UInt(0), - data: UInt = UInt(0), - addr_byte: UInt = UInt(0), - operand_size: UInt = UInt(0), - opcode: UInt = UInt(0), - wmask: UInt = UInt(0), - alloc: Bool = Bool(true)) - (implicit p: Parameters): Acquire = { - Acquire( - is_builtin_type = Bool(true), - a_type = a_type, - client_xact_id = client_xact_id, - addr_block = addr_block, - addr_beat = addr_beat, - data = data, - union = Acquire.makeUnion(a_type, addr_byte, operand_size, opcode, wmask, alloc)) - } -} - -/** Get a single beat of data from the outer memory hierarchy - * - * The client can hint whether he block containing this beat should be - * allocated in the intervening levels of the hierarchy. - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param addr_beat sub-block address (which beat) - * @param addr_byte sub-block address (which byte) - * @param operand_size {byte, half, word, double} from [[uncore.MemoryOpConstants]] - * @param alloc hint whether the block should be allocated in intervening caches - */ -object Get { - def apply( - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt, - alloc: Bool = Bool(true)) - (implicit p: Parameters): Acquire = { - BuiltInAcquireBuilder( - a_type = Acquire.getType, - client_xact_id = client_xact_id, - addr_block = addr_block, - addr_beat = addr_beat, - operand_size = Acquire.fullOperandSize, - opcode = M_XRD, - alloc = alloc) - } - def apply( - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt, - addr_byte: UInt, - operand_size: UInt, - alloc: Bool) - (implicit p: Parameters): Acquire = { - BuiltInAcquireBuilder( - a_type = Acquire.getType, - client_xact_id = client_xact_id, - addr_block = addr_block, - addr_beat = addr_beat, - addr_byte = addr_byte, - operand_size = operand_size, - opcode = M_XRD, - alloc = alloc) - } -} - -/** Get a whole cache block of data from the outer memory hierarchy - * - * The client can hint whether the block should be allocated in the - * intervening levels of the hierarchy. - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param alloc hint whether the block should be allocated in intervening caches - */ -object GetBlock { - def apply( - client_xact_id: UInt = UInt(0), - addr_block: UInt, - alloc: Bool = Bool(true)) - (implicit p: Parameters): Acquire = { - BuiltInAcquireBuilder( - a_type = Acquire.getBlockType, - client_xact_id = client_xact_id, - addr_block = addr_block, - operand_size = Acquire.fullOperandSize, - opcode = M_XRD, - alloc = alloc) - } -} - -/** Prefetch a cache block into the next-outermost level of the memory hierarchy - * with read permissions. - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - */ -object GetPrefetch { - def apply( - client_xact_id: UInt, - addr_block: UInt) - (implicit p: Parameters): Acquire = { - BuiltInAcquireBuilder( - a_type = Acquire.getPrefetchType, - client_xact_id = client_xact_id, - addr_block = addr_block) - } -} - -/** Put a single beat of data into the outer memory hierarchy - * - * The block will be allocated in the next-outermost level of the hierarchy. - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param addr_beat sub-block address (which beat) - * @param data data being refilled to the original requestor - * @param wmask per-byte write mask for this beat - * @param alloc hint whether the block should be allocated in intervening caches - */ -object Put { - def apply( - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt, - data: UInt, - wmask: Option[UInt]= None, - alloc: Bool = Bool(true)) - (implicit p: Parameters): Acquire = { - BuiltInAcquireBuilder( - a_type = Acquire.putType, - addr_block = addr_block, - addr_beat = addr_beat, - client_xact_id = client_xact_id, - data = data, - wmask = wmask.getOrElse(Acquire.fullWriteMask), - alloc = alloc) - } -} - -/** Put a whole cache block of data into the outer memory hierarchy - * - * If the write mask is not full, the block will be allocated in the - * next-outermost level of the hierarchy. If the write mask is full, the - * client can hint whether the block should be allocated or not. - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param addr_beat sub-block address (which beat of several) - * @param data data being refilled to the original requestor - * @param wmask per-byte write mask for this beat - * @param alloc hint whether the block should be allocated in intervening caches - */ -object PutBlock { - def apply( - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt, - data: UInt, - wmask: Option[UInt] = None, - alloc: Bool = Bool(true)) - (implicit p: Parameters): Acquire = { - BuiltInAcquireBuilder( - a_type = Acquire.putBlockType, - client_xact_id = client_xact_id, - addr_block = addr_block, - addr_beat = addr_beat, - data = data, - wmask = wmask.getOrElse(Acquire.fullWriteMask), - alloc = alloc) - } -} - -/** Prefetch a cache block into the next-outermost level of the memory hierarchy - * with write permissions. - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - */ -object PutPrefetch { - def apply( - client_xact_id: UInt, - addr_block: UInt) - (implicit p: Parameters): Acquire = { - BuiltInAcquireBuilder( - a_type = Acquire.putPrefetchType, - client_xact_id = client_xact_id, - addr_block = addr_block) - } -} - -/** Perform an atomic memory operation in the next-outermost level of the memory hierarchy - * - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param addr_beat sub-block address (within which beat) - * @param addr_byte sub-block address (which byte) - * @param atomic_opcode {swap, add, xor, and, min, max, minu, maxu} from [[uncore.MemoryOpConstants]] - * @param operand_size {byte, half, word, double} from [[uncore.MemoryOpConstants]] - * @param data source operand data - */ -object PutAtomic { - def apply( - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt, - addr_byte: UInt, - atomic_opcode: UInt, - operand_size: UInt, - data: UInt) - (implicit p: Parameters): Acquire = { - BuiltInAcquireBuilder( - a_type = Acquire.putAtomicType, - client_xact_id = client_xact_id, - addr_block = addr_block, - addr_beat = addr_beat, - data = data, - addr_byte = addr_byte, - operand_size = operand_size, - opcode = atomic_opcode) - } -} - -/** The Probe channel is used to force clients to release data or cede permissions - * on a cache block. Clients respond to Probes with [[uncore.Release]] messages. - * The available types of Probes are customized by a particular - * [[uncore.CoherencePolicy]]. - */ -class Probe(implicit p: Parameters) extends ManagerToClientChannel - with HasCacheBlockAddress - with HasProbeType - -/** [[uncore.Probe]] with an extra field stating its destination id */ -class ProbeToDst(implicit p: Parameters) extends Probe()(p) with HasClientId - -/** Contains factories for [[uncore.Probe]] and [[uncore.ProbeToDst]] - * - * In general you should avoid using these factories directly and use - * [[uncore.ManagerMetadata.makeProbe(UInt,Acquire)* makeProbe]] instead. - * - * @param dst id of client to which probe should be sent - * @param p_type custom probe type - * @param addr_block address of the cache block - */ -object Probe { - def apply(p_type: UInt, addr_block: UInt)(implicit p: Parameters): Probe = { - val prb = Wire(new Probe) - prb.p_type := p_type - prb.addr_block := addr_block - prb - } - def apply(dst: UInt, p_type: UInt, addr_block: UInt)(implicit p: Parameters): ProbeToDst = { - val prb = Wire(new ProbeToDst) - prb.client_id := dst - prb.p_type := p_type - prb.addr_block := addr_block - prb - } -} - -/** The Release channel is used to release data or permission back to the manager - * in response to [[uncore.Probe]] messages. It can also be used to voluntarily - * write back data, for example in the event that dirty data must be evicted on - * a cache miss. The available types of Release messages are always customized by - * a particular [[uncore.CoherencePolicy]]. Releases may contain data or may be - * simple acknowledgements. Voluntary Releases are acknowledged with [[uncore.Grant Grants]]. - */ -class ReleaseMetadata(implicit p: Parameters) extends ClientToManagerChannel - with HasTileLinkBeatId - with HasCacheBlockAddress - with HasClientTransactionId - with HasReleaseType { - def full_addr(dummy: Int = 0) = Cat(this.addr_block, this.addr_beat, UInt(0, width = tlByteAddrBits)) -} - -/** [[uncore.ReleaseMetadata]] with an extra field containing the data beat */ -class Release(implicit p: Parameters) extends ReleaseMetadata - with HasTileLinkData - -/** [[uncore.ReleaseMetadata]] with an extra field containing the entire cache block */ -class BufferedRelease(implicit p: Parameters) extends ReleaseMetadata - with HasTileLinkBlock - -/** [[uncore.Release]] with an extra field stating its source id */ -class ReleaseFromSrc(implicit p: Parameters) extends Release - with HasClientId - -/** [[uncore.BufferedRelease]] with an extra field stating its source id */ -class BufferedReleaseFromSrc(implicit p: Parameters) extends BufferedRelease - with HasClientId - -/** Contains a [[uncore.Release]] factory - * - * In general you should avoid using this factory directly and use - * [[uncore.ClientMetadata.makeRelease]] instead. - * - * @param voluntary is this a voluntary writeback - * @param r_type type enum defined by coherence protocol - * @param client_xact_id client's transaction id - * @param addr_block address of the cache block - * @param addr_beat beat id of the data - * @param data data being written back - */ -object Release { - def apply( - voluntary: Bool, - r_type: UInt, - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt, - data: UInt) - (implicit p: Parameters): Release = { - val rel = Wire(new Release) - rel.r_type := r_type - rel.client_xact_id := client_xact_id - rel.addr_block := addr_block - rel.addr_beat := addr_beat - rel.data := data - rel.voluntary := voluntary - rel - } - - def apply( - src: UInt, - voluntary: Bool, - r_type: UInt, - client_xact_id: UInt, - addr_block: UInt, - addr_beat: UInt = UInt(0), - data: UInt = UInt(0)) - (implicit p: Parameters): ReleaseFromSrc = { - val rel = Wire(new ReleaseFromSrc) - rel.client_id := src - rel.voluntary := voluntary - rel.r_type := r_type - rel.client_xact_id := client_xact_id - rel.addr_block := addr_block - rel.addr_beat := addr_beat - rel.data := data - rel - } -} - -/** The Grant channel is used to refill data or grant permissions requested of the - * manager agent via an [[uncore.Acquire]] message. It is also used to acknowledge - * the receipt of voluntary writeback from clients in the form of [[uncore.Release]] - * messages. There are built-in Grant messages used for Gets and Puts, and - * coherence policies may also define custom Grant types. Grants may contain data - * or may be simple acknowledgements. Grants are responded to with [[uncore.Finish]]. - */ -class GrantMetadata(implicit p: Parameters) extends ManagerToClientChannel - with HasTileLinkBeatId - with HasClientTransactionId - with HasManagerTransactionId - with HasGrantType { - def makeFinish(dummy: Int = 0): Finish = { - val f = Wire(new Finish) - f.manager_xact_id := this.manager_xact_id - f - } -} - -/** [[uncore.GrantMetadata]] with an extra field containing a single beat of data */ -class Grant(implicit p: Parameters) extends GrantMetadata - with HasTileLinkData - -/** [[uncore.Grant]] with an extra field stating its destination */ -class GrantToDst(implicit p: Parameters) extends Grant - with HasClientId - -/** [[uncore.Grant]] with an extra field stating its destination */ -class GrantFromSrc(implicit p: Parameters) extends Grant - with HasManagerId { - override def makeFinish(dummy: Int = 0): FinishToDst = { - val f = Wire(new FinishToDst) - f.manager_xact_id := this.manager_xact_id - f.manager_id := this.manager_id - f - } -} - -/** [[uncore.GrantMetadata]] with an extra field containing an entire cache block */ -class BufferedGrant(implicit p: Parameters) extends GrantMetadata - with HasTileLinkBlock - -/** [[uncore.BufferedGrant]] with an extra field stating its destination */ -class BufferedGrantToDst(implicit p: Parameters) extends BufferedGrant - with HasClientId - -/** Contains definitions of the the built-in grant types and factories - * for [[uncore.Grant]] and [[uncore.GrantToDst]] - * - * In general you should avoid using these factories directly and use - * [[uncore.ManagerMetadata.makeGrant(uncore.AcquireFromSrc* makeGrant]] instead. - * - * @param dst id of client to which grant should be sent - * @param is_builtin_type built-in or custom type message? - * @param g_type built-in type enum or custom type enum - * @param client_xact_id client's transaction id - * @param manager_xact_id manager's transaction id - * @param addr_beat beat id of the data - * @param data data being refilled to the original requestor - */ -object Grant { - val nBuiltInTypes = 5 - def voluntaryAckType = UInt("b000") // For acking Releases - def prefetchAckType = UInt("b001") // For acking any kind of Prefetch - def putAckType = UInt("b011") // For acking any kind of non-prfetch Put - def getDataBeatType = UInt("b100") // Supplying a single beat of Get - def getDataBlockType = UInt("b101") // Supplying all beats of a GetBlock - def typesWithData = Vec(getDataBlockType, getDataBeatType) - def typesWithMultibeatData= Vec(getDataBlockType) - - def apply( - is_builtin_type: Bool, - g_type: UInt, - client_xact_id: UInt, - manager_xact_id: UInt, - addr_beat: UInt, - data: UInt) - (implicit p: Parameters): Grant = { - val gnt = Wire(new Grant) - gnt.is_builtin_type := is_builtin_type - gnt.g_type := g_type - gnt.client_xact_id := client_xact_id - gnt.manager_xact_id := manager_xact_id - gnt.addr_beat := addr_beat - gnt.data := data - gnt - } - - def apply( - dst: UInt, - is_builtin_type: Bool, - g_type: UInt, - client_xact_id: UInt, - manager_xact_id: UInt, - addr_beat: UInt = UInt(0), - data: UInt = UInt(0)) - (implicit p: Parameters): GrantToDst = { - val gnt = Wire(new GrantToDst) - gnt.client_id := dst - gnt.is_builtin_type := is_builtin_type - gnt.g_type := g_type - gnt.client_xact_id := client_xact_id - gnt.manager_xact_id := manager_xact_id - gnt.addr_beat := addr_beat - gnt.data := data - gnt - } -} - -/** The Finish channel is used to provide a global ordering of transactions - * in networks that do not guarantee point-to-point ordering of messages. - * A Finsish message is sent as acknowledgement of receipt of a [[uncore.Grant]]. - * When a Finish message is received, a manager knows it is safe to begin - * processing other transactions that touch the same cache block. - */ -class Finish(implicit p: Parameters) extends ClientToManagerChannel()(p) - with HasManagerTransactionId { - def hasData(dummy: Int = 0) = Bool(false) - def hasMultibeatData(dummy: Int = 0) = Bool(false) -} - -/** [[uncore.Finish]] with an extra field stating its destination */ -class FinishToDst(implicit p: Parameters) extends Finish - with HasManagerId - -/** Complete IO definition for incoherent TileLink, including networking headers */ -class UncachedTileLinkIO(implicit p: Parameters) extends TLBundle()(p) { - val acquire = new DecoupledIO(new LogicalNetworkIO(new Acquire)) - val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip - val finish = new DecoupledIO(new LogicalNetworkIO(new Finish)) -} - -/** Complete IO definition for coherent TileLink, including networking headers */ -class TileLinkIO(implicit p: Parameters) extends UncachedTileLinkIO()(p) { - val probe = new DecoupledIO(new LogicalNetworkIO(new Probe)).flip - val release = new DecoupledIO(new LogicalNetworkIO(new Release)) -} - -/** This version of UncachedTileLinkIO does not contain network headers. - * It is intended for use within client agents. - * - * Headers are provided in the top-level that instantiates the clients and network, - * probably using a [[uncore.ClientTileLinkNetworkPort]] module. - * By eliding the header subbundles within the clients we can enable - * hierarchical P-and-R while minimizing unconnected port errors in GDS. - * - * Secondly, this version of the interface elides [[uncore.Finish]] messages, with the - * assumption that a [[uncore.FinishUnit]] has been coupled to the TileLinkIO port - * to deal with acking received [[uncore.Grant Grants]]. - */ -class ClientUncachedTileLinkIO(implicit p: Parameters) extends TLBundle()(p) { - val acquire = new DecoupledIO(new Acquire) - val grant = new DecoupledIO(new Grant).flip -} - -/** This version of TileLinkIO does not contain network headers. - * It is intended for use within client agents. - */ -class ClientTileLinkIO(implicit p: Parameters) extends TLBundle()(p) { - val acquire = new DecoupledIO(new Acquire) - val probe = new DecoupledIO(new Probe).flip - val release = new DecoupledIO(new Release) - val grant = new DecoupledIO(new GrantFromSrc).flip - val finish = new DecoupledIO(new FinishToDst) -} - -/** This version of TileLinkIO does not contain network headers, but - * every channel does include an extra client_id subbundle. - * It is intended for use within Management agents. - * - * Managers need to track where [[uncore.Acquire]] and [[uncore.Release]] messages - * originated so that they can send a [[uncore.Grant]] to the right place. - * Similarly they must be able to issues Probes to particular clients. - * However, we'd still prefer to have [[uncore.ManagerTileLinkNetworkPort]] fill in - * the header.src to enable hierarchical p-and-r of the managers. Additionally, - * coherent clients might be mapped to random network port ids, and we'll leave it to the - * [[uncore.ManagerTileLinkNetworkPort]] to apply the correct mapping. Managers do need to - * see Finished so they know when to allow new transactions on a cache - * block to proceed. - */ -class ManagerTileLinkIO(implicit p: Parameters) extends TLBundle()(p) { - val acquire = new DecoupledIO(new AcquireFromSrc).flip - val grant = new DecoupledIO(new GrantToDst) - val finish = new DecoupledIO(new Finish).flip - val probe = new DecoupledIO(new ProbeToDst) - val release = new DecoupledIO(new ReleaseFromSrc).flip -} diff --git a/src/main/scala/uncore/tilelink/Drivers.scala b/src/main/scala/uncore/tilelink/Drivers.scala deleted file mode 100644 index ad8fc73d..00000000 --- a/src/main/scala/uncore/tilelink/Drivers.scala +++ /dev/null @@ -1,425 +0,0 @@ -// See LICENSE.SiFive for license details. -// See LICENSE.Berkeley for license details. - -package uncore.tilelink - -import Chisel._ -import junctions._ -import uncore.constants._ -import uncore.util._ -import util._ -import config._ - -abstract class Driver(implicit p: Parameters) extends TLModule()(p) { - val io = new Bundle { - val mem = new ClientUncachedTileLinkIO - val start = Bool(INPUT) - val finished = Bool(OUTPUT) - } -} - -/** - * Tests that single-beat Gets of decreasing size return subsets of the - * data returned by larger Gets - */ -class GetMultiWidthDriver(implicit p: Parameters) extends Driver()(p) { - val s_start :: s_send :: s_recv :: s_done :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_start) - - val w = 64 - val initialSize = UInt(log2Ceil(w/8)) - val size = Reg(UInt(width = log2Ceil(log2Ceil(w/8)+1))) - val ref = Reg(UInt(width = w)) - val bytemask = (UInt(1) << (UInt(1) << size)) - UInt(1) - val bitmask = FillInterleaved(8, bytemask) - - io.mem.acquire.valid := (state === s_send) - io.mem.acquire.bits := Get( - client_xact_id = UInt(0), - addr_block = UInt(0), - addr_beat = UInt(0), - addr_byte = UInt(0), - operand_size = size, - alloc = Bool(false)) - io.mem.grant.ready := (state === s_recv) - - when (state === s_start && io.start) { - size := initialSize - state := s_send - } - - when (io.mem.acquire.fire()) { state := s_recv } - when (io.mem.grant.fire()) { - when (size === initialSize) { ref := io.mem.grant.bits.data } - size := size - UInt(1) - state := Mux(size === UInt(0), s_done, s_send) - } - - io.finished := state === s_done - - assert(!io.mem.grant.valid || size === initialSize || - (io.mem.grant.bits.data & bitmask) === (ref & bitmask), - "GetMultiWidth: smaller get does not match larger get") -} - -/** - * Tests that single-beat Gets across a range of memory return - * the expected data. - * @param expected The values of the data expected to be read. - * Each element is the data for one beat. - */ -class GetSweepDriver(expected: Seq[BigInt]) - (implicit p: Parameters) extends Driver()(p) { - - val s_start :: s_send :: s_recv :: s_done :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_start) - - val nReqs = expected.size - val (req_cnt, req_done) = Counter(io.mem.grant.fire(), nReqs) - - when (state === s_start && io.start) { state := s_send } - when (io.mem.acquire.fire()) { state := s_recv } - when (io.mem.grant.fire()) { state := s_send } - when (req_done) { state := s_done } - - val (addr_block, addr_beat) = if (nReqs > tlDataBeats) { - (req_cnt(log2Up(nReqs) - 1, tlBeatAddrBits), - req_cnt(tlBeatAddrBits - 1, 0)) - } else { - (UInt(0), req_cnt) - } - - val exp_data = Vec(expected.map(e => UInt(e, tlDataBits))) - - io.mem.acquire.valid := (state === s_send) - io.mem.acquire.bits := Get( - client_xact_id = UInt(0), - addr_block = addr_block, - addr_beat = addr_beat) - io.mem.grant.ready := (state === s_recv) - io.finished := state === s_done - - assert(!io.mem.grant.valid || io.mem.grant.bits.data === exp_data(req_cnt), - "GetSweep: data does not match expected") -} - -/** - * Tests that multi-beat GetBlocks across a range of memory return - * the expected data. - * @param expected The values of the data expected to be read. - * Each element is the data for one beat. - */ -class GetBlockSweepDriver(expected: Seq[BigInt]) - (implicit p: Parameters) extends Driver()(p) { - val s_start :: s_send :: s_recv :: s_done :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_start) - - val nReqs = ((expected.size - 1) / tlDataBeats + 1) * tlDataBeats - val (req_cnt, req_done) = Counter(io.mem.grant.fire(), nReqs) - val (addr_beat, beats_done) = Counter(io.mem.grant.fire(), tlDataBeats) - - val tlBlockOffset = tlByteAddrBits + tlBeatAddrBits - val addr_block = - if (nReqs > tlDataBeats) req_cnt(log2Up(nReqs) - 1, tlBlockOffset) - else UInt(0) - - io.mem.acquire.valid := (state === s_send) - io.mem.acquire.bits := GetBlock( - client_xact_id = UInt(0), - addr_block = addr_block) - io.mem.grant.ready := (state === s_recv) - io.finished := state === s_done - - when (state === s_start && io.start) { state := s_send } - when (io.mem.acquire.fire()) { state := s_recv } - when (beats_done) { state := s_send } - when (req_done) { state := s_done } - - val exp_data = Vec(expected.map(e => UInt(e, tlDataBits))) - - assert(!io.mem.grant.valid || req_cnt >= UInt(expected.size) || - io.mem.grant.bits.data === exp_data(req_cnt), - "GetBlockSweep: data does not match expected") -} - -/** - * Tests that single-beat Puts across a range of memory persists correctly. - * @param n the number of beats to put - */ -class PutSweepDriver(val n: Int)(implicit p: Parameters) extends Driver()(p) { - val (s_idle :: s_put_req :: s_put_resp :: - s_get_req :: s_get_resp :: s_done :: Nil) = Enum(Bits(), 6) - val state = Reg(init = s_idle) - - val (put_cnt, put_done) = Counter(state === s_put_resp && io.mem.grant.valid, n) - val (get_cnt, get_done) = Counter(state === s_get_resp && io.mem.grant.valid, n) - - val (put_block, put_beat) = if (n > tlDataBeats) { - (put_cnt(log2Up(n) - 1, tlBeatAddrBits), - put_cnt(tlBeatAddrBits - 1, 0)) - } else { - (UInt(0), put_cnt) - } - val (get_block, get_beat) = if (n > tlDataBeats) { - (get_cnt(log2Up(n) - 1, tlBeatAddrBits), - get_cnt(tlBeatAddrBits - 1, 0)) - } else { - (UInt(0), get_cnt) - } - - val dataRep = (tlDataBits - 1) / log2Up(n) + 1 - val put_data = Fill(dataRep, put_cnt)(tlDataBits - 1, 0) - val get_data = Fill(dataRep, get_cnt)(tlDataBits - 1, 0) - - io.mem.acquire.valid := state.isOneOf(s_put_req, s_get_req) - io.mem.acquire.bits := Mux(state === s_put_req, - Put( - client_xact_id = UInt(0), - addr_block = put_block, - addr_beat = put_beat, - data = put_data), - Get( - client_xact_id = UInt(0), - addr_block = get_block, - addr_beat = get_beat)) - io.mem.grant.ready := state.isOneOf(s_put_resp, s_get_resp) - - when (state === s_idle && io.start) { state := s_put_req } - when (state === s_put_req && io.mem.acquire.ready) { state := s_put_resp } - when (state === s_put_resp && io.mem.grant.valid) { - state := Mux(put_done, s_get_req, s_put_req) - } - when (state === s_get_req && io.mem.acquire.ready) { state := s_get_resp } - when (state === s_get_resp && io.mem.grant.valid) { - state := Mux(get_done, s_done, s_get_req) - } - - io.finished := (state === s_done) - - assert(!io.mem.grant.valid || !io.mem.grant.bits.hasData() || - io.mem.grant.bits.data === get_data, - "PutSweepDriver: data does not match") -} - -/** - * Tests that write-masked single-beat puts work correctly by putting - * data with steadily smaller write-masks to the same beat. - * @param minBytes the smallest number of bytes that can be in the writemask - */ -class PutMaskDriver(minBytes: Int = 1)(implicit p: Parameters) extends Driver()(p) { - val (s_idle :: s_put_req :: s_put_resp :: - s_get_req :: s_get_resp :: s_done :: Nil) = Enum(Bits(), 6) - val state = Reg(init = s_idle) - val nbytes = Reg(UInt(width = log2Up(tlWriteMaskBits) + 1)) - val wmask = (UInt(1) << nbytes) - UInt(1) - val wdata = Fill(tlDataBits / 8, Wire(UInt(width = 8), init = nbytes)) - // TL data bytes down to minBytes logarithmically by 2 - val expected = (log2Ceil(tlDataBits / 8) to log2Ceil(minBytes) by -1) - .map(1 << _).foldLeft(UInt(0, tlDataBits)) { - // Change the lower nbytes of the value - (value, nbytes) => { - val mask = UInt((BigInt(1) << (nbytes * 8)) - BigInt(1), tlDataBits) - val wval = Fill(tlDataBits / 8, UInt(nbytes, 8)) - (value & ~mask) | (wval & mask) - } - } - - when (state === s_idle && io.start) { - state := s_put_req - nbytes := UInt(8) - } - when (state === s_put_req && io.mem.acquire.ready) { - state := s_put_resp - } - when (state === s_put_resp && io.mem.grant.valid) { - nbytes := nbytes >> UInt(1) - state := Mux(nbytes === UInt(minBytes), s_get_req, s_put_req) - } - when (state === s_get_req && io.mem.acquire.ready) { - state := s_get_resp - } - when (state === s_get_resp && io.mem.grant.valid) { - state := s_done - } - - io.finished := (state === s_done) - io.mem.acquire.valid := state.isOneOf(s_put_req, s_get_req) - io.mem.acquire.bits := Mux(state === s_put_req, - Put( - client_xact_id = UInt(0), - addr_block = UInt(0), - addr_beat = UInt(0), - data = wdata, - wmask = Some(wmask)), - Get( - client_xact_id = UInt(0), - addr_block = UInt(0), - addr_beat = UInt(0))) - io.mem.grant.ready := state.isOneOf(s_put_resp, s_get_resp) - - assert(!io.mem.grant.valid || state =/= s_get_resp || - io.mem.grant.bits.data === expected, - "PutMask: data does not match expected") -} - -class PutBlockSweepDriver(val n: Int)(implicit p: Parameters) - extends Driver()(p) { - val (s_idle :: s_put_req :: s_put_resp :: - s_get_req :: s_get_resp :: s_done :: Nil) = Enum(Bits(), 6) - val state = Reg(init = s_idle) - - val (put_beat, put_beat_done) = Counter( - state === s_put_req && io.mem.acquire.ready, tlDataBeats) - val (put_cnt, put_done) = Counter( - state === s_put_resp && io.mem.grant.valid, n) - val (get_beat, get_beat_done) = Counter( - state === s_get_resp && io.mem.grant.valid, tlDataBeats) - val (get_cnt, get_done) = Counter(get_beat_done, n) - - val dataRep = (tlDataBits - 1) / (log2Up(n) + tlBeatAddrBits) + 1 - val put_data = Fill(dataRep, Cat(put_cnt, put_beat))(tlDataBits - 1, 0) - val get_data = Fill(dataRep, Cat(get_cnt, get_beat))(tlDataBits - 1, 0) - - when (state === s_idle && io.start) { state := s_put_req } - when (put_beat_done) { state := s_put_resp } - when (state === s_put_resp && io.mem.grant.valid) { - state := Mux(put_done, s_get_req, s_put_req) - } - when (state === s_get_req && io.mem.acquire.ready) { state := s_get_resp } - when (get_beat_done) { state := Mux(get_done, s_done, s_get_req) } - - val put_acquire = PutBlock( - client_xact_id = UInt(0), - addr_block = put_cnt, - addr_beat = put_beat, - data = put_data) - - val get_acquire = GetBlock( - client_xact_id = UInt(0), - addr_block = get_cnt) - - io.finished := (state === s_done) - io.mem.acquire.valid := state.isOneOf(s_put_req, s_get_req) - io.mem.acquire.bits := Mux(state === s_put_req, put_acquire, get_acquire) - io.mem.grant.ready := state.isOneOf(s_put_resp, s_get_resp) - - assert(!io.mem.grant.valid || state =/= s_get_resp || - io.mem.grant.bits.data === get_data, - "PutBlockSweep: data does not match expected") -} - -class PutAtomicDriver(implicit p: Parameters) extends Driver()(p) { - val s_idle :: s_put :: s_atomic :: s_get :: s_done :: Nil = Enum(Bits(), 5) - val state = Reg(init = s_idle) - val sending = Reg(init = Bool(false)) - - val put_acquire = Put( - client_xact_id = UInt(0), - addr_block = UInt(0), - addr_beat = UInt(0), - // Put 15 in bytes 7:4 - data = UInt(15L << 32), - wmask = Some(UInt(0xf0))) - - val amo_acquire = PutAtomic( - client_xact_id = UInt(0), - addr_block = UInt(0), - addr_beat = UInt(0), - addr_byte = UInt(4), - atomic_opcode = M_XA_ADD, - operand_size = UInt(log2Ceil(32 / 8)), - data = UInt(3L << 32)) - - val get_acquire = Get( - client_xact_id = UInt(0), - addr_block = UInt(0), - addr_beat = UInt(0)) - - io.finished := (state === s_done) - io.mem.acquire.valid := sending - io.mem.acquire.bits := MuxLookup(state, get_acquire, Seq( - s_put -> put_acquire, - s_atomic -> amo_acquire, - s_get -> get_acquire)) - io.mem.grant.ready := !sending - - when (io.mem.acquire.fire()) { sending := Bool(false) } - - when (state === s_idle && io.start) { - state := s_put - sending := Bool(true) - } - when (io.mem.grant.fire()) { - when (state === s_put) { sending := Bool(true); state := s_atomic } - when (state === s_atomic) { sending := Bool(true); state := s_get } - when (state === s_get) { state := s_done } - } - - assert(!io.mem.grant.valid || state =/= s_get || - io.mem.grant.bits.data(63, 32) === UInt(18)) -} - -class PrefetchDriver(implicit p: Parameters) extends Driver()(p) { - val s_idle :: s_put_pf :: s_get_pf :: s_done :: Nil = Enum(Bits(), 4) - val state = Reg(init = s_idle) - val sending = Reg(init = Bool(false)) - - when (state === s_idle) { - sending := Bool(true) - state := s_put_pf - } - - when (io.mem.acquire.fire()) { sending := Bool(false) } - when (io.mem.grant.fire()) { - when (state === s_put_pf) { sending := Bool(true); state := s_get_pf } - when (state === s_get_pf) { state := s_done } - } - - io.finished := (state === s_done) - io.mem.acquire.valid := sending - io.mem.acquire.bits := Mux(state === s_put_pf, - PutPrefetch( - client_xact_id = UInt(0), - addr_block = UInt(0)), - GetPrefetch( - client_xact_id = UInt(0), - addr_block = UInt(0))) - io.mem.grant.ready := !sending -} - -class DriverSet(driverGen: Parameters => Seq[Driver])(implicit p: Parameters) - extends Driver()(p) { - val s_start :: s_run :: s_done :: Nil = Enum(Bits(), 3) - val state = Reg(init = s_start) - - val drivers = driverGen(p) - val idx = Reg(init = UInt(0, log2Up(drivers.size))) - val finished = Wire(init = Bool(false)) - - when (state === s_start && io.start) { state := s_run } - when (state === s_run && finished) { - when (idx === UInt(drivers.size - 1)) { state := s_done } - idx := idx + UInt(1) - } - - io.finished := state === s_done - - io.mem.acquire.valid := Bool(false) - io.mem.grant.ready := Bool(false) - - drivers.zipWithIndex.foreach { case (driv, i) => - val me = idx === UInt(i) - - driv.io.start := me && state === s_run - driv.io.mem.acquire.ready := io.mem.acquire.ready && me - driv.io.mem.grant.valid := io.mem.grant.valid && me - driv.io.mem.grant.bits := io.mem.grant.bits - - when (me) { - io.mem.acquire.valid := driv.io.mem.acquire.valid - io.mem.acquire.bits := driv.io.mem.acquire.bits - io.mem.grant.ready := driv.io.mem.grant.ready - finished := driv.io.finished - } - } -} diff --git a/src/main/scala/uncore/tilelink/Interconnect.scala b/src/main/scala/uncore/tilelink/Interconnect.scala deleted file mode 100644 index 10a0ec80..00000000 --- a/src/main/scala/uncore/tilelink/Interconnect.scala +++ /dev/null @@ -1,316 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.tilelink - -import Chisel._ -import junctions._ -import scala.collection.mutable.ArraySeq -import uncore.util._ -import config._ - - -/** PortedTileLinkNetworks combine a TileLink protocol with a particular physical - * network implementation. - * - * Specifically, they provide mappings between ClientTileLinkIO/ - * ManagerTileLinkIO channels and LogicalNetwork ports (i.e. generic - * TileLinkIO with networking headers). Channels coming into the network have - * appropriate networking headers appended and outgoing channels have their - * headers stripped. - * - * @constructor base class constructor for Ported TileLink NoC - * @param addrToManagerId a mapping from a physical address to the network - * id of a coherence manager - * @param sharerToClientId a mapping from the id of a particular coherent - * client (as determined by e.g. the directory) and the network id - * of that client - * @param clientDepths the depths of the queue that should be used to buffer - * each channel on the client side of the network - * @param managerDepths the depths of the queue that should be used to buffer - * each channel on the manager side of the network - */ -abstract class PortedTileLinkNetwork( - addrToManagerId: UInt => UInt, - sharerToClientId: UInt => UInt, - clientDepths: TileLinkDepths, - managerDepths: TileLinkDepths) - (implicit p: Parameters) extends TLModule()(p) { - val nClients = tlNClients - val nManagers = tlNManagers - val io = new Bundle { - val clients_cached = Vec(tlNCachingClients, new ClientTileLinkIO).flip - val clients_uncached = Vec(tlNCachelessClients, new ClientUncachedTileLinkIO).flip - val managers = Vec(nManagers, new ManagerTileLinkIO).flip - } - - val clients = (io.clients_cached ++ io.clients_uncached).zipWithIndex.map { - case (io, idx) => { - val qs = Module(new TileLinkEnqueuer(clientDepths)) - io match { - case c: ClientTileLinkIO => { - val port = Module(new ClientTileLinkNetworkPort(idx, addrToManagerId)) - port.io.client <> c - qs.io.client <> port.io.network - qs.io.manager - } - case u: ClientUncachedTileLinkIO => { - val port = Module(new ClientUncachedTileLinkNetworkPort(idx, addrToManagerId)) - port.io.client <> u - qs.io.client <> port.io.network - qs.io.manager - } - } - } - } - - val managers = io.managers.zipWithIndex.map { - case (m, i) => { - val port = Module(new ManagerTileLinkNetworkPort(i, sharerToClientId)) - val qs = Module(new TileLinkEnqueuer(managerDepths)) - port.io.manager <> m - port.io.network <> qs.io.manager - qs.io.client - } - } -} - -/** A simple arbiter for each channel that also deals with header-based routing. - * Assumes a single manager agent. */ -class PortedTileLinkArbiter( - sharerToClientId: UInt => UInt = (u: UInt) => u, - clientDepths: TileLinkDepths = TileLinkDepths(0,0,0,0,0), - managerDepths: TileLinkDepths = TileLinkDepths(0,0,0,0,0)) - (implicit p: Parameters) - extends PortedTileLinkNetwork(u => UInt(0), sharerToClientId, clientDepths, managerDepths)(p) - with TileLinkArbiterLike - with PassesId { - val arbN = nClients - require(nManagers == 1) - if(arbN > 1) { - hookupClientSource(clients.map(_.acquire), managers.head.acquire) - hookupClientSource(clients.map(_.release), managers.head.release) - hookupFinish(clients.map(_.finish), managers.head.finish) - hookupManagerSourceWithHeader(clients.map(_.probe), managers.head.probe) - hookupManagerSourceWithHeader(clients.map(_.grant), managers.head.grant) - } else { - managers.head <> clients.head - } -} - -/** Provides a separate physical crossbar for each channel. Assumes multiple manager - * agents. Managers are assigned to higher physical network port ids than - * clients, and translations between logical network id and physical crossbar - * port id are done automatically. - */ -class PortedTileLinkCrossbar( - addrToManagerId: UInt => UInt = u => UInt(0), - sharerToClientId: UInt => UInt = u => u, - clientDepths: TileLinkDepths = TileLinkDepths(0,0,0,0,0), - managerDepths: TileLinkDepths = TileLinkDepths(0,0,0,0,0)) - (implicit p: Parameters) - extends PortedTileLinkNetwork(addrToManagerId, sharerToClientId, clientDepths, managerDepths)(p) { - val n = p(LNEndpoints) - val phyHdrWidth = log2Up(n) - val count = tlDataBeats - // Actually instantiate the particular networks required for TileLink - val acqNet = Module(new BasicBus(CrossbarConfig(n, new Acquire, count, Some((a: PhysicalNetworkIO[Acquire]) => a.payload.hasMultibeatData())))) - val relNet = Module(new BasicBus(CrossbarConfig(n, new Release, count, Some((r: PhysicalNetworkIO[Release]) => r.payload.hasMultibeatData())))) - val prbNet = Module(new BasicBus(CrossbarConfig(n, new Probe))) - val gntNet = Module(new BasicBus(CrossbarConfig(n, new Grant, count, Some((g: PhysicalNetworkIO[Grant]) => g.payload.hasMultibeatData())))) - val ackNet = Module(new BasicBus(CrossbarConfig(n, new Finish))) - - // Aliases for the various network IO bundle types - type PNIO[T <: Data] = DecoupledIO[PhysicalNetworkIO[T]] - type LNIO[T <: Data] = DecoupledIO[LogicalNetworkIO[T]] - type FromCrossbar[T <: Data] = PNIO[T] => LNIO[T] - type ToCrossbar[T <: Data] = LNIO[T] => PNIO[T] - - // Shims for converting between logical network IOs and physical network IOs - def crossbarToManagerShim[T <: Data](in: PNIO[T]): LNIO[T] = { - val out = DefaultFromPhysicalShim(in) - out.bits.header.src := in.bits.header.src - UInt(nManagers) - out - } - def crossbarToClientShim[T <: Data](in: PNIO[T]): LNIO[T] = { - val out = DefaultFromPhysicalShim(in) - out.bits.header.dst := in.bits.header.dst - UInt(nManagers) - out - } - def managerToCrossbarShim[T <: Data](in: LNIO[T]): PNIO[T] = { - val out = DefaultToPhysicalShim(n, in) - out.bits.header.dst := in.bits.header.dst + UInt(nManagers, phyHdrWidth) - out - } - def clientToCrossbarShim[T <: Data](in: LNIO[T]): PNIO[T] = { - val out = DefaultToPhysicalShim(n, in) - out.bits.header.src := in.bits.header.src + UInt(nManagers, phyHdrWidth) - out - } - - // Make an individual connection between virtual and physical ports using - // a particular shim. Also pin the unused Decoupled control signal low. - def doDecoupledInputHookup[T <: Data](phys_in: PNIO[T], phys_out: PNIO[T], log_io: LNIO[T], shim: ToCrossbar[T]) = { - val s = shim(log_io) - phys_in.valid := s.valid - phys_in.bits := s.bits - s.ready := phys_in.ready - phys_out.ready := Bool(false) - } - - def doDecoupledOutputHookup[T <: Data](phys_in: PNIO[T], phys_out: PNIO[T], log_io: LNIO[T], shim: FromCrossbar[T]) = { - val s = shim(phys_out) - log_io.valid := s.valid - log_io.bits := s.bits - s.ready := log_io.ready - phys_in.valid := Bool(false) - } - - //Hookup all instances of a particular subbundle of TileLink - def doDecoupledHookups[T <: Data](physIO: BasicCrossbarIO[T], getLogIO: TileLinkIO => LNIO[T]) = { - physIO.in.head.bits.payload match { - case c: ClientToManagerChannel => { - managers.zipWithIndex.map { case (i, id) => - doDecoupledOutputHookup(physIO.in(id), physIO.out(id), getLogIO(i), crossbarToManagerShim[T]) - } - clients.zipWithIndex.map { case (i, id) => - doDecoupledInputHookup(physIO.in(id+nManagers), physIO.out(id+nManagers), getLogIO(i), clientToCrossbarShim[T]) - } - } - case m: ManagerToClientChannel => { - managers.zipWithIndex.map { case (i, id) => - doDecoupledInputHookup(physIO.in(id), physIO.out(id), getLogIO(i), managerToCrossbarShim[T]) - } - clients.zipWithIndex.map { case (i, id) => - doDecoupledOutputHookup(physIO.in(id+nManagers), physIO.out(id+nManagers), getLogIO(i), crossbarToClientShim[T]) - } - } - } - } - - doDecoupledHookups(acqNet.io, (tl: TileLinkIO) => tl.acquire) - doDecoupledHookups(relNet.io, (tl: TileLinkIO) => tl.release) - doDecoupledHookups(prbNet.io, (tl: TileLinkIO) => tl.probe) - doDecoupledHookups(gntNet.io, (tl: TileLinkIO) => tl.grant) - doDecoupledHookups(ackNet.io, (tl: TileLinkIO) => tl.finish) -} - -class ClientUncachedTileLinkIORouter( - nOuter: Int, routeSel: UInt => UInt)(implicit p: Parameters) - extends TLModule { - - val io = new Bundle { - val in = (new ClientUncachedTileLinkIO).flip - val out = Vec(nOuter, new ClientUncachedTileLinkIO) - } - - val acq_route = routeSel(io.in.acquire.bits.full_addr()) - - io.in.acquire.ready := Bool(false) - - io.out.zipWithIndex.foreach { case (out, i) => - out.acquire.valid := io.in.acquire.valid && acq_route(i) - out.acquire.bits := io.in.acquire.bits - when (acq_route(i)) { io.in.acquire.ready := out.acquire.ready } - } - - val gnt_arb = Module(new LockingRRArbiter( - new Grant, nOuter, tlDataBeats, Some((gnt: Grant) => gnt.hasMultibeatData()))) - gnt_arb.io.in <> io.out.map(_.grant) - io.in.grant <> gnt_arb.io.out - - assert(!io.in.acquire.valid || acq_route.orR, "No valid route") -} - -class TileLinkInterconnectIO(val nInner: Int, val nOuter: Int) - (implicit p: Parameters) extends Bundle { - val in = Vec(nInner, new ClientUncachedTileLinkIO).flip - val out = Vec(nOuter, new ClientUncachedTileLinkIO) -} - -class ClientUncachedTileLinkIOCrossbar( - nInner: Int, nOuter: Int, routeSel: UInt => UInt) - (implicit p: Parameters) extends TLModule { - - val io = new TileLinkInterconnectIO(nInner, nOuter) - - if (nInner == 1) { - val router = Module(new ClientUncachedTileLinkIORouter(nOuter, routeSel)) - router.io.in <> io.in.head - io.out <> router.io.out - } else { - val routers = List.fill(nInner) { - Module(new ClientUncachedTileLinkIORouter(nOuter, routeSel)) } - val arbiters = List.fill(nOuter) { - Module(new ClientUncachedTileLinkIOArbiter(nInner)) } - - for (i <- 0 until nInner) { - routers(i).io.in <> io.in(i) - } - - for (i <- 0 until nOuter) { - arbiters(i).io.in <> routers.map(r => r.io.out(i)) - io.out(i) <> arbiters(i).io.out - } - } -} - -abstract class TileLinkInterconnect(implicit p: Parameters) extends TLModule()(p) { - val nInner: Int - val nOuter: Int - - lazy val io = new TileLinkInterconnectIO(nInner, nOuter) -} - -class TileLinkRecursiveInterconnect(val nInner: Int, addrMap: AddrMap) - (implicit p: Parameters) extends TileLinkInterconnect()(p) { - def port(name: String) = io.out(addrMap.port(name)) - val nOuter = addrMap.numSlaves - val routeSel = (addr: UInt) => - Cat(addrMap.entries.map(e => addrMap(e.name).containsAddress(addr)).reverse) - - val xbar = Module(new ClientUncachedTileLinkIOCrossbar(nInner, addrMap.length, routeSel)) - xbar.io.in <> io.in - - io.out <> addrMap.entries.zip(xbar.io.out).flatMap { - case (entry, xbarOut) => { - entry.region match { - case submap: AddrMap if submap.isEmpty => - xbarOut.acquire.ready := Bool(false) - xbarOut.grant.valid := Bool(false) - None - case submap: AddrMap if !submap.collapse => - val ic = Module(new TileLinkRecursiveInterconnect(1, submap)) - ic.io.in.head <> xbarOut - ic.io.out - case _ => - Some(xbarOut) - } - } - } -} - -class TileLinkMemoryInterconnect( - nBanksPerChannel: Int, nChannels: Int) - (implicit p: Parameters) extends TileLinkInterconnect()(p) { - - val nBanks = nBanksPerChannel * nChannels - val nInner = nBanks - val nOuter = nChannels - - def connectChannel(outer: ClientUncachedTileLinkIO, inner: ClientUncachedTileLinkIO) { - outer <> inner - outer.acquire.bits.addr_block := inner.acquire.bits.addr_block >> UInt(log2Ceil(nChannels)) - } - - for (i <- 0 until nChannels) { - /* Bank assignments to channels are strided so that consecutive banks - * map to different channels. That way, consecutive cache lines also - * map to different channels */ - val banks = (i until nBanks by nChannels).map(j => io.in(j)) - - val channelArb = Module(new ClientUncachedTileLinkIOArbiter(nBanksPerChannel)) - channelArb.io.in <> banks - connectChannel(io.out(i), channelArb.io.out) - } -} diff --git a/src/main/scala/uncore/tilelink/Network.scala b/src/main/scala/uncore/tilelink/Network.scala deleted file mode 100644 index c80c5675..00000000 --- a/src/main/scala/uncore/tilelink/Network.scala +++ /dev/null @@ -1,309 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.tilelink - -import Chisel._ -import uncore.util._ -import config._ - -case object LNEndpoints extends Field[Int] -case object LNHeaderBits extends Field[Int] - -class PhysicalHeader(n: Int) extends Bundle { - val src = UInt(width = log2Up(n)) - val dst = UInt(width = log2Up(n)) -} - -class PhysicalNetworkIO[T <: Data](n: Int, dType: T) extends Bundle { - val header = new PhysicalHeader(n) - val payload = dType.cloneType - override def cloneType = new PhysicalNetworkIO(n,dType).asInstanceOf[this.type] -} - -class BasicCrossbarIO[T <: Data](n: Int, dType: T) extends Bundle { - val in = Vec(n, Decoupled(new PhysicalNetworkIO(n,dType))).flip - val out = Vec(n, Decoupled(new PhysicalNetworkIO(n,dType))) -} - -abstract class PhysicalNetwork extends Module - -case class CrossbarConfig[T <: Data](n: Int, dType: T, count: Int = 1, needsLock: Option[PhysicalNetworkIO[T] => Bool] = None) - -abstract class AbstractCrossbar[T <: Data](conf: CrossbarConfig[T]) extends PhysicalNetwork { - val io = new BasicCrossbarIO(conf.n, conf.dType) -} - -class BasicBus[T <: Data](conf: CrossbarConfig[T]) extends AbstractCrossbar(conf) { - val arb = Module(new LockingRRArbiter(io.in(0).bits, conf.n, conf.count, conf.needsLock)) - arb.io.in <> io.in - - arb.io.out.ready := io.out(arb.io.out.bits.header.dst).ready - for ((out, i) <- io.out zipWithIndex) { - out.valid := arb.io.out.valid && arb.io.out.bits.header.dst === UInt(i) - out.bits := arb.io.out.bits - } -} - -class BasicCrossbar[T <: Data](conf: CrossbarConfig[T]) extends AbstractCrossbar(conf) { - io.in.foreach { _.ready := Bool(false) } - - io.out.zipWithIndex.map{ case (out, i) => { - val rrarb = Module(new LockingRRArbiter(io.in(0).bits, conf.n, conf.count, conf.needsLock)) - (rrarb.io.in, io.in).zipped.map{ case (arb, in) => { - val destined = in.bits.header.dst === UInt(i) - arb.valid := in.valid && destined - arb.bits := in.bits - when (arb.ready && destined) { in.ready := Bool(true) } - }} - out <> rrarb.io.out - }} -} - -abstract class LogicalNetwork extends Module - -class LogicalHeader(implicit p: Parameters) extends util.ParameterizedBundle()(p) { - val src = UInt(width = p(LNHeaderBits)) - val dst = UInt(width = p(LNHeaderBits)) -} - -class LogicalNetworkIO[T <: Data](dType: T)(implicit p: Parameters) extends Bundle { - val header = new LogicalHeader - val payload = dType.cloneType - override def cloneType = new LogicalNetworkIO(dType)(p).asInstanceOf[this.type] -} - -object DecoupledLogicalNetworkIOWrapper { - def apply[T <: Data]( - in: DecoupledIO[T], - src: UInt = UInt(0), - dst: UInt = UInt(0)) - (implicit p: Parameters): DecoupledIO[LogicalNetworkIO[T]] = { - val out = Wire(Decoupled(new LogicalNetworkIO(in.bits))) - out.valid := in.valid - out.bits.payload := in.bits - out.bits.header.dst := dst - out.bits.header.src := src - in.ready := out.ready - out - } -} - -object DecoupledLogicalNetworkIOUnwrapper { - def apply[T <: Data](in: DecoupledIO[LogicalNetworkIO[T]]) - (implicit p: Parameters): DecoupledIO[T] = { - val out = Wire(Decoupled(in.bits.payload)) - out.valid := in.valid - out.bits := in.bits.payload - in.ready := out.ready - out - } -} - -object DefaultFromPhysicalShim { - def apply[T <: Data](in: DecoupledIO[PhysicalNetworkIO[T]]) - (implicit p: Parameters): DecoupledIO[LogicalNetworkIO[T]] = { - val out = Wire(Decoupled(new LogicalNetworkIO(in.bits.payload))) - out.bits.header := in.bits.header - out.bits.payload := in.bits.payload - out.valid := in.valid - in.ready := out.ready - out - } -} - -object DefaultToPhysicalShim { - def apply[T <: Data](n: Int, in: DecoupledIO[LogicalNetworkIO[T]]) - (implicit p: Parameters): DecoupledIO[PhysicalNetworkIO[T]] = { - val out = Wire(Decoupled(new PhysicalNetworkIO(n, in.bits.payload))) - out.bits.header := in.bits.header - out.bits.payload := in.bits.payload - out.valid := in.valid - in.ready := out.ready - out - } -} - -/** A helper module that automatically issues [[uncore.Finish]] messages in repsonse - * to [[uncore.Grant]] that it receives from a manager and forwards to a client - */ -class FinishUnit(srcId: Int = 0, outstanding: Int = 2)(implicit p: Parameters) extends TLModule()(p) - with HasDataBeatCounters { - val io = new Bundle { - val grant = Decoupled(new LogicalNetworkIO(new Grant)).flip - val refill = Decoupled(new Grant) - val finish = Decoupled(new LogicalNetworkIO(new Finish)) - val ready = Bool(OUTPUT) - } - - val g = io.grant.bits.payload - - if(tlNetworkPreservesPointToPointOrdering) { - io.finish.valid := Bool(false) - io.refill.valid := io.grant.valid - io.refill.bits := g - io.grant.ready := io.refill.ready - io.ready := Bool(true) - } else { - // We only want to send Finishes after we have collected all beats of - // a multibeat Grant. But Grants from multiple managers or transactions may - // get interleaved, so we could need a counter for each. - val done = if(tlNetworkDoesNotInterleaveBeats) { - connectIncomingDataBeatCounterWithHeader(io.grant) - } else { - val entries = 1 << tlClientXactIdBits - def getId(g: LogicalNetworkIO[Grant]) = g.payload.client_xact_id - assert(getId(io.grant.bits) <= UInt(entries), "Not enough grant beat counters, only " + entries + " entries.") - connectIncomingDataBeatCountersWithHeader(io.grant, entries, getId).reduce(_||_) - } - val q = Module(new FinishQueue(outstanding)) - q.io.enq.valid := io.grant.fire() && g.requiresAck() && (!g.hasMultibeatData() || done) - q.io.enq.bits <> g.makeFinish() - q.io.enq.bits.manager_id := io.grant.bits.header.src - - io.finish.bits.header.src := UInt(srcId) - io.finish.bits.header.dst := q.io.deq.bits.manager_id - io.finish.bits.payload <> q.io.deq.bits - io.finish.valid := q.io.deq.valid - q.io.deq.ready := io.finish.ready - - io.refill.valid := (q.io.enq.ready || !g.requiresAck()) && io.grant.valid - io.refill.bits := g - io.grant.ready := (q.io.enq.ready || !g.requiresAck()) && io.refill.ready - io.ready := q.io.enq.ready - } -} - -class FinishQueue(entries: Int)(implicit p: Parameters) extends Queue(new FinishToDst()(p), entries) - -/** A port to convert [[uncore.ClientTileLinkIO]].flip into [[uncore.TileLinkIO]] - * - * Creates network headers for [[uncore.Acquire]] and [[uncore.Release]] messages, - * calculating header.dst and filling in header.src. - * Strips headers from [[uncore.Probe Probes]]. - * Passes [[uncore.GrantFromSrc]] and accepts [[uncore.FinishFromDst]] in response, - * setting up the headers for each. - * - * @param clientId network port id of this agent - * @param addrConvert how a physical address maps to a destination manager port id - */ -class ClientTileLinkNetworkPort(clientId: Int, addrConvert: UInt => UInt) - (implicit p: Parameters) extends TLModule()(p) { - val io = new Bundle { - val client = new ClientTileLinkIO().flip - val network = new TileLinkIO - } - - val acq_with_header = ClientTileLinkHeaderCreator(io.client.acquire, clientId, addrConvert) - val rel_with_header = ClientTileLinkHeaderCreator(io.client.release, clientId, addrConvert) - val fin_with_header = ClientTileLinkHeaderCreator(io.client.finish, clientId) - val prb_without_header = DecoupledLogicalNetworkIOUnwrapper(io.network.probe) - val gnt_without_header = DecoupledLogicalNetworkIOUnwrapper(io.network.grant) - - io.network.acquire <> acq_with_header - io.network.release <> rel_with_header - io.network.finish <> fin_with_header - io.client.probe <> prb_without_header - io.client.grant.bits.manager_id := io.network.grant.bits.header.src - io.client.grant <> gnt_without_header -} - -/** A port to convert [[uncore.ClientUncachedTileLinkIO]].flip into [[uncore.TileLinkIO]] - * - * Creates network headers for [[uncore.Acquire]] and [[uncore.Release]] messages, - * calculating header.dst and filling in header.src. - * Responds to [[uncore.Grant]] by automatically issuing [[uncore.Finish]] to the granting managers. - * - * @param clientId network port id of this agent - * @param addrConvert how a physical address maps to a destination manager port id - */ -class ClientUncachedTileLinkNetworkPort(clientId: Int, addrConvert: UInt => UInt) - (implicit p: Parameters) extends TLModule()(p) { - val io = new Bundle { - val client = new ClientUncachedTileLinkIO().flip - val network = new TileLinkIO - } - - val finisher = Module(new FinishUnit(clientId)) - finisher.io.grant <> io.network.grant - io.network.finish <> finisher.io.finish - - val acq_with_header = ClientTileLinkHeaderCreator(io.client.acquire, clientId, addrConvert) - val gnt_without_header = finisher.io.refill - - io.network.acquire.bits := acq_with_header.bits - io.network.acquire.valid := acq_with_header.valid && finisher.io.ready - acq_with_header.ready := io.network.acquire.ready && finisher.io.ready - io.client.grant <> gnt_without_header - io.network.probe.ready := Bool(false) - io.network.release.valid := Bool(false) -} - -object ClientTileLinkHeaderCreator { - def apply[T <: ClientToManagerChannel with HasManagerId]( - in: DecoupledIO[T], - clientId: Int) - (implicit p: Parameters): DecoupledIO[LogicalNetworkIO[T]] = { - val out = Wire(new DecoupledIO(new LogicalNetworkIO(in.bits))) - out.bits.payload := in.bits - out.bits.header.src := UInt(clientId) - out.bits.header.dst := in.bits.manager_id - out.valid := in.valid - in.ready := out.ready - out - } - def apply[T <: ClientToManagerChannel with HasCacheBlockAddress]( - in: DecoupledIO[T], - clientId: Int, - addrConvert: UInt => UInt) - (implicit p: Parameters): DecoupledIO[LogicalNetworkIO[T]] = { - val out = Wire(new DecoupledIO(new LogicalNetworkIO(in.bits))) - out.bits.payload := in.bits - out.bits.header.src := UInt(clientId) - out.bits.header.dst := addrConvert(in.bits.addr_block) - out.valid := in.valid - in.ready := out.ready - out - } -} - -/** A port to convert [[uncore.ManagerTileLinkIO]].flip into [[uncore.TileLinkIO]].flip - * - * Creates network headers for [[uncore.Probe]] and [[uncore.Grant]] messagess, - * calculating header.dst and filling in header.src. - * Strips headers from [[uncore.Acquire]], [[uncore.Release]] and [[uncore.Finish]], - * but supplies client_id instead. - * - * @param managerId the network port id of this agent - * @param idConvert how a sharer id maps to a destination client port id - */ -class ManagerTileLinkNetworkPort(managerId: Int, idConvert: UInt => UInt) - (implicit p: Parameters) extends TLModule()(p) { - val io = new Bundle { - val manager = new ManagerTileLinkIO().flip - val network = new TileLinkIO().flip - } - io.network.grant <> ManagerTileLinkHeaderCreator(io.manager.grant, managerId, (u: UInt) => u) - io.network.probe <> ManagerTileLinkHeaderCreator(io.manager.probe, managerId, idConvert) - io.manager.acquire <> DecoupledLogicalNetworkIOUnwrapper(io.network.acquire) - io.manager.acquire.bits.client_id := io.network.acquire.bits.header.src - io.manager.release <> DecoupledLogicalNetworkIOUnwrapper(io.network.release) - io.manager.release.bits.client_id := io.network.release.bits.header.src - io.manager.finish <> DecoupledLogicalNetworkIOUnwrapper(io.network.finish) -} - -object ManagerTileLinkHeaderCreator { - def apply[T <: ManagerToClientChannel with HasClientId]( - in: DecoupledIO[T], - managerId: Int, - idConvert: UInt => UInt) - (implicit p: Parameters): DecoupledIO[LogicalNetworkIO[T]] = { - val out = Wire(new DecoupledIO(new LogicalNetworkIO(in.bits))) - out.bits.payload := in.bits - out.bits.header.src := UInt(managerId) - out.bits.header.dst := idConvert(in.bits.client_id) - out.valid := in.valid - in.ready := out.ready - out - } -} diff --git a/src/main/scala/uncore/tilelink2/Legacy.scala b/src/main/scala/uncore/tilelink2/Legacy.scala deleted file mode 100644 index c522a8ec..00000000 --- a/src/main/scala/uncore/tilelink2/Legacy.scala +++ /dev/null @@ -1,140 +0,0 @@ -// See LICENSE.SiFive for license details. - -package uncore.tilelink2 - -import Chisel._ -import diplomacy._ -import config._ -import uncore.tilelink._ -import uncore.constants._ - -class TLLegacy(implicit p: Parameters) extends LazyModule with HasTileLinkParameters -{ - // TL legacy clients don't support anything fancy - val node = TLClientNode(TLClientParameters( - name = "TLLegacy", - sourceId = IdRange(0, 1 << tlClientXactIdBits))) - - lazy val module = new LazyModuleImp(this) with HasTileLinkParameters { - val io = new Bundle { - val legacy = new ClientUncachedTileLinkIO().flip - val out = node.bundleOut - } - - // TL legacy is dumb. All managers must support it's accesses. - val edge = node.edgesOut(0) - require (edge.manager.beatBytes == tlDataBytes) - edge.manager.managers.foreach { m => - // If a slave supports read at all, it must support all TL Legacy requires - if (m.supportsGet) { - require (m.supportsGet.contains(TransferSizes(1, tlDataBytes))) - require (m.supportsGet.contains(TransferSizes(tlDataBeats * tlDataBytes))) - } - // Likewise, any put support must mean full put support - if (m.supportsPutPartial) { - require (m.supportsPutPartial.contains(TransferSizes(1, tlDataBytes))) - require (m.supportsPutPartial.contains(TransferSizes(tlDataBeats * tlDataBytes))) - } - // Any atomic support => must support 32-bit size - if (m.supportsArithmetic) { require (m.supportsArithmetic.contains(TransferSizes(4))) } - if (m.supportsLogical) { require (m.supportsLogical .contains(TransferSizes(4))) } - // We straight-up require hints - require (edge.manager.allSupportHint) - } - // TL legacy will not generate PutFull - // During conversion from TL Legacy, we won't support Acquire - - val out = io.out(0) - out.a.valid := io.legacy.acquire.valid - out.d.ready := io.legacy.grant .ready - io.legacy.acquire.ready := out.a.ready - io.legacy.grant .valid := out.d.valid - - val source = io.legacy.acquire.bits.client_xact_id - val data = io.legacy.acquire.bits.data - val wmask = io.legacy.acquire.bits.wmask() - val address = io.legacy.acquire.bits.full_addr() - - val block = UInt(log2Ceil(tlDataBytes*tlDataBeats)) - val size = io.legacy.acquire.bits.op_size() - - // Find the operation size and offset from the wmask - // Returns: (any_1, size, offset) - def mask_helper(range: UInt): (Bool, UInt, UInt) = { - val len = range.getWidth - if (len == 1) { - (range === UInt(1), UInt(0), UInt(0)) // ugh. offset has one useless bit. - } else { - val mid = len / 2 - val lo = range(mid-1, 0) - val hi = range(len-1, mid) - val (lo_1, lo_s, lo_a) = mask_helper(lo) - val (hi_1, hi_s, hi_a) = mask_helper(hi) - val out_1 = lo_1 || hi_1 - val out_s = Mux(lo_1, Mux(hi_1, UInt(log2Up(len)), lo_s), hi_s) - val out_a = Mux(lo_1, Mux(hi_1, UInt(0), lo_a), Cat(UInt(1), hi_a)) - (out_1, out_s, out_a) - } - } - val (_, wsize, wlow1) = mask_helper(wmask) - val wlow = wlow1 >> 1 - - // Only create atomic messages if TL2 managers support them - val atomics = if (edge.manager.anySupportLogical) { - MuxLookup(io.legacy.acquire.bits.op_code(), Wire(new TLBundleA(edge.bundle)), Array( - MemoryOpConstants.M_XA_SWAP -> edge.Logical(source, address, size, data, TLAtomics.SWAP)._2, - MemoryOpConstants.M_XA_XOR -> edge.Logical(source, address, size, data, TLAtomics.XOR) ._2, - MemoryOpConstants.M_XA_OR -> edge.Logical(source, address, size, data, TLAtomics.OR) ._2, - MemoryOpConstants.M_XA_AND -> edge.Logical(source, address, size, data, TLAtomics.AND) ._2, - MemoryOpConstants.M_XA_ADD -> edge.Arithmetic(source, address, size, data, TLAtomics.ADD)._2, - MemoryOpConstants.M_XA_MIN -> edge.Arithmetic(source, address, size, data, TLAtomics.MIN)._2, - MemoryOpConstants.M_XA_MAX -> edge.Arithmetic(source, address, size, data, TLAtomics.MAX)._2, - MemoryOpConstants.M_XA_MINU -> edge.Arithmetic(source, address, size, data, TLAtomics.MINU)._2, - MemoryOpConstants.M_XA_MAXU -> edge.Arithmetic(source, address, size, data, TLAtomics.MAXU)._2)) - } else { - // If no managers support atomics, assert fail if TL1 asks for them - assert (!io.legacy.acquire.valid || io.legacy.acquire.bits.a_type =/= Acquire.putAtomicType) - Wire(new TLBundleA(edge.bundle)) - } - - val beatMask = UInt(tlDataBytes-1) - val blockMask = UInt(tlDataBytes*tlDataBeats-1) - out.a.bits := MuxLookup(io.legacy.acquire.bits.a_type, Wire(new TLBundleA(edge.bundle)), Array( - Acquire.getType -> edge.Get (source, address, size)._2, - Acquire.getBlockType -> edge.Get (source, ~(~address|blockMask), block)._2, - Acquire.putType -> edge.Put (source, address|wlow, wsize, data, wmask)._2, - Acquire.putBlockType -> edge.Put (source, ~(~address|blockMask), block, data, wmask)._2, - Acquire.getPrefetchType -> edge.Hint(source, ~(~address|blockMask), block, UInt(0))._2, - Acquire.putPrefetchType -> edge.Hint(source, ~(~address|blockMask), block, UInt(1))._2, - Acquire.putAtomicType -> atomics)) - - // Get rid of some unneeded muxes - out.a.bits.source := source - out.a.bits.data := data - - // TL legacy does not support bus errors - assert (!out.d.valid || !out.d.bits.error) - - // Recreate the beat address counter - val beatCounter = RegInit(UInt(0, width = tlBeatAddrBits)) - when (out.d.fire() && edge.hasData(out.d.bits) && out.d.bits.size === block) { - beatCounter := beatCounter + UInt(1) - } - - val grant = io.legacy.grant.bits - grant.g_type := MuxLookup(out.d.bits.opcode, Grant.prefetchAckType, Array( - TLMessages.AccessAck -> Grant.putAckType, - TLMessages.AccessAckData -> Mux(out.d.bits.size === block, Grant.getDataBlockType, Grant.getDataBeatType), - TLMessages.HintAck -> Grant.prefetchAckType)) - grant.is_builtin_type := Bool(true) - grant.client_xact_id := out.d.bits.source - grant.manager_xact_id := UInt(0) - grant.data := out.d.bits.data - grant.addr_beat := beatCounter - - // Tie off unused channels - out.b.ready := Bool(true) - out.c.valid := Bool(false) - out.e.valid := Bool(false) - } -} diff --git a/src/main/scala/uncore/tilelink2/package.scala b/src/main/scala/uncore/tilelink2/package.scala deleted file mode 100644 index 946c3291..00000000 --- a/src/main/scala/uncore/tilelink2/package.scala +++ /dev/null @@ -1,68 +0,0 @@ -// See LICENSE.SiFive for license details. - -package uncore - -import Chisel._ -import diplomacy._ -import util._ -import scala.math.min - -package object tilelink2 -{ - type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] - type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] - type TLAsyncOutwardNode = OutwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle] - type TLRationalOutwardNode = OutwardNodeHandle[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle] - type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]] - type TLMixedNode = MixedNode[TLClientPortParameters, TLManagerPortParameters, TLEdgeIn, TLBundle, - TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLBundle] - - def OH1ToOH(x: UInt) = (x << 1 | UInt(1)) & ~Cat(UInt(0, width=1), x) - def OH1ToUInt(x: UInt) = OHToUInt(OH1ToOH(x)) - def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0) - def trailingZeros(x: Int) = if (x > 0) Some(log2Ceil(x & -x)) else None - // Fill 1s from low bits to high bits - def leftOR(x: UInt): UInt = leftOR(x, x.getWidth, x.getWidth) - def leftOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { - val stop = min(width, cap) - def helper(s: Int, x: UInt): UInt = - if (s >= stop) x else helper(s+s, x | (x << s)(width-1,0)) - helper(1, x)(width-1, 0) - } - // Fill 1s form high bits to low bits - def rightOR(x: UInt): UInt = rightOR(x, x.getWidth, x.getWidth) - def rightOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { - val stop = min(width, cap) - def helper(s: Int, x: UInt): UInt = - if (s >= stop) x else helper(s+s, x | (x >> s)) - helper(1, x)(width-1, 0) - } - // This gets used everywhere, so make the smallest circuit possible ... - // Given an address and size, create a mask of beatBytes size - // eg: (0x3, 0, 4) => 0001, (0x3, 1, 4) => 0011, (0x3, 2, 4) => 1111 - // groupBy applies an interleaved OR reduction; groupBy=2 take 0010 => 01 - def maskGen(addr_lo: UInt, lgSize: UInt, beatBytes: Int, groupBy: Int = 1): UInt = { - require (groupBy >= 1 && beatBytes >= groupBy) - require (isPow2(beatBytes) && isPow2(groupBy)) - val lgBytes = log2Ceil(beatBytes) - val sizeOH = UIntToOH(lgSize, log2Up(beatBytes)) | UInt(groupBy*2 - 1) - def helper(i: Int): Seq[(Bool, Bool)] = { - if (i == 0) { - Seq((lgSize >= UInt(lgBytes), Bool(true))) - } else { - val sub = helper(i-1) - val size = sizeOH(lgBytes - i) - val bit = addr_lo(lgBytes - i) - val nbit = !bit - Seq.tabulate (1 << i) { j => - val (sub_acc, sub_eq) = sub(j/2) - val eq = sub_eq && (if (j % 2 == 1) bit else nbit) - val acc = sub_acc || (size && eq) - (acc, eq) - } - } - } - if (groupBy == beatBytes) UInt(1) else - Cat(helper(lgBytes-log2Ceil(groupBy)).map(_._1).reverse) - } -} diff --git a/src/main/scala/uncore/util/Counters.scala b/src/main/scala/uncore/util/Counters.scala deleted file mode 100644 index e0f20741..00000000 --- a/src/main/scala/uncore/util/Counters.scala +++ /dev/null @@ -1,105 +0,0 @@ -// See LICENSE.Berkeley for license details. - -package uncore.util - -import Chisel._ -import uncore.tilelink._ -import util.TwoWayCounter -import config._ - -class BeatCounterStatus extends Bundle { - val idx = UInt() - val done = Bool() -} - -class TwoWayBeatCounterStatus extends Bundle { - val pending = Bool() - val up = new BeatCounterStatus() - val down = new BeatCounterStatus() -} - -/** Utility trait containing wiring functions to keep track of how many data beats have - * been sent or recieved over a particular [[uncore.TileLinkChannel]] or pair of channels. - * - * Won't count message types that don't have data. - * Used in [[uncore.XactTracker]] and [[uncore.FinishUnit]]. - */ -trait HasDataBeatCounters { - type HasBeat = TileLinkChannel with HasTileLinkBeatId - type HasId = TileLinkChannel with HasClientId - - /** Returns the current count on this channel and when a message is done - * @param inc increment the counter (usually .valid or .fire()) - * @param data the actual channel data - * @param beat count to return for single-beat messages - */ - def connectDataBeatCounter[S <: TileLinkChannel](inc: Bool, data: S, beat: UInt) = { - val multi = data.hasMultibeatData() - val (multi_cnt, multi_done) = Counter(inc && multi, data.tlDataBeats) - val cnt = Mux(multi, multi_cnt, beat) - val done = Mux(multi, multi_done, inc) - (cnt, done) - } - - /** Counter for beats on outgoing [[chisel.DecoupledIO]] */ - def connectOutgoingDataBeatCounter[T <: TileLinkChannel]( - out: DecoupledIO[T], - beat: UInt = UInt(0)): (UInt, Bool) = - connectDataBeatCounter(out.fire(), out.bits, beat) - - /** Returns done but not cnt. Use the addr_beat subbundle instead of cnt for beats on - * incoming channels in case of network reordering. - */ - def connectIncomingDataBeatCounter[T <: TileLinkChannel](in: DecoupledIO[T]): Bool = - connectDataBeatCounter(in.fire(), in.bits, UInt(0))._2 - - /** Counter for beats on incoming DecoupledIO[LogicalNetworkIO[]]s returns done */ - def connectIncomingDataBeatCounterWithHeader[T <: TileLinkChannel](in: DecoupledIO[LogicalNetworkIO[T]]): Bool = - connectDataBeatCounter(in.fire(), in.bits.payload, UInt(0))._2 - - /** If the network might interleave beats from different messages, we need a Vec of counters, - * one for every outstanding message id that might be interleaved. - * - * @param getId mapping from Message to counter id - */ - def connectIncomingDataBeatCountersWithHeader[T <: TileLinkChannel with HasClientTransactionId]( - in: DecoupledIO[LogicalNetworkIO[T]], - entries: Int, - getId: LogicalNetworkIO[T] => UInt): Vec[Bool] = { - Vec((0 until entries).map { i => - connectDataBeatCounter(in.fire() && getId(in.bits) === UInt(i), in.bits.payload, UInt(0))._2 - }) - } - - /** Provides counters on two channels, as well a meta-counter that tracks how many - * messages have been sent over the up channel but not yet responded to over the down channel - * - * @param status bundle of status of the counters - * @param up outgoing channel - * @param down incoming channel - * @param max max number of outstanding ups with no down - * @param beat overrides cnts on single-beat messages - * @param track whether up's message should be tracked - * @return a tuple containing whether their are outstanding messages, up's count, - * up's done, down's count, down's done - */ - def connectTwoWayBeatCounters[T <: TileLinkChannel, S <: TileLinkChannel]( - status: TwoWayBeatCounterStatus, - up: DecoupledIO[T], - down: DecoupledIO[S], - max: Int = 1, - beat: UInt = UInt(0), - trackUp: T => Bool = (t: T) => Bool(true), - trackDown: S => Bool = (s: S) => Bool(true)) { - val (up_idx, up_done) = connectDataBeatCounter(up.fire() && trackUp(up.bits), up.bits, beat) - val (dn_idx, dn_done) = connectDataBeatCounter(down.fire() && trackDown(down.bits), down.bits, beat) - val cnt = TwoWayCounter(up_done, dn_done, max) - status.pending := cnt > UInt(0) - status.up.idx := up_idx - status.up.done := up_done - status.down.idx := dn_idx - status.down.done := dn_done - } -} - - diff --git a/src/main/scala/uncore/util/Enqueuer.scala b/src/main/scala/uncore/util/Enqueuer.scala deleted file mode 100644 index 4e47b3cd..00000000 --- a/src/main/scala/uncore/util/Enqueuer.scala +++ /dev/null @@ -1,76 +0,0 @@ -// See LICENSE.Berkeley for license details. -// See LICENSE.SiFive for license details. - -package uncore.util - -import Chisel._ -import uncore.tilelink._ -import config._ - -/** Struct for describing per-channel queue depths */ -case class TileLinkDepths(acq: Int, prb: Int, rel: Int, gnt: Int, fin: Int) -case class UncachedTileLinkDepths(acq: Int, gnt: Int) - -/** Optionally enqueues each [[uncore.TileLinkChannel]] individually */ -class TileLinkEnqueuer(depths: TileLinkDepths)(implicit p: Parameters) extends Module { - val io = new Bundle { - val client = new TileLinkIO().flip - val manager = new TileLinkIO - } - io.manager.acquire <> (if(depths.acq > 0) Queue(io.client.acquire, depths.acq) else io.client.acquire) - io.client.probe <> (if(depths.prb > 0) Queue(io.manager.probe, depths.prb) else io.manager.probe) - io.manager.release <> (if(depths.rel > 0) Queue(io.client.release, depths.rel) else io.client.release) - io.client.grant <> (if(depths.gnt > 0) Queue(io.manager.grant, depths.gnt) else io.manager.grant) - io.manager.finish <> (if(depths.fin > 0) Queue(io.client.finish, depths.fin) else io.client.finish) -} - -object TileLinkEnqueuer { - def apply(in: TileLinkIO, depths: TileLinkDepths): TileLinkIO = { - val t = Module(new TileLinkEnqueuer(depths)(in.p)) - t.io.client <> in - t.io.manager - } - def apply(in: TileLinkIO, depth: Int): TileLinkIO = { - apply(in, TileLinkDepths(depth, depth, depth, depth, depth)) - } - - def apply(in: ClientTileLinkIO, depths: TileLinkDepths): ClientTileLinkIO = { - val t = Module(new ClientTileLinkEnqueuer(depths)(in.p)) - t.io.inner <> in - t.io.outer - } - def apply(in: ClientTileLinkIO, depth: Int): ClientTileLinkIO = { - apply(in, TileLinkDepths(depth, depth, depth, depth, depth)) - } - def apply(in: ClientUncachedTileLinkIO, depths: UncachedTileLinkDepths): ClientUncachedTileLinkIO = { - val t = Module(new ClientUncachedTileLinkEnqueuer(depths)(in.p)) - t.io.inner <> in - t.io.outer - } - def apply(in: ClientUncachedTileLinkIO, depth: Int): ClientUncachedTileLinkIO = { - apply(in, UncachedTileLinkDepths(depth, depth)) - } -} - -class ClientTileLinkEnqueuer(depths: TileLinkDepths)(implicit p: Parameters) extends Module { - val io = new Bundle { - val inner = new ClientTileLinkIO().flip - val outer = new ClientTileLinkIO - } - - io.outer.acquire <> (if(depths.acq > 0) Queue(io.inner.acquire, depths.acq) else io.inner.acquire) - io.inner.probe <> (if(depths.prb > 0) Queue(io.outer.probe, depths.prb) else io.outer.probe) - io.outer.release <> (if(depths.rel > 0) Queue(io.inner.release, depths.rel) else io.inner.release) - io.inner.grant <> (if(depths.gnt > 0) Queue(io.outer.grant, depths.gnt) else io.outer.grant) - io.outer.finish <> (if(depths.fin > 0) Queue(io.inner.finish, depths.fin) else io.inner.finish) -} - -class ClientUncachedTileLinkEnqueuer(depths: UncachedTileLinkDepths)(implicit p: Parameters) extends Module { - val io = new Bundle { - val inner = new ClientUncachedTileLinkIO().flip - val outer = new ClientUncachedTileLinkIO - } - - io.outer.acquire <> (if(depths.acq > 0) Queue(io.inner.acquire, depths.acq) else io.inner.acquire) - io.inner.grant <> (if(depths.gnt > 0) Queue(io.outer.grant, depths.gnt) else io.outer.grant) -} diff --git a/src/main/scala/unittest/Configs.scala b/src/main/scala/unittest/Configs.scala index 3f0d2f8a..190977ac 100644 --- a/src/main/scala/unittest/Configs.scala +++ b/src/main/scala/unittest/Configs.scala @@ -1,10 +1,15 @@ // See LICENSE.SiFive for license details. -package unittest +package freechips.rocketchip.unittest import Chisel._ -import config._ -import rocketchip.{BaseConfig, BasePlatformConfig} +import freechips.rocketchip.amba.ahb._ +import freechips.rocketchip.amba.apb._ +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.chip.{BaseConfig, BasePlatformConfig} +import freechips.rocketchip.config._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.tilelink._ case object TestDurationMultiplier extends Field[Int] @@ -12,22 +17,20 @@ class WithTestDuration(x: Int) extends Config((site, here, up) => { case TestDurationMultiplier => x }) -class WithUncoreUnitTests extends Config((site, here, up) => { - case uncore.tilelink.TLId => "L1toL2" +class WithAMBAUnitTests extends Config((site, here, up) => { case UnitTests => (q: Parameters) => { implicit val p = q val txns = 100 * site(TestDurationMultiplier) val timeout = 50000 * site(TestDurationMultiplier) Seq( - Module(new uncore.tilelink2.TLFuzzRAMTest( txns=3*txns, timeout=timeout)), - Module(new uncore.ahb.AHBBridgeTest(true, txns=8*txns, timeout=timeout)), - Module(new uncore.ahb.AHBNativeTest(true, txns=6*txns, timeout=timeout)), - Module(new uncore.ahb.AHBNativeTest(false, txns=6*txns, timeout=timeout)), - Module(new uncore.apb.APBBridgeTest(true, txns=6*txns, timeout=timeout)), - Module(new uncore.apb.APBBridgeTest(false, txns=6*txns, timeout=timeout)), - Module(new uncore.axi4.AXI4LiteFuzzRAMTest( txns=6*txns, timeout=timeout)), - Module(new uncore.axi4.AXI4FullFuzzRAMTest( txns=3*txns, timeout=timeout)), - Module(new uncore.axi4.AXI4BridgeTest( txns=3*txns, timeout=timeout))) } + Module(new AHBBridgeTest(true, txns=8*txns, timeout=timeout)), + Module(new AHBNativeTest(true, txns=6*txns, timeout=timeout)), + Module(new AHBNativeTest(false,txns=6*txns, timeout=timeout)), + Module(new APBBridgeTest(true, txns=6*txns, timeout=timeout)), + Module(new APBBridgeTest(false,txns=6*txns, timeout=timeout)), + Module(new AXI4LiteFuzzRAMTest(txns=6*txns, timeout=timeout)), + Module(new AXI4FullFuzzRAMTest(txns=3*txns, timeout=timeout)), + Module(new AXI4BridgeTest( txns=3*txns, timeout=timeout))) } }) class WithTLSimpleUnitTests extends Config((site, here, up) => { @@ -36,15 +39,16 @@ class WithTLSimpleUnitTests extends Config((site, here, up) => { val txns = 100 * site(TestDurationMultiplier) val timeout = 50000 * site(TestDurationMultiplier) Seq( - Module(new uncore.tilelink2.TLRAMSimpleTest(1, txns=15*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMSimpleTest(4, txns=15*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMSimpleTest(16, txns=15*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMZeroDelayTest(4, txns=15*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRR0Test( txns= 3*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRR1Test( txns= 3*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMRationalCrossingTest(txns= 3*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMAsyncCrossingTest( txns= 5*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMAtomicAutomataTest( txns=10*txns, timeout=timeout)) ) } + Module(new TLRAMSimpleTest(1, txns=15*txns, timeout=timeout)), + Module(new TLRAMSimpleTest(4, txns=15*txns, timeout=timeout)), + Module(new TLRAMSimpleTest(16, txns=15*txns, timeout=timeout)), + Module(new TLRAMZeroDelayTest(4, txns=15*txns, timeout=timeout)), + Module(new TLFuzzRAMTest( txns= 3*txns, timeout=timeout)), + Module(new TLRR0Test( txns= 3*txns, timeout=timeout)), + Module(new TLRR1Test( txns= 3*txns, timeout=timeout)), + Module(new TLRAMRationalCrossingTest(txns= 3*txns, timeout=timeout)), + Module(new TLRAMAsyncCrossingTest( txns= 5*txns, timeout=timeout)), + Module(new TLRAMAtomicAutomataTest( txns=10*txns, timeout=timeout)) ) } }) class WithTLWidthUnitTests extends Config((site, here, up) => { @@ -53,12 +57,12 @@ class WithTLWidthUnitTests extends Config((site, here, up) => { val txns = 100 * site(TestDurationMultiplier) val timeout = 50000 * site(TestDurationMultiplier) Seq( - Module(new uncore.tilelink2.TLRAMFragmenterTest( 4, 256, txns= 5*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMFragmenterTest(16, 64, txns=15*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMFragmenterTest( 4, 16, txns=15*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMWidthWidgetTest( 1, 1, txns= 1*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMWidthWidgetTest( 4, 64, txns= 4*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMWidthWidgetTest(64, 4, txns= 5*txns, timeout=timeout)) ) } + Module(new TLRAMFragmenterTest( 4, 256, txns= 5*txns, timeout=timeout)), + Module(new TLRAMFragmenterTest(16, 64, txns=15*txns, timeout=timeout)), + Module(new TLRAMFragmenterTest( 4, 16, txns=15*txns, timeout=timeout)), + Module(new TLRAMWidthWidgetTest( 1, 1, txns= 1*txns, timeout=timeout)), + Module(new TLRAMWidthWidgetTest( 4, 64, txns= 4*txns, timeout=timeout)), + Module(new TLRAMWidthWidgetTest(64, 4, txns= 5*txns, timeout=timeout)) ) } }) class WithTLXbarUnitTests extends Config((site, here, up) => { @@ -67,13 +71,13 @@ class WithTLXbarUnitTests extends Config((site, here, up) => { val txns = 100 * site(TestDurationMultiplier) val timeout = 50000 * site(TestDurationMultiplier) Seq( - Module(new uncore.tilelink2.TLRAMXbarTest(1, txns=5*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMXbarTest(2, txns=5*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLRAMXbarTest(8, txns=5*txns, timeout=timeout)), - Module(new uncore.tilelink2.TLMulticlientXbarTest(4,4, txns=2*txns, timeout=timeout)) ) } + Module(new TLRAMXbarTest(1, txns=5*txns, timeout=timeout)), + Module(new TLRAMXbarTest(2, txns=5*txns, timeout=timeout)), + Module(new TLRAMXbarTest(8, txns=5*txns, timeout=timeout)), + Module(new TLMulticlientXbarTest(4,4, txns=2*txns, timeout=timeout)) ) } }) -class UncoreUnitTestConfig extends Config(new WithUncoreUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig) +class AMBAUnitTestConfig extends Config(new WithAMBAUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig) class TLSimpleUnitTestConfig extends Config(new WithTLSimpleUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig) class TLWidthUnitTestConfig extends Config(new WithTLWidthUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig) class TLXbarUnitTestConfig extends Config(new WithTLXbarUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig) diff --git a/src/main/scala/unittest/Generator.scala b/src/main/scala/unittest/Generator.scala index e337573d..e7ce4ddf 100644 --- a/src/main/scala/unittest/Generator.scala +++ b/src/main/scala/unittest/Generator.scala @@ -1,8 +1,8 @@ // See LICENSE.SiFive for license details. -package unittest +package freechips.rocketchip.unittest -object Generator extends util.GeneratorApp { +object Generator extends freechips.rocketchip.util.GeneratorApp { val longName = names.topModuleProject + "." + names.configs generateFirrtl generateTestSuiteMakefrags // TODO: Needed only for legacy make targets diff --git a/src/main/scala/unittest/TestHarness.scala b/src/main/scala/unittest/TestHarness.scala index d361d78c..63b15a15 100644 --- a/src/main/scala/unittest/TestHarness.scala +++ b/src/main/scala/unittest/TestHarness.scala @@ -1,9 +1,9 @@ // See LICENSE.SiFive for license details. -package unittest +package freechips.rocketchip.unittest import Chisel._ -import config._ +import freechips.rocketchip.config.Parameters class TestHarness(implicit val p: Parameters) extends Module { val io = new Bundle { val success = Bool(OUTPUT) } diff --git a/src/main/scala/unittest/UnitTest.scala b/src/main/scala/unittest/UnitTest.scala index 2f89597f..a0b34a87 100644 --- a/src/main/scala/unittest/UnitTest.scala +++ b/src/main/scala/unittest/UnitTest.scala @@ -1,10 +1,10 @@ // See LICENSE.SiFive for license details. -package unittest +package freechips.rocketchip.unittest import Chisel._ -import config._ -import util.SimpleTimer +import freechips.rocketchip.config._ +import freechips.rocketchip.util.SimpleTimer trait HasUnitTestIO { val io = new Bundle { diff --git a/src/main/scala/util/Arbiters.scala b/src/main/scala/util/Arbiters.scala index d3fd1056..caa91e60 100644 --- a/src/main/scala/util/Arbiters.scala +++ b/src/main/scala/util/Arbiters.scala @@ -1,8 +1,9 @@ // See LICENSE.Berkeley for license details. -package util +package freechips.rocketchip.util + import Chisel._ -import config._ +import freechips.rocketchip.config.Parameters /** A generalized locking RR arbiter that addresses the limitations of the * version in the Chisel standard library */ @@ -93,3 +94,52 @@ class HellaCountingArbiter[T <: Data]( } } } + +/** This arbiter preserves the order of responses */ +class InOrderArbiter[T <: Data, U <: Data](reqTyp: T, respTyp: U, n: Int) + (implicit p: Parameters) extends Module { + val io = new Bundle { + val in_req = Vec(n, Decoupled(reqTyp)).flip + val in_resp = Vec(n, Decoupled(respTyp)) + val out_req = Decoupled(reqTyp) + val out_resp = Decoupled(respTyp).flip + } + + if (n > 1) { + val route_q = Module(new Queue(UInt(width = log2Up(n)), 2)) + val req_arb = Module(new RRArbiter(reqTyp, n)) + req_arb.io.in <> io.in_req + + val req_helper = DecoupledHelper( + req_arb.io.out.valid, + route_q.io.enq.ready, + io.out_req.ready) + + io.out_req.bits := req_arb.io.out.bits + io.out_req.valid := req_helper.fire(io.out_req.ready) + + route_q.io.enq.bits := req_arb.io.chosen + route_q.io.enq.valid := req_helper.fire(route_q.io.enq.ready) + + req_arb.io.out.ready := req_helper.fire(req_arb.io.out.valid) + + val resp_sel = route_q.io.deq.bits + val resp_ready = io.in_resp(resp_sel).ready + val resp_helper = DecoupledHelper( + resp_ready, + route_q.io.deq.valid, + io.out_resp.valid) + + val resp_valid = resp_helper.fire(resp_ready) + for (i <- 0 until n) { + io.in_resp(i).bits := io.out_resp.bits + io.in_resp(i).valid := resp_valid && resp_sel === UInt(i) + } + + route_q.io.deq.ready := resp_helper.fire(route_q.io.deq.valid) + io.out_resp.ready := resp_helper.fire(io.out_resp.valid) + } else { + io.out_req <> io.in_req.head + io.in_resp.head <> io.out_resp + } +} diff --git a/src/main/scala/util/AsyncBundle.scala b/src/main/scala/util/AsyncBundle.scala index 12561f47..fbd60e9c 100644 --- a/src/main/scala/util/AsyncBundle.scala +++ b/src/main/scala/util/AsyncBundle.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ import chisel3.util.{ReadyValidIO} diff --git a/src/main/scala/util/AsyncQueue.scala b/src/main/scala/util/AsyncQueue.scala index 0ed1d857..91e5c05d 100644 --- a/src/main/scala/util/AsyncQueue.scala +++ b/src/main/scala/util/AsyncQueue.scala @@ -1,6 +1,7 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util + import Chisel._ object GrayCounter { diff --git a/src/main/scala/util/BlackBoxRegs.scala b/src/main/scala/util/BlackBoxRegs.scala index 349dea0f..532fdcb0 100644 --- a/src/main/scala/util/BlackBoxRegs.scala +++ b/src/main/scala/util/BlackBoxRegs.scala @@ -1,11 +1,9 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ -import config._ - /** This black-boxes an Async Reset * (or Set) * Register. diff --git a/src/main/scala/util/Broadcaster.scala b/src/main/scala/util/Broadcaster.scala new file mode 100644 index 00000000..41c336ec --- /dev/null +++ b/src/main/scala/util/Broadcaster.scala @@ -0,0 +1,48 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package freechips.rocketchip.util + +import Chisel._ + +/** Takes in data on one decoupled interface and broadcasts it + * to N decoupled output interfaces. + */ +class Broadcaster[T <: Data](typ: T, n: Int) extends Module { + val io = new Bundle { + val in = Decoupled(typ).flip + val out = Vec(n, Decoupled(typ)) + } + + require (n > 0) + + if (n == 1) { + io.out.head <> io.in + } else { + val idx = Reg(init = UInt(0, log2Up(n))) + val save = Reg(typ) + + io.out.head.valid := idx === UInt(0) && io.in.valid + io.out.head.bits := io.in.bits + for (i <- 1 until n) { + io.out(i).valid := idx === UInt(i) + io.out(i).bits := save + } + io.in.ready := io.out.head.ready && idx === UInt(0) + + when (io.in.fire()) { save := io.in.bits } + + when (io.out(idx).fire()) { + when (idx === UInt(n - 1)) { idx := UInt(0) } + .otherwise { idx := idx + UInt(1) } + } + } +} + +object Broadcaster { + def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = { + val split = Module(new Broadcaster(in.bits, n)) + split.io.in <> in + split.io.out + } +} diff --git a/src/main/scala/util/CRC.scala b/src/main/scala/util/CRC.scala index 8dc2ab21..4f2a887b 100644 --- a/src/main/scala/util/CRC.scala +++ b/src/main/scala/util/CRC.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/ClockDivider.scala b/src/main/scala/util/ClockDivider.scala index 91a280fd..c67e4651 100644 --- a/src/main/scala/util/ClockDivider.scala +++ b/src/main/scala/util/ClockDivider.scala @@ -1,6 +1,6 @@ // See LICENSE.Berkeley for license details. -package util +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/Counters.scala b/src/main/scala/util/Counters.scala index eb555f7a..705a54f0 100644 --- a/src/main/scala/util/Counters.scala +++ b/src/main/scala/util/Counters.scala @@ -1,10 +1,9 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ -import config._ import scala.math.max // Produces 0-width value when counting to 1 diff --git a/src/main/scala/util/Crossing.scala b/src/main/scala/util/Crossing.scala index bb67aeed..11bc1e28 100644 --- a/src/main/scala/util/Crossing.scala +++ b/src/main/scala/util/Crossing.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ import chisel3.util.{DecoupledIO, Decoupled, Irrevocable, IrrevocableIO, ReadyValidIO} diff --git a/src/main/scala/uncore/util/Ecc.scala b/src/main/scala/util/ECC.scala similarity index 99% rename from src/main/scala/uncore/util/Ecc.scala rename to src/main/scala/util/ECC.scala index 284e2c27..3912a644 100644 --- a/src/main/scala/uncore/util/Ecc.scala +++ b/src/main/scala/util/ECC.scala @@ -1,9 +1,8 @@ // See LICENSE.Berkeley for license details. -package uncore.util +package freechips.rocketchip.util import Chisel._ -import util._ abstract class Decoding { diff --git a/src/main/scala/util/Frequency.scala b/src/main/scala/util/Frequency.scala new file mode 100644 index 00000000..e5417517 --- /dev/null +++ b/src/main/scala/util/Frequency.scala @@ -0,0 +1,43 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package freechips.rocketchip.util + +import Chisel._ + +/** Given a list of (frequency, value) pairs, return a random value + * according to the frequency distribution. The sum of the + * frequencies in the distribution must be a power of two. + */ +object Frequency { + def apply(dist : List[(Int, Bits)]) : Bits = { + // Distribution must be non-empty + require(dist.length > 0) + + // Require that the frequencies sum to a power of two + val (freqs, vals) = dist.unzip + val total = freqs.sum + require(isPow2(total)) + + // First item in the distribution + val (firstFreq, firstVal) = dist.head + + // Result wire + val result = Wire(Bits(width = firstVal.getWidth)) + result := UInt(0) + + // Random value + val randVal = LCG(log2Up(total)) + + // Pick return value + var count = firstFreq + var select = when (randVal < UInt(firstFreq)) { result := firstVal } + for (p <- dist.drop(1)) { + count = count + p._1 + select = select.elsewhen(randVal < UInt(count)) { result := p._2 } + } + + return result + } +} + diff --git a/src/main/scala/util/GeneratorUtils.scala b/src/main/scala/util/GeneratorUtils.scala index 27c58407..98b3a359 100644 --- a/src/main/scala/util/GeneratorUtils.scala +++ b/src/main/scala/util/GeneratorUtils.scala @@ -1,11 +1,14 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ +import chisel3.internal.firrtl.Circuit import chisel3.experimental.{RawModule} -import config._ -import diplomacy.LazyModule +// TODO: better job of Makefrag generation for non-RocketChip testing platforms +import freechips.rocketchip.chip.{TestGeneration, DefaultTestSuites} +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy.LazyModule import java.io.{File, FileWriter} /** Representation of the information this Generator needs to collect from external sources. */ @@ -40,7 +43,6 @@ trait HasGeneratorUtilities { def getParameters(config: Config): Parameters = Parameters.root(config.toInstance) - import chisel3.internal.firrtl.Circuit def elaborate(names: ParsedInputNames, params: Parameters): Circuit = { val gen = () => Class.forName(names.fullTopModuleClass) @@ -92,13 +94,10 @@ trait GeneratorApp extends App with HasGeneratorUtilities { /** Output software test Makefrags, which provide targets for integration testing. */ def generateTestSuiteMakefrags { addTestSuites - writeOutputFile(td, s"$longName.d", rocketchip.TestGeneration.generateMakefrag) // Coreplex-specific test suites + writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites } def addTestSuites { - // TODO: better job of Makefrag generation - // for non-RocketChip testing platforms - import rocketchip.{DefaultTestSuites, TestGeneration} TestGeneration.addSuite(DefaultTestSuites.groundtest64("p")) TestGeneration.addSuite(DefaultTestSuites.emptyBmarks) TestGeneration.addSuite(DefaultTestSuites.singleRegression) diff --git a/src/main/scala/util/GenericParameterizedBundle.scala b/src/main/scala/util/GenericParameterizedBundle.scala index bed000e5..cdc78be5 100644 --- a/src/main/scala/util/GenericParameterizedBundle.scala +++ b/src/main/scala/util/GenericParameterizedBundle.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/HellaQueue.scala b/src/main/scala/util/HellaQueue.scala index d2050d48..b0a3eec9 100644 --- a/src/main/scala/util/HellaQueue.scala +++ b/src/main/scala/util/HellaQueue.scala @@ -1,9 +1,8 @@ // See LICENSE.Berkeley for license details. -package util +package freechips.rocketchip.util import Chisel._ -import config._ class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module { val io = new QueueIO(data, entries) diff --git a/src/main/scala/util/HeterogeneousBag.scala b/src/main/scala/util/HeterogeneousBag.scala index 1aaff08d..9a614906 100644 --- a/src/main/scala/util/HeterogeneousBag.scala +++ b/src/main/scala/util/HeterogeneousBag.scala @@ -1,4 +1,6 @@ -package util +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.util import Chisel._ import chisel3.core.Record diff --git a/src/main/scala/util/LCG.scala b/src/main/scala/util/LCG.scala new file mode 100644 index 00000000..dbdcdb4d --- /dev/null +++ b/src/main/scala/util/LCG.scala @@ -0,0 +1,55 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package freechips.rocketchip.util + +import Chisel._ + +/** A 16-bit psuedo-random generator based on a linear conguential + * generator (LCG). The state is stored in an unitialised register. + * When using the C++ backend, it is straigtforward to arrange a + * random initial value for each uninitialised register, effectively + * seeding each LCG16 instance with a different seed. + */ +class LCG16 extends Module { + val io = new Bundle { + val out = UInt(OUTPUT, 16) + val inc = Bool(INPUT) + } + val state = Reg(UInt(width = 32)) + when (io.inc) { + state := state * UInt(1103515245, 32) + UInt(12345, 32) + } + io.out := state(30, 15) +} + +/** An n-bit psuedo-random generator made from many instances of a + * 16-bit LCG. Parameter 'width' must be larger than 0. + */ +class LCG(val w: Int) extends Module { + val io = new Bundle { + val out = UInt(OUTPUT, w) + val inc = Bool(INPUT) + } + require(w > 0) + val numLCG16s : Int = (w+15)/16 + val outs = Seq.fill(numLCG16s) { LCG16(io.inc) } + io.out := Cat(outs) +} + +object LCG16 { + def apply(inc: Bool = Bool(true)): UInt = { + val lcg = Module(new LCG16) + lcg.io.inc := inc + lcg.io.out + } +} + +object LCG { + def apply(w: Int, inc: Bool = Bool(true)): UInt = { + val lcg = Module(new LCG(w)) + lcg.io.inc := inc + lcg.io.out + } +} + diff --git a/src/main/scala/util/LatencyPipe.scala b/src/main/scala/util/LatencyPipe.scala index 5dc58337..13503ccf 100644 --- a/src/main/scala/util/LatencyPipe.scala +++ b/src/main/scala/util/LatencyPipe.scala @@ -1,6 +1,6 @@ // See LICENSE.Berkeley for license details. -package util +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/Misc.scala b/src/main/scala/util/Misc.scala index 55dc1ed0..7227802f 100644 --- a/src/main/scala/util/Misc.scala +++ b/src/main/scala/util/Misc.scala @@ -1,10 +1,10 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ -import config._ +import freechips.rocketchip.config.Parameters import scala.math._ class ParameterizedBundle(implicit p: Parameters) extends Bundle { @@ -59,6 +59,19 @@ object MuxTLookup { } } +object ValidMux { + def apply[T <: Data](v1: ValidIO[T], v2: ValidIO[T]*): ValidIO[T] = { + apply(v1 +: v2.toSeq) + } + def apply[T <: Data](valids: Seq[ValidIO[T]]): ValidIO[T] = { + val out = Wire(Valid(valids.head.bits)) + out.valid := valids.map(_.valid).reduce(_ || _) + out.bits := MuxCase(valids.head.bits, + valids.map(v => (v.valid -> v.bits))) + out + } +} + object Str { def apply(s: String): UInt = { @@ -172,3 +185,53 @@ object Majority { def apply(in: UInt): Bool = apply(in.toBools.toSet) } + +object PopCountAtLeast { + private def two(x: UInt): (Bool, Bool) = x.getWidth match { + case 1 => (x.toBool, Bool(false)) + case n => + val half = x.getWidth / 2 + val (leftOne, leftTwo) = two(x(half - 1, 0)) + val (rightOne, rightTwo) = two(x(x.getWidth - 1, half)) + (leftOne || rightOne, leftTwo || rightTwo || (leftOne && rightOne)) + } + def apply(x: UInt, n: Int): Bool = n match { + case 0 => Bool(true) + case 1 => x.orR + case 2 => two(x)._2 + case 3 => PopCount(x) >= UInt(n) + } +} + +// This gets used everywhere, so make the smallest circuit possible ... +// Given an address and size, create a mask of beatBytes size +// eg: (0x3, 0, 4) => 0001, (0x3, 1, 4) => 0011, (0x3, 2, 4) => 1111 +// groupBy applies an interleaved OR reduction; groupBy=2 take 0010 => 01 +object MaskGen { + def apply(addr_lo: UInt, lgSize: UInt, beatBytes: Int, groupBy: Int = 1): UInt = { + require (groupBy >= 1 && beatBytes >= groupBy) + require (isPow2(beatBytes) && isPow2(groupBy)) + val lgBytes = log2Ceil(beatBytes) + val sizeOH = UIntToOH(lgSize, log2Up(beatBytes)) | UInt(groupBy*2 - 1) + + def helper(i: Int): Seq[(Bool, Bool)] = { + if (i == 0) { + Seq((lgSize >= UInt(lgBytes), Bool(true))) + } else { + val sub = helper(i-1) + val size = sizeOH(lgBytes - i) + val bit = addr_lo(lgBytes - i) + val nbit = !bit + Seq.tabulate (1 << i) { j => + val (sub_acc, sub_eq) = sub(j/2) + val eq = sub_eq && (if (j % 2 == 1) bit else nbit) + val acc = sub_acc || (size && eq) + (acc, eq) + } + } + } + + if (groupBy == beatBytes) UInt(1) else + Cat(helper(lgBytes-log2Ceil(groupBy)).map(_._1).reverse) + } +} diff --git a/src/main/scala/junctions/MultiWidthFifo.scala b/src/main/scala/util/MultiWidthFifo.scala similarity index 98% rename from src/main/scala/junctions/MultiWidthFifo.scala rename to src/main/scala/util/MultiWidthFifo.scala index 30d65770..240f914a 100644 --- a/src/main/scala/junctions/MultiWidthFifo.scala +++ b/src/main/scala/util/MultiWidthFifo.scala @@ -1,9 +1,9 @@ // See LICENSE.Berkeley for license details. -package junctions +package freechips.rocketchip.util import Chisel._ -import unittest.UnitTest +import freechips.rocketchip.unittest.UnitTest class MultiWidthFifo(inW: Int, outW: Int, n: Int) extends Module { val io = new Bundle { diff --git a/src/main/scala/util/PlusArg.scala b/src/main/scala/util/PlusArg.scala index fc74de73..e9c9373b 100644 --- a/src/main/scala/util/PlusArg.scala +++ b/src/main/scala/util/PlusArg.scala @@ -1,6 +1,7 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util + import Chisel._ class plusarg_reader(val format: String, val default: Int, val docstring: String) extends BlackBox(Map( diff --git a/src/main/scala/util/PositionalMultiQueue.scala b/src/main/scala/util/PositionalMultiQueue.scala index 77be2888..7863195e 100644 --- a/src/main/scala/util/PositionalMultiQueue.scala +++ b/src/main/scala/util/PositionalMultiQueue.scala @@ -1,6 +1,7 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util + import Chisel._ case class PositionalMultiQueueParameters[T <: Data](gen: T, positions: Int, ways: Int) diff --git a/src/main/scala/util/RationalCrossing.scala b/src/main/scala/util/RationalCrossing.scala index 13eaab25..4f722bfd 100644 --- a/src/main/scala/util/RationalCrossing.scala +++ b/src/main/scala/util/RationalCrossing.scala @@ -1,12 +1,13 @@ // See LICENSE.SiFive for license details. +package freechips.rocketchip.util + +import Chisel._ + // If you know two clocks are related with an N:M relationship, you // can cross the clock domains with lower latency than an AsyncQueue. // This crossing adds 1 cycle in the target clock domain. -package util -import Chisel._ - // A rational crossing must put registers on the slow side. // This trait covers the options of how/where to put the registers. // BEWARE: the source+sink must agree on the direction! diff --git a/src/main/scala/util/ReduceOthers.scala b/src/main/scala/util/ReduceOthers.scala index 6dec6e1c..950067f7 100644 --- a/src/main/scala/util/ReduceOthers.scala +++ b/src/main/scala/util/ReduceOthers.scala @@ -1,6 +1,7 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util + import Chisel._ object ReduceOthers { diff --git a/src/main/scala/util/ReorderQueue.scala b/src/main/scala/util/ReorderQueue.scala index 5cd16cf0..f40c95b9 100644 --- a/src/main/scala/util/ReorderQueue.scala +++ b/src/main/scala/util/ReorderQueue.scala @@ -1,10 +1,9 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package util +package freechips.rocketchip.util import Chisel._ -import config._ class ReorderQueueWrite[T <: Data](dType: T, tagWidth: Int) extends Bundle { val data = dType.cloneType diff --git a/src/main/scala/uncore/tilelink2/Repeater.scala b/src/main/scala/util/Repeater.scala similarity index 96% rename from src/main/scala/uncore/tilelink2/Repeater.scala rename to src/main/scala/util/Repeater.scala index f36afe62..713142da 100644 --- a/src/main/scala/uncore/tilelink2/Repeater.scala +++ b/src/main/scala/util/Repeater.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package uncore.tilelink2 +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/Replacement.scala b/src/main/scala/util/Replacement.scala index 31fce89f..1509a276 100644 --- a/src/main/scala/util/Replacement.scala +++ b/src/main/scala/util/Replacement.scala @@ -1,7 +1,7 @@ // See LICENSE.Berkeley for license details. // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/ResetCatchAndSync.scala b/src/main/scala/util/ResetCatchAndSync.scala index 70976a18..f3f68a95 100644 --- a/src/main/scala/util/ResetCatchAndSync.scala +++ b/src/main/scala/util/ResetCatchAndSync.scala @@ -1,5 +1,6 @@ // See LICENSE.SiFive for license details. -package util + +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/ShiftQueue.scala b/src/main/scala/util/ShiftQueue.scala index 48a714c2..e3a2511f 100644 --- a/src/main/scala/util/ShiftQueue.scala +++ b/src/main/scala/util/ShiftQueue.scala @@ -1,6 +1,6 @@ // See LICENSE.SiFive for license details. -package util +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/Timer.scala b/src/main/scala/util/Timer.scala index 25a901cb..b933155e 100644 --- a/src/main/scala/util/Timer.scala +++ b/src/main/scala/util/Timer.scala @@ -1,7 +1,7 @@ // See LICENSE.SiFive for license details. // See LICENSE.Berkeley for license details. -package util +package freechips.rocketchip.util import Chisel._ diff --git a/src/main/scala/util/Package.scala b/src/main/scala/util/package.scala similarity index 69% rename from src/main/scala/util/Package.scala rename to src/main/scala/util/package.scala index ec9fe0e1..9661201c 100644 --- a/src/main/scala/util/Package.scala +++ b/src/main/scala/util/package.scala @@ -1,6 +1,9 @@ // See LICENSE.SiFive for license details. +package freechips.rocketchip + import Chisel._ +import scala.math.min package object util { implicit class UIntIsOneOf(val x: UInt) extends AnyVal { @@ -70,20 +73,27 @@ package object util { def option[T](z: => T): Option[T] = if (x) Some(z) else None } - object PopCountAtLeast { - private def two(x: UInt): (Bool, Bool) = x.getWidth match { - case 1 => (x.toBool, Bool(false)) - case n => - val half = x.getWidth / 2 - val (leftOne, leftTwo) = two(x(half - 1, 0)) - val (rightOne, rightTwo) = two(x(x.getWidth - 1, half)) - (leftOne || rightOne, leftTwo || rightTwo || (leftOne && rightOne)) - } - def apply(x: UInt, n: Int): Bool = n match { - case 0 => Bool(true) - case 1 => x.orR - case 2 => two(x)._2 - case 3 => PopCount(x) >= UInt(n) - } + def OH1ToOH(x: UInt): UInt = (x << 1 | UInt(1)) & ~Cat(UInt(0, width=1), x) + def OH1ToUInt(x: UInt): UInt = OHToUInt(OH1ToOH(x)) + def UIntToOH1(x: UInt, width: Int): UInt = ~(SInt(-1, width=width).asUInt << x)(width-1, 0) + + def trailingZeros(x: Int): Option[Int] = if (x > 0) Some(log2Ceil(x & -x)) else None + + // Fill 1s from low bits to high bits + def leftOR(x: UInt): UInt = leftOR(x, x.getWidth, x.getWidth) + def leftOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { + val stop = min(width, cap) + def helper(s: Int, x: UInt): UInt = + if (s >= stop) x else helper(s+s, x | (x << s)(width-1,0)) + helper(1, x)(width-1, 0) + } + + // Fill 1s form high bits to low bits + def rightOR(x: UInt): UInt = rightOR(x, x.getWidth, x.getWidth) + def rightOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { + val stop = min(width, cap) + def helper(s: Int, x: UInt): UInt = + if (s >= stop) x else helper(s+s, x | (x >> s)) + helper(1, x)(width-1, 0) } }