#include <cstring>
#include <unordered_set>
#include <regex>
#include <algorithm>

using namespace std;

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

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

#include "physical_types.h"
#include "globals.h"
#include "vpr_utils.h"
#include "cluster_placement.h"
#include "place_macro.h"
#include "string.h"
#include "pack_types.h"
#include "device_grid.h"

/* This module contains subroutines that are used in several unrelated parts *
 * of VPR.  They are VPR-specific utility routines.                          */

/* This defines the maximum string length that could be parsed by functions  *
 * in vpr_utils.                                                             */
#define MAX_STRING_LEN 128

/******************** File-scope variables declarations **********************/

/* These three mappings are needed since there are two different netlist *
 * conventions - in the cluster level, ports and port pins are used      *
 * while in the post-pack level, block pins are used. The reason block   *
 * type is used instead of blocks is to save memories.                   */

/* f_port_from_blk_pin array allow us to quickly find what port a block  *
 * pin corresponds to.                                                   *
 * [0...device_ctx.logical_block_type.size()-1][0...blk_pin_count-1]     *
 *                                                                       */
static int** f_port_from_blk_pin = nullptr;

/* f_port_pin_from_blk_pin array allow us to quickly find what port pin a*
 * block pin corresponds to.                                             *
 * [0...device_ctx.logical_block_types.size()-1][0...blk_pin_count-1]    */
static int** f_port_pin_from_blk_pin = nullptr;

/* f_port_pin_to_block_pin array allows us to quickly find what block                   *
 * pin a port pin corresponds to.                                                       *
 * [0...device_ctx.logical_block_types.size()-1][0...num_ports-1][0...num_port_pins-1]  */
static int*** f_blk_pin_from_port_pin = nullptr;

//Regular expressions used to determine register and logic primitives
//TODO: Make this set-able from command-line?
const std::regex REGISTER_MODEL_REGEX("(.subckt\\s+)?.*(latch|dff).*", std::regex::icase);
const std::regex LOGIC_MODEL_REGEX("(.subckt\\s+)?.*(lut|names|lcell).*", std::regex::icase);

/******************** Subroutine declarations ********************************/

/* Allocates and loads f_port_from_blk_pin and f_port_pin_from_blk_pin   *
 * arrays.                                                               *
 * The arrays are freed in free_placement_structs()                      */
static void alloc_and_load_port_pin_from_blk_pin();

/* Allocates and loads blk_pin_from_port_pin array.                      *
 * The arrays are freed in free_placement_structs()                      */
static void alloc_and_load_blk_pin_from_port_pin();

/* Go through all the ports in all the blocks to find the port that has the same   *
 * name as port_name and belongs to the block type that has the name pb_type_name. *
 * Then, check that whether start_pin_index and end_pin_index are specified. If    *
 * they are, mark down the pins from start_pin_index to end_pin_index, inclusive.  *
 * Otherwise, mark down all the pins in that port.                                 */
static void mark_direct_of_ports(int idirect, int direct_type, char* pb_type_name, char* port_name, int end_pin_index, int start_pin_index, char* src_string, int line, int** idirect_from_blk_pin, int** direct_type_from_blk_pin);

/* Mark the pin entry in idirect_from_blk_pin with idirect and the pin entry in    *
 * direct_type_from_blk_pin with direct_type from start_pin_index to               *
 * end_pin_index.                                                                  */
static void mark_direct_of_pins(int start_pin_index, int end_pin_index, int itype, int iport, int** idirect_from_blk_pin, int idirect, int** direct_type_from_blk_pin, int direct_type, int line, char* src_string);

static void load_pb_graph_pin_lookup_from_index_rec(t_pb_graph_pin** pb_graph_pin_lookup_from_index, t_pb_graph_node* pb_graph_node);

static void load_pin_id_to_pb_mapping_rec(t_pb* cur_pb, t_pb** pin_id_to_pb_mapping);

static std::vector<int> find_connected_internal_clb_sink_pins(ClusterBlockId clb, int pb_pin);
static void find_connected_internal_clb_sink_pins_recurr(ClusterBlockId clb, int pb_pin, std::vector<int>& connected_sink_pb_pins);
static AtomPinId find_atom_pin_for_pb_route_id(ClusterBlockId clb, int pb_route_id, const IntraLbPbPinLookup& pb_gpin_lookup);

static bool block_type_contains_blif_model(t_logical_block_type_ptr type, const std::regex& blif_model_regex);
static bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::regex& blif_model_regex);

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

const t_model* find_model(const t_model* models, const std::string& name, bool required) {
    for (const t_model* model = models; model != nullptr; model = model->next) {
        if (name == model->name) {
            return model;
        }
    }

    if (required) {
        VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Failed to find architecture modedl '%s'\n", name.c_str());
    }

    return nullptr;
}

const t_model_ports* find_model_port(const t_model* model, const std::string& name, bool required) {
    VTR_ASSERT(model);

    for (const t_model_ports* model_ports : {model->inputs, model->outputs}) {
        for (const t_model_ports* port = model_ports; port != nullptr; port = port->next) {
            if (port->name == name) {
                return port;
            }
        }
    }

    if (required) {
        VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Failed to find port '%s; on architecture modedl '%s'\n", name.c_str(), model->name);
    }

    return nullptr;
}

/**
 * print tabs given number of tabs to file
 */
void print_tabs(FILE* fpout, int num_tab) {
    int i;
    for (i = 0; i < num_tab; i++) {
        fprintf(fpout, "\t");
    }
}

/* Points the place_ctx.grid_blocks structure back to the blocks list */
void sync_grid_to_blocks() {
    auto& place_ctx = g_vpr_ctx.mutable_placement();
    auto& device_ctx = g_vpr_ctx.device();
    auto& device_grid = device_ctx.grid;

    /* Reset usage and allocate blocks list if needed */
    auto& grid_blocks = place_ctx.grid_blocks;
    grid_blocks.resize({device_grid.width(), device_grid.height()});
    for (size_t x = 0; x < device_grid.width(); ++x) {
        for (size_t y = 0; y < device_grid.height(); ++y) {
            auto& grid_block = grid_blocks[x][y];
            grid_block.blocks.resize(device_ctx.grid[x][y].type->capacity);

            for (int z = 0; z < device_ctx.grid[x][y].type->capacity; ++z) {
                grid_block.blocks[z] = EMPTY_BLOCK_ID;
            }
        }
    }

    /* Go through each block */
    auto& cluster_ctx = g_vpr_ctx.clustering();
    for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
        int blk_x = place_ctx.block_locs[blk_id].loc.x;
        int blk_y = place_ctx.block_locs[blk_id].loc.y;
        int blk_z = place_ctx.block_locs[blk_id].loc.z;

        auto type = physical_tile_type(blk_id);

        /* Check range of block coords */
        if (blk_x < 0 || blk_y < 0
            || (blk_x + type->width - 1) > int(device_ctx.grid.width() - 1)
            || (blk_y + type->height - 1) > int(device_ctx.grid.height() - 1)
            || blk_z < 0 || blk_z > (type->capacity)) {
            VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Block %zu is at invalid location (%d, %d, %d).\n",
                            size_t(blk_id), blk_x, blk_y, blk_z);
        }

        /* Check types match */
        if (type != device_ctx.grid[blk_x][blk_y].type) {
            VPR_FATAL_ERROR(VPR_ERROR_PLACE, "A block is in a grid location (%d x %d) with a conflicting types '%s' and '%s' .\n",
                            blk_x, blk_y,
                            type->name,
                            device_ctx.grid[blk_x][blk_y].type->name);
        }

        /* Check already in use */
        if ((EMPTY_BLOCK_ID != place_ctx.grid_blocks[blk_x][blk_y].blocks[blk_z])
            && (INVALID_BLOCK_ID != place_ctx.grid_blocks[blk_x][blk_y].blocks[blk_z])) {
            VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Location (%d, %d, %d) is used more than once.\n",
                            blk_x, blk_y, blk_z);
        }

        if (device_ctx.grid[blk_x][blk_y].width_offset != 0 || device_ctx.grid[blk_x][blk_y].height_offset != 0) {
            VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Large block not aligned in placment for cluster_ctx.blocks %lu at (%d, %d, %d).",
                            size_t(blk_id), blk_x, blk_y, blk_z);
        }

        /* Set the block */
        for (int width = 0; width < type->width; ++width) {
            for (int height = 0; height < type->height; ++height) {
                place_ctx.grid_blocks[blk_x + width][blk_y + height].blocks[blk_z] = blk_id;
                place_ctx.grid_blocks[blk_x + width][blk_y + height].usage++;
                VTR_ASSERT(device_ctx.grid[blk_x + width][blk_y + height].width_offset == width);
                VTR_ASSERT(device_ctx.grid[blk_x + width][blk_y + height].height_offset == height);
            }
        }
    }
}

std::string block_type_pin_index_to_name(t_physical_tile_type_ptr type, int pin_index) {
    VTR_ASSERT(pin_index < type->num_pins);

    std::string pin_name = type->name;

    if (type->capacity > 1) {
        int pins_per_inst = type->num_pins / type->capacity;
        int inst_num = pin_index / pins_per_inst;
        pin_index %= pins_per_inst;

        pin_name += "[" + std::to_string(inst_num) + "]";
    }

    pin_name += ".";

    t_pb_type* pb_type = logical_block_type(type)->pb_type;
    int curr_index = 0;
    for (int iport = 0; iport < pb_type->num_ports; ++iport) {
        t_port* port = &pb_type->ports[iport];

        if (curr_index + port->num_pins > pin_index) {
            //This port contains the desired pin index
            int index_in_port = pin_index - curr_index;
            pin_name += port->name;
            pin_name += "[" + std::to_string(index_in_port) + "]";
            return pin_name;
        }

        curr_index += port->num_pins;
    }

    return "<UNKOWN>";
}

std::vector<std::string> block_type_class_index_to_pin_names(t_physical_tile_type_ptr type, int class_index) {
    VTR_ASSERT(class_index < type->num_class);

    //TODO: unsure if classes are modulo capacity or not... so this may be unnessesary
    int classes_per_inst = type->num_class / type->capacity;
    class_index %= classes_per_inst;

    t_class& class_inf = type->class_inf[class_index];

    std::vector<std::string> pin_names;
    for (int ipin = 0; ipin < class_inf.num_pins; ++ipin) {
        pin_names.push_back(block_type_pin_index_to_name(type, class_inf.pinlist[ipin]));
    }

    return pin_names;
}

std::string rr_node_arch_name(int inode) {
    auto& device_ctx = g_vpr_ctx.device();

    const t_rr_node& rr_node = device_ctx.rr_nodes[inode];

    std::string rr_node_arch_name;
    if (rr_node.type() == OPIN || rr_node.type() == IPIN) {
        //Pin names
        auto type = device_ctx.grid[rr_node.xlow()][rr_node.ylow()].type;
        rr_node_arch_name += block_type_pin_index_to_name(type, rr_node.ptc_num());
    } else if (rr_node.type() == SOURCE || rr_node.type() == SINK) {
        //Set of pins associated with SOURCE/SINK
        auto type = device_ctx.grid[rr_node.xlow()][rr_node.ylow()].type;
        auto pin_names = block_type_class_index_to_pin_names(type, rr_node.ptc_num());
        if (pin_names.size() > 1) {
            rr_node_arch_name += rr_node.type_string();
            rr_node_arch_name += " connected to ";
            rr_node_arch_name += "{";
            rr_node_arch_name += vtr::join(pin_names, ", ");
            rr_node_arch_name += "}";
        } else {
            rr_node_arch_name += pin_names[0];
        }
    } else {
        VTR_ASSERT(rr_node.type() == CHANX || rr_node.type() == CHANY);
        //Wire segment name
        auto cost_index = rr_node.cost_index();
        int seg_index = device_ctx.rr_indexed_data[cost_index].seg_index;

        rr_node_arch_name += device_ctx.arch->Segments[seg_index].name;
    }

    return rr_node_arch_name;
}

