/*
 * Author: Jason Luu
 * Date: October 8, 2008
 *
 * Initializes and allocates the physical logic block grid for VPR.
 *
 */

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <regex>
#include <limits>

#include "vtr_assert.h"
#include "vtr_math.h"
#include "vtr_log.h"

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

#include "globals.h"
#include "SetupGrid.h"
#include "expr_eval.h"

static DeviceGrid auto_size_device_grid(const std::vector<t_grid_def>& grid_layouts, const std::map<t_logical_block_type_ptr, size_t>& minimum_instance_counts, float maximum_device_utilization);
static std::vector<t_physical_tile_type_ptr> grid_overused_resources(const DeviceGrid& grid, std::map<t_logical_block_type_ptr, size_t> instance_counts);
static bool grid_satisfies_instance_counts(const DeviceGrid& grid, std::map<t_logical_block_type_ptr, size_t> instance_counts, float maximum_utilization);
static DeviceGrid build_device_grid(const t_grid_def& grid_def, size_t width, size_t height, bool warn_out_of_range = true, std::vector<t_physical_tile_type_ptr> limiting_resources = std::vector<t_physical_tile_type_ptr>());

static void CheckGrid(const DeviceGrid& grid);

static void set_grid_block_type(int priority, const t_physical_tile_type* type, size_t x_root, size_t y_root, vtr::Matrix<t_grid_tile>& grid, vtr::Matrix<int>& grid_priorities, const t_metadata_dict* meta);

//Create the device grid based on resource requirements
DeviceGrid create_device_grid(std::string layout_name, const std::vector<t_grid_def>& grid_layouts, const std::map<t_logical_block_type_ptr, size_t>& minimum_instance_counts, float target_device_utilization) {
    if (layout_name == "auto") {
        //Auto-size the device
        //
        //Note that we treat the target device utilization as a maximum
        return auto_size_device_grid(grid_layouts, minimum_instance_counts, target_device_utilization);
    } else {
        //Use the specified device

        //Find the matching grid definition
        auto cmp = [&](const t_grid_def& grid_def) {
            return grid_def.name == layout_name;
        };

        auto iter = std::find_if(grid_layouts.begin(), grid_layouts.end(), cmp);
        if (iter == grid_layouts.end()) {
            //Not found
            std::string valid_names;
            for (size_t i = 0; i < grid_layouts.size(); ++i) {
                if (i != 0) {
                    valid_names += ", ";
                }
                valid_names += "'" + grid_layouts[i].name + "'";
            }
            VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Failed to find grid layout named '%s' (valid grid layouts: %s)\n", layout_name.c_str(), valid_names.c_str());
        }

        return build_device_grid(*iter, iter->width, iter->height);
    }
}

//Create the device grid based on dimensions
DeviceGrid create_device_grid(std::string layout_name, const std::vector<t_grid_def>& grid_layouts, size_t width, size_t height) {
    if (layout_name == "auto") {
        VTR_ASSERT(grid_layouts.size() > 0);
        //Auto-size
        if (grid_layouts[0].grid_type == GridDefType::AUTO) {
            //Auto layout of the specified dimensions
            return build_device_grid(grid_layouts[0], width, height);
        } else {
            //Find the fixed layout close to the target size
            std::vector<const t_grid_def*> grid_layouts_view;
            grid_layouts_view.reserve(grid_layouts.size());
            for (const auto& layout : grid_layouts) {
                grid_layouts_view.push_back(&layout);
            }
            auto sort_cmp = [](const t_grid_def* lhs, const t_grid_def* rhs) {
                return lhs->width < rhs->width || lhs->height < rhs->width;
            };
            std::stable_sort(grid_layouts_view.begin(), grid_layouts_view.end(), sort_cmp);

            auto find_cmp = [&](const t_grid_def* grid_def) {
                return grid_def->width >= int(width) && grid_def->height >= int(height);
            };
            auto iter = std::find_if(grid_layouts_view.begin(), grid_layouts_view.end(), find_cmp);

            if (iter == grid_layouts_view.end()) {
                //No device larger than specified width/height, so choose largest possible
                VTR_LOG_WARN(
                    "Specified device dimensions (%zux%zu) exceed those of the largest fixed-size device."
                    " Using the largest fixed-size device\n",
                    width, height);
                --iter;
            }

            const t_grid_def* layout = *iter;

            return build_device_grid(*layout, layout->width, layout->height);
        }
    } else {
        //Use the specified device
        auto cmp = [&](const t_grid_def& grid_def) {
            return grid_def.name == layout_name;
        };

        auto iter = std::find_if(grid_layouts.begin(), grid_layouts.end(), cmp);
        if (iter == grid_layouts.end()) {
            //Not found
            std::string valid_names;
            for (size_t i = 0; i < grid_layouts.size(); ++i) {
                if (i != 0) {
                    valid_names += ", ";
                }
                valid_names += "'" + grid_layouts[i].name + "'";
            }
            VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Failed to find grid layout named '%s' (valid grid layouts: %s)\n", layout_name.c_str(), valid_names.c_str());
        }

        return build_device_grid(*iter, iter->width, iter->height);
    }
}

