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
|
||||
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-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
|
||||
grouping["group-tracegen"]="tracegen tracegen-boom"
|
||||
@@ -59,6 +59,7 @@ mapping["chipyard-rocket"]=""
|
||||
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
|
||||
mapping["chipyard-lbwif"]=" CONFIG=LBWIFRocketConfig"
|
||||
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
|
||||
mapping["chipyard-digitaltop"]=" TOP=DigitalTop"
|
||||
mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig"
|
||||
mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig"
|
||||
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
|
||||
|
||||
@@ -110,7 +110,7 @@ generator_temp: $(SCALA_SOURCES) $(sim_files) $(EXTRA_GENERATOR_REQS)
|
||||
--target-dir $(build_dir) \
|
||||
--name $(long_name) \
|
||||
--top-module $(MODEL_PACKAGE).$(MODEL) \
|
||||
--legacy-configs $(CONFIG_PACKAGE).$(CONFIG))
|
||||
--legacy-configs $(CONFIG_PACKAGE):$(CONFIG))
|
||||
|
||||
.PHONY: firrtl
|
||||
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.
|
||||
|
||||
IOBinders
|
||||
=========
|
||||
---------
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -46,7 +46,20 @@ and proceed with the rest of the tutorial.
|
||||
|
||||
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
|
||||
@@ -54,9 +67,4 @@ Converting a Chipyard config (one in ``chipyard/src/main/scala`` to run in FireS
|
||||
:start-after: DOC include start: firesimconfig
|
||||
:end-before: DOC include end: firesimconfig
|
||||
|
||||
|
||||
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.
|
||||
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``)
|
||||
|
||||
@@ -23,12 +23,10 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters)
|
||||
* drive clock and reset generation
|
||||
*/
|
||||
|
||||
class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions with BindingScope {
|
||||
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
|
||||
val iocells = ArrayBuffer.empty[IOCell]
|
||||
|
||||
class ChipTop(implicit p: Parameters) extends LazyModule
|
||||
with HasTestHarnessFunctions with HasIOBinders with BindingScope {
|
||||
// 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
|
||||
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_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
|
||||
lazySystem.module match { case l: LazyModuleImp => {
|
||||
l.clock := implicit_clock
|
||||
|
||||
@@ -8,12 +8,12 @@ import freechips.rocketchip.prci._
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey, InstantiatesTiles}
|
||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
|
||||
import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider}
|
||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||
|
||||
import barstools.iocell.chisel._
|
||||
import testchipip.{TLTileResetCtrl}
|
||||
|
||||
import chipyard.clocking.{DividerOnlyClockGenerator, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier}
|
||||
import chipyard.clocking._
|
||||
|
||||
/**
|
||||
* Chipyard provides three baseline, top-level reset schemes, set using the
|
||||
@@ -121,13 +121,14 @@ object ClockingSchemeGenerators {
|
||||
:= ClockGroup()
|
||||
:= aggregator)
|
||||
(systemAsyncClockGroup
|
||||
:= resetSetter
|
||||
:= ClockGroupNamePrefixer()
|
||||
:= aggregator)
|
||||
:*= resetSetter
|
||||
:*= ClockGroupNamePrefixer()
|
||||
:*= aggregator)
|
||||
|
||||
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
||||
(aggregator
|
||||
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||
:= ClockGroupResetSynchronizer()
|
||||
:= DividerOnlyClockGenerator()
|
||||
:= referenceClockSource)
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@ import chisel3.util.{log2Up}
|
||||
|
||||
import freechips.rocketchip.config.{Field, Parameters, Config}
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.diplomacy.{LazyModule, ValName}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.devices.tilelink.{BootROMLocated}
|
||||
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
|
||||
import freechips.rocketchip.groundtest.{GroundTestSubsystem}
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
|
||||
import freechips.rocketchip.util.{AsyncResetReg}
|
||||
import freechips.rocketchip.util.{AsyncResetReg, Symmetric}
|
||||
import freechips.rocketchip.prci._
|
||||
|
||||
import testchipip._
|
||||
@@ -172,3 +172,46 @@ class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
|
||||
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
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{Analog}
|
||||
import chisel3.experimental.{Analog, BaseModule}
|
||||
|
||||
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||
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)
|
||||
)
|
||||
|
||||
|
||||
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)
|
||||
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) => {
|
||||
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
|
||||
// The ClassTags here are necessary to overcome issues arising from type erasure
|
||||
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]) => {
|
||||
val pts = ports.collect({case p: S => p})
|
||||
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
|
||||
val pts = ports.collect({case p: U => p})
|
||||
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}")
|
||||
val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString)
|
||||
th match {
|
||||
case th: S =>
|
||||
t match {
|
||||
case system: T => fn(system, th, pts)
|
||||
case system: T => composer(upfn)(system, th, pts)
|
||||
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) => {
|
||||
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
|
||||
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||
val pts = ports.collect({case p: S => p})
|
||||
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
|
||||
t match {
|
||||
case system: T => up(HarnessBinders, site)(tag.runtimeClass.toString)(system, th, pts) ++ fn(system, th, pts)
|
||||
case _ => Nil
|
||||
}
|
||||
})
|
||||
)
|
||||
})
|
||||
class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any])
|
||||
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
|
||||
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => fn)
|
||||
|
||||
class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any])
|
||||
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
|
||||
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => (t, th, p) => upfn(t, th, p) ++ fn(t, th, p))
|
||||
|
||||
|
||||
class WithGPIOTiedOff extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => {
|
||||
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Analog]) => {
|
||||
ports.foreach { _ <> AnalogConst(0) }
|
||||
Nil
|
||||
}
|
||||
@@ -74,7 +75,7 @@ class WithGPIOTiedOff extends OverrideHarnessBinder({
|
||||
|
||||
// DOC include start: WithUARTAdapter
|
||||
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)
|
||||
Nil
|
||||
}
|
||||
@@ -82,14 +83,14 @@ class WithUARTAdapter extends OverrideHarnessBinder({
|
||||
// DOC include end: WithUARTAdapter
|
||||
|
||||
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)
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
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)
|
||||
ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) }
|
||||
Nil
|
||||
@@ -97,7 +98,7 @@ class WithSimBlockDevice 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)
|
||||
ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } }
|
||||
Nil
|
||||
@@ -105,7 +106,7 @@ class WithBlockDeviceModel 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)
|
||||
ports.map { n =>
|
||||
withClockAndReset(n.clock, th.harnessReset) {
|
||||
@@ -117,7 +118,7 @@ class WithLoopbackNIC 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)
|
||||
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) }
|
||||
Nil
|
||||
@@ -125,11 +126,11 @@ class WithSimNetwork 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)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
||||
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")
|
||||
}
|
||||
mem.io_axi4.head <> port.bits
|
||||
@@ -139,7 +140,7 @@ class WithSimAXIMem 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)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
||||
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")
|
||||
mem.io.axi <> port.bits
|
||||
mem.io.clock := port.clock
|
||||
mem.io.reset := th.harnessReset
|
||||
mem.io.reset := port.reset
|
||||
}
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
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)
|
||||
(ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) =>
|
||||
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")
|
||||
}
|
||||
mmio_mem.io_axi4.head <> port.bits
|
||||
@@ -168,26 +169,27 @@ class WithSimAXIMMIO 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 }
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
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() })
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
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 {
|
||||
case d: ClockedDMIIO =>
|
||||
val dtm_success = WireInit(false.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 =>
|
||||
val dtm_success = WireInit(false.B)
|
||||
when (dtm_success) { th.success := true.B }
|
||||
@@ -198,7 +200,7 @@ class WithSimDebug extends OverrideHarnessBinder({
|
||||
})
|
||||
|
||||
class WithTiedOffDebug extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||
(system: HasPeripheryDebug, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||
ports.map {
|
||||
case j: JTAGIO =>
|
||||
j.TCK := true.B.asClock
|
||||
@@ -224,7 +226,7 @@ class WithTiedOffDebug 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)
|
||||
ports.map({ port =>
|
||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
||||
@@ -234,7 +236,7 @@ class WithSerialAdapterTiedOff 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)
|
||||
ports.map({ port =>
|
||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
||||
@@ -245,14 +247,14 @@ class WithSimSerial 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 } }
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
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)) }
|
||||
Nil
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package chipyard.iobinders
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.experimental.{BoringUtils}
|
||||
import chisel3.experimental.{Analog, IO, DataMirror}
|
||||
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.devices.debug._
|
||||
import freechips.rocketchip.jtag.{JTAGIO}
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.system.{SimAXIMem}
|
||||
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
|
||||
import freechips.rocketchip.util._
|
||||
import freechips.rocketchip.prci.{ClockSinkNode, ClockSinkParameters}
|
||||
import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem}
|
||||
|
||||
import sifive.blocks.devices.gpio._
|
||||
@@ -28,6 +28,12 @@ import chipyard.GlobalResetSchemeKey
|
||||
|
||||
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
|
||||
// on the scala type of the Target (_not_ its IO). This avoids needing to
|
||||
// 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
|
||||
// the OverrideIOBinder or ComposeIOBinder macros
|
||||
case object IOBinders extends Field[Map[String, (Any) => (Seq[Data], Seq[IOCell])]](
|
||||
Map[String, (Any) => (Seq[Data], Seq[IOCell])]().withDefaultValue((Any) => (Nil, Nil))
|
||||
case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]](
|
||||
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
|
||||
val cells: Iterable[IOCell] = unzipped._2.flatten
|
||||
val portMap: Map[String, Seq[Data]] = map.keys.map(k => k -> (lzy(k)._1 ++ imp(k)._1)).toMap
|
||||
(ports, cells, portMap)
|
||||
}
|
||||
abstract trait HasIOBinders { this: LazyModule =>
|
||||
val lazySystem: LazyModule
|
||||
private val iobinders = p(IOBinders)
|
||||
// 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
|
||||
@@ -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) => {
|
||||
class ConcreteIOBinder[T](composes: Boolean, fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends IOBinder[T](
|
||||
up => (if (composes) up else Nil) ++ Seq(((_, t) => { InModuleBody {
|
||||
t match {
|
||||
case system: T =>
|
||||
val (ports, cells) = fn(system)
|
||||
(ports, cells)
|
||||
case system: T => fn(system)
|
||||
case _ => (Nil, Nil)
|
||||
}
|
||||
})
|
||||
}}): IOBinderFunction)
|
||||
)
|
||||
})
|
||||
|
||||
// This macro composes with previous matches on some Top mixin. This is useful for
|
||||
// annotation-like binders, since those can typically be composed
|
||||
class ComposeIOBinder[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) => {
|
||||
class LazyIOBinder[T](composes: Boolean, fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends IOBinder[T](
|
||||
up => (if (composes) up else Nil) ++ Seq(((isLazy, t) => {
|
||||
val empty = new ModuleValue[IOBinderTuple] {
|
||||
def getWrappedValue: IOBinderTuple = (Nil, Nil)
|
||||
}
|
||||
if (isLazy) {
|
||||
t match {
|
||||
case system: T =>
|
||||
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)
|
||||
case system: T => fn(system)
|
||||
case _ => empty
|
||||
}
|
||||
})
|
||||
} else {
|
||||
empty
|
||||
}
|
||||
}): IOBinderFunction)
|
||||
)
|
||||
})
|
||||
|
||||
object BoreHelper {
|
||||
def apply(name: String, source: Clock): Clock = {
|
||||
val clock_io = IO(Output(Clock())).suggestName(name)
|
||||
val clock_wire = Wire(Clock()).suggestName(s"chiptop_${name}")
|
||||
dontTouch(clock_wire)
|
||||
clock_wire := false.B.asClock // necessary for BoringUtils to work properly
|
||||
BoringUtils.bore(source, Seq(clock_wire))
|
||||
clock_io := clock_wire
|
||||
clock_io
|
||||
}
|
||||
}
|
||||
// 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())
|
||||
@@ -194,21 +202,20 @@ class WithExtInterruptIOCells extends OverrideIOBinder({
|
||||
})
|
||||
|
||||
|
||||
class WithDebugIOCells extends OverrideIOBinder({
|
||||
(system: HasPeripheryDebugModuleImp) => {
|
||||
system.debug.map({ debug =>
|
||||
val p = system.p
|
||||
val tlbus = system.outer.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
|
||||
val debug_clock = Wire(Clock()).suggestName("debug_clock")
|
||||
val debug_reset = Wire(Reset()).suggestName("debug_reset")
|
||||
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))
|
||||
class WithDebugIOCells extends OverrideLazyIOBinder({
|
||||
(system: HasPeripheryDebug) => {
|
||||
implicit val p = GetSystemParameters(system)
|
||||
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
|
||||
val clockSinkNode = system.debugOpt.map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||
clockSinkNode.map(_ := tlbus.fixedClockNode)
|
||||
def clockBundle = clockSinkNode.get.in.head._1
|
||||
|
||||
|
||||
InModuleBody { system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripheryDebugModuleImp => {
|
||||
system.debug.map({ debug =>
|
||||
// We never use the PSDIO, so tie it off on-chip
|
||||
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
|
||||
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := debug_reset.asBool } }
|
||||
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := clockBundle.reset.asBool } }
|
||||
system.debug.map { d =>
|
||||
// Tie off extTrigger
|
||||
d.extTrigger.foreach { t =>
|
||||
@@ -219,13 +226,13 @@ class WithDebugIOCells extends OverrideIOBinder({
|
||||
d.disableDebug.foreach { d => d := false.B }
|
||||
// Drive JTAG on-chip IOs
|
||||
d.systemjtag.map { j =>
|
||||
j.reset := debug_reset
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
Debug.connectDebugClockAndReset(Some(debug), debug_clock)(system.p)
|
||||
Debug.connectDebugClockAndReset(Some(debug), clockBundle.clock)
|
||||
|
||||
// Add IOCells for the DMI/JTAG/APB ports
|
||||
val dmiTuple = debug.clockeddmi.map { d =>
|
||||
@@ -243,6 +250,7 @@ class WithDebugIOCells extends OverrideIOBinder({
|
||||
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
|
||||
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
|
||||
}).getOrElse((Nil, Nil))
|
||||
}}}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -255,40 +263,63 @@ class WithSerialTLIOCells extends OverrideIOBinder({
|
||||
})
|
||||
|
||||
|
||||
class WithAXI4MemPunchthrough extends OverrideIOBinder({
|
||||
class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
|
||||
(system: CanHaveMasterAXI4MemPort) => {
|
||||
val ports: Seq[ClockedIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
val clockSinkNode = p(ExtMem).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||
clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode)
|
||||
def clockBundle = clockSinkNode.get.in.head._1
|
||||
|
||||
InModuleBody {
|
||||
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 := BoreHelper("axi4_mem_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock)
|
||||
p.clock := clockBundle.clock
|
||||
p.reset := clockBundle.reset
|
||||
p
|
||||
})
|
||||
(ports, Nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithAXI4MMIOPunchthrough extends OverrideIOBinder({
|
||||
class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({
|
||||
(system: CanHaveMasterAXI4MMIOPort) => {
|
||||
val ports: Seq[ClockedIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
val clockSinkNode = p(ExtBus).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||
clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode)
|
||||
def clockBundle = clockSinkNode.get.in.head._1
|
||||
|
||||
InModuleBody {
|
||||
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 := BoreHelper("axi4_mmio_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock)
|
||||
p.clock := clockBundle.clock
|
||||
p.reset := clockBundle.reset
|
||||
p
|
||||
})
|
||||
(ports, Nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithL2FBusAXI4Punchthrough extends OverrideIOBinder({
|
||||
class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({
|
||||
(system: CanHaveSlaveAXI4Port) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
val clockSinkNode = p(ExtIn).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||
clockSinkNode.map(_ := system.asInstanceOf[BaseSubsystem].fbus.fixedClockNode)
|
||||
def clockBundle = clockSinkNode.get.in.head._1
|
||||
|
||||
InModuleBody {
|
||||
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 := BoreHelper("axi4_fbus_clock", system.asInstanceOf[BaseSubsystem].fbus.module.clock)
|
||||
p.clock := clockBundle.clock
|
||||
p
|
||||
})
|
||||
(ports, Nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({
|
||||
|
||||
@@ -6,6 +6,7 @@ import freechips.rocketchip.diplomacy.{LazyModule}
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
|
||||
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
||||
import chipyard.iobinders.HasIOBinders
|
||||
|
||||
// -------------------------------
|
||||
// Chipyard Test Harness
|
||||
@@ -14,9 +15,7 @@ import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
||||
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
|
||||
|
||||
trait HasTestHarnessFunctions {
|
||||
val lazySystem: LazyModule
|
||||
val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]]
|
||||
val portMap = scala.collection.mutable.Map[String, Seq[Data]]()
|
||||
}
|
||||
|
||||
trait HasHarnessSignalReferences {
|
||||
@@ -44,7 +43,9 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign
|
||||
|
||||
lazyDut match { case d: HasTestHarnessFunctions =>
|
||||
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
|
||||
* diplomatic graph, and then generates dividers for each unique requested
|
||||
* 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 {
|
||||
@@ -87,6 +91,7 @@ class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName
|
||||
for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) {
|
||||
val div = pllConfig.sinkDividerMap(sinkP)
|
||||
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
|
||||
// Reset handling and synchronization is expected to be handled by a downstream node
|
||||
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.WithInclusiveCache ++ // use Sifive L2 cache
|
||||
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
|
||||
|
||||
|
||||
@@ -179,6 +179,9 @@ class DividedClockRocketConfig extends Config(
|
||||
new chipyard.config.WithTileFrequency(200.0) ++
|
||||
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.WithMemoryBusFrequency(50.0) ++
|
||||
new chipyard.config.WithAsynchrousMemoryBusCrossing ++
|
||||
new testchipip.WithAsynchronousSerialSlaveCrossing ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class LBWIFRocketConfig extends Config(
|
||||
|
||||
@@ -9,7 +9,7 @@ class Sodor1StageConfig extends Config(
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
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 chipyard.config.AbstractConfig)
|
||||
|
||||
@@ -18,7 +18,7 @@ class Sodor2StageConfig extends Config(
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
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 chipyard.config.AbstractConfig)
|
||||
|
||||
@@ -27,7 +27,7 @@ class Sodor3StageConfig extends Config(
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
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 chipyard.config.AbstractConfig)
|
||||
|
||||
@@ -36,7 +36,7 @@ class Sodor3StageSinglePortConfig extends Config(
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
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 chipyard.config.AbstractConfig)
|
||||
|
||||
@@ -45,7 +45,7 @@ class Sodor5StageConfig extends Config(
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
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 chipyard.config.AbstractConfig)
|
||||
|
||||
@@ -54,6 +54,6 @@ class SodorUCodeConfig extends Config(
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
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 chipyard.config.AbstractConfig)
|
||||
|
||||
@@ -12,10 +12,11 @@ private[stage] object UnderscoreDelimitedConfigsAnnotation extends HasShellOptio
|
||||
new ShellOption[String](
|
||||
longOption = "legacy-configs",
|
||||
toAnnotationSeq = a => {
|
||||
val split = a.split('.')
|
||||
val packageName = split.init.mkString(".")
|
||||
val split = a.split(':')
|
||||
assert(split.length == 2)
|
||||
val packageName = split.head
|
||||
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).",
|
||||
shortOption = Some("LC")
|
||||
|
||||
@@ -18,7 +18,7 @@ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvon
|
||||
|
||||
import junctions.{NastiKey, NastiParameters}
|
||||
import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig}
|
||||
import midas.targetutils.{FAMEModelAnnotation, MemModelAnnotation, EnableModelMultiThreadingAnnotation}
|
||||
import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotation}
|
||||
import firesim.bridges._
|
||||
import firesim.configs.MemModelKey
|
||||
import tracegen.{TraceGenSystemModuleImp}
|
||||
@@ -66,7 +66,7 @@ class WithFireSimIOCellModels extends Config((site, here, up) => {
|
||||
})
|
||||
|
||||
class WithSerialBridge extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||
(system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||
ports.map { port =>
|
||||
implicit val p = GetSystemParameters(system)
|
||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
||||
@@ -77,7 +77,7 @@ class WithSerialBridge 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)
|
||||
ports.map { n => NICBridge(n.clock, n.bits)(p) }
|
||||
Nil
|
||||
@@ -85,12 +85,12 @@ class WithNICBridge 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
|
||||
})
|
||||
|
||||
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)
|
||||
ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) }
|
||||
Nil
|
||||
@@ -98,14 +98,14 @@ class WithBlockDeviceBridge 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)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) =>
|
||||
val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth,
|
||||
axi4.bits.ar.bits.addr.getWidth,
|
||||
axi4.bits.ar.bits.id.getWidth)
|
||||
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),
|
||||
nastiKey,
|
||||
Some(AXI4EdgeSummary(edge)),
|
||||
@@ -118,20 +118,20 @@ class WithFASEDBridge extends OverrideHarnessBinder({
|
||||
})
|
||||
|
||||
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)) }
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
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
|
||||
})
|
||||
|
||||
|
||||
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
|
||||
})
|
||||
|
||||
@@ -161,10 +161,8 @@ class WithFireSimFAME5 extends ComposeIOBinder({
|
||||
(system: HasTilesModuleImp) => {
|
||||
system.outer.tiles.map {
|
||||
case b: BoomTile =>
|
||||
annotate(FAMEModelAnnotation(b.module))
|
||||
annotate(EnableModelMultiThreadingAnnotation(b.module))
|
||||
case r: RocketTile =>
|
||||
annotate(FAMEModelAnnotation(r.module))
|
||||
annotate(EnableModelMultiThreadingAnnotation(r.module))
|
||||
}
|
||||
(Nil, Nil)
|
||||
|
||||
@@ -16,7 +16,7 @@ import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock
|
||||
import chipyard._
|
||||
import chipyard.harness._
|
||||
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.
|
||||
// Subsumes legacy supernode support
|
||||
@@ -96,11 +96,12 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
||||
|
||||
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
|
||||
(chiptop.implicitClockSinkNode := ClockGroup() := aggregator)
|
||||
(systemAsyncClockGroup := ClockGroupNamePrefixer() := aggregator)
|
||||
(systemAsyncClockGroup :*= ClockGroupNamePrefixer() :*= aggregator)
|
||||
|
||||
val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
||||
|
||||
(aggregator
|
||||
:= ClockGroupResetSynchronizer()
|
||||
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||
:= inputClockSource)
|
||||
|
||||
@@ -113,16 +114,8 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
||||
|
||||
(clockGroupBundle.member.data zip input_clocks.data).foreach { case (clockBundle, inputClock) =>
|
||||
clockBundle.clock := inputClock
|
||||
}
|
||||
|
||||
// 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 rationalClockSpecs = for ((sinkP, division) <- pllConfig.sinkDividerMap) yield {
|
||||
@@ -160,7 +153,9 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSigna
|
||||
lazyModule match { case d: HasTestHarnessFunctions =>
|
||||
require(d.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
class WithoutClockGating extends Config((site, here, up) => {
|
||||
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
|
||||
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
|
||||
new WithFireSimSimpleClocks ++
|
||||
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
|
||||
new WithBootROM ++
|
||||
// Optional*: Removing this will require adjusting the UART baud rate and
|
||||
// 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
|
||||
new WithoutClockGating ++
|
||||
// Required*: Removes thousands of assertions that would be synthesized (* pending PriorityMux bugfix)
|
||||
@@ -127,7 +133,7 @@ class FireSimSmallSystemConfig extends Config(
|
||||
new WithDefaultFireSimBridges ++
|
||||
new WithDefaultMemModel ++
|
||||
new WithBootROM ++
|
||||
new WithPeripheryBusFrequency(BigInt(3200000000L)) ++
|
||||
new chipyard.config.WithPeripheryBusFrequency(3200.0) ++
|
||||
new WithoutClockGating ++
|
||||
new WithoutTLMonitors ++
|
||||
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
|
||||
|
||||
Submodule generators/testchipip updated: 56bfaa3f9b...03af7aa539
@@ -8,7 +8,7 @@ binary=$1
|
||||
segments=`readelf --segments --wide $binary`
|
||||
entry_hex=`echo -e "$segments" | grep "Entry point" | cut -f3 -d' ' | sed 's/0x//' | tr [:lower:] [:upper:]`
|
||||
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`
|
||||
power_2_length=`echo "x=l($length_dec)/l(2); scale=0; 2^((x+1)/1)" | bc -l`
|
||||
width=64
|
||||
|
||||
Submodule sims/firesim updated: 6318184f30...1c76c446da
Reference in New Issue
Block a user