Combine Coreplex and System Module Hierarchies (#875)
* coreplex collapse: peripherals now in coreplex * coreplex: better factoring of TLBusWrapper attachement points * diplomacy: allow monitorless :*= and :=* * rocket: don't connect monitors to tile tim slave ports * rename chip package to system * coreplex: only sbus has a splitter * TLFragmenter: Continuing my spot battles on requires without explanatory strings * pbus: toFixedWidthSingleBeatSlave * tilelink: more verbose requires * use the new system package for regression * sbus: add more explicit FIFO attachment points * delete leftover top-level utils * cleanup ResetVector and RTC
This commit is contained in:
parent
f2002839eb
commit
01ca3efc2b
2
Makefrag
2
Makefrag
@ -4,7 +4,7 @@ $(error Please set environment variable RISCV. Please take a look at README)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
MODEL ?= TestHarness
|
MODEL ?= TestHarness
|
||||||
PROJECT ?= freechips.rocketchip.chip
|
PROJECT ?= freechips.rocketchip.system
|
||||||
CFG_PROJECT ?= $(PROJECT)
|
CFG_PROJECT ?= $(PROJECT)
|
||||||
CONFIG ?= DefaultConfig
|
CONFIG ?= DefaultConfig
|
||||||
# TODO: For now must match rocketchip.Generator
|
# TODO: For now must match rocketchip.Generator
|
||||||
|
26
README.md
26
README.md
@ -156,9 +156,6 @@ Here is a brief description of what can be found in each package:
|
|||||||
|
|
||||||
* **amba**
|
* **amba**
|
||||||
This RTL package uses diplomacy to generate bus implementations of AMBA protocols, including AXI4, AHB-lite, and APB.
|
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**
|
* **config**
|
||||||
This utility package provides Scala interfaces for configuring a generator via a dynamically-scoped
|
This utility package provides Scala interfaces for configuring a generator via a dynamically-scoped
|
||||||
parameterization library.
|
parameterization library.
|
||||||
@ -188,6 +185,9 @@ This RTL package contains components that can be combined with cores to construc
|
|||||||
* **tilelink**
|
* **tilelink**
|
||||||
This RTL package uses diplomacy to generate bus implementations of the TileLink protocol. It also contains a variety
|
This RTL package uses diplomacy to generate bus implementations of the TileLink protocol. It also contains a variety
|
||||||
of adapters and protocol converters.
|
of adapters and protocol converters.
|
||||||
|
* **system**
|
||||||
|
This top-level utility package invokes Chisel to elaborate a particular configuration of a coreplex,
|
||||||
|
along with the appropriate testing collateral.
|
||||||
* **unittest**
|
* **unittest**
|
||||||
This utility package contains a framework for generateing synthesizeable hardware testers of individual modules.
|
This utility package contains a framework for generateing synthesizeable hardware testers of individual modules.
|
||||||
* **util**
|
* **util**
|
||||||
@ -291,11 +291,11 @@ verilator.
|
|||||||
DefaultConfig.graphml
|
DefaultConfig.graphml
|
||||||
DefaultConfig.json
|
DefaultConfig.json
|
||||||
DefaultConfig.memmap.json
|
DefaultConfig.memmap.json
|
||||||
freechips.rocketchip.chip.DefaultConfig
|
freechips.rocketchip.system.DefaultConfig
|
||||||
freechips.rocketchip.chip.DefaultConfig.d
|
freechips.rocketchip.system.DefaultConfig.d
|
||||||
freechips.rocketchip.chip.DefaultConfig.fir
|
freechips.rocketchip.system.DefaultConfig.fir
|
||||||
freechips.rocketchip.chip.DefaultConfig.v
|
freechips.rocketchip.system.DefaultConfig.v
|
||||||
$ ls $ROCKETCHIP/emulator/generated-src/freechips.rocketchip.chip.DefaultConfig
|
$ ls $ROCKETCHIP/emulator/generated-src/freechips.rocketchip.system.DefaultConfig
|
||||||
VTestHarness__1.cpp
|
VTestHarness__1.cpp
|
||||||
VTestHarness__2.cpp
|
VTestHarness__2.cpp
|
||||||
VTestHarness__3.cpp
|
VTestHarness__3.cpp
|
||||||
@ -360,11 +360,11 @@ Top.DefaultConfig.conf file:
|
|||||||
DefaultConfig.graphml
|
DefaultConfig.graphml
|
||||||
DefaultConfig.json
|
DefaultConfig.json
|
||||||
DefaultConfig.memmap.json
|
DefaultConfig.memmap.json
|
||||||
freechips.rocketchip.chip.DefaultConfig.behav_srams.v
|
freechips.rocketchip.system.DefaultConfig.behav_srams.v
|
||||||
freechips.rocketchip.chip.DefaultConfig.conf
|
freechips.rocketchip.system.DefaultConfig.conf
|
||||||
freechips.rocketchip.chip.DefaultConfig.d
|
freechips.rocketchip.system.DefaultConfig.d
|
||||||
freechips.rocketchip.chip.DefaultConfig.fir
|
freechips.rocketchip.system.DefaultConfig.fir
|
||||||
freechips.rocketchip.chip.DefaultConfig.v
|
freechips.rocketchip.system.DefaultConfig.v
|
||||||
$ cat $ROCKETCHIP/vsim/generated-src/*.conf
|
$ cat $ROCKETCHIP/vsim/generated-src/*.conf
|
||||||
name data_arrays_0_ext depth 512 width 256 ports mrw mask_gran 8
|
name data_arrays_0_ext depth 512 width 256 ports mrw mask_gran 8
|
||||||
name tag_array_ext depth 64 width 88 ports mrw mask_gran 22
|
name tag_array_ext depth 64 width 88 ports mrw mask_gran 22
|
||||||
|
@ -42,17 +42,17 @@ $(error Set SUITE to the regression suite you want to run)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SUITE),RocketSuiteA)
|
ifeq ($(SUITE),RocketSuiteA)
|
||||||
PROJECT=freechips.rocketchip.chip
|
PROJECT=freechips.rocketchip.system
|
||||||
CONFIGS=DefaultConfig
|
CONFIGS=DefaultConfig
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SUITE),RocketSuiteB)
|
ifeq ($(SUITE),RocketSuiteB)
|
||||||
PROJECT=freechips.rocketchip.chip
|
PROJECT=freechips.rocketchip.system
|
||||||
CONFIGS=DefaultBufferlessConfig
|
CONFIGS=DefaultBufferlessConfig
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SUITE),RocketSuiteC)
|
ifeq ($(SUITE),RocketSuiteC)
|
||||||
PROJECT=freechips.rocketchip.chip
|
PROJECT=freechips.rocketchip.system
|
||||||
CONFIGS=TinyConfig
|
CONFIGS=TinyConfig
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ package freechips.rocketchip.amba.axi4
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import freechips.rocketchip.config.Parameters
|
import freechips.rocketchip.config.Parameters
|
||||||
import freechips.rocketchip.devices.tilelink.TLError
|
import freechips.rocketchip.devices.tilelink._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
import freechips.rocketchip.unittest._
|
import freechips.rocketchip.unittest._
|
||||||
@ -98,7 +98,7 @@ class AXI4FuzzSlave()(implicit p: Parameters) extends LazyModule with HasFuzzTar
|
|||||||
val node = AXI4InputNode()
|
val node = AXI4InputNode()
|
||||||
val xbar = LazyModule(new TLXbar)
|
val xbar = LazyModule(new TLXbar)
|
||||||
val ram = LazyModule(new TLRAM(fuzzAddr))
|
val ram = LazyModule(new TLRAM(fuzzAddr))
|
||||||
val error= LazyModule(new TLError(Seq(AddressSet(0x1800, 0xff))))
|
val error= LazyModule(new TLError(ErrorParams(Seq(AddressSet(0x1800, 0xff)))))
|
||||||
|
|
||||||
ram.node := TLFragmenter(4, 16)(xbar.node)
|
ram.node := TLFragmenter(4, 16)(xbar.node)
|
||||||
error.node := TLFragmenter(4, 16)(xbar.node)
|
error.node := TLFragmenter(4, 16)(xbar.node)
|
||||||
|
@ -1,166 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
// See LICENSE.Berkeley for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
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._
|
|
||||||
|
|
||||||
class BasePlatformConfig extends Config((site, here, up) => {
|
|
||||||
// DTS descriptive parameters
|
|
||||||
case DTSModel => "ucbbar,rocketchip-unknown"
|
|
||||||
case DTSCompat => Nil
|
|
||||||
case DTSTimebase => BigInt(1000000) // 1 MHz
|
|
||||||
case RTCPeriod => 1000 // Implies coreplex clock is DTSTimebase * RTCPeriod = 1 GHz
|
|
||||||
// TileLink connection parameters
|
|
||||||
case TLMonitorBuilder => (args: TLMonitorArgs) => Some(LazyModule(new TLMonitor(args)))
|
|
||||||
case TLCombinationalCheck => false
|
|
||||||
//Memory Parameters
|
|
||||||
case NExtTopInterrupts => 2
|
|
||||||
case SOCBusConfig => site(L1toL2Config)
|
|
||||||
case PeripheryBusConfig => TLBusConfig(beatBytes = 4)
|
|
||||||
case PeripheryBusArithmetic => true
|
|
||||||
// Default BootROMParams
|
|
||||||
case PeripheryBootROMKey => BootROMParams()
|
|
||||||
// Note that PLIC asserts that this is > 0.
|
|
||||||
case IncludeJtagDTM => false
|
|
||||||
case JtagDTMKey => new JtagDTMKeyDefault()
|
|
||||||
case ZeroConfig => ZeroConfig(base=0xa000000L, size=0x2000000L, beatBytes=8)
|
|
||||||
case ErrorConfig => ErrorConfig(Seq(AddressSet(0x3000, 0xfff)))
|
|
||||||
case ExtMem => MasterConfig(base=0x80000000L, size=0x10000000L, beatBytes=8, idBits=4)
|
|
||||||
case ExtBus => MasterConfig(base=0x60000000L, size=0x20000000L, beatBytes=8, idBits=4)
|
|
||||||
case ExtIn => SlaveConfig(beatBytes=8, idBits=8, sourceBits=4)
|
|
||||||
})
|
|
||||||
|
|
||||||
/** Actual elaboratable target Configs */
|
|
||||||
|
|
||||||
class BaseConfig extends Config(new BaseCoreplexConfig ++ new BasePlatformConfig)
|
|
||||||
class DefaultConfig extends Config(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 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 DualChannelConfig extends Config(new WithNMemoryChannels(2) ++ new BaseConfig)
|
|
||||||
|
|
||||||
class DualChannelDualBankConfig extends Config(
|
|
||||||
new WithNMemoryChannels(2) ++
|
|
||||||
new WithNBanksPerMemChannel(2) ++ new BaseConfig)
|
|
||||||
|
|
||||||
class RoccExampleConfig extends Config(new WithRoccExample ++ new DefaultConfig)
|
|
||||||
|
|
||||||
class Edge128BitConfig extends Config(
|
|
||||||
new WithEdgeDataBits(128) ++ new BaseConfig)
|
|
||||||
class Edge32BitConfig extends Config(
|
|
||||||
new WithEdgeDataBits(32) ++ new BaseConfig)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseConfig)
|
|
||||||
|
|
||||||
class DualCoreConfig extends Config(
|
|
||||||
new WithNBigCores(2) ++ new BaseConfig)
|
|
||||||
class HeterogeneousDualCoreConfig extends Config(
|
|
||||||
new WithNSmallCores(1) ++ new WithNBigCores(1) ++ new BaseConfig)
|
|
||||||
|
|
||||||
class TinyConfig extends Config(
|
|
||||||
new WithNMemoryChannels(0) ++
|
|
||||||
new WithStatelessBridge ++
|
|
||||||
new BaseConfig().alter((site, here, up) => {
|
|
||||||
case XLen => 32
|
|
||||||
case RocketTilesKey => Seq(
|
|
||||||
RocketTileParams(
|
|
||||||
core = RocketCoreParams(
|
|
||||||
useVM = false,
|
|
||||||
fpu = None,
|
|
||||||
mulDiv = Some(MulDivParams(mulUnroll = 8))),
|
|
||||||
btb = None,
|
|
||||||
dcache = Some(DCacheParams(
|
|
||||||
rowBits = site(L1toL2Config).beatBytes*8,
|
|
||||||
nSets = 256, // 16Kb scratchpad
|
|
||||||
nWays = 1,
|
|
||||||
nTLBEntries = 4,
|
|
||||||
nMSHRs = 0,
|
|
||||||
blockBytes = site(CacheBlockBytes),
|
|
||||||
scratch = Some(0x80000000L))),
|
|
||||||
icache = Some(ICacheParams(
|
|
||||||
rowBits = site(L1toL2Config).beatBytes*8,
|
|
||||||
nSets = 64,
|
|
||||||
nWays = 1,
|
|
||||||
nTLBEntries = 4,
|
|
||||||
blockBytes = site(CacheBlockBytes)))))}))
|
|
||||||
|
|
||||||
/* Composable partial function Configs to set individual parameters */
|
|
||||||
|
|
||||||
class WithEdgeDataBits(dataBits: Int) extends Config((site, here, up) => {
|
|
||||||
case ExtMem => up(ExtMem, site).copy(beatBytes = dataBits/8)
|
|
||||||
case ZeroConfig => up(ZeroConfig, site).copy(beatBytes = dataBits/8)
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithJtagDTM extends Config ((site, here, up) => {
|
|
||||||
case IncludeJtagDTM => true
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithNoPeripheryArithAMO extends Config ((site, here, up) => {
|
|
||||||
case PeripheryBusArithmetic => false
|
|
||||||
})
|
|
||||||
|
|
||||||
class With64BitPeriphery extends Config ((site, here, up) => {
|
|
||||||
case PeripheryBusConfig => TLBusConfig(beatBytes = 8)
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithoutTLMonitors extends Config ((site, here, up) => {
|
|
||||||
case TLMonitorBuilder => (args: TLMonitorArgs) => None
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithNExtTopInterrupts(nExtInts: Int) extends Config((site, here, up) => {
|
|
||||||
case NExtTopInterrupts => nExtInts
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithRTCPeriod(nCycles: Int) extends Config((site, here, up) => {
|
|
||||||
case RTCPeriod => nCycles
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithNMemoryChannels(n: Int) extends Config((site, here, up) => {
|
|
||||||
case BankedL2Config => up(BankedL2Config, site).copy(nMemoryChannels = n)
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithExtMemSize(n: Long) extends Config((site, here, up) => {
|
|
||||||
case ExtMem => up(ExtMem, site).copy(size = n)
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithDTS(model: String, compat: Seq[String]) extends Config((site, here, up) => {
|
|
||||||
case DTSModel => model
|
|
||||||
case DTSCompat => compat
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithTimebase(hertz: BigInt) extends Config((site, here, up) => {
|
|
||||||
case DTSTimebase => hertz
|
|
||||||
})
|
|
||||||
|
|
||||||
class DefaultFPGASmallConfig extends Config(new WithNSmallCores(1) ++ new DefaultFPGAConfig)
|
|
@ -1,39 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
import freechips.rocketchip.config.Parameters
|
|
||||||
|
|
||||||
/** Example system with periphery devices (w/o coreplex) */
|
|
||||||
abstract class ExampleSystem(implicit p: Parameters) extends BaseSystem
|
|
||||||
with HasPeripheryAsyncExtInterrupts
|
|
||||||
with HasPeripheryMasterAXI4MemPort
|
|
||||||
with HasPeripheryMasterAXI4MMIOPort
|
|
||||||
with HasPeripherySlaveAXI4Port
|
|
||||||
with HasPeripheryErrorSlave
|
|
||||||
with HasPeripheryZeroSlave {
|
|
||||||
override lazy val module = new ExampleSystemModule(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExampleSystemModule[+L <: ExampleSystem](_outer: L) extends BaseSystemModule(_outer)
|
|
||||||
with HasPeripheryExtInterruptsModuleImp
|
|
||||||
with HasPeripheryMasterAXI4MemPortModuleImp
|
|
||||||
with HasPeripheryMasterAXI4MMIOPortModuleImp
|
|
||||||
with HasPeripherySlaveAXI4PortModuleImp
|
|
||||||
|
|
||||||
/** Example Top with periphery and a Rocket coreplex */
|
|
||||||
class ExampleRocketTop(implicit p: Parameters) extends ExampleSystem
|
|
||||||
with HasPeripheryBootROM
|
|
||||||
with HasPeripheryDebug
|
|
||||||
with HasPeripheryRTCCounter
|
|
||||||
with HasRocketPlexMaster {
|
|
||||||
override lazy val module = new ExampleRocketTopModule(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExampleRocketTopModule[+L <: ExampleRocketTop](_outer: L) extends ExampleSystemModule(_outer)
|
|
||||||
with HasPeripheryBootROMModuleImp
|
|
||||||
with HasPeripheryDebugModuleImp
|
|
||||||
with HasPeripheryRTCCounterModuleImp
|
|
||||||
with HasRocketPlexMasterModuleImp
|
|
@ -1,374 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
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 */
|
|
||||||
case class MasterConfig(base: Long, size: Long, beatBytes: Int, idBits: Int)
|
|
||||||
case object ExtMem extends Field[MasterConfig]
|
|
||||||
case object ExtBus extends Field[MasterConfig]
|
|
||||||
case class SlaveConfig(beatBytes: Int, idBits: Int, sourceBits: Int)
|
|
||||||
case object ExtIn extends Field[SlaveConfig]
|
|
||||||
/** Specifies the number of external interrupts */
|
|
||||||
case object NExtTopInterrupts extends Field[Int]
|
|
||||||
/** Source of RTC. First bundle is TopIO.extra, Second bundle is periphery.io.extra **/
|
|
||||||
case object RTCPeriod extends Field[Int]
|
|
||||||
/* Specifies the periphery bus configuration */
|
|
||||||
case object PeripheryBusConfig extends Field[TLBusConfig]
|
|
||||||
case object PeripheryBusArithmetic extends Field[Boolean]
|
|
||||||
/* Specifies the SOC-bus configuration */
|
|
||||||
case object SOCBusConfig extends Field[TLBusConfig]
|
|
||||||
/* Specifies the location of the Zero device */
|
|
||||||
case class ZeroConfig(base: Long, size: Long, beatBytes: Int)
|
|
||||||
case object ZeroConfig extends Field[ZeroConfig]
|
|
||||||
/* Specifies the location of the Error device */
|
|
||||||
case class ErrorConfig(address: Seq[AddressSet])
|
|
||||||
case object ErrorConfig extends Field[ErrorConfig]
|
|
||||||
|
|
||||||
/** Utility trait for quick access to some relevant parameters */
|
|
||||||
trait HasPeripheryParameters {
|
|
||||||
implicit val p: Parameters
|
|
||||||
def peripheryBusConfig = p(PeripheryBusConfig)
|
|
||||||
def peripheryBusBytes = peripheryBusConfig.beatBytes
|
|
||||||
def socBusConfig = p(SOCBusConfig)
|
|
||||||
def socBusBytes = socBusConfig.beatBytes
|
|
||||||
def cacheBlockBytes = p(CacheBlockBytes)
|
|
||||||
def peripheryBusArithmetic = p(PeripheryBusArithmetic)
|
|
||||||
def nMemoryChannels = p(BankedL2Config).nMemoryChannels
|
|
||||||
def nExtInterrupts = p(NExtTopInterrupts)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** HasSystemNetworks provides buses that will serve as attachment points,
|
|
||||||
* for use in the following child traits that connect individual agents or external ports.
|
|
||||||
*/
|
|
||||||
trait HasSystemNetworks extends HasPeripheryParameters {
|
|
||||||
val socBus = LazyModule(new TLXbar) // Wide or unordered-access slave devices (TL-UH)
|
|
||||||
val peripheryBus = LazyModule(new TLXbar) // Narrow and ordered-access slave devices (TL-UL)
|
|
||||||
val intBus = LazyModule(new IntXbar) // Device and global external interrupts
|
|
||||||
val fsb = LazyModule(new TLBuffer(BufferParams.none)) // Master devices talking to the frontside of the L2
|
|
||||||
val bsb = LazyModule(new TLBuffer(BufferParams.none)) // Slave devices talking to the backside of the L2
|
|
||||||
val mem = Seq.fill(nMemoryChannels) { LazyModule(new TLXbar) } // Ports out to DRAM
|
|
||||||
|
|
||||||
// The peripheryBus hangs off of socBus;
|
|
||||||
// here we convert TL-UH -> TL-UL
|
|
||||||
peripheryBus.node :=
|
|
||||||
TLBuffer()(
|
|
||||||
TLWidthWidget(socBusConfig.beatBytes)(
|
|
||||||
TLAtomicAutomata(arithmetic = peripheryBusArithmetic)(
|
|
||||||
socBus.node)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This trait adds externally driven interrupts to the system.
|
|
||||||
* However, it should not be used directly; instead one of the below
|
|
||||||
* synchronization wiring child traits should be used.
|
|
||||||
*/
|
|
||||||
abstract trait HasPeripheryExtInterrupts extends HasSystemNetworks {
|
|
||||||
private val device = new Device with DeviceInterrupts {
|
|
||||||
def describe(resources: ResourceBindings): Description = {
|
|
||||||
Description("soc/external-interrupts", describeInterrupts(resources))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This trait should be used if the External Interrupts have NOT
|
|
||||||
* already been synchronized to the Periphery (PLIC) Clock.
|
|
||||||
*/
|
|
||||||
trait HasPeripheryAsyncExtInterrupts extends HasPeripheryExtInterrupts {
|
|
||||||
if (nExtInterrupts > 0) {
|
|
||||||
val extInterruptXing = LazyModule(new IntXing)
|
|
||||||
intBus.intnode := extInterruptXing.intnode
|
|
||||||
extInterruptXing.intnode := extInterrupts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This trait can be used if the External Interrupts have already been synchronized
|
|
||||||
* to the Periphery (PLIC) Clock.
|
|
||||||
*/
|
|
||||||
trait HasPeripherySyncExtInterrupts extends HasPeripheryExtInterrupts {
|
|
||||||
if (nExtInterrupts > 0) {
|
|
||||||
intBus.intnode := extInterrupts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Common io name and methods for propagating or tying off the port bundle */
|
|
||||||
trait HasPeripheryExtInterruptsBundle extends HasPeripheryParameters {
|
|
||||||
val interrupts: UInt
|
|
||||||
def tieOffInterrupts(dummy: Int = 1) {
|
|
||||||
interrupts := UInt(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This trait performs the translation from a UInt IO into Diplomatic Interrupts.
|
|
||||||
* The wiring must be done in the concrete LazyModuleImp.
|
|
||||||
*/
|
|
||||||
trait HasPeripheryExtInterruptsModuleImp extends LazyMultiIOModuleImp with HasPeripheryExtInterruptsBundle {
|
|
||||||
val outer: HasPeripheryExtInterrupts
|
|
||||||
val interrupts = IO(UInt(INPUT, width = outer.nExtInterrupts))
|
|
||||||
|
|
||||||
outer.extInterrupts.bundleIn.flatten.zipWithIndex.foreach { case(o, i) => o := interrupts(i) }
|
|
||||||
}
|
|
||||||
|
|
||||||
///// The following traits add ports to the sytem, in some cases converting to different interconnect standards
|
|
||||||
|
|
||||||
/** Adds a port to the system intended to master an AXI4 DRAM controller. */
|
|
||||||
trait HasPeripheryMasterAXI4MemPort extends HasSystemNetworks {
|
|
||||||
val module: HasPeripheryMasterAXI4MemPortModuleImp
|
|
||||||
|
|
||||||
private val config = p(ExtMem)
|
|
||||||
private val channels = p(BankedL2Config).nMemoryChannels
|
|
||||||
private val blockBytes = p(CacheBlockBytes)
|
|
||||||
|
|
||||||
private val device = new MemoryDevice
|
|
||||||
|
|
||||||
val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(channels) { channel =>
|
|
||||||
val base = AddressSet(config.base, config.size-1)
|
|
||||||
val filter = AddressSet(channel * blockBytes, ~((channels-1) * blockBytes))
|
|
||||||
|
|
||||||
AXI4SlavePortParameters(
|
|
||||||
slaves = Seq(AXI4SlaveParameters(
|
|
||||||
address = base.intersect(filter).toList,
|
|
||||||
resources = device.reg,
|
|
||||||
regionType = RegionType.UNCACHED, // cacheable
|
|
||||||
executable = true,
|
|
||||||
supportsWrite = TransferSizes(1, blockBytes),
|
|
||||||
supportsRead = TransferSizes(1, blockBytes),
|
|
||||||
interleavedId = Some(0))), // slave does not interleave read responses
|
|
||||||
beatBytes = config.beatBytes)
|
|
||||||
})
|
|
||||||
|
|
||||||
private val converter = LazyModule(new TLToAXI4(config.beatBytes))
|
|
||||||
private val trim = LazyModule(new AXI4IdIndexer(config.idBits))
|
|
||||||
private val yank = LazyModule(new AXI4UserYanker)
|
|
||||||
private val buffer = LazyModule(new AXI4Buffer)
|
|
||||||
|
|
||||||
mem foreach { case xbar =>
|
|
||||||
converter.node := xbar.node
|
|
||||||
trim.node := converter.node
|
|
||||||
yank.node := trim.node
|
|
||||||
buffer.node := yank.node
|
|
||||||
mem_axi4 := buffer.node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Common io name and methods for propagating or tying off the port bundle */
|
|
||||||
trait HasPeripheryMasterAXI4MemPortBundle extends HasPeripheryParameters {
|
|
||||||
val mem_axi4: HeterogeneousBag[AXI4Bundle]
|
|
||||||
def connectSimAXIMem(dummy: Int = 1) = {
|
|
||||||
if (nMemoryChannels > 0) Module(LazyModule(new SimAXIMem(nMemoryChannels)).module).io.axi4 <> mem_axi4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Actually generates the corresponding IO in the concrete Module */
|
|
||||||
trait HasPeripheryMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterAXI4MemPortBundle {
|
|
||||||
val outer: HasPeripheryMasterAXI4MemPort
|
|
||||||
val mem_axi4 = IO(outer.mem_axi4.bundleOut)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds a AXI4 port to the system intended to master an MMIO device bus */
|
|
||||||
trait HasPeripheryMasterAXI4MMIOPort extends HasSystemNetworks {
|
|
||||||
private val config = p(ExtBus)
|
|
||||||
private val device = new SimpleBus("mmio", Nil)
|
|
||||||
val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters(
|
|
||||||
slaves = Seq(AXI4SlaveParameters(
|
|
||||||
address = List(AddressSet(BigInt(config.base), config.size-1)),
|
|
||||||
resources = device.ranges,
|
|
||||||
executable = true, // Can we run programs on this memory?
|
|
||||||
supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers
|
|
||||||
supportsRead = TransferSizes(1, 256))),
|
|
||||||
beatBytes = config.beatBytes)))
|
|
||||||
|
|
||||||
mmio_axi4 :=
|
|
||||||
AXI4Buffer()(
|
|
||||||
AXI4UserYanker()(
|
|
||||||
AXI4Deinterleaver(cacheBlockBytes)(
|
|
||||||
AXI4IdIndexer(config.idBits)(
|
|
||||||
TLToAXI4(config.beatBytes)(
|
|
||||||
TLWidthWidget(socBusConfig.beatBytes)( // convert width before attaching to socBus
|
|
||||||
socBus.node))))))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Common io name and methods for propagating or tying off the port bundle */
|
|
||||||
trait HasPeripheryMasterAXI4MMIOPortBundle extends HasPeripheryParameters {
|
|
||||||
val mmio_axi4: HeterogeneousBag[AXI4Bundle]
|
|
||||||
def connectSimAXIMMIO(dummy: Int = 1) {
|
|
||||||
Module(LazyModule(new SimAXIMem(1, 4096)).module).io.axi4 <> mmio_axi4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Actually generates the corresponding IO in the concrete Module */
|
|
||||||
trait HasPeripheryMasterAXI4MMIOPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterAXI4MMIOPortBundle {
|
|
||||||
val outer: HasPeripheryMasterAXI4MMIOPort
|
|
||||||
val mmio_axi4 = IO(outer.mmio_axi4.bundleOut)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */
|
|
||||||
trait HasPeripherySlaveAXI4Port extends HasSystemNetworks {
|
|
||||||
private val config = p(ExtIn)
|
|
||||||
val l2FrontendAXI4Node = AXI4BlindInputNode(Seq(AXI4MasterPortParameters(
|
|
||||||
masters = Seq(AXI4MasterParameters(
|
|
||||||
name = "AXI4 periphery",
|
|
||||||
id = IdRange(0, 1 << config.idBits))))))
|
|
||||||
|
|
||||||
private val fifoBits = 1
|
|
||||||
fsb.node :=
|
|
||||||
TLWidthWidget(config.beatBytes)(
|
|
||||||
AXI4ToTL()(
|
|
||||||
AXI4UserYanker(Some(1 << (config.sourceBits - fifoBits - 1)))(
|
|
||||||
AXI4Fragmenter()(
|
|
||||||
AXI4IdIndexer(fifoBits)(
|
|
||||||
l2FrontendAXI4Node)))))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Common io name and methods for propagating or tying off the port bundle */
|
|
||||||
trait HasPeripherySlaveAXI4PortBundle extends HasPeripheryParameters {
|
|
||||||
val l2_frontend_bus_axi4: HeterogeneousBag[AXI4Bundle]
|
|
||||||
def tieOffAXI4SlavePort(dummy: Int = 1) {
|
|
||||||
l2_frontend_bus_axi4.foreach { l2_axi4 =>
|
|
||||||
l2_axi4.ar.valid := Bool(false)
|
|
||||||
l2_axi4.aw.valid := Bool(false)
|
|
||||||
l2_axi4.w .valid := Bool(false)
|
|
||||||
l2_axi4.r .ready := Bool(true)
|
|
||||||
l2_axi4.b .ready := Bool(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Actually generates the corresponding IO in the concrete Module */
|
|
||||||
trait HasPeripherySlaveAXI4PortModuleImp extends LazyMultiIOModuleImp with HasPeripherySlaveAXI4PortBundle {
|
|
||||||
val outer: HasPeripherySlaveAXI4Port
|
|
||||||
val l2_frontend_bus_axi4 = IO(outer.l2FrontendAXI4Node.bundleIn)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds a TileLink port to the system intended to master an MMIO device bus */
|
|
||||||
trait HasPeripheryMasterTLMMIOPort extends HasSystemNetworks {
|
|
||||||
private val config = p(ExtBus)
|
|
||||||
private val device = new SimpleBus("mmio", Nil)
|
|
||||||
val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters(
|
|
||||||
managers = Seq(TLManagerParameters(
|
|
||||||
address = List(AddressSet(BigInt(config.base), config.size-1)),
|
|
||||||
resources = device.ranges,
|
|
||||||
executable = true,
|
|
||||||
supportsGet = TransferSizes(1, cacheBlockBytes),
|
|
||||||
supportsPutFull = TransferSizes(1, cacheBlockBytes),
|
|
||||||
supportsPutPartial = TransferSizes(1, cacheBlockBytes))),
|
|
||||||
beatBytes = config.beatBytes)))
|
|
||||||
|
|
||||||
mmio_tl :=
|
|
||||||
TLBuffer()(
|
|
||||||
TLSourceShrinker(1 << config.idBits)(
|
|
||||||
TLWidthWidget(socBusConfig.beatBytes)(
|
|
||||||
socBus.node)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Common io name and methods for propagating or tying off the port bundle */
|
|
||||||
trait HasPeripheryMasterTLMMIOPortBundle extends HasPeripheryParameters {
|
|
||||||
val mmio_tl: HeterogeneousBag[TLBundle]
|
|
||||||
def tieOffTLMMIO(dummy: Int = 1) {
|
|
||||||
mmio_tl.foreach { tl =>
|
|
||||||
tl.a.ready := Bool(true)
|
|
||||||
tl.b.valid := Bool(false)
|
|
||||||
tl.c.ready := Bool(true)
|
|
||||||
tl.d.valid := Bool(false)
|
|
||||||
tl.e.ready := Bool(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Actually generates the corresponding IO in the concrete Module */
|
|
||||||
trait HasPeripheryMasterTLMMIOPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterTLMMIOPortBundle {
|
|
||||||
val outer: HasPeripheryMasterTLMMIOPort
|
|
||||||
val mmio_tl = IO(outer.mmio_tl.bundleOut)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus.
|
|
||||||
* NOTE: this port is NOT allowed to issue Acquires.
|
|
||||||
*/
|
|
||||||
trait HasPeripherySlaveTLPort extends HasSystemNetworks {
|
|
||||||
private val config = p(ExtIn)
|
|
||||||
val l2FrontendTLNode = TLBlindInputNode(Seq(TLClientPortParameters(
|
|
||||||
clients = Seq(TLClientParameters(
|
|
||||||
name = "TL periph",
|
|
||||||
sourceId = IdRange(0, 1 << config.idBits))))))
|
|
||||||
|
|
||||||
fsb.node :=
|
|
||||||
TLSourceShrinker(1 << config.sourceBits)(
|
|
||||||
TLWidthWidget(config.beatBytes)(
|
|
||||||
l2FrontendTLNode))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Common io name and methods for propagating or tying off the port bundle */
|
|
||||||
trait HasPeripherySlaveTLPortBundle extends HasPeripheryParameters {
|
|
||||||
val l2_frontend_bus_tl: HeterogeneousBag[TLBundle]
|
|
||||||
def tieOffSlaveTLPort(dummy: Int = 1) {
|
|
||||||
l2_frontend_bus_tl.foreach { tl =>
|
|
||||||
tl.a.valid := Bool(false)
|
|
||||||
tl.b.ready := Bool(true)
|
|
||||||
tl.c.valid := Bool(false)
|
|
||||||
tl.d.ready := Bool(true)
|
|
||||||
tl.e.valid := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Actually generates the corresponding IO in the concrete Module */
|
|
||||||
trait HasPeripherySlaveTLPortModuleImp extends LazyMultiIOModuleImp with HasPeripherySlaveTLPortBundle {
|
|
||||||
val outer: HasPeripherySlaveTLPort
|
|
||||||
val l2_frontend_bus_tl = IO(outer.l2FrontendTLNode.bundleIn)
|
|
||||||
}
|
|
||||||
|
|
||||||
///// The following traits add specific devices to the periphery of the system.
|
|
||||||
|
|
||||||
/** Adds a /dev/null slave that generates */
|
|
||||||
trait HasPeripheryZeroSlave extends HasSystemNetworks {
|
|
||||||
private val config = p(ZeroConfig)
|
|
||||||
private val channels = p(BankedL2Config).nMemoryChannels
|
|
||||||
private val blockBytes = p(CacheBlockBytes)
|
|
||||||
|
|
||||||
private val device = new SimpleDevice("rom", Seq("ucbbar,cacheable-zero0"))
|
|
||||||
|
|
||||||
val zeros = mem.zipWithIndex.map { case (xbar, channel) =>
|
|
||||||
val base = AddressSet(config.base, config.size-1)
|
|
||||||
val filter = AddressSet(channel * blockBytes, ~((channels-1) * blockBytes))
|
|
||||||
val address = base.intersect(filter).get
|
|
||||||
val zero = LazyModule(new TLZero(address, beatBytes = config.beatBytes, resources = device.reg("mem")))
|
|
||||||
zero.node := TLFragmenter(config.beatBytes, blockBytes)(xbar.node)
|
|
||||||
zero
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds a /dev/null slave that generates TL2 error response messages. */
|
|
||||||
trait HasPeripheryErrorSlave extends HasSystemNetworks {
|
|
||||||
private val config = p(ErrorConfig)
|
|
||||||
private val maxXfer = min(config.address.map(_.alignment).max.toInt, 4096)
|
|
||||||
val error = LazyModule(new TLError(config.address, peripheryBusConfig.beatBytes))
|
|
||||||
|
|
||||||
// Most slaves do not support a 4kB burst so this slave ends up with many more source bits than others;
|
|
||||||
// we exclude the onerously large TLMonitor that results.
|
|
||||||
error.node connectButDontMonitor TLFragmenter(peripheryBusConfig.beatBytes, maxXfer)(peripheryBus.node)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Adds a SRAM to the system for testing purposes. */
|
|
||||||
trait HasPeripheryTestRAMSlave extends HasSystemNetworks {
|
|
||||||
val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), true, peripheryBusConfig.beatBytes))
|
|
||||||
testram.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds a fuzzing master to the system for testing purposes. */
|
|
||||||
trait HasPeripheryTestFuzzMaster extends HasSystemNetworks {
|
|
||||||
val fuzzer = LazyModule(new TLFuzzer(5000))
|
|
||||||
peripheryBus.node := fuzzer.node
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
trait HasCoreplexRISCVPlatform {
|
|
||||||
implicit val p: Parameters
|
|
||||||
val coreplex: CoreplexRISCVPlatform
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A wrapper around JTAG providing a reset signal and manufacturer id. */
|
|
||||||
class SystemJTAGIO extends Bundle {
|
|
||||||
val jtag = new JTAGIO(hasTRSTn = false).flip
|
|
||||||
val reset = Bool(INPUT)
|
|
||||||
val mfr_id = UInt(INPUT, 11)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A wrapper bundle containing one of the two possible debug interfaces */
|
|
||||||
class DebugIO(implicit p: Parameters) extends ParameterizedBundle()(p) {
|
|
||||||
val clockeddmi = (!p(IncludeJtagDTM)).option(new ClockedDMIIO().flip)
|
|
||||||
val systemjtag = (p(IncludeJtagDTM)).option(new SystemJTAGIO)
|
|
||||||
val ndreset = Bool(OUTPUT)
|
|
||||||
val dmactive = Bool(OUTPUT)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Either adds a JTAG DTM to system, and exports a JTAG interface,
|
|
||||||
* or exports the Debug Module Interface (DMI), based on a global parameter.
|
|
||||||
*/
|
|
||||||
trait HasPeripheryDebug extends HasSystemNetworks with HasCoreplexRISCVPlatform {
|
|
||||||
val module: HasPeripheryDebugModuleImp
|
|
||||||
}
|
|
||||||
|
|
||||||
trait HasPeripheryDebugBundle extends HasPeripheryParameters {
|
|
||||||
val debug: DebugIO
|
|
||||||
def connectDebug(c: Clock, r: Bool, out: Bool) {
|
|
||||||
debug.clockeddmi.foreach { d =>
|
|
||||||
val dtm = Module(new SimDTM).connect(c, r, d, out)
|
|
||||||
}
|
|
||||||
debug.systemjtag.foreach { sj =>
|
|
||||||
val jtag = Module(new JTAGVPI).connect(sj.jtag, sj.reset, r, out)
|
|
||||||
sj.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait HasPeripheryDebugModuleImp extends LazyMultiIOModuleImp with HasPeripheryDebugBundle {
|
|
||||||
val outer: HasPeripheryDebug
|
|
||||||
|
|
||||||
val debug = IO(new DebugIO)
|
|
||||||
|
|
||||||
debug.clockeddmi.foreach { dbg => outer.coreplex.module.io.debug <> dbg }
|
|
||||||
|
|
||||||
val dtm = debug.systemjtag.map { sj =>
|
|
||||||
val dtm = Module(new DebugTransportModuleJTAG(p(DMKey).nDMIAddrSize, p(JtagDTMKey)))
|
|
||||||
dtm.io.jtag <> sj.jtag
|
|
||||||
|
|
||||||
dtm.clock := sj.jtag.TCK
|
|
||||||
dtm.io.jtag_reset := sj.reset
|
|
||||||
dtm.io.jtag_mfr_id := sj.mfr_id
|
|
||||||
dtm.reset := dtm.io.fsmReset
|
|
||||||
|
|
||||||
outer.coreplex.module.io.debug.dmi <> dtm.io.dmi
|
|
||||||
outer.coreplex.module.io.debug.dmiClock := sj.jtag.TCK
|
|
||||||
outer.coreplex.module.io.debug.dmiReset := ResetCatchAndSync(sj.jtag.TCK, sj.reset, "dmiResetCatch")
|
|
||||||
dtm
|
|
||||||
}
|
|
||||||
|
|
||||||
debug.ndreset := outer.coreplex.module.io.ndreset
|
|
||||||
debug.dmactive := outer.coreplex.module.io.dmactive
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Real-time clock is based on RTCPeriod relative to system clock.
|
|
||||||
* Note: nothing about this is diplomatic, all the work is done in the ModuleImp
|
|
||||||
*/
|
|
||||||
trait HasPeripheryRTCCounter extends HasSystemNetworks with HasCoreplexRISCVPlatform {
|
|
||||||
val module: HasPeripheryRTCCounterModuleImp
|
|
||||||
}
|
|
||||||
|
|
||||||
trait HasPeripheryRTCCounterModuleImp extends LazyMultiIOModuleImp {
|
|
||||||
val outer: HasPeripheryRTCCounter
|
|
||||||
val period = p(RTCPeriod)
|
|
||||||
val rtcCounter = RegInit(UInt(0, width = log2Up(period)))
|
|
||||||
val rtcWrap = rtcCounter === UInt(period-1)
|
|
||||||
|
|
||||||
rtcCounter := Mux(rtcWrap, UInt(0), rtcCounter + UInt(1))
|
|
||||||
outer.coreplex.module.io.rtcToggle := rtcCounter(log2Up(period)-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds a boot ROM that contains the DTB describing the system's coreplex. */
|
|
||||||
case class BootROMParams(address: BigInt = 0x10000, size: Int = 0x10000, hang: BigInt = 0x10040)
|
|
||||||
|
|
||||||
case object PeripheryBootROMKey extends Field[BootROMParams]
|
|
||||||
|
|
||||||
trait HasPeripheryBootROM extends HasSystemNetworks with HasCoreplexRISCVPlatform {
|
|
||||||
val bootROMParams = p(PeripheryBootROMKey)
|
|
||||||
val bootrom_address = bootROMParams.address
|
|
||||||
val bootrom_size = bootROMParams.size
|
|
||||||
val bootrom_hang = bootROMParams.hang
|
|
||||||
private lazy val bootrom_contents = GenerateBootROM(coreplex.dtb)
|
|
||||||
val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes))
|
|
||||||
|
|
||||||
bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Coreplex will power-on running at 0x10040 (BootROM) */
|
|
||||||
trait HasPeripheryBootROMModuleImp extends LazyMultiIOModuleImp {
|
|
||||||
val outer: HasPeripheryBootROM
|
|
||||||
outer.coreplex.module.io.resetVector := UInt(outer.bootrom_hang)
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
import freechips.rocketchip.coreplex.RocketPlex
|
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
|
|
||||||
|
|
||||||
/** Add a RocketPlex to the system */
|
|
||||||
trait HasRocketPlexMaster extends HasSystemNetworks with HasCoreplexRISCVPlatform {
|
|
||||||
val module: HasRocketPlexMasterModuleImp
|
|
||||||
|
|
||||||
val coreplex = LazyModule(new RocketPlex)
|
|
||||||
|
|
||||||
coreplex.l2in :=* fsb.node
|
|
||||||
bsb.node :*= coreplex.l2out
|
|
||||||
socBus.node := coreplex.mmio
|
|
||||||
coreplex.mmioInt := intBus.intnode
|
|
||||||
|
|
||||||
require (mem.size == coreplex.mem.size)
|
|
||||||
(mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
trait HasRocketPlexMasterModuleImp extends LazyMultiIOModuleImp {
|
|
||||||
val outer: HasRocketPlexMaster
|
|
||||||
|
|
||||||
outer.coreplex.module.io.tcrs.foreach { case tcr =>
|
|
||||||
tcr.clock := clock
|
|
||||||
tcr.reset := reset
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
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 {
|
|
||||||
ElaborationArtefacts.add("graphml", graphML)
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class BareSystemModule[+L <: BareSystem](_outer: L) extends LazyMultiIOModuleImp(_outer) {
|
|
||||||
val outer = _outer
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Base System class with no peripheral devices or ports added */
|
|
||||||
abstract class BaseSystem(implicit p: Parameters) extends BareSystem with HasSystemNetworks {
|
|
||||||
override val module: BaseSystemModule[BaseSystem]
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class BaseSystemModule[+L <: BaseSystem](_outer: L) extends BareSystemModule(_outer)
|
|
@ -1,95 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
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 {
|
|
||||||
val success = Bool(OUTPUT)
|
|
||||||
}
|
|
||||||
|
|
||||||
val dut = Module(LazyModule(new ExampleRocketTop).module)
|
|
||||||
dut.reset := reset | dut.debug.ndreset
|
|
||||||
|
|
||||||
dut.tieOffInterrupts()
|
|
||||||
dut.connectSimAXIMem()
|
|
||||||
dut.connectSimAXIMMIO()
|
|
||||||
dut.tieOffAXI4SlavePort()
|
|
||||||
dut.connectDebug(clock, reset, io.success)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) extends LazyModule {
|
|
||||||
val config = p(ExtMem)
|
|
||||||
val totalSize = if (forceSize > 0) forceSize else BigInt(config.size)
|
|
||||||
val size = totalSize / channels
|
|
||||||
require(totalSize % channels == 0)
|
|
||||||
|
|
||||||
val node = AXI4BlindInputNode(Seq.fill(channels) {
|
|
||||||
AXI4MasterPortParameters(Seq(AXI4MasterParameters(
|
|
||||||
name = "dut",
|
|
||||||
id = IdRange(0, 1 << config.idBits))))})
|
|
||||||
|
|
||||||
for (i <- 0 until channels) {
|
|
||||||
val sram = LazyModule(new AXI4RAM(AddressSet(0, size-1), beatBytes = config.beatBytes))
|
|
||||||
sram.node := AXI4Buffer()(AXI4Fragmenter()(node))
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
|
||||||
val io = new Bundle {
|
|
||||||
val axi4 = node.bundleIn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimDTM(implicit p: Parameters) extends BlackBox {
|
|
||||||
val io = new Bundle {
|
|
||||||
val clk = Clock(INPUT)
|
|
||||||
val reset = Bool(INPUT)
|
|
||||||
val debug = new DMIIO
|
|
||||||
val exit = UInt(OUTPUT, 32)
|
|
||||||
}
|
|
||||||
|
|
||||||
def connect(tbclk: Clock, tbreset: Bool, dutio: ClockedDMIIO, tbsuccess: Bool) = {
|
|
||||||
io.clk := tbclk
|
|
||||||
io.reset := tbreset
|
|
||||||
dutio.dmi <> io.debug
|
|
||||||
dutio.dmiClock := tbclk
|
|
||||||
dutio.dmiReset := tbreset
|
|
||||||
|
|
||||||
tbsuccess := io.exit === UInt(1)
|
|
||||||
when (io.exit >= UInt(2)) {
|
|
||||||
printf("*** FAILED *** (exit code = %d)\n", io.exit >> UInt(1))
|
|
||||||
stop(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class JTAGVPI(implicit val p: Parameters) extends BlackBox {
|
|
||||||
val io = new Bundle {
|
|
||||||
val jtag = new JTAGIO(hasTRSTn = false)
|
|
||||||
val enable = Bool(INPUT)
|
|
||||||
val init_done = Bool(INPUT)
|
|
||||||
}
|
|
||||||
|
|
||||||
def connect(dutio: JTAGIO, jtag_reset: Bool, tbreset: Bool, tbsuccess: Bool) = {
|
|
||||||
dutio <> io.jtag
|
|
||||||
|
|
||||||
dutio.TRSTn.foreach{ _:= false.B}
|
|
||||||
jtag_reset := tbreset
|
|
||||||
|
|
||||||
io.enable := ~tbreset
|
|
||||||
io.init_done := ~tbreset
|
|
||||||
|
|
||||||
// Success is determined by the gdbserver
|
|
||||||
// which is controlling this simulation.
|
|
||||||
tbsuccess := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
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
|
|
||||||
private val l = collection.mutable.ListBuffer[(String, Int)]()
|
|
||||||
def add(name: String, element: Int) = { require(!finalized); l += (name -> element) }
|
|
||||||
def rangeMap = {
|
|
||||||
finalized = true
|
|
||||||
(l map {
|
|
||||||
var sum = 0
|
|
||||||
x => { sum += x._2; (x._1 -> (sum-x._2, sum)) }
|
|
||||||
}).toMap
|
|
||||||
}
|
|
||||||
def range(name: String) = rangeMap(name)
|
|
||||||
def print = {
|
|
||||||
rangeMap.toSeq.sortBy(_._2).foreach { case (name, (start, end)) =>
|
|
||||||
println(s"${name} on int ${start}-${end-1}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def sum = {
|
|
||||||
finalized = true
|
|
||||||
l.map(_._2).sum
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ResourceManager[T] {
|
|
||||||
private var finalized = false
|
|
||||||
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 }
|
|
||||||
}
|
|
||||||
|
|
||||||
class GlobalVariable[T] {
|
|
||||||
private var assigned = false
|
|
||||||
private var variable: T = _
|
|
||||||
def assign(value: T) = { require(!assigned); assigned = true; variable = value }
|
|
||||||
def get: T = { require(assigned); variable }
|
|
||||||
}
|
|
||||||
|
|
||||||
object GenerateBootROM {
|
|
||||||
def apply(dtb: DTB)(implicit p: Parameters) = {
|
|
||||||
val romdata = Files.readAllBytes(Paths.get(p(BootROMFile)))
|
|
||||||
val rom = ByteBuffer.wrap(romdata)
|
|
||||||
rom.array() ++ dtb.contents
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,83 +3,133 @@
|
|||||||
package freechips.rocketchip.coreplex
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
import freechips.rocketchip.config._
|
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.tile.{ XLen, TileInterrupts}
|
import freechips.rocketchip.rocket.PAddrBits
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
/** Widths of various points in the SoC */
|
/** Enumerates the three types of clock crossing between tiles and system bus */
|
||||||
case class TLBusConfig(beatBytes: Int)
|
sealed trait CoreplexClockCrossing
|
||||||
case object CBusConfig extends Field[TLBusConfig]
|
case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends CoreplexClockCrossing
|
||||||
case object L1toL2Config extends Field[TLBusConfig]
|
case class RationalCrossing(direction: RationalDirection = FastToSlow) extends CoreplexClockCrossing
|
||||||
|
case class AsynchronousCrossing(depth: Int, sync: Int = 2) extends CoreplexClockCrossing
|
||||||
|
|
||||||
// These parameters apply to all caches, for now
|
/** BareCoreplex is the root class for creating a coreplex sub-system */
|
||||||
case object CacheBlockBytes extends Field[Int]
|
abstract class BareCoreplex(implicit p: Parameters) extends LazyModule with BindingScope {
|
||||||
|
lazy val dts = DTS(bindingTree)
|
||||||
/** L2 Broadcast Hub configuration */
|
lazy val dtb = DTB(dts)
|
||||||
case class BroadcastConfig(
|
lazy val json = JSON(bindingTree)
|
||||||
nTrackers: Int = 4,
|
|
||||||
bufferless: Boolean = false)
|
|
||||||
case object BroadcastConfig extends Field[BroadcastConfig]
|
|
||||||
|
|
||||||
/** L2 memory subsystem configuration */
|
|
||||||
case class BankedL2Config(
|
|
||||||
nMemoryChannels: Int = 1,
|
|
||||||
nBanksPerChannel: Int = 1,
|
|
||||||
coherenceManager: (Parameters, CoreplexNetwork) => (TLInwardNode, TLOutwardNode) = { case (q, _) =>
|
|
||||||
implicit val p = q
|
|
||||||
val BroadcastConfig(nTrackers, bufferless) = p(BroadcastConfig)
|
|
||||||
val bh = LazyModule(new TLBroadcast(p(CacheBlockBytes), nTrackers, bufferless))
|
|
||||||
val ww = LazyModule(new TLWidthWidget(p(L1toL2Config).beatBytes))
|
|
||||||
ww.node :*= bh.node
|
|
||||||
(bh.node, ww.node)
|
|
||||||
}) {
|
|
||||||
val nBanks = nMemoryChannels*nBanksPerChannel
|
|
||||||
}
|
|
||||||
case object BankedL2Config extends Field[BankedL2Config]
|
|
||||||
|
|
||||||
/** The file to read the BootROM contents from */
|
|
||||||
case object BootROMFile extends Field[String]
|
|
||||||
|
|
||||||
trait HasCoreplexParameters {
|
|
||||||
implicit val p: Parameters
|
|
||||||
lazy val tilesParams = p(RocketTilesKey)
|
|
||||||
lazy val sbusConfig = p(L1toL2Config)
|
|
||||||
lazy val pbusConfig = p(CBusConfig)
|
|
||||||
lazy val nTiles = tilesParams.size
|
|
||||||
lazy val l2Config = p(BankedL2Config)
|
|
||||||
def sbusBeatBytes = sbusConfig.beatBytes
|
|
||||||
def sbusBlockBytes = p(CacheBlockBytes)
|
|
||||||
def pbusBeatBytes = pbusConfig.beatBytes
|
|
||||||
def pbusBlockBytes = sbusBlockBytes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters
|
abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyMultiIOModuleImp(_outer) {
|
||||||
|
|
||||||
abstract class BareCoreplex(implicit p: Parameters) extends LazyModule with BindingScope
|
|
||||||
|
|
||||||
abstract class BareCoreplexBundle[+L <: BareCoreplex](_outer: L) extends GenericParameterizedBundle(_outer) {
|
|
||||||
val outer = _outer
|
val outer = _outer
|
||||||
implicit val p = outer.p
|
ElaborationArtefacts.add("graphml", outer.graphML)
|
||||||
}
|
ElaborationArtefacts.add("dts", outer.dts)
|
||||||
|
ElaborationArtefacts.add("json", outer.json)
|
||||||
abstract class BareCoreplexModule[+L <: BareCoreplex, +B <: BareCoreplexBundle[L]](_outer: L, _io: () => B) extends LazyModuleImp(_outer) {
|
println(outer.dts)
|
||||||
val outer = _outer
|
|
||||||
val io = _io ()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Base Coreplex class with no peripheral devices or ports added */
|
||||||
abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex
|
abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex
|
||||||
with CoreplexNetwork
|
with HasInterruptBus
|
||||||
with BankedL2CoherenceManagers {
|
with HasSystemBus
|
||||||
override lazy val module = new BaseCoreplexModule(this, () => new BaseCoreplexBundle(this))
|
with HasPeripheryBus
|
||||||
|
with HasMemoryBus {
|
||||||
|
override val module: BaseCoreplexModule[BaseCoreplex]
|
||||||
|
|
||||||
|
val root = new Device {
|
||||||
|
def describe(resources: ResourceBindings): Description = {
|
||||||
|
val width = resources("width").map(_.value)
|
||||||
|
Description("/", Map(
|
||||||
|
"#address-cells" -> width,
|
||||||
|
"#size-cells" -> width,
|
||||||
|
"model" -> Seq(ResourceString(p(DTSModel))),
|
||||||
|
"compatible" -> (p(DTSModel) +: p(DTSCompat)).map(s => ResourceString(s + "-dev"))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val soc = new Device {
|
||||||
|
def describe(resources: ResourceBindings): Description = {
|
||||||
|
val width = resources("width").map(_.value)
|
||||||
|
Description("soc", Map(
|
||||||
|
"#address-cells" -> width,
|
||||||
|
"#size-cells" -> width,
|
||||||
|
"compatible" -> ((p(DTSModel) +: p(DTSCompat)).map(s => ResourceString(s + "-soc")) :+ ResourceString("simple-bus")),
|
||||||
|
"ranges" -> Nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val cpus = new Device {
|
||||||
|
def describe(resources: ResourceBindings): Description = {
|
||||||
|
Description("cpus", Map(
|
||||||
|
"#address-cells" -> Seq(ResourceInt(1)),
|
||||||
|
"#size-cells" -> Seq(ResourceInt(0)),
|
||||||
|
"timebase-frequency" -> Seq(ResourceInt(p(DTSTimebase)))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make topManagers an Option[] so as to avoid LM name reflection evaluating it...
|
||||||
|
lazy val topManagers = Some(ManagerUnification(sharedMemoryTLEdge.manager.managers))
|
||||||
|
ResourceBinding {
|
||||||
|
val managers = topManagers.get
|
||||||
|
val max = managers.flatMap(_.address).map(_.max).max
|
||||||
|
val width = ResourceInt((log2Ceil(max)+31) / 32)
|
||||||
|
Resource(root, "width").bind(width)
|
||||||
|
Resource(soc, "width").bind(width)
|
||||||
|
Resource(cpus, "null").bind(ResourceString(""))
|
||||||
|
|
||||||
|
managers.foreach { case manager =>
|
||||||
|
val value = manager.toResource
|
||||||
|
manager.resources.foreach { case resource =>
|
||||||
|
resource.bind(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BaseCoreplexBundle[+L <: BaseCoreplex](_outer: L) extends BareCoreplexBundle(_outer)
|
abstract class BaseCoreplexModule[+L <: BaseCoreplex](_outer: L) extends BareCoreplexModule(_outer) {
|
||||||
with CoreplexNetworkBundle
|
println("Generated Address Map")
|
||||||
with BankedL2CoherenceManagersBundle
|
private val aw = (outer.sharedMemoryTLEdge.bundle.addressBits-1)/4 + 1
|
||||||
|
private val fmt = s"\t%${aw}x - %${aw}x %c%c%c%c %s"
|
||||||
|
|
||||||
class BaseCoreplexModule[+L <: BaseCoreplex, +B <: BaseCoreplexBundle[L]](_outer: L, _io: () => B) extends BareCoreplexModule(_outer, _io)
|
private def collect(path: List[String], value: ResourceValue): List[(String, ResourceAddress)] = {
|
||||||
with CoreplexNetworkModule
|
value match {
|
||||||
with BankedL2CoherenceManagersModule
|
case r: ResourceAddress => List((path(1), r))
|
||||||
|
case b: ResourceMapping => List((path(1), ResourceAddress(b.address, b.permissions)))
|
||||||
|
case ResourceMap(value, _) => value.toList.flatMap { case (key, seq) => seq.flatMap(r => collect(key :: path, r)) }
|
||||||
|
case _ => Nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private val ranges = collect(Nil, outer.bindingTree).groupBy(_._2).toList.flatMap { case (key, seq) =>
|
||||||
|
AddressRange.fromSets(key.address).map { r => (r, key.permissions, seq.map(_._1)) }
|
||||||
|
}.sortBy(_._1)
|
||||||
|
private val json = ranges.map { case (range, ResourcePermissions(r, w, x, c), names) =>
|
||||||
|
println(fmt.format(
|
||||||
|
range.base,
|
||||||
|
range.base+range.size,
|
||||||
|
if (r) 'R' else ' ',
|
||||||
|
if (w) 'W' else ' ',
|
||||||
|
if (x) 'X' else ' ',
|
||||||
|
if (c) 'C' else ' ',
|
||||||
|
names.mkString(", ")))
|
||||||
|
s"""{"base":[${range.base}],"size":[${range.size}],"r":[$r],"w":[$w],"x":[$x],"c":[$c],"names":[${names.map('"'+_+'"').mkString(",")}]}"""
|
||||||
|
}
|
||||||
|
println("")
|
||||||
|
ElaborationArtefacts.add("memmap.json", s"""{"mapping":[${json.mkString(",")}]}""")
|
||||||
|
|
||||||
|
// Confirm that all of memory was described by DTS
|
||||||
|
private val dtsRanges = AddressRange.unify(ranges.map(_._1))
|
||||||
|
private val allRanges = AddressRange.unify(outer.topManagers.get.flatMap { m => AddressRange.fromSets(m.address) })
|
||||||
|
|
||||||
|
if (dtsRanges != allRanges) {
|
||||||
|
println("Address map described by DTS differs from physical implementation:")
|
||||||
|
AddressRange.subtract(allRanges, dtsRanges).foreach { case r =>
|
||||||
|
println(s"\texists, but undescribed by DTS: ${r}")
|
||||||
|
}
|
||||||
|
AddressRange.subtract(dtsRanges, allRanges).foreach { case r =>
|
||||||
|
println(s"\tdoes not exist, but described by DTS: ${r}")
|
||||||
|
}
|
||||||
|
println("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
package freechips.rocketchip.coreplex
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
import freechips.rocketchip.devices.debug._
|
import freechips.rocketchip.devices.debug._
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
@ -15,6 +14,7 @@ import freechips.rocketchip.tilelink._
|
|||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
class BaseCoreplexConfig extends Config ((site, here, up) => {
|
class BaseCoreplexConfig extends Config ((site, here, up) => {
|
||||||
|
// Tile parameters
|
||||||
case PAddrBits => 32
|
case PAddrBits => 32
|
||||||
case PgLevels => if (site(XLen) == 64) 3 /* Sv39 */ else 2 /* Sv32 */
|
case PgLevels => if (site(XLen) == 64) 3 /* Sv39 */ else 2 /* Sv32 */
|
||||||
case ASIdBits => 0
|
case ASIdBits => 0
|
||||||
@ -22,19 +22,26 @@ class BaseCoreplexConfig extends Config ((site, here, up) => {
|
|||||||
case ResetVectorBits => site(PAddrBits)
|
case ResetVectorBits => site(PAddrBits)
|
||||||
case MaxHartIdBits => log2Up(site(RocketTilesKey).size)
|
case MaxHartIdBits => log2Up(site(RocketTilesKey).size)
|
||||||
case BuildCore => (p: Parameters) => new Rocket()(p)
|
case BuildCore => (p: Parameters) => new Rocket()(p)
|
||||||
|
case RocketTilesKey => Nil // Will be added by partial configs found below
|
||||||
|
// Interconnect parameters
|
||||||
case RocketCrossing => SynchronousCrossing()
|
case RocketCrossing => SynchronousCrossing()
|
||||||
case RocketTilesKey => Nil
|
case BroadcastParams => BroadcastParams()
|
||||||
case DMKey => DefaultDebugModuleConfig(site(XLen))
|
case BankedL2Params => BankedL2Params()
|
||||||
case PLICKey => PLICParams()
|
case SystemBusParams => SystemBusParams(beatBytes = site(XLen)/8, blockBytes = site(CacheBlockBytes))
|
||||||
case ClintKey => ClintParams()
|
case PeripheryBusParams => PeripheryBusParams(beatBytes = site(XLen)/8, blockBytes = site(CacheBlockBytes))
|
||||||
case CBusConfig => TLBusConfig(beatBytes = site(XLen)/8)
|
case MemoryBusParams => MemoryBusParams(beatBytes = 8, blockBytes = site(CacheBlockBytes))
|
||||||
case L1toL2Config => TLBusConfig(beatBytes = site(XLen)/8) // increase for more PCIe bandwidth
|
|
||||||
case BootROMFile => "./bootrom/bootrom.img"
|
|
||||||
case BroadcastConfig => BroadcastConfig()
|
|
||||||
case BankedL2Config => BankedL2Config()
|
|
||||||
case CacheBlockBytes => 64
|
case CacheBlockBytes => 64
|
||||||
|
// Device parameters
|
||||||
|
case DebugModuleParams => DefaultDebugModuleParams(site(XLen))
|
||||||
|
case PLICParams => PLICParams()
|
||||||
|
case ClintParams => ClintParams()
|
||||||
|
// TileLink connection global parameters
|
||||||
|
case TLMonitorBuilder => (args: TLMonitorArgs) => Some(LazyModule(new TLMonitor(args)))
|
||||||
|
case TLCombinationalCheck => false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/* Composable partial function Configs to set individual parameters */
|
||||||
|
|
||||||
class WithNBigCores(n: Int) extends Config((site, here, up) => {
|
class WithNBigCores(n: Int) extends Config((site, here, up) => {
|
||||||
case RocketTilesKey => {
|
case RocketTilesKey => {
|
||||||
val big = RocketTileParams(
|
val big = RocketTileParams(
|
||||||
@ -43,11 +50,11 @@ class WithNBigCores(n: Int) extends Config((site, here, up) => {
|
|||||||
mulEarlyOut = true,
|
mulEarlyOut = true,
|
||||||
divEarlyOut = true))),
|
divEarlyOut = true))),
|
||||||
dcache = Some(DCacheParams(
|
dcache = Some(DCacheParams(
|
||||||
rowBits = site(L1toL2Config).beatBytes*8,
|
rowBits = site(SystemBusParams).beatBits,
|
||||||
nMSHRs = 0,
|
nMSHRs = 0,
|
||||||
blockBytes = site(CacheBlockBytes))),
|
blockBytes = site(CacheBlockBytes))),
|
||||||
icache = Some(ICacheParams(
|
icache = Some(ICacheParams(
|
||||||
rowBits = site(L1toL2Config).beatBytes*8,
|
rowBits = site(SystemBusParams).beatBits,
|
||||||
blockBytes = site(CacheBlockBytes))))
|
blockBytes = site(CacheBlockBytes))))
|
||||||
List.fill(n)(big) ++ up(RocketTilesKey, site)
|
List.fill(n)(big) ++ up(RocketTilesKey, site)
|
||||||
}
|
}
|
||||||
@ -59,14 +66,14 @@ class WithNSmallCores(n: Int) extends Config((site, here, up) => {
|
|||||||
core = RocketCoreParams(useVM = false, fpu = None),
|
core = RocketCoreParams(useVM = false, fpu = None),
|
||||||
btb = None,
|
btb = None,
|
||||||
dcache = Some(DCacheParams(
|
dcache = Some(DCacheParams(
|
||||||
rowBits = site(L1toL2Config).beatBytes*8,
|
rowBits = site(SystemBusParams).beatBits,
|
||||||
nSets = 64,
|
nSets = 64,
|
||||||
nWays = 1,
|
nWays = 1,
|
||||||
nTLBEntries = 4,
|
nTLBEntries = 4,
|
||||||
nMSHRs = 0,
|
nMSHRs = 0,
|
||||||
blockBytes = site(CacheBlockBytes))),
|
blockBytes = site(CacheBlockBytes))),
|
||||||
icache = Some(ICacheParams(
|
icache = Some(ICacheParams(
|
||||||
rowBits = site(L1toL2Config).beatBytes*8,
|
rowBits = site(SystemBusParams).beatBits,
|
||||||
nSets = 64,
|
nSets = 64,
|
||||||
nWays = 1,
|
nWays = 1,
|
||||||
nTLBEntries = 4,
|
nTLBEntries = 4,
|
||||||
@ -75,12 +82,39 @@ class WithNSmallCores(n: Int) extends Config((site, here, up) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
class WithNTinyCores(n: Int) extends Config((site, here, up) => {
|
||||||
|
case XLen => 32
|
||||||
|
case RocketTilesKey => {
|
||||||
|
val tiny = RocketTileParams(
|
||||||
|
core = RocketCoreParams(
|
||||||
|
useVM = false,
|
||||||
|
fpu = None,
|
||||||
|
mulDiv = Some(MulDivParams(mulUnroll = 8))),
|
||||||
|
btb = None,
|
||||||
|
dcache = Some(DCacheParams(
|
||||||
|
rowBits = site(SystemBusParams).beatBits,
|
||||||
|
nSets = 256, // 16Kb scratchpad
|
||||||
|
nWays = 1,
|
||||||
|
nTLBEntries = 4,
|
||||||
|
nMSHRs = 0,
|
||||||
|
blockBytes = site(CacheBlockBytes),
|
||||||
|
scratch = Some(0x80000000L))),
|
||||||
|
icache = Some(ICacheParams(
|
||||||
|
rowBits = site(SystemBusParams).beatBits,
|
||||||
|
nSets = 64,
|
||||||
|
nWays = 1,
|
||||||
|
nTLBEntries = 4,
|
||||||
|
blockBytes = site(CacheBlockBytes))))
|
||||||
|
List.fill(n)(tiny) ++ up(RocketTilesKey, site)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
class WithNBanksPerMemChannel(n: Int) extends Config((site, here, up) => {
|
class WithNBanksPerMemChannel(n: Int) extends Config((site, here, up) => {
|
||||||
case BankedL2Config => up(BankedL2Config, site).copy(nBanksPerChannel = n)
|
case BankedL2Params => up(BankedL2Params, site).copy(nBanksPerChannel = n)
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithNTrackersPerBank(n: Int) extends Config((site, here, up) => {
|
class WithNTrackersPerBank(n: Int) extends Config((site, here, up) => {
|
||||||
case BroadcastConfig => up(BroadcastConfig, site).copy(nTrackers = n)
|
case BroadcastParams => up(BroadcastParams, site).copy(nTrackers = n)
|
||||||
})
|
})
|
||||||
|
|
||||||
// This is the number of icache sets for all Rocket tiles
|
// This is the number of icache sets for all Rocket tiles
|
||||||
@ -112,7 +146,7 @@ class WithCacheBlockBytes(linesize: Int) extends Config((site, here, up) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithBufferlessBroadcastHub extends Config((site, here, up) => {
|
class WithBufferlessBroadcastHub extends Config((site, here, up) => {
|
||||||
case BroadcastConfig => up(BroadcastConfig, site).copy(bufferless = true)
|
case BroadcastParams => up(BroadcastParams, site).copy(bufferless = true)
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,12 +162,10 @@ class WithBufferlessBroadcastHub extends Config((site, here, up) => {
|
|||||||
* DO NOT use this configuration.
|
* DO NOT use this configuration.
|
||||||
*/
|
*/
|
||||||
class WithStatelessBridge extends Config((site, here, up) => {
|
class WithStatelessBridge extends Config((site, here, up) => {
|
||||||
case BankedL2Config => up(BankedL2Config, site).copy(coherenceManager = { case (q, _) =>
|
case BankedL2Params => up(BankedL2Params, site).copy(coherenceManager = { case (q, _) =>
|
||||||
implicit val p = q
|
implicit val p = q
|
||||||
val cork = LazyModule(new TLCacheCork(unsafe = true))
|
val cork = LazyModule(new TLCacheCork(unsafe = true))
|
||||||
val ww = LazyModule(new TLWidthWidget(p(L1toL2Config).beatBytes))
|
(cork.node, cork.node)
|
||||||
ww.node :*= cork.node
|
|
||||||
(cork.node, ww.node)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -208,7 +240,7 @@ class WithFPUWithoutDivSqrt extends Config((site, here, up) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithBootROMFile(bootROMFile: String) extends Config((site, here, up) => {
|
class WithBootROMFile(bootROMFile: String) extends Config((site, here, up) => {
|
||||||
case BootROMFile => bootROMFile
|
case BootROMParams => up(BootROMParams, site).copy(contentFileName = bootROMFile)
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSynchronousRocketTiles extends Config((site, here, up) => {
|
class WithSynchronousRocketTiles extends Config((site, here, up) => {
|
||||||
@ -223,3 +255,49 @@ class WithRationalRocketTiles extends Config((site, here, up) => {
|
|||||||
case RocketCrossing => RationalCrossing()
|
case RocketCrossing => RationalCrossing()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
class WithEdgeDataBits(dataBits: Int) extends Config((site, here, up) => {
|
||||||
|
case MemoryBusParams => up(MemoryBusParams, site).copy(beatBytes = dataBits/8)
|
||||||
|
case ExtIn => up(ExtIn, site).copy(beatBytes = dataBits/8)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithJtagDTM extends Config ((site, here, up) => {
|
||||||
|
case IncludeJtagDTM => true
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithNoPeripheryArithAMO extends Config ((site, here, up) => {
|
||||||
|
case PeripheryBusParams => up(PeripheryBusParams, site).copy(arithmetic = false)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithNBitPeripheryBus(nBits: Int) extends Config ((site, here, up) => {
|
||||||
|
case PeripheryBusParams => up(PeripheryBusParams, site).copy(beatBytes = nBits/8)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithoutTLMonitors extends Config ((site, here, up) => {
|
||||||
|
case TLMonitorBuilder => (args: TLMonitorArgs) => None
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithNExtTopInterrupts(nExtInts: Int) extends Config((site, here, up) => {
|
||||||
|
case NExtTopInterrupts => nExtInts
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithRTCPeriod(nCycles: Int) extends Config((site, here, up) => {
|
||||||
|
case RTCPeriod => nCycles
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithNMemoryChannels(n: Int) extends Config((site, here, up) => {
|
||||||
|
case BankedL2Params => up(BankedL2Params, site).copy(nMemoryChannels = n)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithExtMemSize(n: Long) extends Config((site, here, up) => {
|
||||||
|
case ExtMem => up(ExtMem, site).copy(size = n)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithDTS(model: String, compat: Seq[String]) extends Config((site, here, up) => {
|
||||||
|
case DTSModel => model
|
||||||
|
case DTSCompat => compat
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithTimebase(hertz: BigInt) extends Config((site, here, up) => {
|
||||||
|
case DTSTimebase => hertz
|
||||||
|
})
|
||||||
|
@ -1,190 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.coreplex
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
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
|
|
||||||
def bindingTree: ResourceMap
|
|
||||||
|
|
||||||
// TODO: do we need one of these? val cbus = LazyModule(new TLXbar) // Locally-visible peripheral devices
|
|
||||||
val sbus = LazyModule(new TLXbar) // Globally-visible high-bandwidth devices
|
|
||||||
val pbus = LazyModule(new TLXbar) // Globally-visible low-bandwidth devices
|
|
||||||
val tile_splitter = LazyModule(new TLSplitter) // Allows cycle-free connection to external networks
|
|
||||||
val int_xbar = LazyModule(new IntXbar) // Interrupt crossbar
|
|
||||||
|
|
||||||
val mmio = TLOutputNode() // Exernal memory-mapped IO slaves
|
|
||||||
val mmioInt = IntInputNode() // Exernal devices' interrupts
|
|
||||||
val l2in = TLInputNode() // External masters talking to the frontside of the shared cache
|
|
||||||
val l2out = TLOutputNode() // External slaves hanging off the backside of the shared cache
|
|
||||||
|
|
||||||
int_xbar.intnode := mmioInt
|
|
||||||
|
|
||||||
// Allows a variable number of inputs from outside to the Xbar
|
|
||||||
private val l2in_buffer = LazyModule(new TLBuffer)
|
|
||||||
private val l2in_fifo = LazyModule(new TLFIFOFixer)
|
|
||||||
sbus.node :=* l2in_fifo.node
|
|
||||||
sbus.node :=* tile_splitter.node
|
|
||||||
l2in_fifo.node :=* l2in_buffer.node
|
|
||||||
l2in_buffer.node :=* l2in
|
|
||||||
|
|
||||||
private val l2out_buffer = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none))
|
|
||||||
l2out :*= l2out_buffer.node
|
|
||||||
l2out_buffer.node :*= sbus.node
|
|
||||||
|
|
||||||
pbus.node :=
|
|
||||||
TLBuffer()(
|
|
||||||
TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata
|
|
||||||
TLWidthWidget(sbusBeatBytes)(
|
|
||||||
sbus.node)))
|
|
||||||
|
|
||||||
mmio :=
|
|
||||||
TLWidthWidget(sbusBeatBytes)(
|
|
||||||
sbus.node)
|
|
||||||
|
|
||||||
val root = new Device {
|
|
||||||
def describe(resources: ResourceBindings): Description = {
|
|
||||||
val width = resources("width").map(_.value)
|
|
||||||
Description("/", Map(
|
|
||||||
"#address-cells" -> width,
|
|
||||||
"#size-cells" -> width,
|
|
||||||
"model" -> Seq(ResourceString(p(DTSModel))),
|
|
||||||
"compatible" -> (p(DTSModel) +: p(DTSCompat)).map(s => ResourceString(s + "-dev"))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val soc = new Device {
|
|
||||||
def describe(resources: ResourceBindings): Description = {
|
|
||||||
val width = resources("width").map(_.value)
|
|
||||||
Description("soc", Map(
|
|
||||||
"#address-cells" -> width,
|
|
||||||
"#size-cells" -> width,
|
|
||||||
"compatible" -> ((p(DTSModel) +: p(DTSCompat)).map(s => ResourceString(s + "-soc")) :+ ResourceString("simple-bus")),
|
|
||||||
"ranges" -> Nil))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val cpus = new Device {
|
|
||||||
def describe(resources: ResourceBindings): Description = {
|
|
||||||
Description("cpus", Map(
|
|
||||||
"#address-cells" -> Seq(ResourceInt(1)),
|
|
||||||
"#size-cells" -> Seq(ResourceInt(0)),
|
|
||||||
"timebase-frequency" -> Seq(ResourceInt(p(DTSTimebase)))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make topManagers an Option[] so as to avoid LM name reflection evaluating it...
|
|
||||||
lazy val topManagers = Some(ManagerUnification(tile_splitter.node.edgesIn.headOption.map(_.manager.managers).getOrElse(Nil)))
|
|
||||||
ResourceBinding {
|
|
||||||
val managers = topManagers.get
|
|
||||||
val max = managers.flatMap(_.address).map(_.max).max
|
|
||||||
val width = ResourceInt((log2Ceil(max)+31) / 32)
|
|
||||||
Resource(root, "width").bind(width)
|
|
||||||
Resource(soc, "width").bind(width)
|
|
||||||
Resource(cpus, "null").bind(ResourceString(""))
|
|
||||||
|
|
||||||
managers.foreach { case manager =>
|
|
||||||
val value = manager.toResource
|
|
||||||
manager.resources.foreach { case resource =>
|
|
||||||
resource.bind(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait CoreplexNetworkBundle extends HasCoreplexParameters {
|
|
||||||
val outer: CoreplexNetwork
|
|
||||||
|
|
||||||
val mmio = outer.mmio.bundleOut
|
|
||||||
val interrupts = outer.mmioInt.bundleIn
|
|
||||||
val l2in = outer.l2in.bundleIn
|
|
||||||
val l2out = outer.l2out.bundleOut
|
|
||||||
}
|
|
||||||
|
|
||||||
trait CoreplexNetworkModule extends HasCoreplexParameters {
|
|
||||||
val outer: CoreplexNetwork
|
|
||||||
val io: CoreplexNetworkBundle
|
|
||||||
|
|
||||||
println("Generated Address Map")
|
|
||||||
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)] = {
|
|
||||||
value match {
|
|
||||||
case r: ResourceAddress => List((path(1), r))
|
|
||||||
case b: ResourceMapping => List((path(1), ResourceAddress(b.address, b.permissions)))
|
|
||||||
case ResourceMap(value, _) => value.toList.flatMap { case (key, seq) => seq.flatMap(r => collect(key :: path, r)) }
|
|
||||||
case _ => Nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private val ranges = collect(Nil, outer.bindingTree).groupBy(_._2).toList.flatMap { case (key, seq) =>
|
|
||||||
AddressRange.fromSets(key.address).map { r => (r, key.permissions, seq.map(_._1)) }
|
|
||||||
}.sortBy(_._1)
|
|
||||||
private val json = ranges.map { case (range, ResourcePermissions(r, w, x, c), names) =>
|
|
||||||
println(fmt.format(
|
|
||||||
range.base,
|
|
||||||
range.base+range.size,
|
|
||||||
if (r) 'R' else ' ',
|
|
||||||
if (w) 'W' else ' ',
|
|
||||||
if (x) 'X' else ' ',
|
|
||||||
if (c) 'C' else ' ',
|
|
||||||
names.mkString(", ")))
|
|
||||||
s"""{"base":[${range.base}],"size":[${range.size}],"r":[$r],"w":[$w],"x":[$x],"c":[$c],"names":[${names.map('"'+_+'"').mkString(",")}]}"""
|
|
||||||
}
|
|
||||||
println("")
|
|
||||||
ElaborationArtefacts.add("memmap.json", s"""{"mapping":[${json.mkString(",")}]}""")
|
|
||||||
|
|
||||||
// Confirm that all of memory was described by DTS
|
|
||||||
private val dtsRanges = AddressRange.unify(ranges.map(_._1))
|
|
||||||
private val allRanges = AddressRange.unify(outer.topManagers.get.flatMap { m => AddressRange.fromSets(m.address) })
|
|
||||||
|
|
||||||
if (dtsRanges != allRanges) {
|
|
||||||
println("Address map described by DTS differs from physical implementation:")
|
|
||||||
AddressRange.subtract(allRanges, dtsRanges).foreach { case r =>
|
|
||||||
println(s"\texists, but undescribed by DTS: ${r}")
|
|
||||||
}
|
|
||||||
AddressRange.subtract(dtsRanges, allRanges).foreach { case r =>
|
|
||||||
println(s"\tdoes not exist, but described by DTS: ${r}")
|
|
||||||
}
|
|
||||||
println("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////
|
|
||||||
|
|
||||||
trait BankedL2CoherenceManagers extends CoreplexNetwork {
|
|
||||||
val module: BankedL2CoherenceManagersModule
|
|
||||||
|
|
||||||
require (isPow2(l2Config.nMemoryChannels) || l2Config.nMemoryChannels == 0)
|
|
||||||
require (isPow2(l2Config.nBanksPerChannel))
|
|
||||||
require (isPow2(sbusBlockBytes))
|
|
||||||
|
|
||||||
private val (in, out) = l2Config.coherenceManager(p, this)
|
|
||||||
private val mask = ~BigInt((l2Config.nBanks-1) * sbusBlockBytes)
|
|
||||||
val mem = Seq.tabulate(l2Config.nMemoryChannels) { channel =>
|
|
||||||
val node = TLOutputNode()
|
|
||||||
for (bank <- 0 until l2Config.nBanksPerChannel) {
|
|
||||||
val offset = (bank * l2Config.nMemoryChannels) + channel
|
|
||||||
in := sbus.node
|
|
||||||
node := TLFilter(AddressSet(offset * sbusBlockBytes, mask))(out)
|
|
||||||
}
|
|
||||||
node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait BankedL2CoherenceManagersBundle extends CoreplexNetworkBundle {
|
|
||||||
val outer: BankedL2CoherenceManagers
|
|
||||||
val mem = HeterogeneousBag(outer.mem.map(_.bundleOut))
|
|
||||||
}
|
|
||||||
|
|
||||||
trait BankedL2CoherenceManagersModule extends CoreplexNetworkModule {
|
|
||||||
val outer: BankedL2CoherenceManagers
|
|
||||||
val io: BankedL2CoherenceManagersBundle
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.coreplex
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
import freechips.rocketchip.diplomacy.LazyModule
|
|
||||||
import freechips.rocketchip.tilelink._
|
|
||||||
|
|
||||||
trait HasISPPort extends CoreplexNetwork {
|
|
||||||
val module: HasISPPortModule
|
|
||||||
|
|
||||||
// TODO: use ChipLink instead of AsyncTileLink
|
|
||||||
val isp_in = TLAsyncInputNode()
|
|
||||||
val isp_out = TLAsyncOutputNode()
|
|
||||||
|
|
||||||
private val out_xbar = LazyModule(new TLXbar)
|
|
||||||
private val out_nums = LazyModule(new TLNodeNumberer)
|
|
||||||
private val out_async = LazyModule(new TLAsyncCrossingSource)
|
|
||||||
out_xbar.node :=* tile_splitter.node
|
|
||||||
out_nums.node :*= out_xbar.node
|
|
||||||
out_async.node :*= out_nums.node
|
|
||||||
isp_out :*= out_async.node
|
|
||||||
|
|
||||||
private val in_async = LazyModule(new TLAsyncCrossingSink)
|
|
||||||
in_async.node :=* isp_in
|
|
||||||
sbus.node :=* in_async.node
|
|
||||||
}
|
|
||||||
|
|
||||||
trait HasISPPortBundle extends CoreplexNetworkBundle {
|
|
||||||
val outer: HasISPPort
|
|
||||||
|
|
||||||
// TODO: move to IO(...) in Module?
|
|
||||||
val isp_in = outer.isp_in.bundleIn
|
|
||||||
val isp_out = outer.isp_out.bundleOut
|
|
||||||
}
|
|
||||||
|
|
||||||
trait HasISPPortModule extends CoreplexNetworkModule {
|
|
||||||
val outer: HasISPPort
|
|
||||||
val io: HasISPPortBundle
|
|
||||||
}
|
|
85
src/main/scala/coreplex/InterruptBus.scala
Normal file
85
src/main/scala/coreplex/InterruptBus.scala
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
|
/** Collects interrupts from internal and external devices and feeds them into the PLIC */
|
||||||
|
class InterruptBusWrapper(implicit p: Parameters) {
|
||||||
|
|
||||||
|
val int_bus = LazyModule(new IntXbar) // Interrupt crossbar
|
||||||
|
|
||||||
|
private def synchronize(sync: Int): IntInwardNode = {
|
||||||
|
val asyncXing = LazyModule(new IntXing(sync))
|
||||||
|
int_bus.intnode := asyncXing.intnode
|
||||||
|
asyncXing.intnode
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromAsync: IntInwardNode = synchronize(3)
|
||||||
|
def fromRational: IntInwardNode = synchronize(1)
|
||||||
|
def fromSync: IntInwardNode = int_bus.intnode
|
||||||
|
def toPLIC: IntOutwardNode = int_bus.intnode
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasInterruptBus {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val ibus = new InterruptBusWrapper
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Specifies the number of external interrupts */
|
||||||
|
case object NExtTopInterrupts extends Field[Int]
|
||||||
|
|
||||||
|
/** This trait adds externally driven interrupts to the system.
|
||||||
|
* However, it should not be used directly; instead one of the below
|
||||||
|
* synchronization wiring child traits should be used.
|
||||||
|
*/
|
||||||
|
abstract trait HasExtInterrupts extends HasInterruptBus {
|
||||||
|
private val device = new Device with DeviceInterrupts {
|
||||||
|
def describe(resources: ResourceBindings): Description = {
|
||||||
|
Description("soc/external-interrupts", describeInterrupts(resources))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val nExtInterrupts = p(NExtTopInterrupts)
|
||||||
|
val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This trait should be used if the External Interrupts have NOT
|
||||||
|
* already been synchronized to the Periphery (PLIC) Clock.
|
||||||
|
*/
|
||||||
|
trait HasAsyncExtInterrupts extends HasExtInterrupts {
|
||||||
|
if (nExtInterrupts > 0) {
|
||||||
|
ibus.fromAsync := extInterrupts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This trait can be used if the External Interrupts have already been synchronized
|
||||||
|
* to the Periphery (PLIC) Clock.
|
||||||
|
*/
|
||||||
|
trait HasSyncExtInterrupts extends HasExtInterrupts {
|
||||||
|
if (nExtInterrupts > 0) {
|
||||||
|
ibus.fromSync := extInterrupts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Common io name and methods for propagating or tying off the port bundle */
|
||||||
|
trait HasExtInterruptsBundle {
|
||||||
|
val interrupts: UInt
|
||||||
|
|
||||||
|
def tieOffInterrupts(dummy: Int = 1) {
|
||||||
|
interrupts := UInt(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This trait performs the translation from a UInt IO into Diplomatic Interrupts.
|
||||||
|
* The wiring must be done in the concrete LazyModuleImp.
|
||||||
|
*/
|
||||||
|
trait HasExtInterruptsModuleImp extends LazyMultiIOModuleImp with HasExtInterruptsBundle {
|
||||||
|
val outer: HasExtInterrupts
|
||||||
|
val interrupts = IO(UInt(INPUT, width = outer.nExtInterrupts))
|
||||||
|
|
||||||
|
outer.extInterrupts.bundleIn.flatten.zipWithIndex.foreach { case(o, i) => o := interrupts(i) }
|
||||||
|
}
|
75
src/main/scala/coreplex/MemoryBus.scala
Normal file
75
src/main/scala/coreplex/MemoryBus.scala
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
// TODO: applies to all caches, for now
|
||||||
|
case object CacheBlockBytes extends Field[Int]
|
||||||
|
|
||||||
|
/** L2 Broadcast Hub configuration */
|
||||||
|
case class BroadcastParams(
|
||||||
|
nTrackers: Int = 4,
|
||||||
|
bufferless: Boolean = false)
|
||||||
|
case object BroadcastParams extends Field[BroadcastParams]
|
||||||
|
|
||||||
|
/** L2 memory subsystem configuration */
|
||||||
|
case class BankedL2Params(
|
||||||
|
nMemoryChannels: Int = 1,
|
||||||
|
nBanksPerChannel: Int = 1,
|
||||||
|
coherenceManager: (Parameters, HasMemoryBus) => (TLInwardNode, TLOutwardNode) = { case (q, _) =>
|
||||||
|
implicit val p = q
|
||||||
|
val MemoryBusParams(_, blockBytes, _, _) = p(MemoryBusParams)
|
||||||
|
val BroadcastParams(nTrackers, bufferless) = p(BroadcastParams)
|
||||||
|
val bh = LazyModule(new TLBroadcast(blockBytes, nTrackers, bufferless))
|
||||||
|
(bh.node, bh.node)
|
||||||
|
}) {
|
||||||
|
val nBanks = nMemoryChannels*nBanksPerChannel
|
||||||
|
}
|
||||||
|
case object BankedL2Params extends Field[BankedL2Params]
|
||||||
|
|
||||||
|
/** Parameterization of the memory-side bus created for each memory channel */
|
||||||
|
case class MemoryBusParams(
|
||||||
|
beatBytes: Int,
|
||||||
|
blockBytes: Int,
|
||||||
|
masterBuffering: BufferParams = BufferParams.none,
|
||||||
|
slaveBuffering: BufferParams = BufferParams.none
|
||||||
|
) extends TLBusParams
|
||||||
|
|
||||||
|
case object MemoryBusParams extends Field[MemoryBusParams]
|
||||||
|
|
||||||
|
/** Wrapper for creating TL nodes from a bus connected to the back of each mem channel */
|
||||||
|
class MemoryBus(params: MemoryBusParams)(implicit p: Parameters) extends TLBusWrapper(params)(p) {
|
||||||
|
def fromCoherenceManager: TLInwardNode = inwardBufNode
|
||||||
|
def toDRAMController: TLOutwardNode = outwardBufNode
|
||||||
|
def toVariableWidthSlave: TLOutwardNode = outwardFragNode
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBus {
|
||||||
|
private val mbusParams = p(MemoryBusParams)
|
||||||
|
private val MemoryBusParams(beatBytes, blockBytes, _, _) = mbusParams
|
||||||
|
private val l2Params = p(BankedL2Params)
|
||||||
|
val BankedL2Params(nMemoryChannels, nBanksPerChannel, coherenceManager) = l2Params
|
||||||
|
val nBanks = l2Params.nBanks
|
||||||
|
val cacheBlockBytes = blockBytes
|
||||||
|
|
||||||
|
require (isPow2(nMemoryChannels) || nMemoryChannels == 0)
|
||||||
|
require (isPow2(nBanksPerChannel))
|
||||||
|
require (isPow2(blockBytes))
|
||||||
|
|
||||||
|
private val (in, out) = coherenceManager(p, this)
|
||||||
|
private val mask = ~BigInt((nBanks-1) * blockBytes)
|
||||||
|
val memBuses = Seq.tabulate(nMemoryChannels) { channel =>
|
||||||
|
val mbus = new MemoryBus(mbusParams)
|
||||||
|
for (bank <- 0 until nBanksPerChannel) {
|
||||||
|
val offset = (bank * nMemoryChannels) + channel
|
||||||
|
in := sbus.toMemoryBus
|
||||||
|
mbus.fromCoherenceManager := TLFilter(AddressSet(offset * blockBytes, mask))(out)
|
||||||
|
}
|
||||||
|
mbus
|
||||||
|
}
|
||||||
|
}
|
48
src/main/scala/coreplex/PeripheryBus.scala
Normal file
48
src/main/scala/coreplex/PeripheryBus.scala
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
|
case class PeripheryBusParams(
|
||||||
|
beatBytes: Int,
|
||||||
|
blockBytes: Int,
|
||||||
|
masterBuffering: BufferParams = BufferParams.default,
|
||||||
|
slaveBuffering: BufferParams = BufferParams.none,
|
||||||
|
arithmetic: Boolean = true
|
||||||
|
) extends TLBusParams {
|
||||||
|
}
|
||||||
|
|
||||||
|
case object PeripheryBusParams extends Field[PeripheryBusParams]
|
||||||
|
|
||||||
|
class PeripheryBus(params: PeripheryBusParams)(implicit p: Parameters) extends TLBusWrapper(params) {
|
||||||
|
def toFixedWidthSingleBeatSlave(widthBytes: Int) = {
|
||||||
|
TLFragmenter(widthBytes, params.blockBytes)(outwardWWNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
def toLargeBurstSlave(maxXferBytes: Int) = {
|
||||||
|
TLFragmenter(params.beatBytes, maxXferBytes)(outwardBufNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
val fromSystemBus: TLInwardNode = {
|
||||||
|
val atomics = LazyModule(new TLAtomicAutomata(arithmetic = params.arithmetic))
|
||||||
|
inwardBufNode := atomics.node
|
||||||
|
atomics.node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides buses that serve as attachment points,
|
||||||
|
* for use in traits that connect individual devices or external ports.
|
||||||
|
*/
|
||||||
|
trait HasPeripheryBus extends HasSystemBus {
|
||||||
|
private val pbusParams = p(PeripheryBusParams)
|
||||||
|
val pbusBeatBytes = pbusParams.beatBytes
|
||||||
|
|
||||||
|
val pbus = new PeripheryBus(pbusParams)
|
||||||
|
|
||||||
|
// The peripheryBus hangs off of systemBus; here we convert TL-UH -> TL-UL
|
||||||
|
pbus.fromSystemBus := sbus.toPeripheryBus
|
||||||
|
}
|
261
src/main/scala/coreplex/Ports.scala
Normal file
261
src/main/scala/coreplex/Ports.scala
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.amba.axi4._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
/** Specifies the size and width of external memory ports */
|
||||||
|
case class MasterPortParams(
|
||||||
|
base: Long,
|
||||||
|
size: Long,
|
||||||
|
beatBytes: Int,
|
||||||
|
idBits: Int,
|
||||||
|
maxXferBytes: Int = 256,
|
||||||
|
executable: Boolean = true)
|
||||||
|
case object ExtMem extends Field[MasterPortParams]
|
||||||
|
case object ExtBus extends Field[MasterPortParams]
|
||||||
|
|
||||||
|
/** Specifies the width of external slave ports */
|
||||||
|
case class SlavePortParams(beatBytes: Int, idBits: Int, sourceBits: Int)
|
||||||
|
case object ExtIn extends Field[SlavePortParams]
|
||||||
|
|
||||||
|
///// The following traits add ports to the sytem, in some cases converting to different interconnect standards
|
||||||
|
|
||||||
|
/** Adds a port to the system intended to master an AXI4 DRAM controller. */
|
||||||
|
trait HasMasterAXI4MemPort extends HasMemoryBus {
|
||||||
|
val module: HasMasterAXI4MemPortModuleImp
|
||||||
|
|
||||||
|
private val params = p(ExtMem)
|
||||||
|
private val device = new MemoryDevice
|
||||||
|
|
||||||
|
val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(nMemoryChannels) { channel =>
|
||||||
|
val base = AddressSet(params.base, params.size-1)
|
||||||
|
val filter = AddressSet(channel * cacheBlockBytes, ~((nMemoryChannels-1) * cacheBlockBytes))
|
||||||
|
|
||||||
|
AXI4SlavePortParameters(
|
||||||
|
slaves = Seq(AXI4SlaveParameters(
|
||||||
|
address = base.intersect(filter).toList,
|
||||||
|
resources = device.reg,
|
||||||
|
regionType = RegionType.UNCACHED, // cacheable
|
||||||
|
executable = true,
|
||||||
|
supportsWrite = TransferSizes(1, cacheBlockBytes),
|
||||||
|
supportsRead = TransferSizes(1, cacheBlockBytes),
|
||||||
|
interleavedId = Some(0))), // slave does not interleave read responses
|
||||||
|
beatBytes = params.beatBytes)
|
||||||
|
})
|
||||||
|
|
||||||
|
val converter = LazyModule(new TLToAXI4(params.beatBytes))
|
||||||
|
val trim = LazyModule(new AXI4IdIndexer(params.idBits))
|
||||||
|
val yank = LazyModule(new AXI4UserYanker)
|
||||||
|
val buffer = LazyModule(new AXI4Buffer)
|
||||||
|
|
||||||
|
memBuses.map(_.toDRAMController).foreach { case node =>
|
||||||
|
converter.node := node
|
||||||
|
trim.node := converter.node
|
||||||
|
yank.node := trim.node
|
||||||
|
buffer.node := yank.node
|
||||||
|
mem_axi4 := buffer.node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Common io name and methods for propagating or tying off the port bundle */
|
||||||
|
trait HasMasterAXI4MemPortBundle {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val mem_axi4: HeterogeneousBag[AXI4Bundle]
|
||||||
|
val nMemoryChannels: Int
|
||||||
|
def connectSimAXIMem(dummy: Int = 1) = {
|
||||||
|
if (nMemoryChannels > 0) Module(LazyModule(new SimAXIMem(nMemoryChannels)).module).io.axi4 <> mem_axi4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually generates the corresponding IO in the concrete Module */
|
||||||
|
trait HasMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with HasMasterAXI4MemPortBundle {
|
||||||
|
val outer: HasMasterAXI4MemPort
|
||||||
|
val mem_axi4 = IO(outer.mem_axi4.bundleOut)
|
||||||
|
val nMemoryChannels = outer.nMemoryChannels
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a AXI4 port to the system intended to master an MMIO device bus */
|
||||||
|
trait HasMasterAXI4MMIOPort extends HasSystemBus {
|
||||||
|
private val params = p(ExtBus)
|
||||||
|
private val device = new SimpleBus("mmio", Nil)
|
||||||
|
val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters(
|
||||||
|
slaves = Seq(AXI4SlaveParameters(
|
||||||
|
address = List(AddressSet(BigInt(params.base), params.size-1)),
|
||||||
|
resources = device.ranges,
|
||||||
|
executable = params.executable,
|
||||||
|
supportsWrite = TransferSizes(1, params.maxXferBytes),
|
||||||
|
supportsRead = TransferSizes(1, params.maxXferBytes))),
|
||||||
|
beatBytes = params.beatBytes)))
|
||||||
|
|
||||||
|
mmio_axi4 :=
|
||||||
|
AXI4Buffer()(
|
||||||
|
AXI4UserYanker()(
|
||||||
|
AXI4Deinterleaver(sbus.blockBytes)(
|
||||||
|
AXI4IdIndexer(params.idBits)(
|
||||||
|
TLToAXI4(params.beatBytes)(
|
||||||
|
sbus.toFixedWidthPorts)))))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Common io name and methods for propagating or tying off the port bundle */
|
||||||
|
trait HasMasterAXI4MMIOPortBundle {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val mmio_axi4: HeterogeneousBag[AXI4Bundle]
|
||||||
|
def connectSimAXIMMIO(dummy: Int = 1) {
|
||||||
|
Module(LazyModule(new SimAXIMem(1, 4096)).module).io.axi4 <> mmio_axi4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually generates the corresponding IO in the concrete Module */
|
||||||
|
trait HasMasterAXI4MMIOPortModuleImp extends LazyMultiIOModuleImp with HasMasterAXI4MMIOPortBundle {
|
||||||
|
val outer: HasMasterAXI4MMIOPort
|
||||||
|
val mmio_axi4 = IO(outer.mmio_axi4.bundleOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */
|
||||||
|
trait HasSlaveAXI4Port extends HasSystemBus {
|
||||||
|
private val params = p(ExtIn)
|
||||||
|
val l2FrontendAXI4Node = AXI4BlindInputNode(Seq(AXI4MasterPortParameters(
|
||||||
|
masters = Seq(AXI4MasterParameters(
|
||||||
|
name = "AXI4 periphery",
|
||||||
|
id = IdRange(0, 1 << params.idBits))))))
|
||||||
|
|
||||||
|
private val fifoBits = 1
|
||||||
|
sbus.fromSyncPorts() :=
|
||||||
|
TLWidthWidget(params.beatBytes)(
|
||||||
|
AXI4ToTL()(
|
||||||
|
AXI4UserYanker(Some(1 << (params.sourceBits - fifoBits - 1)))(
|
||||||
|
AXI4Fragmenter()(
|
||||||
|
AXI4IdIndexer(fifoBits)(
|
||||||
|
l2FrontendAXI4Node)))))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Common io name and methods for propagating or tying off the port bundle */
|
||||||
|
trait HasSlaveAXI4PortBundle {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val l2_frontend_bus_axi4: HeterogeneousBag[AXI4Bundle]
|
||||||
|
def tieOffAXI4SlavePort(dummy: Int = 1) {
|
||||||
|
l2_frontend_bus_axi4.foreach { l2_axi4 =>
|
||||||
|
l2_axi4.ar.valid := Bool(false)
|
||||||
|
l2_axi4.aw.valid := Bool(false)
|
||||||
|
l2_axi4.w .valid := Bool(false)
|
||||||
|
l2_axi4.r .ready := Bool(true)
|
||||||
|
l2_axi4.b .ready := Bool(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually generates the corresponding IO in the concrete Module */
|
||||||
|
trait HasSlaveAXI4PortModuleImp extends LazyMultiIOModuleImp with HasSlaveAXI4PortBundle {
|
||||||
|
val outer: HasSlaveAXI4Port
|
||||||
|
val l2_frontend_bus_axi4 = IO(outer.l2FrontendAXI4Node.bundleIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a TileLink port to the system intended to master an MMIO device bus */
|
||||||
|
trait HasMasterTLMMIOPort extends HasSystemBus {
|
||||||
|
private val params = p(ExtBus)
|
||||||
|
private val device = new SimpleBus("mmio", Nil)
|
||||||
|
val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters(
|
||||||
|
managers = Seq(TLManagerParameters(
|
||||||
|
address = List(AddressSet(BigInt(params.base), params.size-1)),
|
||||||
|
resources = device.ranges,
|
||||||
|
executable = params.executable,
|
||||||
|
supportsGet = TransferSizes(1, sbus.blockBytes),
|
||||||
|
supportsPutFull = TransferSizes(1, sbus.blockBytes),
|
||||||
|
supportsPutPartial = TransferSizes(1, sbus.blockBytes))),
|
||||||
|
beatBytes = params.beatBytes)))
|
||||||
|
|
||||||
|
mmio_tl :=
|
||||||
|
TLBuffer()(
|
||||||
|
TLSourceShrinker(1 << params.idBits)(
|
||||||
|
sbus.toFixedWidthPorts))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Common io name and methods for propagating or tying off the port bundle */
|
||||||
|
trait HasMasterTLMMIOPortBundle {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val mmio_tl: HeterogeneousBag[TLBundle]
|
||||||
|
def tieOffTLMMIO(dummy: Int = 1) {
|
||||||
|
mmio_tl.foreach { tl =>
|
||||||
|
tl.a.ready := Bool(true)
|
||||||
|
tl.b.valid := Bool(false)
|
||||||
|
tl.c.ready := Bool(true)
|
||||||
|
tl.d.valid := Bool(false)
|
||||||
|
tl.e.ready := Bool(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually generates the corresponding IO in the concrete Module */
|
||||||
|
trait HasMasterTLMMIOPortModuleImp extends LazyMultiIOModuleImp with HasMasterTLMMIOPortBundle {
|
||||||
|
val outer: HasMasterTLMMIOPort
|
||||||
|
val mmio_tl = IO(outer.mmio_tl.bundleOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds an TL port to the system intended to be a slave on an MMIO device bus.
|
||||||
|
* NOTE: this port is NOT allowed to issue Acquires.
|
||||||
|
*/
|
||||||
|
trait HasSlaveTLPort extends HasSystemBus {
|
||||||
|
private val params = p(ExtIn)
|
||||||
|
val l2FrontendTLNode = TLBlindInputNode(Seq(TLClientPortParameters(
|
||||||
|
clients = Seq(TLClientParameters(
|
||||||
|
name = "Front Port (TL)",
|
||||||
|
sourceId = IdRange(0, 1 << params.idBits))))))
|
||||||
|
|
||||||
|
sbus.fromSyncPorts() :=
|
||||||
|
TLSourceShrinker(1 << params.sourceBits)(
|
||||||
|
TLWidthWidget(params.beatBytes)(
|
||||||
|
l2FrontendTLNode))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Common io name and methods for propagating or tying off the port bundle */
|
||||||
|
trait HasSlaveTLPortBundle {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val l2_frontend_bus_tl: HeterogeneousBag[TLBundle]
|
||||||
|
def tieOffSlaveTLPort(dummy: Int = 1) {
|
||||||
|
l2_frontend_bus_tl.foreach { tl =>
|
||||||
|
tl.a.valid := Bool(false)
|
||||||
|
tl.b.ready := Bool(true)
|
||||||
|
tl.c.valid := Bool(false)
|
||||||
|
tl.d.ready := Bool(true)
|
||||||
|
tl.e.valid := Bool(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually generates the corresponding IO in the concrete Module */
|
||||||
|
trait HasSlaveTLPortModuleImp extends LazyMultiIOModuleImp with HasSlaveTLPortBundle {
|
||||||
|
val outer: HasSlaveTLPort
|
||||||
|
val l2_frontend_bus_tl = IO(outer.l2FrontendTLNode.bundleIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Memory with AXI port for use in elaboratable test harnesses. */
|
||||||
|
class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val config = p(ExtMem)
|
||||||
|
val totalSize = if (forceSize > 0) forceSize else BigInt(config.size)
|
||||||
|
val size = totalSize / channels
|
||||||
|
require(totalSize % channels == 0)
|
||||||
|
|
||||||
|
val node = AXI4BlindInputNode(Seq.fill(channels) {
|
||||||
|
AXI4MasterPortParameters(Seq(AXI4MasterParameters(
|
||||||
|
name = "dut",
|
||||||
|
id = IdRange(0, 1 << config.idBits)
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
|
||||||
|
for (i <- 0 until channels) {
|
||||||
|
val sram = LazyModule(new AXI4RAM(AddressSet(0, size-1), beatBytes = config.beatBytes))
|
||||||
|
sram.node := AXI4Buffer()(AXI4Fragmenter()(node))
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
val io = new Bundle {
|
||||||
|
val axi4 = node.bundleIn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,65 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.coreplex
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
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]
|
|
||||||
|
|
||||||
trait CoreplexRISCVPlatform extends CoreplexNetwork {
|
|
||||||
val module: CoreplexRISCVPlatformModule
|
|
||||||
|
|
||||||
val debug = LazyModule(new TLDebugModule())
|
|
||||||
debug.node := TLFragmenter(pbusBeatBytes, pbusBlockBytes)(pbus.node)
|
|
||||||
|
|
||||||
val plic = LazyModule(new TLPLIC(p(PLICKey)))
|
|
||||||
plic.node := TLFragmenter(pbusBeatBytes, pbusBlockBytes)(pbus.node)
|
|
||||||
plic.intnode := int_xbar.intnode
|
|
||||||
|
|
||||||
val clint = LazyModule(new CoreplexLocalInterrupter(p(ClintKey)))
|
|
||||||
clint.node := TLFragmenter(pbusBeatBytes, pbusBlockBytes)(pbus.node)
|
|
||||||
|
|
||||||
lazy val dts = DTS(bindingTree)
|
|
||||||
lazy val dtb = DTB(dts)
|
|
||||||
lazy val json = JSON(bindingTree)
|
|
||||||
}
|
|
||||||
|
|
||||||
trait CoreplexRISCVPlatformBundle extends CoreplexNetworkBundle {
|
|
||||||
val outer: CoreplexRISCVPlatform
|
|
||||||
|
|
||||||
val debug = new ClockedDMIIO().flip
|
|
||||||
val rtcToggle = Bool(INPUT)
|
|
||||||
val resetVector = UInt(INPUT, p(ResetVectorBits))
|
|
||||||
val ndreset = Bool(OUTPUT)
|
|
||||||
val dmactive = Bool(OUTPUT)
|
|
||||||
}
|
|
||||||
|
|
||||||
trait CoreplexRISCVPlatformModule extends CoreplexNetworkModule {
|
|
||||||
val outer: CoreplexRISCVPlatform
|
|
||||||
val io: CoreplexRISCVPlatformBundle
|
|
||||||
|
|
||||||
outer.debug.module.io.dmi <> io.debug
|
|
||||||
// TODO in inheriting traits: Set this to something meaningful, e.g. "component is in reset or powered down"
|
|
||||||
val nDebugComponents = outer.debug.intnode.bundleOut.size
|
|
||||||
outer.debug.module.io.ctrl.debugUnavail := Vec.fill(nDebugComponents){Bool(false)}
|
|
||||||
io.dmactive := outer.debug.module.io.ctrl.dmactive
|
|
||||||
io.ndreset := outer.debug.module.io.ctrl.ndreset
|
|
||||||
|
|
||||||
// Synchronize the rtc into the coreplex
|
|
||||||
val rtcSync = ShiftRegister(io.rtcToggle, 3)
|
|
||||||
val rtcLast = Reg(init = Bool(false), next=rtcSync)
|
|
||||||
outer.clint.module.io.rtcTick := Reg(init = Bool(false), next=(rtcSync & (~rtcLast)))
|
|
||||||
|
|
||||||
println(outer.dts)
|
|
||||||
ElaborationArtefacts.add("dts", outer.dts)
|
|
||||||
ElaborationArtefacts.add("json", outer.json)
|
|
||||||
}
|
|
24
src/main/scala/coreplex/RTC.scala
Normal file
24
src/main/scala/coreplex/RTC.scala
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.Field
|
||||||
|
import freechips.rocketchip.diplomacy.LazyMultiIOModuleImp
|
||||||
|
import freechips.rocketchip.devices.tilelink.HasPeripheryClint
|
||||||
|
|
||||||
|
/** Real-time clock is based on RTCPeriod relative to system clock.
|
||||||
|
*/
|
||||||
|
case object RTCPeriod extends Field[Option[Int]]
|
||||||
|
|
||||||
|
trait HasRTCModuleImp extends LazyMultiIOModuleImp {
|
||||||
|
val outer: HasPeripheryClint
|
||||||
|
private val internalPeriod: Option[Int] = outer.p(RTCPeriod)
|
||||||
|
require(internalPeriod.isDefined, "RTCPeriod is not defined")
|
||||||
|
|
||||||
|
// Use the static period to toggle the RTC
|
||||||
|
val (rtc_counter, _) = Counter(true.B, internalPeriod.get)
|
||||||
|
val tick = rtc_counter(log2Up(internalPeriod.get)-1)
|
||||||
|
|
||||||
|
outer.clint.module.io.rtcTick := tick
|
||||||
|
}
|
14
src/main/scala/coreplex/ResetVector.scala
Normal file
14
src/main/scala/coreplex/ResetVector.scala
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.tile.ResetVectorBits
|
||||||
|
|
||||||
|
/** A single place for all tiles to find out the reset vector */
|
||||||
|
trait HasResetVectorWire {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val resetVectorBits = p(ResetVectorBits)
|
||||||
|
val global_reset_vector = Wire(UInt(width = resetVectorBits))
|
||||||
|
}
|
130
src/main/scala/coreplex/RocketCoreplex.scala
Normal file
130
src/main/scala/coreplex/RocketCoreplex.scala
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tile._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
case object RocketTilesKey extends Field[Seq[RocketTileParams]]
|
||||||
|
case object RocketCrossing extends Field[CoreplexClockCrossing]
|
||||||
|
|
||||||
|
trait HasRocketTiles extends HasSystemBus
|
||||||
|
with HasPeripheryBus
|
||||||
|
with HasPeripheryPLIC
|
||||||
|
with HasPeripheryClint
|
||||||
|
with HasPeripheryDebug {
|
||||||
|
val module: HasRocketTilesModuleImp
|
||||||
|
|
||||||
|
private val crossing = p(RocketCrossing)
|
||||||
|
private val tileParams = p(RocketTilesKey)
|
||||||
|
val nRocketTiles = tileParams.size
|
||||||
|
|
||||||
|
// Handle interrupts to be routed directly into each tile
|
||||||
|
// TODO: figure out how to merge the localIntNodes and coreIntXbar below
|
||||||
|
val localIntCounts = tileParams.map(_.core.nLocalInterrupts)
|
||||||
|
val localIntNodes = tileParams map { t =>
|
||||||
|
(t.core.nLocalInterrupts > 0).option(LazyModule(new IntXbar).intnode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a wrapper for each tile that will wire it to coreplex devices and crossbars,
|
||||||
|
// according to the specified type of clock crossing.
|
||||||
|
val wiringTuple = localIntNodes.zip(tileParams).zipWithIndex
|
||||||
|
val wrappers: Seq[RocketTileWrapper] = wiringTuple.map { case ((lip, c), i) =>
|
||||||
|
val pWithExtra = p.alterPartial {
|
||||||
|
case TileKey => c
|
||||||
|
case BuildRoCC => c.rocc
|
||||||
|
case SharedMemoryTLEdge => sharedMemoryTLEdge
|
||||||
|
}
|
||||||
|
|
||||||
|
val wrapper = crossing match {
|
||||||
|
case SynchronousCrossing(params) => {
|
||||||
|
val wrapper = LazyModule(new SyncRocketTile(c, i)(pWithExtra))
|
||||||
|
sbus.fromSyncTiles(params) :=* wrapper.masterNode
|
||||||
|
wrapper.slaveNode :*= pbus.bufferToSlaves
|
||||||
|
wrapper
|
||||||
|
}
|
||||||
|
case AsynchronousCrossing(depth, sync) => {
|
||||||
|
val wrapper = LazyModule(new AsyncRocketTile(c, i)(pWithExtra))
|
||||||
|
sbus.fromAsyncTiles(depth, sync) :=* wrapper.masterNode
|
||||||
|
wrapper.slaveNode :*= pbus.toAsyncSlaves(sync)
|
||||||
|
wrapper
|
||||||
|
}
|
||||||
|
case RationalCrossing(direction) => {
|
||||||
|
val wrapper = LazyModule(new RationalRocketTile(c, i)(pWithExtra))
|
||||||
|
val sink = LazyModule(new TLRationalCrossingSink(direction))
|
||||||
|
val source = LazyModule(new TLRationalCrossingSource)
|
||||||
|
sbus.fromRationalTiles(direction) :=* wrapper.masterNode
|
||||||
|
wrapper.slaveNode :*= pbus.toRationalSlaves
|
||||||
|
wrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local Interrupts must be synchronized to the core clock
|
||||||
|
// before being passed into this module.
|
||||||
|
// This allows faster latency for interrupts which are already synchronized.
|
||||||
|
// The CLINT and PLIC outputs interrupts that are synchronous to the periphery clock,
|
||||||
|
// so may or may not need to be synchronized depending on the Tile's crossing type.
|
||||||
|
// Debug interrupt is definitely asynchronous in all cases.
|
||||||
|
val asyncIntXbar = LazyModule(new IntXbar)
|
||||||
|
asyncIntXbar.intnode := debug.intnode // debug
|
||||||
|
wrapper.asyncIntNode := asyncIntXbar.intnode
|
||||||
|
|
||||||
|
val periphIntXbar = LazyModule(new IntXbar)
|
||||||
|
periphIntXbar.intnode := clint.intnode // msip+mtip
|
||||||
|
periphIntXbar.intnode := plic.intnode // meip
|
||||||
|
if (c.core.useVM) periphIntXbar.intnode := plic.intnode // seip
|
||||||
|
wrapper.periphIntNode := periphIntXbar.intnode
|
||||||
|
|
||||||
|
val coreIntXbar = LazyModule(new IntXbar)
|
||||||
|
lip.foreach { coreIntXbar.intnode := _ } // lip
|
||||||
|
wrapper.coreIntNode := coreIntXbar.intnode
|
||||||
|
|
||||||
|
wrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClockedRocketTileInputs(implicit val p: Parameters) extends ParameterizedBundle
|
||||||
|
with HasExternallyDrivenTileConstants
|
||||||
|
with Clocked
|
||||||
|
|
||||||
|
trait HasRocketTilesBundle {
|
||||||
|
val rocket_tile_inputs: Vec[ClockedRocketTileInputs]
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasRocketTilesModuleImp extends LazyMultiIOModuleImp
|
||||||
|
with HasRocketTilesBundle
|
||||||
|
with HasResetVectorWire
|
||||||
|
with HasPeripheryDebugModuleImp {
|
||||||
|
val outer: HasRocketTiles
|
||||||
|
val rocket_tile_inputs = Wire(Vec(outer.nRocketTiles, new ClockedRocketTileInputs))
|
||||||
|
|
||||||
|
// Unconditionally wire up the non-diplomatic tile inputs
|
||||||
|
outer.wrappers.map(_.module).zip(rocket_tile_inputs).foreach { case(tile, wire) =>
|
||||||
|
tile.clock := wire.clock
|
||||||
|
tile.reset := wire.reset
|
||||||
|
tile.io.hartid := wire.hartid
|
||||||
|
tile.io.resetVector := wire.resetVector
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default values for tile inputs; may be overriden in other traits
|
||||||
|
rocket_tile_inputs.zipWithIndex.foreach { case(wire, i) =>
|
||||||
|
wire.clock := clock
|
||||||
|
wire.reset := reset
|
||||||
|
wire.hartid := UInt(i)
|
||||||
|
wire.resetVector := global_reset_vector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RocketCoreplex(implicit p: Parameters) extends BaseCoreplex
|
||||||
|
with HasRocketTiles {
|
||||||
|
override lazy val module = new RocketCoreplexModule(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class RocketCoreplexModule[+L <: RocketCoreplex](_outer: L) extends BaseCoreplexModule(_outer)
|
||||||
|
with HasRocketTilesModuleImp
|
@ -1,21 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.coreplex
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
import freechips.rocketchip.config.Parameters
|
|
||||||
|
|
||||||
class RocketPlex(implicit p: Parameters) extends BaseCoreplex
|
|
||||||
with CoreplexRISCVPlatform
|
|
||||||
with HasRocketTiles {
|
|
||||||
override lazy val module = new RocketPlexModule(this, () => new RocketPlexBundle(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
class RocketPlexBundle[+L <: RocketPlex](_outer: L) extends BaseCoreplexBundle(_outer)
|
|
||||||
with CoreplexRISCVPlatformBundle
|
|
||||||
with HasRocketTilesBundle
|
|
||||||
|
|
||||||
class RocketPlexModule[+L <: RocketPlex, +B <: RocketPlexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io)
|
|
||||||
with CoreplexRISCVPlatformModule
|
|
||||||
with HasRocketTilesModule
|
|
@ -1,135 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.coreplex
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
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 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[CoreplexClockCrossing]
|
|
||||||
|
|
||||||
trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|
||||||
val module: HasRocketTilesModule
|
|
||||||
|
|
||||||
private val crossing = p(RocketCrossing)
|
|
||||||
val tileParams = p(RocketTilesKey)
|
|
||||||
|
|
||||||
// Handle interrupts to be routed directly into each tile
|
|
||||||
val localIntNodes = tileParams map { t =>
|
|
||||||
(t.core.nLocalInterrupts > 0).option(IntInputNode())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a function for each tile that will wire it to coreplex devices and crossbars,
|
|
||||||
// according to the specified type of clock crossing.
|
|
||||||
val wiringTuple = localIntNodes.zip(tileParams).zipWithIndex
|
|
||||||
val rocketWires: Seq[HasRocketTilesBundle => Unit] = wiringTuple.map { case ((lip, c), i) =>
|
|
||||||
val pWithExtra = p.alterPartial {
|
|
||||||
case TileKey => c
|
|
||||||
case BuildRoCC => c.rocc
|
|
||||||
case SharedMemoryTLEdge => tile_splitter.node.edgesIn(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
val asyncIntXbar = LazyModule(new IntXbar)
|
|
||||||
val periphIntXbar = LazyModule(new IntXbar)
|
|
||||||
val coreIntXbar = LazyModule(new IntXbar)
|
|
||||||
|
|
||||||
// Local Interrupts must be synchronized to the core clock
|
|
||||||
// before being passed into this module.
|
|
||||||
// This allows faster latency for interrupts which are already synchronized.
|
|
||||||
// The CLINT and PLIC outputs interrupts that are synchronous to the periphery clock,
|
|
||||||
// so may or may not need to be synchronized depending on the Tile's
|
|
||||||
// synchronization type.
|
|
||||||
// Debug interrupt is definitely asynchronous in all cases.
|
|
||||||
|
|
||||||
asyncIntXbar.intnode := debug.intnode // debug
|
|
||||||
periphIntXbar.intnode := clint.intnode // msip+mtip
|
|
||||||
periphIntXbar.intnode := plic.intnode // meip
|
|
||||||
if (c.core.useVM) periphIntXbar.intnode := plic.intnode // seip
|
|
||||||
lip.foreach { coreIntXbar.intnode := _ } // lip
|
|
||||||
|
|
||||||
crossing match {
|
|
||||||
case SynchronousCrossing(params) => {
|
|
||||||
val wrapper = LazyModule(new SyncRocketTile(c, i)(pWithExtra))
|
|
||||||
val buffer = LazyModule(new TLBuffer(params))
|
|
||||||
val fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.allUncacheable))
|
|
||||||
buffer.node :=* wrapper.masterNode
|
|
||||||
fixer.node :=* buffer.node
|
|
||||||
tile_splitter.node :=* fixer.node
|
|
||||||
wrapper.slaveNode :*= pbus.node
|
|
||||||
wrapper.asyncIntNode := asyncIntXbar.intnode
|
|
||||||
wrapper.periphIntNode := periphIntXbar.intnode
|
|
||||||
wrapper.coreIntNode := coreIntXbar.intnode
|
|
||||||
(io: HasRocketTilesBundle) => {
|
|
||||||
// leave clock as default (simpler for hierarchical PnR)
|
|
||||||
wrapper.module.io.hartid := UInt(i)
|
|
||||||
wrapper.module.io.resetVector := io.resetVector
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case AsynchronousCrossing(depth, sync) => {
|
|
||||||
val wrapper = LazyModule(new AsyncRocketTile(c, i)(pWithExtra))
|
|
||||||
val sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
|
||||||
val source = LazyModule(new TLAsyncCrossingSource(sync))
|
|
||||||
val fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.allUncacheable))
|
|
||||||
sink.node :=* wrapper.masterNode
|
|
||||||
fixer.node :=* sink.node
|
|
||||||
tile_splitter.node :=* fixer.node
|
|
||||||
wrapper.slaveNode :*= source.node
|
|
||||||
wrapper.asyncIntNode := asyncIntXbar.intnode
|
|
||||||
wrapper.periphIntNode := periphIntXbar.intnode
|
|
||||||
wrapper.coreIntNode := coreIntXbar.intnode
|
|
||||||
source.node :*= pbus.node
|
|
||||||
(io: HasRocketTilesBundle) => {
|
|
||||||
wrapper.module.clock := io.tcrs(i).clock
|
|
||||||
wrapper.module.reset := io.tcrs(i).reset
|
|
||||||
wrapper.module.io.hartid := UInt(i)
|
|
||||||
wrapper.module.io.resetVector := io.resetVector
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case RationalCrossing(direction) => {
|
|
||||||
val wrapper = LazyModule(new RationalRocketTile(c, i)(pWithExtra))
|
|
||||||
val sink = LazyModule(new TLRationalCrossingSink(direction))
|
|
||||||
val source = LazyModule(new TLRationalCrossingSource)
|
|
||||||
val fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.allUncacheable))
|
|
||||||
sink.node :=* wrapper.masterNode
|
|
||||||
fixer.node :=* sink.node
|
|
||||||
tile_splitter.node :=* fixer.node
|
|
||||||
wrapper.slaveNode :*= source.node
|
|
||||||
wrapper.asyncIntNode := asyncIntXbar.intnode
|
|
||||||
wrapper.periphIntNode := periphIntXbar.intnode
|
|
||||||
wrapper.coreIntNode := coreIntXbar.intnode
|
|
||||||
source.node :*= pbus.node
|
|
||||||
(io: HasRocketTilesBundle) => {
|
|
||||||
wrapper.module.clock := io.tcrs(i).clock
|
|
||||||
wrapper.module.reset := io.tcrs(i).reset
|
|
||||||
wrapper.module.io.hartid := UInt(i)
|
|
||||||
wrapper.module.io.resetVector := io.resetVector
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait HasRocketTilesBundle extends CoreplexRISCVPlatformBundle {
|
|
||||||
val outer: HasRocketTiles
|
|
||||||
val local_interrupts = HeterogeneousBag(outer.localIntNodes.flatten.map(_.bundleIn))
|
|
||||||
val tcrs = Vec(p(RocketTilesKey).size, new Bundle {
|
|
||||||
val clock = Clock(INPUT)
|
|
||||||
val reset = Bool(INPUT)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
trait HasRocketTilesModule extends CoreplexRISCVPlatformModule {
|
|
||||||
val outer: HasRocketTiles
|
|
||||||
val io: HasRocketTilesBundle
|
|
||||||
outer.rocketWires.foreach { _(io) }
|
|
||||||
}
|
|
97
src/main/scala/coreplex/SystemBus.scala
Normal file
97
src/main/scala/coreplex/SystemBus.scala
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.coreplex
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
case class SystemBusParams(
|
||||||
|
beatBytes: Int,
|
||||||
|
blockBytes: Int,
|
||||||
|
masterBuffering: BufferParams = BufferParams.default,
|
||||||
|
slaveBuffering: BufferParams = BufferParams.flow // TODO should be BufferParams.none on BCE
|
||||||
|
) extends TLBusParams
|
||||||
|
|
||||||
|
case object SystemBusParams extends Field[SystemBusParams]
|
||||||
|
|
||||||
|
class SystemBus(params: SystemBusParams)(implicit p: Parameters) extends TLBusWrapper(params) {
|
||||||
|
private val master_splitter = LazyModule(new TLSplitter) // Allows cycle-free connection to external networks
|
||||||
|
inwardBufNode :=* master_splitter.node
|
||||||
|
|
||||||
|
protected def inwardSplitNode: TLInwardNode = master_splitter.node
|
||||||
|
protected def outwardSplitNode: TLOutwardNode = master_splitter.node
|
||||||
|
|
||||||
|
private val tile_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.allUncacheable))
|
||||||
|
private val port_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.all))
|
||||||
|
master_splitter.node :=* tile_fixer.node
|
||||||
|
master_splitter.node :=* port_fixer.node
|
||||||
|
|
||||||
|
def toSplitSlaves: TLOutwardNode = outwardSplitNode
|
||||||
|
|
||||||
|
val toPeripheryBus: TLOutwardNode = outwardWWNode
|
||||||
|
|
||||||
|
val toMemoryBus: TLOutwardNode = outwardNode
|
||||||
|
|
||||||
|
def fromAsyncMasters(depth: Int = 8, sync: Int = 3): TLAsyncInwardNode = {
|
||||||
|
val sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
||||||
|
inwardNode :=* sink.node
|
||||||
|
sink.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromSyncTiles(params: BufferParams): TLInwardNode = {
|
||||||
|
val buf = LazyModule(new TLBuffer(params))
|
||||||
|
tile_fixer.node :=* buf.node
|
||||||
|
buf.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromRationalTiles(dir: RationalDirection): TLRationalInwardNode = {
|
||||||
|
val sink = LazyModule(new TLRationalCrossingSink(direction = dir))
|
||||||
|
tile_fixer.node :=* sink.node
|
||||||
|
sink.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromAsyncTiles(depth: Int, sync: Int): TLAsyncInwardNode = {
|
||||||
|
val sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
||||||
|
tile_fixer.node :=* sink.node
|
||||||
|
sink.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromSyncPorts(params: BufferParams = BufferParams.default): TLInwardNode = {
|
||||||
|
val buffer = LazyModule(new TLBuffer(params))
|
||||||
|
port_fixer.node :=* buffer.node
|
||||||
|
buffer.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromSyncFIFOMaster(params: BufferParams = BufferParams.default): TLInwardNode = fromSyncPorts(params)
|
||||||
|
|
||||||
|
def fromAsyncPorts(depth: Int = 8, sync: Int = 3): TLAsyncInwardNode = {
|
||||||
|
val sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
||||||
|
port_fixer.node :=* sink.node
|
||||||
|
sink.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromAsyncFIFOMaster(depth: Int = 8, sync: Int = 3): TLAsyncInwardNode = fromAsyncPorts(depth, sync)
|
||||||
|
|
||||||
|
def fromRationalPorts(dir: RationalDirection): TLRationalInwardNode = {
|
||||||
|
val sink = LazyModule(new TLRationalCrossingSink(dir))
|
||||||
|
port_fixer.node :=* sink.node
|
||||||
|
sink.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromRationalFIFOMaster(dir: RationalDirection): TLRationalInwardNode = fromRationalPorts(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides buses that serve as attachment points,
|
||||||
|
* for use in traits that connect individual devices or external ports.
|
||||||
|
*/
|
||||||
|
trait HasSystemBus extends HasInterruptBus {
|
||||||
|
private val sbusParams = p(SystemBusParams)
|
||||||
|
val sbusBeatBytes = sbusParams.beatBytes
|
||||||
|
|
||||||
|
val sbus = new SystemBus(sbusParams)
|
||||||
|
|
||||||
|
def sharedMemoryTLEdge: TLEdge = sbus.edgesIn.head
|
||||||
|
}
|
@ -61,11 +61,11 @@ object DsbRegAddrs{
|
|||||||
|
|
||||||
// We want DATA to immediately follow PROGBUF so that we can
|
// We want DATA to immediately follow PROGBUF so that we can
|
||||||
// use them interchangeably.
|
// use them interchangeably.
|
||||||
def PROGBUF(cfg:DebugModuleConfig) = {DATA - (cfg.nProgramBufferWords * 4)}
|
def PROGBUF(cfg:DebugModuleParams) = {DATA - (cfg.nProgramBufferWords * 4)}
|
||||||
|
|
||||||
// We want abstract to be immediately before PROGBUF
|
// We want abstract to be immediately before PROGBUF
|
||||||
// because we auto-generate 2 instructions.
|
// because we auto-generate 2 instructions.
|
||||||
def ABSTRACT(cfg:DebugModuleConfig) = PROGBUF(cfg) - 8
|
def ABSTRACT(cfg:DebugModuleParams) = PROGBUF(cfg) - 8
|
||||||
|
|
||||||
def FLAGS = 0x400
|
def FLAGS = 0x400
|
||||||
def ROMBASE = 0x800
|
def ROMBASE = 0x800
|
||||||
@ -112,7 +112,7 @@ import DebugAbstractCommandType._
|
|||||||
* supportHartArray : Whether or not to implement the hart array register.
|
* supportHartArray : Whether or not to implement the hart array register.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
case class DebugModuleConfig (
|
case class DebugModuleParams (
|
||||||
nDMIAddrSize : Int = 7,
|
nDMIAddrSize : Int = 7,
|
||||||
nProgramBufferWords: Int = 16,
|
nProgramBufferWords: Int = 16,
|
||||||
nAbstractDataWords : Int = 4,
|
nAbstractDataWords : Int = 4,
|
||||||
@ -152,17 +152,17 @@ case class DebugModuleConfig (
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object DefaultDebugModuleConfig {
|
object DefaultDebugModuleParams {
|
||||||
|
|
||||||
def apply(xlen:Int /*TODO , val configStringAddr: Int*/): DebugModuleConfig = {
|
def apply(xlen:Int /*TODO , val configStringAddr: Int*/): DebugModuleParams = {
|
||||||
new DebugModuleConfig().copy(
|
new DebugModuleParams().copy(
|
||||||
nAbstractDataWords = (if (xlen == 32) 1 else if (xlen == 64) 2 else 4)
|
nAbstractDataWords = (if (xlen == 32) 1 else if (xlen == 64) 2 else 4)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
case object DMKey extends Field[DebugModuleConfig]
|
case object DebugModuleParams extends Field[DebugModuleParams]
|
||||||
|
|
||||||
// *****************************************
|
// *****************************************
|
||||||
// Module Interfaces
|
// Module Interfaces
|
||||||
@ -192,7 +192,7 @@ class DMIResp( ) extends Bundle {
|
|||||||
* Therefore it has the 'flipped' version of this.
|
* Therefore it has the 'flipped' version of this.
|
||||||
*/
|
*/
|
||||||
class DMIIO(implicit val p: Parameters) extends ParameterizedBundle()(p) {
|
class DMIIO(implicit val p: Parameters) extends ParameterizedBundle()(p) {
|
||||||
val req = new DecoupledIO(new DMIReq(p(DMKey).nDMIAddrSize))
|
val req = new DecoupledIO(new DMIReq(p(DebugModuleParams).nDMIAddrSize))
|
||||||
val resp = new DecoupledIO(new DMIResp).flip()
|
val resp = new DecoupledIO(new DMIResp).flip()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +443,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
|
|||||||
|
|
||||||
lazy val module = new LazyModuleImp(this){
|
lazy val module = new LazyModuleImp(this){
|
||||||
|
|
||||||
val cfg = p(DMKey)
|
val cfg = p(DebugModuleParams)
|
||||||
|
|
||||||
val nComponents = getNComponents()
|
val nComponents = getNComponents()
|
||||||
|
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
package freechips.rocketchip.devices.debug
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
import freechips.rocketchip.devices.debug.{DMIConsts, DMIIO, DMIReq, DMIResp}
|
|
||||||
import freechips.rocketchip.jtag._
|
import freechips.rocketchip.jtag._
|
||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
case object IncludeJtagDTM extends Field[Boolean]
|
|
||||||
|
|
||||||
case class JtagDTMConfig (
|
case class JtagDTMConfig (
|
||||||
idcodeVersion : Int, // chosen by manuf.
|
idcodeVersion : Int, // chosen by manuf.
|
||||||
idcodePartNum : Int, // Chosen by manuf.
|
idcodePartNum : Int, // Chosen by manuf.
|
||||||
@ -63,12 +60,19 @@ class DTMInfo extends Bundle {
|
|||||||
val debugVersion = UInt(4.W)
|
val debugVersion = UInt(4.W)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A wrapper around JTAG providing a reset signal and manufacturer id. */
|
||||||
|
class SystemJTAGIO extends Bundle {
|
||||||
|
val jtag = new JTAGIO(hasTRSTn = false).flip
|
||||||
|
val reset = Bool(INPUT)
|
||||||
|
val mfr_id = UInt(INPUT, 11)
|
||||||
|
}
|
||||||
|
|
||||||
class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig)
|
class DebugTransportModuleJTAG(debugAddrBits: Int, c: JtagDTMConfig)
|
||||||
(implicit val p: Parameters) extends Module {
|
(implicit val p: Parameters) extends Module {
|
||||||
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val dmi = new DMIIO()(p)
|
val dmi = new DMIIO()(p)
|
||||||
val jtag = Flipped(new JTAGIO(hasTRSTn = false))
|
val jtag = Flipped(new JTAGIO(hasTRSTn = false)) // TODO: re-use SystemJTAGIO here?
|
||||||
val jtag_reset = Bool(INPUT)
|
val jtag_reset = Bool(INPUT)
|
||||||
val jtag_mfr_id = UInt(INPUT, 11)
|
val jtag_mfr_id = UInt(INPUT, 11)
|
||||||
val fsmReset = Bool(OUTPUT)
|
val fsmReset = Bool(OUTPUT)
|
123
src/main/scala/devices/debug/Periphery.scala
Normal file
123
src/main/scala/devices/debug/Periphery.scala
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.devices.debug
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.coreplex.HasPeripheryBus
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.jtag._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
/** A knob selecting one of the two possible debug interfaces */
|
||||||
|
case object IncludeJtagDTM extends Field[Boolean]
|
||||||
|
|
||||||
|
/** A wrapper bundle containing one of the two possible debug interfaces */
|
||||||
|
class DebugIO(implicit p: Parameters) extends ParameterizedBundle()(p) {
|
||||||
|
val clockeddmi = (!p(IncludeJtagDTM)).option(new ClockedDMIIO().flip)
|
||||||
|
val systemjtag = (p(IncludeJtagDTM)).option(new SystemJTAGIO)
|
||||||
|
val ndreset = Bool(OUTPUT)
|
||||||
|
val dmactive = Bool(OUTPUT)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Either adds a JTAG DTM to system, and exports a JTAG interface,
|
||||||
|
* or exports the Debug Module Interface (DMI), based on a global parameter.
|
||||||
|
*/
|
||||||
|
trait HasPeripheryDebug extends HasPeripheryBus {
|
||||||
|
val module: HasPeripheryDebugModuleImp
|
||||||
|
|
||||||
|
val debug = LazyModule(new TLDebugModule())
|
||||||
|
|
||||||
|
debug.node := pbus.toVariableWidthSlaves
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasPeripheryDebugBundle {
|
||||||
|
implicit val p: Parameters
|
||||||
|
|
||||||
|
val debug: DebugIO
|
||||||
|
|
||||||
|
def connectDebug(c: Clock, r: Bool, out: Bool) {
|
||||||
|
debug.clockeddmi.foreach { d =>
|
||||||
|
val dtm = Module(new SimDTM).connect(c, r, d, out)
|
||||||
|
}
|
||||||
|
debug.systemjtag.foreach { sj =>
|
||||||
|
val jtag = Module(new JTAGVPI).connect(sj.jtag, sj.reset, r, out)
|
||||||
|
sj.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasPeripheryDebugModuleImp extends LazyMultiIOModuleImp with HasPeripheryDebugBundle {
|
||||||
|
val outer: HasPeripheryDebug
|
||||||
|
|
||||||
|
val debug = IO(new DebugIO)
|
||||||
|
|
||||||
|
debug.clockeddmi.foreach { dbg => outer.debug.module.io.dmi <> dbg }
|
||||||
|
|
||||||
|
val dtm = debug.systemjtag.map { sj =>
|
||||||
|
val dtm = Module(new DebugTransportModuleJTAG(p(DebugModuleParams).nDMIAddrSize, p(JtagDTMKey)))
|
||||||
|
dtm.io.jtag <> sj.jtag
|
||||||
|
|
||||||
|
dtm.clock := sj.jtag.TCK
|
||||||
|
dtm.io.jtag_reset := sj.reset
|
||||||
|
dtm.io.jtag_mfr_id := sj.mfr_id
|
||||||
|
dtm.reset := dtm.io.fsmReset
|
||||||
|
|
||||||
|
outer.debug.module.io.dmi.dmi <> dtm.io.dmi
|
||||||
|
outer.debug.module.io.dmi.dmiClock := sj.jtag.TCK
|
||||||
|
outer.debug.module.io.dmi.dmiReset := ResetCatchAndSync(sj.jtag.TCK, sj.reset, "dmiResetCatch")
|
||||||
|
dtm
|
||||||
|
}
|
||||||
|
|
||||||
|
debug.ndreset := outer.debug.module.io.ctrl.ndreset
|
||||||
|
debug.dmactive := outer.debug.module.io.ctrl.dmactive
|
||||||
|
|
||||||
|
// TODO in inheriting traits: Set this to something meaningful, e.g. "component is in reset or powered down"
|
||||||
|
outer.debug.module.io.ctrl.debugUnavail.foreach { _ := Bool(false) }
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimDTM(implicit p: Parameters) extends BlackBox {
|
||||||
|
val io = new Bundle {
|
||||||
|
val clk = Clock(INPUT)
|
||||||
|
val reset = Bool(INPUT)
|
||||||
|
val debug = new DMIIO
|
||||||
|
val exit = UInt(OUTPUT, 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
def connect(tbclk: Clock, tbreset: Bool, dutio: ClockedDMIIO, tbsuccess: Bool) = {
|
||||||
|
io.clk := tbclk
|
||||||
|
io.reset := tbreset
|
||||||
|
dutio.dmi <> io.debug
|
||||||
|
dutio.dmiClock := tbclk
|
||||||
|
dutio.dmiReset := tbreset
|
||||||
|
|
||||||
|
tbsuccess := io.exit === UInt(1)
|
||||||
|
when (io.exit >= UInt(2)) {
|
||||||
|
printf("*** FAILED *** (exit code = %d)\n", io.exit >> UInt(1))
|
||||||
|
stop(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JTAGVPI(implicit val p: Parameters) extends BlackBox {
|
||||||
|
val io = new Bundle {
|
||||||
|
val jtag = new JTAGIO(hasTRSTn = false)
|
||||||
|
val enable = Bool(INPUT)
|
||||||
|
val init_done = Bool(INPUT)
|
||||||
|
}
|
||||||
|
|
||||||
|
def connect(dutio: JTAGIO, jtag_reset: Bool, tbreset: Bool, tbsuccess: Bool) = {
|
||||||
|
dutio <> io.jtag
|
||||||
|
|
||||||
|
dutio.TRSTn.foreach{ _:= false.B}
|
||||||
|
jtag_reset := tbreset
|
||||||
|
|
||||||
|
io.enable := ~tbreset
|
||||||
|
io.init_done := ~tbreset
|
||||||
|
|
||||||
|
// Success is determined by the gdbserver
|
||||||
|
// which is controlling this simulation.
|
||||||
|
tbsuccess := Bool(false)
|
||||||
|
}
|
||||||
|
}
|
41
src/main/scala/devices/tilelink/BootROM.scala
Normal file
41
src/main/scala/devices/tilelink/BootROM.scala
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.devices.tilelink
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.coreplex._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import java.nio.{ByteBuffer, ByteOrder}
|
||||||
|
import java.nio.file.{Files, Paths}
|
||||||
|
|
||||||
|
/** Size, location and contents of the boot rom. */
|
||||||
|
case class BootROMParams(
|
||||||
|
address: BigInt = 0x10000,
|
||||||
|
size: Int = 0x10000,
|
||||||
|
hang: BigInt = 0x10040,
|
||||||
|
contentFileName: String)
|
||||||
|
case object BootROMParams extends Field[BootROMParams]
|
||||||
|
|
||||||
|
/** Adds a boot ROM that contains the DTB describing the system's coreplex. */
|
||||||
|
trait HasPeripheryBootROM extends HasPeripheryBus {
|
||||||
|
val dtb: DTB
|
||||||
|
private val params = p(BootROMParams)
|
||||||
|
private lazy val contents = {
|
||||||
|
val romdata = Files.readAllBytes(Paths.get(params.contentFileName))
|
||||||
|
val rom = ByteBuffer.wrap(romdata)
|
||||||
|
rom.array() ++ dtb.contents
|
||||||
|
}
|
||||||
|
def resetVector: BigInt = params.hang
|
||||||
|
|
||||||
|
val bootrom = LazyModule(new TLROM(params.address, params.size, contents, true, pbus.beatBytes))
|
||||||
|
|
||||||
|
bootrom.node := pbus.toVariableWidthSlaves
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Coreplex will power-on running at 0x10040 (BootROM) */
|
||||||
|
trait HasPeripheryBootROMModuleImp extends LazyMultiIOModuleImp
|
||||||
|
with HasResetVectorWire {
|
||||||
|
val outer: HasPeripheryBootROM
|
||||||
|
global_reset_vector := UInt(outer.resetVector, width = resetVectorBits)
|
||||||
|
}
|
@ -3,7 +3,8 @@
|
|||||||
package freechips.rocketchip.devices.tilelink
|
package freechips.rocketchip.devices.tilelink
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import freechips.rocketchip.config.Parameters
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.coreplex.HasPeripheryBus
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.regmapper._
|
import freechips.rocketchip.regmapper._
|
||||||
import freechips.rocketchip.tile.XLen
|
import freechips.rocketchip.tile.XLen
|
||||||
@ -29,6 +30,8 @@ case class ClintParams(baseAddress: BigInt = 0x02000000)
|
|||||||
def address = AddressSet(baseAddress, ClintConsts.size-1)
|
def address = AddressSet(baseAddress, ClintConsts.size-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case object ClintParams extends Field[ClintParams]
|
||||||
|
|
||||||
class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) extends LazyModule
|
class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) extends LazyModule
|
||||||
{
|
{
|
||||||
import ClintConsts._
|
import ClintConsts._
|
||||||
@ -90,3 +93,9 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte
|
|||||||
timeOffset -> makeRegFields(time))
|
timeOffset -> makeRegFields(time))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Trait that will connect a Clint to a coreplex */
|
||||||
|
trait HasPeripheryClint extends HasPeripheryBus {
|
||||||
|
val clint = LazyModule(new CoreplexLocalInterrupter(p(ClintParams)))
|
||||||
|
clint.node := pbus.toVariableWidthSlaves
|
||||||
|
}
|
||||||
|
@ -3,13 +3,21 @@
|
|||||||
package freechips.rocketchip.devices.tilelink
|
package freechips.rocketchip.devices.tilelink
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import freechips.rocketchip.config.Parameters
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.coreplex.HasPeripheryBus
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
|
import scala.math.min
|
||||||
|
|
||||||
class TLError(address: Seq[AddressSet], beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
|
case class ErrorParams(address: Seq[AddressSet])
|
||||||
|
case object ErrorParams extends Field[ErrorParams]
|
||||||
|
|
||||||
|
/** Adds a /dev/null slave that generates TL error response messages */
|
||||||
|
class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
|
||||||
{
|
{
|
||||||
|
val address = params.address
|
||||||
|
|
||||||
val device = new SimpleDevice("error-device", Seq("sifive,error0"))
|
val device = new SimpleDevice("error-device", Seq("sifive,error0"))
|
||||||
|
|
||||||
val node = TLManagerNode(Seq(TLManagerPortParameters(
|
val node = TLManagerNode(Seq(TLManagerPortParameters(
|
||||||
@ -55,3 +63,13 @@ class TLError(address: Seq[AddressSet], beatBytes: Int = 4)(implicit p: Paramete
|
|||||||
in.e.ready := Bool(true)
|
in.e.ready := Bool(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait HasPeripheryErrorSlave extends HasPeripheryBus {
|
||||||
|
private val params = p(ErrorParams)
|
||||||
|
private val maxXfer = min(params.address.map(_.alignment).max.toInt, 4096)
|
||||||
|
val error = LazyModule(new TLError(params, pbus.beatBytes))
|
||||||
|
|
||||||
|
// Most slaves do not support a 4kB burst so this slave ends up with many more source bits than others;
|
||||||
|
// we exclude the onerously large TLMonitor that results.
|
||||||
|
error.node connectButDontMonitor pbus.toLargeBurstSlave(maxXfer)
|
||||||
|
}
|
||||||
|
@ -4,7 +4,8 @@ package freechips.rocketchip.devices.tilelink
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
import freechips.rocketchip.config.Parameters
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.coreplex.{HasInterruptBus, HasPeripheryBus}
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.regmapper._
|
import freechips.rocketchip.regmapper._
|
||||||
import freechips.rocketchip.tile.XLen
|
import freechips.rocketchip.tile.XLen
|
||||||
@ -57,6 +58,8 @@ case class PLICParams(baseAddress: BigInt = 0xC000000, maxPriorities: Int = 7)
|
|||||||
def address = AddressSet(baseAddress, PLICConsts.size-1)
|
def address = AddressSet(baseAddress, PLICConsts.size-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case object PLICParams extends Field[PLICParams]
|
||||||
|
|
||||||
/** Platform-Level Interrupt Controller */
|
/** Platform-Level Interrupt Controller */
|
||||||
class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
|
class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
|
||||||
{
|
{
|
||||||
@ -232,3 +235,10 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
|
|||||||
e(0) := false
|
e(0) := false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Trait that will connect a PLIC to a coreplex */
|
||||||
|
trait HasPeripheryPLIC extends HasInterruptBus with HasPeripheryBus {
|
||||||
|
val plic = LazyModule(new TLPLIC(p(PLICParams)))
|
||||||
|
plic.node := pbus.toVariableWidthSlaves
|
||||||
|
plic.intnode := ibus.toPLIC
|
||||||
|
}
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
package freechips.rocketchip.devices.tilelink
|
package freechips.rocketchip.devices.tilelink
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import freechips.rocketchip.config.Parameters
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.coreplex.HasMemoryBus
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
@ -44,3 +45,23 @@ class TLZero(address: AddressSet, resources: Seq[Resource], executable: Boolean
|
|||||||
in.e.ready := Bool(true)
|
in.e.ready := Bool(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specifies the location of the Zero device */
|
||||||
|
case class ZeroParams(base: Long, size: Long, beatBytes: Int)
|
||||||
|
case object ZeroParams extends Field[ZeroParams]
|
||||||
|
|
||||||
|
/** Adds a /dev/null slave that generates zero-filled responses to reads */
|
||||||
|
trait HasMemoryZeroSlave extends HasMemoryBus {
|
||||||
|
private val params = p(ZeroParams)
|
||||||
|
private val device = new SimpleDevice("rom", Seq("ucbbar,cacheable-zero0"))
|
||||||
|
|
||||||
|
val zeros = memBuses.map(_.toVariableWidthSlave).zipWithIndex.map { case (node, channel) =>
|
||||||
|
val channels = memBuses.size
|
||||||
|
val base = AddressSet(params.base, params.size-1)
|
||||||
|
val filter = AddressSet(channel * cacheBlockBytes, ~((channels-1) * cacheBlockBytes))
|
||||||
|
val address = base.intersect(filter).get
|
||||||
|
val zero = LazyModule(new TLZero(address, beatBytes = params.beatBytes, resources = device.reg("mem")))
|
||||||
|
zero.node := node
|
||||||
|
zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -267,6 +267,8 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
|||||||
override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, true)
|
override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, true)
|
||||||
|
|
||||||
def connectButDontMonitor(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE, false)
|
def connectButDontMonitor(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE, false)
|
||||||
|
def connectButDontMonitorSlaves(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR, false)
|
||||||
|
def connectButDontMonitorMasters(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, false)
|
||||||
|
|
||||||
// meta-data for printing the node graph
|
// meta-data for printing the node graph
|
||||||
protected[diplomacy] def colour = inner.colour
|
protected[diplomacy] def colour = inner.colour
|
||||||
|
@ -4,15 +4,14 @@
|
|||||||
package freechips.rocketchip.groundtest
|
package freechips.rocketchip.groundtest
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import freechips.rocketchip.chip.{BaseConfig, ExtMem}
|
|
||||||
import freechips.rocketchip.config.Config
|
import freechips.rocketchip.config.Config
|
||||||
import freechips.rocketchip.coreplex.{CacheBlockBytes, L1toL2Config, WithBufferlessBroadcastHub}
|
import freechips.rocketchip.coreplex._
|
||||||
import freechips.rocketchip.rocket.{DCacheParams, PAddrBits}
|
import freechips.rocketchip.rocket.{DCacheParams, PAddrBits}
|
||||||
import freechips.rocketchip.tile.{MaxHartIdBits, XLen}
|
import freechips.rocketchip.tile.{MaxHartIdBits, XLen}
|
||||||
|
|
||||||
/** Actual testing target Configs */
|
/** Actual testing target Configs */
|
||||||
|
|
||||||
class TraceGenConfig extends Config(new WithTraceGen(List.fill(2){ DCacheParams(nSets = 16, nWays = 1) }) ++ new BaseConfig)
|
class TraceGenConfig extends Config(new WithTraceGen(List.fill(2){ DCacheParams(nSets = 16, nWays = 1) }) ++ new BaseCoreplexConfig)
|
||||||
|
|
||||||
class TraceGenBufferlessConfig extends Config(new WithBufferlessBroadcastHub ++ new TraceGenConfig)
|
class TraceGenBufferlessConfig extends Config(new WithBufferlessBroadcastHub ++ new TraceGenConfig)
|
||||||
|
|
||||||
@ -26,8 +25,8 @@ class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) extends Config(
|
|||||||
addrBag = {
|
addrBag = {
|
||||||
val nSets = 2
|
val nSets = 2
|
||||||
val nWays = 1
|
val nWays = 1
|
||||||
val blockOffset = log2Up(site(CacheBlockBytes))
|
val blockOffset = site(SystemBusParams).blockOffset
|
||||||
val nBeats = site(CacheBlockBytes)/site(L1toL2Config).beatBytes
|
val nBeats = site(SystemBusParams).blockBeats
|
||||||
List.tabulate(4 * nWays) { i =>
|
List.tabulate(4 * nWays) { i =>
|
||||||
Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) }
|
Seq.tabulate(nBeats) { j => BigInt((j * 8) + ((i * nSets) << blockOffset)) }
|
||||||
}.flatten
|
}.flatten
|
||||||
|
@ -14,33 +14,43 @@ import scala.math.max
|
|||||||
|
|
||||||
case object TileId extends Field[Int]
|
case object TileId extends Field[Int]
|
||||||
|
|
||||||
class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
|
class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex
|
||||||
|
with HasMasterAXI4MemPort
|
||||||
|
with HasPeripheryTestRAMSlave {
|
||||||
val tileParams = p(GroundTestTilesKey)
|
val tileParams = p(GroundTestTilesKey)
|
||||||
val tiles = tileParams.zipWithIndex.map { case(c, i) => LazyModule(
|
val tiles = tileParams.zipWithIndex.map { case(c, i) => LazyModule(
|
||||||
c.build(i, p.alterPartial {
|
c.build(i, p.alterPartial {
|
||||||
case TileKey => c
|
case TileKey => c
|
||||||
case SharedMemoryTLEdge => tile_splitter.node.edgesIn(0)
|
case SharedMemoryTLEdge => sbus.edgesIn.head
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
|
|
||||||
val fixer = LazyModule(new TLFIFOFixer)
|
tiles.foreach { sbus.fromSyncTiles(BufferParams.default) :=* _.masterNode }
|
||||||
tile_splitter.node :=* fixer.node
|
|
||||||
tiles.foreach { fixer.node :=* _.masterNode }
|
|
||||||
|
|
||||||
val pbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), false, pbusBeatBytes))
|
val pbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), false, pbus.beatBytes))
|
||||||
pbusRAM.node := TLFragmenter(pbusBeatBytes, pbusBlockBytes)(pbus.node)
|
pbusRAM.node := pbus.toVariableWidthSlaves
|
||||||
|
|
||||||
override lazy val module = new GroundTestCoreplexModule(this, () => new GroundTestCoreplexBundle(this))
|
override lazy val module = new GroundTestCoreplexModule(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroundTestCoreplexBundle[+L <: GroundTestCoreplex](_outer: L) extends BaseCoreplexBundle(_outer) {
|
class GroundTestCoreplexModule[+L <: GroundTestCoreplex](_outer: L) extends BaseCoreplexModule(_outer)
|
||||||
val success = Bool(OUTPUT)
|
with HasMasterAXI4MemPortModuleImp {
|
||||||
}
|
val success = IO(Bool(OUTPUT))
|
||||||
|
|
||||||
class GroundTestCoreplexModule[+L <: GroundTestCoreplex, +B <: GroundTestCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) {
|
|
||||||
|
|
||||||
outer.tiles.zipWithIndex.map { case(t, i) => t.module.io.hartid := UInt(i) }
|
outer.tiles.zipWithIndex.map { case(t, i) => t.module.io.hartid := UInt(i) }
|
||||||
|
|
||||||
val status = DebugCombiner(outer.tiles.map(_.module.io.status))
|
val status = DebugCombiner(outer.tiles.map(_.module.io.status))
|
||||||
io.success := status.finished
|
success := status.finished
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a SRAM to the system for testing purposes. */
|
||||||
|
trait HasPeripheryTestRAMSlave extends HasPeripheryBus {
|
||||||
|
val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), true, pbus.beatBytes))
|
||||||
|
testram.node := pbus.toVariableWidthSlaves
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a fuzzing master to the system for testing purposes. */
|
||||||
|
trait HasPeripheryTestFuzzMaster extends HasPeripheryBus {
|
||||||
|
val fuzzer = LazyModule(new TLFuzzer(5000))
|
||||||
|
pbus.bufferFromMasters := fuzzer.node
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy.LazyModule
|
|||||||
|
|
||||||
class TestHarness(implicit p: Parameters) extends Module {
|
class TestHarness(implicit p: Parameters) extends Module {
|
||||||
val io = new Bundle { val success = Bool(OUTPUT) }
|
val io = new Bundle { val success = Bool(OUTPUT) }
|
||||||
val dut = Module(LazyModule(new GroundTestTop).module)
|
val dut = Module(LazyModule(new GroundTestCoreplex).module)
|
||||||
io.success := dut.io_success
|
io.success := dut.success
|
||||||
dut.connectSimAXIMem()
|
dut.connectSimAXIMem()
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,8 @@ package freechips.rocketchip.groundtest
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
import freechips.rocketchip.coreplex._
|
import freechips.rocketchip.coreplex._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.rocket.{HellaCache, RocketCoreParams}
|
||||||
import freechips.rocketchip.rocket._
|
|
||||||
import freechips.rocketchip.chip._
|
|
||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.tile._
|
||||||
import freechips.rocketchip.tilelink._
|
|
||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
trait GroundTestTileParams extends TileParams {
|
trait GroundTestTileParams extends TileParams {
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
|
|
||||||
package freechips.rocketchip.groundtest
|
|
||||||
|
|
||||||
import Chisel._
|
|
||||||
|
|
||||||
import freechips.rocketchip.config.Parameters
|
|
||||||
import freechips.rocketchip.diplomacy.LazyModule
|
|
||||||
import freechips.rocketchip.chip._
|
|
||||||
|
|
||||||
class GroundTestTop(implicit p: Parameters) extends BaseSystem
|
|
||||||
with HasPeripheryMasterAXI4MemPort
|
|
||||||
with HasPeripheryTestRAMSlave {
|
|
||||||
override lazy val module = new GroundTestTopModule(this)
|
|
||||||
|
|
||||||
val coreplex = LazyModule(new GroundTestCoreplex)
|
|
||||||
|
|
||||||
socBus.node := coreplex.mmio
|
|
||||||
coreplex.mmioInt := intBus.intnode
|
|
||||||
(mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel }
|
|
||||||
}
|
|
||||||
|
|
||||||
class GroundTestTopModule[+L <: GroundTestTop](_outer: L) extends BaseSystemModule(_outer)
|
|
||||||
with HasPeripheryMasterAXI4MemPortModuleImp {
|
|
||||||
val io_success = IO(Bool(OUTPUT))
|
|
||||||
io_success := outer.coreplex.module.io.success
|
|
||||||
}
|
|
@ -183,9 +183,10 @@ class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer)
|
|||||||
val io = new HellaCacheBundle(outer)
|
val io = new HellaCacheBundle(outer)
|
||||||
val tl_out = io.mem(0)
|
val tl_out = io.mem(0)
|
||||||
|
|
||||||
// IOMSHRs must be FIFO for all regions with effects
|
private val fifoManagers = edge.manager.managers.filter(TLFIFOFixer.allUncacheable)
|
||||||
edge.manager.managers.foreach { m =>
|
fifoManagers.foreach { m =>
|
||||||
require (m.fifoId == Some(0) || !TLFIFOFixer.allUncacheable(m))
|
require (m.fifoId == fifoManagers.head.fifoId,
|
||||||
|
s"IOMSHRs must be FIFO for all regions with effects, but HellaCache sees ${m.nodePath.map(_.name)}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,14 +105,14 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend with HasCor
|
|||||||
// 1) Frontend always exists, but may or may not have a scratchpad node
|
// 1) Frontend always exists, but may or may not have a scratchpad node
|
||||||
val fg = LazyModule(new TLFragmenter(fetchWidth*coreInstBytes, p(CacheBlockBytes), earlyAck=true))
|
val fg = LazyModule(new TLFragmenter(fetchWidth*coreInstBytes, p(CacheBlockBytes), earlyAck=true))
|
||||||
val ww = LazyModule(new TLWidthWidget(xLen/8))
|
val ww = LazyModule(new TLWidthWidget(xLen/8))
|
||||||
frontend.slaveNode :*= fg.node
|
frontend.slaveNode connectButDontMonitorSlaves fg.node
|
||||||
fg.node :*= ww.node
|
fg.node connectButDontMonitorSlaves ww.node
|
||||||
ww.node :*= slaveNode
|
ww.node connectButDontMonitorSlaves slaveNode
|
||||||
|
|
||||||
// 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad
|
// 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad
|
||||||
val scratch = tileParams.dcache.flatMap(d => d.scratch.map(s =>
|
val scratch = tileParams.dcache.flatMap(d => d.scratch.map(s =>
|
||||||
LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1)))))
|
LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1)))))
|
||||||
scratch foreach { lm => lm.node := TLFragmenter(xLen/8, p(CacheBlockBytes), earlyAck=true)(slaveNode) }
|
scratch foreach { lm => lm.node connectButDontMonitor TLFragmenter(xLen/8, p(CacheBlockBytes), earlyAck=true)(slaveNode) }
|
||||||
|
|
||||||
def findScratchpadFromICache: Option[AddressSet] = scratch.map { s =>
|
def findScratchpadFromICache: Option[AddressSet] = scratch.map { s =>
|
||||||
val finalNode = frontend.masterNode.edgesOut.head.manager.managers.find(_.nodePath.last == s.node)
|
val finalNode = frontend.masterNode.edgesOut.head.manager.managers.find(_.nodePath.last == s.node)
|
||||||
|
84
src/main/scala/system/Configs.scala
Normal file
84
src/main/scala/system/Configs.scala
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
// See LICENSE.Berkeley for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.system
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.Config
|
||||||
|
import freechips.rocketchip.coreplex._
|
||||||
|
import freechips.rocketchip.devices.debug._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
|
||||||
|
class BaseConfig extends Config(new BaseCoreplexConfig().alter((site,here,up) => {
|
||||||
|
// DTS descriptive parameters
|
||||||
|
case DTSModel => "freechips,rocketchip-unknown"
|
||||||
|
case DTSCompat => Nil
|
||||||
|
case DTSTimebase => BigInt(1000000) // 1 MHz
|
||||||
|
case RTCPeriod => Some(1000) // Implies coreplex clock is DTSTimebase * RTCPeriod = 1 GHz
|
||||||
|
// External port parameters
|
||||||
|
case IncludeJtagDTM => false
|
||||||
|
case JtagDTMKey => new JtagDTMKeyDefault()
|
||||||
|
case NExtTopInterrupts => 2
|
||||||
|
case ExtMem => MasterPortParams(
|
||||||
|
base = 0x80000000L,
|
||||||
|
size = 0x10000000L,
|
||||||
|
beatBytes = site(MemoryBusParams).beatBytes,
|
||||||
|
idBits = 4)
|
||||||
|
case ExtBus => MasterPortParams(
|
||||||
|
base = 0x60000000L,
|
||||||
|
size = 0x20000000L,
|
||||||
|
beatBytes = site(MemoryBusParams).beatBytes,
|
||||||
|
idBits = 4)
|
||||||
|
case ExtIn => SlavePortParams(beatBytes = 8, idBits = 8, sourceBits = 4)
|
||||||
|
// Additional device Parameters
|
||||||
|
case ErrorParams => ErrorParams(Seq(AddressSet(0x3000, 0xfff)))
|
||||||
|
case BootROMParams => BootROMParams(contentFileName = "./bootrom/bootrom.img")
|
||||||
|
}))
|
||||||
|
|
||||||
|
class DefaultConfig extends Config(new WithNBigCores(1) ++ new BaseConfig)
|
||||||
|
|
||||||
|
class DefaultBufferlessConfig extends Config(
|
||||||
|
new WithBufferlessBroadcastHub ++ new WithNBigCores(1) ++ new BaseConfig)
|
||||||
|
|
||||||
|
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 DualChannelConfig extends Config(new WithNMemoryChannels(2) ++ new BaseConfig)
|
||||||
|
|
||||||
|
class DualChannelDualBankConfig extends Config(
|
||||||
|
new WithNMemoryChannels(2) ++
|
||||||
|
new WithNBanksPerMemChannel(2) ++ new BaseConfig)
|
||||||
|
|
||||||
|
class RoccExampleConfig extends Config(new WithRoccExample ++ new DefaultConfig)
|
||||||
|
|
||||||
|
class Edge128BitConfig extends Config(
|
||||||
|
new WithEdgeDataBits(128) ++ new BaseConfig)
|
||||||
|
class Edge32BitConfig extends Config(
|
||||||
|
new WithEdgeDataBits(32) ++ new BaseConfig)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseConfig)
|
||||||
|
|
||||||
|
class DualCoreConfig extends Config(
|
||||||
|
new WithNBigCores(2) ++ new BaseConfig)
|
||||||
|
|
||||||
|
class HeterogeneousDualCoreConfig extends Config(
|
||||||
|
new WithNSmallCores(1) ++ new WithNBigCores(1) ++ new BaseConfig)
|
||||||
|
|
||||||
|
class TinyConfig extends Config(
|
||||||
|
new WithNMemoryChannels(0) ++
|
||||||
|
new WithStatelessBridge ++
|
||||||
|
new WithNTinyCores(1) ++
|
||||||
|
new BaseConfig)
|
||||||
|
|
||||||
|
class DefaultFPGAConfig extends Config(new BaseConfig)
|
||||||
|
|
||||||
|
class DefaultFPGASmallConfig extends Config(new WithNSmallCores(1) ++ new DefaultFPGAConfig)
|
26
src/main/scala/system/ExampleRocketSystem.scala
Normal file
26
src/main/scala/system/ExampleRocketSystem.scala
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.system
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.coreplex._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
|
||||||
|
/** Example Top with periphery devices and ports, and a Rocket coreplex */
|
||||||
|
class ExampleRocketSystem(implicit p: Parameters) extends RocketCoreplex
|
||||||
|
with HasAsyncExtInterrupts
|
||||||
|
with HasMasterAXI4MemPort
|
||||||
|
with HasMasterAXI4MMIOPort
|
||||||
|
with HasSlaveAXI4Port
|
||||||
|
with HasPeripheryBootROM
|
||||||
|
with HasPeripheryErrorSlave {
|
||||||
|
override lazy val module = new ExampleRocketSystemModule(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleRocketSystemModule[+L <: ExampleRocketSystem](_outer: L) extends RocketCoreplexModule(_outer)
|
||||||
|
with HasRTCModuleImp
|
||||||
|
with HasExtInterruptsModuleImp
|
||||||
|
with HasMasterAXI4MemPortModuleImp
|
||||||
|
with HasMasterAXI4MMIOPortModuleImp
|
||||||
|
with HasSlaveAXI4PortModuleImp
|
@ -1,6 +1,6 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
package freechips.rocketchip.system
|
||||||
|
|
||||||
import freechips.rocketchip.coreplex.RocketTilesKey
|
import freechips.rocketchip.coreplex.RocketTilesKey
|
||||||
import freechips.rocketchip.tile.XLen
|
import freechips.rocketchip.tile.XLen
|
@ -1,7 +1,7 @@
|
|||||||
// See LICENSE.Berkeley for license details.
|
// See LICENSE.Berkeley for license details.
|
||||||
// See LICENSE.SiFive for license details.
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
package freechips.rocketchip.chip
|
package freechips.rocketchip.system
|
||||||
|
|
||||||
import scala.collection.mutable.LinkedHashSet
|
import scala.collection.mutable.LinkedHashSet
|
||||||
|
|
22
src/main/scala/system/TestHarness.scala
Normal file
22
src/main/scala/system/TestHarness.scala
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.system
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
val dut = Module(LazyModule(new ExampleRocketSystem).module)
|
||||||
|
dut.reset := reset | dut.debug.ndreset
|
||||||
|
|
||||||
|
dut.tieOffInterrupts()
|
||||||
|
dut.connectSimAXIMem()
|
||||||
|
dut.connectSimAXIMMIO()
|
||||||
|
dut.tieOffAXI4SlavePort()
|
||||||
|
dut.connectDebug(clock, reset, io.success)
|
||||||
|
}
|
@ -21,6 +21,7 @@ trait L1CacheParams {
|
|||||||
trait HasL1CacheParameters {
|
trait HasL1CacheParameters {
|
||||||
implicit val p: Parameters
|
implicit val p: Parameters
|
||||||
val cacheParams: L1CacheParams
|
val cacheParams: L1CacheParams
|
||||||
|
private val bundleParams = p(SharedMemoryTLEdge).bundle
|
||||||
|
|
||||||
def cacheBlockBytes = cacheParams.blockBytes
|
def cacheBlockBytes = cacheParams.blockBytes
|
||||||
def lgCacheBlockBytes = log2Up(cacheBlockBytes)
|
def lgCacheBlockBytes = log2Up(cacheBlockBytes)
|
||||||
@ -28,7 +29,7 @@ trait HasL1CacheParameters {
|
|||||||
def blockOffBits = lgCacheBlockBytes
|
def blockOffBits = lgCacheBlockBytes
|
||||||
def idxBits = log2Up(cacheParams.nSets)
|
def idxBits = log2Up(cacheParams.nSets)
|
||||||
def untagBits = blockOffBits + idxBits
|
def untagBits = blockOffBits + idxBits
|
||||||
def tagBits = p(PAddrBits) - untagBits
|
def tagBits = bundleParams.addressBits - untagBits
|
||||||
def nWays = cacheParams.nWays
|
def nWays = cacheParams.nWays
|
||||||
def wayBits = log2Up(nWays)
|
def wayBits = log2Up(nWays)
|
||||||
def isDM = nWays == 1
|
def isDM = nWays == 1
|
||||||
@ -37,7 +38,7 @@ trait HasL1CacheParameters {
|
|||||||
def rowOffBits = log2Up(rowBytes)
|
def rowOffBits = log2Up(rowBytes)
|
||||||
def nTLBEntries = cacheParams.nTLBEntries
|
def nTLBEntries = cacheParams.nTLBEntries
|
||||||
|
|
||||||
def cacheDataBits = p(SharedMemoryTLEdge).bundle.dataBits
|
def cacheDataBits = bundleParams.dataBits
|
||||||
def cacheDataBeats = (cacheBlockBytes * 8) / cacheDataBits
|
def cacheDataBeats = (cacheBlockBytes * 8) / cacheDataBits
|
||||||
def refillCycles = cacheDataBeats
|
def refillCycles = cacheDataBeats
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
// See LICENSE.SiFive for license details.
|
||||||
// See LICENSE.Berkeley for license details.
|
// See LICENSE.Berkeley for license details.
|
||||||
|
|
||||||
package freechips.rocketchip.rocket
|
package freechips.rocketchip.tile
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
import freechips.rocketchip.coreplex._
|
import freechips.rocketchip.coreplex._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.rocket._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
@ -164,29 +163,14 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
|
|||||||
ptw.io.requestor <> ptwPorts
|
ptw.io.requestor <> ptwPorts
|
||||||
}
|
}
|
||||||
|
|
||||||
class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule {
|
abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule {
|
||||||
val rocket = LazyModule(new RocketTile(rtp, hartid))
|
val rocket = LazyModule(new RocketTile(rtp, hartid))
|
||||||
|
val masterNode: OutputNode[_,_,_,_,_]
|
||||||
val masterNode = TLOutputNode()
|
val slaveNode: InputNode[_,_,_,_,_]
|
||||||
masterNode :=* rocket.masterNode
|
|
||||||
|
|
||||||
val slaveNode = new TLInputNode() { override def reverse = true }
|
|
||||||
rocket.slaveNode :*= slaveNode
|
|
||||||
|
|
||||||
// Fully async interrupts need synchronizers.
|
|
||||||
// Others need no synchronization.
|
|
||||||
|
|
||||||
val asyncIntNode = IntInputNode()
|
val asyncIntNode = IntInputNode()
|
||||||
val periphIntNode = IntInputNode()
|
val periphIntNode = IntInputNode()
|
||||||
val coreIntNode = IntInputNode()
|
val coreIntNode = IntInputNode()
|
||||||
|
|
||||||
val xing = LazyModule(new IntXing(3))
|
|
||||||
xing.intnode := asyncIntNode
|
|
||||||
|
|
||||||
val intXbar = LazyModule(new IntXbar)
|
val intXbar = LazyModule(new IntXbar)
|
||||||
intXbar.intnode := xing.intnode
|
|
||||||
intXbar.intnode := periphIntNode
|
|
||||||
intXbar.intnode := coreIntNode
|
|
||||||
|
|
||||||
rocket.intNode := intXbar.intnode
|
rocket.intNode := intXbar.intnode
|
||||||
|
|
||||||
@ -198,15 +182,30 @@ class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters)
|
|||||||
val periphInterrupts = periphIntNode.bundleIn
|
val periphInterrupts = periphIntNode.bundleIn
|
||||||
val coreInterrupts = coreIntNode.bundleIn
|
val coreInterrupts = coreIntNode.bundleIn
|
||||||
}
|
}
|
||||||
// signals that do not change:
|
// signals that do not change based on crossing type:
|
||||||
rocket.module.io.hartid := io.hartid
|
rocket.module.io.hartid := io.hartid
|
||||||
rocket.module.io.resetVector := io.resetVector
|
rocket.module.io.resetVector := io.resetVector
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule {
|
class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
|
||||||
val rocket = LazyModule(new RocketTile(rtp, hartid))
|
val masterNode = TLOutputNode()
|
||||||
|
masterNode :=* rocket.masterNode
|
||||||
|
|
||||||
|
val slaveNode = new TLInputNode() { override def reverse = true }
|
||||||
|
rocket.slaveNode :*= slaveNode
|
||||||
|
|
||||||
|
// Fully async interrupts need synchronizers.
|
||||||
|
// Others need no synchronization.
|
||||||
|
val xing = LazyModule(new IntXing(3))
|
||||||
|
xing.intnode := asyncIntNode
|
||||||
|
|
||||||
|
intXbar.intnode := xing.intnode
|
||||||
|
intXbar.intnode := periphIntNode
|
||||||
|
intXbar.intnode := coreIntNode
|
||||||
|
}
|
||||||
|
|
||||||
|
class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
|
||||||
val masterNode = TLAsyncOutputNode()
|
val masterNode = TLAsyncOutputNode()
|
||||||
val source = LazyModule(new TLAsyncCrossingSource)
|
val source = LazyModule(new TLAsyncCrossingSource)
|
||||||
source.node :=* rocket.masterNode
|
source.node :=* rocket.masterNode
|
||||||
@ -220,40 +219,17 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters
|
|||||||
// Fully async interrupts need synchronizers,
|
// Fully async interrupts need synchronizers,
|
||||||
// as do those coming from the periphery clock.
|
// as do those coming from the periphery clock.
|
||||||
// Others need no synchronization.
|
// Others need no synchronization.
|
||||||
|
|
||||||
val asyncIntNode = IntInputNode()
|
|
||||||
val periphIntNode = IntInputNode()
|
|
||||||
val coreIntNode = IntInputNode()
|
|
||||||
|
|
||||||
val asyncXing = LazyModule(new IntXing(3))
|
val asyncXing = LazyModule(new IntXing(3))
|
||||||
val periphXing = LazyModule(new IntXing(3))
|
val periphXing = LazyModule(new IntXing(3))
|
||||||
asyncXing.intnode := asyncIntNode
|
asyncXing.intnode := asyncIntNode
|
||||||
periphXing.intnode := periphIntNode
|
periphXing.intnode := periphIntNode
|
||||||
|
|
||||||
val intXbar = LazyModule(new IntXbar)
|
|
||||||
intXbar.intnode := asyncXing.intnode
|
intXbar.intnode := asyncXing.intnode
|
||||||
intXbar.intnode := periphXing.intnode
|
intXbar.intnode := periphXing.intnode
|
||||||
intXbar.intnode := coreIntNode
|
intXbar.intnode := coreIntNode
|
||||||
|
|
||||||
rocket.intNode := intXbar.intnode
|
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
|
||||||
val io = new CoreBundle with HasExternallyDrivenTileConstants {
|
|
||||||
val master = masterNode.bundleOut
|
|
||||||
val slave = slaveNode.bundleIn
|
|
||||||
val asyncInterrupts = asyncIntNode.bundleIn
|
|
||||||
val periphInterrupts = periphIntNode.bundleIn
|
|
||||||
val coreInterrupts = coreIntNode.bundleIn
|
|
||||||
}
|
|
||||||
// signals that do not change:
|
|
||||||
rocket.module.io.hartid := io.hartid
|
|
||||||
rocket.module.io.resetVector := io.resetVector
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule {
|
class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
|
||||||
val rocket = LazyModule(new RocketTile(rtp, hartid))
|
|
||||||
|
|
||||||
val masterNode = TLRationalOutputNode()
|
val masterNode = TLRationalOutputNode()
|
||||||
val source = LazyModule(new TLRationalCrossingSource)
|
val source = LazyModule(new TLRationalCrossingSource)
|
||||||
source.node :=* rocket.masterNode
|
source.node :=* rocket.masterNode
|
||||||
@ -268,33 +244,12 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet
|
|||||||
// Those coming from periphery clock need a
|
// Those coming from periphery clock need a
|
||||||
// rational synchronizer.
|
// rational synchronizer.
|
||||||
// Others need no synchronization.
|
// Others need no synchronization.
|
||||||
|
|
||||||
val asyncIntNode = IntInputNode()
|
|
||||||
val periphIntNode = IntInputNode()
|
|
||||||
val coreIntNode = IntInputNode()
|
|
||||||
|
|
||||||
val asyncXing = LazyModule(new IntXing(3))
|
val asyncXing = LazyModule(new IntXing(3))
|
||||||
val periphXing = LazyModule(new IntXing(1))
|
val periphXing = LazyModule(new IntXing(1))
|
||||||
asyncXing.intnode := asyncIntNode
|
asyncXing.intnode := asyncIntNode
|
||||||
periphXing.intnode := periphIntNode
|
periphXing.intnode := periphIntNode
|
||||||
|
|
||||||
val intXbar = LazyModule(new IntXbar)
|
|
||||||
intXbar.intnode := asyncXing.intnode
|
intXbar.intnode := asyncXing.intnode
|
||||||
intXbar.intnode := periphXing.intnode
|
intXbar.intnode := periphXing.intnode
|
||||||
intXbar.intnode := coreIntNode
|
intXbar.intnode := coreIntNode
|
||||||
|
|
||||||
rocket.intNode := intXbar.intnode
|
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
|
||||||
val io = new CoreBundle with HasExternallyDrivenTileConstants {
|
|
||||||
val master = masterNode.bundleOut
|
|
||||||
val slave = slaveNode.bundleIn
|
|
||||||
val asyncInterrupts = asyncIntNode.bundleIn
|
|
||||||
val periphInterrupts = periphIntNode.bundleIn
|
|
||||||
val coreInterrupts = coreIntNode.bundleIn
|
|
||||||
}
|
|
||||||
// signals that do not change:
|
|
||||||
rocket.module.io.hartid := io.hartid
|
|
||||||
rocket.module.io.resetVector := io.resetVector
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -22,7 +22,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
|||||||
def widen(x: TransferSizes) = if (passthrough && x.min <= 2*mp.beatBytes) TransferSizes(1, max(mp.beatBytes, x.max)) else ourSupport
|
def widen(x: TransferSizes) = if (passthrough && x.min <= 2*mp.beatBytes) TransferSizes(1, max(mp.beatBytes, x.max)) else ourSupport
|
||||||
val canDoit = m.supportsPutFull.contains(ourSupport) && m.supportsGet.contains(ourSupport)
|
val canDoit = m.supportsPutFull.contains(ourSupport) && m.supportsGet.contains(ourSupport)
|
||||||
// Blow up if there are devices to which we cannot add Atomics, because their R|W are too inflexible
|
// Blow up if there are devices to which we cannot add Atomics, because their R|W are too inflexible
|
||||||
require (!m.supportsPutFull || !m.supportsGet || canDoit)
|
require (!m.supportsPutFull || !m.supportsGet || canDoit, s"${m.name} has $ourSupport, needed PutFull(${m.supportsPutFull}) or Get(${m.supportsGet})")
|
||||||
m.copy(
|
m.copy(
|
||||||
supportsArithmetic = if (!arithmetic || !canDoit) m.supportsArithmetic else widen(m.supportsArithmetic),
|
supportsArithmetic = if (!arithmetic || !canDoit) m.supportsArithmetic else widen(m.supportsArithmetic),
|
||||||
supportsLogical = if (!logical || !canDoit) m.supportsLogical else widen(m.supportsLogical))
|
supportsLogical = if (!logical || !canDoit) m.supportsLogical else widen(m.supportsLogical))
|
||||||
|
@ -29,8 +29,8 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa
|
|||||||
if (m.regionType == RegionType.UNCACHED) {
|
if (m.regionType == RegionType.UNCACHED) {
|
||||||
// The device had better support line transfers
|
// The device had better support line transfers
|
||||||
val lowerBound = max(m.supportsPutFull.min, m.supportsGet.min)
|
val lowerBound = max(m.supportsPutFull.min, m.supportsGet.min)
|
||||||
require (!m.supportsPutFull || m.supportsPutFull.contains(lineBytes))
|
require (!m.supportsPutFull || m.supportsPutFull.contains(lineBytes), s"${m.name} only supports PutFull(${m.supportsPutFull}), which does not include $lineBytes")
|
||||||
require (!m.supportsGet || m.supportsGet .contains(lineBytes))
|
require (!m.supportsGet || m.supportsGet .contains(lineBytes), s"${m.name} only supports Get(${m.supportsGet}), which does not include $lineBytes")
|
||||||
m.copy(
|
m.copy(
|
||||||
regionType = RegionType.TRACKED,
|
regionType = RegionType.TRACKED,
|
||||||
supportsAcquireB = TransferSizes(lowerBound, lineBytes),
|
supportsAcquireB = TransferSizes(lowerBound, lineBytes),
|
||||||
|
96
src/main/scala/tilelink/Bus.scala
Normal file
96
src/main/scala/tilelink/Bus.scala
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package freechips.rocketchip.tilelink
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
|
/** Specifies widths of various attachement points in the SoC */
|
||||||
|
trait TLBusParams {
|
||||||
|
val beatBytes: Int
|
||||||
|
val blockBytes: Int
|
||||||
|
val masterBuffering: BufferParams
|
||||||
|
val slaveBuffering: BufferParams
|
||||||
|
|
||||||
|
def beatBits: Int = beatBytes * 8
|
||||||
|
def blockBits: Int = blockBytes * 8
|
||||||
|
def blockBeats: Int = blockBytes / beatBytes
|
||||||
|
def blockOffset: Int = log2Up(blockBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TLBusWrapper(params: TLBusParams)(implicit p: Parameters) extends TLBusParams {
|
||||||
|
val beatBytes = params.beatBytes
|
||||||
|
val blockBytes = params.blockBytes
|
||||||
|
val masterBuffering = params.masterBuffering
|
||||||
|
val slaveBuffering = params.slaveBuffering
|
||||||
|
require(blockBytes % beatBytes == 0)
|
||||||
|
|
||||||
|
private val xbar = LazyModule(new TLXbar)
|
||||||
|
private val master_buffer = LazyModule(new TLBuffer(masterBuffering))
|
||||||
|
private val slave_buffer = LazyModule(new TLBuffer(slaveBuffering))
|
||||||
|
private val slave_frag = LazyModule(new TLFragmenter(beatBytes, blockBytes))
|
||||||
|
private val slave_ww = LazyModule(new TLWidthWidget(beatBytes))
|
||||||
|
|
||||||
|
xbar.node :=* master_buffer.node
|
||||||
|
slave_buffer.node :*= xbar.node
|
||||||
|
slave_frag.node :*= slave_buffer.node
|
||||||
|
slave_ww.node :*= slave_buffer.node
|
||||||
|
|
||||||
|
protected def outwardNode: TLOutwardNode = xbar.node
|
||||||
|
protected def outwardBufNode: TLOutwardNode = slave_buffer.node
|
||||||
|
protected def outwardFragNode: TLOutwardNode = slave_frag.node
|
||||||
|
protected def outwardWWNode: TLOutwardNode = slave_ww.node
|
||||||
|
protected def inwardNode: TLInwardNode = xbar.node
|
||||||
|
protected def inwardBufNode: TLInwardNode = master_buffer.node
|
||||||
|
|
||||||
|
def edgesIn = xbar.node.edgesIn
|
||||||
|
|
||||||
|
def bufferFromMasters: TLInwardNode = inwardBufNode
|
||||||
|
|
||||||
|
def bufferToSlaves: TLOutwardNode = outwardBufNode
|
||||||
|
|
||||||
|
def toAsyncSlaves(sync: Int = 3): TLAsyncOutwardNode = {
|
||||||
|
val source = LazyModule(new TLAsyncCrossingSource(sync))
|
||||||
|
source.node :*= outwardNode
|
||||||
|
source.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def toRationalSlaves: TLRationalOutwardNode = {
|
||||||
|
val source = LazyModule(new TLRationalCrossingSource())
|
||||||
|
source.node :*= outwardNode
|
||||||
|
source.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def toVariableWidthSlaves: TLOutwardNode = outwardFragNode
|
||||||
|
|
||||||
|
def toAsyncVariableWidthSlaves(sync: Int = 3): TLAsyncOutwardNode = {
|
||||||
|
val source = LazyModule(new TLAsyncCrossingSource(sync))
|
||||||
|
source.node :*= outwardFragNode
|
||||||
|
source.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def toRationalVariableWidthSlaves: TLRationalOutwardNode = {
|
||||||
|
val source = LazyModule(new TLRationalCrossingSource())
|
||||||
|
source.node :*= outwardFragNode
|
||||||
|
source.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def toFixedWidthSlaves: TLOutwardNode = outwardWWNode
|
||||||
|
|
||||||
|
def toAsyncFixedWidthSlaves(sync: Int = 3): TLAsyncOutwardNode = {
|
||||||
|
val source = LazyModule(new TLAsyncCrossingSource(sync))
|
||||||
|
source.node := outwardWWNode
|
||||||
|
source.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def toRationalFixedWidthSlaves: TLRationalOutwardNode = {
|
||||||
|
val source = LazyModule(new TLRationalCrossingSource())
|
||||||
|
source.node :*= outwardWWNode
|
||||||
|
source.node
|
||||||
|
}
|
||||||
|
|
||||||
|
def toFixedWidthPorts: TLOutwardNode = outwardWWNode // TODO, do/don't buffer here; knowing we will after the necessary port conversions
|
||||||
|
|
||||||
|
}
|
@ -76,7 +76,9 @@ case class TLManagerPortParameters(
|
|||||||
require (endSinkId >= 0)
|
require (endSinkId >= 0)
|
||||||
require (minLatency >= 0)
|
require (minLatency >= 0)
|
||||||
|
|
||||||
def requireFifo() = managers.foreach { m =>require (m.fifoId == Some(0)) }
|
def requireFifo() = managers.foreach { m =>
|
||||||
|
require(m.fifoId == Some(0), s"${m.name} had fifoId ${m.fifoId}, which was not 0 (${managers.map(s => (s.name, s.fifoId))}) ")
|
||||||
|
}
|
||||||
|
|
||||||
// Bounds on required sizes
|
// Bounds on required sizes
|
||||||
def maxAddress = managers.map(_.maxAddress).max
|
def maxAddress = managers.map(_.maxAddress).max
|
||||||
@ -315,7 +317,7 @@ case class TLEdgeParameters(
|
|||||||
val maxLgSize = log2Ceil(maxTransfer)
|
val maxLgSize = log2Ceil(maxTransfer)
|
||||||
|
|
||||||
// Sanity check the link...
|
// Sanity check the link...
|
||||||
require (maxTransfer >= manager.beatBytes)
|
require (maxTransfer >= manager.beatBytes, s"Link's max transfer (${maxTransfer}) < ${manager.managers.map(_.name)}'s beatBytes (${manager.beatBytes})")
|
||||||
|
|
||||||
val bundle = TLBundleParameters(client, manager)
|
val bundle = TLBundleParameters(client, manager)
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,13 @@ package object tilelink
|
|||||||
{
|
{
|
||||||
type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle]
|
type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle]
|
||||||
type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle]
|
type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle]
|
||||||
|
type TLAsyncInwardNode = InwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]
|
||||||
type TLAsyncOutwardNode = OutwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]
|
type TLAsyncOutwardNode = OutwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]
|
||||||
|
type TLRationalInwardNode = InwardNodeHandle[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle]
|
||||||
type TLRationalOutwardNode = OutwardNodeHandle[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle]
|
type TLRationalOutwardNode = OutwardNodeHandle[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle]
|
||||||
type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]]
|
|
||||||
type TLMixedNode = MixedNode[TLClientPortParameters, TLManagerPortParameters, TLEdgeIn, TLBundle,
|
type TLMixedNode = MixedNode[TLClientPortParameters, TLManagerPortParameters, TLEdgeIn, TLBundle,
|
||||||
TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLBundle]
|
TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLBundle]
|
||||||
|
|
||||||
|
type IntInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]]
|
||||||
|
type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]]
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ import Chisel._
|
|||||||
import freechips.rocketchip.amba.ahb._
|
import freechips.rocketchip.amba.ahb._
|
||||||
import freechips.rocketchip.amba.apb._
|
import freechips.rocketchip.amba.apb._
|
||||||
import freechips.rocketchip.amba.axi4._
|
import freechips.rocketchip.amba.axi4._
|
||||||
import freechips.rocketchip.chip.{BaseConfig, BasePlatformConfig}
|
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.coreplex.{BaseCoreplexConfig}
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class WithTLXbarUnitTests extends Config((site, here, up) => {
|
|||||||
Module(new TLMulticlientXbarTest(4,4, txns=2*txns, timeout=timeout)) ) }
|
Module(new TLMulticlientXbarTest(4,4, txns=2*txns, timeout=timeout)) ) }
|
||||||
})
|
})
|
||||||
|
|
||||||
class AMBAUnitTestConfig extends Config(new WithAMBAUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig)
|
class AMBAUnitTestConfig extends Config(new WithAMBAUnitTests ++ new WithTestDuration(10) ++ new BaseCoreplexConfig)
|
||||||
class TLSimpleUnitTestConfig extends Config(new WithTLSimpleUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig)
|
class TLSimpleUnitTestConfig extends Config(new WithTLSimpleUnitTests ++ new WithTestDuration(10) ++ new BaseCoreplexConfig)
|
||||||
class TLWidthUnitTestConfig extends Config(new WithTLWidthUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig)
|
class TLWidthUnitTestConfig extends Config(new WithTLWidthUnitTests ++ new WithTestDuration(10) ++ new BaseCoreplexConfig)
|
||||||
class TLXbarUnitTestConfig extends Config(new WithTLXbarUnitTests ++ new WithTestDuration(10) ++ new BasePlatformConfig)
|
class TLXbarUnitTestConfig extends Config(new WithTLXbarUnitTests ++ new WithTestDuration(10) ++ new BaseCoreplexConfig)
|
||||||
|
@ -6,7 +6,7 @@ import Chisel._
|
|||||||
import chisel3.internal.firrtl.Circuit
|
import chisel3.internal.firrtl.Circuit
|
||||||
import chisel3.experimental.{RawModule}
|
import chisel3.experimental.{RawModule}
|
||||||
// TODO: better job of Makefrag generation for non-RocketChip testing platforms
|
// TODO: better job of Makefrag generation for non-RocketChip testing platforms
|
||||||
import freechips.rocketchip.chip.{TestGeneration, DefaultTestSuites}
|
import freechips.rocketchip.system.{TestGeneration, DefaultTestSuites}
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
import freechips.rocketchip.diplomacy.LazyModule
|
import freechips.rocketchip.diplomacy.LazyModule
|
||||||
import java.io.{File, FileWriter}
|
import java.io.{File, FileWriter}
|
||||||
|
@ -21,6 +21,11 @@ class ParameterizedBundle(implicit p: Parameters) extends Bundle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Clocked extends Bundle {
|
||||||
|
val clock = Clock()
|
||||||
|
val reset = Bool()
|
||||||
|
}
|
||||||
|
|
||||||
object DecoupledHelper {
|
object DecoupledHelper {
|
||||||
def apply(rvs: Bool*) = new DecoupledHelper(rvs)
|
def apply(rvs: Bool*) = new DecoupledHelper(rvs)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user