diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala index 61a043b6..205135a2 100644 --- a/generators/chipyard/src/main/scala/ChipTop.scala +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -28,7 +28,7 @@ class ChipTop(implicit p: Parameters) extends LazyModule with BindingScope // The system module specified by BuildSystem lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") - // The implicitClockSinkNode provides the implicit clock and reset for the System + // The implicitClockSinkNode provides the implicit clock and reset for the system (connected by clocking scheme) val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock")))) // Generate Clocks and Reset diff --git a/generators/chipyard/src/main/scala/Clocks.scala b/generators/chipyard/src/main/scala/Clocks.scala index 0ba31abb..65346ea6 100644 --- a/generators/chipyard/src/main/scala/Clocks.scala +++ b/generators/chipyard/src/main/scala/Clocks.scala @@ -47,6 +47,12 @@ case object ClockingSchemeKey extends Field[ChipTop => Unit](ClockingSchemeGener */ case object ClockFrequencyAssignersKey extends Field[Seq[(String) => Option[Double]]](Seq.empty) case object DefaultClockFrequencyKey extends Field[Double]() +case object ReferenceClockTrackerKey extends Field[ReferenceClockTracker](new ReferenceClockTracker) +class ReferenceClockTracker { + private var _refFreqMHz: Option[Double] = None + def set(freqMHz: Double): Unit = { _refFreqMHz = Some(freqMHz) } + def get: Option[Double] = { _refFreqMHz } +} class ClockNameMatchesAssignment(name: String, fMHz: Double) extends Config((site, here, up) => { case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++ @@ -86,20 +92,22 @@ object ClockingSchemeGenerators { :*= aggregator) val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters())) + val dividerOnlyClkGenerator = DividerOnlyClockGenerator() // provides all the divided clocks (from the top-level clock) (aggregator := ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey)) := ClockGroupResetSynchronizer() - := DividerOnlyClockGenerator() + := dividerOnlyClkGenerator.node := referenceClockSource) - InModuleBody { val clock_wire = Wire(Input(Clock())) val reset_wire = GenerateReset(chiptop, clock_wire) val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock") chiptop.iocells ++= clockIOCell + p(ReferenceClockTrackerKey).set(dividerOnlyClkGenerator.module.referenceFreq) + referenceClockSource.out.unzip._1.map { o => o.clock := clock_wire o.reset := reset_wire diff --git a/generators/chipyard/src/main/scala/TestHarness.scala b/generators/chipyard/src/main/scala/TestHarness.scala index c638c081..34e2b1ca 100644 --- a/generators/chipyard/src/main/scala/TestHarness.scala +++ b/generators/chipyard/src/main/scala/TestHarness.scala @@ -1,12 +1,16 @@ package chipyard import chisel3._ -import scala.collection.mutable.{ArrayBuffer} + +import scala.collection.mutable.{ArrayBuffer, HashMap} import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.util.{ResetCatchAndSync} +import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters} import chipyard.harness.{ApplyHarnessBinders, HarnessBinders} import chipyard.iobinders.HasIOBinders +import chipyard.clocking.{SimplePllConfiguration, ClockDividerN} // ------------------------------- // Chipyard Test Harness @@ -25,6 +29,46 @@ trait HasHarnessSignalReferences { def success: Bool } +class HarnessClockInstantiator { + private var _clockMap: HashMap[String, (Double, ClockBundle)] = HashMap.empty + + // request a clock bundle at a particular frequency + def getClockBundleWire(name: String, freqRequested: Double): ClockBundle = { + val clockBundle = Wire(new ClockBundle(ClockBundleParameters())) + _clockMap(name) = (freqRequested, clockBundle) + clockBundle + } + + // connect all clock wires specified to a divider only PLL + def instantiateHarnessDividerPLL(refClock: ClockBundle): Unit = { + val sinks = _clockMap.map({ case (name, (freq, bundle)) => + ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq/1000000)),name=Some(name)) + }).toSeq + + val pllConfig = new SimplePllConfiguration("harnessDividerOnlyClockGenerator", sinks) + pllConfig.emitSummaries() + + val dividedClocks = 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 + } + + // connect wires to clock source + for (sinkParams <- sinks) { + val div = pllConfig.sinkDividerMap(sinkParams) + val divClock = dividedClocks.getOrElse(div, instantiateDivider(div)) + _clockMap(sinkParams.name.get)._2.clock := divClock + _clockMap(sinkParams.name.get)._2.reset := ResetCatchAndSync(divClock, refClock.reset.asBool) + } + } +} + +case object HarnessClockInstantiatorKey extends Field[HarnessClockInstantiator](new HarnessClockInstantiator) + class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSignalReferences { val io = IO(new Bundle { val success = Output(Bool()) @@ -34,17 +78,23 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign val dut = Module(lazyDut.module) io.success := false.B - val harnessClock = clock - val harnessReset = WireInit(reset) + val (harnessClock, harnessReset, dutReset) = { + val freqMHz = p(ReferenceClockTrackerKey).get.getOrElse(100.0) // default to 100MHz + val bundle = p(HarnessClockInstantiatorKey).getClockBundleWire("implicit_harness_clock", freqMHz*1000000.0) + (bundle.clock, WireInit(bundle.reset), bundle.reset.asAsyncReset) + } val success = io.success - val dutReset = reset.asAsyncReset - lazyDut match { case d: HasTestHarnessFunctions => d.harnessFunctions.foreach(_(this)) } lazyDut match { case d: HasIOBinders => ApplyHarnessBinders(this, d.lazySystem, d.portMap) } + + val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters())) + implicitHarnessClockBundle.clock := clock + implicitHarnessClockBundle.reset := reset + p(HarnessClockInstantiatorKey).instantiateHarnessDividerPLL(implicitHarnessClockBundle) } diff --git a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala index 2b666196..00cb6814 100644 --- a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala +++ b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala @@ -146,5 +146,5 @@ class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName } object DividerOnlyClockGenerator { - def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new DividerOnlyClockGenerator(valName.name)).node + def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new DividerOnlyClockGenerator(valName.name)) }