IntraLbPbPinLookup::IntraLbPbPinLookup(const std::vector<t_logical_block_type>& block_types)
    : block_types_(block_types) {
    intra_lb_pb_pin_lookup_ = new t_pb_graph_pin**[block_types_.size()];
    for (unsigned int itype = 0; itype < block_types_.size(); ++itype) {
        intra_lb_pb_pin_lookup_[itype] = alloc_and_load_pb_graph_pin_lookup_from_index(&block_types[itype]);
    }
}

IntraLbPbPinLookup::IntraLbPbPinLookup(const IntraLbPbPinLookup& rhs)
    : IntraLbPbPinLookup(rhs.block_types_) {
    //nop
}

IntraLbPbPinLookup& IntraLbPbPinLookup::operator=(IntraLbPbPinLookup rhs) {
    //Copy-swap idiom
    swap(*this, rhs);

    return *this;
}

IntraLbPbPinLookup::~IntraLbPbPinLookup() {
    auto& device_ctx = g_vpr_ctx.device();
    for (unsigned int itype = 0; itype < device_ctx.logical_block_types.size(); itype++) {
        free_pb_graph_pin_lookup_from_index(intra_lb_pb_pin_lookup_[itype]);
    }

    delete[] intra_lb_pb_pin_lookup_;
}

const t_pb_graph_pin* IntraLbPbPinLookup::pb_gpin(unsigned int itype, int ipin) const {
    VTR_ASSERT(itype < block_types_.size());

    return intra_lb_pb_pin_lookup_[itype][ipin];
}

void swap(IntraLbPbPinLookup& lhs, IntraLbPbPinLookup& rhs) {
    std::swap(lhs.block_types_, rhs.block_types_);
    std::swap(lhs.intra_lb_pb_pin_lookup_, rhs.intra_lb_pb_pin_lookup_);
}

//Returns the set of pins which are connected to the top level clb pin
//  The pin(s) may be input(s) or and output (returning the connected sinks or drivers respectively)
std::vector<AtomPinId> find_clb_pin_connected_atom_pins(ClusterBlockId clb, int clb_pin, const IntraLbPbPinLookup& pb_gpin_lookup) {
    std::vector<AtomPinId> atom_pins;

    if (is_opin(clb_pin, physical_tile_type(clb))) {
        //output
        AtomPinId driver = find_clb_pin_driver_atom_pin(clb, clb_pin, pb_gpin_lookup);
        if (driver) {
            atom_pins.push_back(driver);
        }
    } else {
        //input
        atom_pins = find_clb_pin_sink_atom_pins(clb, clb_pin, pb_gpin_lookup);
    }

    return atom_pins;
}

//Returns the atom pin which drives the top level clb output pin
AtomPinId find_clb_pin_driver_atom_pin(ClusterBlockId clb, int clb_pin, const IntraLbPbPinLookup& pb_gpin_lookup) {
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& atom_ctx = g_vpr_ctx.atom();

    int pb_pin_id = find_clb_pb_pin(clb, clb_pin);
    if (pb_pin_id < 0) {
        //CLB output pin has no internal driver
        return AtomPinId::INVALID();
    }
    const t_pb_routes& pb_routes = cluster_ctx.clb_nlist.block_pb(clb)->pb_route;
    AtomNetId atom_net = pb_routes[pb_pin_id].atom_net_id;

    //Trace back until the driver is reached
    while (pb_routes[pb_pin_id].driver_pb_pin_id >= 0) {
        pb_pin_id = pb_routes[pb_pin_id].driver_pb_pin_id;
    }
    VTR_ASSERT(pb_pin_id >= 0);

    VTR_ASSERT(atom_net == pb_routes[pb_pin_id].atom_net_id);

    //Map the pb_pin_id to AtomPinId
    AtomPinId atom_pin = find_atom_pin_for_pb_route_id(clb, pb_pin_id, pb_gpin_lookup);
    VTR_ASSERT(atom_pin);

    VTR_ASSERT_MSG(atom_ctx.nlist.pin_net(atom_pin) == atom_net, "Driver atom pin should drive the same net");

    return atom_pin;
}

//Returns the set of atom sink pins associated with the top level clb input pin
std::vector<AtomPinId> find_clb_pin_sink_atom_pins(ClusterBlockId clb, int clb_pin, const IntraLbPbPinLookup& pb_gpin_lookup) {
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& atom_ctx = g_vpr_ctx.atom();

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

    VTR_ASSERT_MSG(clb_pin < physical_tile_type(clb)->num_pins, "Must be a valid top-level pin");

    int pb_pin = find_clb_pb_pin(clb, clb_pin);

    VTR_ASSERT(cluster_ctx.clb_nlist.block_pb(clb));
    VTR_ASSERT_MSG(pb_pin < cluster_ctx.clb_nlist.block_pb(clb)->pb_graph_node->num_pins(), "Pin must map to a top-level pb pin");

    VTR_ASSERT_MSG(pb_routes[pb_pin].driver_pb_pin_id < 0, "CLB input pin should have no internal drivers");

    AtomNetId atom_net = pb_routes[pb_pin].atom_net_id;
    VTR_ASSERT(atom_net);

    std::vector<int> connected_sink_pb_pins = find_connected_internal_clb_sink_pins(clb, pb_pin);

    std::vector<AtomPinId> sink_atom_pins;
    for (int sink_pb_pin : connected_sink_pb_pins) {
        //Map the pb_pin_id to AtomPinId
        AtomPinId atom_pin = find_atom_pin_for_pb_route_id(clb, sink_pb_pin, pb_gpin_lookup);
        VTR_ASSERT(atom_pin);

        VTR_ASSERT_MSG(atom_ctx.nlist.pin_net(atom_pin) == atom_net, "Sink atom pins should be driven by the same net");

        sink_atom_pins.push_back(atom_pin);
    }

    return sink_atom_pins;
}

//Find sinks internal to the given clb which are connected to the specified pb_pin
static std::vector<int> find_connected_internal_clb_sink_pins(ClusterBlockId clb, int pb_pin) {
    std::vector<int> connected_sink_pb_pins;
    find_connected_internal_clb_sink_pins_recurr(clb, pb_pin, connected_sink_pb_pins);

    return connected_sink_pb_pins;
}

//Recursive helper for find_connected_internal_clb_sink_pins()
static void find_connected_internal_clb_sink_pins_recurr(ClusterBlockId clb, int pb_pin, std::vector<int>& connected_sink_pb_pins) {
    auto& cluster_ctx = g_vpr_ctx.clustering();

    if (cluster_ctx.clb_nlist.block_pb(clb)->pb_route[pb_pin].sink_pb_pin_ids.empty()) {
        //No more sinks => primitive input
        connected_sink_pb_pins.push_back(pb_pin);
    }
    for (int sink_pb_pin : cluster_ctx.clb_nlist.block_pb(clb)->pb_route[pb_pin].sink_pb_pin_ids) {
        find_connected_internal_clb_sink_pins_recurr(clb, sink_pb_pin, connected_sink_pb_pins);
    }
}

//Maps from a CLB's pb_route ID to it's matching AtomPinId (if the pb_route is a primitive pin)
static AtomPinId find_atom_pin_for_pb_route_id(ClusterBlockId clb, int pb_route_id, const IntraLbPbPinLookup& pb_gpin_lookup) {
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& atom_ctx = g_vpr_ctx.atom();

    VTR_ASSERT_MSG(cluster_ctx.clb_nlist.block_pb(clb)->pb_route[pb_route_id].atom_net_id, "PB route should correspond to a valid atom net");

    //Find the graph pin associated with this pb_route
    const t_pb_graph_pin* gpin = pb_gpin_lookup.pb_gpin(cluster_ctx.clb_nlist.block_type(clb)->index, pb_route_id);
    VTR_ASSERT(gpin);

    //Get the PB associated with this block
    const t_pb* pb = cluster_ctx.clb_nlist.block_pb(clb);

    //Find the graph node containing the pin
    const t_pb_graph_node* gnode = gpin->parent_node;

    //Find the pb matching the gnode
    const t_pb* child_pb = pb->find_pb(gnode);

    VTR_ASSERT_MSG(child_pb, "Should find pb containing pb route");

    //Check if this is a leaf/atom pb
    if (child_pb->child_pbs == nullptr) {
        //It is a leaf, and hence should map to an atom

        //Find the associated atom
        AtomBlockId atom_block = atom_ctx.lookup.pb_atom(child_pb);
        VTR_ASSERT(atom_block);

        //Now find the matching pin by seeing which pin maps to the gpin
        for (AtomPinId atom_pin : atom_ctx.nlist.block_pins(atom_block)) {
            const t_pb_graph_pin* atom_pin_gpin = atom_ctx.lookup.atom_pin_pb_graph_pin(atom_pin);
            if (atom_pin_gpin == gpin) {
                //Match
                return atom_pin;
            }
        }
    }

    //No match
    return AtomPinId::INVALID();
}

/* Return the net pin which drive the CLB input connected to sink_pb_pin_id, or nullptr if none (i.e. driven internally)
 *   clb: Block in which the the sink pin is located on
 *   sink_pb_pin_id: The physical pin index of the sink pin on the block
 *
 *  Returns a tuple containing
 *   ClusterNetId: Corresponds to the net connected to the sink pin
 *                 INVALID if not an external CLB pin, or if it's an output (driver pin)
 *   clb_pin: Physical pin index, same as sink_pb_pin_id but potentially with an offset (if z is defined)
 *            -1 if not an external CLB pin, or if it's an output (driver pin)
 *   clb_net_pin: Index of the pin relative to the net, (i.e. 0 = driver, +1 = sink)
 *                -1 if not an external CLB pin, or if it's an output (driver pin)
 */
std::tuple<ClusterNetId, int, int> find_pb_route_clb_input_net_pin(ClusterBlockId clb, int sink_pb_pin_id) {
    auto& cluster_ctx = g_vpr_ctx.clustering();

    VTR_ASSERT(sink_pb_pin_id < cluster_ctx.clb_nlist.block_pb(clb)->pb_graph_node->total_pb_pins);
    VTR_ASSERT(clb != ClusterBlockId::INVALID());
    VTR_ASSERT(sink_pb_pin_id >= 0);

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

    VTR_ASSERT_MSG(pb_routes[sink_pb_pin_id].atom_net_id, "PB route should be associated with a net");

    //Walk back from the sink to the CLB input pin
    int curr_pb_pin_id = sink_pb_pin_id;
    int next_pb_pin_id = pb_routes[curr_pb_pin_id].driver_pb_pin_id;
    while (next_pb_pin_id >= 0) {
        //Advance back towards the input
        curr_pb_pin_id = next_pb_pin_id;

        VTR_ASSERT_MSG(pb_routes[next_pb_pin_id].atom_net_id == pb_routes[sink_pb_pin_id].atom_net_id,
                       "Connected pb_routes should connect the same net");

        next_pb_pin_id = pb_routes[curr_pb_pin_id].driver_pb_pin_id;
    }

    bool is_output_pin = (pb_routes[curr_pb_pin_id].pb_graph_pin->port->type == OUT_PORT);

    if (!is_clb_external_pin(clb, curr_pb_pin_id) || is_output_pin) {
        return std::make_tuple(ClusterNetId::INVALID(), -1, -1);
    }

    //To account for capacity > 1 blocks we need to convert the pb_pin to the clb pin
    int clb_pin = find_pb_pin_clb_pin(clb, curr_pb_pin_id);
    VTR_ASSERT(clb_pin >= 0);

    //clb_pin should be a top-level CLB input
    ClusterNetId clb_net_idx = cluster_ctx.clb_nlist.block_net(clb, clb_pin);
    int clb_net_pin_idx = cluster_ctx.clb_nlist.block_pin_net_index(clb, clb_pin);
    VTR_ASSERT(clb_net_idx != ClusterNetId::INVALID());
    VTR_ASSERT(clb_net_pin_idx >= 0);

    return std::tuple<ClusterNetId, int, int>(clb_net_idx, clb_pin, clb_net_pin_idx);
}

