#include "rr_graph_clock.h"

#include "globals.h"
#include "rr_graph.h"
#include "rr_graph2.h"
#include "rr_graph_area.h"
#include "rr_graph_util.h"
#include "rr_graph_indexed_data.h"

#include "vtr_assert.h"
#include "vtr_log.h"
#include "vpr_error.h"

void ClockRRGraphBuilder::create_and_append_clock_rr_graph(std::vector<t_segment_inf>& segment_inf,
                                                           const float R_minW_nmos,
                                                           const float R_minW_pmos,
                                                           int wire_to_rr_ipin_switch,
                                                           const enum e_base_cost_type base_cost_type) {
    vtr::printf_info("Starting clock network routing resource graph generation...\n");
    clock_t begin = clock();

    auto& device_ctx = g_vpr_ctx.mutable_device();
    auto* chan_width = &device_ctx.chan_width;
    auto& clock_networks = device_ctx.clock_networks;
    auto& clock_routing = device_ctx.clock_connections;

    size_t clock_nodes_start_idx = device_ctx.rr_nodes.size();

    ClockRRGraphBuilder clock_graph = ClockRRGraphBuilder();
    clock_graph.create_clock_networks_wires(clock_networks, segment_inf.size());
    clock_graph.create_clock_networks_switches(clock_routing);

    // Reset fanin to account for newly added clock rr_nodes
    init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());

    clock_graph.add_rr_switches_and_map_to_nodes(clock_nodes_start_idx, R_minW_nmos, R_minW_pmos);

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

    alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
                                   chan_width->max, wire_to_rr_ipin_switch, base_cost_type);

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

// Clock network information comes from the arch file
void ClockRRGraphBuilder::create_clock_networks_wires(std::vector<std::unique_ptr<ClockNetwork>>& clock_networks,
                                                      int num_segments) {
    // Add rr_nodes for each clock network wire
    for (auto& clock_network : clock_networks) {
        clock_network->create_rr_nodes_for_clock_network_wires(*this, num_segments);
    }

    // Reduce the capacity of rr_nodes for performance
    auto& rr_nodes = g_vpr_ctx.mutable_device().rr_nodes;
    rr_nodes.shrink_to_fit();
}

// Clock switch information comes from the arch file
void ClockRRGraphBuilder::create_clock_networks_switches(std::vector<std::unique_ptr<ClockConnection>>& clock_connections) {
    for (auto& clock_connection : clock_connections) {
        clock_connection->create_switches(*this);
    }
}

void ClockRRGraphBuilder::add_rr_switches_and_map_to_nodes(size_t node_start_idx,
                                                           const float R_minW_nmos,
                                                           const float R_minW_pmos) {
    auto& device_ctx = g_vpr_ctx.mutable_device();
    auto& rr_nodes = device_ctx.rr_nodes;

    // Check to see that clock nodes were sucessfully appended to rr_nodes
    VTR_ASSERT(rr_nodes.size() > node_start_idx);

    std::unordered_map<int, int> arch_switch_to_rr_switch;

    // The following assumes that arch_switch was specified earlier when the edges where added
    for (size_t node_idx = node_start_idx; node_idx < rr_nodes.size(); node_idx++) {
        auto& from_node = rr_nodes[node_idx];
        for (int edge_idx = 0; edge_idx < from_node.num_edges(); edge_idx++) {
            int arch_switch_idx = from_node.edge_switch(edge_idx);

            int rr_switch_idx;
            auto itter = arch_switch_to_rr_switch.find(arch_switch_idx);
            if (itter == arch_switch_to_rr_switch.end()) {
                rr_switch_idx = add_rr_switch_from_arch_switch_inf(arch_switch_idx,
                                                                   R_minW_nmos,
                                                                   R_minW_pmos);
                arch_switch_to_rr_switch[arch_switch_idx] = rr_switch_idx;
            } else {
                rr_switch_idx = itter->second;
            }

            from_node.set_edge_switch(edge_idx, rr_switch_idx);
        }
    }

    device_ctx.rr_switch_inf.shrink_to_fit();
}

int ClockRRGraphBuilder::add_rr_switch_from_arch_switch_inf(int arch_switch_idx,
                                                            const float R_minW_nmos,
                                                            const float R_minW_pmos) {
    auto& device_ctx = g_vpr_ctx.mutable_device();
    auto& rr_switch_inf = device_ctx.rr_switch_inf;
    auto& arch_switch_inf = device_ctx.arch_switch_inf;

    rr_switch_inf.emplace_back();
    int rr_switch_idx = rr_switch_inf.size() - 1;

    // TODO: Add support for non fixed Tdel based on fanin information
    //       and move assigning Tdel into add_rr_switch
    VTR_ASSERT(arch_switch_inf[arch_switch_idx].fixed_Tdel());
    int fanin = UNDEFINED;

    load_rr_switch_from_arch_switch(arch_switch_idx, rr_switch_idx, fanin, R_minW_nmos, R_minW_pmos);

    return rr_switch_idx;
}

