Use Chain for dsptools example.

Rename examples, bump dsptools to master, and incorporate feedback.
This commit is contained in:
Paul Rigge
2020-05-26 23:00:37 +00:00
parent a6e96b6496
commit e6984e412b
14 changed files with 104 additions and 97 deletions

View File

@@ -204,16 +204,16 @@ jobs:
steps:
- prepare-rtl:
project-key: "chipyard-sha3"
prepare-chipyard-fir:
prepare-chipyard-streaming-fir:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-fir"
prepare-chipyard-passthrough:
project-key: "chipyard-streaming-fir"
prepare-chipyard-streaming-passthrough:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-passthrough"
project-key: "chipyard-streaming-passthrough"
prepare-chipyard-hetero:
executor: main-env
steps:
@@ -297,16 +297,16 @@ jobs:
steps:
- run-tests:
project-key: "chipyard-sha3"
chipyard-fir-run-tests:
chipyard-streaming-fir-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-fir"
chipyard-passthrough-run-tests:
project-key: "chipyard-streaming-fir"
chipyard-streaming-passthrough-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-passthrough"
project-key: "chipyard-streaming-passthrough"
chipyard-hetero-run-tests:
executor: main-env
steps:
@@ -459,12 +459,12 @@ workflows:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-fir:
- prepare-chipyard-streaming-fir:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-passthrough:
- prepare-chipyard-streaming-passthrough:
requires:
- install-riscv-toolchain
- install-verilator
@@ -555,13 +555,13 @@ workflows:
requires:
- prepare-chipyard-sha3
- chipyard-fir-run-tests:
- chipyard-streaming-fir-run-tests:
requires:
- prepare-chipyard-fir
- prepare-chipyard-streaming-fir
- chipyard-passthrough-run-tests:
- chipyard-streaming-passthrough-run-tests:
requires:
- prepare-chipyard-passthrough
- prepare-chipyard-streaming-passthrough
- chipyard-hetero-run-tests:
requires:

View File

@@ -46,8 +46,8 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim
declare -A mapping
mapping["chipyard-rocket"]="SUB_PROJECT=chipyard"
mapping["chipyard-sha3"]="SUB_PROJECT=chipyard CONFIG=Sha3RocketConfig"
mapping["chipyard-fir"]="SUB_PROJECT=chipyard CONFIG=FIRRocketConfig"
mapping["chipyard-passthrough"]="SUB_PROJECT=chipyard CONFIG=StreamingPassthroughRocketConfig"
mapping["chipyard-streaming-fir"]="SUB_PROJECT=chipyard CONFIG=StreamingFIRRocketConfig"
mapping["chipyard-streaming-passthrough"]="SUB_PROJECT=chipyard CONFIG=StreamingPassthroughRocketConfig"
mapping["chipyard-hetero"]="SUB_PROJECT=chipyard CONFIG=LargeBoomAndRocketConfig"
mapping["chipyard-boom"]="SUB_PROJECT=chipyard CONFIG=SmallBoomConfig"
mapping["chipyard-blkdev"]="SUB_PROJECT=chipyard CONFIG=SimBlockDeviceRocketConfig"

View File

@@ -62,13 +62,13 @@ case $1 in
(cd $LOCAL_CHIPYARD_DIR/generators/sha3/software && ./build.sh)
$LOCAL_SIM_DIR/simulator-chipyard-Sha3RocketConfig $LOCAL_CHIPYARD_DIR/generators/sha3/software/benchmarks/bare/sha3-rocc.riscv
;;
chipyard-passthrough)
chipyard-streaming-passthrough)
make -C $LOCAL_CHIPYARD_DIR/tests
$LOCAL_SIM_DIR/simulator-chipyard-StreamingPassthroughRocketConfig $LOCAL_CHIPYARD_DIR/tests/passthrough.riscv
$LOCAL_SIM_DIR/simulator-chipyard-StreamingPassthroughRocketConfig $LOCAL_CHIPYARD_DIR/tests/streaming-passthrough.riscv
;;
chipyard-fir)
chipyard-streaming-fir)
make -C $LOCAL_CHIPYARD_DIR/tests
$LOCAL_SIM_DIR/simulator-chipyard-FIRRocketConfig $LOCAL_CHIPYARD_DIR/tests/fir.riscv
$LOCAL_SIM_DIR/simulator-chipyard-StreamingFIRRocketConfig $LOCAL_CHIPYARD_DIR/tests/streaming-fir.riscv
;;
chipyard-spiflashread)
make -C $LOCAL_CHIPYARD_DIR/tests

