diff --git a/generators/chipyard/src/main/scala/Clocks.scala b/generators/chipyard/src/main/scala/Clocks.scala index 554e9905..4219c914 100644 --- a/generators/chipyard/src/main/scala/Clocks.scala +++ b/generators/chipyard/src/main/scala/Clocks.scala @@ -8,11 +8,11 @@ import freechips.rocketchip.prci._ import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey} import freechips.rocketchip.config.{Parameters, Field, Config} import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule} -import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider} +import freechips.rocketchip.util.{ResetCatchAndSync} import barstools.iocell.chisel._ -import chipyard.clocking.{DividerOnlyClockGenerator, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier} +import chipyard.clocking._ /** * Chipyard provides three baseline, top-level reset schemes, set using the @@ -116,6 +116,7 @@ object ClockingSchemeGenerators { val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters())) (aggregator := ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey)) + := ClockGroupResetSynchronizer() := DividerOnlyClockGenerator() := referenceClockSource) diff --git a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala index 4355fc71..fb816c35 100644 --- a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala +++ b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala @@ -62,6 +62,10 @@ case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValN * fast reference clock (roughly LCM(requested frequencies)) which is passed up the * diplomatic graph, and then generates dividers for each unique requested * frequency. + * + * Output resets are not synchronized to generated clocks and should be + * synchronized by the user in a manner they see fit. + * */ class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule { @@ -87,6 +91,7 @@ class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) { val div = pllConfig.sinkDividerMap(sinkP) sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div)) + // Reset handling and synchronization is expected to be handled by a downstream node sinkB.reset := refClock.reset } } diff --git a/generators/chipyard/src/main/scala/clocking/ResetSynchronizer.scala b/generators/chipyard/src/main/scala/clocking/ResetSynchronizer.scala new file mode 100644 index 00000000..13a593c5 --- /dev/null +++ b/generators/chipyard/src/main/scala/clocking/ResetSynchronizer.scala @@ -0,0 +1,30 @@ + +package chipyard.clocking + +import chisel3._ + +import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.prci._ +import freechips.rocketchip.util.{ResetCatchAndSync} + +/** + * Instantiates a reset synchronizer on all clock-reset pairs in a clock group + */ +class ClockGroupResetSynchronizer(implicit p: Parameters) extends LazyModule { + val node = ClockGroupIdentityNode() + lazy val module = new LazyRawModuleImp(this) { + (node.out zip node.in).map { case ((oG, _), (iG, _)) => + (oG.member.data zip iG.member.data).foreach { case (o, i) => + o.clock := i.clock + o.reset := ResetCatchAndSync(i.clock, i.reset.asBool) + } + } + } +} + +object ClockGroupResetSynchronizer { + def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new ClockGroupResetSynchronizer()).node +} + + diff --git a/generators/firechip/src/main/scala/FireSim.scala b/generators/firechip/src/main/scala/FireSim.scala index 90fd473a..cfca74f8 100644 --- a/generators/firechip/src/main/scala/FireSim.scala +++ b/generators/firechip/src/main/scala/FireSim.scala @@ -16,7 +16,7 @@ import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock import chipyard._ import chipyard.harness._ import chipyard.iobinders._ -import chipyard.clocking.{FrequencyUtils, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier, SimplePllConfiguration} +import chipyard.clocking._ // Determines the number of times to instantiate the DUT in the harness. // Subsumes legacy supernode support @@ -101,6 +101,7 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => { val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters())) (aggregator + := ClockGroupResetSynchronizer() := ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey)) := inputClockSource) @@ -113,15 +114,7 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => { (clockGroupBundle.member.data zip input_clocks.data).foreach { case (clockBundle, inputClock) => clockBundle.clock := inputClock - } - - // Assign resets. The synchronization scheme is still WIP. - for ((name, clockBundle) <- clockGroupBundle.member.elements) { - if (name.contains("core")) { - clockBundle.reset := ResetCatchAndSync(clockBundle.clock, reset.asBool) - } else { - clockBundle.reset := reset - } + clockBundle.reset := reset } val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)