Merge branch 'main' into bump-barstools

This commit is contained in:
Abraham Gonzalez
2023-10-16 16:22:12 -07:00
committed by GitHub
47 changed files with 1069 additions and 861 deletions

View File

@@ -34,7 +34,7 @@ grouping["group-accels"]="chipyard-mempress chipyard-sha3 chipyard-hwacha chipya
grouping["group-constellation"]="chipyard-constellation"
grouping["group-tracegen"]="tracegen tracegen-boom"
grouping["group-other"]="icenet testchipip constellation rocketchip-amba rocketchip-tlsimple rocketchip-tlwidth rocketchip-tlxbar"
grouping["group-fpga"]="arty vcu118 vc707 arty100t"
grouping["group-fpga"]="arty arty100t nexysvideo vc707 vcu118"
# key value store to get the build strings
declare -A mapping
@@ -79,6 +79,7 @@ mapping["rocketchip-tlwidth"]="SUB_PROJECT=rocketchip CONFIG=TLWidthUnitTestConf
mapping["rocketchip-tlxbar"]="SUB_PROJECT=rocketchip CONFIG=TLXbarUnitTestConfig"
mapping["arty"]="SUB_PROJECT=arty verilog"
mapping["vcu118"]="SUB_PROJECT=vcu118 verilog"
mapping["vc707"]="SUB_PROJECT=vc707 verilog"
mapping["arty100t"]="SUB_PROJECT=arty100t verilog"
mapping["nexysvideo"]="SUB_PROJECT=nexysvideo verilog"
mapping["vc707"]="SUB_PROJECT=vc707 verilog"
mapping["vcu118"]="SUB_PROJECT=vcu118 verilog"

View File

@@ -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

View File

