Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions fpga/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ ifeq ($(SUB_PROJECT),vcu118)
FPGA_BRAND ?= xilinx
endif

ifeq ($(SUB_PROJECT),genesys2)
SBT_PROJECT ?= fpga_platforms
MODEL ?= Genesys2FPGATestHarness
VLOG_MODEL ?= Genesys2FPGATestHarness
MODEL_PACKAGE ?= chipyard.fpga.genesys2
CONFIG ?= RocketGenesys2Config
CONFIG_PACKAGE ?= chipyard.fpga.genesys2
GENERATOR_PACKAGE ?= chipyard
TB ?= none # unused
TOP ?= ChipTop
BOARD ?= genesys2
FPGA_BRAND ?= xilinx
endif

ifeq ($(SUB_PROJECT),bringup)
SBT_PROJECT ?= fpga_platforms
MODEL ?= BringupVCU118FPGATestHarness
Expand Down
57 changes: 57 additions & 0 deletions fpga/src/main/scala/genesys2/Configs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package chipyard.fpga.genesys2

import freechips.rocketchip.config.Config
import freechips.rocketchip.devices.debug.{JtagDTMConfig, JtagDTMKey}
import freechips.rocketchip.diplomacy.DTSTimebase
import freechips.rocketchip.subsystem.{ExtMem, PeripheryBusKey}
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
import sifive.fpgashells.shell.xilinx.Genesys2DDRSize
import testchipip.SerialTLKey

class WithDefaultPeripherals extends Config((site, here, up) => {
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
})

class WithSystemModifications extends Config((site, here, up) => {
case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(site(FPGAFrequencyKey).toInt*1000000))
case DTSTimebase => BigInt(1000000)
case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(Genesys2DDRSize)))) // set extmem to DDR size
case SerialTLKey => None // remove serialized tl port
case JtagDTMKey => JtagDTMConfig (
idcodeVersion = 2,
idcodePartNum = 0x000,
idcodeManufId = 0x000,
debugIdleCycles = 5)
})

class WithGenesys2Tweaks extends Config(
new WithUART ++
new WithJTAG ++
new WithDDRMem ++
new WithUARTIOPassthrough ++
new WithJTAGIOPassthrough ++
new WithTLIOPassthrough ++
new WithDefaultPeripherals ++
new chipyard.config.WithTLBackingMemory ++ // use TL backing memory
new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(1))

class RocketGenesys2Config extends Config(
new WithFPGAFrequency(50) ++
new WithGenesys2Tweaks ++
new chipyard.RocketConfig)

class BoomGenesys2Config extends Config(
new WithFPGAFrequency(50) ++
new WithGenesys2Tweaks ++
new chipyard.MegaBoomConfig)

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)
47 changes: 47 additions & 0 deletions fpga/src/main/scala/genesys2/HarnessBinders.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package chipyard.fpga.genesys2

import chipyard.harness.OverrideHarnessBinder
import chipyard.{CanHaveMasterTLMemPort, HasHarnessSignalReferences}
import chisel3._
import chisel3.experimental.BaseModule
import freechips.rocketchip.devices.debug.HasPeripheryDebug
import freechips.rocketchip.jtag.JTAGIO
import freechips.rocketchip.tilelink.TLBundle
import freechips.rocketchip.util.HeterogeneousBag
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}

/*** UART ***/
class WithUART extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
th match { case genesys2th: Genesys2FPGATestHarnessImp => {
genesys2th.genesys2Outer.io_uart_bb.bundle <> ports.head
} }
}
})

class WithJTAG extends OverrideHarnessBinder({
(system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[JTAGIO]) => {
th match { case genesys2th: Genesys2FPGATestHarnessImp => {
val j = ports.head
val o = genesys2th.genesys2Outer.io_jtag
j.TCK := o.TCK
j.TDI := o.TDI
j.TMS := o.TMS
o.TDO <> j.TDO
} }
}
})

/*** Experimental DDR ***/
class WithDDRMem extends OverrideHarnessBinder({
(system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => {
th match { case genesys2th: Genesys2FPGATestHarnessImp => {
require(ports.size == 1)

val bundles = genesys2th.genesys2Outer.ddrClient.out.map(_._1)
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
ddrClientBundle <> ports.head
} }
}
})
74 changes: 74 additions & 0 deletions fpga/src/main/scala/genesys2/IOBinders.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package chipyard.fpga.genesys2

import chipyard.CanHaveMasterTLMemPort
import chipyard.iobinders.{GetSystemParameters, OverrideIOBinder, OverrideLazyIOBinder}
import chisel3._
import chisel3.experimental.{DataMirror, IO}
import freechips.rocketchip.devices.debug._
import freechips.rocketchip.diplomacy.InModuleBody
import freechips.rocketchip.prci.{ClockSinkNode, ClockSinkParameters}
import freechips.rocketchip.subsystem.BaseSubsystem
import freechips.rocketchip.tilelink.TLBundle
import freechips.rocketchip.util.{HeterogeneousBag, PSDTestMode}
import sifive.blocks.devices.uart.HasPeripheryUARTModuleImp

class WithUARTIOPassthrough extends OverrideIOBinder({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code seems like a copy of the VCU118 code. Maybe we can dedup this by creating a folder like: fpga/src/main/scala/common and putting both sources there (with a new package name chipyard.fpga.common). Then we just reference that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I noticed I was just copying and pasting code when porting too 😂. Should I try to do some dedup work now or after this PR get merged?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would wait until we get back to you on the testing side and fpga-shells gets merged.

(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).foreach { case (io, sysio) =>
io <> sysio
}
(io_uart_pins_temp, Nil)
}
})

