import prjxray.db
from prjxray.roi import Roi
from prjxray.overlay import Overlay
from prjxray import grid_types
import simplejson as json
from lib import progressbar_utils
import datetime
import functools
from collections import namedtuple
from lib.rr_graph import tracks
from lib.rr_graph import graph2
from prjxray.site_type import SitePinDirection
from prjxray_constant_site_pins import yield_ties_to_wire
from lib.connection_database import get_track_model, get_wire_in_tile_from_pin_name
from lib.rr_graph.graph2 import NodeType
import re
import math
import numpy

from prjxray_db_cache import DatabaseCache

now = datetime.datetime.now


def get_node_type(conn, graph_node_pkey):
    """ Returns the node type of a given graph node"""

    c = conn.cursor()
    c.execute(
        """
        SELECT graph_node_type FROM graph_node WHERE pkey = ?""",
        (graph_node_pkey, )
    )

    return c.fetchone()[0]


def get_pins(conn, site_type, site_pin):
    """ Returns a set of the pin graph_nodes related to the input site type and pin names."""

    c = conn.cursor()
    c.execute(
        """
WITH pins(wire_in_tile_pkey) AS (
  SELECT wire_in_tile.pkey FROM wire_in_tile
  INNER JOIN site_pin ON site_pin.pkey = wire_in_tile.site_pin_pkey
  INNER JOIN site_type ON site_pin.site_type_pkey = site_type.pkey
  WHERE
    site_type.name == ?
  AND
    site_pin.name == ?
)
SELECT graph_node.pkey FROM graph_node
INNER JOIN wire ON graph_node.node_pkey = wire.node_pkey
WHERE
  wire.wire_in_tile_pkey IN (SELECT wire_in_tile_pkey FROM pins);
    """, (
            site_type,
            site_pin,
        )
    )

    return set(graph_node_pkey for (graph_node_pkey, ) in c.fetchall())


def add_graph_nodes_for_pins(conn, tile_type, wire, pin_directions):
    """ Adds graph_node rows for each pin on a wire in a tile. """

    (wire_in_tile_pkeys, site_pin_pkey) = get_wire_in_tile_from_pin_name(
        conn=conn, tile_type_str=tile_type, wire_str=wire
    )

    # Determine if this should be an IPIN or OPIN based on the site_pin
    # direction.
    c = conn.cursor()
    c.execute(
        """
        SELECT direction FROM site_pin WHERE pkey = ?;""", (site_pin_pkey, )
    )
    (pin_direction, ) = c.fetchone()

    pin_direction = SitePinDirection(pin_direction)
    if pin_direction == SitePinDirection.IN:
        node_type = NodeType.IPIN
    elif pin_direction == SitePinDirection.OUT:
        node_type = NodeType.OPIN
    # FIXME: Support INOUT pins
    elif pin_direction == SitePinDirection.INOUT:
        node_type = NodeType.OPIN
    else:
        assert False, pin_direction

    write_cur = conn.cursor()
    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")

    for wire_in_tile_pkey in wire_in_tile_pkeys.values():
        # Find all instances of this specific wire.
        c.execute(
            """
            SELECT pkey, node_pkey, tile_pkey
                FROM wire WHERE wire_in_tile_pkey = ?;""",
            (wire_in_tile_pkey, )
        )

        c3 = conn.cursor()

        for wire_pkey, node_pkey, tile_pkey in c:
            c3.execute(
                """
                SELECT grid_x, grid_y FROM tile WHERE pkey = ?;""",
                (tile_pkey, )
            )

            grid_x, grid_y = c3.fetchone()

            updates = []
            values = []

            # Insert a graph_node per pin_direction.
            for pin_direction in pin_directions:
                write_cur.execute(
                    """
                INSERT INTO graph_node(
                    graph_node_type, node_pkey, x_low, x_high, y_low, y_high)
                    VALUES (?, ?, ?, ?, ?, ?)""", (
                        node_type.value,
                        node_pkey,
                        grid_x,
                        grid_x,
                        grid_y,
                        grid_y,
                    )
                )

                updates.append(
                    '{}_graph_node_pkey = ?'.format(
                        pin_direction.name.lower()
                    )
                )
                values.append(write_cur.lastrowid)

            assert len(updates) > 0, (updates, wire_in_tile_pkey, wire_pkey)

            # Update the wire with the graph_nodes in each direction, if
            # applicable.
            write_cur.execute(
                """
                UPDATE wire SET {updates} WHERE pkey = ?;""".format(
                    updates=','.join(updates)
                ), values + [wire_pkey]
            )

    write_cur.execute("""COMMIT TRANSACTION;""")
    write_cur.connection.commit()


class KnownSwitch(object):
    def __init__(self, switch_pkey):
        self.switch_pkey = switch_pkey

    def get_pip_switch(self, src_wire_pkey, dest_wire_pkey):
        assert src_wire_pkey is None
        assert dest_wire_pkey is None
        return self.switch_pkey


class Pip(object):
    def __init__(self, c, tile_type, pip):
        self.c = c
        c.execute(
            """
SELECT
  pkey,
  src_wire_in_tile_pkey,
  dest_wire_in_tile_pkey,
  switch_pkey,
  backward_switch_pkey,
  is_directional,
  is_pseudo,
  can_invert
FROM
  pip_in_tile
WHERE
  name = ?
  AND tile_type_pkey = (
    SELECT
      pkey
    FROM
      tile_type
    WHERE
      name = ?
  );""", (pip, tile_type)
        )

        result = c.fetchone()
        assert result is not None, (tile_type, pip)
        (
            self.pip_pkey, self.src_wire_in_tile_pkey,
            self.dest_wire_in_tile_pkey, self.switch_pkey,
            self.backward_switch_pkey, self.is_directional, self.is_pseudo,
            self.can_invert
        ) = result
        assert self.switch_pkey is not None, (pip, tile_type)

        if self.is_directional:
            assert self.switch_pkey == self.backward_switch_pkey

    def __iter__(self):
        yield "pip_pkey", self.pip_pkey
        yield "src_wire_in_tile_pkey", self.src_wire_in_tile_pkey
        yield "dest_wire_in_tile_pkey", self.dest_wire_in_tile_pkey
        yield "switch_pkey", self.switch_pkey
        yield "backward_switch_pkey", self.backward_switch_pkey
        yield "is_directional", self.is_directional
        yield "is_pseudo", self.is_pseudo
        yield "can_invert", self.can_invert

    def get_pip_switch(self, src_wire_pkey, dest_wire_pkey):
        """ Return the switch_pkey for the given connection.

        Selects either normal or backward switch from pip, or if switch is
        already known, returns known switch.

        It is not valid to provide a switch and provide src/dest/pip arguments.

        Arguments
        ---------
        src_wire_pkey : int
            Source wire row primary key.
        dest_wire_pkey : int
            Destination wire row primary key.
        Returns
        -------
        Switch row primary key to connect through specified pip.

        """

        assert src_wire_pkey is not None
        assert dest_wire_pkey is not None

        if self.switch_pkey == self.backward_switch_pkey:
            return self.switch_pkey

        self.c.execute(
            "SELECT wire_in_tile_pkey FROM wire WHERE pkey = ?",
            (src_wire_pkey, )
        )
        src_wire_in_tile_pkey = self.c.fetchone()[0]

        self.c.execute(
            "SELECT wire_in_tile_pkey FROM wire WHERE pkey = ?",
            (dest_wire_pkey, )
        )
        dest_wire_in_tile_pkey = self.c.fetchone()[0]

        if src_wire_in_tile_pkey == self.src_wire_in_tile_pkey:
            assert dest_wire_in_tile_pkey == self.dest_wire_in_tile_pkey
            return self.switch_pkey
        else:
            assert src_wire_in_tile_pkey == self.dest_wire_in_tile_pkey
            assert dest_wire_in_tile_pkey == self.src_wire_in_tile_pkey
            return self.backward_switch_pkey


def create_find_pip(conn):
    """Returns a function that takes (tile_type, pip) and returns a tuple
     containing: pip_in_tile_pkey, is_directional, is_pseudo, can_invert"""
    c = conn.cursor()

    @functools.lru_cache(maxsize=None)
    def find_pip(tile_type, pip):
        return Pip(c, tile_type, pip)

    return find_pip