@@ -2,18 +2,18 @@ Running a Design on Arty
========================
Arty100T Instructions
----------------------
---------------------
The default Xilinx Arty 100T harness uses a TSI-over-UART adapter to bringup the FPGA.
A user can connect to the Arty 100T target using a special ``uart_tsi`` program that opens a UART TTY.
The default Digilent Arty A7-100T harness uses a TSI-over-UART adapter to bringup the FPGA.
A user can connect to the Arty A7-100T target using a special ``uart_tsi`` program that opens a UART TTY.
The interface for the ``uart_tsi`` program provides unique functionality that is useful for bringing up test chips.
To build the design, run:
To build the design (Vivado should be added to the ``PATH``), run:
.. code-block:: shell
cd fpga/
make SUB_PROJECT=arty100t
make SUB_PROJECT=arty100t bitstream
To build the UART-based frontend server, run:
@@ -58,7 +58,7 @@ Run a design at a higher baud rate than default (For example, if ``CONFIG=UART92
Arty35T Legacy Instructions
---------------------------
The default Xilinx Arty 35T harness is setup to have JTAG available over the board's PMOD pins, and UART available over its FTDI serial USB adapter. The pin mappings for JTAG signals are identical to those described in the `SiFive Freedom E310 Arty 35T Getting Started Guide <https://static.dev.sifive.com/SiFive-E310-arty-gettingstarted-v1.0.6.pdf>`__.
The default Digilent Arty A7-35T harness is setup to have JTAG available over the board's PMOD pins, and UART available over its FTDI serial USB adapter. The pin mappings for JTAG signals are identical to those described in the `SiFive Freedom E310 Arty 35T Getting Started Guide <https://static.dev.sifive.com/SiFive-E310-arty-gettingstarted-v1.0.6.pdf>`__.
The JTAG interface allows a user to connect to the core via OpenOCD, run bare-metal applications, and debug these applications with gdb. UART allows a user to communicate with the core over a USB connection and serial console running on a PC.
To extend this design, a user may create their own Chipyard configuration and add the ``WithArtyTweaks`` located in ``fpga/src/main/scala/arty/Configs.scala``.
Adding this config. fragment will enable and connect the JTAG and UART interfaces to your Chipyard design.
@@ -68,13 +68,13 @@ Adding this config. fragment will enable and connect the JTAG and UART interface
:start-after: DOC include start: AbstractArty and Rocket
:end-before: DOC include end: AbstractArty and Rocket
Future peripherals to be supported include the Arty 35T SPI Flash EEPROM, and I2C/PWM/SPI over the Arty 35T GPIO pins. These peripherals are available as part of sifive-blocks.
Future peripherals to be supported include the Arty A7-35T SPI Flash EEPROM, and I2C/PWM/SPI over the Arty A7-35T GPIO pins. These peripherals are available as part of sifive-blocks.
Brief Implementation Description and Guidance for Adding/Changing Xilinx Collateral
-----------------------------------------------------------------------------------
Like the VCU118, the basis for the Arty 35T design is the creation of a special test harness that connects the external IO (which exist as Xilinx IP blackboxes) to the Chipyard design.
This is done with the ``ArtyTestHarness`` in the basic default Arty 35T target. However, unlike the ``VCU118TestHarness``, the ``ArtyTestHarness`` uses no ``Overlays``, and instead directly connects chip top IO to the ports of the external IO blackboxes, using functions such as ``IOBUF`` provided by ``fpga-shells``.
Unlike the VCU118 and other more complicated test harnesses, the Arty 35T Vivado collateral is not generated by ``Overlays``, but rather are a static collection of ``create_ip`` and ``set_properties`` statements located in the files within ``fpga/fpga-shells/xilinx/arty/tcl`` and ``fpga/fpga-shells/xilinx/arty/constraints``.
Like the VCU118, the basis for the Arty A7-35T design is the creation of a special test harness that connects the external IO (which exist as Xilinx IP blackboxes) to the Chipyard design.
This is done with the ``ArtyTestHarness`` in the basic default Arty A7-35T target. However, unlike the ``VCU118TestHarness``, the ``ArtyTestHarness`` uses no ``Overlays``, and instead directly connects chip top IO to the ports of the external IO blackboxes, using functions such as ``IOBUF`` provided by ``fpga-shells``.
Unlike the VCU118 and other more complicated test harnesses, the Arty A7-35T Vivado collateral is not generated by ``Overlays``, but rather are a static collection of ``create_ip`` and ``set_properties`` statements located in the files within ``fpga/fpga-shells/xilinx/arty/tcl`` and ``fpga/fpga-shells/xilinx/arty/constraints``.
If the user wishes to re-map FPGA package pins to different harness-level IO, this may be changed within ``fpga/fpga-shells/xilinx/arty/constraints/arty-master.xdc``. The addition of new Xilinx IP blocks may be done in ``fpga-shells/xilinx/arty/tcl/ip.tcl``, mapped to harness-level IOs in ``arty-master.xdc``, and wired through from the test harness to the chip top using ``HarnessBinders`` and ``IOBinders``.
Examples of a simple ``IOBinder`` and ``HarnessBinder`` for routing signals (in this case the debug and JTAG resets) from the core to the test harness are the ``WithResetPassthrough`` and ``WithArtyResetHarnessBinder``.

View File

@@ -2,7 +2,7 @@ General Setup and Usage
==============================
Sources
---------------------------
-------
All FPGA prototyping-related collateral and sources are located in the ``fpga`` top-level Chipyard directory.
This includes the ``fpga-shells`` submodule and the ``src`` directory that hold both Scala, TCL and other collateral.

View File

@@ -0,0 +1,49 @@
Running a Design on Nexys Video
===============================
Nexys Video Instructions
------------------------
The default Digilent Nexys Video harness uses a TSI-over-UART adapter to bringup the FPGA.
A user can connect to the Nexys Video target using a special ``uart_tsi`` program that opens a UART TTY.
The interface for the ``uart_tsi`` program provides unique functionality that is useful for bringing up test chips.
To build the design (Vivado should be added to the ``PATH``), run:
.. code-block:: shell
cd fpga/
make SUB_PROJECT=nexysvideo bitstream
To build the UART-based frontend server, run:
.. code-block:: shell
cd generators/testchipip/uart_tsi
make
After programming the bitstream, and connecting the Nexys Video's UART to a host PC via the USB cable, the ``uart_tsi`` program can be run to interact with the target.
Running a program:
.. code-block:: shell
./uart_tsi +tty=/dev/ttyUSBX dhrystone.riscv
Probe an address on the target system:
.. code-block:: shell
./uart_tsi +tty=/dev/ttyUSBX +init_read=0x10040 none
Write some address before running a program:
.. code-block:: shell
./uart_tsi +tty=/dev/ttyUSBX +init_write=0x80000000:0xdeadbeef none
Self-check that binary loading proceeded correctly:
.. code-block:: shell
./uart_tsi +tty=/dev/ttyUSBX +selfcheck dhrystone.riscv

View File

@@ -2,10 +2,10 @@ Prototyping Flow
================
Chipyard supports FPGA prototyping for local FPGAs supported by `fpga-shells <https://github.com/sifive/fpga-shells>`__.
This includes popular FPGAs such as the Xilinx VCU118 and the Xilinx Arty 35T board.
This includes popular FPGAs such as the Xilinx VCU118 and the Digilent Arty A7-35T/A7-100T board.
.. Note:: While ``fpga-shells`` provides harnesses for other FPGA development boards such as the Xilinx VC707 and some MicroSemi PolarFire, only harnesses for the Xilinx VCU118 and Xilinx Arty 35T boards are currently supported in Chipyard.
However, the VCU118 and Arty 35T examples demonstrate how a user may implement support for other harnesses provided by fpga-shells.
.. Note:: While ``fpga-shells`` provides harnesses for other FPGA development boards such as the Xilinx VC707 and some MicroSemi PolarFire, only harnesses for the Xilinx VCU118 and Digilent Arty A7-35T/A7-100T boards are currently supported in Chipyard.
However, the VCU118 and Arty A7-35T/A7-100T examples demonstrate how a user may implement support for other harnesses provided by fpga-shells.
.. toctree::
:maxdepth: 2
@@ -14,3 +14,4 @@ This includes popular FPGAs such as the Xilinx VCU118 and the Xilinx Arty 35T bo
General
VCU118
Arty
NexysVideo

View File

@@ -57,6 +57,21 @@ ifeq ($(SUB_PROJECT),bringup)
BOARD ?= vcu118
FPGA_BRAND ?= xilinx
endif
ifeq ($(SUB_PROJECT),nexysvideo)
SBT_PROJECT ?= fpga_platforms
MODEL ?= NexysVideoHarness
VLOG_MODEL ?= NexysVideoHarness
MODEL_PACKAGE ?= chipyard.fpga.nexysvideo
CONFIG ?= RocketNexysVideoConfig
CONFIG_PACKAGE ?= chipyard.fpga.nexysvideo
GENERATOR_PACKAGE ?= chipyard
TB ?= none # unused
TOP ?= ChipTop
BOARD ?= nexys_video
FPGA_BRAND ?= xilinx
endif
ifeq ($(SUB_PROJECT),arty)
# TODO: Fix with Arty
SBT_PROJECT ?= fpga_platforms

View File

@@ -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 ++

View File

@@ -11,33 +11,29 @@ 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)
withClockAndReset(th.clock_32MHz, th.ck_rst) {
// Debug module reset
th.dut_ndreset := resetPorts(0)
// JTAG reset
resetPorts(1) := PowerOnResetFPGAOnly(th.clock_32MHz)
}
class WithArtyDebugResetHarnessBinder extends HarnessBinder({
case (th: ArtyFPGATestHarness, port: DebugResetPort) => {
th.dut_ndreset := port.io // Debug module reset
}
})
class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({
(system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => {
ports.map {
case j: JTAGChipIO => {
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 := j.TDO
jtag_wire.TDO.data := port.io.TDO
jtag_wire.TDO.driven := true.B
j.TCK := jtag_wire.TCK
j.TMS := jtag_wire.TMS
j.TDI := jtag_wire.TDI
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")
@@ -63,16 +59,13 @@ class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({
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]) => {
class WithArtyUARTHarnessBinder extends HarnessBinder({
case (th: ArtyFPGATestHarness, port: UARTPort) => {
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)
}
}
})

View File

@@ -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)
}
})

View File

@@ -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
}
})

