Address generator unification PR reviews

This commit is contained in:
Jerry Zhao
2020-02-23 22:53:14 -08:00
parent 941c217fbe
commit 708a5fb9a6
17 changed files with 153 additions and 246 deletions

View File

@@ -16,34 +16,29 @@ import testchipip._
import icenet._
import tracegen.{HasTraceGenTilesModuleImp}
import scala.reflect.{ClassTag, classTag}
import scala.reflect.{ClassTag}
// System for instantiating binders based
// on the scala type of the Target (_not_ its IO). This avoids needing to
// duplicate harnesses (essentially test harnesses) for each target.
//
// You could just as well create a custom harness module that instantiates
// bridges explicitly, or add methods to
// your target traits that instantiate the bridge there (i.e., akin to
// SimAXI4Mem). Since cake traits live in Rocket Chip it was easiest to match
// on the types rather than change trait code.
// IOBinders is map between string representations of traits to the desired
// IO connection behavior for tops matching that trait. We use strings to enable
// composition and overriding of IOBinders, much like how normal Keys in the config
// system are used/ At elaboration, the testharness traverses this set of functions,
// and functions which match the type of the Top are evaluated.
// You can add your own binder by adding a new (key, fn) pair, typically by using
// the OverrideIOBinder or ComposeIOBinder macros
// A map of partial functions that match on the type the DUT (_not_ it's
// IO) to generate an appropriate bridge. You can add your own binder by adding
// a new (key, fn) pair. You should override existing pairs in this map when
// using a custom IOBinder
// Since we also want to compose this structure like the existing config system,
// use the scala string representation of the matched trait as a key
case object IOBinders extends Field[Map[String, (Clock, Bool, Bool, Any) => Seq[Any]]](Map())
// DOC include start: IOBinders
case object IOBinders extends Field[Map[String, (Clock, Bool, Bool, Any) => Seq[Any]]](
Map[String, (Clock, Bool, Bool, Any) => Seq[Any]]().withDefaultValue((c: Clock, r: Bool, s: Bool, t: Any) => Nil)
)
// This macro overrides previous matches on some Top mixin. This is useful for
// binders which modify IO, since those typically cannot be composed
class RegisterIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
// binders which drive IO, since those typically cannot be composed
class OverrideIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
((clock: Clock, reset: Bool, success: Bool, t: Any) => {
t match {
@@ -56,34 +51,41 @@ class RegisterIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit ta
// This macro composes with previous matches on some Top mixin. This is useful for
// annotation-like binders, since those can typically be composed
class RegisterBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
class ComposeIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
((clock: Clock, reset: Bool, success: Bool, t: Any) => {
t match {
case top: T => fn(clock, reset, success, top) ++
up(IOBinders, site).getOrElse(tag.runtimeClass.toString, (c: Clock, r: Bool, s: Bool, t: Any) => Nil)(clock, reset, success, top)
case top: T => (up(IOBinders, site)(tag.runtimeClass.toString)(clock, reset, success, top)
++ fn(clock, reset, success, top))
case _ => Nil
}
})
)
})
class WithGPIOTiedOff extends RegisterIOBinder({
// DOC include end: IOBinders
class WithGPIOTiedOff extends OverrideIOBinder({
(c, r, s, top: HasPeripheryGPIOModuleImp) => top.gpio.map(gpio => gpio.pins.map(p => p.i.ival := false.B)); Nil
})
class WithSimBlockDevice extends RegisterIOBinder({
class WithSimBlockDevice extends OverrideIOBinder({
(c, r, s, top: CanHavePeripheryBlockDeviceModuleImp) => top.connectSimBlockDevice(c, r); Nil
})
class WithBlockDeviceModel extends RegisterIOBinder({
class WithBlockDeviceModel extends OverrideIOBinder({
(c, r, s, top: CanHavePeripheryBlockDeviceModuleImp) => top.connectBlockDeviceModel(); Nil
})
class WithLoopbackNIC extends RegisterIOBinder({
class WithLoopbackNIC extends OverrideIOBinder({
(c, r, s, top: CanHavePeripheryIceNICModuleImp) => top.connectNicLoopback(); Nil
})
class WithUARTAdapter extends RegisterIOBinder({
class WithSimNIC extends OverrideIOBinder({
(c, r, s, top: CanHavePeripheryIceNICModuleImp) => top.connectSimNetwork(c, r); Nil
})
class WithUARTAdapter extends OverrideIOBinder({
(c, r, s, top: HasPeripheryUARTModuleImp) => {
val defaultBaudRate = 115200 // matches sifive-blocks uart baudrate
top.uart.zipWithIndex.foreach{ case (dut_io, i) =>
@@ -95,23 +97,25 @@ class WithUARTAdapter extends RegisterIOBinder({
}
})
class WithSimAXIMem extends RegisterIOBinder({
// DOC include start: WithSimAXIMem
class WithSimAXIMem extends OverrideIOBinder({
(c, r, s, top: CanHaveMasterAXI4MemPortModuleImp) => top.connectSimAXIMem(); Nil
})
// DOC include end: WithSimAXIMem
class WithSimAXIMMIO extends RegisterIOBinder({
class WithSimAXIMMIO extends OverrideIOBinder({
(c, r, s, top: CanHaveMasterAXI4MMIOPortModuleImp) => top.connectSimAXIMMIO(); Nil
})
class WithDontTouchPorts extends RegisterIOBinder({
class WithDontTouchPorts extends OverrideIOBinder({
(c, r, s, top: DontTouch) => top.dontTouchPorts(); Nil
})
class WithTieOffInterrupts extends RegisterIOBinder({
class WithTieOffInterrupts extends OverrideIOBinder({
(c, r, s, top: HasExtInterruptsBundle) => top.tieOffInterrupts(); Nil
})
class WithTieOffL2FBusAXI extends RegisterIOBinder({
class WithTieOffL2FBusAXI extends OverrideIOBinder({
(c, r, s, top: CanHaveSlaveAXI4PortModuleImp) => {
top.l2_frontend_bus_axi4.foreach(axi => {
axi.tieoff()
@@ -129,7 +133,7 @@ class WithTieOffL2FBusAXI extends RegisterIOBinder({
}
})
class WithTiedOffDebug extends RegisterIOBinder({
class WithTiedOffDebug extends OverrideIOBinder({
(c, r, s, top: HasPeripheryDebugModuleImp) => {
Debug.tieoffDebug(top.debug, top.psd)
// tieoffDebug doesn't actually tie everything off :/
@@ -138,7 +142,7 @@ class WithTiedOffDebug extends RegisterIOBinder({
}
})
class WithSimSerial extends RegisterIOBinder({
class WithSimSerial extends OverrideIOBinder({
(c, r, s, top: CanHavePeripherySerialModuleImp) => {
val ser_success = top.connectSimSerial()
when (ser_success) { s := true.B }
@@ -146,12 +150,12 @@ class WithSimSerial extends RegisterIOBinder({
}
})
class WithTiedOffSerial extends RegisterIOBinder({
class WithTiedOffSerial extends OverrideIOBinder({
(c, r, s, top: CanHavePeripherySerialModuleImp) => top.tieoffSerial(); Nil
})
class WithSimDTM extends RegisterIOBinder({
class WithSimDebug extends OverrideIOBinder({
(c, r, s, top: HasPeripheryDebugModuleImp) => {
val dtm_success = Wire(Bool())
top.reset := r | top.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)
@@ -162,6 +166,6 @@ class WithSimDTM extends RegisterIOBinder({
})
class WithTraceGenSuccessBinder extends RegisterIOBinder({
(c, r, s, top: HasTraceGenTilesModuleImp) => s := top.success; Nil
class WithTraceGenSuccessBinder extends OverrideIOBinder({
(c, r, s, top: HasTraceGenTilesModuleImp) => when (top.success) { s := true.B }; Nil
})

View File

@@ -90,7 +90,7 @@ class jtagRocketConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithSimAXIMem ++
new chipyard.iobinders.WithSimDTM ++ // add SimJtag and SimSerial, use both to drive sim
new chipyard.iobinders.WithSimDebug ++ // add SimJtag and SimSerial, use both to drive sim
new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++
new chipyard.config.WithNoGPIO ++
@@ -112,7 +112,7 @@ class dmiRocketConfig extends Config(
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithSimAXIMem ++
new chipyard.iobinders.WithTiedOffSerial ++
new chipyard.iobinders.WithSimDTM ++ // add SimDTM and use it to drive simulation
new chipyard.iobinders.WithSimDebug ++ // add SimDebug and use it to drive simulation
new chipyard.config.WithNoGPIO ++
new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++
@@ -345,6 +345,7 @@ class LoopbackNICRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include start: scratchpadrocket
class ScratchpadRocketConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithTieOffInterrupts ++
@@ -363,3 +364,4 @@ class ScratchpadRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include end: scratchpadrocket

View File

@@ -24,6 +24,7 @@ class BoomTraceGenConfig extends Config(
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenTop ++
new tracegen.WithBoomTraceGen(List.fill(2) { DCacheParams(nMSHRs = 8, nSets = 16, nWays = 2) }) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.system.BaseConfig)
class NonBlockingTraceGenL2Config extends Config(

View File

@@ -24,26 +24,26 @@ import tracegen.HasTraceGenTilesModuleImp
import boom.common.{BoomTile}
import chipyard.iobinders.{IOBinders, RegisterIOBinder, RegisterBinder}
import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder}
import chipyard.HasBoomAndRocketTilesModuleImp
class WithSerialBridge extends RegisterIOBinder({
class WithSerialBridge extends OverrideIOBinder({
(c, r, s, target: CanHavePeripherySerialModuleImp) => target.serial.map(s => SerialBridge(s)(target.p)).toSeq
})
class WithNICBridge extends RegisterIOBinder({
class WithNICBridge extends OverrideIOBinder({
(c, r, s, target: CanHavePeripheryIceNICModuleImp) => target.net.map(n => NICBridge(n)(target.p)).toSeq
})
class WithUARTBridge extends RegisterIOBinder({
class WithUARTBridge extends OverrideIOBinder({
(c, r, s, target: HasPeripheryUARTModuleImp) => target.uart.map(u => UARTBridge(u)(target.p)).toSeq
})
class WithBlockDeviceBridge extends RegisterIOBinder({
class WithBlockDeviceBridge extends OverrideIOBinder({
(c, r, s, target: CanHavePeripheryBlockDeviceModuleImp) => target.bdev.map(b => BlockDevBridge(b, target.reset.toBool)(target.p)).toSeq
})
class WithFASEDBridge extends RegisterIOBinder({
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) =>
@@ -58,15 +58,15 @@ class WithFASEDBridge extends RegisterIOBinder({
}
})
class WithTracerVBridge extends RegisterIOBinder({
class WithTracerVBridge extends OverrideIOBinder({
(c, r, s, target: CanHaveTraceIOModuleImp) => target.traceIO.map(t => TracerVBridge(t)(target.p)).toSeq
})
class WithTraceGenBridge extends RegisterIOBinder({
class WithTraceGenBridge extends OverrideIOBinder({
(c, r, s, target: HasTraceGenTilesModuleImp) => Seq(GroundTestBridge(target.success)(target.p))
})
class WithFireSimMultiCycleRegfile extends RegisterBinder({
class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
(c, r, s, target: HasBoomAndRocketTilesModuleImp) => {
target.outer.tiles.map {
case r: RocketTile => {

View File

@@ -0,0 +1,38 @@
//See LICENSE for license details.
package firesim.firesim
import chisel3._
import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule}
import midas.widgets.{Bridge, PeekPokeBridge}
import chipyard.{BuildTop}
import chipyard.iobinders.{IOBinders}
// 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
})
class FireSim(implicit val p: Parameters) extends RawModule {
val clock = IO(Input(Clock()))
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 peekPokeBridge = PeekPokeBridge(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(false.B, target))
}
}
}

View File

@@ -21,7 +21,6 @@ import tracegen.TraceGenKey
import icenet._
import firesim.bridges._
import firesim.util.{WithNumNodes}
import firesim.configs._
import chipyard.{BuildTop}
import chipyard.config.ConfigValName._
@@ -106,11 +105,13 @@ class WithFireSimConfigTweaks extends Config(
//*****************************************************************
// Rocket configs, base off chipyard's RocketConfig
//*****************************************************************
// DOC include start: firesimconfig
class FireSimRocketConfig extends Config(
new WithDefaultFireSimBridges ++
new WithDefaultMemModel ++
new WithFireSimConfigTweaks ++
new chipyard.RocketConfig)
// DOC include end: firesimconfig
class FireSimQuadRocketConfig extends Config(
new WithDefaultFireSimBridges ++
@@ -119,19 +120,6 @@ class FireSimQuadRocketConfig extends Config(
new chipyard.QuadRocketConfig)
//*****************************************************************
// Sha3 rocc-accel configs, base off chipyard's Sha3RocketConfig
//*****************************************************************
class FireSimSha3RocketConfig extends Config(
new WithDefaultFireSimBridges ++
new WithDefaultMemModel ++
new WithFireSimConfigTweaks ++
new chipyard.Sha3RocketConfig)
class FireSimSha3PrintfRocketConfig extends Config(
new sha3.WithSha3Printf ++
new FireSimSha3RocketConfig)
//*****************************************************************
// Boom config, base off chipyard's LargeBoomConfig
//*****************************************************************

View File

@@ -1,43 +0,0 @@
package firesim.firesim
import chisel3._
import freechips.rocketchip._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.devices.debug.HasPeripheryDebugModuleImp
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.util.{HeterogeneousBag}
import freechips.rocketchip.amba.axi4.AXI4Bundle
import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.diplomacy.LazyModule
import icenet._
import firesim.util.DefaultFireSimHarness
import testchipip._
import testchipip.SerialAdapter.SERIAL_IF_WIDTH
import tracegen.{HasTraceGenTiles, HasTraceGenTilesModuleImp}
import sifive.blocks.devices.uart._
import java.io.File
object FireSimValName {
implicit val valName = ValName("FireSimHarness")
}
import FireSimValName._
/*******************************************************************************
* Top level DESIGN configurations. These describe the basic instantiations of
* the designs being simulated.
*
* In general, if you're adding or removing features from any of these, you
* should CREATE A NEW ONE, WITH A NEW NAME. This is because the manager
* will store this name as part of the tags for the AGFI, so that later you can
* reconstruct what is in a particular AGFI. These tags are also used to
* determine which driver to build.
*******************************************************************************/
class FireSim(implicit p: Parameters) extends DefaultFireSimHarness