Split IOBinders into IOBinders and Harness Binders | punch out clocks to harness for simwidgets and bridges

This commit is contained in:
Jerry Zhao
2020-09-04 13:35:05 -07:00
parent 178a0e38b5
commit 0f50e4d118
19 changed files with 643 additions and 524 deletions

View File

@@ -211,7 +211,7 @@ lazy val midas = ProjectRef(firesimDir, "midas")
lazy val firesimLib = ProjectRef(firesimDir, "firesimLib")
lazy val firechip = conditionalDependsOn(project in file("generators/firechip"))
.dependsOn(chipyard, midasTargetUtils, midas, firesimLib % "test->test;compile->compile")
.dependsOn(chipyard, midasTargetUtils, midas, iocell, firesimLib % "test->test;compile->compile")
.settings(
commonSettings,
testGrouping in Test := isolateAllTests( (definedTests in Test).value ),

View File

@@ -9,7 +9,7 @@ import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGr
import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike}
import freechips.rocketchip.util.{ResetCatchAndSync}
import chipyard.iobinders.{IOBinders, TestHarnessFunction, IOBinderTuple}
import chipyard.iobinders._
import barstools.iocell.chisel._
@@ -26,11 +26,9 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters)
class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions {
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
val iocells = ArrayBuffer.empty[IOCell]
// A list of functions to call in the test harness
val harnessFunctions = ArrayBuffer.empty[TestHarnessFunction]
// The system module specified by BuildSystem
val lSystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
// The implicitClockSinkNode provides the implicit clock and reset for the System
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters()))
@@ -50,15 +48,13 @@ class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunc
// The implicit clock and reset for the system is also, by convention, used for all the IOBinders
// TODO: This may not be the right thing to do in all cases
withClockAndReset(implicit_clock, implicit_reset) {
val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem) ++ f(lSystem.module)).unzip3
// We ignore _ports for now...
iocells ++= _iocells.flatten
harnessFunctions ++= _harnessFunctions.flatten
}
val (_ports, _iocells, _portMap) = ApplyIOBinders(lazySystem, p(IOBinders))
// We ignore _ports for now...
iocells ++= _iocells
portMap ++= _portMap
// Connect the implicit clock/reset, if present
lSystem.module match { case l: LazyModuleImp => {
lazySystem.module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}

View File

@@ -91,7 +91,7 @@ object ClockingSchemeGenerators {
chiptop.implicitClockSinkNode := implicitClockSourceNode
// Drive the diplomaticclock graph of the DigitalTop (if present)
val simpleClockGroupSourceNode = chiptop.lSystem match {
val simpleClockGroupSourceNode = chiptop.lazySystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
@@ -120,6 +120,7 @@ object ClockingSchemeGenerators {
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
clock_io := th.harnessClock
Nil
@@ -137,7 +138,7 @@ object ClockingSchemeGenerators {
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
chiptop.implicitClockSinkNode := implicitClockSourceNode
val simpleClockGroupSourceNode = chiptop.lSystem match {
val simpleClockGroupSourceNode = chiptop.lazySystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n

View File

@@ -33,7 +33,6 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l)
with testchipip.CanHaveTraceIOModuleImp
with testchipip.CanHavePeripheryBlockDeviceModuleImp
with testchipip.CanHavePeripherySerialModuleImp
with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
with sifive.blocks.devices.gpio.HasPeripheryGPIOModuleImp
with sifive.blocks.devices.spi.HasPeripherySPIFlashModuleImp

View File

@@ -0,0 +1,274 @@
package chipyard.harness
import chisel3._
import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
import freechips.rocketchip.devices.debug._
import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.system.{SimAXIMem}
import freechips.rocketchip.subsystem._
import sifive.blocks.devices.gpio._
import sifive.blocks.devices.uart._
import sifive.blocks.devices.spi._
import barstools.iocell.chisel._
import testchipip._
import chipyard.HasHarnessSignalReferences
import tracegen.{TraceGenSystemModuleImp}
import icenet.{CanHavePeripheryIceNICModuleImp, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import scala.reflect.{ClassTag}
case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]](
Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => Nil)
)
object ApplyHarnessBinders {
def apply(th: HasHarnessSignalReferences, sys: LazyModule, map: Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]], portMap: Map[String, Seq[Data]]) = {
val pm = portMap.withDefaultValue(Nil)
map.map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) }
}
}
class OverrideHarnessBinder[T](fn: => (T, HasHarnessSignalReferences, Seq[Data]) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
t match {
case system: T => fn(system, th, ports)
case _ => Nil
}
})
)
})
class ComposeHarnessBinder[T](fn: => (T, HasHarnessSignalReferences, Seq[Data]) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
t match {
case system: T => up(HarnessBinders, site)(tag.runtimeClass.toString)(system, th, ports) ++ fn(system, th, ports)
case _ => Nil
}
})
)
})
class WithGPIOTiedOff extends OverrideHarnessBinder({
(system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map { case p: GPIOPortIO => p <> AnalogConst(0) }
Nil
}
})
class WithUARTAdapter extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
UARTAdapter.connect(ports.map(_.asInstanceOf[UARTPortIO]))(system.p)
Nil
}
})
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
(system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
SimSPIFlashModel.connect(ports.map(_.asInstanceOf[SPIChipIO]), th.harnessReset, rdOnly)(system.p)
Nil
}
})
class WithSimBlockDevice extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDeviceModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val clock = WireInit(false.B.asClock)
ports.map {
case p: BlockDeviceIO => SimBlockDevice.connect(clock, th.harnessReset.asBool, Some(p))(system.p)
case c: Clock => clock := c
}
Nil
}
})
class WithBlockDeviceModel extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDeviceModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val clock = WireInit(false.B.asClock)
ports.map {
case p: BlockDeviceIO => withClockAndReset(clock, th.harnessReset) { BlockDeviceModel.connect(Some(p))(system.p) }
case c: Clock => clock := c
}
Nil
}
})
class WithLoopbackNIC extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNICModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val clock = WireInit(false.B.asClock)
ports.map {
case p: NICIOvonly => withClockAndReset(clock, th.harnessReset) {
NicLoopback.connect(Some(p), system.p(NICKey))
}
case c: Clock => clock := c
}
Nil
}
})
class WithSimNetwork extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNICModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val clock = WireInit(false.B.asClock)
ports.map {
case p: NICIOvonly => SimNetwork.connect(Some(p), clock, th.harnessReset.asBool)
case c: Clock => clock := c
}
Nil
}
})
class WithSimAXIMem extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
val clock = WireInit(false.B.asClock)
ports.filter(_.isInstanceOf[Clock]).map { case p: Clock => clock := p }
val axi4_ports = ports.filter(_.isInstanceOf[AXI4Bundle])
(axi4_ports zip system.memAXI4Node.edges.in).map { case (port: AXI4Bundle, edge) =>
val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p))
withClockAndReset(clock, th.harnessReset) {
Module(mem.module).suggestName("mem")
}
mem.io_axi4.head <> port
}
Nil
}
})
class WithBlackBoxSimMem extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
val clock = WireInit(false.B.asClock)
ports.filter(_.isInstanceOf[Clock]).map { case p: Clock => clock := p }
val axi4_ports = ports.collect { case p: AXI4Bundle => p }
(axi4_ports zip system.memAXI4Node.edges.in).map { case (port: AXI4Bundle, edge) =>
val memSize = p(ExtMem).get.master.size
val lineSize = p(CacheBlockBytes)
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle)).suggestName("simdram")
mem.io.axi <> port
mem.io.clock := clock
mem.io.reset := th.harnessReset
}
Nil
}
})
class WithSimAXIMMIO extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
val clock = WireInit(false.B.asClock)
ports.filter(_.isInstanceOf[Clock]).map { case p: Clock => clock := p }
(ports zip system.mmioAXI4Node.edges.in).zipWithIndex.map { case ((port: AXI4Bundle, edge), i) =>
val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096)(p))
withClockAndReset(clock, th.harnessReset) {
Module(mmio_mem.module).suggestName(s"mmio_mem_${i}")
}
mmio_mem.io_axi4.head <> port
}
Nil
}
})
class WithTieOffInterrupts extends OverrideHarnessBinder({
(system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map { case p: UInt => p := 0.U }
Nil
}
})
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
(system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map { case p: AXI4Bundle =>
p := DontCare
p.tieoff()
}
Nil
}
})
class WithSimDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
if (!ports.isEmpty) {
val dtm_success = Wire(Bool())
when (dtm_success) { th.success := true.B }
ports.map {
case d: ClockedDMIIO =>
val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
case j: JTAGIO =>
val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success)
case _ =>
require(false, "We only support DMI or JTAG simulated debug connections")
}
}
Nil
}
})
class WithTiedOffDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map {
case d: ClockedDMIIO =>
d.dmi.req.valid := false.B
d.dmi.req.bits := DontCare
d.dmi.resp.ready := true.B
d.dmiClock := false.B.asClock
d.dmiReset := true.B
case j: JTAGIO =>
j.TCK := true.B.asClock
j.TMS := true.B
j.TDI := true.B
j.TRSTn.foreach { r => r := true.B }
case a: ClockedAPBBundle =>
a.tieoff()
a.clock := false.B.asClock
a.reset := true.B.asAsyncReset
a.psel := false.B
a.penable := false.B
case _ => require(false)
}
Nil
}
})
class WithTiedOffSerial extends OverrideHarnessBinder({
(system: CanHavePeripherySerial, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map { case p: SerialIO => SerialAdapter.tieoff(Some(p)) }
Nil
}
})
class WithSimSerial extends OverrideHarnessBinder({
(system: CanHavePeripherySerial, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val serial_clock = WireInit(false.B.asClock)
ports.map {
case p: SerialIO =>
val ser_success = SerialAdapter.connectSimSerial(p, serial_clock, th.harnessReset)
when (ser_success) { th.success := true.B }
case c: Clock =>
serial_clock := c
}
Nil
}
})
class WithTraceGenSuccess extends OverrideHarnessBinder({
(system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map { case p: Bool => when (p) { th.success := true.B } }
Nil
}
})
class WithSimDromajoBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map { case p: TraceOutputTop => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
Nil
}
})

