Add support for VC707 fpga board

This commit is contained in:
Haoan Li
2022-11-24 16:08:15 +09:00
parent 757d354410
commit fb793d7ee9
6 changed files with 307 additions and 0 deletions

View File

@@ -0,0 +1 @@
vcu118

View File

@@ -0,0 +1,78 @@
package chipyard.fpga.vc707
import sys.process._
import freechips.rocketchip.config.{Config, Parameters}
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.{VC7074GDDRSize}
import testchipip.{SerialTLKey}
import chipyard.{BuildSystem, ExtTLMem, DefaultClockFrequencyKey}
class WithDefaultPeripherals extends Config((site, here, up) => {
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
case PeripherySPIKey => List(SPIParams(rAddress = BigInt(0x64001000L)))
})
class WithSystemModifications extends Config((site, here, up) => {
case DTSTimebase => BigInt{(1e6).toLong}
case BootROMLocated(x) => up(BootROMLocated(x), site).map { p =>
// invoke makefile for sdboot
val freqMHz = (site(DefaultClockFrequencyKey) * 1e6).toLong
val make = s"make -C fpga/src/main/resources/vc707/sdboot PBUS_CLK=${freqMHz} bin"
require (make.! == 0, "Failed to build bootrom")
p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vc707/sdboot/build/sdboot.bin")
}
case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(VC7074GDDRSize)))) // set extmem to DDR size
case SerialTLKey => None // remove serialized tl port
})
// DOC include start: AbstractVC707 and Rocket
class WithVC707Tweaks extends Config(
// harness binders
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
new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size
new chipyard.config.WithNoDebug ++ // remove debug module
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++
new WithFPGAFrequency(50) // default 50MHz freq
)
class RocketVC707Config extends Config(
new WithVC707Tweaks ++
new chipyard.RocketConfig)
// DOC include end: AbstractVC707 and Rocket
class BoomVC707Config extends Config(
new WithFPGAFrequency(50) ++
new WithVC707Tweaks ++
new chipyard.MegaBoomConfig)
class WithFPGAFrequency(fMHz: Double) extends Config(
new chipyard.config.WithPeripheryBusFrequency(fMHz) ++ // assumes using PBUS as default freq.
new chipyard.config.WithMemoryBusFrequency(fMHz)
)
class WithFPGAFreq25MHz extends WithFPGAFrequency(25)
class WithFPGAFreq50MHz extends WithFPGAFrequency(50)
class WithFPGAFreq75MHz extends WithFPGAFrequency(75)
class WithFPGAFreq100MHz extends WithFPGAFrequency(100)

View File

@@ -0,0 +1,39 @@
package chipyard.fpga.vc707
import chisel3._
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 sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{HasSystemXilinxVC707PCIeX1ModuleImp, XilinxVC707PCIeX1IO}
import chipyard.{CanHaveMasterTLMemPort}
import chipyard.harness.{OverrideHarnessBinder}
/*** UART ***/
class WithVC707UARTHarnessBinder extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: VC707FPGATestHarness, ports: Seq[UARTPortIO]) => {
th.io_uart_bb.bundle <> ports.head
}
})
/*** SPI ***/
class WithVC707SPISDCardHarnessBinder extends OverrideHarnessBinder({
(system: HasPeripherySPI, th: VC707FPGATestHarness, ports: Seq[SPIPortIO]) => {
th.io_spi_bb.bundle <> ports.head
}
})
/*** Experimental DDR ***/
class WithVC707DDRMemHarnessBinder extends OverrideHarnessBinder({
(system: CanHaveMasterTLMemPort, th: VC707FPGATestHarness, ports: Seq[HeterogeneousBag[TLBundle]]) => {
require(ports.size == 1)
val bundles = th.ddrClient.out.map(_._1)
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
ddrClientBundle <> ports.head
}
})

View File

@@ -0,0 +1,53 @@
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

