Skip to content

Commit

Permalink
Merge pull request #2802 from AlexandreSinger/feature-verify-placement
Browse files Browse the repository at this point in the history
[Placement] Resolved Inconsistency with Placing at Root Tile Locs
  • Loading branch information
vaughnbetz authored Nov 11, 2024
2 parents fdf6d3c + afcb192 commit 5a062ba
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 108 deletions.
17 changes: 13 additions & 4 deletions vpr/src/base/vpr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <cmath>

#include "cluster_util.h"
#include "verify_placement.h"
#include "vpr_context.h"
#include "vtr_assert.h"
#include "vtr_math.h"
Expand Down Expand Up @@ -801,10 +802,6 @@ bool vpr_place_flow(const Netlist<>& net_list, t_vpr_setup& vpr_setup, const t_a
vpr_load_placement(vpr_setup, arch);
}

// FIXME: This synchronization is not consistent with the rest of
// placement. This requires it to happen after the placement is
// verified. See issue #2801
sync_grid_to_blocks();
post_place_sync();
}

Expand Down Expand Up @@ -877,6 +874,18 @@ void vpr_load_placement(t_vpr_setup& vpr_setup, const t_arch& arch) {
place_ctx.placement_id = read_place(filename_opts.NetFile.c_str(), filename_opts.PlaceFile.c_str(),
blk_loc_registry,
filename_opts.verify_file_digests, device_ctx.grid);

// Verify that the placement invariants are met after reading the placement
// from a file.
unsigned num_errors = verify_placement(g_vpr_ctx);
if (num_errors == 0) {
VTR_LOG("Completed placement consistency check successfully.\n");
} else {
VPR_ERROR(VPR_ERROR_PLACE,
"Completed placement consistency check, %d errors found.\n"
"Aborting program.\n",
num_errors);
}
}