def create_find_wire(conn):
    """ Returns a function finds a wire based on tile name and wire name.

    Args:
        conn: Database connection

    Returns:
        Function.  See find_wire below for signature.
    """
    c = conn.cursor()

    @functools.lru_cache(maxsize=None)
    def find_wire_in_tile(tile_type, wire):
        c.execute(
            """
SELECT
  pkey
FROM
  wire_in_tile
WHERE
  name = ?
  AND phy_tile_type_pkey = (
    SELECT
      pkey
    FROM
      tile_type
    WHERE
      name = ?
  );""", (wire, tile_type)
        )

        result = c.fetchone()
        assert result is not None, (tile_type, wire)
        return result[0]

    @functools.lru_cache(maxsize=100000)
    def find_wire(phy_tile, tile_type, wire):
        """ Finds a wire in the database.

        Args:
            phy_tile (str): Physical tile name
            tile_type (str): Type of tile name
            wire (str): Wire name

        Returns:
            Tuple (wire_pkey, phy_tile_pkey, node_pkey), where:
                wire_pkey (int): Primary key of wire table
                tile_pkey (int): Primary key of VPR tile row that contains
                    this wire.
                phy_tile_pkey (int): Primary key of physical tile row that
                    contains this wire.
                node_pkey (int): Primary key of node table that is the node
                    this wire belongs too.
        """

        wire_in_tile_pkey = find_wire_in_tile(tile_type, wire)
        c.execute(
            """
SELECT
  pkey,
  tile_pkey,
  phy_tile_pkey,
  node_pkey
FROM
  wire
WHERE
  wire_in_tile_pkey = ?
  AND phy_tile_pkey = (
    SELECT
      pkey
    FROM
      phy_tile
    WHERE
      name = ?
  );""", (wire_in_tile_pkey, phy_tile)
        )

        result = c.fetchone()
        assert result is not None, (
            phy_tile, tile_type, wire, wire_in_tile_pkey
        )
        return result

    return find_wire


Pins = namedtuple('Pins', 'x y edge_map site_pin_direction')

OPPOSITE_DIRECTIONS = {
    tracks.Direction.TOP: tracks.Direction.BOTTOM,
    tracks.Direction.BOTTOM: tracks.Direction.TOP,
    tracks.Direction.LEFT: tracks.Direction.RIGHT,
    tracks.Direction.RIGHT: tracks.Direction.LEFT,
}


