Merge branch 'dev' of https://github.com/ucb-bar/chipyard into ariane-decouple
This commit is contained in:
Submodule generators/boom updated: f0caca8d6b...f1a20b1b3e
@@ -23,6 +23,8 @@ class DigitalTop(implicit p: Parameters) extends System
|
||||
with icenet.CanHavePeripheryIceNIC // Enables optionally adding the IceNIC for FireSim
|
||||
with chipyard.example.CanHavePeripheryInitZero // Enables optionally adding the initzero example widget
|
||||
with chipyard.example.CanHavePeripheryGCD // Enables optionally adding the GCD example widget
|
||||
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
|
||||
{
|
||||
override lazy val module = new DigitalTopModule(this)
|
||||
|
||||
@@ -9,6 +9,7 @@ import freechips.rocketchip.diplomacy.{LazyModule}
|
||||
import freechips.rocketchip.devices.debug._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.system.{SimAXIMem}
|
||||
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4EdgeParameters}
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
import sifive.blocks.devices.gpio._
|
||||
@@ -182,6 +183,20 @@ object AddIOCells {
|
||||
port.suggestName("serial")
|
||||
(port, ios)
|
||||
}
|
||||
|
||||
def axi4(io: Seq[AXI4Bundle], node: AXI4SlaveNode): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = {
|
||||
io.zip(node.in).map{ case (mem_axi4, (_, edge)) => {
|
||||
val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some("iocell_mem_axi4"))
|
||||
port.suggestName("mem_axi4")
|
||||
(port, edge, ios)
|
||||
}}
|
||||
}
|
||||
|
||||
def blockDev(bdev: BlockDeviceIO): (BlockDeviceIO, Seq[IOCell]) = {
|
||||
val (port, ios) = IOCell.generateIOFromSignal(bdev, Some("iocell_bdev"))
|
||||
port.suggestName("bdev")
|
||||
(port, ios)
|
||||
}
|
||||
}
|
||||
|
||||
// DOC include start: WithGPIOTiedOff
|
||||
@@ -211,11 +226,25 @@ class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({
|
||||
})
|
||||
|
||||
class WithSimBlockDevice extends OverrideIOBinder({
|
||||
(system: CanHavePeripheryBlockDeviceModuleImp) => system.connectSimBlockDevice(system.clock, system.reset.asBool); Nil
|
||||
(system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev =>
|
||||
val (port, ios) = AddIOCells.blockDev(bdev)
|
||||
val harnessFn = (th: chipyard.TestHarness) => {
|
||||
SimBlockDevice.connect(th.clock, th.reset.asBool, Some(port))(system.p)
|
||||
Nil
|
||||
}
|
||||
Seq((Seq(port), ios, Some(harnessFn)))
|
||||
}.getOrElse(Nil)
|
||||
})
|
||||
|
||||
class WithBlockDeviceModel extends OverrideIOBinder({
|
||||
(system: CanHavePeripheryBlockDeviceModuleImp) => system.connectBlockDeviceModel(); Nil
|
||||
(system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev =>
|
||||
val (port, ios) = AddIOCells.blockDev(bdev)
|
||||
val harnessFn = (th: chipyard.TestHarness) => {
|
||||
BlockDeviceModel.connect(Some(port))(system.p)
|
||||
Nil
|
||||
}
|
||||
Seq((Seq(port), ios, Some(harnessFn)))
|
||||
}.getOrElse(Nil)
|
||||
})
|
||||
|
||||
class WithLoopbackNIC extends OverrideIOBinder({
|
||||
@@ -232,21 +261,38 @@ class WithSimNIC extends OverrideIOBinder({
|
||||
// accessible to the IOBinder
|
||||
// DOC include start: WithSimAXIMem
|
||||
class WithSimAXIMem extends OverrideIOBinder({
|
||||
(system: CanHaveMasterAXI4MemPort with BaseSubsystem) => SimAXIMem.connectMem(system)(system.p); Nil
|
||||
(system: CanHaveMasterAXI4MemPort with BaseSubsystem) => {
|
||||
val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node)
|
||||
// TODO: we are inlining the connectMem method of SimAXIMem because
|
||||
// it takes in a dut rather than seq of axi4 ports
|
||||
val harnessFn = (th: chipyard.TestHarness) => {
|
||||
peiTuples.map { case (port, edge, ios) =>
|
||||
val mem = LazyModule(new SimAXIMem(edge, size = system.p(ExtMem).get.master.size)(system.p))
|
||||
Module(mem.module).suggestName("mem")
|
||||
mem.io_axi4.head <> port
|
||||
}
|
||||
Nil
|
||||
}
|
||||
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
|
||||
}
|
||||
})
|
||||
// DOC include end: WithSimAXIMem
|
||||
|
||||
class WithBlackBoxSimMem extends OverrideIOBinder({
|
||||
(system: CanHaveMasterAXI4MemPort with BaseSubsystem) => {
|
||||
(system.mem_axi4 zip system.memAXI4Node.in).foreach { case (io, (_, edge)) =>
|
||||
val memSize = system.p(ExtMem).get.master.size
|
||||
val lineSize = system.p(CacheBlockBytes)
|
||||
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle))
|
||||
mem.io.axi <> io
|
||||
mem.io.clock := system.module.clock
|
||||
mem.io.reset := system.module.reset
|
||||
val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node)
|
||||
val harnessFn = (th: chipyard.TestHarness) => {
|
||||
peiTuples.map { case (port, edge, ios) =>
|
||||
val memSize = system.p(ExtMem).get.master.size
|
||||
val lineSize = system.p(CacheBlockBytes)
|
||||
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle))
|
||||
mem.io.axi <> port
|
||||
mem.io.clock := th.clock
|
||||
mem.io.reset := th.reset
|
||||
}
|
||||
Nil
|
||||
}
|
||||
Nil
|
||||
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import freechips.rocketchip.config.{Config}
|
||||
class RocketConfig extends Config(
|
||||
new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts
|
||||
new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a SimAXIMem
|
||||
new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a blackbox DRAMSim model
|
||||
new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing)
|
||||
new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing
|
||||
new testchipip.WithTSI ++ // use testchipip serial offchip link
|
||||
@@ -205,6 +205,24 @@ class SmallSPIFlashRocketConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
||||
new freechips.rocketchip.system.BaseConfig)
|
||||
|
||||
class SimAXIRocketConfig extends Config(
|
||||
new chipyard.iobinders.WithUARTAdapter ++
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++
|
||||
new chipyard.iobinders.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory
|
||||
new chipyard.iobinders.WithTiedOffDebug ++
|
||||
new chipyard.iobinders.WithSimSerial ++
|
||||
new testchipip.WithTSI ++
|
||||
new chipyard.config.WithBootROM ++
|
||||
new chipyard.config.WithUART ++
|
||||
new chipyard.config.WithL2TLBs(1024) ++
|
||||
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.WithNBigCores(1) ++
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
||||
new freechips.rocketchip.system.BaseConfig)
|
||||
|
||||
class SimBlockDeviceRocketConfig extends Config(
|
||||
new chipyard.iobinders.WithUARTAdapter ++
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++
|
||||
@@ -384,14 +402,35 @@ class LoopbackNICRocketConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
||||
new freechips.rocketchip.system.BaseConfig)
|
||||
|
||||
// DOC include start: scratchpadrocket
|
||||
class ScratchpadRocketConfig extends Config(
|
||||
// DOC include start: l1scratchpadrocket
|
||||
class L1ScratchpadSmallRocketConfig extends Config(
|
||||
new chipyard.iobinders.WithUARTAdapter ++
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++
|
||||
new chipyard.iobinders.WithTiedOffDebug ++
|
||||
new chipyard.iobinders.WithSimSerial ++
|
||||
new testchipip.WithTSI ++
|
||||
new testchipip.WithBackingScratchpad ++ // add backing scratchpad
|
||||
new chipyard.config.WithBootROM ++
|
||||
new chipyard.config.WithUART ++
|
||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // remove offchip mem port
|
||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++
|
||||
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
|
||||
new freechips.rocketchip.subsystem.WithNoSlavePort ++
|
||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use rocket l1 scratchpad
|
||||
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
|
||||
new freechips.rocketchip.subsystem.WithNSmallCores(1) ++
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
||||
new freechips.rocketchip.system.BaseConfig)
|
||||
// DOC include end: l1scratchpadrocket
|
||||
|
||||
// DOC include start: mbusscratchpadrocket
|
||||
class MbusScratchpadRocketConfig extends Config(
|
||||
new chipyard.iobinders.WithUARTAdapter ++
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++
|
||||
new chipyard.iobinders.WithTiedOffDebug ++
|
||||
new chipyard.iobinders.WithSimSerial ++
|
||||
new testchipip.WithTSI ++
|
||||
new testchipip.WithBackingScratchpad ++ // add mbus backing scratchpad
|
||||
new chipyard.config.WithBootROM ++
|
||||
new chipyard.config.WithUART ++
|
||||
new chipyard.config.WithL2TLBs(1024) ++
|
||||
@@ -403,7 +442,7 @@ class ScratchpadRocketConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
||||
new freechips.rocketchip.system.BaseConfig)
|
||||
// DOC include end: scratchpadrocket
|
||||
// DOC include end: mbusscratchpadrocket
|
||||
|
||||
// DOC include start: RingSystemBusRocket
|
||||
class RingSystemBusRocketConfig extends Config(
|
||||
@@ -426,6 +465,46 @@ class RingSystemBusRocketConfig extends Config(
|
||||
new freechips.rocketchip.system.BaseConfig)
|
||||
// DOC include end: RingSystemBusRocket
|
||||
|
||||
class StreamingPassthroughRocketConfig extends Config(
|
||||
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
|
||||
new chipyard.iobinders.WithUARTAdapter ++
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++
|
||||
new chipyard.iobinders.WithBlackBoxSimMem ++
|
||||
new chipyard.iobinders.WithTiedOffDebug ++
|
||||
new chipyard.iobinders.WithSimSerial ++
|
||||
new testchipip.WithTSI ++
|
||||
new chipyard.config.WithBootROM ++
|
||||
new chipyard.config.WithUART ++
|
||||
new chipyard.config.WithL2TLBs(1024) ++
|
||||
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.WithNBigCores(1) ++
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
||||
new freechips.rocketchip.system.BaseConfig)
|
||||
|
||||
// DOC include start: StreamingFIRRocketConfig
|
||||
class StreamingFIRRocketConfig extends Config (
|
||||
new chipyard.example.WithStreamingFIR ++ // use top with tilelink-controlled streaming FIR
|
||||
new chipyard.iobinders.WithUARTAdapter ++
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++
|
||||
new chipyard.iobinders.WithBlackBoxSimMem ++
|
||||
new chipyard.iobinders.WithTiedOffDebug ++
|
||||
new chipyard.iobinders.WithSimSerial ++
|
||||
new testchipip.WithTSI ++
|
||||
new chipyard.config.WithBootROM ++
|
||||
new chipyard.config.WithUART ++
|
||||
new chipyard.config.WithL2TLBs(1024) ++
|
||||
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.WithNBigCores(1) ++
|
||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
||||
new freechips.rocketchip.system.BaseConfig)
|
||||
// DOC include end: StreamingFIRRocketConfig
|
||||
|
||||
class SmallNVDLARocketConfig extends Config(
|
||||
new chipyard.iobinders.WithUARTAdapter ++
|
||||
new chipyard.iobinders.WithTieOffInterrupts ++
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
package chipyard.example
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import dspblocks._
|
||||
import dsptools.numbers._
|
||||
import freechips.rocketchip.amba.axi4stream._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.regmapper._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.subsystem._
|
||||
|
||||
/**
|
||||
* The memory interface writes entries into the queue.
|
||||
* They stream out the streaming interface
|
||||
* @param depth number of entries in the queue
|
||||
* @param streamParameters parameters for the stream node
|
||||
* @param p
|
||||
*/
|
||||
abstract class WriteQueue[D, U, E, O, B <: Data]
|
||||
(
|
||||
val depth: Int,
|
||||
val streamParameters: AXI4StreamMasterParameters = AXI4StreamMasterParameters()
|
||||
)(implicit p: Parameters) extends DspBlock[D, U, E, O, B] with HasCSR {
|
||||
// stream node, output only
|
||||
val streamNode = AXI4StreamMasterNode(streamParameters)
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
require(streamNode.out.length == 1)
|
||||
|
||||
// get the output bundle associated with the AXI4Stream node
|
||||
val out = streamNode.out.head._1
|
||||
// width (in bits) of the output interface
|
||||
val width = out.params.n * 8
|
||||
// instantiate a queue
|
||||
val queue = Module(new Queue(UInt(out.params.dataBits.W), depth))
|
||||
// connect queue output to streaming output
|
||||
out.valid := queue.io.deq.valid
|
||||
out.bits.data := queue.io.deq.bits
|
||||
// don't use last
|
||||
out.bits.last := false.B
|
||||
queue.io.deq.ready := out.ready
|
||||
|
||||
regmap(
|
||||
// each write adds an entry to the queue
|
||||
0x0 -> Seq(RegField.w(width, queue.io.enq)),
|
||||
// read the number of entries in the queue
|
||||
(width+7)/8 -> Seq(RegField.r(width, queue.io.count)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TLDspBlock specialization of WriteQueue
|
||||
* @param depth number of entries in the queue
|
||||
* @param csrAddress address range for peripheral
|
||||
* @param beatBytes beatBytes of TL interface
|
||||
* @param p
|
||||
*/
|
||||
class TLWriteQueue (depth: Int, csrAddress: AddressSet, beatBytes: Int)
|
||||
(implicit p: Parameters) extends WriteQueue[
|
||||
TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle
|
||||
](depth) with TLHasCSR {
|
||||
val devname = "tlQueueIn"
|
||||
val devcompat = Seq("ucb-art", "dsptools")
|
||||
val device = new SimpleDevice(devname, devcompat) {
|
||||
override def describe(resources: ResourceBindings): Description = {
|
||||
val Description(name, mapping) = super.describe(resources)
|
||||
Description(name, mapping)
|
||||
}
|
||||
}
|
||||
// make diplomatic TL node for regmap
|
||||
override val mem = Some(TLRegisterNode(address = Seq(csrAddress), device = device, beatBytes = beatBytes))
|
||||
}
|
||||
|
||||
object TLWriteQueue {
|
||||
def apply(
|
||||
depth: Int = 8,
|
||||
csrAddress: AddressSet = AddressSet(0x2000, 0xff),
|
||||
beatBytes: Int = 8,
|
||||
)(implicit p: Parameters) = {
|
||||
val writeQueue = LazyModule(new TLWriteQueue(depth = depth, csrAddress = csrAddress, beatBytes = beatBytes))
|
||||
writeQueue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The streaming interface adds elements into the queue.
|
||||
* The memory interface can read elements out of the queue.
|
||||
* @param depth number of entries in the queue
|
||||
* @param streamParameters parameters for the stream node
|
||||
* @param p
|
||||
*/
|
||||
abstract class ReadQueue[D, U, E, O, B <: Data]
|
||||
(
|
||||
val depth: Int,
|
||||
val streamParameters: AXI4StreamSlaveParameters = AXI4StreamSlaveParameters()
|
||||
)(implicit p: Parameters) extends DspBlock[D, U, E, O, B] with HasCSR {
|
||||
val streamNode = AXI4StreamSlaveNode(streamParameters)
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
require(streamNode.in.length == 1)
|
||||
|
||||
// get the input associated with the stream node
|
||||
val in = streamNode.in.head._1
|
||||
// make a Decoupled[UInt] that RegReadFn can do something with
|
||||
val out = Wire(Decoupled(UInt()))
|
||||
// get width of streaming input interface
|
||||
val width = in.params.n * 8
|
||||
// instantiate a queue
|
||||
val queue = Module(new Queue(UInt(in.params.dataBits.W), depth))
|
||||
// connect input to the streaming interface
|
||||
queue.io.enq.valid := in.valid
|
||||
queue.io.enq.bits := in.bits.data
|
||||
in.ready := queue.io.enq.ready
|
||||
// connect output to wire
|
||||
out.valid := queue.io.deq.valid
|
||||
out.bits := queue.io.deq.bits
|
||||
queue.io.deq.ready := out.ready
|
||||
|
||||
regmap(
|
||||
// map the output of the queue
|
||||
0x0 -> Seq(RegField.r(width, RegReadFn(out))),
|
||||
// read the number of elements in the queue
|
||||
(width+7)/8 -> Seq(RegField.r(width, queue.io.count)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TLDspBlock specialization of ReadQueue
|
||||
* @param depth number of entries in the queue
|
||||
* @param csrAddress address range
|
||||
* @param beatBytes beatBytes of TL interface
|
||||
* @param p
|
||||
*/
|
||||
class TLReadQueue( depth: Int, csrAddress: AddressSet, beatBytes: Int)
|
||||
(implicit p: Parameters) extends ReadQueue[
|
||||
TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle
|
||||
](depth) with TLHasCSR {
|
||||
val devname = "tlQueueOut"
|
||||
val devcompat = Seq("ucb-art", "dsptools")
|
||||
val device = new SimpleDevice(devname, devcompat) {
|
||||
override def describe(resources: ResourceBindings): Description = {
|
||||
val Description(name, mapping) = super.describe(resources)
|
||||
Description(name, mapping)
|
||||
}
|
||||
}
|
||||
// make diplomatic TL node for regmap
|
||||
override val mem = Some(TLRegisterNode(address = Seq(csrAddress), device = device, beatBytes = beatBytes))
|
||||
}
|
||||
|
||||
object TLReadQueue {
|
||||
def apply(
|
||||
depth: Int = 8,
|
||||
csrAddress: AddressSet = AddressSet(0x2100, 0xff),
|
||||
beatBytes: Int = 8)(implicit p: Parameters) = {
|
||||
val readQueue = LazyModule(new TLReadQueue(depth = depth, csrAddress = csrAddress, beatBytes = beatBytes))
|
||||
readQueue
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
//// See LICENSE for license details.
|
||||
//
|
||||
package chipyard.example
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.FixedPoint
|
||||
import chisel3.util._
|
||||
import dspblocks._
|
||||
import dsptools.numbers._
|
||||
import freechips.rocketchip.amba.axi4stream._
|
||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.subsystem._
|
||||
|
||||
// FIR params
|
||||
case class GenericFIRParams(
|
||||
writeAddress: BigInt = 0x2000,
|
||||
readAddress: BigInt = 0x2100,
|
||||
depth: Int
|
||||
)
|
||||
|
||||
case object GenericFIRKey extends Field[Option[GenericFIRParams]](None)
|
||||
|
||||
class GenericFIRCellBundle[T<:Data:Ring](genIn:T, genOut:T) extends Bundle {
|
||||
val data: T = genIn.cloneType
|
||||
val carry: T = genOut.cloneType
|
||||
|
||||
override def cloneType: this.type = GenericFIRCellBundle(genIn, genOut).asInstanceOf[this.type]
|
||||
}
|
||||
object GenericFIRCellBundle {
|
||||
def apply[T<:Data:Ring](genIn:T, genOut:T): GenericFIRCellBundle[T] = new GenericFIRCellBundle(genIn, genOut)
|
||||
}
|
||||
|
||||
class GenericFIRCellIO[T<:Data:Ring](genIn:T, genOut:T) extends Bundle {
|
||||
val coeff = Input(genIn.cloneType)
|
||||
val in = Flipped(Decoupled(GenericFIRCellBundle(genIn, genOut)))
|
||||
val out = Decoupled(GenericFIRCellBundle(genIn, genOut))
|
||||
}
|
||||
object GenericFIRCellIO {
|
||||
def apply[T<:Data:Ring](genIn:T, genOut:T): GenericFIRCellIO[T] = new GenericFIRCellIO(genIn, genOut)
|
||||
}
|
||||
|
||||
class GenericFIRBundle[T<:Data:Ring](proto: T) extends Bundle {
|
||||
val data: T = proto.cloneType
|
||||
|
||||
override def cloneType: this.type = GenericFIRBundle(proto).asInstanceOf[this.type]
|
||||
}
|
||||
object GenericFIRBundle {
|
||||
def apply[T<:Data:Ring](proto: T): GenericFIRBundle[T] = new GenericFIRBundle(proto)
|
||||
}
|
||||
|
||||
class GenericFIRIO[T<:Data:Ring](genIn:T, genOut:T) extends Bundle {
|
||||
val in = Flipped(Decoupled(GenericFIRBundle(genIn)))
|
||||
val out = Decoupled(GenericFIRBundle(genOut))
|
||||
}
|
||||
object GenericFIRIO {
|
||||
def apply[T<:Data:Ring](genIn:T, genOut:T): GenericFIRIO[T] = new GenericFIRIO(genIn, genOut)
|
||||
}
|
||||
|
||||
// A generic FIR filter
|
||||
// DOC include start: GenericFIR chisel
|
||||
class GenericFIR[T<:Data:Ring](genIn:T, genOut:T, coeffs: Seq[T]) extends Module {
|
||||
val io = IO(GenericFIRIO(genIn, genOut))
|
||||
|
||||
// Construct a vector of genericFIRDirectCells
|
||||
val directCells = Seq.fill(coeffs.length){ Module(new GenericFIRDirectCell(genIn, genOut)).io }
|
||||
|
||||
// Construct the direct FIR chain
|
||||
for ((cell, coeff) <- directCells.zip(coeffs)) {
|
||||
cell.coeff := coeff
|
||||
}
|
||||
|
||||
// Connect input to first cell
|
||||
directCells.head.in.bits.data := io.in.bits.data
|
||||
directCells.head.in.bits.carry := Ring[T].zero
|
||||
directCells.head.in.valid := io.in.valid
|
||||
io.in.ready := directCells.head.in.ready
|
||||
|
||||
// Connect adjacent cells
|
||||
// Note that .tail() returns a collection that consists of all
|
||||
// elements in the inital collection minus the first one.
|
||||
// This means that we zip together directCells[0, n] and
|
||||
// directCells[1, n]. However, since zip ignores unmatched elements,
|
||||
// the resulting zip is (directCells[0], directCells[1]) ...
|
||||
// (directCells[n-1], directCells[n])
|
||||
for ((current, next) <- directCells.zip(directCells.tail)) {
|
||||
next.in.bits := current.out.bits
|
||||
next.in.valid := current.out.valid
|
||||
current.out.ready := next.in.ready
|
||||
}
|
||||
|
||||
// Connect output to last cell
|
||||
io.out.bits.data := directCells.last.out.bits.carry
|
||||
directCells.last.out.ready := io.out.ready
|
||||
io.out.valid := directCells.last.out.valid
|
||||
|
||||
}
|
||||
// DOC include end: GenericFIR chisel
|
||||
|
||||
// A generic FIR direct cell used to construct a larger direct FIR chain
|
||||
//
|
||||
// in ----- [z^-1]-- out
|
||||
// |
|
||||
// coeff ----[*]
|
||||
// |
|
||||
// carryIn --[+]-- carryOut
|
||||
//
|
||||
// DOC include start: GenericFIRDirectCell chisel
|
||||
class GenericFIRDirectCell[T<:Data:Ring](genIn: T, genOut: T) extends Module {
|
||||
val io = IO(GenericFIRCellIO(genIn, genOut))
|
||||
|
||||
// Registers to delay the input and the valid to propagate with calculations
|
||||
val hasNewData = RegInit(0.U)
|
||||
val inputReg = Reg(genIn.cloneType)
|
||||
|
||||
// Passthrough ready
|
||||
io.in.ready := io.out.ready
|
||||
|
||||
// When a new transaction is ready on the input, we will have new data to output
|
||||
// next cycle. Take this data in
|
||||
when (io.in.fire()) {
|
||||
hasNewData := 1.U
|
||||
inputReg := io.in.bits.data
|
||||
}
|
||||
|
||||
// We should output data when our cell has new data to output and is ready to
|
||||
// recieve new data. This insures that every cell in the chain passes its data
|
||||
// on at the same time
|
||||
io.out.valid := hasNewData & io.in.fire()
|
||||
io.out.bits.data := inputReg
|
||||
|
||||
// Compute carry
|
||||
// This uses the ring implementation for + and *, i.e.
|
||||
// (a * b) maps to (Ring[T].prod(a, b)) for whicever T you use
|
||||
io.out.bits.carry := inputReg * io.coeff + io.in.bits.carry
|
||||
}
|
||||
// DOC include end: GenericFIRDirectCell chisel
|
||||
|
||||
|
||||
// DOC include start: GenericFIRBlock chisel
|
||||
abstract class GenericFIRBlock[D, U, EO, EI, B<:Data, T<:Data:Ring]
|
||||
(
|
||||
genIn: T,
|
||||
genOut: T,
|
||||
coeffs: Seq[T]
|
||||
)(implicit p: Parameters) extends DspBlock[D, U, EO, EI, B] {
|
||||
val streamNode = AXI4StreamIdentityNode()
|
||||
val mem = None
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
require(streamNode.in.length == 1)
|
||||
require(streamNode.out.length == 1)
|
||||
|
||||
val in = streamNode.in.head._1
|
||||
val out = streamNode.out.head._1
|
||||
|
||||
// instantiate generic fir
|
||||
val fir = Module(new GenericFIR(genIn, genOut, coeffs))
|
||||
|
||||
// Attach ready and valid to outside interface
|
||||
in.ready := fir.io.in.ready
|
||||
fir.io.in.valid := in.valid
|
||||
|
||||
fir.io.out.ready := out.ready
|
||||
out.valid := fir.io.out.valid
|
||||
|
||||
// cast UInt to T
|
||||
fir.io.in.bits := in.bits.data.asTypeOf(GenericFIRBundle(genIn))
|
||||
|
||||
// cast T to UInt
|
||||
out.bits.data := fir.io.out.bits.asUInt
|
||||
}
|
||||
}
|
||||
// DOC include end: GenericFIRBlock chisel
|
||||
|
||||
// DOC include start: TLGenericFIRBlock chisel
|
||||
class TLGenericFIRBlock[T<:Data:Ring]
|
||||
(
|
||||
val genIn: T,
|
||||
val genOut: T,
|
||||
coeffs: Seq[T]
|
||||
)(implicit p: Parameters) extends
|
||||
GenericFIRBlock[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle, T](
|
||||
genIn, genOut, coeffs
|
||||
) with TLDspBlock
|
||||
// DOC include end: TLGenericFIRBlock chisel
|
||||
|
||||
// DOC include start: TLGenericFIRChain chisel
|
||||
class TLGenericFIRChain[T<:Data:Ring] (genIn: T, genOut: T, coeffs: Seq[T], params: GenericFIRParams)(implicit p: Parameters)
|
||||
extends TLChain(Seq(
|
||||
TLWriteQueue(params.depth, AddressSet(params.writeAddress, 0xff))(_),
|
||||
{ implicit p: Parameters =>
|
||||
val fir = LazyModule(new TLGenericFIRBlock(genIn, genOut, coeffs))
|
||||
fir
|
||||
},
|
||||
TLReadQueue(params.depth, AddressSet(params.readAddress, 0xff))(_)
|
||||
))
|
||||
// DOC include end: TLGenericFIRChain chisel
|
||||
|
||||
// DOC include start: CanHavePeripheryStreamingFIR chisel
|
||||
trait CanHavePeripheryStreamingFIR extends BaseSubsystem {
|
||||
val streamingFIR = p(GenericFIRKey) match {
|
||||
case Some(params) => {
|
||||
val streamingFIR = LazyModule(new TLGenericFIRChain(
|
||||
genIn = FixedPoint(8.W, 3.BP),
|
||||
genOut = FixedPoint(8.W, 3.BP),
|
||||
coeffs = Seq(1.F(0.BP), 2.F(0.BP), 3.F(0.BP)),
|
||||
params = params))
|
||||
pbus.toVariableWidthSlave(Some("streamingFIR")) { streamingFIR.mem.get := TLFIFOFixer() }
|
||||
Some(streamingFIR)
|
||||
}
|
||||
case None => None
|
||||
}
|
||||
}
|
||||
// DOC include end: CanHavePeripheryStreamingFIR chisel
|
||||
|
||||
/**
|
||||
* Mixin to add FIR to rocket config
|
||||
*/
|
||||
// DOC include start: WithStreamingFIR
|
||||
class WithStreamingFIR extends Config((site, here, up) => {
|
||||
case GenericFIRKey => Some(GenericFIRParams(depth = 8))
|
||||
})
|
||||
// DOC include end: WithStreamingFIR
|
||||
@@ -0,0 +1,150 @@
|
||||
//// See LICENSE for license details.
|
||||
//
|
||||
package chipyard.example
|
||||
|
||||
import chisel3._
|
||||
import chisel3.{Bundle, Module}
|
||||
import chisel3.util._
|
||||
import dspblocks._
|
||||
import dsptools.numbers._
|
||||
import freechips.rocketchip.amba.axi4stream._
|
||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.subsystem._
|
||||
|
||||
// Simple passthrough to use as testbed sanity check
|
||||
// StreamingPassthrough params
|
||||
case class StreamingPassthroughParams(
|
||||
writeAddress: BigInt = 0x2000,
|
||||
readAddress: BigInt = 0x2100,
|
||||
depth: Int
|
||||
)
|
||||
|
||||
// StreamingPassthrough key
|
||||
case object StreamingPassthroughKey extends Field[Option[StreamingPassthroughParams]](None)
|
||||
|
||||
class StreamingPassthroughBundle[T<:Data:Ring](proto: T) extends Bundle {
|
||||
val data: T = proto.cloneType
|
||||
|
||||
override def cloneType: this.type = StreamingPassthroughBundle(proto).asInstanceOf[this.type]
|
||||
}
|
||||
object StreamingPassthroughBundle {
|
||||
def apply[T<:Data:Ring](proto: T): StreamingPassthroughBundle[T] = new StreamingPassthroughBundle(proto)
|
||||
}
|
||||
|
||||
class StreamingPassthroughIO[T<:Data:Ring](proto: T) extends Bundle {
|
||||
val in = Flipped(Decoupled(StreamingPassthroughBundle(proto)))
|
||||
val out = Decoupled(StreamingPassthroughBundle(proto))
|
||||
}
|
||||
object StreamingPassthroughIO {
|
||||
def apply[T<:Data:Ring](proto: T): StreamingPassthroughIO[T] = new StreamingPassthroughIO(proto)
|
||||
}
|
||||
|
||||
class StreamingPassthrough[T<:Data:Ring](proto: T) extends Module {
|
||||
val io = IO(StreamingPassthroughIO(proto))
|
||||
|
||||
io.in.ready := io.out.ready
|
||||
io.out.bits.data := io.in.bits.data
|
||||
io.out.valid := io.in.valid
|
||||
}
|
||||
|
||||
/**
|
||||
* Make DspBlock wrapper for StreamingPassthrough
|
||||
* @param cordicParams parameters for cordic
|
||||
* @param ev$1
|
||||
* @param ev$2
|
||||
* @param ev$3
|
||||
* @param p
|
||||
* @tparam D
|
||||
* @tparam U
|
||||
* @tparam EO
|
||||
* @tparam EI
|
||||
* @tparam B
|
||||
* @tparam T Type parameter for passthrough, i.e. FixedPoint or DspReal
|
||||
*/
|
||||
abstract class StreamingPassthroughBlock[D, U, EO, EI, B<:Data, T<:Data:Ring]
|
||||
(
|
||||
proto: T
|
||||
)(implicit p: Parameters) extends DspBlock[D, U, EO, EI, B] {
|
||||
val streamNode = AXI4StreamIdentityNode()
|
||||
val mem = None
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
require(streamNode.in.length == 1)
|
||||
require(streamNode.out.length == 1)
|
||||
|
||||
val in = streamNode.in.head._1
|
||||
val out = streamNode.out.head._1
|
||||
|
||||
// instantiate passthrough
|
||||
val passthrough = Module(new StreamingPassthrough(proto))
|
||||
|
||||
// Pass ready and valid from read queue to write queue
|
||||
in.ready := passthrough.io.in.ready
|
||||
passthrough.io.in.valid := in.valid
|
||||
|
||||
// cast UInt to T
|
||||
passthrough.io.in.bits := in.bits.data.asTypeOf(StreamingPassthroughBundle(proto))
|
||||
|
||||
passthrough.io.out.ready := out.ready
|
||||
out.valid := passthrough.io.out.valid
|
||||
|
||||
// cast T to UInt
|
||||
out.bits.data := passthrough.io.out.bits.asUInt
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TLDspBlock specialization of StreamingPassthrough
|
||||
* @param cordicParams parameters for passthrough
|
||||
* @param ev$1
|
||||
* @param ev$2
|
||||
* @param ev$3
|
||||
* @param p
|
||||
* @tparam T Type parameter for passthrough data type
|
||||
*/
|
||||
class TLStreamingPassthroughBlock[T<:Data:Ring]
|
||||
(
|
||||
val proto: T
|
||||
)(implicit p: Parameters) extends
|
||||
StreamingPassthroughBlock[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle, T](proto)
|
||||
with TLDspBlock
|
||||
|
||||
/**
|
||||
* A chain of queues acting as our MMIOs with the passthrough module in between them.
|
||||
* @param depth depth of queues
|
||||
* @param ev$1
|
||||
* @param ev$2
|
||||
* @param ev$3
|
||||
* @param p
|
||||
* @tparam T Type parameter for passthrough, i.e. FixedPoint or DspReal
|
||||
*/
|
||||
class TLStreamingPassthroughChain[T<:Data:Ring](params: StreamingPassthroughParams, proto: T)(implicit p: Parameters)
|
||||
extends TLChain(Seq(
|
||||
TLWriteQueue(params.depth, AddressSet(params.writeAddress, 0xff))(_),
|
||||
{ implicit p: Parameters => {
|
||||
val streamingPassthrough = LazyModule(new TLStreamingPassthroughBlock(proto))
|
||||
streamingPassthrough
|
||||
}},
|
||||
TLReadQueue(params.depth, AddressSet(params.readAddress, 0xff))(_)
|
||||
))
|
||||
|
||||
trait CanHavePeripheryStreamingPassthrough { this: BaseSubsystem =>
|
||||
val passthrough = p(StreamingPassthroughKey) match {
|
||||
case Some(params) => {
|
||||
val streamingPassthroughChain = LazyModule(new TLStreamingPassthroughChain(params, UInt(32.W)))
|
||||
pbus.toVariableWidthSlave(Some("streamingPassthrough")) { streamingPassthroughChain.mem.get := TLFIFOFixer() }
|
||||
Some(streamingPassthroughChain)
|
||||
}
|
||||
case None => None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add passthrough to rocket config
|
||||
*/
|
||||
class WithStreamingPassthrough extends Config((site, here, up) => {
|
||||
case StreamingPassthroughKey => Some(StreamingPassthroughParams(depth = 8))
|
||||
})
|
||||
|
||||
@@ -11,7 +11,12 @@ private[stage] object UnderscoreDelimitedConfigsAnnotation extends HasShellOptio
|
||||
override val options = Seq(
|
||||
new ShellOption[String](
|
||||
longOption = "legacy-configs",
|
||||
toAnnotationSeq = a => Seq(new ConfigsAnnotation(a.split("_"))),
|
||||
toAnnotationSeq = a => {
|
||||
val split = a.split('.')
|
||||
val packageName = split.init.mkString(".")
|
||||
val configs = split.last.split("_")
|
||||
Seq(new ConfigsAnnotation(configs map { config => s"${packageName}.${config}" } ))
|
||||
},
|
||||
helpText = "A string of underscore-delimited configs (configs have decreasing precendence from left to right).",
|
||||
shortOption = Some("LC")
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@ import freechips.rocketchip.stage.RocketChipOptions
|
||||
import freechips.rocketchip.stage.phases.{RocketTestSuiteAnnotation}
|
||||
import freechips.rocketchip.system.{RocketTestSuite, TestGeneration}
|
||||
import freechips.rocketchip.util.HasRocketChipStageUtils
|
||||
import freechips.rocketchip.tile.XLen
|
||||
|
||||
import chipyard.{TestSuiteHelper, CoreManager}
|
||||
|
||||
@@ -30,9 +31,13 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS
|
||||
private def addTestSuiteAnnotations(implicit p: Parameters): Seq[Annotation] = {
|
||||
val annotations = mutable.ArrayBuffer[Annotation]()
|
||||
val suiteHelper = new TestSuiteHelper
|
||||
suiteHelper.addRocketTestSuites
|
||||
suiteHelper.addBoomTestSuites
|
||||
CoreManager.cores map (core => suiteHelper.addThirdPartyTestSuites(core.tileParamsLookup))
|
||||
// Use Xlen as a proxy for detecting if we are a processor-like target
|
||||
// The underlying test suites expect this field to be defined
|
||||
if (p.lift(XLen).nonEmpty) {
|
||||
suiteHelper.addRocketTestSuites
|
||||
suiteHelper.addBoomTestSuites
|
||||
CoreManager.cores map (core => suiteHelper.addThirdPartyTestSuites(core.tileParamsLookup))
|
||||
}
|
||||
|
||||
// if hwacha parameter exists then generate its tests
|
||||
// TODO: find a more elegant way to do this. either through
|
||||
|
||||
@@ -29,6 +29,7 @@ object NodeIdx {
|
||||
}
|
||||
|
||||
class FireSim(implicit val p: Parameters) extends RawModule {
|
||||
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
|
||||
val clockBridge = Module(new RationalClockBridge)
|
||||
val clock = clockBridge.io.clocks.head
|
||||
val reset = WireInit(false.B)
|
||||
|
||||
@@ -84,6 +84,7 @@ class FiresimMulticlockTopModule[+L <: DigitalTop](l: L) extends chipyard.Digita
|
||||
|
||||
// Harness Definition
|
||||
class FireSimMulticlockPOC(implicit val p: Parameters) extends RawModule {
|
||||
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
|
||||
val clockBridge = Module(new RationalClockBridge(p(FireSimClockKey).additionalClocks:_*))
|
||||
val refClock = clockBridge.io.clocks.head
|
||||
val reset = WireInit(false.B)
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
//See LICENSE for license details.
|
||||
|
||||
package firesim.firesim
|
||||
|
||||
import java.io.{File, FileWriter}
|
||||
|
||||
import chisel3.RawModule
|
||||
import chisel3.internal.firrtl.{Circuit, Port}
|
||||
|
||||
import freechips.rocketchip.diplomacy.{ValName, AutoBundle}
|
||||
import freechips.rocketchip.devices.debug.DebugIO
|
||||
import freechips.rocketchip.util.{ElaborationArtefacts}
|
||||
import freechips.rocketchip.system.DefaultTestSuites._
|
||||
import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite}
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.subsystem.RocketTilesKey
|
||||
import freechips.rocketchip.tile.XLen
|
||||
|
||||
import firesim.util.{GeneratorArgs, HasTargetAgnosticUtilites, HasFireSimGeneratorUtilities}
|
||||
|
||||
import scala.util.Try
|
||||
|
||||
import chipyard.TestSuiteHelper
|
||||
|
||||
trait HasTestSuites {
|
||||
def addTestSuites(targetName: String, params: Parameters) {
|
||||
val suiteHelper = new TestSuiteHelper
|
||||
suiteHelper.addRocketTestSuites(params)
|
||||
suiteHelper.addBoomTestSuites(params)
|
||||
suiteHelper.addArianeTestSuites(params)
|
||||
TestGeneration.addSuites(suiteHelper.suites.values.toSeq)
|
||||
TestGeneration.addSuite(FastBlockdevTests)
|
||||
TestGeneration.addSuite(SlowBlockdevTests)
|
||||
if (!targetName.contains("NoNIC"))
|
||||
TestGeneration.addSuite(NICLoopbackTests)
|
||||
|
||||
import hwacha.HwachaTestSuites._
|
||||
if (Try(params(hwacha.HwachaNLanes)).getOrElse(0) > 0) {
|
||||
TestGeneration.addSuites(rv64uv.map(_("p")))
|
||||
TestGeneration.addSuites(rv64uv.map(_("vp")))
|
||||
TestGeneration.addSuite(rv64sv("p"))
|
||||
TestGeneration.addSuite(hwachaBmarks)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mixed into an App or into a TestSuite
|
||||
trait IsFireSimGeneratorLike extends HasFireSimGeneratorUtilities with HasTestSuites {
|
||||
/** Output software test Makefrags, which provide targets for integration testing. */
|
||||
def generateTestSuiteMakefrags {
|
||||
addTestSuites(names.topModuleClass, targetParams)
|
||||
writeOutputFile(s"$longName.d", TestGeneration.generateMakeFrag) // Subsystem-specific test suites
|
||||
}
|
||||
|
||||
// Output miscellaneous files produced as a side-effect of elaboration
|
||||
def generateArtefacts {
|
||||
// generate RC's artefacts
|
||||
ElaborationArtefacts.files.foreach { case (extension, contents) =>
|
||||
writeOutputFile(s"${longName}.${extension}", contents ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object FireSimGenerator extends App with IsFireSimGeneratorLike {
|
||||
override lazy val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs
|
||||
lazy val generatorArgs = GeneratorArgs(args)
|
||||
lazy val genDir = new File(names.targetDir)
|
||||
// The only reason this is not generateFirrtl; generateAnno is that we need to use a different
|
||||
// JsonProtocol to properly write out the annotations. Fix once the generated are unified
|
||||
elaborate
|
||||
generateTestSuiteMakefrags
|
||||
generateArtefacts
|
||||
}
|
||||
@@ -6,44 +6,34 @@ import java.io.File
|
||||
import scala.concurrent.{Future, Await, ExecutionContext}
|
||||
import scala.sys.process.{stringSeqToProcess, ProcessLogger}
|
||||
import scala.io.Source
|
||||
import org.scalatest.Suites
|
||||
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.system.{RocketTestSuite, BenchmarkTestSuite}
|
||||
import freechips.rocketchip.system.TestGeneration._
|
||||
import freechips.rocketchip.system.DefaultTestSuites._
|
||||
|
||||
import firesim.util.GeneratorArgs
|
||||
|
||||
abstract class FireSimTestSuite(
|
||||
topModuleClass: String,
|
||||
targetConfigs: String,
|
||||
platformConfigs: String,
|
||||
N: Int = 8
|
||||
) extends firesim.TestSuiteCommon with IsFireSimGeneratorLike {
|
||||
) extends firesim.TestSuiteCommon {
|
||||
import scala.concurrent.duration._
|
||||
import ExecutionContext.Implicits.global
|
||||
|
||||
val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs
|
||||
val topModuleProject = "firesim.firesim"
|
||||
|
||||
lazy val generatorArgs = GeneratorArgs(
|
||||
midasFlowKind = "midas",
|
||||
targetDir = "generated-src",
|
||||
topModuleProject = "firesim.firesim",
|
||||
topModuleClass = topModuleClass,
|
||||
targetConfigProject = "firesim.firesim",
|
||||
targetConfigs = targetConfigs ++ "_WithScalaTestFeatures",
|
||||
platformConfigProject = "firesim.firesim",
|
||||
platformConfigs = platformConfigs)
|
||||
|
||||
// From HasFireSimGeneratorUtilities
|
||||
// For the firesim utilities to use the same directory as the test suite
|
||||
override lazy val testDir = genDir
|
||||
val chipyardLongName = topModuleProject + "." + topModuleClass + "." + targetConfigs
|
||||
|
||||
// From TestSuiteCommon
|
||||
val targetTuple = generatorArgs.tupleName
|
||||
val commonMakeArgs = Seq(s"DESIGN=${generatorArgs.topModuleClass}",
|
||||
s"TARGET_CONFIG=${generatorArgs.targetConfigs}",
|
||||
s"PLATFORM_CONFIG=${generatorArgs.platformConfigs}")
|
||||
val targetTuple = s"$topModuleClass-$targetConfigs-$platformConfigs"
|
||||
val commonMakeArgs = Seq(s"DESIGN=${topModuleClass}",
|
||||
s"TARGET_CONFIG=${targetConfigs}",
|
||||
s"PLATFORM_CONFIG=${platformConfigs}")
|
||||
|
||||
override lazy val genDir = new File(firesimDir, s"generated-src/${chipyardLongName}")
|
||||
|
||||
|
||||
def invokeMlSimulator(backend: String, name: String, debug: Boolean, additionalArgs: Seq[String] = Nil) = {
|
||||
make((Seq(s"${outDir.getAbsolutePath}/${name}.%s".format(if (debug) "vpd" else "out"),
|
||||
@@ -61,12 +51,6 @@ abstract class FireSimTestSuite(
|
||||
}
|
||||
}
|
||||
|
||||
//def runReplay(backend: String, replayBackend: String, name: String) = {
|
||||
// val dir = (new File(outDir, backend)).getAbsolutePath
|
||||
// (Seq("make", s"replay-$replayBackend",
|
||||
// s"SAMPLE=${dir}/${name}.sample", s"output_dir=$dir") ++ makeArgs).!
|
||||
//}
|
||||
|
||||
def runSuite(backend: String, debug: Boolean = false)(suite: RocketTestSuite) {
|
||||
// compile emulators
|
||||
behavior of s"${suite.makeTargetName} running on $backend"
|
||||
@@ -83,20 +67,6 @@ abstract class FireSimTestSuite(
|
||||
results.flatten foreach { case (name, exitcode) =>
|
||||
it should s"pass $name" in { assert(exitcode == 0) }
|
||||
}
|
||||
//replayBackends foreach { replayBackend =>
|
||||
// if (platformParams(midas.EnableSnapshot) && isCmdAvailable("vcs")) {
|
||||
// assert((Seq("make", s"vcs-$replayBackend") ++ makeArgs).! == 0) // compile vcs
|
||||
// suite.names foreach { name =>
|
||||
// it should s"replay $name in $replayBackend" in {
|
||||
// assert(runReplay(backend, replayBackend, s"$name$postfix") == 0)
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// suite.names foreach { name =>
|
||||
// ignore should s"replay $name in $backend"
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
} else {
|
||||
ignore should s"pass $backend"
|
||||
}
|
||||
@@ -127,66 +97,24 @@ abstract class FireSimTestSuite(
|
||||
}
|
||||
|
||||
clean
|
||||
mkdirs
|
||||
elaborate
|
||||
generateTestSuiteMakefrags
|
||||
generateArtefacts
|
||||
runTest("verilator", "rv64ui-p-simple", false, Seq(s"""EXTRA_SIM_ARGS=+trace-humanreadable0"""))
|
||||
//diffTracelog("rv64ui-p-simple.out")
|
||||
runSuite("verilator")(benchmarks)
|
||||
runSuite("verilator")(FastBlockdevTests)
|
||||
}
|
||||
|
||||
class RocketF1Tests extends FireSimTestSuite("FireSim", "DDR3FRFCFSLLC4MB_FireSimQuadRocketConfig", "WithSynthAsserts_BaseF1Config")
|
||||
class BoomF1Tests extends FireSimTestSuite("FireSim", "DDR3FRFCFSLLC4MB_FireSimLargeBoomConfig", "BaseF1Config")
|
||||
class RocketNICF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimRocketConfig", "BaseF1Config") {
|
||||
runSuite("verilator")(NICLoopbackTests)
|
||||
}
|
||||
//class ArianeF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimArianeConfig", "BaseF1Config") {
|
||||
// runSuite("verilator")(NICLoopbackTests)
|
||||
//}
|
||||
// Disabled until RAM optimizations re-enabled in multiclock
|
||||
//class RamModelRocketF1Tests extends FireSimTestSuite("FireSim", "FireSimDualRocketConfig", "BaseF1Config_MCRams")
|
||||
//class RamModelBoomF1Tests extends FireSimTestSuite("FireSim", "FireSimBoomConfig", "BaseF1Config_MCRams")
|
||||
|
||||
class RocketNICF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimRocketConfig", "BaseF1Config")
|
||||
// Multiclock tests
|
||||
class RocketMulticlockF1Tests extends FireSimTestSuite(
|
||||
"FireSimMulticlockPOC",
|
||||
"FireSimQuadRocketMulticlockConfig",
|
||||
"WithSynthAsserts_BaseF1Config")
|
||||
|
||||
// Jerry broke these -- damn it Jerry.
|
||||
//abstract class FireSimTraceGenTest(targetConfig: String, platformConfig: String)
|
||||
// extends firesim.TestSuiteCommon with IsFireSimGeneratorLike {
|
||||
// val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs
|
||||
//
|
||||
// lazy val generatorArgs = GeneratorArgs(
|
||||
// midasFlowKind = "midas",
|
||||
// targetDir = "generated-src",
|
||||
// topModuleProject = "firesim.firesim",
|
||||
// topModuleClass = "FireSimTraceGen",
|
||||
// targetConfigProject = "firesim.firesim",
|
||||
// targetConfigs = targetConfig ++ "_WithScalaTestFeatures",
|
||||
// platformConfigProject = "firesim.firesim",
|
||||
// platformConfigs = platformConfig)
|
||||
//
|
||||
// // From HasFireSimGeneratorUtilities
|
||||
// // For the firesim utilities to use the same directory as the test suite
|
||||
// override lazy val testDir = genDir
|
||||
//
|
||||
// // From TestSuiteCommon
|
||||
// val targetTuple = generatorArgs.tupleName
|
||||
// val commonMakeArgs = Seq(s"DESIGN=${generatorArgs.topModuleClass}",
|
||||
// s"TARGET_CONFIG=${generatorArgs.targetConfigs}",
|
||||
// s"PLATFORM_CONFIG=${generatorArgs.platformConfigs}")
|
||||
//
|
||||
// it should "pass" in {
|
||||
// assert(make("fsim-tracegen") == 0)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//class FireSimLLCTraceGenTest extends FireSimTraceGenTest(
|
||||
// "DDR3FRFCFSLLC4MB_FireSimTraceGenConfig", "BaseF1Config")
|
||||
//
|
||||
//class FireSimL2TraceGenTest extends FireSimTraceGenTest(
|
||||
// "DDR3FRFCFS_FireSimTraceGenL2Config", "BaseF1Config")
|
||||
class ArianeF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimArianeConfig", "BaseF1Config")
|
||||
|
||||
// This test suite only mirrors what is run in CI. CI invokes each test individually, using a testOnly call.
|
||||
class CITests extends Suites(
|
||||
new RocketF1Tests,
|
||||
new BoomF1Tests,
|
||||
new RocketNICF1Tests,
|
||||
new RocketMulticlockF1Tests)
|
||||
|
||||
Submodule generators/gemmini updated: d6f36d37d1...caaf781ec9
@@ -126,27 +126,30 @@ int main(int argc, char** argv)
|
||||
int verilog_plusargs_legal = 1;
|
||||
|
||||
dramsim = 0;
|
||||
opterr = 1;
|
||||
|
||||
while (1) {
|
||||
static struct option long_options[] = {
|
||||
{"cycle-count", no_argument, 0, 'c' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"max-cycles", required_argument, 0, 'm' },
|
||||
{"seed", required_argument, 0, 's' },
|
||||
{"rbb-port", required_argument, 0, 'r' },
|
||||
{"verbose", no_argument, 0, 'V' },
|
||||
{"dramsim", no_argument, 0, 'D' },
|
||||
{"cycle-count", no_argument, 0, 'c' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"max-cycles", required_argument, 0, 'm' },
|
||||
{"seed", required_argument, 0, 's' },
|
||||
{"rbb-port", required_argument, 0, 'r' },
|
||||
{"verbose", no_argument, 0, 'V' },
|
||||
{"dramsim", no_argument, 0, 'D' },
|
||||
{"permissive", no_argument, 0, 'p' },
|
||||
{"permissive-off", no_argument, 0, 'o' },
|
||||
#if VM_TRACE
|
||||
{"vcd", required_argument, 0, 'v' },
|
||||
{"dump-start", required_argument, 0, 'x' },
|
||||
{"vcd", required_argument, 0, 'v' },
|
||||
{"dump-start", required_argument, 0, 'x' },
|
||||
#endif
|
||||
HTIF_LONG_OPTIONS
|
||||
};
|
||||
int option_index = 0;
|
||||
#if VM_TRACE
|
||||
int c = getopt_long(argc, argv, "-chm:s:r:v:Vx:D", long_options, &option_index);
|
||||
int c = getopt_long(argc, argv, "-chm:s:r:v:Vx:Dpo", long_options, &option_index);
|
||||
#else
|
||||
int c = getopt_long(argc, argv, "-chm:s:r:VD", long_options, &option_index);
|
||||
int c = getopt_long(argc, argv, "-chm:s:r:VDpo", long_options, &option_index);
|
||||
#endif
|
||||
if (c == -1) break;
|
||||
retry:
|
||||
@@ -160,6 +163,8 @@ int main(int argc, char** argv)
|
||||
case 'r': rbb_port = atoi(optarg); break;
|
||||
case 'V': verbose = true; break;
|
||||
case 'D': dramsim = 1; break;
|
||||
case 'p': opterr = 0; break;
|
||||
case 'o': opterr = 1; break;
|
||||
#if VM_TRACE
|
||||
case 'v': {
|
||||
vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w");
|
||||
@@ -195,6 +200,10 @@ int main(int argc, char** argv)
|
||||
c = 'c';
|
||||
else if (arg == "+dramsim")
|
||||
c = 'D';
|
||||
else if (arg == "+permissive")
|
||||
c = 'p';
|
||||
else if (arg == "+permissive-off")
|
||||
c = 'o';
|
||||
// If we don't find a legacy '+' EMULATOR argument, it still could be
|
||||
// a VERILOG_PLUSARG and not an error.
|
||||
else if (verilog_plusargs_legal) {
|
||||
@@ -226,9 +235,13 @@ int main(int argc, char** argv)
|
||||
}
|
||||
htif_option++;
|
||||
}
|
||||
std::cerr << argv[0] << ": invalid plus-arg (Verilog or HTIF) \""
|
||||
<< arg << "\"\n";
|
||||
c = '?';
|
||||
if(opterr) {
|
||||
std::cerr << argv[0] << ": invalid plus-arg (Verilog or HTIF) \""
|
||||
<< arg << "\"\n";
|
||||
c = '?';
|
||||
} else {
|
||||
c = 'p';
|
||||
}
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user