Add PortAPI between IO and Harness blocks
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
package firesim.firesim
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.annotate
|
||||
import chisel3.experimental.{DataMirror, Direction}
|
||||
import chisel3.util.experimental.BoringUtils
|
||||
|
||||
@@ -12,7 +11,6 @@ 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._
|
||||
@@ -22,21 +20,19 @@ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvon
|
||||
|
||||
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 +65,65 @@ 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) => {
|
||||
val bits = port.io.bits
|
||||
port.io.clock := th.harnessBinderClock
|
||||
val ram = LazyModule(new SerialRAM(port.serdesser)(Parameters.empty))
|
||||
Module(ram.module)
|
||||
ram.module.io.ser <> port.io.bits
|
||||
TSIBridge(th.harnessBinderClock, ram.module.io.tsi,
|
||||
port.params.serialTLManagerParams.map(_ => MainMemoryConsts.globalName(th.p(MultiChipIdx))), th.harnessBinderReset.asBool)(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
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 WithNICBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: NICPort) => {
|
||||
NICBridge(port.io.clock, port.io.bits)(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
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 WithUARTBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: UARTPort) =>
|
||||
val uartSyncClock = th.harnessClockInstantiator.requestClockMHz("uart_clock", port.freqMHz)
|
||||
UARTBridge(uartSyncClock, port.io, th.harnessBinderReset.asBool)(th.p)
|
||||
})
|
||||
|
||||
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 WithBlockDeviceBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: BlockDevicePort) => {
|
||||
BlockDevBridge(port.io.clock, port.io.bits, th.harnessBinderReset.asBool)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
Nil
|
||||
class WithFASEDBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: AXI4MemPort) => {
|
||||
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(th.p(MultiChipIdx)))))(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
class WithTracerVBridge extends ComposeHarnessBinder({
|
||||
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => {
|
||||
ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
|
||||
Nil
|
||||
class WithTracerVBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: TracePort) => {
|
||||
port.io.traces.map(tileTrace => TracerVBridge(tileTrace)(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 WithCospikeBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: TracePort) => {
|
||||
port.io.traces.zipWithIndex.map(t => CospikeBridge(t._1, t._2, port.cosimCfg))
|
||||
}
|
||||
})
|
||||
|
||||
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 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 WithSuccessBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: SuccessPort) => {
|
||||
GroundTestBridge(th.harnessBinderClock, port.io)(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey, HasTiles}
|
||||
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: HasTiles => {
|
||||
if (p(FireSimMultiCycleRegFile)) ls.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 _ =>
|
||||
}
|
||||
if (p(FireSimFAME5)) ls.tiles.map {
|
||||
case b: BoomTile =>
|
||||
annotate(EnableModelMultiThreadingAnnotation(b.module))
|
||||
case r: RocketTile =>
|
||||
annotate(EnableModelMultiThreadingAnnotation(r.module))
|
||||
case _ => Nil
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,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 +82,8 @@ 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.clocking.WithPassthroughClockGenerator ++
|
||||
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
|
||||
new WithBootROM ++
|
||||
|
||||
Reference in New Issue
Block a user