//Create a device grid which satisfies the minimum block counts
//  If a set of fixed grid layouts are specified, the smallest satisfying grid is picked
//  If an auto grid layouts are specified, the smallest dynamicly sized grid is picked
static DeviceGrid auto_size_device_grid(const std::vector<t_grid_def>& grid_layouts, const std::map<t_logical_block_type_ptr, size_t>& minimum_instance_counts, float maximum_device_utilization) {
    VTR_ASSERT(grid_layouts.size() > 0);

    DeviceGrid grid;

    auto is_auto_grid_def = [](const t_grid_def& grid_def) {
        return grid_def.grid_type == GridDefType::AUTO;
    };

    auto auto_layout_itr = std::find_if(grid_layouts.begin(), grid_layouts.end(), is_auto_grid_def);
    if (auto_layout_itr != grid_layouts.end()) {
        //Automatic grid layout, find the smallest height/width

        VTR_ASSERT_SAFE_MSG(std::find_if(auto_layout_itr + 1, grid_layouts.end(), is_auto_grid_def) == grid_layouts.end(), "Only one <auto_layout>");

        const auto& grid_def = *auto_layout_itr;
        VTR_ASSERT(grid_def.aspect_ratio >= 0.);

        //Initial size is 3x3, the smallest possible while avoiding
        //start before end location issues with <perimeter> location
        //specifications
        size_t width = 3;
        size_t height = 3;
        std::vector<t_physical_tile_type_ptr> limiting_resources;
        do {
            //Scale opposite dimension to match aspect ratio
            height = vtr::nint(width / grid_def.aspect_ratio);

#ifdef VERBOSE
            VTR_LOG("Grid size: %zu x %zu (AR: %.2f) \n", width, height, float(width) / height);
#endif

            //Build the device
            // Don't warn about out-of-range specifications since these can
            // occur (harmlessly) at small device dimensions
            grid = build_device_grid(grid_def, width, height, false, limiting_resources);

            //Check if it satisfies the block counts
            if (grid_satisfies_instance_counts(grid, minimum_instance_counts, maximum_device_utilization)) {
                //Re-build the grid at the final size with out-of-range
                //warnings turned on (so users are aware of out-of-range issues
                //at the final device sizes)
                grid = build_device_grid(grid_def, width, height, true, limiting_resources);
                return grid;
            }

            limiting_resources = grid_overused_resources(grid, minimum_instance_counts);

            //Increase the grid size
            width++;

        } while (true);

    } else {
        VTR_ASSERT(auto_layout_itr == grid_layouts.end());
        //Fixed grid layouts, find the smallest of the fixed layouts

        //Sort the grid layouts from smallest to largest
        std::vector<const t_grid_def*> grid_layouts_view;
        grid_layouts_view.reserve(grid_layouts.size());
        for (const auto& layout : grid_layouts) {
            grid_layouts_view.push_back(&layout);
        }
        auto area_cmp = [](const t_grid_def* lhs, const t_grid_def* rhs) {
            VTR_ASSERT(lhs->grid_type == GridDefType::FIXED);
            VTR_ASSERT(rhs->grid_type == GridDefType::FIXED);

            int lhs_area = lhs->width * lhs->height;
            int rhs_area = rhs->width * rhs->height;

            return lhs_area < rhs_area;
        };
        std::stable_sort(grid_layouts_view.begin(), grid_layouts_view.end(), area_cmp);

        std::vector<t_physical_tile_type_ptr> limiting_resources;

        //Try all the fixed devices in order from smallest to largest
        for (const auto* grid_def : grid_layouts_view) {
            //Build the grid
            grid = build_device_grid(*grid_def, grid_def->width, grid_def->height, true, limiting_resources);

            if (grid_satisfies_instance_counts(grid, minimum_instance_counts, maximum_device_utilization)) {
                return grid;
            }
            limiting_resources = grid_overused_resources(grid, minimum_instance_counts);
        }
    }

    return grid; //Unreachable
}

