Add support for harness pll
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user