//Return the pb pin index corresponding to the pin clb_pin on block clb
// Given a clb_pin index on a this function will return the corresponding
// pin index on the pb_type (accounting for the possible z-coordinate offset).
int find_clb_pb_pin(ClusterBlockId clb, int clb_pin) {
    auto& place_ctx = g_vpr_ctx.placement();

    auto type = physical_tile_type(clb);
    VTR_ASSERT_MSG(clb_pin < type->num_pins, "Must be a valid top-level pin");

    int pb_pin = -1;
    if (place_ctx.block_locs[clb].nets_and_pins_synced_to_z_coordinate) {
        //Pins have been offset by z-coordinate, need to remove offset

        VTR_ASSERT(type->num_pins % type->capacity == 0);
        int num_basic_block_pins = type->num_pins / type->capacity;
        /* Logical location and physical location is offset by z * max_num_block_pins */

        pb_pin = clb_pin - place_ctx.block_locs[clb].loc.z * num_basic_block_pins;
    } else {
        //No offset
        pb_pin = clb_pin;
    }

    VTR_ASSERT(pb_pin >= 0);

    return pb_pin;
}

//Inverse of find_clb_pb_pin()
int find_pb_pin_clb_pin(ClusterBlockId clb, int pb_pin) {
    auto& place_ctx = g_vpr_ctx.placement();

    auto type = physical_tile_type(clb);

    int clb_pin = -1;
    if (place_ctx.block_locs[clb].nets_and_pins_synced_to_z_coordinate) {
        //Pins have been offset by z-coordinate, need to remove offset
        VTR_ASSERT(type->num_pins % type->capacity == 0);
        int num_basic_block_pins = type->num_pins / type->capacity;
        /* Logical location and physical location is offset by z * max_num_block_pins */

        clb_pin = pb_pin + place_ctx.block_locs[clb].loc.z * num_basic_block_pins;
    } else {
        //No offset
        clb_pin = pb_pin;
    }
    VTR_ASSERT(clb_pin >= 0);

    return clb_pin;
}

bool is_clb_external_pin(ClusterBlockId blk_id, int pb_pin_id) {
    auto& cluster_ctx = g_vpr_ctx.clustering();

    const t_pb_graph_pin* gpin = cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route[pb_pin_id].pb_graph_pin;
    VTR_ASSERT(gpin);

    //If the gpin's parent graph node is the same as the pb's graph node
    //this must be a top level pin
    const t_pb_graph_node* gnode = gpin->parent_node;
    bool is_top_level_pin = (gnode == cluster_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node);

    return is_top_level_pin;
}

bool is_opin(int ipin, t_physical_tile_type_ptr type) {
    /* Returns true if this clb pin is an output, false otherwise. */

    if (ipin > type->num_pins) {
        //Not a top level pin
        return false;
    }

    int iclass = type->pin_class[ipin];

    if (type->class_inf[iclass].type == DRIVER)
        return true;
    else
        return false;
}

bool is_input_type(t_physical_tile_type_ptr type) {
    auto& device_ctx = g_vpr_ctx.device();

    return device_ctx.input_types.count(type);
}

bool is_output_type(t_physical_tile_type_ptr type) {
    auto& device_ctx = g_vpr_ctx.device();

    return device_ctx.output_types.count(type);
}

bool is_io_type(t_physical_tile_type_ptr type) {
    return is_input_type(type)
           || is_output_type(type);
}

bool is_empty_type(t_physical_tile_type_ptr type) {
    auto& device_ctx = g_vpr_ctx.device();

    return type == device_ctx.EMPTY_TYPE;
}

t_physical_tile_type_ptr physical_tile_type(t_logical_block_type_ptr logical_block_type) {
    auto& device_ctx = g_vpr_ctx.device();

    /* It is assumed that there is a 1:1 mapping between logical and physical types
     * making it possible to use the same index to access the corresponding type
     */
    return &device_ctx.physical_tile_types[logical_block_type->index];
}

t_physical_tile_type_ptr physical_tile_type(ClusterBlockId blk) {
    auto& cluster_ctx = g_vpr_ctx.clustering();

    auto blk_type = cluster_ctx.clb_nlist.block_type(blk);

    return physical_tile_type(blk_type);
}

t_logical_block_type_ptr logical_block_type(t_physical_tile_type_ptr physical_tile_type) {
    auto& device_ctx = g_vpr_ctx.device();

    /* It is assumed that there is a 1:1 mapping between logical and physical types
     * making it possible to use the same index to access the corresponding type
     */
    return &device_ctx.logical_block_types[physical_tile_type->index];
}

/* Each node in the pb_graph for a top-level pb_type can be uniquely identified
 * by its pins. Since the pins in a cluster of a certain type are densely indexed,
 * this function will find the pin index (int pin_count_in_cluster) of the first
 * pin for a given pb_graph_node, and use this index value as unique identifier
 * for the node.
 */
int get_unique_pb_graph_node_id(const t_pb_graph_node* pb_graph_node) {
    t_pb_graph_pin first_input_pin;
    t_pb_graph_pin first_output_pin;
    int node_id;

    if (pb_graph_node->num_input_pins != nullptr) {
        /* If input port exists on this node, return the index of the first
         * input pin as node_id.
         */
        first_input_pin = pb_graph_node->input_pins[0][0];
        node_id = first_input_pin.pin_count_in_cluster;
        return node_id;
    } else {
        /* If no input port exists on node, then return the index of the first
         * output pin. Every pb_node is guaranteed to have at least an input or
         * output pin.
         */
        first_output_pin = pb_graph_node->output_pins[0][0];
        node_id = first_output_pin.pin_count_in_cluster;
        return node_id;
    }
}

void get_class_range_for_block(const ClusterBlockId blk_id,
                               int* class_low,
                               int* class_high) {
    /* Assumes that the placement has been done so each block has a set of pins allocated to it */
    auto& place_ctx = g_vpr_ctx.placement();

    auto type = physical_tile_type(blk_id);
    VTR_ASSERT(type->num_class % type->capacity == 0);
    *class_low = place_ctx.block_locs[blk_id].loc.z * (type->num_class / type->capacity);
    *class_high = (place_ctx.block_locs[blk_id].loc.z + 1) * (type->num_class / type->capacity) - 1;
}

void get_pin_range_for_block(const ClusterBlockId blk_id,
                             int* pin_low,
                             int* pin_high) {
    /* Assumes that the placement has been done so each block has a set of pins allocated to it */
    auto& place_ctx = g_vpr_ctx.placement();

    auto type = physical_tile_type(blk_id);
    VTR_ASSERT(type->num_pins % type->capacity == 0);
    *pin_low = place_ctx.block_locs[blk_id].loc.z * (type->num_pins / type->capacity);
    *pin_high = (place_ctx.block_locs[blk_id].loc.z + 1) * (type->num_pins / type->capacity) - 1;
}

t_physical_tile_type_ptr find_block_type_by_name(std::string name, const std::vector<t_physical_tile_type>& types) {
    for (auto const& type : types) {
        if (type.name == name) {
            return &type;
        }
    }
    return nullptr; //Not found
}

t_logical_block_type_ptr infer_logic_block_type(const DeviceGrid& grid) {
    auto& device_ctx = g_vpr_ctx.device();
    //Collect candidate blocks which contain LUTs
    std::vector<t_logical_block_type_ptr> logic_block_candidates;

    for (const auto& type : device_ctx.logical_block_types) {
        if (block_type_contains_blif_model(&type, LOGIC_MODEL_REGEX)) {
            logic_block_candidates.push_back(&type);
        }
    }

    if (logic_block_candidates.empty()) {
        //No LUTs, fallback to looking for which contain FFs
        for (const auto& type : device_ctx.logical_block_types) {
            if (block_type_contains_blif_model(&type, REGISTER_MODEL_REGEX)) {
                logic_block_candidates.push_back(&type);
            }
        }
    }

    //Sort the candidates by the most common block type
    auto by_desc_grid_count = [&](t_logical_block_type_ptr lhs, t_logical_block_type_ptr rhs) {
        return grid.num_instances(physical_tile_type(lhs)) > grid.num_instances(physical_tile_type(rhs));
    };
    std::stable_sort(logic_block_candidates.begin(), logic_block_candidates.end(), by_desc_grid_count);

    if (!logic_block_candidates.empty()) {
        return logic_block_candidates.front();
    } else {
        //Otherwise assume it is the most common block type
        auto most_common_type = find_most_common_block_type(grid);
        if (most_common_type == nullptr) {
            VTR_LOG_WARN("Unable to infer which block type is a logic block\n");
        }
        return most_common_type;
    }
}

t_logical_block_type_ptr find_most_common_block_type(const DeviceGrid& grid) {
    auto& device_ctx = g_vpr_ctx.device();

    t_physical_tile_type_ptr max_type = nullptr;
    size_t max_count = 0;
    for (const auto& type : device_ctx.physical_tile_types) {
        size_t inst_cnt = grid.num_instances(&type);
        if (max_count < inst_cnt) {
            max_count = inst_cnt;
            max_type = &type;
        }
    }

    if (max_type == nullptr) {
        VTR_LOG_WARN("Unable to determine most common block type (perhaps the device grid was empty?)\n");
        return nullptr;
    }
    return logical_block_type(max_type);
}

InstPort parse_inst_port(std::string str) {
    InstPort inst_port(str);

    auto& device_ctx = g_vpr_ctx.device();
    auto blk_type = find_block_type_by_name(inst_port.instance_name(), device_ctx.physical_tile_types);
    if (!blk_type) {
        VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Failed to find block type named %s", inst_port.instance_name().c_str());
    }

    const t_port* port = find_pb_graph_port(logical_block_type(blk_type)->pb_graph_head, inst_port.port_name());
    if (!port) {
        VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Failed to find port %s on block type %s", inst_port.port_name().c_str(), inst_port.instance_name().c_str());
    }

    if (inst_port.port_low_index() == InstPort::UNSPECIFIED) {
        VTR_ASSERT(inst_port.port_high_index() == InstPort::UNSPECIFIED);

        inst_port.set_port_low_index(0);
        inst_port.set_port_high_index(port->num_pins - 1);

    } else {
        if (inst_port.port_low_index() < 0 || inst_port.port_low_index() >= port->num_pins
            || inst_port.port_high_index() < 0 || inst_port.port_high_index() >= port->num_pins) {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Pin indices [%d:%d] on port %s of block type %s out of expected range [%d:%d]",
                            inst_port.port_low_index(), inst_port.port_high_index(),
                            inst_port.port_name().c_str(), inst_port.instance_name().c_str(),
                            0, port->num_pins - 1);
        }
    }
    return inst_port;
}

//Returns the pin class associated with the specified pin_index_in_port within the port port_name on type
int find_pin_class(t_logical_block_type_ptr type, std::string port_name, int pin_index_in_port, e_pin_type pin_type) {
    int iclass = OPEN;

    int ipin = find_pin(type, port_name, pin_index_in_port);

    if (ipin != OPEN) {
        iclass = physical_tile_type(type)->pin_class[ipin];

        if (iclass != OPEN) {
            VTR_ASSERT(physical_tile_type(type)->class_inf[iclass].type == pin_type);
        }
    }
    return iclass;
}

int find_pin(t_logical_block_type_ptr type, std::string port_name, int pin_index_in_port) {
    int ipin = OPEN;

    t_pb_type* pb_type = type->pb_type;
    t_port* matched_port = nullptr;
    int port_base_ipin = 0;
    for (int iport = 0; iport < pb_type->num_ports; ++iport) {
        t_port* port = &pb_type->ports[iport];

        if (port->name == port_name) {
            matched_port = port;
            break;
        }
        port_base_ipin += port->num_pins;
    }

    if (matched_port) {
        VTR_ASSERT(matched_port->name == port_name);
        VTR_ASSERT(pin_index_in_port < matched_port->num_pins);

        ipin = port_base_ipin + pin_index_in_port;
    }

    return ipin;
}

