From f1b40d51afdba1e1d7c9bd95742aec2e85adef3d Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Tue, 15 Sep 2020 12:58:58 -0700 Subject: [PATCH] Connected clocks | Exposed Master TL port --- fpga/src/main/scala/vcu118/Configs.scala | 29 ++++-- .../main/scala/vcu118/CustomOverlays.scala | 25 ++--- fpga/src/main/scala/vcu118/Platform.scala | 16 +++- fpga/src/main/scala/vcu118/TestHarness.scala | 94 ++++++++++++++----- .../chipyard/src/main/scala/DigitalTop.scala | 40 ++++++++ .../chipyard/src/main/scala/System.scala | 1 - 6 files changed, 159 insertions(+), 46 deletions(-) diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index 7cc106d5..ab087afa 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -7,7 +7,7 @@ import freechips.rocketchip.config._ import freechips.rocketchip.subsystem._ import freechips.rocketchip.devices.debug._ import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase} +import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet} import freechips.rocketchip.system._ import freechips.rocketchip.tile._ @@ -52,20 +52,35 @@ class WithBringupPeripherals extends Config((site, here, up) => { } }) +class SmallModifications extends Config((site, here, up) => { + 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), + errorDevice = None) + case DTSTimebase => BigInt(1000000) + case JtagDTMKey => new JtagDTMConfig( + idcodeVersion = 2, // 1 was legacy (FE310-G000, Acai). + idcodePartNum = 0x000, // Decided to simplify. + idcodeManufId = 0x489, // As Assigned by JEDEC to SiFive. Only used in wrappers / test harnesses. + debugIdleCycles = 5) // Reasonable guess for synchronization +}) + + class FakeBringupConfig extends Config( new WithBringupPeripherals ++ new WithChipyardBuildTop ++ new chipyard.config.WithBootROM ++ new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.With1TinyCore ++ - new freechips.rocketchip.subsystem.WithNBanks(0) ++ - new freechips.rocketchip.subsystem.WithNoMemPort ++ - new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ - new freechips.rocketchip.subsystem.WithNBreakpoints(2) ++ - new freechips.rocketchip.subsystem.WithJtagDTM ++ + 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 freechips.rocketchip.subsystem.WithCoherentBusTopology ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) diff --git a/fpga/src/main/scala/vcu118/CustomOverlays.scala b/fpga/src/main/scala/vcu118/CustomOverlays.scala index ccb61f0e..2c438a34 100644 --- a/fpga/src/main/scala/vcu118/CustomOverlays.scala +++ b/fpga/src/main/scala/vcu118/CustomOverlays.scala @@ -12,10 +12,11 @@ import sifive.fpgashells.shell.xilinx._ import sifive.blocks.devices.gpio._ + import chipyard.fpga.vcu118.{FMCPMap} /* Connect the I2C to certain FMC pins */ -class BringupI2CVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val designInput: I2CDesignInput, val shellInput: I2CShellInput) +class BringupI2CVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: I2CDesignInput, val shellInput: I2CShellInput) extends I2CXilinxPlacedOverlay(name, designInput, shellInput) { shell { InModuleBody { @@ -32,14 +33,14 @@ class BringupI2CVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val de } } } -class BringupI2CVCU118ShellPlacer(val shell: VCU118Shell, val shellInput: I2CShellInput)(implicit val valName: ValName) - extends I2CShellPlacer[VCU118Shell] +class BringupI2CVCU118ShellPlacer(val shell: VCU118ShellBasicOverlays, val shellInput: I2CShellInput)(implicit val valName: ValName) + extends I2CShellPlacer[VCU118ShellBasicOverlays] { def place(designInput: I2CDesignInput) = new BringupI2CVCU118PlacedOverlay(shell, valName.name, designInput, shellInput) } /* Connect the UART to certain FMC pins */ -class BringupUARTVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val designInput: UARTDesignInput, val shellInput: UARTShellInput) +class BringupUARTVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: UARTDesignInput, val shellInput: UARTShellInput) extends UARTXilinxPlacedOverlay(name, designInput, shellInput, true) { shell { InModuleBody { @@ -61,13 +62,13 @@ class BringupUARTVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val d } } } -class BringupUARTVCU118ShellPlacer(shell: VCU118Shell, val shellInput: UARTShellInput)(implicit val valName: ValName) - extends UARTShellPlacer[VCU118Shell] { +class BringupUARTVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: UARTShellInput)(implicit val valName: ValName) + extends UARTShellPlacer[VCU118ShellBasicOverlays] { def place(designInput: UARTDesignInput) = new BringupUARTVCU118PlacedOverlay(shell, valName.name, designInput, shellInput) } /* Connect SPI to ADI device */ -class BringupSPIVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val designInput: SPIDesignInput, val shellInput: SPIShellInput) +class BringupSPIVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: SPIDesignInput, val shellInput: SPIShellInput) extends SDIOXilinxPlacedOverlay(name, designInput, shellInput) { shell { InModuleBody { @@ -89,8 +90,8 @@ class BringupSPIVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val de } } } -class BringupSPIVCU118ShellPlacer(shell: VCU118Shell, val shellInput: SPIShellInput)(implicit val valName: ValName) - extends SPIShellPlacer[VCU118Shell] { +class BringupSPIVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: SPIShellInput)(implicit val valName: ValName) + extends SPIShellPlacer[VCU118ShellBasicOverlays] { def place(designInput: SPIDesignInput) = new BringupSPIVCU118PlacedOverlay(shell, valName.name, designInput, shellInput) } @@ -123,7 +124,7 @@ abstract class GPIOXilinxPlacedOverlay(name: String, di: GPIODesignInput, si: GP } } } -class BringupGPIOVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val designInput: GPIODesignInput, val shellInput: GPIOShellInput, gpioNames: Seq[String]) +class BringupGPIOVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: GPIODesignInput, val shellInput: GPIOShellInput, gpioNames: Seq[String]) extends GPIOXilinxPlacedOverlay(name, designInput, shellInput) { shell { InModuleBody { @@ -143,8 +144,8 @@ class BringupGPIOVCU118PlacedOverlay(val shell: VCU118Shell, name: String, val d } } } -class BringupGPIOVCU118ShellPlacer(shell: VCU118Shell, val shellInput: GPIOShellInput, gpioNames: Seq[String])(implicit val valName: ValName) - extends GPIOShellPlacer[VCU118Shell] { +class BringupGPIOVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: GPIOShellInput, gpioNames: Seq[String])(implicit val valName: ValName) + extends GPIOShellPlacer[VCU118ShellBasicOverlays] { def place(designInput: GPIODesignInput) = new BringupGPIOVCU118PlacedOverlay(shell, valName.name, designInput, shellInput, gpioNames) } diff --git a/fpga/src/main/scala/vcu118/Platform.scala b/fpga/src/main/scala/vcu118/Platform.scala index 8f9a1ae8..bdacdf42 100644 --- a/fpga/src/main/scala/vcu118/Platform.scala +++ b/fpga/src/main/scala/vcu118/Platform.scala @@ -1,11 +1,12 @@ package chipyard.fpga.vcu118 import chisel3._ -import chisel3.experimental.{Analog, IO} +import chisel3.experimental.{Analog, IO, DataMirror} -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} -import freechips.rocketchip.diplomacy.{InModuleBody, BundleBridgeSource} +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyScope, InModuleBody, BundleBridgeSource, ValName} import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.util.{HeterogeneousBag} +import freechips.rocketchip.tilelink.{TLBundle} import chipyard.{BuildSystem} @@ -19,9 +20,10 @@ trait HasVCU118PlatformIO { val io_spi: Seq[SPIPortIO] val io_i2c: Seq[I2CPort] val io_gpio: Seq[GPIOPortIO] + val io_tl_mem: HeterogeneousBag[TLBundle] } -class VCU118Platform(override implicit val p: Parameters) extends LazyModule { +class VCU118Platform(override implicit val p: Parameters) extends LazyModule with LazyScope { val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") @@ -62,4 +64,10 @@ class VCU118PlatformModule[+L <: VCU118Platform](_outer: L) extends LazyModuleIm } io_gpio_pins_temp } + + val io_tl_mem = _outer.lazySystem match { case sys: chipyard.CanHaveMasterTLMemPort => + val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](sys.mem_tl)).suggestName("tl_slave") + io_tl_mem_pins_temp <> sys.mem_tl + io_tl_mem_pins_temp + } } diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index 9a58960f..d4e299a5 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -4,7 +4,8 @@ import chisel3._ import chisel3.experimental.{Analog, IO} import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.subsystem.{ExtMem, BaseSubsystem} import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.ip.xilinx._ @@ -16,20 +17,55 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.gpio._ -import chipyard.fpga.vcu118.bringup._ +import chipyard.fpga.vcu118.bringup.{BringupGPIOs, BringupUARTVCU118ShellPlacer, BringupSPIVCU118ShellPlacer, BringupI2CVCU118ShellPlacer, BringupGPIOVCU118ShellPlacer} -class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118Shell { +case object DUTFrequencyKey extends Field[Double](100.0) +class VCU118FPGATestHarness(override implicit val p: Parameters) extends ChipyardVCU118Shell { + + def dp = designParameters + + /*** 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 + } + } /*** UART ***/ - require(p(PeripheryUARTKey).size == 2) + 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(p(PeripheryUARTKey).head))) - designParameters(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) + val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head))) + dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_uart_bb.bundle <> dutMod.io_uart.head @@ -38,10 +74,10 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S // 2nd UART goes to the FMC UART - val uart_fmc = Overlay(UARTOverlayKey, new chipyard.fpga.vcu118.bringup.BringupUARTVCU118ShellPlacer(this, UARTShellInput())) + val uart_fmc = Overlay(UARTOverlayKey, new BringupUARTVCU118ShellPlacer(this, UARTShellInput())) - val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(p(PeripheryUARTKey).last))) - designParameters(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) + val io_uart_bb_2 = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last))) + dp(UARTOverlayKey).last.place(UARTDesignInput(io_uart_bb_2)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_uart_bb_2.bundle <> dutMod.io_uart.last @@ -49,12 +85,12 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S } /*** SPI ***/ - require(p(PeripherySPIKey).size == 2) + require(dp(PeripherySPIKey).size == 2) // 1st SPI goes to the VCU118 SDIO port - val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(p(PeripherySPIKey).head))) - val sdio_placed = designParameters(SPIOverlayKey).head.place(SPIDesignInput(p(PeripherySPIKey).head, io_spi_bb)) + val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head))) + val sdio_placed = dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_spi_bb.bundle <> dutMod.io_spi.head @@ -69,10 +105,10 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S // 2nd SPI goes to the ADI port - val adi = Overlay(SPIOverlayKey, new chipyard.fpga.vcu118.bringup.BringupSPIVCU118ShellPlacer(this, SPIShellInput())) + val adi = Overlay(SPIOverlayKey, new BringupSPIVCU118ShellPlacer(this, SPIShellInput())) - val io_spi_bb_2 = BundleBridgeSource(() => (new SPIPortIO(p(PeripherySPIKey).last))) - val adi_placed = designParameters(SPIOverlayKey).last.place(SPIDesignInput(p(PeripherySPIKey).last, io_spi_bb_2)) + 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)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_spi_bb_2.bundle <> dutMod.io_spi.last @@ -86,12 +122,12 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S //} /*** I2C ***/ - require(p(PeripheryI2CKey).size == 1) + require(dp(PeripheryI2CKey).size == 1) - val i2c = Overlay(I2COverlayKey, new chipyard.fpga.vcu118.bringup.BringupI2CVCU118ShellPlacer(this, I2CShellInput())) + val i2c = Overlay(I2COverlayKey, new BringupI2CVCU118ShellPlacer(this, I2CShellInput())) val io_i2c_bb = BundleBridgeSource(() => (new I2CPort)) - designParameters(I2COverlayKey).head.place(I2CDesignInput(io_i2c_bb)) + dp(I2COverlayKey).head.place(I2CDesignInput(io_i2c_bb)) InModuleBody { topDesign.module match { case dutMod: HasVCU118PlatformIO => io_i2c_bb.bundle <> dutMod.io_i2c.head @@ -99,14 +135,14 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S } /*** GPIO ***/ - val gpio = Seq.tabulate(p(PeripheryGPIOKey).size)(i => { + val gpio = Seq.tabulate(dp(PeripheryGPIOKey).size)(i => { val maxGPIOSupport = 32 val names = BringupGPIOs.names.slice(maxGPIOSupport*i, maxGPIOSupport*(i+1)) - Overlay(GPIOOverlayKey, new chipyard.fpga.vcu118.bringup.BringupGPIOVCU118ShellPlacer(this, GPIOShellInput(), names)) + Overlay(GPIOOverlayKey, new BringupGPIOVCU118ShellPlacer(this, GPIOShellInput(), names)) }) - val io_gpio_bb = p(PeripheryGPIOKey).map { p => BundleBridgeSource(() => (new GPIOPortIO(p))) } - (designParameters(GPIOOverlayKey) zip p(PeripheryGPIOKey)).zipWithIndex.map { case ((placer, params), i) => + val io_gpio_bb = dp(PeripheryGPIOKey).map { p => BundleBridgeSource(() => (new GPIOPortIO(p))) } + (dp(GPIOOverlayKey) zip dp(PeripheryGPIOKey)).zipWithIndex.map { case ((placer, params), i) => placer.place(GPIODesignInput(params, io_gpio_bb(i))) } InModuleBody { @@ -116,5 +152,19 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S } } } + + /*** Experimental DDR ***/ + + //val ddrPlaced = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtMem).get.master.base, dutWrangler.node, harnessSysPLL)) + + //topDesign match { case lazyDut: VCU118Platform => + // lazyDut.lazySystem match { case lazyDutWBus: BaseSubsystem => + // lazyDutWBus { + // InModuleBody { + // ddrPlaced.overlayOutput.ddr := lazyDutWBus.mbus.toDRAMController(Some("xilinxvcu118mig"))() + // } + // } + // } + //} } diff --git a/generators/chipyard/src/main/scala/DigitalTop.scala b/generators/chipyard/src/main/scala/DigitalTop.scala index 9e40cfab..dedcfbf8 100644 --- a/generators/chipyard/src/main/scala/DigitalTop.scala +++ b/generators/chipyard/src/main/scala/DigitalTop.scala @@ -29,6 +29,7 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem with chipyard.example.CanHavePeripheryStreamingFIR // Enables optionally adding the DSPTools FIR example widget with chipyard.example.CanHavePeripheryStreamingPassthrough // Enables optionally adding the DSPTools streaming-passthrough example widget with nvidia.blocks.dla.CanHavePeripheryNVDLA // Enables optionally having an NVDLA + with CanHaveMasterTLMemPort { override lazy val module = new DigitalTopModule(this) } @@ -47,3 +48,42 @@ class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l) with chipyard.example.CanHavePeripheryGCDModuleImp with freechips.rocketchip.util.DontTouch // DOC include end: DigitalTop + +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ + +/** Adds a TileLink port to the system intended to master an MMIO device bus */ +trait CanHaveMasterTLMemPort { this: BaseSubsystem => + private val memPortParamsOpt = p(ExtMem) + private val portName = "tl_mem" + private val device = new MemoryDevice + private val idBits = memPortParamsOpt.map(_.master.idBits).getOrElse(1) + + val memTLNode = TLManagerNode(memPortParamsOpt.map({ case MemoryPortParams(memPortParams, nMemoryChannels) => + Seq.tabulate(nMemoryChannels) { channel => + val base = AddressSet.misaligned(memPortParams.base, memPortParams.size) + val filter = AddressSet(channel * mbus.blockBytes, ~((nMemoryChannels-1) * mbus.blockBytes)) + + TLSlavePortParameters.v1( + managers = Seq(TLSlaveParameters.v1( + address = base.flatMap(_.intersect(filter)), + resources = device.reg, + regionType = RegionType.UNCACHED, // cacheable + executable = true, + supportsGet = TransferSizes(1, mbus.blockBytes), + supportsPutFull = TransferSizes(1, mbus.blockBytes), + supportsPutPartial = TransferSizes(1, mbus.blockBytes))), + beatBytes = memPortParams.beatBytes) + } + }).toList.flatten) + + mbus.coupleTo(s"memory_controller_port_named_$portName") { + (memTLNode + :*= TLBuffer() + :*= TLSourceShrinker(1 << idBits) + :*= TLWidthWidget(mbus.beatBytes) + :*= _) + } + + val mem_tl = InModuleBody { memTLNode.makeIOs() } +} diff --git a/generators/chipyard/src/main/scala/System.scala b/generators/chipyard/src/main/scala/System.scala index bd20ddc7..f8906e04 100644 --- a/generators/chipyard/src/main/scala/System.scala +++ b/generators/chipyard/src/main/scala/System.scala @@ -23,7 +23,6 @@ import freechips.rocketchip.util.{DontTouch} */ class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem with HasAsyncExtInterrupts - with CanHaveMasterAXI4MemPort with CanHaveMasterAXI4MMIOPort with CanHaveSlaveAXI4Port {