Merge pull request #1472 from ucb-bar/simpleclocks

Switch RTL sims to absolute clock-generators
This commit is contained in:
Jerry Zhao
2023-05-11 21:36:53 -07:00
committed by GitHub
18 changed files with 127 additions and 160 deletions

View File

@@ -47,7 +47,7 @@ mapping["chipyard-manymmioaccels"]=" CONFIG=ManyMMIOAcceleratorRocketConfig"
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig" mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
mapping["chipyard-boom"]=" CONFIG=MediumBoomCosimConfig" mapping["chipyard-boom"]=" CONFIG=MediumBoomCosimConfig"
mapping["chipyard-dmiboom"]=" CONFIG=dmiMediumBoomCosimConfig" mapping["chipyard-dmiboom"]=" CONFIG=dmiMediumBoomCosimConfig"
mapping["chipyard-spike"]=" CONFIG=SpikeFastUARTConfig EXTRA_SIM_FLAGS='+spike-ipc=10'" mapping["chipyard-spike"]=" CONFIG=SpikeConfig EXTRA_SIM_FLAGS='+spike-ipc=10'"
mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig" mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig"
mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig" mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig"
mapping["chipyard-cva6"]=" CONFIG=CVA6Config" mapping["chipyard-cva6"]=" CONFIG=CVA6Config"

View File

@@ -21,7 +21,7 @@ class WithArtyTweaks extends Config(
new WithArtyJTAGHarnessBinder ++ new WithArtyJTAGHarnessBinder ++
new WithArtyUARTHarnessBinder ++ new WithArtyUARTHarnessBinder ++
new WithDebugResetPassthrough ++ new WithDebugResetPassthrough ++
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.config.WithDTSTimebase(32768) ++ new chipyard.config.WithDTSTimebase(32768) ++
new testchipip.WithNoSerialTL new testchipip.WithNoSerialTL
) )

View File

@@ -3,6 +3,7 @@ package chipyard.fpga.arty
import chisel3._ import chisel3._
import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
import org.chipsalliance.cde.config.{Parameters} import org.chipsalliance.cde.config.{Parameters}
import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell} import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
@@ -36,4 +37,9 @@ class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell
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 := buildtopClock
implicitHarnessClockBundle.reset := buildtopReset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }

View File

@@ -22,6 +22,7 @@ class WithNoDesignKey extends Config((site, here, up) => {
}) })
class WithArty100TTweaks extends Config( class WithArty100TTweaks extends Config(
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new WithArty100TUARTTSI ++ new WithArty100TUARTTSI ++
new WithArty100TDDRTL ++ new WithArty100TDDRTL ++
new WithNoDesignKey ++ new WithNoDesignKey ++

View File

@@ -5,6 +5,7 @@ import chisel3.util._
import freechips.rocketchip.diplomacy._ import freechips.rocketchip.diplomacy._
import org.chipsalliance.cde.config.{Parameters} import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.tilelink.{TLClientNode, TLBlockDuringReset} import freechips.rocketchip.tilelink.{TLClientNode, TLBlockDuringReset}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.shell.xilinx._
import sifive.fpgashells.shell._ import sifive.fpgashells.shell._
@@ -87,6 +88,11 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell
chiptop match { case d: HasIOBinders => chiptop match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap) ApplyHarnessBinders(this, d.lazySystem, d.portMap)
} }
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := buildtopClock
implicitHarnessClockBundle.reset := buildtopReset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }
} }

View File

