Merge remote-tracking branch 'ch/lazy-iobinders' into local-fpga-temp
This commit is contained in:
@@ -47,7 +47,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim
|
|||||||
|
|
||||||
# key value store to get the build groups
|
# key value store to get the build groups
|
||||||
declare -A grouping
|
declare -A grouping
|
||||||
grouping["group-cores"]="chipyard-ariane chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor"
|
grouping["group-cores"]="chipyard-ariane chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop"
|
||||||
grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif"
|
grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif"
|
||||||
grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
|
grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
|
||||||
grouping["group-tracegen"]="tracegen tracegen-boom"
|
grouping["group-tracegen"]="tracegen tracegen-boom"
|
||||||
@@ -59,6 +59,7 @@ mapping["chipyard-rocket"]=""
|
|||||||
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
|
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
|
||||||
mapping["chipyard-lbwif"]=" CONFIG=LBWIFRocketConfig"
|
mapping["chipyard-lbwif"]=" CONFIG=LBWIFRocketConfig"
|
||||||
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
|
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
|
||||||
|
mapping["chipyard-digitaltop"]=" TOP=DigitalTop"
|
||||||
mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig"
|
mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig"
|
||||||
mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig"
|
mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig"
|
||||||
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
|
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ generator_temp: $(SCALA_SOURCES) $(sim_files) $(EXTRA_GENERATOR_REQS)
|
|||||||
--target-dir $(build_dir) \
|
--target-dir $(build_dir) \
|
||||||
--name $(long_name) \
|
--name $(long_name) \
|
||||||
--top-module $(MODEL_PACKAGE).$(MODEL) \
|
--top-module $(MODEL_PACKAGE).$(MODEL) \
|
||||||
--legacy-configs $(CONFIG_PACKAGE).$(CONFIG))
|
--legacy-configs $(CONFIG_PACKAGE):$(CONFIG))
|
||||||
|
|
||||||
.PHONY: firrtl
|
.PHONY: firrtl
|
||||||
firrtl: $(FIRRTL_FILE)
|
firrtl: $(FIRRTL_FILE)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ IOBinders and HarnessBinders
|
|||||||
In Chipyard we use special ``Parameters`` keys, ``IOBinders`` and ``HarnessBinders`` to bridge the gap between digital system IOs and TestHarness collateral.
|
In Chipyard we use special ``Parameters`` keys, ``IOBinders`` and ``HarnessBinders`` to bridge the gap between digital system IOs and TestHarness collateral.
|
||||||
|
|
||||||
IOBinders
|
IOBinders
|
||||||
=========
|
---------
|
||||||
|
|
||||||
The ``IOBinder`` functions are responsible for instantiating IO cells and IOPorts in the ``ChipTop`` layer.
|
The ``IOBinder`` functions are responsible for instantiating IO cells and IOPorts in the ``ChipTop`` layer.
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ For example, the ``WithUARTIOCells`` IOBinder will, for any ``System`` that migh
|
|||||||
:end-before: DOC include end: WithUARTIOCells
|
:end-before: DOC include end: WithUARTIOCells
|
||||||
|
|
||||||
HarnessBinders
|
HarnessBinders
|
||||||
==============
|
--------------
|
||||||
|
|
||||||
The ``HarnessBinder`` functions determine what modules to bind to the IOs of a ``ChipTop`` in the ``TestHarness``. The ``HarnessBinder`` interface is designed to be reused across various simulation/implementation modes, enabling decoupling of the target design from simulation and testing concerns.
|
The ``HarnessBinder`` functions determine what modules to bind to the IOs of a ``ChipTop`` in the ``TestHarness``. The ``HarnessBinder`` interface is designed to be reused across various simulation/implementation modes, enabling decoupling of the target design from simulation and testing concerns.
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,20 @@ and proceed with the rest of the tutorial.
|
|||||||
|
|
||||||
Running your Design in FireSim
|
Running your Design in FireSim
|
||||||
------------------------------
|
------------------------------
|
||||||
Converting a Chipyard config (one in ``chipyard/src/main/scala`` to run in FireSim is simple. We are using the same target (top) RTL, and only need to specify a new set of connection behaviors for the IOs of that module. Simply create a matching config within ``generators/firechip/src/main/scala/TargetConfigs`` that inherits your config defined in ``chipyard``.
|
Converting a Chipyard config (one in ``chipyard/src/main/scala`` to run in FireSim is simple, and can be done either through the traditional configuration system or through FireSim's build-recipes scheme.
|
||||||
|
|
||||||
|
A FireSim simulation requires 3 additional config fragments:
|
||||||
|
|
||||||
|
* ``WithFireSimConfigTweaks`` modifies your design to better fit the FireSim usage model. This is composed of multiple smaller config fragments. For example, the removal of clock-gating (using the ``WithoutClockGating`` config fragment) which is required for correct functioning of the compiler. This config fragment also includes other config fragments such as the inclusion of UART in the design, which although may technically be optional,is *strongly* recommended.
|
||||||
|
* ``WithDefaultMemModel`` provides a default configuration for FASED memory models in the FireSim simulation. See the FireSim documentation for details. This config fragment is currently included by default within ``WithFireSimConfigTweaks``, so it isn't neccessary to add in separately, but it is required if you choose not to use ``WithFireSimConfigTweaks``.
|
||||||
|
* ``WithDefaultFireSimBridges`` sets the ``IOBinders`` key to use FireSim's Bridge system, which can drive target IOs with software bridge models running on the simulation host. See the FireSim documentation for details.
|
||||||
|
|
||||||
|
|
||||||
|
The simplest method to add this config fragments to your custom Chipyard config is through FireSim's build recipe scheme.
|
||||||
|
After your FireSim environment is setup, you will define your custom build recipe in ``sims/firesim/deploy/deploy/config_build_recipes.ini``. By prepending the FireSim config fragments (separated by ``_``) to your Chipyard configuration, these config fragments will be added to your custom configuration as if they were listed in a custom Chisel config class definition. For example, if you would like to convert the Chipyard ``LargeBoomConfig`` to a FireSim simulation with a DDR3 memory model, the appropriate FireSim ``TARGET_CONFIG`` would be ``DDR3FRFCFSLLC4MB_WithDefaultFireSimBridges_WithFireSimConfigTweaks_chipyard.LargeBoomConfig``. Note that the FireSim config fragments are part of the ``firesim.firesim`` scala package and therefore there do not need to be prefixed with the full package name as opposed to the Chipyard config fragments which need to be prefixed with the chipyard package name.
|
||||||
|
|
||||||
|
An alternative method to prepending the FireSim config fragments in the FireSim build recipe is to create a new "permanent" FireChip custom configuration, which includes the FireSim config fragments.
|
||||||
|
We are using the same target (top) RTL, and only need to specify a new set of connection behaviors for the IOs of that module. Simply create a matching config within ``generators/firechip/src/main/scala/TargetConfigs`` that inherits your config defined in ``chipyard``.
|
||||||
|
|
||||||
|
|
||||||
.. literalinclude:: ../../generators/firechip/src/main/scala/TargetConfigs.scala
|
.. literalinclude:: ../../generators/firechip/src/main/scala/TargetConfigs.scala
|
||||||
@@ -54,9 +67,4 @@ Converting a Chipyard config (one in ``chipyard/src/main/scala`` to run in FireS
|
|||||||
:start-after: DOC include start: firesimconfig
|
:start-after: DOC include start: firesimconfig
|
||||||
:end-before: DOC include end: firesimconfig
|
:end-before: DOC include end: firesimconfig
|
||||||
|
|
||||||
|
While this option seems to require the maintenance of additional configuration code, it has the benefit of allowing for the inclusion of more complex config fragments which also accept custom arguments (for example, ``WithDefaultMemModel`` can take an optional argument``)
|
||||||
Only 3 additional config fragments are needed.
|
|
||||||
|
|
||||||
* ``WithFireSimConfigTweaks`` modifies your design to better fit the FireSim usage model. For example, FireSim designs typically include a UART. Technically, adding this in is optional, but *strongly* recommended.
|
|
||||||
* ``WithDefaultMemModel`` sets the external memory model in the FireSim simulation. See the FireSim documentation for details.
|
|
||||||
* ``WithDefaultFireSimBridges`` sets the ``IOBinders`` key to use FireSim's Bridge system, which can drive target IOs with software bridge models running on the simulation host. See the FireSim documentation for details.
|
|
||||||
|
|||||||
@@ -23,12 +23,10 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters)
|
|||||||
* drive clock and reset generation
|
* drive clock and reset generation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions with BindingScope {
|
class ChipTop(implicit p: Parameters) extends LazyModule
|
||||||
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
|
with HasTestHarnessFunctions with HasIOBinders with BindingScope {
|
||||||
val iocells = ArrayBuffer.empty[IOCell]
|
|
||||||
|
|
||||||
// The system module specified by BuildSystem
|
// The system module specified by BuildSystem
|
||||||
val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
||||||
|
|
||||||
// The implicitClockSinkNode provides the implicit clock and reset for the System
|
// The implicitClockSinkNode provides the implicit clock and reset for the System
|
||||||
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
||||||
@@ -45,13 +43,6 @@ class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunc
|
|||||||
val implicit_clock = implicitClockSinkNode.in.head._1.clock
|
val implicit_clock = implicitClockSinkNode.in.head._1.clock
|
||||||
val implicit_reset = implicitClockSinkNode.in.head._1.reset
|
val implicit_reset = implicitClockSinkNode.in.head._1.reset
|
||||||
|
|
||||||
|
|
||||||
// Note: IOBinders cannot rely on the implicit clock/reset, as this is a LazyRawModuleImp
|
|
||||||
val (_ports, _iocells, _portMap) = ApplyIOBinders(lazySystem, p(IOBinders))
|
|
||||||
// We ignore _ports for now...
|
|
||||||
iocells ++= _iocells
|
|
||||||
portMap ++= _portMap
|
|
||||||
|
|
||||||
// Connect the implicit clock/reset, if present
|
// Connect the implicit clock/reset, if present
|
||||||
lazySystem.module match { case l: LazyModuleImp => {
|
lazySystem.module match { case l: LazyModuleImp => {
|
||||||
l.clock := implicit_clock
|
l.clock := implicit_clock
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import freechips.rocketchip.prci._
|
|||||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey, InstantiatesTiles}
|
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey, InstantiatesTiles}
|
||||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||||
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
|
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
|
||||||
import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider}
|
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||||
|
|
||||||
import barstools.iocell.chisel._
|
import barstools.iocell.chisel._
|
||||||
import testchipip.{TLTileResetCtrl}
|
import testchipip.{TLTileResetCtrl}
|
||||||
|
|
||||||
import chipyard.clocking.{DividerOnlyClockGenerator, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier}
|
import chipyard.clocking._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chipyard provides three baseline, top-level reset schemes, set using the
|
* Chipyard provides three baseline, top-level reset schemes, set using the
|
||||||
@@ -121,13 +121,14 @@ object ClockingSchemeGenerators {
|
|||||||
:= ClockGroup()
|
:= ClockGroup()
|
||||||
:= aggregator)
|
:= aggregator)
|
||||||
(systemAsyncClockGroup
|
(systemAsyncClockGroup
|
||||||
:= resetSetter
|
:*= resetSetter
|
||||||
:= ClockGroupNamePrefixer()
|
:*= ClockGroupNamePrefixer()
|
||||||
:= aggregator)
|
:*= aggregator)
|
||||||
|
|
||||||
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
||||||
(aggregator
|
(aggregator
|
||||||
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||||
|
:= ClockGroupResetSynchronizer()
|
||||||
:= DividerOnlyClockGenerator()
|
:= DividerOnlyClockGenerator()
|
||||||
:= referenceClockSource)
|
:= referenceClockSource)
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import chisel3.util.{log2Up}
|
|||||||
|
|
||||||
import freechips.rocketchip.config.{Field, Parameters, Config}
|
import freechips.rocketchip.config.{Field, Parameters, Config}
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, ValName}
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.devices.tilelink.{BootROMLocated}
|
import freechips.rocketchip.devices.tilelink.{BootROMLocated}
|
||||||
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
|
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
|
||||||
import freechips.rocketchip.groundtest.{GroundTestSubsystem}
|
import freechips.rocketchip.groundtest.{GroundTestSubsystem}
|
||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.tile._
|
||||||
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
|
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
|
||||||
import freechips.rocketchip.util.{AsyncResetReg}
|
import freechips.rocketchip.util.{AsyncResetReg, Symmetric}
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
|
|
||||||
import testchipip._
|
import testchipip._
|
||||||
@@ -172,3 +172,46 @@ class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
|
|||||||
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble
|
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixins to specify crossing types between the 5 traditional TL buses
|
||||||
|
*
|
||||||
|
* Note: these presuppose the legacy connections between buses and set
|
||||||
|
* parameters in SubsystemCrossingParams; they may not be resuable in custom
|
||||||
|
* topologies (but you can specify the desired crossings in your topology).
|
||||||
|
*
|
||||||
|
* @param xType The clock crossing type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class WithSbusToMbusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
|
||||||
|
case SbusToMbusXTypeKey => xType
|
||||||
|
})
|
||||||
|
class WithSbusToCbusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
|
||||||
|
case SbusToCbusXTypeKey => xType
|
||||||
|
})
|
||||||
|
class WithCbusToPbusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
|
||||||
|
case CbusToPbusXTypeKey => xType
|
||||||
|
})
|
||||||
|
class WithFbusToSbusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
|
||||||
|
case FbusToSbusXTypeKey => xType
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixins to set the dtsFrequency field of BusParams -- these will percolate its way
|
||||||
|
* up the diplomatic graph to the clock sources.
|
||||||
|
*/
|
||||||
|
class WithPeripheryBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
|
case PeripheryBusKey => up(PeripheryBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
|
})
|
||||||
|
class WithMemoryBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
|
case MemoryBusKey => up(MemoryBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
|
})
|
||||||
|
class WithSystemBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
|
case SystemBusKey => up(SystemBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
|
})
|
||||||
|
class WithControlBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
|
case ControlBusKey => up(ControlBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithRationalMemoryBusCrossing extends WithSbusToMbusCrossingType(RationalCrossing(Symmetric))
|
||||||
|
class WithAsynchrousMemoryBusCrossing extends WithSbusToMbusCrossingType(AsynchronousCrossing())
|
||||||
|
|||||||
62
generators/chipyard/src/main/scala/CustomBusTopologies.scala
Normal file
62
generators/chipyard/src/main/scala/CustomBusTopologies.scala
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
package chipyard
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.util.{Location, Symmetric}
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
|
||||||
|
// I'm putting this code here temporarily as I think it should be a candidate
|
||||||
|
// for upstreaming based on input from Henry Cook, but don't wnat to deal with
|
||||||
|
// an RC branch just yet.
|
||||||
|
|
||||||
|
// For subsystem/BusTopology.scala
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keys that serve as a means to define crossing types from a Parameters instance
|
||||||
|
*/
|
||||||
|
case object SbusToMbusXTypeKey extends Field[ClockCrossingType](NoCrossing)
|
||||||
|
case object SbusToCbusXTypeKey extends Field[ClockCrossingType](NoCrossing)
|
||||||
|
case object CbusToPbusXTypeKey extends Field[ClockCrossingType](SynchronousCrossing())
|
||||||
|
case object FbusToSbusXTypeKey extends Field[ClockCrossingType](SynchronousCrossing())
|
||||||
|
|
||||||
|
// Biancolin: This, modified from Henry's email
|
||||||
|
/** Parameterization of a topology containing a banked coherence manager and a bus for attaching memory devices. */
|
||||||
|
case class CoherentMulticlockBusTopologyParams(
|
||||||
|
sbus: SystemBusParams, // TODO remove this after better width propagation
|
||||||
|
mbus: MemoryBusParams,
|
||||||
|
l2: BankedL2Params,
|
||||||
|
sbusToMbusXType: ClockCrossingType = NoCrossing
|
||||||
|
) extends TLBusWrapperTopology(
|
||||||
|
instantiations = (if (l2.nBanks == 0) Nil else List(
|
||||||
|
(MBUS, mbus),
|
||||||
|
(L2, CoherenceManagerWrapperParams(mbus.blockBytes, mbus.beatBytes, l2.nBanks, L2.name)(l2.coherenceManager)))),
|
||||||
|
connections = if (l2.nBanks == 0) Nil else List(
|
||||||
|
(SBUS, L2, TLBusWrapperConnection(xType = NoCrossing, driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()),
|
||||||
|
(L2, MBUS, TLBusWrapperConnection.crossTo(
|
||||||
|
xType = sbusToMbusXType,
|
||||||
|
driveClockFromMaster = Some(true),
|
||||||
|
nodeBinding = BIND_QUERY))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// For subsystem/Configs.scala
|
||||||
|
|
||||||
|
class WithMulticlockCoherentBusTopology extends Config((site, here, up) => {
|
||||||
|
case TLNetworkTopologyLocated(InSubsystem) => List(
|
||||||
|
JustOneBusTopologyParams(sbus = site(SystemBusKey)),
|
||||||
|
HierarchicalBusTopologyParams(
|
||||||
|
pbus = site(PeripheryBusKey),
|
||||||
|
fbus = site(FrontBusKey),
|
||||||
|
cbus = site(ControlBusKey),
|
||||||
|
xTypes = SubsystemCrossingParams(
|
||||||
|
sbusToCbusXType = site(SbusToCbusXTypeKey),
|
||||||
|
cbusToPbusXType = site(CbusToPbusXTypeKey),
|
||||||
|
fbusToSbusXType = site(FbusToSbusXTypeKey))),
|
||||||
|
CoherentMulticlockBusTopologyParams(
|
||||||
|
sbus = site(SystemBusKey),
|
||||||
|
mbus = site(MemoryBusKey),
|
||||||
|
l2 = site(BankedL2Key),
|
||||||
|
sbusToMbusXType = site(SbusToMbusXTypeKey)))
|
||||||
|
})
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package chipyard.harness
|
package chipyard.harness
|
||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.experimental.{Analog}
|
import chisel3.experimental.{Analog, BaseModule}
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Field, Config, Parameters}
|
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
||||||
@@ -31,42 +31,43 @@ case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalRefer
|
|||||||
Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => Nil)
|
Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
object ApplyHarnessBinders {
|
object ApplyHarnessBinders {
|
||||||
def apply(th: HasHarnessSignalReferences, sys: LazyModule, map: Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]], portMap: Map[String, Seq[Data]]) = {
|
def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters) = {
|
||||||
val pm = portMap.withDefaultValue(Nil)
|
val pm = portMap.withDefaultValue(Nil)
|
||||||
map.map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) }
|
p(HarnessBinders).map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverrideHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => {
|
// The ClassTags here are necessary to overcome issues arising from type erasure
|
||||||
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
|
class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Seq[Any]) => (T, S, Seq[U]) => Seq[Any])(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => {
|
||||||
|
case HarnessBinders => up(HarnessBinders, site) + (systemTag.runtimeClass.toString ->
|
||||||
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||||
val pts = ports.collect({case p: S => p})
|
val pts = ports.collect({case p: U => p})
|
||||||
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
|
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}")
|
||||||
t match {
|
val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString)
|
||||||
case system: T => fn(system, th, pts)
|
th match {
|
||||||
|
case th: S =>
|
||||||
|
t match {
|
||||||
|
case system: T => composer(upfn)(system, th, pts)
|
||||||
|
case _ => Nil
|
||||||
|
}
|
||||||
case _ => Nil
|
case _ => Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
class ComposeHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => {
|
class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any])
|
||||||
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
|
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
|
||||||
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => fn)
|
||||||
val pts = ports.collect({case p: S => p})
|
|
||||||
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
|
class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any])
|
||||||
t match {
|
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
|
||||||
case system: T => up(HarnessBinders, site)(tag.runtimeClass.toString)(system, th, pts) ++ fn(system, th, pts)
|
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => (t, th, p) => upfn(t, th, p) ++ fn(t, th, p))
|
||||||
case _ => Nil
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithGPIOTiedOff extends OverrideHarnessBinder({
|
class WithGPIOTiedOff extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => {
|
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Analog]) => {
|
||||||
ports.foreach { _ <> AnalogConst(0) }
|
ports.foreach { _ <> AnalogConst(0) }
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
@@ -74,7 +75,7 @@ class WithGPIOTiedOff extends OverrideHarnessBinder({
|
|||||||
|
|
||||||
// DOC include start: WithUARTAdapter
|
// DOC include start: WithUARTAdapter
|
||||||
class WithUARTAdapter extends OverrideHarnessBinder({
|
class WithUARTAdapter extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
|
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
|
||||||
UARTAdapter.connect(ports)(system.p)
|
UARTAdapter.connect(ports)(system.p)
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
@@ -82,14 +83,14 @@ class WithUARTAdapter extends OverrideHarnessBinder({
|
|||||||
// DOC include end: WithUARTAdapter
|
// DOC include end: WithUARTAdapter
|
||||||
|
|
||||||
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
|
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
|
||||||
(system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => {
|
(system: HasPeripherySPIFlashModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => {
|
||||||
SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p)
|
SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p)
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSimBlockDevice extends OverrideHarnessBinder({
|
class WithSimBlockDevice extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
(system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) }
|
ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) }
|
||||||
Nil
|
Nil
|
||||||
@@ -97,7 +98,7 @@ class WithSimBlockDevice extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithBlockDeviceModel extends OverrideHarnessBinder({
|
class WithBlockDeviceModel extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
(system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } }
|
ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } }
|
||||||
Nil
|
Nil
|
||||||
@@ -105,7 +106,7 @@ class WithBlockDeviceModel extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithLoopbackNIC extends OverrideHarnessBinder({
|
class WithLoopbackNIC extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
(system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { n =>
|
ports.map { n =>
|
||||||
withClockAndReset(n.clock, th.harnessReset) {
|
withClockAndReset(n.clock, th.harnessReset) {
|
||||||
@@ -117,7 +118,7 @@ class WithLoopbackNIC extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithSimNetwork extends OverrideHarnessBinder({
|
class WithSimNetwork extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
(system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) }
|
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) }
|
||||||
Nil
|
Nil
|
||||||
@@ -125,11 +126,11 @@ class WithSimNetwork extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithSimAXIMem extends OverrideHarnessBinder({
|
class WithSimAXIMem extends OverrideHarnessBinder({
|
||||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||||
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
||||||
val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p))
|
val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p))
|
||||||
withClockAndReset(port.clock, th.harnessReset) {
|
withClockAndReset(port.clock, port.reset) {
|
||||||
Module(mem.module).suggestName("mem")
|
Module(mem.module).suggestName("mem")
|
||||||
}
|
}
|
||||||
mem.io_axi4.head <> port.bits
|
mem.io_axi4.head <> port.bits
|
||||||
@@ -139,7 +140,7 @@ class WithSimAXIMem extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithBlackBoxSimMem extends OverrideHarnessBinder({
|
class WithBlackBoxSimMem extends OverrideHarnessBinder({
|
||||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||||
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
||||||
val memSize = p(ExtMem).get.master.size
|
val memSize = p(ExtMem).get.master.size
|
||||||
@@ -147,18 +148,18 @@ class WithBlackBoxSimMem extends OverrideHarnessBinder({
|
|||||||
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle)).suggestName("simdram")
|
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle)).suggestName("simdram")
|
||||||
mem.io.axi <> port.bits
|
mem.io.axi <> port.bits
|
||||||
mem.io.clock := port.clock
|
mem.io.clock := port.clock
|
||||||
mem.io.reset := th.harnessReset
|
mem.io.reset := port.reset
|
||||||
}
|
}
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSimAXIMMIO extends OverrideHarnessBinder({
|
class WithSimAXIMMIO extends OverrideHarnessBinder({
|
||||||
(system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
(system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||||
(ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) =>
|
(ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) =>
|
||||||
val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p))
|
val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p))
|
||||||
withClockAndReset(port.clock, th.harnessReset) {
|
withClockAndReset(port.clock, port.reset) {
|
||||||
Module(mmio_mem.module).suggestName("mmio_mem")
|
Module(mmio_mem.module).suggestName("mmio_mem")
|
||||||
}
|
}
|
||||||
mmio_mem.io_axi4.head <> port.bits
|
mmio_mem.io_axi4.head <> port.bits
|
||||||
@@ -168,26 +169,27 @@ class WithSimAXIMMIO extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithTieOffInterrupts extends OverrideHarnessBinder({
|
class WithTieOffInterrupts extends OverrideHarnessBinder({
|
||||||
(system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => {
|
(system: HasExtInterruptsModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UInt]) => {
|
||||||
ports.foreach { _ := 0.U }
|
ports.foreach { _ := 0.U }
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
|
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
|
||||||
(system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
(system: CanHaveSlaveAXI4Port, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
||||||
ports.foreach({ p => p := DontCare; p.bits.tieoff() })
|
ports.foreach({ p => p := DontCare; p.bits.tieoff() })
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSimDebug extends OverrideHarnessBinder({
|
class WithSimDebug extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
(system: HasPeripheryDebug, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||||
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map {
|
ports.map {
|
||||||
case d: ClockedDMIIO =>
|
case d: ClockedDMIIO =>
|
||||||
val dtm_success = WireInit(false.B)
|
val dtm_success = WireInit(false.B)
|
||||||
when (dtm_success) { th.success := true.B }
|
when (dtm_success) { th.success := true.B }
|
||||||
val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
|
val dtm = Module(new SimDTM).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
|
||||||
case j: JTAGIO =>
|
case j: JTAGIO =>
|
||||||
val dtm_success = WireInit(false.B)
|
val dtm_success = WireInit(false.B)
|
||||||
when (dtm_success) { th.success := true.B }
|
when (dtm_success) { th.success := true.B }
|
||||||
@@ -198,7 +200,7 @@ class WithSimDebug extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithTiedOffDebug extends OverrideHarnessBinder({
|
class WithTiedOffDebug extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
(system: HasPeripheryDebug, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||||
ports.map {
|
ports.map {
|
||||||
case j: JTAGIO =>
|
case j: JTAGIO =>
|
||||||
j.TCK := true.B.asClock
|
j.TCK := true.B.asClock
|
||||||
@@ -224,7 +226,7 @@ class WithTiedOffDebug extends OverrideHarnessBinder({
|
|||||||
|
|
||||||
|
|
||||||
class WithSerialAdapterTiedOff extends OverrideHarnessBinder({
|
class WithSerialAdapterTiedOff extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
(system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||||
ports.map({ port =>
|
ports.map({ port =>
|
||||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
||||||
@@ -234,7 +236,7 @@ class WithSerialAdapterTiedOff extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithSimSerial extends OverrideHarnessBinder({
|
class WithSimSerial extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
(system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||||
ports.map({ port =>
|
ports.map({ port =>
|
||||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
||||||
@@ -245,14 +247,14 @@ class WithSimSerial extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithTraceGenSuccess extends OverrideHarnessBinder({
|
class WithTraceGenSuccess extends OverrideHarnessBinder({
|
||||||
(system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => {
|
(system: TraceGenSystemModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Bool]) => {
|
||||||
ports.map { p => when (p) { th.success := true.B } }
|
ports.map { p => when (p) { th.success := true.B } }
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSimDromajoBridge extends ComposeHarnessBinder({
|
class WithSimDromajoBridge extends ComposeHarnessBinder({
|
||||||
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
|
(system: CanHaveTraceIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
|
||||||
ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
|
ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package chipyard.iobinders
|
package chipyard.iobinders
|
||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util.experimental.{BoringUtils}
|
|
||||||
import chisel3.experimental.{Analog, IO, DataMirror}
|
import chisel3.experimental.{Analog, IO, DataMirror}
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.devices.debug._
|
import freechips.rocketchip.devices.debug._
|
||||||
import freechips.rocketchip.jtag.{JTAGIO}
|
import freechips.rocketchip.jtag.{JTAGIO}
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.system.{SimAXIMem}
|
import freechips.rocketchip.system.{SimAXIMem}
|
||||||
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
|
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
|
||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
|
import freechips.rocketchip.prci.{ClockSinkNode, ClockSinkParameters}
|
||||||
import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem}
|
import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem}
|
||||||
|
|
||||||
import sifive.blocks.devices.gpio._
|
import sifive.blocks.devices.gpio._
|
||||||
@@ -28,6 +28,12 @@ import chipyard.GlobalResetSchemeKey
|
|||||||
|
|
||||||
import scala.reflect.{ClassTag}
|
import scala.reflect.{ClassTag}
|
||||||
|
|
||||||
|
object IOBinderTypes {
|
||||||
|
type IOBinderTuple = (Seq[Data], Seq[IOCell])
|
||||||
|
type IOBinderFunction = (Boolean, => Any) => ModuleValue[IOBinderTuple]
|
||||||
|
}
|
||||||
|
import IOBinderTypes._
|
||||||
|
|
||||||
// System for instantiating binders based
|
// System for instantiating binders based
|
||||||
// on the scala type of the Target (_not_ its IO). This avoids needing to
|
// on the scala type of the Target (_not_ its IO). This avoids needing to
|
||||||
// duplicate harnesses (essentially test harnesses) for each target.
|
// duplicate harnesses (essentially test harnesses) for each target.
|
||||||
@@ -40,21 +46,30 @@ import scala.reflect.{ClassTag}
|
|||||||
|
|
||||||
// You can add your own binder by adding a new (key, fn) pair, typically by using
|
// You can add your own binder by adding a new (key, fn) pair, typically by using
|
||||||
// the OverrideIOBinder or ComposeIOBinder macros
|
// the OverrideIOBinder or ComposeIOBinder macros
|
||||||
case object IOBinders extends Field[Map[String, (Any) => (Seq[Data], Seq[IOCell])]](
|
case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]](
|
||||||
Map[String, (Any) => (Seq[Data], Seq[IOCell])]().withDefaultValue((Any) => (Nil, Nil))
|
Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil)
|
||||||
)
|
)
|
||||||
object ApplyIOBinders {
|
|
||||||
def apply(sys: LazyModule, map: Map[String, (Any) => (Seq[Data], Seq[IOCell])]):
|
|
||||||
(Iterable[Data], Iterable[IOCell], Map[String, Seq[Data]]) = {
|
|
||||||
val lzy = map.map({ case (s,f) => s -> f(sys) })
|
|
||||||
val imp = map.map({ case (s,f) => s -> f(sys.module) })
|
|
||||||
val unzipped = (lzy.values ++ imp.values).unzip
|
|
||||||
|
|
||||||
val ports: Iterable[Data] = unzipped._1.flatten
|
abstract trait HasIOBinders { this: LazyModule =>
|
||||||
val cells: Iterable[IOCell] = unzipped._2.flatten
|
val lazySystem: LazyModule
|
||||||
val portMap: Map[String, Seq[Data]] = map.keys.map(k => k -> (lzy(k)._1 ++ imp(k)._1)).toMap
|
private val iobinders = p(IOBinders)
|
||||||
(ports, cells, portMap)
|
// Note: IOBinders cannot rely on the implicit clock/reset, as they may be called from the
|
||||||
}
|
// context of a LazyRawModuleImp
|
||||||
|
private val lzy = iobinders.map({ case (s,fns) => s -> fns.map(f => f(true, lazySystem)) })
|
||||||
|
private val imp = iobinders.map({ case (s,fns) => s -> fns.map(f => f(false, lazySystem.module)) })
|
||||||
|
|
||||||
|
private lazy val lzyFlattened: Map[String, IOBinderTuple] = lzy.map({
|
||||||
|
case (s,ms) => s -> (ms.map(_._1).flatten, ms.map(_._2).flatten)
|
||||||
|
})
|
||||||
|
private lazy val impFlattened: Map[String, IOBinderTuple] = imp.map({
|
||||||
|
case (s,ms) => s -> (ms.map(_._1).flatten, ms.map(_._2).flatten)
|
||||||
|
})
|
||||||
|
|
||||||
|
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
|
||||||
|
lazy val iocells = (lzyFlattened.values ++ impFlattened.values).unzip._2.flatten.toBuffer
|
||||||
|
|
||||||
|
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop ports
|
||||||
|
lazy val portMap = iobinders.keys.map(k => k -> (lzyFlattened(k)._1 ++ impFlattened(k)._1)).toMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: The parameters instance is accessible only through LazyModule
|
// Note: The parameters instance is accessible only through LazyModule
|
||||||
@@ -72,52 +87,45 @@ object GetSystemParameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IOBinder(f: (View, View, View) => PartialFunction[Any, Any]) extends Config(f)
|
class IOBinder[T](composer: Seq[IOBinderFunction] => Seq[IOBinderFunction])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
|
||||||
|
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> composer(up(IOBinders, site)(tag.runtimeClass.toString)))
|
||||||
// This macro overrides previous matches on some Top mixin. This is useful for
|
|
||||||
// binders which drive IO, since those typically cannot be composed
|
|
||||||
class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => {
|
|
||||||
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
|
|
||||||
((t: Any) => {
|
|
||||||
t match {
|
|
||||||
case system: T =>
|
|
||||||
val (ports, cells) = fn(system)
|
|
||||||
(ports, cells)
|
|
||||||
case _ => (Nil, Nil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// This macro composes with previous matches on some Top mixin. This is useful for
|
class ConcreteIOBinder[T](composes: Boolean, fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends IOBinder[T](
|
||||||
// annotation-like binders, since those can typically be composed
|
up => (if (composes) up else Nil) ++ Seq(((_, t) => { InModuleBody {
|
||||||
class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => {
|
t match {
|
||||||
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
|
case system: T => fn(system)
|
||||||
((t: Any) => {
|
case _ => (Nil, Nil)
|
||||||
t match {
|
}
|
||||||
case system: T =>
|
}}): IOBinderFunction)
|
||||||
val r = up(IOBinders, site)(tag.runtimeClass.toString)(system)
|
)
|
||||||
val h = fn(system)
|
|
||||||
val ports = r._1 ++ h._1
|
|
||||||
val cells = r._2 ++ h._2
|
|
||||||
(ports, cells)
|
|
||||||
case _ => (Nil, Nil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
object BoreHelper {
|
class LazyIOBinder[T](composes: Boolean, fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends IOBinder[T](
|
||||||
def apply(name: String, source: Clock): Clock = {
|
up => (if (composes) up else Nil) ++ Seq(((isLazy, t) => {
|
||||||
val clock_io = IO(Output(Clock())).suggestName(name)
|
val empty = new ModuleValue[IOBinderTuple] {
|
||||||
val clock_wire = Wire(Clock()).suggestName(s"chiptop_${name}")
|
def getWrappedValue: IOBinderTuple = (Nil, Nil)
|
||||||
dontTouch(clock_wire)
|
}
|
||||||
clock_wire := false.B.asClock // necessary for BoringUtils to work properly
|
if (isLazy) {
|
||||||
BoringUtils.bore(source, Seq(clock_wire))
|
t match {
|
||||||
clock_io := clock_wire
|
case system: T => fn(system)
|
||||||
clock_io
|
case _ => empty
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
empty
|
||||||
|
}
|
||||||
|
}): IOBinderFunction)
|
||||||
|
)
|
||||||
|
|
||||||
|
// The "Override" binders override any previous IOBinders (lazy or concrete) defined on the same trait.
|
||||||
|
// The "Compose" binders do not override previously defined IOBinders on the same trait
|
||||||
|
// The default IOBinders evaluate only in the concrete "ModuleImp" phase of elaboration
|
||||||
|
// The "Lazy" IOBinders evaluate in the LazyModule phase, but can also generate hardware through InModuleBody
|
||||||
|
|
||||||
|
class OverrideIOBinder[T](fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends ConcreteIOBinder[T](false, fn)
|
||||||
|
class ComposeIOBinder[T](fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends ConcreteIOBinder[T](true, fn)
|
||||||
|
|
||||||
|
class OverrideLazyIOBinder[T](fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends LazyIOBinder[T](false, fn)
|
||||||
|
class ComposeLazyIOBinder[T](fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends LazyIOBinder[T](true, fn)
|
||||||
|
|
||||||
|
|
||||||
case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams())
|
case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams())
|
||||||
@@ -194,55 +202,55 @@ class WithExtInterruptIOCells extends OverrideIOBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class WithDebugIOCells extends OverrideIOBinder({
|
class WithDebugIOCells extends OverrideLazyIOBinder({
|
||||||
(system: HasPeripheryDebugModuleImp) => {
|
(system: HasPeripheryDebug) => {
|
||||||
system.debug.map({ debug =>
|
implicit val p = GetSystemParameters(system)
|
||||||
val p = system.p
|
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
|
||||||
val tlbus = system.outer.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
|
val clockSinkNode = system.debugOpt.map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||||
val debug_clock = Wire(Clock()).suggestName("debug_clock")
|
clockSinkNode.map(_ := tlbus.fixedClockNode)
|
||||||
val debug_reset = Wire(Reset()).suggestName("debug_reset")
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
debug_clock := false.B.asClock // must provide default assignment to avoid firrtl unassigned error
|
|
||||||
debug_reset := false.B // must provide default assignment to avoid firrtl unassigned error
|
|
||||||
BoringUtils.bore(tlbus.module.clock, Seq(debug_clock))
|
|
||||||
BoringUtils.bore(tlbus.module.reset, Seq(debug_reset))
|
|
||||||
|
|
||||||
// We never use the PSDIO, so tie it off on-chip
|
|
||||||
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
|
InModuleBody { system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripheryDebugModuleImp => {
|
||||||
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := debug_reset.asBool } }
|
system.debug.map({ debug =>
|
||||||
system.debug.map { d =>
|
// We never use the PSDIO, so tie it off on-chip
|
||||||
// Tie off extTrigger
|
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
|
||||||
d.extTrigger.foreach { t =>
|
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := clockBundle.reset.asBool } }
|
||||||
t.in.req := false.B
|
system.debug.map { d =>
|
||||||
t.out.ack := t.out.req
|
// Tie off extTrigger
|
||||||
|
d.extTrigger.foreach { t =>
|
||||||
|
t.in.req := false.B
|
||||||
|
t.out.ack := t.out.req
|
||||||
|
}
|
||||||
|
// Tie off disableDebug
|
||||||
|
d.disableDebug.foreach { d => d := false.B }
|
||||||
|
// Drive JTAG on-chip IOs
|
||||||
|
d.systemjtag.map { j =>
|
||||||
|
j.reset := clockBundle.reset
|
||||||
|
j.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W)
|
||||||
|
j.part_number := p(JtagDTMKey).idcodePartNum.U(16.W)
|
||||||
|
j.version := p(JtagDTMKey).idcodeVersion.U(4.W)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Tie off disableDebug
|
Debug.connectDebugClockAndReset(Some(debug), clockBundle.clock)
|
||||||
d.disableDebug.foreach { d => d := false.B }
|
|
||||||
// Drive JTAG on-chip IOs
|
// Add IOCells for the DMI/JTAG/APB ports
|
||||||
d.systemjtag.map { j =>
|
val dmiTuple = debug.clockeddmi.map { d =>
|
||||||
j.reset := debug_reset
|
IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
||||||
j.mfr_id := system.p(JtagDTMKey).idcodeManufId.U(11.W)
|
|
||||||
j.part_number := system.p(JtagDTMKey).idcodePartNum.U(16.W)
|
|
||||||
j.version := system.p(JtagDTMKey).idcodeVersion.U(4.W)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Debug.connectDebugClockAndReset(Some(debug), debug_clock)(system.p)
|
|
||||||
|
|
||||||
// Add IOCells for the DMI/JTAG/APB ports
|
val jtagTuple = debug.systemjtag.map { j =>
|
||||||
val dmiTuple = debug.clockeddmi.map { d =>
|
IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
||||||
IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val jtagTuple = debug.systemjtag.map { j =>
|
val apbTuple = debug.apb.map { a =>
|
||||||
IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
||||||
}
|
}
|
||||||
|
|
||||||
val apbTuple = debug.apb.map { a =>
|
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
|
||||||
IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
|
||||||
}
|
}).getOrElse((Nil, Nil))
|
||||||
|
}}}
|
||||||
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
|
|
||||||
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
|
|
||||||
}).getOrElse((Nil, Nil))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -255,39 +263,62 @@ class WithSerialTLIOCells extends OverrideIOBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class WithAXI4MemPunchthrough extends OverrideIOBinder({
|
class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
|
||||||
(system: CanHaveMasterAXI4MemPort) => {
|
(system: CanHaveMasterAXI4MemPort) => {
|
||||||
val ports: Seq[ClockedIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
val clockSinkNode = p(ExtMem).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||||
p.bits <> m
|
clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode)
|
||||||
p.clock := BoreHelper("axi4_mem_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock)
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
p
|
|
||||||
})
|
InModuleBody {
|
||||||
(ports, Nil)
|
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
||||||
|
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
||||||
|
p.bits <> m
|
||||||
|
p.clock := clockBundle.clock
|
||||||
|
p.reset := clockBundle.reset
|
||||||
|
p
|
||||||
|
})
|
||||||
|
(ports, Nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithAXI4MMIOPunchthrough extends OverrideIOBinder({
|
class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({
|
||||||
(system: CanHaveMasterAXI4MMIOPort) => {
|
(system: CanHaveMasterAXI4MMIOPort) => {
|
||||||
val ports: Seq[ClockedIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
|
val clockSinkNode = p(ExtBus).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||||
p.bits <> m
|
clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode)
|
||||||
p.clock := BoreHelper("axi4_mmio_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock)
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
p
|
|
||||||
})
|
InModuleBody {
|
||||||
(ports, Nil)
|
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
|
||||||
|
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
|
||||||
|
p.bits <> m
|
||||||
|
p.clock := clockBundle.clock
|
||||||
|
p.reset := clockBundle.reset
|
||||||
|
p
|
||||||
|
})
|
||||||
|
(ports, Nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithL2FBusAXI4Punchthrough extends OverrideIOBinder({
|
class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({
|
||||||
(system: CanHaveSlaveAXI4Port) => {
|
(system: CanHaveSlaveAXI4Port) => {
|
||||||
val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) =>
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}")
|
val clockSinkNode = p(ExtIn).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||||
m <> p.bits
|
clockSinkNode.map(_ := system.asInstanceOf[BaseSubsystem].fbus.fixedClockNode)
|
||||||
p.clock := BoreHelper("axi4_fbus_clock", system.asInstanceOf[BaseSubsystem].fbus.module.clock)
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
p
|
|
||||||
})
|
InModuleBody {
|
||||||
(ports, Nil)
|
val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) =>
|
||||||
|
val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}")
|
||||||
|
m <> p.bits
|
||||||
|
p.clock := clockBundle.clock
|
||||||
|
p
|
||||||
|
})
|
||||||
|
(ports, Nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import freechips.rocketchip.diplomacy.{LazyModule}
|
|||||||
import freechips.rocketchip.config.{Field, Parameters}
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
|
||||||
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
||||||
|
import chipyard.iobinders.HasIOBinders
|
||||||
|
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// Chipyard Test Harness
|
// Chipyard Test Harness
|
||||||
@@ -14,9 +15,7 @@ import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
|||||||
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
|
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
|
||||||
|
|
||||||
trait HasTestHarnessFunctions {
|
trait HasTestHarnessFunctions {
|
||||||
val lazySystem: LazyModule
|
|
||||||
val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]]
|
val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]]
|
||||||
val portMap = scala.collection.mutable.Map[String, Seq[Data]]()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasHarnessSignalReferences {
|
trait HasHarnessSignalReferences {
|
||||||
@@ -44,7 +43,9 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign
|
|||||||
|
|
||||||
lazyDut match { case d: HasTestHarnessFunctions =>
|
lazyDut match { case d: HasTestHarnessFunctions =>
|
||||||
d.harnessFunctions.foreach(_(this))
|
d.harnessFunctions.foreach(_(this))
|
||||||
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
|
}
|
||||||
|
lazyDut match { case d: HasIOBinders =>
|
||||||
|
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValN
|
|||||||
* fast reference clock (roughly LCM(requested frequencies)) which is passed up the
|
* fast reference clock (roughly LCM(requested frequencies)) which is passed up the
|
||||||
* diplomatic graph, and then generates dividers for each unique requested
|
* diplomatic graph, and then generates dividers for each unique requested
|
||||||
* frequency.
|
* frequency.
|
||||||
|
*
|
||||||
|
* Output resets are not synchronized to generated clocks and should be
|
||||||
|
* synchronized by the user in a manner they see fit.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule {
|
class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule {
|
||||||
@@ -87,6 +91,7 @@ class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName
|
|||||||
for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) {
|
for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) {
|
||||||
val div = pllConfig.sinkDividerMap(sinkP)
|
val div = pllConfig.sinkDividerMap(sinkP)
|
||||||
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
|
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
|
||||||
|
// Reset handling and synchronization is expected to be handled by a downstream node
|
||||||
sinkB.reset := refClock.reset
|
sinkB.reset := refClock.reset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.prci._
|
||||||
|
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a reset synchronizer on all clock-reset pairs in a clock group
|
||||||
|
*/
|
||||||
|
class ClockGroupResetSynchronizer(implicit p: Parameters) extends LazyModule {
|
||||||
|
val node = ClockGroupIdentityNode()
|
||||||
|
lazy val module = new LazyRawModuleImp(this) {
|
||||||
|
(node.out zip node.in).map { case ((oG, _), (iG, _)) =>
|
||||||
|
(oG.member.data zip iG.member.data).foreach { case (o, i) =>
|
||||||
|
o.clock := i.clock
|
||||||
|
o.reset := ResetCatchAndSync(i.clock, i.reset.asBool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ClockGroupResetSynchronizer {
|
||||||
|
def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new ClockGroupResetSynchronizer()).node
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -49,6 +49,6 @@ class AbstractConfig extends Config(
|
|||||||
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
|
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
|
||||||
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache
|
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache
|
||||||
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts
|
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts
|
||||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2
|
new chipyard.WithMulticlockCoherentBusTopology ++ // hierarchical buses including mbus+l2
|
||||||
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
|
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
|
||||||
|
|
||||||
|
|||||||
@@ -179,6 +179,9 @@ class DividedClockRocketConfig extends Config(
|
|||||||
new chipyard.config.WithTileFrequency(200.0) ++
|
new chipyard.config.WithTileFrequency(200.0) ++
|
||||||
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
|
new chipyard.config.WithMemoryBusFrequency(50.0) ++
|
||||||
|
new chipyard.config.WithAsynchrousMemoryBusCrossing ++
|
||||||
|
new testchipip.WithAsynchronousSerialSlaveCrossing ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
class LBWIFRocketConfig extends Config(
|
class LBWIFRocketConfig extends Config(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class Sodor1StageConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ class Sodor2StageConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ class Sodor3StageConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ class Sodor3StageSinglePortConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class Sodor5StageConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -54,6 +54,6 @@ class SodorUCodeConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|||||||
@@ -12,10 +12,11 @@ private[stage] object UnderscoreDelimitedConfigsAnnotation extends HasShellOptio
|
|||||||
new ShellOption[String](
|
new ShellOption[String](
|
||||||
longOption = "legacy-configs",
|
longOption = "legacy-configs",
|
||||||
toAnnotationSeq = a => {
|
toAnnotationSeq = a => {
|
||||||
val split = a.split('.')
|
val split = a.split(':')
|
||||||
val packageName = split.init.mkString(".")
|
assert(split.length == 2)
|
||||||
|
val packageName = split.head
|
||||||
val configs = split.last.split("_")
|
val configs = split.last.split("_")
|
||||||
Seq(new ConfigsAnnotation(configs map { config => s"${packageName}.${config}" } ))
|
Seq(new ConfigsAnnotation(configs map { config => if (config contains ".") s"${config}" else s"${packageName}.${config}" } ))
|
||||||
},
|
},
|
||||||
helpText = "A string of underscore-delimited configs (configs have decreasing precendence from left to right).",
|
helpText = "A string of underscore-delimited configs (configs have decreasing precendence from left to right).",
|
||||||
shortOption = Some("LC")
|
shortOption = Some("LC")
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvon
|
|||||||
|
|
||||||
import junctions.{NastiKey, NastiParameters}
|
import junctions.{NastiKey, NastiParameters}
|
||||||
import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig}
|
import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig}
|
||||||
import midas.targetutils.{FAMEModelAnnotation, MemModelAnnotation, EnableModelMultiThreadingAnnotation}
|
import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotation}
|
||||||
import firesim.bridges._
|
import firesim.bridges._
|
||||||
import firesim.configs.MemModelKey
|
import firesim.configs.MemModelKey
|
||||||
import tracegen.{TraceGenSystemModuleImp}
|
import tracegen.{TraceGenSystemModuleImp}
|
||||||
@@ -66,7 +66,7 @@ class WithFireSimIOCellModels extends Config((site, here, up) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithSerialBridge extends OverrideHarnessBinder({
|
class WithSerialBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
(system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||||
ports.map { port =>
|
ports.map { port =>
|
||||||
implicit val p = GetSystemParameters(system)
|
implicit val p = GetSystemParameters(system)
|
||||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
||||||
@@ -77,7 +77,7 @@ class WithSerialBridge extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithNICBridge extends OverrideHarnessBinder({
|
class WithNICBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
(system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||||
val p: Parameters = GetSystemParameters(system)
|
val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { n => NICBridge(n.clock, n.bits)(p) }
|
ports.map { n => NICBridge(n.clock, n.bits)(p) }
|
||||||
Nil
|
Nil
|
||||||
@@ -85,12 +85,12 @@ class WithNICBridge extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithUARTBridge extends OverrideHarnessBinder({
|
class WithUARTBridge extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) =>
|
(system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) =>
|
||||||
ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil
|
ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
(system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) }
|
ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) }
|
||||||
Nil
|
Nil
|
||||||
@@ -98,14 +98,14 @@ class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithFASEDBridge extends OverrideHarnessBinder({
|
class WithFASEDBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
(system: CanHaveMasterAXI4MemPort, th: FireSim, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
(ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) =>
|
(ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) =>
|
||||||
val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth,
|
val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth,
|
||||||
axi4.bits.ar.bits.addr.getWidth,
|
axi4.bits.ar.bits.addr.getWidth,
|
||||||
axi4.bits.ar.bits.id.getWidth)
|
axi4.bits.ar.bits.id.getWidth)
|
||||||
system match {
|
system match {
|
||||||
case s: BaseSubsystem => FASEDBridge(axi4.clock, axi4.bits, th.harnessReset.asBool,
|
case s: BaseSubsystem => FASEDBridge(axi4.clock, axi4.bits, axi4.reset.asBool,
|
||||||
CompleteConfig(p(firesim.configs.MemModelKey),
|
CompleteConfig(p(firesim.configs.MemModelKey),
|
||||||
nastiKey,
|
nastiKey,
|
||||||
Some(AXI4EdgeSummary(edge)),
|
Some(AXI4EdgeSummary(edge)),
|
||||||
@@ -118,20 +118,20 @@ class WithFASEDBridge extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithTracerVBridge extends ComposeHarnessBinder({
|
class WithTracerVBridge extends ComposeHarnessBinder({
|
||||||
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
|
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => {
|
||||||
ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
|
ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithDromajoBridge extends ComposeHarnessBinder({
|
class WithDromajoBridge extends ComposeHarnessBinder({
|
||||||
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) =>
|
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) =>
|
||||||
ports.map { p => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil
|
ports.map { p => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class WithTraceGenBridge extends OverrideHarnessBinder({
|
class WithTraceGenBridge extends OverrideHarnessBinder({
|
||||||
(system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) =>
|
(system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) =>
|
||||||
ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil
|
ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -161,10 +161,8 @@ class WithFireSimFAME5 extends ComposeIOBinder({
|
|||||||
(system: HasTilesModuleImp) => {
|
(system: HasTilesModuleImp) => {
|
||||||
system.outer.tiles.map {
|
system.outer.tiles.map {
|
||||||
case b: BoomTile =>
|
case b: BoomTile =>
|
||||||
annotate(FAMEModelAnnotation(b.module))
|
|
||||||
annotate(EnableModelMultiThreadingAnnotation(b.module))
|
annotate(EnableModelMultiThreadingAnnotation(b.module))
|
||||||
case r: RocketTile =>
|
case r: RocketTile =>
|
||||||
annotate(FAMEModelAnnotation(r.module))
|
|
||||||
annotate(EnableModelMultiThreadingAnnotation(r.module))
|
annotate(EnableModelMultiThreadingAnnotation(r.module))
|
||||||
}
|
}
|
||||||
(Nil, Nil)
|
(Nil, Nil)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock
|
|||||||
import chipyard._
|
import chipyard._
|
||||||
import chipyard.harness._
|
import chipyard.harness._
|
||||||
import chipyard.iobinders._
|
import chipyard.iobinders._
|
||||||
import chipyard.clocking.{FrequencyUtils, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier, SimplePllConfiguration}
|
import chipyard.clocking._
|
||||||
|
|
||||||
// Determines the number of times to instantiate the DUT in the harness.
|
// Determines the number of times to instantiate the DUT in the harness.
|
||||||
// Subsumes legacy supernode support
|
// Subsumes legacy supernode support
|
||||||
@@ -96,11 +96,12 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
|||||||
|
|
||||||
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
|
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
|
||||||
(chiptop.implicitClockSinkNode := ClockGroup() := aggregator)
|
(chiptop.implicitClockSinkNode := ClockGroup() := aggregator)
|
||||||
(systemAsyncClockGroup := ClockGroupNamePrefixer() := aggregator)
|
(systemAsyncClockGroup :*= ClockGroupNamePrefixer() :*= aggregator)
|
||||||
|
|
||||||
val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
||||||
|
|
||||||
(aggregator
|
(aggregator
|
||||||
|
:= ClockGroupResetSynchronizer()
|
||||||
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||||
:= inputClockSource)
|
:= inputClockSource)
|
||||||
|
|
||||||
@@ -113,15 +114,7 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
|||||||
|
|
||||||
(clockGroupBundle.member.data zip input_clocks.data).foreach { case (clockBundle, inputClock) =>
|
(clockGroupBundle.member.data zip input_clocks.data).foreach { case (clockBundle, inputClock) =>
|
||||||
clockBundle.clock := inputClock
|
clockBundle.clock := inputClock
|
||||||
}
|
clockBundle.reset := reset
|
||||||
|
|
||||||
// Assign resets. The synchronization scheme is still WIP.
|
|
||||||
for ((name, clockBundle) <- clockGroupBundle.member.elements) {
|
|
||||||
if (name.contains("core")) {
|
|
||||||
clockBundle.reset := ResetCatchAndSync(clockBundle.clock, reset.asBool)
|
|
||||||
} else {
|
|
||||||
clockBundle.reset := reset
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)
|
val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)
|
||||||
@@ -160,7 +153,9 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSigna
|
|||||||
lazyModule match { case d: HasTestHarnessFunctions =>
|
lazyModule match { case d: HasTestHarnessFunctions =>
|
||||||
require(d.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
|
require(d.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
|
||||||
d.harnessFunctions.foreach(_(this))
|
d.harnessFunctions.foreach(_(this))
|
||||||
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
|
}
|
||||||
|
lazyModule match { case d: HasIOBinders =>
|
||||||
|
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||||
}
|
}
|
||||||
NodeIdx.increment()
|
NodeIdx.increment()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,6 @@ class WithBootROM extends Config((site, here, up) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithPeripheryBusFrequency(freq: BigInt) extends Config((site, here, up) => {
|
|
||||||
case PeripheryBusKey => up(PeripheryBusKey).copy(dtsFrequency = Some(freq))
|
|
||||||
})
|
|
||||||
|
|
||||||
// Disables clock-gating; doesn't play nice with our FAME-1 pass
|
// Disables clock-gating; doesn't play nice with our FAME-1 pass
|
||||||
class WithoutClockGating extends Config((site, here, up) => {
|
class WithoutClockGating extends Config((site, here, up) => {
|
||||||
case DebugModuleKey => up(DebugModuleKey, site).map(_.copy(clockGate = false))
|
case DebugModuleKey => up(DebugModuleKey, site).map(_.copy(clockGate = false))
|
||||||
@@ -66,13 +62,23 @@ class WithNVDLASmall extends nvidia.blocks.dla.WithNVDLA("small")
|
|||||||
|
|
||||||
// Tweaks that are generally applied to all firesim configs
|
// Tweaks that are generally applied to all firesim configs
|
||||||
class WithFireSimConfigTweaks extends Config(
|
class WithFireSimConfigTweaks extends Config(
|
||||||
|
// Required: Bake in the default FASED memory model
|
||||||
|
new WithDefaultMemModel ++
|
||||||
// Required*: Uses FireSim ClockBridge and PeekPokeBridge to drive the system with a single clock/reset
|
// Required*: Uses FireSim ClockBridge and PeekPokeBridge to drive the system with a single clock/reset
|
||||||
new WithFireSimSimpleClocks ++
|
new WithFireSimSimpleClocks ++
|
||||||
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
|
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
|
||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
// Optional*: Removing this will require adjusting the UART baud rate and
|
// Optional*: Removing this will require adjusting the UART baud rate and
|
||||||
// potential target-software changes to properly capture UART output
|
// potential target-software changes to properly capture UART output
|
||||||
new WithPeripheryBusFrequency(BigInt(3200000000L)) ++
|
new chipyard.config.WithPeripheryBusFrequency(3200.0) ++
|
||||||
|
// Optional: These three configs put the DRAM memory system in it's own clock domian.
|
||||||
|
// Removing the first config will result in the FASED timing model running
|
||||||
|
// at the pbus freq (above, 3.2 GHz), which is outside the range of valid DDR3 speedgrades.
|
||||||
|
// 1 GHz matches the FASED default, using some other frequency will require
|
||||||
|
// runnings the FASED runtime configuration generator to generate faithful DDR3 timing values.
|
||||||
|
new chipyard.config.WithMemoryBusFrequency(1000.0) ++
|
||||||
|
new chipyard.config.WithAsynchrousMemoryBusCrossing ++
|
||||||
|
new testchipip.WithAsynchronousSerialSlaveCrossing ++
|
||||||
// Required: Existing FAME-1 transform cannot handle black-box clock gates
|
// Required: Existing FAME-1 transform cannot handle black-box clock gates
|
||||||
new WithoutClockGating ++
|
new WithoutClockGating ++
|
||||||
// Required*: Removes thousands of assertions that would be synthesized (* pending PriorityMux bugfix)
|
// Required*: Removes thousands of assertions that would be synthesized (* pending PriorityMux bugfix)
|
||||||
@@ -127,7 +133,7 @@ class FireSimSmallSystemConfig extends Config(
|
|||||||
new WithDefaultFireSimBridges ++
|
new WithDefaultFireSimBridges ++
|
||||||
new WithDefaultMemModel ++
|
new WithDefaultMemModel ++
|
||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
new WithPeripheryBusFrequency(BigInt(3200000000L)) ++
|
new chipyard.config.WithPeripheryBusFrequency(3200.0) ++
|
||||||
new WithoutClockGating ++
|
new WithoutClockGating ++
|
||||||
new WithoutTLMonitors ++
|
new WithoutTLMonitors ++
|
||||||
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
|
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
|
||||||
|
|||||||
Submodule generators/testchipip updated: 56bfaa3f9b...03af7aa539
@@ -8,7 +8,7 @@ binary=$1
|
|||||||
segments=`readelf --segments --wide $binary`
|
segments=`readelf --segments --wide $binary`
|
||||||
entry_hex=`echo -e "$segments" | grep "Entry point" | cut -f3 -d' ' | sed 's/0x//' | tr [:lower:] [:upper:]`
|
entry_hex=`echo -e "$segments" | grep "Entry point" | cut -f3 -d' ' | sed 's/0x//' | tr [:lower:] [:upper:]`
|
||||||
entry_dec=`bc <<< "ibase=16;$entry_hex"`
|
entry_dec=`bc <<< "ibase=16;$entry_hex"`
|
||||||
length_hex=`echo "$segments" | grep "LOAD\|TLS" | tail -n 1 | tr -s [:space:] | cut -f4,6 -d' '`
|
length_hex=`echo "$segments" | grep "LOAD\|TLS" | tail -n 1 | tr -s [:space:] | cut -f4,7 -d' '`
|
||||||
length_dec=`echo $length_hex | tr -d x | tr [:lower:] [:upper:] | tr ' ' + | sed 's/^/ibase=16;/' | sed "s/$/-$entry_hex/" | bc`
|
length_dec=`echo $length_hex | tr -d x | tr [:lower:] [:upper:] | tr ' ' + | sed 's/^/ibase=16;/' | sed "s/$/-$entry_hex/" | bc`
|
||||||
power_2_length=`echo "x=l($length_dec)/l(2); scale=0; 2^((x+1)/1)" | bc -l`
|
power_2_length=`echo "x=l($length_dec)/l(2); scale=0; 2^((x+1)/1)" | bc -l`
|
||||||
width=64
|
width=64
|
||||||
|
|||||||
Submodule sims/firesim updated: 6318184f30...1c76c446da
Reference in New Issue
Block a user