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)
Пример #2
0
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)