class Connector(object):
    """ Connector is an object for joining two nodes.

    Connector represents either a site pin within a specific tile or routing
    channel made of one or more channel nodes.


    """

    def __init__(self, conn, pins=None, tracks=None):
        """ Create a Connector object.

        Provide either pins or tracks, not both or neither.

        Args:
            pins (Pins namedtuple): If this Connector object represents a
                site pin, provide the pins named arguments.
            tracks (tuple of (tracks.Tracks, list of graph nodes)): If this
                Connector object represents a routing channel, provide the
                tracks named argument.

                The tuple can most easily be constructed via
                connection_database.get_track_model, which builds the Tracks
                models and the graph node list.
        """
        self.conn = conn
        self.pins = pins
        self.tracks = tracks
        self.track_connections = {}
        assert (self.pins is not None) ^ (self.tracks is not None)

    def find_wire_node(
            self, wire_pkey, graph_node_pkey, track_graph_node_pkey
    ):
        """ Find/create graph node for site pin.

        In order to support site pin timing modelling, an additional node
        is required to support the timing model.  This function returns that
        node, along with the switch that should be used to connect the
        IPIN/OPIN to that node. See diagram for details.

        Arguments
        ---------
        wire_pkey : int
            Wire primary key to a wire attached to a site pin.
        graph_node_pkey : int
            Graph node primary key that represents which IPIN/OPIN node is
            being used to connect the site pin to the routing graph.
        track_graph_node_pkey : int
            Graph node primary key that represents the first routing node this
            site pin connects too.  See diagram for details.

        Returns
        -------
        site_pin_switch_pkey : int
            Switch primary key to the switch to connect IPIN/OPIN node to
            new site pin wire node.  See diagram for details.
        site_pin_graph_node_pkey : int
            Graph node primary key that represents site pin wire node.
            See diagram for details.

        Diagram:

           --+
             |    tile wire #1  +-----+ tile wire #2
             +==>-------------->+ pip +--------------->
             | ^-Site pin       +-----+
           --+

            +----+           +-----+            +-----+
            |OPIN+--edge #1->+CHAN1+--edge #2-->+CHAN2|->
            +----+           +-----+            +-----+

        The timing information from the site pin is encoded in edge #1.
        The timing information from tile wire #1 is encoded in CHAN1.
        The timing information from pip is encoded in edge #2.
        The remaining timing information is encoded in edges and channels
        as expected.

        This function returns edge #1 as the site_pin_switch_pkey.
        This function returns CHAN1 as site_pin_graph_node_pkey.

        The diagram for an IPIN is the same, except reverse all the arrows.

        """
        cur = self.conn.cursor()

        cur.execute(
            """
    SELECT site_wire_pkey FROM node WHERE pkey = (
        SELECT node_pkey FROM wire WHERE pkey = ?
        )
        """, (wire_pkey, )
        )
        site_wire_pkey = cur.fetchone()[0]

        cur.execute(
            """
SELECT
    node_pkey,
    top_graph_node_pkey,
    bottom_graph_node_pkey,
    right_graph_node_pkey,
    left_graph_node_pkey,
    site_pin_graph_node_pkey
FROM wire WHERE pkey = ?""", (site_wire_pkey, )
        )
        values = cur.fetchone()
        node_pkey = values[0]
        edge_nodes = values[1:5]
        site_pin_graph_node_pkey = values[5]

        cur.execute(
            """
SELECT
  site_pin_switch_pkey
FROM
  wire_in_tile
WHERE
  site_pin_switch_pkey IS NOT NULL
AND
  pkey IN (
    SELECT
      wire_in_tile_pkey
    FROM
      wire
    WHERE
      node_pkey IN (
        SELECT
          node_pkey
        FROM
          wire
        WHERE
          pkey = ?
    )
  )""", (wire_pkey, )
        )
        results = cur.fetchall()
        assert len(results) == 1, (wire_pkey, results)
        site_pin_switch_pkey = results[0][0]
        assert site_pin_switch_pkey is not None, wire_pkey

        assert graph_node_pkey in edge_nodes, (
            wire_pkey, graph_node_pkey, track_graph_node_pkey, edge_nodes
        )

        if site_pin_graph_node_pkey is None:
            assert track_graph_node_pkey is not None, (
                wire_pkey, graph_node_pkey, track_graph_node_pkey, edge_nodes
            )

            is_lv_node = False
            for (name, ) in cur.execute("""
SELECT wire_in_tile.name
FROM wire_in_tile
WHERE pkey IN (
    SELECT wire_in_tile_pkey FROM wire WHERE node_pkey = ?
)""", (node_pkey, )):
                if name.startswith('LV'):
                    is_lv_node = True
                    break

            capacitance = 0
            resistance = 0
            for idx, (wire_cap, wire_res) in enumerate(cur.execute("""
SELECT wire_in_tile.capacitance, wire_in_tile.resistance
FROM wire_in_tile
WHERE pkey IN (
    SELECT wire_in_tile_pkey FROM wire WHERE node_pkey = ?
)""", (node_pkey, ))):
                capacitance += wire_cap
                resistance + wire_res

                if is_lv_node and idx == 1:
                    # Only use first 2 wire RC's, ignore the rest.  It appears
                    # that some of the RC constant was lumped into the switch
                    # timing, so don't double count.
                    #
                    # FIXME: Note that this is a hack, and should be fixed if
                    # possible.
                    break

            # This node does not exist, create it now
            write_cur = self.conn.cursor()

            write_cur.execute("INSERT INTO track DEFAULT VALUES")
            new_track_pkey = write_cur.lastrowid

            write_cur.execute(
                """
INSERT INTO
    graph_node(
        graph_node_type,
        node_pkey,
        x_low,
        x_high,
        y_low,
        y_high,
        capacity,
        capacitance,
        resistance,
        track_pkey)
SELECT
    graph_node_type,
    ?,
    x_low,
    x_high,
    y_low,
    y_high,
    capacity,
    ?,
    ?,
    ?
FROM graph_node WHERE pkey = ?""", (
                    node_pkey,
                    capacitance,
                    resistance,
                    new_track_pkey,
                    track_graph_node_pkey,
                )
            )
            site_pin_graph_node_pkey = write_cur.lastrowid

            write_cur.execute(
                """
UPDATE wire SET site_pin_graph_node_pkey = ?
WHERE pkey = ?""", (
                    site_pin_graph_node_pkey,
                    wire_pkey,
                )
            )

            write_cur.connection.commit()

        return site_pin_switch_pkey, site_pin_graph_node_pkey

    def get_edge_with_mux_switch(
            self, src_wire_pkey, pip_pkey, dest_wire_pkey
    ):
        """ Return switch_pkey for EDGE_WITH_MUX instance. """
        cur = self.conn.cursor()

        cur.execute(
            """
SELECT site_wire_pkey FROM node WHERE pkey = (
    SELECT node_pkey FROM wire WHERE pkey = ?
    );""", (src_wire_pkey, )
        )
        src_site_wire_pkey = cur.fetchone()[0]

        cur.execute(
            """
SELECT site_wire_pkey FROM node WHERE pkey = (
    SELECT node_pkey FROM wire WHERE pkey = ?
    );""", (dest_wire_pkey, )
        )
        dest_site_wire_pkey = cur.fetchone()[0]

        cur.execute(
            """
SELECT switch_pkey FROM edge_with_mux WHERE
    src_wire_pkey = ?
AND
    dest_wire_pkey = ?
AND
    pip_in_tile_pkey = ?""", (
                src_site_wire_pkey,
                dest_site_wire_pkey,
                pip_pkey,
            )
        )
        result = cur.fetchone()
        assert result is not None, (
            src_site_wire_pkey,
            dest_site_wire_pkey,
            pip_pkey,
        )
        return result[0]

    def find_connection_at_loc(self, loc):
        assert self.tracks is not None
        tracks_model, graph_nodes = self.tracks
        if loc not in self.track_connections:
            for idx in tracks_model.get_tracks_for_wire_at_coord(loc).values():
                break

            self.track_connections[loc] = idx
        else:
            idx = self.track_connections[loc]

        assert idx is not None

        return idx

    def connect_at(
            self,
            loc,
            other_connector,
            pip,
            src_wire_pkey=None,
            dest_wire_pkey=None,
    ):
        """ Connect two Connector objects at a location within the grid.

        Arguments
        ---------
        loc : prjxray.grid_types.GridLoc
            Location within grid to make connection.
        other_connector : Connector
            Destination connection.
        src_wire_pkey : int
            Source wire pkey of pip being connected.
        dest_wire_pkey : int
            Destination wire pkey of pip being connected.
        pip : Pip
            Pip object of pip being connected.

        Returns:
            Tuple of (src_graph_node_pkey, dest_graph_node_pkey)

        """

        if self.tracks and other_connector.tracks:
            tracks_model, graph_nodes = self.tracks
            idx1 = self.find_connection_at_loc(loc)

            other_tracks_model, other_graph_nodes = other_connector.tracks
            idx2 = other_connector.find_connection_at_loc(loc)

            switch_pkey = pip.get_pip_switch(src_wire_pkey, dest_wire_pkey)

            yield graph_nodes[idx1], switch_pkey, other_graph_nodes[
                idx2], pip.pip_pkey
            return
        elif self.pins and other_connector.tracks:
            assert self.pins.site_pin_direction == SitePinDirection.OUT

            tracks_model, graph_nodes = other_connector.tracks
            for pin_dir, idx in tracks_model.get_tracks_for_wire_at_coord(
                    grid_types.GridLoc(self.pins.x, self.pins.y)).items():
                if pin_dir in self.pins.edge_map:
                    # Site pin -> Interconnect is modelled as:
                    #
                    # OPIN -> edge (Site pin) -> Wire CHAN -> edge (PIP) -> Interconnect CHAN node
                    #
                    src_node = self.pins.edge_map[pin_dir]
                    dest_track_node = graph_nodes[idx]
                    site_pin_switch_pkey, src_wire_node = self.find_wire_node(
                        src_wire_pkey, src_node, dest_track_node
                    )

                    switch_pkey = pip.get_pip_switch(
                        src_wire_pkey, dest_wire_pkey
                    )
                    yield (src_node, site_pin_switch_pkey, src_wire_node, None)
                    yield (
                        src_wire_node, switch_pkey, dest_track_node,
                        pip.pip_pkey
                    )
                    return
        elif self.tracks and other_connector.pins:
            assert other_connector.pins.site_pin_direction == SitePinDirection.IN

            tracks_model, graph_nodes = self.tracks
            for pin_dir, idx in tracks_model.get_tracks_for_wire_at_coord(
                    grid_types.GridLoc(other_connector.pins.x,
                                       other_connector.pins.y)).items():
                if pin_dir in other_connector.pins.edge_map:
                    # Interconnect -> Site pin is modelled as:
                    #
                    # Interconnect CHAN node -> edge (PIP) -> Wire CHAN -> edge (Site pin) -> IPIN
                    #
                    src_track_node = graph_nodes[idx]
                    dest_node = other_connector.pins.edge_map[pin_dir]
                    site_pin_switch_pkey, dest_wire_node = self.find_wire_node(
                        dest_wire_pkey, dest_node, src_track_node
                    )

                    switch_pkey = pip.get_pip_switch(
                        src_wire_pkey, dest_wire_pkey
                    )
                    yield (
                        src_track_node, switch_pkey, dest_wire_node,
                        pip.pip_pkey
                    )
                    yield (
                        dest_wire_node, site_pin_switch_pkey, dest_node, None
                    )
                    return

        elif self.pins and other_connector.pins and not pip.is_pseudo:
            assert self.pins.site_pin_direction == SitePinDirection.OUT, dict(
                pip
            )
            assert other_connector.pins.site_pin_direction == SitePinDirection.IN, dict(
                pip
            )

            switch_pkey = self.get_edge_with_mux_switch(
                src_wire_pkey, pip.pip_pkey, dest_wire_pkey
            )

            if len(self.pins.edge_map) == 1 and len(
                    other_connector.pins.edge_map) == 1:
                # If there is only one choice, make it.
                src_node = list(self.pins.edge_map.values())[0]
                dest_node = list(other_connector.pins.edge_map.values())[0]

                yield (src_node, switch_pkey, dest_node, pip.pip_pkey)
                return

            for pin_dir in self.pins.edge_map:
                if OPPOSITE_DIRECTIONS[pin_dir
                                       ] in other_connector.pins.edge_map:
                    src_node = self.pins.edge_map[pin_dir]
                    dest_node = other_connector.pins.edge_map[
                        OPPOSITE_DIRECTIONS[pin_dir]]
                    yield (src_node, switch_pkey, dest_node, pip.pip_pkey)
                    return

        # If there is a pseudo pip that needs to be explicitly routed through,
        # two CHAN nodes are first created before and after IPIN and OPIN and
        # connected with an edge accordingly
        elif self.pins and other_connector.pins and pip.is_pseudo:
            switch_pkey = pip.get_pip_switch(src_wire_pkey, dest_wire_pkey)

            for pin_dir in self.pins.edge_map:
                if pin_dir in other_connector.pins.edge_map:
                    src_node = self.pins.edge_map[pin_dir]
                    src_node_type = get_node_type(self.conn, src_node)
                    assert NodeType(
                        src_node_type
                    ) == NodeType.IPIN, "src node for ppip is not an IPIN ({}, {})".format(
                        src_node, src_node_type
                    )

                    dest_node = other_connector.pins.edge_map[pin_dir]
                    dest_node_type = get_node_type(self.conn, dest_node)
                    assert NodeType(
                        dest_node_type
                    ) == NodeType.OPIN, "dest node for ppip is not an OPIN ({}, {})".format(
                        src_node, dest_node_type
                    )

                    src_wire_switch_pkey, src_wire_node = self.find_wire_node(
                        src_wire_pkey, src_node, None
                    )

                    dest_wire_switch_pkey, dest_wire_node = self.find_wire_node(
                        dest_wire_pkey, dest_node, None
                    )

                    yield (
                        src_wire_node, switch_pkey, dest_wire_node,
                        pip.pip_pkey
                    )
                    return

        assert False, (
            self.tracks, self.pins, other_connector.tracks,
            other_connector.pins, loc
        )


