Skip to content

Commit 61c17c9

Browse files
[AP] Partial Legalizer
This adds the Patial Legalizer block into VPR. A Partial Legalizer takes a partial placement (which likely has many overlapping blocks and is very illegal with blocks in the wrong tiles) and creates a more legal partial placement. These are often called spreaders since their main task is to spread blocks away from each other (the solver tends to put blocks on top of each other). Added a multi-commodity flow-based spreading partial legalizer based on the work by Darav et al. This algorithm was modified to work within the VPR infrastructure on any hypothetical architecture which can be expressed in VPR.
1 parent 24b3bd3 commit 61c17c9

File tree

9 files changed

+2127
-20
lines changed

9 files changed

+2127
-20
lines changed

vpr/src/analytical_place/analytical_placement_flow.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "full_legalizer.h"
1414
#include "gen_ap_netlist_from_atoms.h"
1515
#include "globals.h"
16+
#include "partial_legalizer.h"
1617
#include "partial_placement.h"
1718
#include "prepack.h"
1819
#include "user_place_constraints.h"
@@ -53,6 +54,7 @@ static void print_ap_netlist_stats(const APNetlist& netlist) {
5354
VTR_LOG("\t\tAverage Fanout: %.2f\n", average_fanout);
5455
VTR_LOG("\t\tHighest Fanout: %zu\n", highest_fanout);
5556
VTR_LOG("\tPins: %zu\n", netlist.pins().size());
57+
VTR_LOG("\n");
5658
}
5759

5860
void run_analytical_placement_flow(t_vpr_setup& vpr_setup) {
@@ -77,11 +79,16 @@ void run_analytical_placement_flow(t_vpr_setup& vpr_setup) {
7779
print_ap_netlist_stats(ap_netlist);
7880

7981
// Run the Global Placer
80-
// For now, just runs the solver.
82+
// For now, just runs the solver and partial legalizer 10 times arbitrarily.
8183
PartialPlacement p_placement(ap_netlist);
8284
std::unique_ptr<AnalyticalSolver> solver = make_analytical_solver(e_analytical_solver::QP_HYBRID,
8385
ap_netlist);
84-
solver->solve(0, p_placement);
86+
std::unique_ptr<PartialLegalizer> legalizer = make_partial_legalizer(e_partial_legalizer::FLOW_BASED,
87+
ap_netlist);
88+
for (size_t i = 0; i < 10; i++) {
89+
solver->solve(i, p_placement);
90+
legalizer->legalize(p_placement);
91+
}
8592

8693
// Verify that the partial placement is valid before running the full
8794
// legalizer.

vpr/src/analytical_place/full_legalizer.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "vpr_error.h"
3030
#include "vpr_types.h"
3131
#include "vtr_assert.h"
32+
#include "vtr_geometry.h"
3233
#include "vtr_ndmatrix.h"
3334
#include "vtr_strong_id.h"
3435
#include "vtr_time.h"
@@ -122,9 +123,8 @@ class APClusterPlacer {
122123
const t_physical_tile_loc& tile_loc,
123124
int sub_tile) {
124125
const DeviceContext& device_ctx = g_vpr_ctx.device();
125-
// FIXME: THIS MUST TAKE INTO ACCOUNT THE CONSTRAINTS AS WELL!!!
126-
// - Right now it is just implied.
127-
// - Will work but is unstable.
126+
const FloorplanningContext& floorplanning_ctx = g_vpr_ctx.floorplanning();
127+
const ClusteringContext& cluster_ctx = g_vpr_ctx.clustering();
128128
const auto& block_locs = g_vpr_ctx.placement().block_locs();
129129
auto& blk_loc_registry = g_vpr_ctx.mutable_placement().mutable_blk_loc_registry();
130130
VTR_ASSERT(!is_block_placed(clb_blk_id, block_locs) && "Block already placed. Is this intentional?");
@@ -137,11 +137,24 @@ class APClusterPlacer {
137137
if (device_ctx.grid.get_physical_type(tile_loc)->sub_tiles.size() == 0)
138138
return false;
139139
VTR_ASSERT(sub_tile >= 0 && sub_tile < device_ctx.grid.get_physical_type(tile_loc)->capacity);
140-
// FIXME: Do this better.
141-
// - May need to try all the sub-tiles in a location.
142-
// - https://github.com/AlexandreSinger/vtr-verilog-to-routing/blob/feature-analytical-placer/vpr/src/place/initial_placement.cpp#L755
143-
to_loc.sub_tile = sub_tile;
144-
return try_place_macro(pl_macro, to_loc, blk_loc_registry);
140+
// Check if this cluster is constrained and this location is legal.
141+
if (is_cluster_constrained(clb_blk_id)) {
142+
const auto& cluster_constraints = floorplanning_ctx.cluster_constraints;
143+
if (cluster_constraints[clb_blk_id].is_loc_in_part_reg(to_loc))
144+
return false;
145+
}
146+
// If the location is legal, try to exhaustively place it at this tile
147+
// location. This should try all sub_tiles.
148+
PartitionRegion pr;
149+
vtr::Rect<int> rect(tile_loc.x, tile_loc.y, tile_loc.x, tile_loc.y);
150+
pr.add_to_part_region(Region(rect, to_loc.layer));
151+
const ClusteredNetlist& clb_nlist = cluster_ctx.clb_nlist;
152+
t_logical_block_type_ptr block_type = clb_nlist.block_type(clb_blk_id);
153+
enum e_pad_loc_type pad_loc_type = g_vpr_ctx.device().pad_loc_type;
154+
// FIXME: This currently ignores the sub_tile. Was running into issues
155+
// with trying to force clusters to specific sub_tiles.
156+
return try_place_macro_exhaustively(pl_macro, pr, block_type,
157+
pad_loc_type, blk_loc_registry);
145158
}
146159

147160
// This is not the best way of doing things, but its the simplest. Given a
@@ -352,10 +365,6 @@ void FullLegalizer::place_clusters(const ClusteredNetlist& clb_nlist,
352365
bool placed = ap_cluster_placer.place_cluster(cluster_blk_id, tile_loc, blk_sub_tile);
353366
if (placed)
354367
continue;
355-
// FIXME: Should now try all sub-tiles at this tile location.
356-
// - May need to try all the sub-tiles in a location.
357-
// - however this may need to be done after.
358-
// - https://github.com/AlexandreSinger/vtr-verilog-to-routing/blob/feature-analytical-placer/vpr/src/place/initial_placement.cpp#L755
359368

360369
// Add to list of unplaced clusters.
361370
unplaced_clusters.push_back(cluster_blk_id);

0 commit comments

Comments
 (0)