| import enum | |
| import os | |
| from lib.rr_graph import graph2 | |
| from lib.rr_graph import tracks | |
| class NodeClassification(enum.Enum): | |
| NULL = 1 | |
| CHANNEL = 2 | |
| EDGES_TO_CHANNEL = 3 | |
| EDGE_WITH_MUX = 4 | |
| def create_tables(conn): | |
| """ Create connection database scheme. """ | |
| connection_database_sql_file = os.path.join( | |
| os.path.dirname(__file__), "connection_database.sql" | |
| ) | |
| with open(connection_database_sql_file, 'r') as f: | |
| c = conn.cursor() | |
| c.executescript(f.read()) | |
| conn.commit() | |
| c = conn.cursor() | |
| c.execute( | |
| """ | |
| INSERT INTO | |
| switch(name, internal_capacitance, drive_resistance, intrinsic_delay, switch_type) | |
| VALUES | |
| ("__vpr_delayless_switch__", 0.0, 0.0, 0.0, "mux"), | |
| ("short", 0.0, 0.0, 0.0, "short") | |
| """ | |
| ) | |
| conn.commit() | |
| def get_wire_pkey(conn, tile_name, wire): | |
| c = conn.cursor() | |
| c.execute( | |
| """ | |
| WITH selected_tile(phy_tile_pkey, tile_type_pkey) AS ( | |
| SELECT | |
| pkey, | |
| tile_type_pkey | |
| FROM | |
| phy_tile | |
| WHERE | |
| name = ? | |
| ) | |
| SELECT | |
| wire.pkey | |
| FROM | |
| wire | |
| WHERE | |
| wire.phy_tile_pkey = ( | |
| SELECT | |
| selected_tile.phy_tile_pkey | |
| FROM | |
| selected_tile | |
| ) | |
| AND wire.wire_in_tile_pkey = ( | |
| SELECT | |
| wire_in_tile.pkey | |
| FROM | |
| wire_in_tile | |
| WHERE | |
| wire_in_tile.name = ? | |
| AND wire_in_tile.tile_type_pkey = ( | |
| SELECT | |
| tile_type_pkey | |
| FROM | |
| selected_tile | |
| ) | |
| ); | |
| """, (tile_name, wire) | |
| ) | |
| results = c.fetchone() | |
| assert results is not None, (tile_name, wire) | |
| return results[0] | |
| def get_track_model(conn, track_pkey): | |
| assert track_pkey is not None | |
| track_list = [] | |
| track_nodes = [] | |
| c2 = conn.cursor() | |
| graph_node_pkey = {} | |
| for idx, (pkey, graph_node_type, x_low, x_high, y_low, | |
| y_high) in enumerate(c2.execute(""" | |
| SELECT pkey, graph_node_type, x_low, x_high, y_low, y_high | |
| FROM graph_node WHERE track_pkey = ?""", (track_pkey, ))): | |
| node_type = graph2.NodeType(graph_node_type) | |
| if node_type == graph2.NodeType.CHANX: | |
| direction = 'X' | |
| elif node_type == graph2.NodeType.CHANY: | |
| direction = 'Y' | |
| graph_node_pkey[pkey] = idx | |
| track_nodes.append(pkey) | |
| track_list.append( | |
| tracks.Track( | |
| direction=direction, | |
| x_low=x_low, | |
| x_high=x_high, | |
| y_low=y_low, | |
| y_high=y_high | |
| ) | |
| ) | |
| track_connections = set() | |
| for src_graph_node_pkey, dest_graph_node_pkey in c2.execute(""" | |
| SELECT src_graph_node_pkey, dest_graph_node_pkey | |
| FROM graph_edge WHERE track_pkey = ?""", (track_pkey, )): | |
| src_idx = graph_node_pkey[src_graph_node_pkey] | |
| dest_idx = graph_node_pkey[dest_graph_node_pkey] | |
| track_connections.add(tuple(sorted((src_idx, dest_idx)))) | |
| tracks_model = tracks.Tracks(track_list, list(track_connections)) | |
| return tracks_model, track_nodes | |
| def yield_wire_info_from_node(conn, node_pkey): | |
| """ Yield tile types and wires attached to specified node. | |
| Parameters | |
| ---------- | |
| conn : sqlite3.Connection | |
| Connection database object. | |
| node_pkey : int | |
| Primary key into node table | |
| Yields | |
| ------- | |
| tile_type : str | |
| Name of tile type for wire being yielded. | |
| wire : str | |
| Name of wire for wire being yielded. | |
| Note: This function yields the prjxray tile_type and wire name. This | |
| function does NOT tile_type's and wire names coorsponding to the VPR tiles. | |
| """ | |
| c2 = conn.cursor() | |
| for tile_type, wire in c2.execute(""" | |
| WITH wires_in_node(phy_tile_pkey, wire_in_tile_pkey) AS ( | |
| SELECT | |
| phy_tile_pkey, | |
| wire_in_tile_pkey | |
| FROM | |
| wire | |
| WHERE | |
| node_pkey = ? | |
| ), | |
| tile_for_wire( | |
| wire_in_tile_pkey, tile_type_pkey | |
| ) AS ( | |
| SELECT | |
| wires_in_node.wire_in_tile_pkey, | |
| phy_tile.tile_type_pkey | |
| FROM | |
| phy_tile | |
| INNER JOIN wires_in_node ON phy_tile.pkey = wires_in_node.phy_tile_pkey | |
| ), | |
| tile_type_for_wire( | |
| wire_in_tile_pkey, tile_type_name | |
| ) AS ( | |
| SELECT | |
| tile_for_wire.wire_in_tile_pkey, | |
| tile_type.name | |
| FROM | |
| tile_type | |
| INNER JOIN tile_for_wire ON tile_type.pkey = tile_for_wire.tile_type_pkey | |
| ) | |
| SELECT | |
| tile_type_for_wire.tile_type_name, | |
| wire_in_tile.name | |
| FROM | |
| wire_in_tile | |
| INNER JOIN tile_type_for_wire ON tile_type_for_wire.wire_in_tile_pkey = wire_in_tile.pkey; | |
| """, (node_pkey, )): | |
| yield tile_type, wire | |
| def yield_logical_wire_info_from_node(conn, node_pkey): | |
| """ Yield tile types and wires attached to specified node. | |
| Parameters | |
| ---------- | |
| conn : sqlite3.Connection | |
| Connection database object. | |
| node_pkey : int | |
| Primary key into node table | |
| Yields | |
| ------- | |
| tile_type : str | |
| Name of tile type for wire being yielded. | |
| wire : str | |
| Name of wire for wire being yielded. | |
| Note: This function yields the prjxray tile_type and wire name. This | |
| function does NOT tile_type's and wire names coorsponding to the VPR tiles. | |
| """ | |
| c2 = conn.cursor() | |
| for tile_type, wire in c2.execute(""" | |
| WITH wires_in_node(tile_pkey, wire_in_tile_pkey) AS ( | |
| SELECT | |
| tile_pkey, | |
| wire_in_tile_pkey | |
| FROM | |
| wire | |
| WHERE | |
| node_pkey = ? | |
| ), | |
| tile_for_wire( | |
| wire_in_tile_pkey, tile_type_pkey | |
| ) AS ( | |
| SELECT | |
| wires_in_node.wire_in_tile_pkey, | |
| tile.tile_type_pkey | |
| FROM | |
| tile | |
| INNER JOIN wires_in_node ON tile.pkey = wires_in_node.tile_pkey | |
| ), | |
| tile_type_for_wire( | |
| wire_in_tile_pkey, tile_type_name | |
| ) AS ( | |
| SELECT | |
| tile_for_wire.wire_in_tile_pkey, | |
| tile_type.name | |
| FROM | |
| tile_type | |
| INNER JOIN tile_for_wire ON tile_type.pkey = tile_for_wire.tile_type_pkey | |
| ) | |
| SELECT | |
| tile_type_for_wire.tile_type_name, | |
| wire_in_tile.name | |
| FROM | |
| wire_in_tile | |
| INNER JOIN tile_type_for_wire ON tile_type_for_wire.wire_in_tile_pkey = wire_in_tile.pkey; | |
| """, (node_pkey, )): | |
| yield tile_type, wire | |
| def node_to_site_pins(conn, node_pkey): | |
| FIND_WIRE_WITH_SITE_PIN = """ | |
| WITH wires_in_node( | |
| pkey, tile_pkey, wire_in_tile_pkey | |
| ) AS ( | |
| SELECT | |
| pkey, | |
| tile_pkey, | |
| wire_in_tile_pkey | |
| FROM | |
| wire | |
| WHERE | |
| node_pkey = ? | |
| ) | |
| SELECT | |
| wires_in_node.pkey, | |
| wires_in_node.tile_pkey, | |
| wire_in_tile.pkey | |
| FROM | |
| wires_in_node | |
| INNER JOIN wire_in_tile ON wires_in_node.wire_in_tile_pkey = wire_in_tile.pkey | |
| WHERE | |
| wire_in_tile.site_pin_pkey IS NOT NULL; | |
| """ | |
| c = conn.cursor() | |
| for wire_pkey, tile_pkey, wire_in_tile_pkey in c.execute( | |
| FIND_WIRE_WITH_SITE_PIN, (node_pkey, )): | |
| yield wire_pkey, tile_pkey, wire_in_tile_pkey | |
| def get_pin_name_of_wire(conn, wire_pkey): | |
| """ Returns pin name of wire. | |
| For unsplit tiles, this is the name of the wire. | |
| For split tiles with only 1 site, this is the name of the site pin | |
| connected to this wire. | |
| For wires that are not a pin, returns None. | |
| Parameters | |
| ---------- | |
| conn : sqlite3.Connection | |
| Connection database object. | |
| wire_pkey : int | |
| Primary key into wire table | |
| Returns | |
| ------- | |
| pin : str | |
| VPR pin name for given wire_pkey. | |
| Returns none if this wire is not a pin. | |
| """ | |
| c = conn.cursor() | |
| c.execute( | |
| """ | |
| SELECT wire_in_tile_pkey, tile_pkey FROM wire WHERE pkey = ? | |
| """, (wire_pkey, ) | |
| ) | |
| wire_in_tile_pkey, tile_pkey = c.fetchone() | |
| c.execute( | |
| """ | |
| SELECT site_as_tile_pkey FROM tile WHERE pkey = ? | |
| """, (tile_pkey, ) | |
| ) | |
| site_as_tile_pkey = c.fetchone()[0] | |
| c.execute( | |
| """ | |
| SELECT name, site_pin_pkey FROM wire_in_tile WHERE pkey = ?; | |
| """, (wire_in_tile_pkey, ) | |
| ) | |
| wire_name, site_pin_pkey = c.fetchone() | |
| if site_pin_pkey is None: | |
| return None | |
| if site_as_tile_pkey is not None: | |
| c.execute( | |
| "SELECT name FROM site_pin WHERE pkey = ?", (site_pin_pkey, ) | |
| ) | |
| return c.fetchone()[0] | |
| else: | |
| return wire_name | |
| def get_wire_in_tile_from_pin_name(conn, tile_type_str, wire_str): | |
| """ Returns wire_in_tile rows match specified tile type and pin name. | |
| Because a split tile type can appear in multiple tiles (e.g. SLICEL in | |
| CLBLL_L, CLBLL_R, etc), multiple wire_in_tile rows may be returned. The | |
| site table primary key disambiguates which row to use. | |
| Parameters | |
| ---------- | |
| conn : sqlite3.Connection | |
| Connection database object. | |
| tile_type_str : str | |
| Name of tile_type this pin belongs to. | |
| wire_str : str | |
| Name of pin to get wire_in_tile rows for. | |
| Returns | |
| ------- | |
| wire_in_tile_pkeys : dict of int to int | |
| Map of site table primary keys to wire_in_tile primary keys. Unsplit | |
| tiles will always have only one dictionary entry. Split tiles may have | |
| more than one. | |
| site_pin_pkey : int | |
| Row into site_pin table for this pin. | |
| """ | |
| # Find the generic wire_in_tile_pkey for the specified tile_type name and | |
| # wire name. | |
| c = conn.cursor() | |
| # Find if this tile_type is a split tile. | |
| c.execute( | |
| """ | |
| SELECT | |
| site_pkey | |
| FROM | |
| site_as_tile | |
| WHERE | |
| parent_tile_type_pkey = ( | |
| SELECT | |
| pkey | |
| FROM | |
| tile_type | |
| WHERE | |
| name = ? | |
| ); | |
| """, (tile_type_str, ) | |
| ) | |
| result = c.fetchone() | |
| wire_is_pin = result is not None | |
| if wire_is_pin: | |
| # This tile is a split tile, lookup for the wire_in_tile_pkey is based | |
| # on the site pin name, rather than the wire name. | |
| site_pkey = result[0] | |
| c.execute( | |
| """ | |
| SELECT | |
| pkey, | |
| site_pin_pkey, | |
| site_pkey | |
| FROM | |
| wire_in_tile | |
| WHERE | |
| site_pin_pkey = ( | |
| SELECT | |
| pkey | |
| FROM | |
| site_pin | |
| WHERE | |
| site_type_pkey = ( | |
| SELECT | |
| site_type_pkey | |
| FROM | |
| site | |
| WHERE | |
| pkey = ? | |
| ) | |
| AND name = ? | |
| );""", (site_pkey, wire_str) | |
| ) | |
| else: | |
| c.execute( | |
| """ | |
| SELECT | |
| pkey, | |
| site_pin_pkey, | |
| site_pkey | |
| FROM | |
| wire_in_tile | |
| WHERE | |
| name = ? | |
| and tile_type_pkey = ( | |
| SELECT | |
| pkey | |
| FROM | |
| tile_type | |
| WHERE | |
| name = ? | |
| ); | |
| """, (wire_str, tile_type_str) | |
| ) | |
| wire_in_tile_pkeys = {} | |
| the_site_pin_pkey = None | |
| for wire_in_tile_pkey, site_pin_pkey, site_pkey in c: | |
| wire_in_tile_pkeys[site_pkey] = wire_in_tile_pkey | |
| if the_site_pin_pkey is not None: | |
| assert the_site_pin_pkey == site_pin_pkey, ( | |
| tile_type_str, wire_str | |
| ) | |
| else: | |
| the_site_pin_pkey = site_pin_pkey | |
| assert the_site_pin_pkey is not None, (tile_type_str, wire_str) | |
| return wire_in_tile_pkeys, the_site_pin_pkey |