def create_find_connector(conn):
    """ Returns a function returns a Connector object for a given wire and node.

    Args:
        conn: Database connection

    Returns:
        Function.  See find_connector below for signature.
    """
    c = conn.cursor()

    @functools.lru_cache(maxsize=100000)
    def find_connector(wire_pkey, node_pkey):
        """ Finds Connector for a wire and node in the database.

        Args:
            wire_pkey (int): Primary key into wire table of target wire
            node_pkey (int): Primary key into node table of parent node of
                specified wire.

        Returns:
            None if wire is disconnected, otherwise returns Connector objet.
        """

        # Find all graph_nodes for this node.
        c.execute(
            """
        SELECT pkey, track_pkey, graph_node_type, x_low, x_high, y_low, y_high FROM graph_node
        WHERE node_pkey = ?;""", (node_pkey, )
        )

        graph_nodes = c.fetchall()

        # If there are no graph nodes, this wire is likely disconnected.
        if len(graph_nodes) == 0:
            return

        # If this is a track (e.g. track_pkey is not NULL), then verify
        # all graph_nodes for the specified node belong to the same track,
        # and then retrieved and return the connector for the track.
        track_pkey = graph_nodes[0][1]
        if track_pkey is not None:
            for node in graph_nodes:
                assert node[1] == track_pkey

            return Connector(
                conn=conn, tracks=get_track_model(conn, track_pkey)
            )

        # Check if this node has a special track.  This is being used to
        # denote the GND and VCC track connections on TIEOFF HARD0 and HARD1.
        c.execute(
            """
SELECT
  track_pkey,
  site_wire_pkey
FROM
  node
WHERE
  pkey = ?;""", (node_pkey, )
        )
        for track_pkey, site_wire_pkey in c:
            if track_pkey is not None and site_wire_pkey is not None:
                return Connector(
                    conn=conn, tracks=get_track_model(conn, track_pkey)
                )

        # This is not a track, so it must be a site pin.  Make sure the
        # graph_nodes share a type and verify that it is in fact a site pin.
        node_type = graph2.NodeType(graph_nodes[0][2])
        for node in graph_nodes:
            assert node_type == graph2.NodeType(
                node[2]
            ), (node_pkey, node_type, graph2.NodeType(node[2]))

        assert node_type in [graph2.NodeType.IPIN, graph2.NodeType.OPIN]
        if node_type == graph2.NodeType.IPIN:
            site_pin_direction = SitePinDirection.IN
        elif node_type == graph2.NodeType.OPIN:
            site_pin_direction = SitePinDirection.OUT
        else:
            assert False, node_type

        # Build the edge_map (map of edge direction to graph node).
        c.execute(
            """
SELECT
  top_graph_node_pkey,
  bottom_graph_node_pkey,
  left_graph_node_pkey,
  right_graph_node_pkey
FROM
  wire
WHERE
  node_pkey = ?;""", (node_pkey, )
        )

        all_graph_node_pkeys = c.fetchall()

        graph_node_pkeys = None
        for keys in all_graph_node_pkeys:
            if any(keys):
                assert graph_node_pkeys is None
                graph_node_pkeys = keys

        # This wire may not have an connections, if so return now.
        if graph_node_pkeys is None:
            return

        edge_map = {}

        for edge, graph_node in zip(
            (
                tracks.Direction.TOP,
                tracks.Direction.BOTTOM,
                tracks.Direction.LEFT,
                tracks.Direction.RIGHT,
            ),
                graph_node_pkeys,
        ):
            if graph_node is not None:
                edge_map[edge] = graph_node

        assert len(edge_map) == len(graph_nodes), (
            edge_map, graph_node_pkeys, graph_nodes
        )

        # Make sure that all graph nodes for this wire are in the edge_map
        # and at the same grid coordinate.
        x = graph_nodes[0][3]
        y = graph_nodes[0][5]
        for pkey, _, _, x_low, x_high, y_low, y_high in graph_nodes:
            assert x == x_low, (wire_pkey, node_pkey, x, x_low, x_high)
            assert x == x_high, (wire_pkey, node_pkey, x, x_low, x_high)

            assert y == y_low, (wire_pkey, node_pkey, y, y_low, y_high)
            assert y == y_high, (wire_pkey, node_pkey, y, y_low, y_high)

            assert pkey in edge_map.values(), (pkey, edge_map)

        return Connector(
            conn=conn,
            pins=Pins(
                edge_map=edge_map,
                x=x,
                y=y,
                site_pin_direction=site_pin_direction,
            )
        )

    return find_connector


def create_const_connectors(conn):
    c = conn.cursor()
    c.execute(
        """
SELECT vcc_track_pkey, gnd_track_pkey FROM constant_sources;
    """
    )
    vcc_track_pkey, gnd_track_pkey = c.fetchone()

    const_connectors = {}
    const_connectors[0] = Connector(
        conn=conn, tracks=get_track_model(conn, gnd_track_pkey)
    )
    const_connectors[1] = Connector(
        conn=conn, tracks=get_track_model(conn, vcc_track_pkey)
    )

    return const_connectors


def create_get_tile_loc(conn):
    c = conn.cursor()

    @functools.lru_cache(maxsize=None)
    def get_tile_loc(tile_pkey):
        c.execute(
            "SELECT grid_x, grid_y FROM tile WHERE pkey = ?", (tile_pkey, )
        )
        return grid_types.GridLoc(*c.fetchone())

    return get_tile_loc


def yield_edges(
        const_connectors, delayless_switch, phy_tile_pkey, src_connector,
        sink_connector, pip, pip_obj, src_wire_pkey, sink_wire_pkey, loc,
        forward
):
    if forward:
        for (src_graph_node_pkey, switch_pkey, dest_graph_node_pkey,
             pip_pkey) in src_connector.connect_at(
                 pip=pip_obj, src_wire_pkey=src_wire_pkey,
                 dest_wire_pkey=sink_wire_pkey, loc=loc,
                 other_connector=sink_connector):
            assert switch_pkey is not None, (
                pip, src_graph_node_pkey, dest_graph_node_pkey, phy_tile_pkey,
                pip_pkey
            )
            yield (
                src_graph_node_pkey, dest_graph_node_pkey, switch_pkey,
                phy_tile_pkey, pip_pkey, False
            )

    if not forward and not pip.is_directional:
        for (src_graph_node_pkey, switch_pkey, dest_graph_node_pkey,
             pip_pkey) in sink_connector.connect_at(
                 pip=pip_obj, src_wire_pkey=sink_wire_pkey,
                 dest_wire_pkey=src_wire_pkey, loc=loc,
                 other_connector=src_connector):
            assert switch_pkey is not None, (
                pip, src_graph_node_pkey, dest_graph_node_pkey, phy_tile_pkey,
                pip_pkey
            )
            yield (
                src_graph_node_pkey, dest_graph_node_pkey, switch_pkey,
                phy_tile_pkey, pip_pkey, True
            )

    if forward:
        # 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(
                     pip=delayless_switch, loc=loc,
                     other_connector=sink_connector):
                assert switch_pkey is not None, (
                    pip, src_graph_node_pkey, dest_graph_node_pkey,
                    phy_tile_pkey, pip_pkey
                )
                yield (
                    src_graph_node_pkey, dest_graph_node_pkey, switch_pkey,
                    phy_tile_pkey, None, False
                )


def make_connection(
        conn, input_only_nodes, output_only_nodes, find_wire, find_pip,
        find_connector, get_tile_loc, tile_name, tile_type, pip,
        delayless_switch, const_connectors, forward
):
    """ 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

    # 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_obj = find_pip(tile_type, pip.name)

    # Generally pseudo-pips are skipped, with the exception for BUFHCE related pips,
    # for which we want to create a routing path to have VPR route thorugh these pips.
    assert not pip_obj.is_pseudo or "CLK_HROW_CK" in pip.name

    loc = get_tile_loc(tile_pkey)

    for edge in yield_edges(
            const_connectors=const_connectors,
            delayless_switch=delayless_switch, phy_tile_pkey=phy_tile_pkey,
            src_connector=src_connector, sink_connector=sink_connector,
            pip=pip, pip_obj=pip_obj, src_wire_pkey=src_wire_pkey,
            sink_wire_pkey=sink_wire_pkey, loc=loc, forward=forward):
        yield edge


def mark_track_liveness(conn, input_only_nodes, output_only_nodes):
    """ Checks tracks for liveness.

    Iterates over all graph nodes that are routing tracks and determines if
    at least one graph edge originates from or two the track.

    Args:
        conn (sqlite3.Connection): Connection database

    """

    alive_tracks = set()
    c = conn.cursor()
    write_cur = conn.cursor()
    for graph_node_pkey, node_pkey, track_pkey in c.execute("""
SELECT
  pkey,
  node_pkey,
  track_pkey
FROM
  graph_node
WHERE
  track_pkey IS NOT NULL;"""):
        if track_pkey in alive_tracks:
            continue

        if node_pkey in input_only_nodes or node_pkey in output_only_nodes:
            alive_tracks.add(track_pkey)
            continue

        write_cur.execute(
            """SELECT count(switch_pkey) FROM graph_edge WHERE
            src_graph_node_pkey = ?;""", (graph_node_pkey, )
        )
        src_count = write_cur.fetchone()[0]

        write_cur.execute(
            """SELECT count(switch_pkey) FROM graph_edge WHERE
            dest_graph_node_pkey = ?;""", (graph_node_pkey, )
        )
        sink_count = write_cur.fetchone()[0]

        write_cur.execute(
            """
SELECT count() FROM (
  SELECT dest_graph_node_pkey FROM graph_edge WHERE src_graph_node_pkey = ?
  UNION
  SELECT src_graph_node_pkey FROM graph_edge WHERE dest_graph_node_pkey = ?
  );""", (graph_node_pkey, graph_node_pkey)
        )
        active_other_nodes = write_cur.fetchone()[0]

        if src_count > 0 and sink_count > 0 and active_other_nodes > 1:
            alive_tracks.add(track_pkey)

    c.execute("SELECT count(pkey) FROM track;")
    track_count = c.fetchone()[0]
    print(
        "{} Alive tracks {} / {}".format(
            now(), len(alive_tracks), track_count
        )
    )

    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")
    for (track_pkey, ) in c.execute("""SELECT pkey FROM track;"""):
        write_cur.execute(
            "UPDATE track SET alive = ? WHERE pkey = ?;",
            (track_pkey in alive_tracks, track_pkey)
        )
    write_cur.execute("""COMMIT TRANSACTION;""")

    print('{} Track aliveness committed'.format(now()))

    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")
    write_cur.execute("""CREATE INDEX alive_tracks ON track(alive);""")
    write_cur.execute(
        """CREATE INDEX graph_node_x_index ON graph_node(x_low);"""
    )
    write_cur.execute(
        """CREATE INDEX graph_node_y_index ON graph_node(y_low);"""
    )
    write_cur.execute("""COMMIT TRANSACTION;""")


def direction_to_enum(pin):
    """ Converts string to tracks.Direction. """
    for direction in tracks.Direction:
        if direction._name_ == pin:
            return direction

    assert False


def build_channels(conn):
    x_channel_models = {}
    y_channel_models = {}

    cur = conn.cursor()

    cur.execute(
        """
