Merge pull request #1774 from ucb-bar/mmio-docs
Update MMIO peripheral docs
This commit is contained in:
@@ -99,10 +99,16 @@ Instantiating the BlackBox and Defining MMIO
|
||||
|
||||
Next, we must instantiate the blackbox. In order to take advantage of
|
||||
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 GCD device example.
|
||||
integrate the peripheral at the Chisel level by instantiating a LazyModule wrapper
|
||||
that instantiates a TileLink RegisterNode.
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/GCD.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: GCD router
|
||||
:end-before: DOC include end: GCD router
|
||||
|
||||
Within the LazyModule, the ``regmap`` function can be called to attach wires and
|
||||
registers to the MMIO port.
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/GCD.scala
|
||||
:language: scala
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
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/chipyard/src/main/scala/example/GCD.scala`` for how an example AXI4 based peripheral is defined and connected to the Tilelink graph through converters.
|
||||
The easiest way to create a MMIO peripheral is to follow the GCD TileLink MMIO example. 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/chipyard/src/main/scala/example/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.
|
||||
To create a MMIO-mapped peripheral, you will need to specify a ``LazyModule`` wrapper containing the TileLink port as a Diplomacy Node, as well as an internal ``LazyModuleImp`` class that defines the MMIO's implementation and any non-TileLink I/O.
|
||||
|
||||
For this example, we will show how to connect a MMIO peripheral which computes the GCD.
|
||||
The full code can be found in ``generators/chipyard/src/main/scala/example/GCD.scala``.
|
||||
@@ -70,17 +70,14 @@ Top-level Traits
|
||||
----------------
|
||||
|
||||
After creating the module, we need to hook it up to our SoC.
|
||||
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 relevant bus.
|
||||
The ``LazyModule`` abstract class containst the TileLink node representing the peripheral's I/O.
|
||||
For a simple memory-mapped peripheral, connecting the peripheral's TileLink node must be connected to the relevant bu.
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/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.
|
||||
|
||||
Peripherals which expose I/O can use `InModuleBody` to punch their I/O to the `DigitalTop` module.
|
||||
|
||||
@@ -134,7 +134,7 @@ to handle TileLink requests, it is usually much easier to use a register node.
|
||||
This type of node provides a ``regmap`` method that allows you to specify
|
||||
control/status registers and automatically generates the logic to handle the
|
||||
TileLink protocol. More information about how to use register nodes can be
|
||||
found in :ref:`TileLink-Diplomacy-Reference/Register-Router:Register Router`.
|
||||
found in :ref:`TileLink-Diplomacy-Reference/Register-Node:Register Node`.
|
||||
|
||||
Identity Node
|
||||
-------------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Register Router
|
||||
Register Node
|
||||
===============
|
||||
|
||||
Memory-mapped devices generally follow a common pattern. They expose a set
|
||||
@@ -10,10 +10,7 @@ While designers can manually instantiate a manager node and write the logic
|
||||
for exposing registers themselves, it's much easier to use RocketChip's
|
||||
``regmap`` interface, which can generate most of the glue logic.
|
||||
|
||||
For TileLink devices, you can use the ``regmap`` interface by extending
|
||||
the ``TLRegisterRouter`` class, as shown in :ref:`mmio-accelerators`,
|
||||
or you can create a regular LazyModule and instantiate a ``TLRegisterNode``.
|
||||
This section will focus on the second method.
|
||||
For TileLink devices, you can use the ``regmap`` interface of the ``TLRegisterNode``.
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
@@ -32,7 +29,7 @@ The default value is 4 bytes. The ``concurrency`` argument is the size of the
|
||||
internal queue for TileLink requests. By default, this value is 0, which means
|
||||
there will be no queue. This value must be greater than 0 if you wish to
|
||||
decoupled requests and responses for register accesses. This is discussed
|
||||
in :ref:`TileLink-Diplomacy-Reference/Register-Router:Using Functions`.
|
||||
in :ref:`TileLink-Diplomacy-Reference/Register-Node:Using Functions`.
|
||||
|
||||
The main way to interact with the node is to call the ``regmap`` method, which
|
||||
takes a sequence of pairs. The first element of the pair is an offset from the
|
||||
@@ -123,12 +120,12 @@ output for write.
|
||||
In order to use this variant, you need to set ``concurrency`` to a value
|
||||
larger than 0.
|
||||
|
||||
Register Routers for Other Protocols
|
||||
Register Nodes for Other Protocols
|
||||
------------------------------------
|
||||
|
||||
One useful feature of the register router interface is that you can easily
|
||||
One useful feature of the register node interface is that you can easily
|
||||
change the protocol being used. For instance, in the first example in
|
||||
:ref:`TileLink-Diplomacy-Reference/Register-Router:Basic Usage`, you could simply change the ``TLRegisterNode`` to
|
||||
:ref:`TileLink-Diplomacy-Reference/Register-Node:Basic Usage`, you could simply change the ``TLRegisterNode`` to
|
||||
and ``AXI4RegisterNode``.
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/RegisterNodeExample.scala
|
||||
@@ -28,5 +28,5 @@ A detailed specification of the TileLink 1.7 protocol can be found on the
|
||||
NodeTypes
|
||||
Diplomacy-Connectors
|
||||
EdgeFunctions
|
||||
Register-Router
|
||||
Register-Node
|
||||
Widgets
|
||||
|
||||
Reference in New Issue
Block a user