blob: a9892cea7607f36fc47772e0b3d7af59ca93ed01 [file] [log] [blame]
=================
VPR routing graph
=================
Database Contents
=================
This section will describe the prjxray database contents with respect to
the routing graph.
Grid
----
Project X-Ray documents one or more **parts**. Within a **part** is a **grid**.
The **grid** is documented in ``tilegrid.json`` and can be accessed via the
prjxray API via the ``prjxray.db.Database.grid`` method.
Each location within the **grid** is a **tile**, which has a **tile
type** and **grid coordinate**. Each instance of a **tile type** has the
same **sites**, **tile wires**, and **pips**. A tile type may have zero
or more **sites**, zero or more **tile wires** and zero or more **pips**.
**Pips** are programmable interconnect points, and connect two **tile
wires** together in a programmatic fashion.
A **tile** may also have a **bits** definition if the output bitstream
configures this tile. A **bits** definition consists of a **block
type**, a **base address**, the number of **frames** in the **base
address column**, a **word offset**, and a number of **words**.
Routing fabric
--------------
Connection schemes
^^^^^^^^^^^^^^^^^^
+------------------+------------------+
| From | To |
+==================+==================+
| Local Tile Wire | PIP |
+------------------+------------------+
| Local Tile Wire | Site Pin |
+------------------+------------------+
| Local Tile Wire | Remote Tile Wire |
+------------------+------------------+
| Remote Tile Wire | Local Tile Wire |
+------------------+------------------+
| Site Pin | Local Tile Wire |
+------------------+------------------+
| PIP | Local Tile Wire |
+------------------+------------------+
Tile wire
^^^^^^^^^
+-----------------+-----------------------------------------------------------+
| Property | Valid choices |
+=================+===========================================================+
| connections | - one or more PIPs, and |
| | - one or more Remote Tile Wires, and |
| | - only 1 site pin |
+-----------------+-----------------------------------------------------------+
PIP
^^^
+-----------------+-----------------------------------------------------------+
| Property | Valid choices |
+=================+===========================================================+
| src_wire | Local Tile Wire |
+-----------------+-----------------------------------------------------------+
| dst_wire | Local Tile Wire |
+-----------------+-----------------------------------------------------------+
| is_directional | True or False |
+-----------------+-----------------------------------------------------------+
.. figure:: ../images/prjxray/rrgraph-wire.svg
A 7-Series part contains nodes, which consist of **tile wires**. **Tile
wires** are sourced either from a **site pin** or a **pip** or a **tile
wire** from another tile within the grid. **Tile wires** sink to either
a **site pin** or a **pip** or a **tile wire** in another tile within
the grid. **Tile wires** have not been observed to have a source and
sink that are both **site pins**.
**Tile wires** that source or sink within a tile are documented in the
**tile type** definition, which is found in the ``tile_type_<tile
type>.json`` files. The **tile type** definition has a list of the **tile
wires** within the tile, a list of **pips** and a list of **sites.** If
the **tile wires** source or sink within the tile, then the **tile
wire** will appear in either a **pip** or a **site** definition. Tile
type definitions can be retrieved via ``db.Database.get_tile_type`` method.
All **pip** definitions have a **src_wire** and **dst_wire** keys,
indicating what **tile wire** is connected to each end of the pip.
.. note::
A bidirectional pip will have the is_directional key set to "0", but use
**src_wire** and **dst_wire** as if it was a unidirectional pip.
Each **site** definition will have a **site_type** and dictionary of
**site_pins**, along with site naming information. The **site_pins**
dictionary maps the **site_pin** of the **site_type** to the
**tile_wires** within the tile. The direction of **site_pin** can be
found in the **site_type** definition, ``site_type_<site type>.json``
file. Site type definitions can be retrieved via
``db.Database.get_site_type`` method.
The **tile wires** combined with the tile's **pip** list and the
**site_pins** definition for each site completes the routing description
for the tile. However there needs to be a relationship between **tile
wires** from **tiles** to each other. This is defined in the
``tileconn.json`` file, provides a list of which **tile wires** are
connected between **tiles**. The ``tileconn.json`` relates tile types via
their grid coordinates.
Example:
^^^^^^^^
.. code-block:: javascript
{
"grid_deltas": [
0,
1
],
"tile_types": [
"CLBLL_L",
"CLBLL_L"
],
"wire_pairs": [
[
"CLBLL_LL_CIN",
"CLBLL_LL_COUT_N"
],
[
"CLBLL_L_CIN",
"CLBLL_L_COUT_N"
]
]
},
This reads as "a ``CLBLL_L`` that is at (x+0, y+1) from another ``CLBLL_L``,
- Connect ``CLBLL_L(x, y+1).CLBLL_LL_COUT_N`` to ``CLBLL_L(x, y).CLBLL_LL_CIN``
- Connect ``CLBLL_L(x, y+1).CLBLL_L_COUT_N`` to ``CLBLL_L(x, y).CLBLL_L_CIN``
The **tile wire** connections can be retrieved via
``db.Database.get_connections``.
The **tile wire** connections from ``tileconn.json``, and the **pips** and
**site pins** from each ``tile_type_<tile type>.json`` provides a complete
routing graph description for a **part** between **sites**. Routing
within sites is done via pb_type architectural XML, and is not
documented as part of prjxray at this time.
VPR routing description
=======================
The previous section documented the contents of the prjxray database.
Prior to describing the process of converting that database into VPR, a
short discussion of the VPR routing data structures is required.
At the most basic level, VPR's routing graph is made of **nodes** and
**edges**. **Edges** are either configurable or static connections
between **nodes**. Static connections are always present. Configurable
connections are selected during routing. All **edges** must have a
**switch**. A **switch** is used to describe timing information along
the edge, and it determines if the switch is configurable or not. The
two most common types of **switches** are SHORT (electrical short) and
MUX.
SHORT is used to join two **nodes** in the routing graph, both logically
and for timing purposes. SHORT's are not configurable.
MUX is roughly equivalent to a **pip**. It is configurable and is used
by the router. For the purposes of timing, the timing on **nodes** on
each side of the pip are seperate. A PASS_GATE is a **switch** that does
not do this isolation.
The detiled description about **switch** types can be found in
`VTR documentation <http://docs.verilogtorouting.org/en/latest/arch/reference/#arch-switches>`_ .
.. figure:: ../images/prjxray/vpr-rrgraph-types.svg
So **edges** connect **nodes** together, but what are the **nodes**
themselves? **Nodes** are either a source/sink (e.g. a **site pin**) or
are routing fabric. VPR models each source or sink as 2 or more nodes.
The **site pin** is a SINK or SOURCE. To accommodate the idea that a
**site pin** might have multiple routing paths, the SINK or SOURCE then
is connected to a IPIN or OPIN respectively. Then IPIN's/OPIN's are
connected to other nodes. So by default, all IPIN's connect to exactly
one SINK, and all SOURCE's connect to exactly one OPIN.
There are two routing fabric node types, CHANX and CHANY. CHANX are
wires that traverse in the x-direction and CHANY are wires that traverse
in the y-direction. Channels lies between tiles (see `this
image <http://docs.verilogtorouting.org/en/latest/_images/fpga_coordinate_system.png>`_
from the `VPR routing graph description
documentation <http://docs.verilogtorouting.org/en/latest/vpr/file_formats/>`_).
Channels cannot extended to the first or last column in the grid.
IPIN's and OPIN's have a direction that they point in relative to the
tile they belong too. They can be on the north, east, west, south, or
some combination. For example, in the image above, a pin at (1, 2) on
the east side could connect to CHANY nodes at (1,2).
Creating a 7-series routing graph for VPR
=========================================
In order to create a routing graph for VPR, several new things must be
defined:
- How to map the routing **tile wires** into VPR channels or other
constructs?
`prjxray_form_channels.py`_
- Which side of the tile should **site pins** be assigned to connect to
other tiles (in the case of direct connections like carry chains)
and to VPR channels?
`prjxray_assign_tile_pin_direction.py`_
After the preparation work, output can be generated for VPR. 3 types of
output are generated:
- Tile pb_types XML's that connect site pb_types **site pins** to
**tile wires**
`prjxray_tile_import.py`_
- Architecture XML that is the grid and has direct inter-tile
connections
`prjxray_arch_import.py`_
- Final routing graph XML
`prjxray_routing_import.py`_
.. _prjxray_form_channels.py: https://github.com/SymbiFlow/symbiflow-arch-defs/blob/master/xc7/utils/prjxray_form_channels.py
.. _prjxray_assign_tile_pin_direction.py: https://github.com/SymbiFlow/symbiflow-arch-defs/blob/master/xc7/utils/prjxray_assign_tile_pin_direction.py
.. _prjxray_tile_import.py: https://github.com/SymbiFlow/symbiflow-arch-defs/blob/master/xc7/utils/prjxray_tile_import.py
.. _prjxray_arch_import.py: https://github.com/SymbiFlow/symbiflow-arch-defs/blob/master/xc7/utils/prjxray_arch_import.py
.. _prjxray_routing_import.py: https://github.com/SymbiFlow/symbiflow-arch-defs/blob/master/xc7/utils/prjxray_routing_import.py
Click on the figure below to zoom-in:
.. thumbnail:: ../images/prjxray/import-flow.png
This diagram shows the importing flow for Project X-Ray.
Tile wire classification
------------------------
Before channels can be formed, **tile wires** need to be bucketed into
their purpose.
Step (1) - Group tile wires into nodes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The first step is to first re-form nodes that contain all the
directly connected **tiles wires** These nodes are *not* VPR
**nodes**, they are simply the collection of **tile wires** that are
already a net (electrically equivalent).
Step (2) - Classify nodes
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Each node then needs to be classified. The simplest classification is
a channel wire, which means that **pips** route on and off of the
node. However there are other important classifications. For example,
the carry chain connection between two CLBLL_L tiles should be
modelled as a tile direct connection, rather than routing onto a
channel and back off. The is classified as a "edge with mux".
The classification is broken down into the following categories:
- CHANNEL - **Pips** route on and off of this node.
- EDGE_WITH_MUX - Two **tile wires** connected by a **pip**.
- The first **tile wire** sources at a **site pin**, and the second
**tile wire** sinks at a **site pin**.
- This captures direct inter-tile connections like carry chain
wires, BRAM data cascade wires, etc.
- NULL - A node that has either no source or no sink. This wires
typically occur near the edge of the grid.
- EDGES_TO_CHANNEL - A node that sources and sinks from a **site pin**
and connects via a **pip** to a CHANNEL
.. figure:: ../images/prjxray/import-wire-class.svg
There is another classification EDGE_WITH_SHORT, which is a direct
connection between two **site pins**. This does not appear to occur in
7-series parts.
The reason this classification is important is that each node that is a
CHANNEL must be mapped into one or more CHANX or CHANY **nodes**.
EDGE_WITH_MUX nodes must be converted into root level architecture
direct connections, and will be **edges** between two **site pin**
nodes. EDGES_TO_CHANNEL will be become **edges** in the routing between
**site pins nodes** and CHANX/CHANY **nodes**.
Channel formation
-----------------
All nodes that were classified as CHANNEL type need to assigned CHANX
and CHANY dimensions. This is done via
`make_tracks <https://github.com/SymbiFlow/symbiflow-arch-defs/blob/master/utils/lib/rr_graph/tracks.py>`_.
make_tracks takes a point bag containing all of the source and sink grid
locations for a particular channel. It returns straight lines such that
all sources and sink grid locations can route on to or off of the
channel.
Point Bag to CHANX / CHANY decomposition
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. figure:: ../images/prjxray/vtr-rrgraph.png
:width: 100%
.. note::
Currently this logic does not optimize for the lowest required
track count, instead aiming to be correct first.
Pin assignment
--------------
Because the pin directions are shared among tile types via the root
pb_type that matches the tile, pin directions must be assigned taking
into account the wire type attached to each **site pin** within the
tile. For example, EDGE_WITH_MUX pins must be facing each other.
EDGES_TO_CHANNEL pins must face a direction that contains their channel,
per the tracks defined during channel formation.
Once pins are assigned, during tile generation, the pin assignments are
used to ensure that pins can be connected into the routing graph as
expected.
Tile pb_type and root architecture XML
--------------------------------------
The tile type pb_type XML files are emitted using the information from
**tile type**, and the pin direction assignment.
The root architecture XML is emitted using the tile **grid**, the direct
inter-tile connections from node classification.
Routing import
--------------
Routing import starts with the virtual routing graph from the
architecture XML. This routing graph will have correct **nodes** for
IPIN, OPIN, SOURCE, and SINK types. However the CHANX and CHANY
**nodes**, and the **edges** to and from the CHANX and CHANY **nodes**
will be incorrect. So the first step is to copy the portions of the
virtual routing graph that are correct (block types, grid definition,
**nodes** and **edges** belong to IPIN, OPIN, SOURCE, SINK).
Then channels are emitted to accommodate the tracks made during channel
formation. Each track in channel formation is a new **node** of type
CHANX or CHANY. If a node is a CHANNEL with multiple tracks, then a
SHORT **edge** is emitted to connect the CHANX's and CHANY's together,
making VPR treat them as electrically common.
Each **pip** in the **grid** is then matched with **src** and **sink**
**nodes**, if possible. When **pips** are added to the routing graph,
they also have FASM metadata to enable the **pip** in the bitstream.
.. note::
As of 2020-03-26 - Not all pips will be emitted. The current
reasons are:
- Dont currently support PIPs which connect the same src and
destinations with the same switch
On the ROI and synthetic tiles
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To avoid requiring support for IOB and clock networks for initial
bringup activities, an ROI harness is used. The ROI harness brings some
input/output signals to specific **tile wires** within the routing
graph, including a clock source. During root architecture and routing
import, synthetic tiles are generated that present the ROI harness sink
or source, and have either an IPAD or OPAD. These tiles are purely
synthetic, and are only used to describe the source or sink location
within the routing graph to VPR of the ROI harness signals.
Several modifications to the standard flow are required to support the
ROI and synthetics. First, **nodes** that contain **tile wires** are
restricted to being either "input only" or "output only" depending on
whether the synthetic tile is a clock, in pad or out pad. On "input
only", all **pip** that would sink to that **node** are skipped. On
"output only", all **pip** that would source from that **node** are
skipped. Then a new synthetic **edge** is added connected a synthetic
IPAD or OPAD tile to the relevant **node**. VPR can then route to or
from this **node** just as if it was a actually IPAD or OPAD.