Add ChipTop to enable real chip configs with IO cells, etc. (#480)
This adds an additional layer (ChipTop) between the System module and the TestHarness. The IOBinder API is now changed to take only a single parameter (an Any) and return a 3 things: The IO port(s), the IO cell(s), and a function to call inside the test harness, which is analogous to the old IOBinder function, except that it takes a TestHarness object as an argument instead of (clock, reset, success). * A new Top-level module, ChipTop, has been created. ChipTop instantiates a "system" module specified by BuildSystem. * BuildTop now builds a ChipTop dut module in the TestHarness by default * A new BuildSystem key has been added, which by default builds DigitalTop (previously just called Top) * The IOBinders API has changed. IOBinders are now called inside of ChipTop and return a tuple3 of (IO ports, IO cells, harness functions). The harness functions are now called inside the TestHarness (this is analogous to the previous IOBinder functions). * IO cell models have been included in ChipTop. These can be replaced with real IO cells for tapeout, or used as-is for simulation. * The default for the TOP make variable is now ChipTop (was Top)
This commit is contained in:
@@ -7,10 +7,11 @@ import chisel3.experimental.annotate
|
||||
|
||||
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||
import freechips.rocketchip.devices.debug.HasPeripheryDebugModuleImp
|
||||
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPortModuleImp}
|
||||
import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebugModuleImp}
|
||||
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPortModuleImp, HasExtInterruptsModuleImp}
|
||||
import freechips.rocketchip.tile.{RocketTile}
|
||||
import sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
|
||||
import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp}
|
||||
|
||||
import testchipip.{CanHavePeripherySerialModuleImp, CanHavePeripheryBlockDeviceModuleImp, CanHaveTraceIOModuleImp}
|
||||
import icenet.CanHavePeripheryIceNICModuleImp
|
||||
@@ -29,56 +30,55 @@ import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder}
|
||||
import chipyard.HasChipyardTilesModuleImp
|
||||
|
||||
class WithSerialBridge extends OverrideIOBinder({
|
||||
(c, r, s, target: CanHavePeripherySerialModuleImp) =>
|
||||
target.serial.map(s => SerialBridge(target.clock, s)(target.p)).toSeq
|
||||
(system: CanHavePeripherySerialModuleImp) =>
|
||||
system.serial.foreach(s => SerialBridge(system.clock, s)(system.p)); Nil
|
||||
})
|
||||
|
||||
class WithNICBridge extends OverrideIOBinder({
|
||||
(c, r, s, target: CanHavePeripheryIceNICModuleImp) =>
|
||||
target.net.map(n => NICBridge(target.clock, n)(target.p)).toSeq
|
||||
(system: CanHavePeripheryIceNICModuleImp) =>
|
||||
system.net.foreach(n => NICBridge(system.clock, n)(system.p)); Nil
|
||||
})
|
||||
|
||||
class WithUARTBridge extends OverrideIOBinder({
|
||||
(c, r, s, target: HasPeripheryUARTModuleImp) =>
|
||||
target.uart.map(u => UARTBridge(target.clock, u)(target.p)).toSeq
|
||||
(system: HasPeripheryUARTModuleImp) =>
|
||||
system.uart.foreach(u => UARTBridge(system.clock, u)(system.p)); Nil
|
||||
})
|
||||
|
||||
class WithBlockDeviceBridge extends OverrideIOBinder({
|
||||
(c, r, s, target: CanHavePeripheryBlockDeviceModuleImp) =>
|
||||
target.bdev.map(b => BlockDevBridge(target.clock, b, target.reset.toBool)(target.p)).toSeq
|
||||
(system: CanHavePeripheryBlockDeviceModuleImp) =>
|
||||
system.bdev.foreach(b => BlockDevBridge(system.clock, b, system.reset.toBool)(system.p)); Nil
|
||||
})
|
||||
|
||||
class WithFASEDBridge extends OverrideIOBinder({
|
||||
(c, r, s, t: CanHaveMasterAXI4MemPortModuleImp) => {
|
||||
implicit val p = t.p
|
||||
(t.mem_axi4 zip t.outer.memAXI4Node).flatMap({ case (io, node) =>
|
||||
(system: CanHaveMasterAXI4MemPortModuleImp) => {
|
||||
implicit val p = system.p
|
||||
(system.mem_axi4 zip system.outer.memAXI4Node).flatMap({ case (io, node) =>
|
||||
(io zip node.in).map({ case (axi4Bundle, (_, edge)) =>
|
||||
val nastiKey = NastiParameters(axi4Bundle.r.bits.data.getWidth,
|
||||
axi4Bundle.ar.bits.addr.getWidth,
|
||||
axi4Bundle.ar.bits.id.getWidth)
|
||||
FASEDBridge(t.clock, axi4Bundle, t.reset.toBool,
|
||||
FASEDBridge(system.clock, axi4Bundle, system.reset.toBool,
|
||||
CompleteConfig(p(firesim.configs.MemModelKey), nastiKey, Some(AXI4EdgeSummary(edge))))
|
||||
})
|
||||
}).toSeq
|
||||
})
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
class WithTracerVBridge extends OverrideIOBinder({
|
||||
(c, r, s, target: CanHaveTraceIOModuleImp) => target.traceIO match {
|
||||
case Some(t) => t.traces.map(tileTrace => TracerVBridge(tileTrace)(target.p))
|
||||
case None => Nil
|
||||
}
|
||||
(system: CanHaveTraceIOModuleImp) =>
|
||||
system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p))); Nil
|
||||
})
|
||||
|
||||
|
||||
class WithTraceGenBridge extends OverrideIOBinder({
|
||||
(c, r, s, target: HasTraceGenTilesModuleImp) =>
|
||||
Seq(GroundTestBridge(target.clock, target.success)(target.p))
|
||||
(system: HasTraceGenTilesModuleImp) =>
|
||||
GroundTestBridge(system.clock, system.success)(system.p); Nil
|
||||
})
|
||||
|
||||
class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
|
||||
(c, r, s, target: HasChipyardTilesModuleImp) => {
|
||||
target.outer.tiles.map {
|
||||
(system: HasChipyardTilesModuleImp) => {
|
||||
system.outer.tiles.map {
|
||||
case r: RocketTile => {
|
||||
annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf))
|
||||
r.module.fpuOpt.foreach(fpu => annotate(MemModelAnnotation(fpu.fpuImpl.regfile)))
|
||||
@@ -100,13 +100,31 @@ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
|
||||
}
|
||||
})
|
||||
|
||||
class WithTiedOffSystemGPIO extends OverrideIOBinder({
|
||||
(system: HasPeripheryGPIOModuleImp) =>
|
||||
system.gpio.foreach(_.pins.foreach(_.i.ival := false.B)); Nil
|
||||
})
|
||||
|
||||
class WithTiedOffSystemDebug extends OverrideIOBinder({
|
||||
(system: HasPeripheryDebugModuleImp) => {
|
||||
Debug.tieoffDebug(system.debug, system.psd)
|
||||
// tieoffDebug doesn't actually tie everything off :/
|
||||
system.debug.foreach(_.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare }))
|
||||
Nil
|
||||
}
|
||||
})
|
||||
|
||||
class WithTiedOffSystemInterrupts extends OverrideIOBinder({
|
||||
(system: HasExtInterruptsModuleImp) =>
|
||||
system.interrupts := 0.U; Nil
|
||||
})
|
||||
|
||||
|
||||
// Shorthand to register all of the provided bridges above
|
||||
class WithDefaultFireSimBridges extends Config(
|
||||
new chipyard.iobinders.WithGPIOTiedOff ++
|
||||
new chipyard.iobinders.WithTiedOffDebug ++
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++
|
||||
new WithTiedOffSystemGPIO ++
|
||||
new WithTiedOffSystemDebug ++
|
||||
new WithTiedOffSystemInterrupts ++
|
||||
new WithSerialBridge ++
|
||||
new WithNICBridge ++
|
||||
new WithUARTBridge ++
|
||||
|
||||
@@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy.{LazyModule}
|
||||
|
||||
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge}
|
||||
|
||||
import chipyard.{BuildTop}
|
||||
import chipyard.{BuildSystem}
|
||||
import chipyard.iobinders.{IOBinders}
|
||||
|
||||
// Determines the number of times to instantiate the DUT in the harness.
|
||||
@@ -26,14 +26,14 @@ class FireSim(implicit val p: Parameters) extends RawModule {
|
||||
val reset = WireInit(false.B)
|
||||
withClockAndReset(clock, reset) {
|
||||
// Instantiate multiple instances of the DUT to implement supernode
|
||||
val targets = Seq.fill(p(NumNodes))(p(BuildTop)(p))
|
||||
val targets = Seq.fill(p(NumNodes))(p(BuildSystem)(p))
|
||||
val peekPokeBridge = PeekPokeBridge(clock, reset)
|
||||
// A Seq of partial functions that will instantiate the right bridge only
|
||||
// if that Mixin trait is present in the target's class instance
|
||||
//
|
||||
// Apply each partial function to each DUT instance
|
||||
for ((target) <- targets) {
|
||||
p(IOBinders).values.map(fn => fn(clock, reset.asBool, false.B, target))
|
||||
p(IOBinders).values.map(_(target))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import boom.common.{BoomTilesKey, BoomCrossingKey}
|
||||
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
|
||||
import firesim.configs._
|
||||
|
||||
import chipyard.{BuildTop, Top, TopModule}
|
||||
import chipyard.{BuildSystem, DigitalTop, DigitalTopModule}
|
||||
import chipyard.config.ConfigValName._
|
||||
import chipyard.iobinders.{IOBinders}
|
||||
|
||||
@@ -64,7 +64,7 @@ class WithSingleRationalTileDomain(multiplier: Int, divisor: Int) extends Config
|
||||
class HalfRateUncore extends WithSingleRationalTileDomain(2,1)
|
||||
|
||||
class WithFiresimMulticlockTop extends Config((site, here, up) => {
|
||||
case BuildTop => (p: Parameters) => Module(LazyModule(new FiresimMulticlockTop()(p)).suggestName("Top").module)
|
||||
case BuildSystem => (p: Parameters) => Module(LazyModule(new FiresimMulticlockTop()(p)).suggestName("system").module)
|
||||
})
|
||||
|
||||
// Complete Config
|
||||
@@ -74,12 +74,12 @@ class FireSimQuadRocketMulticlockConfig extends Config(
|
||||
new FireSimQuadRocketConfig)
|
||||
|
||||
// Top Definition
|
||||
class FiresimMulticlockTop(implicit p: Parameters) extends chipyard.Top
|
||||
class FiresimMulticlockTop(implicit p: Parameters) extends chipyard.DigitalTop
|
||||
{
|
||||
override lazy val module = new FiresimMulticlockTopModule(this)
|
||||
}
|
||||
|
||||
class FiresimMulticlockTopModule[+L <: Top](l: L) extends chipyard.TopModule(l) with HasFireSimClockingImp
|
||||
class FiresimMulticlockTopModule[+L <: DigitalTop](l: L) extends chipyard.DigitalTopModule(l) with HasFireSimClockingImp
|
||||
|
||||
// Harness Definition
|
||||
class FireSimMulticlockPOC(implicit val p: Parameters) extends RawModule {
|
||||
@@ -88,14 +88,14 @@ class FireSimMulticlockPOC(implicit val p: Parameters) extends RawModule {
|
||||
val reset = WireInit(false.B)
|
||||
withClockAndReset(refClock, reset) {
|
||||
// Instantiate multiple instances of the DUT to implement supernode
|
||||
val targets = Seq.fill(p(NumNodes))(p(BuildTop)(p))
|
||||
val targets = Seq.fill(p(NumNodes))(p(BuildSystem)(p))
|
||||
val peekPokeBridge = PeekPokeBridge(refClock, reset)
|
||||
// A Seq of partial functions that will instantiate the right bridge only
|
||||
// if that Mixin trait is present in the target's class instance
|
||||
//
|
||||
// Apply each partial function to each DUT instance
|
||||
for ((target) <- targets) {
|
||||
p(IOBinders).values.map(fn => fn(refClock, reset.asBool, false.B, target))
|
||||
p(IOBinders).values.map(_(target))
|
||||
}
|
||||
targets.collect({ case t: HasAdditionalClocks => t.clocks := clockBridge.io.clocks })
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import testchipip.WithRingSystemBus
|
||||
|
||||
import firesim.bridges._
|
||||
import firesim.configs._
|
||||
import chipyard.{BuildTop}
|
||||
import chipyard.config.ConfigValName._
|
||||
|
||||
class WithBootROM extends Config((site, here, up) => {
|
||||
|
||||
Reference in New Issue
Block a user