#include <cstdio>

#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_memory.h"

#include "vpr_types.h"
#include "vpr_error.h"

#include "globals.h"
#include "route_export.h"
#include "check_route.h"
#include "rr_graph.h"
#include "check_rr_graph.h"
#include "read_xml_arch_file.h"

/******************** Subroutines local to this module **********************/
static void check_node_and_range(int inode, enum e_route_type route_type);
static void check_source(int inode, ClusterNetId net_id);
static void check_sink(int inode, ClusterNetId net_id, bool* pin_done);
static void check_switch(t_trace* tptr, int num_switch);
static bool check_adjacent(int from_node, int to_node);
static int chanx_chany_adjacent(int chanx_node, int chany_node);
static void reset_flags(ClusterNetId inet, bool* connected_to_route);
static void check_locally_used_clb_opins(const t_clb_opins_used& clb_opins_used_locally,
                                         enum e_route_type route_type);

static bool check_non_configurable_edges(ClusterNetId net, const t_non_configurable_rr_sets& non_configurable_rr_sets);

/************************ Subroutine definitions ****************************/

void check_route(enum e_route_type route_type) {
    /* This routine checks that a routing:  (1) Describes a properly         *
     * connected path for each net, (2) this path connects all the           *
     * pins spanned by that net, and (3) that no routing resources are       *
     * oversubscribed (the occupancy of everything is recomputed from        *
     * scratch).                                                             */

    int max_pins, inode, prev_node;
    unsigned int ipin;
    bool valid, connects;
    bool* connected_to_route; /* [0 .. device_ctx.rr_nodes.size()-1] */
    t_trace* tptr;
    bool* pin_done;

    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& route_ctx = g_vpr_ctx.routing();

    const int num_switches = device_ctx.rr_switch_inf.size();

    VTR_LOG("\n");
    VTR_LOG("Checking to ensure routing is legal...\n");

    /* Recompute the occupancy from scratch and check for overuse of routing *
     * resources.  This was already checked in order to determine that this  *
     * is a successful routing, but I want to double check it here.          */

    recompute_occupancy_from_scratch();
    valid = feasible_routing();
    if (valid == false) {
        VPR_ERROR(VPR_ERROR_ROUTE,
                  "Error in check_route -- routing resources are overused.\n");
    }

    check_locally_used_clb_opins(route_ctx.clb_opins_used_locally, route_type);

    auto non_configurable_rr_sets = identify_non_configurable_rr_sets();

    connected_to_route = (bool*)vtr::calloc(device_ctx.rr_nodes.size(), sizeof(bool));

    max_pins = 0;
    for (auto net_id : cluster_ctx.clb_nlist.nets())
        max_pins = std::max(max_pins, (int)cluster_ctx.clb_nlist.net_pins(net_id).size());

    pin_done = (bool*)vtr::malloc(max_pins * sizeof(bool));

    /* Now check that all nets are indeed connected. */
    for (auto net_id : cluster_ctx.clb_nlist.nets()) {
        if (cluster_ctx.clb_nlist.net_is_ignored(net_id) || cluster_ctx.clb_nlist.net_sinks(net_id).size() == 0) /* Skip ignored nets. */
            continue;

        for (ipin = 0; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ipin++)
            pin_done[ipin] = false;

        /* Check the SOURCE of the net. */
        tptr = route_ctx.trace[net_id].head;
        if (tptr == nullptr) {
            VPR_ERROR(VPR_ERROR_ROUTE,
                      "in check_route: net %d has no routing.\n", size_t(net_id));
        }

        inode = tptr->index;
        check_node_and_range(inode, route_type);
        check_switch(tptr, num_switches);
        connected_to_route[inode] = true; /* Mark as in path. */

        check_source(inode, net_id);
        pin_done[0] = true;

        prev_node = inode;
        int prev_switch = tptr->iswitch;
        tptr = tptr->next;

        /* Check the rest of the net */
        size_t num_sinks = 0;
        while (tptr != nullptr) {
            inode = tptr->index;
            check_node_and_range(inode, route_type);
            check_switch(tptr, num_switches);

            if (prev_switch == OPEN) { //Start of a new branch
                if (connected_to_route[inode] == false) {
                    VPR_ERROR(VPR_ERROR_ROUTE,
                              "in check_route: node %d does not link into existing routing for net %d.\n", inode, size_t(net_id));
                }
            } else { //Continuing along existing branch
                connects = check_adjacent(prev_node, inode);
                if (!connects) {
                    VPR_ERROR(VPR_ERROR_ROUTE,
                              "in check_route: found non-adjacent segments in traceback while checking net %d:\n"
                              "  %s\n"
                              "  %s\n",
                              size_t(net_id),
                              describe_rr_node(prev_node).c_str(),
                              describe_rr_node(inode).c_str());
                }

                connected_to_route[inode] = true; /* Mark as in path. */

                if (device_ctx.rr_nodes[inode].type() == SINK) {
                    check_sink(inode, net_id, pin_done);
                    num_sinks += 1;
                }

            } /* End of prev_node type != SINK */
            prev_node = inode;
            prev_switch = tptr->iswitch;
            tptr = tptr->next;
        } /* End while */

        if (num_sinks != cluster_ctx.clb_nlist.net_sinks(net_id).size()) {
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                            "in check_route: net %zu (%s) has %zu SINKs (expected %zu).\n",
                            size_t(net_id), cluster_ctx.clb_nlist.net_name(net_id).c_str(),
                            num_sinks, cluster_ctx.clb_nlist.net_sinks(net_id).size());
        }

        for (ipin = 0; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ipin++) {
            if (pin_done[ipin] == false) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_route: net %zu does not connect to pin %d.\n", size_t(net_id), ipin);
            }
        }

        check_non_configurable_edges(net_id, non_configurable_rr_sets);

        reset_flags(net_id, connected_to_route);

    } /* End for each net */

    free(pin_done);
    free(connected_to_route);
    VTR_LOG("Completed routing consistency check successfully.\n");
    VTR_LOG("\n");
}