static std::vector<t_physical_tile_type_ptr> grid_overused_resources(const DeviceGrid& grid, std::map<t_logical_block_type_ptr, size_t> instance_counts) {
    std::vector<t_physical_tile_type_ptr> overused_resources;

    //Are the resources satisified?
    for (auto kv : instance_counts) {
        t_physical_tile_type_ptr type;
        size_t min_count;
        std::tie(type, min_count) = std::make_pair(physical_tile_type(kv.first), kv.second);

        size_t inst_cnt = grid.num_instances(type);

        if (inst_cnt < min_count) {
            overused_resources.push_back(type);
        }
    }

    return overused_resources;
}

static bool grid_satisfies_instance_counts(const DeviceGrid& grid, std::map<t_logical_block_type_ptr, size_t> instance_counts, float maximum_utilization) {
    //Are the resources satisified?
    auto overused_resources = grid_overused_resources(grid, instance_counts);

    if (!overused_resources.empty()) {
        return false;
    }

    //Is the utilization below the maximum?
    float utilization = calculate_device_utilization(grid, instance_counts);

    if (utilization > maximum_utilization) {
        return false;
    }

    return true; //OK
}

//Build the specified device grid
static DeviceGrid build_device_grid(const t_grid_def& grid_def, size_t grid_width, size_t grid_height, bool warn_out_of_range, const std::vector<t_physical_tile_type_ptr> limiting_resources) {
    if (grid_def.grid_type == GridDefType::FIXED) {
        if (grid_def.width != int(grid_width) || grid_def.height != int(grid_height)) {
            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                            "Requested grid size (%zu%zu) does not match fixed device size (%dx%d)",
                            grid_width, grid_height, grid_def.width, grid_def.height);
        }
    }

    auto& device_ctx = g_vpr_ctx.device();

    //Track the current priority for each grid location
    // Note that we initialize it to the lowest (i.e. most negative) possible value, so
    // any user-specified priority will override the default empty grid
    auto grid_priorities = vtr::Matrix<int>({grid_width, grid_height}, std::numeric_limits<int>::lowest());

    auto grid = vtr::Matrix<t_grid_tile>({grid_width, grid_height});

    //Initialize the device to all empty blocks
    auto empty_type = find_block_type_by_name(EMPTY_BLOCK_NAME, device_ctx.physical_tile_types);
    VTR_ASSERT(empty_type != nullptr);
    for (size_t x = 0; x < grid_width; ++x) {
        for (size_t y = 0; y < grid_height; ++y) {
            set_grid_block_type(std::numeric_limits<int>::lowest() + 1, //+1 so it overrides without warning
                                empty_type, x, y, grid, grid_priorities, /*meta=*/nullptr);
        }
    }

    std::set<t_physical_tile_type_ptr> seen_types;
    for (const auto& grid_loc_def : grid_def.loc_defs) {
        //Fill in the block types according to the specification

        auto type = find_block_type_by_name(grid_loc_def.block_type, device_ctx.physical_tile_types);

        if (!type) {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                            "Failed to find block type '%s' for grid location specification",
                            grid_loc_def.block_type.c_str());
        }

        seen_types.insert(type);

        t_formula_data vars;
        vars.set_var_value("W", grid_width);
        vars.set_var_value("H", grid_height);
        vars.set_var_value("w", type->width);
        vars.set_var_value("h", type->height);

        //Load the x specification
        auto& xspec = grid_loc_def.x;

        VTR_ASSERT_MSG(!xspec.start_expr.empty(), "x start position must be specified");
        VTR_ASSERT_MSG(!xspec.end_expr.empty(), "x end position must be specified");
        VTR_ASSERT_MSG(!xspec.incr_expr.empty(), "x increment must be specified");
        VTR_ASSERT_MSG(!xspec.repeat_expr.empty(), "x repeat must be specified");

        size_t startx = parse_formula(xspec.start_expr, vars);
        size_t endx = parse_formula(xspec.end_expr, vars);
        size_t incrx = parse_formula(xspec.incr_expr, vars);
        size_t repeatx = parse_formula(xspec.repeat_expr, vars);

        //Load the y specification
        auto& yspec = grid_loc_def.y;

        VTR_ASSERT_MSG(!yspec.start_expr.empty(), "y start position must be specified");
        VTR_ASSERT_MSG(!yspec.end_expr.empty(), "y end position must be specified");
        VTR_ASSERT_MSG(!yspec.incr_expr.empty(), "y increment must be specified");
        VTR_ASSERT_MSG(!yspec.repeat_expr.empty(), "y repeat must be specified");

        size_t starty = parse_formula(yspec.start_expr, vars);
        size_t endy = parse_formula(yspec.end_expr, vars);
        size_t incry = parse_formula(yspec.incr_expr, vars);
        size_t repeaty = parse_formula(yspec.repeat_expr, vars);

        //Check start against the device dimensions
        // Start locations outside the device will never create block instances
        if (startx > grid_width - 1) {
            if (warn_out_of_range) {
                VTR_LOG_WARN("Block type '%s' grid location specification startx (%s = %d) falls outside device horizontal range [%d,%d]\n",
                             type->name, xspec.start_expr.c_str(), startx, 0, grid_width - 1);
            }
            continue; //No instances will be created
        }

        if (starty > grid_height - 1) {
            if (warn_out_of_range) {
                VTR_LOG_WARN("Block type '%s' grid location specification starty (%s = %d) falls outside device vertical range [%d,%d]\n",
                             type->name, yspec.start_expr.c_str(), starty, 0, grid_height - 1);
            }
            continue; //No instances will be created
        }

        //Check end against the device dimensions
        if (endx > grid_width - 1) {
            if (warn_out_of_range) {
                VTR_LOG_WARN("Block type '%s' grid location specification endx (%s = %d) falls outside device horizontal range [%d,%d]\n",
                             type->name, xspec.end_expr.c_str(), endx, 0, grid_width - 1);
            }
        }

        if (endy > grid_height - 1) {
            if (warn_out_of_range) {
                VTR_LOG_WARN("Block type '%s' grid location specification endy (%s = %d) falls outside device vertical range [%d,%d]\n",
                             type->name, yspec.end_expr.c_str(), endy, 0, grid_height - 1);
            }
        }

        //The end must fall after (or equal) to the start
        if (endx < startx) {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                            "Grid location specification endx (%s = %d) can not come before startx (%s = %d) for block type '%s'",
                            xspec.end_expr.c_str(), endx, xspec.start_expr.c_str(), startx, type->name);
        }

        if (endy < starty) {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                            "Grid location specification endy (%s = %d) can not come before starty (%s = %d) for block type '%s'",
                            yspec.end_expr.c_str(), endy, yspec.start_expr.c_str(), starty, type->name);
        }

        //The minimum increment is the block dimension
        VTR_ASSERT(type->width > 0);
        if (incrx < size_t(type->width)) {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                            "Grid location specification incrx for block type '%s' must be at least"
                            " block width (%d) to avoid overlapping instances (was %s = %d)",
                            type->name, type->width, xspec.incr_expr.c_str(), incrx);
        }

        VTR_ASSERT(type->height > 0);
        if (incry < size_t(type->height)) {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                            "Grid location specification incry for block type '%s' must be at least"
                            " block height (%d) to avoid overlapping instances (was %s = %d)",
                            type->name, type->height, yspec.incr_expr.c_str(), incry);
        }

        //The minimum repeat is the region dimension
        size_t region_width = endx - startx + 1; //+1 since start/end are both inclusive
        if (repeatx < region_width) {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                            "Grid location specification repeatx for block type '%s' must be at least"
                            " the region width (%d) to avoid overlapping instances (was %s = %d)",
                            type->name, region_width, xspec.repeat_expr.c_str(), repeatx);
        }

        size_t region_height = endy - starty + 1; //+1 since start/end are both inclusive
        if (repeaty < region_height) {
            VPR_FATAL_ERROR(VPR_ERROR_ARCH,
                            "Grid location specification repeaty for block type '%s' must be at least"
                            " the region height (%d) to avoid overlapping instances (was %s = %d)",
                            type->name, region_height, xspec.repeat_expr.c_str(), repeaty);
        }

        //VTR_LOG("Applying grid_loc_def for '%s' priority %d startx=%s=%zu, endx=%s=%zu, starty=%s=%zu, endx=%s=%zu,\n",
        //            type->name, grid_loc_def.priority,
        //            xspec.start_expr.c_str(), startx, xspec.end_expr.c_str(), endx,
        //            yspec.start_expr.c_str(), starty, yspec.end_expr.c_str(), endy);

        size_t x_end = 0;
        for (size_t kx = 0; x_end < grid_width; ++kx) { //Repeat in x direction
            size_t x_start = startx + kx * repeatx;
            x_end = endx + kx * repeatx;

            size_t y_end = 0;
            for (size_t ky = 0; y_end < grid_height; ++ky) { //Repeat in y direction
                size_t y_start = starty + ky * repeaty;
                y_end = endy + ky * repeaty;

                size_t x_max = std::min(x_end, grid_width - 1);
                size_t y_max = std::min(y_end, grid_height - 1);

                //Fill in the region
                for (size_t x = x_start; x + (type->width - 1) <= x_max; x += incrx) {
                    for (size_t y = y_start; y + (type->height - 1) <= y_max; y += incry) {
                        set_grid_block_type(grid_loc_def.priority, type, x, y, grid, grid_priorities, grid_loc_def.meta);
                    }
                }
            }
        }
    }

    //Warn if any types were not specified in the grid layout
    for (auto const& type : device_ctx.physical_tile_types) {
        if (&type == empty_type) continue; //Don't worry if empty hasn't been specified

        if (!seen_types.count(&type)) {
            VTR_LOG_WARN("Block type '%s' was not specified in device grid layout\n",
                         type.name);
        }
    }

    auto device_grid = DeviceGrid(grid_def.name, grid, limiting_resources);

    CheckGrid(device_grid);

    return device_grid;
}

