From 986b5831c871d74608f689c6f9c978ec394d0572 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Fri, 9 Oct 2020 07:23:17 -0700 Subject: [PATCH] [clocking] Sketch out a topology that puts the MBUS is a separate domain --- .../src/main/scala/CustomBusTopologies.scala | 100 ++++++++++++++++++ .../src/main/scala/HarnessBinders.scala | 12 +-- .../chipyard/src/main/scala/IOBinders.scala | 30 ++++-- .../main/scala/config/AbstractConfig.scala | 2 +- .../src/main/scala/config/RocketConfigs.scala | 2 + .../src/main/scala/BridgeBinders.scala | 4 +- .../src/main/scala/TargetConfigs.scala | 6 ++ generators/testchipip | 2 +- 8 files changed, 138 insertions(+), 20 deletions(-) create mode 100644 generators/chipyard/src/main/scala/CustomBusTopologies.scala diff --git a/generators/chipyard/src/main/scala/CustomBusTopologies.scala b/generators/chipyard/src/main/scala/CustomBusTopologies.scala new file mode 100644 index 00000000..5dbcfe1d --- /dev/null +++ b/generators/chipyard/src/main/scala/CustomBusTopologies.scala @@ -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()) diff --git a/generators/chipyard/src/main/scala/HarnessBinders.scala b/generators/chipyard/src/main/scala/HarnessBinders.scala index e5cfacfb..b5992c7b 100644 --- a/generators/chipyard/src/main/scala/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/HarnessBinders.scala @@ -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 diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 4a31e2c0..1ba6c0a9 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -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) diff --git a/generators/chipyard/src/main/scala/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala index 9b04788c..c4b1c9cf 100644 --- a/generators/chipyard/src/main/scala/config/AbstractConfig.scala +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -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 diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index 11399a62..e89727f1 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -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( diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index 5a0b4837..8fa0b54e 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -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)), diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index b70ef647..6ff5065f 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -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) diff --git a/generators/testchipip b/generators/testchipip index 10351d36..b3987a3a 160000 --- a/generators/testchipip +++ b/generators/testchipip @@ -1 +1 @@ -Subproject commit 10351d36a961d89e6f5ac1177dff0e9f3efb8c0f +Subproject commit b3987a3a784c7175c81aa58016fb3e2df58924c2