@@ -40,6 +40,7 @@ class WithSystemModifications extends Config((site, here, up) => {
class WithVC707Tweaks extends Config ( class WithVC707Tweaks extends Config (
// harness binders // harness binders
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new WithVC707UARTHarnessBinder ++ new WithVC707UARTHarnessBinder ++
new WithVC707SPISDCardHarnessBinder ++ new WithVC707SPISDCardHarnessBinder ++
new WithVC707DDRMemHarnessBinder ++ new WithVC707DDRMemHarnessBinder ++

View File

@@ -6,6 +6,7 @@ import chisel3.experimental.{IO}
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource} import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
import org.chipsalliance.cde.config.{Parameters} import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.tilelink.{TLClientNode} import freechips.rocketchip.tilelink.{TLClientNode}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
import sifive.fpgashells.shell.xilinx.{VC707Shell, UARTVC707ShellPlacer, PCIeVC707ShellPlacer, ChipLinkVC707PlacedOverlay} import sifive.fpgashells.shell.xilinx.{VC707Shell, UARTVC707ShellPlacer, PCIeVC707ShellPlacer, ChipLinkVC707PlacedOverlay}
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly} import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
@@ -132,4 +133,9 @@ class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModul
// check the top-level reference clock is equal to the default // check the top-level reference clock is equal to the default
// non-exhaustive since you need all ChipTop clocks to equal the default // non-exhaustive since you need all ChipTop clocks to equal the default
require(getRefClockFreq == p(DefaultClockFrequencyKey)) require(getRefClockFreq == p(DefaultClockFrequencyKey))
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := buildtopClock
implicitHarnessClockBundle.reset := buildtopReset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }

View File

@@ -42,6 +42,7 @@ class WithSystemModifications extends Config((site, here, up) => {
// DOC include start: AbstractVCU118 and Rocket // DOC include start: AbstractVCU118 and Rocket
class WithVCU118Tweaks extends Config( class WithVCU118Tweaks extends Config(
// harness binders // harness binders
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new WithUART ++ new WithUART ++
new WithSPISDCard ++ new WithSPISDCard ++
new WithDDRMem ++ new WithDDRMem ++

View File

@@ -6,6 +6,7 @@ import chisel3.experimental.{IO}
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource} import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
import org.chipsalliance.cde.config.{Parameters} import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.tilelink.{TLClientNode} import freechips.rocketchip.tilelink.{TLClientNode}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.shell.xilinx._
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly} import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
@@ -134,4 +135,9 @@ class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawMod
// check the top-level reference clock is equal to the default // check the top-level reference clock is equal to the default
// non-exhaustive since you need all ChipTop clocks to equal the default // non-exhaustive since you need all ChipTop clocks to equal the default
require(getRefClockFreq == p(DefaultClockFrequencyKey)) require(getRefClockFreq == p(DefaultClockFrequencyKey))
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := buildtopClock
implicitHarnessClockBundle.reset := buildtopReset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }

View File

@@ -25,7 +25,6 @@ import barstools.iocell.chisel._
import testchipip._ import testchipip._
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import chipyard.{CanHaveMasterTLMemPort} import chipyard.{CanHaveMasterTLMemPort}
import chipyard.clocking.{HasChipyardPRCI, DividerOnlyClockGenerator}
import scala.reflect.{ClassTag} import scala.reflect.{ClassTag}

View File

@@ -13,53 +13,11 @@ class ClockWithFreq(val freqMHz: Double) extends Bundle {
val clock = Clock() 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
implicit val p = GetSystemParameters(system)
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
system.connectImplicitClockSinkNode(implicitClockSinkNode)
InModuleBody {
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
}
// Connect all other requested clocks
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
val dividerOnlyClockGen = LazyModule(new DividerOnlyClockGenerator("buildTopClockGenerator"))
(system.allClockGroupsNode
:= dividerOnlyClockGen.node
:= referenceClockSource)
InModuleBody {
val clock_wire = Wire(Input(new ClockWithFreq(dividerOnlyClockGen.module.referenceFreq)))
val reset_wire = Wire(Input(AsyncReset()))
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
referenceClockSource.out.unzip._1.map { o =>
o.clock := clock_wire.clock
o.reset := reset_wire
}
(Seq(clock_io, reset_io), clockIOCell ++ resetIOCell)
}
}
})
// This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate // This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate
// the requested clocks. This also adds TileLink ClockDivider and ClockSelector // the requested clocks. This also adds TileLink ClockDivider and ClockSelector
// 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 verilator or firesim // Note: This will not simulate properly with firesim
class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => { (system: HasChipyardPRCI) => {
// Connect the implicit clock // Connect the implicit clock
@@ -100,7 +58,7 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
pllCtrlSink := pllCtrl.ctrlNode pllCtrlSink := pllCtrl.ctrlNode
InModuleBody { InModuleBody {
val clock_wire = Wire(Input(new ClockWithFreq(80))) val clock_wire = Wire(Input(new ClockWithFreq(100)))
val reset_wire = Wire(Input(AsyncReset())) val reset_wire = Wire(Input(AsyncReset()))
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey)) val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey)) val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
@@ -125,3 +83,41 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
} }
} }
}) })
// This passes all clocks through to the TestHarness
class WithPassthroughClockGenerator extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => {
// Connect the implicit clock
implicit val p = GetSystemParameters(system)
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
system.connectImplicitClockSinkNode(implicitClockSinkNode)
InModuleBody {
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
}
// This aggregate node should do nothing
val clockGroupAggNode = ClockGroupAggregateNode("fake")
val clockGroupsSourceNode = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
system.allClockGroupsNode := clockGroupAggNode := clockGroupsSourceNode
InModuleBody {
val reset_io = IO(Input(AsyncReset()))
require(clockGroupAggNode.out.size == 1)
val (bundle, edge) = clockGroupAggNode.out(0)
val clock_ios = (bundle.member.data zip edge.sink.members).map { case (b, m) =>
val freq = m.take.get.freqMHz
val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}")
b.clock := clock_io.clock
b.reset := reset_io
clock_io
}.toSeq
((clock_ios :+ reset_io), Nil)
}
}
})