SELECT MIN(x_low), MAX(x_high), MIN(y_low), MAX(y_high) FROM graph_node
INNER JOIN track
ON track.pkey = graph_node.track_pkey
WHERE track.alive;"""
    )
    x_min, x_max, y_min, y_max = cur.fetchone()

    for x in progressbar_utils.progressbar(range(x_min, x_max + 1)):
        cur.execute(
            """
SELECT
    graph_node.y_low,
    graph_node.y_high,
    graph_node.pkey
FROM graph_node
INNER JOIN track
ON track.pkey = graph_node.track_pkey
WHERE
    track_pkey IS NOT NULL
AND
    track.alive
AND
    graph_node_type = ?
AND
    x_low = ?;""", (graph2.NodeType.CHANY.value, x)
        )

        data = list(cur)
        y_channel_models[x] = graph2.process_track(data)

    for y in progressbar_utils.progressbar(range(y_min, y_max + 1)):
        cur.execute(
            """
SELECT
    graph_node.x_low,
    graph_node.x_high,
    graph_node.pkey
FROM graph_node
INNER JOIN track
ON track.pkey = graph_node.track_pkey
WHERE
    track_pkey IS NOT NULL
AND
    track.alive
AND
    graph_node_type = ?
AND
    y_low = ?;""", (graph2.NodeType.CHANX.value, y)
        )

        data = list(cur)
        x_channel_models[y] = graph2.process_track(data)

    x_list = []
    y_list = []

    write_cur = conn.cursor()
    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")

    for y in progressbar_utils.progressbar(range(y_max + 1)):
        if y in x_channel_models:
            x_list.append(len(x_channel_models[y].trees))

            for idx, tree in enumerate(x_channel_models[y].trees):
                for i in tree:
                    write_cur.execute(
                        'UPDATE graph_node SET ptc = ? WHERE pkey = ?;',
                        (idx, i[2])
                    )
        else:
            x_list.append(0)

    for x in progressbar_utils.progressbar(range(x_max + 1)):
        if x in y_channel_models:
            y_list.append(len(y_channel_models[x].trees))

            for idx, tree in enumerate(y_channel_models[x].trees):
                for i in tree:
                    write_cur.execute(
                        'UPDATE graph_node SET ptc = ? WHERE pkey = ?;',
                        (idx, i[2])
                    )
        else:
            y_list.append(0)

    write_cur.execute(
        """
    INSERT INTO channel(chan_width_max, x_min, x_max, y_min, y_max) VALUES
        (?, ?, ?, ?, ?);""",
        (max(max(x_list), max(y_list)), x_min, x_max, y_min, y_max)
    )

    for idx, info in enumerate(x_list):
        write_cur.execute(
            """
        INSERT INTO x_list(idx, info) VALUES (?, ?);""", (idx, info)
        )

    for idx, info in enumerate(y_list):
        write_cur.execute(
            """
        INSERT INTO y_list(idx, info) VALUES (?, ?);""", (idx, info)
        )

    write_cur.execute("""COMMIT TRANSACTION;""")


def verify_channels(conn):
    """ Verify PTC numbers in channels.
    No duplicate PTC's.

    Violation of this requirement results in a check failure during rr graph
    loading.

    """

    c = conn.cursor()

    chan_ptcs = {}

    for (graph_node_pkey, alive, graph_node_type, x_low, x_high, y_low, y_high,
         ptc, capacity) in c.execute(
             """
SELECT
    graph_node.pkey,
    track.alive,
    graph_node.graph_node_type,
    graph_node.x_low,
    graph_node.x_high,
    graph_node.y_low,
    graph_node.y_high,
    graph_node.ptc,
    graph_node.capacity
FROM graph_node
INNER JOIN track
ON graph_node.track_pkey = track.pkey
WHERE (graph_node_type = ? or graph_node_type = ?);""",
             (graph2.NodeType.CHANX.value, graph2.NodeType.CHANY.value)):

        if not alive and capacity != 0:
            assert ptc is None, graph_node_pkey
            continue

        assert ptc is not None, graph_node_pkey

        for x in range(x_low, x_high + 1):
            for y in range(y_low, y_high + 1):
                key = (graph_node_type, x, y)
                if key not in chan_ptcs:
                    chan_ptcs[key] = []

                chan_ptcs[key].append((graph_node_pkey, ptc))

    for key in chan_ptcs:
        ptcs = {}
        for graph_node_pkey, ptc in chan_ptcs[key]:
            assert ptc not in ptcs, (ptcs[ptc], graph_node_pkey)
            ptcs[ptc] = graph_node_pkey


def set_pin_connection(
        conn, write_cur, pin_graph_node_pkey, forward, graph_node_pkey, tracks
):
    """ Sets pin connection box location canonical location.

    Tracks that are a part of the pinfeed also get this location.

    """
    cur = conn.cursor()
    cur2 = conn.cursor()
    cur.execute(
        """SELECT node_pkey, graph_node_type FROM graph_node WHERE pkey = ?""",
        (pin_graph_node_pkey, )
    )
    pin_node_pkey, graph_node_type = cur.fetchone()

    source_wires = []
    sink_wires = []
    cur.execute(
        """SELECT pkey FROM wire WHERE node_pkey = (
        SELECT node_pkey FROM graph_node WHERE pkey = ?
        )""", (graph_node_pkey, )
    )
    for (wire_pkey, ) in cur:
        cur2.execute(
            """SELECT count() FROM pip_in_tile WHERE src_wire_in_tile_pkey = (
            SELECT wire_in_tile_pkey FROM wire WHERE pkey = ?
            ) AND pip_in_tile.is_pseudo = 0""", (wire_pkey, )
        )
        has_forward_pip = cur2.fetchone()[0]

        cur2.execute(
            """SELECT count() FROM pip_in_tile WHERE dest_wire_in_tile_pkey = (
            SELECT wire_in_tile_pkey FROM wire WHERE pkey = ?
            ) AND pip_in_tile.is_pseudo = 0""", (wire_pkey, )
        )
        has_backward_pip = cur2.fetchone()[0]

        if forward:
            if has_forward_pip:
                source_wires.append(wire_pkey)
            if has_backward_pip:
                sink_wires.append(wire_pkey)
        else:
            if has_forward_pip:
                sink_wires.append(wire_pkey)
            if has_backward_pip:
                source_wires.append(wire_pkey)

    if len(source_wires) > 1:
        if forward:
            # Ambiguous output location, just use input pips, which should
            # have only 1 phy_tile location.
            cur2.execute(
                """
WITH wires_in_graph_node(phy_tile_pkey, phy_tile_type_pkey, wire_in_tile_pkey) AS (
    SELECT wire.phy_tile_pkey, phy_tile.tile_type_pkey, wire.wire_in_tile_pkey
    FROM graph_node
    INNER JOIN wire ON wire.node_pkey = graph_node.node_pkey
    INNER JOIN phy_tile ON wire.phy_tile_pkey = phy_tile.pkey
    WHERE graph_node.pkey = ?
)
SELECT DISTINCT wire.phy_tile_pkey, pip_in_tile.is_directional
FROM wires_in_graph_node
INNER JOIN pip_in_tile
ON
    pip_in_tile.dest_wire_in_tile_pkey = wires_in_graph_node.wire_in_tile_pkey
AND
    pip_in_tile.tile_type_pkey = wires_in_graph_node.phy_tile_type_pkey
INNER JOIN wire
ON
    wire.wire_in_tile_pkey = pip_in_tile.src_wire_in_tile_pkey