View File

@@ -0,0 +1,72 @@
// See LICENSE for license details.
package chipyard.fpga.nexysvideo
import org.chipsalliance.cde.config._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.debug._
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.system._
import freechips.rocketchip.tile._
import sifive.blocks.devices.uart._
import sifive.fpgashells.shell.{DesignKey}
import testchipip.{SerialTLKey}
import chipyard.{BuildSystem}
// don't use FPGAShell's DesignKey
class WithNoDesignKey extends Config((site, here, up) => {
case DesignKey => (p: Parameters) => new SimpleLazyModule()(p)
})
// DOC include start: WithNexysVideoTweaks and Rocket
class WithNexysVideoTweaks extends Config(
new WithNexysVideoUARTTSI ++
new WithNexysVideoDDRTL ++
new WithNoDesignKey ++
new testchipip.WithUARTTSIClient ++
new chipyard.harness.WithSerialTLTiedOff ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(50) ++
new chipyard.config.WithMemoryBusFrequency(50.0) ++
new chipyard.config.WithFrontBusFrequency(50.0) ++
new chipyard.config.WithSystemBusFrequency(50.0) ++
new chipyard.config.WithPeripheryBusFrequency(50.0) ++
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithNoDebug ++ // no jtag
new chipyard.config.WithNoUART ++ // use UART for the UART-TSI thing instad
new chipyard.config.WithTLBackingMemory ++ // FPGA-shells converts the AXI to TL for us
new freechips.rocketchip.subsystem.WithExtMemSize(BigInt(512) << 20) ++ // 512mb on Nexys Video
new freechips.rocketchip.subsystem.WithoutTLMonitors)
class RocketNexysVideoConfig extends Config(
new WithNexysVideoTweaks ++
new chipyard.config.WithBroadcastManager ++ // no l2
new chipyard.RocketConfig)
// DOC include end: WithNexysVideoTweaks and Rocket
// DOC include start: WithTinyNexysVideoTweaks and Rocket
class WithTinyNexysVideoTweaks extends Config(
new WithNexysVideoUARTTSI ++
new WithNoDesignKey ++
new sifive.fpgashells.shell.xilinx.WithNoNexysVideoShellDDR ++ // no DDR
new testchipip.WithUARTTSIClient ++
new chipyard.harness.WithSerialTLTiedOff ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(50) ++
new chipyard.config.WithMemoryBusFrequency(50.0) ++
new chipyard.config.WithFrontBusFrequency(50.0) ++
new chipyard.config.WithSystemBusFrequency(50.0) ++
new chipyard.config.WithPeripheryBusFrequency(50.0) ++
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithNoDebug ++ // no jtag
new chipyard.config.WithNoUART ++ // use UART for the UART-TSI thing instad
new freechips.rocketchip.subsystem.WithoutTLMonitors)
class TinyRocketNexysVideoConfig extends Config(
new WithTinyNexysVideoTweaks ++
new chipyard.config.WithBroadcastManager ++ // no l2
new chipyard.TinyRocketConfig)
// DOC include end: WithTinyNexysVideoTweaks and Rocket

