Skip to content

Commit e91a7ed

Browse files
[Place] Independent Placement Verification
Created a method that would independently verify the placement in the VPR flow. If a placement passes this verification, it is assumed that it can be used in routing without issue. By design, this method does not use any global variables (everything needs to be passed in) and recomputes everything that it does not assume. This allows it to be independent of the placement flow being used, so this method can be used in the AP flow as well.
1 parent b3b3084 commit e91a7ed

File tree

6 files changed

+360
-159
lines changed

6 files changed

+360
-159
lines changed

vpr/src/analytical_place/full_legalizer.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
#include "full_legalizer.h"
9-
#include <cmath>
109
#include <list>
1110
#include <unordered_set>
1211
#include <vector>
@@ -24,6 +23,7 @@
2423
#include "pack.h"
2524
#include "physical_types.h"
2625
#include "place_constraints.h"
26+
#include "verify_placement.h"
2727
#include "vpr_api.h"
2828
#include "vpr_context.h"
2929
#include "vpr_error.h"
@@ -393,5 +393,16 @@ void FullLegalizer::legalize(const PartialPlacement& p_placement) {
393393

394394
// Place the clusters based on where the atoms want to be placed.
395395
place_clusters(clb_nlist, p_placement);
396+
397+
// Verify that the placement created by the full legalizer is valid.
398+
unsigned num_placement_errors = verify_placement(g_vpr_ctx);
399+
if (num_placement_errors == 0) {
400+
VTR_LOG("Completed placement consistency check successfully.\n");
401+
} else {
402+
VPR_ERROR(VPR_ERROR_AP,
403+
"Completed placement consistency check, %d errors found.\n"
404+
"Aborting program.\n",
405+
num_placement_errors);
406+
}
396407
}
397408

vpr/src/place/place.cpp

Lines changed: 14 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include <optional>
99

1010
#include "NetPinTimingInvalidator.h"
11+
#include "clustered_netlist.h"
12+
#include "device_grid.h"
13+
#include "verify_placement.h"
1114
#include "vtr_assert.h"
1215
#include "vtr_log.h"
1316
#include "vtr_util.h"
@@ -228,11 +231,6 @@ static int check_placement_costs(const t_placer_costs& costs,
228231
PlacerState& placer_state,
229232
NetCostHandler& net_cost_handler);
230233