AND
    wire.phy_tile_pkey = wires_in_graph_node.phy_tile_pkey;
                """, (graph_node_pkey, )
            )
            src_phy_tiles = cur2.fetchall()

            if len(src_phy_tiles) > 1:
                # Try pruning bi-directional pips
                src_phy_tiles = [
                    (phy_tile_pkey, is_directional)
                    for (phy_tile_pkey, is_directional) in src_phy_tiles
                    if is_directional
                ]

            assert len(src_phy_tiles) == 1, (
                pin_graph_node_pkey, graph_node_pkey, source_wires, tracks,
                src_phy_tiles
            )
            phy_tile_pkey = src_phy_tiles[0][0]
        else:
            # Have an ambiguous source, see if there is an unambigous sink.
            #
            # Remove sinks that are also sources (e.g. bidirectional wires)
            sink_wires = list(set(sink_wires) - set(source_wires))

            if len(sink_wires) == 1:
                cur.execute(
                    "SELECT phy_tile_pkey FROM wire WHERE pkey = ?",
                    (sink_wires[0], )
                )
                source_wires = sink_wires
                phy_tile_pkey = cur.fetchone()[0]
            else:
                assert False, (
                    pin_graph_node_pkey, graph_node_pkey, source_wires,
                    sink_wires, tracks
                )
                return
    elif len(source_wires) == 1:
        cur.execute(
            "SELECT phy_tile_pkey FROM wire WHERE pkey = ?",
            (source_wires[0], )
        )
        phy_tile_pkey = cur.fetchone()[0]
    elif len(sink_wires) == 1:
        cur.execute(
            "SELECT phy_tile_pkey FROM wire WHERE pkey = ?", (sink_wires[0], )
        )
        source_wires = sink_wires
        phy_tile_pkey = cur.fetchone()[0]
    else:
        return

    for track_pkey in tracks:
        write_cur.execute(
            "UPDATE track SET canon_phy_tile_pkey = ? WHERE pkey = ?", (
                phy_tile_pkey,
                track_pkey,
            )
        )

    if not forward:
        assert NodeType(graph_node_type) == NodeType.IPIN
        source_wire_pkey = source_wires[0]
        write_cur.execute(
            """
UPDATE graph_node SET connection_box_wire_pkey = ? WHERE pkey = ?
            """, (
                source_wire_pkey,
                pin_graph_node_pkey,
            )
        )


def walk_and_mark_segment(
        conn, write_cur, graph_node_pkey, forward, segment_pkey, unknown_pkey,
        pin_graph_node_pkey, tracks, visited_nodes
):
    """ Recursive function to walk along a node and mark segments.

    This algorithm is used for marking INPINFEED and OUTPINFEED on nodes
    starting from an IPIN or OPIN edge.

    In addition, the canonical location of the connection box IPIN/OPIN nodes
    is the canonical location of the routing interface.  For example, the
    CLBLL_R tile is located to the right of the INT_R tile.  The routing
    lookahead routes to the INT_R (e.g. a x-1 of the CLBLL_R).  So the
    canonical location of the CLBLL_R IPIN is the INT_R tile, not the CLBLL_R
    tile.

    """
    cur = conn.cursor()

    # Update track segment's to segment_pkey (e.g. INPINFEED or OUTPINFEED).
    cur.execute(
        """SELECT graph_node_type FROM graph_node WHERE pkey = ?""",
        (graph_node_pkey, )
    )
    graph_node_type = NodeType(cur.fetchone()[0])
    if graph_node_type in [NodeType.CHANX, NodeType.CHANY]:
        cur.execute(
            "SELECT track_pkey FROM graph_node WHERE pkey = ?",
            (graph_node_pkey, )
        )
        track_pkey = cur.fetchone()[0]
        assert track_pkey is not None

        cur.execute(
            "SELECT segment_pkey FROM track WHERE pkey = ?", (track_pkey, )
        )
        old_segment_pkey = cur.fetchone()[0]
        if old_segment_pkey == unknown_pkey or old_segment_pkey is None:
            tracks.append(track_pkey)
            write_cur.execute(
                "UPDATE track SET segment_pkey = ? WHERE pkey = ?", (
                    segment_pkey,
                    track_pkey,
                )
            )
    else:
        track_pkey = None

    # Traverse to the next graph node.
    if forward:
        cur.execute(
            """
SELECT
    graph_edge.dest_graph_node_pkey,
    graph_node.track_pkey
FROM
    graph_edge
INNER JOIN graph_node ON graph_node.pkey = graph_edge.dest_graph_node_pkey
WHERE
    src_graph_node_pkey = ?
""", (graph_node_pkey, )
        )
        next_nodes = cur.fetchall()
    else:
        cur.execute(
            """
SELECT
    graph_edge.src_graph_node_pkey,
    graph_node.track_pkey
FROM
    graph_edge
INNER JOIN graph_node ON graph_node.pkey = graph_edge.src_graph_node_pkey
WHERE
    dest_graph_node_pkey = ?
""", (graph_node_pkey, )
        )
        next_nodes = cur.fetchall()

    if not forward:
        # Some nodes simply lead to GND/VCC tieoff pins, these should not
        # stop the walk, as they are not relevant to connection box.
        next_non_tieoff_nodes = []
        for (next_graph_node_pkey, next_track) in next_nodes:
            cur.execute(
                """
SELECT count() FROM constant_sources WHERE
    vcc_track_pkey = (SELECT track_pkey FROM graph_node WHERE pkey = ?)
OR
    gnd_track_pkey = (SELECT track_pkey FROM graph_node WHERE pkey = ?)
    """, (
                    next_graph_node_pkey,
                    next_graph_node_pkey,
                )
            )
            if cur.fetchone()[0] == 0:
                next_non_tieoff_nodes.append(
                    (next_graph_node_pkey, next_track)
                )

        if len(next_non_tieoff_nodes) == 1:
            (next_node, next_track) = next_non_tieoff_nodes[0]

        next_nodes = next_non_tieoff_nodes

    if len(next_nodes) == 1:
        # This is a simple edge, keep walking.
        (next_node, next_track) = next_nodes[0]
    else:
        next_other_nodes = []
        for next_node, next_track in next_nodes:
            # Shorted groups will have edges back to previous nodes, but they
            # will be in the same track, so ignore these.
            if next_node in visited_nodes and track_pkey == next_track:
                continue
            else:
                next_other_nodes.append((next_node, next_track))

        if len(next_other_nodes) == 1:
            # This is a simple edge, keep walking.
            (next_node, next_track) = next_other_nodes[0]
        else:
            next_node = None

    if next_node is not None and next_node not in visited_nodes:
        # If there is a next node, keep walking
        visited_nodes.add(next_node)
        walk_and_mark_segment(
            conn=conn,
            write_cur=write_cur,
            graph_node_pkey=next_node,
            forward=forward,
            segment_pkey=segment_pkey,
            unknown_pkey=unknown_pkey,
            pin_graph_node_pkey=pin_graph_node_pkey,
            tracks=tracks,
            visited_nodes=visited_nodes
        )
    else:
        # There is not a next node, update the connection box of the IPIN/OPIN
        # the walk was started from.
        set_pin_connection(
            conn=conn,
            write_cur=write_cur,
            pin_graph_node_pkey=pin_graph_node_pkey,
            forward=forward,
            graph_node_pkey=graph_node_pkey,
            tracks=tracks
        )


def active_graph_node(conn, graph_node_pkey, forward):
    """ Returns true if an edge in the specified direction exists. """
    cur = conn.cursor()

    if forward:
        cur.execute(
            """
SELECT count(*) FROM graph_edge WHERE src_graph_node_pkey = ? LIMIT 1
            """, (graph_node_pkey, )
        )
    else:
        cur.execute(
            """
SELECT count(*) FROM graph_edge WHERE dest_graph_node_pkey = ? LIMIT 1
            """, (graph_node_pkey, )
        )

    return cur.fetchone()[0] > 0


def annotate_pin_feeds(conn, ccio_sites):
    """ Identifies and annotates pin feed channels.

    Some channels are simply paths from IPIN's or OPIN's.  Set
    pin_classification to either IPIN_FEED or OPIN_FEED.  During track creation
    if these nodes are not given a specific segment, they will be assigned as
    INPINFEED or OUTPINFEED.
    """
    write_cur = conn.cursor()
    cur = conn.cursor()

    segments = {}
    for segment_pkey, segment_name in cur.execute(
            "SELECT pkey, name FROM segment"):
        segments[segment_name] = segment_pkey

    # Find BUFHCE OPIN's, so that walk_and_mark_segment uses correct segment
    # type.
    bufhce_opins = get_pins(conn, "BUFHCE", "O")

    # Find BUFGCTRL OPIN's, so that walk_and_mark_segment uses correct segment
    # type.
    bufg_opins = get_pins(conn, "BUFGCTRL", "O")

    # Find BUFGCTRL IPIN's, so that walk_and_mark_segment uses correct segment
    # type.
    bufg_ipins = set()
    for nipins in range(2):
        bufg_ipins |= get_pins(conn, "BUFGCTRL", "I{}".format(nipins))

    # Find PLL OPIN's, so that walk_and_mark_segment uses correct segment
    # type.
    pll_opins = set()
    for nclk in range(6):
        pll_opins |= get_pins(conn, "PLLE2_ADV", "CLKOUT{}".format(nclk))

    # Find PLL IPIN's, so that walk_and_mark_segment uses correct segment
    # type.
    pll_ipins = set()
    for nclk in range(2):
        pll_ipins |= get_pins(conn, "PLLE2_ADV", "CLKIN{}".format(nclk + 1))

    ccio_opins = set()

    # Find graph nodes for IOI_ILOGIC0_O for IOPAD_M's that are CCIO tiles (
    # e.g. have dedicate clock paths).
    for ccio_site in ccio_sites:
        ccio_ilogic = ccio_site.replace('IOB', 'ILOGIC')
        cur.execute(
            """