/* Checks that this SINK node is one of the terminals of inet, and marks   *
 * the appropriate pin as being reached.                                   */
static void check_sink(int inode, ClusterNetId net_id, bool* pin_done) {
    int i, j, ifound, ptc_num, iclass, iblk, pin_index;
    ClusterBlockId bnum;
    unsigned int ipin;
    t_physical_tile_type_ptr type;
    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& place_ctx = g_vpr_ctx.placement();

    VTR_ASSERT(device_ctx.rr_nodes[inode].type() == SINK);
    i = device_ctx.rr_nodes[inode].xlow();
    j = device_ctx.rr_nodes[inode].ylow();
    type = device_ctx.grid[i][j].type;
    /* For sinks, ptc_num is the class */
    ptc_num = device_ctx.rr_nodes[inode].ptc_num();
    ifound = 0;

    for (iblk = 0; iblk < type->capacity; iblk++) {
        bnum = place_ctx.grid_blocks[i][j].blocks[iblk]; /* Hardcoded to one cluster_ctx block*/
        ipin = 1;
        for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
            if (cluster_ctx.clb_nlist.pin_block(pin_id) == bnum) {
                pin_index = cluster_ctx.clb_nlist.pin_physical_index(pin_id);
                iclass = type->pin_class[pin_index];
                if (iclass == ptc_num) {
                    /* Could connect to same pin class on the same clb more than once.  Only   *
                     * update pin_done for a pin that hasn't been reached yet.                 */
                    if (pin_done[ipin] == false) {
                        ifound++;
                        pin_done[ipin] = true;
                    }
                }
            }
            ipin++;
        }
    }

    if (ifound > 1 && is_io_type(type)) {
        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                        "in check_sink: found %d terminals of net %d of pad %d at location (%d, %d).\n", ifound, size_t(net_id), ptc_num, i, j);
    }

    if (ifound < 1) {
        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                        "in check_sink: node %d does not connect to any terminal of net %s #%lu.\n"
                        "This error is usually caused by incorrectly specified logical equivalence in your architecture file.\n"
                        "You should try to respecify what pins are equivalent or turn logical equivalence off.\n",
                        inode, cluster_ctx.clb_nlist.net_name(net_id).c_str(), size_t(net_id));
    }
}