RouteStatus vpr_route_flow(const Netlist<>& net_list,
Expand Down
39 changes: 14 additions & 25 deletions vpr/src/pack/sync_netlists_to_routing_flat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,24 @@ inline ClusterBlockId get_cluster_block_from_rr_node(RRNodeId inode){
auto& place_ctx = g_vpr_ctx.placement();
auto& rr_graph = device_ctx.rr_graph;

auto physical_tile = device_ctx.grid.get_physical_type({
rr_graph.node_xlow(inode),
rr_graph.node_ylow(inode),
rr_graph.node_layer(inode)
});
t_physical_tile_loc node_phy_tile_loc(rr_graph.node_xlow(inode),
rr_graph.node_ylow(inode),
rr_graph.node_layer(inode));
auto physical_tile = device_ctx.grid.get_physical_type(node_phy_tile_loc);

int source_pin = rr_graph.node_pin_num(inode);

auto [_, subtile] = get_sub_tile_from_pin_physical_num(physical_tile, source_pin);

// The placer will only place Clusters at the root tile location. Need to
// offset to the root tile location to get the cluster block at this
// tile.
int width_offset = device_ctx.grid.get_width_offset(node_phy_tile_loc);
int height_offset = device_ctx.grid.get_height_offset(node_phy_tile_loc);

ClusterBlockId clb = place_ctx.grid_blocks().block_at_location({
rr_graph.node_xlow(inode),
rr_graph.node_ylow(inode),
rr_graph.node_xlow(inode) - width_offset,
rr_graph.node_ylow(inode) - height_offset,
subtile,
rr_graph.node_layer(inode)
});
Expand Down Expand Up @@ -185,7 +190,6 @@ static void sync_pb_routes_to_routing(void){
auto& device_ctx = g_vpr_ctx.device();
auto& atom_ctx = g_vpr_ctx.atom();
auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
auto& place_ctx = g_vpr_ctx.placement();
auto& route_ctx = g_vpr_ctx.routing();
auto& rr_graph = device_ctx.rr_graph;

Expand Down Expand Up @@ -220,6 +224,7 @@ static void sync_pb_routes_to_routing(void){

/* Restore the connections */
for(auto [source_inode, sink_inode]: conns_to_restore){
ClusterBlockId clb = get_cluster_block_from_rr_node(source_inode);
auto physical_tile = device_ctx.grid.get_physical_type({
rr_graph.node_xlow(source_inode),
rr_graph.node_ylow(source_inode),
Expand All @@ -228,15 +233,6 @@ static void sync_pb_routes_to_routing(void){
int source_pin = rr_graph.node_pin_num(source_inode);
int sink_pin = rr_graph.node_pin_num(sink_inode);

auto [_, subtile] = get_sub_tile_from_pin_physical_num(physical_tile, source_pin);

ClusterBlockId clb = place_ctx.grid_blocks().block_at_location({
rr_graph.node_xlow(source_inode),
rr_graph.node_ylow(source_inode),
subtile,
rr_graph.node_layer(source_inode)
});

/* Look up pb graph pins from pb type if pin is not on tile, look up from block otherwise */
const t_pb_graph_pin* source_pb_graph_pin, *sink_pb_graph_pin;
if(is_pin_on_tile(physical_tile, sink_pin)){
Expand Down Expand Up @@ -361,14 +357,7 @@ static void sync_clustered_netlist_to_routing(void){

int pin_index = rr_graph.node_pin_num(rt_node.inode);

auto [_, subtile] = get_sub_tile_from_pin_physical_num(physical_tile, pin_index);

ClusterBlockId clb = place_ctx.grid_blocks().block_at_location({
rr_graph.node_xlow(rt_node.inode),
rr_graph.node_ylow(rt_node.inode),
subtile,
rr_graph.node_layer(rt_node.inode)
});
ClusterBlockId clb = get_cluster_block_from_rr_node(rt_node.inode);

if(!is_pin_on_tile(physical_tile, pin_index))
continue;
Expand Down
30 changes: 30 additions & 0 deletions vpr/src/place/verify_placement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* - The grid blocks matches the block locations.
* - Blocks are not in invalid grid locations.
* - All clusters are placed.
* - Clusters are only placed at the root tile location of large tiles.
*
* @param blk_loc_registry A registry containing the block locations and
* the blocks at each grid location.
Expand All @@ -57,6 +58,35 @@ static unsigned check_block_placement_consistency(const BlkLocRegistry& blk_loc_
for (int j = 0; j < (int)device_grid.height(); j++) {
const t_physical_tile_loc tile_loc(i, j, layer_num);
const auto& type = device_grid.get_physical_type(tile_loc);

// If this is not a root tile block, ensure that its usage is 0
// and that it has no valid clusters placed at this location.
// TODO: Eventually it should be made impossible to place blocks
// at these locations.
if (device_grid.get_width_offset(tile_loc) != 0 ||
device_grid.get_height_offset(tile_loc) != 0) {
// Usage must be 0
if (grid_blocks.get_usage(tile_loc) != 0) {
VTR_LOG_ERROR(
"%d blocks were placed at non-root tile location "
"(%d, %d, %d), but no blocks should be placed here.\n",
grid_blocks.get_usage(tile_loc), i, j, layer_num);
num_errors++;
}
// Check that all clusters at this tile location are invalid.
for (int k = 0; k < type->capacity; k++) {
ClusterBlockId bnum = grid_blocks.block_at_location({i, j, k, layer_num});
if (bnum.is_valid()) {
VTR_LOG_ERROR(
"Block %zu was placed at non-root tile location "
"(%d, %d, %d), but no blocks should be placed "
"here.\n",
size_t(bnum), i, j, layer_num);
num_errors++;
}
}
}

if (grid_blocks.get_usage(tile_loc) > type->capacity) {
VTR_LOG_ERROR(
"%d blocks were placed at grid location (%d,%d,%d), but location capacity is %d.\n",
Expand Down
78 changes: 1 addition & 77 deletions vpr/src/util/vpr_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,82 +88,6 @@ void print_tabs(FILE* fpout, int num_tab) {
}
}

/* 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;

const int num_layers = device_ctx.grid.get_num_layers();

auto& grid_blocks = place_ctx.mutable_grid_blocks();
auto& block_locs = place_ctx.block_locs();

/* Reset usage and allocate blocks list if needed */
grid_blocks = GridBlock(device_grid.width(), device_grid.height(), device_ctx.grid.get_num_layers());


for (int layer_num = 0; layer_num < num_layers; layer_num++) {
for (int x = 0; x < (int)device_grid.width(); ++x) {
for (int y = 0; y < (int)device_grid.height(); ++y) {
const t_physical_tile_type_ptr type = device_ctx.grid.get_physical_type({x, y, layer_num});
grid_blocks.initialized_grid_block_at_location({x, y, layer_num}, type->capacity);
}
}
}

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

auto type = physical_tile_type(blk_loc);

/* 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.get_physical_type({blk_x, blk_y, blk_layer})) {
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "A block is in a grid location (%d x %d) layer (%d) with a conflicting types '%s' and '%s' .\n",
blk_x, blk_y, blk_layer,
type->name.c_str(),
device_ctx.grid.get_physical_type({blk_x, blk_y, blk_layer})->name.c_str());
}

/* Check already in use */
if (grid_blocks.block_at_location(blk_loc)) {
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Location (%d, %d, %d, %d) is used more than once.\n",
blk_x, blk_y, blk_z, blk_layer);
}

if (device_ctx.grid.get_width_offset({blk_x, blk_y, blk_layer}) != 0 || device_ctx.grid.get_height_offset({blk_x, blk_y, blk_layer}) != 0) {
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Large block not aligned in placement for cluster_ctx.blocks %lu at (%d, %d, %d, %d).",
size_t(blk_id), blk_x, blk_y, blk_z, blk_layer);
}

/* Set the block */
for (int width = 0; width < type->width; ++width) {
for (int height = 0; height < type->height; ++height) {
grid_blocks.set_block_at_location({blk_x + width, blk_y + height, blk_z, blk_layer}, blk_id);
grid_blocks.increment_usage({blk_x + width, blk_y + height, blk_layer});

VTR_ASSERT(device_ctx.grid.get_width_offset({blk_x + width, blk_y + height, blk_layer}) == width);
VTR_ASSERT(device_ctx.grid.get_height_offset({blk_x + width, blk_y + height, blk_layer}) == height);
}
}
}
}

std::string rr_node_arch_name(RRNodeId inode, bool is_flat) {
auto& device_ctx = g_vpr_ctx.device();
const auto& rr_graph = device_ctx.rr_graph;
Expand Down Expand Up @@ -2134,4 +2058,4 @@ int PortPinToBlockPinConverter::get_blk_pin_from_port_pin(int blk_type_index, in
// Return the port and port_pin for the pin.
int blk_pin = blk_pin_from_port_pin_[blk_type_index][sub_tile][port][port_pin];
return blk_pin;
}
}
2 changes: 0 additions & 2 deletions vpr/src/util/vpr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ inline ParentNetId get_cluster_net_parent_id(const AtomLookup& atom_look_up, Clu
return par_net_id;
}

void sync_grid_to_blocks();

//Returns a user-friendly architectural identifier for the specified RR node
std::string rr_node_arch_name(RRNodeId inode, bool is_flat);

Expand Down

0 comments on commit 5a062ba

Please sign in to comment.