From 061413bc7a8849c904d11b0f66f8383a9205d9f9 Mon Sep 17 00:00:00 2001 From: AlexandreSinger Date: Mon, 14 Jul 2025 20:08:52 -0400 Subject: [PATCH] [Place] Added an Initial Placement Checkpoint I found that the annealer may sometimes pick a temperature so high that it destroys the quality of the initial placement. This behavior is most aparent with the AP flow, since its initial placement quality is much better than the default flow. Added a checkpoint at the start of the anneal that saves the initial placement and, after 20 iterations, if the quality of the current anneal is worse than the initial placement, it will restore that placement and continue at that temperature. --- vpr/src/place/place_checkpoint.cpp | 12 +++++++ vpr/src/place/place_checkpoint.h | 4 +++ vpr/src/place/placer.cpp | 52 ++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/vpr/src/place/place_checkpoint.cpp b/vpr/src/place/place_checkpoint.cpp index a6e2858e577..6fadec65f27 100644 --- a/vpr/src/place/place_checkpoint.cpp +++ b/vpr/src/place/place_checkpoint.cpp @@ -1,11 +1,13 @@ #include "place_checkpoint.h" +#include "net_cost_handler.h" #include "noc_place_utils.h" #include "placer_state.h" #include "grid_block.h" #include "PlacerCriticalities.h" #include "PlacerSetupSlacks.h" +#include "vpr_types.h" float t_placement_checkpoint::get_cp_cpd() const { return cpd_; } @@ -49,6 +51,9 @@ void restore_best_placement(PlacerState& placer_state, std::shared_ptr& place_delay_model, std::unique_ptr& pin_timing_invalidator, PlaceCritParams crit_params, + NetCostHandler& net_cost_handler, + const t_placer_opts& placer_opts, + const t_noc_opts& noc_opts, std::optional& noc_cost_handler) { /* The (valid) checkpoint is restored if the following conditions are met: * 1) The checkpoint has a lower critical path delay. @@ -73,6 +78,13 @@ void restore_best_placement(PlacerState& placer_state, &costs, placer_state); + // Recompute the wirelength cost terms from scratch. + costs.bb_cost = net_cost_handler.comp_bb_cost(e_cost_methods::NORMAL).first; + + // Update the normalization factors and recompute the total cost. + costs.update_norm_factors(); + costs.cost = costs.get_total_cost(placer_opts, noc_opts); + /* If NoC is enabled, re-compute NoC costs and re-initialize NoC internal data structures. * If some routers have different locations than the last placement, NoC-related costs and * internal data structures that are used to keep track of each flow's cost are no longer valid, diff --git a/vpr/src/place/place_checkpoint.h b/vpr/src/place/place_checkpoint.h index b0933f9aee5..6b9939e338e 100644 --- a/vpr/src/place/place_checkpoint.h +++ b/vpr/src/place/place_checkpoint.h @@ -8,6 +8,7 @@ #include "place_delay_model.h" #include "place_timing_update.h" +class NetCostHandler; class NocCostHandler; /** @@ -74,4 +75,7 @@ void restore_best_placement(PlacerState& placer_state, std::shared_ptr& place_delay_model, std::unique_ptr& pin_timing_invalidator, PlaceCritParams crit_params, + NetCostHandler& net_cost_handler, + const t_placer_opts& placer_opts, + const t_noc_opts& noc_opts, std::optional& noc_cost_handler); diff --git a/vpr/src/place/placer.cpp b/vpr/src/place/placer.cpp index c2980ce9842..54f3def933e 100644 --- a/vpr/src/place/placer.cpp +++ b/vpr/src/place/placer.cpp @@ -286,6 +286,19 @@ void Placer::place() { // Table header log_printer_.print_place_status_header(); + // Save a checkpoint of the initial placement. This may be restored + // during the anneal (or rarely at the end of anneal) if it is found to + // have a better quality than the current placement solution. + bool checkpoint_is_initial_placement = false; + if (placer_opts_.place_algorithm.is_timing_driven()) { + critical_path_ = timing_info_->least_slack_critical_path(); + save_placement_checkpoint_if_needed(placer_state_.mutable_block_locs(), + placement_checkpoint_, + timing_info_, costs_, critical_path_.delay()); + checkpoint_is_initial_placement = true; + } + + unsigned num_outer_loop_iterations = 0; // Outer loop of the simulated annealing begins do { vtr::Timer temperature_timer; @@ -295,11 +308,33 @@ void Placer::place() { if (placer_opts_.place_algorithm.is_timing_driven()) { critical_path_ = timing_info_->least_slack_critical_path(); - // see if we should save the current placement solution as a checkpoint - if (placer_opts_.place_checkpointing && annealer_->get_agent_state() == e_agent_state::LATE_IN_THE_ANNEAL) { - save_placement_checkpoint_if_needed(placer_state_.mutable_block_locs(), - placement_checkpoint_, - timing_info_, costs_, critical_path_.delay()); + // If place checkpointing is on, depending on the current state + // of the anneal, we should see if we should save the current + // placement solution as a checkpoint or restore it. + if (placer_opts_.place_checkpointing) { + if (checkpoint_is_initial_placement && num_outer_loop_iterations == 20) { + // If the checkpoint currently saved is the intial placement, + // after 20 iterations of the outer loop, if the quality is + // worse we should restore to that initial placement solution. + const t_annealing_state& annealing_state = annealer_->get_annealing_state(); + PlaceCritParams crit_params; + crit_params.crit_exponent = annealing_state.crit_exponent; + crit_params.crit_limit = placer_opts_.place_crit_limit; + restore_best_placement(placer_state_, + placement_checkpoint_, timing_info_, costs_, + placer_criticalities_, placer_setup_slacks_, place_delay_model_, + pin_timing_invalidator_, crit_params, + net_cost_handler_, + placer_opts_, noc_opts_, + noc_cost_handler_); + } else if (annealer_->get_agent_state() == e_agent_state::LATE_IN_THE_ANNEAL) { + // If we are late in the anneal, we should try and create a + // checkpoint if needed. + save_placement_checkpoint_if_needed(placer_state_.mutable_block_locs(), + placement_checkpoint_, + timing_info_, costs_, critical_path_.delay()); + checkpoint_is_initial_placement = false; + } } } @@ -308,6 +343,8 @@ void Placer::place() { log_printer_.print_place_status(temperature_timer.elapsed_sec()); + num_outer_loop_iterations++; + // Outer loop of the simulated annealing ends } while (annealer_->outer_loop_update_state()); } // skip_anneal ends @@ -355,7 +392,10 @@ void Placer::place() { restore_best_placement(placer_state_, placement_checkpoint_, timing_info_, costs_, placer_criticalities_, placer_setup_slacks_, place_delay_model_, - pin_timing_invalidator_, crit_params, noc_cost_handler_); + pin_timing_invalidator_, crit_params, + net_cost_handler_, + placer_opts_, noc_opts_, + noc_cost_handler_); } if (placer_opts_.placement_saves_per_temperature >= 1) {