Merge pull request #1399 from ucb-bar/iobinder-qol
QoL improvement to IOBinders + custom ChipTop example
This commit is contained in:
@@ -18,6 +18,13 @@ The ``IOBinders`` are responsible for instantiating the IO cells for ``ChipTop``
|
|||||||
The ``HarnessBinders`` are responsible for instantiating test harness collateral that connects to the ``ChipTop`` ports.
|
The ``HarnessBinders`` are responsible for instantiating test harness collateral that connects to the ``ChipTop`` ports.
|
||||||
Most types of devices and testing collateral can be instantiated using custom ``IOBinders`` and ``HarnessBinders``.
|
Most types of devices and testing collateral can be instantiated using custom ``IOBinders`` and ``HarnessBinders``.
|
||||||
|
|
||||||
|
Custom ChipTops
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The default standard ``ChipTop`` provides a mimimal, barebones template for ``IOBinders`` to generate IOCells around ``DigitalTop`` traits.
|
||||||
|
For tapeouts, integrating Analog IP, or other non-standard use cases, Chipyard supports specifying a custom ``ChipTop`` using the ``BuildTop`` key.
|
||||||
|
An example of a custom ChipTop which uses non-standard IOCells is provided in `generators/chipyard/src/main/scala/example/CustomChipTop.scala <https://github.com/ucb-bar/chipyard/blob/main/generators/chipyard/src/main/scala/example/CustomChipTop.scala>`__
|
||||||
|
|
||||||
|
|
||||||
System/DigitalTop
|
System/DigitalTop
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]](
|
|||||||
Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil)
|
Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case object DontTouchIOBindersPorts extends Field[Boolean](true)
|
||||||
|
|
||||||
|
class WithDontTouchIOBinders(b: Boolean = true) extends Config((site, here, up) => {
|
||||||
|
case DontTouchIOBindersPorts => b
|
||||||
|
})
|
||||||
|
|
||||||
abstract trait HasIOBinders { this: LazyModule =>
|
abstract trait HasIOBinders { this: LazyModule =>
|
||||||
val lazySystem: LazyModule
|
val lazySystem: LazyModule
|
||||||
private val iobinders = p(IOBinders)
|
private val iobinders = p(IOBinders)
|
||||||
@@ -67,10 +73,33 @@ abstract trait HasIOBinders { this: LazyModule =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
|
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
|
||||||
lazy val iocells = (lzyFlattened.values ++ impFlattened.values).unzip._2.flatten.toBuffer
|
val iocells = InModuleBody { (lzyFlattened.values ++ impFlattened.values).unzip._2.flatten.toBuffer }
|
||||||
|
|
||||||
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop ports
|
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop ports
|
||||||
lazy val portMap = iobinders.keys.map(k => k -> (lzyFlattened(k)._1 ++ impFlattened(k)._1)).toMap
|
val portMap = InModuleBody { iobinders.keys.map(k => k -> (lzyFlattened(k)._1 ++ impFlattened(k)._1)).toMap }
|
||||||
|
|
||||||
|
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop iocells
|
||||||
|
val iocellMap = InModuleBody { iobinders.keys.map(k => k -> (lzyFlattened(k)._2 ++ impFlattened(k)._2)).toMap }
|
||||||
|
|
||||||
|
InModuleBody {
|
||||||
|
if (p(DontTouchIOBindersPorts)) {
|
||||||
|
portMap.values.foreach(_.foreach(dontTouch(_)))
|
||||||
|
}
|
||||||
|
|
||||||
|
println("IOCells generated by IOBinders:")
|
||||||
|
for ((k, v) <- iocellMap) {
|
||||||
|
if (!v.isEmpty) {
|
||||||
|
val cells = v.map(_.getClass.getSimpleName).groupBy(identity).mapValues(_.size)
|
||||||
|
|
||||||
|
println(s" IOBinder for $k generated:")
|
||||||
|
for ((t, c) <- cells) { println(s" $c X $t") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
val totals = iocells.map(_.getClass.getSimpleName).groupBy(identity).mapValues(_.size)
|
||||||
|
println(s" Total generated ${iocells.size} IOCells:")
|
||||||
|
for ((t, c) <- totals) { println(s" $c X $t") }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: The parameters instance is accessible only through LazyModule
|
// Note: The parameters instance is accessible only through LazyModule
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
|||||||
|
|
||||||
// DOC include start: FFTRocketConfig
|
// DOC include start: FFTRocketConfig
|
||||||
class FFTRocketConfig extends Config(
|
class FFTRocketConfig extends Config(
|
||||||
|
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC
|
||||||
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
|
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
@@ -58,6 +59,7 @@ class LargeNVDLARocketConfig extends Config(
|
|||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
class ManyMMIOAcceleratorRocketConfig extends Config(
|
class ManyMMIOAcceleratorRocketConfig extends Config(
|
||||||
|
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC
|
||||||
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
|
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
|
||||||
new nvidia.blocks.dla.WithNVDLA("small") ++ // add a small NVDLA
|
new nvidia.blocks.dla.WithNVDLA("small") ++ // add a small NVDLA
|
||||||
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
|
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class RocketConfig extends Config(
|
|||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
class TinyRocketConfig extends Config(
|
class TinyRocketConfig extends Config(
|
||||||
|
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO FIX: Don't dontTouch the ports
|
||||||
new chipyard.config.WithTLSerialLocation(
|
new chipyard.config.WithTLSerialLocation(
|
||||||
freechips.rocketchip.subsystem.FBUS,
|
freechips.rocketchip.subsystem.FBUS,
|
||||||
freechips.rocketchip.subsystem.PBUS) ++ // attach TL serial adapter to f/p busses
|
freechips.rocketchip.subsystem.PBUS) ++ // attach TL serial adapter to f/p busses
|
||||||
@@ -126,3 +127,9 @@ class MulticlockAXIOverSerialConfig extends Config(
|
|||||||
new freechips.rocketchip.subsystem.WithNBigCores(2) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(2) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
// DOC include end: MulticlockAXIOverSerialConfig
|
// DOC include end: MulticlockAXIOverSerialConfig
|
||||||
|
|
||||||
|
class CustomIOChipTopRocketConfig extends Config(
|
||||||
|
new chipyard.example.WithCustomChipTop ++
|
||||||
|
new chipyard.example.WithCustomIOCells ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ class TutorialSha3BlackBoxConfig extends Config(
|
|||||||
|
|
||||||
// Tutorial Phase 5: Map a multicore heterogeneous SoC with multiple cores and memory-mapped accelerators
|
// Tutorial Phase 5: Map a multicore heterogeneous SoC with multiple cores and memory-mapped accelerators
|
||||||
class TutorialNoCConfig extends Config(
|
class TutorialNoCConfig extends Config(
|
||||||
|
new chipyard.iobinders.WithDontTouchIOBinders(false) ++
|
||||||
// Try changing the dimensions of the Mesh topology
|
// Try changing the dimensions of the Mesh topology
|
||||||
new constellation.soc.WithGlobalNoC(constellation.soc.GlobalNoCParams(
|
new constellation.soc.WithGlobalNoC(constellation.soc.GlobalNoCParams(
|
||||||
NoCParams(
|
NoCParams(
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package chipyard.example
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chipyard.iobinders._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.diplomacy.{InModuleBody}
|
||||||
|
import barstools.iocell.chisel._
|
||||||
|
import chipyard._
|
||||||
|
|
||||||
|
// A "custom" IOCell with additional I/O
|
||||||
|
// The IO don't do anything here in this example
|
||||||
|
class CustomDigitalInIOCellBundle extends DigitalInIOCellBundle {
|
||||||
|
val custom_out = Output(Bool())
|
||||||
|
val custom_in = Input(Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using a custom digital in iocell instead of the default one
|
||||||
|
class CustomDigitalInIOCell extends RawModule with DigitalInIOCell {
|
||||||
|
val io = IO(new CustomDigitalInIOCellBundle)
|
||||||
|
io.i := io.pad
|
||||||
|
io.custom_out := io.pad
|
||||||
|
}
|
||||||
|
|
||||||
|
case class CustomIOCellParams() extends IOCellTypeParams {
|
||||||
|
def analog() = Module(new GenericAnalogIOCell)
|
||||||
|
def gpio() = Module(new GenericDigitalGPIOCell)
|
||||||
|
def input() = Module(new CustomDigitalInIOCell)
|
||||||
|
def output() = Module(new GenericDigitalOutIOCell)
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomChipTop(implicit p: Parameters) extends ChipTop {
|
||||||
|
// making the module name ChipTop instead of CustomChipTop means
|
||||||
|
// we don't have to set the TOP make variable to CustomChipTop
|
||||||
|
override lazy val desiredName = "ChipTop"
|
||||||
|
|
||||||
|
// InModuleBody blocks are executed within the LazyModuleImp of this block
|
||||||
|
InModuleBody {
|
||||||
|
iocellMap.foreach { case (interface, cells) => {
|
||||||
|
cells.foreach { _ match {
|
||||||
|
case c: CustomDigitalInIOCell => {
|
||||||
|
c.io.custom_in := false.B
|
||||||
|
}
|
||||||
|
case c: GenericDigitalOutIOCell => {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
case c => {
|
||||||
|
require(false, "Unsupported iocell type ${c.getClass}")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
// demonstrate accessing the iocellMap directly
|
||||||
|
val serialTLIOCells = iocellMap("interface testchipip.CanHavePeripheryTLSerial")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WithCustomIOCells extends Config((site, here, up) => {
|
||||||
|
case IOCellKey => CustomIOCellParams()
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithCustomChipTop extends Config((site, here, up) => {
|
||||||
|
case BuildTop => (p: Parameters) => new CustomChipTop()(p)
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user