Merge pull request #1716 from ucb-bar/symmetric_sertl
Add support for symmetric serial-tilelink
This commit is contained in:
3
.github/scripts/defaults.sh
vendored
3
.github/scripts/defaults.sh
vendored
@@ -29,7 +29,7 @@ REMOTE_COURSIER_CACHE=$REMOTE_WORK_DIR/.coursier-cache
|
||||
# key value store to get the build groups
|
||||
declare -A grouping
|
||||
grouping["group-cores"]="chipyard-cva6 chipyard-ibex chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket chipyard-nomem-scratchpad chipyard-spike chipyard-clone chipyard-prefetchers chipyard-shuttle"
|
||||
grouping["group-peripherals"]="chipyard-dmirocket chipyard-dmiboom chipyard-spiflashwrite chipyard-mmios chipyard-nocores chipyard-manyperipherals chipyard-chiplike chipyard-tethered"
|
||||
grouping["group-peripherals"]="chipyard-dmirocket chipyard-dmiboom chipyard-spiflashwrite chipyard-mmios chipyard-nocores chipyard-manyperipherals chipyard-chiplike chipyard-tethered chipyard-symmetric"
|
||||
grouping["group-accels"]="chipyard-mempress chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-manymmioaccels chipyard-nvdla chipyard-aes256ecb"
|
||||
grouping["group-constellation"]="chipyard-constellation"
|
||||
grouping["group-tracegen"]="tracegen tracegen-boom"
|
||||
@@ -58,6 +58,7 @@ mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig EXTRA_SIM_F
|
||||
mapping["chipyard-manyperipherals"]=" CONFIG=ManyPeripheralsRocketConfig EXTRA_SIM_FLAGS='+spiflash0=${LOCAL_CHIPYARD_DIR}/tests/spiflash.img'"
|
||||
mapping["chipyard-chiplike"]=" CONFIG=ChipLikeRocketConfig MODEL=FlatTestHarness MODEL_PACKAGE=chipyard.example verilog"
|
||||
mapping["chipyard-tethered"]=" CONFIG=VerilatorCITetheredChipLikeRocketConfig"
|
||||
mapping["chipyard-symmetric"]=" CONFIG=MultiSimSymmetricChipletRocketConfig"
|
||||
mapping["chipyard-cloneboom"]=" CONFIG=Cloned64MegaBoomConfig verilog"
|
||||
mapping["chipyard-nocores"]=" CONFIG=NoCoresConfig verilog"
|
||||
mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config"
|
||||
|
||||
4
.github/scripts/run-tests.sh
vendored
4
.github/scripts/run-tests.sh
vendored
@@ -118,6 +118,10 @@ case $1 in
|
||||
make -C $LOCAL_CHIPYARD_DIR/tests
|
||||
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/hello.riscv LOADMEM=1 EXTRA_SIM_FLAGS="+cflush_addr=0x2010200"
|
||||
;;
|
||||
chipyard-symmetric)
|
||||
make -C $LOCAL_CHIPYARD_DIR/tests
|
||||
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/symmetric.riscv LOADMEM=1
|
||||
;;
|
||||
tracegen)
|
||||
run_tracegen
|
||||
;;
|
||||
|
||||
24
.github/workflows/chipyard-run-tests.yml
vendored
24
.github/workflows/chipyard-run-tests.yml
vendored
@@ -708,6 +708,29 @@ jobs:
|
||||
group-key: "group-peripherals"
|
||||
project-key: "chipyard-tethered"
|
||||
|
||||
chipyard-symmetric-run-tests:
|
||||
name: chipyard-symmetric-run-tests
|
||||
needs: prepare-chipyard-peripherals
|
||||
runs-on: as4
|
||||
steps:
|
||||
- name: Delete old checkout
|
||||
run: |
|
||||
ls -alh .
|
||||
rm -rf ${{ github.workspace }}/* || true
|
||||
rm -rf ${{ github.workspace }}/.* || true
|
||||
ls -alh .
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Git workaround
|
||||
uses: ./.github/actions/git-workaround
|
||||
- name: Create conda env
|
||||
uses: ./.github/actions/create-conda-env
|
||||
- name: Run tests
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
group-key: "group-peripherals"
|
||||
project-key: "chipyard-symmetric"
|
||||
|
||||
chipyard-sha3-run-tests:
|
||||
name: chipyard-sha3-run-tests
|
||||
needs: prepare-chipyard-accels
|
||||
@@ -1071,6 +1094,7 @@ jobs:
|
||||
chipyard-spiflashwrite-run-tests,
|
||||
chipyard-manyperipherals-run-tests,
|
||||
chipyard-tethered-run-tests,
|
||||
chipyard-symmetric-run-tests,
|
||||
chipyard-sha3-run-tests,
|
||||
chipyard-gemmini-run-tests,
|
||||
chipyard-manymmioaccels-run-tests, # chipyard-nvdla-run-tests,
|
||||
|
||||
@@ -23,8 +23,8 @@ dependencies:
|
||||
# bundle FireSim driver with deps into installer shell-script
|
||||
- constructor
|
||||
|
||||
- gcc<13
|
||||
- gxx<13
|
||||
- gcc<12
|
||||
- gxx<12
|
||||
- sysroot_linux-64=2.17 # needed to match pre-built CI XRT glibc version
|
||||
- conda-gcc-specs
|
||||
- binutils
|
||||
@@ -88,7 +88,7 @@ dependencies:
|
||||
- graphviz
|
||||
- expect
|
||||
- dtc
|
||||
- verilator==5.008
|
||||
- verilator==5.020
|
||||
- screen
|
||||
- elfutils
|
||||
- libdwarf-dev==0.0.0.20190110_28_ga81397fc4 # from ucb-bar channel - using mainline libdwarf-feedstock
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,19 +15,19 @@ import chipyard.harness.{HarnessBinder}
|
||||
import chipyard.iobinders._
|
||||
|
||||
class WithArtyDebugResetHarnessBinder extends HarnessBinder({
|
||||
case (th: Arty35THarness, port: DebugResetPort) => {
|
||||
case (th: Arty35THarness, port: DebugResetPort, chipId: Int) => {
|
||||
th.dut_ndreset := port.io // Debug module reset
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyJTAGResetHarnessBinder extends HarnessBinder({
|
||||
case (th: Arty35THarness, port: JTAGResetPort) => {
|
||||
case (th: Arty35THarness, port: JTAGResetPort, chipId: Int) => {
|
||||
port.io := PowerOnResetFPGAOnly(th.clock_32MHz) // JTAG module reset
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyJTAGHarnessBinder extends HarnessBinder({
|
||||
case (th: Arty35THarness, port: JTAGPort) => {
|
||||
case (th: Arty35THarness, port: JTAGPort, chipId: Int) => {
|
||||
val jtag_wire = Wire(new JTAGIO)
|
||||
jtag_wire.TDO.data := port.io.TDO
|
||||
jtag_wire.TDO.driven := true.B
|
||||
@@ -62,7 +62,7 @@ class WithArtyJTAGHarnessBinder extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithArtyUARTHarnessBinder extends HarnessBinder({
|
||||
case (th: Arty35THarness, port: UARTPort) => {
|
||||
case (th: Arty35THarness, port: UARTPort, chipId: Int) => {
|
||||
withClockAndReset(th.clock_32MHz, th.ck_rst) {
|
||||
IOBUF(th.uart_rxd_out, port.io.txd)
|
||||
port.io.rxd := IOBUF(th.uart_txd_in)
|
||||
|
||||
@@ -58,5 +58,5 @@ class NoCoresArty100TConfig extends Config(
|
||||
class BringupArty100TConfig extends Config(
|
||||
new WithArty100TSerialTLToGPIO ++
|
||||
new WithArty100TTweaks(freqMHz = 50) ++
|
||||
new testchipip.serdes.WithSerialTLClockDirection(provideClockFreqMHz = Some(50)) ++
|
||||
new testchipip.serdes.WithSerialTLPHYParams(testchipip.serdes.InternalSyncSerialParams(freqMHz=50)) ++
|
||||
new chipyard.ChipBringupHostConfig)
|
||||
|
||||
@@ -19,9 +19,10 @@ import sifive.fpgashells.clocks._
|
||||
import chipyard._
|
||||
import chipyard.harness._
|
||||
import chipyard.iobinders._
|
||||
import testchipip.serdes._
|
||||
|
||||
class WithArty100TUARTTSI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTTSIPort) => {
|
||||
case (th: HasHarnessInstantiators, port: UARTTSIPort, chipId: Int) => {
|
||||
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
|
||||
val harnessIO = IO(new UARTPortIO(port.io.uartParams)).suggestName("uart_tsi")
|
||||
harnessIO <> port.io.uart
|
||||
@@ -44,7 +45,7 @@ class WithArty100TUARTTSI extends HarnessBinder({
|
||||
|
||||
|
||||
class WithArty100TDDRTL extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: TLMemPort) => {
|
||||
case (th: HasHarnessInstantiators, port: TLMemPort, chipId: Int) => {
|
||||
val artyTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
|
||||
val bundles = artyTh.ddrClient.out.map(_._1)
|
||||
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||
@@ -55,47 +56,58 @@ class WithArty100TDDRTL extends HarnessBinder({
|
||||
|
||||
// Uses PMOD JA/JB
|
||||
class WithArty100TSerialTLToGPIO extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SerialTLPort) => {
|
||||
case (th: HasHarnessInstantiators, port: SerialTLPort, chipId: Int) => {
|
||||
val artyTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
|
||||
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("serial_tl")
|
||||
harnessIO <> port.io
|
||||
val clkIO = IOPin(harnessIO.clock)
|
||||
val packagePinsWithPackageIOs = Seq(
|
||||
("G13", clkIO),
|
||||
("B11", IOPin(harnessIO.bits.out.valid)),
|
||||
("A11", IOPin(harnessIO.bits.out.ready)),
|
||||
("D12", IOPin(harnessIO.bits.in.valid)),
|
||||
("D13", IOPin(harnessIO.bits.in.ready)),
|
||||
("B18", IOPin(harnessIO.bits.out.bits, 0)),
|
||||
("A18", IOPin(harnessIO.bits.out.bits, 1)),
|
||||
("K16", IOPin(harnessIO.bits.out.bits, 2)),
|
||||
("E15", IOPin(harnessIO.bits.out.bits, 3)),
|
||||
("E16", IOPin(harnessIO.bits.in.bits, 0)),
|
||||
("D15", IOPin(harnessIO.bits.in.bits, 1)),
|
||||
("C15", IOPin(harnessIO.bits.in.bits, 2)),
|
||||
("J17", IOPin(harnessIO.bits.in.bits, 3))
|
||||
)
|
||||
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||
artyTh.xdc.addPackagePin(io, pin)
|
||||
artyTh.xdc.addIOStandard(io, "LVCMOS33")
|
||||
}}
|
||||
|
||||
// Don't add IOB to the clock, if its an input
|
||||
if (DataMirror.directionOf(port.io.clock) == Direction.Input) {
|
||||
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||
artyTh.xdc.addIOB(io)
|
||||
}}
|
||||
harnessIO match {
|
||||
case io: DecoupledSerialIO => {
|
||||
val clkIO = io match {
|
||||
case io: InternalSyncSerialIO => IOPin(io.clock_out)
|
||||
case io: ExternalSyncSerialIO => IOPin(io.clock_in)
|
||||
}
|
||||
val packagePinsWithPackageIOs = Seq(
|
||||
("G13", clkIO),
|
||||
("B11", IOPin(io.out.valid)),
|
||||
("A11", IOPin(io.out.ready)),
|
||||
("D12", IOPin(io.in.valid)),
|
||||
("D13", IOPin(io.in.ready)),
|
||||
("B18", IOPin(io.out.bits, 0)),
|
||||
("A18", IOPin(io.out.bits, 1)),
|
||||
("K16", IOPin(io.out.bits, 2)),
|
||||
("E15", IOPin(io.out.bits, 3)),
|
||||
("E16", IOPin(io.in.bits, 0)),
|
||||
("D15", IOPin(io.in.bits, 1)),
|
||||
("C15", IOPin(io.in.bits, 2)),
|
||||
("J17", IOPin(io.in.bits, 3))
|
||||
)
|
||||
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||
artyTh.xdc.addPackagePin(io, pin)
|
||||
artyTh.xdc.addIOStandard(io, "LVCMOS33")
|
||||
}}
|
||||
|
||||
// Don't add IOB to the clock, if its an input
|
||||
io match {
|
||||
case io: InternalSyncSerialIO => packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||
artyTh.xdc.addIOB(io)
|
||||
}}
|
||||
case io: ExternalSyncSerialIO => packagePinsWithPackageIOs.drop(1).foreach { case (pin, io) => {
|
||||
artyTh.xdc.addIOB(io)
|
||||
}}
|
||||
}
|
||||
|
||||
artyTh.sdc.addClock("ser_tl_clock", clkIO, 100)
|
||||
artyTh.sdc.addGroup(pins = Seq(clkIO))
|
||||
artyTh.xdc.clockDedicatedRouteFalse(clkIO)
|
||||
}
|
||||
}
|
||||
|
||||
artyTh.sdc.addClock("ser_tl_clock", clkIO, 100)
|
||||
artyTh.sdc.addGroup(pins = Seq(clkIO))
|
||||
artyTh.xdc.clockDedicatedRouteFalse(clkIO)
|
||||
}
|
||||
})
|
||||
|
||||
// Maps the UART device to the on-board USB-UART
|
||||
class WithArty100TUART(rxdPin: String = "A9", txdPin: String = "D10") extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTPort) => {
|
||||
case (th: HasHarnessInstantiators, port: UARTPort, chipId: Int) => {
|
||||
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
|
||||
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("uart")
|
||||
harnessIO <> port.io
|
||||
@@ -114,7 +126,7 @@ class WithArty100TUART(rxdPin: String = "A9", txdPin: String = "D10") extends Ha
|
||||
class WithArty100TPMODUART extends WithArty100TUART("G2", "F3")
|
||||
|
||||
class WithArty100TJTAG extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: JTAGPort) => {
|
||||
case (th: HasHarnessInstantiators, port: JTAGPort, chipId: Int) => {
|
||||
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
|
||||
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("jtag")
|
||||
harnessIO <> port.io
|
||||
|
||||
@@ -15,7 +15,7 @@ import chipyard.harness._
|
||||
import chipyard.iobinders._
|
||||
|
||||
class WithNexysVideoUARTTSI(uartBaudRate: BigInt = 115200) extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTTSIPort) => {
|
||||
case (th: HasHarnessInstantiators, port: UARTTSIPort, chipId: Int) => {
|
||||
val nexysvideoth = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[NexysVideoHarness]
|
||||
nexysvideoth.io_uart_bb.bundle <> port.io.uart
|
||||
nexysvideoth.other_leds(1) := port.io.dropped
|
||||
@@ -27,7 +27,7 @@ class WithNexysVideoUARTTSI(uartBaudRate: BigInt = 115200) extends HarnessBinder
|
||||
})
|
||||
|
||||
class WithNexysVideoDDRTL extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: TLMemPort) => {
|
||||
case (th: HasHarnessInstantiators, port: TLMemPort, chipId: Int) => {
|
||||
val nexysTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[NexysVideoHarness]
|
||||
val bundles = nexysTh.ddrClient.get.out.map(_._1)
|
||||
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||
|
||||
@@ -16,21 +16,21 @@ import chipyard.iobinders._
|
||||
|
||||
/*** UART ***/
|
||||
class WithVC707UARTHarnessBinder extends HarnessBinder({
|
||||
case (th: VC707FPGATestHarnessImp, port: UARTPort) => {
|
||||
case (th: VC707FPGATestHarnessImp, port: UARTPort, chipId: Int) => {
|
||||
th.vc707Outer.io_uart_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** SPI ***/
|
||||
class WithVC707SPISDCardHarnessBinder extends HarnessBinder({
|
||||
case (th: VC707FPGATestHarnessImp, port: SPIPort) => {
|
||||
case (th: VC707FPGATestHarnessImp, port: SPIPort, chipId: Int) => {
|
||||
th.vc707Outer.io_spi_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** Experimental DDR ***/
|
||||
class WithVC707DDRMemHarnessBinder extends HarnessBinder({
|
||||
case (th: VC707FPGATestHarnessImp, port: TLMemPort) => {
|
||||
case (th: VC707FPGATestHarnessImp, port: TLMemPort, chipId: Int) => {
|
||||
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 }
|
||||
|
||||
@@ -15,21 +15,21 @@ import chipyard.iobinders._
|
||||
|
||||
/*** UART ***/
|
||||
class WithUART extends HarnessBinder({
|
||||
case (th: VCU118FPGATestHarnessImp, port: UARTPort) => {
|
||||
case (th: VCU118FPGATestHarnessImp, port: UARTPort, chipId: Int) => {
|
||||
th.vcu118Outer.io_uart_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** SPI ***/
|
||||
class WithSPISDCard extends HarnessBinder({
|
||||
case (th: VCU118FPGATestHarnessImp, port: SPIPort) => {
|
||||
case (th: VCU118FPGATestHarnessImp, port: SPIPort, chipId: Int) => {
|
||||
th.vcu118Outer.io_spi_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** Experimental DDR ***/
|
||||
class WithDDRMem extends HarnessBinder({
|
||||
case (th: VCU118FPGATestHarnessImp, port: TLMemPort) => {
|
||||
case (th: VCU118FPGATestHarnessImp, port: TLMemPort, chipId: Int) => {
|
||||
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 }
|
||||
|
||||
@@ -18,34 +18,34 @@ import chipyard.iobinders._
|
||||
|
||||
/*** UART ***/
|
||||
class WithBringupUART extends HarnessBinder({
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: UARTPort) => {
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: UARTPort, chipId: Int) => {
|
||||
th.bringupOuter.io_fmc_uart_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** I2C ***/
|
||||
class WithBringupI2C extends HarnessBinder({
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: chipyard.iobinders.I2CPort) => {
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: chipyard.iobinders.I2CPort, chipId: Int) => {
|
||||
th.bringupOuter.io_i2c_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** GPIO ***/
|
||||
class WithBringupGPIO extends HarnessBinder({
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: GPIOPort) => {
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: GPIOPort, chipId: Int) => {
|
||||
th.bringupOuter.io_gpio_bb(port.pinId).bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
/*** TSI Host Widget ***/
|
||||
class WithBringupTSIHost extends HarnessBinder({
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: TLMemPort) => {
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: TLMemPort, chipId: Int) => {
|
||||
val tsiBundles = th.bringupOuter.tsiDdrClient.out.map(_._1)
|
||||
val tsiDdrClientBundle = Wire(new HeterogeneousBag(tsiBundles.map(_.cloneType)))
|
||||
tsiBundles.zip(tsiDdrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
tsiDdrClientBundle <> port.io
|
||||
}
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: TSIHostWidgetPort) => {
|
||||
case (th: BringupVCU118FPGATestHarnessImp, port: TSIHostWidgetPort, chipId: Int) => {
|
||||
th.bringupOuter.io_tsi_serial_bb.bundle <> port.io
|
||||
}
|
||||
})
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#if __has_include("spiketile_tsi.h")
|
||||
#define SPIKETILE_HTIF_TSI
|
||||
extern htif_t* tsi;
|
||||
extern std::map<int, htif_t*> tsis;
|
||||
#endif
|
||||
#if __has_include("spiketile_dtm.h")
|
||||
#define SPIKETILE_HTIF_DTM
|
||||
@@ -346,8 +346,8 @@ extern "C" void spike_tile(int hartid, char* isa,
|
||||
chipyard_simif_t* simif = tile->simif;
|
||||
processor_t* proc = tile->proc;
|
||||
#if defined(SPIKETILE_HTIF_TSI)
|
||||
if (!simif->htif && tsi)
|
||||
simif->htif = tsi;
|
||||
if (!simif->htif && tsis.size() > 0 && tsis[0])
|
||||
simif->htif = tsis[0];
|
||||
#endif
|
||||
#if defined(SPIKETILE_HTIF_DTM)
|
||||
if (!simif->htif && dtm)
|
||||
|
||||
@@ -13,10 +13,10 @@ import freechips.rocketchip.prci._
|
||||
case object ClockTapKey extends Field[Boolean](true)
|
||||
|
||||
trait CanHaveClockTap { this: BaseSubsystem =>
|
||||
require(p(SubsystemDriveAsyncClockGroupsKey).isEmpty, "Subsystem asyncClockGroups must be undriven")
|
||||
require(!p(SubsystemDriveClockGroupsFromIO), "Subsystem must not drive clocks from IO")
|
||||
val clockTapNode = Option.when(p(ClockTapKey)) {
|
||||
val clockTap = ClockSinkNode(Seq(ClockSinkParameters(name=Some("clock_tap"))))
|
||||
clockTap := ClockGroup() := asyncClockGroupsNode
|
||||
clockTap := ClockGroup() := allClockGroupsNode
|
||||
clockTap
|
||||
}
|
||||
val clockTapIO = clockTapNode.map { node => InModuleBody {
|
||||
|
||||
@@ -67,8 +67,8 @@ class AbstractConfig extends Config(
|
||||
new testchipip.boot.WithBootAddrReg ++ // add a boot-addr-reg for configurable boot address
|
||||
new testchipip.serdes.WithSerialTL(Seq( // add a serial-tilelink interface
|
||||
testchipip.serdes.SerialTLParams(
|
||||
client = Some(testchipip.serdes.SerialTLClientParams(idBits=4)), // serial-tilelink interface will master the FBUS, and support 4 idBits
|
||||
width = 32 // serial-tilelink interface with 32 lanes
|
||||
client = Some(testchipip.serdes.SerialTLClientParams()), // serial-tilelink interface will master the FBUS, and support 4 idBits
|
||||
phyParams = testchipip.serdes.ExternalSyncSerialParams(width=32) // serial-tilelink interface with 32 lanes
|
||||
)
|
||||
)) ++
|
||||
new testchipip.soc.WithMbusScratchpad(base = 0x08000000, // add 64 KiB on-chip scratchpad
|
||||
|
||||
@@ -22,8 +22,18 @@ class ChipLikeRocketConfig extends Config(
|
||||
//==================================
|
||||
// Set up I/O
|
||||
//==================================
|
||||
new testchipip.serdes.WithSerialTLWidth(4) ++ // 4bit wide Serialized TL interface to minimize IO
|
||||
new testchipip.serdes.WithSerialTLMem(size = (1 << 30) * 4L) ++ // Configure the off-chip memory accessible over serial-tl as backing memory
|
||||
new testchipip.serdes.WithSerialTL(Seq(testchipip.serdes.SerialTLParams( // 1 serial tilelink port
|
||||
manager = Some(testchipip.serdes.SerialTLManagerParams( // port acts as a manager of offchip memory
|
||||
memParams = Seq(testchipip.serdes.ManagerRAMParams( // 4 GB of off-chip memory
|
||||
address = BigInt("80000000", 16),
|
||||
size = BigInt("100000000", 16)
|
||||
)),
|
||||
isMemoryDevice = true
|
||||
)),
|
||||
client = Some(testchipip.serdes.SerialTLClientParams()), // Allow an external manager to probe this chip
|
||||
phyParams = testchipip.serdes.ExternalSyncSerialParams(width=4) // 4-bit bidir interface, sync'd to an external clock
|
||||
))) ++
|
||||
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++ // Remove axi4 mem port
|
||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ // 1 memory channel
|
||||
|
||||
@@ -60,10 +70,16 @@ class ChipBringupHostConfig extends Config(
|
||||
//=============================
|
||||
// Setup the SerialTL side on the bringup device
|
||||
//=============================
|
||||
new testchipip.serdes.WithSerialTLWidth(4) ++ // match width with the chip
|
||||
new testchipip.serdes.WithSerialTLMem(base = 0x0, size = 0x80000000L, // accessible memory of the chip that doesn't come from the tethered host
|
||||
idBits = 4, isMainMemory = false) ++ // This assumes off-chip mem starts at 0x8000_0000
|
||||
new testchipip.serdes.WithSerialTLClockDirection(provideClockFreqMHz = Some(75)) ++ // bringup board drives the clock for the serial-tl receiver on the chip, use 75MHz clock
|
||||
new testchipip.serdes.WithSerialTL(Seq(testchipip.serdes.SerialTLParams(
|
||||
manager = Some(testchipip.serdes.SerialTLManagerParams(
|
||||
memParams = Seq(testchipip.serdes.ManagerRAMParams( // Bringup platform can access all memory from 0 to DRAM_BASE
|
||||
address = BigInt("00000000", 16),
|
||||
size = BigInt("80000000", 16)
|
||||
))
|
||||
)),
|
||||
client = Some(testchipip.serdes.SerialTLClientParams()), // Allow chip to access this device's memory (DRAM)
|
||||
phyParams = testchipip.serdes.InternalSyncSerialParams(width=4, freqMHz = 75) // bringup platform provides the clock
|
||||
))) ++
|
||||
|
||||
//============================
|
||||
// Setup bus topology on the bringup system
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package chipyard
|
||||
|
||||
import org.chipsalliance.cde.config.{Config}
|
||||
import freechips.rocketchip.diplomacy.{AddressSet}
|
||||
import freechips.rocketchip.subsystem.{SBUS}
|
||||
import testchipip.soc.{OBUS}
|
||||
|
||||
// ------------------------------------------------
|
||||
// Configs demonstrating chip-to-chip communication
|
||||
// ------------------------------------------------
|
||||
|
||||
// Simple design which exposes a second serial-tl port that can connect to another instance of itself
|
||||
class SymmetricChipletRocketConfig extends Config(
|
||||
new chipyard.harness.WithSerialTLTiedOff(tieoffs=Some(Seq(1))) ++ // Tie-off the chip-to-chip link in single-chip sims
|
||||
new testchipip.serdes.WithSerialTL(Seq(
|
||||
testchipip.serdes.SerialTLParams( // 0th serial-tl is chip-to-bringup-fpga
|
||||
client = Some(testchipip.serdes.SerialTLClientParams()), // bringup serial-tl acts only as a client
|
||||
phyParams = testchipip.serdes.ExternalSyncSerialParams() // bringup serial-tl is sync'd to external clock
|
||||
),
|
||||
testchipip.serdes.SerialTLParams( // 1st serial-tl is chip-to-chip
|
||||
client = Some(testchipip.serdes.SerialTLClientParams()), // chip-to-chip serial-tl acts as a client
|
||||
manager = Some(testchipip.serdes.SerialTLManagerParams( // chip-to-chip serial-tl managers other chip's memory
|
||||
memParams = Seq(testchipip.serdes.ManagerRAMParams(
|
||||
address = 0,
|
||||
size = 1L << 32,
|
||||
)),
|
||||
slaveWhere = OBUS
|
||||
)),
|
||||
phyParams = testchipip.serdes.SourceSyncSerialParams() // chip-to-chip serial-tl is symmetric source-sync'd
|
||||
))
|
||||
) ++
|
||||
new testchipip.soc.WithOffchipBusClient(SBUS, // obus provides path to other chip's memory
|
||||
blockRange = Seq(AddressSet(0, (1L << 32) - 1)), // The lower 4GB is mapped to this chip
|
||||
replicationBase = Some(1L << 32) // The upper 4GB goes off-chip
|
||||
) ++
|
||||
new testchipip.soc.WithOffchipBus ++
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
// Simulates 2X of the SymmetricChipletRocketConfig in a multi-sim config
|
||||
class MultiSimSymmetricChipletRocketConfig extends Config(
|
||||
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++
|
||||
new chipyard.harness.WithMultiChipSerialTL(chip0=0, chip1=1, chip0portId=1, chip1portId=1) ++
|
||||
new chipyard.harness.WithMultiChip(0, new SymmetricChipletRocketConfig) ++
|
||||
new chipyard.harness.WithMultiChip(1, new SymmetricChipletRocketConfig)
|
||||
)
|
||||
@@ -11,10 +11,10 @@ import freechips.rocketchip.util.{PlusArg}
|
||||
import freechips.rocketchip.subsystem.{CacheBlockBytes}
|
||||
import freechips.rocketchip.devices.debug.{SimJTAG}
|
||||
import freechips.rocketchip.jtag.{JTAGIO}
|
||||
import testchipip.serdes.{SerialTLKey}
|
||||
import testchipip.serdes._
|
||||
import testchipip.uart.{UARTAdapter}
|
||||
import testchipip.dram.{SimDRAM}
|
||||
import testchipip.tsi.{TSIHarness, SimTSI}
|
||||
import testchipip.tsi.{TSIHarness, SimTSI, SerialRAM}
|
||||
import chipyard.harness.{BuildTop}
|
||||
|
||||
// A "flat" TestHarness that doesn't use IOBinders
|
||||
@@ -46,18 +46,28 @@ class FlatTestHarness(implicit val p: Parameters) extends Module {
|
||||
val serialTLManagerParams = sVal.manager.get
|
||||
require(serialTLManagerParams.isMemoryDevice)
|
||||
|
||||
withClockAndReset(clock, reset) {
|
||||
val serial_bits = dut.serial_tl_pad.bits
|
||||
if (DataMirror.directionOf(dut.serial_tl_pad.clock) == Direction.Input) {
|
||||
dut.serial_tl_pad.clock := clock
|
||||
}
|
||||
val harnessRAM = TSIHarness.connectRAM(
|
||||
p(SerialTLKey)(0),
|
||||
lazyDut.system.serdessers(0),
|
||||
serial_bits,
|
||||
reset)
|
||||
io.success := SimTSI.connect(harnessRAM.module.io.tsi, clock, reset)
|
||||
// Figure out which clock drives the harness TLSerdes, based on the port type
|
||||
val serial_ram_clock = dut.serial_tl_pad match {
|
||||
case io: InternalSyncSerialIO => io.clock_out
|
||||
case io: ExternalSyncSerialIO => clock
|
||||
}
|
||||
dut.serial_tl_pad match {
|
||||
case io: ExternalSyncSerialIO => io.clock_in := clock
|
||||
case io: InternalSyncSerialIO =>
|
||||
}
|
||||
|
||||
dut.serial_tl_pad match {
|
||||
case pad: DecoupledSerialIO => {
|
||||
withClockAndReset(serial_ram_clock, reset) {
|
||||
// SerialRAM implements the memory regions the chip expects
|
||||
val ram = Module(LazyModule(new SerialRAM(lazyDut.system.serdessers(0), p(SerialTLKey)(0))).module)
|
||||
ram.io.ser.in <> pad.out
|
||||
pad.in <> ram.io.ser.out
|
||||
|
||||
// Allow TSI to master the chip
|
||||
io.success := SimTSI.connect(ram.io.tsi, serial_ram_clock, reset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JTAG
|
||||
|
||||
@@ -17,7 +17,7 @@ import testchipip.tsi.{SimTSI, SerialRAM, TSI, TSIIO}
|
||||
import testchipip.soc.{TestchipSimDTM}
|
||||
import testchipip.spi.{SimSPIFlashModel}
|
||||
import testchipip.uart.{UARTAdapter, UARTToSerial}
|
||||
import testchipip.serdes.{SerialWidthAdapter}
|
||||
import testchipip.serdes._
|
||||
import testchipip.iceblk.{SimBlockDevice, BlockDeviceModel}
|
||||
import testchipip.cosim.{SpikeCosim}
|
||||
import icenet.{NicLoopback, SimNetwork}
|
||||
@@ -28,8 +28,8 @@ import chipyard.iobinders._
|
||||
case object HarnessBinders extends Field[HarnessBinderFunction]({case _ => })
|
||||
|
||||
object ApplyHarnessBinders {
|
||||
def apply(th: HasHarnessInstantiators, ports: Seq[Port[_]])(implicit p: Parameters): Unit = {
|
||||
ports.foreach(port => p(HarnessBinders)(th, port))
|
||||
def apply(th: HasHarnessInstantiators, ports: Seq[Port[_]], chipId: Int)(implicit p: Parameters): Unit = {
|
||||
ports.foreach(port => p(HarnessBinders)(th, port, chipId))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,24 +41,22 @@ class HarnessBinder[T <: HasHarnessInstantiators, S <: Port[_]](
|
||||
|
||||
|
||||
class WithGPIOTiedOff extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: GPIOPort) => {
|
||||
case (th: HasHarnessInstantiators, port: GPIOPort, chipId: Int) => {
|
||||
port.io <> AnalogConst(0)
|
||||
}
|
||||
})
|
||||
|
||||
// DOC include start: WithUARTAdapter
|
||||
class WithUARTAdapter extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTPort) => {
|
||||
case (th: HasHarnessInstantiators, port: UARTPort, chipId: Int) => {
|
||||
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
|
||||
UARTAdapter.connect(Seq(port.io), div, false)
|
||||
}
|
||||
})
|
||||
// DOC include end: WithUARTAdapter
|
||||
|
||||
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SPIFlashPort) => {
|
||||
case (th: HasHarnessInstantiators, port: SPIFlashPort, chipId: Int) => {
|
||||
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.")
|
||||
@@ -69,7 +67,7 @@ class WithSimSPIFlashModel(rdOnly: Boolean = true) extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithSimBlockDevice extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: BlockDevicePort) => {
|
||||
case (th: HasHarnessInstantiators, port: BlockDevicePort, chipId: Int) => {
|
||||
val sim_blkdev = Module(new SimBlockDevice(port.params))
|
||||
sim_blkdev.io.bdev <> port.io.bits
|
||||
sim_blkdev.io.clock := port.io.clock
|
||||
@@ -78,7 +76,7 @@ class WithSimBlockDevice extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithBlockDeviceModel extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: BlockDevicePort) => {
|
||||
case (th: HasHarnessInstantiators, port: BlockDevicePort, chipId: Int) => {
|
||||
val blkdev_model = Module(new BlockDeviceModel(16, port.params))
|
||||
blkdev_model.io <> port.io.bits
|
||||
blkdev_model.clock := port.io.clock
|
||||
@@ -87,33 +85,33 @@ class WithBlockDeviceModel extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithLoopbackNIC extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: NICPort) => {
|
||||
case (th: HasHarnessInstantiators, port: NICPort, chipId: Int) => {
|
||||
withClock(port.io.clock) { NicLoopback.connect(port.io.bits, port.params) }
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimNetwork extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: NICPort) => {
|
||||
case (th: HasHarnessInstantiators, port: NICPort, chipId: Int) => {
|
||||
withClock(port.io.clock) { SimNetwork.connect(Some(port.io.bits), port.io.clock, th.harnessBinderReset.asBool) }
|
||||
}
|
||||
})
|
||||
|
||||
class WithSimAXIMem extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: AXI4MemPort) => {
|
||||
case (th: HasHarnessInstantiators, port: AXI4MemPort, chipId: Int) => {
|
||||
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
|
||||
mem.io_axi4.head <> port.io.bits
|
||||
}
|
||||
})
|
||||
|
||||
class WithBlackBoxSimMem(additionalLatency: Int = 0) extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: AXI4MemPort) => {
|
||||
case (th: HasHarnessInstantiators, port: AXI4MemPort, chipId: Int) => {
|
||||
// TODO FIX: This currently makes each SimDRAM contain the entire memory space
|
||||
val memSize = port.params.master.size
|
||||
val memBase = port.params.master.base
|
||||
val lineSize = 64 // cache block size
|
||||
val clockFreq = port.clockFreqMHz
|
||||
val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, memBase, port.edge.bundle)).suggestName("simdram")
|
||||
val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, memBase, port.edge.bundle, chipId)).suggestName("simdram")
|
||||
|
||||
mem.io.clock := port.io.clock
|
||||
mem.io.reset := th.harnessBinderReset.asAsyncReset
|
||||
@@ -140,7 +138,7 @@ class WithBlackBoxSimMem(additionalLatency: Int = 0) extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithSimAXIMMIO extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: AXI4MMIOPort) => {
|
||||
case (th: HasHarnessInstantiators, port: AXI4MMIOPort, chipId: Int) => {
|
||||
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
|
||||
@@ -148,13 +146,13 @@ class WithSimAXIMMIO extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithTieOffInterrupts extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: ExtIntPort) => {
|
||||
case (th: HasHarnessInstantiators, port: ExtIntPort, chipId: Int) => {
|
||||
port.io := 0.U
|
||||
}
|
||||
})
|
||||
|
||||
class WithTieOffL2FBusAXI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: AXI4InPort) => {
|
||||
case (th: HasHarnessInstantiators, port: AXI4InPort, chipId: Int) => {
|
||||
port.io := DontCare
|
||||
port.io.bits.aw.valid := false.B
|
||||
port.io.bits.w.valid := false.B
|
||||
@@ -165,7 +163,7 @@ class WithTieOffL2FBusAXI extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithSimJTAGDebug extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: JTAGPort) => {
|
||||
case (th: HasHarnessInstantiators, port: JTAGPort, chipId: Int) => {
|
||||
val dtm_success = WireInit(false.B)
|
||||
when (dtm_success) { th.success := true.B }
|
||||
val jtag_wire = Wire(new JTAGIO)
|
||||
@@ -180,7 +178,7 @@ class WithSimJTAGDebug extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithSimDMI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: DMIPort) => {
|
||||
case (th: HasHarnessInstantiators, port: DMIPort, chipId: Int) => {
|
||||
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)
|
||||
@@ -188,7 +186,7 @@ class WithSimDMI extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithTiedOffJTAG extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: JTAGPort) => {
|
||||
case (th: HasHarnessInstantiators, port: JTAGPort, chipId: Int) => {
|
||||
port.io.TCK := true.B.asClock
|
||||
port.io.TMS := true.B
|
||||
port.io.TDI := true.B
|
||||
@@ -196,7 +194,7 @@ class WithTiedOffJTAG extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithTiedOffDMI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: DMIPort) => {
|
||||
case (th: HasHarnessInstantiators, port: DMIPort, chipId: Int) => {
|
||||
port.io.dmi.req.valid := false.B
|
||||
port.io.dmi.req.bits := DontCare
|
||||
port.io.dmi.resp.ready := true.B
|
||||
@@ -205,40 +203,57 @@ class WithTiedOffDMI extends HarnessBinder({
|
||||
}
|
||||
})
|
||||
|
||||
class WithSerialTLTiedOff extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SerialTLPort) => {
|
||||
if (DataMirror.directionOf(port.io.clock) == Direction.Input) {
|
||||
port.io.clock := false.B.asClock
|
||||
// If tieoffs is specified, a list of serial portIds to tie off
|
||||
// If tieoffs is unspecified, ties off all serial ports
|
||||
class WithSerialTLTiedOff(tieoffs: Option[Seq[Int]] = None) extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SerialTLPort, chipId: Int) if (tieoffs.map(_.contains(port.portId)).getOrElse(true)) => {
|
||||
port.io match {
|
||||
case io: DecoupledSerialIO => io.out.ready := false.B; io.in.valid := false.B; io.in.bits := DontCare;
|
||||
case io: SourceSyncSerialIO => {
|
||||
io.clock_in := false.B.asClock
|
||||
io.reset_in := false.B.asAsyncReset
|
||||
io.in := DontCare
|
||||
io.credit_in := DontCare
|
||||
}
|
||||
}
|
||||
port.io match {
|
||||
case io: InternalSyncSerialIO =>
|
||||
case io: ExternalSyncSerialIO => io.clock_in := false.B.asClock
|
||||
case _ =>
|
||||
}
|
||||
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
|
||||
case (th: HasHarnessInstantiators, port: SerialTLPort, chipId: Int) if (port.portId == 0) => {
|
||||
port.io match {
|
||||
case io: InternalSyncSerialIO =>
|
||||
case io: ExternalSyncSerialIO => io.clock_in := th.harnessBinderClock
|
||||
}
|
||||
|
||||
port.io match {
|
||||
case io: DecoupledSerialIO => {
|
||||
// If the port is locally synchronous (provides a clock), drive everything with that clock
|
||||
// Else, drive everything with the harnes clock
|
||||
val clock = port.io match {
|
||||
case io: InternalSyncSerialIO => io.clock_out
|
||||
case io: ExternalSyncSerialIO => th.harnessBinderClock
|
||||
}
|
||||
withClock(clock) {
|
||||
val ram = Module(LazyModule(new SerialRAM(port.serdesser, port.params)(port.serdesser.p)).module)
|
||||
ram.io.ser.in <> io.out
|
||||
io.in <> ram.io.ser.out
|
||||
|
||||
val success = SimTSI.connect(ram.io.tsi, clock, th.harnessBinderReset, chipId)
|
||||
when (success) { th.success := true.B }
|
||||
}
|
||||
}
|
||||
}
|
||||
val ram = LazyModule(new SerialRAM(port.serdesser, port.params)(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.get
|
||||
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 HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTPort) => {
|
||||
case (th: HasHarnessInstantiators, port: UARTPort, chipId: Int) => {
|
||||
UARTAdapter.connect(Seq(port.io),
|
||||
baudrate=port.io.c.initBaudRate,
|
||||
clockFrequency=th.getHarnessBinderClockFreqHz.toInt,
|
||||
@@ -247,7 +262,7 @@ class WithSimUARTToUARTTSI extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithSimTSIToUARTTSI extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: UARTTSIPort) => {
|
||||
case (th: HasHarnessInstantiators, port: UARTTSIPort, chipId: Int) => {
|
||||
val freq = th.getHarnessBinderClockFreqHz.toInt
|
||||
val uart_to_serial = Module(new UARTToSerial(freq, port.io.uart.c))
|
||||
val serial_width_adapter = Module(new SerialWidthAdapter(8, TSI.WIDTH))
|
||||
@@ -261,27 +276,27 @@ class WithSimTSIToUARTTSI extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithTraceGenSuccess extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: SuccessPort) => {
|
||||
case (th: HasHarnessInstantiators, port: SuccessPort, chipId: Int) => {
|
||||
when (port.io) { th.success := true.B }
|
||||
}
|
||||
})
|
||||
|
||||
class WithCospike extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: TracePort) => {
|
||||
case (th: HasHarnessInstantiators, port: TracePort, chipId: Int) => {
|
||||
port.io.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, port.cosimCfg))
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithCustomBootPinPlusArg extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: CustomBootPort) => {
|
||||
case (th: HasHarnessInstantiators, port: CustomBootPort, chipId: Int) => {
|
||||
val pin = PlusArg("custom_boot_pin", width=1)
|
||||
port.io := pin
|
||||
}
|
||||
})
|
||||
|
||||
class WithClockFromHarness extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: ClockPort) => {
|
||||
case (th: HasHarnessInstantiators, port: ClockPort, chipId: Int) => {
|
||||
// DOC include start: HarnessClockInstantiatorEx
|
||||
port.io := th.harnessClockInstantiator.requestClockMHz(s"clock_${port.freqMHz}MHz", port.freqMHz)
|
||||
// DOC include end: HarnessClockInstantiatorEx
|
||||
@@ -289,7 +304,7 @@ class WithClockFromHarness extends HarnessBinder({
|
||||
})
|
||||
|
||||
class WithResetFromHarness extends HarnessBinder({
|
||||
case (th: HasHarnessInstantiators, port: ResetPort) => {
|
||||
case (th: HasHarnessInstantiators, port: ResetPort, chipId: Int) => {
|
||||
port.io := th.referenceReset.asAsyncReset
|
||||
}
|
||||
})
|
||||
|
||||
@@ -89,7 +89,7 @@ trait HasHarnessInstantiators {
|
||||
withClockAndReset (harnessBinderClock, harnessBinderReset) {
|
||||
lazyDuts.zipWithIndex.foreach {
|
||||
case (d: HasChipyardPorts, i: Int) => {
|
||||
ApplyHarnessBinders(this, d.ports)(chipParameters(i))
|
||||
ApplyHarnessBinders(this, d.ports, i)(chipParameters(i))
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import freechips.rocketchip.devices.debug._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
import testchipip._
|
||||
import testchipip.serdes._
|
||||
|
||||
import chipyard._
|
||||
import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasChipyardPorts, Port, SerialTLPort}
|
||||
@@ -38,10 +38,10 @@ class MultiHarnessBinder[T <: Port[_], S <: HasHarnessInstantiators](
|
||||
)(implicit tag0: ClassTag[T], tag1: ClassTag[S]) extends Config((site, here, up) => {
|
||||
// Override any HarnessBinders for chip0/chip1
|
||||
case MultiChipParameters(`chip0`) => new Config(
|
||||
new HarnessBinder({case (th: S, port: T) if chip0portFn(port) => }) ++ up(MultiChipParameters(chip0))
|
||||
new HarnessBinder({case (th: S, port: T, chipId: Int) if chip0portFn(port) => }) ++ up(MultiChipParameters(chip0))
|
||||
)
|
||||
case MultiChipParameters(`chip1`) => new Config(
|
||||
new HarnessBinder({case (th: S, port: T) if chip1portFn(port) => }) ++ up(MultiChipParameters(chip1))
|
||||
new HarnessBinder({case (th: S, port: T, chipId: Int) if chip1portFn(port) => }) ++ up(MultiChipParameters(chip1))
|
||||
)
|
||||
// Set the multiharnessbinder key
|
||||
case MultiHarnessBinders(`chip0`, `chip1`) => up(MultiHarnessBinders(chip0, chip1)) :+ {
|
||||
@@ -60,11 +60,25 @@ class WithMultiChipSerialTL(chip0: Int, chip1: Int, chip0portId: Int = 0, chip1p
|
||||
(p0: SerialTLPort) => p0.portId == chip0portId,
|
||||
(p1: SerialTLPort) => p1.portId == chip1portId,
|
||||
(th: HasHarnessInstantiators, 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
|
||||
def connectDecoupledSyncSerialIO(clkSource: InternalSyncSerialIO, clkSink: ExternalSyncSerialIO) = {
|
||||
clkSink.clock_in := clkSource.clock_out
|
||||
clkSink.in <> clkSource.out
|
||||
clkSource.in <> clkSink.out
|
||||
}
|
||||
def connectSourceSyncSerialIO(a: SourceSyncSerialIO, b: SourceSyncSerialIO) = {
|
||||
a.clock_in := b.clock_out
|
||||
b.clock_in := a.clock_out
|
||||
a.reset_in := b.reset_out
|
||||
b.reset_in := a.reset_out
|
||||
a.in := b.out
|
||||
b.in := a.out
|
||||
a.credit_in := b.credit_out
|
||||
b.credit_in := a.credit_out
|
||||
}
|
||||
(p0.io, p1.io) match {
|
||||
case (io0: InternalSyncSerialIO, io1: ExternalSyncSerialIO) => connectDecoupledSyncSerialIO(io0, io1)
|
||||
case (io0: ExternalSyncSerialIO, io1: InternalSyncSerialIO) => connectDecoupledSyncSerialIO(io1, io0)
|
||||
case (io0: SourceSyncSerialIO , io1: SourceSyncSerialIO ) => connectSourceSyncSerialIO (io0, io1)
|
||||
}
|
||||
p0.io.bits.in <> p1.io.bits.out
|
||||
p1.io.bits.in <> p0.io.bits.out
|
||||
}
|
||||
)
|
||||
|
||||
@@ -6,6 +6,6 @@ import scala.collection.immutable.ListMap
|
||||
package object harness
|
||||
{
|
||||
import chipyard.iobinders.Port
|
||||
type HarnessBinderFunction = PartialFunction[(HasHarnessInstantiators, Port[_]), Unit]
|
||||
type HarnessBinderFunction = PartialFunction[(HasHarnessInstantiators, Port[_], Int), Unit]
|
||||
type MultiHarnessBinderFunction = (HasHarnessInstantiators, Seq[Port[_]], Seq[Port[_]]) => Unit
|
||||
}
|
||||
|
||||
@@ -72,8 +72,9 @@ case class DMIPort (val getIO: () => ClockedDMIIO)
|
||||
case class JTAGPort (val getIO: () => JTAGChipIO)
|
||||
extends Port[JTAGChipIO]
|
||||
|
||||
case class SerialTLPort (val getIO: () => ClockedIO[SerialIO], val params: SerialTLParams, val serdesser: TLSerdesser, val portId: Int)
|
||||
extends Port[ClockedIO[SerialIO]]
|
||||
// Lack of nice union types in scala-2 means we have to set this type as Data
|
||||
case class SerialTLPort (val getIO: () => Data, val params: SerialTLParams, val serdesser: TLSerdesser, val portId: Int)
|
||||
extends Port[Data]
|
||||
|
||||
case class UARTTSIPort (val getIO: () => UARTTSIIO)
|
||||
extends Port[UARTTSIIO]
|
||||
|
||||
@@ -15,6 +15,7 @@ import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
|
||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||
import sifive.blocks.devices.uart._
|
||||
|
||||
import testchipip.serdes.{ExternalSyncSerialIO}
|
||||
import testchipip.tsi.{SerialRAM}
|
||||
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
|
||||
|
||||
@@ -66,43 +67,46 @@ class WithFireSimIOCellModels extends Config((site, here, up) => {
|
||||
})
|
||||
|
||||
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, port.params)(port.serdesser.p))
|
||||
Module(ram.module)
|
||||
ram.module.io.ser <> port.io.bits
|
||||
case (th: FireSim, port: SerialTLPort, chipId: Int) => {
|
||||
port.io match {
|
||||
case io: ExternalSyncSerialIO => {
|
||||
io.clock_in := th.harnessBinderClock
|
||||
val ram = Module(LazyModule(new SerialRAM(port.serdesser, port.params)(port.serdesser.p)).module)
|
||||
ram.io.ser.in <> io.out
|
||||
io.in <> ram.io.ser.out
|
||||
|
||||
// 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.get, mainMemoryName, th.harnessBinderReset.asBool)(th.p)
|
||||
// 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(chipId)(ExtMem).isDefined
|
||||
val mainMemoryName = Option.when(hasMainMemory)(MainMemoryConsts.globalName(chipId))
|
||||
TSIBridge(th.harnessBinderClock, ram.io.tsi.get, mainMemoryName, th.harnessBinderReset.asBool)(th.p)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithNICBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: NICPort) => {
|
||||
case (th: FireSim, port: NICPort, chipId: Int) => {
|
||||
NICBridge(port.io.clock, port.io.bits)(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
class WithUARTBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: UARTPort) =>
|
||||
case (th: FireSim, port: UARTPort, chipId: Int) =>
|
||||
val uartSyncClock = th.harnessClockInstantiator.requestClockMHz("uart_clock", port.freqMHz)
|
||||
UARTBridge(uartSyncClock, port.io, th.harnessBinderReset.asBool, port.freqMHz)(th.p)
|
||||
})
|
||||
|
||||
class WithBlockDeviceBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: BlockDevicePort) => {
|
||||
case (th: FireSim, port: BlockDevicePort, chipId: Int) => {
|
||||
BlockDevBridge(port.io.clock, port.io.bits, th.harnessBinderReset.asBool)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithFASEDBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: AXI4MemPort) => {
|
||||
case (th: FireSim, port: AXI4MemPort, chipId: Int) => {
|
||||
val nastiKey = NastiParameters(port.io.bits.r.bits.data.getWidth,
|
||||
port.io.bits.ar.bits.addr.getWidth,
|
||||
port.io.bits.ar.bits.id.getWidth)
|
||||
@@ -110,24 +114,24 @@ class WithFASEDBridge extends HarnessBinder({
|
||||
CompleteConfig(th.p(firesim.configs.MemModelKey),
|
||||
nastiKey,
|
||||
Some(AXI4EdgeSummary(port.edge)),
|
||||
Some(MainMemoryConsts.globalName(th.p(MultiChipIdx)))))(th.p)
|
||||
Some(MainMemoryConsts.globalName(chipId))))(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
class WithTracerVBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: TracePort) => {
|
||||
case (th: FireSim, port: TracePort, chipId: Int) => {
|
||||
port.io.traces.map(tileTrace => TracerVBridge(tileTrace)(th.p))
|
||||
}
|
||||
})
|
||||
|
||||
class WithCospikeBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: TracePort) => {
|
||||
case (th: FireSim, port: TracePort, chipId: Int) => {
|
||||
port.io.traces.zipWithIndex.map(t => CospikeBridge(t._1, t._2, port.cosimCfg))
|
||||
}
|
||||
})
|
||||
|
||||
class WithSuccessBridge extends HarnessBinder({
|
||||
case (th: FireSim, port: SuccessPort) => {
|
||||
case (th: FireSim, port: SuccessPort, chipId: Int) => {
|
||||
GroundTestBridge(th.harnessBinderClock, port.io)(th.p)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -265,7 +265,7 @@ class FireSimSmallSystemConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
|
||||
new testchipip.serdes.WithSerialTL(Seq(testchipip.serdes.SerialTLParams(
|
||||
client = Some(testchipip.serdes.SerialTLClientParams(idBits = 4)),
|
||||
width = 32
|
||||
phyParams = testchipip.serdes.ExternalSyncSerialParams(width=32)
|
||||
))) ++
|
||||
new testchipip.iceblk.WithBlockDevice ++
|
||||
new chipyard.config.WithUARTInitBaudRate(BigInt(3686400L)) ++
|
||||
|
||||
Submodule generators/testchipip updated: 5435474950...e844c51a08
@@ -162,8 +162,7 @@ VERILATOR_NONCC_OPTS = \
|
||||
VERILATOR_CXXFLAGS = \
|
||||
$(SIM_CXXFLAGS) \
|
||||
$(RUNTIME_PROFILING_CFLAGS) \
|
||||
-DVERILATOR \
|
||||
-include $(build_dir)/$(long_name).plusArgs
|
||||
-DVERILATOR
|
||||
|
||||
VERILATOR_LDFLAGS = $(SIM_LDFLAGS)
|
||||
|
||||
@@ -194,13 +193,13 @@ model_mk_debug = $(model_dir_debug)/V$(TB).mk
|
||||
$(model_mk): $(sim_common_files) $(EXTRA_SIM_REQS)
|
||||
rm -rf $(model_dir)
|
||||
mkdir -p $(model_dir)
|
||||
$(VERILATOR) $(VERILATOR_OPTS) $(EXTRA_SIM_SOURCES) -o $(sim) -Mdir $(model_dir) -CFLAGS "-include $(model_header)"
|
||||
$(VERILATOR) $(VERILATOR_OPTS) $(EXTRA_SIM_SOURCES) -o $(sim) -Mdir $(model_dir)
|
||||
touch $@
|
||||
|
||||
$(model_mk_debug): $(sim_common_files) $(EXTRA_SIM_REQS)
|
||||
rm -rf $(model_dir_debug)
|
||||
mkdir -p $(model_dir_debug)
|
||||
$(VERILATOR) $(VERILATOR_OPTS) +define+DEBUG $(EXTRA_SIM_SOURCES) -o $(sim_debug) $(TRACING_OPTS) -Mdir $(model_dir_debug) -CFLAGS "-include $(model_header_debug)"
|
||||
$(VERILATOR) $(VERILATOR_OPTS) +define+DEBUG $(EXTRA_SIM_SOURCES) -o $(sim_debug) $(TRACING_OPTS) -Mdir $(model_dir_debug)
|
||||
touch $@
|
||||
|
||||
#########################################################################################
|
||||
|
||||
@@ -29,7 +29,7 @@ include libgloss.mk
|
||||
|
||||
PROGRAMS = pwm blkdev accum charcount nic-loopback big-blkdev pingd \
|
||||
streaming-passthrough streaming-fir nvdla spiflashread spiflashwrite fft gcd \
|
||||
hello mt-hello
|
||||
hello mt-hello symmetric
|
||||
|
||||
|
||||
.DEFAULT_GOAL := default
|
||||
|
||||
30
tests/symmetric.c
Normal file
30
tests/symmetric.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <riscv-pk/encoding.h>
|
||||
#include "marchid.h"
|
||||
|
||||
#define OBUS_OFFSET (0x1L << 32)
|
||||
|
||||
char src[] = "This is a test string. It will be written into the off-chip memory address, then copied back.";
|
||||
char dest[4096];
|
||||
char test[4096];
|
||||
|
||||
int main(void) {
|
||||
size_t write_start = rdcycle();
|
||||
memcpy(dest + OBUS_OFFSET, src, sizeof(src));
|
||||
size_t write_end = rdcycle();
|
||||
|
||||
printf("Wrote %ld bytes in %ld cycles\n", sizeof(src), write_end - write_start);
|
||||
|
||||
size_t read_start = rdcycle();
|
||||
memcpy(test, dest + OBUS_OFFSET, sizeof(src));
|
||||
size_t read_end = rdcycle();
|
||||
|
||||
if (memcmp(src, test, sizeof(src))) {
|
||||
printf("Remote write/read failed\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("Read %ld bytes in %ld cycles\n", sizeof(src), read_end - read_start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user