Revamp the config system for Top/Harness (#347)

* Refactor how Configs parameterize the Top and TestHarnesses

* Bump sha3, testchipip, icenet, firesim
This commit is contained in:
Jerry Zhao
2020-01-21 20:44:54 -08:00
committed by GitHub
parent 1786b9a7f4
commit ac5235e5ed
35 changed files with 1087 additions and 858 deletions

View File

@@ -45,7 +45,7 @@ mapping["example"]="SUB_PROJECT=example"
mapping["boomrocketexample"]="SUB_PROJECT=example CONFIG=LargeBoomAndRocketConfig"
mapping["boom"]="SUB_PROJECT=example CONFIG=SmallBoomConfig"
mapping["rocketchip"]="SUB_PROJECT=rocketchip"
mapping["blockdevrocketchip"]="SUB_PROJECT=example CONFIG=SimBlockDeviceRocketConfig TOP=TopWithBlockDevice"
mapping["blockdevrocketchip"]="SUB_PROJECT=example CONFIG=SimBlockDeviceRocketConfig"
mapping["hwacha"]="SUB_PROJECT=example CONFIG=HwachaRocketConfig"
mapping["gemmini"]="SUB_PROJECT=example CONFIG=GemminiRocketConfig"
mapping["tracegen"]="SUB_PROJECT=tracegen CONFIG=NonBlockingTraceGenL2Config"

View File

@@ -0,0 +1,111 @@
.. _cdes:
Context-Dependent-Environments
========================================
Readers may notice that the parameterization system frequently uses ``(site, here, up)``.
This construct is an artifact of the "context-dependent-environment" system which Chipyard and Rocket Chip both leverage for powerful composable hardware configuration.
The CDE parameterization system provides different "Views" of a single global parameterization. The syntax for accessing a ``Field`` within a ``View`` is ``my_view(MyKey, site_view)``, where ``site_view`` is a "global" view that will be passed recursively into various functions and key-lookups in the call-stack of ``my_view(MyKey, site_view)``.
.. note::
Rocket Chip based designs will frequently use ``val p: Parameters`` and ``p(SomeKey)`` to lookup the value of a key. ``Parameters`` is just a subclass of the ``View`` abstract class, and ``p(SomeKey)`` really expands into ``p(SomeKey, p)``. This is because we consider the call ``p(SomeKey)`` to be the "site", or "source" of the original key query, so we need to pass in the view of the configuration provided by ``p`` recursively to future calls through the ``site`` argument.
Consider the following example using CDEs.
.. code:: scala
case object SomeKeyX extends Field[Boolean](false) // default is false
case object SomeKeyY extends Field[Boolean](false) // default is false
case object SomeKeyZ extends Field[Boolean](false) // default is false
class WithX(b: Boolean) extends Config((site, here, up) => {
case SomeKeyX => b
}
class WithY(b: Boolean) extends Config((site, here, up) => {
case SomeKeyY => b
}
When forming a query based on a ``Parameters`` object, like ``p(SomeKeyX)``, the configuration system traverses the "chain" of mixins until it finds a partial function which is defined at the key, and then returns that value.
.. code:: scala
val params = Config(new WithX(true) ++ new WithY(true)) // "chain" together mixins
params(SomeKeyX) // evaluates to true
params(SomeKeyY) // evaluates to true
params(SomeKeyZ) // evaluates to false
In this example, the evaluation of ``params(SomeKeyX)`` will terminate in the partial function defined in ``WithX(true)``, while the evaluation of ``params(SomeKeyY)`` will terminate in the partial function defined in ``WithY(true)``. Note that when no partial functions match, the evaluation will return the default value for that parameter.
The real power of CDEs arises from the ``(site, here, up)`` parameters to the partial functions, which provide useful "views" into the global parameterization that the partial functions may access to determine a parameterization.
.. note::
Additional information on the motivations for CDEs can be found in Chapter 2 of `Henry Cook's Thesis <https://www2.eecs.berkeley.edu/Pubs/TechRpts/2016/EECS-2016-89.pdf>`_ .
Site
~~~~
``site`` provides a ``View`` of the "source" of the original parameter query.
.. code:: scala
class WithXEqualsYSite extends Config((site, here, up) => {
case SomeKeyX => site(SomeKeyY) // expands to site(SomeKeyY, site)
}
val params_1 = Config(new WithXEqualsYSite ++ new WithY(true))
val params_2 = Config(new WithY(true) ++ new WithXEqualsYSite)
params_1(SomeKeyX) // evaluates to true
params_2(SomeKeyX) // evaluates to true
In this example, the partial function in ``WithXEqualsYSite`` will look up the value of ``SomeKeyY`` in the original ``params_N`` object, which becomes ``site`` in each call in the recursive traversal.
Here
~~~~
``here`` provides a ``View`` of the locally defined Config, which typically just contains some partial function.
.. code:: scala
class WithXEqualsYHere extends Config((site, here, up) => {
case SomeKeyY => false
case SomeKeyX => here(SomeKeyY, site)
}
val params_1 = Config(new WithXEqualsYHere ++ new WithY(true))
val params_2 = Config(new WithY(true) ++ new WithXEqualsYHere)
params_1(SomeKeyX) // evaluates to false
params_2(SomeKeyX) // evaluates to false
In this example, note that although our final parameterization in ``params_2`` has ``SomeKeyY`` set to ``true``, the call to ``here(SomeKeyY, site)`` only looks in the local partial function defined in ``WithXEqualsYHere``. Note that we pass ``site`` to ``here`` since ``site`` may be used in the recursive call.
Up
~~~~
``up`` provides a ``View`` of the previously defined set of partial functions in the "chain" of partial functions. This is useful when we want to lookup a previously set value for some key, but not the final value for that key.
.. code:: scala
class WithXEqualsYUp extends Config((site, here, up) => {
case SomeKeyX => up(SomeKeyY, site)
}
val params_1 = Config(new WithXEqualsYUp ++ new WithY(true))
val params_2 = Config(new WithY(true) ++ new WithXEqualsYUp)
params_1(SomeKeyX) // evaluates to true
params_2(SomeKeyX) // evaluates to false
In this example, note how ``up(SomeKeyY, site)`` in ``WithXEqualsYUp`` will refer to *either* the the partial function defining ``SomeKeyY`` in ``WithY(true)`` *or* the default value for ``SomeKeyY`` provided in the original ``case object SomeKeyY`` definition, *depending on the order in which the mixins were used*. Since the order of mixins affects the the order of the ``View`` traversal, ``up`` provides a different ``View`` of the parameterization in ``params_1`` and ``params_2``.
Also note that again, ``site`` must be recursively passed through the call to ``up``.

View File

@@ -12,3 +12,5 @@ They expect you to know about Chisel, Parameters, Configs, etc.
Chip-Communication
Debugging-RTL
Resources
CDEs

View File

@@ -16,6 +16,7 @@ Hit next to get started!
:caption: Chipyard Basics:
Chipyard-Components
Development-Ecosystem
Configs-Parameters-Mixins
Initial-Repo-Setup

View File

@@ -1,261 +0,0 @@
.. _adding-an-accelerator:
Adding an Accelerator/Device
===============================
Accelerators or custom IO devices can be added to your SoC in several ways:
* MMIO Peripheral (a.k.a TileLink-Attached Accelerator)
* Tightly-Coupled RoCC Accelerator
These approaches differ in the method of the communication between the processor and the custom block.
With the TileLink-Attached approach, the processor communicates with MMIO peripherals through memory-mapped registers.
In contrast, the processor communicates with a RoCC accelerators through a custom protocol and custom non-standard ISA instructions reserved in the RISC-V ISA encoding space.
Each core can have up to four accelerators that are controlled by custom instructions and share resources with the CPU.
RoCC coprocessor instructions have the following form.
.. code-block:: none
customX rd, rs1, rs2, funct
The X will be a number 0-3, and determines the opcode of the instruction, which controls which accelerator an instruction will be routed to.
The ``rd``, ``rs1``, and ``rs2`` fields are the register numbers of the destination register and two source registers.
The ``funct`` field is a 7-bit integer that the accelerator can use to distinguish different instructions from each other.
Note that communication through a RoCC interface requires a custom software toolchain, whereas MMIO peripherals can use that standard toolchain with appropriate driver support.
Integrating into the Generator Build System
-------------------------------------------
While developing, you want to include Chisel code in a submodule so that it can be shared by different projects.
To add a submodule to the Chipyard framework, make sure that your project is organized as follows.
.. code-block:: none
yourproject/
build.sbt
src/main/scala/
YourFile.scala
Put this in a git repository and make it accessible.
Then add it as a submodule to under the following directory hierarchy: ``generators/yourproject``.
.. code-block:: shell
cd generators/
git submodule add https://git-repository.com/yourproject.git
Then add ``yourproject`` to the Chipyard top-level build.sbt file.
.. code-block:: scala
lazy val yourproject = (project in file("generators/yourproject")).settings(commonSettings).dependsOn(rocketchip)
You can then import the classes defined in the submodule in a new project if
you add it as a dependency. For instance, if you want to use this code in
the ``example`` project, change the final line in build.sbt to the following.
.. code-block:: scala
lazy val example = (project in file(".")).settings(commonSettings).dependsOn(testchipip, yourproject)
MMIO Peripheral
------------------
The easiest way to create a TileLink peripheral is to use the ``TLRegisterRouter``, which abstracts away the details of handling the TileLink protocol and provides a convenient interface for specifying memory-mapped registers.
To create a RegisterRouter-based peripheral, you will need to specify a parameter case class for the configuration settings, a bundle trait with the extra top-level ports, and a module implementation containing the actual RTL.
In this case we use a submodule ``PWMBase`` to actually perform the pulse-width modulation. The ``PWMModule`` class only creates the registers and hooks them
up using ``regmap``.
.. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
:start-after: DOC include start: PWM generic traits
:end-before: DOC include end: PWM generic traits
Once you have these classes, you can construct the final peripheral by extending the ``TLRegisterRouter`` and passing the proper arguments.
The first set of arguments determines where the register router will be placed in the global address map and what information will be put in its device tree entry.
The second set of arguments is the IO bundle constructor, which we create by extending ``TLRegBundle`` with our bundle trait.
The final set of arguments is the module constructor, which we create by extends ``TLRegModule`` with our module trait.
.. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
:start-after: DOC include start: PWMTL
:end-before: DOC include end: PWMTL
The full module code can be found in ``generators/example/src/main/scala/PWM.scala``.
After creating the module, we need to hook it up to our SoC.
Rocket Chip accomplishes this using the cake pattern.
This basically involves placing code inside traits.
In the Rocket Chip cake, there are two kinds of traits: a ``LazyModule`` trait and a module implementation trait.
The ``LazyModule`` trait runs setup code that must execute before all the hardware gets elaborated.
For a simple memory-mapped peripheral, this just involves connecting the peripheral's TileLink node to the MMIO crossbar.
.. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
:start-after: DOC include start: HasPeripheryPWMTL
:end-before: DOC include end: HasPeripheryPWMTL
Note that the ``PWMTL`` class we created from the register router is itself a ``LazyModule``.
Register routers have a TileLink node simply named "node", which we can hook up to the Rocket Chip bus.
This will automatically add address map and device tree entries for the peripheral.
The module implementation trait is where we instantiate our PWM module and connect it to the rest of the SoC.
Since this module has an extra `pwmout` output, we declare that in this trait, using Chisel's multi-IO functionality.
We then connect the ``PWMTL``'s pwmout to the pwmout we declared.
.. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
:start-after: DOC include start: HasPeripheryPWMTLModuleImp
:end-before: DOC include end: HasPeripheryPWMTLModuleImp
Now we want to mix our traits into the system as a whole.
This code is from ``generators/example/src/main/scala/Top.scala``.
.. literalinclude:: ../../generators/example/src/main/scala/Top.scala
:language: scala
:start-after: DOC include start: TopWithPWMTL
:end-before: DOC include end: TopWithPWMTL
Just as we need separate traits for ``LazyModule`` and module implementation, we need two classes to build the system.
The ``Top`` classes already have the basic peripherals included for us, so we will just extend those.
The ``Top`` class includes the pre-elaboration code and also a ``lazy val`` to produce the module implementation (hence ``LazyModule``).
The ``TopModule`` class is the actual RTL that gets synthesized.
Next, we need to add a configuration mixin in ``generators/example/src/main/scala/ConfigMixins.scala`` that tells the ``TestHarness`` to instantiate ``TopWithPWMTL`` instead of the default ``Top``.
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: WithPWMTop
:end-before: DOC include end: WithPWMTop
And finally, we create a configuration class in ``generators/example/src/main/scala/Configs.scala`` that uses this mixin.
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
:language: scala
:start-after: DOC include start: PWMRocketConfig
:end-before: DOC include end: PWMRocketConfig
Now we can test that the PWM is working. The test program is in ``tests/pwm.c``.
.. literalinclude:: ../../tests/pwm.c
:language: c
This just writes out to the registers we defined earlier.
The base of the module's MMIO region is at 0x2000.
This will be printed out in the address map portion when you generated the verilog code.
Compiling this program with make produces a ``pwm.riscv`` executable.
Now with all of that done, we can go ahead and run our simulation.
.. code-block:: shell
cd sims/verilator
make CONFIG=PWMRocketConfig TOP=TopWithPWMTL
./simulator-example-PWMRocketConfig ../../tests/pwm.riscv
Adding a RoCC Accelerator
----------------------------
RoCC accelerators are lazy modules that extend the ``LazyRoCC`` class.
Their implementation should extends the ``LazyRoCCModule`` class.
.. code-block:: scala
class CustomAccelerator(opcodes: OpcodeSet)
(implicit p: Parameters) extends LazyRoCC(opcodes) {
override lazy val module = new CustomAcceleratorModule(this)
}
class CustomAcceleratorModule(outer: CustomAccelerator)
extends LazyRoCCModuleImp(outer) {
val cmd = Queue(io.cmd)
// The parts of the command are as follows
// inst - the parts of the instruction itself
// opcode
// rd - destination register number
// rs1 - first source register number
// rs2 - second source register number
// funct
// xd - is the destination register being used?
// xs1 - is the first source register being used?
// xs2 - is the second source register being used?
// rs1 - the value of source register 1
// rs2 - the value of source register 2
...
}
The ``opcodes`` parameter for ``LazyRoCC`` is the set of custom opcodes that will map to this accelerator.
More on this in the next subsection.
The ``LazyRoCC`` class contains two TLOutputNode instances, ``atlNode`` and ``tlNode``.
The former connects into a tile-local arbiter along with the backside of the L1 instruction cache.
The latter connects directly to the L1-L2 crossbar.
The corresponding Tilelink ports in the module implementation's IO bundle are ``atl`` and ``tl``, respectively.
The other interfaces available to the accelerator are ``mem``, which provides access to the L1 cache;
``ptw`` which provides access to the page-table walker;
the ``busy`` signal, which indicates when the accelerator is still handling an instruction;
and the ``interrupt`` signal, which can be used to interrupt the CPU.
Look at the examples in ``generators/rocket-chip/src/main/scala/tile/LazyRocc.scala`` for detailed information on the different IOs.
Adding RoCC accelerator to Config
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RoCC accelerators can be added to a core by overriding the ``BuildRoCC`` parameter in the configuration.
This takes a sequence of functions producing ``LazyRoCC`` objects, one for each accelerator you wish to add.
For instance, if we wanted to add the previously defined accelerator and route custom0 and custom1 instructions to it, we could do the following.
.. code-block:: scala
class WithCustomAccelerator extends Config((site, here, up) => {
case BuildRoCC => Seq((p: Parameters) => LazyModule(
new CustomAccelerator(OpcodeSet.custom0 | OpcodeSet.custom1)(p)))
})
class CustomAcceleratorConfig extends Config(
new WithCustomAccelerator ++ new RocketConfig)
To add RoCC instructions in your program, use the RoCC C macros provided in ``tests/rocc.h``. You can find examples in the files ``tests/accum.c`` and ``charcount.c``.
Adding a DMA port
-------------------
For IO devices or accelerators (like a disk or network driver), instead of
having the CPU poll data from the device, we may want to have the device write
directly to the coherent memory system instead. For example, here is a device
that writes zeros to the memory at a configured address.
.. literalinclude:: ../../generators/example/src/main/scala/InitZero.scala
:language: scala
.. literalinclude:: ../../generators/example/src/main/scala/Top.scala
:language: scala
:start-after: DOC include start: TopWithInitZero
:end-before: DOC include end: TopWithInitZero
We use ``TLHelper.makeClientNode`` to create a TileLink client node for us.
We then connect the client node to the memory system through the front bus (fbus).
For more info on creating TileLink client nodes, take a look at :ref:`Client Node`.
Once we've created our top-level module including the DMA widget, we can create a configuration for it as we did before.
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: WithInitZero
:end-before: DOC include end: WithInitZero
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
:language: scala
:start-after: DOC include start: InitZeroRocketConfig
:end-before: DOC include end: InitZeroRocketConfig

View File

@@ -0,0 +1,59 @@
.. _custom_chisel:
Integrating Custom Chisel Projects into the Generator Build System
==================================================================
.. warning::
This section assumes integration of custom Chisel through git submodules.
While it is possible to directly commit custom Chisel into the Chipyard framework,
we heavily recommend managing custom code through git submodules. Using submodules decouples
development of custom features from development on the Chipyard framework.
While developing, you want to include Chisel code in a submodule so that it can be shared by different projects.
To add a submodule to the Chipyard framework, make sure that your project is organized as follows.
.. code-block:: none
yourproject/
build.sbt
src/main/scala/
YourFile.scala
Put this in a git repository and make it accessible.
Then add it as a submodule to under the following directory hierarchy: ``generators/yourproject``.
The ``build.sbt`` is a minimal file which describes metadata for a Chisel project.
For a simple project, the ``build.sbt`` can even be empty, but below we provide an example
build.sbt.
.. code-block:: scala
organization := "edu.berkeley.cs"
version := "1.0"
name := "yourproject"
scalaVersion := "2.12.4"
.. code-block:: shell
cd generators/
git submodule add https://git-repository.com/yourproject.git
Then add ``yourproject`` to the Chipyard top-level build.sbt file.
.. code-block:: scala
lazy val yourproject = (project in file("generators/yourproject")).settings(commonSettings).dependsOn(rocketchip)
You can then import the classes defined in the submodule in a new project if
you add it as a dependency. For instance, if you want to use this code in
the ``example`` project, change the final line in build.sbt to the following.
.. code-block:: scala
lazy val example = (project in file(".")).settings(commonSettings).dependsOn(testchipip, yourproject)

View File

@@ -0,0 +1,39 @@
.. _dma-devices:
Adding a DMA Device
===================
DMA devices are Tilelink widgets which act as masters. In other words,
DMA devices can send their own read and write requests to the chip's memory
system.
For IO devices or accelerators (like a disk or network driver), instead of
having the CPU poll data from the device, we may want to have the device write
directly to the coherent memory system instead. For example, here is a device
that writes zeros to the memory at a configured address.
.. literalinclude:: ../../generators/example/src/main/scala/InitZero.scala
:language: scala
.. literalinclude:: ../../generators/example/src/main/scala/Top.scala
:language: scala
:start-after: DOC include start: Top
:end-before: DOC include end: Top
We use ``TLHelper.makeClientNode`` to create a TileLink client node for us.
We then connect the client node to the memory system through the front bus (fbus).
For more info on creating TileLink client nodes, take a look at :ref:`Client Node`.
Once we've created our top-level module including the DMA widget, we can create a configuration for it as we did before.
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: WithInitZero
:end-before: DOC include end: WithInitZero
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
:language: scala
:start-after: DOC include start: InitZeroRocketConfig
:end-before: DOC include end: InitZeroRocketConfig

View File

@@ -8,8 +8,7 @@ design flows. Fortunately, both Chisel and Chipyard provide extensive
support for Verilog integration.
Here, we will examine the process of incorporating an MMIO peripheral
(similar to the PWM example from the previous section) that uses a
Verilog implementation of Greatest Common Denominator (GCD)
that uses a Verilog implementation of Greatest Common Denominator (GCD)
algorithm. There are a few steps to adding a Verilog peripheral:
* Adding a Verilog resource file to the project
@@ -58,7 +57,7 @@ and Verilog sources follow the prescribed directory layout.
build.sbt
src/main/
scala/
GCDMMIOBlackBox.scala
GCD.scala
resources/
vsrc/
GCDMMIOBlackBox.v
@@ -89,7 +88,7 @@ as the bitwidth of the GCD calculation does in this example.
**Chisel BlackBox Definition**
.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD blackbox
:end-before: DOC include end: GCD blackbox
@@ -102,54 +101,32 @@ diplomatic memory mapping on the system bus, we still have to
integrate the peripheral at the Chisel level by mixing
peripheral-specific traits into a ``TLRegisterRouter``. The ``params``
member and ``HasRegMap`` base trait should look familiar from the
previous memory-mapped PWM device example.
previous memory-mapped GCD device example.
.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD instance regmap
:end-before: DOC include end: GCD instance regmap
Advanced Features of RegField Entries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
One significant difference from the PWM example is in the peripheral's
memory map. ``RegField`` exposes polymorphic ``r`` and ``w`` methods
that allow read- and write-only memory-mapped registers to be
interfaced to hardware in multiple ways.
* ``RegField.r(2, status)`` is used to create a 2-bit, read-only register that captures the current value of the ``status`` signal when read.
* ``RegField.r(params.width, gcd)`` "connects" the decoupled handshaking interface ``gcd`` to a read-only memory-mapped register. When this register is read via MMIO, the ``ready`` signal is asserted. This is in turn connected to ``output_ready`` on the Verilog blackbox through the glue logic.
* ``RegField.w(params.width, x)`` exposes a plain register (much like those in the PWM example) via MMIO, but makes it write-only.
* ``RegField.w(params.width, y)`` associates the decoupled interface signal ``y`` with a write-only memory-mapped register, causing ``y.valid`` to be asserted when the register is written.
Since the ready/valid signals of ``y`` are connected to the
``input_ready`` and ``input_valid`` signals of the blackbox,
respectively, this register map and glue logic has the effect of
triggering the GCD algorithm when ``y`` is written. Therefore, the
algorithm is set up by first writing ``x`` and then performing a
triggering write to ``y``. Polling can be used for status checks.
Defining a Chip with a GCD Peripheral
Defining a Chip with a BlackBox
---------------------------------------
As with the PWM example, a few more pieces are needed to tie the system together.
Since we've parameterized the GCD instantiation to choose between the
Chisel and the verilog module, creating a config is easy.
**Composing traits into a complete cake pattern peripheral**
.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
:language: scala
:start-after: DOC include start: GCD cake
:end-before: DOC include end: GCD cake
:start-after: DOC include start: GCDAXI4BlackBoxRocketConfig
:end-before: DOC include end: GCDAXI4BlackBoxRocketConfig
Note the differences arising due to the fact that this peripheral has
no top-level IO. To build a complete system, a new ``Top`` and new
``Config`` objects are added in a manner exactly analogous to the PWM
example.
You can play with the parameterization of the mixin to choose a TL/AXI4, BlackBox/Chisel
version of the GCD.
Software Testing
----------------
The GCD module has a slightly more complex interface, so polling is
The GCD module has a more complex interface, so polling is
used to check the status of the device before each triggering read or
write.

View File

@@ -0,0 +1,106 @@
.. _keys-traits-configs:
Keys, Traits, and Configs
=========================
You have probably seen snippets of Chisel referencing Keys, Traits, and Configs by this point.
This section aims to elucidate the interactions between these Chisel/Scala components, and provide
best practices for how these should be used to create a parameterized design and configure it.
We will continue to use the GCD example.
Keys
----
Keys specify some parameter which controls some custom widget. Keys should typically be implemented as **Option types**, with a default value of ``None`` that means no change in the system. In other words, the default behavior when the user does not explicitly set the key should be a no-op.
Keys should be defined and documented in sub-projects, since they generally deal with some specific block, and not system-level integration. (We make an exception for the example GCD widget).
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD key
:end-before: DOC include end: GCD key
The object within a key is typically a ``case class XXXParams``, which defines a set of parameters which some block accepts. For example, the GCD widget's ``GCDParams`` parameterizes its address, operand widths, whether the widget should be connected by Tilelink or AXI4, and whether the widget should use the blackbox-verilog implementation, or the Chisel implementation.
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD params
:end-before: DOC include end: GCD params
Accessing the value stored in the key is easy in Chisel, as long as the ``implicit p: Parameters`` object is being passed through to the relevant module. For example, ``p(GCDKey).get.address`` returns the address field of ``GCDParams``. Note this only works if ``GCDKey`` was not set to ``None``, so your Chisel should check for that case!
Traits
------
Typically, most custom blocks will need to modify the behavior of some pre-existing block. For example, the GCD widget needs the ``Top`` module to instantiate and connect the widget via Tilelink, generate a top-level ``gcd_busy`` port, and connect that to the module as well. Traits let us do this without modifying the existing code for the ``Top``, and enables compartmentalization of code for different custom blocks.
Top-level traits specify that the ``Top`` has been parameterized to read some custom Key and optionally instantiate and connect a widget defined by that Key. Traits **should not** mandate the instantiation of custom logic. In other words, traits should be written with ``CanHave`` semantics, where the default behavior when the Key is unset is a no-op.
Top-level traits should be defined and documented in subprojects, alongside their corresponding Keys. The traits should then be added to the ``Top`` being used by Chipyard.
Below we see the traits for the GCD example. The Lazy trait connects the GCD module to the Diplomacy graph, while the Implementation trait causes the ``Top`` to instantiate an additional port and concretely connect it to the GCD module.
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD lazy trait
:end-before: DOC include end: GCD imp trait
These traits are added to the default ``Top`` in Chipyard.
.. literalinclude:: ../../generators/example/src/main/scala/Top.scala
:language: scala
:start-after: DOC include start: Top
:end-before: DOC include end: Top
Mixins
------
Mixins set the keys to a non-default value. Together, the collection of Mixins which define a configuration generate the values for all the keys used by the generator.
For example, the ``WithGCDMixin`` is parameterized by the type of GCD widget you want to instantiate. When this mixin is added to a config, the ``GCDKey`` is set to a instance of ``GCDParams``, informing the previously mentioned traits to instantiate and connect the GCD widget appropriately.
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: GCD mixin
:end-before: DOC include end: GCD mixin
We can use this mixin when composing our configs.
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
:language: scala
:start-after: DOC include start: GCDTLRocketConfig
:end-before: DOC include end: GCDTLRocketConfig
BuildTop
--------
The ``BuildTop`` key is special, because sometimes, we need to instantiate ``TestHarness`` modules to interface with a custom widget. The ``BuildTop`` key provides a function which can call some method of the Top to instantiate these ``TestHarness`` modules. Since the ``BuildTop`` key is called from the ``TestHarness``, these modules will appear in the ``TestHarness``. The config system also lets the ``BuildTop`` key look recursively into previous definitions of itself. This enables composability of the ``Top`` configurations.
For example, conside a config that contains the mixins ``WithGPIO ++ WithTSI``. We need to instantiate the TSI serial adapter, and connect it to the ``success`` signal of our ``TestHarness``. We also need to instantiate the GPIO pins, and tie their inputs to 0 in the ``TestHarness``, since we currently cannot drive the GPIOs in simulation.
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: tsi mixin
:end-before: DOC include end: tsi mixin
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: gpio mixin
:end-before: DOC include end: gpio mixin
When ``WithGPIO ++ WithTSI`` is evaluated right to left, the call to ``up(BuildTop, site)`` in ``WithGPIO`` will reference the function defined in the ``BuildTop`` key of ``WithTSI``. Thus, at elaboration time, when the ``BuildTop`` function is called by the ``TestHarness``, first the ``BuildTop`` function in ``WithTSI`` will be evaluated. This connects the ``success`` signal of the ``TestHarness`` to the ``SerialAdapter`` enabled by ``WithTSI``. Then, the rest of the code in the ``BuildTop`` function of ``WithGPIO`` will execute, tieing off the top-level GPIO input pins. Thus the evaluation of the ``BuildTop`` functions in a completed config is "right-to-left", matching how the evaluation of the mixins at compile-time is also "right-to-left".
.. warning::
Note that in some cases, the ordering and duplication of mixins which extend ``BuildTop`` will have unintended consequences.
For example, ``WithTSI ++ WithTSI`` will attempt to generate and connect two ``SimSerial`` widgets in the ``TestHarness``,
which will likely break the simulation.
In general, you should avoid attaching multiple mixins which interface to the same top-level ports.
.. note::
Readers who want more information on the configuration system may be interested in reading :ref:`cdes`.

View File

@@ -0,0 +1,142 @@
.. _mmio-accelerators:
MMIO Peripherals
==================
The easiest way to create a MMIO peripheral is to use the ``TLRegisterRouter`` or ``AXI4RegisterRouter`` widgets, which abstracts away the details of handling the interconnect protocols and provides a convenient interface for specifying memory-mapped registers. Since Chipyard and Rocket Chip SoCs primarily use Tilelink as the on-chip interconnect protocol, this section will primarily focus on designing Tilelink-based peripherals. However, see ``generators/example/src/main/scala/GCD.scala`` for how an example AXI4 based peripheral is defined and connected to the Tilelink graph through converters.
To create a RegisterRouter-based peripheral, you will need to specify a parameter case class for the configuration settings, a bundle trait with the extra top-level ports, and a module implementation containing the actual RTL.
For this example, we will show how to connect a MMIO peripheral which computes the GCD.
The full code can be found in ``generators/example/src/main/scala/GCD.scala``.
In this case we use a submodule ``GCDMMIOChiselModule`` to actually perform the GCD. The ``GCDModule`` class only creates the registers and hooks them up using ``regmap``.
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD chisel
:end-before: DOC include end: GCD chisel
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD instance regmap
:end-before: DOC include end: GCD instance regmap
Advanced Features of RegField Entries
-------------------------------------
``RegField`` exposes polymorphic ``r`` and ``w`` methods
that allow read- and write-only memory-mapped registers to be
interfaced to hardware in multiple ways.
* ``RegField.r(2, status)`` is used to create a 2-bit, read-only register that captures the current value of the ``status`` signal when read.
* ``RegField.r(params.width, gcd)`` "connects" the decoupled handshaking interface ``gcd`` to a read-only memory-mapped register. When this register is read via MMIO, the ``ready`` signal is asserted. This is in turn connected to ``output_ready`` on the GCD module through the glue logic.
* ``RegField.w(params.width, x)`` exposes a plain register via MMIO, but makes it write-only.
* ``RegField.w(params.width, y)`` associates the decoupled interface signal ``y`` with a write-only memory-mapped register, causing ``y.valid`` to be asserted when the register is written.
Since the ready/valid signals of ``y`` are connected to the
``input_ready`` and ``input_valid`` signals of the GCD module,
respectively, this register map and glue logic has the effect of
triggering the GCD algorithm when ``y`` is written. Therefore, the
algorithm is set up by first writing ``x`` and then performing a
triggering write to ``y``. Polling can be used for status checks.
Connecting by TileLink
----------------------
Once you have these classes, you can construct the final peripheral by extending the ``TLRegisterRouter`` and passing the proper arguments.
The first set of arguments determines where the register router will be placed in the global address map and what information will be put in its device tree entry.
The second set of arguments is the IO bundle constructor, which we create by extending ``TLRegBundle`` with our bundle trait.
The final set of arguments is the module constructor, which we create by extends ``TLRegModule`` with our module trait.
Notice how we can create an analogous AXI4 version of our peripheral.
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD router
:end-before: DOC include end: GCD router
Top-level Traits
----------------
After creating the module, we need to hook it up to our SoC.
Rocket Chip accomplishes this using the cake pattern.
This basically involves placing code inside traits.
In the Rocket Chip cake, there are two kinds of traits: a ``LazyModule`` trait and a module implementation trait.
The ``LazyModule`` trait runs setup code that must execute before all the hardware gets elaborated.
For a simple memory-mapped peripheral, this just involves connecting the peripheral's TileLink node to the MMIO crossbar.
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD lazy trait
:end-before: DOC include end: GCD lazy trait
Note that the ``GCDTL`` class we created from the register router is itself a ``LazyModule``.
Register routers have a TileLink node simply named "node", which we can hook up to the Rocket Chip bus.
This will automatically add address map and device tree entries for the peripheral.
Also observe how we have to place additional AXI4 buffers and converters for the AXI4 version of this peripheral.
For peripherals which instantiate a concrete module, or which need to be connected to concrete IOs or wires, a matching concrete trait is necessary. We will make our GCD example output a ``gcd_busy`` signal as a top-level port to demonstrate. In the concrete module implementation trait, we instantiate the top level IO (a concrete object) and wire it to the IO of our lazy module.
.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala
:language: scala
:start-after: DOC include start: GCD imp trait
:end-before: DOC include end: GCD imp trait
Constructing the Top and Config
-------------------------------
Now we want to mix our traits into the system as a whole.
This code is from ``generators/example/src/main/scala/Top.scala``.
.. literalinclude:: ../../generators/example/src/main/scala/Top.scala
:language: scala
:start-after: DOC include start: Top
:end-before: DOC include end: Top
Just as we need separate traits for ``LazyModule`` and module implementation, we need two classes to build the system.
The ``Top`` class contains the set of traits which parameterize and define the ``Top``. Typically these traits will optionally add IOs or peripherals to the ``Top``.
The ``Top`` class includes the pre-elaboration code and also a ``lazy val`` to produce the module implementation (hence ``LazyModule``).
The ``TopModule`` class is the actual RTL that gets synthesized.
And finally, we create a configuration class in ``generators/example/src/main/scala/Configs.scala`` that uses the ``WithGCD`` mixin defined earlier.
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: GCD mixin
:end-before: DOC include end: GCD mixin
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
:language: scala
:start-after: DOC include start: GCDTLRocketConfig
:end-before: DOC include end: GCDTLRocketConfig
Testing
-------
Now we can test that the GCD is working. The test program is in ``tests/gcd.c``.
.. literalinclude:: ../../tests/gcd.c
:language: c
This just writes out to the registers we defined earlier.
The base of the module's MMIO region is at 0x2000 by default.
This will be printed out in the address map portion when you generate the verilog code.
You can also see how this changes the emitted ``.json`` addressmap files in ``generated-src``.
Compiling this program with ``make`` produces a ``gcd.riscv`` executable.
Now with all of that done, we can go ahead and run our simulation.
.. code-block:: shell
cd sims/verilator
make CONFIG=GCDTLRocketConfig BINARY=../../tests/gcd.riscv run-binary

View File

@@ -0,0 +1,70 @@
.. _rocc-accelerators:
Adding a RoCC Accelerator
----------------------------
RoCC accelerators are lazy modules that extend the ``LazyRoCC`` class.
Their implementation should extends the ``LazyRoCCModule`` class.
.. code-block:: scala
class CustomAccelerator(opcodes: OpcodeSet)
(implicit p: Parameters) extends LazyRoCC(opcodes) {
override lazy val module = new CustomAcceleratorModule(this)
}
class CustomAcceleratorModule(outer: CustomAccelerator)
extends LazyRoCCModuleImp(outer) {
val cmd = Queue(io.cmd)
// The parts of the command are as follows
// inst - the parts of the instruction itself
// opcode
// rd - destination register number
// rs1 - first source register number
// rs2 - second source register number
// funct
// xd - is the destination register being used?
// xs1 - is the first source register being used?
// xs2 - is the second source register being used?
// rs1 - the value of source register 1
// rs2 - the value of source register 2
...
}
The ``opcodes`` parameter for ``LazyRoCC`` is the set of custom opcodes that will map to this accelerator.
More on this in the next subsection.
The ``LazyRoCC`` class contains two TLOutputNode instances, ``atlNode`` and ``tlNode``.
The former connects into a tile-local arbiter along with the backside of the L1 instruction cache.
The latter connects directly to the L1-L2 crossbar.
The corresponding Tilelink ports in the module implementation's IO bundle are ``atl`` and ``tl``, respectively.
The other interfaces available to the accelerator are ``mem``, which provides access to the L1 cache;
``ptw`` which provides access to the page-table walker;
the ``busy`` signal, which indicates when the accelerator is still handling an instruction;
and the ``interrupt`` signal, which can be used to interrupt the CPU.
Look at the examples in ``generators/rocket-chip/src/main/scala/tile/LazyRocc.scala`` for detailed information on the different IOs.
Adding RoCC accelerator to Config
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RoCC accelerators can be added to a core by overriding the ``BuildRoCC`` parameter in the configuration.
This takes a sequence of functions producing ``LazyRoCC`` objects, one for each accelerator you wish to add.
For instance, if we wanted to add the previously defined accelerator and route custom0 and custom1 instructions to it, we could do the following.
.. code-block:: scala
class WithCustomAccelerator extends Config((site, here, up) => {
case BuildRoCC => Seq((p: Parameters) => LazyModule(
new CustomAccelerator(OpcodeSet.custom0 | OpcodeSet.custom1)(p)))
})
class CustomAcceleratorConfig extends Config(
new WithCustomAccelerator ++
new RocketConfig)
To add RoCC instructions in your program, use the RoCC C macros provided in ``tests/rocc.h``. You can find examples in the files ``tests/accum.c`` and ``charcount.c``.

View File

@@ -0,0 +1,27 @@
.. _rocc-vs-mmio:
RoCC vs MMIO
------------
Accelerators or custom IO devices can be added to your SoC in several ways:
* MMIO Peripheral (a.k.a TileLink-Attached Accelerator)
* Tightly-Coupled RoCC Accelerator
These approaches differ in the method of the communication between the processor and the custom block.
With the TileLink-Attached approach, the processor communicates with MMIO peripherals through memory-mapped registers.
In contrast, the processor communicates with a RoCC accelerators through a custom protocol and custom non-standard ISA instructions reserved in the RISC-V ISA encoding space.
Each core can have up to four accelerators that are controlled by custom instructions and share resources with the CPU.
RoCC coprocessor instructions have the following form.
.. code-block:: none
customX rd, rs1, rs2, funct
The X will be a number 0-3, and determines the opcode of the instruction, which controls which accelerator an instruction will be routed to.
The ``rd``, ``rs1``, and ``rs2`` fields are the register numbers of the destination register and two source registers.
The ``funct`` field is a 7-bit integer that the accelerator can use to distinguish different instructions from each other.
Note that communication through a RoCC interface requires a custom software toolchain, whereas MMIO peripherals can use that standard toolchain with appropriate driver support.

View File

@@ -3,18 +3,41 @@ Customization
These guides will walk you through customization of your system-on-chip:
- Contructing heterogenous systems-on-chip using the Chipyard generators and configuration system.
- Contructing heterogenous systems-on-chip using the existing Chipyard generators and configuration system.
- Adding custom accelerators to your system-on-chip.
- How to include your custom Chisel sources in the Chipyard build system
Hit next to get started!
- Adding custom RoCC accelerators to an existing Chipyard core (BOOM or Rocket)
- Adding custom MMIO widgets to the Chipyard memory system by Tilelink or AXI4, with custom Top-level IOs
- Standard practices for using Keys, Traits, and Configs to parameterize your design
- Customizing the memory hierarchy
- Connect widgets which act as TileLink masters
- Adding custom blackboxed verilog to a Chipyard design
We also provide information on:
- The boot process for Chipyard SoCs
- Examples of FIRRTL transforms used in Chipyard, and where they are specified
We recommend reading all these pages in order. Hit next to get started!
.. toctree::
:maxdepth: 2
:caption: Customization:
Heterogeneous-SoCs
Adding-An-Accelerator
Custom-Chisel
RoCC-or-MMIO
RoCC-Accelerators
MMIO-Peripherals
Keys-Traits-Configs
DMA-Devices
Incorporating-Verilog-Blocks
Memory-Hierarchy
Boot-Process

View File

@@ -56,7 +56,7 @@ The ``software`` directory of the generator includes the aforementioned library
The Gemmini generator generates a C header file based on the generator parameters. This header files gets compiled together with the matrix multiplication library to tune library performance. The generated header file can be found under ``software/gemmini-rocc-tests/include/gemmini_params.h``
Build and Run Gemmini Tests
^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^
To build Gemmini tests:

View File

@@ -78,6 +78,6 @@ this mixin is shown here:
:end-before: DOC include end: Sha3Rocket
The SHA3 example baremetal and Linux tests are located in the SHA3 repository.
Please refer to its `README.md<https://github.com/ucb-bar/sha3/blob/master/README.md>`__ for more information on how to run/build the tests.
Please refer to its `README.md <https://github.com/ucb-bar/sha3/blob/master/README.md>`_ for more information on how to run/build the tests.

View File

@@ -20,17 +20,11 @@ To integrate one of these devices in your SoC, you will need to define a custom
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: WithGPIO
:end-before: DOC include end: WithGPIO
:start-after: DOC include start: gpio mixin
:end-before: DOC include end: gpio mixin
Additionally, if the device requires top-level IOs, you will need to define a mixin to change the top-level configuration of your SoC.
When adding a top-level IO, you should also be aware of whether it interacts with the test-harness.
For example, a GPIO device would require a GPIO pin, and therefore we would write a mixin to augment the top level as follows:
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: WithGPIOTop
:end-before: DOC include end: WithGPIOTop
This example instantiates a top-level module with include GPIO ports (``TopWithGPIO``), and then ties-off the GPIO port inputs to 0 (``false.B``).

View File

@@ -54,7 +54,7 @@ This depends on what you are planning to do with Chipyard.
* If you intend to run a full-system FireSim simulation, go to :ref:`firesim-sim-intro` and follow the instructions.
* If you intend to add a new accelerator, go to :ref:`adding-an-accelerator` and follow the instructions.
* If you intend to add a new accelerator, go to :ref:`customization` and follow the instructions.
* If you want to learn about the structure of Chipyard, go to :ref:`chipyard-components`.

View File

@@ -10,7 +10,8 @@ module GCDMMIOBlackBox
input [WIDTH-1:0] y,
input output_ready,
output output_valid,
output reg [WIDTH-1:0] gcd
output reg [WIDTH-1:0] gcd,
output busy
);
// DOC include end: GCD portlist
@@ -21,6 +22,7 @@ module GCDMMIOBlackBox
assign input_ready = state == S_IDLE;
assign output_valid = state == S_DONE;
assign busy = state != S_IDLE;
always @(posedge clock) begin
if (reset)

View File

@@ -9,54 +9,72 @@ import freechips.rocketchip.config.{Config}
// ---------------------
class SmallBoomConfig extends Config(
new WithTop ++ // use normal top
new WithTSI ++ // use testchipip serial offchip link
new WithNoGPIO ++ // no top-level GPIO pins (overrides default set in sifive-blocks)
new WithBootROM ++ // use testchipip bootrom
new WithUART ++ // add a UART
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level mmio master port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level mmio slave port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use SiFive L2 cache
new boom.common.WithSmallBooms ++ // 1-wide BOOM
new boom.common.WithNBoomCores(1) ++ // single-core
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
class MediumBoomConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new boom.common.WithMediumBooms ++ // 2-wide BOOM
new boom.common.WithNBoomCores(1) ++
new freechips.rocketchip.system.BaseConfig)
class LargeBoomConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new boom.common.WithLargeBooms ++ // 3-wide BOOM
new boom.common.WithNBoomCores(1) ++
new freechips.rocketchip.system.BaseConfig)
class MegaBoomConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new boom.common.WithMegaBooms ++ // 4-wide BOOM
new boom.common.WithNBoomCores(1) ++
new freechips.rocketchip.system.BaseConfig)
class DualSmallBoomConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new boom.common.WithSmallBooms ++
new boom.common.WithNBoomCores(2) ++ // dual-core
new freechips.rocketchip.system.BaseConfig)
class SmallRV32BoomConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new boom.common.WithoutBoomFPU ++ // no fp
new boom.common.WithBoomRV32 ++ // rv32 (32bit)
@@ -65,9 +83,12 @@ class SmallRV32BoomConfig extends Config(
new freechips.rocketchip.system.BaseConfig)
class HwachaLargeBoomConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
new boom.common.WithLargeBooms ++ // 3-wide BOOM
@@ -75,11 +96,16 @@ class HwachaLargeBoomConfig extends Config(
new freechips.rocketchip.system.BaseConfig)
class LoopbackNICBoomConfig extends Config(
new WithIceNIC ++
new WithLoopbackNICTop ++
new WithTSI ++
new WithNoGPIO ++
new WithLoopbackNIC ++ // loopback the NIC
new WithIceNIC ++ // add IceNIC
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new boom.common.WithLargeBooms ++ // 3-wide BOOM
new boom.common.WithLargeBooms ++
new boom.common.WithNBoomCores(1) ++
new freechips.rocketchip.system.BaseConfig)

View File

@@ -7,8 +7,10 @@ import freechips.rocketchip.config.{Field, Parameters, Config}
import freechips.rocketchip.subsystem.{SystemBusKey, RocketTilesKey, WithRoccExample, WithNMemoryChannels, WithNBigCores, WithRV32, CacheBlockBytes}
import freechips.rocketchip.diplomacy.{LazyModule, ValName}
import freechips.rocketchip.devices.tilelink.BootROMParams
import freechips.rocketchip.tile.{RocketTileParams, MaxHartIdBits, XLen, BuildRoCC, TileKey, LazyRoCC}
import freechips.rocketchip.devices.debug.{Debug}
import freechips.rocketchip.tile.{XLen, BuildRoCC, TileKey, LazyRoCC, RocketTileParams, MaxHartIdBits}
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
import freechips.rocketchip.util.{AsyncResetReg}
import boom.common.{BoomTilesKey}
@@ -33,23 +35,30 @@ import ConfigValName._
// Common Parameter Mixins
// -----------------------
/**
* Class to specify where the BootRom file is (from `rebar` top)
*/
class WithBootROM extends Config((site, here, up) => {
case BootROMParams => BootROMParams(
contentFileName = s"./bootrom/bootrom.rv${site(XLen)}.img")
})
// DOC include start: WithGPIO
/**
* Class to add in GPIO
*/
// DOC include start: gpio mixin
class WithGPIO extends Config((site, here, up) => {
case PeripheryGPIOKey => Seq(
GPIOParams(address = 0x10012000, width = 4, includeIOF = false))
case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => {
val top = up(BuildTop, site)(clock, reset, p, success)
// TODO: Currently FIRRTL will error if the GPIO input
// pins are unconnected, so tie them to 0.
// In future IO cell blackboxes will replace this with
// more correct functionality
for (gpio <- top.gpio) {
for (pin <- gpio.pins) {
pin.i.ival := false.B
}
}
top
}
})
// DOC include end: WithGPIO
// DOC include end: gpio mixin
/**
* Class to add in UART
@@ -59,92 +68,58 @@ class WithUART extends Config((site, here, up) => {
UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256))
})
// -----------------------------------------------
// BOOM and/or Rocket Top Level System Parameter Mixins
// -----------------------------------------------
/**
* Class to specify a "plain" top level BOOM and/or Rocket system
*/
class WithTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => {
Module(LazyModule(new Top()(p)).module)
class WithNoGPIO extends Config((site, here, up) => {
case PeripheryGPIOKey => Seq()
})
// DOC include start: tsi mixin
class WithTSI extends Config((site, here, up) => {
case SerialKey => true
case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => {
val top = up(BuildTop, site)(clock, reset, p, success)
success := top.connectSimSerial()
top
}
})
// DOC include end: tsi mixin
class WithDTM extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => {
val top = up(BuildTop, site)(clock, reset, p, success)
top.reset := reset.asBool | top.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)
Debug.connectDebug(top.debug, top.psd, clock, reset.asBool, success)(p)
top
}
})
/**
* Class to specify a top level BOOM and/or Rocket system with DTM
*/
class WithDTMTop extends Config((site, here, up) => {
case BuildTopWithDTM => (clock: Clock, reset: Bool, p: Parameters) => {
Module(LazyModule(new TopWithDTM()(p)).module)
}
// DOC include start: GCD mixin
class WithGCD(useAXI4: Boolean, useBlackBox: Boolean) extends Config((site, here, up) => {
case GCDKey => Some(GCDParams(useAXI4 = useAXI4, useBlackBox = useBlackBox))
})
// DOC include end: GCD mixin
/**
* Class to specify a top level BOOM and/or Rocket system with PWM
*/
// DOC include start: WithPWMTop
class WithPWMTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) =>
Module(LazyModule(new TopWithPWMTL()(p)).module)
})
// DOC include end: WithPWMTop
/**
* Class to specify a top level BOOM and/or Rocket system with a PWM AXI4
*/
class WithPWMAXI4Top extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) =>
Module(LazyModule(new TopWithPWMAXI4()(p)).module)
})
/**
* Class to specify a top level BOOM and/or Rocket system with a TL-attached GCD device
*/
class WithGCDTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) =>
Module(LazyModule(new TopWithGCD()(p)).module)
})
/**
* Class to specify a top level BOOM and/or Rocket system with a block device
*/
class WithBlockDeviceModelTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => {
val top = Module(LazyModule(new TopWithBlockDevice()(p)).module)
class WithBlockDeviceModel extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => {
val top = up(BuildTop, site)(clock, reset, p, success)
top.connectBlockDeviceModel()
top
}
})
/**
* Class to specify a top level BOOM and/or Rocket system with a simulator block device
*/
class WithSimBlockDeviceTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => {
val top = Module(LazyModule(new TopWithBlockDevice()(p)).module)
class WithSimBlockDevice extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => {
val top = up(BuildTop, site)(clock, reset, p, success)
top.connectSimBlockDevice(clock, reset)
top
}
})
// DOC include start: WithGPIOTop
/**
* Class to specify a top level BOOM and/or Rocket system with GPIO
*/
class WithGPIOTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => {
val top = Module(LazyModule(new TopWithGPIO()(p)).module)
for (gpio <- top.gpio) {
for (pin <- gpio.pins) {
pin.i.ival := false.B
}
}
top
}
// DOC include start: WithInitZero
class WithInitZero(base: BigInt, size: BigInt) extends Config((site, here, up) => {
case InitZeroKey => Some(InitZeroConfig(base, size))
})
// DOC include end: WithGPIOTop
// DOC include end: WithInitZero
// ------------------
// Multi-RoCC Support
@@ -184,16 +159,6 @@ class WithMultiRoCCHwacha(harts: Int*) extends Config((site, here, up) => {
}
})
// DOC include start: WithInitZero
class WithInitZero(base: BigInt, size: BigInt) extends Config((site, here, up) => {
case InitZeroKey => InitZeroConfig(base, size)
})
class WithInitZeroTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) =>
Module(LazyModule(new TopWithInitZero()(p)).module)
})
// DOC include end: WithInitZero
/**
* Mixin to add a small Rocket core to the system as a "control" core.
@@ -227,15 +192,15 @@ class WithControlCore extends Config((site, here, up) => {
class WithIceNIC(inBufFlits: Int = 1800, usePauser: Boolean = false)
extends Config((site, here, up) => {
case NICKey => NICConfig(
case NICKey => Some(NICConfig(
inBufFlits = inBufFlits,
usePauser = usePauser,
checksumOffload = true)
checksumOffload = true))
})
class WithLoopbackNICTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => {
val top = Module(LazyModule(new TopWithIceNIC()(p)).module)
class WithLoopbackNIC extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => {
val top = up(BuildTop, site)(clock, reset, p, success)
top.connectNicLoopback()
top
}

View File

@@ -0,0 +1,200 @@
package example
import chisel3._
import chisel3.util._
import chisel3.experimental.{IntParam, BaseModule}
import freechips.rocketchip.amba.axi4._
import freechips.rocketchip.subsystem.BaseSubsystem
import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper.{HasRegMap, RegField}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.UIntIsOneOf
// DOC include start: GCD params
case class GCDParams(
address: BigInt = 0x2000,
width: Int = 32,
useAXI4: Boolean = false,
useBlackBox: Boolean = true)
// DOC include end: GCD params
// DOC include start: GCD key
case object GCDKey extends Field[Option[GCDParams]](None)
// DOC include end: GCD key
class GCDIO(val w: Int) extends Bundle {
val clock = Input(Clock())
val reset = Input(Bool())
val input_ready = Output(Bool())
val input_valid = Input(Bool())
val x = Input(UInt(w.W))
val y = Input(UInt(w.W))
val output_ready = Input(Bool())
val output_valid = Output(Bool())
val gcd = Output(UInt(w.W))
val busy = Output(Bool())
}
trait GCDTopIO extends Bundle {
val gcd_busy = Output(Bool())
}
trait HasGCDIO extends BaseModule {
val w: Int
val io = IO(new GCDIO(w))
}
// DOC include start: GCD blackbox
class GCDMMIOBlackBox(val w: Int) extends BlackBox(Map("WIDTH" -> IntParam(w))) with HasBlackBoxResource
with HasGCDIO
{
addResource("/vsrc/GCDMMIOBlackBox.v")
}
// DOC include end: GCD blackbox
// DOC include start: GCD chisel
class GCDMMIOChiselModule(val w: Int) extends Module
with HasGCDIO
{
val s_idle :: s_run :: s_done :: Nil = Enum(3)
val state = RegInit(s_idle)
val tmp = Reg(UInt(w.W))
val gcd = Reg(UInt(w.W))
io.input_ready := state === s_idle
io.output_valid := state === s_done
io.gcd := gcd
when (state === s_idle && io.input_valid) {
state := s_run
} .elsewhen (state === s_run && tmp === 0.U) {
state := s_done
} .elsewhen (state === s_done && io.output_ready) {
state := s_idle
}
when (state === s_idle && io.input_valid) {
gcd := io.x
tmp := io.y
} .elsewhen (state === s_run) {
when (gcd > tmp) {
gcd := gcd - tmp
} .otherwise {
tmp := tmp - gcd
}
}
io.busy := state =/= s_idle
}
// DOC include end: GCD chisel
// DOC include start: GCD instance regmap
trait GCDModule extends HasRegMap {
val io: GCDTopIO
implicit val p: Parameters
def params: GCDParams
val clock: Clock
val reset: Reset
// How many clock cycles in a PWM cycle?
val x = Reg(UInt(params.width.W))
val y = Wire(new DecoupledIO(UInt(params.width.W)))
val gcd = Wire(new DecoupledIO(UInt(params.width.W)))
val status = Wire(UInt(2.W))
val impl = if (params.useBlackBox) {
Module(new GCDMMIOBlackBox(params.width))
} else {
Module(new GCDMMIOChiselModule(params.width))
}
impl.io.clock := clock
impl.io.reset := reset.asBool
impl.io.x := x
impl.io.y := y.bits
impl.io.input_valid := y.valid
y.ready := impl.io.input_ready
gcd.bits := impl.io.gcd
gcd.valid := impl.io.output_valid
impl.io.output_ready := gcd.ready
status := Cat(impl.io.input_ready, impl.io.output_ready)
io.gcd_busy := impl.io.busy
regmap(
0x00 -> Seq(
RegField.r(2, status)), // a read-only register capturing current status
0x04 -> Seq(
RegField.w(params.width, x)), // a plain, write-only register
0x08 -> Seq(
RegField.w(params.width, y)), // write-only, y.valid is set on write
0x0C -> Seq(
RegField.r(params.width, gcd))) // read-only, gcd.ready is set on read
}
// DOC include end: GCD instance regmap
// DOC include start: GCD router
class GCDTL(params: GCDParams, beatBytes: Int)(implicit p: Parameters)
extends TLRegisterRouter(
params.address, "gcd", Seq("ucbbar,gcd"),
beatBytes = beatBytes)(
new TLRegBundle(params, _) with GCDTopIO)(
new TLRegModule(params, _, _) with GCDModule)
class GCDAXI4(params: GCDParams, beatBytes: Int)(implicit p: Parameters)
extends AXI4RegisterRouter(
params.address,
beatBytes=beatBytes)(
new AXI4RegBundle(params, _) with GCDTopIO)(
new AXI4RegModule(params, _, _) with GCDModule)
// DOC include end: GCD router
// DOC include start: GCD lazy trait
trait CanHavePeripheryGCD { this: BaseSubsystem =>
private val portName = "gcd"
// Only build if we are using the TL (nonAXI4) version
val gcd = p(GCDKey) match {
case Some(params) => {
if (params.useAXI4) {
val gcd = LazyModule(new GCDAXI4(params, pbus.beatBytes)(p))
pbus.toSlave(Some(portName)) {
gcd.node :=
AXI4Buffer () :=
TLToAXI4 () :=
// toVariableWidthSlave doesn't use holdFirstDeny, which TLToAXI4() needsx
TLFragmenter(pbus.beatBytes, pbus.blockBytes, holdFirstDeny = true)
}
Some(gcd)
} else {
val gcd = LazyModule(new GCDTL(params, pbus.beatBytes)(p))
pbus.toVariableWidthSlave(Some(portName)) { gcd.node }
Some(gcd)
}
}
case None => None
}
}
// DOC include end: GCD lazy trait
// DOC include start: GCD imp trait
trait CanHavePeripheryGCDModuleImp extends LazyModuleImp {
val outer: CanHavePeripheryGCD
val gcd_busy = outer.gcd match {
case Some(gcd) => {
val busy = IO(Output(Bool()))
busy := gcd.module.io.gcd_busy
Some(busy)
}
case None => None
}
}
// DOC include end: GCD imp trait

View File

@@ -1,98 +0,0 @@
package example
import chisel3._
import chisel3.util._
import chisel3.core.{IntParam, Reset}
import freechips.rocketchip.amba.axi4._
import freechips.rocketchip.subsystem.BaseSubsystem
import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper.{HasRegMap, RegField}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.UIntIsOneOf
// DOC include start: GCD blackbox
class GCDMMIOBlackBox(w: Int) extends BlackBox(Map("WIDTH" -> IntParam(w))) with HasBlackBoxResource {
val io = IO(new Bundle {
val clock = Input(Clock())
val reset = Input(Bool())
val input_ready = Output(Bool())
val input_valid = Input(Bool())
val x = Input(UInt(w.W))
val y = Input(UInt(w.W))
val output_ready = Input(Bool())
val output_valid = Output(Bool())
val gcd = Output(UInt(w.W))
})
addResource("/vsrc/GCDMMIOBlackBox.v")
}
// DOC include end: GCD blackbox
// DOC include start: GCD instance regmap
case class GCDParams(address: BigInt, beatBytes: Int, width: Int)
trait GCDModule extends HasRegMap {
implicit val p: Parameters
def params: GCDParams
val clock: Clock
val reset: Reset
val impl = Module(new GCDMMIOBlackBox(params.width))
// How many clock cycles in a PWM cycle?
val x = Reg(UInt(params.width.W))
val y = Wire(new DecoupledIO(impl.io.y))
val gcd = Wire(new DecoupledIO(impl.io.gcd))
val status = Cat(impl.io.input_ready, impl.io.output_valid)
impl.io.clock := clock
impl.io.reset := reset.asBool
impl.io.x := x
impl.io.y := y.bits
impl.io.input_valid := y.valid
y.ready := impl.io.input_ready
gcd.bits := impl.io.gcd
gcd.valid := impl.io.output_valid
impl.io.output_ready := gcd.ready
regmap(
0x00 -> Seq(
RegField.r(2, status)), // a read-only register capturing current status
0x04 -> Seq(
RegField.w(params.width, x)), // a plain, write-only register
0x08 -> Seq(
RegField.w(params.width, y)), // write-only, y.valid is set on write
0x0C -> Seq(
RegField.r(params.width, gcd))) // read-only, gcd.ready is set on read
}
// DOC include end: GCD instance regmap
// DOC include start: GCD cake
class GCD(c: GCDParams)(implicit p: Parameters)
extends TLRegisterRouter(
c.address, "gcd", Seq("ucbbar,gcd"),
beatBytes = c.beatBytes)(
new TLRegBundle(c, _))(
new TLRegModule(c, _, _) with GCDModule)
trait HasPeripheryGCD { this: BaseSubsystem =>
implicit val p: Parameters
private val address = 0x2000
private val portName = "gcd"
private val gcdWidth = 32
val gcd = LazyModule(new GCD(
GCDParams(address, pbus.beatBytes, gcdWidth))(p))
pbus.toVariableWidthSlave(Some(portName)) { gcd.node }
}
trait HasPeripheryGCDModuleImp extends LazyModuleImp {
implicit val p: Parameters
val outer: HasPeripheryGCD
}
// DOC include end: GCD cake

View File

@@ -9,10 +9,13 @@ import freechips.rocketchip.config.{Config}
// ---------------------
class LargeBoomAndRocketConfig extends Config(
new WithTop ++ // default top
new WithTSI ++ // use testchipip serial offchip link
new WithNoGPIO ++ // no top-level GPIO pins (overrides default set in sifive-blocks)
new WithBootROM ++ // default bootrom
new WithUART ++ // add a UART
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use SiFive l2
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
new boom.common.WithRenumberHarts ++ // avoid hartid overlap
new boom.common.WithLargeBooms ++ // 3-wide boom
new boom.common.WithNBoomCores(1) ++ // single-core boom
@@ -20,10 +23,13 @@ class LargeBoomAndRocketConfig extends Config(
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
class SmallBoomAndRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new boom.common.WithRenumberHarts ++
new boom.common.WithSmallBooms ++ // 1-wide boom
new boom.common.WithNBoomCores(1) ++
@@ -32,11 +38,14 @@ class SmallBoomAndRocketConfig extends Config(
// DOC include start: BoomAndRocketWithHwacha
class HwachaLargeBoomAndHwachaRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new hwacha.DefaultHwachaConfig ++ // add hwacha to all harts
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new boom.common.WithRenumberHarts ++
new boom.common.WithLargeBooms ++
new boom.common.WithNBoomCores(1) ++
@@ -45,10 +54,13 @@ class HwachaLargeBoomAndHwachaRocketConfig extends Config(
// DOC include end: BoomAndRocketWithHwacha
class RoccLargeBoomAndRoccRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithRoccExample ++ // add example rocc accelerator to all harts
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new boom.common.WithRenumberHarts ++
new boom.common.WithLargeBooms ++
@@ -57,9 +69,12 @@ class RoccLargeBoomAndRoccRocketConfig extends Config(
new freechips.rocketchip.system.BaseConfig)
class DualLargeBoomAndRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new boom.common.WithRenumberHarts ++
new boom.common.WithLargeBooms ++
@@ -69,10 +84,13 @@ class DualLargeBoomAndRocketConfig extends Config(
// DOC include start: DualBoomAndRocketOneHwacha
class DualLargeBoomAndHwachaRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new WithMultiRoCC ++ // support heterogeneous rocc
new WithMultiRoCCHwacha(2) ++ // put hwacha on hart-2 (rocket)
new boom.common.WithRenumberHarts ++
@@ -83,10 +101,13 @@ class DualLargeBoomAndHwachaRocketConfig extends Config(
// DOC include end: DualBoomAndRocketOneHwacha
class LargeBoomAndRV32RocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new boom.common.WithRenumberHarts ++
new boom.common.WithLargeBooms ++
new boom.common.WithNBoomCores(1) ++
@@ -96,10 +117,13 @@ class LargeBoomAndRV32RocketConfig extends Config(
// DOC include start: DualBoomAndRocket
class DualLargeBoomAndDualRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new boom.common.WithRenumberHarts ++
new boom.common.WithLargeBooms ++
new boom.common.WithNBoomCores(2) ++ // 2 boom cores
@@ -108,10 +132,13 @@ class DualLargeBoomAndDualRocketConfig extends Config(
// DOC include end: DualBoomAndRocket
class MultiCoreWithControlCoreConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new WithControlCore ++ // add small control core (last hartid)
new boom.common.WithRenumberHarts ++
new boom.common.WithLargeBooms ++

View File

@@ -8,7 +8,7 @@ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, IdRange}
import testchipip.TLHelper
case class InitZeroConfig(base: BigInt, size: BigInt)
case object InitZeroKey extends Field[InitZeroConfig]
case object InitZeroKey extends Field[Option[InitZeroConfig]](None)
class InitZero(implicit p: Parameters) extends LazyModule {
val node = TLHelper.makeClientNode(
@@ -18,7 +18,7 @@ class InitZero(implicit p: Parameters) extends LazyModule {
}
class InitZeroModuleImp(outer: InitZero) extends LazyModuleImp(outer) {
val config = p(InitZeroKey)
val config = p(InitZeroKey).get
val (mem, edge) = outer.node.out(0)
val addrBits = edge.bundle.addressBits
@@ -57,13 +57,11 @@ class InitZeroModuleImp(outer: InitZero) extends LazyModuleImp(outer) {
}
}
trait HasPeripheryInitZero { this: BaseSubsystem =>
trait CanHavePeripheryInitZero { this: BaseSubsystem =>
implicit val p: Parameters
val initZero = LazyModule(new InitZero()(p))
fbus.fromPort(Some("init-zero"))() := initZero.node
}
trait HasPeripheryInitZeroModuleImp extends LazyModuleImp {
// Don't need anything here
p(InitZeroKey) .map { k =>
val initZero = LazyModule(new InitZero()(p))
fbus.fromPort(Some("init-zero"))() := initZero.node
}
}

View File

@@ -1,134 +0,0 @@
package example
import chisel3._
import chisel3.util._
import freechips.rocketchip.amba.axi4._
import freechips.rocketchip.subsystem.BaseSubsystem
import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper.{HasRegMap, RegField}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.UIntIsOneOf
// DOC include start: PWM generic traits
case class PWMParams(address: BigInt, beatBytes: Int)
class PWMBase(w: Int) extends Module {
val io = IO(new Bundle {
val pwmout = Output(Bool())
val period = Input(UInt(w.W))
val duty = Input(UInt(w.W))
val enable = Input(Bool())
})
// The counter should count up until period is reached
val counter = Reg(UInt(w.W))
when (counter >= (io.period - 1.U)) {
counter := 0.U
} .otherwise {
counter := counter + 1.U
}
// If PWM is enabled, pwmout is high when counter < duty
// If PWM is not enabled, it will always be low
io.pwmout := io.enable && (counter < io.duty)
}
trait PWMBundle extends Bundle {
val pwmout = Output(Bool())
}
trait PWMModule extends HasRegMap {
val io: PWMBundle
implicit val p: Parameters
def params: PWMParams
// How many clock cycles in a PWM cycle?
val period = Reg(UInt(32.W))
// For how many cycles should the clock be high?
val duty = Reg(UInt(32.W))
// Is the PWM even running at all?
val enable = RegInit(false.B)
val base = Module(new PWMBase(32))
io.pwmout := base.io.pwmout
base.io.period := period
base.io.duty := duty
base.io.enable := enable
regmap(
0x00 -> Seq(
RegField(32, period)),
0x04 -> Seq(
RegField(32, duty)),
0x08 -> Seq(
RegField(1, enable)))
}
// DOC include end: PWM generic traits
// DOC include start: PWMTL
class PWMTL(c: PWMParams)(implicit p: Parameters)
extends TLRegisterRouter(
c.address, "pwm", Seq("ucbbar,pwm"),
beatBytes = c.beatBytes)(
new TLRegBundle(c, _) with PWMBundle)(
new TLRegModule(c, _, _) with PWMModule)
// DOC include end: PWMTL
class PWMAXI4(c: PWMParams)(implicit p: Parameters)
extends AXI4RegisterRouter(c.address, beatBytes = c.beatBytes)(
new AXI4RegBundle(c, _) with PWMBundle)(
new AXI4RegModule(c, _, _) with PWMModule)
// DOC include start: HasPeripheryPWMTL
trait HasPeripheryPWMTL { this: BaseSubsystem =>
implicit val p: Parameters
private val address = 0x2000
private val portName = "pwm"
val pwm = LazyModule(new PWMTL(
PWMParams(address, pbus.beatBytes))(p))
pbus.toVariableWidthSlave(Some(portName)) { pwm.node }
}
// DOC include end: HasPeripheryPWMTL
// DOC include start: HasPeripheryPWMTLModuleImp
trait HasPeripheryPWMTLModuleImp extends LazyModuleImp {
implicit val p: Parameters
val outer: HasPeripheryPWMTL
val pwmout = IO(Output(Bool()))
pwmout := outer.pwm.module.io.pwmout
}
// DOC include end: HasPeripheryPWMTLModuleImp
trait HasPeripheryPWMAXI4 { this: BaseSubsystem =>
implicit val p: Parameters
private val address = 0x2000
private val portName = "pwm"
val pwm = LazyModule(new PWMAXI4(
PWMParams(address, pbus.beatBytes))(p))
pbus.toSlave(Some(portName)) {
pwm.node :=
AXI4Buffer () :=
TLToAXI4() :=
// toVariableWidthSlave doesn't use holdFirstDeny, which TLToAXI4() needs
TLFragmenter(pbus.beatBytes, pbus.blockBytes, holdFirstDeny = true)
}
}
trait HasPeripheryPWMAXI4ModuleImp extends LazyModuleImp {
implicit val p: Parameters
val outer: HasPeripheryPWMAXI4
val pwmout = IO(Output(Bool()))
pwmout := outer.pwm.module.io.pwmout
}

View File

@@ -9,17 +9,23 @@ import freechips.rocketchip.config.{Config}
// --------------
class RocketConfig extends Config(
new WithTop ++ // use default top
new WithTSI ++ // use testchipip serial offchip link
new WithNoGPIO ++ // no top-level GPIO pins (overrides default set in sifive-blocks)
new WithBootROM ++ // use default bootrom
new WithUART ++ // add a UART
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
class HwachaRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
@@ -27,9 +33,12 @@ class HwachaRocketConfig extends Config(
// DOC include start: GemminiRocketConfig
class GemminiRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new gemmini.DefaultGemminiConfig ++ // use Gemmini systolic array GEMM accelerator
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
@@ -37,9 +46,12 @@ class GemminiRocketConfig extends Config(
// DOC include end: GemminiRocketConfig
class RoccRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithRoccExample ++ // use example RoCC-based accelerator
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
@@ -47,10 +59,13 @@ class RoccRocketConfig extends Config(
// DOC include start: JtagRocket
class jtagRocketConfig extends Config(
new WithDTMTop ++ // use top with dtm
new freechips.rocketchip.subsystem.WithJtagDTM ++ // add jtag+DTM module to coreplex
new WithDTM ++ // use top with dtm
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithJtagDTM ++ // enable communicating with the DTM using jtag
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
@@ -58,100 +73,127 @@ class jtagRocketConfig extends Config(
// DOC include start: DmiRocket
class dmiRocketConfig extends Config(
new WithDTMTop ++ // use top with dtm
new WithDTM ++ // use top with dtm
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include end: DmiRocket
// DOC include start: PWMRocketConfig
class PWMRocketConfig extends Config(
new WithPWMTop ++ // use top with tilelink-controlled PWM
new WithBootROM ++
// DOC include start: GCDTLRocketConfig
class GCDTLRocketConfig extends Config(
new WithTSI ++
new WithNoGPIO ++
new WithUART ++
new WithGCD(useAXI4=false, useBlackBox=false) ++ // Use GCD Chisel, connect Tilelink
new WithBootROM ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include end: PWMRocketConfig
// DOC include end: GCDTLRocketConfig
class PWMAXI4RocketConfig extends Config(
new WithPWMAXI4Top ++ // use top with axi4-controlled PWM
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
class GCDRocketConfig extends Config( // add MMIO GCD module
new WithGCDTop ++
new WithBootROM ++
// DOC include start: GCDAXI4BlackBoxRocketConfig
class GCDAXI4BlackBoxRocketConfig extends Config(
new WithTSI ++
new WithUART ++
new WithNoGPIO ++
new WithGCD(useAXI4=true, useBlackBox=true) ++ // Use GCD blackboxed verilog, connect by AXI4->Tilelink
new WithBootROM ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include end: GCDAXI4BlackBoxRocketConfig
class SimBlockDeviceRocketConfig extends Config(
new WithTSI ++
new WithNoGPIO ++
new testchipip.WithBlockDevice ++ // add block-device module to peripherybus
new WithSimBlockDeviceTop ++ // use top with block-device IOs and connect to simblockdevice
new WithSimBlockDevice ++ // use top with block-device IOs and connect to simblockdevice
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
class BlockDeviceModelRocketConfig extends Config(
new WithTSI ++
new WithNoGPIO ++
new testchipip.WithBlockDevice ++ // add block-device module to periphery bus
new WithBlockDeviceModelTop ++ // use top with block-device IOs and connect to a blockdevicemodel
new WithBlockDeviceModel ++ // use top with block-device IOs and connect to a blockdevicemodel
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include start: GPIORocketConfig
class GPIORocketConfig extends Config(
new WithTSI ++
new WithGPIO ++ // add GPIOs to the peripherybus
new WithGPIOTop ++ // use top with GPIOs
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include end: GPIORocketConfig
class DualCoreRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithBootROM ++
new WithUART ++
new WithNoGPIO ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(2) ++ // dual-core (2 RocketTiles)
new freechips.rocketchip.system.BaseConfig)
class RV32RocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithRV32 ++ // set RocketTiles to be 32-bit
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
class GB1MemoryRocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithExtMemSize((1<<30) * 1L) ++ // use 2GB simulated external memory
new freechips.rocketchip.subsystem.WithExtMemSize((1<<30) * 1L) ++ // use 1GB simulated external memory
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include start: Sha3Rocket
class Sha3RocketConfig extends Config(
new WithTop ++
new WithTSI ++
new WithNoGPIO ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new sha3.WithSha3Accel ++ // add SHA3 rocc accelerator
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
@@ -160,20 +202,27 @@ class Sha3RocketConfig extends Config(
// DOC include start: InitZeroRocketConfig
class InitZeroRocketConfig extends Config(
new WithInitZero(0x88000000L, 0x1000L) ++
new WithInitZeroTop ++
new WithInitZero(0x88000000L, 0x1000L) ++ // add InitZero
new WithNoGPIO ++
new WithTSI ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include end: InitZeroRocketConfig
class LoopbackNICRocketConfig extends Config(
new WithTSI ++
new WithIceNIC ++
new WithLoopbackNICTop ++
new WithNoGPIO ++
new WithLoopbackNIC ++
new WithBootROM ++
new WithUART ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)

View File

@@ -10,12 +10,22 @@ import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.util.GeneratorApp
import freechips.rocketchip.devices.debug.{Debug}
/**
* TODO: Why do we need this?
*/
import ConfigValName._
// -------------------------------
// BOOM and/or Rocket Test Harness
// -------------------------------
case object BuildTop extends Field[(Clock, Bool, Parameters) => TopModule[Top]]
case object BuildTopWithDTM extends Field[(Clock, Bool, Parameters) => TopWithDTMModule[TopWithDTM]]
case object BuildTop extends Field[(Clock, Bool, Parameters, Bool) => TopModule[Top]](
(clock: Clock, reset: Bool, p: Parameters, success: Bool) => {
val top = Module(LazyModule(new Top()(p)).suggestName("top").module)
top.debug.map { debug => debug := DontCare }
top
}
)
/**
* Test harness using TSI to bringup the system
@@ -25,48 +35,8 @@ class TestHarness(implicit val p: Parameters) extends Module {
val success = Output(Bool())
})
// force Chisel to rename module
override def desiredName = "TestHarness"
val dut = p(BuildTop)(clock, reset.toBool, p)
dut.debug.foreach(_ := DontCare)
dut.connectSimAXIMem()
dut.connectSimAXIMMIO()
dut.dontTouchPorts()
dut.tieOffInterrupts()
dut.l2_frontend_bus_axi4.foreach(axi => {
axi.tieoff()
experimental.DataMirror.directionOf(axi.ar.ready) match {
case core.ActualDirection.Input =>
axi.r.bits := DontCare
axi.b.bits := DontCare
case core.ActualDirection.Output =>
axi.aw.bits := DontCare
axi.ar.bits := DontCare
axi.w.bits := DontCare
}
})
val dut = p(BuildTop)(clock, reset.toBool, p, io.success)
dut.connectSimUARTs()
io.success := dut.connectSimSerial()
}
/**
* Test harness using the Debug Test Module (DTM) to bringup the system
*/
class TestHarnessWithDTM(implicit p: Parameters) extends Module
{
val io = IO(new Bundle {
val success = Output(Bool())
})
// force Chisel to rename module
override def desiredName = "TestHarness"
val dut = p(BuildTopWithDTM)(clock, reset.toBool, p)
dut.reset := reset.asBool | dut.debug.get.ndreset
dut.connectSimAXIMem()
dut.connectSimAXIMMIO()
dut.dontTouchPorts()
@@ -84,5 +54,4 @@ class TestHarnessWithDTM(implicit p: Parameters) extends Module
}
})
Debug.connectDebug(dut.debug, dut.psd, clock, reset.asBool, io.success)
}