View File

@@ -1,9 +1,8 @@
package chipyard
package object iobinders {
package chipyard.iobinders
import chisel3._
import chisel3.util.experimental.{BoringUtils}
import chisel3.experimental.{Analog, IO}
import chisel3.experimental.{Analog, IO, DataMirror}
import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
@@ -23,7 +22,9 @@ import tracegen.{TraceGenSystemModuleImp}
import barstools.iocell.chisel._
import testchipip._
import icenet.{CanHavePeripheryIceNICModuleImp, SimNetwork, NicLoopback, NICKey}
import icenet.{CanHavePeripheryIceNICModuleImp, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import chipyard.GlobalResetSchemeKey
import scala.reflect.{ClassTag}
@@ -43,17 +44,22 @@ import scala.reflect.{ClassTag}
// DOC include start: IOBinders
// This type describes a function callable on the TestHarness instance. Its return type is unused.
type TestHarnessFunction = (chipyard.HasHarnessSignalReferences) => Seq[Any]
// IOBinders will return a Seq of this tuple, which contains three fields:
// 1. A Seq containing all IO ports created by the IOBinder function
// 2. A Seq containing all IO cell modules created by the IOBinder function
// 3. An optional function to call inside the test harness (e.g. to connect the IOs)
type IOBinderTuple = (Seq[Data], Seq[IOCell], Option[TestHarnessFunction])
case object IOBinders extends Field[Map[String, (Any) => Seq[IOBinderTuple]]](
Map[String, (Any) => Seq[IOBinderTuple]]().withDefaultValue((Any) => Nil)
case object IOBinders extends Field[Map[String, (Any) => (Seq[Data], Seq[IOCell])]](
Map[String, (Any) => (Seq[Data], Seq[IOCell])]().withDefaultValue((Any) => (Nil, Nil))
)
object ApplyIOBinders {
def apply(sys: LazyModule, map: Map[String, (Any) => (Seq[Data], Seq[IOCell])]):
(Iterable[Data], Iterable[IOCell], Map[String, Seq[Data]]) = {
val r = map.map({ case (s,f) => (f(sys), s) }) ++ map.map({ case (s,f) => (f(sys.module), s) })
(r.flatMap(_._1._1), r.flatMap(_._1._2), r.map { t => t._2 -> t._1._1 })
}
}
// Note: The parameters instance is accessible only through LazyModule
// or LazyModuleImpLike. The self-type requirement in traits like
// CanHaveMasterAXI4MemPort is insufficient to make it accessible to the IOBinder
@@ -71,12 +77,12 @@ object GetSystemParameters {
// This macro overrides previous matches on some Top mixin. This is useful for
// binders which drive IO, since those typically cannot be composed
class OverrideIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
class OverrideIOBinder[T](fn: => (T) => (Seq[Data], Seq[IOCell]))(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
((t: Any) => {
t match {
case system: T => fn(system)
case _ => Nil
case _ => (Nil, Nil)
}
})
)
@@ -84,32 +90,44 @@ class OverrideIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassT
// This macro composes with previous matches on some Top mixin. This is useful for
// annotation-like binders, since those can typically be composed
class ComposeIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
class ComposeIOBinder[T](fn: => (T) => (Seq[Data], Seq[IOCell]))(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
((t: Any) => {
t match {
case system: T => (up(IOBinders, site)(tag.runtimeClass.toString)(system)
++ fn(system))
case _ => Nil
case system: T =>
val r = up(IOBinders, site)(tag.runtimeClass.toString)(system)
val h = fn(system)
(r._1 ++ h._1, r._2 ++ h._2)
case _ => (Nil, Nil)
}
})
)
})
object BoreHelper {
def apply(name: String, source: Clock): Clock = {
val clock_io = IO(Output(Clock())).suggestName(name)
val clock_wire = Wire(Clock()).suggestName(s"chiptop_${name}")
dontTouch(clock_wire)
clock_wire := false.B.asClock // necessary for BoringUtils to work properly
BoringUtils.bore(source, Seq(clock_wire))
clock_io := clock_wire
clock_io
}
}
// DOC include end: IOBinders
object AddIOCells {
/**
* Add IO cells to a SiFive GPIO devices and name the IO ports.
* @param gpios A Seq of GPIO port bundles
* @param genFn A callable function to generate a DigitalGPIOCell module to use
* @return Returns a tuple of (a 2D Seq of Analog IOs corresponding to individual GPIO pins; a 2D Seq of IOCell module references)
*/
def gpio(gpios: Seq[GPIOPortIO], genFn: () => DigitalGPIOCell = IOCell.genericGPIO): (Seq[Seq[Analog]], Seq[Seq[IOCell]]) = {
gpios.zipWithIndex.map({ case (gpio, i) =>
case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams())
class WithGPIOCells extends OverrideIOBinder({
(system: HasPeripheryGPIOModuleImp) => {
val (ports2d, cells2d) = system.gpio.zipWithIndex.map({ case (gpio, i) =>
gpio.pins.zipWithIndex.map({ case (pin, j) =>
val g = IO(Analog(1.W)).suggestName(s"gpio_${i}_${j}")
val iocell = genFn().suggestName(s"iocell_gpio_${i}_${j}")
val iocell = system.p(IOCellKey).gpio().suggestName(s"iocell_gpio_${i}_${j}")
iocell.io.o := pin.o.oval
iocell.io.oe := pin.o.oe
iocell.io.ie := pin.o.ie
@@ -118,40 +136,35 @@ object AddIOCells {
(g, iocell)
}).unzip
}).unzip
(ports2d.flatten, cells2d.flatten)
}
})
/**
* Add IO cells to a SiFive UART devices and name the IO ports.
* @param uartPins A Seq of UART port bundles
* @return Returns a tuple of (A Seq of top-level UARTPortIO IOs; a 2D Seq of IOCell module references)
*/
def uart(uartPins: Seq[UARTPortIO]): (Seq[UARTPortIO], Seq[Seq[IOCell]]) = {
uartPins.zipWithIndex.map({ case (u, i) =>
val (port, ios) = IOCell.generateIOFromSignal(u, Some(s"iocell_uart_${i}"))
class WithUARTIOCells extends OverrideIOBinder({
(system: HasPeripheryUARTModuleImp) => {
val (ports, cells2d) = system.uart.zipWithIndex.map({ case (u, i) =>
val (port, ios) = IOCell.generateIOFromSignal(u, Some(s"iocell_uart_${i}"), system.p(IOCellKey))
port.suggestName(s"uart_${i}")
(port, ios)
}).unzip
(ports, cells2d.flatten)
}
})
/**
* Add IO cells to a SiFive SPI devices and name the IO ports.
* @param spiPins A Seq of SPI port bundles
* @param basename The base name for this port (defaults to "spi")
* @param genFn A callable function to generate a DigitalGPIOCell module to use
* @return Returns a tuple of (A Seq of top-level SPIChipIO IOs; a 2D Seq of IOCell module references)
*/
def spi(spiPins: Seq[SPIPortIO], basename: String = "spi", genFn: () => DigitalGPIOCell = IOCell.genericGPIO): (Seq[SPIChipIO], Seq[Seq[IOCell]]) = {
spiPins.zipWithIndex.map({ case (s, i) =>
val port = IO(new SPIChipIO(s.c.csWidth)).suggestName(s"${basename}_${i}")
val iocellBase = s"iocell_${basename}_${i}"
class WithSPIIOCells extends OverrideIOBinder({
(system: HasPeripherySPIFlashModuleImp) => {
val (ports, cells2d) = system.qspi.zipWithIndex.map({ case (s, i) =>
val port = IO(new SPIChipIO(s.c.csWidth)).suggestName(s"spi_${i}")
val iocellBase = s"iocell_spi_${i}"
// SCK and CS are unidirectional outputs
val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck"))
val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs"))
val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck"), system.p(IOCellKey))
val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs"), system.p(IOCellKey))
// DQ are bidirectional, so then need special treatment
val dqIOs = s.dq.zip(port.dq).zipWithIndex.map { case ((pin, ana), j) =>
val iocell = genFn().suggestName(s"${iocellBase}_dq_${j}")
val iocell = system.p(IOCellKey).gpio().suggestName(s"${iocellBase}_dq_${j}")
iocell.io.o := pin.o
iocell.io.oe := pin.oe
iocell.io.ie := true.B
@@ -162,17 +175,27 @@ object AddIOCells {
(port, dqIOs ++ csIOs ++ sckIOs)
}).unzip
(ports, cells2d.flatten)
}
})
/**
* Add IO cells to a debug module and name the IO ports, for debug IO which must go off-chip
* For on-chip debug IO, drive them appropriately
* Mostly copied from rocket-chip/src/main/scala/devices/debug/Periphery.scala
* @param system A BaseSubsystem that might have a debug module
* @return Returns a tuple2 of (Generated debug io ports, Generated IOCells)
*/
def debug(system: HasPeripheryDebugModuleImp)(implicit p: Parameters): (Seq[Bundle], Seq[IOCell]) = {
system.debug.map { debug =>
class WithExtInterruptIOCells extends OverrideIOBinder({
(system: HasExtInterruptsModuleImp) => {
if (system.outer.nExtInterrupts > 0) {
val (port, cells) = IOCell.generateIOFromSignal(system.interrupts, Some("iocell_interrupts"), system.p(IOCellKey))
port.suggestName("ext_interrupts")
(Seq(port), cells)
} else {
(Nil, Nil)
}
}
})
class WithDebugIOCells extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
system.debug.map({ debug =>
val p = system.p
val tlbus = system.outer.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
val debug_clock = Wire(Clock()).suggestName("debug_clock")
val debug_reset = Wire(Reset()).suggestName("debug_reset")
@@ -204,288 +227,130 @@ object AddIOCells {
// Add IOCells for the DMI/JTAG/APB ports
val dmiTuple = debug.clockeddmi.map { d =>
IOCell.generateIOFromSignal(d, Some("iocell_dmi"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
IOCell.generateIOFromSignal(d, Some("iocell_dmi"), p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
dmiTuple.map(_._1).foreach(_.suggestName("dmi"))
val jtagTuple = debug.systemjtag.map { j =>
IOCell.generateIOFromSignal(j.jtag, Some("iocell_jtag"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
IOCell.generateIOFromSignal(j.jtag, Some("iocell_jtag"), p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
jtagTuple.map(_._1).foreach(_.suggestName("jtag"))
val apbTuple = debug.apb.map { a =>
IOCell.generateIOFromSignal(a, Some("iocell_apb"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
IOCell.generateIOFromSignal(a, Some("iocell_apb"), p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
apbTuple.map(_._1).foreach(_.suggestName("apb"))
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
}.getOrElse((Nil, Nil))
}).getOrElse((Nil, Nil))
}
})
/**
* Add IO cells to a serial module and name the IO ports.
* @param serial A SerialIO bundle
* @return Returns a tuple of (Top-level SerialIO IO; a list of IOCell module references)
*/
def serial(serial: SerialIO): (SerialIO, Seq[IOCell]) = {
val (port, ios) = IOCell.generateIOFromSignal(serial, Some("iocell_serial"))
class WithSerialIOCells extends OverrideIOBinder({
(system: CanHavePeripherySerial) => system.serial.map({ s =>
val sys = system.asInstanceOf[BaseSubsystem]
val (port, cells) = IOCell.generateIOFromSignal(s, Some("iocell_serial"), sys.p(IOCellKey))
val serial_clock = Wire(Output(Clock())).suggestName("chiptop_serial_clock")
serial_clock := false.B.asClock // necessary for BoringUtils to work properly
dontTouch(serial_clock)
BoringUtils.bore(sys.fbus.module.clock, Seq(serial_clock))
val (serial_clock_io, serial_clock_cell) = IOCell.generateIOFromSignal(serial_clock, Some("serial_clock"), sys.p(IOCellKey))
serial_clock_io.suggestName("serial_clock")
port.suggestName("serial")
(port, ios)
}
def axi4(io: Seq[AXI4Bundle], node: AXI4SlaveNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = {
io.zip(node.edges.in).zipWithIndex.map{ case ((mem_axi4, edge), i) => {
val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_slave_${i}"))
port.suggestName(s"${name}_axi4_slave_${i}")
(port, edge, ios)
}}
}
def axi4(io: Seq[AXI4Bundle], node: AXI4MasterNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = {
io.zip(node.edges.out).zipWithIndex.map{ case ((mem_axi4, edge), i) => {
//val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_master_${i}"))
val port = IO(Flipped(AXI4Bundle(edge.bundle)))
val ios = IOCell.generateFromSignal(mem_axi4, port, Some(s"iocell_${name}_axi4_master_${i}"))
port.suggestName(s"${name}_axi4_master_${i}")
(port, edge, ios)
}}
}
def blockDev(bdev: BlockDeviceIO): (BlockDeviceIO, Seq[IOCell]) = {
val (port, ios) = IOCell.generateIOFromSignal(bdev, Some("iocell_bdev"))
port.suggestName("bdev")
(port, ios)
}
}
// DOC include start: WithGPIOTiedOff
class WithGPIOTiedOff extends OverrideIOBinder({
(system: HasPeripheryGPIOModuleImp) => {
val (ports2d, ioCells2d) = AddIOCells.gpio(system.gpio)
val harnessFn = (th: HasHarnessSignalReferences) => { ports2d.flatten.foreach(_ <> AnalogConst(0)); Nil }
Seq((ports2d.flatten, ioCells2d.flatten, Some(harnessFn)))
}
})
// DOC include end: WithGPIOTiedOff
class WithUARTAdapter extends OverrideIOBinder({
(system: HasPeripheryUARTModuleImp) => {
val (ports, ioCells2d) = AddIOCells.uart(system.uart)
val harnessFn = (th: HasHarnessSignalReferences) => { UARTAdapter.connect(ports)(system.p); Nil }
Seq((ports, ioCells2d.flatten, Some(harnessFn)))
}
(Seq(port, serial_clock_io), cells ++ serial_clock_cell)
}).getOrElse((Nil, Nil))
})
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({
(system: HasPeripherySPIFlashModuleImp) => {
val (ports, ioCells2d) = AddIOCells.spi(system.qspi, "qspi")
val harnessFn = (th: HasHarnessSignalReferences) => { SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p); Nil }
Seq((ports, ioCells2d.flatten, Some(harnessFn)))
}
})
class WithSimBlockDevice extends OverrideIOBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev =>
val (port, ios) = AddIOCells.blockDev(bdev)
val harnessFn = (th: HasHarnessSignalReferences) => {
// TODO: Using harness clock/reset will be incorrect when systemClock =/= harnessClock
SimBlockDevice.connect(th.harnessClock, th.harnessReset.asBool, Some(port))(system.p)
Nil
}
Seq((Seq(port), ios, Some(harnessFn)))
}.getOrElse(Nil)
})
class WithBlockDeviceModel extends OverrideIOBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev =>
val (port, ios) = AddIOCells.blockDev(bdev)
val harnessFn = (th: HasHarnessSignalReferences) => {
BlockDeviceModel.connect(Some(port))(system.p)
Nil
}
Seq((Seq(port), ios, Some(harnessFn)))
}.getOrElse(Nil)
})
class WithLoopbackNIC extends OverrideIOBinder({
(system: CanHavePeripheryIceNICModuleImp) => system.connectNicLoopback(); Nil
})
class WithSimNIC extends OverrideIOBinder({
(system: CanHavePeripheryIceNICModuleImp) => system.connectSimNetwork(system.clock, system.reset.asBool); Nil
})
// DOC include start: WithSimAXIMem
class WithSimAXIMem extends OverrideIOBinder({
class WithAXI4MemPunchthrough extends OverrideIOBinder({
(system: CanHaveMasterAXI4MemPort) => {
implicit val p: Parameters = GetSystemParameters(system)
val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem")
// TODO: we are inlining the connectMem method of SimAXIMem because
// it takes in a dut rather than seq of axi4 ports
val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.map { case (port, edge, ios) =>
val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size))
Module(mem.module).suggestName("mem")
mem.io_axi4.head <> port
}
Nil
val clock = if (!system.mem_axi4.isEmpty) {
Some(BoreHelper("axi4_mem_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock))
} else {
None
}
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
}
})
// DOC include end: WithSimAXIMem
class WithBlackBoxSimMem extends OverrideIOBinder({
(system: CanHaveMasterAXI4MemPort) => {
implicit val p: Parameters = GetSystemParameters(system)
val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem")
val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.map { case (port, edge, ios) =>
val memSize = p(ExtMem).get.master.size
val lineSize = p(CacheBlockBytes)
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle))
mem.io.axi <> port
// TODO: Using harness clock/reset will be incorrect when systemClock =/= harnessClock
mem.io.clock := th.harnessClock
mem.io.reset := th.harnessReset
}
Nil
}
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
val ports = system.mem_axi4.map({ m =>
val p = IO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)).suggestName("axi4_mem")
p <> m
p
})
(ports ++ clock, Nil)
}
})
class WithSimAXIMMIO extends OverrideIOBinder({
class WithAXI4MMIOPunchthrough extends OverrideIOBinder({
(system: CanHaveMasterAXI4MMIOPort) => {
implicit val p: Parameters = GetSystemParameters(system)
val peiTuples = AddIOCells.axi4(system.mmio_axi4, system.mmioAXI4Node, "mmio_mem")
val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.zipWithIndex.map { case ((port, edge, ios), i) =>
val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096))
Module(mmio_mem.module).suggestName(s"mmio_mem_${i}")
mmio_mem.io_axi4.head <> port
}
Nil
val clock = if (!system.mmio_axi4.isEmpty) {
Some(BoreHelper("axi4_mmio_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock))
} else {
None
}
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
val ports = system.mmio_axi4.map({ m =>
val p = IO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)).suggestName("axi4_mmio")
p <> m
p
})
(ports ++ clock, Nil)
}
})
class WithL2FBusAXI4Punchthrough extends OverrideIOBinder({
(system: CanHaveSlaveAXI4Port) => {
val port = system.l2_frontend_bus_axi4.map { m =>
val p = IO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)).suggestName("axi4_fbus")
p <> m
p
}
(port, Nil)
}
})
class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => {
val ports = system.bdev.map({ bdev =>
val p = IO(new BlockDeviceIO()(system.p)).suggestName("blockdev")
val clock = BoreHelper("blkdev_clk", system.outer.controller.get.module.clock)
p <> bdev
Seq(p, clock)
}).getOrElse(Nil)
(ports, Nil)
}
})
class WithNICIOPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryIceNICModuleImp) => {
val port = system.net.map({ n =>
val p = IO(new NICIOvonly).suggestName("nic")
val clock = BoreHelper("nic_clk", system.outer.icenicOpt.get.module.clock)
p <> n
Seq(p, clock)
}).getOrElse(Nil)
(port.toSeq, Nil)
}
})
class WithTraceGenSuccessPunchthrough extends OverrideIOBinder({
(system: TraceGenSystemModuleImp) => {
val success = IO(Output(Bool())).suggestName("success")
success := system.success
(Seq(success), Nil)
}
})
class WithTraceIOPunchthrough extends OverrideIOBinder({
(system: CanHaveTraceIOModuleImp) => {
val ports = system.traceIO.map { t =>
val trace = IO(DataMirror.internal.chiselTypeClone[TraceOutputTop](t)).suggestName("trace")
trace <> t
trace
}
(ports.toSeq, Nil)
}
})
class WithDontTouchPorts extends OverrideIOBinder({
(system: DontTouch) => system.dontTouchPorts(); Nil
(system: DontTouch) => system.dontTouchPorts(); (Nil, Nil)
})
class WithTieOffInterrupts extends OverrideIOBinder({
(system: HasExtInterruptsModuleImp) => {
val (port, ioCells) = IOCell.generateIOFromSignal(system.interrupts, Some("iocell_interrupts"))
port.suggestName("interrupts")
val harnessFn = (th: HasHarnessSignalReferences) => { port := 0.U; Nil }
Seq((Seq(port), ioCells, Some(harnessFn)))
}
})
class WithTieOffL2FBusAXI extends OverrideIOBinder({
(system: CanHaveSlaveAXI4Port) => {
val peiTuples = AddIOCells.axi4(system.l2_frontend_bus_axi4, system.l2FrontendAXI4Node, "l2_fbus")
val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.zipWithIndex.map { case ((port, edge, ios), i) =>
port := DontCare // tieoff doesn't completely tie-off, for some reason
port.tieoff()
}
Nil
}
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
}
})
class WithSimDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
val (ports, iocells) = AddIOCells.debug(system)(system.p)
val harnessFn = (th: HasHarnessSignalReferences) => {
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
ports.map {
case d: ClockedDMIIO =>
val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
case j: JTAGIO =>
val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success)
case _ =>
require(false, "We only support DMI or JTAG simulated debug connections")
}
Nil
}
Seq((ports, iocells, Some(harnessFn)))
}
})
class WithTiedOffDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
val (ports, iocells) = AddIOCells.debug(system)(system.p)
val harnessFn = (th: HasHarnessSignalReferences) => {
ports.map {
case d: ClockedDMIIO =>
d.dmi.req.valid := false.B
d.dmi.req.bits := DontCare
d.dmi.resp.ready := true.B
d.dmiClock := false.B.asClock
d.dmiReset := true.B
case j: JTAGIO =>
j.TCK := true.B.asClock
j.TMS := true.B
j.TDI := true.B
j.TRSTn.foreach { r => r := true.B }
case a: ClockedAPBBundle =>
a.tieoff()
a.clock := false.B.asClock
a.reset := true.B.asAsyncReset
a.psel := false.B
a.penable := false.B
case _ => require(false)
}
Nil
}
Seq((ports, iocells, Some(harnessFn)))
}
})
class WithTiedOffSerial extends OverrideIOBinder({
(system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial =>
val (port, ioCells) = AddIOCells.serial(serial)
val harnessFn = (th: HasHarnessSignalReferences) => {
SerialAdapter.tieoff(port)
Nil
}
Seq((Seq(port), ioCells, Some(harnessFn)))
}).getOrElse(Nil)
})
class WithSimSerial extends OverrideIOBinder({
(system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial =>
val (port, ioCells) = AddIOCells.serial(serial)
val harnessFn = (th: HasHarnessSignalReferences) => {
val ser_success = SerialAdapter.connectSimSerial(port, th.harnessClock, th.harnessReset)
when (ser_success) { th.success := true.B }
Nil
}
Seq((Seq(port), ioCells, Some(harnessFn)))
}).getOrElse(Nil)
})
class WithTraceGenSuccessBinder extends OverrideIOBinder({
(system: TraceGenSystemModuleImp) => {
val (successPort, ioCells) = IOCell.generateIOFromSignal(system.success, Some("iocell_success"))
successPort.suggestName("success")
val harnessFn = (th: HasHarnessSignalReferences) => { when (successPort) { th.success := true.B }; Nil }
Seq((Seq(successPort), ioCells, Some(harnessFn)))
}
})
class WithSimDromajoBridge extends ComposeIOBinder({
(system: CanHaveTraceIOModuleImp) => {
system.traceIO match { case Some(t) => t.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
Nil
}
})
} /* end package object */

View File

@@ -1,19 +1,22 @@
package chipyard
import chisel3._
import scala.collection.mutable.{ArrayBuffer}
import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.config.{Field, Parameters}
import chipyard.iobinders.{TestHarnessFunction}
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
// -------------------------------
// Chipyard Test Harness
// -------------------------------
case object BuildTop extends Field[Parameters => LazyModule with HasTestHarnessFunctions]((p: Parameters) => new ChipTop()(p))
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
trait HasTestHarnessFunctions {
val harnessFunctions: Seq[TestHarnessFunction]
val lazySystem: LazyModule
val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]]
val portMap = scala.collection.mutable.Map[String, Seq[Data]]()
}
trait HasHarnessSignalReferences {
@@ -39,7 +42,9 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign
// dutReset assignment can be overridden via a harnessFunction, but by default it is just reset
val dutReset = WireDefault(if (p(GlobalResetSchemeKey).pinIsAsync) reset.asAsyncReset else reset)
ldut.harnessFunctions.foreach(_(this))
ldut match { case d: HasTestHarnessFunctions =>
d.harnessFunctions.foreach(_(this))
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
}
}

