diff --git a/src/gpl/README.md b/src/gpl/README.md index 327ca9506a4..faf3ebcf9c5 100644 --- a/src/gpl/README.md +++ b/src/gpl/README.md @@ -97,6 +97,7 @@ global_placement [-timing_driven_net_weight_max] [-timing_driven_nets_percentage] [-keep_resize_below_overflow] + [-disable_revert_if_diverge] ``` #### Options @@ -119,6 +120,7 @@ global_placement | `-pad_left` | Set left padding in terms of number of sites. The default value is 0, and the allowed values are integers `[1, MAX_INT]` | | `-pad_right` | Set right padding in terms of number of sites. The default value is 0, and the allowed values are integers `[1, MAX_INT]` | | `-skip_io` | Flag to ignore the IO ports when computing wirelength during placement. The default value is False, allowed values are boolean. | +| `-disable_revert_if_diverge` | Flag to make gpl store the placement state along iterations, if a divergence is detected, gpl reverts to the snapshot state. The default value is disabled. | #### Routability-Driven Arguments diff --git a/src/gpl/include/gpl/Replace.h b/src/gpl/include/gpl/Replace.h index 29ab0e9c148..ef966ca2446 100644 --- a/src/gpl/include/gpl/Replace.h +++ b/src/gpl/include/gpl/Replace.h @@ -119,18 +119,16 @@ class Replace void setTimingDrivenMode(bool mode); void setSkipIoMode(bool mode); + void setDisableRevertIfDiverge(bool mode); void setRoutabilityDrivenMode(bool mode); void setRoutabilityUseGrt(bool mode); void setRoutabilityCheckOverflow(float overflow); void setRoutabilityMaxDensity(float density); - void setRoutabilityMaxInflationIter(int iter); - void setRoutabilityTargetRcMetric(float rc); void setRoutabilityInflationRatioCoef(float coef); void setRoutabilityMaxInflationRatio(float ratio); - void setRoutabilityRcCoefficients(float k1, float k2, float k3, float k4); void addTimingNetWeightOverflow(int overflow); @@ -204,6 +202,7 @@ class Replace bool routabilityUseRudy_ = true; bool uniformTargetDensityMode_ = false; bool skipIoMode_ = false; + bool disableRevertIfDiverge_ = false; std::vector timingNetWeightOverflows_; diff --git a/src/gpl/src/nesterovBase.h b/src/gpl/src/nesterovBase.h index 6303ce1ea2c..4c85c0c1436 100644 --- a/src/gpl/src/nesterovBase.h +++ b/src/gpl/src/nesterovBase.h @@ -782,6 +782,7 @@ class NesterovPlaceVars bool timingDrivenMode = true; int timingDrivenIterCounter = 0; bool routabilityDrivenMode = true; + bool disableRevertIfDiverge = false; bool debug = false; int debug_pause_iterations = 10; diff --git a/src/gpl/src/nesterovPlace.cpp b/src/gpl/src/nesterovPlace.cpp index 83d11571b9a..d5e4ecd9d4f 100644 --- a/src/gpl/src/nesterovPlace.cpp +++ b/src/gpl/src/nesterovPlace.cpp @@ -318,14 +318,15 @@ int NesterovPlace::doNesterovPlace(int start_iter) graphics_->cellPlot(true); } - // snapshot saving detection - bool isSnapshotSaved = false; - - // snapshot info - float snapshotA = 0; - float snapshotWlCoefX = 0, snapshotWlCoefY = 0; + // routability snapshot info + bool is_routability_snapshot_saved = false; + float route_snapshotA = 0; + float route_snapshot_WlCoefX = 0, route_snapshot_WlCoefY = 0; bool isDivergeTriedRevert = false; + // divergence snapshot info + float diverge_snapshot_WlCoefX = 0, diverge_snapshot_WlCoefY = 0; + // backTracking variable. float curA = 1.0; @@ -342,7 +343,6 @@ int NesterovPlace::doNesterovPlace(int start_iter) // here, prevA is a_(k), curA is a_(k+1) // See, the ePlace-MS paper's Algorithm 1 - // curA = (1.0 + sqrt(4.0 * prevA * prevA + 1.0)) * 0.5; // coeff is (a_k - 1) / ( a_(k+1) ) in paper. @@ -412,9 +412,18 @@ int NesterovPlace::doNesterovPlace(int start_iter) updateNextIter(iter); + if (!npVars_.disableRevertIfDiverge) { + if (is_min_hpwl_) { + diverge_snapshot_WlCoefX = wireLengthCoefX_; + diverge_snapshot_WlCoefY = wireLengthCoefY_; + for (auto& nb : nbVec_) { + nb->snapshot(); + } + } + } + // For JPEG Saving // debug - const int debug_start_iter = npVars_.debug_start_iter; if (graphics_ && (debug_start_iter == 0 || iter + 1 >= debug_start_iter)) { bool update @@ -531,13 +540,10 @@ int NesterovPlace::doNesterovPlace(int start_iter) if (!isDivergeTriedRevert && rb_->numCall() >= 1) { // get back to the working rc size rb_->revertGCellSizeToMinRc(); - - curA = snapshotA; - wireLengthCoefX_ = snapshotWlCoefX; - wireLengthCoefY_ = snapshotWlCoefY; - + curA = route_snapshotA; + wireLengthCoefX_ = route_snapshot_WlCoefX; + wireLengthCoefY_ = route_snapshot_WlCoefY; nbc_->updateWireLengthForceWA(wireLengthCoefX_, wireLengthCoefY_); - for (auto& nb : nbVec_) { nb->revertDivergence(); } @@ -548,27 +554,46 @@ int NesterovPlace::doNesterovPlace(int start_iter) isDivergeTriedRevert = true; // turn off the RD forcely isRoutabilityNeed_ = false; + } else if (!npVars_.disableRevertIfDiverge) { + // In case diverged and not in routability mode, finish with min hpwl + // stored since overflow below 0.25 + log_->warn(GPL, + 90, + "Divergence detected, reverting to snapshot with min hpwl."); + log_->warn(GPL, + 91, + "Revert to iter: {:4d} overflow: {:.3f} HPWL: {}", + diverge_snapshot_iter_, + diverge_snapshot_average_overflow_unscaled_, + min_hpwl_); + wireLengthCoefX_ = diverge_snapshot_WlCoefX; + wireLengthCoefY_ = diverge_snapshot_WlCoefY; + nbc_->updateWireLengthForceWA(wireLengthCoefX_, wireLengthCoefY_); + for (auto& nb : nbVec_) { + nb->revertDivergence(); + } + isDiverged_ = false; + break; } else { - // no way to revert break; } } - if (!isSnapshotSaved && npVars_.routabilityDrivenMode + if (!is_routability_snapshot_saved && npVars_.routabilityDrivenMode && 0.6 >= average_overflow_unscaled_) { - snapshotWlCoefX = wireLengthCoefX_; - snapshotWlCoefY = wireLengthCoefY_; - snapshotA = curA; - isSnapshotSaved = true; + route_snapshot_WlCoefX = wireLengthCoefX_; + route_snapshot_WlCoefY = wireLengthCoefY_; + route_snapshotA = curA; + is_routability_snapshot_saved = true; for (auto& nb : nbVec_) { nb->snapshot(); } - log_->report("[NesterovSolve] Snapshot saved at iter = {}", iter); + log_->info(GPL, 88, "Routability snapshot saved at iter = {}", iter); } - // check routability using GR + // check routability using RUDY or GR if (npVars_.routabilityDrivenMode && isRoutabilityNeed_ && npVars_.routabilityCheckOverflow >= average_overflow_unscaled_) { // recover the densityPenalty values @@ -582,9 +607,9 @@ int NesterovPlace::doNesterovPlace(int start_iter) // cutFillerCoordinates(); // revert back the current density penality - curA = snapshotA; - wireLengthCoefX_ = snapshotWlCoefX; - wireLengthCoefY_ = snapshotWlCoefY; + curA = route_snapshotA; + wireLengthCoefX_ = route_snapshot_WlCoefX; + wireLengthCoefY_ = route_snapshot_WlCoefY; nbc_->updateWireLengthForceWA(wireLengthCoefX_, wireLengthCoefY_); @@ -592,7 +617,7 @@ int NesterovPlace::doNesterovPlace(int start_iter) nb->revertDivergence(); nb->resetMinSumOverflow(); } - log_->report("[NesterovSolve] Revert back to snapshot coordi"); + log_->info(GPL, 89, "Routability: revert back to snapshot"); } } @@ -658,6 +683,19 @@ void NesterovPlace::updateNextIter(const int iter) // For coefficient, using average regions' overflow updateWireLengthCoef(average_overflow_); + + // Update divergence snapshot + if (!npVars_.disableRevertIfDiverge) { + int64_t hpwl = nbc_->getHpwl(); + if (hpwl < min_hpwl_ && average_overflow_unscaled_ <= 0.25) { + min_hpwl_ = hpwl; + diverge_snapshot_average_overflow_unscaled_ = average_overflow_unscaled_; + diverge_snapshot_iter_ = iter; + is_min_hpwl_ = true; + } else { + is_min_hpwl_ = false; + } + } } void NesterovPlace::updateDb() diff --git a/src/gpl/src/nesterovPlace.h b/src/gpl/src/nesterovPlace.h index cdb08fa3ca5..32f58fcfdcc 100644 --- a/src/gpl/src/nesterovPlace.h +++ b/src/gpl/src/nesterovPlace.h @@ -115,9 +115,16 @@ class NesterovPlace float total_sum_overflow_ = 0; float total_sum_overflow_unscaled_ = 0; + // The average here is between regions (NB objects) float average_overflow_ = 0; float average_overflow_unscaled_ = 0; + // Snapshot saving for revert if diverge + float diverge_snapshot_average_overflow_unscaled_ = 0; + int64_t min_hpwl_ = INT64_MAX; + int diverge_snapshot_iter_ = 0; + bool is_min_hpwl_ = false; + // densityPenalty stor std::vector densityPenaltyStor_; diff --git a/src/gpl/src/replace.cpp b/src/gpl/src/replace.cpp index 605289a874c..12f7d36a578 100644 --- a/src/gpl/src/replace.cpp +++ b/src/gpl/src/replace.cpp @@ -118,6 +118,7 @@ void Replace::reset() routabilityUseRudy_ = true; uniformTargetDensityMode_ = false; skipIoMode_ = false; + disableRevertIfDiverge_ = false; padLeft_ = padRight_ = 0; @@ -354,6 +355,7 @@ bool Replace::initNesterovPlace(int threads) npVars.debug_draw_bins = gui_debug_draw_bins_; npVars.debug_inst = gui_debug_inst_; npVars.debug_start_iter = gui_debug_start_iter_; + npVars.disableRevertIfDiverge = disableRevertIfDiverge_; for (const auto& nb : nbVec_) { nb->setNpVars(&npVars); @@ -375,7 +377,20 @@ int Replace::doNesterovPlace(int threads, int start_iter) if (timingDrivenMode_) { rs_->resizeSlackPreamble(); } - return np_->doNesterovPlace(start_iter); + + auto start = std::chrono::high_resolution_clock::now(); + + int return_do_nesterov = np_->doNesterovPlace(start_iter); + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = end - start; + debugPrint(log_, + GPL, + "runtime", + 1, + "NP->doNesterovPlace() runtime: {} seconds ", + elapsed.count()); + return return_do_nesterov; } void Replace::setInitialPlaceMaxIter(int iter) @@ -485,6 +500,11 @@ void Replace::setDebug(int pause_iterations, gui_debug_start_iter_ = start_iter; } +void Replace::setDisableRevertIfDiverge(bool mode) +{ + disableRevertIfDiverge_ = mode; +} + void Replace::setSkipIoMode(bool mode) { skipIoMode_ = mode; diff --git a/src/gpl/src/replace.i b/src/gpl/src/replace.i index c3b794d55fe..14cc9282d94 100644 --- a/src/gpl/src/replace.i +++ b/src/gpl/src/replace.i @@ -250,6 +250,13 @@ set_skip_io_mode_cmd(bool mode) replace->setSkipIoMode(mode); } +void +set_disable_revert_if_diverge(bool disable_revert_if_diverge) +{ + Replace* replace = getReplace(); + replace->setDisableRevertIfDiverge(disable_revert_if_diverge); +} + float get_global_placement_uniform_density_cmd() { diff --git a/src/gpl/src/replace.tcl b/src/gpl/src/replace.tcl index 26978859d26..6faab122ff1 100644 --- a/src/gpl/src/replace.tcl +++ b/src/gpl/src/replace.tcl @@ -64,6 +64,7 @@ sta::define_cmd_args "global_placement" {\ [-timing_driven_nets_percentage timing_driven_nets_percentage]\ [-pad_left pad_left]\ [-pad_right pad_right]\ + [-disable_revert_if_diverge]\ } proc global_placement { args } { @@ -92,7 +93,8 @@ proc global_placement { args } { -disable_timing_driven \ -disable_routability_driven \ -skip_io \ - -incremental} + -incremental\ + -disable_revert_if_diverge} # flow control for initial_place if { [info exists flags(-skip_initial_place)] } { @@ -176,6 +178,14 @@ proc global_placement { args } { } } + # Disable revert to saved snapshot if a divergence is detected. + set disable_revert_if_diverge [info exists flags(-disable_revert_if_diverge)] + gpl::set_disable_revert_if_diverge $disable_revert_if_diverge + if { $disable_revert_if_diverge } { + utl::info "GPL" 153 \ + "Revert-to-snapshot on divergence detection is disabled." + } + if { [info exists keys(-initial_place_max_fanout)] } { set initial_place_max_fanout $keys(-initial_place_max_fanout) sta::check_positive_integer "-initial_place_max_fanout" $initial_place_max_fanout diff --git a/src/gpl/test/simple01-rd.ok b/src/gpl/test/simple01-rd.ok index e7f3712dc25..c276c435de3 100644 --- a/src/gpl/test/simple01-rd.ok +++ b/src/gpl/test/simple01-rd.ok @@ -59,7 +59,7 @@ [NesterovSolve] Iter: 190 overflow: 0.683 HPWL: 4375212 [NesterovSolve] Iter: 200 overflow: 0.661 HPWL: 4447293 [NesterovSolve] Iter: 210 overflow: 0.625 HPWL: 4516566 -[NesterovSolve] Snapshot saved at iter = 216 +[INFO GPL-0088] Routability snapshot saved at iter = 216 [NesterovSolve] Iter: 220 overflow: 0.586 HPWL: 4589913 [NesterovSolve] Iter: 230 overflow: 0.547 HPWL: 4672006 [NesterovSolve] Iter: 240 overflow: 0.494 HPWL: 4711101 diff --git a/src/gpl/test/simple02-rd.ok b/src/gpl/test/simple02-rd.ok index 826a2e2a52a..002df826118 100644 --- a/src/gpl/test/simple02-rd.ok +++ b/src/gpl/test/simple02-rd.ok @@ -59,7 +59,7 @@ [NesterovSolve] Iter: 190 overflow: 0.683 HPWL: 4375212 [NesterovSolve] Iter: 200 overflow: 0.661 HPWL: 4447293 [NesterovSolve] Iter: 210 overflow: 0.625 HPWL: 4516566 -[NesterovSolve] Snapshot saved at iter = 216 +[INFO GPL-0088] Routability snapshot saved at iter = 216 [NesterovSolve] Iter: 220 overflow: 0.586 HPWL: 4589913 [NesterovSolve] Iter: 230 overflow: 0.547 HPWL: 4672006 [NesterovSolve] Iter: 240 overflow: 0.494 HPWL: 4711101 diff --git a/src/gpl/test/simple03-rd.ok b/src/gpl/test/simple03-rd.ok index 3b4d7d675be..175b50d3732 100644 --- a/src/gpl/test/simple03-rd.ok +++ b/src/gpl/test/simple03-rd.ok @@ -58,7 +58,7 @@ [NesterovSolve] Iter: 190 overflow: 0.683 HPWL: 4375212 [NesterovSolve] Iter: 200 overflow: 0.661 HPWL: 4447293 [NesterovSolve] Iter: 210 overflow: 0.625 HPWL: 4516566 -[NesterovSolve] Snapshot saved at iter = 216 +[INFO GPL-0088] Routability snapshot saved at iter = 216 [NesterovSolve] Iter: 220 overflow: 0.586 HPWL: 4589913 [NesterovSolve] Iter: 230 overflow: 0.547 HPWL: 4672006 [NesterovSolve] Iter: 240 overflow: 0.494 HPWL: 4711101 diff --git a/src/gpl/test/simple04-rd.ok b/src/gpl/test/simple04-rd.ok index 628ba6c2cff..1f777ae2f5c 100644 --- a/src/gpl/test/simple04-rd.ok +++ b/src/gpl/test/simple04-rd.ok @@ -58,7 +58,7 @@ [NesterovSolve] Iter: 190 overflow: 0.683 HPWL: 4375212 [NesterovSolve] Iter: 200 overflow: 0.661 HPWL: 4447293 [NesterovSolve] Iter: 210 overflow: 0.625 HPWL: 4516566 -[NesterovSolve] Snapshot saved at iter = 216 +[INFO GPL-0088] Routability snapshot saved at iter = 216 [NesterovSolve] Iter: 220 overflow: 0.586 HPWL: 4589913 [NesterovSolve] Iter: 230 overflow: 0.547 HPWL: 4672006 [NesterovSolve] Iter: 240 overflow: 0.494 HPWL: 4711101