View File

@@ -92,57 +92,3 @@ class SimplePllConfiguration(
def referenceSinkParams(): ClockSinkParameters = sinkDividerMap.find(_._2 == 1).get._1 def referenceSinkParams(): ClockSinkParameters = sinkDividerMap.find(_._2 == 1).get._1
} }
case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName)
extends MixedNexusNode(ClockImp, ClockGroupImp)(
dFn = { _ => ClockGroupSourceParameters() },
uFn = { u =>
require(u.size == 1)
require(!u.head.members.contains(None),
"All output clocks in group must set their take parameters. Use a ClockGroupDealiaser")
ClockSinkParameters(
name = Some(s"${pllName}_reference_input"),
take = Some(ClockParameters(new SimplePllConfiguration(pllName, u.head.members).referenceFreqMHz))) }
)
/**
* Generates a digital-divider-only PLL model that verilator can simulate.
* Inspects all take-specified frequencies in the output ClockGroup, calculates a
* fast reference clock (roughly LCM(requested frequencies)) which is passed up the
* diplomatic graph, and then generates dividers for each unique requested
* frequency.
*
* Output resets are not synchronized to generated clocks and should be
* synchronized by the user in a manner they see fit.
*
*/
class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule {
val node = DividerOnlyClockGeneratorNode(pllName)
lazy val module = new Impl
class Impl extends LazyRawModuleImp(this) {
require(node.out.size == 1, "Idealized PLL expects to generate a single output clock group. Use a ClockGroupAggregator")
val (refClock, ClockEdgeParameters(_, refSinkParam, _, _)) = node.in.head
val (outClocks, ClockGroupEdgeParameters(_, outSinkParams, _, _)) = node.out.head
val referenceFreq = refSinkParam.take.get.freqMHz
val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members)
pllConfig.emitSummaries()
val dividedClocks = mutable.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
}
for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) {
val div = pllConfig.sinkDividerMap(sinkP)
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
// Reset handling and synchronization is expected to be handled by a downstream node
sinkB.reset := refClock.reset
}
}
}

View File

