renamed Advanced section | move Top-Testharness to Advanced [ci skip]

This commit is contained in:
abejgonzalez
2019-09-28 14:14:41 -07:00
parent be55af17e1
commit 5a825d77c4
8 changed files with 104 additions and 81 deletions

View 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

View 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)

View 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.

View 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