/*This function loads in a routing resource graph written in xml format
 into vpr when the option --read_rr_graph <file name> is specified.
 * When it is not specified the build_rr_graph function is then called.
 * This is done using the libpugixml library. This is useful
 * when specific routing resources should remain constant or when
 * some information left out in the architecture can be specified
 * in the routing resource graph. The routing resource graph file is
 * contained in a <rr_graph> tag. Its subtags describe the rr graph's
 * various features such as nodes, edges, and segments. Information such
 * as blocks, grids, and segments are verified with the architecture
 * to ensure it matches. An error will through if any feature does not match.
 * Other elements such as edges, nodes, and switches
 * are overwritten by the rr graph file if one is specified. If an optional
 * identifier such as capacitance is not specified, it is set to 0*/

#include <string.h>
#include <algorithm>
#include <ctime>
#include "pugixml.hpp"
#include "pugixml_util.hpp"
#include "read_xml_arch_file.h"
#include "read_xml_util.h"
#include "globals.h"
#include "build_rr_graph.h"
#include "build_rr_graph2.h"
#include "rr_graph_indexed_data.h"
#include "vtr_version.h"
#include <sstream>
#include <utility>
#include "vtr_assert.h"
#include "vtr_util.h"
#include "vtr_memory.h"
#include "vtr_matrix.h"
#include "vtr_math.h"
#include "vtr_log.h"
#include "rr_graph_writer.h"
#include "check_rr_graph.h"

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

#include "rr_graph_reader.h"


using namespace std;
using namespace pugiutil;

