Merge remote-tracking branch 'upstream/main' into graphics

This commit is contained in:
Hansung Kim
2024-01-16 22:39:37 -08:00
171 changed files with 5890 additions and 4232 deletions

View File

@@ -12,7 +12,7 @@
#if __has_include("spiketile_tsi.h")
#define SPIKETILE_HTIF_TSI
extern htif_t* tsi;
extern std::map<int, htif_t*> tsis;
#endif
#if __has_include("spiketile_dtm.h")
#define SPIKETILE_HTIF_DTM
@@ -346,8 +346,8 @@ extern "C" void spike_tile(int hartid, char* isa,
chipyard_simif_t* simif = tile->simif;
processor_t* proc = tile->proc;
#if defined(SPIKETILE_HTIF_TSI)
if (!simif->htif && tsi)
simif->htif = tsi;
if (!simif->htif && tsis.size() > 0 && tsis[0])
simif->htif = tsis[0];
#endif
#if defined(SPIKETILE_HTIF_DTM)
if (!simif->htif && dtm)
@@ -447,18 +447,6 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
use_stq(false),
htif(nullptr),
fast_clint(false),
cfg(std::make_pair(0, 0),
nullptr,
isastr,
"MSU",
"vlen:128,elen:64",
false,
endianness_little,
pmpregions,
std::vector<mem_cfg_t>(),
std::vector<size_t>(),
false,
0),
accessed_tofrom_host(false),
icache_ways(icache_ways),
icache_sets(icache_sets),
@@ -470,6 +458,19 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
mmio_inflight(false)
{
cfg.initrd_bounds = std::make_pair(0, 0);
cfg.bootargs = nullptr;
cfg.isa = isastr;
cfg.priv = "MSU";
cfg.varch = "vlen:128,elen:64";
cfg.misaligned = false;
cfg.endianness = endianness_little;
cfg.pmpregions = pmpregions;
cfg.mem_layout = std::vector<mem_cfg_t>();
cfg.hartids = std::vector<size_t>();
cfg.explicit_hartids = false;
cfg.trigger_count = 0;
icache.resize(icache_ways);
for (auto &w : icache) {
w.resize(icache_sets);

View File

@@ -5,10 +5,9 @@ import chisel3._
import scala.collection.mutable.{ArrayBuffer}
import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup}
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
import org.chipsalliance.cde.config.{Parameters, Field}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike, BindingScope}
import freechips.rocketchip.util.{ResetCatchAndSync}
import freechips.rocketchip.util.{DontTouch}
import chipyard.iobinders._
import barstools.iocell.chisel._
@@ -31,5 +30,5 @@ class ChipTop(implicit p: Parameters) extends LazyModule with BindingScope
// of ChipTop (ex: ClockGroup) do not receive clock or reset.
// However. anonymous children of ChipTop should not need an implicit Clock or Reset
// anyways, they probably need to be explicitly clocked.
lazy val module: LazyModuleImpLike = new LazyRawModuleImp(this) { }
lazy val module: LazyModuleImpLike = new LazyRawModuleImp(this) with DontTouch { }
}

View File

@@ -13,13 +13,14 @@ import freechips.rocketchip.devices.tilelink._
// DOC include start: DigitalTop
class DigitalTop(implicit p: Parameters) extends ChipyardSystem
with testchipip.CanHavePeripheryUARTTSI // Enables optional UART-based TSI transport
with testchipip.CanHavePeripheryCustomBootPin // Enables optional custom boot pin
with testchipip.CanHavePeripheryBootAddrReg // Use programmable boot address register
with testchipip.CanHaveTraceIO // Enables optionally adding trace IO
with testchipip.CanHaveBankedScratchpad // Enables optionally adding a banked scratchpad
with testchipip.CanHavePeripheryBlockDevice // Enables optionally adding the block device
with testchipip.CanHavePeripheryTLSerial // Enables optionally adding the backing memory and serial adapter
with testchipip.tsi.CanHavePeripheryUARTTSI // Enables optional UART-based TSI transport
with testchipip.boot.CanHavePeripheryCustomBootPin // Enables optional custom boot pin
with testchipip.boot.CanHavePeripheryBootAddrReg // Use programmable boot address register
with testchipip.cosim.CanHaveTraceIO // Enables optionally adding trace IO
with testchipip.soc.CanHaveBankedScratchpad // Enables optionally adding a banked scratchpad
with testchipip.iceblk.CanHavePeripheryBlockDevice // Enables optionally adding the block device
with testchipip.serdes.CanHavePeripheryTLSerial // Enables optionally adding the backing memory and serial adapter
with testchipip.soc.CanHavePeripheryChipIdPin // Enables optional pin to set chip id for multi-chip configs
with sifive.blocks.devices.i2c.HasPeripheryI2C // Enables optionally adding the sifive I2C
with sifive.blocks.devices.pwm.HasPeripheryPWM // Enables optionally adding the sifive PWM
with sifive.blocks.devices.uart.HasPeripheryUART // Enables optionally adding the sifive UART
@@ -39,6 +40,7 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
with chipyard.example.CanHavePeripheryStreamingPassthrough // Enables optionally adding the DSPTools streaming-passthrough example widget
with nvidia.blocks.dla.CanHavePeripheryNVDLA // Enables optionally having an NVDLA
with chipyard.clocking.HasChipyardPRCI // Use Chipyard reset/clock distribution
with chipyard.clocking.CanHaveClockTap // Enables optionally adding a clock tap output port
with fftgenerator.CanHavePeripheryFFT // Enables optionally having an MMIO-based FFT block
with constellation.soc.CanHaveGlobalNoC // Support instantiating a global NoC interconnect
{
@@ -46,7 +48,6 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
}
class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l)
with testchipip.CanHaveTraceIOModuleImp
with sifive.blocks.devices.i2c.HasPeripheryI2CModuleImp
with sifive.blocks.devices.pwm.HasPeripheryPWMModuleImp
with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp

View File

@@ -2,7 +2,7 @@ package chipyard
import chisel3._
import chisel3.util._
import chisel3.experimental.{IntParam, StringParam, IO}
import chisel3.experimental.{IntParam, StringParam}
import org.chipsalliance.cde.config._
import freechips.rocketchip.subsystem._
@@ -77,14 +77,15 @@ case class SpikeTileAttachParams(
}
case class SpikeTileParams(
hartId: Int = 0,
tileId: Int = 0,
val core: SpikeCoreParams = SpikeCoreParams(),
icacheParams: ICacheParams = ICacheParams(nWays = 32),
dcacheParams: DCacheParams = DCacheParams(nWays = 32),
tcmParams: Option[MasterPortParams] = None // tightly coupled memory
) extends InstantiableTileParams[SpikeTile]
{
val name = Some("spike_tile")
val baseName = "spike_tile"
val uniqueName = s"${baseName}_$tileId"
val beuAddr = None
val blockerCtrlAddr = None
val btb = None
@@ -92,7 +93,7 @@ case class SpikeTileParams(
val dcache = Some(dcacheParams)
val icache = Some(icacheParams)
val clockSinkParams = ClockSinkParameters()
def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): SpikeTile = {
def instantiate(crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): SpikeTile = {
new SpikeTile(this, crossing, lookup)
}
}
@@ -106,11 +107,11 @@ class SpikeTile(
with SourcesExternalNotifications
{
// Private constructor ensures altered LazyModule.p is used implicitly
def this(params: SpikeTileParams, crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) =
def this(params: SpikeTileParams, crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) =
this(params, crossing.crossingType, lookup, p)
// Required TileLink nodes
val intOutwardNode = IntIdentityNode()
val intOutwardNode = None
val masterNode = visibilityNode
val slaveNode = TLIdentityNode()
@@ -129,21 +130,21 @@ class SpikeTile(
}
ResourceBinding {
Resource(cpuDevice, "reg").bind(ResourceAddress(hartId))
Resource(cpuDevice, "reg").bind(ResourceAddress(tileId))
}
val icacheNode = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
sourceId = IdRange(0, 1),
name = s"Core ${staticIdForMetadataUseOnly} ICache")))))
name = s"Core ${tileId} ICache")))))
val dcacheNode = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = s"Core ${staticIdForMetadataUseOnly} DCache",
name = s"Core ${tileId} DCache",
sourceId = IdRange(0, tileParams.dcache.get.nMSHRs),
supportsProbe = TransferSizes(p(CacheBlockBytes), p(CacheBlockBytes)))))))
val mmioNode = TLClientNode((Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = s"Core ${staticIdForMetadataUseOnly} MMIO",
name = s"Core ${tileId} MMIO",
sourceId = IdRange(0, 1),
requestFifo = true))))))
@@ -313,7 +314,7 @@ class SpikeBlackBox(
}
class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
val tileParams = outer.tileParams
// We create a bundle here and decode the interrupt.
val int_bundle = Wire(new TileInterrupts())
outer.decodeCoreInterrupts(int_bundle)
@@ -337,7 +338,7 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
// then the DTM-based bringup with SimDTM will be used. This isn't required to be
// true, but it usually is
val useDTM = p(ExportDebug).protocols.contains(DMI)
val spike = Module(new SpikeBlackBox(hartId, isaDTS, tileParams.core.nPMPs,
val spike = Module(new SpikeBlackBox(outer.tileId, outer.isaDTS, tileParams.core.nPMPs,
tileParams.icache.get.nSets, tileParams.icache.get.nWays,
tileParams.dcache.get.nSets, tileParams.dcache.get.nWays,
tileParams.dcache.get.nMSHRs,
@@ -467,19 +468,21 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
}
}
class WithNSpikeCores(n: Int = 1, tileParams: SpikeTileParams = SpikeTileParams(),
overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
class WithNSpikeCores(n: Int = 1, tileParams: SpikeTileParams = SpikeTileParams()
) extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => {
// Calculate the next available hart ID (since hart ID cannot be duplicated)
val prev = up(TilesLocated(InSubsystem), site)
val idOffset = overrideIdOffset.getOrElse(prev.size)
val idOffset = up(NumTiles)
// Create TileAttachParams for every core to be instantiated
(0 until n).map { i =>
SpikeTileAttachParams(
tileParams = tileParams.copy(hartId = i + idOffset)
tileParams = tileParams.copy(tileId = i + idOffset)
)
} ++ prev
}
case NumTiles => up(NumTiles) + n
})
class WithSpikeTCM extends Config((site, here, up) => {
@@ -492,5 +495,5 @@ class WithSpikeTCM extends Config((site, here, up) => {
)))
}
case ExtMem => None
case BankedL2Key => up(BankedL2Key).copy(nBanks = 0)
case SubsystemBankedCoherenceKey => up(SubsystemBankedCoherenceKey).copy(nBanks = 0)
})

View File

@@ -24,12 +24,12 @@ import freechips.rocketchip.amba.axi4._
import boom.common.{BoomTile}
import testchipip.{CanHavePeripheryTLSerial, SerialTLKey}
import testchipip.serdes.{CanHavePeripheryTLSerial, SerialTLKey}
trait CanHaveHTIF { this: BaseSubsystem =>
// Advertise HTIF if system can communicate with fesvr
if (this match {
case _: CanHavePeripheryTLSerial if p(SerialTLKey).nonEmpty => true
case _: CanHavePeripheryTLSerial if (p(SerialTLKey).size != 0) => true
case _: HasPeripheryDebug if (!p(DebugModuleKey).isEmpty && p(ExportDebug).dmi) => true
case _ => false
}) {
@@ -71,18 +71,24 @@ trait CanHaveChosenInDTS { this: BaseSubsystem =>
}
class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
with HasTiles
with HasPeripheryDebug
with CanHaveHTIF
with CanHaveChosenInDTS
with InstantiatesHierarchicalElements
with HasTileNotificationSinks
with HasTileInputConstants
with CanHavePeripheryCLINT
with CanHavePeripheryPLIC
with HasPeripheryDebug
with HasHierarchicalElementsRootContext
with HasHierarchicalElements
with CanHaveHTIF
with CanHaveChosenInDTS
{
def coreMonitorBundles = tiles.map {
def coreMonitorBundles = totalTiles.values.map {
case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle
case b: BoomTile => b.module.core.coreMonitorBundle
}.toList
// No-tile configs have to be handled specially.
if (tiles.size == 0) {
if (totalTiles.size == 0) {
// no PLIC, so sink interrupts to nowhere
require(!p(PLICKey).isDefined)
val intNexus = IntNexusNode(sourceFn = x => x.head, sinkFn = x => x.head)
@@ -90,16 +96,12 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
intSink := intNexus :=* ibus.toPLIC
// avoids a bug when there are no interrupt sources
ibus.fromAsync := NullIntSource()
ibus { ibus.fromAsync := NullIntSource() }
// Need to have at least 1 driver to the tile notification sinks
tileHaltXbarNode := IntSourceNode(IntSourcePortSimple())
tileWFIXbarNode := IntSourceNode(IntSourcePortSimple())
tileCeaseXbarNode := IntSourceNode(IntSourcePortSimple())
// Sink reset vectors to nowhere
val resetVectorSink = BundleBridgeSink[UInt](Some(() => UInt(28.W)))
resetVectorSink := tileResetVectorNode
}
// Relying on [[TLBusWrapperConnection]].driveClockFromMaster for
@@ -107,7 +109,7 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
// ClockGroup. This makes it impossible to determine which clocks are driven
// by which bus based on the member names, which is problematic when there is
// a rational crossing between two buses. Instead, provide all bus clocks
// directly from the asyncClockGroupsNode in the subsystem to ensure bus
// directly from the allClockGroupsNode in the subsystem to ensure bus
// names are always preserved in the top-level clock names.
//
// For example, using a RationalCrossing between the Sbus and Cbus, and
@@ -116,12 +118,12 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
// Conversly, if an async crossing is used, they instead receive names of the
// form "subsystem_cbus_[0-9]*". The assignment below provides the latter names in all cases.
Seq(PBUS, FBUS, MBUS, CBUS).foreach { loc =>
tlBusWrapperLocationMap.lift(loc).foreach { _.clockGroupNode := asyncClockGroupsNode }
tlBusWrapperLocationMap.lift(loc).foreach { _.clockGroupNode := allClockGroupsNode }
}
override lazy val module = new ChipyardSubsystemModuleImp(this)
}
class ChipyardSubsystemModuleImp[+L <: ChipyardSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer)
with HasTilesModuleImp
with HasHierarchicalElementsRootContextModuleImp
{
}

View File

@@ -32,13 +32,6 @@ class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) }
val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) }
// If there is no bootrom, the tile reset vector bundle will be tied to zero
if (bootROM.isEmpty) {
val fakeResetVectorSourceNode = BundleBridgeSource[UInt]()
InModuleBody { fakeResetVectorSourceNode.bundle := 0.U }
tileResetVectorNexusNode := fakeResetVectorSourceNode
}
override lazy val module = new ChipyardSystemModule(this)
}

View File

@@ -65,7 +65,7 @@ class TestSuiteHelper
*/
def addGenericTestSuites(tiles: Seq[TileParams])(implicit p: Parameters) = {
val xlen = p(XLen)
tiles.find(_.hartId == 0).map { tileParams =>
tiles.find(_.tileId == 0).map { tileParams =>
val coreParams = tileParams.core
val vm = coreParams.useVM
val env = if (vm) List("p","v") else List("p")

View File

@@ -0,0 +1,27 @@
package chipyard.clocking
import chisel3._
import org.chipsalliance.cde.config.{Parameters, Field, Config}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.util._
import freechips.rocketchip.tile._
import freechips.rocketchip.prci._
case object ClockTapKey extends Field[Boolean](true)
trait CanHaveClockTap { this: BaseSubsystem =>
require(!p(SubsystemDriveClockGroupsFromIO), "Subsystem must not drive clocks from IO")
val clockTapNode = Option.when(p(ClockTapKey)) {
val clockTap = ClockSinkNode(Seq(ClockSinkParameters(name=Some("clock_tap"))))
clockTap := ClockGroup() := allClockGroupsNode
clockTap
}
val clockTapIO = clockTapNode.map { node => InModuleBody {
val clock_tap = IO(Output(Clock()))
clock_tap := node.in.head._1.clock
clock_tap
}}
}

View File

@@ -2,47 +2,36 @@ package chipyard.clocking
import chisel3._
import chisel3.util._
import chipyard.iobinders.{OverrideLazyIOBinder, GetSystemParameters, IOCellKey}
import chipyard.iobinders._
import freechips.rocketchip.prci._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.tilelink._
import barstools.iocell.chisel._
class ClockWithFreq(val freqMHz: Double) extends Bundle {
val clock = Clock()
}
// This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate
// the requested clocks. This also adds TileLink ClockDivider and ClockSelector
// blocks, which allow memory-mapped control of clock division, and clock muxing
// between the FakePLL and the slow off-chip clock
// Note: This will not simulate properly with firesim
class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
// Unsetting enable will prevent the divider/selector from actually modifying the clock,
// while preserving the address map. Unsetting enable should only be done for RTL
// simulators (Verilator) which do not model reset properly
class WithPLLSelectorDividerClockGenerator(enable: Boolean = true) extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => {
// Connect the implicit clock
implicit val p = GetSystemParameters(system)
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
system.connectImplicitClockSinkNode(implicitClockSinkNode)
InModuleBody {
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
}
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(system.prciParams.slaveWhere)
val baseAddress = system.prciParams.baseAddress
val clockDivider = system.prci_ctrl_domain { LazyModule(new TLClockDivider (baseAddress + 0x20000, tlbus.beatBytes)) }
val clockSelector = system.prci_ctrl_domain { LazyModule(new TLClockSelector(baseAddress + 0x30000, tlbus.beatBytes)) }
val clockDivider = system.prci_ctrl_domain { LazyModule(new TLClockDivider (baseAddress + 0x20000, tlbus.beatBytes, enable=enable)) }
val clockSelector = system.prci_ctrl_domain { LazyModule(new TLClockSelector(baseAddress + 0x30000, tlbus.beatBytes, enable=enable)) }
val pllCtrl = system.prci_ctrl_domain { LazyModule(new FakePLLCtrl (baseAddress + 0x40000, tlbus.beatBytes)) }
clockDivider.tlNode := system.prci_ctrl_domain { TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := system.prci_ctrl_bus.get }
clockSelector.tlNode := system.prci_ctrl_domain { TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := system.prci_ctrl_bus.get }
pllCtrl.tlNode := system.prci_ctrl_domain { TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := system.prci_ctrl_bus.get }
system.allClockGroupsNode := clockDivider.clockNode := clockSelector.clockNode
system.chiptopClockGroupsNode := clockDivider.clockNode := clockSelector.clockNode
// Connect all other requested clocks
val slowClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
@@ -58,13 +47,13 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
pllCtrlSink := pllCtrl.ctrlNode
InModuleBody {
val clock_wire = Wire(Input(new ClockWithFreq(100)))
val clock_wire = Wire(Input(Clock()))
val reset_wire = Wire(Input(AsyncReset()))
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
slowClockSource.out.unzip._1.map { o =>
o.clock := clock_wire.clock
o.clock := clock_wire
o.reset := reset_wire
}
@@ -79,31 +68,20 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
o.reset := reset_wire
}
(Seq(clock_io, reset_io), clockIOCell ++ resetIOCell)
(Seq(ClockPort(() => clock_io, 100), ResetPort(() => reset_io)), clockIOCell ++ resetIOCell)
}
}
})
// This passes all clocks through to the TestHarness
class WithPassthroughClockGenerator extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => {
// Connect the implicit clock
implicit val p = GetSystemParameters(system)
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
system.connectImplicitClockSinkNode(implicitClockSinkNode)
InModuleBody {
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
}
// This aggregate node should do nothing
val clockGroupAggNode = ClockGroupAggregateNode("fake")
val clockGroupsSourceNode = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
system.allClockGroupsNode := clockGroupAggNode := clockGroupsSourceNode
system.chiptopClockGroupsNode := clockGroupAggNode := clockGroupsSourceNode
InModuleBody {
val reset_io = IO(Input(AsyncReset()))
@@ -114,12 +92,21 @@ class WithPassthroughClockGenerator extends OverrideLazyIOBinder({
require(m.take.isDefined, s"""Clock ${m.name.get} has no requested frequency
|Clocks: ${edge.sink.members.map(_.name.get)}""".stripMargin)
val freq = m.take.get.freqMHz
val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}")
b.clock := clock_io.clock
val clock_io = IO(Input(Clock())).suggestName(s"clock_${m.name.get}")
b.clock := clock_io
b.reset := reset_io
clock_io
ClockPort(() => clock_io, freq)
}.toSeq
((clock_ios :+ reset_io), Nil)
((clock_ios :+ ResetPort(() => reset_io)), Nil)
}
}
})
class WithClockTapIOCells extends OverrideIOBinder({
(system: CanHaveClockTap) => {
system.clockTapIO.map { tap =>
val (clock_tap_io, clock_tap_cell) = IOCell.generateIOFromSignal(tap.getWrappedValue, "clock_tap")
(Seq(ClockTapPort(() => clock_tap_io)), clock_tap_cell)
}.getOrElse((Nil, Nil))
}
})

View File

@@ -2,7 +2,7 @@ package chipyard.clocking
import chisel3._
import chisel3.util._
import chisel3.experimental.{Analog, IO}
import chisel3.experimental.Analog
import org.chipsalliance.cde.config._
import freechips.rocketchip.subsystem._

View File