static void set_grid_block_type(int priority, const t_physical_tile_type* type, size_t x_root, size_t y_root, vtr::Matrix<t_grid_tile>& grid, vtr::Matrix<int>& grid_priorities, const t_metadata_dict* meta) {
    struct TypeLocation {
        TypeLocation(size_t x_val, size_t y_val, const t_physical_tile_type* type_val, int priority_val)
            : x(x_val)
            , y(y_val)
            , type(type_val)
            , priority(priority_val) {}
        size_t x;
        size_t y;
        const t_physical_tile_type* type;
        int priority;

        bool operator<(const TypeLocation& rhs) const {
            return x < rhs.x || y < rhs.y || type < rhs.type;
        }
    };

    //Collect locations effected by this block
    std::set<TypeLocation> target_locations;
    for (size_t x = x_root; x < x_root + type->width; ++x) {
        for (size_t y = y_root; y < y_root + type->height; ++y) {
            target_locations.insert(TypeLocation(x, y, grid[x][y].type, grid_priorities[x][y]));
        }
    }

    //Record the highest priority of all effected locations
    auto iter = target_locations.begin();
    TypeLocation max_priority_type_loc = *iter;
    for (; iter != target_locations.end(); ++iter) {
        if (iter->priority > max_priority_type_loc.priority) {
            max_priority_type_loc = *iter;
        }
    }

    if (priority < max_priority_type_loc.priority) {
        //Lower priority, do not override
#ifdef VERBOSE
        VTR_LOG("Not creating block '%s' at (%zu,%zu) since overlaps block '%s' at (%zu,%zu) with higher priority (%d > %d)\n",
                type->name, x_root, y_root, max_priority_type_loc.type->name, max_priority_type_loc.x, max_priority_type_loc.y,
                max_priority_type_loc.priority, priority);
#endif
        return;
    }

    if (priority == max_priority_type_loc.priority) {
        //Ambiguous case where current grid block and new specification have equal priority
        //
        //We arbitrarily decide to take the 'last applied' wins approach, and warn the user
        //about the potential ambiguity
        VTR_LOG_WARN(
            "Ambiguous block type specification at grid location (%zu,%zu)."
            " Existing block type '%s' at (%zu,%zu) has the same priority (%d) as new overlapping type '%s'."
            " The last specification will apply.\n",
            x_root, y_root,
            max_priority_type_loc.type->name, max_priority_type_loc.x, max_priority_type_loc.y,
            priority, type->name);
    }

    //Mark all the grid tiles 'covered' by this block with the appropriate type
    //and width/height offsets
    std::set<TypeLocation> root_blocks_to_rip_up;
    auto& device_ctx = g_vpr_ctx.device();
    for (size_t x = x_root; x < x_root + type->width; ++x) {
        VTR_ASSERT(x < grid.end_index(0));

        size_t x_offset = x - x_root;
        for (size_t y = y_root; y < y_root + type->height; ++y) {
            VTR_ASSERT(y < grid.end_index(1));
            size_t y_offset = y - y_root;

            auto& grid_tile = grid[x][y];
            VTR_ASSERT(grid_priorities[x][y] <= priority);

            if (grid_tile.type != nullptr
                && grid_tile.type != device_ctx.EMPTY_TYPE) {
                //We are overriding a non-empty block, we need to be careful
                //to ensure we remove any blocks which will be invalidated when we
                //overwrite part of their locations

                size_t orig_root_x = x - grid[x][y].width_offset;
                size_t orig_root_y = y - grid[x][y].height_offset;

                root_blocks_to_rip_up.insert(TypeLocation(orig_root_x, orig_root_y, grid[x][y].type, grid_priorities[x][y]));
            }

            grid[x][y].type = type;
            grid[x][y].width_offset = x_offset;
            grid[x][y].height_offset = y_offset;
            grid[x][y].meta = meta;

            grid_priorities[x][y] = priority;
        }
    }

    //Rip-up any invalidated blocks
    for (auto invalidated_root : root_blocks_to_rip_up) {
        //Mark all the grid locations used by this root block as empty
        for (size_t x = invalidated_root.x; x < invalidated_root.x + invalidated_root.type->width; ++x) {
            int x_offset = x - invalidated_root.x;
            for (size_t y = invalidated_root.y; y < invalidated_root.y + invalidated_root.type->height; ++y) {
                int y_offset = y - invalidated_root.y;

                if (grid[x][y].type == invalidated_root.type
                    && grid[x][y].width_offset == x_offset
                    && grid[x][y].height_offset == y_offset) {
                    //This is a left-over invalidated block, mark as empty
                    // Note: that we explicitly check the type and offsets, since the original block
                    //       may have been completely overwritten, and we don't want to change anything
                    //       in that case
                    VTR_ASSERT(device_ctx.EMPTY_TYPE->width == 1);
                    VTR_ASSERT(device_ctx.EMPTY_TYPE->height == 1);

#ifdef VERBOSE
                    VTR_LOG("Ripping up block '%s' at (%d,%d) offset (%d,%d). Overlapped by '%s' at (%d,%d)\n",
                            invalidated_root.type->name, invalidated_root.x, invalidated_root.y,
                            x_offset, y_offset,
                            type->name, x_root, y_root);
#endif

                    grid[x][y].type = device_ctx.EMPTY_TYPE;
                    grid[x][y].width_offset = 0;
                    grid[x][y].height_offset = 0;

                    grid_priorities[x][y] = std::numeric_limits<int>::lowest();
                }
            }
        }
    }
}