/* Checks that the node passed in is a valid source for this net. */
static void check_source(int inode, ClusterNetId net_id) {
    t_rr_type rr_type;
    t_physical_tile_type_ptr type;
    ClusterBlockId blk_id;
    int i, j, ptc_num, node_block_pin, iclass;
    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& place_ctx = g_vpr_ctx.placement();

    rr_type = device_ctx.rr_nodes[inode].type();
    if (rr_type != SOURCE) {
        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                        "in check_source: net %d begins with a node of type %d.\n", size_t(net_id), rr_type);
    }

    i = device_ctx.rr_nodes[inode].xlow();
    j = device_ctx.rr_nodes[inode].ylow();
    /* for sinks and sources, ptc_num is class */
    ptc_num = device_ctx.rr_nodes[inode].ptc_num();
    /* First node_block for net is the source */
    blk_id = cluster_ctx.clb_nlist.net_driver_block(net_id);
    type = device_ctx.grid[i][j].type;

    if (place_ctx.block_locs[blk_id].loc.x != i || place_ctx.block_locs[blk_id].loc.y != j) {
        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                        "in check_source: net SOURCE is in wrong location (%d,%d).\n", i, j);
    }

    //Get the driver pin's index in the block
    node_block_pin = cluster_ctx.clb_nlist.net_pin_physical_index(net_id, 0);
    iclass = type->pin_class[node_block_pin];

    if (ptc_num != iclass) {
        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                        "in check_source: net SOURCE is of wrong class (%d).\n", ptc_num);
    }
}

static void check_switch(t_trace* tptr, int num_switch) {
    /* Checks that the switch leading from this traceback element to the next *
     * one is a legal switch type.                                            */

    int inode;
    short switch_type;

    auto& device_ctx = g_vpr_ctx.device();

    inode = tptr->index;
    switch_type = tptr->iswitch;

    if (device_ctx.rr_nodes[inode].type() != SINK) {
        if (switch_type >= num_switch) {
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                            "in check_switch: rr_node %d left via switch type %d.\n"
                            "\tSwitch type is out of range.\n",
                            inode, switch_type);
        }
    }

    else { /* Is a SINK */

        /* Without feedthroughs, there should be no switch.  If feedthroughs are    *
         * allowed, change to treat a SINK like any other node (as above).          */

        if (switch_type != OPEN) {
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                            "in check_switch: rr_node %d is a SINK, but attempts to use a switch of type %d.\n", inode, switch_type);
        }
    }
}

static void reset_flags(ClusterNetId inet, bool* connected_to_route) {
    /* This routine resets the flags of all the channel segments contained *
     * in the traceback of net inet to 0.  This allows us to check the     *
     * next net for connectivity (and the default state of the flags       *
     * should always be zero after they have been used).                   */

    t_trace* tptr;
    int inode;

    auto& route_ctx = g_vpr_ctx.routing();

    tptr = route_ctx.trace[inet].head;

    while (tptr != nullptr) {
        inode = tptr->index;
        connected_to_route[inode] = false; /* Not in routed path now. */
        tptr = tptr->next;
    }
}