/*********************** Subroutines local to this module *******************/
void process_switches(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
void verify_segments(pugi::xml_node parent, const pugiutil::loc_data & loc_data, const t_segment_inf *segment_inf);
void verify_blocks(pugi::xml_node parent, const pugiutil::loc_data & loc_data);
void process_blocks(pugi::xml_node parent, const pugiutil::loc_data & loc_data);
void verify_grid(pugi::xml_node parent, const pugiutil::loc_data& loc_data, const DeviceGrid& grid);
void process_nodes(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
void process_edges(pugi::xml_node parent, const pugiutil::loc_data& loc_data, int *wire_to_rr_ipin_switch, const int num_rr_switches);
void process_channels(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
void process_rr_node_indices(const DeviceGrid& grid);
void process_seg_id(pugi::xml_node parent, const pugiutil::loc_data & loc_data);
void set_cost_indices(pugi::xml_node parent, const pugiutil::loc_data& loc_data,
        const bool is_global_graph, const int num_seg_types);

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

/*loads the given RR_graph file into the appropriate data structures
 * as specified by read_rr_graph_name. Set up correct routing data
 * structures as well*/
void load_rr_file(const t_graph_type graph_type,
        const DeviceGrid& grid,
        t_chan_width *nodes_per_chan,
        const int num_seg_types,
        const t_segment_inf * segment_inf,
        const enum e_base_cost_type base_cost_type,
        int *wire_to_rr_ipin_switch,
        int *num_rr_switches,
        const char* read_rr_graph_name) {

    const char *Prop;
    pugi::xml_node next_component;

    pugi::xml_document doc;
    pugiutil::loc_data loc_data;

    if (vtr::check_file_name_extension(read_rr_graph_name, ".xml") == false) {
        vtr::printf_warning(__FILE__, __LINE__,
                "Architecture file '%s' may be in incorrect format. "
                "Expecting .xml format for RR graph files.\n",
                read_rr_graph_name);
    }
    try {

        //parse the file
        loc_data = pugiutil::load_xml(doc, read_rr_graph_name);

        auto& device_ctx = g_vpr_ctx.mutable_device();

        auto rr_graph = get_single_child(doc, "rr_graph", loc_data);

        //Check for errors
        Prop = get_attribute(rr_graph, "tool_version", loc_data, OPTIONAL).as_string(NULL);
        if (Prop != NULL) {
            if (strcmp(Prop, vtr::VERSION) != 0) {
                vtr::printf("\n");
                vtr::printf_warning(__FILE__, __LINE__,
                        "This architecture version is for VPR %s while your current VPR version is %s compatability issues may arise\n",
                        vtr::VERSION, Prop);
                vtr::printf("\n");
            }
        }
        Prop = get_attribute(rr_graph, "tool_comment", loc_data, OPTIONAL).as_string(NULL);
        string correct_string = "Generated from arch file ";
        correct_string += get_arch_file_name();
        if (Prop != NULL) {
            if (Prop != correct_string) {
                vtr::printf("\n");
                vtr::printf_warning(__FILE__, __LINE__,
                        "This RR graph file is based on %s while your input architecture file is %s compatability issues may arise\n"
                        , get_arch_file_name(), Prop);
                vtr::printf("\n");
            }
        }

        //Compare with the architecture file to ensure consistency
        next_component = get_single_child(rr_graph, "grid", loc_data);
        verify_grid(next_component, loc_data, grid);

        next_component = get_single_child(rr_graph, "block_types", loc_data);
        verify_blocks(next_component, loc_data);

        next_component = get_single_child(rr_graph, "segments", loc_data);
        verify_segments(next_component, loc_data, segment_inf);

        vtr::printf_info("Starting build routing resource graph...\n");
        clock_t begin = clock();

        next_component = get_first_child(rr_graph, "channels", loc_data);
        process_channels(next_component, loc_data);

        /* Decode the graph_type */
        bool is_global_graph = (GRAPH_GLOBAL == graph_type ? true : false);

        /* Global routing uses a single longwire track */
        int max_chan_width = (is_global_graph ? 1 : nodes_per_chan->max);
        VTR_ASSERT(max_chan_width > 0);

        /* Alloc rr nodes and count count nodes */
        next_component = get_single_child(rr_graph, "rr_nodes", loc_data);

        device_ctx.num_rr_nodes = count_children(next_component, "node", loc_data);

        device_ctx.rr_nodes = new t_rr_node[device_ctx.num_rr_nodes];
        process_nodes(next_component, loc_data);

        /* Loads edges, switches, and node look up tables*/
        next_component = get_single_child(rr_graph, "switches", loc_data);

        int numSwitches = count_children(next_component, "switch", loc_data);
        *num_rr_switches = numSwitches;
        device_ctx.rr_switch_inf = new t_rr_switch_inf[numSwitches];

        process_switches(next_component, loc_data);

        next_component = get_single_child(rr_graph, "rr_edges", loc_data);
        process_edges(next_component, loc_data, wire_to_rr_ipin_switch, *num_rr_switches);

        process_rr_node_indices(grid);

        init_fan_in(device_ctx.rr_nodes, device_ctx.num_rr_nodes);

        //sets the cost index and seg id information
        next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
        set_cost_indices(next_component, loc_data, is_global_graph, num_seg_types);

        alloc_and_load_rr_indexed_data(segment_inf, num_seg_types, device_ctx.rr_node_indices,
                max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);

        process_seg_id(next_component, loc_data);

        check_rr_graph(graph_type, grid, *num_rr_switches, device_ctx.block_types, segment_inf);

#ifdef USE_MAP_LOOKAHEAD
        compute_router_lookahead(num_seg_types);
#endif

        float elapsed_time = (float) (clock() - begin) / CLOCKS_PER_SEC;
        vtr::printf_info("Build routing resource graph took %g seconds\n", elapsed_time);

    } catch (XmlError& e) {

        vpr_throw(VPR_ERROR_ROUTE, read_rr_graph_name, e.line(), "%s", e.what());
    }

}

/* Reads in the switch information and adds it to device_ctx.rr_switch_inf as specified*/
void process_switches(pugi::xml_node parent, const pugiutil::loc_data & loc_data) {
    auto& device_ctx = g_vpr_ctx.device();
    pugi::xml_node Switch, SwitchSubnode;

    Switch = get_first_child(parent, "switch", loc_data);

    while (Switch) {
        int iSwitch = get_attribute(Switch, "id", loc_data).as_int();
        auto& rr_switch = device_ctx.rr_switch_inf[iSwitch];
        rr_switch.name = get_attribute(Switch, "name", loc_data, OPTIONAL).as_string(NULL);
        rr_switch.buffered = get_attribute(Switch, "buffered", loc_data).as_bool();
        SwitchSubnode = get_single_child(Switch, "timing", loc_data, OPTIONAL);
        if (SwitchSubnode) {
            rr_switch.R = get_attribute(SwitchSubnode, "R", loc_data).as_float();
            rr_switch.Cin = get_attribute(SwitchSubnode, "Cin", loc_data).as_float();
            rr_switch.Cout = get_attribute(SwitchSubnode, "Cout", loc_data).as_float();
            rr_switch.Tdel = get_attribute(SwitchSubnode, "Tdel", loc_data).as_float();
        } else {
            rr_switch.R = 0;
            rr_switch.Cin = 0;
            rr_switch.Cout = 0;
            rr_switch.Tdel = 0;
        }
        SwitchSubnode = get_single_child(Switch, "sizing", loc_data);
        rr_switch.mux_trans_size = get_attribute(SwitchSubnode, "mux_trans_size", loc_data).as_float();
        rr_switch.buf_size = get_attribute(SwitchSubnode, "buf_size", loc_data).as_float();

        Switch = Switch.next_sibling(Switch.name());
    }

}

/*Only CHANX and CHANY components have a segment id. This function
 *reads in the segment id of each node*/
void process_seg_id(pugi::xml_node parent, const pugiutil::loc_data & loc_data) {
    auto& device_ctx = g_vpr_ctx.mutable_device();
    pugi::xml_node segmentSubnode;
    pugi::xml_node rr_node;
    pugi::xml_attribute attribute;
    int id;

    rr_node = get_first_child(parent, "node", loc_data);

    while (rr_node) {
        id = get_attribute(rr_node, "id", loc_data).as_int();
        auto& node = device_ctx.rr_nodes[id];

        segmentSubnode = get_single_child(rr_node, "segment", loc_data, OPTIONAL);
        if (segmentSubnode) {
            attribute = get_attribute(segmentSubnode, "segment_id", loc_data, OPTIONAL);
            if (attribute) {
                int seg_id = get_attribute(segmentSubnode, "segment_id", loc_data).as_int(0);
                device_ctx.rr_indexed_data[node.cost_index()].seg_index = seg_id;
            } else {
                //-1 for non chanx or chany nodes
                device_ctx.rr_indexed_data[node.cost_index()].seg_index = -1;
            }
        }
        rr_node = rr_node.next_sibling(rr_node.name());
    }
}

/* Node info are processed. Seg_id of nodes are processed separately when rr_index_data is allocated*/
void process_nodes(pugi::xml_node parent, const pugiutil::loc_data & loc_data) {
    auto& device_ctx = g_vpr_ctx.mutable_device();
    pugi::xml_node locSubnode, timingSubnode, segmentSubnode;
    pugi::xml_node rr_node;

    rr_node = get_first_child(parent, "node", loc_data);

    while (rr_node) {
        int i = get_attribute(rr_node, "id", loc_data).as_int();
        auto& node = device_ctx.rr_nodes[i];

        const char* node_type = get_attribute(rr_node, "type", loc_data).as_string();
        t_rr_type newType = NUM_RR_TYPES;
        if (strcmp(node_type, "CHANX") == 0) {
            node.set_type(CHANX);
        } else if (strcmp(node_type, "CHANY") == 0) {
            node.set_type(CHANY);
        } else if (strcmp(node_type, "SOURCE") == 0) {
            node.set_type(SOURCE);
        } else if (strcmp(node_type, "SINK") == 0) {
            node.set_type(SINK);
        } else if (strcmp(node_type, "OPIN") == 0) {
            node.set_type(OPIN);
        } else if (strcmp(node_type, "IPIN") == 0) {
            node.set_type(IPIN);
        } else {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                    "Valid inputs for class types are \"CHANX\", \"CHANY\",\"SOURCE\", \"SINK\",\"OPIN\", and \"IPIN\".");
        }

        if (newType == CHANX || newType == CHANY) {
            const char* correct_direction = get_attribute(rr_node, "direction", loc_data).as_string();
            if (strcmp(correct_direction, "INC_DIR") == 0) {
                node.set_direction(INC_DIRECTION);
            } else if (strcmp(correct_direction, "DEC_DIR") == 0) {
                node.set_direction(DEC_DIRECTION);
            } else if (strcmp(correct_direction, "BI_DIR") == 0) {
                node.set_direction(BI_DIRECTION);
            } else {
                VTR_ASSERT((strcmp(correct_direction, "NO_DIR") == 0));
                node.set_direction(NO_DIRECTION);
            }
        }

        node.set_capacity(get_attribute(rr_node, "capacity", loc_data).as_float());

        //--------------
        locSubnode = get_single_child(rr_node, "loc", loc_data);

        short x1, x2, y1, y2;
        x1 = get_attribute(locSubnode, "xlow", loc_data).as_float();
        x2 = get_attribute(locSubnode, "xhigh", loc_data).as_float();
        y1 = get_attribute(locSubnode, "ylow", loc_data).as_float();
        y2 = get_attribute(locSubnode, "yhigh", loc_data).as_float();

        if (newType == IPIN || newType == OPIN) {
            e_side side;
            std::string side_str = get_attribute(locSubnode, "side", loc_data).as_string();
            if (side_str == "LEFT") {
                side = LEFT;
            } else if (side_str == "RIGHT") {
                side = RIGHT;
            } else if (side_str == "TOP") {
                side = TOP;
            } else {
                VTR_ASSERT(side_str == "BOTTOM");
                side = BOTTOM;
            }
            node.set_side(side);
        }

        node.set_coordinates(x1, y1, x2, y2);
        node.set_ptc_num(get_attribute(locSubnode, "ptc", loc_data).as_int());

        //-------
        timingSubnode = get_single_child(rr_node, "timing", loc_data, OPTIONAL);

        if (timingSubnode) {
            node.set_R(get_attribute(timingSubnode, "R", loc_data).as_float());
            node.set_C(get_attribute(timingSubnode, "C", loc_data).as_float());
        } else {
            node.set_R(0);
            node.set_C(0);
        }
        //clear each node edge
        node.set_num_edges(0);

        rr_node = rr_node.next_sibling(rr_node.name());
    }
}

/*Loads the edges information from file into vpr. Nodes and switches must be loaded
 before calling this function*/
void process_edges(pugi::xml_node parent, const pugiutil::loc_data & loc_data,
        int *wire_to_rr_ipin_switch, const int num_rr_switches) {

    auto& device_ctx = g_vpr_ctx.mutable_device();
    pugi::xml_node edges;

    edges = get_first_child(parent, "edge", loc_data);
    int source_node;
    //count the number of edges and store it in a vector
    vector<int> num_edges_for_node;
    num_edges_for_node.resize(device_ctx.num_rr_nodes, 0);

    while (edges) {
        source_node = get_attribute(edges, "src_node", loc_data).as_int(0);
        num_edges_for_node[source_node]++;
        device_ctx.rr_nodes[source_node].set_num_edges(num_edges_for_node[source_node]);
        edges = edges.next_sibling(edges.name());
    }

    //reset this vector in order to start count for num edges again
    for (int inode = 0; inode < device_ctx.num_rr_nodes; inode++) {
        num_edges_for_node[inode] = 0;
    }

    int sink_node, switch_id;
    edges = get_first_child(parent, "edge", loc_data);
    /*initialize a vector that keeps track of the number of wire to ipin switches
    There should be only one wire to ipin switch. In case there are more, make sure to
    store the most frequent switch */
    std::vector<int> count_for_wire_to_ipin_switches;
    count_for_wire_to_ipin_switches.resize(num_rr_switches, 0);
    //first is index, second is count
    pair <int, int> most_frequent_switch(-1, 0);

    while (edges) {
        source_node = get_attribute(edges, "src_node", loc_data).as_int(0);
        sink_node = get_attribute(edges, "sink_node", loc_data).as_int(0);
        switch_id = get_attribute(edges, "switch_id", loc_data).as_int(0);

        /*Keeps track of the number of the specific type of switch that connects a wire to an ipin
         * use the pair data structure to keep the maximum*/
        if (device_ctx.rr_nodes[source_node].type() == CHANX || device_ctx.rr_nodes[source_node].type() == CHANY) {
            if (device_ctx.rr_nodes[sink_node].type() == IPIN) {
                count_for_wire_to_ipin_switches[switch_id]++;
                if (count_for_wire_to_ipin_switches[switch_id] > most_frequent_switch.second) {
                    most_frequent_switch.first = switch_id;
                    most_frequent_switch.second = count_for_wire_to_ipin_switches[switch_id];
                }
            }
        }
        //set edge in correct rr_node data structure
        device_ctx.rr_nodes[source_node].set_edge_sink_node(num_edges_for_node[source_node], sink_node);
        device_ctx.rr_nodes[source_node].set_edge_switch(num_edges_for_node[source_node], switch_id);
        edges = edges.next_sibling(edges.name());
        num_edges_for_node[source_node]++;
    }
    *wire_to_rr_ipin_switch = most_frequent_switch.first;
    num_edges_for_node.clear();
    count_for_wire_to_ipin_switches.clear();
}

/* All channel info is read in and loaded into device_ctx.chan_width*/
void process_channels(pugi::xml_node parent, const pugiutil::loc_data & loc_data) {
    auto& device_ctx = g_vpr_ctx.mutable_device();
    pugi::xml_node channel, channelLists;
    int index;

    channel = get_first_child(parent, "channel", loc_data);

    device_ctx.chan_width.max = get_attribute(channel, "chan_width_max", loc_data).as_uint();
    device_ctx.chan_width.x_min = get_attribute(channel, "x_min", loc_data).as_uint();
    device_ctx.chan_width.y_min = get_attribute(channel, "y_min", loc_data).as_uint();
    device_ctx.chan_width.x_max = get_attribute(channel, "x_max", loc_data).as_uint();
    device_ctx.chan_width.y_max = get_attribute(channel, "y_max", loc_data).as_uint();

    channelLists = get_first_child(parent, "x_list", loc_data);
    while (channelLists) {
        index = get_attribute(channelLists, "index", loc_data).as_int(0);
        device_ctx.chan_width.x_list[index] = get_attribute(channelLists, "info", loc_data).as_float();
        channelLists = channelLists.next_sibling(channelLists.name());
    }
    channelLists = get_first_child(parent, "y_list", loc_data);
    while (channelLists) {
        index = get_attribute(channelLists, "index", loc_data).as_int(0);
        device_ctx.chan_width.y_list[index] = get_attribute(channelLists, "info", loc_data).as_float();
        channelLists = channelLists.next_sibling(channelLists.name());
    }

}

/* Grid was initialized from the architecture file. This function checks 
 * if it corresponds to the RR graph. Errors out if it doesn't correspond*/
void verify_grid(pugi::xml_node parent, const pugiutil::loc_data & loc_data, const DeviceGrid& grid) {
    pugi::xml_node grid_node;
    int num_grid_node = count_children(parent, "grid_loc", loc_data);

    grid_node = get_first_child(parent, "grid_loc", loc_data);
    for (int i = 0; i < num_grid_node; i++) {
        int x = get_attribute(grid_node, "x", loc_data).as_float();
        int y = get_attribute(grid_node, "y", loc_data).as_float();

        const t_grid_tile& grid_tile = grid[x][y];

        if (grid_tile.type->index != get_attribute(grid_node, "block_type_id", loc_data).as_float(0)) {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                    "Architecture file does not match RR graph's block_type_id");
        }
        if (grid_tile.width_offset != get_attribute(grid_node, "width_offset", loc_data).as_float(0)) {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                    "Architecture file does not match RR graph's width_offset");
        }

        if (grid_tile.height_offset != get_attribute(grid_node, "height_offset", loc_data).as_float(0)) {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                    "Architecture file does not match RR graph's height_offset");
        }
        grid_node = grid_node.next_sibling(grid_node.name());
    }
}