View File

@@ -16,7 +16,7 @@ It has a AXI4-stream interface and an optional memory interface.
The idea is that these ``DspBlocks`` can be easily designed, unit tested, and assembled lego-style to build complex functionality.
A ``DspChain`` is one example of how to assemble ``DspBlocks``, in which case the streaming interfaces are connected serially into a pipeline, and a bus is instatiated and connected to every block with a memory interface.
This project has example designs that integrate a ``DspBlock`` to a rocketchip-based SoC as an MMIO peripheral. The custom ``DspBlock`` has a ``ReadQueue`` before it and a ``WriteQueue`` after it, which allow memory mapped access to the streaming interfaces so the rocket core can interact with the ``DspBlock``. This section will primarily focus on designing Tilelink-based peripherals. However, through the resources provided in Dsptools, one could also define an AXI4-based peripheral by following similar steps. Furthermore, the examples here are simple, but can be extended to implement more complex accelerators, for example an `OFDM baseband <https://github.com/grebe/ofdm>`_ or a `spectrometer <https://github.com/ucb-art/craft2-chip>`_.
Chipyard has example designs that integrate a ``DspBlock`` to a rocketchip-based SoC as an MMIO peripheral. The custom ``DspBlock`` has a ``ReadQueue`` before it and a ``WriteQueue`` after it, which allow memory mapped access to the streaming interfaces so the rocket core can interact with the ``DspBlock``. This section will primarily focus on designing Tilelink-based peripherals. However, through the resources provided in Dsptools, one could also define an AXI4-based peripheral by following similar steps. Furthermore, the examples here are simple, but can be extended to implement more complex accelerators, for example an `OFDM baseband <https://github.com/grebe/ofdm>`_ or a `spectrometer <https://github.com/ucb-art/craft2-chip>`_.
For this example, we will show you how to connect a simple FIR filter created using Dsptools as an MMIO peripheral. The full code can be found in ``generators/chipyard/src/main/scala/example/dsptools/GenericFIR.scala``. That being said, one could substitute any module with a ready valid interface in the place of the FIR and achieve the same results. As long as the read and valid signals of the module are attached to those of a corresponding ``DSPBlock`` wrapper, and that wrapper is placed in a chain with a ``ReadQueue`` and a ``WriteQueue``, following the general outline establised by these steps will allow you to interact with that block as a memory mapped IO.
@@ -69,8 +69,8 @@ As in the previous MMIO example, we use a cake pattern to hook up our module to
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/dsptools/GenericFIR.scala
:language: scala
:start-after: DOC include start: CanHavePeripheryFIR chisel
:end-before: DOC include end: CanHavePeripheryFIR chisel
:start-after: DOC include start: CanHavePeripheryStreamingFIR chisel
:end-before: DOC include end: CanHavePeripheryStreamingFIR chisel
Note that this is the point at which we decide the datatype for our FIR.
@@ -90,29 +90,29 @@ Finally, we create the configuration class in ``generators/chipyard/src/main/sca
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/dsptools/GenericFIR.scala
:language: scala
:start-after: DOC include start: WithFIR
:end-before: DOC include end: WithFIR
:start-after: DOC include start: WithStreamingFIR
:end-before: DOC include end: WithStreamingFIR
.. literalinclude:: ../../generators/chipyard/src/main/scala/config/RocketConfigs.scala
:language: scala
:start-after: DOC include start: FIRRocketConfig
:end-before: DOC include end: FIRRocketConfig
:start-after: DOC include start: StreamingFIRRocketConfig
:end-before: DOC include end: StreamingFIRRocketConfig
FIR Testing
-----------
We can now test that the FIR is working. The test program is found in ``tests/fir.c``.
We can now test that the FIR is working. The test program is found in ``tests/streaming-fir.c``.
.. literalinclude:: ../../tests/fir.c
.. literalinclude:: ../../tests/streaming-fir.c
:language: c
The test feed a series of values into the fir and compares the output to a golden model of computation. The base of the module's MMIO write region is at 0x2000 and the base of the read region is at 0x2100 by default.
Compiling this program with ``make`` produces a ``fir.riscv`` executable.
Compiling this program with ``make`` produces a ``streaming-fir.riscv`` executable.
Now we can run our simulation.
.. code-block:: shell
cd sims/verilator
make CONFIG=GCDTLRocketConfig BINARY=../../tests/fir.riscv run-binary
make CONFIG=StreamingFIRRocketConfig BINARY=../../tests/streaming-fir.riscv run-binary

