[clocking] Synchronize all output clocks from DividerOnly generator
This commit is contained in:
@@ -8,11 +8,11 @@ import freechips.rocketchip.prci._
|
|||||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
||||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||||
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
|
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
|
||||||
import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider}
|
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||||
|
|
||||||
import barstools.iocell.chisel._
|
import barstools.iocell.chisel._
|
||||||
|
|
||||||
import chipyard.clocking.{DividerOnlyClockGenerator, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier}
|
import chipyard.clocking._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chipyard provides three baseline, top-level reset schemes, set using the
|
* Chipyard provides three baseline, top-level reset schemes, set using the
|
||||||
@@ -116,6 +116,7 @@ object ClockingSchemeGenerators {
|
|||||||
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
||||||
(aggregator
|
(aggregator
|
||||||
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||||
|
:= ClockGroupResetSynchronizer()
|
||||||
:= DividerOnlyClockGenerator()
|
:= DividerOnlyClockGenerator()
|
||||||
:= referenceClockSource)
|
:= referenceClockSource)
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValN
|
|||||||
* fast reference clock (roughly LCM(requested frequencies)) which is passed up the
|
* fast reference clock (roughly LCM(requested frequencies)) which is passed up the
|
||||||
* diplomatic graph, and then generates dividers for each unique requested
|
* diplomatic graph, and then generates dividers for each unique requested
|
||||||
* frequency.
|
* 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 {
|
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)) {
|
for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) {
|
||||||
val div = pllConfig.sinkDividerMap(sinkP)
|
val div = pllConfig.sinkDividerMap(sinkP)
|
||||||
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
|
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
|
||||||
|
// Reset handling and synchronization is expected to be handled by a downstream node
|
||||||
sinkB.reset := refClock.reset
|
sinkB.reset := refClock.reset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock
|
|||||||
import chipyard._
|
import chipyard._
|
||||||
import chipyard.harness._
|
import chipyard.harness._
|
||||||
import chipyard.iobinders._
|
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.
|
// Determines the number of times to instantiate the DUT in the harness.
|
||||||
// Subsumes legacy supernode support
|
// Subsumes legacy supernode support
|
||||||
@@ -101,6 +101,7 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
|||||||
val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
||||||
|
|
||||||
(aggregator
|
(aggregator
|
||||||
|
:= ClockGroupResetSynchronizer()
|
||||||
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||||
:= inputClockSource)
|
:= inputClockSource)
|
||||||
|
|
||||||
@@ -113,15 +114,7 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
|||||||
|
|
||||||
(clockGroupBundle.member.data zip input_clocks.data).foreach { case (clockBundle, inputClock) =>
|
(clockGroupBundle.member.data zip input_clocks.data).foreach { case (clockBundle, inputClock) =>
|
||||||
clockBundle.clock := inputClock
|
clockBundle.clock := inputClock
|
||||||
}
|
clockBundle.reset := reset
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)
|
val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)
|
||||||
|
|||||||
Reference in New Issue
Block a user