/* Blocks were initialized from the architecture file. This function checks 
 * if it corresponds to the RR graph. Errors out if it doesn't correspond*/
void verify_blocks(pugi::xml_node parent, const pugiutil::loc_data & loc_data) {

    pugi::xml_node Block;
    pugi::xml_node pin_class;
    Block = get_first_child(parent, "block_type", loc_data);
    auto& device_ctx = g_vpr_ctx.mutable_device();
    while (Block) {

        auto block_info = device_ctx.block_types[get_attribute(Block, "id", loc_data).as_int(0)];

        const char* name = get_attribute(Block, "name", loc_data).as_string(NULL);

        if (strcmp(block_info.name, name) != 0) {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                    "Architecture file does not match RR graph's block name");
        }

        if (block_info.width != get_attribute(Block, "width", loc_data).as_float(0)) {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                    "Architecture file does not match RR graph's block width");
        }
        if (block_info.height != get_attribute(Block, "height", loc_data).as_float(0)) {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                    "Architecture file does not match RR graph's block height");
        }

        pin_class = get_first_child(Block, "pin_class", loc_data, OPTIONAL);

        block_info.num_class = count_children(Block, "pin_class", loc_data, OPTIONAL);

        for (int classNum = 0; classNum < block_info.num_class; classNum++) {
            auto& class_inf = block_info.class_inf[classNum];
            e_pin_type type;

            /*Verify types and pins*/
            const char* typeInfo = get_attribute(pin_class, "type", loc_data).value();
            if (strcmp(typeInfo, "OPEN") == 0) {
                type = OPEN;
            } else if (strcmp(typeInfo, "OUTPUT") == 0) {
                type = DRIVER;
            } else if (strcmp(typeInfo, "INPUT") == 0) {
                type = RECEIVER;
            } else {
                vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                        "Valid inputs for class types are \"OPEN\", \"OUTPUT\", and \"INPUT\".");
                type = OPEN;
            }

            if (class_inf.type != type) {
                vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                        "Architecture file does not match RR graph's block type");
            }

            //Go through each pin of the pin list
            string temp = pin_class.child_value();
            std::vector<std::string> tokens;
            tokens = vtr::split(temp);
            if (!tokens.empty()) {
                for (unsigned ipin = 0; ipin < tokens.size(); ipin++) {
                    if (class_inf.pinlist[ipin] != atoi(tokens[ipin].c_str())) {
                        vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                                "Architecture file does not match RR graph's block pin list");
                    }
                }
            }
            tokens.clear();
            pin_class = pin_class.next_sibling(pin_class.name());
        }
        Block = Block.next_sibling(Block.name());
    }
}

