def handle_edges_to_channels(conn, null_tile_wires, edge_assignments, channel_wires_to_tracks): c = conn.cursor() c.execute(""" SELECT vcc_track_pkey, gnd_track_pkey FROM constant_sources; """) vcc_track_pkey, gnd_track_pkey = c.fetchone() const_tracks = { 0: gnd_track_pkey, 1: vcc_track_pkey, } for node_pkey, classification in progressbar.progressbar( c.execute( """ SELECT pkey, classification FROM node WHERE classification != ?; """, (NodeClassification.CHANNEL.value, ))): reason = NodeClassification(classification) if reason == NodeClassification.NULL: for (tile_type, wire) in yield_wire_info_from_node(conn, node_pkey): null_tile_wires.add((tile_type, wire)) if reason != NodeClassification.EDGES_TO_CHANNEL: continue c2 = conn.cursor() for wire_pkey, tile_pkey, wire_in_tile_pkey in c2.execute( """ SELECT pkey, tile_pkey, wire_in_tile_pkey FROM wire WHERE node_pkey = ?; """, (node_pkey, )): c3 = conn.cursor() c3.execute(""" SELECT grid_x, grid_y FROM tile WHERE pkey = ?;""", (tile_pkey, )) (grid_x, grid_y) = c3.fetchone() c3.execute( """ SELECT name FROM tile_type WHERE pkey = ( SELECT tile_type_pkey FROM tile WHERE pkey = ? ); """, (tile_pkey, )) (tile_type, ) = c3.fetchone() wire = get_pin_name_of_wire(conn, wire_pkey) if wire is None: # This node has no site pin, don't need to assign pin direction. continue for pip_pkey, pip, src_wire_in_tile_pkey, dest_wire_in_tile_pkey in c3.execute( """ SELECT pkey, name, src_wire_in_tile_pkey, dest_wire_in_tile_pkey FROM pip_in_tile WHERE is_directional = 1 AND is_pseudo = 0 AND ( src_wire_in_tile_pkey = ? OR dest_wire_in_tile_pkey = ?);""", (wire_in_tile_pkey, wire_in_tile_pkey)): assert (src_wire_in_tile_pkey == wire_in_tile_pkey or dest_wire_in_tile_pkey == wire_in_tile_pkey), pip if src_wire_in_tile_pkey == wire_in_tile_pkey: other_wire_in_tile_pkey = dest_wire_in_tile_pkey else: other_wire_in_tile_pkey = src_wire_in_tile_pkey # Need to walk from the wire_in_tile table, to the wire table, # to the node table and get track_pkey. # other_wire_in_tile_pkey -> wire pkey -> node_pkey -> track_pkey c4 = conn.cursor() c4.execute( """ SELECT track_pkey, classification FROM node WHERE pkey = ( SELECT node_pkey FROM wire WHERE tile_pkey = ? AND wire_in_tile_pkey = ? );""", (tile_pkey, other_wire_in_tile_pkey)) result = c4.fetchone() assert result is not None, (wire_pkey, pip_pkey, tile_pkey, wire_in_tile_pkey, other_wire_in_tile_pkey) (track_pkey, classification) = result # Some pips do connect to a track at all, e.g. null node if track_pkey is None: # TODO: Handle weird connections. #other_node_class = NodeClassification(classification) #assert other_node_class == NodeClassification.NULL, ( # node_pkey, pip_pkey, pip, other_node_class) continue tracks_model = channel_wires_to_tracks[track_pkey] available_pins = set( pin_dir for _, pin_dir in tracks_model.get_tracks_for_wire_at_coord((grid_x, grid_y))) edge_assignments[(tile_type, wire)].append(available_pins) for constant in yield_ties_to_wire(wire): tracks_model = channel_wires_to_tracks[ const_tracks[constant]] available_pins = set( pin_dir for _, pin_dir in tracks_model.get_tracks_for_wire_at_coord((grid_x, grid_y))) edge_assignments[(tile_type, wire)].append(available_pins)
def handle_edges_to_channels(conn, null_tile_wires, edge_assignments, channel_wires_to_tracks): c = conn.cursor() c.execute(""" SELECT vcc_track_pkey, gnd_track_pkey FROM constant_sources; """) vcc_track_pkey, gnd_track_pkey = c.fetchone() const_tracks = { 0: gnd_track_pkey, 1: vcc_track_pkey, } for node_pkey, classification in progressbar_utils.progressbar( c.execute( """ SELECT pkey, classification FROM node WHERE classification != ?; """, (NodeClassification.CHANNEL.value, ))): reason = NodeClassification(classification) if reason == NodeClassification.NULL: for (tile_type, wire) in yield_logical_wire_info_from_node(conn, node_pkey): null_tile_wires.add((tile_type, wire)) if reason != NodeClassification.EDGES_TO_CHANNEL: continue c2 = conn.cursor() for wire_pkey, phy_tile_pkey, tile_pkey, wire_in_tile_pkey in c2.execute( """ SELECT pkey, phy_tile_pkey, tile_pkey, wire_in_tile_pkey FROM wire WHERE node_pkey = ?; """, (node_pkey, )): c3 = conn.cursor() c3.execute(""" SELECT grid_x, grid_y FROM tile WHERE pkey = ?;""", (tile_pkey, )) (grid_x, grid_y) = c3.fetchone() c3.execute( """ SELECT name FROM tile_type WHERE pkey = ( SELECT tile_type_pkey FROM tile WHERE pkey = ? ); """, (tile_pkey, )) (tile_type, ) = c3.fetchone() wire = get_pin_name_of_wire(conn, wire_pkey) if wire is None: # This node has no site pin, don't need to assign pin direction. continue for other_phy_tile_pkey, other_wire_in_tile_pkey, pip_pkey, pip in c3.execute( """ WITH wires_from_node(wire_in_tile_pkey, phy_tile_pkey) AS ( SELECT wire_in_tile_pkey, phy_tile_pkey FROM wire WHERE node_pkey = ? AND phy_tile_pkey IS NOT NULL ), other_wires(other_phy_tile_pkey, pip_pkey, other_wire_in_tile_pkey) AS ( SELECT wires_from_node.phy_tile_pkey, undirected_pips.pip_in_tile_pkey, undirected_pips.other_wire_in_tile_pkey FROM undirected_pips INNER JOIN wires_from_node ON undirected_pips.wire_in_tile_pkey = wires_from_node.wire_in_tile_pkey) SELECT other_wires.other_phy_tile_pkey, other_wires.other_wire_in_tile_pkey, pip_in_tile.pkey, pip_in_tile.name FROM other_wires INNER JOIN pip_in_tile ON pip_in_tile.pkey == other_wires.pip_pkey WHERE pip_in_tile.is_directional = 1 AND pip_in_tile.is_pseudo = 0; """, (node_pkey, )): # Need to walk from the wire_in_tile table, to the wire table, # to the node table and get track_pkey. # other_wire_in_tile_pkey -> wire pkey -> node_pkey -> track_pkey c4 = conn.cursor() c4.execute( """ SELECT track_pkey, classification FROM node WHERE pkey = ( SELECT node_pkey FROM wire WHERE phy_tile_pkey = ? AND wire_in_tile_pkey = ? );""", (other_phy_tile_pkey, other_wire_in_tile_pkey)) result = c4.fetchone() assert result is not None, (wire_pkey, pip_pkey, tile_pkey, wire_in_tile_pkey, other_wire_in_tile_pkey) (track_pkey, classification) = result # Some pips do connect to a track at all, e.g. null node if track_pkey is None: # TODO: Handle weird connections. #other_node_class = NodeClassification(classification) #assert other_node_class == NodeClassification.NULL, ( # node_pkey, pip_pkey, pip, other_node_class) continue tracks_model = channel_wires_to_tracks[track_pkey] available_pins = set( tracks_model.get_tracks_for_wire_at_coord( (grid_x, grid_y)).keys()) edge_assignments[(tile_type, wire)].append(available_pins) for constant in yield_ties_to_wire(wire): tracks_model = channel_wires_to_tracks[ const_tracks[constant]] available_pins = set( tracks_model.get_tracks_for_wire_at_coord( (grid_x, grid_y)).keys()) edge_assignments[(tile_type, wire)].append(available_pins)
def make_connection(conn, input_only_nodes, output_only_nodes, find_wire, find_pip, find_connector, tile_name, tile_type, pip, delayless_switch_pkey, const_connectors): """ Attempt to connect graph nodes on either side of a pip. Args: input_only_nodes (set of node_pkey): Nodes that can only be used as sinks. This is because a synthetic tile will use this node as a source. output_only_nodes (set of node_pkey): Nodes that can only be used as sources. This is because a synthetic tile will use this node as a sink. find_wire (function): Return value from create_find_wire. find_pip (function): Return value from create_find_pip. find_connector (function): Return value from create_find_connector. tile_name (str): Name of tile pip belongs too. pip (prjxray.tile.Pip): Pip being connected. switch_pkey (int): Primary key to switch table of switch to be used in this connection. Returns: None if connection cannot be made, otherwise returns tuple of: src_graph_node_pkey (int) - Primary key into graph_node table of source. dest_graph_node_pkey (int) - Primary key into graph_node table of destination. switch_pkey (int) - Primary key into switch table of switch used in connection. phy_tile_pkey (int) - Primary key into table of parent physical tile of the pip. pip_pkey (int) - Primary key into pip_in_tile table for this pip. """ src_wire_pkey, tile_pkey, phy_tile_pkey, src_node_pkey = find_wire( tile_name, tile_type, pip.net_from) sink_wire_pkey, tile_pkey2, phy_tile_pkey2, sink_node_pkey = find_wire( tile_name, tile_type, pip.net_to) assert phy_tile_pkey == phy_tile_pkey2 assert tile_pkey == tile_pkey2 c = conn.cursor() c.execute("SELECT grid_x, grid_y FROM tile WHERE pkey = ?", (tile_pkey, )) loc = grid_types.GridLoc(*c.fetchone()) # Skip nodes that are reserved because of ROI if src_node_pkey in input_only_nodes: return if sink_node_pkey in output_only_nodes: return src_connector = find_connector(src_wire_pkey, src_node_pkey) if src_connector is None: return sink_connector = find_connector(sink_wire_pkey, sink_node_pkey) if sink_connector is None: return pip_pkey, pip_is_directional, pip_is_pseudo, pip_can_invert = \ find_pip(tile_type, pip.name) assert not pip_is_pseudo for src_graph_node_pkey, switch_pkey, dest_graph_node_pkey in src_connector.connect_at( pip_pkey=pip_pkey, src_wire_pkey=src_wire_pkey, dest_wire_pkey=sink_wire_pkey, loc=loc, other_connector=sink_connector): yield (src_graph_node_pkey, dest_graph_node_pkey, switch_pkey, phy_tile_pkey, pip_pkey, False) if not pip_is_directional: for src_graph_node_pkey, switch_pkey, dest_graph_node_pkey in sink_connector.connect_at( pip_pkey=pip_pkey, src_wire_pkey=sink_wire_pkey, dest_wire_pkey=src_wire_pkey, loc=loc, other_connector=src_connector): yield (src_graph_node_pkey, dest_graph_node_pkey, switch_pkey, phy_tile_pkey, pip_pkey, True) # Make additional connections to constant network if the sink needs it. for constant_src in yield_ties_to_wire(pip.net_to): for src_graph_node_pkey, switch_pkey, dest_graph_node_pkey in const_connectors[ constant_src].connect_at(switch_pkey=delayless_switch_pkey, loc=loc, other_connector=sink_connector): yield (src_graph_node_pkey, dest_graph_node_pkey, switch_pkey, phy_tile_pkey, None, False)