static void CheckGrid(const DeviceGrid& grid) {
    /* Check grid is valid */
    for (size_t i = 0; i < grid.width(); ++i) {
        for (size_t j = 0; j < grid.height(); ++j) {
            auto type = grid[i][j].type;
            if (nullptr == type) {
                VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Grid Location (%d,%d) has no type.\n", i, j);
            }

            if ((grid[i][j].width_offset < 0)
                || (grid[i][j].width_offset >= type->width)) {
                VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Grid Location (%d,%d) has invalid width offset (%d).\n", i, j, grid[i][j].width_offset);
            }
            if ((grid[i][j].height_offset < 0)
                || (grid[i][j].height_offset >= type->height)) {
                VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Grid Location (%d,%d) has invalid height offset (%d).\n", i, j, grid[i][j].height_offset);
            }

            //Verify that type and width/height offsets are correct (e.g. for dimension > 1 blocks)
            if (grid[i][j].width_offset == 0 && grid[i][j].height_offset == 0) {
                //From the root block check that all other blocks are correct
                for (size_t x = i; x < i + type->width; ++x) {
                    int x_offset = x - i;
                    for (size_t y = j; y < j + type->height; ++y) {
                        int y_offset = y - j;

                        auto& tile = grid[x][y];
                        if (tile.type != type) {
                            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                                            "Grid Location (%d,%d) should have type '%s' (based on root location) but has type '%s'\n",
                                            i, j, type->name, tile.type->name);
                        }

                        if (tile.width_offset != x_offset) {
                            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                                            "Grid Location (%d,%d) of type '%s' should have width offset '%d' (based on root location) but has '%d'\n",
                                            i, j, type->name, x_offset, tile.width_offset);
                        }

                        if (tile.height_offset != y_offset) {
                            VPR_FATAL_ERROR(VPR_ERROR_OTHER,
                                            "Grid Location (%d,%d)  of type '%s' should have height offset '%d' (based on root location) but has '%d'\n",
                                            i, j, type->name, y_offset, tile.height_offset);
                        }
                    }
                }
            }
        }
    }
}