/* Segments was initialized already. This function checks 
 * if it corresponds to the RR graph. Errors out if it doesn't correspond*/
void verify_segments(pugi::xml_node parent, const pugiutil::loc_data & loc_data, const t_segment_inf * segment_inf) {
    pugi::xml_node Segment, subnode;

    Segment = get_first_child(parent, "segment", loc_data);
    while (Segment) {
        int segNum = get_attribute(Segment, "id", loc_data).as_int();
        const char* name = get_attribute(Segment, "name", loc_data).as_string();
        if (strcmp(segment_inf[segNum].name, name) != 0) {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                    "Architecture file does not match RR graph's segment name");
        }

        subnode = get_single_child(parent, "timing", loc_data, OPTIONAL);

        if (subnode) {
            if (segment_inf[segNum].Rmetal != get_attribute(subnode, "R_per_meter", loc_data).as_float(0)) {
                vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                        "Architecture file does not match RR graph's segment R_per_meter");
            }
            if (segment_inf[segNum].Cmetal != get_attribute(subnode, "C_per_meter", loc_data).as_float(0)) {
                vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                        "Architecture file does not match RR graph's segment C_per_meter");
            }
        }
        Segment = Segment.next_sibling(Segment.name());
    }
}

/*Allocates and load the rr_node look up table. SINK and SOURCE, IPIN and OPIN
 *share the same look up table. CHANX and CHANY have individual look ups */
