| 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 |