//Returns true if the specified block type contains the specified blif model name
bool block_type_contains_blif_model(t_logical_block_type_ptr type, std::string blif_model_name) {
    return pb_type_contains_blif_model(type->pb_type, blif_model_name);
}

static bool block_type_contains_blif_model(t_logical_block_type_ptr type, const std::regex& blif_model_regex) {
    return pb_type_contains_blif_model(type->pb_type, blif_model_regex);
}

//Returns true of a pb_type (or it's children) contain the specified blif model name
bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::string& blif_model_name) {
    if (!pb_type) {
        return false;
    }

    if (pb_type->blif_model != nullptr) {
        //Leaf pb_type
        VTR_ASSERT(pb_type->num_modes == 0);
        if (blif_model_name == pb_type->blif_model
            || ".subckt " + blif_model_name == pb_type->blif_model) {
            return true;
        } else {
            return false;
        }
    } else {
        for (int imode = 0; imode < pb_type->num_modes; ++imode) {
            const t_mode* mode = &pb_type->modes[imode];

            for (int ichild = 0; ichild < mode->num_pb_type_children; ++ichild) {
                const t_pb_type* pb_type_child = &mode->pb_type_children[ichild];
                if (pb_type_contains_blif_model(pb_type_child, blif_model_name)) {
                    return true;
                }
            }
        }
    }
    return false;
}

static bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::regex& blif_model_regex) {
    if (!pb_type) {
        return false;
    }

    if (pb_type->blif_model != nullptr) {
        //Leaf pb_type
        VTR_ASSERT(pb_type->num_modes == 0);
        if (std::regex_match(pb_type->blif_model, blif_model_regex)) {
            return true;
        } else {
            return false;
        }
    } else {
        for (int imode = 0; imode < pb_type->num_modes; ++imode) {
            const t_mode* mode = &pb_type->modes[imode];

            for (int ichild = 0; ichild < mode->num_pb_type_children; ++ichild) {
                const t_pb_type* pb_type_child = &mode->pb_type_children[ichild];
                if (pb_type_contains_blif_model(pb_type_child, blif_model_regex)) {
                    return true;
                }
            }
        }
    }
    return false;
}

int get_max_primitives_in_pb_type(t_pb_type* pb_type) {
    int i, j;
    int max_size, temp_size;
    if (pb_type->modes == nullptr) {
        max_size = 1;
    } else {
        max_size = 0;
        temp_size = 0;
        for (i = 0; i < pb_type->num_modes; i++) {
            for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
                temp_size += pb_type->modes[i].pb_type_children[j].num_pb
                             * get_max_primitives_in_pb_type(
                                   &pb_type->modes[i].pb_type_children[j]);
            }
            if (temp_size > max_size) {
                max_size = temp_size;
            }
        }
    }
    return max_size;
}

/* finds maximum number of nets that can be contained in pb_type, this is bounded by the number of driving pins */
int get_max_nets_in_pb_type(const t_pb_type* pb_type) {
    int i, j;
    int max_nets, temp_nets;
    if (pb_type->modes == nullptr) {
        max_nets = pb_type->num_output_pins;
    } else {
        max_nets = 0;
        for (i = 0; i < pb_type->num_modes; i++) {
            temp_nets = 0;
            for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
                temp_nets += pb_type->modes[i].pb_type_children[j].num_pb
                             * get_max_nets_in_pb_type(
                                   &pb_type->modes[i].pb_type_children[j]);
            }
            if (temp_nets > max_nets) {
                max_nets = temp_nets;
            }
        }
    }
    if (pb_type->parent_mode == nullptr) {
        max_nets += pb_type->num_input_pins + pb_type->num_output_pins
                    + pb_type->num_clock_pins;
    }
    return max_nets;
}

int get_max_depth_of_pb_type(t_pb_type* pb_type) {
    int i, j;
    int max_depth, temp_depth;
    max_depth = pb_type->depth;
    for (i = 0; i < pb_type->num_modes; i++) {
        for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
            temp_depth = get_max_depth_of_pb_type(
                &pb_type->modes[i].pb_type_children[j]);
            if (temp_depth > max_depth) {
                max_depth = temp_depth;
            }
        }
    }
    return max_depth;
}

/**
 * given an atom block and physical primitive type, is the mapping legal
 */
bool primitive_type_feasible(const AtomBlockId blk_id, const t_pb_type* cur_pb_type) {
    if (cur_pb_type == nullptr) {
        return false;
    }

    auto& atom_ctx = g_vpr_ctx.atom();
    if (cur_pb_type->model != atom_ctx.nlist.block_model(blk_id)) {
        //Primitive and atom do not match
        return false;
    }

    VTR_ASSERT_MSG(atom_ctx.nlist.is_compressed(), "This function assumes a compressed/non-dirty netlist");

    //Keep track of how many atom ports were checked.
    //
    //We need to do this since we iterate over the pb's ports and
    //may miss some atom ports if there is a mismatch
    size_t checked_ports = 0;

    //Look at each port on the pb and find the associated port on the
    //atom. To be feasible the pb must have as many pins on each port
    //as the atom requires
    for (int iport = 0; iport < cur_pb_type->num_ports; ++iport) {
        const t_port* pb_port = &cur_pb_type->ports[iport];
        const t_model_ports* pb_model_port = pb_port->model_port;

        //Find the matching port on the atom
        auto port_id = atom_ctx.nlist.find_atom_port(blk_id, pb_model_port);

        if (port_id) { //Port is used by the atom

            //In compressed form the atom netlist stores only in-use pins,
            //so we can query the number of required pins directly
            int required_atom_pins = atom_ctx.nlist.port_pins(port_id).size();

            int available_pb_pins = pb_port->num_pins;

            if (available_pb_pins < required_atom_pins) {
                //Too many pins required
                return false;
            }

            //Note that this port was checked
            ++checked_ports;
        }
    }

    //Similarly to pins, only in-use ports are stored in the compressed
    //atom netlist, so we can figure out how many ports should have been
    //checked directly
    size_t atom_ports = atom_ctx.nlist.block_ports(blk_id).size();

    //See if all the atom ports were checked
    if (checked_ports != atom_ports) {
        VTR_ASSERT(checked_ports < atom_ports);
        //Required atom port was missing from physical primitive
        return false;
    }

    //Feasible
    return true;
}

//Returns the sibling atom of a memory slice pb
//  Note that the pb must be part of a MEMORY_CLASS
AtomBlockId find_memory_sibling(const t_pb* pb) {
    auto& atom_ctx = g_vpr_ctx.atom();

    const t_pb_type* pb_type = pb->pb_graph_node->pb_type;

    VTR_ASSERT(pb_type->class_type == MEMORY_CLASS);

    const t_pb* memory_class_pb = pb->parent_pb;

    for (int isibling = 0; isibling < pb_type->parent_mode->num_pb_type_children; ++isibling) {
        const t_pb* sibling_pb = &memory_class_pb->child_pbs[pb->mode][isibling];

        if (sibling_pb->name != nullptr) {
            return atom_ctx.lookup.pb_atom(sibling_pb);
        }
    }
    return AtomBlockId::INVALID();
}

/**
 * Return pb_graph_node pin from model port and pin
 *  NULL if not found
 */
t_pb_graph_pin* get_pb_graph_node_pin_from_model_port_pin(const t_model_ports* model_port, const int model_pin, const t_pb_graph_node* pb_graph_node) {
    int i;

    if (model_port->dir == IN_PORT) {
        if (model_port->is_clock == false) {
            for (i = 0; i < pb_graph_node->num_input_ports; i++) {
                if (pb_graph_node->input_pins[i][0].port->model_port == model_port) {
                    if (pb_graph_node->num_input_pins[i] > model_pin) {
                        return &pb_graph_node->input_pins[i][model_pin];
                    } else {
                        return nullptr;
                    }
                }
            }
        } else {
            for (i = 0; i < pb_graph_node->num_clock_ports; i++) {
                if (pb_graph_node->clock_pins[i][0].port->model_port == model_port) {
                    if (pb_graph_node->num_clock_pins[i] > model_pin) {
                        return &pb_graph_node->clock_pins[i][model_pin];
                    } else {
                        return nullptr;
                    }
                }
            }
        }
    } else {
        VTR_ASSERT(model_port->dir == OUT_PORT);
        for (i = 0; i < pb_graph_node->num_output_ports; i++) {
            if (pb_graph_node->output_pins[i][0].port->model_port == model_port) {
                if (pb_graph_node->num_output_pins[i] > model_pin) {
                    return &pb_graph_node->output_pins[i][model_pin];
                } else {
                    return nullptr;
                }
            }
        }
    }
    return nullptr;
}

//Retrieves the atom pin associated with a specific CLB and pb_graph_pin
AtomPinId find_atom_pin(ClusterBlockId blk_id, const t_pb_graph_pin* pb_gpin) {
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& atom_ctx = g_vpr_ctx.atom();

    int pb_route_id = pb_gpin->pin_count_in_cluster;
    AtomNetId atom_net = cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route[pb_route_id].atom_net_id;

    VTR_ASSERT(atom_net);

    AtomPinId atom_pin;

    //Look through all the pins on this net, looking for the matching pin
    for (AtomPinId pin : atom_ctx.nlist.net_pins(atom_net)) {
        AtomBlockId blk = atom_ctx.nlist.pin_block(pin);
        if (atom_ctx.lookup.atom_clb(blk) == blk_id) {
            //Part of the same CLB
            if (atom_ctx.lookup.atom_pin_pb_graph_pin(pin) == pb_gpin)
                //The same pin
                atom_pin = pin;
        }
    }

    VTR_ASSERT(atom_pin);

    return atom_pin;
}

//Retrieves the pb_graph_pin associated with an AtomPinId
//  Currently this function just wraps get_pb_graph_node_pin_from_model_port_pin()
//  in a more convenient interface.
const t_pb_graph_pin* find_pb_graph_pin(const AtomNetlist& netlist, const AtomLookup& netlist_lookup, const AtomPinId pin_id) {
    VTR_ASSERT(pin_id);

    //Get the graph node
    AtomBlockId blk_id = netlist.pin_block(pin_id);
    const t_pb_graph_node* pb_gnode = netlist_lookup.atom_pb_graph_node(blk_id);
    VTR_ASSERT(pb_gnode);

    //The graph node and pin/block should agree on the model they represent
    VTR_ASSERT(netlist.block_model(blk_id) == pb_gnode->pb_type->model);

    //Get the pin index
    AtomPortId port_id = netlist.pin_port(pin_id);
    int ipin = netlist.pin_port_bit(pin_id);

    //Get the model port
    const t_model_ports* model_port = netlist.port_model(port_id);
    VTR_ASSERT(model_port);

    return get_pb_graph_node_pin_from_model_port_pin(model_port, ipin, pb_gnode);
}

t_pb_graph_pin* get_pb_graph_node_pin_from_block_pin(ClusterBlockId iblock, int ipin) {
    int i, count;
    const t_pb_type* pb_type;
    t_pb_graph_node* pb_graph_node;
    auto& cluster_ctx = g_vpr_ctx.clustering();

    pb_graph_node = cluster_ctx.clb_nlist.block_pb(iblock)->pb_graph_node;
    pb_type = pb_graph_node->pb_type;

    /* If this is post-placed, then the ipin may have been shuffled up by the z * num_pins,
     * bring it back down to 0..num_pins-1 range for easier analysis */
    ipin %= (pb_type->num_input_pins + pb_type->num_output_pins + pb_type->num_clock_pins);

    if (ipin < pb_type->num_input_pins) {
        count = ipin;
        for (i = 0; i < pb_graph_node->num_input_ports; i++) {
            if (count - pb_graph_node->num_input_pins[i] >= 0) {
                count -= pb_graph_node->num_input_pins[i];
            } else {
                return &pb_graph_node->input_pins[i][count];
            }
        }
    } else if (ipin < pb_type->num_input_pins + pb_type->num_output_pins) {
        count = ipin - pb_type->num_input_pins;
        for (i = 0; i < pb_graph_node->num_output_ports; i++) {
            if (count - pb_graph_node->num_output_pins[i] >= 0) {
                count -= pb_graph_node->num_output_pins[i];
            } else {
                return &pb_graph_node->output_pins[i][count];
            }
        }
    } else {
        count = ipin - pb_type->num_input_pins - pb_type->num_output_pins;
        for (i = 0; i < pb_graph_node->num_clock_ports; i++) {
            if (count - pb_graph_node->num_clock_pins[i] >= 0) {
                count -= pb_graph_node->num_clock_pins[i];
            } else {
                return &pb_graph_node->clock_pins[i][count];
            }
        }
    }
    VTR_ASSERT(0);
    return nullptr;
}

