From 71fe1ad8585ec0b5031c4acce093e2cd0e80e00f Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 10 May 2023 14:30:58 -0700 Subject: [PATCH 01/12] Switch RTL sims to absolute clock-generators --- .../chipyard/src/main/scala/IOBinders.scala | 1 - .../main/scala/clocking/ClockBinders.scala | 84 +++++++++---------- .../clocking/DividerOnlyClockGenerator.scala | 54 ------------ .../main/scala/config/AbstractConfig.scala | 7 +- .../main/scala/config/TracegenConfigs.scala | 3 +- .../main/scala/harness/HarnessClocks.scala | 38 --------- .../src/main/scala/harness/TestHarness.scala | 2 +- 7 files changed, 46 insertions(+), 143 deletions(-) diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 1e234144d0..8dd0020ea7 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -25,7 +25,6 @@ import barstools.iocell.chisel._ import testchipip._ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} import chipyard.{CanHaveMasterTLMemPort} -import chipyard.clocking.{HasChipyardPRCI, DividerOnlyClockGenerator} import scala.reflect.{ClassTag} diff --git a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala index 5a02277c31..c91f5cb492 100644 --- a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala +++ b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala @@ -13,53 +13,11 @@ class ClockWithFreq(val freqMHz: Double) extends Bundle { val clock = Clock() } -// This uses synthesizable clock divisors to approximate frequency rations -// between the requested clocks. This is currently the defualt clock generator "model", -// as it can be used in VCS/Xcelium/Verilator/FireSim -class WithDividerOnlyClockGenerator extends OverrideLazyIOBinder({ - (system: HasChipyardPRCI) => { - // Connect the implicit clock - 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 - }} - } - - // Connect all other requested clocks - val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters())) - val dividerOnlyClockGen = LazyModule(new DividerOnlyClockGenerator("buildTopClockGenerator")) - - (system.allClockGroupsNode - := dividerOnlyClockGen.node - := referenceClockSource) - - InModuleBody { - val clock_wire = Wire(Input(new ClockWithFreq(dividerOnlyClockGen.module.referenceFreq))) - 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)) - - referenceClockSource.out.unzip._1.map { o => - o.clock := clock_wire.clock - o.reset := reset_wire - } - - (Seq(clock_io, reset_io), clockIOCell ++ resetIOCell) - } - } -}) - // This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate // the requested clocks. This also adds TileLink ClockDivider and ClockSelector // blocks, which allow memory-mapped control of clock division, and clock muxing // between the FakePLL and the slow off-chip clock -// Note: This will not simulate properly with verilator or firesim +// Note: This will not simulate properly with firesim class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({ (system: HasChipyardPRCI) => { // Connect the implicit clock @@ -100,7 +58,7 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({ pllCtrlSink := pllCtrl.ctrlNode InModuleBody { - val clock_wire = Wire(Input(new ClockWithFreq(80))) + 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)) @@ -125,3 +83,41 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({ } } }) + +// This passes all clocks through to the TestHarness +class WithPassthroughClockGenerator extends OverrideLazyIOBinder({ + (system: HasChipyardPRCI) => { + // Connect the implicit clock + 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 + }} + } + + // This aggregate node should do nothing + val clockGroupAggNode = ClockGroupAggregateNode("fake") + val clockGroupsSourceNode = ClockGroupSourceNode(Seq(ClockGroupSourceParameters())) + system.allClockGroupsNode :*= clockGroupAggNode := clockGroupsSourceNode + + InModuleBody { + val reset_io = IO(Input(AsyncReset())) + val clock_ios = clockGroupAggNode.out.map { case (bundle, edge) => + val freqs = edge.sink.members.map(_.take.map(_.freqMHz)).flatten + require(freqs.distinct.size == 1) + val clock_io = IO(Input(new ClockWithFreq(freqs.head))).suggestName(s"clock_${edge.sink.name}") + bundle.member.data.foreach { b => + b.clock := clock_io.clock + b.reset := reset_io + } + clock_io + } + ((clock_ios :+ reset_io), Nil) + } + } +}) diff --git a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala index 121cca24f9..0458c62146 100644 --- a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala +++ b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala @@ -92,57 +92,3 @@ class SimplePllConfiguration( def referenceSinkParams(): ClockSinkParameters = sinkDividerMap.find(_._2 == 1).get._1 } -case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName) - extends MixedNexusNode(ClockImp, ClockGroupImp)( - dFn = { _ => ClockGroupSourceParameters() }, - uFn = { u => - require(u.size == 1) - require(!u.head.members.contains(None), - "All output clocks in group must set their take parameters. Use a ClockGroupDealiaser") - ClockSinkParameters( - name = Some(s"${pllName}_reference_input"), - take = Some(ClockParameters(new SimplePllConfiguration(pllName, u.head.members).referenceFreqMHz))) } - ) - -/** - * Generates a digital-divider-only PLL model that verilator can simulate. - * Inspects all take-specified frequencies in the output ClockGroup, calculates a - * 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 { - val node = DividerOnlyClockGeneratorNode(pllName) - - lazy val module = new Impl - class Impl extends LazyRawModuleImp(this) { - require(node.out.size == 1, "Idealized PLL expects to generate a single output clock group. Use a ClockGroupAggregator") - val (refClock, ClockEdgeParameters(_, refSinkParam, _, _)) = node.in.head - val (outClocks, ClockGroupEdgeParameters(_, outSinkParams, _, _)) = node.out.head - - val referenceFreq = refSinkParam.take.get.freqMHz - val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members) - pllConfig.emitSummaries() - - val dividedClocks = mutable.HashMap[Int, Clock]() - def instantiateDivider(div: Int): Clock = { - val divider = Module(new ClockDividerN(div)) - divider.suggestName(s"ClockDivideBy${div}") - divider.io.clk_in := refClock.clock - dividedClocks(div) = divider.io.clk_out - divider.io.clk_out - } - - 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/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala index ceee4c0fa9..02ab9b5a2c 100644 --- a/generators/chipyard/src/main/scala/config/AbstractConfig.scala +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -23,6 +23,7 @@ class AbstractConfig extends Config( new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present new chipyard.harness.WithCustomBootPinPlusArg ++ new chipyard.harness.WithClockAndResetFromHarness ++ + new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // The IOBinders instantiate ChipTop IOs to match desired digital IOs // IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through @@ -41,10 +42,8 @@ class AbstractConfig extends Config( new chipyard.iobinders.WithExtInterruptIOCells ++ new chipyard.iobinders.WithCustomBootPin ++ - // Default behavior is to use a divider-only clock-generator - // This works in VCS, Verilator, and FireSim/ - // This should get replaced with a PLL-like config instead - new chipyard.clocking.WithDividerOnlyClockGenerator ++ + // By default, punch out IOs to the Harness + new chipyard.clocking.WithPassthroughClockGenerator ++ new testchipip.WithCustomBootPin ++ // add a custom-boot-pin to support pin-driven boot address new testchipip.WithBootAddrReg ++ // add a boot-addr-reg for configurable boot address diff --git a/generators/chipyard/src/main/scala/config/TracegenConfigs.scala b/generators/chipyard/src/main/scala/config/TracegenConfigs.scala index b92b2f4601..3c2b9a0cd4 100644 --- a/generators/chipyard/src/main/scala/config/TracegenConfigs.scala +++ b/generators/chipyard/src/main/scala/config/TracegenConfigs.scala @@ -4,12 +4,13 @@ import org.chipsalliance.cde.config.{Config} import freechips.rocketchip.rocket.{DCacheParams} class AbstractTraceGenConfig extends Config( + new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ new chipyard.harness.WithBlackBoxSimMem ++ new chipyard.harness.WithTraceGenSuccess ++ new chipyard.harness.WithClockAndResetFromHarness ++ new chipyard.iobinders.WithAXI4MemPunchthrough ++ new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++ - new chipyard.clocking.WithDividerOnlyClockGenerator ++ + new chipyard.clocking.WithPassthroughClockGenerator ++ new chipyard.config.WithTracegenSystem ++ new chipyard.config.WithNoSubsystemDrivenClocks ++ new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ diff --git a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala index 513ca38c79..22c7417e7b 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala @@ -36,44 +36,6 @@ trait HarnessClockInstantiator { def instantiateHarnessClocks(refClock: ClockBundle): Unit } -// The DividerOnlyHarnessClockInstantiator uses synthesizable clock divisors -// to approximate frequency ratios between the requested clocks -class DividerOnlyHarnessClockInstantiator extends HarnessClockInstantiator { - // connect all clock wires specified to a divider only PLL - def instantiateHarnessClocks(refClock: ClockBundle): Unit = { - val sinks = _clockMap.map({ case (name, (freq, bundle)) => - ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))), name=Some(name)) - }).toSeq - - val pllConfig = new SimplePllConfiguration("harnessDividerOnlyClockGenerator", sinks) - pllConfig.emitSummaries() - - val dividedClocks = LinkedHashMap[Int, Clock]() - def instantiateDivider(div: Int): Clock = { - val divider = Module(new ClockDividerN(div)) - divider.suggestName(s"ClockDivideBy${div}") - divider.io.clk_in := refClock.clock - dividedClocks(div) = divider.io.clk_out - divider.io.clk_out - } - - // connect wires to clock source - for (sinkParams <- sinks) { - // bypass the reference freq. (don't create a divider + reset sync) - val (divClock, divReset) = if (sinkParams.take.get.freqMHz != pllConfig.referenceFreqMHz) { - val div = pllConfig.sinkDividerMap(sinkParams) - val divClock = dividedClocks.getOrElse(div, instantiateDivider(div)) - (divClock, ResetCatchAndSync(divClock, refClock.reset.asBool)) - } else { - (refClock.clock, refClock.reset) - } - - _clockMap(sinkParams.name.get)._2.clock := divClock - _clockMap(sinkParams.name.get)._2.reset := divReset - } - } -} - // The AbsoluteFreqHarnessClockInstantiator uses a Verilog blackbox to // provide the precise requested frequency. // This ClockInstantiator cannot be synthesized, run in Verilator, or run in FireSim diff --git a/generators/chipyard/src/main/scala/harness/TestHarness.scala b/generators/chipyard/src/main/scala/harness/TestHarness.scala index 22bcc1670a..cb8cfe4765 100644 --- a/generators/chipyard/src/main/scala/harness/TestHarness.scala +++ b/generators/chipyard/src/main/scala/harness/TestHarness.scala @@ -19,7 +19,7 @@ import chipyard.{ChipTop} case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p)) case object DefaultClockFrequencyKey extends Field[Double](100.0) // MHz -case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator](() => new DividerOnlyHarnessClockInstantiator) +case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator]() trait HasHarnessSignalReferences { implicit val p: Parameters From 5c8ea080eed8e710d8043704df60173067821558 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 10 May 2023 16:52:42 -0700 Subject: [PATCH 02/12] Switch to our own ClockSourceAtFreq that is verilator-compatible --- .../main/scala/harness/HarnessClocks.scala | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala index 22c7417e7b..585062a5ef 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala @@ -1,7 +1,8 @@ package chipyard.harness import chisel3._ - +import chisel3.util._ +import chisel3.experimental.DoubleParam import scala.collection.mutable.{ArrayBuffer, LinkedHashMap} import freechips.rocketchip.diplomacy.{LazyModule} import org.chipsalliance.cde.config.{Field, Parameters, Config} @@ -36,6 +37,26 @@ trait HarnessClockInstantiator { def instantiateHarnessClocks(refClock: ClockBundle): Unit } +class ClockSourceAtFreqMHz(val freqMHz: Double) extends BlackBox(Map( + "PERIOD" -> DoubleParam(freqMHz) +)) with HasBlackBoxInline { + val io = IO(new ClockSourceIO) + + setInline("ClockSourceAtFreqMHz.v", + s""" + |module ClockSourceAtFreqMHz #(parameter PERIOD="") ( + | input power, + | input gate, + | output clk); + | + | reg clk_i = 1'b0; + | always #(PERIOD/2.0) clk_i = ~clk_i & (power & ~gate); + | assign clk = clk_i; + |endmodule + |""".stripMargin) +} + + // The AbsoluteFreqHarnessClockInstantiator uses a Verilog blackbox to // provide the precise requested frequency. // This ClockInstantiator cannot be synthesized, run in Verilator, or run in FireSim @@ -48,7 +69,7 @@ class AbsoluteFreqHarnessClockInstantiator extends HarnessClockInstantiator { // connect wires to clock source for (sinkParams <- sinks) { - val source = Module(new ClockSourceAtFreq(sinkParams.take.get.freqMHz)) + val source = Module(new ClockSourceAtFreqMHz(sinkParams.take.get.freqMHz)) source.io.power := true.B source.io.gate := false.B From bcd273986fde0e979cd8c551d64df33587b56199 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 10 May 2023 21:18:52 -0700 Subject: [PATCH 03/12] Fix ClockSourceAtFreqMHz period calc --- generators/chipyard/src/main/scala/harness/HarnessClocks.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala index 585062a5ef..d505c66b1c 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala @@ -38,7 +38,7 @@ trait HarnessClockInstantiator { } class ClockSourceAtFreqMHz(val freqMHz: Double) extends BlackBox(Map( - "PERIOD" -> DoubleParam(freqMHz) + "PERIOD" -> DoubleParam(1000/freqMHz) )) with HasBlackBoxInline { val io = IO(new ClockSourceIO) From 1916d3e4fc5e794af6b293dfe1eca91314b6f09d Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 10 May 2023 21:30:59 -0700 Subject: [PATCH 04/12] Add timeunit to ClockSourceAtFreqMHz --- generators/chipyard/src/main/scala/harness/HarnessClocks.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala index d505c66b1c..9f0d41b553 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala @@ -48,7 +48,7 @@ class ClockSourceAtFreqMHz(val freqMHz: Double) extends BlackBox(Map( | input power, | input gate, | output clk); - | + | timeunit 1ns/1ps; | reg clk_i = 1'b0; | always #(PERIOD/2.0) clk_i = ~clk_i & (power & ~gate); | assign clk = clk_i; From ffc4d1f66218a78869ef3eb34de90b43f879c530 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 10 May 2023 21:37:19 -0700 Subject: [PATCH 05/12] Use getClass.getSimpleName for ClockSourceAtFreqMHz blackbox inline --- .../chipyard/src/main/scala/harness/HarnessClocks.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala index 9f0d41b553..beded345f6 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala @@ -41,10 +41,11 @@ class ClockSourceAtFreqMHz(val freqMHz: Double) extends BlackBox(Map( "PERIOD" -> DoubleParam(1000/freqMHz) )) with HasBlackBoxInline { val io = IO(new ClockSourceIO) + val moduleName = this.getClass.getSimpleName - setInline("ClockSourceAtFreqMHz.v", + setInline(s"$moduleName.v", s""" - |module ClockSourceAtFreqMHz #(parameter PERIOD="") ( + |module $moduleName #(parameter PERIOD="") ( | input power, | input gate, | output clk); From 624785376a584dc293e1d717e2ea38f72b209b42 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 10 May 2023 23:34:29 -0700 Subject: [PATCH 06/12] Fix PassThroughClockGenerator to handle multiclock properly --- .../main/scala/clocking/ClockBinders.scala | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala index c91f5cb492..5a53051e73 100644 --- a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala +++ b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala @@ -103,20 +103,20 @@ class WithPassthroughClockGenerator extends OverrideLazyIOBinder({ // This aggregate node should do nothing val clockGroupAggNode = ClockGroupAggregateNode("fake") val clockGroupsSourceNode = ClockGroupSourceNode(Seq(ClockGroupSourceParameters())) - system.allClockGroupsNode :*= clockGroupAggNode := clockGroupsSourceNode + system.allClockGroupsNode := clockGroupAggNode := clockGroupsSourceNode InModuleBody { val reset_io = IO(Input(AsyncReset())) - val clock_ios = clockGroupAggNode.out.map { case (bundle, edge) => - val freqs = edge.sink.members.map(_.take.map(_.freqMHz)).flatten - require(freqs.distinct.size == 1) - val clock_io = IO(Input(new ClockWithFreq(freqs.head))).suggestName(s"clock_${edge.sink.name}") - bundle.member.data.foreach { b => - b.clock := clock_io.clock - b.reset := reset_io - } + require(clockGroupAggNode.out.size == 1) + val (bundle, edge) = clockGroupAggNode.out(0) + + val clock_ios = (bundle.member.data zip edge.sink.members).map { case (b, m) => + val freq = m.take.get.freqMHz + val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}") + b.clock := clock_io.clock + b.reset := reset_io clock_io - } + }.toSeq ((clock_ios :+ reset_io), Nil) } } From f4bf1b0a2836fa631c7deb19f0747d23b29b738b Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 11 May 2023 00:52:57 -0700 Subject: [PATCH 07/12] Fix multiclockrocketconfig --- generators/chipyard/src/main/scala/config/RocketConfigs.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index 965a81fcbe..ea00f8b27e 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -86,7 +86,7 @@ class MbusScratchpadRocketConfig extends Config( // DOC include end: mbusscratchpadrocket class MulticlockRocketConfig extends Config( - new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore + new freechips.rocketchip.subsystem.WithAsynchronousRocketTiles(3, 3) ++ // Add async crossings between RocketTile and uncore new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // Frequency specifications new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540 From 4dd017d181524d54acd9b8e5e6e6f98b8325d0af Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 11 May 2023 00:53:52 -0700 Subject: [PATCH 08/12] Fix WithClockAndResetFromHarness to actually request harness clocks --- .../chipyard/src/main/scala/harness/HarnessBinders.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala index e4e8391b43..d78318f8d1 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala @@ -393,8 +393,8 @@ class WithClockAndResetFromHarness extends OverrideHarnessBinder({ implicit val p = GetSystemParameters(system) ports.map ({ case c: ClockWithFreq => { - th.setRefClockFreq(c.freqMHz) - c.clock := th.buildtopClock + val clock = th.harnessClockInstantiator.requestClockBundle(s"clock_${c.freqMHz}MHz", c.freqMHz * (1000 * 1000)) + c.clock := clock.clock } case r: AsyncReset => r := th.buildtopReset.asAsyncReset }) From 1a6b34696eb74524485d7aee33fa2a3c50c9c199 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 11 May 2023 10:43:16 -0700 Subject: [PATCH 09/12] Set a more realistic 500 MHz uncore clock: --- .../chipyard/src/main/scala/config/AbstractConfig.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala index 02ab9b5a2c..6d243d5f11 100644 --- a/generators/chipyard/src/main/scala/config/AbstractConfig.scala +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -56,8 +56,8 @@ class AbstractConfig extends Config( new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set) - new chipyard.config.WithMemoryBusFrequency(100.0) ++ // Default 100 MHz mbus - new chipyard.config.WithPeripheryBusFrequency(100.0) ++ // Default 100 MHz pbus + new chipyard.config.WithMemoryBusFrequency(500.0) ++ // Default 500 MHz mbus + new chipyard.config.WithPeripheryBusFrequency(500.0) ++ // Default 500 MHz pbus new freechips.rocketchip.subsystem.WithNMemoryChannels(2) ++ // Default 2 memory channels new freechips.rocketchip.subsystem.WithClockGateModel ++ // add default EICG_wrapper clock gate model new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port From a9bc11accbb71d3907c10d033228c6001a03ea43 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 11 May 2023 10:45:31 -0700 Subject: [PATCH 10/12] Update comments on harnessbinders in AbstractConfig --- .../main/scala/config/AbstractConfig.scala | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/generators/chipyard/src/main/scala/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala index 6d243d5f11..4b179fd0ad 100644 --- a/generators/chipyard/src/main/scala/config/AbstractConfig.scala +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -12,18 +12,18 @@ import org.chipsalliance.cde.config.{Config} class AbstractConfig extends Config( // The HarnessBinders control generation of hardware in the TestHarness - new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present - new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled - new chipyard.harness.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM - new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled - new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present - new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled - new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled - new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present - new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present - new chipyard.harness.WithCustomBootPinPlusArg ++ - new chipyard.harness.WithClockAndResetFromHarness ++ - new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ + new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present + new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled + new chipyard.harness.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM + new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled + new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present + new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled + new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled + new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present + new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present + new chipyard.harness.WithCustomBootPinPlusArg ++ // drive custom-boot pin with a plusarg, if custom-boot-pin is present + new chipyard.harness.WithClockAndResetFromHarness ++ // all Clock/Reset I/O in ChipTop should be driven by harnessClockInstantiator + new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // generate clocks in harness with unsynthesizable ClockSourceAtFreqMHz // The IOBinders instantiate ChipTop IOs to match desired digital IOs // IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through From 64ad77bbcf829cfd6b4f8bea23eaea5b460762c9 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 11 May 2023 13:03:47 -0700 Subject: [PATCH 11/12] Make FPGA flows use the harnessClockInstantiator --- fpga/src/main/scala/arty/Configs.scala | 2 +- fpga/src/main/scala/arty/TestHarness.scala | 6 ++++++ fpga/src/main/scala/arty100t/Configs.scala | 1 + fpga/src/main/scala/arty100t/Harness.scala | 6 ++++++ fpga/src/main/scala/vc707/Configs.scala | 1 + fpga/src/main/scala/vc707/TestHarness.scala | 6 ++++++ fpga/src/main/scala/vcu118/Configs.scala | 1 + fpga/src/main/scala/vcu118/TestHarness.scala | 6 ++++++ .../src/main/scala/harness/HarnessClocks.scala | 15 +++++++++++++++ 9 files changed, 43 insertions(+), 1 deletion(-) diff --git a/fpga/src/main/scala/arty/Configs.scala b/fpga/src/main/scala/arty/Configs.scala index 10af02237e..ad8b9a328b 100644 --- a/fpga/src/main/scala/arty/Configs.scala +++ b/fpga/src/main/scala/arty/Configs.scala @@ -21,7 +21,7 @@ class WithArtyTweaks extends Config( new WithArtyJTAGHarnessBinder ++ new WithArtyUARTHarnessBinder ++ new WithDebugResetPassthrough ++ - + new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++ new chipyard.config.WithDTSTimebase(32768) ++ new testchipip.WithNoSerialTL ) diff --git a/fpga/src/main/scala/arty/TestHarness.scala b/fpga/src/main/scala/arty/TestHarness.scala index d368ec5568..6f7c5ea5a1 100644 --- a/fpga/src/main/scala/arty/TestHarness.scala +++ b/fpga/src/main/scala/arty/TestHarness.scala @@ -3,6 +3,7 @@ package chipyard.fpga.arty import chisel3._ import freechips.rocketchip.diplomacy.{LazyModule} +import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters} import org.chipsalliance.cde.config.{Parameters} import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell} @@ -36,4 +37,9 @@ class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell lazyDut match { case d: HasIOBinders => ApplyHarnessBinders(this, d.lazySystem, d.portMap) } + + val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters())) + implicitHarnessClockBundle.clock := buildtopClock + implicitHarnessClockBundle.reset := buildtopReset + harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle) } diff --git a/fpga/src/main/scala/arty100t/Configs.scala b/fpga/src/main/scala/arty100t/Configs.scala index 673b8b58cd..16683141b6 100644 --- a/fpga/src/main/scala/arty100t/Configs.scala +++ b/fpga/src/main/scala/arty100t/Configs.scala @@ -22,6 +22,7 @@ class WithNoDesignKey extends Config((site, here, up) => { }) class WithArty100TTweaks extends Config( + new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++ new WithArty100TUARTTSI ++ new WithArty100TDDRTL ++ new WithNoDesignKey ++ diff --git a/fpga/src/main/scala/arty100t/Harness.scala b/fpga/src/main/scala/arty100t/Harness.scala index dd76589a5c..d4e7ebc9a0 100644 --- a/fpga/src/main/scala/arty100t/Harness.scala +++ b/fpga/src/main/scala/arty100t/Harness.scala @@ -5,6 +5,7 @@ import chisel3.util._ import freechips.rocketchip.diplomacy._ import org.chipsalliance.cde.config.{Parameters} import freechips.rocketchip.tilelink.{TLClientNode, TLBlockDuringReset} +import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters} import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.shell._ @@ -87,6 +88,11 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell chiptop match { case d: HasIOBinders => ApplyHarnessBinders(this, d.lazySystem, d.portMap) } + + val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters())) + implicitHarnessClockBundle.clock := buildtopClock + implicitHarnessClockBundle.reset := buildtopReset + harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle) } } diff --git a/fpga/src/main/scala/vc707/Configs.scala b/fpga/src/main/scala/vc707/Configs.scala index c029861094..70bd7073a7 100644 --- a/fpga/src/main/scala/vc707/Configs.scala +++ b/fpga/src/main/scala/vc707/Configs.scala @@ -40,6 +40,7 @@ class WithSystemModifications extends Config((site, here, up) => { class WithVC707Tweaks extends Config ( // harness binders + new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++ new WithVC707UARTHarnessBinder ++ new WithVC707SPISDCardHarnessBinder ++ new WithVC707DDRMemHarnessBinder ++ diff --git a/fpga/src/main/scala/vc707/TestHarness.scala b/fpga/src/main/scala/vc707/TestHarness.scala index 8e0bd5bf59..553cf06eb2 100644 --- a/fpga/src/main/scala/vc707/TestHarness.scala +++ b/fpga/src/main/scala/vc707/TestHarness.scala @@ -6,6 +6,7 @@ import chisel3.experimental.{IO} import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource} import org.chipsalliance.cde.config.{Parameters} import freechips.rocketchip.tilelink.{TLClientNode} +import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters} import sifive.fpgashells.shell.xilinx.{VC707Shell, UARTVC707ShellPlacer, PCIeVC707ShellPlacer, ChipLinkVC707PlacedOverlay} import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly} @@ -132,4 +133,9 @@ class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModul // check the top-level reference clock is equal to the default // non-exhaustive since you need all ChipTop clocks to equal the default require(getRefClockFreq == p(DefaultClockFrequencyKey)) + + val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters())) + implicitHarnessClockBundle.clock := buildtopClock + implicitHarnessClockBundle.reset := buildtopReset + harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle) } diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index ea6df6c3a5..0d82e1076e 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -42,6 +42,7 @@ class WithSystemModifications extends Config((site, here, up) => { // DOC include start: AbstractVCU118 and Rocket class WithVCU118Tweaks extends Config( // harness binders + new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++ new WithUART ++ new WithSPISDCard ++ new WithDDRMem ++ diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index 9e7529dddb..5ca3d4a03b 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -6,6 +6,7 @@ import chisel3.experimental.{IO} import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource} import org.chipsalliance.cde.config.{Parameters} import freechips.rocketchip.tilelink.{TLClientNode} +import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters} import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly} @@ -134,4 +135,9 @@ class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawMod // check the top-level reference clock is equal to the default // non-exhaustive since you need all ChipTop clocks to equal the default require(getRefClockFreq == p(DefaultClockFrequencyKey)) + + val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters())) + implicitHarnessClockBundle.clock := buildtopClock + implicitHarnessClockBundle.reset := buildtopReset + harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle) } diff --git a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala index beded345f6..4fb7ea9ed2 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala @@ -83,3 +83,18 @@ class AbsoluteFreqHarnessClockInstantiator extends HarnessClockInstantiator { class WithAbsoluteFreqHarnessClockInstantiator extends Config((site, here, up) => { case HarnessClockInstantiatorKey => () => new AbsoluteFreqHarnessClockInstantiator }) + +class AllClocksFromHarnessClockInstantiator extends HarnessClockInstantiator { + def instantiateHarnessClocks(refClock: ClockBundle): Unit = { + val freqs = _clockMap.map(_._2._1) + freqs.tail.foreach(t => require(t == freqs.head, s"Mismatching clocks $t != ${freqs.head}")) + for ((_, (_, bundle)) <- _clockMap) { + bundle.clock := refClock.clock + bundle.reset := refClock.reset + } + } +} + +class WithAllClocksFromHarnessClockInstantiator extends Config((site, here, up) => { + case HarnessClockInstantiatorKey => () => new AllClocksFromHarnessClockInstantiator +}) From d673c61b8bfdb310b27f19187896452eea3059ce Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 11 May 2023 17:19:17 -0700 Subject: [PATCH 12/12] Switch SpikeTile CI to SpikeConfig --- .github/scripts/defaults.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/defaults.sh b/.github/scripts/defaults.sh index 176d20d5b7..d2362dbd17 100755 --- a/.github/scripts/defaults.sh +++ b/.github/scripts/defaults.sh @@ -47,7 +47,7 @@ mapping["chipyard-manymmioaccels"]=" CONFIG=ManyMMIOAcceleratorRocketConfig" mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig" mapping["chipyard-boom"]=" CONFIG=MediumBoomCosimConfig" mapping["chipyard-dmiboom"]=" CONFIG=dmiMediumBoomCosimConfig" -mapping["chipyard-spike"]=" CONFIG=SpikeFastUARTConfig EXTRA_SIM_FLAGS='+spike-ipc=10'" +mapping["chipyard-spike"]=" CONFIG=SpikeConfig EXTRA_SIM_FLAGS='+spike-ipc=10'" mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig" mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig" mapping["chipyard-cva6"]=" CONFIG=CVA6Config"