get started on documenting TileLink/Diplomacy
This commit is contained in:
38
docs/TileLink-Diplomacy-Reference/Diplomacy-Connectors.rst
Normal file
38
docs/TileLink-Diplomacy-Reference/Diplomacy-Connectors.rst
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
Diplomacy Connectors
|
||||||
|
====================
|
||||||
|
|
||||||
|
Nodes in a diplomacy graph are connected to each other with edges. The diplomacy
|
||||||
|
library provides four operators that can be used to form edges between nodes.
|
||||||
|
|
||||||
|
:=
|
||||||
|
--
|
||||||
|
|
||||||
|
This is the basic connection operator. It is the same syntax as the Chisel
|
||||||
|
uni-directional connector, but it is not equivalent. This operator connects
|
||||||
|
diplomacy node, not Chisel bundles.
|
||||||
|
|
||||||
|
The basic connection operator always creates a single edge between the two
|
||||||
|
nodes.
|
||||||
|
|
||||||
|
:=*
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a "query" type connection operator. It can create multiple edges
|
||||||
|
between nodes, with the number of edges determined by the client node
|
||||||
|
(the node on the right side of the operator). This can be useful if you
|
||||||
|
are connecting a multi-edge client to a nexus node or adapter node.
|
||||||
|
|
||||||
|
:*=
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a "star" type connection operator. It also creates multiple edges,
|
||||||
|
but the number of edges is determined by the manager (left side of operator),
|
||||||
|
rather than the client. It's useful for connecting nexus nodes to multi-edge
|
||||||
|
manager nodes.
|
||||||
|
|
||||||
|
:*=*
|
||||||
|
----
|
||||||
|
|
||||||
|
This is a "flex" connection operator. It creates multiple edges based on
|
||||||
|
whichever side of the operator has a known number of edges. This can be used
|
||||||
|
in generators where the type of node on either side isn't known until runtime.
|
||||||
158
docs/TileLink-Diplomacy-Reference/EdgeFunctions.rst
Normal file
158
docs/TileLink-Diplomacy-Reference/EdgeFunctions.rst
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
TileLink Edge Object Methods
|
||||||
|
============================
|
||||||
|
|
||||||
|
The edge object associated with a TileLink node has several helpful methods
|
||||||
|
for constructing TileLink messages and retrieving data from them.
|
||||||
|
|
||||||
|
|
||||||
|
Get
|
||||||
|
---
|
||||||
|
|
||||||
|
Constructor for a TLBundleA encoding a ``Get`` message, which requests data
|
||||||
|
from memory. The D channel response to this message will be an
|
||||||
|
``AccessAckData``, which may have multiple beats.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``fromSource: UInt`` - Source ID for this transaction
|
||||||
|
- ``toAddress: UInt`` - The address to read from
|
||||||
|
- ``lgSize: UInt`` - Base two logarithm of the number of bytes to be read
|
||||||
|
|
||||||
|
Put
|
||||||
|
---
|
||||||
|
|
||||||
|
Constructor for a TLBundleA encoding a ``PutFull`` or ``PutPartial`` message,
|
||||||
|
which write data to memory. It will be a ``PutPartial`` if the ``mask`` is
|
||||||
|
specified and a ``PutFull`` if it is omitted. The put may require multiple
|
||||||
|
beats. If that is the case, only ``data`` and ``mask`` should change for each
|
||||||
|
beat. All other fields must be the same for all beats in the transaction,
|
||||||
|
including the address. The manager will respond to this message with a single
|
||||||
|
``AccessAck``.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``fromSource: UInt`` - Source ID for this transaction.
|
||||||
|
- ``toAddress: UInt`` - The address to write to.
|
||||||
|
- ``lgSize: UInt`` - Base two logarithm of the number of bytes to be written.
|
||||||
|
- ``data: UInt`` - The data to write on this beat.
|
||||||
|
- ``mask: UInt`` - (optional) The write mask for this beat.
|
||||||
|
|
||||||
|
Arithmetic
|
||||||
|
----------
|
||||||
|
|
||||||
|
Constructor for a TLBundleA encoding an ``Arithmetic`` message, which is an
|
||||||
|
atomic operation. The possible values for the ``atomic`` field are defined
|
||||||
|
in the ``TLAtomics`` object. It can be ``MIN``, ``MAX``, ``MINU``, ``MAXU``, or
|
||||||
|
``ADD``, which correspond to atomic minimum, maximum, unsigned minimum, unsigned
|
||||||
|
maximum, or addition operations, respectively. The previous value at the
|
||||||
|
memory location will be returned in the response, which will be in the form
|
||||||
|
of an ``AccessAckData``.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``fromSource: UInt`` - Source ID for this transaction.
|
||||||
|
- ``toAddress: UInt`` - The address to perform an arithmetic operation on.
|
||||||
|
- ``lgSize: UInt`` - Base two logarithm of the number of bytes to operate on.
|
||||||
|
- ``data: UInt`` - Right-hand operand of the arithmetic operation
|
||||||
|
- ``atomic: UInt`` - Arithmetic operation type (from ``TLAtomics``)
|
||||||
|
|
||||||
|
Logical
|
||||||
|
-------
|
||||||
|
|
||||||
|
Constructor for a TLBundleA encoding a ``Logical`` message, an atomic operation.
|
||||||
|
The possible values for the ``atomic`` field are ``XOR``, ``OR``, ``AND``, and
|
||||||
|
``SWAP``, which correspond to atomic bitwise exclusive or, bitwise inclusive or,
|
||||||
|
bitwise and, and swap operations, respectively. The previous value at the
|
||||||
|
memory location will be returned in an ``AccessAckData`` response.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``fromSource: UInt`` - Source ID for this transaction.
|
||||||
|
- ``toAddress: UInt`` - The address to perform a logical operation on.
|
||||||
|
- ``lgSize: UInt`` - Base two logarithm of the number of bytes to operate on.
|
||||||
|
- ``data: UInt`` - Right-hand operand of the logical operation
|
||||||
|
- ``atomic: UInt`` - Logical operation type (from ``TLAtomics``)
|
||||||
|
|
||||||
|
Hint
|
||||||
|
----
|
||||||
|
|
||||||
|
Constructor for a TLBundleA encoding a ``Hint`` message, which is used to
|
||||||
|
send prefetch hints to caches. The ``param`` argument determines what kind
|
||||||
|
of hint it is. The possible values come from the ``TLHints`` object and are
|
||||||
|
``PREFETCH_READ`` and ``PREFETCH_WRITE``. The first one tells caches to
|
||||||
|
acquire data in a shared state. The second one tells cache to acquire data
|
||||||
|
in an exclusive state. If the cache this message reaches is a last-level cache,
|
||||||
|
there won't be any difference. If the manager this message reaches is not a
|
||||||
|
cache, it will simply be ignored. In any case, a ``HintAck`` message will be
|
||||||
|
sent in response.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``fromSource: UInt`` - Source ID for this transaction.
|
||||||
|
- ``toAddress: UInt`` - The address to prefetch
|
||||||
|
- ``lgSize: UInt`` - Base two logarithm of the number of bytes to prefetch
|
||||||
|
- ``param: UInt`` - Hint type (from TLHints)
|
||||||
|
|
||||||
|
AccessAck
|
||||||
|
---------
|
||||||
|
|
||||||
|
Constructor for a TLBundleD encoding an ``AccessAck`` or ``AccessAckData``
|
||||||
|
message. If the optional ``data`` field is supplied, it will be an
|
||||||
|
``AccessAckData``. Otherwise, it will be an ``AccessAck``.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- ``a: TLBundleA`` - The A channel message to acknowledge
|
||||||
|
- ``data: UInt`` - (optional) The data to send back
|
||||||
|
|
||||||
|
HintAck
|
||||||
|
-------
|
||||||
|
|
||||||
|
Constructor for a TLBundleD encoding a ``HintAck`` message.
|
||||||
|
|
||||||
|
**Arguments**
|
||||||
|
|
||||||
|
- ``a: TLBundleA`` - The A channel message to acknowledge
|
||||||
|
|
||||||
|
first/last/count
|
||||||
|
----------------
|
||||||
|
|
||||||
|
These methods take a decoupled channel (either the A channel or D channel)
|
||||||
|
and determines whether the current beat is the first of the transaction,
|
||||||
|
whether the current beat is the last in the transaction, or the count
|
||||||
|
(starting from 0) of the current beat in the transaction.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``x: DecoupledIO[TLChannel]`` - The decoupled channel to snoop on.
|
||||||
|
|
||||||
|
numBeats
|
||||||
|
---------
|
||||||
|
|
||||||
|
This method takes in a TileLink bundle and gives the number of beats expected
|
||||||
|
for the transaction.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``x: TLChannel`` - The TileLink bundle to get the number of beats from
|
||||||
|
|
||||||
|
numBeats1
|
||||||
|
---------
|
||||||
|
|
||||||
|
Similar to ``numBeats`` except it gives the number of beats minus one. If this
|
||||||
|
is what you need, you should use this instead of doing ``numBeats - 1.U``, as
|
||||||
|
this is more efficient.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``x: TLChannel`` - The TileLink bundle to get the number of beats from
|
||||||
|
|
||||||
|
hasData
|
||||||
|
--------
|
||||||
|
|
||||||
|
Determines whether the TileLink message contains data or not. This is true
|
||||||
|
if the message is a PutFull, PutPartial, Arithmetic, Logical, or AccessAckData.
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- ``x: TLChannel`` - The TileLink bundle to check
|
||||||
311
docs/TileLink-Diplomacy-Reference/NodeTypes.rst
Normal file
311
docs/TileLink-Diplomacy-Reference/NodeTypes.rst
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
TileLink Node Types
|
||||||
|
===================
|
||||||
|
|
||||||
|
Diplomacy represents the different components of an SoC as nodes of a
|
||||||
|
directed acyclic graph. TileLink nodes can come in several different types.
|
||||||
|
|
||||||
|
Client Node
|
||||||
|
-----------
|
||||||
|
|
||||||
|
TileLink clients are modules that initiate TileLink transactions by sending
|
||||||
|
requests on the A channel and receive responses on the D channel. If the
|
||||||
|
client implements TL-C, it will receive probes on the B channel, send releases
|
||||||
|
on the C channel, and send grant acknowledgements on the E channel.
|
||||||
|
|
||||||
|
The L1 caches and DMA devices in RocketChip/Chipyard have client nodes.
|
||||||
|
|
||||||
|
You can add a TileLink client node to your LazyModule using the TLHelper
|
||||||
|
object from testchipip like so:
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink.{TLClientParameters}
|
||||||
|
import testchipip.TLHelper
|
||||||
|
|
||||||
|
class MyClient(implicit p: Parameters) extends LazyModule {
|
||||||
|
val node = TLHelper.makeClientNode(TLClientParameters(
|
||||||
|
name = "my-client",
|
||||||
|
sourceId = IdRange(0, 4),
|
||||||
|
requestFifo = true,
|
||||||
|
visibility = Seq(AddressSet(0, 0xffff))))
|
||||||
|
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
val (tl, edge) = node.out(0)
|
||||||
|
|
||||||
|
// Rest of code here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``name`` argument identifies the node in the diplomacy graph. It is the
|
||||||
|
only required argument for TLClientParameters.
|
||||||
|
|
||||||
|
The ``sourceId`` argument specifies the range of source identifiers that this
|
||||||
|
client will use. Since we have set the range to [0, 4) here, this client will
|
||||||
|
be able to send up to four requests in flight at a time. Each request will
|
||||||
|
have a distinct value in its source field. The default value for this field
|
||||||
|
is ``IdRange(0, 1)``, which means it would only be able to send a single
|
||||||
|
request inflight.
|
||||||
|
|
||||||
|
The ``requestFifo`` argument is a boolean option which defaults to false.
|
||||||
|
If it is set to true, the client will request that downstream managers that
|
||||||
|
support it send responses in FIFO order (that is, in the same order the
|
||||||
|
corresponding requests were sent).
|
||||||
|
|
||||||
|
The ``visibility`` argument specifies the address ranges that the client
|
||||||
|
will access. By default it is set to include all addresses. In this example,
|
||||||
|
we set it to contain a single address range ``AddressSet(0, 0xffff)``, which
|
||||||
|
means that the client will only access addresses in this range. Clients
|
||||||
|
normally do not specify this, but it can help downstream crossbar generators
|
||||||
|
optimize the hardware by not arbitrating the client to managers with address
|
||||||
|
ranges that don't overlap with its visibility.
|
||||||
|
|
||||||
|
Inside your lazy module implementation, you can call ``node.out`` to get a
|
||||||
|
list of bundle/edge pairs. If you used the TLHelper, you only specified a
|
||||||
|
single client edge, so this list will only have one pair.
|
||||||
|
|
||||||
|
The ``tl`` bundle is a Chisel hardware bundle that connects to the IO of this
|
||||||
|
module. It contains two (in the case of TL-UL and TL-UH) or five (in the case
|
||||||
|
of TL-C) decoupled bundles corresponding to the TileLink channels. This is
|
||||||
|
what you should connect your hardware logic to in order to actually send/receive
|
||||||
|
TileLink messages.
|
||||||
|
|
||||||
|
The ``edge`` object represents the edge of the diplomacy graph. It contains
|
||||||
|
some useful helper functions which will be documented in
|
||||||
|
:ref:`TileLink Edge Object Methods`.
|
||||||
|
|
||||||
|
Manager Node
|
||||||
|
------------
|
||||||
|
|
||||||
|
TileLink managers take requests from clients on the A channel and send
|
||||||
|
responses back on the D channel. You can create a manager node using the
|
||||||
|
TLHelper like so:
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink.{TLManagerParameters}
|
||||||
|
import testchipip.TLHelper
|
||||||
|
|
||||||
|
class MyManager(implicit p: Parameters) extends LazyModule {
|
||||||
|
val device = new SimpleDevice("my-device", Seq("tutorial,my-device0"))
|
||||||
|
val beatBytes = 8
|
||||||
|
val node = TLHelper.makeManagerNode(beatBytes, TLManagerParameters(
|
||||||
|
address = Seq(AddressSet(0x20000, 0xfff)),
|
||||||
|
resources = device.reg,
|
||||||
|
regionType = RegionType.UNCACHED,
|
||||||
|
executable = true,
|
||||||
|
supportsArithemetic = TransferSizes(1, beatBytes),
|
||||||
|
supportsLogical = TransferSizes(1, beatBytes),
|
||||||
|
supportsGet = TransferSizes(1, beatBytes),
|
||||||
|
supportsPutFull = TransferSizes(1, beatBytes),
|
||||||
|
supportsPutPartial = TransferSizes(1, beatBytes),
|
||||||
|
supportsHint = TransferSizes(1, beatBytes),
|
||||||
|
fifoId = Some(0)))
|
||||||
|
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
val (tl, edge) = node.in(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``makeManagerNode`` method takes two arguments. The first is ``beatBytes``,
|
||||||
|
which is the physical width of the TileLink interface in bytes. The second
|
||||||
|
is a TLManagerParameters object.
|
||||||
|
|
||||||
|
The only required argument for ``TLManagerParameters`` is the ``address``,
|
||||||
|
which is the set of address ranges that this manager will serve.
|
||||||
|
This information is used to route requests from the clients.
|
||||||
|
|
||||||
|
The second argument is ``resources``, which is usually retrieved from a
|
||||||
|
``Device`` object. In this case, we use a ``SimpleDevice`` object.
|
||||||
|
This argument is necessary if you want to add an entry to the DeviceTree in
|
||||||
|
the BootROM so that it can be read by a Linux driver. The two arguments to
|
||||||
|
``SimpleDevice`` are the name and compatibility list for the device tree
|
||||||
|
entry. For this manager, then, the device tree entry would look like
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
L12: my-device@20000 {
|
||||||
|
compatible = "tutorial,my-device0";
|
||||||
|
reg = <0x20000 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
The next argument is ``regionType``, which gives some information about
|
||||||
|
the caching behavior of the manager. There are seven region types, listed below:
|
||||||
|
|
||||||
|
1. ``CACHED`` - An intermediate agent may have cached a copy of the region for you.
|
||||||
|
2. ``TRACKED`` - The region may have been cached by another master, but coherence is being provided.
|
||||||
|
3. ``UNCACHED`` - The region has not been cached yet, but should be cached when possible.
|
||||||
|
4. ``IDEMPOTENT`` - Gets return most recently put content, but content should not be cached.
|
||||||
|
5. ``VOLATILE`` - Content may change without a put, but puts and gets have no side effects.
|
||||||
|
6. ``PUT_EFFECTS`` - Puts produce side effects and so must not be combined/delayed.
|
||||||
|
7. ``GET_EFFECTS`` - Gets produce side effects and so must not be issued speculatively.
|
||||||
|
|
||||||
|
Next is the ``executable`` argument, which determines if the CPU is allowed to
|
||||||
|
fetch instructions from this manager. By default it is false, which is what
|
||||||
|
most MMIO peripherals should set it to.
|
||||||
|
|
||||||
|
The next six arguments start with ``support`` and determine the different
|
||||||
|
A channel message types that the manager can accept. The definitions of the
|
||||||
|
message types are explained in :ref:`TileLink Edge Object Methods`.
|
||||||
|
The ``TransferSizes`` case class specifies the range of logical sizes (in bytes)
|
||||||
|
that the manager can accept for the particular message type. This is an inclusive
|
||||||
|
range and all logical sizes must be powers of two. So in this case, the manager
|
||||||
|
can accept requests with sizes of 1, 2, 4, or 8 bytes.
|
||||||
|
|
||||||
|
The final argument shown here is the ``fifoId`` setting, which determines
|
||||||
|
which FIFO domain (if any) the manager is in. If this argument is set to ``None``
|
||||||
|
(the default), the manager will not guarantee any ordering of the responses.
|
||||||
|
If the ``fifoId`` is set, it will share a FIFO domain with all other managers
|
||||||
|
that specify the same ``fifoId``. This means that client requests sent to
|
||||||
|
that FIFO domain will see responses in the same order.
|
||||||
|
|
||||||
|
Register Node
|
||||||
|
-------------
|
||||||
|
|
||||||
|
While you can directly specify a manager node and write all of the logic
|
||||||
|
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:`Register Router`.
|
||||||
|
|
||||||
|
Identity Node
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Unlike the previous node types, which had only inputs or only outputs, the
|
||||||
|
identity node has both. As its name suggests, it simply connects the inputs
|
||||||
|
to the outputs unchanged. This node is mainly used to combine multiple
|
||||||
|
nodes into a single node with multiple edges. For instance, say we have two
|
||||||
|
client lazy modules, each with their own client node.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
class MyClient1(implicit p: Parameters) extends LazyModule {
|
||||||
|
val node = TLHelper.makeClientNode("my-client1", IdRange(0, 1))
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyClient2(implicit p: Parameters) extends LazyModule {
|
||||||
|
val node = TLHelper.makeClientNode("my-client2", IdRange(0, 1))
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
Now we instantiate these two clients in another lazy module and expose their
|
||||||
|
nodes as a single node.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
class MyClientGroup(implicit p: Parameters) extends LazyModule {
|
||||||
|
val client1 = LazyModule(new MyClient1)
|
||||||
|
val client2 = LazyModule(new MyClient2)
|
||||||
|
val node = TLIdentityNode()
|
||||||
|
|
||||||
|
node := client1.node
|
||||||
|
node := client2.node
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
We can also do the same for managers.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
class MyManager1(beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val node = TLHelper.makeManagerNode(beatBytes, TLManagerParameters(
|
||||||
|
address = Seq(AddressSet(0x0, 0xfff))))
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyManager2(beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val node = TLHelper.makeManagerNode(beatBytes, TLManagerParameters(
|
||||||
|
address = Seq(AddressSet(0x1000, 0xfff))))
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyManagerGroup(beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val man1 = LazyModule(new MyManager1(beatBytes))
|
||||||
|
val man2 = LazyModule(new MyManager2(beatBytes))
|
||||||
|
val node = TLIdentityNode()
|
||||||
|
|
||||||
|
man1.node := node
|
||||||
|
man2.node := node
|
||||||
|
}
|
||||||
|
|
||||||
|
If we want to connect the client and manager groups together, we can now do this.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
class ClientManagerComplex(implicit p: Parameters) extends LazyModule {
|
||||||
|
val client = LazyModule(new MyClientGroup)
|
||||||
|
val manager = LazyModule(new MyManagerGroup(8))
|
||||||
|
|
||||||
|
manager.node :=* client.node
|
||||||
|
}
|
||||||
|
|
||||||
|
The meaning of the ``:=*`` operator is explained in more detail in the
|
||||||
|
:ref:`Diplomacy Connectors` section. In summary, it connects two nodes together
|
||||||
|
using multiple edges. The edges in the identity node are assigned in order,
|
||||||
|
so in this case ``client1.node`` will eventually connect to ``manager1.node``
|
||||||
|
and ``client2.node`` will connect to ``manager2.node``.
|
||||||
|
|
||||||
|
The number of inputs to an identity node should match the number of outputs.
|
||||||
|
A mismatch will cause an elaboration error.
|
||||||
|
|
||||||
|
Adapter Node
|
||||||
|
------------
|
||||||
|
|
||||||
|
Like the identity node, the adapter node takes some number of inputs and
|
||||||
|
produces the same number of outputs. However, unlike the identity node, the
|
||||||
|
adapter node does not simply pass the connections through unchanged.
|
||||||
|
It can change the logical and physical interfaces between input and output and
|
||||||
|
rewrite messages going through. RocketChip provides a library of adapters,
|
||||||
|
which are catalogued in :ref:`Diplomatic Widgets`.
|
||||||
|
|
||||||
|
You will rarely need to create an adapter node yourself, but the invocation is
|
||||||
|
as follows.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
val node = TLAdapterNode(
|
||||||
|
clientFn = { cp =>
|
||||||
|
// ..
|
||||||
|
},
|
||||||
|
managerFn = { mp =>
|
||||||
|
// ..
|
||||||
|
})
|
||||||
|
|
||||||
|
The ``clientFn`` is a function that takes the ``TLClientPortParameters`` of
|
||||||
|
the input as an argument and returns the corresponding parameters for the
|
||||||
|
output. The ``managerFn`` takes the ``TLManagerPortParameters`` of the output
|
||||||
|
as an argument and returns the corresponding parameters for the input.
|
||||||
|
|
||||||
|
Nexus Node
|
||||||
|
----------
|
||||||
|
|
||||||
|
The nexus node is similar to the adapter node in that it has a different
|
||||||
|
output interface than input interface. But it can also have a different
|
||||||
|
number of inputs than it does outputs. This node type is mainly used by
|
||||||
|
the ``TLXbar`` widget, which provides a TileLink crossbar generator. You will
|
||||||
|
also likely not need to define this node type manually, but its invocation is
|
||||||
|
as follows.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
val node = TLNexusNode(
|
||||||
|
clientFn = { seq =>
|
||||||
|
// ..
|
||||||
|
},
|
||||||
|
managerFn = { seq =>
|
||||||
|
// ..
|
||||||
|
})
|
||||||
|
|
||||||
|
This has similar arguments as the adapter node's constructor, but instead of
|
||||||
|
taking single parameters objects as arguments and returning single objects
|
||||||
|
as results, the functions take and return sequences of parameters. And as you
|
||||||
|
might expect, the size of the returned sequence need not be the same size as
|
||||||
|
the input sequence.
|
||||||
2
docs/TileLink-Diplomacy-Reference/Register-Router.rst
Normal file
2
docs/TileLink-Diplomacy-Reference/Register-Router.rst
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Register Router
|
||||||
|
===============
|
||||||
2
docs/TileLink-Diplomacy-Reference/Widgets.rst
Normal file
2
docs/TileLink-Diplomacy-Reference/Widgets.rst
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Diplomatic Widgets
|
||||||
|
==================
|
||||||
29
docs/TileLink-Diplomacy-Reference/index.rst
Normal file
29
docs/TileLink-Diplomacy-Reference/index.rst
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
TileLink and Diplomacy Reference
|
||||||
|
================================
|
||||||
|
|
||||||
|
TileLink is the cache coherence and memory protocol used by RocketChip and
|
||||||
|
other Chipyard generators. It is how different modules like caches, memories,
|
||||||
|
peripherals, and DMA devices communicate with each other.
|
||||||
|
|
||||||
|
TileLink is built on top of diplomacy, a framework for exchanging
|
||||||
|
configuration information among Chisel generators in a two-phase elaboration
|
||||||
|
scheme.
|
||||||
|
|
||||||
|
A brief overview of how to connect simple TileLink widgets can be found
|
||||||
|
in the :ref:`Adding-an-Accelerator` section. This section will provide a
|
||||||
|
detailed reference for the TileLink and Diplomacy functionality provided by
|
||||||
|
RocketChip.
|
||||||
|
|
||||||
|
A detailed specification of the TileLink 1.7 protocol can be found on the
|
||||||
|
`SiFive website <https://sifive.cdn.prismic.io/sifive%2F57f93ecf-2c42-46f7-9818-bcdd7d39400a_tilelink-spec-1.7.1.pdf>`.
|
||||||
|
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
:caption: Reference
|
||||||
|
|
||||||
|
NodeTypes
|
||||||
|
Diplomacy-Connectors
|
||||||
|
EdgeFunctions
|
||||||
|
Register-Router
|
||||||
|
Widgets
|
||||||
@@ -30,6 +30,7 @@ New to Chipyard? Jump to the :ref:`Chipyard Basics` page for more info.
|
|||||||
|
|
||||||
Advanced-Usage/index
|
Advanced-Usage/index
|
||||||
|
|
||||||
|
TileLink-Diplomacy-Reference/index
|
||||||
|
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
|
|||||||
Reference in New Issue
Block a user