Skip to content

Commit 499b266

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 5a062ba commit 499b266

File tree

9 files changed

+2133
-23
lines changed

9 files changed

+2133
-23
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"
@@ -33,6 +35,7 @@
3335
#include "vpr_error.h"
3436
#include "vpr_types.h"
3537
#include "vtr_assert.h"
38+
#include "vtr_geometry.h"
3639
#include "vtr_ndmatrix.h"
3740
#include "vtr_strong_id.h"
3841
#include "vtr_time.h"
@@ -126,9 +129,8 @@ class APClusterPlacer {
126129
const t_physical_tile_loc& tile_loc,
127130
int sub_tile) {
128131
const DeviceContext& device_ctx = g_vpr_ctx.device();
129-
// FIXME: THIS MUST TAKE INTO ACCOUNT THE CONSTRAINTS AS WELL!!!
130-
// - Right now it is just implied.
131-
// - Will work but is unstable.
132+
const FloorplanningContext& floorplanning_ctx = g_vpr_ctx.floorplanning();
133+
const ClusteringContext& cluster_ctx = g_vpr_ctx.clustering();
132134
const auto& block_locs = g_vpr_ctx.placement().block_locs();
133135
auto& blk_loc_registry = g_vpr_ctx.mutable_placement().mutable_blk_loc_registry();
134136
VTR_ASSERT(!is_block_placed(clb_blk_id, block_locs) && "Block already placed. Is this intentional?");
@@ -141,11 +143,24 @@ class APClusterPlacer {
141143
if (device_ctx.grid.get_physical_type(tile_loc)->sub_tiles.size() == 0)
142144
return false;
143145
VTR_ASSERT(sub_tile >= 0 && sub_tile < device_ctx.grid.get_physical_type(tile_loc)->capacity);
144-
// FIXME: Do this better.
145-
// - May need to try all the sub-tiles in a location.
146-
// - https://github.com/AlexandreSinger/vtr-verilog-to-routing/blob/feature-analytical-placer/vpr/src/place/initial_placement.cpp#L755
147-
to_loc.sub_tile = sub_tile;
148-
return try_place_macro(pl_macro, to_loc, blk_loc_registry);
146+
// Check if this cluster is constrained and this location is legal.
147+
if (is_cluster_constrained(clb_blk_id)) {
148+
const auto& cluster_constraints = floorplanning_ctx.cluster_constraints;
149+
if (cluster_constraints[clb_blk_id].is_loc_in_part_reg(to_loc))
150+
return false;
151+
}
152+
// If the location is legal, try to exhaustively place it at this tile
153+
// location. This should try all sub_tiles.
154+
PartitionRegion pr;
155+
vtr::Rect<int> rect(tile_loc.x, tile_loc.y, tile_loc.x, tile_loc.y);
156+
pr.add_to_part_region(Region(rect, to_loc.layer));
157+
const ClusteredNetlist& clb_nlist = cluster_ctx.clb_nlist;
158+
t_logical_block_type_ptr block_type = clb_nlist.block_type(clb_blk_id);
159+
enum e_pad_loc_type pad_loc_type = g_vpr_ctx.device().pad_loc_type;
160+
// FIXME: This currently ignores the sub_tile. Was running into issues
161+
// with trying to force clusters to specific sub_tiles.
162+
return try_place_macro_exhaustively(pl_macro, pr, block_type,
163+
pad_loc_type, blk_loc_registry);
149164
}
150165

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

364375
// Add to list of unplaced clusters.
365376
unplaced_clusters.push_back(cluster_blk_id);

0 commit comments

Comments
 (0)