Skip to content

Commit ab9e064

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 ab9e064

File tree

9 files changed

+2135
-21
lines changed

9 files changed

+2135
-21
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: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
* @file
33
* @author Alex Singer
44
* @date September 2024
5-
* @brief Implements the full legalizer in the AP flow.
5+
* @brief Implements the full legalizer in the AP flow. The Full Legalizer
6+
* takes a partial placement and fully legalizes it. This involves
7+
* creating legal clusters and placing them into valid tile sites.
68
*/
79

810
#include "full_legalizer.h"
@@ -29,6 +31,7 @@
2931
#include "vpr_error.h"
3032
#include "vpr_types.h"
3133
#include "vtr_assert.h"
34+
#include "vtr_geometry.h"
3235
#include "vtr_ndmatrix.h"
3336
#include "vtr_strong_id.h"
3437
#include "vtr_time.h"
@@ -122,9 +125,8 @@ class APClusterPlacer {
122125
const t_physical_tile_loc& tile_loc,
123126
int sub_tile) {
124127
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.
128+
const FloorplanningContext& floorplanning_ctx = g_vpr_ctx.floorplanning();
129+
const ClusteringContext& cluster_ctx = g_vpr_ctx.clustering();
128130
const auto& block_locs = g_vpr_ctx.placement().block_locs();
129131
auto& blk_loc_registry = g_vpr_ctx.mutable_placement().mutable_blk_loc_registry();
130132
VTR_ASSERT(!is_block_placed(clb_blk_id, block_locs) && "Block already placed. Is this intentional?");
@@ -137,11 +139,24 @@ class APClusterPlacer {
137139
if (device_ctx.grid.get_physical_type(tile_loc)->sub_tiles.size() == 0)
138140
return false;
139141
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);
142+
// Check if this cluster is constrained and this location is legal.
143+
if (is_cluster_constrained(clb_blk_id)) {
144+
const auto& cluster_constraints = floorplanning_ctx.cluster_constraints;
145+
if (cluster_constraints[clb_blk_id].is_loc_in_part_reg(to_loc))
146+
return false;
147+
}
148+
// If the location is legal, try to exhaustively place it at this tile
149+
// location. This should try all sub_tiles.
150+
PartitionRegion pr;
151+
vtr::Rect<int> rect(tile_loc.x, tile_loc.y, tile_loc.x, tile_loc.y);
152+
pr.add_to_part_region(Region(rect, to_loc.layer));
153+
const ClusteredNetlist& clb_nlist = cluster_ctx.clb_nlist;
154+
t_logical_block_type_ptr block_type = clb_nlist.block_type(clb_blk_id);
155+
enum e_pad_loc_type pad_loc_type = g_vpr_ctx.device().pad_loc_type;
156+
// FIXME: This currently ignores the sub_tile. Was running into issues
157+
// with trying to force clusters to specific sub_tiles.
158+
return try_place_macro_exhaustively(pl_macro, pr, block_type,
159+
pad_loc_type, blk_loc_registry);
145160
}
146161

147162
// This is not the best way of doing things, but its the simplest. Given a
@@ -352,10 +367,6 @@ void FullLegalizer::place_clusters(const ClusteredNetlist& clb_nlist,
352367
bool placed = ap_cluster_placer.place_cluster(cluster_blk_id, tile_loc, blk_sub_tile);
353368
if (placed)
354369
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
359370

360371
// Add to list of unplaced clusters.
361372
unplaced_clusters.push_back(cluster_blk_id);

0 commit comments

Comments
 (0)