[clocking] Sketch out a topology that puts the MBUS is a separate domain
This commit is contained in:
100
generators/chipyard/src/main/scala/CustomBusTopologies.scala
Normal file
100
generators/chipyard/src/main/scala/CustomBusTopologies.scala
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
package chipyard
|
||||
|
||||
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util.{Location, Symmetric}
|
||||
import freechips.rocketchip.subsystem._
|
||||
|
||||
// I'm putting this code here temporarily as I think it should be a candidate
|
||||
// for upstreaming based on input from Henry Cook, but don't wnat to deal with
|
||||
// an RC branch just yet.
|
||||
|
||||
// For subsystem/BusTopology.scala
|
||||
|
||||
/**
|
||||
* Keys that serve as a means to define crossing types from a Parameters instance
|
||||
*/
|
||||
case object SubsystemCrossingParamsKey extends Field[SubsystemCrossingParams](SubsystemCrossingParams())
|
||||
case object MemoryBusCrossingTypeKey extends Field[ClockCrossingType](NoCrossing)
|
||||
|
||||
// Biancolin: This, modified from Henry's email
|
||||
/** Parameterization of a topology containing a banked coherence manager and a bus for attaching memory devices. */
|
||||
case class CoherentBusTopologyParams(
|
||||
sbus: SystemBusParams, // TODO remove this after better width propagation
|
||||
mbus: MemoryBusParams,
|
||||
l2: BankedL2Params,
|
||||
sbusToMbusXType: ClockCrossingType = NoCrossing
|
||||
) extends TLBusWrapperTopology(
|
||||
instantiations = (if (l2.nBanks == 0) Nil else List(
|
||||
(MBUS, mbus),
|
||||
(L2, CoherenceManagerWrapperParams(mbus.blockBytes, mbus.beatBytes, l2.nBanks, L2.name)(l2.coherenceManager)))),
|
||||
connections = if (l2.nBanks == 0) Nil else List(
|
||||
(SBUS, L2, TLBusWrapperConnection(xType = NoCrossing, driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()),
|
||||
(L2, MBUS, TLBusWrapperConnection.crossTo(
|
||||
xType = sbusToMbusXType,
|
||||
driveClockFromMaster = Some(true),
|
||||
nodeBinding = BIND_QUERY))
|
||||
)
|
||||
)
|
||||
|
||||
// For subsystem/Configs.scala
|
||||
|
||||
class WithCoherentBusTopology extends Config((site, here, up) => {
|
||||
case TLNetworkTopologyLocated(InSubsystem) => List(
|
||||
JustOneBusTopologyParams(sbus = site(SystemBusKey)),
|
||||
HierarchicalBusTopologyParams(
|
||||
pbus = site(PeripheryBusKey),
|
||||
fbus = site(FrontBusKey),
|
||||
cbus = site(ControlBusKey),
|
||||
xTypes = SubsystemCrossingParams()),
|
||||
CoherentBusTopologyParams(
|
||||
sbus = site(SystemBusKey),
|
||||
mbus = site(MemoryBusKey),
|
||||
l2 = site(BankedL2Key),
|
||||
sbusToMbusXType = site(MemoryBusCrossingTypeKey)))
|
||||
})
|
||||
|
||||
/**
|
||||
* Mixins to specify crossing types between the 5 traditional TL buses
|
||||
*
|
||||
* Note: these presuppose the legacy connections between buses and set
|
||||
* parameters in SubsystemCrossingParams; they may not be resuable in custom
|
||||
* topologies (but you can specify the desired crossings in your topology).
|
||||
*
|
||||
* @param xType The clock crossing type
|
||||
*
|
||||
*/
|
||||
class WithMemoryBusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
|
||||
case MemoryBusCrossingTypeKey => xType
|
||||
})
|
||||
|
||||
class WithFrontBusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
|
||||
case SubsystemCrossingParamsKey => up(SubsystemCrossingParamsKey, site)
|
||||
.copy(fbusToSbusXType = xType)
|
||||
})
|
||||
|
||||
class WithControlBusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
|
||||
case SubsystemCrossingParamsKey => up(SubsystemCrossingParamsKey, site)
|
||||
.copy(sbusToCbusXType = xType)
|
||||
})
|
||||
|
||||
class WithPeripheryBusCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
|
||||
case SubsystemCrossingParamsKey => up(SubsystemCrossingParamsKey, site)
|
||||
.copy(cbusToPbusXType = xType)
|
||||
})
|
||||
|
||||
/**
|
||||
* Mixins to set the dtsFrequency field of BusParams -- these will percolate it'st way
|
||||
* through the diplomatic clock graph to the clock sources.
|
||||
*/
|
||||
class WithPeripheryBusFrequency(freq: BigInt) extends Config((site, here, up) => {
|
||||
case PeripheryBusKey => up(PeripheryBusKey).copy(dtsFrequency = Some(freq))
|
||||
})
|
||||
class WithMemoryBusFrequency(freq: BigInt) extends Config((site, here, up) => {
|
||||
case MemoryBusKey => up(MemoryBusKey).copy(dtsFrequency = Some(freq))
|
||||
})
|
||||
|
||||
class WithRationalMemoryBusCrossing extends WithMemoryBusCrossingType(RationalCrossing(Symmetric))
|
||||
class WithAsynchrousMemoryBusCrossing extends WithMemoryBusCrossingType(AsynchronousCrossing())
|
||||
@@ -125,11 +125,11 @@ class WithSimNetwork extends OverrideHarnessBinder({
|
||||
})
|
||||
|
||||
class WithSimAXIMem extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
||||
val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p))
|
||||
withClockAndReset(port.clock, th.harnessReset) {
|
||||
withClockAndReset(port.clock, port.reset) {
|
||||
Module(mem.module).suggestName("mem")
|
||||
}
|
||||
mem.io_axi4.head <> port.bits
|
||||
@@ -139,7 +139,7 @@ class WithSimAXIMem extends OverrideHarnessBinder({
|
||||
})
|
||||
|
||||
class WithBlackBoxSimMem extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
||||
val memSize = p(ExtMem).get.master.size
|
||||
@@ -147,18 +147,18 @@ class WithBlackBoxSimMem extends OverrideHarnessBinder({
|
||||
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle)).suggestName("simdram")
|
||||
mem.io.axi <> port.bits
|
||||
mem.io.clock := port.clock
|
||||
mem.io.reset := th.harnessReset
|
||||
mem.io.reset := port.reset
|
||||
}
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimAXIMMIO extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
||||
(system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||
(ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) =>
|
||||
val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p))
|
||||
withClockAndReset(port.clock, th.harnessReset) {
|
||||
withClockAndReset(port.clock, port.reset) {
|
||||
Module(mmio_mem.module).suggestName("mmio_mem")
|
||||
}
|
||||
mmio_mem.io_axi4.head <> port.bits
|
||||
|
||||
@@ -108,14 +108,23 @@ class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implici
|
||||
})
|
||||
|
||||
object BoreHelper {
|
||||
def apply(name: String, source: Clock): Clock = {
|
||||
val clock_io = IO(Output(Clock())).suggestName(name)
|
||||
val clock_wire = Wire(Clock()).suggestName(s"chiptop_${name}")
|
||||
dontTouch(clock_wire)
|
||||
clock_wire := false.B.asClock // necessary for BoringUtils to work properly
|
||||
BoringUtils.bore(source, Seq(clock_wire))
|
||||
clock_io := clock_wire
|
||||
clock_io
|
||||
def apply[T <: Data](name: String, source: T): T = {
|
||||
val (io, wire) = source match {
|
||||
case c: Clock =>
|
||||
val wire = Wire(Clock())
|
||||
wire := false.B.asClock
|
||||
(IO(Output(Clock())), wire)
|
||||
case r: Reset =>
|
||||
val wire = Wire(Reset())
|
||||
wire := false.B
|
||||
(IO(Output(Reset())), wire)
|
||||
}
|
||||
io.suggestName(name)
|
||||
wire.suggestName(s"chiptop_${name}")
|
||||
dontTouch(wire)
|
||||
BoringUtils.bore(source, Seq(wire))
|
||||
io := wire
|
||||
io.asInstanceOf[source.type]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,10 +266,11 @@ class WithSerialTLIOCells extends OverrideIOBinder({
|
||||
|
||||
class WithAXI4MemPunchthrough extends OverrideIOBinder({
|
||||
(system: CanHaveMasterAXI4MemPort) => {
|
||||
val ports: Seq[ClockedIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
||||
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
||||
p.bits <> m
|
||||
p.clock := BoreHelper("axi4_mem_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock)
|
||||
p.reset := BoreHelper("axi4_mem_reset", system.asInstanceOf[BaseSubsystem].mbus.module.reset)
|
||||
p
|
||||
})
|
||||
(ports, Nil)
|
||||
|
||||
@@ -49,6 +49,6 @@ class AbstractConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
|
||||
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache
|
||||
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2
|
||||
new chipyard.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2
|
||||
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
|
||||
|
||||
|
||||
@@ -178,6 +178,8 @@ class DividedClockRocketConfig extends Config(
|
||||
new chipyard.config.WithTileFrequency(200.0) ++
|
||||
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.WithMemoryBusFrequency(50 * 1000 * 1000) ++
|
||||
new chipyard.WithAsynchrousMemoryBusCrossing ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class LBWIFRocketConfig extends Config(
|
||||
|
||||
@@ -97,14 +97,14 @@ class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
||||
})
|
||||
|
||||
class WithFASEDBridge extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) =>
|
||||
val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth,
|
||||
axi4.bits.ar.bits.addr.getWidth,
|
||||
axi4.bits.ar.bits.id.getWidth)
|
||||
system match {
|
||||
case s: BaseSubsystem => FASEDBridge(axi4.clock, axi4.bits, th.harnessReset.asBool,
|
||||
case s: BaseSubsystem => FASEDBridge(axi4.clock, axi4.bits, axi4.reset.asBool,
|
||||
CompleteConfig(p(firesim.configs.MemModelKey),
|
||||
nastiKey,
|
||||
Some(AXI4EdgeSummary(edge)),
|
||||
|
||||
@@ -73,6 +73,12 @@ class WithFireSimConfigTweaks extends Config(
|
||||
// Optional*: Removing this will require adjusting the UART baud rate and
|
||||
// potential target-software changes to properly capture UART output
|
||||
new WithPeripheryBusFrequency(BigInt(3200000000L)) ++
|
||||
// Optional: Removing these two configs 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 * 1000 * 1000) ++
|
||||
new chipyard.config.WithAsynchrousMemoryBusCrossing ++
|
||||
// Required: Existing FAME-1 transform cannot handle black-box clock gates
|
||||
new WithoutClockGating ++
|
||||
// Required*: Removes thousands of assertions that would be synthesized (* pending PriorityMux bugfix)
|
||||
|
||||
Submodule generators/testchipip updated: 10351d36a9...b3987a3a78
Reference in New Issue
Block a user