/*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 <sstream>
#include <utility>

#include "vtr_version.h"
#include "vtr_assert.h"
#include "vtr_util.h"
#include "vtr_memory.h"
#include "vtr_math.h"
#include "vtr_log.h"
#include "vtr_time.h"

#include "pugixml.hpp"
#include "pugixml_util.hpp"
#include "read_xml_arch_file.h"
#include "read_xml_util.h"
#include "globals.h"
#include "rr_graph.h"
#include "rr_graph2.h"
#include "rr_metadata.h"
#include "rr_graph_indexed_data.h"
#include "rr_graph_writer.h"
#include "check_rr_graph.h"
#include "echo_files.h"

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

#include "rr_graph_reader.h"

/*********************** 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 std::vector<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(t_chan_width& chan_width, const DeviceGrid& grid, 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,
                  const std::vector<t_segment_inf>& segment_inf,
                  const enum e_base_cost_type base_cost_type,
                  int* wire_to_rr_ipin_switch,
                  const char* read_rr_graph_name) {
    vtr::ScopedStartFinishTimer timer("Loading routing resource graph");

    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_LOG_WARN(
            "RR graph file '%s' may be in incorrect format. "
            "Expecting .xml format\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, pugiutil::OPTIONAL).as_string(nullptr);
        if (Prop != nullptr) {
            if (strcmp(Prop, vtr::VERSION) != 0) {
                VTR_LOG("\n");
                VTR_LOG_WARN("This architecture version is for VPR %s while your current VPR version is %s compatability issues may arise\n",
                             vtr::VERSION, Prop);
                VTR_LOG("\n");
            }
        }
        Prop = get_attribute(rr_graph, "tool_comment", loc_data, pugiutil::OPTIONAL).as_string(nullptr);
        std::string correct_string = "Generated from arch file ";
        correct_string += get_arch_file_name();
        if (Prop != nullptr) {
            if (Prop != correct_string) {
                VTR_LOG("\n");
                VTR_LOG_WARN("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_LOG("\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_LOG("Starting build routing resource graph...\n");

        next_component = get_first_child(rr_graph, "channels", loc_data);
        t_chan_width nodes_per_chan;
        process_channels(nodes_per_chan, grid, 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);

        int num_rr_nodes = count_children(next_component, "node", loc_data);

        device_ctx.rr_nodes.resize(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);
        device_ctx.rr_switch_inf.resize(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, numSwitches);

        //Partition the rr graph edges for efficient access to configurable/non-configurable
        //edge subsets. Must be done after RR switches have been allocated
        partition_rr_graph_edges(device_ctx);

        process_rr_node_indices(grid);

        init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());

        //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, segment_inf.size());

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

        process_seg_id(next_component, loc_data);

        device_ctx.chan_width = nodes_per_chan;
        device_ctx.read_rr_graph_filename = std::string(read_rr_graph_name);

        check_rr_graph(graph_type, grid, device_ctx.physical_tile_types);

    } catch (pugiutil::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.mutable_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];
        const char* name = get_attribute(Switch, "name", loc_data, pugiutil::OPTIONAL).as_string(nullptr);
        bool found_arch_name = false;
        if (name != nullptr) {
            for (int i = 0; i < device_ctx.num_arch_switches; ++i) {
                if (strcmp(name, device_ctx.arch_switch_inf[i].name) == 0) {
                    name = device_ctx.arch_switch_inf[i].name;
                    found_arch_name = true;
                    break;
                }
            }
        }

        if (name != nullptr && !found_arch_name) {
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Switch name '%s' not found in architecture\n", name);
        }

        rr_switch.name = name;

        std::string switch_type_str = get_attribute(Switch, "type", loc_data).as_string();
        SwitchType switch_type = SwitchType::INVALID;
        if (switch_type_str == "tristate") {
            switch_type = SwitchType::TRISTATE;
        } else if (switch_type_str == "mux") {
            switch_type = SwitchType::MUX;
        } else if (switch_type_str == "pass_gate") {
            switch_type = SwitchType::PASS_GATE;
        } else if (switch_type_str == "short") {
            switch_type = SwitchType::SHORT;
        } else if (switch_type_str == "buffer") {
            switch_type = SwitchType::BUFFER;
        } else {
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Invalid switch type '%s'\n", switch_type_str.c_str());
        }
        rr_switch.set_type(switch_type);
        SwitchSubnode = get_single_child(Switch, "timing", loc_data, pugiutil::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.Cinternal = get_attribute(SwitchSubnode, "Cinternal", 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.Cinternal = 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, pugiutil::OPTIONAL);
        if (segmentSubnode) {
            attribute = get_attribute(segmentSubnode, "segment_id", loc_data, pugiutil::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 inode = get_attribute(rr_node, "id", loc_data).as_int();
        auto& node = device_ctx.rr_nodes[inode];

        const char* node_type = get_attribute(rr_node, "type", loc_data).as_string();
        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_FATAL_ERROR(VPR_ERROR_OTHER,
                            "Valid inputs for class types are \"CHANX\", \"CHANY\",\"SOURCE\", \"SINK\",\"OPIN\", and \"IPIN\".");
        }

        if (node.type() == CHANX || node.type() == 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 (node.type() == IPIN || node.type() == 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, pugiutil::OPTIONAL);

        float R = 0.;
        float C = 0.;
        if (timingSubnode) {
            R = get_attribute(timingSubnode, "R", loc_data).as_float();
            C = get_attribute(timingSubnode, "C", loc_data).as_float();
        }
        node.set_rc_index(find_create_rr_rc_data(R, C));

        //clear each node edge
        node.set_num_edges(0);

        //  <metadata>
        //    <meta name='grid_prefix' >CLBLL_L_</meta>
        //  </metadata>
        auto metadata = get_single_child(rr_node, "metadata", loc_data, pugiutil::OPTIONAL);
        if (metadata) {
            auto rr_node_meta = get_first_child(metadata, "meta", loc_data);
            while (rr_node_meta) {
                auto key = get_attribute(rr_node_meta, "name", loc_data).as_string();

                vpr::add_rr_node_metadata(inode, key, rr_node_meta.child_value());

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

        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);
    //count the number of edges and store it in a vector
    std::vector<size_t> num_edges_for_node;
    num_edges_for_node.resize(device_ctx.rr_nodes.size(), 0);

    while (edges) {
        size_t source_node = get_attribute(edges, "src_node", loc_data).as_uint();
        if (source_node >= device_ctx.rr_nodes.size()) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "source_node %d is larger than rr_nodes.size() %d",
                            source_node, device_ctx.rr_nodes.size());
        }

        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 (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        if (num_edges_for_node[inode] > std::numeric_limits<t_edge_size>::max()) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "source node %d edge count %d is too high",
                            inode, num_edges_for_node[inode]);
        }
        device_ctx.rr_nodes[inode].set_num_edges(num_edges_for_node[inode]);
        num_edges_for_node[inode] = 0;
    }

    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
    std::pair<int, int> most_frequent_switch(-1, 0);

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

        if (sink_node >= device_ctx.rr_nodes.size()) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "sink_node %d is larger than rr_nodes.size() %d",
                            sink_node, device_ctx.rr_nodes.size());
        }

        if (switch_id >= num_rr_switches) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "switch_id %d is larger than num_rr_switches %d",
                            switch_id, num_rr_switches);
        }

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

        // Read the metadata for the edge
        auto metadata = get_single_child(edges, "metadata", loc_data, pugiutil::OPTIONAL);
        if (metadata) {
            auto edges_meta = get_first_child(metadata, "meta", loc_data);
            while (edges_meta) {
                auto key = get_attribute(edges_meta, "name", loc_data).as_string();

                vpr::add_rr_edge_metadata(source_node, sink_node, switch_id,
                                          key, edges_meta.child_value());

                edges_meta = edges_meta.next_sibling(edges_meta.name());
            }
        }
        num_edges_for_node[source_node]++;

        edges = edges.next_sibling(edges.name()); //Next edge
    }
    *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(t_chan_width& chan_width, const DeviceGrid& grid, pugi::xml_node parent, const pugiutil::loc_data& loc_data) {
    pugi::xml_node channel, channelLists;

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

    chan_width.max = get_attribute(channel, "chan_width_max", loc_data).as_uint();
    chan_width.x_min = get_attribute(channel, "x_min", loc_data).as_uint();
    chan_width.y_min = get_attribute(channel, "y_min", loc_data).as_uint();
    chan_width.x_max = get_attribute(channel, "x_max", loc_data).as_uint();
    chan_width.y_max = get_attribute(channel, "y_max", loc_data).as_uint();
    chan_width.x_list.resize(grid.height());
    chan_width.y_list.resize(grid.width());

    channelLists = get_first_child(parent, "x_list", loc_data);
    while (channelLists) {
        size_t index = get_attribute(channelLists, "index", loc_data).as_uint();
        if (index >= chan_width.x_list.size()) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "index %d on x_list exceeds x_list size %u",
                            index, chan_width.x_list.size());
        }
        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) {
        size_t index = get_attribute(channelLists, "index", loc_data).as_uint();
        if (index >= chan_width.y_list.size()) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "index %d on y_list exceeds y_list size %u",
                            index, chan_width.y_list.size());
        }
        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_int(0)) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "Architecture file does not match RR graph's block_type_id at (%d, %d): arch used ID %d, RR graph used ID %d.", x, y,
                            (grid_tile.type->index), get_attribute(grid_node, "block_type_id", loc_data).as_int(0));
        }
        if (grid_tile.width_offset != get_attribute(grid_node, "width_offset", loc_data).as_float(0)) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "Architecture file does not match RR graph's width_offset at (%d, %d)", x, y);
        }

        if (grid_tile.height_offset != get_attribute(grid_node, "height_offset", loc_data).as_float(0)) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "Architecture file does not match RR graph's height_offset at (%d, %d)", x, y);
        }
        grid_node = grid_node.next_sibling(grid_node.name());
    }
}

static int pin_index_by_num(const t_class& class_inf, int num) {
    for (int index = 0; index < class_inf.num_pins; ++index) {
        if (num == class_inf.pinlist[index]) {
            return index;
        }
    }
    return -1;
}

/* 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;
    pugi::xml_node pin;
    Block = get_first_child(parent, "block_type", loc_data);
    auto& device_ctx = g_vpr_ctx.mutable_device();
    while (Block) {
        auto block_info = device_ctx.physical_tile_types[get_attribute(Block, "id", loc_data).as_int(0)];

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

        if (strcmp(block_info.name, name) != 0) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "Architecture file does not match RR graph's block name: arch uses name %s, RR graph uses name %s", block_info.name, name);
        }

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

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

        block_info.num_class = count_children(Block, "pin_class", loc_data, pugiutil::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_FATAL_ERROR(VPR_ERROR_OTHER,
                                "Valid inputs for class types are \"OPEN\", \"OUTPUT\", and \"INPUT\".");
                type = OPEN;
            }

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

            if (class_inf.num_pins != (int)count_children(pin_class, "pin", loc_data)) {
                VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                                "Incorrect number of pins in %d pin_class in block %s", classNum, block_info.name);
            }

            pin = get_first_child(pin_class, "pin", loc_data, pugiutil::OPTIONAL);
            while (pin) {
                auto num = get_attribute(pin, "ptc", loc_data).as_uint();
                auto index = pin_index_by_num(class_inf, num);

                if (index < 0) {
                    VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                                    "Architecture file does not match RR graph's block pin list: invalid ptc for pin class");
                }

                if (pin.child_value() != block_type_pin_index_to_name(&block_info, class_inf.pinlist[index])) {
                    VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                                    "Architecture file does not match RR graph's block pin list");
                }
                pin = pin.next_sibling("pin");
            }
            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 std::vector<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.c_str(), name) != 0) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "Architecture file does not match RR graph's segment name: arch uses %s, RR graph uses %s", segment_inf[segNum].name.c_str(), name);
        }

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

        if (subnode) {
            if (segment_inf[segNum].Rmetal != get_attribute(subnode, "R_per_meter", loc_data).as_float(0)) {
                VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                                "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_FATAL_ERROR(VPR_ERROR_OTHER,
                                "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);

    typedef struct max_ptc {
        short chanx_max_ptc = 0;
        short chany_max_ptc = 0;
    } t_max_ptc;

    /*
     * Local multi-dimensional vector to hold max_ptc for every coordinate.
     * It has same height and width as CHANY and CHANX are inverted
     */
    vtr::Matrix<t_max_ptc> coordinates_max_ptc; /* [x][y] */
    size_t max_coord_size = std::max(grid.width(), grid.height());
    coordinates_max_ptc.resize({max_coord_size, max_coord_size}, t_max_ptc());

    /* Alloc the lookup table */
    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
     * For CHANX and CHANY no node is added yet, but the maximum ptc is counted for each
     * x/y location. This is needed later to add the correct node corresponding to CHANX
     * and CHANY.
     *
     * Note that CHANX and CHANY 's x and y are swapped due to the chan and seg convention.
     */
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); 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++) {
                    coordinates_max_ptc[iy][ix].chanx_max_ptc = std::max(coordinates_max_ptc[iy][ix].chanx_max_ptc, node.ptc_num());
                }
            }
        } else if (node.type() == CHANY) {
            for (int ix = node.xlow(); ix <= node.xhigh(); ix++) {
                for (int iy = node.ylow(); iy <= node.yhigh(); iy++) {
                    coordinates_max_ptc[ix][iy].chany_max_ptc = std::max(coordinates_max_ptc[ix][iy].chany_max_ptc, node.ptc_num());
                }
            }
        }
    }

    /* Alloc the lookup table */
    for (t_rr_type rr_type : RR_TYPES) {
        if (rr_type == CHANX) {
            for (size_t y = 0; y < grid.height(); ++y) {
                for (size_t x = 0; x < grid.width(); ++x) {
                    indices[CHANX][y][x][0].resize(coordinates_max_ptc[y][x].chanx_max_ptc + 1, OPEN);
                }
            }
        } else if (rr_type == CHANY) {
            for (size_t x = 0; x < grid.width(); ++x) {
                for (size_t y = 0; y < grid.height(); ++y) {
                    indices[CHANY][x][y][0].resize(coordinates_max_ptc[x][y].chany_max_ptc + 1, OPEN);
                }
            }
        }
    }

    int count;
    /* CHANX and CHANY need to reevaluated with its ptc num as the correct index*/
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); 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();
                    if (count >= int(indices[CHANX][iy][ix][0].size())) {
                        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                        "Ptc index %d for CHANX (%d, %d) is out of bounds, size = %zu",
                                        count, ix, iy, indices[CHANX][iy][ix][0].size());
                    }
                    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();
                    if (count >= int(indices[CHANY][ix][iy][0].size())) {
                        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                        "Ptc index %d for CHANY (%d, %d) is out of bounds, size = %zu",
                                        count, ix, iy, indices[CHANY][ix][iy][0].size());
                    }
                    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 (size_t inode = 0; inode < device_ctx.rr_nodes.size(); 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);

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

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

        segmentSubnode = get_single_child(rr_node, "segment", loc_data, pugiutil::OPTIONAL);
        if (segmentSubnode) {
            attribute = get_attribute(segmentSubnode, "segment_id", loc_data, pugiutil::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 (node.type() == CHANX) {
                    node.set_cost_index(CHANX_COST_INDEX_START + seg_id);
                } else if (node.type() == CHANY) {
                    node.set_cost_index(CHANX_COST_INDEX_START + num_seg_types + seg_id);
                }
            }
        }
        rr_node = rr_node.next_sibling(rr_node.name());
    }
}