View File

@@ -5,14 +5,40 @@ import freechips.rocketchip.config.{Config}
// --------------
// Chipyard abstract ("base") configuration
// NOTE: This configuration is NOT INSTANTIABLE, as it defines a empty system with no tiles
//
// The default set of IOBinders instantiate IOcells and ChipTop IOs for digital IO bundles.
// The default set of HarnessBinders instantiate TestHarness hardware for interacting with ChipTop IOs
// --------------
class AbstractConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter
new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts
new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a blackbox DRAMSim model
new chipyard.iobinders.WithSimDebug ++ // attach SimJTAG
new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing
// The HarnessBinders control generation of hardware in the TestHarness
new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present
new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled
new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
new chipyard.harness.WithSimSerial ++ // add SimSerial adapter for HTIF, if serial port is present
new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present
new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled
new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled
new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present
new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present
// The IOBinders instantiate ChipTop IOs to match desired digital IOs
// IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithAXI4MMIOPunchthrough ++
new chipyard.iobinders.WithL2FBusAXI4Punchthrough ++
new chipyard.iobinders.WithBlockDeviceIOPunchthrough ++
new chipyard.iobinders.WithNICIOPunchthrough ++
new chipyard.iobinders.WithSerialIOCells ++
new chipyard.iobinders.WithDebugIOCells ++
new chipyard.iobinders.WithUARTIOCells ++
new chipyard.iobinders.WithGPIOCells ++
new chipyard.iobinders.WithUARTIOCells ++
new chipyard.iobinders.WithSPIIOCells ++
new chipyard.iobinders.WithTraceIOPunchthrough ++
new chipyard.iobinders.WithExtInterruptIOCells ++
new testchipip.WithTSI ++ // use testchipip serial offchip link
new chipyard.config.WithBootROM ++ // use default bootrom
new chipyard.config.WithUART ++ // add a UART