@@ -0,0 +1,122 @@
package chipyard.fpga.vc707
import chisel3._
import chisel3.experimental.{IO}
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
import freechips.rocketchip.config.{Parameters}
import freechips.rocketchip.tilelink.{TLClientNode}
import sifive.fpgashells.shell.xilinx.{VC707Shell, UARTVC707ShellPlacer, PCIeVC707ShellPlacer, ChipLinkVC707PlacedOverlay}
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
import sifive.fpgashells.shell.{ClockInputOverlayKey, ClockInputDesignInput, UARTOverlayKey, UARTDesignInput, UARTShellInput, SPIOverlayKey, SPIDesignInput, PCIeOverlayKey, PCIeDesignInput, PCIeShellInput, DDROverlayKey, DDRDesignInput}
import sifive.fpgashells.clocks.{ClockGroup, ClockSinkNode, PLLFactoryKey, ResetWrangler}
import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{XilinxVC707PCIeX1IO}
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTPortIO}
import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO}
import chipyard.{HasHarnessSignalReferences, BuildTop, ChipTop, ExtTLMem, CanHaveMasterTLMemPort, DefaultClockFrequencyKey}
import chipyard.iobinders.{HasIOBinders}
import chipyard.harness.{ApplyHarnessBinders}
class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707Shell { outer =>
def dp = designParameters
// Order matters; ddr depends on sys_clock
val uart = Overlay(UARTOverlayKey, new UARTVC707ShellPlacer(this, UARTShellInput()))
val pcie = Overlay(PCIeOverlayKey, new PCIeVC707ShellPlacer(this, PCIeShellInput()))
val topDesign = LazyModule(p(BuildTop)(dp)).suggestName("chiptop")
// place all clocks in the shell
require(dp(ClockInputOverlayKey).size >= 1)
val sysClkNode = dp(ClockInputOverlayKey)(0).place(ClockInputDesignInput()).overlayOutput.node
/*** Connect/Generate clocks ***/
// connect to the PLL that will generate multiple clocks
val harnessSysPLL = dp(PLLFactoryKey)()
harnessSysPLL := sysClkNode
// create and connect to the dutClock
println(s"VC707 FPGA Base Clock Freq: ${dp(DefaultClockFrequencyKey)} MHz")
val dutClock = ClockSinkNode(freqMHz = dp(DefaultClockFrequencyKey))
val dutWrangler = LazyModule(new ResetWrangler)
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL
/*** UART ***/
// 1st UART goes to the VC707 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 VC707 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 ddrNode = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLL)).overlayOutput.ddr
// 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))
ddrNode := ddrClient
// module implementation
override lazy val module = new LazyRawModuleImp(this) with HasHarnessSignalReferences {
val reset = IO(Input(Bool()))
xdc.addBoardPin(reset, "reset")
val resetIBUF = Module(new IBUF)
resetIBUF.io.I := reset
val sysclk: Clock = sysClkNode.out.head._1.clock
// val sysclk: Clock = sys_clock.get() match {
// case Some(x: SysClockVC707PlacedOverlay) => x.clock
// }
val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk)
sdc.addAsyncPath(Seq(powerOnReset))
val ereset: Bool = chiplink.get() match {
case Some(x: ChipLinkVC707PlacedOverlay) => !x.ereset_n
case _ => false.B
}
pllReset := (resetIBUF.io.O || powerOnReset || ereset)
// reset setup
val hReset = Wire(Reset())
hReset := dutClock.in.head._1.reset
val buildtopClock = dutClock.in.head._1.clock
val buildtopReset = WireInit(hReset)
val dutReset = hReset.asAsyncReset
val success = false.B
childClock := buildtopClock
childReset := buildtopReset
// harness binders are non-lazy
topDesign match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
// check the top-level reference clock is equal to the default
// non-exhaustive since you need all ChipTop clocks to equal the default
require(getRefClockFreq == p(DefaultClockFrequencyKey))
}
}