void process_rr_node_indices(const DeviceGrid& grid) {
    auto& device_ctx = g_vpr_ctx.mutable_device();

    /* Alloc the lookup table */

    auto& indices = device_ctx.rr_node_indices;

    indices.resize(NUM_RR_TYPES);

    /* Alloc the lookup table */
    indices.resize(NUM_RR_TYPES);
    for (t_rr_type rr_type : RR_TYPES) {
        if (rr_type == CHANX) {
            indices[rr_type].resize(grid.height());
            for (size_t y = 0; y < grid.height(); ++y) {
                indices[rr_type][y].resize(grid.width());
                for (size_t x = 0; x < grid.width(); ++x) {
                    indices[rr_type][y][x].resize(NUM_SIDES);
                }
            }
        } else {
            indices[rr_type].resize(grid.width());
            for (size_t x = 0; x < grid.width(); ++x) {
                indices[rr_type][x].resize(grid.height());
                for (size_t y = 0; y < grid.height(); ++y) {
                    indices[rr_type][x][y].resize(NUM_SIDES);
                }
            }
        }
    }

    /*Add the correct node into the vector
     * Note that CHANX and CHANY 's x and y are swapped due to the chan and seg convention.
     * Push back temporary incorrect nodes for CHANX and CHANY to set the length of the vector*/

    for (int inode = 0; inode < device_ctx.num_rr_nodes; inode++) {
        auto& node = device_ctx.rr_nodes[inode];
        if (node.type() == SOURCE || node.type() == SINK) {
            for (int ix = node.xlow(); ix <= node.xhigh(); ix++) {
                for (int iy = node.ylow(); iy <= node.yhigh(); iy++) {
                    if (node.type() == SOURCE) {
                        indices[SOURCE][ix][iy][0].push_back(inode);
                        indices[SINK][ix][iy][0].push_back(OPEN);
                    } else  {
                        VTR_ASSERT(node.type() == SINK);
                        indices[SINK][ix][iy][0].push_back(inode);
                        indices[SOURCE][ix][iy][0].push_back(OPEN);
                    }
                }
            }
        } else if (node.type() == IPIN || node.type() == OPIN) {
            for (int ix = node.xlow(); ix <= node.xhigh(); ix++) {
                for (int iy = node.ylow(); iy <= node.yhigh(); iy++) {

                    if (node.type() == OPIN) {
                        indices[OPIN][ix][iy][node.side()].push_back(inode);
                        indices[IPIN][ix][iy][node.side()].push_back(OPEN);
                    } else {
                        VTR_ASSERT(node.type() == IPIN);
                        indices[IPIN][ix][iy][node.side()].push_back(inode);
                        indices[OPIN][ix][iy][node.side()].push_back(OPEN);
                    }
                }
            }
        } else if (node.type() == CHANX) {
            for (int ix = node.xlow(); ix <= node.xhigh(); ix++) {
                for (int iy = node.ylow(); iy <= node.yhigh(); iy++) {
                    indices[CHANX][iy][ix][0].push_back(inode);
                }
            }
        } else if (node.type() == CHANY) {
            for (int ix = node.xlow(); ix <= node.xhigh(); ix++) {
                for (int iy = node.ylow(); iy <= node.yhigh(); iy++) {
                    indices[CHANY][ix][iy][0].push_back(inode);
                }
            }
        }
    }

    int count;
    /* CHANX and CHANY need to reevaluated with its ptc num as the correct index*/
    for (int inode = 0; inode < device_ctx.num_rr_nodes; inode++) {
        auto& node = device_ctx.rr_nodes[inode];
        if (node.type() == CHANX) {
            for (int iy = node.ylow(); iy <= node.yhigh(); iy++) {
                for (int ix = node.xlow(); ix <= node.xhigh(); ix++) {
                    count = node.ptc_num();
                    indices[CHANX][iy][ix][0][count] = inode;
                }
            }
        } else if (node.type() == CHANY) {
            for (int ix = node.xlow(); ix <= node.xhigh(); ix++) {
                for (int iy = node.ylow(); iy <= node.yhigh(); iy++) {
                    count = node.ptc_num();
                    indices[CHANY][ix][iy][0][count] = inode;
                }
            }
        }
    }
    //Copy the SOURCE/SINK nodes to all offset positions for blocks with width > 1 and/or height > 1
    // This ensures that look-ups on non-root locations will still find the correct SOURCE/SINK
    for (size_t x = 0; x < grid.width(); x++) {
        for (size_t y = 0; y < grid.height(); y++) {
            int width_offset = grid[x][y].width_offset;
            int height_offset = grid[x][y].height_offset;
            if (width_offset != 0 || height_offset != 0) {
                int root_x = x - width_offset;
                int root_y = y - height_offset;

                indices[SOURCE][x][y] = indices[SOURCE][root_x][root_y];
                indices[SINK][x][y] = indices[SINK][root_x][root_y];
            }
        }
    }

    device_ctx.rr_node_indices = indices;
}

