Enabling disable all the PLLSelectorDivider features for Verilator CI
This is to work-around Verilator's modeling of reset, which does not model a posedge reset as t=0
This commit is contained in:
@@ -14,7 +14,10 @@ import barstools.iocell.chisel._
|
|||||||
// blocks, which allow memory-mapped control of clock division, and clock muxing
|
// blocks, which allow memory-mapped control of clock division, and clock muxing
|
||||||
// between the FakePLL and the slow off-chip clock
|
// between the FakePLL and the slow off-chip clock
|
||||||
// Note: This will not simulate properly with firesim
|
// Note: This will not simulate properly with firesim
|
||||||
class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
|
// Unsetting enable will prevent the divider/selector from actually modifying the clock,
|
||||||
|
// while preserving the address map. Unsetting enable should only be done for RTL
|
||||||
|
// simulators (Verilator) which do not model reset properly
|
||||||
|
class WithPLLSelectorDividerClockGenerator(enable: Boolean = true) extends OverrideLazyIOBinder({
|
||||||
(system: HasChipyardPRCI) => {
|
(system: HasChipyardPRCI) => {
|
||||||
// Connect the implicit clock
|
// Connect the implicit clock
|
||||||
implicit val p = GetSystemParameters(system)
|
implicit val p = GetSystemParameters(system)
|
||||||
@@ -30,8 +33,8 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
|
|||||||
}
|
}
|
||||||
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(system.prciParams.slaveWhere)
|
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(system.prciParams.slaveWhere)
|
||||||
val baseAddress = system.prciParams.baseAddress
|
val baseAddress = system.prciParams.baseAddress
|
||||||
val clockDivider = system.prci_ctrl_domain { LazyModule(new TLClockDivider (baseAddress + 0x20000, tlbus.beatBytes)) }
|
val clockDivider = system.prci_ctrl_domain { LazyModule(new TLClockDivider (baseAddress + 0x20000, tlbus.beatBytes, enable=enable)) }
|
||||||
val clockSelector = system.prci_ctrl_domain { LazyModule(new TLClockSelector(baseAddress + 0x30000, tlbus.beatBytes)) }
|
val clockSelector = system.prci_ctrl_domain { LazyModule(new TLClockSelector(baseAddress + 0x30000, tlbus.beatBytes, enable=enable)) }
|
||||||
val pllCtrl = system.prci_ctrl_domain { LazyModule(new FakePLLCtrl (baseAddress + 0x40000, tlbus.beatBytes)) }
|
val pllCtrl = system.prci_ctrl_domain { LazyModule(new FakePLLCtrl (baseAddress + 0x40000, tlbus.beatBytes)) }
|
||||||
|
|
||||||
clockDivider.tlNode := system.prci_ctrl_domain { TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := system.prci_ctrl_bus.get }
|
clockDivider.tlNode := system.prci_ctrl_domain { TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := system.prci_ctrl_bus.get }
|
||||||
|
|||||||
@@ -15,11 +15,27 @@ import testchipip._
|
|||||||
|
|
||||||
// This module adds a TileLink memory-mapped clock divider to the clock graph
|
// 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
|
// 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 {
|
// If enable is unset, this will not divide the clock
|
||||||
|
// DO NOT unset enable for VLSI, or prototyping flows. The disable feature is a work around for
|
||||||
|
// some RTL simulators which do not simulate the reset synchronization properly
|
||||||
|
class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8, enable: Boolean = true)(implicit p: Parameters) extends LazyModule {
|
||||||
val device = new SimpleDevice(s"clk-div-ctrl", Nil)
|
val device = new SimpleDevice(s"clk-div-ctrl", Nil)
|
||||||
val clockNode = ClockGroupIdentityNode()
|
val clockNode = ClockGroupIdentityNode()
|
||||||
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
|
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
|
||||||
|
|
||||||
|
if (!enable) println(Console.RED + s"""
|
||||||
|
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
|
||||||
|
YOU ARE USING THE TLCLOCKDIVIDER IN
|
||||||
|
"DISABLED" MODE. THIS SHOULD ONLY BE DONE
|
||||||
|
FOR RTL SIMULATION
|
||||||
|
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
""" + Console.RESET)
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
lazy val module = new LazyModuleImp(this) {
|
||||||
require (clockNode.out.size == 1)
|
require (clockNode.out.size == 1)
|
||||||
val sources = clockNode.in.head._1.member.data.toSeq
|
val sources = clockNode.in.head._1.member.data.toSeq
|
||||||
@@ -45,13 +61,21 @@ class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit
|
|||||||
// by setting divisor=0. The divisor signal into the ClockDividerOrPass is synchronized internally
|
// by setting divisor=0. The divisor signal into the ClockDividerOrPass is synchronized internally
|
||||||
divider.io.divisor := Mux(busReset.asBool, 0.U, reg.io.q)
|
divider.io.divisor := Mux(busReset.asBool, 0.U, reg.io.q)
|
||||||
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset
|
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset
|
||||||
sinks(i)._2.clock := divider.io.clockOut
|
|
||||||
|
|
||||||
// Note this is not synchronized to the output clock, which takes time to appear
|
if (enable) {
|
||||||
// so this is still asyncreset
|
sinks(i)._2.clock := divider.io.clockOut
|
||||||
// Stretch the reset for 40 cycles, to give enough time to reset any downstream
|
|
||||||
// digital logic
|
// Note this is not synchronized to the output clock, which takes time to appear
|
||||||
sinks(i)._2.reset := ResetStretcher(sources(i).clock, asyncReset, 40).asAsyncReset
|
// so this is still asyncreset
|
||||||
|
// Stretch the reset for 40 cycles, to give enough time to reset any downstream
|
||||||
|
// digital logic
|
||||||
|
sinks(i)._2.reset := ResetStretcher(sources(i).clock, asyncReset, 40).asAsyncReset
|
||||||
|
} else {
|
||||||
|
// WARNING: THIS IS FOR RTL SIMULATION ONLY
|
||||||
|
sinks(i)._2.clock := sources(i).clock
|
||||||
|
sinks(i)._2.reset := sources(i).reset
|
||||||
|
}
|
||||||
|
|
||||||
reg
|
reg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,30 @@ case class ClockSelNode()(implicit valName: ValName)
|
|||||||
|
|
||||||
// This module adds a TileLink memory-mapped clock mux for each downstream clock domain
|
// 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
|
// in the clock graph. The output clock/reset should be synchronized downstream
|
||||||
class TLClockSelector(address: BigInt, beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
// If enable is unset, this will always pass through the 0'th clock
|
||||||
|
// DO NOT unset enable for VLSI, or prototyping flows. The disable feature is a work around for
|
||||||
|
// some RTL simulators which do not simulate the reset synchronization properly
|
||||||
|
class TLClockSelector(address: BigInt, beatBytes: Int, enable: Boolean = true)(implicit p: Parameters) extends LazyModule {
|
||||||
val device = new SimpleDevice("clk-sel-ctrl", Nil)
|
val device = new SimpleDevice("clk-sel-ctrl", Nil)
|
||||||
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
|
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
|
||||||
|
|
||||||
val clockNode = ClockSelNode()
|
val clockNode = ClockSelNode()
|
||||||
|
|
||||||
|
if (!enable) println(Console.RED + s"""
|
||||||
|
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
|
||||||
|
YOU ARE USING THE TLCLOCKSELECTOR IN
|
||||||
|
"DISABLED" MODE. THIS SHOULD ONLY BE DONE
|
||||||
|
FOR RTL SIMULATION
|
||||||
|
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
""" + Console.RESET)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
lazy val module = new LazyModuleImp(this) {
|
||||||
val asyncReset = clockNode.in.map(_._1).map(_.reset).toSeq(0)
|
val asyncReset = clockNode.in.map(_._1).map(_.reset).toSeq(0)
|
||||||
val clocks = clockNode.in.map(_._1).map(_.clock)
|
val clocks = clockNode.in.map(_._1).map(_.clock)
|
||||||
@@ -43,10 +61,15 @@ class TLClockSelector(address: BigInt, beatBytes: Int)(implicit p: Parameters) e
|
|||||||
val mux = testchipip.ClockMutexMux(clocks).suggestName(s"${sinkName}_clkmux")
|
val mux = testchipip.ClockMutexMux(clocks).suggestName(s"${sinkName}_clkmux")
|
||||||
mux.io.sel := sel
|
mux.io.sel := sel
|
||||||
mux.io.resetAsync := asyncReset.asAsyncReset
|
mux.io.resetAsync := asyncReset.asAsyncReset
|
||||||
sinks(i).clock := mux.io.clockOut
|
if (enable) {
|
||||||
// Stretch the reset for 20 cycles, to give time to reset any downstream digital logic
|
sinks(i).clock := mux.io.clockOut
|
||||||
sinks(i).reset := ResetStretcher(clocks(0), asyncReset, 20).asAsyncReset
|
// Stretch the reset for 20 cycles, to give time to reset any downstream digital logic
|
||||||
|
sinks(i).reset := ResetStretcher(clocks(0), asyncReset, 20).asAsyncReset
|
||||||
|
} else {
|
||||||
|
// WARNING: THIS IS FOR RTL SIMULATION ONLY
|
||||||
|
sinks(i).clock := clocks(0)
|
||||||
|
sinks(i).reset := asyncReset
|
||||||
|
}
|
||||||
reg
|
reg
|
||||||
}
|
}
|
||||||
tlNode.regmap((0 until sinks.size).map { i =>
|
tlNode.regmap((0 until sinks.size).map { i =>
|
||||||
|
|||||||
@@ -110,7 +110,8 @@ class TetheredChipLikeRocketConfig extends Config(
|
|||||||
class VerilatorCITetheredChipLikeRocketConfig extends Config(
|
class VerilatorCITetheredChipLikeRocketConfig extends Config(
|
||||||
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // use absolute freqs for sims in the harness
|
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // use absolute freqs for sims in the harness
|
||||||
new chipyard.harness.WithMultiChipSerialTL(0, 1) ++ // connect the serial-tl ports of the chips together
|
new chipyard.harness.WithMultiChipSerialTL(0, 1) ++ // connect the serial-tl ports of the chips together
|
||||||
new chipyard.harness.WithMultiChip(0,
|
new chipyard.harness.WithMultiChip(0, // These fragments remove all troublesome
|
||||||
|
new chipyard.clocking.WithPLLSelectorDividerClockGenerator(enable=false) ++ // clocking features from the design
|
||||||
new chipyard.iobinders.WithDebugIOCells(syncReset = false) ++
|
new chipyard.iobinders.WithDebugIOCells(syncReset = false) ++
|
||||||
new chipyard.config.WithNoResetSynchronizers ++
|
new chipyard.config.WithNoResetSynchronizers ++
|
||||||
new ChipLikeRocketConfig) ++
|
new ChipLikeRocketConfig) ++
|
||||||
|
|||||||
Reference in New Issue
Block a user