View File

@@ -13,7 +13,7 @@ class ArianeConfig extends Config(
new chipyard.config.AbstractConfig)
class dmiArianeConfig extends Config(
new chipyard.iobinders.WithTiedOffSerial ++ // Tie off the serial port, override default instantiation of SimSerial
new chipyard.harness.WithTiedOffSerial ++ // Tie off the serial port, override default instantiation of SimSerial
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new ariane.WithNArianeCores(1) ++ // single Ariane core
new chipyard.config.AbstractConfig)

View File

@@ -33,13 +33,13 @@ class HwachaLargeBoomConfig extends Config(
new chipyard.config.AbstractConfig)
class LoopbackNICLargeBoomConfig extends Config(
new chipyard.iobinders.WithLoopbackNIC ++ // drive NIC IOs with loopback
new chipyard.harness.WithLoopbackNIC ++ // drive NIC IOs with loopback
new icenet.WithIceNIC ++ // build a NIC
new boom.common.WithNLargeBooms(1) ++
new chipyard.config.AbstractConfig)
class DromajoBoomConfig extends Config(
new chipyard.iobinders.WithSimDromajoBridge ++ // attach Dromajo
new chipyard.harness.WithSimDromajoBridge ++ // attach Dromajo
new chipyard.config.WithTraceIO ++ // enable the traceio
new boom.common.WithNSmallBooms(1) ++
new chipyard.config.AbstractConfig)