const t_port* find_pb_graph_port(const t_pb_graph_node* pb_gnode, std::string port_name) {
    const t_pb_graph_pin* gpin = find_pb_graph_pin(pb_gnode, port_name, 0);

    if (gpin != nullptr) {
        return gpin->port;
    }
    return nullptr;
}

const t_pb_graph_pin* find_pb_graph_pin(const t_pb_graph_node* pb_gnode, std::string port_name, int index) {
    for (int iport = 0; iport < pb_gnode->num_input_ports; iport++) {
        if (pb_gnode->num_input_pins[iport] < index) continue;

        const t_pb_graph_pin* gpin = &pb_gnode->input_pins[iport][index];

        if (gpin->port->name == port_name) {
            return gpin;
        }
    }
    for (int iport = 0; iport < pb_gnode->num_output_ports; iport++) {
        if (pb_gnode->num_output_pins[iport] < index) continue;

        const t_pb_graph_pin* gpin = &pb_gnode->output_pins[iport][index];

        if (gpin->port->name == port_name) {
            return gpin;
        }
    }
    for (int iport = 0; iport < pb_gnode->num_clock_ports; iport++) {
        if (pb_gnode->num_clock_pins[iport] < index) continue;

        const t_pb_graph_pin* gpin = &pb_gnode->clock_pins[iport][index];

        if (gpin->port->name == port_name) {
            return gpin;
        }
    }

    //Not found
    return nullptr;
}

/* Recusively visit through all pb_graph_nodes to populate pb_graph_pin_lookup_from_index */
static void load_pb_graph_pin_lookup_from_index_rec(t_pb_graph_pin** pb_graph_pin_lookup_from_index, t_pb_graph_node* pb_graph_node) {
    for (int iport = 0; iport < pb_graph_node->num_input_ports; iport++) {
        for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ipin++) {
            t_pb_graph_pin* pb_pin = &pb_graph_node->input_pins[iport][ipin];
            VTR_ASSERT(pb_graph_pin_lookup_from_index[pb_pin->pin_count_in_cluster] == nullptr);
            pb_graph_pin_lookup_from_index[pb_pin->pin_count_in_cluster] = pb_pin;
        }
    }
    for (int iport = 0; iport < pb_graph_node->num_output_ports; iport++) {
        for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ipin++) {
            t_pb_graph_pin* pb_pin = &pb_graph_node->output_pins[iport][ipin];
            VTR_ASSERT(pb_graph_pin_lookup_from_index[pb_pin->pin_count_in_cluster] == nullptr);
            pb_graph_pin_lookup_from_index[pb_pin->pin_count_in_cluster] = pb_pin;
        }
    }
    for (int iport = 0; iport < pb_graph_node->num_clock_ports; iport++) {
        for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ipin++) {
            t_pb_graph_pin* pb_pin = &pb_graph_node->clock_pins[iport][ipin];
            VTR_ASSERT(pb_graph_pin_lookup_from_index[pb_pin->pin_count_in_cluster] == nullptr);
            pb_graph_pin_lookup_from_index[pb_pin->pin_count_in_cluster] = pb_pin;
        }
    }

    for (int imode = 0; imode < pb_graph_node->pb_type->num_modes; imode++) {
        for (int ipb_type = 0; ipb_type < pb_graph_node->pb_type->modes[imode].num_pb_type_children; ipb_type++) {
            for (int ipb = 0; ipb < pb_graph_node->pb_type->modes[imode].pb_type_children[ipb_type].num_pb; ipb++) {
                load_pb_graph_pin_lookup_from_index_rec(pb_graph_pin_lookup_from_index, &pb_graph_node->child_pb_graph_nodes[imode][ipb_type][ipb]);
            }
        }
    }
}

/* Create a lookup that returns a pb_graph_pin pointer given the pb_graph_pin index */
t_pb_graph_pin** alloc_and_load_pb_graph_pin_lookup_from_index(t_logical_block_type_ptr type) {
    t_pb_graph_pin** pb_graph_pin_lookup_from_type = nullptr;

    t_pb_graph_node* pb_graph_head = type->pb_graph_head;
    if (pb_graph_head == nullptr) {
        return nullptr;
    }
    int num_pins = pb_graph_head->total_pb_pins;

    VTR_ASSERT(num_pins > 0);

    pb_graph_pin_lookup_from_type = new t_pb_graph_pin*[num_pins];
    for (int id = 0; id < num_pins; id++) {
        pb_graph_pin_lookup_from_type[id] = nullptr;
    }

    VTR_ASSERT(pb_graph_pin_lookup_from_type);

    load_pb_graph_pin_lookup_from_index_rec(pb_graph_pin_lookup_from_type, pb_graph_head);

    for (int id = 0; id < num_pins; id++) {
        VTR_ASSERT(pb_graph_pin_lookup_from_type[id] != nullptr);
    }

    return pb_graph_pin_lookup_from_type;
}

/* Free pb_graph_pin lookup array */
void free_pb_graph_pin_lookup_from_index(t_pb_graph_pin** pb_graph_pin_lookup_from_type) {
    if (pb_graph_pin_lookup_from_type == nullptr) {
        return;
    }
    delete[] pb_graph_pin_lookup_from_type;
}

/**
 * Create lookup table that returns a pointer to the pb given [index to block][pin_id].
 */
vtr::vector<ClusterBlockId, t_pb**> alloc_and_load_pin_id_to_pb_mapping() {
    auto& cluster_ctx = g_vpr_ctx.clustering();

    vtr::vector<ClusterBlockId, t_pb**> pin_id_to_pb_mapping(cluster_ctx.clb_nlist.blocks().size());
    for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
        pin_id_to_pb_mapping[blk_id] = new t_pb*[cluster_ctx.clb_nlist.block_type(blk_id)->pb_graph_head->total_pb_pins];
        for (int j = 0; j < cluster_ctx.clb_nlist.block_type(blk_id)->pb_graph_head->total_pb_pins; j++) {
            pin_id_to_pb_mapping[blk_id][j] = nullptr;
        }
        load_pin_id_to_pb_mapping_rec(cluster_ctx.clb_nlist.block_pb(blk_id), pin_id_to_pb_mapping[blk_id]);
    }
    return pin_id_to_pb_mapping;
}

/**
 * Recursively create lookup table that returns a pointer to the pb given a pb_graph_pin id.
 */
static void load_pin_id_to_pb_mapping_rec(t_pb* cur_pb, t_pb** pin_id_to_pb_mapping) {
    t_pb_graph_node* pb_graph_node = cur_pb->pb_graph_node;
    t_pb_type* pb_type = pb_graph_node->pb_type;
    int mode = cur_pb->mode;

    for (int i = 0; i < pb_graph_node->num_input_ports; i++) {
        for (int j = 0; j < pb_graph_node->num_input_pins[i]; j++) {
            pin_id_to_pb_mapping[pb_graph_node->input_pins[i][j].pin_count_in_cluster] = cur_pb;
        }
    }
    for (int i = 0; i < pb_graph_node->num_output_ports; i++) {
        for (int j = 0; j < pb_graph_node->num_output_pins[i]; j++) {
            pin_id_to_pb_mapping[pb_graph_node->output_pins[i][j].pin_count_in_cluster] = cur_pb;
        }
    }
    for (int i = 0; i < pb_graph_node->num_clock_ports; i++) {
        for (int j = 0; j < pb_graph_node->num_clock_pins[i]; j++) {
            pin_id_to_pb_mapping[pb_graph_node->clock_pins[i][j].pin_count_in_cluster] = cur_pb;
        }
    }

    if (pb_type->num_modes == 0 || cur_pb->child_pbs == nullptr) {
        return;
    }

    for (int i = 0; i < pb_type->modes[mode].num_pb_type_children; i++) {
        for (int j = 0; j < pb_type->modes[mode].pb_type_children[i].num_pb; j++) {
            load_pin_id_to_pb_mapping_rec(&cur_pb->child_pbs[i][j], pin_id_to_pb_mapping);
        }
    }
}

/**
 * free pin_index_to_pb_mapping lookup table
 */
void free_pin_id_to_pb_mapping(vtr::vector<ClusterBlockId, t_pb**>& pin_id_to_pb_mapping) {
    auto& cluster_ctx = g_vpr_ctx.clustering();
    for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
        delete[] pin_id_to_pb_mapping[blk_id];
    }
    pin_id_to_pb_mapping.clear();
}

/**
 * Determine cost for using primitive within a complex block, should use primitives of low cost before selecting primitives of high cost
 * For now, assume primitives that have a lot of pins are scarcer than those without so use primitives with less pins before those with more
 */
float compute_primitive_base_cost(const t_pb_graph_node* primitive) {
    return (primitive->pb_type->num_input_pins
            + primitive->pb_type->num_output_pins
            + primitive->pb_type->num_clock_pins);
}

int num_ext_inputs_atom_block(AtomBlockId blk_id) {
    /* Returns the number of input pins on this atom block that must be hooked *
     * up through external interconnect. That is, the number of input          *
     * pins used - the number which connect (internally) to the outputs.       */

    int ext_inps = 0;

    /* TODO: process to get ext_inps is slow, should cache in lookup table */

    std::unordered_set<AtomNetId> input_nets;

    //Record the unique input nets
    auto& atom_ctx = g_vpr_ctx.atom();
    for (auto pin_id : atom_ctx.nlist.block_input_pins(blk_id)) {
        auto net_id = atom_ctx.nlist.pin_net(pin_id);
        input_nets.insert(net_id);
    }

    ext_inps = input_nets.size();

    //Look through the output nets for any duplicates of the input nets
    for (auto pin_id : atom_ctx.nlist.block_output_pins(blk_id)) {
        auto net_id = atom_ctx.nlist.pin_net(pin_id);
        if (input_nets.count(net_id)) {
            --ext_inps;
        }
    }

    VTR_ASSERT(ext_inps >= 0);

    return (ext_inps);
}

void free_pb(t_pb* pb) {
    if (pb == nullptr) {
        return;
    }

    const t_pb_type* pb_type;
    int i, j, mode;

    pb_type = pb->pb_graph_node->pb_type;

    if (pb->name) {
        free(pb->name);
        pb->name = nullptr;
    }

    if (pb_type->blif_model == nullptr) {
        mode = pb->mode;
        for (i = 0; i < pb_type->modes[mode].num_pb_type_children && pb->child_pbs != nullptr; i++) {
            for (j = 0; j < pb_type->modes[mode].pb_type_children[i].num_pb && pb->child_pbs[i] != nullptr; j++) {
                if (pb->child_pbs[i][j].name != nullptr || pb->child_pbs[i][j].child_pbs != nullptr) {
                    free_pb(&pb->child_pbs[i][j]);
                }
            }
            if (pb->child_pbs[i]) {
                //Free children (num_pb)
                delete[] pb->child_pbs[i];
            }
        }
        if (pb->child_pbs) {
            //Free child pointers (modes)
            delete[] pb->child_pbs;
        }

        pb->child_pbs = nullptr;

    } else {
        /* Primitive */
        auto& atom_ctx = g_vpr_ctx.mutable_atom();
        auto blk_id = atom_ctx.lookup.pb_atom(pb);
        if (blk_id) {
            //Update atom netlist mapping
            atom_ctx.lookup.set_atom_clb(blk_id, ClusterBlockId::INVALID());
            atom_ctx.lookup.set_atom_pb(blk_id, nullptr);
        }
        atom_ctx.lookup.set_atom_pb(AtomBlockId::INVALID(), pb);
    }
    free_pb_stats(pb);
}