static bool check_adjacent(int from_node, int to_node) {
    /* This routine checks if the rr_node to_node is reachable from from_node.   *
     * It returns true if is reachable and false if it is not.  Check_node has   *
     * already been used to verify that both nodes are valid rr_nodes, so only   *
     * adjacency is checked here.
     * Special case: direct OPIN to IPIN connections need not be adjacent.  These
     * represent specially-crafted connections such as carry-chains or more advanced
     * blocks where adjacency is overridden by the architect */

    int from_xlow, from_ylow, to_xlow, to_ylow, from_ptc, to_ptc, iclass;
    int num_adj, to_xhigh, to_yhigh, from_xhigh, from_yhigh;
    bool reached;
    t_rr_type from_type, to_type;
    t_physical_tile_type_ptr from_grid_type, to_grid_type;

    auto& device_ctx = g_vpr_ctx.device();

    reached = false;

    for (t_edge_size iconn = 0; iconn < device_ctx.rr_nodes[from_node].num_edges(); iconn++) {
        if (device_ctx.rr_nodes[from_node].edge_sink_node(iconn) == to_node) {
            reached = true;
            break;
        }
    }

    if (!reached)
        return (false);

    /* Now we know the rr graph says these two nodes are adjacent.  Double  *
     * check that this makes sense, to verify the rr graph.                 */
    VTR_ASSERT(reached);

    num_adj = 0;

    from_type = device_ctx.rr_nodes[from_node].type();
    from_xlow = device_ctx.rr_nodes[from_node].xlow();
    from_ylow = device_ctx.rr_nodes[from_node].ylow();
    from_xhigh = device_ctx.rr_nodes[from_node].xhigh();
    from_yhigh = device_ctx.rr_nodes[from_node].yhigh();
    from_ptc = device_ctx.rr_nodes[from_node].ptc_num();
    to_type = device_ctx.rr_nodes[to_node].type();
    to_xlow = device_ctx.rr_nodes[to_node].xlow();
    to_ylow = device_ctx.rr_nodes[to_node].ylow();
    to_xhigh = device_ctx.rr_nodes[to_node].xhigh();
    to_yhigh = device_ctx.rr_nodes[to_node].yhigh();
    to_ptc = device_ctx.rr_nodes[to_node].ptc_num();

    switch (from_type) {
        case SOURCE:
            VTR_ASSERT(to_type == OPIN);

            //The OPIN should be contained within the bounding box of it's connected source
            if (from_xlow <= to_xlow
                && from_ylow <= to_ylow
                && from_xhigh >= to_xhigh
                && from_yhigh >= to_yhigh) {
                from_grid_type = device_ctx.grid[from_xlow][from_ylow].type;
                to_grid_type = device_ctx.grid[to_xlow][to_ylow].type;
                VTR_ASSERT(from_grid_type == to_grid_type);

                iclass = to_grid_type->pin_class[to_ptc];
                if (iclass == from_ptc)
                    num_adj++;
            }
            break;

        case SINK:
            /* SINKS are adjacent to not connected */
            break;

        case OPIN:
            if (to_type == CHANX || to_type == CHANY) {
                num_adj += 1; //adjacent
            } else {
                VTR_ASSERT(to_type == IPIN); /* direct OPIN to IPIN connections not necessarily adjacent */
                return true;                 /* Special case, direct OPIN to IPIN connections need not be adjacent */
            }

            break;

        case IPIN:
            VTR_ASSERT(to_type == SINK);

            //An IPIN should be contained within the bounding box of it's connected sink
            if (from_xlow >= to_xlow
                && from_ylow >= to_ylow
                && from_xhigh <= to_xhigh
                && from_yhigh <= to_yhigh) {
                from_grid_type = device_ctx.grid[from_xlow][from_ylow].type;
                to_grid_type = device_ctx.grid[to_xlow][to_ylow].type;
                VTR_ASSERT(from_grid_type == to_grid_type);

                iclass = from_grid_type->pin_class[from_ptc];
                if (iclass == to_ptc)
                    num_adj++;
            }
            break;

        case CHANX:
            if (to_type == IPIN) {
                num_adj += 1; //adjacent
            } else if (to_type == CHANX) {
                from_xhigh = device_ctx.rr_nodes[from_node].xhigh();
                to_xhigh = device_ctx.rr_nodes[to_node].xhigh();
                if (from_ylow == to_ylow) {
                    /* UDSD Modification by WMF Begin */
                    /*For Fs > 3, can connect to overlapping wire segment */
                    if (to_xhigh == from_xlow - 1 || from_xhigh == to_xlow - 1) {
                        num_adj++;
                    }
                    /* Overlapping */
                    else {
                        int i;

                        for (i = from_xlow; i <= from_xhigh; i++) {
                            if (i >= to_xlow && i <= to_xhigh) {
                                num_adj++;
                                break;
                            }
                        }
                    }
                    /* UDSD Modification by WMF End */
                }
            } else if (to_type == CHANY) {
                num_adj += chanx_chany_adjacent(from_node, to_node);
            } else {
                VTR_ASSERT(0);
            }
            break;

        case CHANY:
            if (to_type == IPIN) {
                num_adj += 1; //adjacent
            } else if (to_type == CHANY) {
                from_yhigh = device_ctx.rr_nodes[from_node].yhigh();
                to_yhigh = device_ctx.rr_nodes[to_node].yhigh();
                if (from_xlow == to_xlow) {
                    /* UDSD Modification by WMF Begin */
                    if (to_yhigh == from_ylow - 1 || from_yhigh == to_ylow - 1) {
                        num_adj++;
                    }
                    /* Overlapping */
                    else {
                        int j;

                        for (j = from_ylow; j <= from_yhigh; j++) {
                            if (j >= to_ylow && j <= to_yhigh) {
                                num_adj++;
                                break;
                            }
                        }
                    }
                    /* UDSD Modification by WMF End */
                }
            } else if (to_type == CHANX) {
                num_adj += chanx_chany_adjacent(to_node, from_node);
            } else {
                VTR_ASSERT(0);
            }
            break;

        default:
            break;
    }

    if (num_adj == 1)
        return (true);
    else if (num_adj == 0)
        return (false);

    VPR_ERROR(VPR_ERROR_ROUTE,
              "in check_adjacent: num_adj = %d. Expected 0 or 1.\n", num_adj);
    return false; //Should not reach here once thrown
}

