#include <cstdio>
using namespace std;

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

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

#include "globals.h"
#include "net_delay.h"
#include "route_tree_timing.h"

/* This module keeps track of the time delays for signals to arrive at       *
 * each pin in every net after timing-driven routing is complete. It         *
 * achieves this by first constructing the skeleton route tree               * 
 * from the traceback. Next, to obtain the completed route tree, it          *
 * calls functions to calculate the resistance, capacitance, and time        *
 * delays associated with each node. Then, it recursively traverses          *
 * the tree, copying the time delay from each node into the                  *
 * net_delay data structure. Essentially, the delays are calculated          *
 * by building the completed route tree from scratch, and is used            *
 * to check against the time delays computed incrementally during           * 
 * timing-driven routing.                                                    */

/********************** Variables local to this module ***********************/

/* Unordered map below stores the pair whose key is the index of the rr_node *
 * that corresponds to the rt_node, and whose value is the time delay        *
 * associated with that node. The map will be used to store delays while     *
 * traversing the nodes of the route tree in load_one_net_delay_recurr.      */

static std::unordered_map<int, float> inode_to_Tdel_map;

/*********************** Subroutines local to this module ********************/

static void load_one_net_delay(vtr::vector<ClusterNetId, float*>& net_delay, ClusterNetId net_id);

static void load_one_net_delay_recurr(t_rt_node* node, ClusterNetId net_id);

static void load_one_constant_net_delay(vtr::vector<ClusterNetId, float*>& net_delay, ClusterNetId net_id, float delay_value);

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

/* Allocates space for the net_delay data structure   *
 * [0..nets.size()-1][1..num_pins-1]. I chunk the data *
 * to save space on large problems.                    */
vtr::vector<ClusterNetId, float*> alloc_net_delay(vtr::t_chunk* chunk_list_ptr) {
    auto& cluster_ctx = g_vpr_ctx.clustering();
    vtr::vector<ClusterNetId, float*> net_delay; /* [0..nets.size()-1][1..num_pins-1] */

    auto nets = cluster_ctx.clb_nlist.nets();
    net_delay.resize(nets.size());

    for (auto net_id : nets) {
        float* tmp_ptr = (float*)vtr::chunk_malloc(cluster_ctx.clb_nlist.net_sinks(net_id).size() * sizeof(float), chunk_list_ptr);

        net_delay[net_id] = tmp_ptr - 1; /* [1..num_pins-1] */

        //Ensure the net delays are initialized with non-garbage values
        for (size_t ipin = 1; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ++ipin) {
            net_delay[net_id][ipin] = std::numeric_limits<float>::quiet_NaN();
        }
    }

    return (net_delay);
}

void free_net_delay(vtr::vector<ClusterNetId, float*>& net_delay,
                    vtr::t_chunk* chunk_list_ptr) {
    net_delay.clear();
    vtr::free_chunk_memory(chunk_list_ptr);
}

void load_net_delay_from_routing(vtr::vector<ClusterNetId, float*>& net_delay) {
    /* This routine loads net_delay[0..nets.size()-1][1..num_pins-1].  Each entry   *
     * is the Elmore delay from the net source to the appropriate sink. Both       *
     * the rr_graph and the routing traceback must be completely constructed        *
     * before this routine is called, and the net_delay array must have been        *
     * allocated.                                                                   */
    auto& cluster_ctx = g_vpr_ctx.clustering();

    for (auto net_id : cluster_ctx.clb_nlist.nets()) {
        if (cluster_ctx.clb_nlist.net_is_ignored(net_id)) {
            load_one_constant_net_delay(net_delay, net_id, 0.);
        } else {
            load_one_net_delay(net_delay, net_id);
        }
    }
}

static void load_one_net_delay(vtr::vector<ClusterNetId, float*>& net_delay, ClusterNetId net_id) {
    /* This routine loads delay values for one net in                            *
     * net_delay[net_id][1..num_pins-1]. First, from the traceback, it           *
     * constructs the route tree and computes its values for R, C, and Tdel.     *
     * Next, it walks the route tree recursively, storing the time delays for    * 
     * each node into the map inode_to_Tdel. Then, while looping through the     *
     * net_delay array we search for the inode corresponding to the pin          * 
     * identifiers, and correspondingly update the entry in net_delay.           *
     * Finally, it frees the route tree and clears the inode_to_Tdel_map         *
     * associated with that net.                                                 */

    auto& route_ctx = g_vpr_ctx.routing();

    if (route_ctx.trace[net_id].head == nullptr) {
        VPR_FATAL_ERROR(VPR_ERROR_TIMING,
                        "in load_one_net_delay: Traceback for net %lu does not exist.\n", size_t(net_id));
    }

    auto& cluster_ctx = g_vpr_ctx.clustering();
    int inode;

    t_rt_node* rt_root = traceback_to_route_tree(net_id); // obtain the root of the tree constructed from the traceback
    load_new_subtree_R_upstream(rt_root);                 // load in the resistance values for the route tree
    load_new_subtree_C_downstream(rt_root);               // load in the capacitance values for the route tree
    load_route_tree_Tdel(rt_root, 0.);                    // load the time delay values for the route tree
    load_one_net_delay_recurr(rt_root, net_id);           // recursively traverse the tree and load entries into the inode_to_Tdel map

    for (unsigned int ipin = 1; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ipin++) {
        inode = route_ctx.net_rr_terminals[net_id][ipin];                // look for the index of the rr node that corresponds to the sink that was used to route a certain connection.
        net_delay[net_id][ipin] = inode_to_Tdel_map.find(inode)->second; // search for the value of Tdel in the inode map and load into net_delay
    }
    free_route_tree(rt_root);  // free the route tree
    inode_to_Tdel_map.clear(); // clear the map
}

static void load_one_net_delay_recurr(t_rt_node* node, ClusterNetId net_id) {
    /* This routine recursively traverses the route tree, and copies the Tdel of the node into the map.  */

    inode_to_Tdel_map[node->inode] = node->Tdel; // add to the map, process current node

    for (t_linked_rt_edge* edge = node->u.child_list; edge != nullptr; edge = edge->next) { // process children
        load_one_net_delay_recurr(edge->child, net_id);
    }
}

static void load_one_constant_net_delay(vtr::vector<ClusterNetId, float*>& net_delay, ClusterNetId net_id, float delay_value) {
    /* Sets each entry of the net_delay array for net inet to delay_value.     */
    auto& cluster_ctx = g_vpr_ctx.clustering();

    for (unsigned int ipin = 1; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ipin++)
        net_delay[net_id][ipin] = delay_value;
}