float calculate_device_utilization(const DeviceGrid& grid, std::map<t_logical_block_type_ptr, size_t> instance_counts) {
    //Record the resources of the grid
    std::map<t_physical_tile_type_ptr, size_t> grid_resources;
    for (size_t x = 0; x < grid.width(); ++x) {
        for (size_t y = 0; y < grid.height(); ++y) {
            const auto& grid_tile = grid[x][y];
            if (grid_tile.width_offset == 0 && grid_tile.height_offset == 0) {
                ++grid_resources[grid_tile.type];
            }
        }
    }

    //Determine the area of grid in tile units
    float grid_area = 0.;
    for (auto& kv : grid_resources) {
        t_physical_tile_type_ptr type = kv.first;
        size_t count = kv.second;

        float type_area = type->width * type->height;

        grid_area += type_area * count;
    }

    //Determine the area of instances in tile units
    float instance_area = 0.;
    for (auto& kv : instance_counts) {
        t_physical_tile_type_ptr type = physical_tile_type(kv.first);
        size_t count = kv.second;

        float type_area = type->width * type->height;

        //Instances of multi-capaicty blocks take up less space
        if (type->capacity != 0) {
            type_area /= type->capacity;
        }

        instance_area += type_area * count;
    }

    float utilization = instance_area / grid_area;

    return utilization;
}

size_t count_grid_tiles(const DeviceGrid& grid) {
    return grid.width() * grid.height();
}
