Add some comments on harness/chiptop clocking APIs

This commit is contained in:
Jerry Zhao
2023-04-08 17:19:25 -07:00
parent de293f5fdf
commit 0ffc3c7770
4 changed files with 22 additions and 0 deletions

View File

@@ -13,6 +13,9 @@ import chipyard.iobinders.HasIOBinders
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
import chipyard.HarnessClockInstantiatorKey
// HarnessClockInstantiators are classes which generate clocks that drive
// TestHarness simulation models and any Clock inputs to the ChipTop
trait HarnessClockInstantiator {
val _clockMap: LinkedHashMap[String, (Double, ClockBundle)] = LinkedHashMap.empty
@@ -23,9 +26,13 @@ trait HarnessClockInstantiator {
clockBundle
}
// refClock is the clock generated by TestDriver that is
// passed to the TestHarness as its implicit clock
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 = {
@@ -62,6 +69,10 @@ class DividerOnlyHarnessClockInstantiator extends HarnessClockInstantiator {
}
}
// The AbsoluteFreqHarnessClockInstantiator uses a Verilog blackbox to
// provide the precise requested frequency.
// This ClockInstantiator cannot be synthesized, run in Verilator, or run in FireSim
// It is useful for VCS/Xcelium-driven RTL simulations
class AbsoluteFreqHarnessClockInstantiator extends HarnessClockInstantiator {
def instantiateHarnessClocks(refClock: ClockBundle): Unit = {
val sinks = _clockMap.map({ case (name, (freq, bundle)) =>

View File

@@ -13,6 +13,9 @@ 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
@@ -52,6 +55,10 @@ class WithDividerOnlyClockGenerator extends OverrideLazyIOBinder({
}
})
// 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
class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => {

View File

@@ -13,6 +13,8 @@ import freechips.rocketchip.util.ElaborationArtefacts
import testchipip._
// This module adds a TileLink memory-mapped clock divider to the clock graph
// The output clock/reset pairs from this module should be synchronized later
class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit p: Parameters) extends LazyModule {
val device = new SimpleDevice(s"clk-div-ctrl", Nil)
val clockNode = ClockGroupIdentityNode()

View File

@@ -36,6 +36,8 @@ case class ClockSelNode()(implicit valName: ValName)
uFn = { u => ClockSinkParameters() }
)
// This module adds a TileLink memory-mapped clock mux for each downstream clock domain
// in the clock graph. The output clock/reset should be synchronized downstream
class TLClockSelector(address: BigInt, beatBytes: Int)(implicit p: Parameters) extends LazyModule {
val device = new SimpleDevice("clk-sel-ctrl", Nil)
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)