View File

@@ -0,0 +1,92 @@
// See LICENSE for license details.
package chipyard.fpga.nexysvideo
import chisel3._
import chisel3.util._
import freechips.rocketchip.diplomacy._
import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.subsystem.{SystemBusKey}
import sifive.fpgashells.shell.xilinx._
import sifive.fpgashells.shell._
import sifive.fpgashells.clocks.{ClockGroup, ClockSinkNode, PLLFactoryKey, ResetWrangler}
import sifive.blocks.devices.uart._
import chipyard._
import chipyard.harness._
import chipyard.iobinders.{HasIOBinders}
class NexysVideoHarness(override implicit val p: Parameters) extends NexysVideoShell {
def dp = designParameters
val clockOverlay = dp(ClockInputOverlayKey).map(_.place(ClockInputDesignInput())).head
val harnessSysPLL = dp(PLLFactoryKey)
val harnessSysPLLNode = harnessSysPLL()
val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
println(s"NexysVideo FPGA Base Clock Freq: ${dutFreqMHz} MHz")
val dutWrangler = LazyModule(new ResetWrangler())
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLLNode
harnessSysPLLNode := clockOverlay.overlayOutput.node
val io_uart_bb = BundleBridgeSource(() => new UARTPortIO(dp(PeripheryUARTKey).headOption.getOrElse(UARTParams(0))))
val uartOverlay = dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb))
// Optional DDR
val ddrOverlay = if (p(NexysVideoShellDDR)) Some(dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLLNode)).asInstanceOf[DDRNexysVideoPlacedOverlay]) else None
val ddrClient = if (p(NexysVideoShellDDR)) Some(TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = "chip_ddr",
sourceId = IdRange(0, 1 << dp(ExtTLMem).get.master.idBits)
)))))) else None
val ddrBlockDuringReset = if (p(NexysVideoShellDDR)) Some(LazyModule(new TLBlockDuringReset(4))) else None
if (p(NexysVideoShellDDR)) { ddrOverlay.get.overlayOutput.ddr := ddrBlockDuringReset.get.node := ddrClient.get }
val ledOverlays = dp(LEDOverlayKey).map(_.place(LEDDesignInput()))
val all_leds = ledOverlays.map(_.overlayOutput.led)
val status_leds = all_leds.take(2)
val other_leds = all_leds.drop(2)
override lazy val module = new HarnessLikeImpl
class HarnessLikeImpl extends Impl with HasHarnessInstantiators {
all_leds.foreach(_ := DontCare)
clockOverlay.overlayOutput.node.out(0)._1.reset := ~resetPin
val clk_100mhz = clockOverlay.overlayOutput.node.out.head._1.clock
// Blink the status LEDs for sanity
withClockAndReset(clk_100mhz, dutClock.in.head._1.reset) {
val period = (BigInt(100) << 20) / status_leds.size
val counter = RegInit(0.U(log2Ceil(period).W))
val on = RegInit(0.U(log2Ceil(status_leds.size).W))
status_leds.zipWithIndex.map { case (o,s) => o := on === s.U }
counter := Mux(counter === (period-1).U, 0.U, counter + 1.U)
when (counter === 0.U) {
on := Mux(on === (status_leds.size-1).U, 0.U, on + 1.U)
}
}
other_leds(0) := resetPin
harnessSysPLL.plls.foreach(_._1.getReset.get := pllReset)
def referenceClockFreqMHz = dutFreqMHz
def referenceClock = dutClock.in.head._1.clock
def referenceReset = dutClock.in.head._1.reset
def success = { require(false, "Unused"); false.B }
if (p(NexysVideoShellDDR)) {
ddrOverlay.get.mig.module.clock := harnessBinderClock
ddrOverlay.get.mig.module.reset := harnessBinderReset
ddrBlockDuringReset.get.module.clock := harnessBinderClock
ddrBlockDuringReset.get.module.reset := harnessBinderReset.asBool || !ddrOverlay.get.mig.module.io.port.init_calib_complete
}
instantiateChipTops()
}
}

