diff --git a/fpga/Makefile b/fpga/Makefile index 748a5029..74af21e9 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -14,22 +14,52 @@ sim_name := none ######################################################################################### # include shared variables ######################################################################################### +SUB_PROJECT ?= vcu118 + +ifeq ($(SUB_PROJECT),vcu118) + SBT_PROJECT ?= fpga_platforms + MODEL ?= VCU118FPGATestHarness + VLOG_MODEL ?= VCU118FPGATestHarness + MODEL_PACKAGE ?= chipyard.fpga.vcu118 + CONFIG ?= RocketVCU118Config + CONFIG_PACKAGE ?= chipyard.fpga.vcu118 + GENERATOR_PACKAGE ?= chipyard + TB ?= none # unused + TOP ?= ChipTop + BOARD ?= vcu118 +endif + +ifeq ($(SUB_PROJECT),bringup) + SBT_PROJECT ?= fpga_platforms + MODEL ?= BringupVCU118FPGATestHarness + VLOG_MODEL ?= BringupVCU118FPGATestHarness + MODEL_PACKAGE ?= chipyard.fpga.vcu118.bringup + CONFIG ?= RocketBringupConfig + CONFIG_PACKAGE ?= chipyard.fpga.vcu118.bringup + GENERATOR_PACKAGE ?= chipyard + TB ?= none # unused + TOP ?= ChipTop + BOARD ?= vcu118 +endif + +ifeq ($(SUB_PROJECT),arty) + # TODO: Fix with Arty + SBT_PROJECT ?= fpga_platforms + MODEL ?= BringupVCU118FPGATestHarness + VLOG_MODEL ?= BringupVCU118FPGATestHarness + MODEL_PACKAGE ?= chipyard.fpga.vcu118.bringup + CONFIG ?= RocketBringupConfig + CONFIG_PACKAGE ?= chipyard.fpga.vcu118.bringup + GENERATOR_PACKAGE ?= chipyard + TB ?= none # unused + TOP ?= ChipTop + BOARD ?= arty +endif + include $(base_dir)/variables.mk # default variables to build the arty example -SUB_PROJECT := fpga -SBT_PROJECT := fpga_platforms -MODEL := BringupVCU118FPGATestHarness -VLOG_MODEL := BringupVCU118FPGATestHarness -MODEL_PACKAGE := chipyard.fpga.vcu118.bringup -CONFIG := FakeBringupConfig -CONFIG_PACKAGE := chipyard.fpga.vcu118.bringup -GENERATOR_PACKAGE := chipyard -TB := none # unused -TOP := ChipTop - # setup the board to use -BOARD ?= vcu118 .PHONY: default default: $(mcs) diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala new file mode 100644 index 00000000..f7b0df10 --- /dev/null +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -0,0 +1,85 @@ +package chipyard.fpga.vcu118 + +import sys.process._ + +import freechips.rocketchip.config.{Config} +import freechips.rocketchip.subsystem.{SystemBusKey, PeripheryBusKey, ControlBusKey, ExtMem} +import freechips.rocketchip.devices.debug.{DebugModuleKey, ExportDebug, JTAG} +import freechips.rocketchip.devices.tilelink.{DevNullParams, BootROMLocated} +import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet} +import freechips.rocketchip.tile.{XLen} + +import sifive.blocks.devices.spi.{PeripherySPIKey, SPIParams} +import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams} + +import sifive.fpgashells.shell.{DesignKey} +import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize} + +class WithDefaultPeripherals extends Config((site, here, up) => { + case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L))) + case PeripherySPIKey => List(SPIParams(rAddress = BigInt(0x64001000L))) + case VCU118ShellPMOD => "SDIO" +}) + +class WithSystemModifications extends Config((site, here, up) => { + case DebugModuleKey => None // disable debug module + case ExportDebug => up(ExportDebug).copy(protocols = Set(JTAG)) // don't generate HTIF DTS + case SystemBusKey => up(SystemBusKey).copy( + errorDevice = Some(DevNullParams( + Seq(AddressSet(0x3000, 0xfff)), + maxAtomic=site(XLen)/8, + maxTransfer=128, + region = RegionType.TRACKED))) + case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = + Some(BigDecimal(site(FPGAFrequencyKey)*1000000).setScale(0, BigDecimal.RoundingMode.HALF_UP).toBigInt)) + case ControlBusKey => up(ControlBusKey, site).copy( + errorDevice = None) + case DTSTimebase => BigInt(1000000) + case BootROMLocated(x) => up(BootROMLocated(x), site).map { p => + // invoke makefile for sdboot + val freqMHz = site(FPGAFrequencyKey).toInt * 1000000 + val make = s"make -C fpga/src/main/resources/vcu118/sdboot PBUS_CLK=${freqMHz} bin" + require (make.! == 0, "Failed to build bootrom") + p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vcu118/sdboot/build/sdboot.bin") + } + case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(VCU118DDRSize)))) +}) + +class AbstractVCU118Config extends Config( + new WithUART ++ + new WithSPISDCard ++ + new WithDDRMem ++ + new WithUARTIOPassthrough ++ + new WithSPIIOPassthrough ++ + new WithTLIOPassthrough ++ + new WithDefaultPeripherals ++ + new WithSystemModifications ++ // remove debug module, setup busses, use sdboot bootrom, setup ext. mem. size + new freechips.rocketchip.subsystem.WithoutTLMonitors ++ + new chipyard.config.WithNoSubsystemDrivenClocks ++ + new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ + new chipyard.config.WithL2TLBs(1024) ++ + new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ + new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ + new chipyard.WithMulticlockCoherentBusTopology ++ + new freechips.rocketchip.system.BaseConfig) + +class RocketVCU118Config extends Config( + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new AbstractVCU118Config) + +class BoomVCU118Config extends Config( + new WithFPGAFrequency(75) ++ + new boom.common.WithNLargeBooms(1) ++ + new AbstractVCU118Config) + +class WithFPGAFrequency(MHz: Double) extends Config((site, here, up) => { + case FPGAFrequencyKey => MHz +}) + +class WithFPGAFreq25MHz extends WithFPGAFrequency(25) +class WithFPGAFreq50MHz extends WithFPGAFrequency(50) +class WithFPGAFreq75MHz extends WithFPGAFrequency(75) +class WithFPGAFreq100MHz extends WithFPGAFrequency(100) diff --git a/fpga/src/main/scala/vcu118/HarnessBinders.scala b/fpga/src/main/scala/vcu118/HarnessBinders.scala new file mode 100644 index 00000000..ae2462a2 --- /dev/null +++ b/fpga/src/main/scala/vcu118/HarnessBinders.scala @@ -0,0 +1,51 @@ +package chipyard.fpga.vcu118 + +import chisel3._ +import chisel3.experimental.{BaseModule} + +import freechips.rocketchip.util.{HeterogeneousBag} +import freechips.rocketchip.tilelink.{TLBundle} + +import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO} +import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO} + +import chipyard.{CanHaveMasterTLMemPort, HasHarnessSignalReferences} +import chipyard.harness.{OverrideHarnessBinder} + +/*** UART ***/ +class WithUART extends OverrideHarnessBinder({ + (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { + th match { case vcu118th: VCU118FPGATestHarnessImp => { + vcu118th.vcu118Outer.io_uart_bb.bundle <> ports.head + } } + + Nil + } +}) + +/*** SPI ***/ +class WithSPISDCard extends OverrideHarnessBinder({ + (system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => { + th match { case vcu118th: VCU118FPGATestHarnessImp => { + vcu118th.vcu118Outer.io_spi_bb.bundle <> ports.head + } } + + Nil + } +}) + +/*** Experimental DDR ***/ +class WithDDRMem extends OverrideHarnessBinder({ + (system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => { + th match { case vcu118th: VCU118FPGATestHarnessImp => { + require(ports.size == 1) + + val bundles = vcu118th.vcu118Outer.ddrClient.out.map(_._1) + val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType))) + bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } + ddrClientBundle <> ports.head + } } + + Nil + } +}) diff --git a/fpga/src/main/scala/vcu118/IOBinders.scala b/fpga/src/main/scala/vcu118/IOBinders.scala new file mode 100644 index 00000000..a1f67bcd --- /dev/null +++ b/fpga/src/main/scala/vcu118/IOBinders.scala @@ -0,0 +1,52 @@ +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) + } } + } + } +}) + +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) + } +}) diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala new file mode 100644 index 00000000..4748c528 --- /dev/null +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -0,0 +1,144 @@ +package chipyard.fpga.vcu118 + +import chisel3._ +import chisel3.experimental.{IO} + +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.config._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.tilelink._ + +import sifive.fpgashells.shell.xilinx._ +import sifive.fpgashells.ip.xilinx._ +import sifive.fpgashells.shell._ +import sifive.fpgashells.clocks._ + +import sifive.blocks.devices.uart._ +import sifive.blocks.devices.spi._ +import sifive.blocks.devices.i2c._ +import sifive.blocks.devices.gpio._ + +import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop, CanHaveMasterTLMemPort, ChipTop} +import chipyard.iobinders.{HasIOBinders} +import chipyard.harness.{ApplyHarnessBinders} + +case object FPGAFrequencyKey extends Field[Double](100.0) + +class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays { + + def dp = designParameters + + val pmod_is_sdio = p(VCU118ShellPMOD) == "SDIO" + val jtag_location = Some(if (pmod_is_sdio) "FMC_J2" else "PMOD_J52") + + // Order matters; ddr depends on sys_clock + val uart = Overlay(UARTOverlayKey, new UARTVCU118ShellPlacer(this, UARTShellInput())) + val sdio = if (pmod_is_sdio) Some(Overlay(SPIOverlayKey, new SDIOVCU118ShellPlacer(this, SPIShellInput()))) else None + val jtag = Overlay(JTAGDebugOverlayKey, new JTAGDebugVCU118ShellPlacer(this, JTAGDebugShellInput(location = jtag_location))) + val cjtag = Overlay(cJTAGDebugOverlayKey, new cJTAGDebugVCU118ShellPlacer(this, cJTAGDebugShellInput())) + val jtagBScan = Overlay(JTAGDebugBScanOverlayKey, new JTAGDebugBScanVCU118ShellPlacer(this, JTAGDebugBScanShellInput())) + val fmc = Overlay(PCIeOverlayKey, new PCIeVCU118FMCShellPlacer(this, PCIeShellInput())) + val edge = Overlay(PCIeOverlayKey, new PCIeVCU118EdgeShellPlacer(this, PCIeShellInput())) + + val topDesign = LazyModule(p(BuildTop)(dp)) + + // place all clocks in the shell + dp(ClockInputOverlayKey).foreach { _.place(ClockInputDesignInput()) } + + /*** Connect/Generate clocks ***/ + + // connect to the PLL that will generate multiple clocks + val harnessSysPLL = dp(PLLFactoryKey)() + sys_clock.get() match { + case Some(x : SysClockVCU118PlacedOverlay) => { + harnessSysPLL := x.node + } + } + + // create and connect to the dutClock + val dutClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey)) + val dutWrangler = LazyModule(new ResetWrangler) + val dutGroup = ClockGroup() + dutClock := dutWrangler.node := dutGroup := harnessSysPLL + + // connect ref clock to dummy sink node + ref_clock.get() match { + case Some(x : RefClockVCU118PlacedOverlay) => { + val sink = ClockSinkNode(Seq(ClockSinkParameters())) + sink := x.node + } + } + + /*** UART ***/ + + // 1st UART goes to the VCU118 dedicated UART + + val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head))) + dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) + + /*** SPI ***/ + + // 1st SPI goes to the VCU118 SDIO port + + val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head))) + dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb)) + + /*** DDR ***/ + + val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, dutWrangler.node, harnessSysPLL)) + + // connect 1 mem. channel to the FPGA DDR + val inParams = topDesign match { case td: ChipTop => + td.lazySystem match { case lsys: CanHaveMasterTLMemPort => + lsys.memTLNode.edges.in(0) + } + } + val ddrClient = TLClientNode(Seq(inParams.master)) + ddrPlaced.overlayOutput.ddr := ddrClient + + // module implementation + override lazy val module = new VCU118FPGATestHarnessImp(this) +} + +class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences { + + val vcu118Outer = _outer + + val reset = IO(Input(Bool())) + _outer.xdc.addPackagePin(reset, "L19") + _outer.xdc.addIOStandard(reset, "LVCMOS12") + + val reset_ibuf = Module(new IBUF) + reset_ibuf.io.I := reset + + val sysclk: Clock = _outer.sys_clock.get() match { + case Some(x: SysClockVCU118PlacedOverlay) => x.clock + } + + val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk) + _outer.sdc.addAsyncPath(Seq(powerOnReset)) + + val ereset: Bool = _outer.chiplink.get() match { + case Some(x: ChipLinkVCU118PlacedOverlay) => !x.ereset_n + case _ => false.B + } + + _outer.pllReset := (reset_ibuf.io.O || powerOnReset || ereset) + + // cy stuff + val harnessClock = _outer.dutClock.in.head._1.clock + val harnessReset = WireInit(_outer.dutClock.in.head._1.reset) + val dutReset = harnessReset + val success = false.B + + childClock := harnessClock + childReset := harnessReset + + // harness binders are non-lazy + _outer.topDesign match { case d: HasTestHarnessFunctions => + d.harnessFunctions.foreach(_(this)) + } + _outer.topDesign match { case d: HasIOBinders => + ApplyHarnessBinders(this, d.lazySystem, d.portMap) + } +} diff --git a/fpga/src/main/scala/vcu118/bringup/Configs.scala b/fpga/src/main/scala/vcu118/bringup/Configs.scala index 79dbf6db..0e5602e5 100644 --- a/fpga/src/main/scala/vcu118/bringup/Configs.scala +++ b/fpga/src/main/scala/vcu118/bringup/Configs.scala @@ -1,39 +1,24 @@ package chipyard.fpga.vcu118.bringup import math.min -import sys.process._ -import freechips.rocketchip.config._ -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.devices.debug._ -import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.config.{Config} import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet, ResourceBinding, Resource, ResourceAddress} -import freechips.rocketchip.system._ -import freechips.rocketchip.tile._ -import sifive.blocks.devices.gpio._ -import sifive.blocks.devices.pwm._ -import sifive.blocks.devices.spi._ -import sifive.blocks.devices.uart._ -import sifive.blocks.devices.i2c._ +import sifive.blocks.devices.gpio.{PeripheryGPIOKey, GPIOParams} +import sifive.blocks.devices.i2c.{PeripheryI2CKey, I2CParams} +import sifive.blocks.devices.spi.{PeripherySPIKey, SPIParams} +import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams} import sifive.fpgashells.shell.{DesignKey} import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize} -import chipyard.{BuildTop} - -import chipyard.harness._ +import chipyard.fpga.vcu118.{RocketVCU118Config, BoomVCU118Config} class WithBringupPeripherals extends Config((site, here, up) => { - case PeripheryUARTKey => List( - UARTParams(address = BigInt(0x64000000L)), - UARTParams(address = BigInt(0x64003000L))) - case PeripherySPIKey => List( - SPIParams(rAddress = BigInt(0x64001000L)), - SPIParams(rAddress = BigInt(0x64004000L))) - case VCU118ShellPMOD => "SDIO" - case PeripheryI2CKey => List( - I2CParams(address = BigInt(0x64005000L))) + case PeripheryUARTKey => up(PeripheryUARTKey, site) ++ List(UARTParams(address = BigInt(0x64003000L))) + case PeripherySPIKey => up(PeripherySPIKey, site) ++ List(SPIParams(rAddress = BigInt(0x64004000L))) + case PeripheryI2CKey => List(I2CParams(address = BigInt(0x64005000L))) case PeripheryGPIOKey => { if (BringupGPIOs.width > 0) { require(BringupGPIOs.width <= 64) // currently only support 64 GPIOs (change addrs to get more) @@ -49,60 +34,19 @@ class WithBringupPeripherals extends Config((site, here, up) => { } }) -class SmallModifications extends Config((site, here, up) => { - case DebugModuleKey => None // disable debug module - case ExportDebug => up(ExportDebug).copy(protocols = Set(JTAG)) // don't generate HTIF DTS - case SystemBusKey => up(SystemBusKey).copy( - errorDevice = Some(DevNullParams( - Seq(AddressSet(0x3000, 0xfff)), - maxAtomic=site(XLen)/8, - maxTransfer=128, - region = RegionType.TRACKED))) - case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = - Some(BigDecimal(site(DUTFrequencyKey)*1000000).setScale(0, BigDecimal.RoundingMode.HALF_UP).toBigInt)) - case ControlBusKey => up(ControlBusKey, site).copy( - errorDevice = None) - case DTSTimebase => BigInt(1000000) -}) - -class WithBootROM extends Config((site, here, up) => { - case BootROMLocated(x) => up(BootROMLocated(x), site).map { p => - // invoke makefile for sdboot - val freqMHz = site(DUTFrequencyKey).toInt * 1000000 - val make = s"make -C fpga/src/main/resources/vcu118/sdboot PBUS_CLK=${freqMHz} bin" - require (make.! == 0, "Failed to build bootrom") - p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vcu118/sdboot/build/sdboot.bin") - } -}) - -class WithExtMemSetToDDR extends Config((site, here, up) => { - case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(VCU118DDRSize)))) -}) - -class FakeBringupConfig extends Config( - new SmallModifications ++ +class WithBringupAdditions extends Config( new WithBringupUART ++ new WithBringupSPI ++ new WithBringupI2C ++ new WithBringupGPIO ++ - new WithBringupDDR ++ - new WithUARTIOPassthrough ++ - new WithSPIIOPassthrough ++ new WithI2CIOPassthrough ++ new WithGPIOIOPassthrough ++ - new WithTLIOPassthrough ++ + new WithBringupPeripherals) + +class RocketBringupConfig extends Config( new WithBringupPeripherals ++ - new WithExtMemSetToDDR ++ // set the external mem port size properly - new freechips.rocketchip.subsystem.WithoutTLMonitors ++ - new chipyard.config.WithNoSubsystemDrivenClocks ++ - new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ - new WithBootROM ++ // use local bootrom - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - //new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new chipyard.WithMulticlockCoherentBusTopology ++ - new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.system.BaseConfig) + new RocketVCU118Config) + +class BoomBringupConfig extends Config( + new WithBringupPeripherals ++ + new BoomVCU118Config) diff --git a/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala index fdbbb919..c0a96d3c 100644 --- a/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala +++ b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala @@ -4,15 +4,11 @@ import chisel3._ import chisel3.experimental.{attach} import freechips.rocketchip.diplomacy._ -import chipsalliance.rocketchip.config.{Parameters, Field} import sifive.fpgashells.shell._ import sifive.fpgashells.ip.xilinx._ import sifive.fpgashells.shell.xilinx._ -import sifive.blocks.devices.gpio._ - - import chipyard.fpga.vcu118.{FMCPMap} /* Connect the I2C to certain FMC pins */ diff --git a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala index 79f602dc..b6693036 100644 --- a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala @@ -3,33 +3,21 @@ package chipyard.fpga.vcu118.bringup import chisel3._ import chisel3.experimental.{Analog, IO, BaseModule} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.config.{Parameters, Field} -import freechips.rocketchip.subsystem.{ExtMem, BaseSubsystem} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ +import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO} +import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO} +import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp, I2CPort} +import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp, GPIOPortIO} -import sifive.fpgashells.shell.xilinx._ -import sifive.fpgashells.ip.xilinx._ -import sifive.fpgashells.shell._ -import sifive.fpgashells.clocks._ - -import sifive.blocks.devices.uart._ -import sifive.blocks.devices.spi._ -import sifive.blocks.devices.i2c._ -import sifive.blocks.devices.gpio._ - -import chipyard.{CanHaveMasterTLMemPort, HasHarnessSignalReferences} -import chipyard.harness._ +import chipyard.{HasHarnessSignalReferences} +import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder} /*** UART ***/ -class WithBringupUART extends OverrideHarnessBinder({ +class WithBringupUART extends ComposeHarnessBinder({ (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 2) - vcu118th.outer.io_uart_bb.bundle <> ports.head - vcu118th.outer.io_uart_bb_2.bundle <> ports.last + vcu118th.bringupOuter.io_fmc_uart_bb.bundle <> ports.last } } Nil @@ -37,13 +25,12 @@ class WithBringupUART extends OverrideHarnessBinder({ }) /*** SPI ***/ -class WithBringupSPI extends OverrideHarnessBinder({ +class WithBringupSPI extends ComposeHarnessBinder({ (system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 2) - vcu118th.outer.io_spi_bb.bundle <> ports.head - vcu118th.outer.io_spi_bb_2.bundle <> ports.last + vcu118th.bringupOuter.io_adi_spi_bb.bundle <> ports.last } } Nil @@ -56,7 +43,7 @@ class WithBringupI2C extends OverrideHarnessBinder({ th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { require(ports.size == 1) - vcu118th.outer.io_i2c_bb.bundle <> ports.head + vcu118th.bringupOuter.io_i2c_bb.bundle <> ports.head } } Nil @@ -67,7 +54,7 @@ class WithBringupI2C extends OverrideHarnessBinder({ class WithBringupGPIO extends OverrideHarnessBinder({ (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => { th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { - (vcu118th.outer.io_gpio_bb zip ports).map { case (bb_io, dut_io) => + (vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) => bb_io.bundle <> dut_io } } } @@ -75,19 +62,3 @@ class WithBringupGPIO extends OverrideHarnessBinder({ Nil } }) - -/*** Experimental DDR ***/ -class WithBringupDDR extends OverrideHarnessBinder({ - (system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => { - th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { - require(ports.size == 1) - - val bundles = vcu118th.outer.ddrClient.out.map(_._1) - val ddrClientBundle = Wire(new freechips.rocketchip.util.HeterogeneousBag(bundles.map(_.cloneType))) - bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } - ddrClientBundle <> ports.head - } } - - Nil - } -}) diff --git a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala index 558b074f..168933f7 100644 --- a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala @@ -1,43 +1,12 @@ package chipyard.fpga.vcu118.bringup import chisel3._ -import chisel3.util.experimental.{BoringUtils} -import chisel3.experimental.{Analog, IO, DataMirror} +import chisel3.experimental.{IO, DataMirror} -import freechips.rocketchip.config._ -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike, ResourceBinding, Resource, ResourceAddress, InModuleBody} -import freechips.rocketchip.devices.debug._ -import freechips.rocketchip.jtag.{JTAGIO} -import freechips.rocketchip.subsystem._ -import freechips.rocketchip.system.{SimAXIMem} -import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} -import freechips.rocketchip.util._ -import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem} -import freechips.rocketchip.tilelink.{TLBundle} +import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp} +import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp} -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.{GlobalResetSchemeKey, 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) - } -}) +import chipyard.iobinders.{OverrideIOBinder} class WithGPIOIOPassthrough extends OverrideIOBinder({ (system: HasPeripheryGPIOModuleImp) => { @@ -49,25 +18,6 @@ class WithGPIOIOPassthrough extends OverrideIOBinder({ } }) -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 WithI2CIOPassthrough extends OverrideIOBinder({ (system: HasPeripheryI2CModuleImp) => { val io_i2c_pins_temp = system.i2c.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"i2c_$i") } @@ -77,11 +27,3 @@ class WithI2CIOPassthrough extends OverrideIOBinder({ (io_i2c_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) - } -}) diff --git a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala index 9f51d2aa..080f6189 100644 --- a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala @@ -1,11 +1,10 @@ package chipyard.fpga.vcu118.bringup import chisel3._ -import chisel3.experimental.{Analog, IO} import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.config.{Parameters, Field} -import freechips.rocketchip.subsystem.{ExtMem, BaseSubsystem} +import freechips.rocketchip.config._ +import freechips.rocketchip.subsystem._ import freechips.rocketchip.tilelink._ import sifive.fpgashells.shell.xilinx._ @@ -18,100 +17,31 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.gpio._ -import chipyard.harness._ -import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop, CanHaveMasterTLMemPort, ChipTop} -import chipyard.iobinders.{HasIOBinders} +import chipyard.fpga.vcu118.{VCU118FPGATestHarness, VCU118FPGATestHarnessImp} -case object DUTFrequencyKey extends Field[Double](100.0) - -class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays { - - def dp = designParameters - - val pmod_is_sdio = p(VCU118ShellPMOD) == "SDIO" - val jtag_location = Some(if (pmod_is_sdio) "FMC_J2" else "PMOD_J52") - - // Order matters; ddr depends on sys_clock - val uart = Overlay(UARTOverlayKey, new UARTVCU118ShellPlacer(this, UARTShellInput())) - val sdio = if (pmod_is_sdio) Some(Overlay(SPIOverlayKey, new SDIOVCU118ShellPlacer(this, SPIShellInput()))) else None - val jtag = Overlay(JTAGDebugOverlayKey, new JTAGDebugVCU118ShellPlacer(this, JTAGDebugShellInput(location = jtag_location))) - val cjtag = Overlay(cJTAGDebugOverlayKey, new cJTAGDebugVCU118ShellPlacer(this, cJTAGDebugShellInput())) - val jtagBScan = Overlay(JTAGDebugBScanOverlayKey, new JTAGDebugBScanVCU118ShellPlacer(this, JTAGDebugBScanShellInput())) - val fmc = Overlay(PCIeOverlayKey, new PCIeVCU118FMCShellPlacer(this, PCIeShellInput())) - val edge = Overlay(PCIeOverlayKey, new PCIeVCU118EdgeShellPlacer(this, PCIeShellInput())) - - val topDesign = LazyModule(p(BuildTop)(dp)) - - // place all clocks in the shell - dp(ClockInputOverlayKey).foreach { _.place(ClockInputDesignInput()) } - - /*** Connect/Generate clocks ***/ - - // connect to the PLL that will generate multiple clocks - val harnessSysPLL = dp(PLLFactoryKey)() - sys_clock.get() match { - case Some(x : SysClockVCU118PlacedOverlay) => { - harnessSysPLL := x.node - } - } - - // create and connect to the dutClock - val dutClock = ClockSinkNode(freqMHz = dp(DUTFrequencyKey)) - val dutWrangler = LazyModule(new ResetWrangler) - val dutGroup = ClockGroup() - dutClock := dutWrangler.node := dutGroup := harnessSysPLL - - //InModuleBody { - // topDesign.module match { case td: LazyModuleImp => { - // td.clock := dutClock.in.head._1.clock - // td.reset := dutClock.in.head._1.reset - // } - // } - //} - - // connect ref clock to dummy sink node - ref_clock.get() match { - case Some(x : RefClockVCU118PlacedOverlay) => { - val sink = ClockSinkNode(Seq(ClockSinkParameters())) - sink := x.node - } - } - - // extra overlays +class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118FPGATestHarness { /*** UART ***/ require(dp(PeripheryUARTKey).size == 2) - // 1st UART goes to the VCU118 dedicated UART - - // BundleBridgeSource is a was for Diplomacy to connect something from very deep in the design - // to somewhere much, much higher. For ex. tunneling trace from the tile to the very top level. - val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head))) - dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) - // 2nd UART goes to the FMC UART val uart_fmc = Overlay(UARTOverlayKey, new BringupUARTVCU118ShellPlacer(this, UARTShellInput())) - val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last))) - dp(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) + val io_fmc_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last))) + dp(UARTOverlayKey).last.place(UARTDesignInput(io_fmc_uart_bb)) /*** SPI ***/ require(dp(PeripherySPIKey).size == 2) - // 1st SPI goes to the VCU118 SDIO port - - val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head))) - val sdio_placed = dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb)) - // 2nd SPI goes to the ADI port val adi = Overlay(SPIOverlayKey, new BringupSPIVCU118ShellPlacer(this, SPIShellInput())) - val io_spi_bb_2 = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).last))) - val adi_placed = dp(SPIOverlayKey).last.place(SPIDesignInput(dp(PeripherySPIKey).last, io_spi_bb_2)) + val io_adi_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).last))) + dp(SPIOverlayKey).last.place(SPIDesignInput(dp(PeripherySPIKey).last, io_adi_spi_bb)) /*** I2C ***/ @@ -123,7 +53,7 @@ class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends /*** GPIO ***/ val gpio = Seq.tabulate(dp(PeripheryGPIOKey).size)(i => { - val maxGPIOSupport = 32 + val maxGPIOSupport = 32 // max gpio per gpio chip val names = BringupGPIOs.names.slice(maxGPIOSupport*i, maxGPIOSupport*(i+1)) Overlay(GPIOOverlayKey, new BringupGPIOVCU118ShellPlacer(this, GPIOShellInput(), names)) }) @@ -133,62 +63,10 @@ class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends placer.place(GPIODesignInput(params, io_gpio_bb(i))) } - /*** DDR ***/ - - val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, dutWrangler.node, harnessSysPLL)) - - // connect 1 mem. channel to the FPGA DDR - val inParams = topDesign match { case td: ChipTop => - td.lazySystem match { case lsys: CanHaveMasterTLMemPort => - lsys.memTLNode.edges.in(0) - } - } - val ddrClient = TLClientNode(Seq(inParams.master)) - ddrPlaced.overlayOutput.ddr := ddrClient - // module implementation override lazy val module = new BringupVCU118FPGATestHarnessImp(this) } -class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences { - - val outer = _outer - - val reset = IO(Input(Bool())) - _outer.xdc.addPackagePin(reset, "L19") - _outer.xdc.addIOStandard(reset, "LVCMOS12") - - val reset_ibuf = Module(new IBUF) - reset_ibuf.io.I := reset - - val sysclk: Clock = _outer.sys_clock.get() match { - case Some(x: SysClockVCU118PlacedOverlay) => x.clock - } - - val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk) - _outer.sdc.addAsyncPath(Seq(powerOnReset)) - - val ereset: Bool = _outer.chiplink.get() match { - case Some(x: ChipLinkVCU118PlacedOverlay) => !x.ereset_n - case _ => false.B - } - - _outer.pllReset := (reset_ibuf.io.O || powerOnReset || ereset) - - // cy stuff - val harnessClock = _outer.dutClock.in.head._1.clock - val harnessReset = WireInit(_outer.dutClock.in.head._1.reset) - val dutReset = harnessReset - val success = false.B - - childClock := harnessClock - childReset := harnessReset - - // harness binders are non-lazy - _outer.topDesign match { case d: HasTestHarnessFunctions => - d.harnessFunctions.foreach(_(this)) - } - _outer.topDesign match { case d: HasIOBinders => - ApplyHarnessBinders(this, d.lazySystem, d.portMap) - } +class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) extends VCU118FPGATestHarnessImp(_outer) { + val bringupOuter = _outer } diff --git a/generators/sifive-blocks b/generators/sifive-blocks index 25eae85e..7e2121ee 160000 --- a/generators/sifive-blocks +++ b/generators/sifive-blocks @@ -1 +1 @@ -Subproject commit 25eae85e711d650a305eb1cd923421a2872fcc56 +Subproject commit 7e2121ee26e614f2144a9e4c67c440773aa7544d