Add PortAPI between IO and Harness blocks
This commit is contained in:
@@ -13,7 +13,7 @@ The ``IOBinder`` functions are responsible for instantiating IO cells and IOPort
|
||||
For example, the ``WithUARTIOCells`` IOBinder will, for any ``System`` that might have UART ports (``HasPeripheryUARTModuleImp``, generate ports within the ``ChipTop`` (``ports``) as well as IOCells with the appropriate type and direction (``cells2d``). This function returns a the list of generated ports, and the list of generated IOCells. The list of generated ports is passed to the ``HarnessBinders`` such that they can be connected to ``TestHarness`` devices.
|
||||
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/iobinders/IOBinders.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: WithUARTIOCells
|
||||
:end-before: DOC include end: WithUARTIOCells
|
||||
|
||||
@@ -17,7 +17,8 @@ import chipyard.{BuildSystem}
|
||||
|
||||
// DOC include start: AbstractArty and Rocket
|
||||
class WithArtyTweaks extends Config(
|
||||
new WithArtyResetHarnessBinder ++
|
||||
new WithArtyDebugResetHarnessBinder ++
|
||||
new WithArtyJTAGResetHarnessBinder ++
|
||||
new WithArtyJTAGHarnessBinder ++
|
||||
new WithArtyUARTHarnessBinder ++
|
||||
new WithDebugResetPassthrough ++
|
||||
|
||||
@@ -11,68 +11,61 @@ import sifive.blocks.devices.pinctrl.{BasePin}
|
||||
|
||||
import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly}
|
||||
|
||||
import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder}
|
||||
import chipyard.iobinders.JTAGChipIO
|
||||
import chipyard.harness.{HarnessBinder}
|
||||
import chipyard.iobinders._
|
||||
|
||||
class WithArtyResetHarnessBinder extends ComposeHarnessBinder({
|
||||
(system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => {
|
||||
val resetPorts = ports.collect { case b: Bool => b }
|
||||
require(resetPorts.size == 2)
|
||||
class WithArtyDebugResetHarnessBinder extends HarnessBinder({
|
||||
case (th: ArtyFPGATestHarness, port: DebugResetPort) => {
|
||||
th.dut_ndreset := port.io // Debug module reset
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyJTAGResetHarnessBinder extends HarnessBinder({
|
||||
case (th: ArtyFPGATestHarness, port: JTAGResetPort) => {
|
||||
port.io := PowerOnResetFPGAOnly(th.clock_32MHz) // JTAG module reset
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyJTAGHarnessBinder extends HarnessBinder({
|
||||
case (th: ArtyFPGATestHarness, port: JTAGPort) => {
|
||||
val jtag_wire = Wire(new JTAGIO)
|
||||
jtag_wire.TDO.data := port.io.TDO
|
||||
jtag_wire.TDO.driven := true.B
|
||||
port.io.TCK := jtag_wire.TCK
|
||||
port.io.TMS := jtag_wire.TMS
|
||||
port.io.TDI := jtag_wire.TDI
|
||||
|
||||
val io_jtag = Wire(new JTAGPins(() => new BasePin(), false)).suggestName("jtag")
|
||||
|
||||
JTAGPinsFromPort(io_jtag, jtag_wire)
|
||||
|
||||
io_jtag.TCK.i.ival := IBUFG(IOBUF(th.jd_2).asClock).asBool
|
||||
|
||||
IOBUF(th.jd_5, io_jtag.TMS)
|
||||
PULLUP(th.jd_5)
|
||||
|
||||
IOBUF(th.jd_4, io_jtag.TDI)
|
||||
PULLUP(th.jd_4)
|
||||
|
||||
IOBUF(th.jd_0, io_jtag.TDO)
|
||||
|
||||
// mimic putting a pullup on this line (part of reset vote)
|
||||
th.SRST_n := IOBUF(th.jd_6)
|
||||
PULLUP(th.jd_6)
|
||||
|
||||
// ignore the po input
|
||||
io_jtag.TCK.i.po.map(_ := DontCare)
|
||||
io_jtag.TDI.i.po.map(_ := DontCare)
|
||||
io_jtag.TMS.i.po.map(_ := DontCare)
|
||||
io_jtag.TDO.i.po.map(_ := DontCare)
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyUARTHarnessBinder extends HarnessBinder({
|
||||
case (th: ArtyFPGATestHarness, port: UARTPort) => {
|
||||
withClockAndReset(th.clock_32MHz, th.ck_rst) {
|
||||
// Debug module reset
|
||||
th.dut_ndreset := resetPorts(0)
|
||||
|
||||
// JTAG reset
|
||||
resetPorts(1) := PowerOnResetFPGAOnly(th.clock_32MHz)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => {
|
||||
ports.map {
|
||||
case j: JTAGChipIO => {
|
||||
val jtag_wire = Wire(new JTAGIO)
|
||||
jtag_wire.TDO.data := j.TDO
|
||||
jtag_wire.TDO.driven := true.B
|
||||
j.TCK := jtag_wire.TCK
|
||||
j.TMS := jtag_wire.TMS
|
||||
j.TDI := jtag_wire.TDI
|
||||
|
||||
val io_jtag = Wire(new JTAGPins(() => new BasePin(), false)).suggestName("jtag")
|
||||
|
||||
JTAGPinsFromPort(io_jtag, jtag_wire)
|
||||
|
||||
io_jtag.TCK.i.ival := IBUFG(IOBUF(th.jd_2).asClock).asBool
|
||||
|
||||
IOBUF(th.jd_5, io_jtag.TMS)
|
||||
PULLUP(th.jd_5)
|
||||
|
||||
IOBUF(th.jd_4, io_jtag.TDI)
|
||||
PULLUP(th.jd_4)
|
||||
|
||||
IOBUF(th.jd_0, io_jtag.TDO)
|
||||
|
||||
// mimic putting a pullup on this line (part of reset vote)
|
||||
th.SRST_n := IOBUF(th.jd_6)
|
||||
PULLUP(th.jd_6)
|
||||
|
||||
// ignore the po input
|
||||
io_jtag.TCK.i.po.map(_ := DontCare)
|
||||
io_jtag.TDI.i.po.map(_ := DontCare)
|
||||
io_jtag.TMS.i.po.map(_ := DontCare)
|
||||
io_jtag.TDO.i.po.map(_ := DontCare)
|
||||
}
|
||||
case b: Bool =>
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyUARTHarnessBinder extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: ArtyFPGATestHarness, ports: Seq[UARTPortIO]) => {
|
||||
withClockAndReset(th.clock_32MHz, th.ck_rst) {
|
||||
IOBUF(th.uart_rxd_out, ports.head.txd)
|
||||
ports.head.rxd := IOBUF(th.uart_txd_in)
|
||||
IOBUF(th.uart_rxd_out, port.io.txd)
|
||||
port.io.rxd := IOBUF(th.uart_txd_in)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -5,7 +5,7 @@ import chisel3.experimental.{IO}
|
||||
|
||||
import freechips.rocketchip.devices.debug.{HasPeripheryDebug}
|
||||
|
||||
import chipyard.iobinders.{ComposeIOBinder}
|
||||
import chipyard.iobinders.{ComposeIOBinder, DebugResetPort, JTAGResetPort}
|
||||
|
||||
class WithDebugResetPassthrough extends ComposeIOBinder({
|
||||
(system: HasPeripheryDebug) => {
|
||||
@@ -18,6 +18,6 @@ class WithDebugResetPassthrough extends ComposeIOBinder({
|
||||
val io_sjtag_reset: Bool = IO(Input(Bool())).suggestName("sjtag_reset")
|
||||
sjtag.reset := io_sjtag_reset
|
||||
|
||||
(Seq(io_ndreset, io_sjtag_reset), Nil)
|
||||
(Seq(DebugResetPort(io_ndreset), JTAGResetPort(io_sjtag_reset)), Nil)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -16,33 +16,28 @@ import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly}
|
||||
|
||||
import chipyard._
|
||||
import chipyard.harness._
|
||||
import chipyard.iobinders.JTAGChipIO
|
||||
import chipyard.iobinders._
|
||||
|
||||
import testchipip._
|
||||
|
||||
class WithArty100TUARTTSI(uartBaudRate: BigInt = 115200) extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => {
|
||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||
require(ports.size <= 1)
|
||||
class WithArty100TUARTTSI(uartBaudRate: BigInt = 115200) extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTTSIPort) => {
|
||||
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
|
||||
ports.map({ port =>
|
||||
ath.io_uart_bb.bundle <> port.uart
|
||||
ath.other_leds(1) := port.dropped
|
||||
ath.other_leds(9) := port.tsi2tl_state(0)
|
||||
ath.other_leds(10) := port.tsi2tl_state(1)
|
||||
ath.other_leds(11) := port.tsi2tl_state(2)
|
||||
ath.other_leds(12) := port.tsi2tl_state(3)
|
||||
})
|
||||
ath.io_uart_bb.bundle <> port.io.uart
|
||||
ath.other_leds(1) := port.io.dropped
|
||||
ath.other_leds(9) := port.io.tsi2tl_state(0)
|
||||
ath.other_leds(10) := port.io.tsi2tl_state(1)
|
||||
ath.other_leds(11) := port.io.tsi2tl_state(2)
|
||||
ath.other_leds(12) := port.io.tsi2tl_state(3)
|
||||
}
|
||||
})
|
||||
|
||||
class WithArty100TDDRTL extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterTLMemPort, th: HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => {
|
||||
require(ports.size == 1)
|
||||
class WithArty100TDDRTL extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: TLMemPort) => {
|
||||
val artyTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
|
||||
val bundles = artyTh.ddrClient.out.map(_._1)
|
||||
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
ddrClientBundle <> ports.head
|
||||
ddrClientBundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
@@ -53,10 +53,6 @@ class WithVC707Tweaks extends Config (
|
||||
new WithVC707UARTHarnessBinder ++
|
||||
new WithVC707SPISDCardHarnessBinder ++
|
||||
new WithVC707DDRMemHarnessBinder ++
|
||||
// io binders
|
||||
new WithUARTIOPassthrough ++
|
||||
new WithSPIIOPassthrough ++
|
||||
new WithTLIOPassthrough ++
|
||||
// other configuration
|
||||
new WithDefaultPeripherals ++
|
||||
new chipyard.config.WithTLBackingMemory ++ // use TL backing memory
|
||||
|
||||
@@ -11,36 +11,29 @@ import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
|
||||
import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{HasSystemXilinxVC707PCIeX1ModuleImp, XilinxVC707PCIeX1IO}
|
||||
|
||||
import chipyard.{CanHaveMasterTLMemPort}
|
||||
import chipyard.harness.{OverrideHarnessBinder}
|
||||
import chipyard.harness.{HarnessBinder}
|
||||
import chipyard.iobinders._
|
||||
|
||||
/*** UART ***/
|
||||
class WithVC707UARTHarnessBinder extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: BaseModule, ports: Seq[UARTPortIO]) => {
|
||||
th match { case vc707th: VC707FPGATestHarnessImp => {
|
||||
vc707th.vc707Outer.io_uart_bb.bundle <> ports.head
|
||||
}}
|
||||
class WithVC707UARTHarnessBinder extends HarnessBinder({
|
||||
case (th: VC707FPGATestHarnessImp, port: UARTPort) => {
|
||||
th.vc707Outer.io_uart_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** SPI ***/
|
||||
class WithVC707SPISDCardHarnessBinder extends OverrideHarnessBinder({
|
||||
(system: HasPeripherySPI, th: BaseModule, ports: Seq[SPIPortIO]) => {
|
||||
th match { case vc707th: VC707FPGATestHarnessImp => {
|
||||
vc707th.vc707Outer.io_spi_bb.bundle <> ports.head
|
||||
}}
|
||||
class WithVC707SPISDCardHarnessBinder extends HarnessBinder({
|
||||
case (th: VC707FPGATestHarnessImp, port: SPIPort) => {
|
||||
th.vc707Outer.io_spi_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** Experimental DDR ***/
|
||||
class WithVC707DDRMemHarnessBinder extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterTLMemPort, th: BaseModule, ports: Seq[HeterogeneousBag[TLBundle]]) => {
|
||||
th match { case vc707th: VC707FPGATestHarnessImp => {
|
||||
require(ports.size == 1)
|
||||
|
||||
val bundles = vc707th.vc707Outer.ddrClient.out.map(_._1)
|
||||
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
ddrClientBundle <> ports.head
|
||||
}}
|
||||
class WithVC707DDRMemHarnessBinder extends HarnessBinder({
|
||||
case (th: VC707FPGATestHarnessImp, port: TLMemPort) => {
|
||||
val bundles = th.vc707Outer.ddrClient.out.map(_._1)
|
||||
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
ddrClientBundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package chipyard.fpga.vc707
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{IO, DataMirror}
|
||||
|
||||
import freechips.rocketchip.diplomacy.{ResourceBinding, Resource, ResourceAddress, InModuleBody}
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystem}
|
||||
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||
import freechips.rocketchip.tilelink.{TLBundle}
|
||||
|
||||
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp}
|
||||
import sifive.blocks.devices.spi.{HasPeripherySPI, HasPeripherySPIModuleImp, MMCDevice}
|
||||
import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{HasSystemXilinxVC707PCIeX1ModuleImp}
|
||||
|
||||
import chipyard.{CanHaveMasterTLMemPort}
|
||||
import chipyard.iobinders.{OverrideIOBinder, OverrideLazyIOBinder}
|
||||
|
||||
class WithUARTIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryUARTModuleImp) => {
|
||||
val io_uart_pins_temp = system.uart.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"uart_$i") }
|
||||
(io_uart_pins_temp zip system.uart).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_uart_pins_temp, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithSPIIOPassthrough extends OverrideLazyIOBinder({
|
||||
(system: HasPeripherySPI) => {
|
||||
// attach resource to 1st SPI
|
||||
ResourceBinding {
|
||||
Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0))
|
||||
}
|
||||
|
||||
InModuleBody {
|
||||
system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripherySPIModuleImp => {
|
||||
val io_spi_pins_temp = system.spi.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"spi_$i") }
|
||||
(io_spi_pins_temp zip system.spi).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_spi_pins_temp, Nil)
|
||||
} }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithTLIOPassthrough extends OverrideIOBinder({
|
||||
(system: CanHaveMasterTLMemPort) => {
|
||||
val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.mem_tl)).suggestName("tl_slave")
|
||||
io_tl_mem_pins_temp <> system.mem_tl
|
||||
(Seq(io_tl_mem_pins_temp), Nil)
|
||||
}
|
||||
})
|
||||
@@ -52,9 +52,6 @@ class WithVCU118Tweaks extends Config(
|
||||
new WithUART ++
|
||||
new WithSPISDCard ++
|
||||
new WithDDRMem ++
|
||||
// io binders
|
||||
new WithUARTIOPassthrough ++
|
||||
new WithSPIIOPassthrough ++
|
||||
// other configuration
|
||||
new WithDefaultPeripherals ++
|
||||
new chipyard.config.WithTLBackingMemory ++ // use TL backing memory
|
||||
|
||||
@@ -11,35 +11,28 @@ import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
|
||||
|
||||
import chipyard._
|
||||
import chipyard.harness._
|
||||
import chipyard.iobinders._
|
||||
|
||||
/*** UART ***/
|
||||
class WithUART extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
|
||||
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||
vcu118th.vcu118Outer.io_uart_bb.bundle <> ports.head
|
||||
} }
|
||||
class WithUART extends HarnessBinder({
|
||||
case (th: VCU118FPGATestHarnessImp, port: UARTPort) => {
|
||||
th.vcu118Outer.io_uart_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** SPI ***/
|
||||
class WithSPISDCard extends OverrideHarnessBinder({
|
||||
(system: HasPeripherySPI, th: BaseModule with HasHarnessInstantiators, ports: Seq[SPIPortIO]) => {
|
||||
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||
vcu118th.vcu118Outer.io_spi_bb.bundle <> ports.head
|
||||
} }
|
||||
class WithSPISDCard extends HarnessBinder({
|
||||
case (th: VCU118FPGATestHarnessImp, port: SPIPort) => {
|
||||
th.vcu118Outer.io_spi_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** Experimental DDR ***/
|
||||
class WithDDRMem extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => {
|
||||
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||
require(ports.size == 1)
|
||||
|
||||
val bundles = vcu118th.vcu118Outer.ddrClient.out.map(_._1)
|
||||
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
ddrClientBundle <> ports.head
|
||||
} }
|
||||
class WithDDRMem extends HarnessBinder({
|
||||
case (th: VCU118FPGATestHarnessImp, port: TLMemPort) => {
|
||||
val bundles = th.vcu118Outer.ddrClient.out.map(_._1)
|
||||
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
ddrClientBundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package chipyard.fpga.vcu118
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{IO, DataMirror}
|
||||
|
||||
import freechips.rocketchip.diplomacy.{ResourceBinding, Resource, ResourceAddress, InModuleBody}
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystem}
|
||||
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||
import freechips.rocketchip.tilelink.{TLBundle}
|
||||
|
||||
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp}
|
||||
import sifive.blocks.devices.spi.{HasPeripherySPI, HasPeripherySPIModuleImp, MMCDevice}
|
||||
|
||||
import chipyard.{CanHaveMasterTLMemPort}
|
||||
import chipyard.iobinders.{OverrideIOBinder, OverrideLazyIOBinder}
|
||||
|
||||
class WithUARTIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryUARTModuleImp) => {
|
||||
val io_uart_pins_temp = system.uart.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"uart_$i") }
|
||||
(io_uart_pins_temp zip system.uart).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_uart_pins_temp, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithSPIIOPassthrough extends OverrideLazyIOBinder({
|
||||
(system: HasPeripherySPI) => {
|
||||
// attach resource to 1st SPI
|
||||
ResourceBinding {
|
||||
Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0))
|
||||
}
|
||||
|
||||
InModuleBody {
|
||||
system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripherySPIModuleImp => {
|
||||
val io_spi_pins_temp = system.spi.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"spi_$i") }
|
||||
(io_spi_pins_temp zip system.spi).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_spi_pins_temp, Nil)
|
||||
} }
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -20,6 +20,7 @@ import testchipip.{PeripheryTSIHostKey, TSIHostParams, TSIHostSerdesParams}
|
||||
import chipyard.{BuildSystem}
|
||||
|
||||
import chipyard.fpga.vcu118.{WithVCU118Tweaks, WithFPGAFrequency, VCU118DDR2Size}
|
||||
import chipyard.iobinders.{WithGPIOPunchthrough}
|
||||
|
||||
class WithBringupPeripherals extends Config((site, here, up) => {
|
||||
case PeripheryUARTKey => up(PeripheryUARTKey, site) ++ List(UARTParams(address = BigInt(0x64003000L)))
|
||||
@@ -80,8 +81,7 @@ class WithBringupAdditions extends Config(
|
||||
new WithBringupGPIO ++
|
||||
new WithBringupTSIHost ++
|
||||
new WithTSITLIOPassthrough ++
|
||||
new WithI2CIOPassthrough ++
|
||||
new WithGPIOIOPassthrough ++
|
||||
new WithGPIOPunchthrough ++
|
||||
new WithBringupPeripherals ++
|
||||
new WithBringupVCU118System)
|
||||
|
||||
|
||||
@@ -14,56 +14,38 @@ import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp, GPIOPortIO}
|
||||
import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO}
|
||||
|
||||
import chipyard.harness._
|
||||
import chipyard.iobinders._
|
||||
|
||||
/*** UART ***/
|
||||
class WithBringupUART extends ComposeHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
|
||||
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||
require(ports.size == 2)
|
||||
|
||||
vcu118th.bringupOuter.io_fmc_uart_bb.bundle <> ports.last
|
||||
} }
|
||||
class WithBringupUART extends HarnessBinder({
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: UARTPort) => {
|
||||
th.bringupOuter.io_fmc_uart_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** I2C ***/
|
||||
class WithBringupI2C extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[I2CPort]) => {
|
||||
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||
require(ports.size == 1)
|
||||
|
||||
vcu118th.bringupOuter.io_i2c_bb.bundle <> ports.head
|
||||
} }
|
||||
class WithBringupI2C extends HarnessBinder({
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: chipyard.iobinders.I2CPort) => {
|
||||
th.bringupOuter.io_i2c_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** GPIO ***/
|
||||
class WithBringupGPIO extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[GPIOPortIO]) => {
|
||||
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||
(vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) =>
|
||||
bb_io.bundle <> dut_io
|
||||
}
|
||||
} }
|
||||
class WithBringupGPIO extends HarnessBinder({
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: GPIOPort) => {
|
||||
th.bringupOuter.io_gpio_bb(port.pinId).bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** TSI Host Widget ***/
|
||||
class WithBringupTSIHost extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryTSIHostWidget, th: BaseModule with HasHarnessInstantiators, ports: Seq[Data]) => {
|
||||
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||
require(ports.size == 2) // 1st goes to the TL mem, 2nd goes to the serial link
|
||||
|
||||
ports.head match { case tlPort: HeterogeneousBag[TLBundle] =>
|
||||
val tsiBundles = vcu118th.bringupOuter.tsiDdrClient.out.map(_._1)
|
||||
val tsiDdrClientBundle = Wire(new HeterogeneousBag(tsiBundles.map(_.cloneType)))
|
||||
tsiBundles.zip(tsiDdrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
tsiDdrClientBundle <> tlPort
|
||||
}
|
||||
|
||||
ports.last match { case serialPort: TSIHostWidgetIO =>
|
||||
vcu118th.bringupOuter.io_tsi_serial_bb.bundle <> serialPort
|
||||
}
|
||||
} }
|
||||
class WithBringupTSIHost extends HarnessBinder({
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: TLMemPort) => {
|
||||
val tsiBundles = th.bringupOuter.tsiDdrClient.out.map(_._1)
|
||||
val tsiDdrClientBundle = Wire(new HeterogeneousBag(tsiBundles.map(_.cloneType)))
|
||||
tsiBundles.zip(tsiDdrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
tsiDdrClientBundle <> port.io
|
||||
}
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: TSIHostWidgetPort) => {
|
||||
th.bringupOuter.io_tsi_serial_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
@@ -11,27 +11,10 @@ import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp}
|
||||
|
||||
import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO}
|
||||
|
||||
import chipyard.iobinders.{OverrideIOBinder}
|
||||
import chipyard.iobinders.{OverrideIOBinder, Port, TLMemPort}
|
||||
|
||||
class WithGPIOIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryGPIOModuleImp) => {
|
||||
val io_gpio_pins_temp = system.gpio.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"gpio_$i") }
|
||||
(io_gpio_pins_temp zip system.gpio).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_gpio_pins_temp, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithI2CIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryI2CModuleImp) => {
|
||||
val io_i2c_pins_temp = system.i2c.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"i2c_$i") }
|
||||
(io_i2c_pins_temp zip system.i2c).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_i2c_pins_temp, Nil)
|
||||
}
|
||||
})
|
||||
case class TSIHostWidgetPort(val io: TSIHostWidgetIO)
|
||||
extends Port[TSIHostWidgetIO]
|
||||
|
||||
class WithTSITLIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryTSIHostWidget) => {
|
||||
@@ -42,6 +25,6 @@ class WithTSITLIOPassthrough extends OverrideIOBinder({
|
||||
require(system.tsiSerial.size == 1)
|
||||
val io_tsi_serial_pins_temp = IO(DataMirror.internal.chiselTypeClone[TSIHostWidgetIO](system.tsiSerial.head)).suggestName("tsi_serial")
|
||||
io_tsi_serial_pins_temp <> system.tsiSerial.head
|
||||
(Seq(io_tsi_tl_mem_pins_temp, io_tsi_serial_pins_temp), Nil)
|
||||
(Seq(TLMemPort(io_tsi_tl_mem_pins_temp), TSIHostWidgetPort(io_tsi_serial_pins_temp)), Nil)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,17 +2,13 @@ package chipyard.clocking
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chipyard.iobinders.{OverrideLazyIOBinder, GetSystemParameters, IOCellKey}
|
||||
import chipyard.iobinders.{OverrideLazyIOBinder, GetSystemParameters, IOCellKey, ClockPort, ResetPort}
|
||||
import freechips.rocketchip.prci._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import barstools.iocell.chisel._
|
||||
|
||||
class ClockWithFreq(val freqMHz: Double) extends Bundle {
|
||||
val clock = Clock()
|
||||
}
|
||||
|
||||
// This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate
|
||||
// the requested clocks. This also adds TileLink ClockDivider and ClockSelector
|
||||
// blocks, which allow memory-mapped control of clock division, and clock muxing
|
||||
@@ -58,13 +54,13 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
|
||||
pllCtrlSink := pllCtrl.ctrlNode
|
||||
|
||||
InModuleBody {
|
||||
val clock_wire = Wire(Input(new ClockWithFreq(100)))
|
||||
val clock_wire = Wire(Input(Clock()))
|
||||
val reset_wire = Wire(Input(AsyncReset()))
|
||||
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
|
||||
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
|
||||
|
||||
slowClockSource.out.unzip._1.map { o =>
|
||||
o.clock := clock_wire.clock
|
||||
o.clock := clock_wire
|
||||
o.reset := reset_wire
|
||||
}
|
||||
|
||||
@@ -79,7 +75,7 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
|
||||
o.reset := reset_wire
|
||||
}
|
||||
|
||||
(Seq(clock_io, reset_io), clockIOCell ++ resetIOCell)
|
||||
(Seq(ClockPort(clock_io, 100), ResetPort(reset_io)), clockIOCell ++ resetIOCell)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -114,12 +110,12 @@ class WithPassthroughClockGenerator extends OverrideLazyIOBinder({
|
||||
require(m.take.isDefined, s"""Clock ${m.name.get} has no requested frequency
|
||||
|Clocks: ${edge.sink.members.map(_.name.get)}""".stripMargin)
|
||||
val freq = m.take.get.freqMHz
|
||||
val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}")
|
||||
b.clock := clock_io.clock
|
||||
val clock_io = IO(Input(Clock())).suggestName(s"clock_${m.name.get}")
|
||||
b.clock := clock_io
|
||||
b.reset := reset_io
|
||||
clock_io
|
||||
ClockPort(clock_io, freq)
|
||||
}.toSeq
|
||||
((clock_ios :+ reset_io), Nil)
|
||||
((clock_ios :+ ResetPort(reset_io)), Nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -51,7 +51,7 @@ object FrequencyUtils {
|
||||
require(!requestedOutputs.contains(0.0))
|
||||
val requestedFreqs = requestedOutputs.map(_.freqMHz)
|
||||
val fastestFreq = requestedFreqs.max
|
||||
require(fastestFreq <= maximumAllowableFreqMHz)
|
||||
require(fastestFreq <= maximumAllowableFreqMHz, s"Fastest Freq $fastestFreq > Max Freq $maximumAllowableFreqMHz")
|
||||
|
||||
val candidateFreqs =
|
||||
Seq.tabulate(Math.ceil(maximumAllowableFreqMHz / fastestFreq).toInt)(i => (i + 1) * fastestFreq)
|
||||
|
||||
@@ -15,7 +15,8 @@ class AbstractConfig extends Config(
|
||||
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.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM
|
||||
new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
|
||||
new chipyard.harness.WithSimJTAGDebug ++ // add SimJTAG if JTAG for debug exposed
|
||||
new chipyard.harness.WithSimDMI ++ // add SimJTAG if DMI exposed
|
||||
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
|
||||
@@ -23,7 +24,8 @@ class AbstractConfig extends Config(
|
||||
new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present
|
||||
new chipyard.harness.WithCustomBootPinPlusArg ++ // drive custom-boot pin with a plusarg, if custom-boot-pin is present
|
||||
new chipyard.harness.WithSimUARTToUARTTSI ++ // connect a SimUART to the UART-TSI port
|
||||
new chipyard.harness.WithClockAndResetFromHarness ++ // all Clock/Reset I/O in ChipTop should be driven by harnessClockInstantiator
|
||||
new chipyard.harness.WithClockFromHarness ++ // all Clock I/O in ChipTop should be driven by harnessClockInstantiator
|
||||
new chipyard.harness.WithResetFromHarness ++ // reset controlled by harness
|
||||
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // generate clocks in harness with unsynthesizable ClockSourceAtFreqMHz
|
||||
|
||||
// The IOBinders instantiate ChipTop IOs to match desired digital IOs
|
||||
@@ -32,11 +34,13 @@ class AbstractConfig extends Config(
|
||||
new chipyard.iobinders.WithDebugIOCells ++
|
||||
new chipyard.iobinders.WithUARTIOCells ++
|
||||
new chipyard.iobinders.WithGPIOCells ++
|
||||
new chipyard.iobinders.WithSPIIOCells ++
|
||||
new chipyard.iobinders.WithSPIFlashIOCells ++
|
||||
new chipyard.iobinders.WithExtInterruptIOCells ++
|
||||
new chipyard.iobinders.WithCustomBootPin ++
|
||||
// The "punchthrough" IOBInders below don't generate IOCells, as these interfaces shouldn't really be mapped to ASIC IO
|
||||
// Instead, they directly pass through the DigitalTop ports to ports in the ChipTop
|
||||
new chipyard.iobinders.WithI2CPunchthrough ++
|
||||
new chipyard.iobinders.WithSPIIOPunchthrough ++
|
||||
new chipyard.iobinders.WithAXI4MemPunchthrough ++
|
||||
new chipyard.iobinders.WithAXI4MMIOPunchthrough ++
|
||||
new chipyard.iobinders.WithTLMemPunchthrough ++
|
||||
|
||||
@@ -7,7 +7,8 @@ class AbstractTraceGenConfig extends Config(
|
||||
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++
|
||||
new chipyard.harness.WithBlackBoxSimMem ++
|
||||
new chipyard.harness.WithTraceGenSuccess ++
|
||||
new chipyard.harness.WithClockAndResetFromHarness ++
|
||||
new chipyard.harness.WithClockFromHarness ++
|
||||
new chipyard.harness.WithResetFromHarness ++
|
||||
new chipyard.iobinders.WithAXI4MemPunchthrough ++
|
||||
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
|
||||
new chipyard.clocking.WithPassthroughClockGenerator ++
|
||||
|
||||
@@ -68,13 +68,13 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule {
|
||||
l.reset := implicit_reset
|
||||
}}
|
||||
|
||||
val clock_wire = Wire(Input(new ClockWithFreq(80)))
|
||||
val clock_wire = Wire(Input(Clock()))
|
||||
val reset_wire = Wire(Input(AsyncReset()))
|
||||
val (clock_pad, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
|
||||
val (reset_pad, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
|
||||
|
||||
slowClockSource.out.unzip._1.map { o =>
|
||||
o.clock := clock_wire.clock
|
||||
o.clock := clock_wire
|
||||
o.reset := reset_wire
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class FlatTestHarness(implicit val p: Parameters) extends Module {
|
||||
val clock_source = Module(new ClockSourceAtFreqFromPlusArg("slow_clk_freq_mhz"))
|
||||
clock_source.io.power := true.B
|
||||
clock_source.io.gate := false.B
|
||||
dut.clock_pad.clock := clock_source.io.clk
|
||||
dut.clock_pad := clock_source.io.clk
|
||||
|
||||
// Reset
|
||||
dut.reset_pad := reset.asAsyncReset
|
||||
|
||||
@@ -6,355 +6,284 @@ import chisel3.experimental.{Analog, BaseModule, DataMirror, Direction}
|
||||
|
||||
import org.chipsalliance.cde.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 freechips.rocketchip.util._
|
||||
|
||||
import sifive.blocks.devices.gpio._
|
||||
import sifive.blocks.devices.uart._
|
||||
import sifive.blocks.devices.spi._
|
||||
|
||||
import freechips.rocketchip.jtag.{JTAGIO}
|
||||
import freechips.rocketchip.devices.debug.{SimJTAG}
|
||||
import barstools.iocell.chisel._
|
||||
|
||||
import testchipip._
|
||||
|
||||
import icenet.{NicLoopback, SimNetwork}
|
||||
import chipyard._
|
||||
import chipyard.clocking.{HasChipyardPRCI, ClockWithFreq}
|
||||
import chipyard.iobinders.{GetSystemParameters, JTAGChipIO}
|
||||
import chipyard.clocking.{HasChipyardPRCI}
|
||||
import chipyard.iobinders._
|
||||
|
||||
import tracegen.{TraceGenSystemModuleImp}
|
||||
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
|
||||
|
||||
import scala.reflect.{ClassTag}
|
||||
|
||||
case object HarnessBinders extends Field[HarnessBinderMap](HarnessBinderMapDefault)
|
||||
case object HarnessBinders extends Field[HarnessBinderFunction]({case _ => })
|
||||
|
||||
object ApplyHarnessBinders {
|
||||
def apply(th: HasHarnessInstantiators, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters): Unit = {
|
||||
val pm = portMap.withDefaultValue(Nil)
|
||||
p(HarnessBinders).foreach { case (s, f) =>
|
||||
f(sys, th, pm(s))
|
||||
f(sys.module, th, pm(s))
|
||||
}
|
||||
def apply(th: HasHarnessInstantiators, ports: Seq[Port[_]])(implicit p: Parameters): Unit = {
|
||||
ports.foreach(port => p(HarnessBinders)(th, port))
|
||||
}
|
||||
}
|
||||
|
||||
// The ClassTags here are necessary to overcome issues arising from type erasure
|
||||
class HarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](composer: ((T, S, Seq[U]) => Unit) => (T, S, Seq[U]) => Unit)(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => {
|
||||
case HarnessBinders => up(HarnessBinders, site) + (systemTag.runtimeClass.toString ->
|
||||
((t: Any, th: HasHarnessInstantiators, ports: Seq[Data]) => {
|
||||
val pts = ports.collect({case p: U => p})
|
||||
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}")
|
||||
val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString)
|
||||
(th, t) match {
|
||||
case (th: S, system: T) => composer(upfn)(system, th, pts)
|
||||
case _ =>
|
||||
}
|
||||
})
|
||||
)
|
||||
class HarnessBinder[T <: HasHarnessInstantiators, S <: Port[_]](
|
||||
fn: => HarnessBinderFunction
|
||||
) extends Config((site, here, up) => {
|
||||
case HarnessBinders => fn orElse up(HarnessBinders)
|
||||
})
|
||||
|
||||
class OverrideHarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](fn: => (T, S, Seq[U]) => Unit)
|
||||
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
|
||||
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => fn)
|
||||
|
||||
class ComposeHarnessBinder[T, S <: HasHarnessInstantiators, U <: Data](fn: => (T, S, Seq[U]) => Unit)
|
||||
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
|
||||
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => (t, th, p) => {
|
||||
upfn(t, th, p)
|
||||
fn(t, th, p)
|
||||
})
|
||||
|
||||
|
||||
class WithGPIOTiedOff extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryGPIOModuleImp, th: HasHarnessInstantiators, ports: Seq[Analog]) => {
|
||||
ports.foreach { _ <> AnalogConst(0) }
|
||||
class WithGPIOTiedOff extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: GPIOPort) => {
|
||||
port.io <> AnalogConst(0)
|
||||
}
|
||||
})
|
||||
|
||||
// DOC include start: WithUARTAdapter
|
||||
class WithUARTAdapter extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
|
||||
UARTAdapter.connect(ports)(system.p)
|
||||
class WithUARTAdapter extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTPort) => {
|
||||
val div = (th.getHarnessBinderClockFreqMHz / port.io.c.initBaudRate.toDouble).toInt
|
||||
val uart_sim = Module(new UARTAdapter(port.uartNo, div, false)).suggestName(s"uart_sim_uartno${port.uartNo}")
|
||||
uart_sim.io.uart.txd := port.io.txd
|
||||
port.io.rxd := uart_sim.io.uart.rxd
|
||||
}
|
||||
})
|
||||
// DOC include end: WithUARTAdapter
|
||||
|
||||
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
|
||||
(system: HasPeripherySPIFlashModuleImp, th: HasHarnessInstantiators, ports: Seq[SPIChipIO]) => {
|
||||
SimSPIFlashModel.connect(ports, th.harnessBinderReset, rdOnly)(system.p)
|
||||
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SPIFlashPort) => {
|
||||
val spi_mem = Module(new SimSPIFlashModel(port.params.fSize, port.spiId, rdOnly)).suggestName(s"spi_mem${port.spiId}")
|
||||
spi_mem.io.sck := port.io.sck
|
||||
require(port.params.csWidth == 1, "I don't know what to do with your extra CS bits. Fix me please.")
|
||||
spi_mem.io.cs(0) := port.io.cs(0)
|
||||
spi_mem.io.dq.zip(port.io.dq).foreach { case (x, y) => x <> y }
|
||||
spi_mem.io.reset := th.harnessBinderReset
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimBlockDevice extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryBlockDevice, th: HasHarnessInstantiators, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
ports.map { b => SimBlockDevice.connect(b.clock, th.harnessBinderReset.asBool, Some(b.bits)) }
|
||||
class WithSimBlockDevice extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: BlockDevicePort) => {
|
||||
val sim_blkdev = Module(new SimBlockDevice(port.params))
|
||||
sim_blkdev.io.bdev <> port.io.bits
|
||||
sim_blkdev.io.clock := port.io.clock
|
||||
sim_blkdev.io.reset := th.harnessBinderReset
|
||||
}
|
||||
})
|
||||
|
||||
class WithBlockDeviceModel extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryBlockDevice, th: HasHarnessInstantiators, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
ports.map { b => BlockDeviceModel.connect(Some(b.bits)) }
|
||||
class WithBlockDeviceModel extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: BlockDevicePort) => {
|
||||
val blkdev_model = Module(new BlockDeviceModel(16, port.params))
|
||||
blkdev_model.io <> port.io.bits
|
||||
blkdev_model.clock := port.io.clock
|
||||
blkdev_model.reset := th.harnessBinderReset
|
||||
}
|
||||
})
|
||||
|
||||
class WithLoopbackNIC extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryIceNIC, th: HasHarnessInstantiators, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
ports.map { n => NicLoopback.connect(Some(n.bits), p(NICKey)) }
|
||||
class WithLoopbackNIC extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: NICPort) => {
|
||||
withClock(port.io.clock) { NicLoopback.connect(port.io.bits, port.params) }
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimNetwork extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessInstantiators, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessBinderReset.asBool) }
|
||||
class WithSimNetwork extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: NICPort) => {
|
||||
withClock(port.io.clock) { SimNetwork.connect(Some(port.io.bits), port.io.clock, th.harnessBinderReset.asBool) }
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimAXIMem extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
||||
val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p))
|
||||
Module(mem.module).suggestName("mem")
|
||||
mem.io_axi4.head <> port.bits
|
||||
class WithSimAXIMem extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: AXI4MemPort) => {
|
||||
val mem = LazyModule(new SimAXIMem(port.edge, size=port.params.master.size)(Parameters.empty))
|
||||
withClock(port.io.clock) { Module(mem.module) }
|
||||
mem.io_axi4.head <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
class WithBlackBoxSimMem(additionalLatency: Int = 0) extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: AXI4MemPort) => {
|
||||
// TODO FIX: This currently makes each SimDRAM contain the entire memory space
|
||||
val memSize = port.params.master.size
|
||||
val memBase = port.params.master.base
|
||||
val lineSize = 64 // cache block size
|
||||
val clockFreq = port.clockFreqMHz
|
||||
val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, memBase, port.edge.bundle)).suggestName("simdram")
|
||||
|
||||
mem.io.clock := port.io.clock
|
||||
mem.io.reset := th.harnessBinderReset.asAsyncReset
|
||||
mem.io.axi <> port.io.bits
|
||||
// Bug in Chisel implementation. See https://github.com/chipsalliance/chisel3/pull/1781
|
||||
def Decoupled[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = {
|
||||
require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.")
|
||||
val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits)))
|
||||
d.bits := irr.bits
|
||||
d.valid := irr.valid
|
||||
irr.ready := d.ready
|
||||
d
|
||||
}
|
||||
if (additionalLatency > 0) {
|
||||
withClock (port.io.clock) {
|
||||
mem.io.axi.aw <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.aw))((t, _) => Queue(t, 1, pipe=true))
|
||||
mem.io.axi.w <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.w ))((t, _) => Queue(t, 1, pipe=true))
|
||||
port.io.bits.b <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.b ))((t, _) => Queue(t, 1, pipe=true))
|
||||
mem.io.axi.ar <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.ar))((t, _) => Queue(t, 1, pipe=true))
|
||||
port.io.bits.r <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.r ))((t, _) => Queue(t, 1, pipe=true))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
|
||||
// TODO FIX: This currently makes each SimDRAM contain the entire memory space
|
||||
val memSize = p(ExtMem).get.master.size
|
||||
val memBase = p(ExtMem).get.master.base
|
||||
val lineSize = p(CacheBlockBytes)
|
||||
val clockFreq = p(MemoryBusKey).dtsFrequency.get
|
||||
val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, memBase, edge.bundle)).suggestName("simdram")
|
||||
mem.io.axi <> port.bits
|
||||
// Bug in Chisel implementation. See https://github.com/chipsalliance/chisel3/pull/1781
|
||||
def Decoupled[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = {
|
||||
require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.")
|
||||
val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits)))
|
||||
d.bits := irr.bits
|
||||
d.valid := irr.valid
|
||||
irr.ready := d.ready
|
||||
d
|
||||
}
|
||||
if (additionalLatency > 0) {
|
||||
withClockAndReset (port.clock, port.reset) {
|
||||
mem.io.axi.aw <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.aw))((t, _) => Queue(t, 1, pipe=true))
|
||||
mem.io.axi.w <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.w ))((t, _) => Queue(t, 1, pipe=true))
|
||||
port.bits.b <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.b))((t, _) => Queue(t, 1, pipe=true))
|
||||
mem.io.axi.ar <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.ar))((t, _) => Queue(t, 1, pipe=true))
|
||||
port.bits.r <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.r))((t, _) => Queue(t, 1, pipe=true))
|
||||
}
|
||||
}
|
||||
mem.io.clock := port.clock
|
||||
mem.io.reset := port.reset
|
||||
class WithSimAXIMMIO extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: AXI4MMIOPort) => {
|
||||
val mmio_mem = LazyModule(new SimAXIMem(port.edge, size = port.params.size)(Parameters.empty))
|
||||
withClock(port.io.clock) { Module(mmio_mem.module) }
|
||||
mmio_mem.io_axi4.head <> port.io.bits
|
||||
}
|
||||
})
|
||||
|
||||
class WithTieOffInterrupts extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: ExtIntPort) => {
|
||||
port.io := 0.U
|
||||
}
|
||||
})
|
||||
|
||||
class WithTieOffL2FBusAXI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: AXI4InPort) => {
|
||||
port.io := DontCare
|
||||
port.io.bits.aw.valid := false.B
|
||||
port.io.bits.w.valid := false.B
|
||||
port.io.bits.b.ready := false.B
|
||||
port.io.bits.ar.valid := false.B
|
||||
port.io.bits.r.ready := false.B
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimJTAGDebug extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: JTAGPort) => {
|
||||
val dtm_success = WireInit(false.B)
|
||||
when (dtm_success) { th.success := true.B }
|
||||
val jtag_wire = Wire(new JTAGIO)
|
||||
jtag_wire.TDO.data := port.io.TDO
|
||||
jtag_wire.TDO.driven := true.B
|
||||
port.io.TCK := jtag_wire.TCK
|
||||
port.io.TMS := jtag_wire.TMS
|
||||
port.io.TDI := jtag_wire.TDI
|
||||
val jtag = Module(new SimJTAG(tickDelay=3))
|
||||
jtag.connect(jtag_wire, th.harnessBinderClock, th.harnessBinderReset.asBool, ~(th.harnessBinderReset.asBool), dtm_success)
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimDMI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: DMIPort) => {
|
||||
val dtm_success = WireInit(false.B)
|
||||
when (dtm_success) { th.success := true.B }
|
||||
val dtm = Module(new TestchipSimDTM()(Parameters.empty)).connect(th.harnessBinderClock, th.harnessBinderReset.asBool, port.io, dtm_success)
|
||||
}
|
||||
})
|
||||
|
||||
class WithTiedOffJTAG extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: JTAGPort) => {
|
||||
port.io.TCK := true.B.asClock
|
||||
port.io.TMS := true.B
|
||||
port.io.TDI := true.B
|
||||
}
|
||||
})
|
||||
|
||||
class WithTiedOffDMI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: DMIPort) => {
|
||||
port.io.dmi.req.valid := false.B
|
||||
port.io.dmi.req.bits := DontCare
|
||||
port.io.dmi.resp.ready := true.B
|
||||
port.io.dmiClock := false.B.asClock
|
||||
port.io.dmiReset := true.B
|
||||
}
|
||||
})
|
||||
|
||||
class WithSerialTLTiedOff extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SerialTLPort) => {
|
||||
if (DataMirror.directionOf(port.io.clock) == Direction.Input) {
|
||||
port.io.clock := false.B.asClock
|
||||
}
|
||||
port.io.bits.out.ready := false.B
|
||||
port.io.bits.in.valid := false.B
|
||||
port.io.bits.in.bits := DontCare
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimAXIMMIO extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterAXI4MMIOPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
|
||||
(ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) =>
|
||||
val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p))
|
||||
withClockAndReset(port.clock, port.reset) {
|
||||
Module(mmio_mem.module).suggestName("mmio_mem")
|
||||
}
|
||||
mmio_mem.io_axi4.head <> port.bits
|
||||
class WithSimTSIOverSerialTL extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SerialTLPort) => {
|
||||
val bits = port.io.bits
|
||||
if (DataMirror.directionOf(port.io.clock) == Direction.Input) {
|
||||
port.io.clock := th.harnessBinderClock
|
||||
}
|
||||
val ram = LazyModule(new SerialRAM(port.serdesser)(port.serdesser.p))
|
||||
Module(ram.module)
|
||||
ram.module.io.ser <> port.io.bits
|
||||
val tsi = Module(new SimTSI)
|
||||
tsi.io.clock := th.harnessBinderClock
|
||||
tsi.io.reset := th.harnessBinderReset
|
||||
tsi.io.tsi <> ram.module.io.tsi
|
||||
val exit = tsi.io.exit
|
||||
val success = exit === 1.U
|
||||
val error = exit >= 2.U
|
||||
assert(!error, "*** FAILED *** (exit code = %d)\n", exit >> 1.U)
|
||||
when (success) { th.success := true.B }
|
||||
}
|
||||
})
|
||||
|
||||
class WithTieOffInterrupts extends OverrideHarnessBinder({
|
||||
(system: HasExtInterruptsModuleImp, th: HasHarnessInstantiators, ports: Seq[UInt]) => {
|
||||
ports.foreach { _ := 0.U }
|
||||
class WithSimUARTToUARTTSI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTPort) => {
|
||||
UARTAdapter.connect(Seq(port.io),
|
||||
baudrate=port.io.c.initBaudRate,
|
||||
clockFrequency=th.getHarnessBinderClockFreqHz.toInt,
|
||||
forcePty=true)
|
||||
}
|
||||
})
|
||||
|
||||
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
|
||||
(system: CanHaveSlaveAXI4Port, th: HasHarnessInstantiators, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
||||
ports.foreach({ p =>
|
||||
p.bits := DontCare
|
||||
p.bits.aw.valid := false.B
|
||||
p.bits.w.valid := false.B
|
||||
p.bits.b.ready := false.B
|
||||
p.bits.ar.valid := false.B
|
||||
p.bits.r.ready := false.B
|
||||
})
|
||||
class WithSimTSIToUARTTSI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTTSIPort) => {
|
||||
val freq = th.getHarnessBinderClockFreqHz.toInt
|
||||
val uart_to_serial = Module(new UARTToSerial(freq, port.io.uart.c))
|
||||
val serial_width_adapter = Module(new SerialWidthAdapter(8, TSI.WIDTH))
|
||||
val success = SimTSI.connect(Some(TSIIO(serial_width_adapter.io.wide)), th.harnessBinderClock, th.harnessBinderReset)
|
||||
when (success) { th.success := true.B }
|
||||
assert(!uart_to_serial.io.dropped)
|
||||
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
|
||||
uart_to_serial.io.uart.rxd := port.io.uart.txd
|
||||
port.io.uart.rxd := uart_to_serial.io.uart.txd
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimDebug extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryDebug, th: HasHarnessInstantiators, ports: Seq[Data]) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
ports.map {
|
||||
case d: ClockedDMIIO =>
|
||||
val dtm_success = WireInit(false.B)
|
||||
when (dtm_success) { th.success := true.B }
|
||||
val dtm = Module(new TestchipSimDTM).connect(th.harnessBinderClock, th.harnessBinderReset.asBool, d, dtm_success)
|
||||
case j: JTAGChipIO =>
|
||||
val dtm_success = WireInit(false.B)
|
||||
when (dtm_success) { th.success := true.B }
|
||||
val jtag_wire = Wire(new JTAGIO)
|
||||
jtag_wire.TDO.data := j.TDO
|
||||
jtag_wire.TDO.driven := true.B
|
||||
j.TCK := jtag_wire.TCK
|
||||
j.TMS := jtag_wire.TMS
|
||||
j.TDI := jtag_wire.TDI
|
||||
val jtag = Module(new SimJTAG(tickDelay=3))
|
||||
jtag.connect(jtag_wire, th.harnessBinderClock, th.harnessBinderReset.asBool, ~(th.harnessBinderReset.asBool), dtm_success)
|
||||
}
|
||||
class WithTraceGenSuccess extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SuccessPort) => {
|
||||
when (port.io) { th.success := true.B }
|
||||
}
|
||||
})
|
||||
|
||||
class WithTiedOffDebug extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryDebug, th: HasHarnessInstantiators, ports: Seq[Data]) => {
|
||||
ports.map {
|
||||
case j: JTAGChipIO =>
|
||||
j.TCK := true.B.asClock
|
||||
j.TMS := true.B
|
||||
j.TDI := true.B
|
||||
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 a: ClockedAPBBundle =>
|
||||
a.pready := false.B
|
||||
a.pslverr := false.B
|
||||
a.prdata := 0.U
|
||||
a.pduser := DontCare
|
||||
a.clock := false.B.asClock
|
||||
a.reset := true.B.asAsyncReset
|
||||
a.psel := false.B
|
||||
a.penable := false.B
|
||||
}
|
||||
class WithCospike extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: TracePort) => {
|
||||
port.io.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, port.cosimCfg))
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithSerialTLTiedOff extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||
ports.map({ port =>
|
||||
val bits = port.bits
|
||||
if (DataMirror.directionOf(port.clock) == Direction.Input) {
|
||||
port.clock := false.B.asClock
|
||||
}
|
||||
port.bits.out.ready := false.B
|
||||
port.bits.in.valid := false.B
|
||||
port.bits.in.bits := DontCare
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimTSIOverSerialTL extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||
ports.map({ port =>
|
||||
val bits = port.bits
|
||||
if (DataMirror.directionOf(port.clock) == Direction.Input) {
|
||||
port.clock := th.harnessBinderClock
|
||||
}
|
||||
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
|
||||
val success = SimTSI.connect(Some(ram.module.io.tsi), th.harnessBinderClock, th.harnessBinderReset.asBool)
|
||||
when (success) { th.success := true.B }
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimUARTToUARTTSI extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => {
|
||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||
require(ports.size <= 1)
|
||||
ports.map { port => {
|
||||
UARTAdapter.connect(Seq(port.uart),
|
||||
baudrate=port.uartParams.initBaudRate,
|
||||
clockFrequency=th.getHarnessBinderClockFreqHz.toInt,
|
||||
forcePty=true)
|
||||
assert(!port.dropped)
|
||||
}}
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimTSIToUARTTSI extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => {
|
||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||
require(ports.size <= 1)
|
||||
ports.map({ port =>
|
||||
val freq = th.getHarnessBinderClockFreqHz.toInt
|
||||
val uart_to_serial = Module(new UARTToSerial(freq, port.uartParams))
|
||||
val serial_width_adapter = Module(new SerialWidthAdapter(8, TSI.WIDTH))
|
||||
val success = SimTSI.connect(Some(TSIIO(serial_width_adapter.io.wide)), th.harnessBinderClock, th.harnessBinderReset)
|
||||
when (success) { th.success := true.B }
|
||||
assert(!uart_to_serial.io.dropped)
|
||||
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
|
||||
uart_to_serial.io.uart.rxd := port.uart.txd
|
||||
port.uart.rxd := uart_to_serial.io.uart.txd
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithTraceGenSuccess extends OverrideHarnessBinder({
|
||||
(system: TraceGenSystemModuleImp, th: HasHarnessInstantiators, ports: Seq[Bool]) => {
|
||||
ports.map { p => when (p) { th.success := true.B } }
|
||||
}
|
||||
})
|
||||
|
||||
class WithCospike extends ComposeHarnessBinder({
|
||||
(system: CanHaveTraceIOModuleImp, th: HasHarnessInstantiators, ports: Seq[TraceOutputTop]) => {
|
||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||
val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem]
|
||||
val tiles = chipyardSystem.tiles
|
||||
val cfg = SpikeCosimConfig(
|
||||
isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
|
||||
vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0),
|
||||
priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""),
|
||||
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
|
||||
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
|
||||
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
|
||||
nharts = tiles.size,
|
||||
bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse(""),
|
||||
has_dtm = p(ExportDebug).protocols.contains(DMI) // assume that exposing clockeddmi means we will connect SimDTM
|
||||
)
|
||||
ports.map { p => p.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, cfg)) }
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithCustomBootPinPlusArg extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryCustomBootPin, th: HasHarnessInstantiators, ports: Seq[Bool]) => {
|
||||
class WithCustomBootPinPlusArg extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: CustomBootPort) => {
|
||||
val pin = PlusArg("custom_boot_pin", width=1)
|
||||
ports.foreach(_ := pin)
|
||||
port.io := pin
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithClockAndResetFromHarness extends OverrideHarnessBinder({
|
||||
(system: HasChipyardPRCI, th: HasHarnessInstantiators, ports: Seq[Data]) => {
|
||||
implicit val p = GetSystemParameters(system)
|
||||
val clocks = ports.collect { case c: ClockWithFreq => c }
|
||||
class WithClockFromHarness extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: ClockPort) => {
|
||||
// DOC include start: HarnessClockInstantiatorEx
|
||||
ports.map ({
|
||||
case c: ClockWithFreq => {
|
||||
val clock = th.harnessClockInstantiator.requestClockMHz(s"clock_${c.freqMHz.toInt}MHz", c.freqMHz)
|
||||
c.clock := clock
|
||||
}
|
||||
case r: AsyncReset => r := th.referenceReset.asAsyncReset
|
||||
})
|
||||
port.io := th.harnessClockInstantiator.requestClockMHz(s"clock_${port.freqMHz}MHz", port.freqMHz)
|
||||
// DOC include end: HarnessClockInstantiatorEx
|
||||
}
|
||||
})
|
||||
|
||||
class WithResetFromHarness extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: ResetPort) => {
|
||||
port.io := th.referenceReset.asAsyncReset
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ trait HasHarnessInstantiators {
|
||||
|
||||
withClockAndReset (harnessBinderClock, harnessBinderReset) {
|
||||
lazyDuts.zipWithIndex.foreach {
|
||||
case (d: HasIOBinders, i: Int) => ApplyHarnessBinders(this, d.lazySystem, d.portMap)(chipParameters(i))
|
||||
case (d: HasIOBinders, i: Int) => ApplyHarnessBinders(this, d.portMap.values.flatten.toSeq)(chipParameters(i))
|
||||
case _ =>
|
||||
}
|
||||
ApplyMultiHarnessBinders(this, lazyDuts)
|
||||
|
||||
@@ -2,6 +2,7 @@ package chipyard.harness
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chisel3.experimental.{DataMirror, Direction}
|
||||
|
||||
import org.chipsalliance.cde.config.{Field, Config, Parameters}
|
||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
||||
@@ -12,67 +13,58 @@ import freechips.rocketchip.util._
|
||||
import testchipip._
|
||||
|
||||
import chipyard._
|
||||
import chipyard.clocking.{HasChipyardPRCI, ClockWithFreq}
|
||||
import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasIOBinders}
|
||||
import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasIOBinders, Port, SerialTLPort}
|
||||
|
||||
import scala.reflect.{ClassTag}
|
||||
|
||||
case class MultiHarnessBinders(c0: Int, c1: Int) extends Field[MultiHarnessBinderMap](MultiHarnessBinderMapDefault)
|
||||
|
||||
class MultiHarnessBinder[T0, T1, S <: HasHarnessInstantiators, U0 <: Data, U1 <: Data]
|
||||
(chip0: Int, chip1: Int, fn: => (T0, T1, S, Seq[U0], Seq[U1]) => Unit)
|
||||
(implicit tag0: ClassTag[T0], tag1: ClassTag[T1], thtag: ClassTag[S], ptag0: ClassTag[U0], ptag1: ClassTag[U1])
|
||||
extends Config((site, here, up) => {
|
||||
// Override any HarnessBinders for chip0/chip1
|
||||
case MultiChipParameters(`chip0`) => new Config(
|
||||
new OverrideHarnessBinder[T0, S, U0]((system: T0, th: S, ports: Seq[U0]) => Nil) ++
|
||||
up(MultiChipParameters(chip0))
|
||||
)
|
||||
case MultiChipParameters(`chip1`) => new Config(
|
||||
new OverrideHarnessBinder[T1, S, U1]((system: T1, th: S, ports: Seq[U1]) => Nil) ++
|
||||
up(MultiChipParameters(chip1))
|
||||
)
|
||||
// Set the multiharnessbinder key
|
||||
case MultiHarnessBinders(`chip0`, `chip1`) => up(MultiHarnessBinders(chip0, chip1)) +
|
||||
((tag0.runtimeClass.toString, tag1.runtimeClass.toString) ->
|
||||
((c0: Any, c1: Any, th: HasHarnessInstantiators, ports0: Seq[Data], ports1: Seq[Data]) => {
|
||||
val pts0 = ports0.map(_.asInstanceOf[U0])
|
||||
val pts1 = ports1.map(_.asInstanceOf[U1])
|
||||
require(pts0.size == pts1.size)
|
||||
(c0, c1, th) match {
|
||||
case (c0: T0, c1: T1, th: S) => fn(c0, c1, th, pts0, pts1)
|
||||
case _ =>
|
||||
}
|
||||
})
|
||||
)
|
||||
})
|
||||
case class MultiHarnessBinders(chip0: Int, chip1: Int) extends Field[Seq[MultiHarnessBinderFunction]](Nil)
|
||||
|
||||
object ApplyMultiHarnessBinders {
|
||||
def apply(th: HasHarnessInstantiators, chips: Seq[LazyModule])(implicit p: Parameters): Unit = {
|
||||
Seq.tabulate(chips.size, chips.size) { case (i, j) => if (i != j) {
|
||||
(chips(i), chips(j)) match {
|
||||
case (l0: HasIOBinders, l1: HasIOBinders) => p(MultiHarnessBinders(i, j)).foreach {
|
||||
case ((s0, s1), f) => {
|
||||
f(l0.lazySystem , l1.lazySystem , th, l0.portMap(s0), l1.portMap(s1))
|
||||
f(l0.lazySystem.module, l1.lazySystem.module, th, l0.portMap(s0), l1.portMap(s1))
|
||||
}
|
||||
case (l0: HasIOBinders, l1: HasIOBinders) => p(MultiHarnessBinders(i, j)).foreach { f =>
|
||||
f(l0.portMap.values.flatten.toSeq, l1.portMap.values.flatten.toSeq)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
class WithMultiChipSerialTL(chip0: Int, chip1: Int) extends MultiHarnessBinder(chip0, chip1, (
|
||||
(system0: CanHavePeripheryTLSerial, system1: CanHavePeripheryTLSerial,
|
||||
th: HasHarnessInstantiators,
|
||||
ports0: Seq[ClockedIO[SerialIO]], ports1: Seq[ClockedIO[SerialIO]]
|
||||
) => {
|
||||
require(ports0.size == ports1.size)
|
||||
(ports0 zip ports1).map { case (l, r) =>
|
||||
l.clock <> r.clock
|
||||
require(l.bits.w == r.bits.w)
|
||||
l.bits.flipConnect(r.bits)
|
||||
class MultiHarnessBinder[T <: Port[_]](
|
||||
chip0: Int, chip1: Int,
|
||||
chip0portFn: T => Boolean, chip1portFn: T => Boolean,
|
||||
connectFn: (T, T) => Unit
|
||||
)(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
|
||||
// Override any HarnessBinders for chip0/chip1
|
||||
case MultiChipParameters(`chip0`) => new Config(
|
||||
new HarnessBinder({case (th, port: T) if chip0portFn(port) => }) ++ up(MultiChipParameters(chip0))
|
||||
)
|
||||
case MultiChipParameters(`chip1`) => new Config(
|
||||
new HarnessBinder({case (th, port: T) if chip1portFn(port) => }) ++ up(MultiChipParameters(chip1))
|
||||
)
|
||||
// Set the multiharnessbinder key
|
||||
case MultiHarnessBinders(`chip0`, `chip1`) => up(MultiHarnessBinders(chip0, chip1)) :+ {
|
||||
((chip0Ports: Seq[Port[_]], chip1Ports: Seq[Port[_]]) => {
|
||||
val chip0Port: Seq[T] = chip0Ports.collect { case (p: T) if chip0portFn(p) => p }
|
||||
val chip1Port: Seq[T] = chip1Ports.collect { case (p: T) if chip1portFn(p) => p }
|
||||
require(chip0Port.size == 1 && chip1Port.size == 1)
|
||||
connectFn(chip0Port(0), chip1Port(0))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithMultiChipSerialTL(chip0: Int, chip1: Int, chip0portId: Int = 0, chip1portId: Int = 0) extends MultiHarnessBinder[SerialTLPort](
|
||||
chip0, chip1,
|
||||
(p0: SerialTLPort) => p0.portId == chip0portId,
|
||||
(p1: SerialTLPort) => p1.portId == chip1portId,
|
||||
(p0: SerialTLPort, p1: SerialTLPort) => {
|
||||
(DataMirror.directionOf(p0.io.clock), DataMirror.directionOf(p1.io.clock)) match {
|
||||
case (Direction.Input, Direction.Output) => p0.io.clock := p1.io.clock
|
||||
case (Direction.Output, Direction.Input) => p1.io.clock := p0.io.clock
|
||||
}
|
||||
p0.io.bits.in <> p1.io.bits.out
|
||||
p1.io.bits.in <> p0.io.bits.out
|
||||
}
|
||||
))
|
||||
)
|
||||
|
||||
@@ -5,13 +5,7 @@ import scala.collection.immutable.ListMap
|
||||
|
||||
package object harness
|
||||
{
|
||||
type HarnessBinderFunction = (Any, HasHarnessInstantiators, Seq[Data]) => Unit
|
||||
type HarnessBinderMap = Map[String, HarnessBinderFunction]
|
||||
def HarnessBinderMapDefault: HarnessBinderMap = (new ListMap[String, HarnessBinderFunction])
|
||||
.withDefaultValue((t: Any, th: HasHarnessInstantiators, d: Seq[Data]) => ())
|
||||
|
||||
type MultiHarnessBinderFunction = (Any, Any, HasHarnessInstantiators, Seq[Data], Seq[Data]) => Unit
|
||||
type MultiHarnessBinderMap = Map[(String, String), MultiHarnessBinderFunction]
|
||||
def MultiHarnessBinderMapDefault: MultiHarnessBinderMap = (new ListMap[(String, String), MultiHarnessBinderFunction])
|
||||
.withDefaultValue((_: Any, _: Any, _: HasHarnessInstantiators, _: Seq[Data], _: Seq[Data]) => ())
|
||||
import chipyard.iobinders.Port
|
||||
type HarnessBinderFunction = PartialFunction[(HasHarnessInstantiators, Port[_]), Unit]
|
||||
type MultiHarnessBinderFunction = (Seq[Port[_]], Seq[Port[_]]) => Unit
|
||||
}
|
||||
|
||||
@@ -18,18 +18,19 @@ import freechips.rocketchip.tilelink.{TLBundle}
|
||||
import sifive.blocks.devices.gpio._
|
||||
import sifive.blocks.devices.uart._
|
||||
import sifive.blocks.devices.spi._
|
||||
import sifive.blocks.devices.i2c._
|
||||
import tracegen.{TraceGenSystemModuleImp}
|
||||
|
||||
import barstools.iocell.chisel._
|
||||
|
||||
import testchipip._
|
||||
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
|
||||
import chipyard.{CanHaveMasterTLMemPort}
|
||||
import chipyard.{CanHaveMasterTLMemPort, ChipyardSystem, ChipyardSystemModule}
|
||||
|
||||
import scala.reflect.{ClassTag}
|
||||
|
||||
object IOBinderTypes {
|
||||
type IOBinderTuple = (Seq[Data], Seq[IOCell])
|
||||
type IOBinderTuple = (Seq[Port[_]], Seq[IOCell])
|
||||
type IOBinderFunction = (Boolean, => Any) => ModuleValue[IOBinderTuple]
|
||||
}
|
||||
import IOBinderTypes._
|
||||
@@ -82,7 +83,7 @@ abstract trait HasIOBinders { this: LazyModule =>
|
||||
|
||||
InModuleBody {
|
||||
if (p(DontTouchIOBindersPorts)) {
|
||||
portMap.values.foreach(_.foreach(dontTouch(_)))
|
||||
portMap.values.flatten.foreach { case (port: Port[Data]) => dontTouch(port.io) }
|
||||
}
|
||||
|
||||
println("IOCells generated by IOBinders:")
|
||||
@@ -171,29 +172,72 @@ class WithGPIOCells extends OverrideIOBinder({
|
||||
iocell.io.ie := pin.o.ie
|
||||
pin.i.ival := iocell.io.i
|
||||
iocell.io.pad <> g
|
||||
(g, iocell)
|
||||
(GPIOPort(g, i, j), iocell)
|
||||
}).unzip
|
||||
}).unzip
|
||||
val ports: Seq[Analog] = ports2d.flatten
|
||||
(ports, cells2d.flatten)
|
||||
(ports2d.flatten, cells2d.flatten)
|
||||
}
|
||||
})
|
||||
|
||||
class WithGPIOPunchthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryGPIOModuleImp) => {
|
||||
val ports = system.gpio.zipWithIndex.map { case (gpio, i) =>
|
||||
val io_gpio = IO(gpio.cloneType).suggestName(s"gpio_$i")
|
||||
io_gpio <> gpio
|
||||
GPIOPinsPort(io_gpio, i)
|
||||
}
|
||||
(ports, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithI2CPunchthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryI2CModuleImp) => {
|
||||
val ports = system.i2c.zipWithIndex.map { case (i2c, i) =>
|
||||
val io_i2c = IO(i2c.cloneType).suggestName(s"i2c_$i")
|
||||
io_i2c <> i2c
|
||||
I2CPort(i2c)
|
||||
}
|
||||
(ports, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
// DOC include start: WithUARTIOCells
|
||||
class WithUARTIOCells extends OverrideIOBinder({
|
||||
(system: HasPeripheryUARTModuleImp) => {
|
||||
val (ports: Seq[UARTPortIO], cells2d) = system.uart.zipWithIndex.map({ case (u, i) =>
|
||||
val (ports: Seq[UARTPort], cells2d) = system.uart.zipWithIndex.map({ case (u, i) =>
|
||||
val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey), abstractResetAsAsync = true)
|
||||
(port, ios)
|
||||
val where = PBUS // TODO fix
|
||||
val bus = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where)
|
||||
val freqMHz = bus.dtsFrequency.get.toInt / 1000000000
|
||||
(UARTPort(port, i, freqMHz), ios)
|
||||
}).unzip
|
||||
(ports, cells2d.flatten)
|
||||
}
|
||||
})
|
||||
// DOC include end: WithUARTIOCells
|
||||
|
||||
class WithSPIIOCells extends OverrideIOBinder({
|
||||
class WithSPIIOPunchthrough extends OverrideLazyIOBinder({
|
||||
(system: HasPeripherySPI) => {
|
||||
// attach resource to 1st SPI
|
||||
if (system.tlSpiNodes.size > 0) ResourceBinding {
|
||||
Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0))
|
||||
}
|
||||
InModuleBody {
|
||||
val spi = system.asInstanceOf[BaseSubsystem].module.asInstanceOf[HasPeripherySPIBundle].spi
|
||||
val ports = spi.zipWithIndex.map({ case (s, i) =>
|
||||
val io_spi = IO(s.cloneType).suggestName(s"spi_$i")
|
||||
io_spi <> s
|
||||
SPIPort(io_spi)
|
||||
})
|
||||
(ports, Nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithSPIFlashIOCells extends OverrideIOBinder({
|
||||
(system: HasPeripherySPIFlashModuleImp) => {
|
||||
val (ports: Seq[SPIChipIO], cells2d) = system.qspi.zipWithIndex.map({ case (s, i) =>
|
||||
val (ports: Seq[SPIFlashPort], cells2d) = system.qspi.zipWithIndex.map({ case (s, i) =>
|
||||
|
||||
val name = s"spi_${i}"
|
||||
val port = IO(new SPIChipIO(s.c.csWidth)).suggestName(name)
|
||||
val iocellBase = s"iocell_${name}"
|
||||
@@ -213,7 +257,7 @@ class WithSPIIOCells extends OverrideIOBinder({
|
||||
iocell
|
||||
}
|
||||
|
||||
(port, dqIOs ++ csIOs ++ sckIOs)
|
||||
(SPIFlashPort(port, system.p(PeripherySPIFlashKey)(i), i), dqIOs ++ csIOs ++ sckIOs)
|
||||
}).unzip
|
||||
(ports, cells2d.flatten)
|
||||
}
|
||||
@@ -223,7 +267,7 @@ class WithExtInterruptIOCells extends OverrideIOBinder({
|
||||
(system: HasExtInterruptsModuleImp) => {
|
||||
if (system.outer.nExtInterrupts > 0) {
|
||||
val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey), abstractResetAsAsync = true)
|
||||
(Seq(port), cells)
|
||||
(Seq(ExtIntPort(port)), cells)
|
||||
} else {
|
||||
system.interrupts := DontCare // why do I have to drive this 0-wide wire???
|
||||
(Nil, Nil)
|
||||
@@ -273,7 +317,8 @@ class WithDebugIOCells extends OverrideLazyIOBinder({
|
||||
|
||||
// Add IOCells for the DMI/JTAG/APB ports
|
||||
val dmiTuple = debug.clockeddmi.map { d =>
|
||||
IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true)
|
||||
val (port, cells) = IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true)
|
||||
(DMIPort(port), cells)
|
||||
}
|
||||
|
||||
val jtagTuple = debug.systemjtag.map { j =>
|
||||
@@ -282,14 +327,13 @@ class WithDebugIOCells extends OverrideLazyIOBinder({
|
||||
j.jtag.TMS := jtag_wire.TMS
|
||||
j.jtag.TDI := jtag_wire.TDI
|
||||
jtag_wire.TDO := j.jtag.TDO.data
|
||||
IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true)
|
||||
val (port, cells) = IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true)
|
||||
(JTAGPort(port), cells)
|
||||
}
|
||||
|
||||
val apbTuple = debug.apb.map { a =>
|
||||
IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = true)
|
||||
}
|
||||
require(!debug.apb.isDefined)
|
||||
|
||||
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
|
||||
val allTuples = (dmiTuple ++ jtagTuple).toSeq
|
||||
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
|
||||
}).getOrElse((Nil, Nil))
|
||||
}}}
|
||||
@@ -297,20 +341,26 @@ class WithDebugIOCells extends OverrideLazyIOBinder({
|
||||
})
|
||||
|
||||
class WithSerialTLIOCells extends OverrideIOBinder({
|
||||
(system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s =>
|
||||
val sys = system.asInstanceOf[BaseSubsystem]
|
||||
val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey), abstractResetAsAsync = true)
|
||||
(Seq(port), cells)
|
||||
}).getOrElse((Nil, Nil))
|
||||
(system: CanHavePeripheryTLSerial) => {
|
||||
val (ports, cells) = system.serial_tl.zipWithIndex.map({ case (s, id) =>
|
||||
val sys = system.asInstanceOf[BaseSubsystem]
|
||||
val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey), abstractResetAsAsync = true)
|
||||
(SerialTLPort(port, sys.p(SerialTLKey).get, system.serdesser.get, id), cells)
|
||||
}).unzip
|
||||
(ports.toSeq, cells.flatten.toSeq)
|
||||
}
|
||||
})
|
||||
|
||||
class WithSerialTLPunchthrough extends OverrideIOBinder({
|
||||
(system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s =>
|
||||
val sys = system.asInstanceOf[BaseSubsystem]
|
||||
val port = IO(s.getWrappedValue.cloneType)
|
||||
port <> s.getWrappedValue
|
||||
(Seq(port), Nil)
|
||||
}).getOrElse((Nil, Nil))
|
||||
(system: CanHavePeripheryTLSerial) => {
|
||||
val (ports, cells) = system.serial_tl.zipWithIndex.map({ case (s, id) =>
|
||||
val sys = system.asInstanceOf[BaseSubsystem]
|
||||
val port = IO(s.getWrappedValue.cloneType)
|
||||
port <> s.getWrappedValue
|
||||
(SerialTLPort(port, sys.p(SerialTLKey).get, system.serdesser.get, id), Nil)
|
||||
}).unzip
|
||||
(ports.toSeq, cells.flatten.toSeq)
|
||||
}
|
||||
})
|
||||
|
||||
class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
|
||||
@@ -321,12 +371,11 @@ class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
|
||||
def clockBundle = clockSinkNode.get.in.head._1
|
||||
|
||||
InModuleBody {
|
||||
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
||||
p.bits <> m
|
||||
p.clock := clockBundle.clock
|
||||
p.reset := clockBundle.reset
|
||||
p
|
||||
val ports: Seq[AXI4MemPort] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val port = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
||||
port.bits <> m
|
||||
port.clock := clockBundle.clock
|
||||
AXI4MemPort(port, p(ExtMem).get, system.memAXI4Node.edges.in(i), p(MemoryBusKey).dtsFrequency.get.toInt)
|
||||
}).toSeq
|
||||
(ports, Nil)
|
||||
}
|
||||
@@ -341,12 +390,11 @@ class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({
|
||||
def clockBundle = clockSinkNode.get.in.head._1
|
||||
|
||||
InModuleBody {
|
||||
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
|
||||
p.bits <> m
|
||||
p.clock := clockBundle.clock
|
||||
p.reset := clockBundle.reset
|
||||
p
|
||||
val ports: Seq[AXI4MMIOPort] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val port = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
|
||||
port.bits <> m
|
||||
port.clock := clockBundle.clock
|
||||
AXI4MMIOPort(port, p(ExtBus).get, system.mmioAXI4Node.edges.in(i))
|
||||
}).toSeq
|
||||
(ports, Nil)
|
||||
}
|
||||
@@ -361,11 +409,11 @@ class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({
|
||||
def clockBundle = clockSinkNode.get.in.head._1
|
||||
|
||||
InModuleBody {
|
||||
val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}")
|
||||
m <> p.bits
|
||||
p.clock := clockBundle.clock
|
||||
p
|
||||
val ports: Seq[AXI4InPort] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) =>
|
||||
val port = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}")
|
||||
m <> port.bits
|
||||
port.clock := clockBundle.clock
|
||||
AXI4InPort(port, p(ExtIn).get)
|
||||
}).toSeq
|
||||
(ports, Nil)
|
||||
}
|
||||
@@ -374,10 +422,12 @@ class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({
|
||||
|
||||
class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({
|
||||
(system: CanHavePeripheryBlockDevice) => {
|
||||
val ports: Seq[ClockedIO[BlockDeviceIO]] = system.bdev.map({ bdev =>
|
||||
val p = IO(new ClockedIO(new BlockDeviceIO()(GetSystemParameters(system)))).suggestName("blockdev")
|
||||
p <> bdev
|
||||
p
|
||||
val ports: Seq[BlockDevicePort] = system.bdev.map({ bdev =>
|
||||
val p = GetSystemParameters(system)
|
||||
val bdParams = p(BlockDeviceKey).get
|
||||
val port = IO(new ClockedIO(new BlockDeviceIO(bdParams))).suggestName("blockdev")
|
||||
port <> bdev
|
||||
BlockDevicePort(port, bdParams)
|
||||
}).toSeq
|
||||
(ports, Nil)
|
||||
}
|
||||
@@ -385,10 +435,11 @@ class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({
|
||||
|
||||
class WithNICIOPunchthrough extends OverrideIOBinder({
|
||||
(system: CanHavePeripheryIceNIC) => {
|
||||
val ports: Seq[ClockedIO[NICIOvonly]] = system.icenicOpt.map({ n =>
|
||||
val p = IO(new ClockedIO(new NICIOvonly)).suggestName("nic")
|
||||
p <> n
|
||||
p
|
||||
val ports: Seq[NICPort] = system.icenicOpt.map({ n =>
|
||||
val p = GetSystemParameters(system)
|
||||
val port = IO(new ClockedIO(new NICIOvonly)).suggestName("nic")
|
||||
port <> n
|
||||
NICPort(port, p(NICKey).get)
|
||||
}).toSeq
|
||||
(ports, Nil)
|
||||
}
|
||||
@@ -398,16 +449,30 @@ class WithTraceGenSuccessPunchthrough extends OverrideIOBinder({
|
||||
(system: TraceGenSystemModuleImp) => {
|
||||
val success: Bool = IO(Output(Bool())).suggestName("success")
|
||||
success := system.success
|
||||
(Seq(success), Nil)
|
||||
(Seq(SuccessPort(success)), Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithTraceIOPunchthrough extends OverrideIOBinder({
|
||||
(system: CanHaveTraceIOModuleImp) => {
|
||||
val ports: Option[TraceOutputTop] = system.traceIO.map { t =>
|
||||
val ports: Option[TracePort] = system.traceIO.map { t =>
|
||||
val trace = IO(DataMirror.internal.chiselTypeClone[TraceOutputTop](t)).suggestName("trace")
|
||||
trace <> t
|
||||
trace
|
||||
val p = GetSystemParameters(system)
|
||||
val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem]
|
||||
val tiles = chipyardSystem.tiles
|
||||
val cfg = SpikeCosimConfig(
|
||||
isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
|
||||
vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0),
|
||||
priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""),
|
||||
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
|
||||
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
|
||||
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
|
||||
nharts = tiles.size,
|
||||
bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse(""),
|
||||
has_dtm = p(ExportDebug).protocols.contains(DMI) // assume that exposing clockeddmi means we will connect SimDTM
|
||||
)
|
||||
TracePort(trace, cfg)
|
||||
}
|
||||
(ports.toSeq, Nil)
|
||||
}
|
||||
@@ -417,7 +482,7 @@ class WithCustomBootPin extends OverrideIOBinder({
|
||||
(system: CanHavePeripheryCustomBootPin) => system.custom_boot_pin.map({ p =>
|
||||
val sys = system.asInstanceOf[BaseSubsystem]
|
||||
val (port, cells) = IOCell.generateIOFromSignal(p.getWrappedValue, "custom_boot", sys.p(IOCellKey), abstractResetAsAsync = true)
|
||||
(Seq(port), cells)
|
||||
(Seq(CustomBootPort(port)), cells)
|
||||
}).getOrElse((Nil, Nil))
|
||||
})
|
||||
|
||||
@@ -426,7 +491,7 @@ class WithUARTTSIPunchthrough extends OverrideIOBinder({
|
||||
val sys = system.asInstanceOf[BaseSubsystem]
|
||||
val uart_tsi = IO(new UARTTSIIO(p.uartParams))
|
||||
uart_tsi <> p
|
||||
(Seq(uart_tsi), Nil)
|
||||
(Seq(UARTTSIPort(uart_tsi)), Nil)
|
||||
}).getOrElse((Nil, Nil))
|
||||
})
|
||||
|
||||
@@ -434,7 +499,7 @@ class WithTLMemPunchthrough extends OverrideIOBinder({
|
||||
(system: CanHaveMasterTLMemPort) => {
|
||||
val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.mem_tl)).suggestName("tl_slave")
|
||||
io_tl_mem_pins_temp <> system.mem_tl
|
||||
(Seq(io_tl_mem_pins_temp), Nil)
|
||||
(Seq(TLMemPort(io_tl_mem_pins_temp)), Nil)
|
||||
}
|
||||
})
|
||||
|
||||
94
generators/chipyard/src/main/scala/iobinders/Ports.scala
Normal file
94
generators/chipyard/src/main/scala/iobinders/Ports.scala
Normal file
@@ -0,0 +1,94 @@
|
||||
package chipyard.iobinders
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{Analog}
|
||||
import sifive.blocks.devices.uart.{UARTPortIO}
|
||||
import sifive.blocks.devices.spi.{SPIFlashParams, SPIPortIO}
|
||||
import sifive.blocks.devices.i2c.{I2CPort}
|
||||
import sifive.blocks.devices.gpio.{GPIOPortIO}
|
||||
import testchipip._
|
||||
import icenet.{NICIOvonly, NICConfig}
|
||||
import org.chipsalliance.cde.config.{Parameters}
|
||||
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4EdgeParameters}
|
||||
import freechips.rocketchip.subsystem.{MemoryPortParams, MasterPortParams, SlavePortParams}
|
||||
import freechips.rocketchip.devices.debug.{ClockedDMIIO}
|
||||
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||
import freechips.rocketchip.tilelink.{TLBundle}
|
||||
|
||||
trait Port[T <: Data] {
|
||||
val io: T
|
||||
}
|
||||
|
||||
// These case classes are generated by IOBinders, and interpreted by HarnessBinders
|
||||
case class GPIOPort (val io: Analog, val gpioId: Int, val pinId: Int)
|
||||
extends Port[Analog]
|
||||
|
||||
case class GPIOPinsPort (val io: GPIOPortIO, val gpioId: Int)
|
||||
extends Port[GPIOPortIO]
|
||||
|
||||
case class I2CPort (val io: sifive.blocks.devices.i2c.I2CPort)
|
||||
extends Port[sifive.blocks.devices.i2c.I2CPort]
|
||||
|
||||
case class UARTPort (val io: UARTPortIO, val uartNo: Int, val freqMHz: Int)
|
||||
extends Port[UARTPortIO]
|
||||
|
||||
case class SPIFlashPort (val io: SPIChipIO, val params: SPIFlashParams, val spiId: Int)
|
||||
extends Port[SPIChipIO]
|
||||
|
||||
case class SPIPort (val io: SPIPortIO)
|
||||
extends Port[SPIPortIO]
|
||||
|
||||
case class BlockDevicePort (val io: ClockedIO[BlockDeviceIO], val params: BlockDeviceConfig)
|
||||
extends Port[ClockedIO[BlockDeviceIO]]
|
||||
|
||||
case class NICPort (val io: ClockedIO[NICIOvonly], val params: NICConfig)
|
||||
extends Port[ClockedIO[NICIOvonly]]
|
||||
|
||||
case class AXI4MemPort (val io: ClockedIO[AXI4Bundle], val params: MemoryPortParams, val edge: AXI4EdgeParameters, val clockFreqMHz: Int)
|
||||
extends Port[ClockedIO[AXI4Bundle]]
|
||||
|
||||
case class AXI4MMIOPort (val io: ClockedIO[AXI4Bundle], val params: MasterPortParams, val edge: AXI4EdgeParameters)
|
||||
extends Port[ClockedIO[AXI4Bundle]]
|
||||
|
||||
case class AXI4InPort (val io: ClockedIO[AXI4Bundle], val params: SlavePortParams)
|
||||
extends Port[ClockedIO[AXI4Bundle]]
|
||||
|
||||
case class ExtIntPort (val io: UInt)
|
||||
extends Port[UInt]
|
||||
|
||||
case class DMIPort (val io: ClockedDMIIO)
|
||||
extends Port[ClockedDMIIO]
|
||||
|
||||
case class JTAGPort (val io: JTAGChipIO)
|
||||
extends Port[JTAGChipIO]
|
||||
|
||||
case class SerialTLPort (val io: ClockedIO[SerialIO], val params: SerialTLParams, val serdesser: TLSerdesser, val portId: Int)
|
||||
extends Port[ClockedIO[SerialIO]]
|
||||
|
||||
case class UARTTSIPort (val io: UARTTSIIO)
|
||||
extends Port[UARTTSIIO]
|
||||
|
||||
case class SuccessPort (val io: Bool)
|
||||
extends Port[Bool]
|
||||
|
||||
case class TracePort (val io: TraceOutputTop, val cosimCfg: SpikeCosimConfig)
|
||||
extends Port[TraceOutputTop]
|
||||
|
||||
case class CustomBootPort (val io: Bool)
|
||||
extends Port[Bool]
|
||||
|
||||
case class ClockPort (val io: Clock, val freqMHz: Double)
|
||||
extends Port[Clock]
|
||||
|
||||
case class ResetPort (val io: AsyncReset)
|
||||
extends Port[Reset]
|
||||
|
||||
case class DebugResetPort (val io: Reset)
|
||||
extends Port[Reset]
|
||||
|
||||
case class JTAGResetPort (val io: Reset)
|
||||
extends Port[Reset]
|
||||
|
||||
case class TLMemPort (val io: HeterogeneousBag[TLBundle])
|
||||
extends Port[HeterogeneousBag[TLBundle]]
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
package firesim.firesim
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.annotate
|
||||
import chisel3.experimental.{DataMirror, Direction}
|
||||
import chisel3.util.experimental.BoringUtils
|
||||
|
||||
@@ -12,7 +11,6 @@ import freechips.rocketchip.diplomacy.{LazyModule}
|
||||
import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebug, ExportDebug, DMI}
|
||||
import freechips.rocketchip.amba.axi4.{AXI4Bundle}
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tile.{RocketTile}
|
||||
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
|
||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||
import sifive.blocks.devices.uart._
|
||||
@@ -22,21 +20,19 @@ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvon
|
||||
|
||||
import junctions.{NastiKey, NastiParameters}
|
||||
import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig}
|
||||
import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotation}
|
||||
import firesim.bridges._
|
||||
import firesim.configs.MemModelKey
|
||||
import tracegen.{TraceGenSystemModuleImp}
|
||||
import cva6.CVA6Tile
|
||||
|
||||
import boom.common.{BoomTile}
|
||||
import barstools.iocell.chisel._
|
||||
import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters, IOCellKey}
|
||||
import chipyard.iobinders._
|
||||
import chipyard._
|
||||
import chipyard.harness._
|
||||
|
||||
object MainMemoryConsts {
|
||||
val regionNamePrefix = "MainMemory"
|
||||
def globalName()(implicit p: Parameters) = s"${regionNamePrefix}_${p(MultiChipIdx)}"
|
||||
def globalName(chipId: Int) = s"${regionNamePrefix}_$chipId"
|
||||
}
|
||||
|
||||
trait Unsupported {
|
||||
@@ -69,130 +65,65 @@ class WithFireSimIOCellModels extends Config((site, here, up) => {
|
||||
case IOCellKey => FireSimIOCellParams()
|
||||
})
|
||||
|
||||
class WithTSIBridgeAndHarnessRAMOverSerialTL extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||
ports.map { port =>
|
||||
implicit val p = GetSystemParameters(system)
|
||||
val bits = port.bits
|
||||
port.clock := th.harnessBinderClock
|
||||
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
|
||||
TSIBridge(th.harnessBinderClock, ram.module.io.tsi, p(ExtMem).map(_ => MainMemoryConsts.globalName), th.harnessBinderReset.asBool)
|
||||
}
|
||||
Nil
|
||||
class WithTSIBridgeAndHarnessRAMOverSerialTL extends HarnessBinder({
|
||||
case (th: FireSim, port: SerialTLPort) => {
|
||||
val bits = port.io.bits
|
||||
port.io.clock := th.harnessBinderClock
|
||||
val ram = LazyModule(new SerialRAM(port.serdesser)(Parameters.empty))
|
||||
Module(ram.module)
|
||||
ram.module.io.ser <> port.io.bits
|
||||
TSIBridge(th.harnessBinderClock, ram.module.io.tsi,
|
||||
port.params.serialTLManagerParams.map(_ => MainMemoryConsts.globalName(th.p(MultiChipIdx))), th.harnessBinderReset.asBool)(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
class WithNICBridge extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||
val p: Parameters = GetSystemParameters(system)
|
||||
ports.map { n => NICBridge(n.clock, n.bits)(p) }
|
||||
Nil
|
||||
class WithNICBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: NICPort) => {
|
||||
NICBridge(port.io.clock, port.io.bits)(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
class WithUARTBridge extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) =>
|
||||
val uartSyncClock = Wire(Clock())
|
||||
uartSyncClock := false.B.asClock
|
||||
val pbusClockNode = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(PBUS).fixedClockNode
|
||||
val pbusClock = pbusClockNode.in.head._1.clock
|
||||
BoringUtils.bore(pbusClock, Seq(uartSyncClock))
|
||||
ports.map { p => UARTBridge(uartSyncClock, p, th.harnessBinderReset.asBool)(system.p) }; Nil
|
||||
class WithUARTBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: UARTPort) =>
|
||||
val uartSyncClock = th.harnessClockInstantiator.requestClockMHz("uart_clock", port.freqMHz)
|
||||
UARTBridge(uartSyncClock, port.io, th.harnessBinderReset.asBool)(th.p)
|
||||
})
|
||||
|
||||
class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
||||
(system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessBinderReset.asBool) }
|
||||
Nil
|
||||
class WithBlockDeviceBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: BlockDevicePort) => {
|
||||
BlockDevBridge(port.io.clock, port.io.bits, th.harnessBinderReset.asBool)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithFASEDBridge extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterAXI4MemPort, th: FireSim, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||
implicit val p: Parameters = GetSystemParameters(system)
|
||||
(ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) =>
|
||||
val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth,
|
||||
axi4.bits.ar.bits.addr.getWidth,
|
||||
axi4.bits.ar.bits.id.getWidth)
|
||||
system match {
|
||||
case s: BaseSubsystem => FASEDBridge(axi4.clock, axi4.bits, axi4.reset.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 WithFASEDBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: AXI4MemPort) => {
|
||||
val nastiKey = NastiParameters(port.io.bits.r.bits.data.getWidth,
|
||||
port.io.bits.ar.bits.addr.getWidth,
|
||||
port.io.bits.ar.bits.id.getWidth)
|
||||
FASEDBridge(port.io.clock, port.io.bits, th.harnessBinderReset.asBool,
|
||||
CompleteConfig(th.p(firesim.configs.MemModelKey),
|
||||
nastiKey,
|
||||
Some(AXI4EdgeSummary(port.edge)),
|
||||
Some(MainMemoryConsts.globalName(th.p(MultiChipIdx)))))(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
class WithTracerVBridge extends ComposeHarnessBinder({
|
||||
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => {
|
||||
ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
|
||||
Nil
|
||||
class WithTracerVBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: TracePort) => {
|
||||
port.io.traces.map(tileTrace => TracerVBridge(tileTrace)(th.p))
|
||||
}
|
||||
})
|
||||
|
||||
class WithCospikeBridge extends ComposeHarnessBinder({
|
||||
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => {
|
||||
implicit val p = chipyard.iobinders.GetSystemParameters(system)
|
||||
val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem]
|
||||
val tiles = chipyardSystem.tiles
|
||||
val cfg = SpikeCosimConfig(
|
||||
isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
|
||||
vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0),
|
||||
priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""),
|
||||
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
|
||||
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
|
||||
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
|
||||
nharts = tiles.size,
|
||||
bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse(""),
|
||||
has_dtm = p(ExportDebug).protocols.contains(DMI) // assume that exposing clockeddmi means we will connect SimDTM
|
||||
)
|
||||
ports.map { p => p.traces.zipWithIndex.map(t => CospikeBridge(t._1, t._2, cfg)) }
|
||||
class WithCospikeBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: TracePort) => {
|
||||
port.io.traces.zipWithIndex.map(t => CospikeBridge(t._1, t._2, port.cosimCfg))
|
||||
}
|
||||
})
|
||||
|
||||
class WithTraceGenBridge extends OverrideHarnessBinder({
|
||||
(system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) =>
|
||||
ports.map { p => GroundTestBridge(th.harnessBinderClock, p)(system.p) }; Nil
|
||||
})
|
||||
|
||||
class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
|
||||
(system: HasTilesModuleImp) => {
|
||||
system.outer.tiles.map {
|
||||
case r: RocketTile => {
|
||||
annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf))
|
||||
r.module.fpuOpt.foreach(fpu => annotate(MemModelAnnotation(fpu.fpuImpl.regfile)))
|
||||
}
|
||||
case b: BoomTile => {
|
||||
val core = b.module.core
|
||||
core.iregfile match {
|
||||
case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile))
|
||||
}
|
||||
if (core.fp_pipeline != null) core.fp_pipeline.fregfile match {
|
||||
case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile))
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
(Nil, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithFireSimFAME5 extends ComposeIOBinder({
|
||||
(system: HasTilesModuleImp) => {
|
||||
system.outer.tiles.map {
|
||||
case b: BoomTile =>
|
||||
annotate(EnableModelMultiThreadingAnnotation(b.module))
|
||||
case r: RocketTile =>
|
||||
annotate(EnableModelMultiThreadingAnnotation(r.module))
|
||||
case _ => Nil
|
||||
}
|
||||
(Nil, Nil)
|
||||
class WithSuccessBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: SuccessPort) => {
|
||||
GroundTestBridge(th.harnessBinderClock, port.io)(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -5,21 +5,26 @@ package firesim.firesim
|
||||
import scala.collection.mutable.{LinkedHashMap}
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{IO}
|
||||
import chisel3.experimental.{IO, annotate}
|
||||
|
||||
import freechips.rocketchip.prci._
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey, HasTiles}
|
||||
import org.chipsalliance.cde.config.{Field, Config, Parameters}
|
||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, InModuleBody, ValName}
|
||||
import freechips.rocketchip.util.{ResetCatchAndSync, RecordMap}
|
||||
import freechips.rocketchip.tile.{RocketTile}
|
||||
import boom.common.{BoomTile}
|
||||
|
||||
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock, ResetPulseBridge, ResetPulseBridgeParameters}
|
||||
|
||||
import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotation}
|
||||
import chipyard._
|
||||
import chipyard.harness._
|
||||
import chipyard.iobinders._
|
||||
import chipyard.clocking._
|
||||
|
||||
case object FireSimMultiCycleRegFile extends Field[Boolean](false)
|
||||
case object FireSimFAME5 extends Field[Boolean](false)
|
||||
|
||||
/**
|
||||
* Under FireSim's current multiclock implementation there can be only a
|
||||
* single clock bridge. This requires, therefore, that it be instantiated in
|
||||
@@ -85,11 +90,46 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessInsta
|
||||
|
||||
override val supportsMultiChip = true
|
||||
|
||||
instantiateChipTops()
|
||||
val chiptops = instantiateChipTops()
|
||||
|
||||
// Ensures FireSim-synthesized assertions and instrumentation is disabled
|
||||
// while resetBridge.io.reset is asserted. This ensures assertions do not fire at
|
||||
// time zero in the event their local reset is delayed (typically because it
|
||||
// has been pipelined)
|
||||
midas.targetutils.GlobalResetCondition(resetBridge.io.reset)
|
||||
|
||||
|
||||
// FireSim multi-cycle regfile optimization
|
||||
// FireSim ModelMultithreading
|
||||
chiptops.foreach {
|
||||
case c: ChipTop => c.lazySystem match {
|
||||
case ls: HasTiles => {
|
||||
if (p(FireSimMultiCycleRegFile)) ls.tiles.map {
|
||||
case r: RocketTile => {
|
||||
annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf))
|
||||
r.module.fpuOpt.foreach(fpu => annotate(MemModelAnnotation(fpu.fpuImpl.regfile)))
|
||||
}
|
||||
case b: BoomTile => {
|
||||
val core = b.module.core
|
||||
core.iregfile match {
|
||||
case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile))
|
||||
}
|
||||
if (core.fp_pipeline != null) core.fp_pipeline.fregfile match {
|
||||
case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile))
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
if (p(FireSimFAME5)) ls.tiles.map {
|
||||
case b: BoomTile =>
|
||||
annotate(EnableModelMultiThreadingAnnotation(b.module))
|
||||
case r: RocketTile =>
|
||||
annotate(EnableModelMultiThreadingAnnotation(r.module))
|
||||
case _ => Nil
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,16 @@ class WithScalaTestFeatures extends Config((site, here, up) => {
|
||||
case TracePortKey => up(TracePortKey, site).map(_.copy(print = true))
|
||||
})
|
||||
|
||||
// Multi-cycle regfile for rocket+boom
|
||||
class WithFireSimMultiCycleRegfile extends Config((site, here, up) => {
|
||||
case FireSimMultiCycleRegFile => true
|
||||
})
|
||||
|
||||
// Model multithreading optimization
|
||||
class WithFireSimFAME5 extends Config((site, here, up) => {
|
||||
case FireSimFAME5 => true
|
||||
})
|
||||
|
||||
// FASED Config Aliases. This to enable config generation via "_" concatenation
|
||||
// which requires that all config classes be defined in the same package
|
||||
class DDR3FCFS extends FCFS16GBQuadRank
|
||||
@@ -72,7 +82,8 @@ class WithMinimalFireSimDesignTweaks extends Config(
|
||||
// Required*: Punch all clocks to FireSim's harness clock instantiator
|
||||
new WithFireSimHarnessClockBridgeInstantiator ++
|
||||
new chipyard.harness.WithHarnessBinderClockFreqMHz(1000.0) ++
|
||||
new chipyard.harness.WithClockAndResetFromHarness ++
|
||||
new chipyard.harness.WithClockFromHarness ++
|
||||
new chipyard.harness.WithResetFromHarness ++
|
||||
new chipyard.clocking.WithPassthroughClockGenerator ++
|
||||
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
|
||||
new WithBootROM ++
|
||||
|
||||
Submodule generators/icenet updated: 68b4c7f30f...18e88b5779
Submodule generators/testchipip updated: 177e307199...6436959d99
Submodule sims/firesim updated: 08b565c8c6...f80c60313c
Reference in New Issue
Block a user