void revalid_molecules(const t_pb* pb, const std::multimap<AtomBlockId, t_pack_molecule*>& atom_molecules) {
    const t_pb_type* pb_type = pb->pb_graph_node->pb_type;

    if (pb_type->blif_model == nullptr) {
        int mode = pb->mode;
        for (int i = 0; i < pb_type->modes[mode].num_pb_type_children && pb->child_pbs != nullptr; i++) {
            for (int j = 0; j < pb_type->modes[mode].pb_type_children[i].num_pb && pb->child_pbs[i] != nullptr; j++) {
                if (pb->child_pbs[i][j].name != nullptr || pb->child_pbs[i][j].child_pbs != nullptr) {
                    revalid_molecules(&pb->child_pbs[i][j], atom_molecules);
                }
            }
        }
    } else {
        //Primitive
        auto& atom_ctx = g_vpr_ctx.mutable_atom();

        auto blk_id = atom_ctx.lookup.pb_atom(pb);
        if (blk_id) {
            /* If any molecules were marked invalid because of this logic block getting packed, mark them valid */

            //Update atom netlist mapping
            atom_ctx.lookup.set_atom_clb(blk_id, ClusterBlockId::INVALID());
            atom_ctx.lookup.set_atom_pb(blk_id, nullptr);

            auto rng = atom_molecules.equal_range(blk_id);
            for (const auto& kv : vtr::make_range(rng.first, rng.second)) {
                t_pack_molecule* cur_molecule = kv.second;
                if (cur_molecule->valid == false) {
                    int i;
                    for (i = 0; i < get_array_size_of_molecule(cur_molecule); i++) {
                        if (cur_molecule->atom_block_ids[i]) {
                            if (atom_ctx.lookup.atom_clb(cur_molecule->atom_block_ids[i]) != ClusterBlockId::INVALID()) {
                                break;
                            }
                        }
                    }
                    /* All atom blocks are open for this molecule, place back in queue */
                    if (i == get_array_size_of_molecule(cur_molecule)) {
                        cur_molecule->valid = true;
                        // when invalidating a molecule check if it's a chain molecule
                        // that is part of a long chain. If so, check if this molecule
                        // have modified the chain_id value based on the stale packing
                        // then reset the chain id and the first packed molecule pointer
                        // this is packing is being reset
                        if (cur_molecule->is_chain() && cur_molecule->chain_info->is_long_chain && cur_molecule->chain_info->first_packed_molecule == cur_molecule) {
                            cur_molecule->chain_info->first_packed_molecule = nullptr;
                            cur_molecule->chain_info->chain_id = -1;
                        }
                    }
                }
            }
        }
    }
}

void free_pb_stats(t_pb* pb) {
    if (pb) {
        if (pb->pb_stats == nullptr) {
            return;
        }

        pb->pb_stats->gain.clear();
        pb->pb_stats->timinggain.clear();
        pb->pb_stats->sharinggain.clear();
        pb->pb_stats->hillgain.clear();
        pb->pb_stats->connectiongain.clear();
        pb->pb_stats->num_pins_of_net_in_pb.clear();

        if (pb->pb_stats->feasible_blocks) {
            free(pb->pb_stats->feasible_blocks);
        }
        if (!pb->parent_pb) {
            pb->pb_stats->transitive_fanout_candidates.clear();
        }
        delete pb->pb_stats;
        pb->pb_stats = nullptr;
    }
}

/***************************************************************************************
 * Y.G.THIEN
 * 29 AUG 2012
 *
 * The following functions maps the block pins indices for all block types to the      *
 * corresponding port indices and port_pin indices. This is necessary since there are  *
 * different netlist conventions - in the cluster level, ports and port pins are used  *
 * while in the post-pack level, block pins are used.                                  *
 *                                                                                     *
 ***************************************************************************************/

void get_port_pin_from_blk_pin(int blk_type_index, int blk_pin, int* port, int* port_pin) {
    /* These two mappings are needed since there are two different netlist   *
     * conventions - in the cluster level, ports and port pins are used      *
     * while in the post-pack level, block pins are used. The reason block   *
     * type is used instead of blocks is that the mapping is the same for    *
     * blocks belonging to the same block type.                              *
     *                                                                       *
     * f_port_from_blk_pin array allow us to quickly find what port a        *
     * block pin corresponds to.                                             *
     * [0...device_ctx.logical_block_types.size()-1][0...blk_pin_count-1]    *
     *                                                                       *
     * f_port_pin_from_blk_pin array allow us to quickly find what port      *
     * pin a block pin corresponds to.                                       *
     * [0...device_ctx.logical_block_types.size()-1][0...blk_pin_count-1]    */

    /* If either one of the arrays is not allocated and loaded, it is        *
     * corrupted, so free both of them.                                      */
    if ((f_port_from_blk_pin == nullptr && f_port_pin_from_blk_pin != nullptr)
        || (f_port_from_blk_pin != nullptr && f_port_pin_from_blk_pin == nullptr)) {
        free_port_pin_from_blk_pin();
    }

    /* If the arrays are not allocated and loaded, allocate it.              */
    if (f_port_from_blk_pin == nullptr && f_port_pin_from_blk_pin == nullptr) {
        alloc_and_load_port_pin_from_blk_pin();
    }

    /* Return the port and port_pin for the pin.                             */
    *port = f_port_from_blk_pin[blk_type_index][blk_pin];
    *port_pin = f_port_pin_from_blk_pin[blk_type_index][blk_pin];
}

void free_port_pin_from_blk_pin() {
    /* Frees the f_port_from_blk_pin and f_port_pin_from_blk_pin arrays.     *
     *                                                                       *
     * This function is called when the file-scope arrays are corrupted.     *
     * Otherwise, the arrays are freed in free_placement_structs()           */

    unsigned int itype;

    auto& device_ctx = g_vpr_ctx.device();

    if (f_port_from_blk_pin != nullptr) {
        for (itype = 1; itype < device_ctx.logical_block_types.size(); itype++) {
            free(f_port_from_blk_pin[itype]);
        }
        free(f_port_from_blk_pin);

        f_port_from_blk_pin = nullptr;
    }

    if (f_port_pin_from_blk_pin != nullptr) {
        for (itype = 1; itype < device_ctx.logical_block_types.size(); itype++) {
            free(f_port_pin_from_blk_pin[itype]);
        }
        free(f_port_pin_from_blk_pin);

        f_port_pin_from_blk_pin = nullptr;
    }
}

static void alloc_and_load_port_pin_from_blk_pin() {
    /* Allocates and loads f_port_from_blk_pin and f_port_pin_from_blk_pin   *
     * arrays.                                                               *
     *                                                                       *
     * The arrays are freed in free_placement_structs()                      */

    int** temp_port_from_blk_pin = nullptr;
    int** temp_port_pin_from_blk_pin = nullptr;
    unsigned int itype;
    int iblk_pin, iport, iport_pin;
    int blk_pin_count, num_port_pins, num_ports;
    auto& device_ctx = g_vpr_ctx.device();

    /* Allocate and initialize the values to OPEN (-1). */
    temp_port_from_blk_pin = (int**)vtr::malloc(device_ctx.logical_block_types.size() * sizeof(int*));
    temp_port_pin_from_blk_pin = (int**)vtr::malloc(device_ctx.logical_block_types.size() * sizeof(int*));
    for (const auto& type : device_ctx.logical_block_types) {
        itype = type.index;
        blk_pin_count = physical_tile_type(&type)->num_pins;

        temp_port_from_blk_pin[itype] = (int*)vtr::malloc(blk_pin_count * sizeof(int));
        temp_port_pin_from_blk_pin[itype] = (int*)vtr::malloc(blk_pin_count * sizeof(int));

        for (iblk_pin = 0; iblk_pin < blk_pin_count; iblk_pin++) {
            temp_port_from_blk_pin[itype][iblk_pin] = OPEN;
            temp_port_pin_from_blk_pin[itype][iblk_pin] = OPEN;
        }
    }

    /* Load the values */
    for (const auto& type : device_ctx.logical_block_types) {
        itype = type.index;

        /* itype starts from 1 since device_ctx.logical_block_types[0] is the EMPTY_TYPE. */
        if (itype == 0) {
            continue;
        }

        blk_pin_count = 0;
        num_ports = type.pb_type->num_ports;

        for (iport = 0; iport < num_ports; iport++) {
            num_port_pins = type.pb_type->ports[iport].num_pins;

            for (iport_pin = 0; iport_pin < num_port_pins; iport_pin++) {
                temp_port_from_blk_pin[itype][blk_pin_count] = iport;
                temp_port_pin_from_blk_pin[itype][blk_pin_count] = iport_pin;
                blk_pin_count++;
            }
        }
    }

    /* Sets the file_scope variables to point at the arrays. */
    f_port_from_blk_pin = temp_port_from_blk_pin;
    f_port_pin_from_blk_pin = temp_port_pin_from_blk_pin;
}

void get_blk_pin_from_port_pin(int blk_type_index, int port, int port_pin, int* blk_pin) {
    /* This mapping is needed since there are two different netlist                         *
     * conventions - in the cluster level, ports and port pins are used                     *
     * while in the post-pack level, block pins are used. The reason block                  *
     * type is used instead of blocks is to save memories.                                  *
     *                                                                                      *
     * f_port_pin_to_block_pin array allows us to quickly find what block                   *
     * pin a port pin corresponds to.                                                       *
     * [0...device_ctx.logical_block_types.size()-1][0...num_ports-1][0...num_port_pins-1]  */

    /* If the array is not allocated and loaded, allocate it.                */
    if (f_blk_pin_from_port_pin == nullptr) {
        alloc_and_load_blk_pin_from_port_pin();
    }

    /* Return the port and port_pin for the pin.                             */
    *blk_pin = f_blk_pin_from_port_pin[blk_type_index][port][port_pin];
}

void free_blk_pin_from_port_pin() {
    /* Frees the f_blk_pin_from_port_pin array.               *
     *                                                        *
     * This function is called when the arrays are freed in   *
     * free_placement_structs()                               */

    int iport, num_ports;
    auto& device_ctx = g_vpr_ctx.device();

    if (f_blk_pin_from_port_pin != nullptr) {
        for (const auto& type : device_ctx.logical_block_types) {
            int itype = type.index;

            // Avoid EMPTY_TYPE
            if (itype == 0) {
                continue;
            }

            num_ports = type.pb_type->num_ports;
            for (iport = 0; iport < num_ports; iport++) {
                free(f_blk_pin_from_port_pin[itype][iport]);
            }
            free(f_blk_pin_from_port_pin[itype]);
        }
        free(f_blk_pin_from_port_pin);

        f_blk_pin_from_port_pin = nullptr;
    }
}