View File

@@ -23,7 +23,7 @@ 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.CanHavePeripheryFIR // Enables optionally adding the DSPTools FIR 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
{

View File

@@ -427,7 +427,7 @@ class RingSystemBusRocketConfig extends Config(
// DOC include end: RingSystemBusRocket
class StreamingPassthroughRocketConfig extends Config(
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled passthrough
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithBlackBoxSimMem ++
@@ -445,9 +445,9 @@ class StreamingPassthroughRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.system.BaseConfig)
// DOC include start: FIRRocketConfig
class FIRRocketConfig extends Config (
new chipyard.example.WithFIR ++ // use top with tilelink-controlled FIR
// 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 ++

View File

@@ -18,11 +18,11 @@ import freechips.rocketchip.subsystem._
* @param streamParameters parameters for the stream node
* @param p
*/
abstract class WriteQueue
abstract class WriteQueue[D, U, E, O, B <: Data]
(
val depth: Int = 8,
val depth: Int,
val streamParameters: AXI4StreamMasterParameters = AXI4StreamMasterParameters()
)(implicit p: Parameters) extends LazyModule with HasCSR {
)(implicit p: Parameters) extends DspBlock[D, U, E, O, B] with HasCSR {
// stream node, output only
val streamNode = AXI4StreamMasterNode(streamParameters)
@@ -58,12 +58,10 @@ abstract class WriteQueue
* @param beatBytes beatBytes of TL interface
* @param p
*/
class TLWriteQueue
(
depth: Int = 8,
csrAddress: AddressSet = AddressSet(0x2000, 0xff),
beatBytes: Int = 8,
)(implicit p: Parameters) extends WriteQueue(depth) with TLHasCSR {
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) {
@@ -76,6 +74,17 @@ class TLWriteQueue
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.
@@ -83,11 +92,11 @@ class TLWriteQueue
* @param streamParameters parameters for the stream node
* @param p
*/
abstract class ReadQueue
abstract class ReadQueue[D, U, E, O, B <: Data]
(
val depth: Int = 8,
val depth: Int,
val streamParameters: AXI4StreamSlaveParameters = AXI4StreamSlaveParameters()
)(implicit p: Parameters) extends LazyModule with HasCSR {
)(implicit p: Parameters) extends DspBlock[D, U, E, O, B] with HasCSR {
val streamNode = AXI4StreamSlaveNode(streamParameters)
lazy val module = new LazyModuleImp(this) {
@@ -126,12 +135,10 @@ abstract class ReadQueue
* @param beatBytes beatBytes of TL interface
* @param p
*/
class TLReadQueue
(
depth: Int = 8,
csrAddress: AddressSet = AddressSet(0x2100, 0xff),
beatBytes: Int = 8
)(implicit p: Parameters) extends ReadQueue(depth) with TLHasCSR {
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) {
@@ -142,5 +149,14 @@ class TLReadQueue
}
// 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
}
}

View File

@@ -188,30 +188,27 @@ GenericFIRBlock[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEd
// DOC include start: TLGenericFIRChain chisel
class TLGenericFIRChain[T<:Data:Ring] (genIn: T, genOut: T, coeffs: Seq[T], params: GenericFIRParams)(implicit p: Parameters)
extends LazyModule {
val writeQueue = LazyModule(new TLWriteQueue(params.depth, AddressSet(params.writeAddress, 0xff)))
val fir = LazyModule(new TLGenericFIRBlock(genIn, genOut, coeffs))
val readQueue = LazyModule(new TLReadQueue(params.depth, AddressSet(params.readAddress, 0xff)))
// connect streamNodes of queues and FIR
readQueue.streamNode := fir.streamNode := writeQueue.streamNode
lazy val module = new LazyModuleImp(this)
}
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: CanHavePeripheryFIR chisel
trait CanHavePeripheryFIR extends BaseSubsystem {
val fir = p(GenericFIRKey) match {
trait CanHavePeripheryStreamingFIR extends BaseSubsystem {
val streamingFIR = p(GenericFIRKey) match {
case Some(params) => {
val fir = LazyModule(new TLGenericFIRChain(
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("firWrite")) { fir.writeQueue.mem.get }
pbus.toVariableWidthSlave(Some("firRead")) { fir.readQueue.mem.get }
pbus.toVariableWidthSlave(Some("streamingFIR")) { streamingFIR.mem.get := TLFIFOFixer() }
Some(streamingFIR)
}
case None => None
}
@@ -222,7 +219,7 @@ trait CanHavePeripheryFIR extends BaseSubsystem {
* Mixin to add FIR to rocket config
*/
// DOC include start: WithFIR
class WithFIR extends Config((site, here, up) => {
class WithStreamingFIR extends Config((site, here, up) => {
case GenericFIRKey => Some(GenericFIRParams(depth = 8))
})
// DOC include end: WithFIR

View File

@@ -121,27 +121,21 @@ with TLDspBlock
* @tparam T Type parameter for passthrough, i.e. FixedPoint or DspReal
*/
class TLStreamingPassthroughChain[T<:Data:Ring](params: StreamingPassthroughParams, proto: T)(implicit p: Parameters)
extends LazyModule {
// instantiate lazy modules
val writeQueue = LazyModule(new TLWriteQueue(params.depth, AddressSet(params.writeAddress, 0xff)))
val passthrough = LazyModule(new TLStreamingPassthroughBlock(proto))
val readQueue = LazyModule(new TLReadQueue(params.depth, AddressSet(params.readAddress, 0xff)))
// connect streamNodes of queues and passthrough
readQueue.streamNode := passthrough.streamNode := writeQueue.streamNode
lazy val module = new LazyModuleImp(this)
}
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 passthrough = LazyModule(new TLStreamingPassthroughChain(params, UInt(32.W)))
pbus.toVariableWidthSlave(Some("passthroughWrite")) { passthrough.writeQueue.mem.get }
pbus.toVariableWidthSlave(Some("passthroughRead")) { passthrough.readQueue.mem.get }
Some(passthrough)
val streamingPassthroughChain = LazyModule(new TLStreamingPassthroughChain(params, UInt(32.W)))
pbus.toVariableWidthSlave(Some("streamingPassthrough")) { streamingPassthroughChain.mem.get := TLFIFOFixer() }
Some(streamingPassthroughChain)
}
case None => None
}

View File

@@ -1,17 +1,17 @@
diff --git a/build.sbt b/build.sbt
index 0c4581f..ff0597c 100644
index 5d642c1..56f6fda 100644
--- a/build.sbt
+++ b/build.sbt
@@ -128,7 +128,7 @@ lazy val iocell = (project in file("./tools/barstools/iocell/"))
@@ -130,7 +130,7 @@ lazy val iocell = (project in file("./tools/barstools/iocell/"))
lazy val chipyard = conditionalDependsOn(project in file("generators/chipyard"))
.dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell,
- sha3, // On separate line to allow for cleaner tutorial-setup patches
+// sha3, // On separate line to allow for cleaner tutorial-setup patches
dsptools, `rocket-dsptools`,
gemmini, icenet, tracegen, ariane, nvdla)
.settings(commonSettings)
@@ -155,9 +155,9 @@ lazy val ariane = (project in file("generators/ariane"))
@@ -158,9 +158,9 @@ lazy val ariane = (project in file("generators/ariane"))
.dependsOn(rocketchip)
.settings(commonSettings)

View File

@@ -6,7 +6,7 @@ LDFLAGS= -static
include libgloss.mk
PROGRAMS = pwm blkdev accum charcount nic-loopback big-blkdev pingd \
passthrough fir nvdla spiflashread spiflashwrite
streaming-passthrough streaming-fir nvdla spiflashread spiflashwrite
spiflash.img: spiflash.py
python3 $<