| ================= | |
| 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: | |
| - Don’t 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. |