static void alloc_and_load_blk_pin_from_port_pin() {
    /* Allocates and loads blk_pin_from_port_pin array.                      *
     *                                                                       *
     * The arrays are freed in free_placement_structs()                      */

    int*** temp_blk_pin_from_port_pin = nullptr;
    unsigned int itype;
    int iport, iport_pin;
    int blk_pin_count, num_port_pins, num_ports;
    auto& device_ctx = g_vpr_ctx.device();

    /* Allocate and initialize the values to OPEN (-1). */
    temp_blk_pin_from_port_pin = (int***)vtr::malloc(device_ctx.logical_block_types.size() * sizeof(int**));
    for (itype = 1; itype < device_ctx.logical_block_types.size(); itype++) {
        num_ports = device_ctx.logical_block_types[itype].pb_type->num_ports;
        temp_blk_pin_from_port_pin[itype] = (int**)vtr::malloc(num_ports * sizeof(int*));
        for (iport = 0; iport < num_ports; iport++) {
            num_port_pins = device_ctx.logical_block_types[itype].pb_type->ports[iport].num_pins;
            temp_blk_pin_from_port_pin[itype][iport] = (int*)vtr::malloc(num_port_pins * sizeof(int));

            for (iport_pin = 0; iport_pin < num_port_pins; iport_pin++) {
                temp_blk_pin_from_port_pin[itype][iport][iport_pin] = OPEN;
            }
        }
    }

    /* Load the values */
    /* itype starts from 1 since device_ctx.block_types[0] is the EMPTY_TYPE. */
    for (itype = 1; itype < device_ctx.logical_block_types.size(); itype++) {
        blk_pin_count = 0;
        num_ports = device_ctx.logical_block_types[itype].pb_type->num_ports;
        for (iport = 0; iport < num_ports; iport++) {
            num_port_pins = device_ctx.logical_block_types[itype].pb_type->ports[iport].num_pins;
            for (iport_pin = 0; iport_pin < num_port_pins; iport_pin++) {
                temp_blk_pin_from_port_pin[itype][iport][iport_pin] = blk_pin_count;
                blk_pin_count++;
            }
        }
    }

    /* Sets the file_scope variables to point at the arrays. */
    f_blk_pin_from_port_pin = temp_blk_pin_from_port_pin;
}

/***************************************************************************************
 * Y.G.THIEN
 * 30 AUG 2012
 *
 * The following functions parses the direct connections' information obtained from    *
 * the arch file. Then, the functions map the block pins indices for all block types   *
 * to the corresponding idirect (the index of the direct connection as specified in    *
 * the arch file) and direct type (whether this pin is a SOURCE or a SINK for the      *
 * direct connection). If a pin is not part of any direct connections, the value       *
 * OPEN (-1) is stored in both entries.                                                *
 *                                                                                     *
 * The mapping arrays are freed by the caller. Currently, this mapping is only used to *
 * load placement macros in place_macro.c                                              *
 *                                                                                     *
 ***************************************************************************************/

void parse_direct_pin_name(char* src_string, int line, int* start_pin_index, int* end_pin_index, char* pb_type_name, char* port_name) {
    /* Parses out the pb_type_name and port_name from the direct passed in.   *
     * If the start_pin_index and end_pin_index is specified, parse them too. *
     * Return the values parsed by reference.                                 */

    char source_string[MAX_STRING_LEN + 1];
    char* find_format = nullptr;
    int ichar, match_count;

    if (vtr::split(src_string).size() > 1) {
        VPR_THROW(VPR_ERROR_ARCH,
                  "Only a single port pin range specification allowed for direct connect (was: '%s')", src_string);
    }

    // parse out the pb_type and port name, possibly pin_indices
    find_format = strstr(src_string, "[");
    if (find_format == nullptr) {
        /* Format "pb_type_name.port_name" */
        *start_pin_index = *end_pin_index = -1;

        if (strlen(src_string) + 1 <= MAX_STRING_LEN + 1) {
            strcpy(source_string, src_string);
        } else {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                            "Pin name exceeded buffer size of %zu characters", MAX_STRING_LEN + 1);
        }
        for (ichar = 0; ichar < (int)(strlen(source_string)); ichar++) {
            if (source_string[ichar] == '.')
                source_string[ichar] = ' ';
        }

        match_count = sscanf(source_string, "%s %s", pb_type_name, port_name);
        if (match_count != 2) {
            VTR_LOG_ERROR(
                "[LINE %d] Invalid pin - %s, name should be in the format "
                "\"pb_type_name\".\"port_name\" or \"pb_type_name\".\"port_name[end_pin_index:start_pin_index]\". "
                "The end_pin_index and start_pin_index can be the same.\n",
                line, src_string);
            exit(1);
        }
    } else {
        /* Format "pb_type_name.port_name[end_pin_index:start_pin_index]" */
        strcpy(source_string, src_string);
        for (ichar = 0; ichar < (int)(strlen(source_string)); ichar++) {
            //Need white space between the components when using %s with
            //sscanf
            if (source_string[ichar] == '.')
                source_string[ichar] = ' ';
            if (source_string[ichar] == '[')
                source_string[ichar] = ' ';
        }

        match_count = sscanf(source_string, "%s %s %d:%d]",
                             pb_type_name, port_name,
                             end_pin_index, start_pin_index);
        if (match_count != 4) {
            VTR_LOG_ERROR(
                "[LINE %d] Invalid pin - %s, name should be in the format "
                "\"pb_type_name\".\"port_name\" or \"pb_type_name\".\"port_name[end_pin_index:start_pin_index]\". "
                "The end_pin_index and start_pin_index can be the same.\n",
                line, src_string);
            exit(1);
        }
        if (*end_pin_index < 0 || *start_pin_index < 0) {
            VTR_LOG_ERROR(
                "[LINE %d] Invalid pin - %s, the pin_index in "
                "[end_pin_index:start_pin_index] should not be a negative value.\n",
                line, src_string);
            exit(1);
        }
        if (*end_pin_index < *start_pin_index) {
            VTR_LOG_ERROR(
                "[LINE %d] Invalid from_pin - %s, the end_pin_index in "
                "[end_pin_index:start_pin_index] should not be less than start_pin_index.\n",
                line, src_string);
            exit(1);
        }
    }
}

static void mark_direct_of_pins(int start_pin_index, int end_pin_index, int itype, int iport, int** idirect_from_blk_pin, int idirect, int** direct_type_from_blk_pin, int direct_type, int line, char* src_string) {
    /* Mark the pin entry in idirect_from_blk_pin with idirect and the pin entry in    *
     * direct_type_from_blk_pin with direct_type from start_pin_index to               *
     * end_pin_index.                                                                  */

    int iport_pin, iblk_pin;
    auto& device_ctx = g_vpr_ctx.device();

    // Mark pins with indices from start_pin_index to end_pin_index, inclusive
    for (iport_pin = start_pin_index; iport_pin <= end_pin_index; iport_pin++) {
        get_blk_pin_from_port_pin(itype, iport, iport_pin, &iblk_pin);

        //iterate through all segment connections and check if all Fc's are 0
        bool all_fcs_0 = true;
        for (const auto& fc_spec : device_ctx.physical_tile_types[itype].fc_specs) {
            for (int ipin : fc_spec.pins) {
                if (iblk_pin == ipin && fc_spec.fc_value > 0) {
                    all_fcs_0 = false;
                    break;
                }
            }
            if (!all_fcs_0) break;
        }

        // Check the fc for the pin, direct chain link only if fc == 0
        if (all_fcs_0) {
            idirect_from_blk_pin[itype][iblk_pin] = idirect;

            // Check whether the pins are marked, errors out if so
            if (direct_type_from_blk_pin[itype][iblk_pin] != OPEN) {
                VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                                "[LINE %d] Invalid pin - %s, this pin is in more than one direct connection.\n",
                                line, src_string);
            } else {
                direct_type_from_blk_pin[itype][iblk_pin] = direct_type;
            }
        }
    } // Finish marking all the pins
}

static void mark_direct_of_ports(int idirect, int direct_type, char* pb_type_name, char* port_name, int end_pin_index, int start_pin_index, char* src_string, int line, int** idirect_from_blk_pin, int** direct_type_from_blk_pin) {
    /* Go through all the ports in all the blocks to find the port that has the same   *
     * name as port_name and belongs to the block type that has the name pb_type_name. *
     * Then, check that whether start_pin_index and end_pin_index are specified. If    *
     * they are, mark down the pins from start_pin_index to end_pin_index, inclusive.  *
     * Otherwise, mark down all the pins in that port.                                 */

    int num_ports, num_port_pins;
    unsigned int itype;
    int iport;
    auto& device_ctx = g_vpr_ctx.device();

    // Go through all the block types
    for (itype = 1; itype < device_ctx.logical_block_types.size(); itype++) {
        // Find blocks with the same pb_type_name
        if (strcmp(device_ctx.logical_block_types[itype].pb_type->name, pb_type_name) == 0) {
            num_ports = device_ctx.logical_block_types[itype].pb_type->num_ports;
            for (iport = 0; iport < num_ports; iport++) {
                // Find ports with the same port_name
                if (strcmp(device_ctx.logical_block_types[itype].pb_type->ports[iport].name, port_name) == 0) {
                    num_port_pins = device_ctx.logical_block_types[itype].pb_type->ports[iport].num_pins;

                    // Check whether the end_pin_index is valid
                    if (end_pin_index > num_port_pins) {
                        VTR_LOG_ERROR(
                            "[LINE %d] Invalid pin - %s, the end_pin_index in "
                            "[end_pin_index:start_pin_index] should "
                            "be less than the num_port_pins %d.\n",
                            line, src_string, num_port_pins);
                        exit(1);
                    }

                    // Check whether the pin indices are specified
                    if (start_pin_index >= 0 || end_pin_index >= 0) {
                        mark_direct_of_pins(start_pin_index, end_pin_index, itype,
                                            iport, idirect_from_blk_pin, idirect,
                                            direct_type_from_blk_pin, direct_type, line, src_string);
                    } else {
                        mark_direct_of_pins(0, num_port_pins - 1, itype,
                                            iport, idirect_from_blk_pin, idirect,
                                            direct_type_from_blk_pin, direct_type, line, src_string);
                    }
                } // Do nothing if port_name does not match
            }     // Finish going through all the ports
        }         // Do nothing if pb_type_name does not match
    }             // Finish going through all the blocks
}

void alloc_and_load_idirect_from_blk_pin(t_direct_inf* directs, int num_directs, int*** idirect_from_blk_pin, int*** direct_type_from_blk_pin) {
    /* Allocates and loads idirect_from_blk_pin and direct_type_from_blk_pin arrays.    *
     *                                                                                  *
     * For a bus (multiple bits) direct connection, all the pins in the bus are marked. *
     *                                                                                  *
     * idirect_from_blk_pin array allow us to quickly find pins that could be in a      *
     * direct connection. Values stored is the index of the possible direct connection  *
     * as specified in the arch file, OPEN (-1) is stored for pins that could not be    *
     * part of a direct chain conneciton.                                               *
     *                                                                                  *
     * direct_type_from_blk_pin array stores the value SOURCE if the pin is the         *
     * from_pin, SINK if the pin is the to_pin in the direct connection as specified in *
     * the arch file, OPEN (-1) is stored for pins that could not be part of a direct   *
     * chain conneciton.                                                                *
     *                                                                                  *
     * Stores the pointers to the two 2D arrays in the addresses passed in.             *
     *                                                                                  *
     * The two arrays are freed by the caller(s).                                       */

    int iblk_pin, idirect, num_type_pins;
    int **temp_idirect_from_blk_pin, **temp_direct_type_from_blk_pin;

    char to_pb_type_name[MAX_STRING_LEN + 1], to_port_name[MAX_STRING_LEN + 1],
        from_pb_type_name[MAX_STRING_LEN + 1], from_port_name[MAX_STRING_LEN + 1];
    int to_start_pin_index = -1, to_end_pin_index = -1;
    int from_start_pin_index = -1, from_end_pin_index = -1;
    auto& device_ctx = g_vpr_ctx.device();

    /* Allocate and initialize the values to OPEN (-1). */
    temp_idirect_from_blk_pin = (int**)vtr::malloc(device_ctx.logical_block_types.size() * sizeof(int*));
    temp_direct_type_from_blk_pin = (int**)vtr::malloc(device_ctx.logical_block_types.size() * sizeof(int*));
    for (const auto& type : device_ctx.logical_block_types) {
        int itype = type.index;
        num_type_pins = physical_tile_type(&type)->num_pins;

        temp_idirect_from_blk_pin[itype] = (int*)vtr::malloc(num_type_pins * sizeof(int));
        temp_direct_type_from_blk_pin[itype] = (int*)vtr::malloc(num_type_pins * sizeof(int));

        /* Initialize values to OPEN */
        for (iblk_pin = 0; iblk_pin < num_type_pins; iblk_pin++) {
            temp_idirect_from_blk_pin[itype][iblk_pin] = OPEN;
            temp_direct_type_from_blk_pin[itype][iblk_pin] = OPEN;
        }
    }

    /* Load the values */
    // Go through directs and find pins with possible direct connections
    for (idirect = 0; idirect < num_directs; idirect++) {
        // Parse out the pb_type and port name, possibly pin_indices from from_pin
        parse_direct_pin_name(directs[idirect].from_pin, directs[idirect].line,
                              &from_end_pin_index, &from_start_pin_index, from_pb_type_name, from_port_name);

        // Parse out the pb_type and port name, possibly pin_indices from to_pin
        parse_direct_pin_name(directs[idirect].to_pin, directs[idirect].line,
                              &to_end_pin_index, &to_start_pin_index, to_pb_type_name, to_port_name);

        /* Now I have all the data that I need, I could go through all the block pins   *
         * in all the blocks to find all the pins that could have possible direct       *
         * connections. Mark all down all those pins with the idirect the pins belong   *
         * to and whether it is a source or a sink of the direct connection.            */

        // Find blocks with the same name as from_pb_type_name and from_port_name
        mark_direct_of_ports(idirect, SOURCE, from_pb_type_name, from_port_name,
                             from_end_pin_index, from_start_pin_index, directs[idirect].from_pin,
                             directs[idirect].line,
                             temp_idirect_from_blk_pin, temp_direct_type_from_blk_pin);

        // Then, find blocks with the same name as to_pb_type_name and from_port_name
        mark_direct_of_ports(idirect, SINK, to_pb_type_name, to_port_name,
                             to_end_pin_index, to_start_pin_index, directs[idirect].to_pin,
                             directs[idirect].line,
                             temp_idirect_from_blk_pin, temp_direct_type_from_blk_pin);

    } // Finish going through all the directs

    /* Returns the pointer to the 2D arrays by reference. */
    *idirect_from_blk_pin = temp_idirect_from_blk_pin;
    *direct_type_from_blk_pin = temp_direct_type_from_blk_pin;
}