static int chanx_chany_adjacent(int chanx_node, int chany_node) {
    /* Returns 1 if the specified CHANX and CHANY nodes are adjacent, 0         *
     * otherwise.                                                               */

    int chanx_y, chanx_xlow, chanx_xhigh;
    int chany_x, chany_ylow, chany_yhigh;

    auto& device_ctx = g_vpr_ctx.device();

    chanx_y = device_ctx.rr_nodes[chanx_node].ylow();
    chanx_xlow = device_ctx.rr_nodes[chanx_node].xlow();
    chanx_xhigh = device_ctx.rr_nodes[chanx_node].xhigh();

    chany_x = device_ctx.rr_nodes[chany_node].xlow();
    chany_ylow = device_ctx.rr_nodes[chany_node].ylow();
    chany_yhigh = device_ctx.rr_nodes[chany_node].yhigh();

    if (chany_ylow > chanx_y + 1 || chany_yhigh < chanx_y)
        return (0);

    if (chanx_xlow > chany_x + 1 || chanx_xhigh < chany_x)
        return (0);

    return (1);
}

void recompute_occupancy_from_scratch() {
    /*
     * This routine updates the occ field in the route_ctx.rr_node_route_inf structure
     * according to the resource usage of the current routing.  It does a
     * brute force recompute from scratch that is useful for sanity checking.
     */

    int inode, iclass, ipin, num_local_opins;
    t_trace* tptr;

    auto& route_ctx = g_vpr_ctx.mutable_routing();
    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();

    /* First set the occupancy of everything to zero. */

    for (size_t inode_idx = 0; inode_idx < device_ctx.rr_nodes.size(); inode_idx++)
        route_ctx.rr_node_route_inf[inode_idx].set_occ(0);

    /* Now go through each net and count the tracks and pins used everywhere */

    for (auto net_id : cluster_ctx.clb_nlist.nets()) {
        if (cluster_ctx.clb_nlist.net_is_ignored(net_id)) /* Skip ignored nets. */
            continue;

        tptr = route_ctx.trace[net_id].head;
        if (tptr == nullptr)
            continue;

        for (;;) {
            inode = tptr->index;
            route_ctx.rr_node_route_inf[inode].set_occ(route_ctx.rr_node_route_inf[inode].occ() + 1);

            if (tptr->iswitch == OPEN) {
                tptr = tptr->next; /* Skip next segment. */
                if (tptr == nullptr)
                    break;
            }

            tptr = tptr->next;
        }
    }

    /* Now update the occupancy of each of the "locally used" OPINs on each CLB *
     * (CLB outputs used up by being directly wired to subblocks used only      *
     * locally).                                                                */
    for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
        for (iclass = 0; iclass < physical_tile_type(blk_id)->num_class; iclass++) {
            num_local_opins = route_ctx.clb_opins_used_locally[blk_id][iclass].size();
            /* Will always be 0 for pads or SINK classes. */
            for (ipin = 0; ipin < num_local_opins; ipin++) {
                inode = route_ctx.clb_opins_used_locally[blk_id][iclass][ipin];
                route_ctx.rr_node_route_inf[inode].set_occ(route_ctx.rr_node_route_inf[inode].occ() + 1);
            }
        }
    }
}