View File

@@ -0,0 +1,39 @@
// See LICENSE for license details.
package chipyard.fpga.nexysvideo
import chisel3._
import freechips.rocketchip.subsystem.{PeripheryBusKey}
import freechips.rocketchip.tilelink.{TLBundle}
import freechips.rocketchip.util.{HeterogeneousBag}
import freechips.rocketchip.diplomacy.{LazyRawModuleImp}
import sifive.blocks.devices.uart.{UARTParams}
import chipyard._
import chipyard.harness._
import testchipip._
import chipyard.iobinders._
class WithNexysVideoUARTTSI(uartBaudRate: BigInt = 115200) extends HarnessBinder({
case (th: HasHarnessInstantiators, port: UARTTSIPort) => {
val nexysvideoth = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[NexysVideoHarness]
nexysvideoth.io_uart_bb.bundle <> port.io.uart
nexysvideoth.other_leds(1) := port.io.dropped
nexysvideoth.other_leds(2) := port.io.tsi2tl_state(0)
nexysvideoth.other_leds(3) := port.io.tsi2tl_state(1)
nexysvideoth.other_leds(4) := port.io.tsi2tl_state(2)
nexysvideoth.other_leds(5) := port.io.tsi2tl_state(3)
}
})
class WithNexysVideoDDRTL extends HarnessBinder({
case (th: HasHarnessInstantiators, port: TLMemPort) => {
val nexysTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[NexysVideoHarness]
val bundles = nexysTh.ddrClient.get.out.map(_._1)
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
ddrClientBundle <> port.io
}
})