/*
 * this function is only called by print_switch_usage()
 * at the point of this function call, every switch type / fanin combination
 * has a unique index.
 * but for switch usage analysis, we need to convert the index back to the
 * type / fanin combination
 */
static int convert_switch_index(int* switch_index, int* fanin) {
    if (*switch_index == -1)
        return 1;

    auto& device_ctx = g_vpr_ctx.device();

    for (int iswitch = 0; iswitch < device_ctx.num_arch_switches; iswitch++) {
        for (auto itr = device_ctx.switch_fanin_remap[iswitch].begin(); itr != device_ctx.switch_fanin_remap[iswitch].end(); itr++) {
            if (itr->second == *switch_index) {
                *switch_index = iswitch;
                *fanin = itr->first;
                return 0;
            }
        }
    }
    *switch_index = -1;
    *fanin = -1;
    VTR_LOG("\n\nerror converting switch index ! \n\n");
    return -1;
}

/*
 * print out number of usage for every switch (type / fanin combination)
 * (referring to rr_graph.c: alloc_rr_switch_inf())
 * NOTE: to speed up this function, for XXX uni-directional arch XXX, the most efficient
 * way is to change the device_ctx.rr_nodes data structure (let it store the inward switch index,
 * instead of outward switch index list): --> instead of using a nested loop of
 *     for (inode in rr_nodes) {
 *         for (iedges in edges) {
 *             get switch type;
 *             get fanin;
 *         }
 *     }
 * as is done in rr_graph.c: alloc_rr_switch_inf()
 * we can just use a single loop
 *     for (inode in rr_nodes) {
 *         get switch type of inode;
 *         get fanin of inode;
 *     }
 * now since device_ctx.rr_nodes does not contain the switch type inward to the current node,
 * we have to use an extra loop to setup the information of inward switch first.
 */
void print_switch_usage() {
    auto& device_ctx = g_vpr_ctx.device();

    if (device_ctx.switch_fanin_remap.empty()) {
        VTR_LOG_WARN("Cannot print switch usage stats: device_ctx.switch_fanin_remap is empty\n");
        return;
    }
    map<int, int>* switch_fanin_count;
    map<int, float>* switch_fanin_delay;
    switch_fanin_count = new map<int, int>[device_ctx.num_arch_switches];
    switch_fanin_delay = new map<int, float>[device_ctx.num_arch_switches];
    // a node can have multiple inward switches, so
    // map key: switch index; map value: count (fanin)
    map<int, int>* inward_switch_inf = new map<int, int>[device_ctx.rr_nodes.size()];
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        const t_rr_node& from_node = device_ctx.rr_nodes[inode];
        int num_edges = from_node.num_edges();
        for (int iedge = 0; iedge < num_edges; iedge++) {
            int switch_index = from_node.edge_switch(iedge);
            int to_node_index = from_node.edge_sink_node(iedge);
            // Assumption: suppose for a L4 wire (bi-directional): ----+----+----+----, it can be driven from any point (0, 1, 2, 3).
            //             physically, the switch driving from point 1 & 3 should be the same. But we will assign then different switch
            //             index; or there is no way to differentiate them after abstracting a 2D wire into a 1D node
            if (inward_switch_inf[to_node_index].count(switch_index) == 0)
                inward_switch_inf[to_node_index][switch_index] = 0;
            //VTR_ASSERT(from_node.type != OPIN);
            inward_switch_inf[to_node_index][switch_index]++;
        }
    }
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        map<int, int>::iterator itr;
        for (itr = inward_switch_inf[inode].begin(); itr != inward_switch_inf[inode].end(); itr++) {
            int switch_index = itr->first;
            int fanin = itr->second;
            float Tdel = device_ctx.rr_switch_inf[switch_index].Tdel;
            int status = convert_switch_index(&switch_index, &fanin);
            if (status == -1) {
                delete[] switch_fanin_count;
                delete[] switch_fanin_delay;
                delete[] inward_switch_inf;
                return;
            }
            if (switch_fanin_count[switch_index].count(fanin) == 0) {
                switch_fanin_count[switch_index][fanin] = 0;
            }
            switch_fanin_count[switch_index][fanin]++;
            switch_fanin_delay[switch_index][fanin] = Tdel;
        }
    }
    VTR_LOG("\n=============== switch usage stats ===============\n");
    for (int iswitch = 0; iswitch < device_ctx.num_arch_switches; iswitch++) {
        char* s_name = device_ctx.arch_switch_inf[iswitch].name;
        float s_area = device_ctx.arch_switch_inf[iswitch].mux_trans_size;
        VTR_LOG(">>>>> switch index: %d, name: %s, mux trans size: %g\n", iswitch, s_name, s_area);

        map<int, int>::iterator itr;
        for (itr = switch_fanin_count[iswitch].begin(); itr != switch_fanin_count[iswitch].end(); itr++) {
            VTR_LOG("\t\tnumber of fanin: %d", itr->first);
            VTR_LOG("\t\tnumber of wires driven by this switch: %d", itr->second);
            VTR_LOG("\t\tTdel: %g\n", switch_fanin_delay[iswitch][itr->first]);
        }
    }
    VTR_LOG("\n==================================================\n\n");
    delete[] switch_fanin_count;
    delete[] switch_fanin_delay;
    delete[] inward_switch_inf;
}

/*
 * Motivation:
 *     to see what portion of long wires are utilized
 *     potentially a good measure for router look ahead quality
 */
/*
 * void print_usage_by_wire_length() {
 * map<int, int> used_wire_count;
 * map<int, int> total_wire_count;
 * auto& device_ctx = g_vpr_ctx.device();
 * for (int inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
 * if (device_ctx.rr_nodes[inode].type() == CHANX || rr_node[inode].type() == CHANY) {
 * //int length = abs(device_ctx.rr_nodes[inode].get_xhigh() + rr_node[inode].get_yhigh()
 * //             - device_ctx.rr_nodes[inode].get_xlow() - rr_node[inode].get_ylow());
 * int length = device_ctx.rr_nodes[inode].get_length();
 * if (rr_node_route_inf[inode].occ() > 0) {
 * if (used_wire_count.count(length) == 0)
 * used_wire_count[length] = 0;
 * used_wire_count[length] ++;
 * }
 * if (total_wire_count.count(length) == 0)
 * total_wire_count[length] = 0;
 * total_wire_count[length] ++;
 * }
 * }
 * int total_wires = 0;
 * map<int, int>::iterator itr;
 * for (itr = total_wire_count.begin(); itr != total_wire_count.end(); itr++) {
 * total_wires += itr->second;
 * }
 * VTR_LOG("\n\t-=-=-=-=-=-=-=-=-=-=- wire usage stats -=-=-=-=-=-=-=-=-=-=-\n");
 * for (itr = total_wire_count.begin(); itr != total_wire_count.end(); itr++)
 * VTR_LOG("\ttotal number: wire of length %d, ratio to all length of wires: %g\n", itr->first, ((float)itr->second) / total_wires);
 * for (itr = used_wire_count.begin(); itr != used_wire_count.end(); itr++) {
 * float ratio_to_same_type_total = ((float)itr->second) / total_wire_count[itr->first];
 * float ratio_to_all_type_total = ((float)itr->second) / total_wires;
 * VTR_LOG("\t\tratio to same type of wire: %g\tratio to all types of wire: %g\n", ratio_to_same_type_total, ratio_to_all_type_total);
 * }
 * VTR_LOG("\n\t-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n");
 * used_wire_count.clear();
 * total_wire_count.clear();
 * }
 */

void place_sync_external_block_connections(ClusterBlockId iblk) {
    auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
    auto& place_ctx = g_vpr_ctx.mutable_placement();
    VTR_ASSERT_MSG(place_ctx.block_locs[iblk].nets_and_pins_synced_to_z_coordinate == false, "Block net and pins must not be already synced");

    auto type = physical_tile_type(iblk);
    VTR_ASSERT(type->num_pins % type->capacity == 0);
    int max_num_block_pins = type->num_pins / type->capacity;
    /* Logical location and physical location is offset by z * max_num_block_pins */

    auto& clb_nlist = cluster_ctx.clb_nlist;
    for (auto pin : clb_nlist.block_pins(iblk)) {
        int orig_phys_pin_index = clb_nlist.pin_physical_index(pin);
        int new_phys_pin_index = orig_phys_pin_index + place_ctx.block_locs[iblk].loc.z * max_num_block_pins;
        clb_nlist.set_pin_physical_index(pin, new_phys_pin_index);
    }

    //Mark the block as synced
    place_ctx.block_locs[iblk].nets_and_pins_synced_to_z_coordinate = true;
}

int max_pins_per_grid_tile() {
    auto& device_ctx = g_vpr_ctx.device();
    int max_pins = 0;
    for (auto& type : device_ctx.physical_tile_types) {
        int pins_per_grid_tile = type.num_pins / (type.width * type.height);
        //Use the maximum number of pins normalized by block area
        max_pins = max(max_pins, pins_per_grid_tile);
    }
    return max_pins;
}

void pretty_print_uint(const char* prefix, size_t value, int num_digits, int scientific_precision) {
    //Print as integer if it will fit in the width, other wise scientific
    if (value <= std::pow(10, num_digits) - 1) {
        //Direct
        VTR_LOG("%s%*zu", prefix, num_digits, value);
    } else {
        //Scientific
        VTR_LOG("%s%#*.*g", prefix, num_digits, scientific_precision, float(value));
    }
}

void pretty_print_float(const char* prefix, double value, int num_digits, int scientific_precision) {
    //Print as float if it will fit in the width, other wise scientific

    //How many whole digits are there in non-scientific style?
    size_t whole_digits = num_digits - scientific_precision - 1; //-1 for decimal point
    if (value <= std::pow(10, whole_digits) - 1) {
        //Direct
        VTR_LOG("%s%*.*f", prefix, num_digits, scientific_precision, value);
    } else {
        //Scientific
        VTR_LOG("%s%#*.*g", prefix, num_digits, scientific_precision + 1, value);
    }
}