static void check_locally_used_clb_opins(const t_clb_opins_used& clb_opins_used_locally,
                                         enum e_route_type route_type) {
    /* Checks that enough OPINs on CLBs have been set aside (used up) to make a *
     * legal routing if subblocks connect to OPINs directly.                    */

    int iclass, num_local_opins, inode, ipin;
    t_rr_type rr_type;

    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& device_ctx = g_vpr_ctx.device();

    for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
        for (iclass = 0; iclass < physical_tile_type(blk_id)->num_class; iclass++) {
            num_local_opins = clb_opins_used_locally[blk_id][iclass].size();
            /* Always 0 for pads and for SINK classes */

            for (ipin = 0; ipin < num_local_opins; ipin++) {
                inode = clb_opins_used_locally[blk_id][iclass][ipin];
                check_node_and_range(inode, route_type); /* Node makes sense? */

                /* Now check that node is an OPIN of the right type. */

                rr_type = device_ctx.rr_nodes[inode].type();
                if (rr_type != OPIN) {
                    VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                    "in check_locally_used_opins: block #%lu (%s)\n"
                                    "\tClass %d local OPIN is wrong rr_type -- rr_node #%d of type %d.\n",
                                    size_t(blk_id), cluster_ctx.clb_nlist.block_name(blk_id).c_str(), iclass, inode, rr_type);
                }

                ipin = device_ctx.rr_nodes[inode].ptc_num();
                if (physical_tile_type(blk_id)->pin_class[ipin] != iclass) {
                    VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                    "in check_locally_used_opins: block #%lu (%s):\n"
                                    "\tExpected class %d local OPIN has class %d -- rr_node #: %d.\n",
                                    size_t(blk_id), cluster_ctx.clb_nlist.block_name(blk_id).c_str(), iclass, physical_tile_type(blk_id)->pin_class[ipin], inode);
                }
            }
        }
    }
}

static void check_node_and_range(int inode, enum e_route_type route_type) {
    /* Checks that inode is within the legal range, then calls check_node to    *
     * check that everything else about the node is OK.                         */

    auto& device_ctx = g_vpr_ctx.device();

    if (inode < 0 || inode >= (int)device_ctx.rr_nodes.size()) {
        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                        "in check_node_and_range: rr_node #%d is out of legal, range (0 to %d).\n", inode, device_ctx.rr_nodes.size() - 1);
    }
    check_rr_node(inode, route_type, device_ctx);
}

