Unify multi-node btw chipyard/firechip | unify harness clocking

This commit is contained in:
Jerry Zhao
2023-05-12 08:21:18 -07:00
parent 0cbca54e19
commit 607c2b5a73
31 changed files with 441 additions and 634 deletions

View File

@@ -21,8 +21,12 @@ class WithArtyTweaks extends Config(
new WithArtyJTAGHarnessBinder ++ new WithArtyJTAGHarnessBinder ++
new WithArtyUARTHarnessBinder ++ new WithArtyUARTHarnessBinder ++
new WithDebugResetPassthrough ++ new WithDebugResetPassthrough ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(32) ++
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++ new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.config.WithDTSTimebase(32768) ++ new chipyard.config.WithDTSTimebase(32768) ++
new chipyard.config.WithSystemBusFrequency(32) ++
new chipyard.config.WithPeripheryBusFrequency(32) ++
new testchipip.WithNoSerialTL new testchipip.WithNoSerialTL
) )

View File

@@ -31,7 +31,7 @@ class WithArtyResetHarnessBinder extends ComposeHarnessBinder({
class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({ class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({
(system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => { (system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => {
ports.map { ports.map {
case j: JTAGChipIO => withClockAndReset(th.buildtopClock, th.hReset) { case j: JTAGChipIO => {
val jtag_wire = Wire(new JTAGIO) val jtag_wire = Wire(new JTAGIO)
jtag_wire.TDO.data := j.TDO jtag_wire.TDO.data := j.TDO
jtag_wire.TDO.driven := true.B jtag_wire.TDO.driven := true.B

View File

@@ -8,13 +8,10 @@ import org.chipsalliance.cde.config.{Parameters}
import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell} import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
import chipyard.harness.{ApplyHarnessBinders, BuildTop, HasHarnessSignalReferences} import chipyard.harness.{HasHarnessInstantiators}
import chipyard.iobinders.{HasIOBinders} import chipyard.iobinders.{HasIOBinders}
class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessSignalReferences { class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessInstantiators {
val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
// Convert harness resets from Bool to Reset type. // Convert harness resets from Bool to Reset type.
val hReset = Wire(Reset()) val hReset = Wire(Reset())
hReset := ~ck_rst hReset := ~ck_rst
@@ -22,24 +19,10 @@ class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell
val dReset = Wire(AsyncReset()) val dReset = Wire(AsyncReset())
dReset := reset_core.asAsyncReset dReset := reset_core.asAsyncReset
// default to 32MHz clock def success = {require(false, "Success not supported"); false.B }
withClockAndReset(clock_32MHz, hReset) {
val dut = Module(lazyDut.module)
}
val buildtopClock = clock_32MHz def implicitClock = clock_32MHz
val buildtopReset = hReset def implicitReset = hReset
val success = false.B
val dutReset = dReset instantiateChipTops()
// must be after HasHarnessSignalReferences assignments
lazyDut match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := buildtopClock
implicitHarnessClockBundle.reset := buildtopReset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }

View File

@@ -26,6 +26,12 @@ class WithArty100TTweaks extends Config(
new WithArty100TUARTTSI ++ new WithArty100TUARTTSI ++
new WithArty100TDDRTL ++ new WithArty100TDDRTL ++
new WithNoDesignKey ++ new WithNoDesignKey ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(50) ++
new chipyard.config.WithMemoryBusFrequency(50.0) ++
new chipyard.config.WithSystemBusFrequency(50.0) ++
new chipyard.config.WithPeripheryBusFrequency(50.0) ++
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithNoDebug ++ // no jtag new chipyard.config.WithNoDebug ++ // no jtag
new chipyard.config.WithNoUART ++ // use UART for the UART-TSI thing instad new chipyard.config.WithNoUART ++ // use UART for the UART-TSI thing instad
new chipyard.config.WithTLBackingMemory ++ // FPGA-shells converts the AXI to TL for us new chipyard.config.WithTLBackingMemory ++ // FPGA-shells converts the AXI to TL for us
@@ -34,8 +40,6 @@ class WithArty100TTweaks extends Config(
class RocketArty100TConfig extends Config( class RocketArty100TConfig extends Config(
new WithArty100TTweaks ++ new WithArty100TTweaks ++
new chipyard.config.WithMemoryBusFrequency(50.0) ++
new chipyard.config.WithPeripheryBusFrequency(50.0) ++ // Match the sbus and pbus frequency
new chipyard.config.WithBroadcastManager ++ // no l2 new chipyard.config.WithBroadcastManager ++ // no l2
new chipyard.RocketConfig) new chipyard.RocketConfig)

View File

@@ -4,8 +4,9 @@ import chisel3._
import chisel3.util._ 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._
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters} import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
import freechips.rocketchip.subsystem.{SystemBusKey}
import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.shell.xilinx._
import sifive.fpgashells.shell._ import sifive.fpgashells.shell._
@@ -14,21 +15,21 @@ import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
import sifive.blocks.devices.uart._ import sifive.blocks.devices.uart._
import chipyard.{ChipTop, CanHaveMasterTLMemPort, ExtTLMem} import chipyard._
import chipyard.harness._ import chipyard.harness._
import chipyard.iobinders.{HasIOBinders} import chipyard.iobinders.{HasIOBinders}
class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell with HasHarnessSignalReferences class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell {
{
def dp = designParameters def dp = designParameters
val chiptop = LazyModule(p(BuildTop)(p)) require(dp(MultiChipNChips) == 0, "Arty100T harness does not support multi-chip")
val clockOverlay = dp(ClockInputOverlayKey).map(_.place(ClockInputDesignInput())).head val clockOverlay = dp(ClockInputOverlayKey).map(_.place(ClockInputDesignInput())).head
val harnessSysPLL = dp(PLLFactoryKey) val harnessSysPLL = dp(PLLFactoryKey)
val harnessSysPLLNode = harnessSysPLL() val harnessSysPLLNode = harnessSysPLL()
println(s"Arty100T FPGA Base Clock Freq: ${dp(DefaultClockFrequencyKey)} MHz") val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
val dutClock = ClockSinkNode(freqMHz = dp(DefaultClockFrequencyKey)) val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
println(s"Arty100T FPGA Base Clock Freq: ${dutFreqMHz} MHz")
val dutWrangler = LazyModule(new ResetWrangler()) val dutWrangler = LazyModule(new ResetWrangler())
val dutGroup = ClockGroup() val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLLNode dutClock := dutWrangler.node := dutGroup := harnessSysPLLNode
@@ -39,12 +40,10 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell
val uartOverlay = dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) val uartOverlay = dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb))
val ddrOverlay = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLLNode)).asInstanceOf[DDRArtyPlacedOverlay] val ddrOverlay = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLLNode)).asInstanceOf[DDRArtyPlacedOverlay]
val ddrInParams = chiptop match { case td: ChipTop => val ddrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
td.lazySystem match { case lsys: CanHaveMasterTLMemPort => name = "chip_ddr",
lsys.memTLNode.edges.in(0) sourceId = IdRange(0, 64)
} )))))
}
val ddrClient = TLClientNode(Seq(ddrInParams.master))
val ddrBlockDuringReset = LazyModule(new TLBlockDuringReset(4)) val ddrBlockDuringReset = LazyModule(new TLBlockDuringReset(4))
ddrOverlay.overlayOutput.ddr := ddrBlockDuringReset.node := ddrClient ddrOverlay.overlayOutput.ddr := ddrBlockDuringReset.node := ddrClient
@@ -53,17 +52,16 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell
val status_leds = all_leds.take(3) val status_leds = all_leds.take(3)
val other_leds = all_leds.drop(3) val other_leds = all_leds.drop(3)
def buildtopClock = dutClock.in.head._1.clock
def buildtopReset = dutClock.in.head._1.reset
def success = { require(false, "Unused"); false.B }
InModuleBody { override lazy val module = new HarnessLikeImpl
class HarnessLikeImpl extends Impl with HasHarnessInstantiators {
clockOverlay.overlayOutput.node.out(0)._1.reset := ~resetPin clockOverlay.overlayOutput.node.out(0)._1.reset := ~resetPin
val clk_100mhz = clockOverlay.overlayOutput.node.out.head._1.clock val clk_100mhz = clockOverlay.overlayOutput.node.out.head._1.clock
// Blink the status LEDs for sanity // Blink the status LEDs for sanity
withClock(clk_100mhz) { withClockAndReset(clk_100mhz, dutClock.in.head._1.reset) {
val period = (BigInt(100) << 20) / status_leds.size val period = (BigInt(100) << 20) / status_leds.size
val counter = RegInit(0.U(log2Ceil(period).W)) val counter = RegInit(0.U(log2Ceil(period).W))
val on = RegInit(0.U(log2Ceil(status_leds.size).W)) val on = RegInit(0.U(log2Ceil(status_leds.size).W))
@@ -78,21 +76,17 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell
harnessSysPLL.plls.foreach(_._1.getReset.get := pllReset) harnessSysPLL.plls.foreach(_._1.getReset.get := pllReset)
ddrOverlay.mig.module.clock := buildtopClock def implicitClock = dutClock.in.head._1.clock
ddrOverlay.mig.module.reset := buildtopReset def implicitReset = dutClock.in.head._1.reset
ddrBlockDuringReset.module.clock := buildtopClock def success = { require(false, "Unused"); false.B }
ddrBlockDuringReset.module.reset := buildtopReset || !ddrOverlay.mig.module.io.port.init_calib_complete
ddrOverlay.mig.module.clock := harnessBinderClock
ddrOverlay.mig.module.reset := harnessBinderReset
ddrBlockDuringReset.module.clock := harnessBinderClock
ddrBlockDuringReset.module.reset := harnessBinderReset.asBool || !ddrOverlay.mig.module.io.port.init_calib_complete
other_leds(6) := ddrOverlay.mig.module.io.port.init_calib_complete other_leds(6) := ddrOverlay.mig.module.io.port.init_calib_complete
chiptop match { case d: HasIOBinders => instantiateChipTops()
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := buildtopClock
implicitHarnessClockBundle.reset := buildtopReset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }
} }

View File

@@ -6,6 +6,7 @@ import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.subsystem.{PeripheryBusKey} import freechips.rocketchip.subsystem.{PeripheryBusKey}
import freechips.rocketchip.tilelink.{TLBundle} import freechips.rocketchip.tilelink.{TLBundle}
import freechips.rocketchip.util.{HeterogeneousBag} import freechips.rocketchip.util.{HeterogeneousBag}
import freechips.rocketchip.diplomacy.{LazyRawModuleImp}
import sifive.blocks.devices.uart.{UARTPortIO, HasPeripheryUARTModuleImp, UARTParams} import sifive.blocks.devices.uart.{UARTPortIO, HasPeripheryUARTModuleImp, UARTParams}
import sifive.blocks.devices.jtag.{JTAGPins, JTAGPinsFromPort} import sifive.blocks.devices.jtag.{JTAGPins, JTAGPinsFromPort}
@@ -20,39 +21,37 @@ import chipyard.iobinders.JTAGChipIO
import testchipip._ import testchipip._
class WithArty100TUARTTSI(uartBaudRate: BigInt = 115200) extends OverrideHarnessBinder({ class WithArty100TUARTTSI(uartBaudRate: BigInt = 115200) extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { (system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system) implicit val p = chipyard.iobinders.GetSystemParameters(system)
ports.map({ port => ports.map({ port =>
val ath = th.asInstanceOf[Arty100THarness] val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
val freq = p(PeripheryBusKey).dtsFrequency.get val freq = p(PeripheryBusKey).dtsFrequency.get
val bits = port.bits val bits = port.bits
port.clock := th.buildtopClock port.clock := th.harnessBinderClock
withClockAndReset(th.buildtopClock, th.buildtopReset) { val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.buildtopReset) val uart_to_serial = Module(new UARTToSerial(
val uart_to_serial = Module(new UARTToSerial( freq, UARTParams(0, initBaudRate=uartBaudRate)))
freq, UARTParams(0, initBaudRate=uartBaudRate))) val serial_width_adapter = Module(new SerialWidthAdapter(
val serial_width_adapter = Module(new SerialWidthAdapter( narrowW = 8, wideW = TSI.WIDTH))
narrowW = 8, wideW = TSI.WIDTH)) serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
ram.module.io.tsi.flipConnect(serial_width_adapter.io.wide) ram.module.io.tsi.flipConnect(serial_width_adapter.io.wide)
ath.io_uart_bb.bundle <> uart_to_serial.io.uart ath.io_uart_bb.bundle <> uart_to_serial.io.uart
ath.other_leds(1) := uart_to_serial.io.dropped ath.other_leds(1) := uart_to_serial.io.dropped
ath.other_leds(9) := ram.module.io.tsi2tl_state(0) ath.other_leds(9) := ram.module.io.tsi2tl_state(0)
ath.other_leds(10) := ram.module.io.tsi2tl_state(1) ath.other_leds(10) := ram.module.io.tsi2tl_state(1)
ath.other_leds(11) := ram.module.io.tsi2tl_state(2) ath.other_leds(11) := ram.module.io.tsi2tl_state(2)
ath.other_leds(12) := ram.module.io.tsi2tl_state(3) ath.other_leds(12) := ram.module.io.tsi2tl_state(3)
}
}) })
} }
}) })
class WithArty100TDDRTL extends OverrideHarnessBinder({ class WithArty100TDDRTL extends OverrideHarnessBinder({
(system: CanHaveMasterTLMemPort, th: HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => { (system: CanHaveMasterTLMemPort, th: HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => {
require(ports.size == 1) require(ports.size == 1)
val artyTh = th.asInstanceOf[Arty100THarness] val artyTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
val bundles = artyTh.ddrClient.out.map(_._1) val bundles = artyTh.ddrClient.out.map(_._1)
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType))) val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }

View File

@@ -18,7 +18,7 @@ import sifive.fpgashells.shell.xilinx.{VC7074GDDRSize}
import testchipip.{SerialTLKey} import testchipip.{SerialTLKey}
import chipyard.{BuildSystem, ExtTLMem} import chipyard.{BuildSystem, ExtTLMem}
import chipyard.harness.{DefaultClockFrequencyKey} import chipyard.harness._
class WithDefaultPeripherals extends Config((site, here, up) => { class WithDefaultPeripherals extends Config((site, here, up) => {
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L))) case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
@@ -29,7 +29,7 @@ class WithSystemModifications extends Config((site, here, up) => {
case DTSTimebase => BigInt{(1e6).toLong} case DTSTimebase => BigInt{(1e6).toLong}
case BootROMLocated(x) => up(BootROMLocated(x), site).map { p => case BootROMLocated(x) => up(BootROMLocated(x), site).map { p =>
// invoke makefile for sdboot // invoke makefile for sdboot
val freqMHz = (site(DefaultClockFrequencyKey) * 1e6).toLong val freqMHz = (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toLong
val make = s"make -C fpga/src/main/resources/vc707/sdboot PBUS_CLK=${freqMHz} bin" val make = s"make -C fpga/src/main/resources/vc707/sdboot PBUS_CLK=${freqMHz} bin"
require (make.! == 0, "Failed to build bootrom") require (make.! == 0, "Failed to build bootrom")
p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vc707/sdboot/build/sdboot.bin") p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vc707/sdboot/build/sdboot.bin")
@@ -39,6 +39,15 @@ class WithSystemModifications extends Config((site, here, up) => {
}) })
class WithVC707Tweaks extends Config ( class WithVC707Tweaks extends Config (
// clocking
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithMemoryBusFrequency(50.0) ++
new chipyard.config.WithSystemBusFrequency(50.0) ++
new chipyard.config.WithPeripheryBusFrequency(50.0) ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(50) ++
new WithFPGAFrequency(50) ++ // default 50MHz freq
// harness binders // harness binders
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++ new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new WithVC707UARTHarnessBinder ++ new WithVC707UARTHarnessBinder ++
@@ -54,8 +63,7 @@ class WithVC707Tweaks extends Config (
new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size
new chipyard.config.WithNoDebug ++ // remove debug module new chipyard.config.WithNoDebug ++ // remove debug module
new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ new freechips.rocketchip.subsystem.WithNMemoryChannels(1)
new WithFPGAFrequency(50) // default 50MHz freq
) )
class RocketVC707Config extends Config ( class RocketVC707Config extends Config (

View File

@@ -1,25 +1,25 @@
package chipyard.fpga.vc707 package chipyard.fpga.vc707
import chisel3._ import chisel3._
import chisel3.experimental.{IO} 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._
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters} import freechips.rocketchip.subsystem.{SystemBusKey}
import freechips.rocketchip.diplomacy.{IdRange, TransferSizes}
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}
import sifive.fpgashells.shell.{ClockInputOverlayKey, ClockInputDesignInput, UARTOverlayKey, UARTDesignInput, UARTShellInput, LEDOverlayKey, LEDDesignInput, SwitchOverlayKey, SwitchDesignInput, ButtonOverlayKey, ButtonDesignInput, SPIOverlayKey, SPIDesignInput, ChipLinkOverlayKey, ChipLinkDesignInput, PCIeOverlayKey, PCIeDesignInput, PCIeShellInput, DDROverlayKey, DDRDesignInput, JTAGDebugOverlayKey, JTAGDebugDesignInput} import sifive.fpgashells.shell._
import sifive.fpgashells.clocks.{ClockGroup, ClockSinkNode, PLLFactoryKey, ResetWrangler} import sifive.fpgashells.clocks.{ClockGroup, ClockSinkNode, PLLFactoryKey, ResetWrangler}
import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{XilinxVC707PCIeX1IO} import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{XilinxVC707PCIeX1IO}
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTPortIO} import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTPortIO}
import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO} import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO}
import chipyard.{ChipTop, ExtTLMem, CanHaveMasterTLMemPort} import chipyard._
import chipyard.iobinders.{HasIOBinders} import chipyard.iobinders.{HasIOBinders}
import chipyard.harness.{ApplyHarnessBinders, HasHarnessSignalReferences, BuildTop, DefaultClockFrequencyKey} import chipyard.harness._
class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707Shell { outer => class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707Shell { outer =>
@@ -28,8 +28,6 @@ class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707She
// Order matters; ddr depends on sys_clock // Order matters; ddr depends on sys_clock
val uart = Overlay(UARTOverlayKey, new UARTVC707ShellPlacer(this, UARTShellInput())) val uart = Overlay(UARTOverlayKey, new UARTVC707ShellPlacer(this, UARTShellInput()))
val topDesign = LazyModule(p(BuildTop)(dp)).suggestName("chiptop")
// place all clocks in the shell // place all clocks in the shell
require(dp(ClockInputOverlayKey).size >= 1) require(dp(ClockInputOverlayKey).size >= 1)
val sysClkNode = dp(ClockInputOverlayKey).head.place(ClockInputDesignInput()).overlayOutput.node val sysClkNode = dp(ClockInputOverlayKey).head.place(ClockInputDesignInput()).overlayOutput.node
@@ -41,8 +39,9 @@ class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707She
harnessSysPLL := sysClkNode harnessSysPLL := sysClkNode
// create and connect to the dutClock // create and connect to the dutClock
println(s"VC707 FPGA Base Clock Freq: ${dp(DefaultClockFrequencyKey)} MHz") val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
val dutClock = ClockSinkNode(freqMHz = dp(DefaultClockFrequencyKey)) val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
println(s"VC707 FPGA Base Clock Freq: ${dutFreqMHz} MHz")
val dutWrangler = LazyModule(new ResetWrangler) val dutWrangler = LazyModule(new ResetWrangler)
val dutGroup = ClockGroup() val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL dutClock := dutWrangler.node := dutGroup := harnessSysPLL
@@ -77,21 +76,19 @@ class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707She
// Modify the last field of `DDRDesignInput` for 1GB RAM size // Modify the last field of `DDRDesignInput` for 1GB RAM size
val ddrNode = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLL, true)).overlayOutput.ddr val ddrNode = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLL, true)).overlayOutput.ddr
val ddrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = "chip_ddr",
sourceId = IdRange(0, 64)
)))))
// connect 1 mem. channel to the FPGA DDR
val inParams = topDesign match { case td: ChipTop =>
td.lazySystem match { case lsys: CanHaveMasterTLMemPort =>
lsys.memTLNode.edges.in(0)
}
}
val ddrClient = TLClientNode(Seq(inParams.master))
ddrNode := ddrClient ddrNode := ddrClient
// module implementation // module implementation
override lazy val module = new VC707FPGATestHarnessImp(this) override lazy val module = new VC707FPGATestHarnessImp(this)
} }
class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences { class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessInstantiators {
require (p(MultiChipNChips) == 0)
val vc707Outer = _outer val vc707Outer = _outer
@@ -117,25 +114,12 @@ class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModul
val hReset = Wire(Reset()) val hReset = Wire(Reset())
hReset := _outer.dutClock.in.head._1.reset hReset := _outer.dutClock.in.head._1.reset
val buildtopClock = _outer.dutClock.in.head._1.clock def implicitClock = _outer.dutClock.in.head._1.clock
val buildtopReset = WireInit(hReset) def implicitReset = hReset
val dutReset = hReset.asAsyncReset def success = { require(false, "Unused"); false.B }
val success = false.B
childClock := buildtopClock childClock := implicitClock
childReset := buildtopReset childReset := implicitReset
// harness binders are non-lazy instantiateChipTops()
_outer.topDesign match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
// check the top-level reference clock is equal to the default
// non-exhaustive since you need all ChipTop clocks to equal the default
require(getRefClockFreq == p(DefaultClockFrequencyKey))
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := buildtopClock
implicitHarnessClockBundle.reset := buildtopReset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }

View File

@@ -17,8 +17,8 @@ import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize}
import testchipip.{SerialTLKey} import testchipip.{SerialTLKey}
import chipyard.{BuildSystem, ExtTLMem} import chipyard._
import chipyard.harness.{DefaultClockFrequencyKey} import chipyard.harness._
class WithDefaultPeripherals extends Config((site, here, up) => { class WithDefaultPeripherals extends Config((site, here, up) => {
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L))) case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
@@ -30,7 +30,7 @@ class WithSystemModifications extends Config((site, here, up) => {
case DTSTimebase => BigInt((1e6).toLong) case DTSTimebase => BigInt((1e6).toLong)
case BootROMLocated(x) => up(BootROMLocated(x), site).map { p => case BootROMLocated(x) => up(BootROMLocated(x), site).map { p =>
// invoke makefile for sdboot // invoke makefile for sdboot
val freqMHz = (site(DefaultClockFrequencyKey) * 1e6).toLong val freqMHz = (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toLong
val make = s"make -C fpga/src/main/resources/vcu118/sdboot PBUS_CLK=${freqMHz} bin" val make = s"make -C fpga/src/main/resources/vcu118/sdboot PBUS_CLK=${freqMHz} bin"
require (make.! == 0, "Failed to build bootrom") require (make.! == 0, "Failed to build bootrom")
p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vcu118/sdboot/build/sdboot.bin") p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vcu118/sdboot/build/sdboot.bin")
@@ -41,8 +41,14 @@ 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 // clocking
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++ new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithMemoryBusFrequency(100) ++
new chipyard.config.WithSystemBusFrequency(100) ++
new chipyard.config.WithPeripheryBusFrequency(100) ++
new WithFPGAFrequency(100) ++ // default 100MHz freq
// harness binders
new WithUART ++ new WithUART ++
new WithSPISDCard ++ new WithSPISDCard ++
new WithDDRMem ++ new WithDDRMem ++
@@ -55,8 +61,7 @@ class WithVCU118Tweaks extends Config(
new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size
new chipyard.config.WithNoDebug ++ // remove debug module new chipyard.config.WithNoDebug ++ // remove debug module
new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ new freechips.rocketchip.subsystem.WithNMemoryChannels(1)
new WithFPGAFrequency(100) // default 100MHz freq
) )
class RocketVCU118Config extends Config( class RocketVCU118Config extends Config(

View File

@@ -9,12 +9,12 @@ import freechips.rocketchip.tilelink.{TLBundle}
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO} import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO} import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
import chipyard.{CanHaveMasterTLMemPort} import chipyard._
import chipyard.harness.{HasHarnessSignalReferences, OverrideHarnessBinder} import chipyard.harness._
/*** UART ***/ /*** UART ***/
class WithUART extends OverrideHarnessBinder({ class WithUART extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
th match { case vcu118th: VCU118FPGATestHarnessImp => { th match { case vcu118th: VCU118FPGATestHarnessImp => {
vcu118th.vcu118Outer.io_uart_bb.bundle <> ports.head vcu118th.vcu118Outer.io_uart_bb.bundle <> ports.head
} } } }
@@ -23,7 +23,7 @@ class WithUART extends OverrideHarnessBinder({
/*** SPI ***/ /*** SPI ***/
class WithSPISDCard extends OverrideHarnessBinder({ class WithSPISDCard extends OverrideHarnessBinder({
(system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => { (system: HasPeripherySPI, th: BaseModule with HasHarnessInstantiators, ports: Seq[SPIPortIO]) => {
th match { case vcu118th: VCU118FPGATestHarnessImp => { th match { case vcu118th: VCU118FPGATestHarnessImp => {
vcu118th.vcu118Outer.io_spi_bb.bundle <> ports.head vcu118th.vcu118Outer.io_spi_bb.bundle <> ports.head
} } } }
@@ -32,7 +32,7 @@ class WithSPISDCard extends OverrideHarnessBinder({
/*** Experimental DDR ***/ /*** Experimental DDR ***/
class WithDDRMem extends OverrideHarnessBinder({ class WithDDRMem extends OverrideHarnessBinder({
(system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => { (system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => {
th match { case vcu118th: VCU118FPGATestHarnessImp => { th match { case vcu118th: VCU118FPGATestHarnessImp => {
require(ports.size == 1) require(ports.size == 1)

View File

@@ -5,8 +5,9 @@ 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._
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters} import freechips.rocketchip.diplomacy.{IdRange, TransferSizes}
import freechips.rocketchip.subsystem.{SystemBusKey}
import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.shell.xilinx._
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly} import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
@@ -38,8 +39,6 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
val sys_clock2 = Overlay(ClockInputOverlayKey, new SysClock2VCU118ShellPlacer(this, ClockInputShellInput())) val sys_clock2 = Overlay(ClockInputOverlayKey, new SysClock2VCU118ShellPlacer(this, ClockInputShellInput()))
val ddr2 = Overlay(DDROverlayKey, new DDR2VCU118ShellPlacer(this, DDRShellInput())) val ddr2 = Overlay(DDROverlayKey, new DDR2VCU118ShellPlacer(this, DDRShellInput()))
val topDesign = LazyModule(p(BuildTop)(dp)).suggestName("chiptop")
// DOC include start: ClockOverlay // DOC include start: ClockOverlay
// place all clocks in the shell // place all clocks in the shell
require(dp(ClockInputOverlayKey).size >= 1) require(dp(ClockInputOverlayKey).size >= 1)
@@ -52,8 +51,9 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
harnessSysPLL := sysClkNode harnessSysPLL := sysClkNode
// create and connect to the dutClock // create and connect to the dutClock
println(s"VCU118 FPGA Base Clock Freq: ${dp(DefaultClockFrequencyKey)} MHz") val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
val dutClock = ClockSinkNode(freqMHz = dp(DefaultClockFrequencyKey)) val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
println(s"VCU118 FPGA Base Clock Freq: ${dutFreqMHz} MHz")
val dutWrangler = LazyModule(new ResetWrangler) val dutWrangler = LazyModule(new ResetWrangler)
val dutGroup = ClockGroup() val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL dutClock := dutWrangler.node := dutGroup := harnessSysPLL
@@ -80,19 +80,18 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
val ddrNode = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLL)).overlayOutput.ddr val ddrNode = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLL)).overlayOutput.ddr
// connect 1 mem. channel to the FPGA DDR // connect 1 mem. channel to the FPGA DDR
val inParams = topDesign match { case td: ChipTop => val ddrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
td.lazySystem match { case lsys: CanHaveMasterTLMemPort => name = "chip_ddr",
lsys.memTLNode.edges.in(0) sourceId = IdRange(0, 64)
} )))))
}
val ddrClient = TLClientNode(Seq(inParams.master))
ddrNode := ddrClient ddrNode := ddrClient
// module implementation // module implementation
override lazy val module = new VCU118FPGATestHarnessImp(this) override lazy val module = new VCU118FPGATestHarnessImp(this)
} }
class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences { class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessInstantiators {
require(p(MultiChipNChips) == 0)
val vcu118Outer = _outer val vcu118Outer = _outer
@@ -119,25 +118,12 @@ class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawMod
val hReset = Wire(Reset()) val hReset = Wire(Reset())
hReset := _outer.dutClock.in.head._1.reset hReset := _outer.dutClock.in.head._1.reset
val buildtopClock = _outer.dutClock.in.head._1.clock def implicitClock = _outer.dutClock.in.head._1.clock
val buildtopReset = WireInit(hReset) def implicitReset = hReset
val dutReset = hReset.asAsyncReset def success = { require(false, "Unused"); false.B }
val success = false.B
childClock := buildtopClock childClock := implicitClock
childReset := buildtopReset childReset := implicitReset
// harness binders are non-lazy instantiateChipTops()
_outer.topDesign match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
// check the top-level reference clock is equal to the default
// non-exhaustive since you need all ChipTop clocks to equal the default
require(getRefClockFreq == p(DefaultClockFrequencyKey))
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := buildtopClock
implicitHarnessClockBundle.reset := buildtopReset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }

View File

@@ -13,11 +13,11 @@ import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp, GPIOPortIO}
import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO} import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO}
import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder, HasHarnessSignalReferences} import chipyard.harness._
/*** UART ***/ /*** UART ***/
class WithBringupUART extends ComposeHarnessBinder({ class WithBringupUART extends ComposeHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
require(ports.size == 2) require(ports.size == 2)
@@ -28,7 +28,7 @@ class WithBringupUART extends ComposeHarnessBinder({
/*** I2C ***/ /*** I2C ***/
class WithBringupI2C extends OverrideHarnessBinder({ class WithBringupI2C extends OverrideHarnessBinder({
(system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[I2CPort]) => { (system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[I2CPort]) => {
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
require(ports.size == 1) require(ports.size == 1)
@@ -39,7 +39,7 @@ class WithBringupI2C extends OverrideHarnessBinder({
/*** GPIO ***/ /*** GPIO ***/
class WithBringupGPIO extends OverrideHarnessBinder({ class WithBringupGPIO extends OverrideHarnessBinder({
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => { (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[GPIOPortIO]) => {
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
(vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) => (vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) =>
bb_io.bundle <> dut_io bb_io.bundle <> dut_io
@@ -50,7 +50,7 @@ class WithBringupGPIO extends OverrideHarnessBinder({
/*** TSI Host Widget ***/ /*** TSI Host Widget ***/
class WithBringupTSIHost extends OverrideHarnessBinder({ class WithBringupTSIHost extends OverrideHarnessBinder({
(system: HasPeripheryTSIHostWidget, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { (system: HasPeripheryTSIHostWidget, th: BaseModule with HasHarnessInstantiators, ports: Seq[Data]) => {
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
require(ports.size == 2) // 1st goes to the TL mem, 2nd goes to the serial link require(ports.size == 2) // 1st goes to the TL mem, 2nd goes to the serial link

View File

@@ -1,5 +1,4 @@
package chipyard.fpga.vcu118.bringup package chipyard.fpga.vcu118.bringup
import chisel3._ import chisel3._
import freechips.rocketchip.diplomacy._ import freechips.rocketchip.diplomacy._
@@ -22,6 +21,7 @@ import testchipip.{HasPeripheryTSIHostWidget, PeripheryTSIHostKey, TSIHostWidget
import chipyard.fpga.vcu118.{VCU118FPGATestHarness, VCU118FPGATestHarnessImp, DDR2VCU118ShellPlacer, SysClock2VCU118ShellPlacer} import chipyard.fpga.vcu118.{VCU118FPGATestHarness, VCU118FPGATestHarnessImp, DDR2VCU118ShellPlacer, SysClock2VCU118ShellPlacer}
import chipyard.{ChipTop} import chipyard.{ChipTop}
import chipyard.harness._
class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118FPGATestHarness { class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118FPGATestHarness {
@@ -78,12 +78,10 @@ class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends
dp(TSIHostOverlayKey).head.place(TSIHostDesignInput(dp(PeripheryTSIHostKey).head.offchipSerialIfWidth, io_tsi_serial_bb)) dp(TSIHostOverlayKey).head.place(TSIHostDesignInput(dp(PeripheryTSIHostKey).head.offchipSerialIfWidth, io_tsi_serial_bb))
// connect 1 mem. channel to the FPGA DDR // connect 1 mem. channel to the FPGA DDR
val inTsiParams = topDesign match { case td: ChipTop => val tsiDdrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
td.lazySystem match { case lsys: HasPeripheryTSIHostWidget => name = "chip_ddr",
lsys.tsiMemTLNodes.head.edges.in(0) sourceId = IdRange(0, 64)
} )))))
}
val tsiDdrClient = TLClientNode(Seq(inTsiParams.master))
(ddr2Node (ddr2Node
:= TLFragmenter(8,64,holdFirstDeny=true) := TLFragmenter(8,64,holdFirstDeny=true)
:= TLCacheCork() := TLCacheCork()

View File

@@ -111,6 +111,7 @@ class WithPassthroughClockGenerator extends OverrideLazyIOBinder({
val (bundle, edge) = clockGroupAggNode.out(0) val (bundle, edge) = clockGroupAggNode.out(0)
val clock_ios = (bundle.member.data zip edge.sink.members).map { case (b, m) => val clock_ios = (bundle.member.data zip edge.sink.members).map { case (b, m) =>
require(m.take.isDefined, s"Clock ${m.name.get} has no requested frequency")
val freq = m.take.get.freqMHz val freq = m.take.get.freqMHz
val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}") val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}")
b.clock := clock_io.clock b.clock := clock_io.clock

View File

@@ -23,10 +23,9 @@ object ClockGroupCombiner {
case object ClockGroupCombinerKey extends Field[Seq[(String, ClockSinkParameters => Boolean)]](Nil) case object ClockGroupCombinerKey extends Field[Seq[(String, ClockSinkParameters => Boolean)]](Nil)
// All clock groups with a name containing any substring in names will be combined into a single clock group // All clock groups with a name containing any substring in names will be combined into a single clock group
class WithClockGroupsCombinedByName(grouped_name: String, names: String*) extends Config((site, here, up) => { class WithClockGroupsCombinedByName(groups: (String, Seq[String])*) extends Config((site, here, up) => {
case ClockGroupCombinerKey => { case ClockGroupCombinerKey => groups.map { case (grouped_name, matched_names) =>
val combiner: ClockSinkParameters => Boolean = { m => names.map(n => m.name.get.contains(n)).reduce(_||_) } (grouped_name, (m: ClockSinkParameters) => matched_names.map(n => m.name.get.contains(n)).reduce(_||_))
up(ClockGroupCombinerKey) ++ Seq((grouped_name, combiner))
} }
}) })
@@ -49,9 +48,14 @@ class ClockGroupCombiner(implicit p: Parameters, v: ValName) extends LazyModule
val name = combiners(i)._1 val name = combiners(i)._1
i = i + 1 i = i + 1
require(g.size >= 1) require(g.size >= 1)
require(g.forall(_.take.get == g.head.take.get)) val takes = g.map(_.take).flatten
(grouped ++ Seq(ClockSinkParameters(take = g.head.take, name = Some(name))), r) require(takes.distinct.size <= 1,
s"Clock group $name has non-homogeneous requested ClockParameters $takes")
require(takes.size > 0,
s"Clock group $name has no inheritable frequencies")
(grouped ++ Seq(ClockSinkParameters(take = takes.headOption, name = Some(name))), r)
} }
ClockGroupSinkParameters( ClockGroupSinkParameters(
name = u.name, name = u.name,
members = grouped ++ rest members = grouped ++ rest

View File

@@ -60,23 +60,23 @@ object ClockGroupNamePrefixer {
* The default if all functions return None. * The default if all functions return None.
*/ */
object ClockGroupFrequencySpecifier { object ClockGroupFrequencySpecifier {
def apply( def apply(assigners: Seq[(String) => Option[Double]])(
assigners: Seq[(String) => Option[Double]], implicit p: Parameters, valName: ValName): ClockGroupAdapterNode = {
defaultFreq: Double)(
implicit p: Parameters, valName: ValName): ClockGroupAdapterNode = {
def lookupFrequencyForName(clock: ClockSinkParameters): ClockSinkParameters = { def lookupFrequencyForName(clock: ClockSinkParameters): ClockSinkParameters = clock.copy(take = clock.take match {
require(clock.name.nonEmpty, "All clocks in clock group must have an assigned name") case Some(cp) =>
val clockFreq = assigners.foldLeft(defaultFreq)( println(s"Clock ${clock.name.get}: using diplomatically specified frequency of ${cp.freqMHz}.")
(currentFreq, candidateFunc) => candidateFunc(clock.name.get).getOrElse(currentFreq)) Some(cp)
case None => {
clock.copy(take = clock.take match { val freqs = assigners.map { f => f(clock.name.get) }.flatten
case Some(cp) => if (freqs.size > 0) {
println(s"Clock ${clock.name.get}: using diplomatically specified frequency of ${cp.freqMHz}.") println(s"Clock ${clock.name.get}: using specified frequency of ${freqs.last}")
Some(cp) Some(ClockParameters(freqs.last))
case None => Some(ClockParameters(clockFreq)) } else {
}) None
} }
}
})
LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.map(lookupFrequencyForName)) })).node LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.map(lookupFrequencyForName)) })).node
} }

View File

@@ -15,7 +15,6 @@ import freechips.rocketchip.tile._
import freechips.rocketchip.prci._ import freechips.rocketchip.prci._
import testchipip.{TLTileResetCtrl} import testchipip.{TLTileResetCtrl}
import chipyard.harness.{DefaultClockFrequencyKey}
case class ChipyardPRCIControlParams( case class ChipyardPRCIControlParams(
slaveWhere: TLBusWrapperLocation = CBUS, slaveWhere: TLBusWrapperLocation = CBUS,
@@ -70,7 +69,7 @@ trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
// 5. Add reset control registers to the tiles (if desired) // 5. Add reset control registers to the tiles (if desired)
// The final clock group here contains physically distinct clock domains, which some PRCI node in a // The final clock group here contains physically distinct clock domains, which some PRCI node in a
// diplomatic IOBinder should drive // diplomatic IOBinder should drive
val frequencySpecifier = ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey)) val frequencySpecifier = ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey))
val clockGroupCombiner = ClockGroupCombiner() val clockGroupCombiner = ClockGroupCombiner()
val resetSynchronizer = ClockGroupResetSynchronizer() val resetSynchronizer = ClockGroupResetSynchronizer()
val tileClockGater = if (prciParams.enableTileClockGating) { prci_ctrl_domain { val tileClockGater = if (prciParams.enableTileClockGating) { prci_ctrl_domain {

View File

@@ -44,6 +44,9 @@ class AbstractConfig extends Config(
// By default, punch out IOs to the Harness // By default, punch out IOs to the Harness
new chipyard.clocking.WithPassthroughClockGenerator ++ new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("sbus", "mbus", "pbus", "fbus", "cbus", "implicit"))) ++
new chipyard.config.WithPeripheryBusFrequency(500.0) ++ // Default 500 MHz pbus
new chipyard.config.WithMemoryBusFrequency(500.0) ++ // Default 500 MHz mbus
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
@@ -55,9 +58,6 @@ class AbstractConfig extends Config(
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
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.WithMemoryBusFrequency(500.0) ++ // Default 500 MHz mbus
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

@@ -32,7 +32,7 @@ class ChipLikeQuadRocketConfig extends Config(
new chipyard.clocking.WithPLLSelectorDividerClockGenerator ++ // Use a PLL-based clock selector/divider generator structure new chipyard.clocking.WithPLLSelectorDividerClockGenerator ++ // Use a PLL-based clock selector/divider generator structure
// Create the uncore clock group // Create the uncore clock group
new chipyard.clocking.WithClockGroupsCombinedByName("uncore", "implicit", "sbus", "mbus", "cbus", "system_bus", "fbus", "pbus") ++ new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("implicit", "sbus", "mbus", "cbus", "system_bus", "fbus", "pbus"))) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)

View File

@@ -25,7 +25,7 @@ class TinyRocketConfig extends Config(
class UARTTSIRocketConfig extends Config( class UARTTSIRocketConfig extends Config(
new chipyard.harness.WithUARTSerial ++ new chipyard.harness.WithUARTSerial ++
new chipyard.config.WithNoUART ++ new chipyard.config.WithNoUART ++
new chipyard.config.WithMemoryBusFrequency(10) ++ new chipyard.config.WithMemoryBusFrequency(10) ++
new chipyard.config.WithPeripheryBusFrequency(10) ++ new chipyard.config.WithPeripheryBusFrequency(10) ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
@@ -90,11 +90,13 @@ class MulticlockRocketConfig extends Config(
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
new chipyard.config.WithSystemBusFrequency(800.0) ++ // Ditto new chipyard.clocking.WithClockGroupsCombinedByName(("uncore" , Seq("sbus", "cbus", "implicit")),
("periphery", Seq("pbus", "fbus"))) ++
new chipyard.config.WithSystemBusFrequency(800.0) ++ // Matches the maximum frequency of U540
new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // 2x the U540 freq (appropriate for a 128b Mbus) new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // 2x the U540 freq (appropriate for a 128b Mbus)
new chipyard.config.WithPeripheryBusFrequency(100) ++ // Retains the default pbus frequency new chipyard.config.WithPeripheryBusFrequency(100) ++ // Slow periphery bus
new chipyard.config.WithSystemBusFrequencyAsDefault ++ // All unspecified clock frequencies, notably the implicit clock, will use the sbus freq (800 MHz)
// Crossing specifications // Crossing specifications
new chipyard.config.WithFbusToSbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between FBUS and SBUS
new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS
new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS
new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS
@@ -102,7 +104,6 @@ class MulticlockRocketConfig extends Config(
// DOC include start: MulticlockAXIOverSerialConfig // DOC include start: MulticlockAXIOverSerialConfig
class MulticlockAXIOverSerialConfig extends Config( class MulticlockAXIOverSerialConfig extends Config(
new chipyard.config.WithSystemBusFrequencyAsDefault ++
new chipyard.config.WithSystemBusFrequency(250) ++ new chipyard.config.WithSystemBusFrequency(250) ++
new chipyard.config.WithPeripheryBusFrequency(250) ++ new chipyard.config.WithPeripheryBusFrequency(250) ++
new chipyard.config.WithMemoryBusFrequency(250) ++ new chipyard.config.WithMemoryBusFrequency(250) ++

View File

@@ -13,7 +13,6 @@ class AbstractTraceGenConfig extends Config(
new chipyard.clocking.WithPassthroughClockGenerator ++ 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.WithMemoryBusFrequency(100.0) ++ new chipyard.config.WithMemoryBusFrequency(100.0) ++
new chipyard.config.WithPeripheryBusFrequency(100.0) ++ new chipyard.config.WithPeripheryBusFrequency(100.0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new freechips.rocketchip.subsystem.WithCoherentBusTopology ++

View File

@@ -13,7 +13,6 @@ import freechips.rocketchip.tilelink.{HasTLBusParams}
import chipyard._ import chipyard._
import chipyard.clocking._ import chipyard.clocking._
import chipyard.harness.{DefaultClockFrequencyKey}
// The default RocketChip BaseSubsystem drives its diplomatic clock graph // The default RocketChip BaseSubsystem drives its diplomatic clock graph
// with the implicit clocks of Subsystem. Don't do that, instead we extend // with the implicit clocks of Subsystem. Don't do that, instead we extend
@@ -37,14 +36,6 @@ class WithTileFrequency(fMHz: Double, hartId: Option[Int] = None) extends ClockN
}, },
fMHz) fMHz)
class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get.toDouble / (1000 * 1000))
})
class WithSystemBusFrequencyAsDefault extends Config((site, here, up) => {
case DefaultClockFrequencyKey => (site(SystemBusKey).dtsFrequency.get.toDouble / (1000 * 1000))
})
class BusFrequencyAssignment[T <: HasTLBusParams](re: Regex, key: Field[T]) extends Config((site, here, up) => { class BusFrequencyAssignment[T <: HasTLBusParams](re: Regex, key: Field[T]) extends Config((site, here, up) => {
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++ case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
Seq((cName: String) => site(key).dtsFrequency.flatMap { f => Seq((cName: String) => site(key).dtsFrequency.flatMap { f =>

View File

@@ -46,15 +46,12 @@ class FlatTestHarness(implicit val p: Parameters) extends Module {
val memFreq = axiDomainParams.getMemFrequency(lazyDut.system) val memFreq = axiDomainParams.getMemFrequency(lazyDut.system)
withClockAndReset(clock, reset) { withClockAndReset(clock, reset) {
val memOverSerialTLClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
memOverSerialTLClockBundle.clock := clock
memOverSerialTLClockBundle.reset := reset
val serial_bits = dut.serial_tl_pad.bits val serial_bits = dut.serial_tl_pad.bits
dut.serial_tl_pad.clock := clock dut.serial_tl_pad.clock := clock
val harnessMultiClockAXIRAM = TSIHarness.connectMultiClockAXIRAM( val harnessMultiClockAXIRAM = TSIHarness.connectMultiClockAXIRAM(
lazyDut.system.serdesser.get, lazyDut.system.serdesser.get,
serial_bits, serial_bits,
memOverSerialTLClockBundle, clock,
reset) reset)
io.success := SimTSI.connect(Some(harnessMultiClockAXIRAM.module.io.tsi), clock, reset) io.success := SimTSI.connect(Some(harnessMultiClockAXIRAM.module.io.tsi), clock, reset)

View File

@@ -30,12 +30,12 @@ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvon
import scala.reflect.{ClassTag} import scala.reflect.{ClassTag}
case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Unit]]( case object HarnessBinders extends Field[Map[String, (Any, HasHarnessInstantiators, Seq[Data]) => Unit]](
Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Unit]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => ()) Map[String, (Any, HasHarnessInstantiators, Seq[Data]) => Unit]().withDefaultValue((t: Any, th: HasHarnessInstantiators, d: Seq[Data]) => ())
) )
object ApplyHarnessBinders { object ApplyHarnessBinders {
def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters): Unit = { def apply(th: HasHarnessInstantiators, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters): Unit = {
val pm = portMap.withDefaultValue(Nil) val pm = portMap.withDefaultValue(Nil)
p(HarnessBinders).foreach { case (s, f) => p(HarnessBinders).foreach { case (s, f) =>
f(sys, th, pm(s)) f(sys, th, pm(s))
@@ -45,9 +45,9 @@ object ApplyHarnessBinders {
} }
// The ClassTags here are necessary to overcome issues arising from type erasure // The ClassTags here are necessary to overcome issues arising from type erasure
class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Unit) => (T, S, Seq[U]) => Unit)(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => { class HarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](composer: ((T, S, Seq[U]) => Unit) => (T, S, Seq[U]) => Unit)(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => {
case HarnessBinders => up(HarnessBinders, site) + (systemTag.runtimeClass.toString -> case HarnessBinders => up(HarnessBinders, site) + (systemTag.runtimeClass.toString ->
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { ((t: Any, th: HasHarnessInstantiators, ports: Seq[Data]) => {
val pts = ports.collect({case p: U => p}) val pts = ports.collect({case p: U => p})
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}") require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}")
val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString) val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString)
@@ -63,11 +63,11 @@ class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T
) )
}) })
class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Unit) class OverrideHarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](fn: => (T, S, Seq[U]) => Unit)
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => fn) extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => fn)
class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Unit) class ComposeHarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](fn: => (T, S, Seq[U]) => Unit)
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => (t, th, p) => { extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => (t, th, p) => {
upfn(t, th, p) upfn(t, th, p)
@@ -76,72 +76,66 @@ class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: =>
class WithGPIOTiedOff extends OverrideHarnessBinder({ class WithGPIOTiedOff extends OverrideHarnessBinder({
(system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => { (system: HasPeripheryGPIOModuleImp, th: HasHarnessInstantiators, ports: Seq[Analog]) => {
ports.foreach { _ <> AnalogConst(0) } ports.foreach { _ <> AnalogConst(0) }
} }
}) })
// DOC include start: WithUARTAdapter // DOC include start: WithUARTAdapter
class WithUARTAdapter extends OverrideHarnessBinder({ class WithUARTAdapter extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { (system: HasPeripheryUARTModuleImp, th: HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
UARTAdapter.connect(ports)(system.p) UARTAdapter.connect(ports)(system.p)
} }
}) })
// DOC include end: WithUARTAdapter // DOC include end: WithUARTAdapter
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({ class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
(system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { (system: HasPeripherySPIFlashModuleImp, th: HasHarnessInstantiators, ports: Seq[SPIChipIO]) => {
SimSPIFlashModel.connect(ports, th.buildtopReset, rdOnly)(system.p) SimSPIFlashModel.connect(ports, th.harnessBinderReset, rdOnly)(system.p)
} }
}) })
class WithSimBlockDevice extends OverrideHarnessBinder({ class WithSimBlockDevice extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { (system: CanHavePeripheryBlockDevice, th: HasHarnessInstantiators, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
ports.map { b => SimBlockDevice.connect(b.clock, th.buildtopReset.asBool, Some(b.bits)) } ports.map { b => SimBlockDevice.connect(b.clock, th.harnessBinderReset.asBool, Some(b.bits)) }
} }
}) })
class WithBlockDeviceModel extends OverrideHarnessBinder({ class WithBlockDeviceModel extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { (system: CanHavePeripheryBlockDevice, th: HasHarnessInstantiators, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
ports.map { b => withClockAndReset(b.clock, th.buildtopReset) { BlockDeviceModel.connect(Some(b.bits)) } } ports.map { b => BlockDeviceModel.connect(Some(b.bits)) }
} }
}) })
class WithLoopbackNIC extends OverrideHarnessBinder({ class WithLoopbackNIC extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { (system: CanHavePeripheryIceNIC, th: HasHarnessInstantiators, ports: Seq[ClockedIO[NICIOvonly]]) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
ports.map { n => ports.map { n => NicLoopback.connect(Some(n.bits), p(NICKey)) }
withClockAndReset(n.clock, th.buildtopReset) {
NicLoopback.connect(Some(n.bits), p(NICKey))
}
}
} }
}) })
class WithSimNetwork extends OverrideHarnessBinder({ class WithSimNetwork extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessInstantiators, ports: Seq[ClockedIO[NICIOvonly]]) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.buildtopReset.asBool) } ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessBinderReset.asBool) }
} }
}) })
class WithSimAXIMem extends OverrideHarnessBinder({ class WithSimAXIMem extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => { (system: CanHaveMasterAXI4MemPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system) val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) => (ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p)) val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p))
withClockAndReset(port.clock, port.reset) { Module(mem.module).suggestName("mem")
Module(mem.module).suggestName("mem")
}
mem.io_axi4.head <> port.bits mem.io_axi4.head <> port.bits
} }
} }
}) })
class WithSimAXIMemOverSerialTL extends OverrideHarnessBinder({ class WithSimAXIMemOverSerialTL extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { (system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system) implicit val p = chipyard.iobinders.GetSystemParameters(system)
p(SerialTLKey).map({ sVal => p(SerialTLKey).map({ sVal =>
@@ -153,29 +147,27 @@ class WithSimAXIMemOverSerialTL extends OverrideHarnessBinder({
ports.map({ port => ports.map({ port =>
// DOC include start: HarnessClockInstantiatorEx // DOC include start: HarnessClockInstantiatorEx
withClockAndReset(th.buildtopClock, th.buildtopReset) { val memOverSerialTLClock = th.harnessClockInstantiator.requestClockHz("mem_over_serial_tl_clock", memFreq)
val memOverSerialTLClockBundle = th.harnessClockInstantiator.requestClockBundle("mem_over_serial_tl_clock", memFreq) val serial_bits = port.bits
val serial_bits = port.bits port.clock := th.harnessBinderClock
port.clock := th.buildtopClock val harnessMultiClockAXIRAM = TSIHarness.connectMultiClockAXIRAM(
val harnessMultiClockAXIRAM = TSIHarness.connectMultiClockAXIRAM( system.serdesser.get,
system.serdesser.get, serial_bits,
serial_bits, memOverSerialTLClock,
memOverSerialTLClockBundle, th.harnessBinderReset)
th.buildtopReset) // DOC include end: HarnessClockInstantiatorEx
// DOC include end: HarnessClockInstantiatorEx val success = SimTSI.connect(Some(harnessMultiClockAXIRAM.module.io.tsi), th.harnessBinderClock, th.harnessBinderReset.asBool)
val success = SimTSI.connect(Some(harnessMultiClockAXIRAM.module.io.tsi), th.buildtopClock, th.buildtopReset.asBool) when (success) { th.success := true.B }
when (success) { th.success := true.B }
// connect SimDRAM from the AXI port coming from the harness multi clock axi ram // connect SimDRAM from the AXI port coming from the harness multi clock axi ram
(harnessMultiClockAXIRAM.mem_axi4 zip harnessMultiClockAXIRAM.memNode.edges.in).map { case (axi_port, edge) => (harnessMultiClockAXIRAM.mem_axi4 zip harnessMultiClockAXIRAM.memNode.edges.in).map { case (axi_port, edge) =>
val memSize = sVal.memParams.size val memSize = sVal.memParams.size
val memBase = sVal.memParams.base val memBase = sVal.memParams.base
val lineSize = p(CacheBlockBytes) val lineSize = p(CacheBlockBytes)
val mem = Module(new SimDRAM(memSize, lineSize, BigInt(memFreq.toLong), memBase, edge.bundle)).suggestName("simdram") val mem = Module(new SimDRAM(memSize, lineSize, BigInt(memFreq.toLong), memBase, edge.bundle)).suggestName("simdram")
mem.io.axi <> axi_port.bits mem.io.axi <> axi_port.bits
mem.io.clock := axi_port.clock mem.io.clock := axi_port.clock
mem.io.reset := axi_port.reset mem.io.reset := axi_port.reset
}
} }
}) })
}) })
@@ -183,7 +175,7 @@ class WithSimAXIMemOverSerialTL extends OverrideHarnessBinder({
}) })
class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBinder({ class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => { (system: CanHaveMasterAXI4MemPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system) val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) => (ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
// TODO FIX: This currently makes each SimDRAM contain the entire memory space // TODO FIX: This currently makes each SimDRAM contain the entire memory space
@@ -218,7 +210,7 @@ class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBind
}) })
class WithSimAXIMMIO extends OverrideHarnessBinder({ class WithSimAXIMMIO extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => { (system: CanHaveMasterAXI4MMIOPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system) val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
(ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) => (ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) =>
val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p)) val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p))
@@ -231,13 +223,13 @@ class WithSimAXIMMIO extends OverrideHarnessBinder({
}) })
class WithTieOffInterrupts extends OverrideHarnessBinder({ class WithTieOffInterrupts extends OverrideHarnessBinder({
(system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => { (system: HasExtInterruptsModuleImp, th: HasHarnessInstantiators, ports: Seq[UInt]) => {
ports.foreach { _ := 0.U } ports.foreach { _ := 0.U }
} }
}) })
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({ class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
(system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { (system: CanHaveSlaveAXI4Port, th: HasHarnessInstantiators, ports: Seq[ClockedIO[AXI4Bundle]]) => {
ports.foreach({ p => ports.foreach({ p =>
p.bits := DontCare p.bits := DontCare
p.bits.aw.valid := false.B p.bits.aw.valid := false.B
@@ -250,13 +242,13 @@ class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
}) })
class WithSimDebug extends OverrideHarnessBinder({ class WithSimDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[Data]) => { (system: HasPeripheryDebug, th: HasHarnessInstantiators, ports: Seq[Data]) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
ports.map { ports.map {
case d: ClockedDMIIO => case d: ClockedDMIIO =>
val dtm_success = WireInit(false.B) val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B } when (dtm_success) { th.success := true.B }
val dtm = Module(new TestchipSimDTM).connect(th.buildtopClock, th.buildtopReset.asBool, d, dtm_success) val dtm = Module(new TestchipSimDTM).connect(th.harnessBinderClock, th.harnessBinderReset.asBool, d, dtm_success)
case j: JTAGChipIO => case j: JTAGChipIO =>
val dtm_success = WireInit(false.B) val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B } when (dtm_success) { th.success := true.B }
@@ -267,13 +259,13 @@ class WithSimDebug extends OverrideHarnessBinder({
j.TMS := jtag_wire.TMS j.TMS := jtag_wire.TMS
j.TDI := jtag_wire.TDI j.TDI := jtag_wire.TDI
val jtag = Module(new SimJTAG(tickDelay=3)) val jtag = Module(new SimJTAG(tickDelay=3))
jtag.connect(jtag_wire, th.buildtopClock, th.buildtopReset.asBool, ~(th.buildtopReset.asBool), dtm_success) jtag.connect(jtag_wire, th.harnessBinderClock, th.harnessBinderReset.asBool, ~(th.harnessBinderReset.asBool), dtm_success)
} }
} }
}) })
class WithTiedOffDebug extends OverrideHarnessBinder({ class WithTiedOffDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[Data]) => { (system: HasPeripheryDebug, th: HasHarnessInstantiators, ports: Seq[Data]) => {
ports.map { ports.map {
case j: JTAGChipIO => case j: JTAGChipIO =>
j.TCK := true.B.asClock j.TCK := true.B.asClock
@@ -300,7 +292,7 @@ class WithTiedOffDebug extends OverrideHarnessBinder({
class WithSerialTLTiedOff extends OverrideHarnessBinder({ class WithSerialTLTiedOff extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { (system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system) implicit val p = chipyard.iobinders.GetSystemParameters(system)
ports.map({ port => ports.map({ port =>
val bits = port.bits val bits = port.bits
@@ -313,56 +305,52 @@ class WithSerialTLTiedOff extends OverrideHarnessBinder({
}) })
class WithSimTSIOverSerialTL extends OverrideHarnessBinder({ class WithSimTSIOverSerialTL extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { (system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system) implicit val p = chipyard.iobinders.GetSystemParameters(system)
ports.map({ port => ports.map({ port =>
val bits = port.bits val bits = port.bits
port.clock := th.buildtopClock port.clock := th.harnessBinderClock
withClockAndReset(th.buildtopClock, th.buildtopReset) { val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.buildtopReset) val success = SimTSI.connect(Some(ram.module.io.tsi), th.harnessBinderClock, th.harnessBinderReset.asBool)
val success = SimTSI.connect(Some(ram.module.io.tsi), th.buildtopClock, th.buildtopReset.asBool) when (success) { th.success := true.B }
when (success) { th.success := true.B }
}
}) })
} }
}) })
class WithUARTSerial extends OverrideHarnessBinder({ class WithUARTSerial extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { (system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system) implicit val p = chipyard.iobinders.GetSystemParameters(system)
ports.map({ port => ports.map({ port =>
val freq = p(PeripheryBusKey).dtsFrequency.get val freq = p(PeripheryBusKey).dtsFrequency.get
val bits = port.bits val bits = port.bits
port.clock := th.buildtopClock port.clock := th.harnessBinderClock
withClockAndReset(th.buildtopClock, th.buildtopReset) { val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.buildtopReset) val uart_to_serial = Module(new UARTToSerial(freq, UARTParams(0)))
val uart_to_serial = Module(new UARTToSerial(freq, UARTParams(0))) val serial_width_adapter = Module(new SerialWidthAdapter(
val serial_width_adapter = Module(new SerialWidthAdapter( 8, TSI.WIDTH))
8, TSI.WIDTH)) ram.module.io.tsi.flipConnect(serial_width_adapter.io.wide)
ram.module.io.tsi.flipConnect(serial_width_adapter.io.wide) UARTAdapter.connect(Seq(uart_to_serial.io.uart), uart_to_serial.div)
UARTAdapter.connect(Seq(uart_to_serial.io.uart), uart_to_serial.div) serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial) th.success := false.B
th.success := false.B
}
}) })
} }
}) })
class WithTraceGenSuccess extends OverrideHarnessBinder({ class WithTraceGenSuccess extends OverrideHarnessBinder({
(system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => { (system: TraceGenSystemModuleImp, th: HasHarnessInstantiators, ports: Seq[Bool]) => {
ports.map { p => when (p) { th.success := true.B } } ports.map { p => when (p) { th.success := true.B } }
} }
}) })
class WithSimDromajoBridge extends ComposeHarnessBinder({ class WithSimDromajoBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { (system: CanHaveTraceIOModuleImp, th: HasHarnessInstantiators, ports: Seq[TraceOutputTop]) => {
ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) } ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
} }
}) })
class WithCospike extends ComposeHarnessBinder({ class WithCospike extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { (system: CanHaveTraceIOModuleImp, th: HasHarnessInstantiators, ports: Seq[TraceOutputTop]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system) implicit val p = chipyard.iobinders.GetSystemParameters(system)
val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem] val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem]
val tiles = chipyardSystem.tiles val tiles = chipyardSystem.tiles
@@ -381,7 +369,7 @@ class WithCospike extends ComposeHarnessBinder({
class WithCustomBootPinPlusArg extends OverrideHarnessBinder({ class WithCustomBootPinPlusArg extends OverrideHarnessBinder({
(system: CanHavePeripheryCustomBootPin, th: HasHarnessSignalReferences, ports: Seq[Bool]) => { (system: CanHavePeripheryCustomBootPin, th: HasHarnessInstantiators, ports: Seq[Bool]) => {
val pin = PlusArg("custom_boot_pin", width=1) val pin = PlusArg("custom_boot_pin", width=1)
ports.foreach(_ := pin) ports.foreach(_ := pin)
} }
@@ -389,14 +377,14 @@ class WithCustomBootPinPlusArg extends OverrideHarnessBinder({
class WithClockAndResetFromHarness extends OverrideHarnessBinder({ class WithClockAndResetFromHarness extends OverrideHarnessBinder({
(system: HasChipyardPRCI, th: HasHarnessSignalReferences, ports: Seq[Data]) => { (system: HasChipyardPRCI, th: HasHarnessInstantiators, ports: Seq[Data]) => {
implicit val p = GetSystemParameters(system) implicit val p = GetSystemParameters(system)
ports.map ({ ports.map ({
case c: ClockWithFreq => { case c: ClockWithFreq => {
val clock = th.harnessClockInstantiator.requestClockBundle(s"clock_${c.freqMHz}MHz", c.freqMHz * (1000 * 1000)) val clock = th.harnessClockInstantiator.requestClockMHz(s"clock_${c.freqMHz}MHz", c.freqMHz)
c.clock := clock.clock c.clock := clock
} }
case r: AsyncReset => r := th.buildtopReset.asAsyncReset case r: AsyncReset => r := th.harnessBinderReset.asAsyncReset
}) })
} }
}) })

View File

@@ -17,24 +17,26 @@ import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
// HarnessClockInstantiators are classes which generate clocks that drive // HarnessClockInstantiators are classes which generate clocks that drive
// TestHarness simulation models and any Clock inputs to the ChipTop // TestHarness simulation models and any Clock inputs to the ChipTop
trait HarnessClockInstantiator { trait HarnessClockInstantiator {
val _clockMap: LinkedHashMap[String, (Double, ClockBundle)] = LinkedHashMap.empty val clockMap: LinkedHashMap[String, (Double, Clock)] = LinkedHashMap.empty
// request a clock bundle at a particular frequency // request a clock at a particular frequency
def requestClockBundle(name: String, freqRequested: Double): ClockBundle = { def requestClockHz(name: String, freqHzRequested: Double): Clock = {
if (_clockMap.contains(name)) { if (clockMap.contains(name)) {
require(freqRequested == _clockMap(name)._1, require(freqHzRequested == clockMap(name)._1,
s"Request clock freq = $freqRequested != previously requested ${_clockMap(name)._2} for requested clock $name") s"Request clock freq = $freqHzRequested != previously requested ${clockMap(name)._2} for requested clock $name")
_clockMap(name)._2 clockMap(name)._2
} else { } else {
val clockBundle = Wire(new ClockBundle(ClockBundleParameters())) val clock = Wire(Clock())
_clockMap(name) = (freqRequested, clockBundle) clockMap(name) = (freqHzRequested, clock)
clockBundle clock
} }
} }
def requestClockMHz(name: String, freqMHzRequested: Double): Clock = {
requestClockHz(name, freqMHzRequested * (1000 * 1000))
}
// refClock is the clock generated by TestDriver that is // refClock is the clock generated by TestDriver that is
// passed to the TestHarness as its implicit clock // passed to the TestHarness as its implicit clock
def instantiateHarnessClocks(refClock: ClockBundle): Unit def instantiateHarnessClocks(refClock: Clock): Unit
} }
class ClockSourceAtFreqMHz(val freqMHz: Double) extends BlackBox(Map( class ClockSourceAtFreqMHz(val freqMHz: Double) extends BlackBox(Map(
@@ -63,19 +65,14 @@ class ClockSourceAtFreqMHz(val freqMHz: Double) extends BlackBox(Map(
// This ClockInstantiator cannot be synthesized, run in Verilator, or run in FireSim // This ClockInstantiator cannot be synthesized, run in Verilator, or run in FireSim
// It is useful for VCS/Xcelium-driven RTL simulations // It is useful for VCS/Xcelium-driven RTL simulations
class AbsoluteFreqHarnessClockInstantiator extends HarnessClockInstantiator { class AbsoluteFreqHarnessClockInstantiator extends HarnessClockInstantiator {
def instantiateHarnessClocks(refClock: ClockBundle): Unit = { def instantiateHarnessClocks(refClock: Clock): Unit = {
val sinks = _clockMap.map({ case (name, (freq, bundle)) =>
ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))), name=Some(name))
}).toSeq
// connect wires to clock source // connect wires to clock source
for (sinkParams <- sinks) { for ((name, (freqHz, clock)) <- clockMap) {
val source = Module(new ClockSourceAtFreqMHz(sinkParams.take.get.freqMHz)) val source = Module(new ClockSourceAtFreqMHz(freqHz / (1000 * 1000)))
source.io.power := true.B source.io.power := true.B
source.io.gate := false.B source.io.gate := false.B
_clockMap(sinkParams.name.get)._2.clock := source.io.clk clock := source.io.clk
_clockMap(sinkParams.name.get)._2.reset := refClock.reset
} }
} }
} }
@@ -85,12 +82,11 @@ class WithAbsoluteFreqHarnessClockInstantiator extends Config((site, here, up) =
}) })
class AllClocksFromHarnessClockInstantiator extends HarnessClockInstantiator { class AllClocksFromHarnessClockInstantiator extends HarnessClockInstantiator {
def instantiateHarnessClocks(refClock: ClockBundle): Unit = { def instantiateHarnessClocks(refClock: Clock): Unit = {
val freqs = _clockMap.map(_._2._1) val freqs = clockMap.map(_._2._1)
freqs.tail.foreach(t => require(t == freqs.head, s"Mismatching clocks $t != ${freqs.head}")) freqs.tail.foreach(t => require(t == freqs.head, s"Mismatching clocks $t != ${freqs.head}"))
for ((_, (_, bundle)) <- _clockMap) { for ((name, (freq, clock)) <- clockMap) {
bundle.clock := refClock.clock clock := refClock
bundle.reset := refClock.reset
} }
} }
} }

View File

@@ -0,0 +1,95 @@
package chipyard.harness
import chisel3._
import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
import freechips.rocketchip.diplomacy.{LazyModule}
import org.chipsalliance.cde.config.{Field, Parameters, Config}
import freechips.rocketchip.util.{ResetCatchAndSync}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters}
import freechips.rocketchip.stage.phases.TargetDirKey
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
import chipyard.iobinders.HasIOBinders
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
import chipyard.{ChipTop}
// -------------------------------
// Chipyard Test Harness
// -------------------------------
case object MultiChipNChips extends Field[Int](0) // 0 means ignore MultiChipParams
case class MultiChipParameters(chipId: Int) extends Field[Parameters]
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator]()
case object HarnessBinderClockFrequencyKey extends Field[Double](100.0) // MHz
case object MultiChipIdx extends Field[Int](0)
class WithMultiChip(id: Int, p: Parameters) extends Config((site, here, up) => {
case MultiChipParameters(`id`) => p
case MultiChipNChips => up(MultiChipNChips) max (id + 1)
})
class WithHomogeneousMultiChip(n: Int, p: Parameters, idStart: Int = 0) extends Config((site, here, up) => {
case MultiChipParameters(id) => if (id >= idStart && id < idStart + n) p else up(MultiChipParameters(id))
case MultiChipNChips => up(MultiChipNChips) max (idStart + n)
})
class WithHarnessBinderClockFreqMHz(freqMHz: Double) extends Config((site, here, up) => {
case HarnessBinderClockFrequencyKey => freqMHz
})
// A TestHarness mixing this in will
// - use the HarnessClockInstantiator clock provide
trait HasHarnessInstantiators {
implicit val p: Parameters
// clock/reset of the chiptop reference clock (can be different than the implicit harness clock/reset)
private val harnessBinderClockFreq: Double = p(HarnessBinderClockFrequencyKey)
def getHarnessBinderClockFreqHz: Double = harnessBinderClockFreq * 1000000
def getHarnessBinderClockFreqMHz: Double = harnessBinderClockFreq
// buildtopClock takes the refClockFreq, and drives the harnessbinders
val harnessBinderClock = Wire(Clock())
val harnessBinderReset = Wire(Reset())
// classes which inherit this trait should provide the below definitions
def implicitClock: Clock
def implicitReset: Reset
def success: Bool
// This can be accessed to get new clocks from the harness
val harnessClockInstantiator = p(HarnessClockInstantiatorKey)()
private val chipParameters = if (p(MultiChipNChips) == 0) {
Seq(p)
} else {
(0 until p(MultiChipNChips)).map { i => p(MultiChipParameters(i)).alterPartial {
case TargetDirKey => p(TargetDirKey) // hacky fix
case MultiChipIdx => i
}}
}
// This shold be called last to build the ChipTops
def instantiateChipTops(): Seq[LazyModule] = {
val lazyDuts = chipParameters.zipWithIndex.map { case (q,i) =>
LazyModule(q(BuildTop)(q)).suggestName(s"chiptop$i")
}
val duts = lazyDuts.map(l => Module(l.module))
withClockAndReset (harnessBinderClock, harnessBinderReset) {
lazyDuts.zipWithIndex.foreach {
case (d: HasIOBinders, i: Int) => ApplyHarnessBinders(this, d.lazySystem, d.portMap)(chipParameters(i))
case _ =>
}
}
val harnessBinderClk = harnessClockInstantiator.requestClockMHz("harnessbinder_clock", getHarnessBinderClockFreqMHz)
println(s"Harness binder clock is $harnessBinderClockFreq")
harnessBinderClock := harnessBinderClk
harnessBinderReset := implicitReset
harnessClockInstantiator.instantiateHarnessClocks(implicitClock)
lazyDuts
}
}

View File

@@ -17,48 +17,15 @@ import chipyard.{ChipTop}
// Chipyard Test Harness // Chipyard Test Harness
// ------------------------------- // -------------------------------
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p)) class TestHarness(implicit val p: Parameters) extends Module with HasHarnessInstantiators {
case object DefaultClockFrequencyKey extends Field[Double](100.0) // MHz
case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator]()
trait HasHarnessSignalReferences {
implicit val p: Parameters
val harnessClockInstantiator = p(HarnessClockInstantiatorKey)()
// clock/reset of the chiptop reference clock (can be different than the implicit harness clock/reset)
var refClockFreq: Double = p(DefaultClockFrequencyKey)
def setRefClockFreq(freqMHz: Double) = { refClockFreq = freqMHz }
def getRefClockFreq: Double = refClockFreq
def buildtopClock: Clock
def buildtopReset: Reset
def success: Bool
}
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())
}) })
val success = WireInit(false.B)
io.success := success
val buildtopClock = Wire(Clock()) def implicitClock = clock
val buildtopReset = Wire(Reset()) def implicitReset = reset
val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop") instantiateChipTops()
val dut = Module(lazyDut.module)
io.success := false.B
val success = io.success
lazyDut match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
val refClkBundle = harnessClockInstantiator.requestClockBundle("buildtop_reference_clock", getRefClockFreq * (1000 * 1000))
buildtopClock := refClkBundle.clock
buildtopReset := WireInit(refClkBundle.reset)
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := clock
implicitHarnessClockBundle.reset := reset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
} }

View File

@@ -4,6 +4,7 @@ package firesim.firesim
import chisel3._ import chisel3._
import chisel3.experimental.annotate import chisel3.experimental.annotate
import chisel3.experimental.{DataMirror, Direction}
import chisel3.util.experimental.BoringUtils import chisel3.util.experimental.BoringUtils
import org.chipsalliance.cde.config.{Field, Config, Parameters} import org.chipsalliance.cde.config.{Field, Config, Parameters}
@@ -30,11 +31,12 @@ import cva6.CVA6Tile
import boom.common.{BoomTile} import boom.common.{BoomTile}
import barstools.iocell.chisel._ import barstools.iocell.chisel._
import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters, IOCellKey} import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters, IOCellKey}
import chipyard._
import chipyard.harness._ import chipyard.harness._
object MainMemoryConsts { object MainMemoryConsts {
val regionNamePrefix = "MainMemory" val regionNamePrefix = "MainMemory"
def globalName = s"${regionNamePrefix}_${NodeIdx()}" def globalName()(implicit p: Parameters) = s"${regionNamePrefix}_${p(MultiChipIdx)}"
} }
trait Unsupported { trait Unsupported {
@@ -72,11 +74,9 @@ class WithTSIBridgeAndHarnessRAMOverSerialTL extends OverrideHarnessBinder({
ports.map { port => ports.map { port =>
implicit val p = GetSystemParameters(system) implicit val p = GetSystemParameters(system)
val bits = port.bits val bits = port.bits
port.clock := th.buildtopClock port.clock := th.harnessBinderClock
val ram = withClockAndReset(th.buildtopClock, th.buildtopReset) { val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
TSIHarness.connectRAM(system.serdesser.get, bits, th.buildtopReset) TSIBridge(th.harnessBinderClock, ram.module.io.tsi, p(ExtMem).map(_ => MainMemoryConsts.globalName), th.harnessBinderReset.asBool)
}
TSIBridge(th.buildtopClock, ram.module.io.tsi, p(ExtMem).map(_ => MainMemoryConsts.globalName), th.buildtopReset.asBool)
} }
Nil Nil
} }
@@ -97,13 +97,13 @@ class WithUARTBridge extends OverrideHarnessBinder({
val pbusClockNode = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(PBUS).fixedClockNode val pbusClockNode = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(PBUS).fixedClockNode
val pbusClock = pbusClockNode.in.head._1.clock val pbusClock = pbusClockNode.in.head._1.clock
BoringUtils.bore(pbusClock, Seq(uartSyncClock)) BoringUtils.bore(pbusClock, Seq(uartSyncClock))
ports.map { p => UARTBridge(uartSyncClock, p, th.buildtopReset.asBool)(system.p) }; Nil ports.map { p => UARTBridge(uartSyncClock, p, th.harnessBinderReset.asBool)(system.p) }; Nil
}) })
class WithBlockDeviceBridge extends OverrideHarnessBinder({ class WithBlockDeviceBridge extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => { (system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
ports.map { b => BlockDevBridge(b.clock, b.bits, th.buildtopReset.asBool) } ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessBinderReset.asBool) }
Nil Nil
} }
}) })
@@ -120,21 +120,16 @@ class WithAXIOverSerialTLCombinedBridges extends OverrideHarnessBinder({
val memFreq = axiDomainParams.getMemFrequency(system.asInstanceOf[HasTileLinkLocations]) val memFreq = axiDomainParams.getMemFrequency(system.asInstanceOf[HasTileLinkLocations])
ports.map({ port => ports.map({ port =>
val axiClock = p(ClockBridgeInstantiatorKey).requestClock("mem_over_serial_tl_clock", memFreq) val axiClock = th.harnessClockInstantiator.requestClockHz("mem_over_serial_tl_clock", memFreq)
val axiClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
axiClockBundle.clock := axiClock
axiClockBundle.reset := ResetCatchAndSync(axiClock, th.buildtopReset.asBool)
val serial_bits = port.bits val serial_bits = port.bits
port.clock := th.buildtopClock port.clock := th.harnessBinderClock
val harnessMultiClockAXIRAM = withClockAndReset(th.buildtopClock, th.buildtopReset) { val harnessMultiClockAXIRAM = TSIHarness.connectMultiClockAXIRAM(
TSIHarness.connectMultiClockAXIRAM( system.serdesser.get,
system.serdesser.get, serial_bits,
serial_bits, axiClock,
axiClockBundle, ResetCatchAndSync(axiClock, th.harnessBinderReset.asBool))
th.buildtopReset) TSIBridge(th.harnessBinderClock, harnessMultiClockAXIRAM.module.io.tsi, Some(MainMemoryConsts.globalName), th.harnessBinderReset.asBool)
}
TSIBridge(th.buildtopClock, harnessMultiClockAXIRAM.module.io.tsi, Some(MainMemoryConsts.globalName), th.buildtopReset.asBool)
// connect SimAxiMem // connect SimAxiMem
(harnessMultiClockAXIRAM.mem_axi4 zip harnessMultiClockAXIRAM.memNode.edges.in).map { case (axi4, edge) => (harnessMultiClockAXIRAM.mem_axi4 zip harnessMultiClockAXIRAM.memNode.edges.in).map { case (axi4, edge) =>
@@ -192,7 +187,7 @@ class WithDromajoBridge extends ComposeHarnessBinder({
class WithTraceGenBridge extends OverrideHarnessBinder({ class WithTraceGenBridge extends OverrideHarnessBinder({
(system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) => (system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) =>
ports.map { p => GroundTestBridge(th.buildtopClock, p)(system.p) }; Nil ports.map { p => GroundTestBridge(th.harnessBinderClock, p)(system.p) }; Nil
}) })
class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({

View File

@@ -20,258 +20,67 @@ import chipyard.harness._
import chipyard.iobinders._ import chipyard.iobinders._
import chipyard.clocking._ import chipyard.clocking._
// Determines the number of times to instantiate the DUT in the harness.
// Subsumes legacy supernode support
case object NumNodes extends Field[Int](1)
class WithNumNodes(n: Int) extends Config((pname, site, here) => {
case NumNodes => n
})
// Hacky: Set before each node is generated. Ideally we'd give IO binders
// accesses to the the Harness's parameters instance. We could then alter that.
object NodeIdx {
private var idx = 0
def increment(): Unit = {idx = idx + 1 }
def apply(): Int = idx
}
/**
* Specifies DUT clocks for the rational clock bridge
*
* @param allClocks Seq. of RationalClocks that want a clock
*
* @param baseClockName Name of domain that the allClocks is rational to
*
* @param baseFreqRequested Freq. for the reference domain in Hz
*/
case class BuildTopClockParameters(allClocks: Seq[RationalClock], baseClockName: String, baseFreqRequested: Double)
/** /**
* Under FireSim's current multiclock implementation there can be only a * Under FireSim's current multiclock implementation there can be only a
* single clock bridge. This requires, therefore, that it be instantiated in * single clock bridge. This requires, therefore, that it be instantiated in
* the harness and reused across all supernode instances. This class attempts to * the harness and reused across all supernode instances. This class attempts to
* memoize its instantiation such that it can be referenced from within a ClockScheme function. * memoize its instantiation such that it can be referenced from within a ClockScheme function.
*/ */
class ClockBridgeInstantiator { class FireSimClockBridgeInstantiator extends HarnessClockInstantiator {
private val _harnessClockMap: LinkedHashMap[String, (Double, Clock)] = LinkedHashMap.empty // connect all clock wires specified to the RationalClockBridge
def instantiateHarnessClocks(refClock: Clock): Unit = {
val sinks = clockMap.map({ case (name, (freq, bundle)) =>
ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))), name=Some(name))
}).toSeq
// Assumes that the supernode implementation results in duplicated clocks val pllConfig = new SimplePllConfiguration("firesimRationalClockBridge", sinks)
// (i.e. only 1 set of clocks is generated for all BuildTop designs) pllConfig.emitSummaries()
private var _buildTopClockParams: Option[BuildTopClockParameters] = None
private val _buildTopClockMap: LinkedHashMap[String, (RationalClock, Clock)] = LinkedHashMap.empty
private var _buildTopClockRecord: Option[RecordMap[Clock]] = None
/** var instantiatedClocks = LinkedHashMap[Int, (Clock, Seq[String])]()
* Request a clock at a particular frequency // connect wires to clock source
* for ((name, (freq, clock)) <- clockMap) {
* @param name An identifier for the associated clock domain val freqMHz = (freq / (1000 * 1000)).toInt
* if (!instantiatedClocks.contains(freqMHz)) {
* @param freqRequested Freq. for the domain in Hz val clock = Wire(Clock())
*/ instantiatedClocks(freqMHz) = (clock, Seq(name))
def requestClock(name: String, freqRequested: Double): Clock = { } else {
val clkWire = Wire(new Clock) instantiatedClocks(freqMHz) = (instantiatedClocks(freqMHz)._1, instantiatedClocks(freqMHz)._2 :+ name)
_harnessClockMap(name) = (freqRequested, clkWire)
clkWire
}
/**
* Get a RecordMap of clocks for a set of input RationalClocks. Used to drive
* the design elaborated by buildtop
*
* @param clockMapParameters Defines the set of required clocks
*/
def requestClockRecordMap(clockMapParameters: BuildTopClockParameters): RecordMap[Clock] = {
if (_buildTopClockParams.isDefined) {
require(_buildTopClockParams.get == clockMapParameters, "Must request same set of clocks on repeated invocations.")
} else {
val clockRecord = Wire(RecordMap(clockMapParameters.allClocks.map { c => (c.name, Clock()) }:_*))
// Build up the mutable structures describing the clocks for the dut
_buildTopClockParams = Some(clockMapParameters)
_buildTopClockRecord = Some(clockRecord)
for (clock <- clockMapParameters.allClocks) {
val clockWire = Wire(new Clock)
_buildTopClockMap(clock.name) = (clock, clockWire)
clockRecord(clock.name).get := clockWire
} }
clock := instantiatedClocks(freqMHz)._1
} }
_buildTopClockRecord.get val ratClocks = instantiatedClocks.map { case (freqMHz, (clock, names)) =>
} (RationalClock(names.mkString(","), 1, pllConfig.referenceFreqMHz.toInt / freqMHz), clock)
/**
* Connect all clocks requested to ClockBridge
*/
def instantiateFireSimClockBridge: Unit = {
require(_buildTopClockParams.isDefined, "Must have rational clocks to assign to")
val BuildTopClockParameters(allClocks, refRatClockName, refRatClockFreq) = _buildTopClockParams.get
require(_buildTopClockMap.exists(_._1 == refRatClockName),
s"Provided base-clock name for rational clocks, ${refRatClockName}, doesn't match a name within specified rational clocks." +
"Available clocks:\n " + _buildTopClockMap.map(_._1).mkString("\n "))
// Simplify the RationalClocks ratio's
val refRatClock = _buildTopClockMap.find(_._1 == refRatClockName).get._2._1
val simpleRatClocks = _buildTopClockMap.map { t =>
val ratClock = t._2._1
ratClock.copy(
multiplier = ratClock.multiplier * refRatClock.divisor,
divisor = ratClock.divisor * refRatClock.multiplier).simplify
}
// Determine all the clock dividers (harness + rational clocks)
// Note: Requires that the BuildTop reference frequency is requested with proper freq.
val refRatSinkParams = ClockSinkParameters(take=Some(ClockParameters(freqMHz=refRatClockFreq / (1000 * 1000))),name=Some(refRatClockName))
val harSinkParams = _harnessClockMap.map { case (name, (freq, bundle)) =>
ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))),name=Some(name))
}.toSeq }.toSeq
val allSinkParams = harSinkParams :+ refRatSinkParams val clockBridge = Module(new RationalClockBridge(ratClocks.map(_._1)))
(clockBridge.io.clocks zip ratClocks).foreach { case (clk, rat) =>
// Use PLL config to determine overall div's rat._2 := clk
val pllConfig = new SimplePllConfiguration("firesimOverallClockBridge", allSinkParams)
pllConfig.emitSummaries
// Adjust all BuildTop RationalClocks with the div determined by the PLL
val refRatDiv = pllConfig.sinkDividerMap(refRatSinkParams)
val adjRefRatClocks = simpleRatClocks.map { clock =>
clock.copy(divisor = clock.divisor * refRatDiv).simplify
}
// Convert harness clocks to RationalClocks
val harRatClocks = harSinkParams.map { case ClockSinkParameters(_, _, _, _, clkParamsOpt, nameOpt) =>
RationalClock(nameOpt.get, 1, pllConfig.referenceFreqMHz.toInt / clkParamsOpt.get.freqMHz.toInt)
}
val allAdjRatClks = adjRefRatClocks ++ harRatClocks
// Removes clocks that have the same frequency before instantiating the
// clock bridge to avoid unnecessary BUFGCE use.
val allDistinctRatClocks = allAdjRatClks.foldLeft(Seq(RationalClock(pllConfig.referenceSinkParams.name.get, 1, 1))) {
case (list, candidate) => if (list.exists { clock => clock.equalFrequency(candidate) }) list else list :+ candidate
}
val clockBridge = Module(new RationalClockBridge(allDistinctRatClocks))
val cbVecTuples = allDistinctRatClocks.zip(clockBridge.io.clocks)
// Connect all clocks (harness + BuildTop clocks)
for (clock <- allAdjRatClks) {
val (_, cbClockField) = cbVecTuples.find(_._1.equalFrequency(clock)).get
_buildTopClockMap.get(clock.name).map { case (_, clk) => clk := cbClockField }
_harnessClockMap.get(clock.name).map { case (_, clk) => clk := cbClockField }
} }
} }
} }
case object ClockBridgeInstantiatorKey extends Field[ClockBridgeInstantiator](new ClockBridgeInstantiator) class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessInstantiators {
case object FireSimBaseClockNameKey extends Field[String]("implicit_clock") require(harnessClockInstantiator.isInstanceOf[FireSimClockBridgeInstantiator])
class ClocksWithSinkParams(val params: Seq[ClockSinkParameters]) extends Bundle {
val clocks = Vec(params.size, Clock())
}
class WithFireSimSimpleClocks extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => {
implicit val p = GetSystemParameters(system)
// Figure out what provides this in the chipyard scheme
implicit val valName = ValName("FireSimClocking")
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
}}
}
val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
system.allClockGroupsNode := inputClockSource
InModuleBody {
val (clockGroupBundle, clockGroupEdge) = inputClockSource.out.head
val reset_io = IO(Input(AsyncReset())).suggestName("async_reset")
val input_clocks = IO(Input(new ClocksWithSinkParams(clockGroupEdge.sink.members)))
.suggestName("clocks")
(clockGroupBundle.member.data zip input_clocks.clocks).foreach { case (clockBundle, inputClock) =>
clockBundle.clock := inputClock
clockBundle.reset := reset_io
}
(Seq(reset_io, input_clocks), Nil)
}
}
})
class WithFireSimHarnessClockBinder extends OverrideHarnessBinder({
(system: HasChipyardPRCI, th: FireSim, ports: Seq[Data]) => {
implicit val p = th.p
ports.map ({
case c: ClocksWithSinkParams => {
val pllConfig = new SimplePllConfiguration("firesimBuildTopClockGenerator", c.params)
pllConfig.emitSummaries
th.setRefClockFreq(pllConfig.referenceFreqMHz)
val rationalClockSpecs = for ((sinkP, division) <- pllConfig.sinkDividerMap) yield {
RationalClock(sinkP.name.get, 1, division)
}
val input_clocks: RecordMap[Clock] = p(ClockBridgeInstantiatorKey).requestClockRecordMap(
BuildTopClockParameters(
rationalClockSpecs.toSeq,
p(FireSimBaseClockNameKey),
pllConfig.referenceFreqMHz * (1000 * 1000)))
(c.clocks zip c.params) map ({ case (clock, param) =>
clock := input_clocks(param.name.get).get
})
}
case r: Reset => r := th.buildtopReset.asAsyncReset
})
}
})
class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSignalReferences {
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary()) freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
val buildtopClock = Wire(Clock())
val buildtopReset = WireInit(false.B)
// The peek-poke bridge must still be instantiated even though it's // The peek-poke bridge must still be instantiated even though it's
// functionally unused. This will be removed in a future PR. // functionally unused. This will be removed in a future PR.
val dummy = WireInit(false.B) val dummy = WireInit(false.B)
val peekPokeBridge = PeekPokeBridge(buildtopClock, dummy) val peekPokeBridge = PeekPokeBridge(harnessBinderClock, dummy)
val resetBridge = Module(new ResetPulseBridge(ResetPulseBridgeParameters())) val resetBridge = Module(new ResetPulseBridge(ResetPulseBridgeParameters()))
// In effect, the bridge counts the length of the reset in terms of this clock. // In effect, the bridge counts the length of the reset in terms of this clock.
resetBridge.io.clock := buildtopClock resetBridge.io.clock := harnessBinderClock
buildtopReset := resetBridge.io.reset
// Ensures FireSim-synthesized assertions and instrumentation is disabled
// while buildtopReset is asserted. This ensures assertions do not fire at
// time zero in the event their local reset is delayed (typically because it
// has been pipelined)
midas.targetutils.GlobalResetCondition(buildtopReset)
def dutReset = { require(false, "dutReset should not be used in Firesim"); false.B } def implicitClock = false.B.asClock // unused
def implicitReset = resetBridge.io.reset
def success = { require(false, "success should not be used in Firesim"); false.B } def success = { require(false, "success should not be used in Firesim"); false.B }
// Instantiate multiple instances of the DUT to implement supernode instantiateChipTops()
for (i <- 0 until p(NumNodes)) {
// It's not a RC bump without some hacks...
// Copy the AsyncClockGroupsKey to generate a fresh node on each
// instantiation of the dut, otherwise the initial instance will be
// reused across each node
import freechips.rocketchip.subsystem.AsyncClockGroupsKey
val lazyModule = LazyModule(p(BuildTop)(p))
val module = Module(lazyModule.module)
lazyModule match { case d: HasIOBinders => // Ensures FireSim-synthesized assertions and instrumentation is disabled
ApplyHarnessBinders(this, d.lazySystem, d.portMap) // while resetBridge.io.reset is asserted. This ensures assertions do not fire at
} // time zero in the event their local reset is delayed (typically because it
NodeIdx.increment() // has been pipelined)
} midas.targetutils.GlobalResetCondition(resetBridge.io.reset)
buildtopClock := p(ClockBridgeInstantiatorKey).requestClock("buildtop_reference_clock", getRefClockFreq * (1000 * 1000))
p(ClockBridgeInstantiatorKey).instantiateFireSimClockBridge
} }

View File

@@ -18,6 +18,7 @@ import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
import scala.math.{min, max} import scala.math.{min, max}
import chipyard.clocking.{ChipyardPRCIControlKey} import chipyard.clocking.{ChipyardPRCIControlKey}
import chipyard.harness.{HarnessClockInstantiatorKey}
import icenet._ import icenet._
import firesim.bridges._ import firesim.bridges._
@@ -43,6 +44,11 @@ class WithoutClockGating extends Config((site, here, up) => {
case ChipyardPRCIControlKey => up(ChipyardPRCIControlKey, site).copy(enableTileClockGating = false) case ChipyardPRCIControlKey => up(ChipyardPRCIControlKey, site).copy(enableTileClockGating = false)
}) })
// Use the firesim clock bridge instantiator. this is required
class WithFireSimHarnessClockBridgeInstantiator extends Config((site, here, up) => {
case HarnessClockInstantiatorKey => () => new FireSimClockBridgeInstantiator
})
// Testing configurations // Testing configurations
// This enables printfs used in testing // This enables printfs used in testing
class WithScalaTestFeatures extends Config((site, here, up) => { class WithScalaTestFeatures extends Config((site, here, up) => {
@@ -63,9 +69,10 @@ class WithNVDLASmall extends nvidia.blocks.dla.WithNVDLA("small")
// Minimal set of FireSim-related design tweaks - notably discludes FASED, TraceIO, and the BlockDevice // Minimal set of FireSim-related design tweaks - notably discludes FASED, TraceIO, and the BlockDevice
class WithMinimalFireSimDesignTweaks extends Config( class WithMinimalFireSimDesignTweaks extends Config(
// Required*: Uses FireSim ClockBridge and PeekPokeBridge to drive the system with a single clock/reset // Required*: Punch all clocks to FireSim's harness clock instantiator
new WithFireSimHarnessClockBinder ++ new WithFireSimHarnessClockBridgeInstantiator ++
new WithFireSimSimpleClocks ++ new chipyard.harness.WithClockAndResetFromHarness ++
new chipyard.clocking.WithPassthroughClockGenerator ++
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source // Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
new WithBootROM ++ new WithBootROM ++
// Required: Existing FAME-1 transform cannot handle black-box clock gates // Required: Existing FAME-1 transform cannot handle black-box clock gates
@@ -116,19 +123,11 @@ class WithFireSimConfigTweaks extends Config(
// Using some other frequency will require runnings the FASED runtime configuration generator // Using some other frequency will require runnings the FASED runtime configuration generator
// to generate faithful DDR3 timing values. // to generate faithful DDR3 timing values.
new chipyard.config.WithSystemBusFrequency(1000.0) ++ new chipyard.config.WithSystemBusFrequency(1000.0) ++
new chipyard.config.WithSystemBusFrequencyAsDefault ++ // All unspecified clock frequencies, notably the implicit clock, will use the sbus freq (1000 MHz)
// Explicitly set PBUS + MBUS to 1000 MHz, since they will be driven to 100 MHz by default because of assignments in the Chisel
new chipyard.config.WithPeripheryBusFrequency(1000.0) ++ new chipyard.config.WithPeripheryBusFrequency(1000.0) ++
new chipyard.config.WithMemoryBusFrequency(1000.0) ++ new chipyard.config.WithMemoryBusFrequency(1000.0) ++
new WithFireSimDesignTweaks new WithFireSimDesignTweaks
) )
// Tweak more representative of testchip configs
class WithFireSimTestChipConfigTweaks extends Config(
new chipyard.config.WithTestChipBusFreqs ++
new WithFireSimDesignTweaks
)
// Tweaks to use minimal design tweaks // Tweaks to use minimal design tweaks
// Need to use initramfs to use linux (no block device) // Need to use initramfs to use linux (no block device)
class WithMinimalFireSimHighPerfConfigTweaks extends Config( class WithMinimalFireSimHighPerfConfigTweaks extends Config(
@@ -267,9 +266,10 @@ class FireSimLeanGemminiPrintfRocketConfig extends Config(
// Supernode Configurations, base off chipyard's RocketConfig // Supernode Configurations, base off chipyard's RocketConfig
//********************************************************************************** //**********************************************************************************
class SupernodeFireSimRocketConfig extends Config( class SupernodeFireSimRocketConfig extends Config(
new WithNumNodes(4) ++ new WithFireSimHarnessClockBridgeInstantiator ++
new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 8L) ++ // 8 GB new chipyard.harness.WithHomogeneousMultiChip(n=4, new Config(
new FireSimRocketConfig) new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 8L) ++ // 8GB DRAM per node
new FireSimRocketConfig)))
//********************************************************************************** //**********************************************************************************
//* CVA6 Configurations //* CVA6 Configurations