Add support for harness pll

This commit is contained in:
abejgonzalez
2021-03-04 23:31:49 -08:00
parent 3d9cd61d16
commit d2a6dd6822
4 changed files with 67 additions and 9 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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))
}