//Checks that the specified routing is legal with respect to non-configurable edges
//
//For routing to be legal if *any* non-configurable edge is used, so must *all*
//other non-configurable edges in the same set
static bool check_non_configurable_edges(ClusterNetId net, const t_non_configurable_rr_sets& non_configurable_rr_sets) {
    auto& route_ctx = g_vpr_ctx.routing();
    auto& cluster_ctx = g_vpr_ctx.clustering();

    t_trace* head = route_ctx.trace[net].head;

    //Collect all the edges used by this net's routing
    std::set<t_node_edge> routing_edges;
    std::set<int> routing_nodes;
    for (t_trace* trace = head; trace != nullptr; trace = trace->next) {
        int inode = trace->index;

        routing_nodes.insert(inode);

        if (trace->iswitch == OPEN) {
            continue; //End of branch
        } else if (trace->next) {
            int inode_next = trace->next->index;

            t_node_edge edge = {inode, inode_next};

            routing_edges.insert(edge);
        }
    }

    //We need to perform two types of checks:
    //
    // 1) That all nodes in a non-configurable set are included
    // 2) That all (required) non-configurable edges are used
    //
    //We need to check (2) in addition to (1) to ensure that (1) did not pass
    //because the nodes 'happend' to be connected together by configurable
    //routing (to be legal, by definition, they must be connected by
    //non-configurable routing).

    //Check that all nodes in each non-configurable set are full included if any element
    //within a set is used by the routing
    for (const auto& rr_nodes : non_configurable_rr_sets.node_sets) {
        //Compute the intersection of the routing and current non-configurable nodes set
        std::vector<int> intersection;
        std::set_intersection(routing_nodes.begin(), routing_nodes.end(),
                              rr_nodes.begin(), rr_nodes.end(),
                              std::back_inserter(intersection));

        //If the intersection is non-empty then the current routing uses
        //at least one non-configurable edge in this set
        if (!intersection.empty()) {
            //To be legal *all* the nodes must be included in the routing
            if (intersection.size() != rr_nodes.size()) {
                //Illegal

                //Compute the difference to identify the missing nodes
                //for detailed error reporting -- the nodes
                //which are in rr_nodes but not in routing_nodes.
                std::vector<int> difference;
                std::set_difference(rr_nodes.begin(), rr_nodes.end(),
                                    routing_nodes.begin(), routing_nodes.end(),
                                    std::back_inserter(difference));

                VTR_ASSERT(difference.size() > 0);
                std::string msg = vtr::string_fmt(
                    "Illegal routing for net '%s' (#%zu) some "
                    "required non-configurably connected nodes are missing:\n",
                    cluster_ctx.clb_nlist.net_name(net).c_str(), size_t(net));

                for (auto inode : difference) {
                    msg += vtr::string_fmt("  Missing %s\n", describe_rr_node(inode).c_str());
                }

                VPR_FATAL_ERROR(VPR_ERROR_ROUTE, msg.c_str());
            }
        }
    }

    //Check that any sets of non-configurable RR graph edges are fully included
    //in the routing, if any of a set's edges are used
    for (const auto& rr_edges : non_configurable_rr_sets.edge_sets) {
        //Compute the intersection of the routing and current non-configurable edge set
        std::vector<t_node_edge> intersection;
        std::set_intersection(routing_edges.begin(), routing_edges.end(),
                              rr_edges.begin(), rr_edges.end(),
                              std::back_inserter(intersection));

        //If the intersection is non-empty then the current routing uses
        //at least one non-configurable edge in this set
        if (!intersection.empty()) {
            //Since at least one non-configurable edge is used, to be legal
            //the full set of non-configurably connected edges must be used.
            //
            //This is somewhat complicted by the fact that non-configurable edges
            //are sometimes bi-directional (e.g. electrical shorts) and so appear
            //in rr_edges twice (once forward, once backward). Only one of the
            //paired edges need appear to be correct.

            //To figure out which edges are missing we compute
            //the difference from rr_edges to routing_edges -- the nodes
            //which are in rr_edges but not in routing_edges.
            std::vector<t_node_edge> difference;
            std::set_difference(rr_edges.begin(), rr_edges.end(),
                                routing_edges.begin(), routing_edges.end(),
                                std::back_inserter(difference));

            //Next we remove edges in the difference if there is a reverse
            //edge in rr_edges and the forward edge is found in routing (or vice-versa).
            //It is OK if there is an unused reverse/forward edge provided the
            //forward/reverse edge is used.
            std::vector<t_node_edge> dedupped_difference;
            std::copy_if(difference.begin(), difference.end(),
                         std::back_inserter(dedupped_difference),
                         [&](t_node_edge forward_edge) {
                             VTR_ASSERT_MSG(!routing_edges.count(forward_edge), "Difference should not contain used routing edges");

                             t_node_edge reverse_edge = {forward_edge.to_node, forward_edge.from_node};

                             //Check whether the reverse edge was used
                             if (rr_edges.count(reverse_edge) && routing_edges.count(reverse_edge)) {
                                 //The reverse edge exists in the set of rr_edges, and was used
                                 //by the routing.
                                 //
                                 //We can therefore safely ignore the fact that this (forward) edge is un-used
                                 return false; //Drop from difference
                             } else {
                                 return true; //Keep, this edge should have been used
                             }
                         });

            //At this point only valid missing node pairs are in the set
            if (!dedupped_difference.empty()) {
                std::string msg = vtr::string_fmt("Illegal routing for net '%s' (#%zu) some required non-configurable edges are missing:\n",
                                                  cluster_ctx.clb_nlist.net_name(net).c_str(), size_t(net));

                for (t_node_edge missing_edge : dedupped_difference) {
                    msg += vtr::string_fmt("  Expected RR Node: %d and RR Node: %d to be non-configurably connected, but edge missing from routing:\n",
                                           missing_edge.from_node, missing_edge.to_node);
                    msg += vtr::string_fmt("    %s\n", describe_rr_node(missing_edge.from_node).c_str());
                    msg += vtr::string_fmt("    %s\n", describe_rr_node(missing_edge.to_node).c_str());
                }

                VPR_FATAL_ERROR(VPR_ERROR_ROUTE, msg.c_str());
            }

            //TODO: verify that the switches used in trace are actually non-configurable
        }
    }

    return true;
}
