#include <cstdio>
using namespace std;

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

struct t_node_edge {
    t_node_edge(int fnode, int tnode) {
        from_node = fnode;
        to_node = tnode;
    }

    int from_node;
    int to_node;

    //For std::set
    friend bool operator<(const t_node_edge& lhs, const t_node_edge& rhs) {
        return std::tie(lhs.from_node, lhs.to_node) < std::tie(rhs.from_node, rhs.to_node);
    }
};

struct t_non_configurable_rr_sets {

    std::set<std::set<int>> node_sets;
    std::set<std::set<t_node_edge>> edge_sets;
};

/******************** 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 t_non_configurable_rr_sets identify_non_configurable_rr_sets();
static void expand_non_configurable(int inode, std::set<t_node_edge>& edge_set);
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, int num_switches) {

	/* 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.num_rr_nodes-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();

	vtr::printf_info("\n");
	vtr::printf_info("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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 		
			"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.num_rr_nodes, sizeof(bool));

	max_pins = 0;
	for (auto net_id : cluster_ctx.clb_nlist.nets())
		max_pins = 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_global(net_id) || cluster_ctx.clb_nlist.net_sinks(net_id).size() == 0) /* Skip global 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_head[net_id];
		if (tptr == nullptr) {
			vpr_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 			
				"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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 					
						"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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 					
						"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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 			
				"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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 				
					"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::printf_info("Completed routing consistency check successfully.\n");
	vtr::printf_info("\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_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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 		
			"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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 		
				 "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_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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 		
			"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].x != i || place_ctx.block_locs[blk_id].y != j) {		
			vpr_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 			
				"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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 			
				"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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 			
				"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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 			
				"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_head[inet];

	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, iconn;
	bool reached;
	t_rr_type from_type, to_type;
	t_type_ptr from_grid_type, to_grid_type;

    auto& device_ctx = g_vpr_ctx.device();

	reached = false;

	for (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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 			
		"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 (inode = 0; inode < device_ctx.num_rr_nodes; inode++)
		route_ctx.rr_node_route_inf[inode].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_global(net_id)) /* Skip global nets. */
			continue;

		tptr = route_ctx.trace_head[net_id];
		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 < cluster_ctx.clb_nlist.block_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 < cluster_ctx.clb_nlist.block_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_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 					
						"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 (cluster_ctx.clb_nlist.block_type(blk_id)->pin_class[ipin] != iclass) {
					vpr_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 					
						"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, cluster_ctx.clb_nlist.block_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 >= device_ctx.num_rr_nodes) { 		
			vpr_throw(VPR_ERROR_ROUTE, __FILE__, __LINE__, 			
				"in check_node_and_range: rr_node #%d is out of legal, range (0 to %d).\n", inode, device_ctx.num_rr_nodes - 1);
	}
	check_rr_node(inode, route_type, device_ctx);
}

//Collects the sets of connected non-configurable edges in the RR graph
static t_non_configurable_rr_sets identify_non_configurable_rr_sets() {
    std::set<std::set<t_node_edge>> edge_sets;

    //Walk through the RR graph and recursively expand non-configurable edges
    //to collect the sets of non-configurably connected nodes
    auto& device_ctx = g_vpr_ctx.device();
    for (int inode = 0; inode < device_ctx.num_rr_nodes; ++inode) {
        std::set<t_node_edge> edge_set;

        expand_non_configurable(inode, edge_set);

        if (!edge_set.empty()) {
            edge_sets.insert(edge_set);
        }
    }

    std::set<std::set<int>> node_sets;
    for (auto& edge_set : edge_sets) {
        std::set<int> node_set;

        for (const auto& edge : edge_set) {
            node_set.insert(edge.from_node);
            node_set.insert(edge.to_node);
        }

        VTR_ASSERT(!node_set.empty());

        node_sets.insert(node_set);
    }

    t_non_configurable_rr_sets non_configurable_rr_sets;
    non_configurable_rr_sets.edge_sets = edge_sets;
    non_configurable_rr_sets.node_sets = node_sets;

    return non_configurable_rr_sets;
}

//Builds a set of non-configurably connected RR graph edges
static void expand_non_configurable(int inode, std::set<t_node_edge>& edge_set) {
    auto& device_ctx = g_vpr_ctx.device();

    for (int iedge = 0; iedge < device_ctx.rr_nodes[inode].num_edges(); ++iedge) {
        bool edge_non_configurable = !device_ctx.rr_nodes[inode].edge_is_configurable(iedge);

        if (edge_non_configurable) {
            int to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge);

            t_node_edge edge = {inode, to_node};

            if (edge_set.count(edge)) {
                continue; //Already seen don't re-expand to avoid loops
            }

            edge_set.emplace(edge);

            expand_non_configurable(to_node, edge_set);
        }
    }
}

//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_head[net];

    //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_THROW(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_THROW(VPR_ERROR_ROUTE, msg.c_str());
            }

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

    return true;
}