class WithJTAGIOPassthrough extends OverrideLazyIOBinder({
(system: HasPeripheryDebug) => {
implicit val p = GetSystemParameters(system)
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
val clockSinkNode = system.debugOpt.map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
clockSinkNode.map(_ := tlbus.fixedClockNode)
def clockBundle = clockSinkNode.get.in.head._1

InModuleBody { system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripheryDebugModuleImp => {
system.debug.map({ debug =>
// We never use the PSDIO, so tie it off on-chip
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := clockBundle.reset.asBool } }
system.debug.map { d =>
// Tie off extTrigger
d.extTrigger.foreach { t =>
t.in.req := false.B
t.out.ack := t.out.req
}
// Tie off disableDebug
d.disableDebug.foreach { d => d := false.B }
// Drive JTAG on-chip IOs
d.systemjtag.map { j =>
j.reset := clockBundle.reset
j.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W)
j.part_number := p(JtagDTMKey).idcodePartNum.U(16.W)
j.version := p(JtagDTMKey).idcodeVersion.U(4.W)
}
}
Debug.connectDebugClockAndReset(Some(debug), clockBundle.clock)

val jtagPins = debug.systemjtag.map { j =>
val io_jtag_pins_temp = IO(Flipped(j.jtag.cloneType)).suggestName(s"debug_jtag")
io_jtag_pins_temp <> j.jtag
io_jtag_pins_temp
}.get

(Seq(jtagPins), Nil)
}).getOrElse((Nil, 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)
}
})
107 changes: 107 additions & 0 deletions fpga/src/main/scala/genesys2/TestHarness.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package chipyard.fpga.genesys2

import chipyard.harness.ApplyHarnessBinders
import chipyard.iobinders.HasIOBinders
import chipyard._
import chisel3._
import freechips.rocketchip.config._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import sifive.blocks.devices.uart._
import sifive.fpgashells.clocks._
import sifive.fpgashells.ip.xilinx._
import sifive.fpgashells.shell._
import sifive.fpgashells.shell.xilinx._

case object FPGAFrequencyKey extends Field[Double](100.0)

class Genesys2FPGATestHarness(override implicit val p: Parameters) extends Genesys2ShellBasicOverlays {

def dp = designParameters

val jtag_location = Some("PMOD_JA")

// Order matters; ddr depends on sys_clock
val uart = Overlay(UARTOverlayKey, new UARTGenesys2ShellPlacer(this, UARTShellInput()))
val jtag = Overlay(JTAGDebugOverlayKey, new JTAGDebugGenesys2ShellPlacer(this, JTAGDebugShellInput(location = jtag_location)))

val topDesign = LazyModule(p(BuildTop)(dp)).suggestName("chiptop")

// place all clocks in the shell
require(dp(ClockInputOverlayKey).nonEmpty)
val sysClkNode = dp(ClockInputOverlayKey).head.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
val dutClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey))
val dutWrangler = LazyModule(new ResetWrangler)
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL

/*** UART ***/
val io_uart_bb = BundleBridgeSource(() => new UARTPortIO(dp(PeripheryUARTKey).head))
dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb))

/*** JTAG ***/
val io_jtag = dp(JTAGDebugOverlayKey).head.place(JTAGDebugDesignInput()).overlayOutput.jtag

/*** 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.head
}
}
val ddrClient = TLClientNode(Seq(inParams.master))
ddrNode := ddrClient

// module implementation
override lazy val module = new Genesys2FPGATestHarnessImp(this)
}

class Genesys2FPGATestHarnessImp(_outer: Genesys2FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences {

val genesys2Outer = _outer

val reset_n = IO(Input(Bool()))
_outer.xdc.addPackagePin(reset_n, "R19")
_outer.xdc.addIOStandard(reset_n, "LVCMOS33")

val resetIBUF = Module(new IBUF)
resetIBUF.io.I := ~reset_n

val sysclk: Clock = _outer.sysClkNode.out.head._1.clock

val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk)
_outer.sdc.addAsyncPath(Seq(powerOnReset))


_outer.pllReset := (resetIBUF.io.O || powerOnReset)

// reset setup
val hReset = Wire(Reset())
hReset := _outer.dutClock.in.head._1.reset

val harnessClock = _outer.dutClock.in.head._1.clock
val harnessReset = WireInit(hReset)
val dutReset = hReset.asAsyncReset()
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)
}
}