231-
232-
static int check_placement_consistency(const BlkLocRegistry& blk_loc_registry);
233-
static int check_block_placement_consistency(const BlkLocRegistry& blk_loc_registry);
234-
static int check_macro_placement_consistency(const BlkLocRegistry& blk_loc_registry);
235-
236234
static float starting_t(const t_annealing_state* state,
237235
t_placer_costs* costs,
238236
t_annealing_sched annealing_sched,
@@ -1947,12 +1945,21 @@ static void check_place(const t_placer_costs& costs,
19471945
* every block, blocks are in legal spots, etc. Also recomputes *
19481946
* the final placement cost from scratch and makes sure it is *
19491947
* within roundoff of what we think the cost is. */
1948+
const auto& pl_macros = g_vpr_ctx.placement().pl_macros;
1949+
const ClusteredNetlist& clb_nlist = g_vpr_ctx.clustering().clb_nlist;
1950+
const DeviceGrid& device_grid = g_vpr_ctx.device().grid;
1951+
const auto& cluster_constraints = g_vpr_ctx.floorplanning().cluster_constraints;
19501952

19511953
int error = 0;
19521954

1953-
error += check_placement_consistency(placer_state.blk_loc_registry());
1955+
// Verify the placement invariants independent to the placement flow.
1956+
error += verify_placement(placer_state.blk_loc_registry(),
1957+
pl_macros,
1958+
clb_nlist,
1959+
device_grid,
1960+
cluster_constraints);
1961+
19541962
error += check_placement_costs(costs, delay_model, criticalities, place_algorithm, placer_state, net_cost_handler);
1955-
error += check_placement_floorplanning(placer_state.block_locs());
19561963

19571964
if (noc_opts.noc) {
19581965
// check the NoC costs during placement if the user is using the NoC supported flow
@@ -2004,133 +2011,6 @@ static int check_placement_costs(const t_placer_costs& costs,
20042011
return error;
20052012
}
20062013

2007-
static int check_placement_consistency(const BlkLocRegistry& blk_loc_registry) {
2008-
return check_block_placement_consistency(blk_loc_registry) + check_macro_placement_consistency(blk_loc_registry);
2009-
}
2010-
2011-
static int check_block_placement_consistency(const BlkLocRegistry& blk_loc_registry) {
2012-
auto& cluster_ctx = g_vpr_ctx.clustering();
2013-
auto& device_ctx = g_vpr_ctx.device();
2014-
const auto& block_locs = blk_loc_registry.block_locs();
2015-
const auto& grid_blocks = blk_loc_registry.grid_blocks();
2016-
2017-
int error = 0;
2018-
2019-
vtr::vector<ClusterBlockId, int> bdone(cluster_ctx.clb_nlist.blocks().size(), 0);
2020-
2021-
/* Step through device grid and placement. Check it against blocks */
2022-
for (int layer_num = 0; layer_num < (int)device_ctx.grid.get_num_layers(); layer_num++) {
2023-
for (int i = 0; i < (int)device_ctx.grid.width(); i++) {
2024-
for (int j = 0; j < (int)device_ctx.grid.height(); j++) {
2025-
const t_physical_tile_loc tile_loc(i, j, layer_num);
2026-
const auto& type = device_ctx.grid.get_physical_type(tile_loc);
2027-
if (grid_blocks.get_usage(tile_loc) > type->capacity) {
2028-
VTR_LOG_ERROR(
2029-
"%d blocks were placed at grid location (%d,%d,%d), but location capacity is %d.\n",
2030-
grid_blocks.get_usage(tile_loc), i, j, layer_num, type->capacity);
2031-
error++;
2032-
}
2033-
int usage_check = 0;
2034-
for (int k = 0; k < type->capacity; k++) {
2035-
ClusterBlockId bnum = grid_blocks.block_at_location({i, j, k, layer_num});
2036-
if (bnum == ClusterBlockId::INVALID()) {
2037-
continue;
2038-
}
2039-
2040-
auto logical_block = cluster_ctx.clb_nlist.block_type(bnum);
2041-
auto physical_tile = type;
2042-
t_pl_loc block_loc = block_locs[bnum].loc;
2043-
2044-
if (physical_tile_type(block_loc) != physical_tile) {
2045-
VTR_LOG_ERROR(
2046-
"Block %zu type (%s) does not match grid location (%zu,%zu, %d) type (%s).\n",
2047-
size_t(bnum), logical_block->name, i, j, layer_num, physical_tile->name);
2048-
error++;
2049-
}
2050-
2051-
auto& loc = block_locs[bnum].loc;
2052-
if (loc.x != i || loc.y != j || loc.layer != layer_num
2053-
|| !is_sub_tile_compatible(physical_tile, logical_block,
2054-
loc.sub_tile)) {
2055-
VTR_LOG_ERROR(
2056-
"Block %zu's location is (%d,%d,%d,%d) but found in grid at (%d,%d,%d,%d).\n",
2057-
size_t(bnum),
2058-
loc.x,
2059-
loc.y,
2060-
loc.sub_tile,
2061-
loc.layer,
2062-
i,
2063-
j,
2064-
k,
2065-
layer_num);
2066-
error++;
2067-
}
2068-
++usage_check;
2069-
bdone[bnum]++;
2070-
}
2071-
if (usage_check != grid_blocks.get_usage(tile_loc)) {
2072-
VTR_LOG_ERROR(
2073-
"%d block(s) were placed at location (%d,%d,%d), but location contains %d block(s).\n",
2074-
grid_blocks.get_usage(tile_loc),
2075-
tile_loc.x,
2076-
tile_loc.y,
2077-
tile_loc.layer_num,
2078-
usage_check);
2079-
error++;
2080-
}
2081-
}
2082-
}
2083-
}
2084-
2085-
/* Check that every block exists in the device_ctx.grid and cluster_ctx.blocks arrays somewhere. */
2086-
for (ClusterBlockId blk_id : cluster_ctx.clb_nlist.blocks())
2087-
if (bdone[blk_id] != 1) {
2088-
VTR_LOG_ERROR("Block %zu listed %d times in device context grid.\n",
2089-
size_t(blk_id), bdone[blk_id]);
2090-
error++;
2091-
}
2092-
2093-
return error;
2094-
}
2095-
2096-
int check_macro_placement_consistency(const BlkLocRegistry& blk_loc_registry) {
2097-
const auto& pl_macros = g_vpr_ctx.placement().pl_macros;
2098-
const auto& block_locs = blk_loc_registry.block_locs();
2099-
const auto& grid_blocks = blk_loc_registry.grid_blocks();
2100-
2101-
int error = 0;
2102-
2103-
/* Check the pl_macro placement are legal - blocks are in the proper relative position. */
2104-
for (size_t imacro = 0; imacro < pl_macros.size(); imacro++) {
2105-
auto head_iblk = pl_macros[imacro].members[0].blk_index;
2106-
2107-
for (size_t imember = 0; imember < pl_macros[imacro].members.size(); imember++) {
2108-
auto member_iblk = pl_macros[imacro].members[imember].blk_index;
2109-
2110-
// Compute the supposed member's x,y,z location
2111-
t_pl_loc member_pos = block_locs[head_iblk].loc + pl_macros[imacro].members[imember].offset;
2112-
2113-
// Check the blk_loc_registry.block_locs data structure first
2114-
if (block_locs[member_iblk].loc != member_pos) {
2115-
VTR_LOG_ERROR(
2116-
"Block %zu in pl_macro #%zu is not placed in the proper orientation.\n",
2117-
size_t(member_iblk), imacro);
2118-
error++;
2119-
}
2120-
2121-
// Then check the blk_loc_registry.grid data structure
2122-
if (grid_blocks.block_at_location(member_pos) != member_iblk) {
2123-
VTR_LOG_ERROR(
2124-
"Block %zu in pl_macro #%zu is not placed in the proper orientation.\n",
2125-
size_t(member_iblk), imacro);
2126-
error++;
2127-
}
2128-
} // Finish going through all the members
2129-
} // Finish going through all the macros
2130-
2131-
return error;
2132-
}
2133-
21342014
#ifdef VERBOSE
21352015
void print_clb_placement(const char* fname) {
21362016
/* Prints out the clb placements to a file. */

vpr/src/place/place_constraints.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,6 @@
1313
#include "place_util.h"
1414
#include "vpr_context.h"
1515

16-
int check_placement_floorplanning(const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs) {
17-
int error = 0;
18-
auto& cluster_ctx = g_vpr_ctx.clustering();
19-
20-
for (ClusterBlockId blk_id : cluster_ctx.clb_nlist.blocks()) {
21-
t_pl_loc loc = block_locs[blk_id].loc;
22-
if (!cluster_floorplanning_legal(blk_id, loc)) {
23-
error++;
24-
VTR_LOG_ERROR("Block %zu is not in correct floorplanning region.\n", size_t(blk_id));
25-
}
26-
}
27-
28-
return error;
29-
}
30-
3116
bool is_cluster_constrained(ClusterBlockId blk_id) {
3217
auto& floorplanning_ctx = g_vpr_ctx.floorplanning();
3318
const PartitionRegion& pr = floorplanning_ctx.cluster_constraints[blk_id];

vpr/src/place/place_constraints.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,6 @@
1515
#include "place_macro.h"
1616
#include "grid_tile_lookup.h"
1717

18-
/**
19-
* @brief Check that placement of each block is within the floorplan constraint region
20-
* of that block (if the block has any constraints).
21-
*
22-
* @param block_locs Contains the location where each clustered block is placed.
23-
* @return int The number of errors (inconsistencies in adherence to floorplanning constraints).
24-
*/
25-
int check_placement_floorplanning(const vtr::vector_map<ClusterBlockId, t_block_loc>& block_locs);
26-
2718
/**
2819
* @brief Check if the block has floorplanning constraints.
2920
*

0 commit comments

Comments
 (0)