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
|
// The system module specified by BuildSystem
|
||||||
lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
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"))))
|
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
||||||
|
|
||||||
// Generate Clocks and Reset
|
// 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 ClockFrequencyAssignersKey extends Field[Seq[(String) => Option[Double]]](Seq.empty)
|
||||||
case object DefaultClockFrequencyKey extends Field[Double]()
|
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) => {
|
class ClockNameMatchesAssignment(name: String, fMHz: Double) extends Config((site, here, up) => {
|
||||||
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
|
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
|
||||||
@@ -86,20 +92,22 @@ object ClockingSchemeGenerators {
|
|||||||
:*= aggregator)
|
:*= aggregator)
|
||||||
|
|
||||||
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
||||||
|
val dividerOnlyClkGenerator = DividerOnlyClockGenerator()
|
||||||
// provides all the divided clocks (from the top-level clock)
|
// provides all the divided clocks (from the top-level clock)
|
||||||
(aggregator
|
(aggregator
|
||||||
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||||
:= ClockGroupResetSynchronizer()
|
:= ClockGroupResetSynchronizer()
|
||||||
:= DividerOnlyClockGenerator()
|
:= dividerOnlyClkGenerator.node
|
||||||
:= referenceClockSource)
|
:= referenceClockSource)
|
||||||
|
|
||||||
|
|
||||||
InModuleBody {
|
InModuleBody {
|
||||||
val clock_wire = Wire(Input(Clock()))
|
val clock_wire = Wire(Input(Clock()))
|
||||||
val reset_wire = GenerateReset(chiptop, clock_wire)
|
val reset_wire = GenerateReset(chiptop, clock_wire)
|
||||||
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock")
|
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock")
|
||||||
chiptop.iocells ++= clockIOCell
|
chiptop.iocells ++= clockIOCell
|
||||||
|
|
||||||
|
p(ReferenceClockTrackerKey).set(dividerOnlyClkGenerator.module.referenceFreq)
|
||||||
|
|
||||||
referenceClockSource.out.unzip._1.map { o =>
|
referenceClockSource.out.unzip._1.map { o =>
|
||||||
o.clock := clock_wire
|
o.clock := clock_wire
|
||||||
o.reset := reset_wire
|
o.reset := reset_wire
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import scala.collection.mutable.{ArrayBuffer}
|
|
||||||
|
import scala.collection.mutable.{ArrayBuffer, HashMap}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule}
|
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||||
import freechips.rocketchip.config.{Field, Parameters}
|
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.harness.{ApplyHarnessBinders, HarnessBinders}
|
||||||
import chipyard.iobinders.HasIOBinders
|
import chipyard.iobinders.HasIOBinders
|
||||||
|
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
|
||||||
|
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// Chipyard Test Harness
|
// Chipyard Test Harness
|
||||||
@@ -25,6 +29,46 @@ trait HasHarnessSignalReferences {
|
|||||||
def success: Bool
|
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 {
|
class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSignalReferences {
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
val success = Output(Bool())
|
val success = Output(Bool())
|
||||||
@@ -34,17 +78,23 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign
|
|||||||
val dut = Module(lazyDut.module)
|
val dut = Module(lazyDut.module)
|
||||||
io.success := false.B
|
io.success := false.B
|
||||||
|
|
||||||
val harnessClock = clock
|
val (harnessClock, harnessReset, dutReset) = {
|
||||||
val harnessReset = WireInit(reset)
|
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 success = io.success
|
||||||
|
|
||||||
val dutReset = reset.asAsyncReset
|
|
||||||
|
|
||||||
lazyDut match { case d: HasTestHarnessFunctions =>
|
lazyDut match { case d: HasTestHarnessFunctions =>
|
||||||
d.harnessFunctions.foreach(_(this))
|
d.harnessFunctions.foreach(_(this))
|
||||||
}
|
}
|
||||||
lazyDut match { case d: HasIOBinders =>
|
lazyDut match { case d: HasIOBinders =>
|
||||||
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
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 {
|
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