/* This function sets the Source pins, sink pins, ipin, and opin
 * to their unique cost index identifier. CHANX and CHANY cost indicies are set after the 
 * seg_id is read in from the rr graph*/
void set_cost_indices(pugi::xml_node parent, const pugiutil::loc_data& loc_data,
        const bool is_global_graph, const int num_seg_types) {
    auto& device_ctx = g_vpr_ctx.mutable_device();

    //set the cost index in order to load the segment information, rr nodes should be set already
    for (int inode = 0; inode < device_ctx.num_rr_nodes; inode++) {
        if (device_ctx.rr_nodes[inode].type() == SOURCE) {
            device_ctx.rr_nodes[inode].set_cost_index(SOURCE_COST_INDEX);
        } else if (device_ctx.rr_nodes[inode].type() == SINK) {
            device_ctx.rr_nodes[inode].set_cost_index(SINK_COST_INDEX);
        } else if (device_ctx.rr_nodes[inode].type() == IPIN) {
            device_ctx.rr_nodes[inode].set_cost_index(IPIN_COST_INDEX);
        } else if (device_ctx.rr_nodes[inode].type() == OPIN) {
            device_ctx.rr_nodes[inode].set_cost_index(OPIN_COST_INDEX);
        }
    }

    pugi::xml_node segmentSubnode;
    pugi::xml_node rr_node;
    pugi::xml_attribute attribute;

    /*Go through each rr_node and use the segment ids to set CHANX and CHANY cost index*/
    rr_node = get_first_child(parent, "node", loc_data);

    for (int i = 0; i < device_ctx.num_rr_nodes; i++) {
        auto& node = device_ctx.rr_nodes[i];

        /*CHANX and CHANY cost index is dependent on the segment id*/

        segmentSubnode = get_single_child(rr_node, "segment", loc_data, OPTIONAL);
        if (segmentSubnode) {
            attribute = get_attribute(segmentSubnode, "segment_id", loc_data, OPTIONAL);
            if (attribute) {
                int seg_id = get_attribute(segmentSubnode, "segment_id", loc_data).as_int(0);
                if (is_global_graph) {
                    node.set_cost_index(0);
                } else if (device_ctx.rr_nodes[i].type() == CHANX) {
                    node.set_cost_index(CHANX_COST_INDEX_START + seg_id);
                } else if (device_ctx.rr_nodes[i].type() == CHANY) {
                    node.set_cost_index(CHANX_COST_INDEX_START + num_seg_types + seg_id);

                }
            }
        }
        rr_node = rr_node.next_sibling(rr_node.name());
    }
}