WITH ilogic_o_wires(wire_in_tile_pkey) AS (
  SELECT wire_in_tile.pkey FROM wire_in_tile
  INNER JOIN site_pin ON site_pin.pkey = wire_in_tile.site_pin_pkey
  INNER JOIN site_type ON site_pin.site_type_pkey = site_type.pkey
  WHERE
    site_type.name == "ILOGICE3"
  AND
    site_pin.name == "O"
  AND
    wire_in_tile.site_pkey IN (
        SELECT site_pkey FROM site_instance WHERE name = ?
    )
)
SELECT graph_node.pkey FROM graph_node
INNER JOIN wire ON graph_node.node_pkey = wire.node_pkey
WHERE
  wire.wire_in_tile_pkey IN (SELECT wire_in_tile_pkey FROM ilogic_o_wires)
AND
  wire.phy_tile_pkey = (SELECT phy_tile_pkey FROM site_instance WHERE name = ?);
        """, (ccio_ilogic, ccio_ilogic)
        )
        for (graph_node_pkey, ) in cur:
            ccio_opins.add(graph_node_pkey)

    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")

    # Walk from OPIN's first.
    for (graph_node_pkey, node_pkey) in cur.execute("""
SELECT graph_node.pkey, graph_node.node_pkey
FROM graph_node
WHERE graph_node.graph_node_type = ?
        """, (NodeType.OPIN.value, )):
        if not active_graph_node(conn, graph_node_pkey, forward=True):
            continue

        if graph_node_pkey in bufhce_opins:
            segment_pkey = segments["HCLK_ROWS"]
        elif graph_node_pkey in bufg_opins:
            segment_pkey = segments["GCLK_OUTPINFEED"]
        elif graph_node_pkey in pll_opins:
            segment_pkey = segments["PLL_OUTPINFEED"]
        elif graph_node_pkey in ccio_opins:
            segment_pkey = segments["CCIO_OUTPINFEED"]
        else:
            segment_pkey = segments["OUTPINFEED"]

        walk_and_mark_segment(
            conn,
            write_cur,
            graph_node_pkey,
            forward=True,
            segment_pkey=segment_pkey,
            unknown_pkey=segments["unknown"],
            pin_graph_node_pkey=graph_node_pkey,
            tracks=list(),
            visited_nodes=set()
        )

    # Walk from IPIN's next.
    for (graph_node_pkey, ) in cur.execute("""
SELECT graph_node.pkey
FROM graph_node
WHERE graph_node.graph_node_type = ?
        """, (NodeType.IPIN.value, )):

        if not active_graph_node(conn, graph_node_pkey, forward=False):
            continue

        if graph_node_pkey in bufg_ipins:
            segment_pkey = segments["GCLK_INPINFEED"]
        elif graph_node_pkey in pll_ipins:
            segment_pkey = segments["PLL_INPINFEED"]
        else:
            segment_pkey = segments["INPINFEED"]

        walk_and_mark_segment(
            conn,
            write_cur,
            graph_node_pkey,
            forward=False,
            segment_pkey=segment_pkey,
            unknown_pkey=segments["unknown"],
            pin_graph_node_pkey=graph_node_pkey,
            tracks=list(),
            visited_nodes=set()
        )

    write_cur.execute("""COMMIT TRANSACTION;""")


def set_track_canonical_loc(conn):
    """ For each track, compute a canonical location.

    This canonical location should be consisent across instances of the track
    type.  For example, a 6 length NW should always have a canonical location
    at the SE corner of the the track.

    For bidirection wires (generally long segments), use a consisent
    canonilization.
    """

    write_cur = conn.cursor()
    cur = conn.cursor()
    cur2 = conn.cursor()
    cur3 = conn.cursor()

    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")

    cur.execute("SELECT pkey FROM track WHERE alive")
    tracks = cur.fetchall()
    for (track_pkey, ) in progressbar_utils.progressbar(tracks):
        source_wires = []
        for (wire_pkey, ) in cur2.execute("""
SELECT pkey FROM wire WHERE node_pkey IN (
    SELECT pkey FROM node WHERE track_pkey = ?
    )""", (track_pkey, )):
            cur3.execute(
                """
SELECT count(*)
FROM pip_in_tile
WHERE
    dest_wire_in_tile_pkey = (SELECT wire_in_tile_pkey FROM wire WHERE pkey = ?)
LIMIT 1
    """, (wire_pkey, )
            )
            pips_to_wire = cur3.fetchone()[0]
            if pips_to_wire > 0:
                cur3.execute(
                    """
SELECT grid_x, grid_y FROM phy_tile WHERE pkey = (
    SELECT phy_tile_pkey FROM wire WHERE pkey = ?
                    )""", (wire_pkey, )
                )
                grid_x, grid_y = cur3.fetchone()
                source_wires.append(((grid_x, grid_y), wire_pkey))

        if len(source_wires) > 0:
            source_wire_pkey = min(source_wires, key=lambda x: x[0])[1]
            write_cur.execute(
                """
UPDATE track
SET canon_phy_tile_pkey = (SELECT phy_tile_pkey FROM wire WHERE pkey = ?)
WHERE pkey = ?
            """, (source_wire_pkey, track_pkey)
            )

    write_cur.execute("""COMMIT TRANSACTION;""")


def get_segment_length(segment_lengths):
    if len(segment_lengths) == 0:
        return 1

    median_length = int(math.ceil(numpy.median(segment_lengths)))

    return max(1, median_length)


def compute_segment_lengths(conn):
    """ Determine segment lengths used for cost normalization. """
    cur = conn.cursor()
    cur2 = conn.cursor()
    cur3 = conn.cursor()
    cur4 = conn.cursor()

    write_cur = conn.cursor()

    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")

    for (segment_pkey, ) in cur.execute("SELECT pkey FROM segment"):

        segment_lengths = []

        # Get all tracks with this segment
        for (track_pkey, src_phy_tile_pkey) in cur2.execute("""
SELECT pkey, canon_phy_tile_pkey FROM track
WHERE
    canon_phy_tile_pkey IS NOT NULL
AND
    segment_pkey = ?
        """, (segment_pkey, )):
            segment_length = 1
            cur4.execute(
                "SELECT grid_x, grid_y FROM phy_tile WHERE pkey = ?",
                (src_phy_tile_pkey, )
            )
            src_x, src_y = cur4.fetchone()

            # Get tiles downstream of this track.
            for (dest_phy_tile_pkey, ) in cur3.execute("""
