Add PortAPI between IO and Harness blocks

This commit is contained in:
Jerry Zhao
2023-10-02 17:30:13 -07:00
parent 8c1319073c
commit eb3a0aecf4
32 changed files with 715 additions and 822 deletions

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,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)
}
})

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.{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 _ =>
}
}

View File

@@ -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 ++