[firechip] Support registration of custom endpoint binders

This commit is contained in:
David Biancolin
2019-09-26 20:49:03 +00:00
parent f44f3aacbf
commit 4c45d2e48a
5 changed files with 6 additions and 103 deletions

View File

@@ -1,84 +0,0 @@
//See LICENSE for license details.
package firesim.firesim
import chisel3._
import chisel3.experimental.RawModule
import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.devices.debug.HasPeripheryDebugModuleImp
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPortModuleImp}
import sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
import testchipip.{HasPeripherySerialModuleImp, HasPeripheryBlockDeviceModuleImp}
import icenet.HasPeripheryIceNICModuleImpValidOnly
import junctions.{NastiKey, NastiParameters}
import midas.widgets.{IsEndpoint, PeekPokeEndpoint}
import midas.models.{FASEDEndpoint, FasedAXI4Edge}
import firesim.endpoints._
import firesim.configs.MemModelKey
// Creates a wrapper FireSim harness module that instantiates endpoints 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
// endpoints explicitly, or add methods to
// your target traits that instantiate the endpoint 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.
// Determines the number of times to instantiate the DUT in the harness.
// Subsumes legacy supernode support
case object NumNodes extends Field[Int](1)
class DefaultFireSimHarness[T <: LazyModule](dutGen: () => T)(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))(Module(LazyModule(dutGen()).module))
val peekPokeEndpoint = PeekPokeEndpoint(reset)
// A Seq of partial functions that will instantiate the right endpoint only
// if that Mixin trait is present in the target's class instance
//
// TODO: If we like this PF approach, register them in the config instead of centralizing them here
val endpointBinders = Seq[PartialFunction[Any, Seq[IsEndpoint]]](
{ case t: HasPeripheryDebugModuleImp =>
t.debug.clockeddmi.foreach({ cdmi =>
cdmi.dmi.req.valid := false.B
cdmi.dmi.req.bits := DontCare
cdmi.dmi.resp.ready := false.B
cdmi.dmiClock := false.B.asClock
cdmi.dmiReset := false.B
})
Seq()
},
{ case t: HasPeripherySerialModuleImp => Seq(SerialEndpoint(t.serial)) },
{ case t: HasPeripheryIceNICModuleImpValidOnly => Seq(NICEndpoint(t.net)) },
{ case t: HasPeripheryUARTModuleImp => t.uart.map(u => UARTEndpoint(u)) },
{ case t: HasPeripheryBlockDeviceModuleImp => Seq(BlockDevEndpoint(t.bdev, reset)) },
{ case t: CanHaveMasterAXI4MemPortModuleImp =>
(t.mem_axi4 zip t.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)
val fasedP = p.alterPartial({
case NastiKey => nastiKey
case FasedAXI4Edge => Some(edge)
})
FASEDEndpoint(axi4Bundle, reset, p(MemModelKey)(fasedP))(fasedP)
})
}).toSeq
},
{ case t: HasTraceIOImp => TracerVEndpoint(t.traceIO) }
)
// Apply each partial function to each DUT instance
for ((target) <- targets) {
endpointBinders.map(_.lift).flatMap(elaborator => elaborator(target))
}
}
}

View File

@@ -3,9 +3,8 @@
package firesim.firesim
import chisel3._
import chisel3.experimental.RawModule
import freechips.rocketchip.config.{Field, Parameters, Config}
import freechips.rocketchip.config.{Field, Config}
import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.devices.debug.HasPeripheryDebugModuleImp
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPortModuleImp}
@@ -15,23 +14,12 @@ import testchipip.{HasPeripherySerialModuleImp, HasPeripheryBlockDeviceModuleImp
import icenet.HasPeripheryIceNICModuleImpValidOnly
import junctions.{NastiKey, NastiParameters}
import midas.widgets.{IsEndpoint, PeekPokeEndpoint}
import midas.widgets.{IsEndpoint}
import midas.models.{FASEDEndpoint, FasedAXI4Edge}
import firesim.endpoints._
import firesim.configs.MemModelKey
import firesim.util.RegisterEndpointBinder
// A sequence of partial functions that match on the type the DUT (_not_ it's
// IO) to generate an appropriate endpoint. You can add your own endpoint by prepending
// a custom PartialFunction to this Seq
case object EndpointBinders extends Field[Seq[PartialFunction[Any, Seq[IsEndpoint]]]](Seq())
// Config sugar that accepts a partial function and prepends it to EndpointBinders
class RegisterEndpointBinder(pf: =>PartialFunction[Any, Seq[IsEndpoint]]) extends Config((site, here, up) => {
case EndpointBinders => pf +: up(EndpointBinders, site)
})
// Default FireSim Endpoint binders follow
class WithTiedOffDebug extends RegisterEndpointBinder({ case target: HasPeripheryDebugModuleImp =>
target.debug.clockeddmi.foreach({ cdmi =>
cdmi.dmi.req.valid := false.B

View File

@@ -19,6 +19,7 @@ import tracegen.TraceGenKey
import icenet._
import firesim.endpoints._
import firesim.util.{WithNumNodes}
import firesim.configs.WithDefaultMemModel
class WithBootROM extends Config((site, here, up) => {
@@ -174,9 +175,6 @@ class FireSimBoomQuadCoreConfig extends Config(
//**********************************************************************************
//* Supernode Configurations
//*********************************************************************************/
class WithNumNodes(n: Int) extends Config((pname, site, here) => {
case NumNodes => n
})
class SupernodeFireSimRocketChipConfig extends Config(
new WithNumNodes(4) ++

View File

@@ -14,6 +14,7 @@ import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.diplomacy.LazyModule
import utilities.{Subsystem, SubsystemModuleImp}
import icenet._
import firesim.util.DefaultFireSimHarness
import testchipip._
import testchipip.SerialAdapter.SERIAL_IF_WIDTH
import tracegen.{HasTraceGenTiles, HasTraceGenTilesModuleImp}