View File

@@ -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

View File

@@ -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)
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 <> ports.head
}}
ddrClientBundle <> port.io
}
})

View File

@@ -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)
}
})

View File

@@ -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

View File

@@ -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)
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 <> ports.head
} }
ddrClientBundle <> port.io
}
})

View File

@@ -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)
} }
}
}
})

View File

@@ -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)

View File

@@ -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)
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 <> tlPort
tsiDdrClientBundle <> port.io
}
ports.last match { case serialPort: TSIHostWidgetIO =>
vcu118th.bringupOuter.io_tsi_serial_bb.bundle <> serialPort
}
} }
case (th: BringupVCU118FPGATestHarnessImp, port: TSIHostWidgetPort) => {
th.bringupOuter.io_tsi_serial_bb.bundle <> port.io
}
})

View File

@@ -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)
}
})

View File

@@ -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)
}
}
})

View File

@@ -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)

View File

@@ -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 ++

View File

@@ -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 ++

View File

@@ -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
}

View File

@@ -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

View File

@@ -6,143 +6,111 @@ 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.toDouble * 1000000 / 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 =>
withClockAndReset(n.clock, th.harnessBinderReset.asBool) {
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 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) =>
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 = 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
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.")
@@ -153,212 +121,169 @@ class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBind
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))
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))
}
}
mem.io.clock := port.clock
mem.io.reset := port.reset
}
}
})
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 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).suggestName("mmio_mem") }
mmio_mem.io_axi4.head <> port.io.bits
}
})
class WithTieOffInterrupts extends OverrideHarnessBinder({
(system: HasExtInterruptsModuleImp, th: HasHarnessInstantiators, ports: Seq[UInt]) => {
ports.foreach { _ := 0.U }
class WithTieOffInterrupts extends HarnessBinder({
case (th: HasHarnessInstantiators, port: ExtIntPort) => {
port.io := 0.U
}
})
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 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 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 =>
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 := j.TDO
jtag_wire.TDO.data := port.io.TDO
jtag_wire.TDO.driven := true.B
j.TCK := jtag_wire.TCK
j.TMS := jtag_wire.TMS
j.TDI := jtag_wire.TDI
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 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 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 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 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 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
class WithSerialTLTiedOff extends HarnessBinder({
case (th: HasHarnessInstantiators, port: SerialTLPort) => {
if (DataMirror.directionOf(port.io.clock) == Direction.Input) {
port.io.clock := false.B.asClock
}
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset)
val success = SimTSI.connect(Some(ram.module.io.tsi), th.harnessBinderClock, th.harnessBinderReset.asBool)
port.io.bits.out.ready := false.B
port.io.bits.in.valid := false.B
port.io.bits.in.bits := DontCare
}
})
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 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,
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)
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 =>
class WithSimTSIToUARTTSI extends HarnessBinder({
case (th: HasHarnessInstantiators, port: UARTTSIPort) => {
val freq = th.getHarnessBinderClockFreqHz.toInt
val uart_to_serial = Module(new UARTToSerial(freq, port.uartParams))
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.uart.txd
port.uart.rxd := uart_to_serial.io.uart.txd
})
uart_to_serial.io.uart.rxd := port.io.uart.txd
port.io.uart.rxd := uart_to_serial.io.uart.txd
}
})
class WithTraceGenSuccess extends HarnessBinder({
case (th: HasHarnessInstantiators, port: SuccessPort) => {
when (port.io) { th.success := true.B }
}
})
class WithCospike extends HarnessBinder({
case (th: HasHarnessInstantiators, port: TracePort) => {
port.io.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, port.cosimCfg))
}
})
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
}
})

