renamed Advanced section | move Top-Testharness to Advanced [ci skip]
This commit is contained in:
168
docs/Advanced-Concepts/Chip-Communication.rst
Normal file
168
docs/Advanced-Concepts/Chip-Communication.rst
Normal file
@@ -0,0 +1,168 @@
|
||||
.. _chip-communication:
|
||||
|
||||
Communicating with the DUT
|
||||
===============================
|
||||
|
||||
There are two types of DUTs that can be made: `tethered` or `standalone` DUTs.
|
||||
A `tethered` DUT is where a host computer (or just host) must send transactions to the DUT to bringup a program.
|
||||
This differs from a `standalone` DUT that can bringup itself (has its own bootrom, loads programs itself, etc).
|
||||
An example of a tethered DUT is a Chipyard simulation where the host loads the test program into the DUTs memory and signals to the DUT that the program is ready to run.
|
||||
An example of a standalone DUT is a Chipyard simulation where a program can be loaded from an SDCard by default.
|
||||
In this section, we mainly describe how to communicate to tethered DUTs.
|
||||
|
||||
There are two ways the host (otherwise known as the outside world) can communicate with a tethered Chipyard DUT:
|
||||
|
||||
* Using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI) with the Front-End Server (FESVR) to communicate with the DUT
|
||||
* Using the JTAG interface with OpenOCD and GDB to communicate with the DUT
|
||||
|
||||
The following picture shows a block diagram view of all the supported communication mechanisms
|
||||
split between the host and the simulation.
|
||||
|
||||
.. image:: ../_static/images/chip-communication.png
|
||||
|
||||
Using the Tethered Serial Interface (TSI) or the Debug Module Interface (DMI)
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
If you are using TSI or DMI to communicate with the DUT, you are using
|
||||
the Front-End Server (FESVR) to facilitate communication between the host and the DUT.
|
||||
|
||||
Primer on the Front-End Server (FESVR)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
FESVR is a C++ library that manages communication
|
||||
between a host machine and a RISC-V DUT. For debugging, it provides a simple API to reset,
|
||||
send messages, and load/run programs on a DUT. It also emulates peripheral devices.
|
||||
It can be incorporated with simulators (VCS, Verilator, FireSim), or used in a bringup sequence
|
||||
for a taped out chip.
|
||||
|
||||
Specifically, FESVR uses the Host Target Interface (HTIF), a communication protocol,
|
||||
to speak with the DUT. HTIF is a non-standard Berkeley protocol that uses a FIFO non-blocking
|
||||
interface to communicate with the DUT. It defines a protocol where you can read/write memory,
|
||||
load/start/stop the program, and more. Both TSI and DMI implement this HTIF protocol differently
|
||||
in order to communicate with the DUT.
|
||||
|
||||
Using the Tethered Serial Interface (TSI)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the DUT.
|
||||
TSI protocol is an implementation of HTIF that is used to send commands to the
|
||||
RISC-V DUT. These TSI commands are simple R/W commands
|
||||
that are able to probe the DUT's memory space. During simulation, the host sends TSI commands to a
|
||||
simulation stub called ``SimSerial`` (C++ class) that resides in a ``SimSerial`` verilog module
|
||||
(both are located in the ``generators/testchipip`` project). This ``SimSerial`` verilog module then
|
||||
sends the TSI command recieved by the simulation stub into the DUT which then converts the TSI
|
||||
command into a TileLink request. This conversion is done by the ``SerialAdapter`` module
|
||||
(located in the ``generators/testchipip`` project). In simulation, FESVR
|
||||
resets the DUT, writes into memory the test program, and indicates to the DUT to start the program
|
||||
through an interrupt (see :ref:`Chipyard Boot Process`). Using TSI is currently the fastest
|
||||
mechanism to communicate with the DUT in simulation.
|
||||
|
||||
In the case of a chip tapeout bringup, TSI commands can be sent over a custom communication
|
||||
medium to communicate with the chip. For example, some Berkeley tapeouts have a FPGA
|
||||
with a RISC-V soft-core that runs FESVR. The FESVR on the soft-core sends TSI commands
|
||||
to a TSI-to-TileLink converter living on the FPGA (i.e. ``SerialAdapter``). Then this converter
|
||||
sends the converted TileLink commands over a serial link to the chip. The following image shows this flow:
|
||||
|
||||
.. image:: ../_static/images/chip-bringup.png
|
||||
|
||||
Using the Debug Module Interface (DMI)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Another option to interface with the DUT is to use the Debug Module Interface (DMI).
|
||||
Similar to TSI, the DMI protocol is an implementation of HTIF.
|
||||
In order to communicate with the DUT with the DMI protocol, the DUT needs to contain a Debug Transfer Module (DTM).
|
||||
The DTM is given in the `RISC-V Debug Specification <https://riscv.org/specifications/debug-specification/>`__
|
||||
and is responsible for managing communication between the DUT and whatever lives on the other side of the DMI (in this case FESVR).
|
||||
This is implemented in the Rocket Chip ``Subsystem`` by having the ``HasPeripheryDebug`` and ``HasPeripheryDebugModuleImp`` mixins.
|
||||
During simulation, the host sends DMI commands to a
|
||||
simulation stub called ``SimDTM`` (C++ class) that resides in a ``SimDTM`` verilog module
|
||||
(both are located in the ``generators/rocket-chip`` project). This ``SimDTM`` verilog module then
|
||||
sends the DMI command recieved by the simulation stub into the DUT which then converts the DMI
|
||||
command into a TileLink request. This conversion is done by the DTM named ``DebugModule`` in the ``generators/rocket-chip`` project.
|
||||
When the DTM receives the program to load, it starts to write the binary byte-wise into memory.
|
||||
This is considerably slower than the TSI protocol communication pipeline (i.e. ``SimSerial``/``SerialAdapter``/TileLink)
|
||||
which directly writes the program binary to memory.
|
||||
Thus, Chipyard removes the DTM by default in favor of the TSI protocol for DUT communication.
|
||||
|
||||
Starting the TSI or DMI Simulation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All default Chipyard configurations use TSI to communicate between the simulation and the simulated SoC/DUT. Hence, when running a
|
||||
software RTL simulation, as is indicated in the :ref:`Software RTL Simulation` section, you are in-fact using TSI to communicate with the DUT. As a
|
||||
reminder, to run a software RTL simulation, run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd sims/verilator
|
||||
# or
|
||||
cd sims/vcs
|
||||
|
||||
make CONFIG=LargeBoomConfig run-asm-tests
|
||||
|
||||
FireSim FPGA-accelerated simulations use TSI by default as well.
|
||||
|
||||
If you would like to build and simulate a Chipyard configuration with a DTM configured for DMI communication, then you must create a
|
||||
top-level system with the DTM (``TopWithDTM``), a test-harness to connect to the DTM (``TestHarnessWithDTM``), as well as a config to use that top-level system.
|
||||
|
||||
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: DmiRocket
|
||||
:end-before: DOC include end: DmiRocket
|
||||
|
||||
In this example, the ``WithDTMTop`` mixin specifies that the top-level SoC will instantiate a DTM (that by default is setup to use DMI).
|
||||
The rest of the mixins specify the rest of the system (cores, accelerators, etc).
|
||||
Then you can run simulations with the new DMI-enabled top-level and test-harness.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd sims/verilator
|
||||
# or
|
||||
cd sims/vcs
|
||||
|
||||
make CONFIG=dmiRocketConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM run-asm-tests
|
||||
|
||||
Using the JTAG Interface
|
||||
------------------------
|
||||
|
||||
The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Transfer Module (DTM)
|
||||
and configure it to use a JTAG interface (by default the DTM is setup to use the DMI interface mentioned above).
|
||||
|
||||
Creating a DTM+JTAG Config
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
First, a DTM config must be created for the system that you want to create.
|
||||
This step is similar to the DMI simulation section within the :ref:`Starting the TSI or DMI Simulation` section.
|
||||
First, you must make a top-level system (``TopWithDTM``) and test-harness (``TestHarnessWithDTM``) that instantiates
|
||||
and connects the DTM correctly. The configuration is very similar to a DMI-based configuration. The main difference
|
||||
is the addition of the ``WithJtagDTM`` mixin that configures the instantiated DTM to use the JTAG protocol as the
|
||||
bringup method.
|
||||
|
||||
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: JtagRocket
|
||||
:end-before: DOC include end: JtagRocket
|
||||
|
||||
Building a DTM+JTAG Simulator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After creating the config, call the ``make`` command like the following to build a simulator for your RTL:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd sims/verilator
|
||||
# or
|
||||
cd sims/vcs
|
||||
|
||||
make CONFIG=jtagRocketConfig TOP=TopWithDTM MODEL=TestHarnessWithDTM
|
||||
|
||||
In this example, the simulation will use the config that you previously specified, as well as set
|
||||
the other parameters that are needed to satisfy the build system. After that point, you
|
||||
should have a JTAG enabled simulator that you can attach to using OpenOCD and GDB!
|
||||
|
||||
Debugging with JTAG
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Please refer to the following resources on how to debug with JTAG.
|
||||
|
||||
* https://github.com/chipsalliance/rocket-chip#-debugging-with-gdb
|
||||
* https://github.com/riscv/riscv-isa-sim#debugging-with-gdb
|
||||
39
docs/Advanced-Concepts/Resources.rst
Normal file
39
docs/Advanced-Concepts/Resources.rst
Normal file
@@ -0,0 +1,39 @@
|
||||
Accessing Scala Resources
|
||||
===============================
|
||||
|
||||
A simple way to copy over a source file to the build directory to be used for a simulation compile or VLSI flow is to use the ``addResource`` function given by FIRRTL.
|
||||
An example of its use can be seen in `generators/testchipip/src/main/scala/SerialAdapter.scala <https://github.com/ucb-bar/testchipip/blob/master/src/main/scala/SerialAdapter.scala>`_.
|
||||
Here is the example inlined:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
class SimSerial(w: Int) extends BlackBox with HasBlackBoxResource {
|
||||
val io = IO(new Bundle {
|
||||
val clock = Input(Clock())
|
||||
val reset = Input(Bool())
|
||||
val serial = Flipped(new SerialIO(w))
|
||||
val exit = Output(Bool())
|
||||
})
|
||||
|
||||
addResource("/testchipip/vsrc/SimSerial.v")
|
||||
addResource("/testchipip/csrc/SimSerial.cc")
|
||||
}
|
||||
|
||||
In this example, the ``SimSerial`` files will be copied from a specific folder (in this case the ``path/to/testchipip/src/main/resources/testchipip/...``) to the build folder.
|
||||
The ``addResource`` path retrieves resources from the ``src/main/resources`` directory.
|
||||
So to get an item at ``src/main/resources/fileA.v`` you can use ``addResource("/fileA.v")``.
|
||||
However, one caveat of this approach is that to retrieve the file during the FIRRTL compile, you must have that project in the FIRRTL compiler's classpath.
|
||||
Thus, you need to add the SBT project as a dependency to the FIRRTL compiler in the Chipyard ``build.sbt``, which in Chipyards case is the ``tapeout`` project.
|
||||
For example, you added a new project called ``myAwesomeAccel`` in the Chipyard ``build.sbt``.
|
||||
Then you can add it as a ``dependsOn`` dependency to the ``tapeout`` project.
|
||||
For example:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
lazy val myAwesomeAccel = (project in file("generators/myAwesomeAccelFolder"))
|
||||
.dependsOn(rocketchip)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val tapeout = conditionalDependsOn(project in file("./tools/barstools/tapeout/"))
|
||||
.dependsOn(myAwesomeAccel)
|
||||
.settings(commonSettings)
|
||||
90
docs/Advanced-Concepts/Top-Testharness.rst
Normal file
90
docs/Advanced-Concepts/Top-Testharness.rst
Normal file
@@ -0,0 +1,90 @@
|
||||
Tops, Test-Harnesses, and the Test-Driver
|
||||
====================================
|
||||
|
||||
The three highest levels of hierarchy in a Chipyard
|
||||
SoC are the Top (DUT), ``TestHarness``, and the ``TestDriver``.
|
||||
The Top and ``TestHarness`` are both emitted by Chisel generators.
|
||||
The ``TestDriver`` serves as our testbench, and is a verilog
|
||||
file in Rocket Chip.
|
||||
|
||||
|
||||
Top/DUT
|
||||
-------------------------
|
||||
|
||||
The top-level module of a Rocket Chip SoC is composed via cake-pattern.
|
||||
Specifically, "Tops" extend a ``System``, which extends a ``Subsystem``, which extends a ``BaseSubsystem``.
|
||||
|
||||
|
||||
BaseSubsystem
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``BaseSubsystem`` is defined in ``generators/rocketchip/src/main/scala/subsystem/BaseSubsystem.scala``.
|
||||
Looking at the ``BaseSubsystem`` abstract class, we see that this class instantiates the top-level buses
|
||||
(frontbus, systembus, peripherybus, etc.), but does not specify a topology.
|
||||
We also see this class define several ``ElaborationArtefacts``, files emitted after Chisel elaboration
|
||||
(e.g. the device tree string, and the diplomacy graph visualization GraphML file).
|
||||
|
||||
Subsystem
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Looking in `generators/utilities/src/main/scala/Subsystem.scala <https://github.com/ucb-bar/chipyard/blob/master/generators/utilities/src/main/scala/Subsystem.scala>`__, we can see how Chipyard's ``Subsystem``
|
||||
extends the ``BaseSubsystem`` abstract class. ``Subsystem`` mixes in the ``HasBoomAndRocketTiles`` trait that
|
||||
defines and instantiates BOOM or Rocket tiles, depending on the parameters specified.
|
||||
We also connect some basic IOs for each tile here, specifically the hartids and the reset vector.
|
||||
|
||||
System
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``generators/utilities/src/main/scala/System.scala`` completes the definition of the ``System``.
|
||||
|
||||
- ``HasHierarchicalBusTopology`` is defined in Rocket Chip, and specifies connections between the top-level buses
|
||||
- ``HasAsyncExtInterrupts`` and ``HasExtInterruptsModuleImp`` adds IOs for external interrupts and wires them appropriately to tiles
|
||||
- ``CanHave...AXI4Port`` adds various Master and Slave AXI4 ports, adds TL-to-AXI4 converters, and connects them to the appropriate buses
|
||||
- ``HasPeripheryBootROM`` adds a BootROM device
|
||||
|
||||
Tops
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A SoC Top then extends the ``System`` class with any config-specific components. There are two "classes" of Tops in Chipyard that enable different bringup methods.
|
||||
Please refer to :ref:`Communicating with the DUT` for more information on these bringup methods.
|
||||
|
||||
- ``Top`` is the default setup. These top modules instantiate a serial module which interfaces with the ``TestHarness``. In addition, the Debug Transfer Module (DTM) is removed and replaced with a TSI-based bringup flow. All other example "Tops" (except the ``TopWithDTM``) extend this Top as the "base" top-level system.
|
||||
- ``TopWithDTM`` does not include the TSI-based bringup flow. Instead it keeps the Debug Transfer Module (DTM) within the design so that you can use a DMI-based or JTAG-based bringup.
|
||||
|
||||
For a custom Top a mixed-in trait adds the additional modules or IOs (an example of this is ``TopWithGPIO``).
|
||||
|
||||
TestHarness
|
||||
-------------------------
|
||||
|
||||
There are two variants of ``TestHarness`` generators in Chipyard, both located in
|
||||
`generators/example/src/main/scala/TestHarness.scala <https://github.com/ucb-bar/chipyard/blob/master/generators/example/src/main/scala/TestHarness.scala>`__.
|
||||
One is designed for TSI-based bringup, while the other performs DTM-based bringup.
|
||||
See :ref:`Communicating with the DUT` for more information on these two methodologies.
|
||||
|
||||
The wiring between the ``TestHarness`` and the Top are performed in methods defined in mixins added to the Top.
|
||||
When these methods are called from the ``TestHarness``, they may instantiate modules within the scope of the harness,
|
||||
and then connect them to the DUT. For example, the ``connectSimAXIMem`` method defined in the
|
||||
``CanHaveMasterAXI4MemPortModuleImp`` trait, when called from the ``TestHarness``, will instantiate ``SimAXIMem``s
|
||||
and connect them to the correct IOs of the top.
|
||||
|
||||
While this roundabout way of attaching to the IOs of the top may seem to be unnecessarily complex, it allows the designer to compose
|
||||
custom traits together without having to worry about the details of the implementation of any particular trait.
|
||||
|
||||
Specifying a Top
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To see why the Top connection method is useful, consider the case where we want to use a custom Top with additional GPIO pins.
|
||||
In `generators/example/src/main/scala/Top.scala <https://github.com/ucb-bar/chipyard/blob/master/generators/example/src/main/scala/Top.scala>`__,
|
||||
we can see how the ``TopWithGPIO`` class adds the ``HasPeripheryGPIO`` trait. This trait adds IOs to the Top module,
|
||||
instantiates a TileLink GPIO node, and connects it to the proper buses.
|
||||
|
||||
If we look at the ``WithGPIOTop`` mixin in the ``ConfigMixins.scala`` file, we see that adding this mixin to the top-level Config overrides the
|
||||
``BuildTop`` key with a custom function that both instantiates the custom Top, and drives all the GPIO pins.
|
||||
When the ``TestHarness`` looksup the ``BuildTop`` key, this function will run and perform this wiring, and then return the Top module.
|
||||
|
||||
TestDriver
|
||||
-------------------------
|
||||
|
||||
The ``TestDriver`` is defined in ``generators/rocketchip/src/main/resources/vsrc/TestDriver.v``.
|
||||
This verilog file executes a simulation by instantiating the ``TestHarness``, driving the clock and reset signals, and interpreting the success output.
|
||||
This file is compiled with the generated verilog for the ``TestHarness`` and the Top to produce a simulator.
|
||||
13
docs/Advanced-Concepts/index.rst
Normal file
13
docs/Advanced-Concepts/index.rst
Normal file
@@ -0,0 +1,13 @@
|
||||
Advanced Concepts
|
||||
================================
|
||||
|
||||
The following sections are advanced topics about how to Chipyard works, how to use Chipyard, and special features of the framework.
|
||||
They expect you to know about Chisel, Parameters, Configs, etc.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Advanced Concepts:
|
||||
|
||||
Top-Testharness
|
||||
Chip-Communication
|
||||
Resources
|
||||
Reference in New Issue
Block a user