View File

@@ -15,103 +15,33 @@ import utilities.{System, SystemModule}
import sifive.blocks.devices.gpio._
import sifive.blocks.devices.uart._
import icenet.{HasPeripheryIceNIC, HasPeripheryIceNICModuleImp}
import icenet.{CanHavePeripheryIceNIC, CanHavePeripheryIceNICModuleImp}
// ------------------------------------
// BOOM and/or Rocket Top Level Systems
// ------------------------------------
// DOC include start: Top
class Top(implicit p: Parameters) extends System
with HasNoDebug
with HasPeripherySerial
with CanHavePeripheryUARTWithAdapter {
with CanHavePeripheryUARTAdapter // Enables optionally adding the UART print adapter
with HasPeripheryUART // Enables optionally adding the sifive UART
with HasPeripheryGPIO // Enables optionally adding the sifive GPIOs
with CanHavePeripheryBlockDevice // Enables optionally adding the block device
with CanHavePeripheryInitZero // Enables optionally adding the initzero example widget
with CanHavePeripheryGCD // Enables optionally adding the GCD example widget
with CanHavePeripherySerial // Enables optionally adding the TSI serial-adapter and port
with CanHavePeripheryIceNIC // Enables optionally adding the IceNIC for firesim
{
override lazy val module = new TopModule(this)
}
class TopModule[+L <: Top](l: L) extends SystemModule(l)
with HasNoDebugModuleImp
with HasPeripherySerialModuleImp
with CanHavePeripheryUARTWithAdapterImp
with DontTouch
//---------------------------------------------------------------------------------------------------------
// DOC include start: TopWithPWMTL
class TopWithPWMTL(implicit p: Parameters) extends Top
with HasPeripheryPWMTL {
override lazy val module = new TopWithPWMTLModule(this)
}
class TopWithPWMTLModule(l: TopWithPWMTL) extends TopModule(l)
with HasPeripheryPWMTLModuleImp
// DOC include end: TopWithPWMTL
//---------------------------------------------------------------------------------------------------------
class TopWithPWMAXI4(implicit p: Parameters) extends Top
with HasPeripheryPWMAXI4 {
override lazy val module = new TopWithPWMAXI4Module(this)
}
class TopWithPWMAXI4Module(l: TopWithPWMAXI4) extends TopModule(l)
with HasPeripheryPWMAXI4ModuleImp
//---------------------------------------------------------------------------------------------------------
class TopWithGCD(implicit p: Parameters) extends Top
with HasPeripheryGCD {
override lazy val module = new TopWithGCDModule(this)
}
class TopWithGCDModule(l: TopWithGCD) extends TopModule(l)
with HasPeripheryGCDModuleImp
//---------------------------------------------------------------------------------------------------------
class TopWithBlockDevice(implicit p: Parameters) extends Top
with HasPeripheryBlockDevice {
override lazy val module = new TopWithBlockDeviceModule(this)
}
class TopWithBlockDeviceModule(l: TopWithBlockDevice) extends TopModule(l)
with HasPeripheryBlockDeviceModuleImp
//---------------------------------------------------------------------------------------------------------
class TopWithGPIO(implicit p: Parameters) extends Top
with HasPeripheryGPIO {
override lazy val module = new TopWithGPIOModule(this)
}
class TopWithGPIOModule(l: TopWithGPIO)
extends TopModule(l)
with HasPeripheryGPIOModuleImp
//---------------------------------------------------------------------------------------------------------
class TopWithDTM(implicit p: Parameters) extends System
{
override lazy val module = new TopWithDTMModule(this)
}
class TopWithDTMModule[+L <: TopWithDTM](l: L) extends SystemModule(l)
//---------------------------------------------------------------------------------------------------------
// DOC include start: TopWithInitZero
class TopWithInitZero(implicit p: Parameters) extends Top
with HasPeripheryInitZero {
override lazy val module = new TopWithInitZeroModuleImp(this)
}
class TopWithInitZeroModuleImp(l: TopWithInitZero) extends TopModule(l)
with HasPeripheryInitZeroModuleImp
// DOC include end: TopWithInitZero
class TopWithIceNIC(implicit p: Parameters) extends Top
with HasPeripheryIceNIC {
override lazy val module = new TopWithIceNICModule(this)
}
class TopWithIceNICModule(outer: TopWithIceNIC)
extends TopModule(outer)
with HasPeripheryIceNICModuleImp
with HasPeripheryUARTModuleImp
with CanHavePeripheryBlockDeviceModuleImp
with CanHavePeripheryGCDModuleImp
with CanHavePeripherySerialModuleImp
with CanHavePeripheryIceNICModuleImp
with CanHavePeripheryUARTAdapterModuleImp
with DontTouch
// DOC include end: Top

View File

@@ -10,7 +10,7 @@ import freechips.rocketchip.devices.debug.HasPeripheryDebugModuleImp
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPortModuleImp}
import sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
import testchipip.{HasPeripherySerialModuleImp, HasPeripheryBlockDeviceModuleImp}
import testchipip.{CanHavePeripherySerialModuleImp, CanHavePeripheryBlockDeviceModuleImp}
import icenet.HasPeripheryIceNICModuleImpValidOnly
import junctions.{NastiKey, NastiParameters}
@@ -32,19 +32,19 @@ class WithTiedOffDebug extends RegisterBridgeBinder({ case target: HasPeripheryD
})
class WithSerialBridge extends RegisterBridgeBinder({
case target: HasPeripherySerialModuleImp => Seq(SerialBridge(target.serial)(target.p))
case target: CanHavePeripherySerialModuleImp => Seq(SerialBridge(target.serial.get)(target.p))
})
class WithNICBridge extends RegisterBridgeBinder({
case target: HasPeripheryIceNICModuleImpValidOnly => Seq(NICBridge(target.net)(target.p))
case target: HasPeripheryIceNICModuleImpValidOnly => Seq(NICBridge(target.net)(target.p))
})
class WithUARTBridge extends RegisterBridgeBinder({
case target: HasPeripheryUARTModuleImp => target.uart.map(u => UARTBridge(u)(target.p))
case target: HasPeripheryUARTModuleImp => target.uart.map(u => UARTBridge(u)(target.p))
})
class WithBlockDeviceBridge extends RegisterBridgeBinder({
case target: HasPeripheryBlockDeviceModuleImp => Seq(BlockDevBridge(target.bdev, target.reset.toBool)(target.p))
case target: CanHavePeripheryBlockDeviceModuleImp => Seq(BlockDevBridge(target.bdev.get, target.reset.toBool)(target.p))
})
class WithFASEDBridge extends RegisterBridgeBinder({

View File

@@ -12,7 +12,7 @@ import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.tilelink.BootROMParams
import freechips.rocketchip.devices.debug.{DebugModuleParams, DebugModuleKey}
import boom.common.BoomTilesKey
import testchipip.{BlockDeviceKey, BlockDeviceConfig}
import testchipip.{BlockDeviceKey, BlockDeviceConfig, SerialKey}
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
import scala.math.{min, max}
import tracegen.TraceGenKey
@@ -47,13 +47,17 @@ class WithUARTKey extends Config((site, here, up) => {
nRxEntries = 256))
})
class WithSerial extends Config((site, here, up) => {
case SerialKey => true
})
class WithBlockDevice extends Config(new testchipip.WithBlockDevice)
class WithNICKey extends Config((site, here, up) => {
case NICKey => NICConfig(
case NICKey => Some(NICConfig(
inBufFlits = 8192,
ctrlQueueDepth = 64,
checksumOffload = true)
checksumOffload = true))
})
class WithRocketL2TLBs(entries: Int) extends Config((site, here, up) => {
@@ -112,6 +116,7 @@ class FireSimRocketChipConfig extends Config(
new WithoutTLMonitors ++
new WithUARTKey ++
new WithNICKey ++
new WithSerial ++
new WithBlockDevice ++
new WithRocketL2TLBs(1024) ++
new WithPerfCounters ++
@@ -169,6 +174,7 @@ class FireSimBoomConfig extends Config(
new WithoutTLMonitors ++
new WithUARTKey ++
new WithNICKey ++
new WithSerial ++
new WithBlockDevice ++
new WithBoomL2TLBs(1024) ++
new WithoutClockGating ++

View File

@@ -42,10 +42,10 @@ class FireSimDUT(implicit p: Parameters) extends Subsystem
with HasHierarchicalBusTopology
with CanHaveMasterAXI4MemPort
with HasPeripheryBootROM
with HasPeripherySerial
with CanHavePeripherySerial
with HasPeripheryUART
with HasPeripheryIceNIC
with HasPeripheryBlockDevice
with CanHavePeripheryIceNIC
with CanHavePeripheryBlockDevice
with HasTraceIO
{
override lazy val module = new FireSimModuleImp(this)
@@ -55,10 +55,10 @@ class FireSimModuleImp[+L <: FireSimDUT](l: L) extends SubsystemModuleImp(l)
with HasRTCModuleImp
with CanHaveMasterAXI4MemPortModuleImp
with HasPeripheryBootROMModuleImp
with HasPeripherySerialModuleImp
with CanHavePeripherySerialModuleImp
with HasPeripheryUARTModuleImp
with HasPeripheryIceNICModuleImpValidOnly
with HasPeripheryBlockDeviceModuleImp
with CanHavePeripheryBlockDeviceModuleImp
with HasTraceIOImp
with CanHaveMultiCycleRegfileImp
@@ -68,9 +68,9 @@ class FireSimNoNICDUT(implicit p: Parameters) extends Subsystem
with HasHierarchicalBusTopology
with CanHaveMasterAXI4MemPort
with HasPeripheryBootROM
with HasPeripherySerial
with CanHavePeripherySerial
with HasPeripheryUART
with HasPeripheryBlockDevice
with CanHavePeripheryBlockDevice
with HasTraceIO
{
override lazy val module = new FireSimNoNICModuleImp(this)
@@ -80,9 +80,9 @@ class FireSimNoNICModuleImp[+L <: FireSimNoNICDUT](l: L) extends SubsystemModule
with HasRTCModuleImp
with CanHaveMasterAXI4MemPortModuleImp
with HasPeripheryBootROMModuleImp
with HasPeripherySerialModuleImp
with CanHavePeripherySerialModuleImp
with HasPeripheryUARTModuleImp
with HasPeripheryBlockDeviceModuleImp
with CanHavePeripheryBlockDeviceModuleImp
with HasTraceIOImp
with CanHaveMultiCycleRegfileImp
@@ -107,12 +107,11 @@ class FireSimSupernode(implicit p: Parameters) extends DefaultFireSimHarness(()
// Verilog blackbox integration demo
class FireSimVerilogGCDDUT(implicit p: Parameters) extends FireSimDUT
with example.HasPeripheryGCD
with example.CanHavePeripheryGCD
{
override lazy val module = new FireSimVerilogGCDModuleImp(this)
}
class FireSimVerilogGCDModuleImp[+L <: FireSimVerilogGCDDUT](l: L) extends FireSimModuleImp(l)
with example.HasPeripheryGCDModuleImp
class FireSimVerilogGCD(implicit p: Parameters) extends DefaultFireSimHarness(() => new FireSimVerilogGCDDUT)