From 9a5673ddef7e5dd925a3a0d352553b85f1e973c9 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 5 May 2023 11:26:27 -0700 Subject: [PATCH 1/2] Add singleclock broadcast clockbinder --- .../main/scala/clocking/ClockBinders.scala | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala index d075fcbb..3582ba08 100644 --- a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala +++ b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala @@ -102,6 +102,42 @@ class WithPassthroughClockGenerator extends OverrideLazyIOBinder({ } }) +// Broadcasts a single clock IO to all clock domains +class WithSingleClockBroadcastClockGenerator extends OverrideLazyIOBinder({ + (system: HasChipyardPRCI) => { + implicit val p = GetSystemParameters(system) + val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock")))) + system.connectImplicitClockSinkNode(implicitClockSinkNode) + InModuleBody { + val implicit_clock = implicitClockSinkNode.in.head._1.clock + val implicit_reset = implicitClockSinkNode.in.head._1.reset + system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => { + l.clock := implicit_clock + l.reset := implicit_reset + }} + } + + val clockGroupsAggregateNode = ClockGroupAggregateNode("single_clock") + val clockGroupsSourceNode = ClockGroupSourceNode(Seq(ClockGroupSourceParameters())) + system.allClockGroupsNode :*= clockGroupsAggregateNode := clockGroupsSourceNode + + InModuleBody { + val clock_wire = Wire(Input(new ClockWithFreq(100))) + val reset_wire = Wire(Input(AsyncReset())) + val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey)) + val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey)) + + clockGroupsSourceNode.out.foreach { case (bundle, edge) => + bundle.member.data.foreach { b => + b.clock := clock_io.clock + b.reset := reset_io + } + } + (Seq(clock_io, reset_io), clockIOCell ++ resetIOCell) + } + } +}) + class WithClockTapIOCells extends OverrideIOBinder({ (system: CanHaveClockTap) => { system.clockTapIO.map { tap => From 17f784bfd331cc7335dae49e5b26054342a1c252 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Tue, 28 May 2024 12:26:18 -0700 Subject: [PATCH 2/2] Add example clocking configs and SingleClockBroadcast option --- .../main/scala/clocking/ClockBinders.scala | 26 +++++--------- .../main/scala/config/ClockingConfigs.scala | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+), 18 deletions(-) create mode 100644 generators/chipyard/src/main/scala/config/ClockingConfigs.scala diff --git a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala index 3582ba08..bcf2fb49 100644 --- a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala +++ b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala @@ -72,7 +72,7 @@ class WithPLLSelectorDividerClockGenerator(enable: Boolean = true) extends Overr } } }) - + // This passes all clocks through to the TestHarness class WithPassthroughClockGenerator extends OverrideLazyIOBinder({ (system: HasChipyardPRCI) => { @@ -102,38 +102,28 @@ class WithPassthroughClockGenerator extends OverrideLazyIOBinder({ } }) -// Broadcasts a single clock IO to all clock domains -class WithSingleClockBroadcastClockGenerator extends OverrideLazyIOBinder({ +// Broadcasts a single clock IO to all clock domains. Ignores all requested frequencies +class WithSingleClockBroadcastClockGenerator(freqMHz: Int = 100) extends OverrideLazyIOBinder({ (system: HasChipyardPRCI) => { implicit val p = GetSystemParameters(system) - val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock")))) - system.connectImplicitClockSinkNode(implicitClockSinkNode) - InModuleBody { - val implicit_clock = implicitClockSinkNode.in.head._1.clock - val implicit_reset = implicitClockSinkNode.in.head._1.reset - system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => { - l.clock := implicit_clock - l.reset := implicit_reset - }} - } - val clockGroupsAggregateNode = ClockGroupAggregateNode("single_clock") + val clockGroupsAggregator = LazyModule(new ClockGroupAggregator("single_clock")) val clockGroupsSourceNode = ClockGroupSourceNode(Seq(ClockGroupSourceParameters())) - system.allClockGroupsNode :*= clockGroupsAggregateNode := clockGroupsSourceNode + system.chiptopClockGroupsNode :*= clockGroupsAggregator.node := clockGroupsSourceNode InModuleBody { - val clock_wire = Wire(Input(new ClockWithFreq(100))) + val clock_wire = Wire(Input(Clock())) val reset_wire = Wire(Input(AsyncReset())) val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey)) val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey)) clockGroupsSourceNode.out.foreach { case (bundle, edge) => bundle.member.data.foreach { b => - b.clock := clock_io.clock + b.clock := clock_io b.reset := reset_io } } - (Seq(clock_io, reset_io), clockIOCell ++ resetIOCell) + (Seq(ClockPort(() => clock_io, freqMHz), ResetPort(() => reset_io)), clockIOCell ++ resetIOCell) } } }) diff --git a/generators/chipyard/src/main/scala/config/ClockingConfigs.scala b/generators/chipyard/src/main/scala/config/ClockingConfigs.scala new file mode 100644 index 00000000..0d3197ea --- /dev/null +++ b/generators/chipyard/src/main/scala/config/ClockingConfigs.scala @@ -0,0 +1,34 @@ +package chipyard + +import org.chipsalliance.cde.config.{Config} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.subsystem.{MBUS, SBUS} +import testchipip.soc.{OBUS} + +//================================================== +// This file contains examples of the different ways +// clocks can be generated for chiypard designs +//================================================== + +// The default constructs IOs for all requested clocks in the chiptopClockGroupsNode +// Note: This is what designs inheriting from AbstractConfig do by default +class DefaultClockingRocketConfig extends Config( + new chipyard.clocking.WithPassthroughClockGenerator ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new chipyard.config.AbstractConfig) + +// This is a more physically realistic approach, normally we can't punch out a separate +// pin for each clock domain. The standard "test chip" approach is to punch a few slow clock +// inputs, integrate a PLL, and generate an array of selectors/dividers to configure the +// clocks for each domain. See the source for WithPLLSelectorDividerClockGenerator for more info +class ChipLikeClockingRocketConfig extends Config( + new chipyard.clocking.WithPLLSelectorDividerClockGenerator ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new chipyard.config.AbstractConfig) + +// This merges all the clock domains in chiptopClockGroupsNode into one, then generates a single +// clock input pin. +class SingleClockBroadcastRocketConfig extends Config( + new chipyard.clocking.WithSingleClockBroadcastClockGenerator ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new chipyard.config.AbstractConfig)