SELECT DISTINCT canon_phy_tile_pkey FROM track WHERE pkey IN (
    SELECT track_pkey FROM graph_node WHERE pkey IN (
        SELECT dest_graph_node_pkey FROM graph_edge WHERE src_graph_node_pkey IN (
            SELECT pkey FROM graph_node WHERE track_pkey = ?
        )
    )
) AND canon_phy_tile_pkey IS NOT NULL
            """, (track_pkey, )):
                if src_phy_tile_pkey == dest_phy_tile_pkey:
                    continue

                cur4.execute(
                    "SELECT grid_x, grid_y FROM phy_tile WHERE pkey = ?",
                    (dest_phy_tile_pkey, )
                )
                dest_x, dest_y = cur4.fetchone()

                segment_length = max(
                    segment_length,
                    abs(dest_x - src_x) + abs(dest_y - src_y)
                )

            segment_lengths.append(segment_length)

        write_cur.execute(
            "UPDATE segment SET length = ? WHERE pkey = ?", (
                get_segment_length(segment_lengths),
                segment_pkey,
            )
        )

    write_cur.execute("""COMMIT TRANSACTION;""")


def commit_edges(write_cur, edges):
    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")
    write_cur.executemany(
        """
        INSERT INTO graph_edge(
            src_graph_node_pkey, dest_graph_node_pkey, switch_pkey,
            phy_tile_pkey, pip_in_tile_pkey, backward) VALUES (?, ?, ?, ?, ?, ?)""",
        edges
    )
    write_cur.execute("""COMMIT TRANSACTION;""")


REMOVE_TRAILING_NUM = re.compile(r'[0-9]+$')


def pip_sort_key(forward_pip):
    """ Sort pips to match canonical order. """
    forward, pip = forward_pip

    count = (
        len(REMOVE_TRAILING_NUM.sub('', pip.net_to)) +
        len(REMOVE_TRAILING_NUM.sub('', pip.net_from))
    )

    if forward:
        return (pip.is_pseudo, count, pip.net_to, pip.net_from)
    else:
        return (pip.is_pseudo, count, pip.net_from, pip.net_to)


def make_sorted_pips(pips):
    out_pips = []

    for pip in pips:
        # Add forward copy of pip
        out_pips.append((True, pip))

        # Add backward copy of pip if not directional.
        if not pip.is_directional:
            out_pips.append((False, pip))

    out_pips.sort(key=pip_sort_key)
    return out_pips


def create_edge_indices(conn):
    write_cur = conn.cursor()

    write_cur.execute("""BEGIN EXCLUSIVE TRANSACTION;""")
    write_cur.execute(
        """CREATE INDEX src_node_index ON graph_edge(src_graph_node_pkey);"""
    )
    write_cur.execute(
        """CREATE INDEX dest_node_index ON graph_edge(dest_graph_node_pkey);"""
    )
    write_cur.execute("""CREATE INDEX node_track_index ON node(track_pkey);""")
    write_cur.execute("""COMMIT TRANSACTION;""")
    write_cur.connection.commit()

    print('{} Indices created, marking track liveness'.format(now()))


def create_and_insert_edges(
        db, grid, conn, use_roi, roi, input_only_nodes, output_only_nodes
):
    write_cur = conn.cursor()

    write_cur.execute(
        'SELECT pkey FROM switch WHERE name = ?;',
        ('__vpr_delayless_switch__', )
    )
    delayless_switch_pkey = write_cur.fetchone()[0]
    delayless_switch = KnownSwitch(delayless_switch_pkey)

    find_pip = create_find_pip(conn)
    find_wire = create_find_wire(conn)
    find_connector = create_find_connector(conn)
    get_tile_loc = create_get_tile_loc(conn)

    const_connectors = create_const_connectors(conn)

    sorted_pips = {}

    num_edges = 0
    edges = []
    for loc in progressbar_utils.progressbar(grid.tile_locations()):
        edge_set = set()

        gridinfo = grid.gridinfo_at_loc(loc)
        tile_name = grid.tilename_at_loc(loc)

        # Not a synth node, check if in ROI.
        if use_roi and not roi.tile_in_roi(loc):
            continue

        tile_type = db.get_tile_type(gridinfo.tile_type)

        if tile_type not in sorted_pips:
            sorted_pips[tile_type] = make_sorted_pips(tile_type.get_pips())

        for forward, pip in sorted_pips[tile_type]:
            # FIXME: The PADOUT0/1 connections do not work.
            #
            # These connections are used for:
            #  - XADC
            #  - Differential signal signal connection between pads.
            #
            # Issue tracking fix:
            # https://github.com/SymbiFlow/f4pga-arch-defs/issues/1033
            if 'PADOUT0' in pip.name and 'DIFFI_IN1' not in pip.name:
                continue
            if 'PADOUT1' in pip.name and 'DIFFI_IN0' not in pip.name:
                continue

            # These edges are used for bringing general interconnect to the
            # horizontal clock buffers.  This should only be used when routing
            # clocks.
            if 'CLK_HROW_CK_INT_' in pip.name:
                continue

            # Generally pseudo-pips are skipped, with the exception for BUFHCE related pips,
            # for which we want to create a routing path to have VPR route thorugh these pips.
            if pip.is_pseudo and "CLK_HROW_CK" not in pip.name:
                continue

            # Filter out PIPs related to MIO and DDR pins of the Zynq7 PS.
            # These PIPs are actually not there, they are just informative.
            if "PS72_" in pip.net_to or "PS72_" in pip.net_from:
                continue

            connections = make_connection(
                conn=conn,
                input_only_nodes=input_only_nodes,
                output_only_nodes=output_only_nodes,
                find_pip=find_pip,
                find_wire=find_wire,
                find_connector=find_connector,
                get_tile_loc=get_tile_loc,
                tile_name=tile_name,
                tile_type=gridinfo.tile_type,
                pip=pip,
                delayless_switch=delayless_switch,
                const_connectors=const_connectors,
                forward=forward,
            )

            if connections:
                for connection in connections:
                    key = tuple(connection[0:3])
                    if key in edge_set:
                        continue

                    edge_set.add(key)
                    edges.append(connection)

        if len(edges) > 1000:
            commit_edges(write_cur, edges)

            num_edges += len(edges)
            edges = []

    print('{} Created {} edges, inserted'.format(now(), num_edges))


def get_ccio_sites(grid):
    ccio_sites = set()

    for tile in grid.tiles():
        gridinfo = grid.gridinfo_at_tilename(tile)

        for site, pin_function in gridinfo.pin_functions.items():
            if 'SRCC' in pin_function or 'MRCC' in pin_function:
                if gridinfo.sites[site][-1] == 'M':
                    ccio_sites.add(site)

    return ccio_sites


def create_edges(args):
    db = prjxray.db.Database(args.db_root, args.part)
    grid = db.grid()

    with DatabaseCache(args.connection_database) as conn:

        with open(args.pin_assignments) as f:
            pin_assignments = json.load(f)

        tile_wires = []
        for tile_type, wire_map in pin_assignments['pin_directions'].items():
            for wire in wire_map.keys():
                tile_wires.append((tile_type, wire))

        for tile_type, wire in progressbar_utils.progressbar(tile_wires):
            pins = [
                direction_to_enum(pin)
                for pin in pin_assignments['pin_directions'][tile_type][wire]
            ]
            add_graph_nodes_for_pins(conn, tile_type, wire, pins)

        if args.overlay:
            assert args.synth_tiles
            use_roi = True
            with open(args.synth_tiles) as f:
                synth_tiles = json.load(f)

            region_dict = dict()
            for r in synth_tiles['info']:
                bounds = (
                    r['GRID_X_MIN'], r['GRID_X_MAX'], r['GRID_Y_MIN'],
                    r['GRID_Y_MAX']
                )
                region_dict[r['name']] = bounds

            roi = Overlay(region_dict=region_dict)

            print('{} generating routing graph for Overlay.'.format(now()))
        elif args.synth_tiles:
            use_roi = True
            with open(args.synth_tiles) as f:
                synth_tiles = json.load(f)

            roi = Roi(
                db=db,
                x1=synth_tiles['info']['GRID_X_MIN'],
                y1=synth_tiles['info']['GRID_Y_MIN'],
                x2=synth_tiles['info']['GRID_X_MAX'],
                y2=synth_tiles['info']['GRID_Y_MAX'],
            )

            print('{} generating routing graph for ROI.'.format(now()))
        elif args.graph_limit:
            use_roi = True
            x_min, y_min, x_max, y_max = map(int, args.graph_limit.split(','))
            roi = Roi(
                db=db,
                x1=x_min,
                y1=y_min,
                x2=x_max,
                y2=y_max,
            )
            synth_tiles = {'tiles': {}}
        else:
            use_roi = False

        output_only_nodes = set()
        input_only_nodes = set()

        print('{} Finding nodes belonging to ROI'.format(now()))
        if use_roi:
            find_wire = create_find_wire(conn)
            for loc in progressbar_utils.progressbar(grid.tile_locations()):
                gridinfo = grid.gridinfo_at_loc(loc)
                tile_name = grid.tilename_at_loc(loc)

                if tile_name in synth_tiles['tiles']:
                    synth_tile = synth_tiles['tiles'][tile_name]
                    for pin in synth_tile['pins']:
                        if pin['port_type'] not in ['input', 'output']:
                            continue

                        _, _, _, node_pkey = find_wire(
                            tile_name, gridinfo.tile_type, pin['wire']
                        )

                        is_input = pin['port_type'] == 'input'
                        is_output = pin['port_type'] == 'output'

                        assert is_input or is_output, pin

                        if is_input:
                            # This track can be used as a sink.
                            input_only_nodes.add(node_pkey)
                        elif is_output:
                            # This track can be used as a src.
                            output_only_nodes.add(node_pkey)

                        # Adding all wires outside of the ROI relative to this synth tile
                        # to the input/output only nodes, so that the corresponding nodes
                        # have only outgoing or incoming edges
                        for tile, wires in synth_tile['wires_outside_roi'
                                                      ].items():
                            tile_type = grid.gridinfo_at_tilename(
                                tile
                            ).tile_type

                            for wire in wires:
                                _, _, _, node_pkey = find_wire(
                                    tile, tile_type, wire
                                )

                                if is_input:
                                    # This track can be used as a sink.
                                    input_only_nodes.add(node_pkey)
                                elif is_output:
                                    # This track can be used as a src.
                                    output_only_nodes.add(node_pkey)

        create_and_insert_edges(
            db=db,
            grid=grid,
            conn=conn,
            use_roi=use_roi,
            roi=roi if use_roi else None,
            input_only_nodes=input_only_nodes,
            output_only_nodes=output_only_nodes
        )

        create_edge_indices(conn)

        mark_track_liveness(conn, input_only_nodes, output_only_nodes)

    return get_ccio_sites(grid)