void ClockRRGraphBuilder::add_switch_location(std::string clock_name,
                                              std::string switch_point_name,
                                              int x,
                                              int y,
                                              int node_index) {
    // Note use of operator[] will automatically insert clock name if it doesn't exist
    clock_name_to_switch_points[clock_name].insert_switch_node_idx(switch_point_name, x, y, node_index);
}

void SwitchPoints::insert_switch_node_idx(std::string switch_point_name, int x, int y, int node_idx) {
    // Note use of operator[] will automatically insert switch name if it doesn't exit
    switch_point_name_to_switch_location[switch_point_name].insert_node_idx(x, y, node_idx);
}

void SwitchPoint::insert_node_idx(int x, int y, int node_idx) {
    // allocate 2d vector of grid size
    if (rr_node_indices.empty()) {
        auto& grid = g_vpr_ctx.device().grid;
        rr_node_indices.resize(grid.width());
        for (size_t i = 0; i < grid.width(); i++) {
            rr_node_indices[i].resize(grid.height());
        }
    }

    // insert node_idx at location
    rr_node_indices[x][y].push_back(node_idx);
    locations.insert({x, y});
}

std::vector<int> ClockRRGraphBuilder::get_rr_node_indices_at_switch_location(std::string clock_name,
                                                                             std::string switch_point_name,
                                                                             int x,
                                                                             int y) const {
    auto itter = clock_name_to_switch_points.find(clock_name);

    // assert that clock name exists in map
    VTR_ASSERT(itter != clock_name_to_switch_points.end());

    auto& switch_points = itter->second;
    return switch_points.get_rr_node_indices_at_location(switch_point_name, x, y);
}

std::vector<int> SwitchPoints::get_rr_node_indices_at_location(std::string switch_point_name,
                                                               int x,
                                                               int y) const {
    auto itter = switch_point_name_to_switch_location.find(switch_point_name);

    // assert that switch name exists in map
    VTR_ASSERT(itter != switch_point_name_to_switch_location.end());

    auto& switch_point = itter->second;
    std::vector<int> rr_node_indices = switch_point.get_rr_node_indices_at_location(x, y);
    return rr_node_indices;
}

std::vector<int> SwitchPoint::get_rr_node_indices_at_location(int x, int y) const {
    // assert that switch is connected to nodes at the location
    VTR_ASSERT(!rr_node_indices[x][y].empty());

    return rr_node_indices[x][y];
}

std::set<std::pair<int, int>> ClockRRGraphBuilder::get_switch_locations(std::string clock_name,
                                                                        std::string switch_point_name) const {
    auto itter = clock_name_to_switch_points.find(clock_name);

    // assert that clock name exists in map
    VTR_ASSERT(itter != clock_name_to_switch_points.end());

    auto& switch_points = itter->second;
    return switch_points.get_switch_locations(switch_point_name);
}

std::set<std::pair<int, int>> SwitchPoints::get_switch_locations(std::string switch_point_name) const {
    auto itter = switch_point_name_to_switch_location.find(switch_point_name);

    // assert that switch name exists in map
    VTR_ASSERT(itter != switch_point_name_to_switch_location.end());

    auto& switch_point = itter->second;
    return switch_point.get_switch_locations();
}

std::set<std::pair<int, int>> SwitchPoint::get_switch_locations() const {
    // assert that switch is connected to nodes at the location
    VTR_ASSERT(!locations.empty());

    return locations;
}

int ClockRRGraphBuilder::get_and_increment_chanx_ptc_num() {
    auto& device_ctx = g_vpr_ctx.mutable_device();
    auto& grid = device_ctx.grid;
    auto* channel_width = &device_ctx.chan_width;

    // ptc_num is determined by the channel width
    // The channel width lets the drawing engine how much to space the LBs appart
    int ptc_num = channel_width->x_max++;
    if (channel_width->x_max > channel_width->max) {
        channel_width->max = channel_width->x_max;
    }

    for (size_t i = 0; i < grid.height(); ++i) {
        device_ctx.chan_width.x_list[i]++;
    }

    return ptc_num;
}

int ClockRRGraphBuilder::get_and_increment_chany_ptc_num() {
    auto& device_ctx = g_vpr_ctx.mutable_device();
    auto& grid = device_ctx.grid;
    auto* channel_width = &device_ctx.chan_width;

    // ptc_num is determined by the channel width
    // The channel width lets the drawing engine how much to space the LBs appart
    int ptc_num = channel_width->y_max++;
    if (channel_width->y_max > channel_width->max) {
        channel_width->max = channel_width->y_max;
    }

    for (size_t i = 0; i < grid.width(); ++i) {
        device_ctx.chan_width.y_list[i]++;
    }

    return ptc_num;
}