@@ -12,17 +12,18 @@ import org.chipsalliance.cde.config.{Config}
class AbstractConfig extends Config( class AbstractConfig extends Config(
// The HarnessBinders control generation of hardware in the TestHarness // The HarnessBinders control generation of hardware in the TestHarness
new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present
new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled
new chipyard.harness.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM new chipyard.harness.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM
new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present
new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled
new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled
new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present
new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present
new chipyard.harness.WithCustomBootPinPlusArg ++ new chipyard.harness.WithCustomBootPinPlusArg ++ // drive custom-boot pin with a plusarg, if custom-boot-pin is present
new chipyard.harness.WithClockAndResetFromHarness ++ new chipyard.harness.WithClockAndResetFromHarness ++ // all Clock/Reset I/O in ChipTop should be driven by harnessClockInstantiator
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // generate clocks in harness with unsynthesizable ClockSourceAtFreqMHz
// The IOBinders instantiate ChipTop IOs to match desired digital IOs // The IOBinders instantiate ChipTop IOs to match desired digital IOs
// IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through // IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through
@@ -41,10 +42,8 @@ class AbstractConfig extends Config(
new chipyard.iobinders.WithExtInterruptIOCells ++ new chipyard.iobinders.WithExtInterruptIOCells ++
new chipyard.iobinders.WithCustomBootPin ++ new chipyard.iobinders.WithCustomBootPin ++
// Default behavior is to use a divider-only clock-generator // By default, punch out IOs to the Harness
// This works in VCS, Verilator, and FireSim/ new chipyard.clocking.WithPassthroughClockGenerator ++
// This should get replaced with a PLL-like config instead
new chipyard.clocking.WithDividerOnlyClockGenerator ++
new testchipip.WithCustomBootPin ++ // add a custom-boot-pin to support pin-driven boot address new testchipip.WithCustomBootPin ++ // add a custom-boot-pin to support pin-driven boot address
new testchipip.WithBootAddrReg ++ // add a boot-addr-reg for configurable boot address new testchipip.WithBootAddrReg ++ // add a boot-addr-reg for configurable boot address
@@ -57,8 +56,8 @@ class AbstractConfig extends Config(
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set) new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set)
new chipyard.config.WithMemoryBusFrequency(100.0) ++ // Default 100 MHz mbus new chipyard.config.WithMemoryBusFrequency(500.0) ++ // Default 500 MHz mbus
new chipyard.config.WithPeripheryBusFrequency(100.0) ++ // Default 100 MHz pbus new chipyard.config.WithPeripheryBusFrequency(500.0) ++ // Default 500 MHz pbus
new freechips.rocketchip.subsystem.WithNMemoryChannels(2) ++ // Default 2 memory channels new freechips.rocketchip.subsystem.WithNMemoryChannels(2) ++ // Default 2 memory channels
new freechips.rocketchip.subsystem.WithClockGateModel ++ // add default EICG_wrapper clock gate model new freechips.rocketchip.subsystem.WithClockGateModel ++ // add default EICG_wrapper clock gate model
new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port

View File

@@ -86,7 +86,7 @@ class MbusScratchpadRocketConfig extends Config(
// DOC include end: mbusscratchpadrocket // DOC include end: mbusscratchpadrocket
class MulticlockRocketConfig extends Config( class MulticlockRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore new freechips.rocketchip.subsystem.WithAsynchronousRocketTiles(3, 3) ++ // Add async crossings between RocketTile and uncore
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
// Frequency specifications // Frequency specifications
new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540 new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540

View File

@@ -4,12 +4,13 @@ import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.rocket.{DCacheParams} import freechips.rocketchip.rocket.{DCacheParams}
class AbstractTraceGenConfig extends Config( class AbstractTraceGenConfig extends Config(
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++
new chipyard.harness.WithBlackBoxSimMem ++ new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.harness.WithTraceGenSuccess ++ new chipyard.harness.WithTraceGenSuccess ++
new chipyard.harness.WithClockAndResetFromHarness ++ new chipyard.harness.WithClockAndResetFromHarness ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++ new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++ new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.clocking.WithDividerOnlyClockGenerator ++ new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithTracegenSystem ++ new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++ new chipyard.config.WithNoSubsystemDrivenClocks ++
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ new chipyard.config.WithPeripheryBusFrequencyAsDefault ++

View File

@@ -393,8 +393,8 @@ class WithClockAndResetFromHarness extends OverrideHarnessBinder({
implicit val p = GetSystemParameters(system) implicit val p = GetSystemParameters(system)
ports.map ({ ports.map ({
case c: ClockWithFreq => { case c: ClockWithFreq => {
th.setRefClockFreq(c.freqMHz) val clock = th.harnessClockInstantiator.requestClockBundle(s"clock_${c.freqMHz}MHz", c.freqMHz * (1000 * 1000))
c.clock := th.buildtopClock c.clock := clock.clock
} }
case r: AsyncReset => r := th.buildtopReset.asAsyncReset case r: AsyncReset => r := th.buildtopReset.asAsyncReset
}) })

View File

@@ -1,7 +1,8 @@
package chipyard.harness package chipyard.harness
import chisel3._ import chisel3._
import chisel3.util._
import chisel3.experimental.DoubleParam
import scala.collection.mutable.{ArrayBuffer, LinkedHashMap} import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.diplomacy.{LazyModule}
import org.chipsalliance.cde.config.{Field, Parameters, Config} import org.chipsalliance.cde.config.{Field, Parameters, Config}
@@ -36,44 +37,27 @@ trait HarnessClockInstantiator {
def instantiateHarnessClocks(refClock: ClockBundle): Unit def instantiateHarnessClocks(refClock: ClockBundle): Unit
} }
// The DividerOnlyHarnessClockInstantiator uses synthesizable clock divisors class ClockSourceAtFreqMHz(val freqMHz: Double) extends BlackBox(Map(
// to approximate frequency ratios between the requested clocks "PERIOD" -> DoubleParam(1000/freqMHz)
class DividerOnlyHarnessClockInstantiator extends HarnessClockInstantiator { )) with HasBlackBoxInline {
// connect all clock wires specified to a divider only PLL val io = IO(new ClockSourceIO)
def instantiateHarnessClocks(refClock: ClockBundle): Unit = { val moduleName = this.getClass.getSimpleName
val sinks = _clockMap.map({ case (name, (freq, bundle)) =>
ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))), name=Some(name))
}).toSeq
val pllConfig = new SimplePllConfiguration("harnessDividerOnlyClockGenerator", sinks) setInline(s"$moduleName.v",
pllConfig.emitSummaries() s"""
|module $moduleName #(parameter PERIOD="") (
val dividedClocks = LinkedHashMap[Int, Clock]() | input power,
def instantiateDivider(div: Int): Clock = { | input gate,
val divider = Module(new ClockDividerN(div)) | output clk);
divider.suggestName(s"ClockDivideBy${div}") | timeunit 1ns/1ps;
divider.io.clk_in := refClock.clock | reg clk_i = 1'b0;
dividedClocks(div) = divider.io.clk_out | always #(PERIOD/2.0) clk_i = ~clk_i & (power & ~gate);
divider.io.clk_out | assign clk = clk_i;
} |endmodule
|""".stripMargin)
// connect wires to clock source
for (sinkParams <- sinks) {
// bypass the reference freq. (don't create a divider + reset sync)
val (divClock, divReset) = if (sinkParams.take.get.freqMHz != pllConfig.referenceFreqMHz) {
val div = pllConfig.sinkDividerMap(sinkParams)
val divClock = dividedClocks.getOrElse(div, instantiateDivider(div))
(divClock, ResetCatchAndSync(divClock, refClock.reset.asBool))
} else {
(refClock.clock, refClock.reset)
}
_clockMap(sinkParams.name.get)._2.clock := divClock
_clockMap(sinkParams.name.get)._2.reset := divReset
}
}
} }
// The AbsoluteFreqHarnessClockInstantiator uses a Verilog blackbox to // The AbsoluteFreqHarnessClockInstantiator uses a Verilog blackbox to
// provide the precise requested frequency. // provide the precise requested frequency.
// This ClockInstantiator cannot be synthesized, run in Verilator, or run in FireSim // This ClockInstantiator cannot be synthesized, run in Verilator, or run in FireSim
@@ -86,7 +70,7 @@ class AbsoluteFreqHarnessClockInstantiator extends HarnessClockInstantiator {
// connect wires to clock source // connect wires to clock source
for (sinkParams <- sinks) { for (sinkParams <- sinks) {
val source = Module(new ClockSourceAtFreq(sinkParams.take.get.freqMHz)) val source = Module(new ClockSourceAtFreqMHz(sinkParams.take.get.freqMHz))
source.io.power := true.B source.io.power := true.B
source.io.gate := false.B source.io.gate := false.B
@@ -99,3 +83,18 @@ class AbsoluteFreqHarnessClockInstantiator extends HarnessClockInstantiator {
class WithAbsoluteFreqHarnessClockInstantiator extends Config((site, here, up) => { class WithAbsoluteFreqHarnessClockInstantiator extends Config((site, here, up) => {
case HarnessClockInstantiatorKey => () => new AbsoluteFreqHarnessClockInstantiator case HarnessClockInstantiatorKey => () => new AbsoluteFreqHarnessClockInstantiator
}) })
class AllClocksFromHarnessClockInstantiator extends HarnessClockInstantiator {
def instantiateHarnessClocks(refClock: ClockBundle): Unit = {
val freqs = _clockMap.map(_._2._1)
freqs.tail.foreach(t => require(t == freqs.head, s"Mismatching clocks $t != ${freqs.head}"))
for ((_, (_, bundle)) <- _clockMap) {
bundle.clock := refClock.clock
bundle.reset := refClock.reset
}
}
}
class WithAllClocksFromHarnessClockInstantiator extends Config((site, here, up) => {
case HarnessClockInstantiatorKey => () => new AllClocksFromHarnessClockInstantiator
})

View File

@@ -19,7 +19,7 @@ import chipyard.{ChipTop}
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p)) case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
case object DefaultClockFrequencyKey extends Field[Double](100.0) // MHz case object DefaultClockFrequencyKey extends Field[Double](100.0) // MHz
case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator](() => new DividerOnlyHarnessClockInstantiator) case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator]()
trait HasHarnessSignalReferences { trait HasHarnessSignalReferences {
implicit val p: Parameters implicit val p: Parameters