View File

@@ -63,7 +63,7 @@ trait HasHarnessInstantiators {
val supportsMultiChip: Boolean = false
private val chipParameters = p(MultiChipNChips) match {
val chipParameters = p(MultiChipNChips) match {
case Some(n) => (0 until n).map { i => p(MultiChipParameters(i)).alterPartial {
case TargetDirKey => p(TargetDirKey) // hacky fix
case MultiChipIdx => i
@@ -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)

View File

@@ -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
}
)

View File

@@ -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
}

View File

@@ -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 / 1000000
(UARTPort(port, i, freqMHz.toInt), 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 =>
(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)
(Seq(port), cells)
}).getOrElse((Nil, Nil))
(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 =>
(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
(Seq(port), Nil)
}).getOrElse((Nil, Nil))
(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)
}
})

View 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]]

View File

@@ -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,70 @@ 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
// This assumes that:
// If ExtMem for the target is defined, then FASED bridge will be attached
// If FASED bridge is attached, loadmem widget is present
val hasMainMemory = th.chipParameters(th.p(MultiChipIdx))(ExtMem).isDefined
val mainMemoryName = Option.when(hasMainMemory)(MainMemoryConsts.globalName(th.p(MultiChipIdx)))
TSIBridge(th.harnessBinderClock, ram.module.io.tsi, mainMemoryName, 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, port.freqMHz)(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),
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(edge)),
Some(MainMemoryConsts.globalName)))
case _ => throw new Exception("Attempting to attach FASED Bridge to misconfigured design")
}
}
Nil
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)
}
})

View File

@@ -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 _ =>
}
}

View File

@@ -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 ++
@@ -289,6 +300,7 @@ class FireSimLeanGemminiPrintfRocketConfig extends Config(
//**********************************************************************************
class SupernodeFireSimRocketConfig extends Config(
new WithFireSimHarnessClockBridgeInstantiator ++
new WithDefaultMemModel ++ // this is a global for all the multi-chip configs
new chipyard.harness.WithHomogeneousMultiChip(n=4, new Config(
new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 8L) ++ // 8GB DRAM per node
new FireSimRocketConfig)))

View File

