Split IOBinders into IOBinders and Harness Binders | punch out clocks to harness for simwidgets and bridges
This commit is contained in:
@@ -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 ),
|
||||
|
||||
@@ -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
|
||||
}}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
274
generators/chipyard/src/main/scala/HarnessBinders.scala
Normal file
274
generators/chipyard/src/main/scala/HarnessBinders.scala
Normal 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
|
||||
}
|
||||
})
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) ++
|
||||
|
||||
@@ -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))) ++
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Submodule generators/icenet updated: 705ca50690...bb23c81fcf
Submodule generators/testchipip updated: 1e7373f639...6f4e7ae2c9
Submodule sims/firesim updated: 05edd6be8c...069c3c111d
Submodule tools/barstools updated: aa1c90c4cc...ba681676f3
Reference in New Issue
Block a user