@@ -51,7 +51,7 @@ object FrequencyUtils {
require(!requestedOutputs.contains(0.0))
val requestedFreqs = requestedOutputs.map(_.freqMHz)
val fastestFreq = requestedFreqs.max
require(fastestFreq <= maximumAllowableFreqMHz)
require(fastestFreq <= maximumAllowableFreqMHz, s"Fastest Freq $fastestFreq > Max Freq $maximumAllowableFreqMHz")
val candidateFreqs =
Seq.tabulate(Math.ceil(maximumAllowableFreqMHz / fastestFreq).toInt)(i => (i + 1) * fastestFreq)

View File

@@ -14,7 +14,8 @@ import freechips.rocketchip.util._
import freechips.rocketchip.tile._
import freechips.rocketchip.prci._
import testchipip.{TLTileResetCtrl, ClockGroupFakeResetSynchronizer}
import testchipip.boot.{TLTileResetCtrl}
import testchipip.clocking.{ClockGroupFakeResetSynchronizer}
case class ChipyardPRCIControlParams(
slaveWhere: TLBusWrapperLocation = CBUS,
@@ -29,15 +30,14 @@ case class ChipyardPRCIControlParams(
case object ChipyardPRCIControlKey extends Field[ChipyardPRCIControlParams](ChipyardPRCIControlParams())
trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
require(p(SubsystemDriveAsyncClockGroupsKey).isEmpty, "Subsystem asyncClockGroups must be undriven")
trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesHierarchicalElements =>
require(!p(SubsystemDriveClockGroupsFromIO), "Subsystem allClockGroups cannot be driven from implicit clocks")
val prciParams = p(ChipyardPRCIControlKey)
// Set up clock domain
private val tlbus = locateTLBusWrapper(prciParams.slaveWhere)
val prci_ctrl_domain = LazyModule(new ClockSinkDomain(name=Some("chipyard-prci-control")))
prci_ctrl_domain.clockNode := tlbus.fixedClockNode
val prci_ctrl_domain = tlbus.generateSynchronousDomain.suggestName("chipyard_prcictrl_domain")
val prci_ctrl_bus = Option.when(prciParams.generatePRCIXBar) { prci_ctrl_domain { TLXbar() } }
prci_ctrl_bus.foreach(xbar => tlbus.coupleTo("prci_ctrl") { (xbar
@@ -48,29 +48,13 @@ trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
// Aggregate all the clock groups into a single node
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
val allClockGroupsNode = ClockGroupEphemeralNode()
// There are two "sets" of clocks which must be dealt with
// 1. The implicit clock from the subsystem. RC is moving away from depending on this
// clock, but some modules still use it. Since the implicit clock sink node
// is created in the ChipTop (the hierarchy wrapping the subsystem), this function
// is provided to allow connecting that clock to the clock aggregator. This function
// should be called in the ChipTop context
def connectImplicitClockSinkNode(sink: ClockSinkNode) = {
val implicitClockGrouper = this { ClockGroup() }
(sink
:= implicitClockGrouper
:= aggregator)
}
// 2. The rest of the diplomatic clocks in the subsystem are routed to this asyncClockGroupsNode
// The diplomatic clocks in the subsystem are routed to this allClockGroupsNode
val clockNamePrefixer = ClockGroupNamePrefixer()
(asyncClockGroupsNode
(allClockGroupsNode
:*= clockNamePrefixer
:*= aggregator)
// Once all the clocks are gathered in the aggregator node, several steps remain
// 1. Assign frequencies to any clock groups which did not specify a frequency.
// 2. Combine duplicated clock groups (clock groups which physically should be in the same clock domain)
@@ -91,7 +75,7 @@ trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
} }
val tileResetSetter = Option.when(prciParams.enableTileResetSetting) { prci_ctrl_domain {
val reset_setter = LazyModule(new TileResetSetter(prciParams.baseAddress + 0x10000, tlbus.beatBytes,
tile_prci_domains.map(_.tile_reset_domain.clockNode.portParams(0).name.get), Nil))
tile_prci_domains.map(_._2.tile_reset_domain.clockNode.portParams(0).name.get).toSeq, Nil))
reset_setter.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := prci_ctrl_bus.get
reset_setter
} }
@@ -115,11 +99,14 @@ RTL SIMULATORS, NAMELY VERILATOR.
""" + Console.RESET)
}
// The chiptopClockGroupsNode shouuld be what ClockBinders attach to
val chiptopClockGroupsNode = ClockGroupEphemeralNode()
(aggregator
:= frequencySpecifier
:= clockGroupCombiner
:= resetSynchronizer
:= tileClockGater.map(_.clockNode).getOrElse(ClockGroupEphemeralNode()(ValName("temp")))
:= tileResetSetter.map(_.clockNode).getOrElse(ClockGroupEphemeralNode()(ValName("temp")))
:= allClockGroupsNode)
:= chiptopClockGroupsNode)
}

View File

@@ -11,15 +11,31 @@ import freechips.rocketchip.util._
import freechips.rocketchip.prci._
import freechips.rocketchip.util.ElaborationArtefacts
import testchipip._
import testchipip.clocking._
// This module adds a TileLink memory-mapped clock divider to the clock graph
// The output clock/reset pairs from this module should be synchronized later
class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit p: Parameters) extends LazyModule {
// If enable is unset, this will not divide the clock
// DO NOT unset enable for VLSI, or prototyping flows. The disable feature is a work around for
// some RTL simulators which do not simulate the reset synchronization properly
class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8, enable: Boolean = true)(implicit p: Parameters) extends LazyModule {
val device = new SimpleDevice(s"clk-div-ctrl", Nil)
val clockNode = ClockGroupIdentityNode()
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
if (!enable) println(Console.RED + s"""
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WARNING:
YOU ARE USING THE TLCLOCKDIVIDER IN
"DISABLED" MODE. THIS SHOULD ONLY BE DONE
FOR RTL SIMULATION
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
""" + Console.RESET)
lazy val module = new LazyModuleImp(this) {
require (clockNode.out.size == 1)
val sources = clockNode.in.head._1.member.data.toSeq
@@ -38,20 +54,28 @@ class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit
val reg = Module(new AsyncResetRegVec(w=divBits, init=0))
println(s"${(address+i*4).toString(16)}: Clock domain $sinkName divider")
val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl)))
val divider = Module(new ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl)))
divider.io.clockIn := sources(i).clock
// busReset is expected to be high for a long time, since reset will take a while to propagate
// to the TL bus. While reset is propagating, make sure we propagate a fast, undivided clock
// by setting divisor=0. The divisor signal into the ClockDividerOrPass is synchronized internally
divider.io.divisor := Mux(busReset.asBool, 0.U, reg.io.q)
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset
sinks(i)._2.clock := divider.io.clockOut
// Note this is not synchronized to the output clock, which takes time to appear
// so this is still asyncreset
// Stretch the reset for 40 cycles, to give enough time to reset any downstream
// digital logic
sinks(i)._2.reset := ResetStretcher(sources(i).clock, asyncReset, 40).asAsyncReset
if (enable) {
sinks(i)._2.clock := divider.io.clockOut
// Note this is not synchronized to the output clock, which takes time to appear
// so this is still asyncreset
// Stretch the reset for 40 cycles, to give enough time to reset any downstream
// digital logic
sinks(i)._2.reset := ResetStretcher(sources(i).clock, asyncReset, 40).asAsyncReset
} else {
// WARNING: THIS IS FOR RTL SIMULATION ONLY
sinks(i)._2.clock := sources(i).clock
sinks(i)._2.reset := sources(i).reset
}
reg
}

View File

@@ -11,7 +11,7 @@ import freechips.rocketchip.util._
import freechips.rocketchip.prci._
import freechips.rocketchip.util.ElaborationArtefacts
import testchipip._
import testchipip.clocking._
case class ClockSelNode()(implicit valName: ValName)
extends MixedNexusNode(ClockImp, ClockGroupImp)(
@@ -21,12 +21,30 @@ case class ClockSelNode()(implicit valName: ValName)
// This module adds a TileLink memory-mapped clock mux for each downstream clock domain
// in the clock graph. The output clock/reset should be synchronized downstream
class TLClockSelector(address: BigInt, beatBytes: Int)(implicit p: Parameters) extends LazyModule {
// If enable is unset, this will always pass through the 0'th clock
// DO NOT unset enable for VLSI, or prototyping flows. The disable feature is a work around for
// some RTL simulators which do not simulate the reset synchronization properly
class TLClockSelector(address: BigInt, beatBytes: Int, enable: Boolean = true)(implicit p: Parameters) extends LazyModule {
val device = new SimpleDevice("clk-sel-ctrl", Nil)
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
val clockNode = ClockSelNode()
if (!enable) println(Console.RED + s"""
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WARNING:
YOU ARE USING THE TLCLOCKSELECTOR IN
"DISABLED" MODE. THIS SHOULD ONLY BE DONE
FOR RTL SIMULATION
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
""" + Console.RESET)
lazy val module = new LazyModuleImp(this) {
val asyncReset = clockNode.in.map(_._1).map(_.reset).toSeq(0)
val clocks = clockNode.in.map(_._1).map(_.clock)
@@ -40,13 +58,18 @@ class TLClockSelector(address: BigInt, beatBytes: Int)(implicit p: Parameters) e
sel := reg.io.q
println(s"${(address+i*4).toString(16)}: Clock domain $sinkName clock mux")
val mux = testchipip.ClockMutexMux(clocks).suggestName(s"${sinkName}_clkmux")
val mux = ClockMutexMux(clocks).suggestName(s"${sinkName}_clkmux")
mux.io.sel := sel
mux.io.resetAsync := asyncReset.asAsyncReset
sinks(i).clock := mux.io.clockOut
// Stretch the reset for 20 cycles, to give time to reset any downstream digital logic
sinks(i).reset := ResetStretcher(clocks(0), asyncReset, 20).asAsyncReset
if (enable) {
sinks(i).clock := mux.io.clockOut
// Stretch the reset for 20 cycles, to give time to reset any downstream digital logic
sinks(i).reset := ResetStretcher(clocks(0), asyncReset, 20).asAsyncReset
} else {
// WARNING: THIS IS FOR RTL SIMULATION ONLY
sinks(i).clock := clocks(0)
sinks(i).reset := asyncReset
}
reg
}
tlNode.regmap((0 until sinks.size).map { i =>

View File

@@ -2,7 +2,7 @@ package chipyard.clocking
import chisel3._
import chisel3.util._
import chisel3.experimental.{Analog, IO}
import chisel3.experimental.Analog
import org.chipsalliance.cde.config._
import freechips.rocketchip.subsystem._

View File

@@ -2,7 +2,7 @@ package chipyard.clocking
import chisel3._
import chisel3.util._
import chisel3.experimental.{Analog, IO}
import chisel3.experimental.Analog
import org.chipsalliance.cde.config._
import freechips.rocketchip.subsystem._

View File

@@ -15,15 +15,18 @@ class AbstractConfig extends Config(
new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present
new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled
new chipyard.harness.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM
new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
new chipyard.harness.WithSimJTAGDebug ++ // add SimJTAG if JTAG for debug exposed
new chipyard.harness.WithSimDMI ++ // add SimJTAG if DMI exposed
new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present
new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled
new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled
new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present
new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present
new chipyard.harness.WithCustomBootPinPlusArg ++ // drive custom-boot pin with a plusarg, if custom-boot-pin is present
new chipyard.harness.WithDriveChipIdPin ++ // drive chip id pin from harness binder, if chip id pin is present
new chipyard.harness.WithSimUARTToUARTTSI ++ // connect a SimUART to the UART-TSI port
new chipyard.harness.WithClockAndResetFromHarness ++ // all Clock/Reset I/O in ChipTop should be driven by harnessClockInstantiator
new chipyard.harness.WithClockFromHarness ++ // all Clock I/O in ChipTop should be driven by harnessClockInstantiator
new chipyard.harness.WithResetFromHarness ++ // reset controlled by harness
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // generate clocks in harness with unsynthesizable ClockSourceAtFreqMHz
// The IOBinders instantiate ChipTop IOs to match desired digital IOs
@@ -32,11 +35,14 @@ class AbstractConfig extends Config(
new chipyard.iobinders.WithDebugIOCells ++
new chipyard.iobinders.WithUARTIOCells ++
new chipyard.iobinders.WithGPIOCells ++
new chipyard.iobinders.WithSPIIOCells ++
new chipyard.iobinders.WithSPIFlashIOCells ++
new chipyard.iobinders.WithExtInterruptIOCells ++
new chipyard.iobinders.WithChipIdIOCells ++
new chipyard.iobinders.WithCustomBootPin ++
// The "punchthrough" IOBInders below don't generate IOCells, as these interfaces shouldn't really be mapped to ASIC IO
// Instead, they directly pass through the DigitalTop ports to ports in the ChipTop
new chipyard.iobinders.WithI2CPunchthrough ++
new chipyard.iobinders.WithSPIIOPunchthrough ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithAXI4MMIOPunchthrough ++
new chipyard.iobinders.WithTLMemPunchthrough ++
@@ -47,22 +53,33 @@ class AbstractConfig extends Config(
new chipyard.iobinders.WithUARTTSIPunchthrough ++
new chipyard.iobinders.WithNMITiedOff ++
// By default, punch out IOs to the Harness
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("sbus", "mbus", "pbus", "fbus", "cbus", "implicit"), Seq("tile"))) ++
new chipyard.clocking.WithClockTapIOCells ++ // Default generate a clock tapio
new chipyard.clocking.WithPassthroughClockGenerator ++ // Default punch out IOs to the Harness
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", // Default merge all the bus clocks
Seq("sbus", "mbus", "pbus", "fbus", "cbus", "obus", "implicit", "clock_tap"), Seq("tile"))) ++
new chipyard.config.WithPeripheryBusFrequency(500.0) ++ // Default 500 MHz pbus
new chipyard.config.WithControlBusFrequency(500.0) ++ // Default 500 MHz cbus
new chipyard.config.WithMemoryBusFrequency(500.0) ++ // Default 500 MHz mbus
new chipyard.config.WithControlBusFrequency(500.0) ++ // Default 500 MHz cbus
new chipyard.config.WithSystemBusFrequency(500.0) ++ // Default 500 MHz sbus
new chipyard.config.WithFrontBusFrequency(500.0) ++ // Default 500 MHz fbus
new chipyard.config.WithOffchipBusFrequency(500.0) ++ // Default 500 MHz obus
new testchipip.WithCustomBootPin ++ // add a custom-boot-pin to support pin-driven boot address
new testchipip.WithBootAddrReg ++ // add a boot-addr-reg for configurable boot address
new testchipip.WithSerialTLClientIdBits(4) ++ // support up to 1 << 4 simultaneous requests from serialTL port
new testchipip.WithSerialTLWidth(32) ++ // fatten the serialTL interface to improve testing performance
new testchipip.WithDefaultSerialTL ++ // use serialized tilelink port to external serialadapter/harnessRAM
new testchipip.boot.WithCustomBootPin ++ // add a custom-boot-pin to support pin-driven boot address
new testchipip.boot.WithBootAddrReg ++ // add a boot-addr-reg for configurable boot address
new testchipip.serdes.WithSerialTL(Seq( // add a serial-tilelink interface
testchipip.serdes.SerialTLParams(
client = Some(testchipip.serdes.SerialTLClientParams()), // serial-tilelink interface will master the FBUS, and support 4 idBits
phyParams = testchipip.serdes.ExternalSyncSerialParams(width=32) // serial-tilelink interface with 32 lanes
)
)) ++
new testchipip.soc.WithMbusScratchpad(base = 0x08000000, // add 64 KiB on-chip scratchpad
size = 64 * 1024) ++
new chipyard.config.WithDebugModuleAbstractDataWords(8) ++ // increase debug module data capacity
new chipyard.config.WithBootROM ++ // use default bootrom
new chipyard.config.WithUART ++ // add a UART
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
new chipyard.config.WithNoSubsystemClockIO ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ // Default 1 memory channels
new freechips.rocketchip.subsystem.WithClockGateModel ++ // add default EICG_wrapper clock gate model

View File

@@ -3,7 +3,7 @@ package chipyard
import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.subsystem.{MBUS, SBUS}
import testchipip.{OBUS}
import testchipip.soc.{OBUS}
// A simple config demonstrating how to set up a basic chip in Chipyard
class ChipLikeRocketConfig extends Config(
@@ -22,16 +22,26 @@ class ChipLikeRocketConfig extends Config(
//==================================
// Set up I/O
//==================================
new testchipip.WithSerialTLWidth(4) ++ // 4bit wide Serialized TL interface to minimize IO
new testchipip.WithSerialTLBackingMemory ++ // Configure the off-chip memory accessible over serial-tl as backing memory
new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 4L) ++ // 4GB max external memory
new testchipip.serdes.WithSerialTL(Seq(testchipip.serdes.SerialTLParams( // 1 serial tilelink port
manager = Some(testchipip.serdes.SerialTLManagerParams( // port acts as a manager of offchip memory
memParams = Seq(testchipip.serdes.ManagerRAMParams( // 4 GB of off-chip memory
address = BigInt("80000000", 16),
size = BigInt("100000000", 16)
)),
isMemoryDevice = true
)),
client = Some(testchipip.serdes.SerialTLClientParams()), // Allow an external manager to probe this chip
phyParams = testchipip.serdes.ExternalSyncSerialParams(width=4) // 4-bit bidir interface, sync'd to an external clock
))) ++
new freechips.rocketchip.subsystem.WithNoMemPort ++ // Remove axi4 mem port
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ // 1 memory channel
//==================================
// Set up buses
//==================================
new testchipip.WithOffchipBusClient(MBUS) ++ // offchip bus connects to MBUS, since the serial-tl needs to provide backing memory
new testchipip.WithOffchipBus ++ // attach a offchip bus, since the serial-tl will master some external tilelink memory
new testchipip.soc.WithOffchipBusClient(MBUS) ++ // offchip bus connects to MBUS, since the serial-tl needs to provide backing memory
new testchipip.soc.WithOffchipBus ++ // attach a offchip bus, since the serial-tl will master some external tilelink memory
//==================================
// Set up clock./reset
@@ -43,6 +53,10 @@ class ChipLikeRocketConfig extends Config(
new chipyard.config.AbstractConfig)
class FlatChipTopChipLikeRocketConfig extends Config(
new chipyard.example.WithFlatChipTop ++
new chipyard.ChipLikeRocketConfig)
// A simple config demonstrating a "bringup prototype" to bringup the ChipLikeRocketconfig
class ChipBringupHostConfig extends Config(
//=============================
@@ -56,17 +70,23 @@ class ChipBringupHostConfig extends Config(
//=============================
// Setup the SerialTL side on the bringup device
//=============================
new testchipip.WithSerialTLWidth(4) ++ // match width with the chip
new testchipip.WithSerialTLMem(base = 0x0, size = 0x80000000L, // accessible memory of the chip that doesn't come from the tethered host
idBits = 4, isMainMemory = false) ++ // This assumes off-chip mem starts at 0x8000_0000
new testchipip.WithSerialTLClockDirection(provideClockFreqMHz = Some(75)) ++ // bringup board drives the clock for the serial-tl receiver on the chip, use 75MHz clock
new testchipip.serdes.WithSerialTL(Seq(testchipip.serdes.SerialTLParams(
manager = Some(testchipip.serdes.SerialTLManagerParams(
memParams = Seq(testchipip.serdes.ManagerRAMParams( // Bringup platform can access all memory from 0 to DRAM_BASE
address = BigInt("00000000", 16),
size = BigInt("80000000", 16)
))
)),
client = Some(testchipip.serdes.SerialTLClientParams()), // Allow chip to access this device's memory (DRAM)
phyParams = testchipip.serdes.InternalSyncSerialParams(width=4, freqMHz = 75) // bringup platform provides the clock
))) ++
//============================
// Setup bus topology on the bringup system
//============================
new testchipip.WithOffchipBusClient(SBUS, // offchip bus hangs off the SBUS
new testchipip.soc.WithOffchipBusClient(SBUS, // offchip bus hangs off the SBUS
blockRange = AddressSet.misaligned(0x80000000L, (BigInt(1) << 30) * 4)) ++ // offchip bus should not see the main memory of the testchip, since that can be accessed directly
new testchipip.WithOffchipBus ++ // offchip bus
new testchipip.soc.WithOffchipBus ++ // offchip bus
//=============================
// Set up memory on the bringup system
@@ -76,7 +96,7 @@ class ChipBringupHostConfig extends Config(
//=============================
// Generate the TSI-over-UART side of the bringup system
//=============================
new testchipip.WithUARTTSIClient(initBaudRate = BigInt(921600)) ++ // nonstandard baud rate to improve performance
new testchipip.tsi.WithUARTTSIClient(initBaudRate = BigInt(921600)) ++ // nonstandard baud rate to improve performance
//=============================
// Set up clocks of the bringup system
@@ -85,6 +105,9 @@ class ChipBringupHostConfig extends Config(
new chipyard.config.WithFrontBusFrequency(75.0) ++ // run all buses of this system at 75 MHz
new chipyard.config.WithMemoryBusFrequency(75.0) ++
new chipyard.config.WithPeripheryBusFrequency(75.0) ++
new chipyard.config.WithSystemBusFrequency(75.0) ++
new chipyard.config.WithControlBusFrequency(75.0) ++
new chipyard.config.WithOffchipBusFrequency(75.0) ++
// Base is the no-cores config
new chipyard.NoCoresConfig)
@@ -103,5 +126,9 @@ class TetheredChipLikeRocketConfig extends Config(
class VerilatorCITetheredChipLikeRocketConfig extends Config(
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // use absolute freqs for sims in the harness
new chipyard.harness.WithMultiChipSerialTL(0, 1) ++ // connect the serial-tl ports of the chips together
new chipyard.harness.WithMultiChip(0, new chipyard.config.WithNoResetSynchronizers ++ new ChipLikeRocketConfig) ++
new chipyard.harness.WithMultiChip(0, // These fragments remove all troublesome
new chipyard.clocking.WithPLLSelectorDividerClockGenerator(enable=false) ++ // clocking features from the design
new chipyard.iobinders.WithDebugIOCells(syncReset = false) ++
new chipyard.config.WithNoResetSynchronizers ++
new ChipLikeRocketConfig) ++
new chipyard.harness.WithMultiChip(1, new ChipBringupHostConfig))

View File

@@ -0,0 +1,47 @@
package chipyard
import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.diplomacy.{AddressSet}
import freechips.rocketchip.subsystem.{SBUS}
import testchipip.soc.{OBUS}
// ------------------------------------------------
// Configs demonstrating chip-to-chip communication
// ------------------------------------------------
// Simple design which exposes a second serial-tl port that can connect to another instance of itself
class SymmetricChipletRocketConfig extends Config(
new testchipip.soc.WithChipIdPin ++ // Add pin to identify chips
new chipyard.harness.WithSerialTLTiedOff(tieoffs=Some(Seq(1))) ++ // Tie-off the chip-to-chip link in single-chip sims
new testchipip.serdes.WithSerialTL(Seq(
testchipip.serdes.SerialTLParams( // 0th serial-tl is chip-to-bringup-fpga
client = Some(testchipip.serdes.SerialTLClientParams()), // bringup serial-tl acts only as a client
phyParams = testchipip.serdes.ExternalSyncSerialParams() // bringup serial-tl is sync'd to external clock
),
testchipip.serdes.SerialTLParams( // 1st serial-tl is chip-to-chip
client = Some(testchipip.serdes.SerialTLClientParams()), // chip-to-chip serial-tl acts as a client
manager = Some(testchipip.serdes.SerialTLManagerParams( // chip-to-chip serial-tl managers other chip's memory
memParams = Seq(testchipip.serdes.ManagerRAMParams(
address = 0,
size = 1L << 32,
)),
slaveWhere = OBUS
)),
phyParams = testchipip.serdes.SourceSyncSerialParams() // chip-to-chip serial-tl is symmetric source-sync'd
))
) ++
new testchipip.soc.WithOffchipBusClient(SBUS, // obus provides path to other chip's memory
blockRange = Seq(AddressSet(0, (1L << 32) - 1)), // The lower 4GB is mapped to this chip
replicationBase = Some(1L << 32) // The upper 4GB goes off-chip
) ++
new testchipip.soc.WithOffchipBus ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// Simulates 2X of the SymmetricChipletRocketConfig in a multi-sim config
class MultiSimSymmetricChipletRocketConfig extends Config(
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++
new chipyard.harness.WithMultiChipSerialTL(chip0=0, chip1=1, chip0portId=1, chip1portId=1) ++
new chipyard.harness.WithMultiChip(0, new SymmetricChipletRocketConfig) ++
new chipyard.harness.WithMultiChip(1, new SymmetricChipletRocketConfig)
)

View File

@@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
// DOC include start: FFTRocketConfig
class FFTRocketConfig extends Config(
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC
new chipyard.harness.WithDontTouchChipTopPorts(false) ++ // TODO: hack around dontTouch not working in SFC
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
@@ -59,7 +59,7 @@ class LargeNVDLARocketConfig extends Config(
new chipyard.config.AbstractConfig)
class ManyMMIOAcceleratorRocketConfig extends Config(
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC
new chipyard.harness.WithDontTouchChipTopPorts(false) ++ // TODO: hack around dontTouch not working in SFC
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
new chipyard.example.WithStreamingFIR ++ // use top with tilelink-controlled streaming FIR

View File

@@ -0,0 +1,41 @@
package chipyard
import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
// ------------------------------------------------------------
// Configs which demonstrate modifying the uncore memory system
// ------------------------------------------------------------
class SimAXIRocketConfig extends Config(
new chipyard.harness.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory, instead of default SimDRAM
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class GB1MemoryRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithExtMemSize((1<<30) * 1L) ++ // use 1GB simulated external memory
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include start: mbusscratchpadrocket
class MbusScratchpadOnlyRocketConfig extends Config(
new testchipip.soc.WithMbusScratchpad(banks=2, partitions=2) ++ // add 2 partitions of 2 banks mbus backing scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove offchip mem port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include end: mbusscratchpadrocket
class SbusScratchpadRocketConfig extends Config(
new testchipip.soc.WithSbusScratchpad(base=0x70000000L, banks=4) ++ // add 4 banks sbus scratchpad
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class SbusBypassRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithExtMemSbusBypass ++ // Add bypass path to access DRAM incoherently through an address alias
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class QuadChannelRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNMemoryChannels(4) ++ // 4 AXI4 channels
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)

View File

@@ -6,6 +6,7 @@ import freechips.rocketchip.subsystem.{SBUS, MBUS}
import constellation.channel._
import constellation.routing._
import constellation.router._
import constellation.topology._
import constellation.noc._
import constellation.soc.{GlobalNoCParams}
@@ -45,7 +46,7 @@ import scala.collection.immutable.ListMap
* | SI:Core 2 | SO:system[0] | SO:system[1] | SI:Core 3 |
* |(0)___________|(1)___________|(2)___________|(3)___________|
* | FBus | Core 0 | Core 1 | Pbus |
* | SI:serial-tl | SI:Core 0 | SI:Core 1 | SO:pbus |
* | SI:serial_tl | SI:Core 0 | SI:Core 1 | SO:pbus |
* |______________|______________|______________|______________|
*
* |(0)___________|(1)___________|(2)___________|(3)___________|
@@ -62,37 +63,37 @@ import scala.collection.immutable.ListMap
*/
// DOC include start: MultiNoCConfig
class MultiNoCConfig extends Config(
new constellation.soc.WithCbusNoC(constellation.protocol.TLNoCParams(
new constellation.soc.WithCbusNoC(constellation.protocol.SimpleTLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap(
"serial-tl" -> 0),
"serial_tl" -> 0),
outNodeMapping = ListMap(
"error" -> 1, "l2[0]" -> 2, "pbus" -> 3, "plic" -> 4,
"error" -> 1, "ctrls[0]" -> 2, "pbus" -> 3, "plic" -> 4,
"clint" -> 5, "dmInner" -> 6, "bootrom" -> 7, "clock" -> 8)),
NoCParams(
topology = TerminalRouter(BidirectionalLine(9)),
channelParamGen = (a, b) => UserChannelParams(Seq.fill(5) { UserVirtualChannelParams(4) }),
routingRelation = NonblockingVirtualSubnetworksRouting(TerminalRouterRouting(BidirectionalLineRouting()), 5, 1))
)) ++
new constellation.soc.WithMbusNoC(constellation.protocol.TLNoCParams(
new constellation.soc.WithMbusNoC(constellation.protocol.SimpleTLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap(
"L2 InclusiveCache[0]" -> 1, "L2 InclusiveCache[1]" -> 2,
"L2 InclusiveCache[2]" -> 5, "L2 InclusiveCache[3]" -> 6),
outNodeMapping = ListMap(
"system[0]" -> 0, "system[1]" -> 3, "system[2]" -> 4 , "system[3]" -> 7,
"serdesser" -> 0)),
"serial_tl_0" -> 0)),
NoCParams(
topology = TerminalRouter(BidirectionalTorus1D(8)),
channelParamGen = (a, b) => UserChannelParams(Seq.fill(10) { UserVirtualChannelParams(4) }),
routingRelation = BlockingVirtualSubnetworksRouting(TerminalRouterRouting(BidirectionalTorus1DShortestRouting()), 5, 2))
)) ++
new constellation.soc.WithSbusNoC(constellation.protocol.TLNoCParams(
new constellation.soc.WithSbusNoC(constellation.protocol.SimpleTLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap(
"Core 0" -> 1, "Core 1" -> 2, "Core 2" -> 4 , "Core 3" -> 7,
"Core 4" -> 8, "Core 5" -> 11, "Core 6" -> 13, "Core 7" -> 14,
"serial-tl" -> 0),
"serial_tl" -> 0),
outNodeMapping = ListMap(
"system[0]" -> 5, "system[1]" -> 6, "system[2]" -> 9, "system[3]" -> 10,
"pbus" -> 3)),
@@ -133,7 +134,7 @@ class MultiNoCConfig extends Config(
* Core 6 | SI | Core 6 | 16
* Core 7 | SI | Core 7 | 18
* Core 8 | SI | Core 8 | 19
* fbus | SI | serial-tl | 9
* fbus | SI | serial_tl | 9
* pbus | SO | pbus | 4
* L2 0 | SO | system[0] | 0
* L2 1 | SO | system[1] | 2
@@ -145,7 +146,7 @@ class MultiNoCConfig extends Config(
* L2 3 | MI | Cache[3] | 6
* DRAM 0 | MO | system[0] | 3
* DRAM 1 | MO | system[1] | 5
* extram | MO | serdesser | 9
* spad | MO | ram[0] | 9
*/
// DOC include start: SharedNoCConfig
class SharedNoCConfig extends Config(
@@ -162,24 +163,24 @@ class SharedNoCConfig extends Config(
BidirectionalLineRouting()))), 10, 2)
)
)) ++
new constellation.soc.WithMbusNoC(constellation.protocol.TLNoCParams(
new constellation.soc.WithMbusNoC(constellation.protocol.GlobalTLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap(
"Cache[0]" -> 0, "Cache[1]" -> 2, "Cache[2]" -> 8, "Cache[3]" -> 6),
outNodeMapping = ListMap(
"system[0]" -> 3, "system[1]" -> 5,
"serdesser" -> 9))
), true) ++
new constellation.soc.WithSbusNoC(constellation.protocol.TLNoCParams(
"ram[0]" -> 9))
)) ++
new constellation.soc.WithSbusNoC(constellation.protocol.GlobalTLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap(
"serial-tl" -> 9, "Core 0" -> 2,
"serial_tl" -> 9, "Core 0" -> 2,
"Core 1" -> 10, "Core 2" -> 11, "Core 3" -> 13, "Core 4" -> 14,
"Core 5" -> 15, "Core 6" -> 16, "Core 7" -> 18, "Core 8" -> 19),
outNodeMapping = ListMap(
"system[0]" -> 0, "system[1]" -> 2, "system[2]" -> 8, "system[3]" -> 6,
"pbus" -> 4))
), true) ++
)) ++
new freechips.rocketchip.subsystem.WithNBigCores(8) ++
new freechips.rocketchip.subsystem.WithNBanks(4) ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(2) ++
@@ -187,8 +188,9 @@ class SharedNoCConfig extends Config(
)
// DOC include end: SharedNoCConfig
// This Config implements a simple ring interconnect for the system bus
class SbusRingNoCConfig extends Config(
new constellation.soc.WithSbusNoC(constellation.protocol.TLNoCParams(
new constellation.soc.WithSbusNoC(constellation.protocol.SplitACDxBETLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap(
"Core 0" -> 0,
@@ -199,19 +201,67 @@ class SbusRingNoCConfig extends Config(
"Core 5" -> 5,
"Core 6" -> 6,
"Core 7" -> 7,
"serial-tl" -> 8),
"serial_tl" -> 8),
outNodeMapping = ListMap(
"system[0]" -> 9,
"system[1]" -> 10,
"system[2]" -> 11,
"system[3]" -> 12,
"pbus" -> 8)), // TSI is on the pbus, so serial-tl and pbus should be on the same node
NoCParams(
acdNoCParams = NoCParams(
topology = UnidirectionalTorus1D(13),
channelParamGen = (a, b) => UserChannelParams(Seq.fill(10) { UserVirtualChannelParams(4) }),
routingRelation = NonblockingVirtualSubnetworksRouting(UnidirectionalTorus1DDatelineRouting(), 5, 2))
channelParamGen = (a, b) => UserChannelParams(Seq.fill(6) { UserVirtualChannelParams(4) }),
routingRelation = NonblockingVirtualSubnetworksRouting(UnidirectionalTorus1DDatelineRouting(), 3, 2)),
beNoCParams = NoCParams(
topology = UnidirectionalTorus1D(13),
channelParamGen = (a, b) => UserChannelParams(Seq.fill(4) { UserVirtualChannelParams(1) }),
routingRelation = NonblockingVirtualSubnetworksRouting(UnidirectionalTorus1DDatelineRouting(), 2, 2))
)) ++
new freechips.rocketchip.subsystem.WithNBigCores(8) ++
new freechips.rocketchip.subsystem.WithNBanks(4) ++
new chipyard.config.AbstractConfig
)
// This config integrates a mesh interconnect for the system bus, and divides the system bus
// tilelink messages across two isolated interconnects
class SbusMeshNoCConfig extends Config(
new constellation.soc.WithSbusNoC(constellation.protocol.SplitACDxBETLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap(
"Core 0 " -> 0,
"Core 1 " -> 1,
"Core 2 " -> 2,
"Core 3 " -> 3,
"Core 4 " -> 4,
"Core 5 " -> 7,
"Core 6 " -> 8,
"Core 7 " -> 11,
"Core 8 " -> 12,
"Core 9 " -> 13,
"Core 10 " -> 14,
"Core 11 " -> 15,
"serial-tl" -> 0),
outNodeMapping = ListMap(
"system[0]" -> 5,
"system[1]" -> 6,
"system[2]" -> 9,
"system[3]" -> 10,
"pbus" -> 0)), // TSI is on the pbus, so serial-tl and pbus should be on the same node
acdNoCParams = NoCParams(
topology = Mesh2D(4, 4),
channelParamGen = (a, b) => UserChannelParams(Seq.fill(3) { UserVirtualChannelParams(3) }, unifiedBuffer = false),
routerParams = (i) => UserRouterParams(combineRCVA=true, combineSAST=true),
routingRelation = NonblockingVirtualSubnetworksRouting(Mesh2DDimensionOrderedRouting(), 3, 1)),
beNoCParams = NoCParams(
topology = Mesh2D(4, 4),
channelParamGen = (a, b) => UserChannelParams(Seq.fill(2) { UserVirtualChannelParams(3) }, unifiedBuffer = false),
routerParams = (i) => UserRouterParams(combineRCVA=true, combineSAST=true),
routingRelation = NonblockingVirtualSubnetworksRouting(Mesh2DDimensionOrderedRouting(), 2, 1)),
beDivision = 4
)) ++
new freechips.rocketchip.subsystem.WithNBigCores(12) ++
new freechips.rocketchip.subsystem.WithNBanks(4) ++
new chipyard.config.WithSystemBusWidth(128) ++
new chipyard.config.AbstractConfig
)

View File

@@ -4,8 +4,9 @@ import org.chipsalliance.cde.config.{Config}
// A empty config with no cores. Useful for testing
class NoCoresConfig extends Config(
new testchipip.WithNoBootAddrReg ++
new testchipip.WithNoCustomBootPin ++
new testchipip.soc.WithNoScratchpads ++
new testchipip.boot.WithNoBootAddrReg ++
new testchipip.boot.WithNoCustomBootPin ++
new chipyard.config.WithNoCLINT ++
new chipyard.config.WithNoBootROM ++
new chipyard.config.WithBroadcastManager ++

View File

@@ -22,13 +22,13 @@ class SmallSPIFlashRocketConfig extends Config(
class SimBlockDeviceRocketConfig extends Config(
new chipyard.harness.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice
new testchipip.WithBlockDevice ++ // add block-device module to peripherybus
new testchipip.iceblk.WithBlockDevice ++ // add block-device module to peripherybus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class BlockDeviceModelRocketConfig extends Config(
new chipyard.harness.WithBlockDeviceModel ++ // drive block-device IOs with a BlockDeviceModel
new testchipip.WithBlockDevice ++ // add block-device module to periphery bus
new testchipip.iceblk.WithBlockDevice ++ // add block-device module to periphery bus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
@@ -52,8 +52,11 @@ class MMIORocketConfig extends Config(
new chipyard.config.AbstractConfig)
class LBWIFRocketConfig extends Config(
new testchipip.WithSerialTLMem(isMainMemory=true) ++ // set lbwif memory base to DRAM_BASE, use as main memory
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove AXI4 backing memory
new chipyard.config.WithOffchipBusFrequency(500) ++
new testchipip.soc.WithOffchipBusClient(MBUS) ++
new testchipip.soc.WithOffchipBus ++
new testchipip.serdes.WithSerialTLMem(isMainMemory=true) ++ // set lbwif memory base to DRAM_BASE, use as main memory
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove AXI4 backing memory
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
@@ -66,10 +69,10 @@ class dmiRocketConfig extends Config(
// DOC include end: DmiRocket
class ManyPeripheralsRocketConfig extends Config(
new testchipip.WithBlockDevice ++ // add block-device module to peripherybus
new testchipip.WithOffchipBusClient(MBUS) ++ // OBUS provides backing memory to the MBUS
new testchipip.WithOffchipBus ++ // OBUS must exist for serial-tl to master off-chip memory
new testchipip.WithSerialTLMem(isMainMemory=true) ++ // set lbwif memory base to DRAM_BASE, use as main memory
new testchipip.iceblk.WithBlockDevice ++ // add block-device module to peripherybus
new testchipip.soc.WithOffchipBusClient(MBUS) ++ // OBUS provides backing memory to the MBUS
new testchipip.soc.WithOffchipBus ++ // OBUS must exist for serial-tl to master off-chip memory
new testchipip.serdes.WithSerialTLMem(isMainMemory=true) ++ // set lbwif memory base to DRAM_BASE, use as main memory
new chipyard.harness.WithSimSPIFlashModel(true) ++ // add the SPI flash model in the harness (read-only)
new chipyard.harness.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice
new chipyard.config.WithSPIFlash ++ // add the SPI flash controller
@@ -79,14 +82,9 @@ class ManyPeripheralsRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class QuadChannelRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNMemoryChannels(4) ++ // 4 AXI4 channels
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class UARTTSIRocketConfig extends Config(
new chipyard.harness.WithSerialTLTiedOff ++
new testchipip.WithUARTTSIClient ++
new testchipip.tsi.WithUARTTSIClient ++
new chipyard.config.WithMemoryBusFrequency(10) ++
new chipyard.config.WithFrontBusFrequency(10) ++
new chipyard.config.WithPeripheryBusFrequency(10) ++

View File

@@ -56,3 +56,9 @@ class HwachaLargeBoomConfig extends Config(
new boom.common.WithNLargeBooms(1) ++
new chipyard.config.WithSystemBusWidth(128) ++
new chipyard.config.AbstractConfig)
class AES256ECBRocketConfig extends Config(
new aes.WithAES256ECBAccel ++ // use Caliptra AES 256 ECB accelerator
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.WithSystemBusWidth(256) ++
new chipyard.config.AbstractConfig)

View File

@@ -2,6 +2,7 @@ package chipyard
import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
import freechips.rocketchip.subsystem.{InCluster}
// --------------
// Rocket Configs
@@ -12,18 +13,14 @@ class RocketConfig extends Config(
new chipyard.config.AbstractConfig)
class TinyRocketConfig extends Config(
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO FIX: Don't dontTouch the ports
new chipyard.harness.WithDontTouchChipTopPorts(false) ++ // TODO FIX: Don't dontTouch the ports
new testchipip.soc.WithNoScratchpads ++ // All memory is the Rocket TCMs
new freechips.rocketchip.subsystem.WithIncoherentBusTopology ++ // use incoherent bus topology
new freechips.rocketchip.subsystem.WithNBanks(0) ++ // remove L2$
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove backing memory
new freechips.rocketchip.subsystem.With1TinyCore ++ // single tiny rocket-core
new chipyard.config.AbstractConfig)
class SimAXIRocketConfig extends Config(
new chipyard.harness.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory, instead of default SimDRAM
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class QuadRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(4) ++ // quad-core (4 RocketTiles)
new chipyard.config.AbstractConfig)
@@ -38,14 +35,10 @@ class RV32RocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class GB1MemoryRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithExtMemSize((1<<30) * 1L) ++ // use 1GB simulated external memory
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include start: l1scratchpadrocket
class ScratchpadOnlyRocketConfig extends Config(
new chipyard.config.WithL2TLBs(0) ++
new testchipip.soc.WithNoScratchpads ++ // remove subsystem scratchpads, confusingly named, does not remove the L1D$ scratchpads
new freechips.rocketchip.subsystem.WithNBanks(0) ++
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove offchip mem port
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use rocket l1 DCache scratchpad as base phys mem
@@ -65,26 +58,12 @@ class L1ScratchpadRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include start: mbusscratchpadrocket
class MbusScratchpadOnlyRocketConfig extends Config(
new testchipip.WithMbusScratchpad(banks=2, partitions=2) ++ // add 2 partitions of 2 banks mbus backing scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove offchip mem port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include end: mbusscratchpadrocket
class SbusScratchpadRocketConfig extends Config(
new testchipip.WithSbusScratchpad(base=0x70000000L, banks=4) ++ // add 4 banks sbus backing scratchpad
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class MulticlockRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithAsynchronousRocketTiles(3, 3) ++ // Add async crossings between RocketTile and uncore
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
// Frequency specifications
new chipyard.config.WithTileFrequency(1000.0) ++ // Matches the maximum frequency of U540
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore" , Seq("sbus", "cbus", "implicit"), Nil),
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore" , Seq("sbus", "cbus", "implicit", "clock_tap"), Nil),
("periphery", Seq("pbus", "fbus"), Nil)) ++
new chipyard.config.WithSystemBusFrequency(500.0) ++ // Matches the maximum frequency of U540
new chipyard.config.WithMemoryBusFrequency(500.0) ++ // Matches the maximum frequency of U540
@@ -93,10 +72,10 @@ class MulticlockRocketConfig extends Config(
new chipyard.config.WithFbusToSbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between FBUS and SBUS
new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS
new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS
new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS
new chipyard.config.AbstractConfig)
class CustomIOChipTopRocketConfig extends Config(
new chipyard.example.WithBrokenOutUARTIO ++
new chipyard.example.WithCustomChipTop ++
new chipyard.example.WithCustomIOCells ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
@@ -110,3 +89,10 @@ class PrefetchingRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNonblockingL1(2) ++ // non-blocking L1D$, L1 prefetching only works with non-blocking L1D$
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
new chipyard.config.AbstractConfig)
class ClusteredRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(4, location=InCluster(1)) ++
new freechips.rocketchip.subsystem.WithNBigCores(4, location=InCluster(0)) ++
new freechips.rocketchip.subsystem.WithCluster(1) ++
new freechips.rocketchip.subsystem.WithCluster(0) ++
new chipyard.config.AbstractConfig)

View File

@@ -7,7 +7,8 @@ import org.chipsalliance.cde.config.{Config}
class Sodor1StageConfig extends Config(
// Create a Sodor 1-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.soc.WithNoScratchpads ++ // No scratchpads
new testchipip.serdes.WithSerialTLWidth(32) ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -16,7 +17,8 @@ class Sodor1StageConfig extends Config(
class Sodor2StageConfig extends Config(
// Create a Sodor 2-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.soc.WithNoScratchpads ++ // No scratchpads
new testchipip.serdes.WithSerialTLWidth(32) ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -25,7 +27,8 @@ class Sodor2StageConfig extends Config(
class Sodor3StageConfig extends Config(
// Create a Sodor 1-stage core with two ports
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.soc.WithNoScratchpads ++ // No scratchpads
new testchipip.serdes.WithSerialTLWidth(32) ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -34,7 +37,8 @@ class Sodor3StageConfig extends Config(
class Sodor3StageSinglePortConfig extends Config(
// Create a Sodor 3-stage core with one ports (instruction and data memory access controlled by arbiter)
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.soc.WithNoScratchpads ++ // No scratchpads
new testchipip.serdes.WithSerialTLWidth(32) ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -43,7 +47,8 @@ class Sodor3StageSinglePortConfig extends Config(
class Sodor5StageConfig extends Config(
// Create a Sodor 5-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.soc.WithNoScratchpads ++ // No scratchpads
new testchipip.serdes.WithSerialTLWidth(32) ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -52,7 +57,8 @@ class Sodor5StageConfig extends Config(
class SodorUCodeConfig extends Config(
// Construct a Sodor microcode-based single-bus core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.soc.WithNoScratchpads ++ // No scratchpads
new testchipip.serdes.WithSerialTLWidth(32) ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++

View File

@@ -43,7 +43,7 @@ class SpikeUltraFastDevicesConfig extends Config(
new chipyard.harness.WithSimBlockDevice ++
new chipyard.harness.WithLoopbackNIC ++
new icenet.WithIceNIC ++
new testchipip.WithBlockDevice ++
new testchipip.iceblk.WithBlockDevice ++
new chipyard.WithSpikeTCM ++
new chipyard.WithNSpikeCores(1) ++

View File

@@ -7,14 +7,16 @@ class AbstractTraceGenConfig extends Config(
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++
new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.harness.WithTraceGenSuccess ++
new chipyard.harness.WithClockAndResetFromHarness ++
new chipyard.harness.WithClockFromHarness ++
new chipyard.harness.WithResetFromHarness ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("sbus", "implicit"), Nil)) ++
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("sbus"), Nil)) ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new chipyard.config.WithNoSubsystemClockIO ++
new chipyard.config.WithMemoryBusFrequency(1000.0) ++
new chipyard.config.WithControlBusFrequency(1000.0) ++
new chipyard.config.WithSystemBusFrequency(1000.0) ++
new chipyard.config.WithPeripheryBusFrequency(1000.0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
@@ -42,6 +44,6 @@ class NonBlockingTraceGenL2Config extends Config(
class NonBlockingTraceGenL2RingConfig extends Config(
new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++
new testchipip.WithRingSystemBus ++
new testchipip.soc.WithRingSystemBus ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new AbstractTraceGenConfig)

View File

@@ -77,7 +77,7 @@ class TutorialSha3BlackBoxConfig extends Config(
// Tutorial Phase 5: Map a multicore heterogeneous SoC with multiple cores and memory-mapped accelerators
class TutorialNoCConfig extends Config(
new chipyard.iobinders.WithDontTouchIOBinders(false) ++
new chipyard.harness.WithDontTouchChipTopPorts(false) ++
// Try changing the dimensions of the Mesh topology
new constellation.soc.WithGlobalNoC(constellation.soc.GlobalNoCParams(
NoCParams(
@@ -90,14 +90,14 @@ class TutorialNoCConfig extends Config(
// The inNodeMapping and outNodeMapping values are the physical identifiers of
// routers on the topology to map the agents to. Try changing these to any
// value within the range [0, topology.nNodes)
new constellation.soc.WithPbusNoC(constellation.protocol.TLNoCParams(
new constellation.soc.WithPbusNoC(constellation.protocol.GlobalTLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap("Core" -> 7),
outNodeMapping = ListMap(
"pbus" -> 8, "uart" -> 9, "control" -> 10, "gcd" -> 11,
"writeQueue[0]" -> 0, "writeQueue[1]" -> 1, "tailChain[0]" -> 2))
), true) ++
new constellation.soc.WithSbusNoC(constellation.protocol.TLNoCParams(
)) ++
new constellation.soc.WithSbusNoC(constellation.protocol.GlobalTLNoCParams(
constellation.protocol.DiplomaticNetworkNodeMapping(
inNodeMapping = ListMap(
"Core 0" -> 0, "Core 1" -> 1,
@@ -105,7 +105,7 @@ class TutorialNoCConfig extends Config(
outNodeMapping = ListMap(
"system[0]" -> 3, "system[1]" -> 4, "system[2]" -> 5, "system[3]" -> 6,
"pbus" -> 7))
), true) ++
)) ++
new chipyard.example.WithGCD ++
new chipyard.harness.WithLoopbackNIC ++
new icenet.WithIceNIC ++

View File

@@ -13,13 +13,14 @@ import freechips.rocketchip.tilelink.{HasTLBusParams}
import chipyard._
import chipyard.clocking._
import testchipip.soc.{OffchipBusKey}
// The default RocketChip BaseSubsystem drives its diplomatic clock graph
// with the implicit clocks of Subsystem. Don't do that, instead we extend
// the diplomacy graph upwards into the ChipTop, where we connect it to
// our clock drivers
class WithNoSubsystemDrivenClocks extends Config((site, here, up) => {
case SubsystemDriveAsyncClockGroupsKey => None
class WithNoSubsystemClockIO extends Config((site, here, up) => {
case SubsystemDriveClockGroupsFromIO => false
})
/**
@@ -103,18 +104,29 @@ class WithFrontBusFrequency(freqMHz: Double) extends Config((site, here, up) =>
class WithControlBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
case ControlBusKey => up(ControlBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
})
class WithOffchipBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
case OffchipBusKey => up(OffchipBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
})
class WithRationalMemoryBusCrossing extends WithSbusToMbusCrossingType(RationalCrossing(Symmetric))
class WithAsynchrousMemoryBusCrossing extends WithSbusToMbusCrossingType(AsynchronousCrossing())
// Remove the tile clock gaters in this system
class WithNoTileClockGaters extends Config((site, here, up) => {
case ChipyardPRCIControlKey => up(ChipyardPRCIControlKey).copy(enableTileClockGating = false)
})
// Remove the tile reset control blocks in this system
class WithNoTileResetSetters extends Config((site, here, up) => {
case ChipyardPRCIControlKey => up(ChipyardPRCIControlKey).copy(enableTileResetSetting = false)
})
// Remove the global reset synchronizers in this system
class WithNoResetSynchronizers extends Config((site, here, up) => {
case ChipyardPRCIControlKey => up(ChipyardPRCIControlKey).copy(enableResetSynchronizers = false)
})
// Remove any ClockTap ports in this system
class WithNoClockTap extends Config((site, here, up) => {
case ClockTapKey => false
})

View File

@@ -29,7 +29,7 @@ import chipyard.{ExtTLMem}
* @param hang the power-on reset vector, i.e. the program counter will be set to this value on reset
* @param contentFileName the path to the BootROM image
*/
class WithBootROM(address: BigInt = 0x10000, size: Int = 0x10000, hang: BigInt = 0x10040) extends Config((site, here, up) => {
class WithBootROM(address: BigInt = 0x10000, size: Int = 0x10000, hang: BigInt = 0x10000) extends Config((site, here, up) => {
case BootROMLocated(x) => up(BootROMLocated(x), site)
.map(_.copy(
address = address,

View File

@@ -12,15 +12,15 @@ import gemmini._
import chipyard.{TestSuitesKey, TestSuiteHelper}
/**
* Map from a hartId to a particular RoCC accelerator
* Map from a tileId to a particular RoCC accelerator
*/
case object MultiRoCCKey extends Field[Map[Int, Seq[Parameters => LazyRoCC]]](Map.empty[Int, Seq[Parameters => LazyRoCC]])
/**
* Config fragment to enable different RoCCs based on the hartId
* Config fragment to enable different RoCCs based on the tileId
*/
class WithMultiRoCC extends Config((site, here, up) => {
case BuildRoCC => site(MultiRoCCKey).getOrElse(site(TileKey).hartId, Nil)
case BuildRoCC => site(MultiRoCCKey).getOrElse(site(TileKey).tileId, Nil)
})
/**
@@ -39,7 +39,7 @@ class WithMultiRoCCFromBuildRoCC(harts: Int*) extends Config((site, here, up) =>
*
* For ex:
* Core 0, 1, 2, 3 have been defined earlier
* with hartIds of 0, 1, 2, 3 respectively
* with tileIds of 0, 1, 2, 3 respectively
* And you call WithMultiRoCCHwacha(0,1)
* Then Core 0 and 1 will get a Hwacha
*

View File

@@ -1,12 +1,17 @@
package chipyard.config
import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.subsystem.{SystemBusKey, BankedL2Key, CoherenceManagerWrapper}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.diplomacy.{DTSTimebase}
import sifive.blocks.inclusivecache.{InclusiveCachePortParameters}
// Replaces the L2 with a broadcast manager for maintaining coherence
class WithBroadcastManager extends Config((site, here, up) => {
case BankedL2Key => up(BankedL2Key, site).copy(coherenceManager = CoherenceManagerWrapper.broadcastManager)
case SubsystemBankedCoherenceKey => up(SubsystemBankedCoherenceKey, site).copy(coherenceManager = CoherenceManagerWrapper.broadcastManager)
})
class WithBroadcastParams(params: BroadcastParams) extends Config((site, here, up) => {
case BroadcastKey => params
})
class WithSystemBusWidth(bitWidth: Int) extends Config((site, here, up) => {
@@ -16,3 +21,13 @@ class WithSystemBusWidth(bitWidth: Int) extends Config((site, here, up) => {
class WithDTSTimebase(freqMHz: BigInt) extends Config((site, here, up) => {
case DTSTimebase => freqMHz
})
// Adds buffers on the interior of the inclusive LLC, to improve PD
class WithInclusiveCacheInteriorBuffer(buffer: InclusiveCachePortParameters = InclusiveCachePortParameters.full) extends Config((site, here, up) => {
case InclusiveCacheKey => up(InclusiveCacheKey).copy(bufInnerInterior=buffer, bufOuterInterior=buffer)
})
// Adds buffers on the exterior of the inclusive LLC, to improve PD
class WithInclusiveCacheExteriorBuffer(buffer: InclusiveCachePortParameters = InclusiveCachePortParameters.full) extends Config((site, here, up) => {
case InclusiveCacheKey => up(InclusiveCacheKey).copy(bufInnerExterior=buffer, bufOuterExterior=buffer)
})

View File

@@ -11,7 +11,7 @@ import boom.common.{BoomTileAttachParams}
import cva6.{CVA6TileAttachParams}
import sodor.common.{SodorTileAttachParams}
import ibex.{IbexTileAttachParams}
import testchipip._
import testchipip.cosim.{TracePortKey, TracePortParams}
import barf.{TilePrefetchingMasterPortParams}
class WithL2TLBs(entries: Int) extends Config((site, here, up) => {
@@ -66,10 +66,19 @@ class WithNPMPs(n: Int = 8) extends Config((site, here, up) => {
}
})
class WithRocketCacheRowBits(rowBits: Int = 64) extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem)) map {
case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(
dcache = tp.tileParams.dcache.map(_.copy(rowBits = rowBits)),
icache = tp.tileParams.icache.map(_.copy(rowBits = rowBits))
))
}
})
class WithRocketICacheScratchpad extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map {
case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(
icache = tp.tileParams.icache.map(_.copy(itimAddr = Some(0x300000 + tp.tileParams.hartId * 0x10000)))
icache = tp.tileParams.icache.map(_.copy(itimAddr = Some(0x300000 + tp.tileParams.tileId * 0x10000)))
))
}
})
@@ -77,7 +86,7 @@ class WithRocketICacheScratchpad extends Config((site, here, up) => {
class WithRocketDCacheScratchpad extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map {
case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(
dcache = tp.tileParams.dcache.map(_.copy(nSets = 32, nWays = 1, scratch = Some(0x200000 + tp.tileParams.hartId * 0x10000)))
dcache = tp.tileParams.dcache.map(_.copy(nSets = 32, nWays = 1, scratch = Some(0x200000 + tp.tileParams.tileId * 0x10000)))
))
}
})
@@ -85,14 +94,24 @@ class WithRocketDCacheScratchpad extends Config((site, here, up) => {
class WithTilePrefetchers extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map {
case tp: RocketTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy(
master = TilePrefetchingMasterPortParams(tp.tileParams.hartId, tp.crossingParams.master)))
master = TilePrefetchingMasterPortParams(tp.tileParams.tileId, tp.crossingParams.master)))
case tp: BoomTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy(
master = TilePrefetchingMasterPortParams(tp.tileParams.hartId, tp.crossingParams.master)))
master = TilePrefetchingMasterPortParams(tp.tileParams.tileId, tp.crossingParams.master)))
case tp: SodorTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy(
master = TilePrefetchingMasterPortParams(tp.tileParams.hartId, tp.crossingParams.master)))
master = TilePrefetchingMasterPortParams(tp.tileParams.tileId, tp.crossingParams.master)))
case tp: IbexTileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy(
master = TilePrefetchingMasterPortParams(tp.tileParams.hartId, tp.crossingParams.master)))
master = TilePrefetchingMasterPortParams(tp.tileParams.tileId, tp.crossingParams.master)))
case tp: CVA6TileAttachParams => tp.copy(crossingParams = tp.crossingParams.copy(
master = TilePrefetchingMasterPortParams(tp.tileParams.hartId, tp.crossingParams.master)))
master = TilePrefetchingMasterPortParams(tp.tileParams.tileId, tp.crossingParams.master)))
}
})
// Adds boundary buffers to RocketTiles, which places buffers between the caches and the TileLink interface
// This typically makes it easier to close timing
class WithRocketBoundaryBuffers(buffers: Option[RocketTileBoundaryBufferParams] = Some(RocketTileBoundaryBufferParams(true))) extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem)) map {
case tp: RocketTileAttachParams => tp.copy(tileParams=tp.tileParams.copy(
boundaryBuffers=buffers
))
}
})

View File

@@ -5,9 +5,11 @@ import chipyard.iobinders._
import org.chipsalliance.cde.config._
import freechips.rocketchip.diplomacy.{InModuleBody}
import freechips.rocketchip.subsystem.{PBUS, HasTileLinkLocations}
import barstools.iocell.chisel._
import chipyard._
import chipyard.harness.{BuildTop}
import sifive.blocks.devices.uart._
// A "custom" IOCell with additional I/O
// The IO don't do anything here in this example
@@ -63,3 +65,21 @@ class WithCustomIOCells extends Config((site, here, up) => {
class WithCustomChipTop extends Config((site, here, up) => {
case BuildTop => (p: Parameters) => new CustomChipTop()(p)
})
class WithBrokenOutUARTIO extends OverrideIOBinder({
(system: HasPeripheryUARTModuleImp) => {
val uart_txd = IO(Output(Bool()))
val uart_rxd = IO(Input(Bool()))
system.uart(0).rxd := uart_rxd
uart_txd := system.uart(0).txd
val where = PBUS // TODO fix
val bus = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where)
val freqMHz = bus.dtsFrequency.get / 1000000
(Seq(UARTPort(() => {
val uart_wire = Wire(new UARTPortIO(system.uart(0).c))
uart_wire.txd := uart_txd
uart_rxd := uart_wire.rxd
uart_wire
}, 0, freqMHz.toInt)), Nil)
}
})

View File

@@ -2,31 +2,34 @@ package chipyard.example
import chisel3._
import org.chipsalliance.cde.config.{Field, Parameters}
import org.chipsalliance.cde.config.{Config, Field, Parameters}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.prci._
import freechips.rocketchip.util._
import freechips.rocketchip.subsystem.{PBUS, HasTileLinkLocations}
import freechips.rocketchip.devices.debug.{ExportDebug, JtagDTMKey, Debug}
import freechips.rocketchip.tilelink.{TLBuffer, TLFragmenter}
import chipyard.{BuildSystem, DigitalTop}
import chipyard.harness.{BuildTop}
import chipyard.clocking._
import chipyard.iobinders.{IOCellKey, JTAGChipIO}
import chipyard.iobinders._
import barstools.iocell.chisel._
import testchipip.serdes.{SerialTLKey}
class WithFlatChipTop extends Config((site, here, up) => {
case BuildTop => (p: Parameters) => new FlatChipTop()(p)
})
// This "FlatChipTop" uses no IOBinders, so all the IO have
// to be explicitly constructed.
// This only supports the base "DigitalTop"
class FlatChipTop(implicit p: Parameters) extends LazyModule {
class FlatChipTop(implicit p: Parameters) extends LazyModule with HasChipyardPorts {
override lazy val desiredName = "ChipTop"
val system = LazyModule(p(BuildSystem)(p)).suggestName("system").asInstanceOf[DigitalTop]
//========================
// Diplomatic clock stuff
//========================
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
system.connectImplicitClockSinkNode(implicitClockSinkNode)
val tlbus = system.locateTLBusWrapper(system.prciParams.slaveWhere)
val baseAddress = system.prciParams.baseAddress
val clockDivider = system.prci_ctrl_domain { LazyModule(new TLClockDivider (baseAddress + 0x20000, tlbus.beatBytes)) }
@@ -37,7 +40,7 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule {
tlbus.coupleTo("clock-sel-ctrl") { clockSelector.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := TLBuffer() := _ }
tlbus.coupleTo("pll-ctrl") { pllCtrl.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := TLBuffer() := _ }
system.allClockGroupsNode := clockDivider.clockNode := clockSelector.clockNode
system.chiptopClockGroupsNode := clockDivider.clockNode := clockSelector.clockNode
// Connect all other requested clocks
val slowClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
@@ -56,28 +59,26 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule {
debugClockSinkNode := system.locateTLBusWrapper(p(ExportDebug).slaveWhere).fixedClockNode
def debugClockBundle = debugClockSinkNode.in.head._1
var ports: Seq[Port[_]] = Nil
override lazy val module = new FlatChipTopImpl
class FlatChipTopImpl extends LazyRawModuleImp(this) {
//=========================
// Clock/reset
//=========================
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
system.module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
val clock_wire = Wire(Input(new ClockWithFreq(80)))
val clock_wire = Wire(Input(Clock()))
val reset_wire = Wire(Input(AsyncReset()))
val (clock_pad, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
val (reset_pad, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
slowClockSource.out.unzip._1.map { o =>
o.clock := clock_wire.clock
o.clock := clock_wire
o.reset := reset_wire
}
ports = ports :+ ClockPort(() => clock_pad, 100.0)
ports = ports :+ ResetPort(() => reset_pad)
// For a real chip you should replace this ClockSourceAtFreqFromPlusArg
// with a blackbox of whatever PLL is being integrated
val fake_pll = Module(new ClockSourceAtFreqFromPlusArg("pll_freq_mhz"))
@@ -93,11 +94,13 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule {
// Custom Boot
//=========================
val (custom_boot_pad, customBootIOCell) = IOCell.generateIOFromSignal(system.custom_boot_pin.get.getWrappedValue, "custom_boot", p(IOCellKey))
ports = ports :+ CustomBootPort(() => custom_boot_pad)
//=========================
// Serialized TileLink
//=========================
val (serial_tl_pad, serialTLIOCells) = IOCell.generateIOFromSignal(system.serial_tl.get.getWrappedValue, "serial_tl", p(IOCellKey))
val (serial_tl_pad, serialTLIOCells) = IOCell.generateIOFromSignal(system.serial_tls(0).getWrappedValue, "serial_tl", p(IOCellKey))
ports = ports :+ SerialTLPort(() => serial_tl_pad, p(SerialTLKey)(0), system.serdessers(0), 0)
//=========================
// JTAG/Debug
@@ -136,12 +139,17 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule {
IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true)
}.get
ports = ports :+ JTAGPort(() => jtag_pad)
//==========================
// UART
//==========================
require(system.uarts.size == 1)
val (uart_pad, uartIOCells) = IOCell.generateIOFromSignal(system.module.uart.head, "uart_0", p(IOCellKey))
val where = PBUS // TODO fix
val bus = system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where)
val freqMHz = bus.dtsFrequency.get / 1000000
ports = ports :+ UARTPort(() => uart_pad, 0, freqMHz.toInt)
//==========================
// External interrupts (tie off)

View File

@@ -11,7 +11,10 @@ import freechips.rocketchip.util.{PlusArg}
import freechips.rocketchip.subsystem.{CacheBlockBytes}
import freechips.rocketchip.devices.debug.{SimJTAG}
import freechips.rocketchip.jtag.{JTAGIO}
import testchipip.{SerialTLKey, UARTAdapter, SimDRAM, TSIHarness, SimTSI}
import testchipip.serdes._
import testchipip.uart.{UARTAdapter}
import testchipip.dram.{SimDRAM}
import testchipip.tsi.{TSIHarness, SimTSI, SerialRAM}
import chipyard.harness.{BuildTop}
// A "flat" TestHarness that doesn't use IOBinders
@@ -30,7 +33,7 @@ class FlatTestHarness(implicit val p: Parameters) extends Module {
val clock_source = Module(new ClockSourceAtFreqFromPlusArg("slow_clk_freq_mhz"))
clock_source.io.power := true.B
clock_source.io.gate := false.B
dut.clock_pad.clock := clock_source.io.clk
dut.clock_pad := clock_source.io.clk
// Reset
dut.reset_pad := reset.asAsyncReset
@@ -39,21 +42,32 @@ class FlatTestHarness(implicit val p: Parameters) extends Module {
dut.custom_boot_pad := PlusArg("custom_boot_pin", width=1)
// Serialized TL
val sVal = p(SerialTLKey).get
val serialTLManagerParams = sVal.serialTLManagerParams.get
val sVal = p(SerialTLKey)(0)
val serialTLManagerParams = sVal.manager.get
require(serialTLManagerParams.isMemoryDevice)
withClockAndReset(clock, reset) {
val serial_bits = dut.serial_tl_pad.bits
if (DataMirror.directionOf(dut.serial_tl_pad.clock) == Direction.Input) {
dut.serial_tl_pad.clock := clock
}
val harnessRAM = TSIHarness.connectRAM(
lazyDut.system.serdesser.get,
serial_bits,
reset)
io.success := SimTSI.connect(Some(harnessRAM.module.io.tsi), clock, reset)
// Figure out which clock drives the harness TLSerdes, based on the port type
val serial_ram_clock = dut.serial_tl_pad match {
case io: InternalSyncSerialIO => io.clock_out
case io: ExternalSyncSerialIO => clock
}
dut.serial_tl_pad match {
case io: ExternalSyncSerialIO => io.clock_in := clock
case io: InternalSyncSerialIO =>
}
dut.serial_tl_pad match {
case pad: DecoupledSerialIO => {
withClockAndReset(serial_ram_clock, reset) {
// SerialRAM implements the memory regions the chip expects
val ram = Module(LazyModule(new SerialRAM(lazyDut.system.serdessers(0), p(SerialTLKey)(0))).module)
ram.io.ser.in <> pad.out
pad.in <> ram.io.ser.out
// Allow TSI to master the chip
io.success := SimTSI.connect(ram.io.tsi, serial_ram_clock, reset)
}
}
}
// JTAG

View File

@@ -13,7 +13,7 @@ import freechips.rocketchip.util.UIntIsOneOf
// DOC include start: GCD params
case class GCDParams(
address: BigInt = 0x1000,
address: BigInt = 0x4000,
width: Int = 32,
useAXI4: Boolean = false,
useBlackBox: Boolean = true)
@@ -185,7 +185,7 @@ trait CanHavePeripheryGCD { this: BaseSubsystem =>
// DOC include end: GCD lazy trait
// DOC include start: GCD imp trait
trait CanHavePeripheryGCDModuleImp extends LazyModuleImp {
trait CanHavePeripheryGCDModuleImp extends LazyRawModuleImp {
val outer: CanHavePeripheryGCD
val gcd_busy = outer.gcd match {
case Some(gcd) => {

View File

@@ -82,7 +82,7 @@ case class MyTileAttachParams(
case class MyTileParams(
name: Option[String] = Some("my_tile"),
hartId: Int = 0,
tileId: Int = 0,
trace: Boolean = false,
val core: MyCoreParams = MyCoreParams()
) extends InstantiableTileParams[MyTile]
@@ -94,9 +94,11 @@ case class MyTileParams(
val dcache: Option[DCacheParams] = Some(DCacheParams())
val icache: Option[ICacheParams] = Some(ICacheParams())
val clockSinkParams: ClockSinkParameters = ClockSinkParameters()
def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): MyTile = {
def instantiate(crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): MyTile = {
new MyTile(this, crossing, lookup)
}
val baseName = name.getOrElse("my_tile")
val uniqueName = s"${baseName}_$tileId"
}
// DOC include start: Tile class
@@ -111,11 +113,11 @@ class MyTile(
{
// Private constructor ensures altered LazyModule.p is used implicitly
def this(params: MyTileParams, crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) =
def this(params: MyTileParams, crossing: HierarchicalElementCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) =
this(params, crossing.crossingType, lookup, p)
// Require TileLink nodes
val intOutwardNode = IntIdentityNode()
val intOutwardNode = None
val masterNode = visibilityNode
val slaveNode = TLIdentityNode()
@@ -135,7 +137,7 @@ class MyTile(
}
ResourceBinding {
Resource(cpuDevice, "reg").bind(ResourceAddress(hartId))
Resource(cpuDevice, "reg").bind(ResourceAddress(tileId))
}
// TODO: Create TileLink nodes and connections here.
@@ -228,15 +230,15 @@ class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){
}
// DOC include start: Config fragment
class WithNMyCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
class WithNMyCores(n: Int = 1) extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => {
// Calculate the next available hart ID (since hart ID cannot be duplicated)
val prev = up(TilesLocated(InSubsystem), site)
val idOffset = overrideIdOffset.getOrElse(prev.size)
val idOffset = up(NumTiles)
// Create TileAttachParams for every core to be instantiated
(0 until n).map { i =>
MyTileAttachParams(
tileParams = MyTileParams(hartId = i + idOffset),
tileParams = MyTileParams(tileId = i + idOffset),
crossingParams = RocketCrossingParams()
)
} ++ prev
@@ -245,5 +247,6 @@ class WithNMyCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Con
case SystemBusKey => up(SystemBusKey, site).copy(beatBytes = 8)
// The # of instruction bits. Use maximum # of bits if your core supports both 32 and 64 bits.
case XLen => 64
case NumTiles => up(NumTiles) + n
})
// DOC include end: Config fragment

View File

@@ -199,12 +199,13 @@ class TLGenericFIRChain[T<:Data:Ring] (genIn: T, genOut: T, coeffs: => Seq[T], p
trait CanHavePeripheryStreamingFIR extends BaseSubsystem {
val streamingFIR = p(GenericFIRKey) match {
case Some(params) => {
val streamingFIR = LazyModule(new TLGenericFIRChain(
val domain = pbus.generateSynchronousDomain.suggestName("fir_domain")
val streamingFIR = domain { LazyModule(new TLGenericFIRChain(
genIn = FixedPoint(8.W, 3.BP),
genOut = FixedPoint(8.W, 3.BP),
coeffs = Seq(1.U.asFixedPoint(0.BP), 2.U.asFixedPoint(0.BP), 3.U.asFixedPoint(0.BP)),
params = params))
pbus.coupleTo("streamingFIR") { streamingFIR.mem.get := TLFIFOFixer() := TLFragmenter(pbus.beatBytes, pbus.blockBytes) := _ }
params = params)) }
pbus.coupleTo("streamingFIR") { domain { streamingFIR.mem.get := TLFIFOFixer() := TLFragmenter(pbus.beatBytes, pbus.blockBytes) } := _ }
Some(streamingFIR)
}
case None => None

View File

@@ -131,8 +131,9 @@ class TLStreamingPassthroughChain[T<:Data:Ring](params: StreamingPassthroughPara
trait CanHavePeripheryStreamingPassthrough { this: BaseSubsystem =>
val passthrough = p(StreamingPassthroughKey) match {
case Some(params) => {
val streamingPassthroughChain = LazyModule(new TLStreamingPassthroughChain(params, UInt(32.W)))
pbus.coupleTo("streamingPassthrough") { streamingPassthroughChain.mem.get := TLFIFOFixer() := TLFragmenter(pbus.beatBytes, pbus.blockBytes) := _ }
val domain = pbus.generateSynchronousDomain.suggestName("streaming_passthrough_domain")
val streamingPassthroughChain = domain { LazyModule(new TLStreamingPassthroughChain(params, UInt(32.W))) }
pbus.coupleTo("streamingPassthrough") { domain { streamingPassthroughChain.mem.get := TLFIFOFixer() := TLFragmenter(pbus.beatBytes, pbus.blockBytes)} := _ }
Some(streamingPassthroughChain)
}
case None => None

View File

@@ -6,355 +6,313 @@ import chisel3.experimental.{Analog, BaseModule, DataMirror, Direction}
import org.chipsalliance.cde.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
import freechips.rocketchip.devices.debug._
import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.system.{SimAXIMem}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.util._
import sifive.blocks.devices.gpio._
import sifive.blocks.devices.uart._
import sifive.blocks.devices.spi._
import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.devices.debug.{SimJTAG}
import barstools.iocell.chisel._
import testchipip._
import testchipip.dram.{SimDRAM}
import testchipip.tsi.{SimTSI, SerialRAM, TSI, TSIIO}
import testchipip.soc.{TestchipSimDTM}
import testchipip.spi.{SimSPIFlashModel}
import testchipip.uart.{UARTAdapter, UARTToSerial}
import testchipip.serdes._
import testchipip.iceblk.{SimBlockDevice, BlockDeviceModel}
import testchipip.cosim.{SpikeCosim}
import icenet.{NicLoopback, SimNetwork}
import chipyard._
import chipyard.clocking.{HasChipyardPRCI, ClockWithFreq}
import chipyard.iobinders.{GetSystemParameters, JTAGChipIO}
import chipyard.clocking.{HasChipyardPRCI}
import chipyard.iobinders._
import tracegen.{TraceGenSystemModuleImp}
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import scala.reflect.{ClassTag}
case object HarnessBinders extends Field[HarnessBinderMap](HarnessBinderMapDefault)
case object HarnessBinders extends Field[HarnessBinderFunction]({case _ => })
object ApplyHarnessBinders {
def apply(th: HasHarnessInstantiators, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters): Unit = {
val pm = portMap.withDefaultValue(Nil)
p(HarnessBinders).foreach { case (s, f) =>
f(sys, th, pm(s))
f(sys.module, th, pm(s))
}
def apply(th: HasHarnessInstantiators, ports: Seq[Port[_]], chipId: Int)(implicit p: Parameters): Unit = {
ports.foreach(port => p(HarnessBinders)(th, port, chipId))
}
}
// The ClassTags here are necessary to overcome issues arising from type erasure
class HarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](composer: ((T, S, Seq[U]) => Unit) => (T, S, Seq[U]) => Unit)(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: HasHarnessInstantiators, ports: Seq[Data]) => {
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, t) match {
case (th: S, system: T) => composer(upfn)(system, th, pts)
case _ =>
}
})
)
class HarnessBinder[T <: HasHarnessInstantiators, S <: Port[_]](
fn: => HarnessBinderFunction
) extends Config((site, here, up) => {
case HarnessBinders => fn orElse up(HarnessBinders)
})
class OverrideHarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](fn: => (T, S, Seq[U]) => Unit)
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => fn)
class ComposeHarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](fn: => (T, S, Seq[U]) => Unit)
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => (t, th, p) => {
upfn(t, th, p)
fn(t, th, p)
})
class WithGPIOTiedOff extends OverrideHarnessBinder({
(system: HasPeripheryGPIOModuleImp, th: HasHarnessInstantiators, ports: Seq[Analog]) => {
ports.foreach { _ <> AnalogConst(0) }
class WithGPIOTiedOff extends HarnessBinder({
case (th: HasHarnessInstantiators, port: GPIOPort, chipId: Int) => {
port.io <> AnalogConst(0)
}
})
// DOC include start: WithUARTAdapter
class WithUARTAdapter extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
UARTAdapter.connect(ports)(system.p)
class WithUARTAdapter extends HarnessBinder({
case (th: HasHarnessInstantiators, port: UARTPort, chipId: Int) => {
val div = (th.getHarnessBinderClockFreqMHz.toDouble * 1000000 / port.io.c.initBaudRate.toDouble).toInt
UARTAdapter.connect(Seq(port.io), div, false)
}
})
// DOC include end: WithUARTAdapter
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
(system: HasPeripherySPIFlashModuleImp, th: HasHarnessInstantiators, ports: Seq[SPIChipIO]) => {
SimSPIFlashModel.connect(ports, th.harnessBinderReset, rdOnly)(system.p)
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends HarnessBinder({
case (th: HasHarnessInstantiators, port: SPIFlashPort, chipId: Int) => {
val spi_mem = Module(new SimSPIFlashModel(port.params.fSize, port.spiId, rdOnly)).suggestName(s"spi_mem${port.spiId}")
spi_mem.io.sck := port.io.sck
require(port.params.csWidth == 1, "I don't know what to do with your extra CS bits. Fix me please.")
spi_mem.io.cs(0) := port.io.cs(0)
spi_mem.io.dq.zip(port.io.dq).foreach { case (x, y) => x <> y }
spi_mem.io.reset := th.harnessBinderReset
}
})
class WithSimBlockDevice extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: HasHarnessInstantiators, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { b => SimBlockDevice.connect(b.clock, th.harnessBinderReset.asBool, Some(b.bits)) }
class WithSimBlockDevice extends HarnessBinder({
case (th: HasHarnessInstantiators, port: BlockDevicePort, chipId: Int) => {
val sim_blkdev = Module(new SimBlockDevice(port.params))
sim_blkdev.io.bdev <> port.io.bits
sim_blkdev.io.clock := port.io.clock
sim_blkdev.io.reset := th.harnessBinderReset
}
})
class WithBlockDeviceModel extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: HasHarnessInstantiators, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { b => BlockDeviceModel.connect(Some(b.bits)) }
class WithBlockDeviceModel extends HarnessBinder({
case (th: HasHarnessInstantiators, port: BlockDevicePort, chipId: Int) => {
val blkdev_model = Module(new BlockDeviceModel(16, port.params))
blkdev_model.io <> port.io.bits
blkdev_model.clock := port.io.clock
blkdev_model.reset := th.harnessBinderReset
}
})
class WithLoopbackNIC extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNIC, th: HasHarnessInstantiators, ports: Seq[ClockedIO[NICIOvonly]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { n => NicLoopback.connect(Some(n.bits), p(NICKey)) }
class WithLoopbackNIC extends HarnessBinder({
case (th: HasHarnessInstantiators, port: NICPort, chipId: Int) => {
withClock(port.io.clock) { NicLoopback.connect(port.io.bits, port.params) }
}
})
class WithSimNetwork extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessInstantiators, ports: Seq[ClockedIO[NICIOvonly]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessBinderReset.asBool) }
class WithSimNetwork extends HarnessBinder({
case (th: HasHarnessInstantiators, port: NICPort, chipId: Int) => {
withClock(port.io.clock) { SimNetwork.connect(Some(port.io.bits), port.io.clock, th.harnessBinderReset.asBool) }
}
})
class WithSimAXIMem extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: HasHarnessInstantiators, 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))
Module(mem.module).suggestName("mem")
mem.io_axi4.head <> port.bits
class WithSimAXIMem extends HarnessBinder({
case (th: HasHarnessInstantiators, port: AXI4MemPort, chipId: Int) => {
val mem = LazyModule(new SimAXIMem(port.edge, size=port.params.master.size)(Parameters.empty))
withClock(port.io.clock) { Module(mem.module) }
mem.io_axi4.head <> port.io.bits
}
})
class WithBlackBoxSimMem(additionalLatency: Int = 0) extends HarnessBinder({
case (th: HasHarnessInstantiators, port: AXI4MemPort, chipId: Int) => {
// TODO FIX: This currently makes each SimDRAM contain the entire memory space
val memSize = port.params.master.size
val memBase = port.params.master.base
val lineSize = 64 // cache block size
val clockFreq = port.clockFreqMHz
val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, memBase, port.edge.bundle, chipId)).suggestName("simdram")
mem.io.clock := port.io.clock
mem.io.reset := th.harnessBinderReset.asAsyncReset
mem.io.axi <> port.io.bits
// Bug in Chisel implementation. See https://github.com/chipsalliance/chisel3/pull/1781
def Decoupled[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = {
require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.")
val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits)))
d.bits := irr.bits
d.valid := irr.valid
irr.ready := d.ready
d
}
if (additionalLatency > 0) {
withClock (port.io.clock) {
mem.io.axi.aw <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.aw))((t, _) => Queue(t, 1, pipe=true))
mem.io.axi.w <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.w ))((t, _) => Queue(t, 1, pipe=true))
port.io.bits.b <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.b ))((t, _) => Queue(t, 1, pipe=true))
mem.io.axi.ar <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.ar))((t, _) => Queue(t, 1, pipe=true))
port.io.bits.r <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.r ))((t, _) => Queue(t, 1, pipe=true))
}
}
}
})
class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
// TODO FIX: This currently makes each SimDRAM contain the entire memory space
val memSize = p(ExtMem).get.master.size
val memBase = p(ExtMem).get.master.base
val lineSize = p(CacheBlockBytes)
val clockFreq = p(MemoryBusKey).dtsFrequency.get
val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, memBase, edge.bundle)).suggestName("simdram")
mem.io.axi <> port.bits
// Bug in Chisel implementation. See https://github.com/chipsalliance/chisel3/pull/1781
def Decoupled[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = {
require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.")
val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits)))
d.bits := irr.bits
d.valid := irr.valid
irr.ready := d.ready
d
class WithSimAXIMMIO extends HarnessBinder({
case (th: HasHarnessInstantiators, port: AXI4MMIOPort, chipId: Int) => {
val mmio_mem = LazyModule(new SimAXIMem(port.edge, size = port.params.size)(Parameters.empty))
withClock(port.io.clock) { Module(mmio_mem.module).suggestName("mmio_mem") }
mmio_mem.io_axi4.head <> port.io.bits
}
})
class WithTieOffInterrupts extends HarnessBinder({
case (th: HasHarnessInstantiators, port: ExtIntPort, chipId: Int) => {
port.io := 0.U
}
})
class WithTieOffL2FBusAXI extends HarnessBinder({
case (th: HasHarnessInstantiators, port: AXI4InPort, chipId: Int) => {
port.io := DontCare
port.io.bits.aw.valid := false.B
port.io.bits.w.valid := false.B
port.io.bits.b.ready := false.B
port.io.bits.ar.valid := false.B
port.io.bits.r.ready := false.B
}
})
class WithSimJTAGDebug extends HarnessBinder({
case (th: HasHarnessInstantiators, port: JTAGPort, chipId: Int) => {
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
val jtag_wire = Wire(new JTAGIO)
jtag_wire.TDO.data := port.io.TDO
jtag_wire.TDO.driven := true.B
port.io.TCK := jtag_wire.TCK
port.io.TMS := jtag_wire.TMS
port.io.TDI := jtag_wire.TDI
val jtag = Module(new SimJTAG(tickDelay=3))
jtag.connect(jtag_wire, th.harnessBinderClock, th.harnessBinderReset.asBool, ~(th.harnessBinderReset.asBool), dtm_success)
}
})
class WithSimDMI extends HarnessBinder({
case (th: HasHarnessInstantiators, port: DMIPort, chipId: Int) => {
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
val dtm = Module(new TestchipSimDTM()(Parameters.empty)).connect(th.harnessBinderClock, th.harnessBinderReset.asBool, port.io, dtm_success)
}
})
class WithTiedOffJTAG extends HarnessBinder({
case (th: HasHarnessInstantiators, port: JTAGPort, chipId: Int) => {
port.io.TCK := true.B.asClock
port.io.TMS := true.B
port.io.TDI := true.B
}
})
class WithTiedOffDMI extends HarnessBinder({
case (th: HasHarnessInstantiators, port: DMIPort, chipId: Int) => {
port.io.dmi.req.valid := false.B
port.io.dmi.req.bits := DontCare
port.io.dmi.resp.ready := true.B
port.io.dmiClock := false.B.asClock
port.io.dmiReset := true.B
}
})
// If tieoffs is specified, a list of serial portIds to tie off
// If tieoffs is unspecified, ties off all serial ports
class WithSerialTLTiedOff(tieoffs: Option[Seq[Int]] = None) extends HarnessBinder({
case (th: HasHarnessInstantiators, port: SerialTLPort, chipId: Int) if (tieoffs.map(_.contains(port.portId)).getOrElse(true)) => {
port.io match {
case io: DecoupledSerialIO => io.out.ready := false.B; io.in.valid := false.B; io.in.bits := DontCare;
case io: SourceSyncSerialIO => {
io.clock_in := false.B.asClock
io.reset_in := false.B.asAsyncReset
io.in := DontCare
io.credit_in := DontCare
}
if (additionalLatency > 0) {
withClockAndReset (port.clock, port.reset) {
mem.io.axi.aw <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.aw))((t, _) => Queue(t, 1, pipe=true))
mem.io.axi.w <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.w ))((t, _) => Queue(t, 1, pipe=true))
port.bits.b <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.b))((t, _) => Queue(t, 1, pipe=true))
mem.io.axi.ar <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.ar))((t, _) => Queue(t, 1, pipe=true))
port.bits.r <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.r))((t, _) => Queue(t, 1, pipe=true))
}
port.io match {
case io: InternalSyncSerialIO =>
case io: ExternalSyncSerialIO => io.clock_in := false.B.asClock
case _ =>
}
}
})
class WithSimTSIOverSerialTL extends HarnessBinder({
case (th: HasHarnessInstantiators, port: SerialTLPort, chipId: Int) if (port.portId == 0) => {
port.io match {
case io: InternalSyncSerialIO =>
case io: ExternalSyncSerialIO => io.clock_in := th.harnessBinderClock
}
port.io match {
case io: DecoupledSerialIO => {
// If the port is locally synchronous (provides a clock), drive everything with that clock
// Else, drive everything with the harnes clock
val clock = port.io match {
case io: InternalSyncSerialIO => io.clock_out
case io: ExternalSyncSerialIO => th.harnessBinderClock
}
withClock(clock) {
val ram = Module(LazyModule(new SerialRAM(port.serdesser, port.params)(port.serdesser.p)).module)
ram.io.ser.in <> io.out
io.in <> ram.io.ser.out
val success = SimTSI.connect(ram.io.tsi, clock, th.harnessBinderReset, chipId)
when (success) { th.success := true.B }
}
}
mem.io.clock := port.clock
mem.io.reset := port.reset
}
}
})
class WithSimAXIMMIO extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MMIOPort, th: HasHarnessInstantiators, 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, port.reset) {
Module(mmio_mem.module).suggestName("mmio_mem")
}
mmio_mem.io_axi4.head <> port.bits
}
class WithDriveChipIdPin extends HarnessBinder({
case (th: HasHarnessInstantiators, port: ChipIdPort, chipId: Int) => {
require(chipId < math.pow(2, port.io.getWidth), "ID Pin is not wide enough")
port.io := chipId.U
}
})
class WithTieOffInterrupts extends OverrideHarnessBinder({
(system: HasExtInterruptsModuleImp, th: HasHarnessInstantiators, ports: Seq[UInt]) => {
ports.foreach { _ := 0.U }
class WithSimUARTToUARTTSI extends HarnessBinder({
case (th: HasHarnessInstantiators, port: UARTPort, chipId: Int) => {
UARTAdapter.connect(Seq(port.io),
baudrate=port.io.c.initBaudRate,
clockFrequency=th.getHarnessBinderClockFreqHz.toInt,
forcePty=true)
}
})
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
(system: CanHaveSlaveAXI4Port, th: HasHarnessInstantiators, ports: Seq[ClockedIO[AXI4Bundle]]) => {
ports.foreach({ p =>
p.bits := DontCare
p.bits.aw.valid := false.B
p.bits.w.valid := false.B
p.bits.b.ready := false.B
p.bits.ar.valid := false.B
p.bits.r.ready := false.B
})
class WithSimTSIToUARTTSI extends HarnessBinder({
case (th: HasHarnessInstantiators, port: UARTTSIPort, chipId: Int) => {
val freq = th.getHarnessBinderClockFreqHz.toInt
val uart_to_serial = Module(new UARTToSerial(freq, port.io.uart.c))
val serial_width_adapter = Module(new SerialWidthAdapter(8, TSI.WIDTH))
val success = SimTSI.connect(Some(TSIIO(serial_width_adapter.io.wide)), th.harnessBinderClock, th.harnessBinderReset)
when (success) { th.success := true.B }
assert(!uart_to_serial.io.dropped)
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
uart_to_serial.io.uart.rxd := port.io.uart.txd
port.io.uart.rxd := uart_to_serial.io.uart.txd
}
})
class WithSimDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebug, th: HasHarnessInstantiators, 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 TestchipSimDTM).connect(th.harnessBinderClock, th.harnessBinderReset.asBool, d, dtm_success)
case j: JTAGChipIO =>
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
val jtag_wire = Wire(new JTAGIO)
jtag_wire.TDO.data := j.TDO
jtag_wire.TDO.driven := true.B
j.TCK := jtag_wire.TCK
j.TMS := jtag_wire.TMS
j.TDI := jtag_wire.TDI
val jtag = Module(new SimJTAG(tickDelay=3))
jtag.connect(jtag_wire, th.harnessBinderClock, th.harnessBinderReset.asBool, ~(th.harnessBinderReset.asBool), dtm_success)
}
class WithTraceGenSuccess extends HarnessBinder({
case (th: HasHarnessInstantiators, port: SuccessPort, chipId: Int) => {
when (port.io) { th.success := true.B }
}
})
class WithTiedOffDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebug, th: HasHarnessInstantiators, ports: Seq[Data]) => {
ports.map {
case j: JTAGChipIO =>
j.TCK := true.B.asClock
j.TMS := true.B
j.TDI := true.B
case d: ClockedDMIIO =>
d.dmi.req.valid := false.B
d.dmi.req.bits := DontCare
d.dmi.resp.ready := true.B
d.dmiClock := false.B.asClock
d.dmiReset := true.B
case a: ClockedAPBBundle =>
a.pready := false.B
a.pslverr := false.B
a.prdata := 0.U
a.pduser := DontCare
a.clock := false.B.asClock
a.reset := true.B.asAsyncReset
a.psel := false.B
a.penable := false.B
}
class WithCospike extends HarnessBinder({
case (th: HasHarnessInstantiators, port: TracePort, chipId: Int) => {
port.io.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, port.cosimCfg))
}
})
class WithSerialTLTiedOff extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
ports.map({ port =>
val bits = port.bits
if (DataMirror.directionOf(port.clock) == Direction.Input) {
port.clock := false.B.asClock
}
port.bits.out.ready := false.B
port.bits.in.valid := false.B
port.bits.in.bits := DontCare
})
}
})
class WithSimTSIOverSerialTL extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
ports.map({ port =>
val bits = port.bits
if (DataMirror.directionOf(port.clock) == Direction.Input) {
port.clock := th.harnessBinderClock
}
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
val success = SimTSI.connect(Some(ram.module.io.tsi), th.harnessBinderClock, th.harnessBinderReset.asBool)
when (success) { th.success := true.B }
})
}
})
class WithSimUARTToUARTTSI extends OverrideHarnessBinder({
(system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
require(ports.size <= 1)
ports.map { port => {
UARTAdapter.connect(Seq(port.uart),
baudrate=port.uartParams.initBaudRate,
clockFrequency=th.getHarnessBinderClockFreqHz.toInt,
forcePty=true)
assert(!port.dropped)
}}
}
})
class WithSimTSIToUARTTSI extends OverrideHarnessBinder({
(system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
require(ports.size <= 1)
ports.map({ port =>
val freq = th.getHarnessBinderClockFreqHz.toInt
val uart_to_serial = Module(new UARTToSerial(freq, port.uartParams))
val serial_width_adapter = Module(new SerialWidthAdapter(8, TSI.WIDTH))
val success = SimTSI.connect(Some(TSIIO(serial_width_adapter.io.wide)), th.harnessBinderClock, th.harnessBinderReset)
when (success) { th.success := true.B }
assert(!uart_to_serial.io.dropped)
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
uart_to_serial.io.uart.rxd := port.uart.txd
port.uart.rxd := uart_to_serial.io.uart.txd
})
}
})
class WithTraceGenSuccess extends OverrideHarnessBinder({
(system: TraceGenSystemModuleImp, th: HasHarnessInstantiators, ports: Seq[Bool]) => {
ports.map { p => when (p) { th.success := true.B } }
}
})
class WithCospike extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: HasHarnessInstantiators, ports: Seq[TraceOutputTop]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem]
val tiles = chipyardSystem.tiles
val cfg = SpikeCosimConfig(
isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0),
priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""),
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
nharts = tiles.size,
bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse(""),
has_dtm = p(ExportDebug).protocols.contains(DMI) // assume that exposing clockeddmi means we will connect SimDTM
)
ports.map { p => p.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, cfg)) }
}
})
class WithCustomBootPinPlusArg extends OverrideHarnessBinder({
(system: CanHavePeripheryCustomBootPin, th: HasHarnessInstantiators, ports: Seq[Bool]) => {
class WithCustomBootPinPlusArg extends HarnessBinder({
case (th: HasHarnessInstantiators, port: CustomBootPort, chipId: Int) => {
val pin = PlusArg("custom_boot_pin", width=1)
ports.foreach(_ := pin)
port.io := pin
}
})
class WithClockAndResetFromHarness extends OverrideHarnessBinder({
(system: HasChipyardPRCI, th: HasHarnessInstantiators, ports: Seq[Data]) => {
implicit val p = GetSystemParameters(system)
val clocks = ports.collect { case c: ClockWithFreq => c }
class WithClockFromHarness extends HarnessBinder({
case (th: HasHarnessInstantiators, port: ClockPort, chipId: Int) => {
// DOC include start: HarnessClockInstantiatorEx
ports.map ({
case c: ClockWithFreq => {
val clock = th.harnessClockInstantiator.requestClockMHz(s"clock_${c.freqMHz.toInt}MHz", c.freqMHz)
c.clock := clock
}
case r: AsyncReset => r := th.referenceReset.asAsyncReset
})
port.io := th.harnessClockInstantiator.requestClockMHz(s"clock_${port.freqMHz}MHz", port.freqMHz)
// DOC include end: HarnessClockInstantiatorEx
}
})
class WithResetFromHarness extends HarnessBinder({
case (th: HasHarnessInstantiators, port: ResetPort, chipId: Int) => {
port.io := th.referenceReset.asAsyncReset
}
})

View File

@@ -10,7 +10,6 @@ import freechips.rocketchip.util.{ResetCatchAndSync}
import freechips.rocketchip.prci._
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders, HarnessClockInstantiatorKey}
import chipyard.iobinders.HasIOBinders
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}

View File

@@ -5,12 +5,12 @@ import chisel3._
import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
import freechips.rocketchip.diplomacy.{LazyModule}
import org.chipsalliance.cde.config.{Field, Parameters, Config}
import freechips.rocketchip.util.{ResetCatchAndSync}
import freechips.rocketchip.util.{ResetCatchAndSync, DontTouch}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters}
import chipyard.stage.phases.TargetDirKey
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
import chipyard.iobinders.HasIOBinders
import chipyard.iobinders.HasChipyardPorts
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
import chipyard.{ChipTop}
@@ -24,6 +24,7 @@ case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) =>
case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator]()
case object HarnessBinderClockFrequencyKey extends Field[Double](100.0) // MHz
case object MultiChipIdx extends Field[Int](0)
case object DontTouchChipTopPorts extends Field[Boolean](true)
class WithMultiChip(id: Int, p: Parameters) extends Config((site, here, up) => {
case MultiChipParameters(`id`) => p
@@ -39,6 +40,10 @@ class WithHarnessBinderClockFreqMHz(freqMHz: Double) extends Config((site, here,
case HarnessBinderClockFrequencyKey => freqMHz
})
class WithDontTouchChipTopPorts(b: Boolean = true) extends Config((site, here, up) => {
case DontTouchChipTopPorts => b
})
// A TestHarness mixing this in will
// - use the HarnessClockInstantiator clock provide
trait HasHarnessInstantiators {
@@ -63,7 +68,7 @@ trait HasHarnessInstantiators {
val supportsMultiChip: Boolean = false
private val chipParameters = p(MultiChipNChips) match {
val chipParameters = p(MultiChipNChips) match {
case Some(n) => (0 until n).map { i => p(MultiChipParameters(i)).alterPartial {
case TargetDirKey => p(TargetDirKey) // hacky fix
case MultiChipIdx => i
@@ -83,12 +88,20 @@ trait HasHarnessInstantiators {
withClockAndReset (harnessBinderClock, harnessBinderReset) {
lazyDuts.zipWithIndex.foreach {
case (d: HasIOBinders, i: Int) => ApplyHarnessBinders(this, d.lazySystem, d.portMap)(chipParameters(i))
case (d: HasChipyardPorts, i: Int) => {
ApplyHarnessBinders(this, d.ports, i)(chipParameters(i))
}
case _ =>
}
ApplyMultiHarnessBinders(this, lazyDuts)
}
if (p(DontTouchChipTopPorts)) {
duts.map(_ match {
case d: DontTouch => d.dontTouchPorts()
})
}
val harnessBinderClk = harnessClockInstantiator.requestClockMHz("harnessbinder_clock", getHarnessBinderClockFreqMHz)
println(s"Harness binder clock is $harnessBinderClockFreq")
harnessBinderClock := harnessBinderClk

View File

@@ -2,6 +2,7 @@ package chipyard.harness
import chisel3._
import chisel3.util._
import chisel3.experimental.{DataMirror, Direction}
import org.chipsalliance.cde.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
@@ -9,70 +10,75 @@ import freechips.rocketchip.devices.debug._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.util._
import testchipip._
import testchipip.serdes._
import chipyard._
import chipyard.clocking.{HasChipyardPRCI, ClockWithFreq}
import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasIOBinders}
import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasChipyardPorts, Port, SerialTLPort}
import scala.reflect.{ClassTag}
case class MultiHarnessBinders(c0: Int, c1: Int) extends Field[MultiHarnessBinderMap](MultiHarnessBinderMapDefault)
class MultiHarnessBinder[T0, T1, S <: HasHarnessInstantiators, U0 <: Data, U1 <: Data]
(chip0: Int, chip1: Int, fn: => (T0, T1, S, Seq[U0], Seq[U1]) => Unit)
(implicit tag0: ClassTag[T0], tag1: ClassTag[T1], thtag: ClassTag[S], ptag0: ClassTag[U0], ptag1: ClassTag[U1])
extends Config((site, here, up) => {
// Override any HarnessBinders for chip0/chip1
case MultiChipParameters(`chip0`) => new Config(
new OverrideHarnessBinder[T0, S, U0]((system: T0, th: S, ports: Seq[U0]) => Nil) ++
up(MultiChipParameters(chip0))
)
case MultiChipParameters(`chip1`) => new Config(
new OverrideHarnessBinder[T1, S, U1]((system: T1, th: S, ports: Seq[U1]) => Nil) ++
up(MultiChipParameters(chip1))
)
// Set the multiharnessbinder key
case MultiHarnessBinders(`chip0`, `chip1`) => up(MultiHarnessBinders(chip0, chip1)) +
((tag0.runtimeClass.toString, tag1.runtimeClass.toString) ->
((c0: Any, c1: Any, th: HasHarnessInstantiators, ports0: Seq[Data], ports1: Seq[Data]) => {
val pts0 = ports0.map(_.asInstanceOf[U0])
val pts1 = ports1.map(_.asInstanceOf[U1])
require(pts0.size == pts1.size)
(c0, c1, th) match {
case (c0: T0, c1: T1, th: S) => fn(c0, c1, th, pts0, pts1)
case _ =>
}
})
)
})
case class MultiHarnessBinders(chip0: Int, chip1: Int) extends Field[Seq[MultiHarnessBinderFunction]](Nil)
object ApplyMultiHarnessBinders {
def apply(th: HasHarnessInstantiators, chips: Seq[LazyModule])(implicit p: Parameters): Unit = {
Seq.tabulate(chips.size, chips.size) { case (i, j) => if (i != j) {
(chips(i), chips(j)) match {
case (l0: HasIOBinders, l1: HasIOBinders) => p(MultiHarnessBinders(i, j)).foreach {
case ((s0, s1), f) => {
f(l0.lazySystem , l1.lazySystem , th, l0.portMap(s0), l1.portMap(s1))
f(l0.lazySystem.module, l1.lazySystem.module, th, l0.portMap(s0), l1.portMap(s1))
}
case (l0: HasChipyardPorts, l1: HasChipyardPorts) => p(MultiHarnessBinders(i, j)).foreach { f =>
f(th, l0.ports, l1.ports)
}
case _ =>
}
}}
}
}
class WithMultiChipSerialTL(chip0: Int, chip1: Int) extends MultiHarnessBinder(chip0, chip1, (
(system0: CanHavePeripheryTLSerial, system1: CanHavePeripheryTLSerial,
th: HasHarnessInstantiators,
ports0: Seq[ClockedIO[SerialIO]], ports1: Seq[ClockedIO[SerialIO]]
) => {
require(ports0.size == ports1.size)
(ports0 zip ports1).map { case (l, r) =>
l.clock <> r.clock
require(l.bits.w == r.bits.w)
l.bits.flipConnect(r.bits)
class MultiHarnessBinder[T <: Port[_], S <: HasHarnessInstantiators](
chip0: Int, chip1: Int,
chip0portFn: T => Boolean, chip1portFn: T => Boolean,
connectFn: (S, T, T) => Unit
)(implicit tag0: ClassTag[T], tag1: ClassTag[S]) extends Config((site, here, up) => {
// Override any HarnessBinders for chip0/chip1
case MultiChipParameters(`chip0`) => new Config(
new HarnessBinder({case (th: S, port: T, chipId: Int) if chip0portFn(port) => }) ++ up(MultiChipParameters(chip0))
)
case MultiChipParameters(`chip1`) => new Config(
new HarnessBinder({case (th: S, port: T, chipId: Int) if chip1portFn(port) => }) ++ up(MultiChipParameters(chip1))
)
// Set the multiharnessbinder key
case MultiHarnessBinders(`chip0`, `chip1`) => up(MultiHarnessBinders(chip0, chip1)) :+ {
((th: S, chip0Ports: Seq[Port[_]], chip1Ports: Seq[Port[_]]) => {
val chip0Port: Seq[T] = chip0Ports.collect { case (p: T) if chip0portFn(p) => p }
val chip1Port: Seq[T] = chip1Ports.collect { case (p: T) if chip1portFn(p) => p }
require(chip0Port.size == 1 && chip1Port.size == 1)
connectFn(th, chip0Port(0), chip1Port(0))
})
}
})
class WithMultiChipSerialTL(chip0: Int, chip1: Int, chip0portId: Int = 0, chip1portId: Int = 0) extends MultiHarnessBinder(
chip0, chip1,
(p0: SerialTLPort) => p0.portId == chip0portId,
(p1: SerialTLPort) => p1.portId == chip1portId,
(th: HasHarnessInstantiators, p0: SerialTLPort, p1: SerialTLPort) => {
def connectDecoupledSyncSerialIO(clkSource: InternalSyncSerialIO, clkSink: ExternalSyncSerialIO) = {
clkSink.clock_in := clkSource.clock_out
clkSink.in <> clkSource.out
clkSource.in <> clkSink.out
}
def connectSourceSyncSerialIO(a: SourceSyncSerialIO, b: SourceSyncSerialIO) = {
a.clock_in := b.clock_out
b.clock_in := a.clock_out
a.reset_in := b.reset_out
b.reset_in := a.reset_out
a.in := b.out
b.in := a.out
a.credit_in := b.credit_out
b.credit_in := a.credit_out
}
(p0.io, p1.io) match {
case (io0: InternalSyncSerialIO, io1: ExternalSyncSerialIO) => connectDecoupledSyncSerialIO(io0, io1)
case (io0: ExternalSyncSerialIO, io1: InternalSyncSerialIO) => connectDecoupledSyncSerialIO(io1, io0)
case (io0: SourceSyncSerialIO , io1: SourceSyncSerialIO ) => connectSourceSyncSerialIO (io0, io1)
}
}
))
)

View File

@@ -9,7 +9,6 @@ import freechips.rocketchip.util.{ResetCatchAndSync}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters}
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
import chipyard.iobinders.HasIOBinders
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
import chipyard.{ChipTop}

View File

@@ -5,13 +5,7 @@ import scala.collection.immutable.ListMap
package object harness
{
type HarnessBinderFunction = (Any, HasHarnessInstantiators, Seq[Data]) => Unit
type HarnessBinderMap = Map[String, HarnessBinderFunction]
def HarnessBinderMapDefault: HarnessBinderMap = (new ListMap[String, HarnessBinderFunction])
.withDefaultValue((t: Any, th: HasHarnessInstantiators, d: Seq[Data]) => ())
type MultiHarnessBinderFunction = (Any, Any, HasHarnessInstantiators, Seq[Data], Seq[Data]) => Unit
type MultiHarnessBinderMap = Map[(String, String), MultiHarnessBinderFunction]
def MultiHarnessBinderMapDefault: MultiHarnessBinderMap = (new ListMap[(String, String), MultiHarnessBinderFunction])
.withDefaultValue((_: Any, _: Any, _: HasHarnessInstantiators, _: Seq[Data], _: Seq[Data]) => ())
import chipyard.iobinders.Port
type HarnessBinderFunction = PartialFunction[(HasHarnessInstantiators, Port[_], Int), Unit]
type MultiHarnessBinderFunction = (HasHarnessInstantiators, Seq[Port[_]], Seq[Port[_]]) => Unit
}

View File

@@ -1,7 +1,8 @@
package chipyard.iobinders
import chisel3._
import chisel3.experimental.{Analog, IO, DataMirror}
import chisel3.reflect.DataMirror
import chisel3.experimental.Analog
import org.chipsalliance.cde.config._
import freechips.rocketchip.diplomacy._
@@ -18,18 +19,26 @@ import freechips.rocketchip.tilelink.{TLBundle}
import sifive.blocks.devices.gpio._
import sifive.blocks.devices.uart._
import sifive.blocks.devices.spi._
import sifive.blocks.devices.i2c._
import tracegen.{TraceGenSystemModuleImp}
import barstools.iocell.chisel._
import testchipip._
import testchipip.serdes.{CanHavePeripheryTLSerial, SerialTLKey}
import testchipip.spi.{SPIChipIO}
import testchipip.boot.{CanHavePeripheryCustomBootPin}
import testchipip.soc.{CanHavePeripheryChipIdPin}
import testchipip.util.{ClockedIO}
import testchipip.iceblk.{CanHavePeripheryBlockDevice, BlockDeviceKey, BlockDeviceIO}
import testchipip.cosim.{CanHaveTraceIO, TraceOutputTop, SpikeCosimConfig}
import testchipip.tsi.{CanHavePeripheryUARTTSI, UARTTSIIO}
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import chipyard.{CanHaveMasterTLMemPort}
import chipyard.{CanHaveMasterTLMemPort, ChipyardSystem, ChipyardSystemModule}
import scala.reflect.{ClassTag}
object IOBinderTypes {
type IOBinderTuple = (Seq[Data], Seq[IOCell])
type IOBinderTuple = (Seq[Port[_]], Seq[IOCell])
type IOBinderFunction = (Boolean, => Any) => ModuleValue[IOBinderTuple]
}
import IOBinderTypes._
@@ -50,13 +59,7 @@ case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]](
Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil)
)
case object DontTouchIOBindersPorts extends Field[Boolean](true)
class WithDontTouchIOBinders(b: Boolean = true) extends Config((site, here, up) => {
case DontTouchIOBindersPorts => b
})
abstract trait HasIOBinders { this: LazyModule =>
abstract trait HasIOBinders extends HasChipyardPorts { 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
@@ -80,11 +83,9 @@ abstract trait HasIOBinders { this: LazyModule =>
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop iocells
val iocellMap = InModuleBody { iobinders.keys.map(k => k -> (lzyFlattened(k)._2 ++ impFlattened(k)._2)).toMap }
InModuleBody {
if (p(DontTouchIOBindersPorts)) {
portMap.values.foreach(_.foreach(dontTouch(_)))
}
def ports = portMap.getWrappedValue.values.flatten.toSeq
InModuleBody {
println("IOCells generated by IOBinders:")
for ((k, v) <- iocellMap) {
if (!v.isEmpty) {
@@ -117,7 +118,10 @@ object GetSystemParameters {
}
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)))
case IOBinders => {
val upMap = up(IOBinders)
upMap + (tag.runtimeClass.toString -> composer(upMap(tag.runtimeClass.toString)))
}
})
class ConcreteIOBinder[T](composes: Boolean, fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends IOBinder[T](
@@ -171,29 +175,72 @@ class WithGPIOCells extends OverrideIOBinder({
iocell.io.ie := pin.o.ie
pin.i.ival := iocell.io.i
iocell.io.pad <> g
(g, iocell)
(GPIOPort(() => g, i, j), iocell)
}).unzip
}).unzip
val ports: Seq[Analog] = ports2d.flatten
(ports, cells2d.flatten)
(ports2d.flatten, cells2d.flatten)
}
})
class WithGPIOPunchthrough extends OverrideIOBinder({
(system: HasPeripheryGPIOModuleImp) => {
val ports = system.gpio.zipWithIndex.map { case (gpio, i) =>
val io_gpio = IO(gpio.cloneType).suggestName(s"gpio_$i")
io_gpio <> gpio
GPIOPinsPort(() => io_gpio, i)
}
(ports, Nil)
}
})
class WithI2CPunchthrough extends OverrideIOBinder({
(system: HasPeripheryI2CModuleImp) => {
val ports = system.i2c.zipWithIndex.map { case (i2c, i) =>
val io_i2c = IO(i2c.cloneType).suggestName(s"i2c_$i")
io_i2c <> i2c
I2CPort(() => i2c)
}
(ports, Nil)
}
})
// DOC include start: WithUARTIOCells
class WithUARTIOCells extends OverrideIOBinder({
(system: HasPeripheryUARTModuleImp) => {
val (ports: Seq[UARTPortIO], cells2d) = system.uart.zipWithIndex.map({ case (u, i) =>
val (ports: Seq[UARTPort], cells2d) = system.uart.zipWithIndex.map({ case (u, i) =>
val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey), abstractResetAsAsync = true)
(port, ios)
val where = PBUS // TODO fix
val bus = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where)
val freqMHz = bus.dtsFrequency.get / 1000000
(UARTPort(() => port, i, freqMHz.toInt), ios)
}).unzip
(ports, cells2d.flatten)
}
})
// DOC include end: WithUARTIOCells
class WithSPIIOCells extends OverrideIOBinder({
class WithSPIIOPunchthrough extends OverrideLazyIOBinder({
(system: HasPeripherySPI) => {
// attach resource to 1st SPI
if (system.tlSpiNodes.size > 0) ResourceBinding {
Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0))
}
InModuleBody {
val spi = system.asInstanceOf[BaseSubsystem].module.asInstanceOf[HasPeripherySPIBundle].spi
val ports = spi.zipWithIndex.map({ case (s, i) =>
val io_spi = IO(s.cloneType).suggestName(s"spi_$i")
io_spi <> s
SPIPort(() => io_spi)
})
(ports, Nil)
}
}
})
class WithSPIFlashIOCells extends OverrideIOBinder({
(system: HasPeripherySPIFlashModuleImp) => {
val (ports: Seq[SPIChipIO], cells2d) = system.qspi.zipWithIndex.map({ case (s, i) =>
val (ports: Seq[SPIFlashPort], cells2d) = system.qspi.zipWithIndex.map({ case (s, i) =>
val name = s"spi_${i}"
val port = IO(new SPIChipIO(s.c.csWidth)).suggestName(name)
val iocellBase = s"iocell_${name}"
@@ -213,7 +260,7 @@ class WithSPIIOCells extends OverrideIOBinder({
iocell
}
(port, dqIOs ++ csIOs ++ sckIOs)
(SPIFlashPort(() => port, system.p(PeripherySPIFlashKey)(i), i), dqIOs ++ csIOs ++ sckIOs)
}).unzip
(ports, cells2d.flatten)
}
@@ -223,7 +270,7 @@ class WithExtInterruptIOCells extends OverrideIOBinder({
(system: HasExtInterruptsModuleImp) => {
if (system.outer.nExtInterrupts > 0) {
val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey), abstractResetAsAsync = true)
(Seq(port), cells)
(Seq(ExtIntPort(() => port)), cells)
} else {
system.interrupts := DontCare // why do I have to drive this 0-wide wire???
(Nil, Nil)
@@ -239,7 +286,9 @@ class JTAGChipIO extends Bundle {
val TDO = Output(Bool())
}
class WithDebugIOCells extends OverrideLazyIOBinder({
// WARNING: Don't disable syncReset unless you are trying to
// get around bugs in RTL simulators
class WithDebugIOCells(syncReset: Boolean = true) extends OverrideLazyIOBinder({
(system: HasPeripheryDebug) => {
implicit val p = GetSystemParameters(system)
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
@@ -263,7 +312,7 @@ class WithDebugIOCells extends OverrideLazyIOBinder({
d.disableDebug.foreach { d => d := false.B }
// Drive JTAG on-chip IOs
d.systemjtag.map { j =>
j.reset := ResetCatchAndSync(j.jtag.TCK, clockBundle.reset.asBool)
j.reset := (if (syncReset) ResetCatchAndSync(j.jtag.TCK, clockBundle.reset.asBool) else clockBundle.reset.asBool)
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)
@@ -273,7 +322,8 @@ class WithDebugIOCells extends OverrideLazyIOBinder({
// Add IOCells for the DMI/JTAG/APB ports
val dmiTuple = debug.clockeddmi.map { d =>
IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true)
val (port, cells) = IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true)
(DMIPort(() => port), cells)
}
val jtagTuple = debug.systemjtag.map { j =>
@@ -282,14 +332,13 @@ class WithDebugIOCells extends OverrideLazyIOBinder({
j.jtag.TMS := jtag_wire.TMS
j.jtag.TDI := jtag_wire.TDI
jtag_wire.TDO := j.jtag.TDO.data
IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true)
val (port, cells) = IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true)
(JTAGPort(() => port), cells)
}
val apbTuple = debug.apb.map { a =>
IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = true)
}
require(!debug.apb.isDefined)
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
val allTuples = (dmiTuple ++ jtagTuple).toSeq
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
}).getOrElse((Nil, Nil))
}}}
@@ -297,20 +346,34 @@ class WithDebugIOCells extends OverrideLazyIOBinder({
})
class WithSerialTLIOCells extends OverrideIOBinder({
(system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s =>
(system: CanHavePeripheryTLSerial) => {
val (ports, cells) = system.serial_tls.zipWithIndex.map({ case (s, id) =>
val sys = system.asInstanceOf[BaseSubsystem]
val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, s"serial_tl_$id", sys.p(IOCellKey), abstractResetAsAsync = true)
(SerialTLPort(() => port, sys.p(SerialTLKey)(id), system.serdessers(id), id), cells)
}).unzip
(ports.toSeq, cells.flatten.toSeq)
}
})
class WithChipIdIOCells extends OverrideIOBinder({
(system: CanHavePeripheryChipIdPin) => system.chip_id_pin.map({ p =>
val sys = system.asInstanceOf[BaseSubsystem]
val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey), abstractResetAsAsync = true)
(Seq(port), cells)
}).getOrElse((Nil, Nil))
val (port, cells) = IOCell.generateIOFromSignal(p.getWrappedValue, s"chip_id", sys.p(IOCellKey), abstractResetAsAsync = true)
(Seq(ChipIdPort(() => port)), cells)
}).getOrElse(Nil, Nil)
})
class WithSerialTLPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s =>
val sys = system.asInstanceOf[BaseSubsystem]
val port = IO(s.getWrappedValue.cloneType)
port <> s.getWrappedValue
(Seq(port), Nil)
}).getOrElse((Nil, Nil))
(system: CanHavePeripheryTLSerial) => {
val (ports, cells) = system.serial_tls.zipWithIndex.map({ case (s, id) =>
val sys = system.asInstanceOf[BaseSubsystem]
val port = IO(chiselTypeOf(s.getWrappedValue))
port <> s.getWrappedValue
(SerialTLPort(() => port, sys.p(SerialTLKey)(id), system.serdessers(id), id), Nil)
}).unzip
(ports.toSeq, cells.flatten.toSeq)
}
})
class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
@@ -321,12 +384,11 @@ class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
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 := clockBundle.clock
p.reset := clockBundle.reset
p
val ports: Seq[AXI4MemPort] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
val port = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
port.bits <> m
port.clock := clockBundle.clock
AXI4MemPort(() => port, p(ExtMem).get, system.memAXI4Node.edges.in(i), p(MemoryBusKey).dtsFrequency.get.toInt)
}).toSeq
(ports, Nil)
}
@@ -341,12 +403,11 @@ class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({
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 := clockBundle.clock
p.reset := clockBundle.reset
p
val ports: Seq[AXI4MMIOPort] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
val port = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
port.bits <> m
port.clock := clockBundle.clock
AXI4MMIOPort(() => port, p(ExtBus).get, system.mmioAXI4Node.edges.in(i))
}).toSeq
(ports, Nil)
}
@@ -361,11 +422,11 @@ class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({
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 := clockBundle.clock
p
val ports: Seq[AXI4InPort] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) =>
val port = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}")
m <> port.bits
port.clock := clockBundle.clock
AXI4InPort(() => port, p(ExtIn).get)
}).toSeq
(ports, Nil)
}
@@ -374,10 +435,12 @@ class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({
class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryBlockDevice) => {
val ports: Seq[ClockedIO[BlockDeviceIO]] = system.bdev.map({ bdev =>
val p = IO(new ClockedIO(new BlockDeviceIO()(GetSystemParameters(system)))).suggestName("blockdev")
p <> bdev
p
val ports: Seq[BlockDevicePort] = system.bdev.map({ bdev =>
val p = GetSystemParameters(system)
val bdParams = p(BlockDeviceKey).get
val port = IO(new ClockedIO(new BlockDeviceIO(bdParams))).suggestName("blockdev")
port <> bdev
BlockDevicePort(() => port, bdParams)
}).toSeq
(ports, Nil)
}
@@ -385,10 +448,11 @@ class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({
class WithNICIOPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryIceNIC) => {
val ports: Seq[ClockedIO[NICIOvonly]] = system.icenicOpt.map({ n =>
val p = IO(new ClockedIO(new NICIOvonly)).suggestName("nic")
p <> n
p
val ports: Seq[NICPort] = system.icenicOpt.map({ n =>
val p = GetSystemParameters(system)
val port = IO(new ClockedIO(new NICIOvonly)).suggestName("nic")
port <> n
NICPort(() => port, p(NICKey).get)
}).toSeq
(ports, Nil)
}
@@ -398,16 +462,30 @@ class WithTraceGenSuccessPunchthrough extends OverrideIOBinder({
(system: TraceGenSystemModuleImp) => {
val success: Bool = IO(Output(Bool())).suggestName("success")
success := system.success
(Seq(success), Nil)
(Seq(SuccessPort(() => success)), Nil)
}
})
class WithTraceIOPunchthrough extends OverrideIOBinder({
(system: CanHaveTraceIOModuleImp) => {
val ports: Option[TraceOutputTop] = system.traceIO.map { t =>
class WithTraceIOPunchthrough extends OverrideLazyIOBinder({
(system: CanHaveTraceIO) => InModuleBody {
val ports: Option[TracePort] = system.traceIO.map { t =>
val trace = IO(DataMirror.internal.chiselTypeClone[TraceOutputTop](t)).suggestName("trace")
trace <> t
trace
val p = GetSystemParameters(system)
val chipyardSystem = system.asInstanceOf[ChipyardSystem]
val tiles = chipyardSystem.totalTiles.values
val cfg = SpikeCosimConfig(
isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0),
priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""),
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
nharts = tiles.size,
bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse(""),
has_dtm = p(ExportDebug).protocols.contains(DMI) // assume that exposing clockeddmi means we will connect SimDTM
)
TracePort(() => trace, cfg)
}
(ports.toSeq, Nil)
}
@@ -417,7 +495,7 @@ class WithCustomBootPin extends OverrideIOBinder({
(system: CanHavePeripheryCustomBootPin) => system.custom_boot_pin.map({ p =>
val sys = system.asInstanceOf[BaseSubsystem]
val (port, cells) = IOCell.generateIOFromSignal(p.getWrappedValue, "custom_boot", sys.p(IOCellKey), abstractResetAsAsync = true)
(Seq(port), cells)
(Seq(CustomBootPort(() => port)), cells)
}).getOrElse((Nil, Nil))
})
@@ -426,7 +504,7 @@ class WithUARTTSIPunchthrough extends OverrideIOBinder({
val sys = system.asInstanceOf[BaseSubsystem]
val uart_tsi = IO(new UARTTSIIO(p.uartParams))
uart_tsi <> p
(Seq(uart_tsi), Nil)
(Seq(UARTTSIPort(() => uart_tsi)), Nil)
}).getOrElse((Nil, Nil))
})
@@ -434,7 +512,7 @@ class WithTLMemPunchthrough extends OverrideIOBinder({
(system: CanHaveMasterTLMemPort) => {
val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.mem_tl)).suggestName("tl_slave")
io_tl_mem_pins_temp <> system.mem_tl
(Seq(io_tl_mem_pins_temp), Nil)
(Seq(TLMemPort(() => io_tl_mem_pins_temp)), Nil)
}
})
@@ -444,8 +522,8 @@ class WithDontTouchPorts extends OverrideIOBinder({
})
class WithNMITiedOff extends ComposeIOBinder({
(system: HasTilesModuleImp) => {
system.nmi.flatten.foreach { nmi =>
(system: HasHierarchicalElementsRootContextModuleImp) => {
system.nmi.foreach { nmi =>
nmi.rnmi := false.B
nmi.rnmi_interrupt_vector := 0.U
nmi.rnmi_exception_vector := 0.U

View File

@@ -0,0 +1,111 @@
package chipyard.iobinders
import chisel3._
import chisel3.experimental.{Analog}
import sifive.blocks.devices.uart.{UARTPortIO}
import sifive.blocks.devices.spi.{SPIFlashParams, SPIPortIO}
import sifive.blocks.devices.gpio.{GPIOPortIO}
import testchipip.util.{ClockedIO}
import testchipip.serdes.{TLSerdesser, SerialIO, SerialTLParams}
import testchipip.spi.{SPIChipIO}
import testchipip.cosim.{TraceOutputTop, SpikeCosimConfig}
import testchipip.iceblk.{BlockDeviceIO, BlockDeviceConfig}
import testchipip.tsi.{UARTTSIIO}
import icenet.{NICIOvonly, NICConfig}
import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4EdgeParameters}
import freechips.rocketchip.subsystem.{MemoryPortParams, MasterPortParams, SlavePortParams}
import freechips.rocketchip.devices.debug.{ClockedDMIIO}
import freechips.rocketchip.util.{HeterogeneousBag}
import freechips.rocketchip.tilelink.{TLBundle}
trait Port[T <: Data] {
val getIO: () => T
// port.io should only be called in the TestHarness context
lazy val io = getIO()
}
trait HasChipyardPorts {
def ports: Seq[Port[_]]
}
// These case classes are generated by IOBinders, and interpreted by HarnessBinders
case class GPIOPort (val getIO: () => Analog, val gpioId: Int, val pinId: Int)
extends Port[Analog]
case class GPIOPinsPort (val getIO: () => GPIOPortIO, val gpioId: Int)
extends Port[GPIOPortIO]
case class I2CPort (val getIO: () => sifive.blocks.devices.i2c.I2CPort)
extends Port[sifive.blocks.devices.i2c.I2CPort]
case class UARTPort (val getIO: () => UARTPortIO, val uartNo: Int, val freqMHz: Int)
extends Port[UARTPortIO]
case class SPIFlashPort (val getIO: () => SPIChipIO, val params: SPIFlashParams, val spiId: Int)
extends Port[SPIChipIO]
case class SPIPort (val getIO: () => SPIPortIO)
extends Port[SPIPortIO]
case class BlockDevicePort (val getIO: () => ClockedIO[BlockDeviceIO], val params: BlockDeviceConfig)
extends Port[ClockedIO[BlockDeviceIO]]
case class NICPort (val getIO: () => ClockedIO[NICIOvonly], val params: NICConfig)
extends Port[ClockedIO[NICIOvonly]]
case class AXI4MemPort (val getIO: () => ClockedIO[AXI4Bundle], val params: MemoryPortParams, val edge: AXI4EdgeParameters, val clockFreqMHz: Int)
extends Port[ClockedIO[AXI4Bundle]]
case class AXI4MMIOPort (val getIO: () => ClockedIO[AXI4Bundle], val params: MasterPortParams, val edge: AXI4EdgeParameters)
extends Port[ClockedIO[AXI4Bundle]]
case class AXI4InPort (val getIO: () => ClockedIO[AXI4Bundle], val params: SlavePortParams)
extends Port[ClockedIO[AXI4Bundle]]
case class ExtIntPort (val getIO: () => UInt)
extends Port[UInt]
case class DMIPort (val getIO: () => ClockedDMIIO)
extends Port[ClockedDMIIO]
case class JTAGPort (val getIO: () => JTAGChipIO)
extends Port[JTAGChipIO]
// Lack of nice union types in scala-2 means we have to set this type as Data
case class SerialTLPort (val getIO: () => Data, val params: SerialTLParams, val serdesser: TLSerdesser, val portId: Int)
extends Port[Data]
case class ChipIdPort (val getIO: () => UInt)
extends Port[UInt]
case class UARTTSIPort (val getIO: () => UARTTSIIO)
extends Port[UARTTSIIO]
case class SuccessPort (val getIO: () => Bool)
extends Port[Bool]
case class TracePort (val getIO: () => TraceOutputTop, val cosimCfg: SpikeCosimConfig)
extends Port[TraceOutputTop]
case class CustomBootPort (val getIO: () => Bool)
extends Port[Bool]
case class ClockPort (val getIO: () => Clock, val freqMHz: Double)
extends Port[Clock]
case class ClockTapPort (val getIO: () => Clock)
extends Port[Clock]
case class ResetPort (val getIO: () => AsyncReset)
extends Port[Reset]
case class DebugResetPort (val getIO: () => Reset)
extends Port[Reset]
case class JTAGResetPort (val getIO: () => Reset)
extends Port[Reset]
case class TLMemPort (val getIO: () => HeterogeneousBag[TLBundle])
extends Port[HeterogeneousBag[TLBundle]]

View File

@@ -3,7 +3,6 @@
package firesim.firesim
import chisel3._
import chisel3.experimental.annotate
import chisel3.experimental.{DataMirror, Direction}
import chisel3.util.experimental.BoringUtils
@@ -12,31 +11,29 @@ import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebug, ExportDebug, DMI}
import freechips.rocketchip.amba.axi4.{AXI4Bundle}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.tile.{RocketTile}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
import freechips.rocketchip.util.{ResetCatchAndSync}
import sifive.blocks.devices.uart._
import testchipip._
import testchipip.serdes.{ExternalSyncSerialIO}
import testchipip.tsi.{SerialRAM}
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import junctions.{NastiKey, NastiParameters}
import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig}
import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotation}
import firesim.bridges._
import firesim.configs.MemModelKey
import tracegen.{TraceGenSystemModuleImp}
import cva6.CVA6Tile
import boom.common.{BoomTile}
import barstools.iocell.chisel._
import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters, IOCellKey}
import chipyard.iobinders._
import chipyard._
import chipyard.harness._
object MainMemoryConsts {
val regionNamePrefix = "MainMemory"
def globalName()(implicit p: Parameters) = s"${regionNamePrefix}_${p(MultiChipIdx)}"
def globalName(chipId: Int) = s"${regionNamePrefix}_$chipId"
}
trait Unsupported {
@@ -69,130 +66,73 @@ class WithFireSimIOCellModels extends Config((site, here, up) => {
case IOCellKey => FireSimIOCellParams()
})
class WithTSIBridgeAndHarnessRAMOverSerialTL extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => {
ports.map { port =>
implicit val p = GetSystemParameters(system)
val bits = port.bits
port.clock := th.harnessBinderClock
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
TSIBridge(th.harnessBinderClock, ram.module.io.tsi, p(ExtMem).map(_ => MainMemoryConsts.globalName), th.harnessBinderReset.asBool)
}
Nil
}
})
class WithTSIBridgeAndHarnessRAMOverSerialTL extends HarnessBinder({
case (th: FireSim, port: SerialTLPort, chipId: Int) => {
port.io match {
case io: ExternalSyncSerialIO => {
io.clock_in := th.harnessBinderClock
val ram = Module(LazyModule(new SerialRAM(port.serdesser, port.params)(port.serdesser.p)).module)
ram.io.ser.in <> io.out
io.in <> ram.io.ser.out
class WithNICBridge extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => {
val p: Parameters = GetSystemParameters(system)
ports.map { n => NICBridge(n.clock, n.bits)(p) }
Nil
}
})
class WithUARTBridge extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) =>
val uartSyncClock = Wire(Clock())
uartSyncClock := false.B.asClock
val pbusClockNode = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(PBUS).fixedClockNode
val pbusClock = pbusClockNode.in.head._1.clock
BoringUtils.bore(pbusClock, Seq(uartSyncClock))
ports.map { p => UARTBridge(uartSyncClock, p, th.harnessBinderReset.asBool)(system.p) }; Nil
})
class WithBlockDeviceBridge extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessBinderReset.asBool) }
Nil
}
})
class WithFASEDBridge extends OverrideHarnessBinder({
(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, axi4.reset.asBool,
CompleteConfig(p(firesim.configs.MemModelKey),
nastiKey,
Some(AXI4EdgeSummary(edge)),
Some(MainMemoryConsts.globalName)))
case _ => throw new Exception("Attempting to attach FASED Bridge to misconfigured design")
// This assumes that:
// If ExtMem for the target is defined, then FASED bridge will be attached
// If FASED bridge is attached, loadmem widget is present
val hasMainMemory = th.chipParameters(chipId)(ExtMem).isDefined
val mainMemoryName = Option.when(hasMainMemory)(MainMemoryConsts.globalName(chipId))
TSIBridge(th.harnessBinderClock, ram.io.tsi.get, mainMemoryName, th.harnessBinderReset.asBool)(th.p)
}
}
Nil
}
})
class WithTracerVBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => {
ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
Nil
class WithNICBridge extends HarnessBinder({
case (th: FireSim, port: NICPort, chipId: Int) => {
NICBridge(port.io.clock, port.io.bits)(th.p)
}
})
class WithCospikeBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem]
val tiles = chipyardSystem.tiles
val cfg = SpikeCosimConfig(
isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0),
priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""),
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
nharts = tiles.size,
bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse(""),
has_dtm = p(ExportDebug).protocols.contains(DMI) // assume that exposing clockeddmi means we will connect SimDTM
)
ports.map { p => p.traces.zipWithIndex.map(t => CospikeBridge(t._1, t._2, cfg)) }
class WithUARTBridge extends HarnessBinder({
case (th: FireSim, port: UARTPort, chipId: Int) =>
val uartSyncClock = th.harnessClockInstantiator.requestClockMHz("uart_clock", port.freqMHz)
UARTBridge(uartSyncClock, port.io, th.harnessBinderReset.asBool, port.freqMHz)(th.p)
})
class WithBlockDeviceBridge extends HarnessBinder({
case (th: FireSim, port: BlockDevicePort, chipId: Int) => {
BlockDevBridge(port.io.clock, port.io.bits, th.harnessBinderReset.asBool)
}
})
class WithTraceGenBridge extends OverrideHarnessBinder({
(system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) =>
ports.map { p => GroundTestBridge(th.harnessBinderClock, p)(system.p) }; Nil
})
class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
(system: HasTilesModuleImp) => {
system.outer.tiles.map {
case r: RocketTile => {
annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf))
r.module.fpuOpt.foreach(fpu => annotate(MemModelAnnotation(fpu.fpuImpl.regfile)))
}
case b: BoomTile => {
val core = b.module.core
core.iregfile match {
case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile))
}
if (core.fp_pipeline != null) core.fp_pipeline.fregfile match {
case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile))
}
}
case _ =>
}
(Nil, Nil)
class WithFASEDBridge extends HarnessBinder({
case (th: FireSim, port: AXI4MemPort, chipId: Int) => {
val nastiKey = NastiParameters(port.io.bits.r.bits.data.getWidth,
port.io.bits.ar.bits.addr.getWidth,
port.io.bits.ar.bits.id.getWidth)
FASEDBridge(port.io.clock, port.io.bits, th.harnessBinderReset.asBool,
CompleteConfig(th.p(firesim.configs.MemModelKey),
nastiKey,
Some(AXI4EdgeSummary(port.edge)),
Some(MainMemoryConsts.globalName(chipId))))(th.p)
}
})
class WithFireSimFAME5 extends ComposeIOBinder({
(system: HasTilesModuleImp) => {
system.outer.tiles.map {
case b: BoomTile =>
annotate(EnableModelMultiThreadingAnnotation(b.module))
case r: RocketTile =>
annotate(EnableModelMultiThreadingAnnotation(r.module))
case _ => Nil
}
(Nil, Nil)
class WithTracerVBridge extends HarnessBinder({
case (th: FireSim, port: TracePort, chipId: Int) => {
port.io.traces.map(tileTrace => TracerVBridge(tileTrace)(th.p))
}
})
class WithCospikeBridge extends HarnessBinder({
case (th: FireSim, port: TracePort, chipId: Int) => {
port.io.traces.zipWithIndex.map(t => CospikeBridge(t._1, t._2, port.cosimCfg))
}
})
class WithSuccessBridge extends HarnessBinder({
case (th: FireSim, port: SuccessPort, chipId: Int) => {
GroundTestBridge(th.harnessBinderClock, port.io)(th.p)
}
})

View File

@@ -5,21 +5,26 @@ package firesim.firesim
import scala.collection.mutable.{LinkedHashMap}
import chisel3._
import chisel3.experimental.{IO}
import chisel3.experimental.{IO, annotate}
import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
import freechips.rocketchip.subsystem._
import org.chipsalliance.cde.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, InModuleBody, ValName}
import freechips.rocketchip.util.{ResetCatchAndSync, RecordMap}
import freechips.rocketchip.tile.{RocketTile}
import boom.common.{BoomTile}
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock, ResetPulseBridge, ResetPulseBridgeParameters}
import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotation}
import chipyard._
import chipyard.harness._
import chipyard.iobinders._
import chipyard.clocking._
case object FireSimMultiCycleRegFile extends Field[Boolean](false)
case object FireSimFAME5 extends Field[Boolean](false)
/**
* Under FireSim's current multiclock implementation there can be only a
* single clock bridge. This requires, therefore, that it be instantiated in
@@ -85,11 +90,46 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessInsta
override val supportsMultiChip = true
instantiateChipTops()
val chiptops = instantiateChipTops()
// Ensures FireSim-synthesized assertions and instrumentation is disabled
// while resetBridge.io.reset is asserted. This ensures assertions do not fire at
// time zero in the event their local reset is delayed (typically because it
// has been pipelined)
midas.targetutils.GlobalResetCondition(resetBridge.io.reset)
// FireSim multi-cycle regfile optimization
// FireSim ModelMultithreading
chiptops.foreach {
case c: ChipTop => c.lazySystem match {
case ls: InstantiatesHierarchicalElements => {
if (p(FireSimMultiCycleRegFile)) ls.totalTiles.values.map {
case r: RocketTile => {
annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf))
r.module.fpuOpt.foreach(fpu => annotate(MemModelAnnotation(fpu.fpuImpl.regfile)))
}
case b: BoomTile => {
val core = b.module.core
core.iregfile match {
case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile))
}
if (core.fp_pipeline != null) core.fp_pipeline.fregfile match {
case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile))
}
}
case _ =>
}
if (p(FireSimFAME5)) ls.totalTiles.values.map {
case b: BoomTile =>
annotate(EnableModelMultiThreadingAnnotation(b.module))
case r: RocketTile =>
annotate(EnableModelMultiThreadingAnnotation(r.module))
case _ => Nil
}
}
case _ =>
}
case _ =>
}
}

View File

@@ -13,7 +13,8 @@ import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.tilelink.{BootROMLocated, BootROMParams}
import freechips.rocketchip.devices.debug.{DebugModuleParams, DebugModuleKey}
import freechips.rocketchip.diplomacy.{LazyModule, AsynchronousCrossing}
import testchipip.{BlockDeviceKey, BlockDeviceConfig, TracePortKey, TracePortParams}
import testchipip.iceblk.{BlockDeviceKey, BlockDeviceConfig}
import testchipip.cosim.{TracePortKey, TracePortParams}
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
import scala.math.{min, max}
@@ -55,6 +56,16 @@ class WithScalaTestFeatures extends Config((site, here, up) => {
case TracePortKey => up(TracePortKey, site).map(_.copy(print = true))
})
// Multi-cycle regfile for rocket+boom
class WithFireSimMultiCycleRegfile extends Config((site, here, up) => {
case FireSimMultiCycleRegFile => true
})
// Model multithreading optimization
class WithFireSimFAME5 extends Config((site, here, up) => {
case FireSimFAME5 => true
})
// FASED Config Aliases. This to enable config generation via "_" concatenation
// which requires that all config classes be defined in the same package
class DDR3FCFS extends FCFS16GBQuadRank
@@ -72,7 +83,9 @@ class WithMinimalFireSimDesignTweaks extends Config(
// Required*: Punch all clocks to FireSim's harness clock instantiator
new WithFireSimHarnessClockBridgeInstantiator ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(1000.0) ++
new chipyard.harness.WithClockAndResetFromHarness ++
new chipyard.harness.WithClockFromHarness ++
new chipyard.harness.WithResetFromHarness ++
new chipyard.config.WithNoClockTap ++
new chipyard.clocking.WithPassthroughClockGenerator ++
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
new WithBootROM ++
@@ -87,18 +100,20 @@ class WithMinimalFireSimDesignTweaks extends Config(
// Non-frequency tweaks that are generally applied to all firesim configs
class WithFireSimDesignTweaks extends Config(
new WithMinimalFireSimDesignTweaks ++
// Required: Remove the debug clock tap, this breaks compilation of target-level sim in FireSim
new chipyard.config.WithNoClockTap ++
// Required: Bake in the default FASED memory model
new WithDefaultMemModel ++
// Optional: reduce the width of the Serial TL interface
new testchipip.WithSerialTLWidth(4) ++
new testchipip.serdes.WithSerialTLWidth(4) ++
// Required*: Scale default baud rate with periphery bus frequency
new chipyard.config.WithUARTInitBaudRate(BigInt(3686400L)) ++
// Optional: Adds IO to attach tracerV bridges
new chipyard.config.WithTraceIO ++
// Optional: Request 16 GiB of target-DRAM by default (can safely request up to 32 GiB on F1)
// Optional: Request 16 GiB of target-DRAM by default (can safely request up to 64 GiB on F1)
new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 16L) ++
// Optional: Removing this will require using an initramfs under linux
new testchipip.WithBlockDevice
new testchipip.iceblk.WithBlockDevice
)
// Tweaks to modify target clock frequencies / crossings to legacy firesim defaults
@@ -110,16 +125,17 @@ class WithFireSimHighPerfClocking extends Config(
// This frequency selection matches FireSim's legacy selection and is required
// to support 200Gb NIC performance. You may select a smaller value.
new chipyard.config.WithPeripheryBusFrequency(3200.0) ++
new chipyard.config.WithControlBusFrequency(3200.0) ++
new chipyard.config.WithSystemBusFrequency(3200.0) ++
new chipyard.config.WithFrontBusFrequency(3200.0) ++
new chipyard.config.WithControlBusFrequency(3200.0) ++
// Optional: These three configs put the DRAM memory system in it's own clock domain.
// 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
new chipyard.config.WithAsynchrousMemoryBusCrossing
)
// Tweaks that are generally applied to all firesim configs setting a single clock domain at 1000 MHz
@@ -128,8 +144,11 @@ class WithFireSimConfigTweaks extends Config(
// Using some other frequency will require runnings the FASED runtime configuration generator
// to generate faithful DDR3 timing values.
new chipyard.config.WithSystemBusFrequency(1000.0) ++
new chipyard.config.WithControlBusFrequency(1000.0) ++
new chipyard.config.WithPeripheryBusFrequency(1000.0) ++
new chipyard.config.WithControlBusFrequency(1000.0) ++
new chipyard.config.WithMemoryBusFrequency(1000.0) ++
new chipyard.config.WithFrontBusFrequency(1000.0) ++
new WithFireSimDesignTweaks
)
@@ -138,7 +157,7 @@ class WithFireSimConfigTweaks extends Config(
class WithMinimalFireSimHighPerfConfigTweaks extends Config(
new WithFireSimHighPerfClocking ++
new freechips.rocketchip.subsystem.WithNoMemPort ++
new testchipip.WithMbusScratchpad ++
new testchipip.soc.WithMbusScratchpad ++
new WithMinimalFireSimDesignTweaks
)
@@ -148,8 +167,8 @@ class WithMinimalFireSimHighPerfConfigTweaks extends Config(
class WithMinimalAndBlockDeviceFireSimHighPerfConfigTweaks extends Config(
new WithFireSimHighPerfClocking ++
new freechips.rocketchip.subsystem.WithNoMemPort ++ // removes mem port for FASEDBridge to match against
new testchipip.WithMbusScratchpad ++ // adds backing scratchpad for memory to replace FASED model
new testchipip.WithBlockDevice(true) ++ // add in block device
new testchipip.soc.WithMbusScratchpad ++ // adds backing scratchpad for memory to replace FASED model
new testchipip.iceblk.WithBlockDevice(true) ++ // add in block device
new WithMinimalFireSimDesignTweaks
)
@@ -175,13 +194,14 @@ class WithFireSimTestChipConfigTweaks extends Config(
new chipyard.config.WithSystemBusFrequency(500.0) ++ // Realistic system bus frequency
new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // Needs to be 1000 MHz to model DDR performance accurately
new chipyard.config.WithPeripheryBusFrequency(500.0) ++ // Match the sbus and pbus frequency
new chipyard.config.WithFrontBusFrequency(500.0) ++ // Match the sbus and fbus frequency
new chipyard.config.WithControlBusFrequency(500.0) ++ // Match the sbus and cbus frequency
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("sbus", "pbus", "fbus", "cbus", "implicit"), Seq("tile"))) ++
// Crossing specifications
new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS
new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
new boom.common.WithRationalBoomTiles ++ // Add rational crossings between BoomTile and uncore
new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS
new WithFireSimDesignTweaks
)
@@ -236,11 +256,18 @@ class FireSimSmallSystemConfig extends Config(
new WithDefaultMemModel ++
new WithBootROM ++
new chipyard.config.WithPeripheryBusFrequency(3200.0) ++
new chipyard.config.WithControlBusFrequency(3200.0) ++
new chipyard.config.WithSystemBusFrequency(3200.0) ++
new chipyard.config.WithFrontBusFrequency(3200.0) ++
new chipyard.config.WithMemoryBusFrequency(3200.0) ++
new WithoutClockGating ++
new WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
new testchipip.WithDefaultSerialTL ++
new testchipip.WithBlockDevice ++
new testchipip.serdes.WithSerialTL(Seq(testchipip.serdes.SerialTLParams(
client = Some(testchipip.serdes.SerialTLClientParams(idBits = 4)),
phyParams = testchipip.serdes.ExternalSyncSerialParams(width=32)
))) ++
new testchipip.iceblk.WithBlockDevice ++
new chipyard.config.WithUARTInitBaudRate(BigInt(3686400L)) ++
new freechips.rocketchip.subsystem.WithInclusiveCache(nWays = 2, capacityKB = 64) ++
new chipyard.RocketConfig)
@@ -289,6 +316,7 @@ class FireSimLeanGemminiPrintfRocketConfig extends Config(
//**********************************************************************************
class SupernodeFireSimRocketConfig extends Config(
new WithFireSimHarnessClockBridgeInstantiator ++
new WithDefaultMemModel ++ // this is a global for all the multi-chip configs
new chipyard.harness.WithHomogeneousMultiChip(n=4, new Config(
new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 8L) ++ // 8GB DRAM per node
new FireSimRocketConfig)))
@@ -317,7 +345,7 @@ class FireSim16LargeBoomConfig extends Config(
class FireSimNoMemPortConfig extends Config(
new WithDefaultFireSimBridges ++
new freechips.rocketchip.subsystem.WithNoMemPort ++
new testchipip.WithMbusScratchpad ++
new testchipip.soc.WithMbusScratchpad ++
new WithFireSimConfigTweaks ++
new chipyard.RocketConfig)

View File

@@ -13,19 +13,18 @@ import scala.math.{max, min}
class WithTraceGen(
n: Int = 2,
overrideIdOffset: Option[Int] = None,
overrideMemOffset: Option[BigInt] = None)(
params: Seq[DCacheParams] = List.fill(n){ DCacheParams(nSets = 16, nWays = 1) },
nReqs: Int = 8192
) extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => {
val prev = up(TilesLocated(InSubsystem), site)
val idOffset = overrideIdOffset.getOrElse(prev.size)
val idOffset = up(NumTiles)
val memOffset: BigInt = overrideMemOffset.orElse(site(ExtMem).map(_.master.base)).getOrElse(0x0L)
params.zipWithIndex.map { case (dcp, i) =>
TraceGenTileAttachParams(
tileParams = TraceGenParams(
hartId = i + idOffset,
tileId = i + idOffset,
dcache = Some(dcp),
wordBits = site(XLen),
addrBits = 48,
@@ -48,23 +47,23 @@ class WithTraceGen(
)
} ++ prev
}
case NumTiles => up(NumTiles) + n
})
class WithBoomTraceGen(
n: Int = 2,
overrideIdOffset: Option[Int] = None,
overrideMemOffset: Option[BigInt] = None)(
params: Seq[DCacheParams] = List.fill(n){ DCacheParams(nMSHRs = 4, nSets = 16, nWays = 2) },
nReqs: Int = 8192
) extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => {
val prev = up(TilesLocated(InSubsystem), site)
val idOffset = overrideIdOffset.getOrElse(prev.size)
val idOffset = up(NumTiles)
val memOffset: BigInt = overrideMemOffset.orElse(site(ExtMem).map(_.master.base)).getOrElse(0x0L)
params.zipWithIndex.map { case (dcp, i) =>
BoomTraceGenTileAttachParams(
tileParams = BoomTraceGenParams(
hartId = i + idOffset,
tileId = i + idOffset,
dcache = Some(dcp),
wordBits = site(XLen),
addrBits = 48,
@@ -84,24 +83,24 @@ class WithBoomTraceGen(
)
} ++ prev
}
case NumTiles => up(NumTiles) + n
})
class WithL2TraceGen(
n: Int = 2,
overrideIdOffset: Option[Int] = None,
overrideMemOffset: Option[BigInt] = None)(
params: Seq[DCacheParams] = List.fill(n){ DCacheParams(nSets = 16, nWays = 1) },
nReqs: Int = 8192
) extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => {
val prev = up(TilesLocated(InSubsystem), site)
val idOffset = overrideIdOffset.getOrElse(prev.size)
val idOffset = up(NumTiles)
val memOffset: BigInt = overrideMemOffset.orElse(site(ExtMem).map(_.master.base)).getOrElse(0x0L)
params.zipWithIndex.map { case (dcp, i) =>
TraceGenTileAttachParams(
tileParams = TraceGenParams(
hartId = i + idOffset,
tileId = i + idOffset,
dcache = Some(dcp),
wordBits = site(XLen),
addrBits = 48,
@@ -126,4 +125,5 @@ class WithL2TraceGen(
)
} ++ prev
}
case NumTiles => up(NumTiles) + n
})

View File

@@ -9,15 +9,28 @@ import freechips.rocketchip.subsystem._
import boom.lsu.BoomTraceGenTile
class TraceGenSystem(implicit p: Parameters) extends BaseSubsystem
with HasTiles
with InstantiatesHierarchicalElements
with HasTileNotificationSinks
with HasTileInputConstants
with HasHierarchicalElementsRootContext
with HasHierarchicalElements
with CanHaveMasterAXI4MemPort {
def coreMonitorBundles = Nil
val tileStatusNodes = tiles.collect {
val tileStatusNodes = totalTiles.values.toSeq.collect {
case t: GroundTestTile => t.statusNode.makeSink()
case t: BoomTraceGenTile => t.statusNode.makeSink()
}
lazy val debugNode = IntSyncXbar() := NullIntSyncSource()
lazy val fakeClockDomain = sbus.generateSynchronousDomain
lazy val clintOpt = None
lazy val debugOpt = None
lazy val plicOpt = None
lazy val clintDomainOpt = Some(fakeClockDomain)
lazy val plicDomainOpt = Some(fakeClockDomain)
override lazy val module = new TraceGenSystemModuleImp(this)
}