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) {