View File

@@ -25,7 +25,7 @@ class GemminiRocketConfig extends Config(
// DOC include start: DmiRocket
class dmiRocketConfig extends Config(
new chipyard.iobinders.WithTiedOffSerial ++ // don't use serial to drive the chip, since we use DMI instead
new chipyard.harness.WithTiedOffSerial ++ // don't use serial to drive the chip, since we use DMI instead
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
@@ -46,37 +46,36 @@ class GCDAXI4BlackBoxRocketConfig extends Config(
// DOC include end: GCDAXI4BlackBoxRocketConfig
class LargeSPIFlashROMRocketConfig extends Config(
new chipyard.iobinders.WithSimSPIFlashModel(true) ++ // add the SPI flash model in the harness (read-only)
new chipyard.harness.WithSimSPIFlashModel(true) ++ // add the SPI flash model in the harness (read-only)
new chipyard.config.WithSPIFlash ++ // add the SPI flash controller
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class SmallSPIFlashRocketConfig extends Config(
new chipyard.iobinders.WithSimSPIFlashModel(false) ++ // add the SPI flash model in the harness (writeable)
new chipyard.harness.WithSimSPIFlashModel(false) ++ // add the SPI flash model in the harness (writeable)
new chipyard.config.WithSPIFlash(0x100000) ++ // add the SPI flash controller (1 MiB)
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class SimAXIRocketConfig extends Config(
new chipyard.iobinders.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory, instead of default SimDRAM
new chipyard.harness.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory, instead of default SimDRAM
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class SimBlockDeviceRocketConfig extends Config(
new chipyard.iobinders.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice
new chipyard.harness.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice
new testchipip.WithBlockDevice ++ // add block-device module to peripherybus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class BlockDeviceModelRocketConfig extends Config(
new chipyard.iobinders.WithBlockDeviceModel ++ // drive block-device IOs with a BlockDeviceModel
new chipyard.harness.WithBlockDeviceModel ++ // drive block-device IOs with a BlockDeviceModel
new testchipip.WithBlockDevice ++ // add block-device module to periphery bus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include start: GPIORocketConfig
class GPIORocketConfig extends Config(
new chipyard.iobinders.WithGPIOTiedOff ++ // tie off GPIO inputs into the top
new chipyard.config.WithGPIO ++ // add GPIOs to the peripherybus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
@@ -111,7 +110,7 @@ class InitZeroRocketConfig extends Config(
// DOC include end: InitZeroRocketConfig
class LoopbackNICRocketConfig extends Config(
new chipyard.iobinders.WithLoopbackNIC ++ // drive NIC IOs with loopback
new chipyard.harness.WithLoopbackNIC ++ // drive NIC IOs with loopback
new icenet.WithIceNIC ++ // add an IceNIC
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
@@ -170,8 +169,6 @@ class LargeNVDLARocketConfig extends Config(
new chipyard.config.AbstractConfig)
class MMIORocketConfig extends Config(
new chipyard.iobinders.WithTieOffL2FBusAXI ++ // Tie-off the incoming MMIO port
new chipyard.iobinders.WithSimAXIMMIO ++ // Attach a simulated memory to the outwards MMIO port
new freechips.rocketchip.subsystem.WithDefaultMMIOPort ++ // add default external master port
new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++

View File

@@ -4,8 +4,10 @@ import freechips.rocketchip.config.{Config}
import freechips.rocketchip.rocket.{DCacheParams}
class TraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.harness.WithTraceGenSuccess ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++
@@ -13,8 +15,10 @@ class TraceGenConfig extends Config(
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class NonBlockingTraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.harness.WithTraceGenSuccess ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++
@@ -22,8 +26,10 @@ class NonBlockingTraceGenConfig extends Config(
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class BoomTraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.harness.WithTraceGenSuccess ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithBoomTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 8, nSets = 16, nWays = 2) }) ++
@@ -32,8 +38,10 @@ class BoomTraceGenConfig extends Config(
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class NonBlockingTraceGenL2Config extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.harness.WithTraceGenSuccess ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++
@@ -42,8 +50,10 @@ class NonBlockingTraceGenL2Config extends Config(
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class NonBlockingTraceGenL2RingConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.harness.WithTraceGenSuccess ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++

View File

@@ -12,27 +12,16 @@ import freechips.rocketchip.config.{Config}
// This file was originally developed for the cancelled ASPLOS-2020
// Chipyard tutorial. While the configs here work, the corresponding
// slideware has not yet been created
// slideware has not yet been created.
// NOTE: Configs should be read bottom-up, since they are applied bottom-up
// NOTE: The TutorialConfigs build off of the AbstractConfig defined in AbstractConfig.scala
// Users should try to understand the functionality of the AbstractConfig before proceeding
// with the TutorialConfigs below
// Tutorial Phase 1: Configure the cores, caches
class TutorialStarterConfig extends Config(
// IOBinders specify how to connect to IOs in our TestHarness
// These config fragments do not affect
new chipyard.iobinders.WithUARTAdapter ++ // Connect a SimUART adapter to display UART on stdout
new chipyard.iobinders.WithBlackBoxSimMem ++ // Connect simulated external memory
new chipyard.iobinders.WithTieOffInterrupts ++ // Do not simulate external interrupts
new chipyard.iobinders.WithSimDebug ++ // Connect SimJTAG (or SimDTM) widgets to debug ios
new chipyard.iobinders.WithSimSerial ++ // Connect external SimSerial widget to drive TSI
// Config fragments below this line affect hardware generation
// of the Top
new testchipip.WithTSI ++ // Add a TSI (Test Serial Interface) widget to bring-up the core
new chipyard.config.WithBootROM ++ // Use the Chipyard BootROM
new chipyard.config.WithUART ++ // Add a UART
new chipyard.config.WithNoSubsystemDrivenClocks ++ // Don't drive the subsystem clocks from within the subsystem
// CUSTOMIZE THE CORE
// Uncomment out one (or multiple) of the lines below, and choose
// how many cores you want.
@@ -43,36 +32,11 @@ class TutorialStarterConfig extends Config(
// Uncomment this line, and specify a size if you want to have a L2
// new freechips.rocketchip.subsystem.WithInclusiveCache(nBanks=1, nWays=4, capacityKB=128) ++
// Set the debug module to expose an external JTAG port
new freechips.rocketchip.subsystem.WithJtagDTM ++
// For simpler designs, we want to minimize IOs on
// our Top. These config fragments remove unnecessary
// ports
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
// Use the standard hierarchical bus topology including mbus+l2
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
// BaseConfig configures "bare" rocketchip system
new freechips.rocketchip.system.BaseConfig
new chipyard.config.AbstractConfig
)
// Tutorial Phase 2: Integrate a TileLink or AXI4 MMIO device
class TutorialMMIOConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithSimDebug ++
new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Attach either a TileLink or AXI4 version of GCD
// Uncomment one of the below lines
@@ -81,66 +45,26 @@ class TutorialMMIOConfig extends Config(
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithJtagDTM ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.system.BaseConfig
new chipyard.config.AbstractConfig
)
// Tutorial Phase 3: Integrate a SHA3 RoCC accelerator
// // Tutorial Phase 3: Integrate a SHA3 RoCC accelerator
class TutorialSha3Config extends Config(
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithSimDebug ++
new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Uncomment this line once you added SHA3 to the build.sbt, and cloned the SHA3 repo
// new sha3.WithSha3Accel ++
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithJtagDTM ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.system.BaseConfig
new chipyard.config.AbstractConfig
)
// Tutorial Phase 4: Integrate a Black-box verilog version of the SHA3 RoCC accelerator
class TutorialSha3BlackBoxConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithSimDebug ++
new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Uncomment these lines once SHA3 is integrated
// new sha3.WithSha3BlackBox ++ // Specify we want the Black-box verilog version of Sha3 Ctrl
// new sha3.WithSha3Accel ++
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithJtagDTM ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.system.BaseConfig
new chipyard.config.AbstractConfig
)

View File

@@ -8,13 +8,13 @@ import chisel3.experimental.annotate
import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebugModuleImp}
import freechips.rocketchip.amba.axi4.{AXI4Bundle}
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPort, HasExtInterruptsModuleImp, BaseSubsystem, HasTilesModuleImp}
import freechips.rocketchip.tile.{RocketTile}
import sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp}
import sifive.blocks.devices.uart._
import testchipip.{CanHavePeripherySerialModuleImp, CanHavePeripheryBlockDeviceModuleImp}
import icenet.CanHavePeripheryIceNICModuleImp
import testchipip._
import icenet.{CanHavePeripheryIceNICModuleImp, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import junctions.{NastiKey, NastiParameters}
import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig}
@@ -25,73 +25,116 @@ import tracegen.{TraceGenSystemModuleImp}
import ariane.ArianeTile
import boom.common.{BoomTile}
import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters}
import testchipip.{CanHaveTraceIOModuleImp}
import barstools.iocell.chisel._
import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters, IOCellKey}
import chipyard.{HasHarnessSignalReferences}
import chipyard.harness._
object MainMemoryConsts {
val regionNamePrefix = "MainMemory"
def globalName = s"${regionNamePrefix}_${NodeIdx()}"
}
class WithSerialBridge extends OverrideIOBinder({
(system: CanHavePeripherySerialModuleImp) =>
system.serial.foreach(s => SerialBridge(system.clock, s, MainMemoryConsts.globalName)(system.p)); Nil
trait Unsupported {
require(false, "We do not support this IOCell type")
}
class FireSimAnalogIOCell extends RawModule with AnalogIOCell with Unsupported
class FireSimDigitalGPIOCell extends RawModule with DigitalGPIOCell with Unsupported
class FireSimDigitalInIOCell extends RawModule with DigitalInIOCell { io.i := io.pad }
class FireSimDigitalOutIOCell extends RawModule with DigitalOutIOCell { io.pad := io.o }
case class FireSimIOCellParams() extends IOCellTypeParams {
def analog() = Module(new FireSimAnalogIOCell)
def gpio() = Module(new FireSimDigitalGPIOCell)
def input() = Module(new FireSimDigitalInIOCell)
def output() = Module(new FireSimDigitalOutIOCell)
}
class WithFireSimIOCellModels extends Config((site, here, up) => {
case IOCellKey => FireSimIOCellParams()
})
class WithNICBridge extends OverrideIOBinder({
(system: CanHavePeripheryIceNICModuleImp) =>
system.net.foreach(n => NICBridge(system.clock, n)(system.p)); Nil
class WithSerialBridge extends OverrideHarnessBinder({
(system: CanHavePeripherySerial, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val clock = ports.collectFirst({case c: Clock => c})
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
ports.filter(_.isInstanceOf[SerialIO]).map {
case s: SerialIO => withClockAndReset(clock.get, th.harnessReset) {
SerialBridge(clock.get, s, MainMemoryConsts.globalName)(p)
}
case _ =>
}
Nil
}
})
class WithUARTBridge extends OverrideIOBinder({
(system: HasPeripheryUARTModuleImp) =>
system.uart.foreach(u => UARTBridge(system.clock, u)(system.p)); Nil
class WithNICBridge extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNICModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val clock = ports.collectFirst({case c: Clock => c})
ports.map {
case p: NICIOvonly => withClockAndReset(clock.get, th.harnessReset) { NICBridge(clock.get, p)(system.p) }
case _ =>
}
Nil
}
})
class WithBlockDeviceBridge extends OverrideIOBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) =>
system.bdev.foreach(b => BlockDevBridge(system.clock, b, system.reset.toBool)(system.p)); Nil
class WithUARTBridge extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) =>
ports.map { case p: UARTPortIO => UARTBridge(th.harnessClock, p)(system.p) }; Nil
})
class WithBlockDeviceBridge extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDeviceModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val clock = ports.collectFirst({case c: Clock => c})
ports.map {
case p: BlockDeviceIO => BlockDevBridge(clock.get, p, th.harnessReset.toBool)(system.p)
case _ =>
}
Nil
}
})
class WithFASEDBridge extends OverrideIOBinder({
(system: CanHaveMasterAXI4MemPort) => {
class WithFASEDBridge extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
implicit val p: Parameters = GetSystemParameters(system)
(system.mem_axi4 zip system.memAXI4Node.edges.in).foreach({ case (axi4, edge) =>
val clock = ports.collectFirst({case c: Clock => c})
val axi4_ports = ports.collect { case p: AXI4Bundle => p }
(axi4_ports zip system.memAXI4Node.edges.in).map { case (axi4: AXI4Bundle, edge) =>
val nastiKey = NastiParameters(axi4.r.bits.data.getWidth,
axi4.ar.bits.addr.getWidth,
axi4.ar.bits.id.getWidth)
system match {
case s: BaseSubsystem => FASEDBridge(s.module.clock, axi4, s.module.reset.toBool,
case s: BaseSubsystem => FASEDBridge(clock.get, axi4, th.harnessReset.asBool,
CompleteConfig(p(firesim.configs.MemModelKey),
nastiKey,
Some(AXI4EdgeSummary(edge)),
Some(MainMemoryConsts.globalName)))
case _ => throw new Exception("Attempting to attach FASED Bridge to misconfigured design")
}
})
}
Nil
}
})
class WithTracerVBridge extends ComposeIOBinder({
(system: CanHaveTraceIOModuleImp) =>
system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p))); Nil
})
class WithDromajoBridge extends ComposeIOBinder({
(system: CanHaveTraceIOModuleImp) => {
system.traceIO.foreach(_.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p))); Nil
class WithTracerVBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map { case p: TraceOutputTop => p.traces.map(tileTrace =>
withClockAndReset(tileTrace.clock, tileTrace.reset) { TracerVBridge(tileTrace)(system.p) }
)}
}
})
class WithDromajoBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) =>
ports.map { case p: TraceOutputTop => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil
})
class WithTraceGenBridge extends OverrideIOBinder({
(system: TraceGenSystemModuleImp) =>
GroundTestBridge(system.clock, system.success)(system.p); Nil
class WithTraceGenBridge extends OverrideHarnessBinder({
(system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) =>
ports.map { case p: Bool => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil
})
class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
@@ -105,52 +148,25 @@ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
val core = b.module.core
core.iregfile match {
case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile))
case _ => Nil
}
if (core.fp_pipeline != null) core.fp_pipeline.fregfile match {
case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile))
case _ => Nil
}
}
case _ =>
}
Nil
(Nil, Nil)
}
})
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.resetctrl, Some(system.psd))(system.p)
// tieoffDebug doesn't actually tie everything off :/
system.debug.foreach { d =>
d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare })
d.dmactiveAck := 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 WithTiedOffSystemGPIO ++
new WithTiedOffSystemDebug ++
new WithTiedOffSystemInterrupts ++
new WithSerialBridge ++
new WithNICBridge ++
new WithUARTBridge ++
new WithBlockDeviceBridge ++
new WithFASEDBridge ++
new WithFireSimMultiCycleRegfile ++
new WithTracerVBridge
new WithTracerVBridge ++
new WithFireSimIOCellModels
)

