Skip to content

Commit afcb192

Browse files
[Placement] Resolved Inconsistency with Placing at Root Tile Locs
Found an inconsistency with how the placement of cluster blocks into large tiles was handled in VPR. During placement, clusters are only placed at the rool tile location of the grid; however, specific parts of the later stages require that clusters are placed at all tile locations of large tiles. This is inconsistent and makes it confusing to know where clusters should be placed. Enforced that clusters must be placed at the root tile location and never placed in other tile locations in the large tiles. This required fixing an oversite in the flat router which was relying on the fact that clusters will not be placed at the root tile location.
1 parent 1876d05 commit afcb192

File tree

5 files changed

+58
-108
lines changed

5 files changed

+58
-108
lines changed

vpr/src/base/vpr_api.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <cmath>
1717

1818
#include "cluster_util.h"
19+
#include "verify_placement.h"
1920
#include "vpr_context.h"
2021
#include "vtr_assert.h"
2122
#include "vtr_math.h"
@@ -801,10 +802,6 @@ bool vpr_place_flow(const Netlist<>& net_list, t_vpr_setup& vpr_setup, const t_a
801802
vpr_load_placement(vpr_setup, arch);
802803
}
803804

804-
// FIXME: This synchronization is not consistent with the rest of
805-
// placement. This requires it to happen after the placement is
806-
// verified. See issue #2801
807-
sync_grid_to_blocks();
808805
post_place_sync();
809806
}
810807

@@ -877,6 +874,18 @@ void vpr_load_placement(t_vpr_setup& vpr_setup, const t_arch& arch) {
877874
place_ctx.placement_id = read_place(filename_opts.NetFile.c_str(), filename_opts.PlaceFile.c_str(),
878875
blk_loc_registry,
879876
filename_opts.verify_file_digests, device_ctx.grid);
877+
878+
// Verify that the placement invariants are met after reading the placement
879+
// from a file.
880+
unsigned num_errors = verify_placement(g_vpr_ctx);
881+
if (num_errors == 0) {
882+
VTR_LOG("Completed placement consistency check successfully.\n");
883+
} else {
884+
VPR_ERROR(VPR_ERROR_PLACE,
885+
"Completed placement consistency check, %d errors found.\n"
886+
"Aborting program.\n",
887+
num_errors);
888+
}
880889
}
881890

