#include "clb_delay_calc.h"

#include "globals.h"

/*
 * ClbDelayCalc
 */

inline ClbDelayCalc::ClbDelayCalc()
    : intra_lb_pb_pin_lookup_(g_vpr_ctx.device().logical_block_types) {}

inline float ClbDelayCalc::clb_input_to_internal_sink_delay(const ClusterBlockId block_id, const int pin_index, int internal_sink_pin, DelayType delay_type) const {
    int pb_ipin = find_clb_pb_pin(block_id, pin_index);
    return trace_delay(block_id, pb_ipin, internal_sink_pin, delay_type);
}

inline float ClbDelayCalc::internal_src_to_clb_output_delay(const ClusterBlockId block_id, const int pin_index, int internal_src_pin, DelayType delay_type) const {
    int pb_opin = find_clb_pb_pin(block_id, pin_index);
    return trace_delay(block_id, internal_src_pin, pb_opin, delay_type);
}

inline float ClbDelayCalc::internal_src_to_internal_sink_delay(const ClusterBlockId clb, int internal_src_pin, int internal_sink_pin, DelayType delay_type) const {
    return trace_delay(clb, internal_src_pin, internal_sink_pin, delay_type);
}

inline float ClbDelayCalc::trace_delay(ClusterBlockId clb, int src_pb_route_id, int sink_pb_route_id, DelayType delay_type) const {
    auto& cluster_ctx = g_vpr_ctx.clustering();

    VTR_ASSERT(src_pb_route_id < cluster_ctx.clb_nlist.block_pb(clb)->pb_graph_node->total_pb_pins);
    VTR_ASSERT(sink_pb_route_id < cluster_ctx.clb_nlist.block_pb(clb)->pb_graph_node->total_pb_pins);

    const auto& pb_routes = cluster_ctx.clb_nlist.block_pb(clb)->pb_route;

    VTR_ASSERT_SAFE(pb_routes.count(src_pb_route_id));

    AtomNetId atom_net = pb_routes[src_pb_route_id].atom_net_id;

    VTR_ASSERT_MSG(atom_net, "Source pin must be connected to a valid net");
    VTR_ASSERT_MSG(atom_net == pb_routes[sink_pb_route_id].atom_net_id, "Source pin and sink pin must connect to the same net");

    float delay = 0.;

    //Trace back the internal routing from the sink to the source pin
    int curr_pb_route_id = sink_pb_route_id;
    while(pb_routes[curr_pb_route_id].driver_pb_pin_id >= 0) {
        VTR_ASSERT_MSG(atom_net == pb_routes[curr_pb_route_id].atom_net_id, "Internal routing must connect the same net");

        delay += pb_route_delay(clb, curr_pb_route_id, delay_type);

        curr_pb_route_id = pb_routes[curr_pb_route_id].driver_pb_pin_id;
    }

    VTR_ASSERT_MSG(curr_pb_route_id == src_pb_route_id, "Sink pin should trace back to source pin");

    return delay;
}

inline float ClbDelayCalc::pb_route_delay(ClusterBlockId clb, int pb_route_idx, DelayType delay_type) const {
    const t_pb_graph_edge* pb_edge = find_pb_graph_edge(clb, pb_route_idx);

    if(pb_edge) {
        if (delay_type == DelayType::MAX) {
            return pb_edge->delay_max;
        } else {
            VTR_ASSERT(delay_type == DelayType::MIN);
            return pb_edge->delay_min;
        }
    } else {
        return 0.;
    }
}

inline const t_pb_graph_edge* ClbDelayCalc::find_pb_graph_edge(ClusterBlockId clb, int pb_route_idx) const {
    auto& cluster_ctx = g_vpr_ctx.clustering();

    int type_index = cluster_ctx.clb_nlist.block_type(clb)->index;

    const t_pb* pb = cluster_ctx.clb_nlist.block_pb(clb);
    if (pb->pb_route.count(pb_route_idx)) {
        int upstream_pb_route_idx = pb->pb_route[pb_route_idx].driver_pb_pin_id;

        if(upstream_pb_route_idx >= 0) {

            const t_pb_graph_pin* pb_gpin = intra_lb_pb_pin_lookup_.pb_gpin(type_index, pb_route_idx);
            const t_pb_graph_pin* upstream_pb_gpin = intra_lb_pb_pin_lookup_.pb_gpin(type_index, upstream_pb_route_idx);

            return find_pb_graph_edge(upstream_pb_gpin, pb_gpin); 
        }
    }

    return nullptr;
}

inline const t_pb_graph_edge* ClbDelayCalc::find_pb_graph_edge(const t_pb_graph_pin* driver, const t_pb_graph_pin* sink) const {
    VTR_ASSERT(driver);
    VTR_ASSERT(sink);

    const t_pb_graph_edge* pb_edge = nullptr;
    for(int iedge = 0; iedge < driver->num_output_edges; ++iedge) {
        const t_pb_graph_edge* check_edge = driver->output_edges[iedge];
        VTR_ASSERT(check_edge);

        VTR_ASSERT(check_edge->num_output_pins == 1);
        if(check_edge->output_pins[0] == sink) {
            pb_edge = check_edge;
        }

    }
    VTR_ASSERT_MSG(pb_edge, "Should find pb_graph_edge connecting PB pins");

    return pb_edge;
}