View File

@@ -13,8 +13,9 @@ import freechips.rocketchip.util.{ResetCatchAndSync}
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
import chipyard.{BuildSystem, BuildTop, HasHarnessSignalReferences, ChipyardSubsystem, ClockingSchemeKey, ChipTop}
import chipyard.iobinders.{IOBinders}
import chipyard._
import chipyard.harness._
import chipyard.iobinders._
// Determines the number of times to instantiate the DUT in the harness.
// Subsumes legacy supernode support
@@ -50,7 +51,7 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => {
chiptop.implicitClockSinkNode := implicitClockSourceNode
// Drive the diplomaticclock graph of the DigitalTop (if present)
val simpleClockGroupSourceNode = chiptop.lSystem match {
val simpleClockGroupSourceNode = chiptop.lazySystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
@@ -93,7 +94,7 @@ class WithFireSimRationalTileDomain(multiplier: Int, divisor: Int) extends Confi
chiptop.implicitClockSinkNode := implicitClockSourceNode
// Drive the diplomaticclock graph of the DigitalTop (if present)
val simpleClockGroupSourceNode = chiptop.lSystem match {
val simpleClockGroupSourceNode = chiptop.lazySystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
@@ -159,8 +160,13 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSigna
case AsyncClockGroupsKey => p(AsyncClockGroupsKey).copy
})))
val module = Module(lazyModule.module)
require(lazyModule.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
lazyModule.harnessFunctions.foreach(_(this))
lazyModule match { case d: HasTestHarnessFunctions =>
require(d.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
d.harnessFunctions.foreach(_(this))
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
}
NodeIdx.increment()
}
}