882891
RouteStatus vpr_route_flow(const Netlist<>& net_list,

vpr/src/pack/sync_netlists_to_routing_flat.cpp

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,24 @@ inline ClusterBlockId get_cluster_block_from_rr_node(RRNodeId inode){
7070
auto& place_ctx = g_vpr_ctx.placement();
7171
auto& rr_graph = device_ctx.rr_graph;
7272

73-
auto physical_tile = device_ctx.grid.get_physical_type({
74-
rr_graph.node_xlow(inode),
75-
rr_graph.node_ylow(inode),
76-
rr_graph.node_layer(inode)
77-
});
73+
t_physical_tile_loc node_phy_tile_loc(rr_graph.node_xlow(inode),
74+
rr_graph.node_ylow(inode),
75+
rr_graph.node_layer(inode));
76+
auto physical_tile = device_ctx.grid.get_physical_type(node_phy_tile_loc);
7877

7978
int source_pin = rr_graph.node_pin_num(inode);
8079

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

82+
// The placer will only place Clusters at the root tile location. Need to
83+
// offset to the root tile location to get the cluster block at this
84+
// tile.
85+
int width_offset = device_ctx.grid.get_width_offset(node_phy_tile_loc);
86+
int height_offset = device_ctx.grid.get_height_offset(node_phy_tile_loc);
87+
8388
ClusterBlockId clb = place_ctx.grid_blocks().block_at_location({
84-
rr_graph.node_xlow(inode),
85-
rr_graph.node_ylow(inode),
89+
rr_graph.node_xlow(inode) - width_offset,
90+
rr_graph.node_ylow(inode) - height_offset,
8691
subtile,
8792
rr_graph.node_layer(inode)
8893
});
@@ -185,7 +190,6 @@ static void sync_pb_routes_to_routing(void){
185190
auto& device_ctx = g_vpr_ctx.device();
186191
auto& atom_ctx = g_vpr_ctx.atom();
187192
auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
188-
auto& place_ctx = g_vpr_ctx.placement();
189193
auto& route_ctx = g_vpr_ctx.routing();
190194
auto& rr_graph = device_ctx.rr_graph;
191195

@@ -220,6 +224,7 @@ static void sync_pb_routes_to_routing(void){
220224

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

231-
auto [_, subtile] = get_sub_tile_from_pin_physical_num(physical_tile, source_pin);
232-
233-
ClusterBlockId clb = place_ctx.grid_blocks().block_at_location({
234-
rr_graph.node_xlow(source_inode),
235-
rr_graph.node_ylow(source_inode),
236-
subtile,
237-
rr_graph.node_layer(source_inode)
238-
});
239-
240236
/* Look up pb graph pins from pb type if pin is not on tile, look up from block otherwise */
241237
const t_pb_graph_pin* source_pb_graph_pin, *sink_pb_graph_pin;
242238
if(is_pin_on_tile(physical_tile, sink_pin)){
@@ -361,14 +357,7 @@ static void sync_clustered_netlist_to_routing(void){
361357

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

364-
auto [_, subtile] = get_sub_tile_from_pin_physical_num(physical_tile, pin_index);
365-
366-
ClusterBlockId clb = place_ctx.grid_blocks().block_at_location({
367-
rr_graph.node_xlow(rt_node.inode),
368-
rr_graph.node_ylow(rt_node.inode),
369-
subtile,
370-
rr_graph.node_layer(rt_node.inode)
371-
});
360+
ClusterBlockId clb = get_cluster_block_from_rr_node(rt_node.inode);
372361

373362
if(!is_pin_on_tile(physical_tile, pin_index))
374363
continue;

vpr/src/place/verify_placement.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
* - The grid blocks matches the block locations.
3434
* - Blocks are not in invalid grid locations.
3535
* - All clusters are placed.
36+
* - Clusters are only placed at the root tile location of large tiles.
3637
*
3738
* @param blk_loc_registry A registry containing the block locations and
3839
* the blocks at each grid location.
@@ -57,6 +58,35 @@ static unsigned check_block_placement_consistency(const BlkLocRegistry& blk_loc_
5758
for (int j = 0; j < (int)device_grid.height(); j++) {
5859
const t_physical_tile_loc tile_loc(i, j, layer_num);
5960
const auto& type = device_grid.get_physical_type(tile_loc);
61+
62+
// If this is not a root tile block, ensure that its usage is 0
63+
// and that it has no valid clusters placed at this location.
64+
// TODO: Eventually it should be made impossible to place blocks
65+
// at these locations.
66+
if (device_grid.get_width_offset(tile_loc) != 0 ||
67+
device_grid.get_height_offset(tile_loc) != 0) {
68+
// Usage must be 0
69+
if (grid_blocks.get_usage(tile_loc) != 0) {
70+
VTR_LOG_ERROR(
71+
"%d blocks were placed at non-root tile location "
72+
"(%d, %d, %d), but no blocks should be placed here.\n",
73+
grid_blocks.get_usage(tile_loc), i, j, layer_num);
74+
num_errors++;
75+
}
76+
// Check that all clusters at this tile location are invalid.
77+
for (int k = 0; k < type->capacity; k++) {
78+
ClusterBlockId bnum = grid_blocks.block_at_location({i, j, k, layer_num});
79+
if (bnum.is_valid()) {
80+
VTR_LOG_ERROR(
81+
"Block %zu was placed at non-root tile location "
82+
"(%d, %d, %d), but no blocks should be placed "
83+
"here.\n",
84+
size_t(bnum), i, j, layer_num);
85+
num_errors++;
86+
}
87+
}
88+
}
89+
6090
if (grid_blocks.get_usage(tile_loc) > type->capacity) {
6191
VTR_LOG_ERROR(
6292
"%d blocks were placed at grid location (%d,%d,%d), but location capacity is %d.\n",

vpr/src/util/vpr_utils.cpp

Lines changed: 1 addition & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -88,82 +88,6 @@ void print_tabs(FILE* fpout, int num_tab) {
8888
}
8989
}
9090

91-
/* Points the place_ctx.grid_blocks structure back to the blocks list */
92-
void sync_grid_to_blocks() {
93-
auto& place_ctx = g_vpr_ctx.mutable_placement();
94-
auto& device_ctx = g_vpr_ctx.device();
95-
auto& device_grid = device_ctx.grid;
96-
97-
const int num_layers = device_ctx.grid.get_num_layers();
98-
99-
auto& grid_blocks = place_ctx.mutable_grid_blocks();
100-
auto& block_locs = place_ctx.block_locs();
101-
102-
/* Reset usage and allocate blocks list if needed */
103-
grid_blocks = GridBlock(device_grid.width(), device_grid.height(), device_ctx.grid.get_num_layers());
104-
105-
106-
for (int layer_num = 0; layer_num < num_layers; layer_num++) {
107-
for (int x = 0; x < (int)device_grid.width(); ++x) {
108-
for (int y = 0; y < (int)device_grid.height(); ++y) {
109-
const t_physical_tile_type_ptr type = device_ctx.grid.get_physical_type({x, y, layer_num});
110-
grid_blocks.initialized_grid_block_at_location({x, y, layer_num}, type->capacity);
111-
}
112-
}
113-
}
114-
115-
/* Go through each block */
116-
auto& cluster_ctx = g_vpr_ctx.clustering();
117-
for (ClusterBlockId blk_id : cluster_ctx.clb_nlist.blocks()) {
118-
const auto& blk_loc = block_locs[blk_id].loc;
119-
int blk_x = block_locs[blk_id].loc.x;
120-
int blk_y = block_locs[blk_id].loc.y;
121-
int blk_z = block_locs[blk_id].loc.sub_tile;
122-
int blk_layer = block_locs[blk_id].loc.layer;
123-
124-
auto type = physical_tile_type(blk_loc);
125-
126-
/* Check range of block coords */
127-
if (blk_x < 0 || blk_y < 0
128-
|| (blk_x + type->width - 1) > int(device_ctx.grid.width() - 1)
129-
|| (blk_y + type->height - 1) > int(device_ctx.grid.height() - 1)
130-
|| blk_z < 0 || blk_z > (type->capacity)) {
131-
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Block %zu is at invalid location (%d, %d, %d).\n",
132-
size_t(blk_id), blk_x, blk_y, blk_z);
133-
}
134-
135-
/* Check types match */
136-
if (type != device_ctx.grid.get_physical_type({blk_x, blk_y, blk_layer})) {
137-
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",
138-
blk_x, blk_y, blk_layer,
139-
type->name.c_str(),
140-
device_ctx.grid.get_physical_type({blk_x, blk_y, blk_layer})->name.c_str());
141-
}
142-
143-
/* Check already in use */
144-
if (grid_blocks.block_at_location(blk_loc)) {
145-
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Location (%d, %d, %d, %d) is used more than once.\n",
146-
blk_x, blk_y, blk_z, blk_layer);
147-
}
148-
149-
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) {
150-
VPR_FATAL_ERROR(VPR_ERROR_PLACE, "Large block not aligned in placement for cluster_ctx.blocks %lu at (%d, %d, %d, %d).",
151-
size_t(blk_id), blk_x, blk_y, blk_z, blk_layer);
152-
}
153-
154-
/* Set the block */
155-
for (int width = 0; width < type->width; ++width) {
156-
for (int height = 0; height < type->height; ++height) {
157-
grid_blocks.set_block_at_location({blk_x + width, blk_y + height, blk_z, blk_layer}, blk_id);
158-
grid_blocks.increment_usage({blk_x + width, blk_y + height, blk_layer});
159-
160-
VTR_ASSERT(device_ctx.grid.get_width_offset({blk_x + width, blk_y + height, blk_layer}) == width);
161-
VTR_ASSERT(device_ctx.grid.get_height_offset({blk_x + width, blk_y + height, blk_layer}) == height);
162-
}
163-
}
164-
}
165-
}
166-
16791
std::string rr_node_arch_name(RRNodeId inode, bool is_flat) {
16892
auto& device_ctx = g_vpr_ctx.device();
16993
const auto& rr_graph = device_ctx.rr_graph;
@@ -2134,4 +2058,4 @@ int PortPinToBlockPinConverter::get_blk_pin_from_port_pin(int blk_type_index, in
21342058
// Return the port and port_pin for the pin.
21352059
int blk_pin = blk_pin_from_port_pin_[blk_type_index][sub_tile][port][port_pin];
21362060
return blk_pin;
2137-
}
2061+
}

vpr/src/util/vpr_utils.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,6 @@ inline ParentNetId get_cluster_net_parent_id(const AtomLookup& atom_look_up, Clu
126126
return par_net_id;
127127
}
128128

129-
void sync_grid_to_blocks();
130-
131129
//Returns a user-friendly architectural identifier for the specified RR node
132130
std::string rr_node_arch_name(RRNodeId inode, bool is_flat);
133131

0 commit comments

Comments
 (0)