================= 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_.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_.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_.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 `_ . .. 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 `_ from the `VPR routing graph description documentation `_). 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 `_. 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.