@@ -109,8 +109,31 @@ if [ $TOOLCHAIN_TYPE == "esp-tools" ]; then
done
fi
#######################################
###### BEGIN STEP-BY-STEP SETUP #######
#######################################
# In order to run code on error, we must handle errors manually
set +e;
function begin_step
{
thisStepNum=$1;
thisStepDesc=$2;
echo " ========== BEGINNING STEP $thisStepNum: $thisStepDesc =========="
}
function exit_if_last_command_failed
{
local exitcode=$?;
if [ $exitcode -ne 0 ]; then
die "Build script failed with exit code $exitcode at step $thisStepNum: $thisStepDesc" $exitcode;
fi
}
# setup and install conda environment
if run_step "1"; then
begin_step "1" "Conda environment setup"
# note: lock file must end in .conda-lock.yml - see https://github.com/conda-incubator/conda-lock/issues/154
CONDA_REQS=$CYDIR/conda-reqs
CONDA_LOCK_REQS=$CONDA_REQS/conda-lock-reqs
@@ -120,13 +143,15 @@ if run_step "1"; then
if [ "$USE_UNPINNED_DEPS" = true ]; then
# auto-gen the lockfiles
$CYDIR/scripts/generate-conda-lockfiles.sh
exit_if_last_command_failed
fi
# use conda-lock to create env
conda-lock install --conda $(which conda) -p $CYDIR/.conda-env $LOCKFILE
conda-lock install --conda $(which conda) -p $CYDIR/.conda-env $LOCKFILE &&
source $CYDIR/.conda-env/etc/profile.d/conda.sh
source $CYDIR/.conda-env/etc/profile.d/conda.sh &&
conda activate $CYDIR/.conda-env
exit_if_last_command_failed
fi
if [ -z "$FORCE_FLAG" ]; then
@@ -138,11 +163,14 @@ fi
# initialize all submodules (without the toolchain submodules)
if run_step "2"; then
begin_step "2" "Initializing Chipyard submodules"
$CYDIR/scripts/init-submodules-no-riscv-tools.sh $FORCE_FLAG
exit_if_last_command_failed
fi
# build extra toolchain collateral (i.e. spike, pk, riscv-tests, libgloss)
if run_step "3"; then
begin_step "3" "Building toolchain collateral"
if run_step "1"; then
PREFIX=$CONDA_PREFIX/$TOOLCHAIN_TYPE
else
@@ -153,57 +181,73 @@ if run_step "3"; then
PREFIX=$RISCV
fi
$CYDIR/scripts/build-toolchain-extra.sh $TOOLCHAIN_TYPE -p $PREFIX
exit_if_last_command_failed
fi
# run ctags for code navigation
if run_step "4"; then
begin_step "4" "Running ctags for code navigation"
$CYDIR/scripts/gen-tags.sh
exit_if_last_command_failed
fi
# precompile chipyard scala sources
if run_step "5"; then
pushd $CYDIR/sims/verilator
make launch-sbt SBT_COMMAND=";project chipyard; compile"
make launch-sbt SBT_COMMAND=";project tapeout; compile"
begin_step "5" "Pre-compiling Chipyard Scala sources"
pushd $CYDIR/sims/verilator &&
make launch-sbt SBT_COMMAND=";project chipyard; compile" &&
make launch-sbt SBT_COMMAND=";project tapeout; compile" &&
popd
exit_if_last_command_failed
fi
# setup firesim
if run_step "6"; then
$CYDIR/scripts/firesim-setup.sh
begin_step "6" "Setting up FireSim"
$CYDIR/scripts/firesim-setup.sh &&
$CYDIR/sims/firesim/gen-tags.sh
exit_if_last_command_failed
# precompile firesim scala sources
if run_step "7"; then
pushd $CYDIR/sims/firesim
begin_step "7" "Pre-compiling Firesim Scala sources"
pushd $CYDIR/sims/firesim &&
(
set -e # Subshells un-set "set -e" so it must be re enabled
echo $CYDIR
source sourceme-manager.sh --skip-ssh-setup
pushd sim
make sbt SBT_COMMAND="project {file:$CYDIR}firechip; compile" TARGET_PROJECT=firesim
popd
)
exit_if_last_command_failed
popd
fi
fi
# setup firemarshal
if run_step "8"; then
pushd $CYDIR/software/firemarshal
begin_step "8" "Setting up FireMarshal"
pushd $CYDIR/software/firemarshal &&
./init-submodules.sh
exit_if_last_command_failed
# precompile firemarshal buildroot sources
if run_step "9"; then
source $CYDIR/scripts/fix-open-files.sh
./marshal $VERBOSE_FLAG build br-base.json
begin_step "9" "Pre-compiling FireMarshal buildroot sources"
source $CYDIR/scripts/fix-open-files.sh &&
./marshal $VERBOSE_FLAG build br-base.json &&
./marshal $VERBOSE_FLAG clean br-base.json
exit_if_last_command_failed
fi
popd
fi
# do misc. cleanup for a "clean" git status
if run_step "10"; then
begin_step "10" "Cleaning up repository"
$CYDIR/scripts/repo-clean.sh
exit_if_last_command_failed
fi
cat <<EOT >> env.sh