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