diff --git a/src/gpl/src/nesterovBase.cpp b/src/gpl/src/nesterovBase.cpp index 3ddd7b4ee60..a22ab8dab54 100644 --- a/src/gpl/src/nesterovBase.cpp +++ b/src/gpl/src/nesterovBase.cpp @@ -3680,10 +3680,12 @@ void NesterovBase::initDensity1() initCoordi_.resize(gCellSize, FloatPoint()); - snapshotCoordi_.resize(gCellSize, FloatPoint()); - snapshotSLPCoordi_.resize(gCellSize, FloatPoint()); - snapshotSLPSumGrads_.resize(gCellSize, FloatPoint()); - snapshotPrevSLPSumGrads_.resize(gCellSize, FloatPoint()); + for (Snapshot& snap : snapshots_) { + snap.coordi.resize(gCellSize, FloatPoint()); + snap.slpCoordi.resize(gCellSize, FloatPoint()); + snap.slpSumGrads.resize(gCellSize, FloatPoint()); + snap.prevSLPSumGrads.resize(gCellSize, FloatPoint()); + } #pragma omp parallel for num_threads(nbc_->getNumThreads()) for (auto it = nb_gcells_.begin(); it < nb_gcells_.end(); ++it) { @@ -4495,7 +4497,7 @@ void NesterovBase::nesterovAdjustPhi() } } -void NesterovBase::saveSnapshot() +void NesterovBase::saveSnapshot(SnapshotSlot slot) { if (isConverged_) { return; @@ -4514,13 +4516,13 @@ void NesterovBase::saveSnapshot() } #endif - // save snapshots for routability-driven - snapshotCoordi_ = curCoordi_; - snapshotSLPCoordi_ = curSLPCoordi_; - snapshotSLPSumGrads_ = curSLPSumGrads_; - snapshotPrevSLPSumGrads_ = prevSLPSumGrads_; - snapshotDensityPenalty_ = densityPenalty_; - snapshotStepLength_ = stepLength_; + Snapshot& snap = snapshot(slot); + snap.coordi = curCoordi_; + snap.slpCoordi = curSLPCoordi_; + snap.slpSumGrads = curSLPSumGrads_; + snap.prevSLPSumGrads = prevSLPSumGrads_; + snap.densityPenalty = densityPenalty_; + snap.stepLength = stepLength_; } bool NesterovBase::checkConvergence(int gpl_iter_count, @@ -4658,6 +4660,14 @@ bool NesterovBase::isSettled() const return coordiDistance_ <= kSettleFraction * peak_coordi_distance_; } +float NesterovBase::getSettleRatio() const +{ + if (peak_coordi_distance_ <= 0) { + return 1.0f; + } + return coordiDistance_ / peak_coordi_distance_; +} + bool NesterovBase::checkDivergence() { if (sum_overflow_unscaled_ < 0.2f @@ -4699,7 +4709,7 @@ bool NesterovBase::checkDivergence() return isDiverged_; } -bool NesterovBase::revertToSnapshot() +bool NesterovBase::revertToSnapshot(SnapshotSlot slot) { if (isConverged_) { return true; @@ -4709,12 +4719,13 @@ bool NesterovBase::revertToSnapshot() // device-resident pipeline the host copies are stale — refresh first. pullCoordsFromDevice(); // revert back the current density penality - curCoordi_ = snapshotCoordi_; - curSLPCoordi_ = snapshotSLPCoordi_; - curSLPSumGrads_ = snapshotSLPSumGrads_; - prevSLPSumGrads_ = snapshotPrevSLPSumGrads_; - densityPenalty_ = snapshotDensityPenalty_; - stepLength_ = snapshotStepLength_; + const Snapshot& snap = snapshot(slot); + curCoordi_ = snap.coordi; + curSLPCoordi_ = snap.slpCoordi; + curSLPSumGrads_ = snap.slpSumGrads; + prevSLPSumGrads_ = snap.prevSLPSumGrads; + densityPenalty_ = snap.densityPenalty; + stepLength_ = snap.stepLength; updateGCellDensityCenterLocation(curCoordi_); updateDensityFieldBin(); @@ -5130,6 +5141,15 @@ void NesterovBase::cutFillerCells(int64_t inflation_area) --i) { if (nb_gcells_[i]->isFiller()) { const GCell& removed = fillerStor_[nb_gcells_[i].getStorageIndex()]; + std::array snapshot_points; + for (size_t s = 0; s < kNumSnapshotSlots; ++s) { + const Snapshot& snap = snapshots_[s]; + snapshot_points[s] + = SnapshotPoint{.coordi = snap.coordi[i], + .slpCoordi = snap.slpCoordi[i], + .slpSumGrads = snap.slpSumGrads[i], + .prevSLPSumGrads = snap.prevSLPSumGrads[i]}; + } removed_fillers_.push_back(RemovedFillerState{ .gcell = removed, .curSLPCoordi = curSLPCoordi_[i], @@ -5151,10 +5171,7 @@ void NesterovBase::cutFillerCells(int64_t inflation_area) .nextCoordi = nextCoordi_[i], .initCoordi = initCoordi_[i], - .snapshotCoordi = snapshotCoordi_[i], - .snapshotSLPCoordi = snapshotSLPCoordi_[i], - .snapshotSLPSumGrads = snapshotSLPSumGrads_[i], - .snapshotPrevSLPSumGrads = snapshotPrevSLPSumGrads_[i]}); + .snapshots = snapshot_points}); destroyFillerGCell(i); availableFillerArea -= single_filler_area; @@ -5174,8 +5191,10 @@ void NesterovBase::cutFillerCells(int64_t inflation_area) block->dbuAreaToMicrons(totalFillerArea_)); } - log_->info(GPL, - 76, + debugPrint(log_, + GPL, + "routability", + 1, "Removing fillers, count: Before: {}, After: {} ({:+.2f}%)", num_filler_before_removal, fillerStor_.size(), @@ -5186,9 +5205,11 @@ void NesterovBase::cutFillerCells(int64_t inflation_area) / num_filler_before_removal * 100.0) : 0.0); - log_->info( + debugPrint( + log_, GPL, - 77, + "routability", + 1, "Filler area (um^2) : Before: {:.3f}, After: {:.3f} ({:+.2f}%)", block->dbuAreaToMicrons(filler_area_before_removal), block->dbuAreaToMicrons(totalFillerArea_), @@ -5200,8 +5221,10 @@ void NesterovBase::cutFillerCells(int64_t inflation_area) int64_t removedFillerArea = single_filler_area * removed_count; int64_t remainingInflationArea = originalInflationArea - removedFillerArea; - log_->info(GPL, - 78, + debugPrint(log_, + GPL, + "routability", + 1, "Removed fillers count: {}, area removed: {:.3f} um^2. Remaining " "area to be " "compensated by modifying density: {:.3f} um^2", @@ -5215,7 +5238,8 @@ void NesterovBase::cutFillerCells(int64_t inflation_area) setTargetDensity(static_cast(totalGCellArea) / static_cast(getWhiteSpaceArea())); movableArea_ = whiteSpaceArea_ * targetDensity_; - log_->info(GPL, 79, "New target density: {}", targetDensity_); + debugPrint( + log_, GPL, "routability", 1, "New target density: {}", targetDensity_); } // nb_gcells_ has shrunk; rebuild the GPU device context against the new @@ -5281,8 +5305,10 @@ void NesterovBase::destroyFillerGCell(size_t nb_index_remove) void NesterovBase::restoreRemovedFillers() { pullCoordsFromDevice(); - log_->info(GPL, - 80, + debugPrint(log_, + GPL, + "routability", + 1, "Restoring {} previously removed fillers.", removed_fillers_.size()); @@ -5322,10 +5348,14 @@ void NesterovBase::restoreRemovedFillers() nextCoordi_[idx] = filler.nextCoordi; initCoordi_[idx] = filler.initCoordi; - snapshotCoordi_[idx] = filler.snapshotCoordi; - snapshotSLPCoordi_[idx] = filler.snapshotSLPCoordi; - snapshotSLPSumGrads_[idx] = filler.snapshotSLPSumGrads; - snapshotPrevSLPSumGrads_[idx] = filler.snapshotPrevSLPSumGrads; + for (size_t s = 0; s < kNumSnapshotSlots; ++s) { + Snapshot& snap = snapshots_[s]; + const SnapshotPoint& point = filler.snapshots[s]; + snap.coordi[idx] = point.coordi; + snap.slpCoordi[idx] = point.slpCoordi; + snap.slpSumGrads[idx] = point.slpSumGrads; + snap.prevSLPSumGrads[idx] = point.prevSLPSumGrads; + } totalFillerArea_ += getFillerCellArea(); } @@ -5350,16 +5380,20 @@ void NesterovBase::restoreRemovedFillers() double area_before_um = block->dbuAreaToMicrons(area_before); double area_after_um = block->dbuAreaToMicrons(area_after); - log_->info(GPL, - 81, + debugPrint(log_, + GPL, + "routability", + 1, "Number of fillers before restoration {} and after {} . Relative " "change: {:+.2f}%%", num_fill_before, num_fill_after, rel_count_change); - log_->info(GPL, - 82, + debugPrint(log_, + GPL, + "routability", + 1, "Total filler area before restoration {:.2f} and after {:.2f} " "(um^2). Relative change: {:+.2f}%%", area_before_um, @@ -5481,11 +5515,13 @@ void NesterovBase::swapAndPopParallelVectors(size_t remove_index, last_index); // Avoid modifying this if snapshot has not been saved yet. - if (curSLPCoordi_.size() == snapshotCoordi_.size()) { - swapAndPop(snapshotCoordi_, remove_index, last_index); - swapAndPop(snapshotSLPCoordi_, remove_index, last_index); - swapAndPop(snapshotSLPSumGrads_, remove_index, last_index); - swapAndPop(snapshotPrevSLPSumGrads_, remove_index, last_index); + for (Snapshot& snap : snapshots_) { + if (curSLPCoordi_.size() == snap.coordi.size()) { + swapAndPop(snap.coordi, remove_index, last_index); + swapAndPop(snap.slpCoordi, remove_index, last_index); + swapAndPop(snap.slpSumGrads, remove_index, last_index); + swapAndPop(snap.prevSLPSumGrads, remove_index, last_index); + } } swapAndPop(curSLPCoordi_, remove_index, last_index); swapAndPop(curSLPWireLengthGrads_, remove_index, last_index); @@ -5552,11 +5588,13 @@ void NesterovBase::rebindHandleIndex(size_t nb_index) void NesterovBase::appendParallelVectors() { - if (curSLPCoordi_.size() == snapshotCoordi_.size()) { - snapshotCoordi_.emplace_back(); - snapshotSLPCoordi_.emplace_back(); - snapshotSLPSumGrads_.emplace_back(); - snapshotPrevSLPSumGrads_.emplace_back(); + for (Snapshot& snap : snapshots_) { + if (curSLPCoordi_.size() == snap.coordi.size()) { + snap.coordi.emplace_back(); + snap.slpCoordi.emplace_back(); + snap.slpSumGrads.emplace_back(); + snap.prevSLPSumGrads.emplace_back(); + } } curSLPCoordi_.emplace_back(); curSLPWireLengthGrads_.emplace_back(); @@ -5697,11 +5735,13 @@ void NesterovBase::writeGCellVectorsToCSV(const std::string& filename, add_value(nextCoordi_); add_value(initCoordi_); - if (snapshotCoordi_.size() == curSLPCoordi_.size()) { - add_value(snapshotCoordi_); - add_value(snapshotSLPCoordi_); - add_value(snapshotSLPSumGrads_); - add_value(snapshotPrevSLPSumGrads_); + for (const Snapshot& snap : snapshots_) { + if (snap.coordi.size() == curSLPCoordi_.size()) { + add_value(snap.coordi); + add_value(snap.slpCoordi); + add_value(snap.slpSumGrads); + add_value(snap.prevSLPSumGrads); + } } file << "\n"; diff --git a/src/gpl/src/nesterovBase.h b/src/gpl/src/nesterovBase.h index 927a79037b1..c4e63422411 100644 --- a/src/gpl/src/nesterovBase.h +++ b/src/gpl/src/nesterovBase.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include @@ -1251,6 +1252,9 @@ class NesterovBase // overflow can sit at very different displacements depending on how fast // the penalty schedule happens to be ramping. bool isSettled() const; + float getSettleRatio() const; + static constexpr float getSettleFraction() { return kSettleFraction; } + float getStoredGradDistance() const { return gradDistance_; } bool checkConvergence(int gpl_iter_count, @@ -1259,8 +1263,18 @@ class NesterovBase void resetConverged() { isConverged_ = false; } bool checkDivergence(); - void saveSnapshot(); - bool revertToSnapshot(); + + // Separate snapshot storage for routability and divergence recovery, since + // a divergence can happen in the middle of a routability pass. + enum class SnapshotSlot + { + Routability, + Diverge + }; + static constexpr size_t kNumSnapshotSlots = 2; + + void saveSnapshot(SnapshotSlot slot); + bool revertToSnapshot(SnapshotSlot slot); // GPU device-resident density path: the hot loop no longer syncs coords // (or host GCell density centers) every iteration. Cold-path consumers @@ -1388,6 +1402,16 @@ class NesterovBase // used to update gcell states after fixPointers() is called std::vector new_instances_; + // One gcell's worth of a Snapshot, saved when a filler is cut out so the + // stored placements survive a routability filler cut/restore round trip. + struct SnapshotPoint + { + FloatPoint coordi; + FloatPoint slpCoordi; + FloatPoint slpSumGrads; + FloatPoint prevSLPSumGrads; + }; + struct RemovedFillerState { GCell gcell; @@ -1406,10 +1430,8 @@ class NesterovBase FloatPoint curCoordi; FloatPoint nextCoordi; FloatPoint initCoordi; - FloatPoint snapshotCoordi; - FloatPoint snapshotSLPCoordi; - FloatPoint snapshotSLPSumGrads; - FloatPoint snapshotPrevSLPSumGrads; + // One entry per SnapshotSlot, in slot order. + std::array snapshots; }; std::vector removed_fillers_; @@ -1463,13 +1485,22 @@ class NesterovBase // save initial coordinates -- needed for RD std::vector initCoordi_; - // Snapshot data for routability, parallel vectors - std::vector snapshotCoordi_; - std::vector snapshotSLPCoordi_; - std::vector snapshotSLPSumGrads_; - std::vector snapshotPrevSLPSumGrads_; - float snapshotDensityPenalty_ = 0; - float snapshotStepLength_ = 0; + // Snapshot data, parallel vectors. One set per SnapshotSlot. + struct Snapshot + { + std::vector coordi; + std::vector slpCoordi; + std::vector slpSumGrads; + std::vector prevSLPSumGrads; + float densityPenalty = 0; + float stepLength = 0; + }; + std::array snapshots_; + + Snapshot& snapshot(SnapshotSlot slot) + { + return snapshots_[static_cast(slot)]; + } // For destroying elements in parallel vectors void swapAndPop(std::vector& vec, diff --git a/src/gpl/src/nesterovPlace.cpp b/src/gpl/src/nesterovPlace.cpp index 64ecb28b952..fe5ee7d09bf 100644 --- a/src/gpl/src/nesterovPlace.cpp +++ b/src/gpl/src/nesterovPlace.cpp @@ -264,7 +264,18 @@ void NesterovPlace::reset() wireLengthCoefX_ = wireLengthCoefY_ = 0; prevHpwl_ = 0; num_region_diverged_ = 0; + diverge_revert_count_ = 0; + routability_diverge_attempt_count_ = 0; + is_routability_snapshot_saved_ = false; + route_snapshot_a_ = 0; + route_snapshot_wl_coef_x_ = 0; + route_snapshot_wl_coef_y_ = 0; + is_diverge_snapshot_saved_ = false; + diverge_snapshot_wl_coef_x_ = 0; + diverge_snapshot_wl_coef_y_ = 0; + diverge_snapshot_hpwl_ = 0; is_routability_need_ = true; + routability_settle_wait_start_iter_ = -1; divergeMsg_ = ""; divergeCode_ = 0; @@ -583,9 +594,59 @@ void NesterovPlace::runTimingDriven(int iter, } } -bool NesterovPlace::isDiverged(float& diverge_snapshot_WlCoefX, - float& diverge_snapshot_WlCoefY, - bool& is_diverge_snapshot_saved) +bool NesterovPlace::tryRoutabilityDivergeRecovery(float& curA) +{ + if (!is_routability_snapshot_saved_ + || routability_diverge_attempt_count_ >= kMaxRoutabilityDivergeAttempts) { + return false; + } + + ++routability_diverge_attempt_count_; + const bool is_last_attempt + = routability_diverge_attempt_count_ == kMaxRoutabilityDivergeAttempts; + + // Before the first pass there is no minimum on record and the stored + // target density is still zero, so reverting to it would zero the density. + const bool has_inflation = rb_->getRevertCount() >= 1; + if (has_inflation) { + rb_->revertToMinCongestion(); + } + + if (is_last_attempt) { + is_routability_need_ = false; + } + + log_->warn( + GPL, + 112, + "Divergence detected, reverting to the routability snapshot " + "(attempt {} of {}): inflation {}, further inflation {}.", + routability_diverge_attempt_count_, + kMaxRoutabilityDivergeAttempts, + has_inflation ? "rolled back to minimum congestion" : "none applied yet", + is_last_attempt ? "disabled" : "still allowed"); + + wireLengthCoefX_ = route_snapshot_wl_coef_x_; + wireLengthCoefY_ = route_snapshot_wl_coef_y_; + nbc_->updateWireLengthForceWA(wireLengthCoefX_, wireLengthCoefY_); + + for (auto& nb : nbVec_) { + nb->revertToSnapshot(NesterovBase::SnapshotSlot::Routability); + nb->resetMinSumOverflow(); + } + + // Momentum reset due to divergence. + curA = 1.0; + routability_settle_wait_start_iter_ = -1; + if (has_inflation) { + min_hpwl_ = std::numeric_limits::max(); + is_min_hpwl_ = false; + } + + return true; +} + +bool NesterovPlace::isDiverged(float& curA) { // diverge detection on // large max_phi_cof value + large design @@ -598,67 +659,50 @@ bool NesterovPlace::isDiverged(float& diverge_snapshot_WlCoefX, num_region_diverged_ += nb->checkDivergence(); } - if (!npVars_.disableRevertIfDiverge && num_region_diverged_ == 0 - && (!npVars_.routability_driven_mode || !is_routability_need_)) { - if (is_min_hpwl_) { - diverge_snapshot_WlCoefX = wireLengthCoefX_; - diverge_snapshot_WlCoefY = wireLengthCoefY_; - for (auto& nb : nbVec_) { - nb->saveSnapshot(); - } - is_diverge_snapshot_saved = true; + if (num_region_diverged_ == 0 && is_min_hpwl_ + && !npVars_.disableRevertIfDiverge) { + diverge_snapshot_wl_coef_x_ = wireLengthCoefX_; + diverge_snapshot_wl_coef_y_ = wireLengthCoefY_; + diverge_snapshot_hpwl_ = min_hpwl_; + for (auto& nb : nbVec_) { + nb->saveSnapshot(NesterovBase::SnapshotSlot::Diverge); } + is_diverge_snapshot_saved_ = true; } if (num_region_diverged_ > 0) { log_->report("Divergence occured in {} regions.", num_region_diverged_); - // TODO: this divergence treatment uses the non-deterministic aspect of - // routability inflation to try one more time if a divergence is detected. - // This feature lost its consistency since we allow for non-virtual timing - // driven iterations. Meaning we would go back to a snapshot without newly - // added instances. A way to maintain this feature is to store two - // snapshots one for routability revert if diverge and try again, and - // another for simply revert if diverge and finish without hitting 0.10 - // overflow. - // // revert back to the original rb solutions - // // one more opportunity - // if (!isDivergeTriedRevert && rb_->getRevertCount() >= 1) { - // // get back to the working rc size - // rb_->revertGCellSizeToMinRc(); - // curA = route_snapshotA; - // wireLengthCoefX_ = route_snapshot_WlCoefX; - // wireLengthCoefY_ = route_snapshot_WlCoefY; - // nbc_->updateWireLengthForceWA(wireLengthCoefX_, wireLengthCoefY_); - // for (auto& nb : nbVec_) { - // nb->revertToSnapshot(); - // } - - // isDiverged_ = false; - // divergeCode_ = 0; - // divergeMsg_ = ""; - // isDivergeTriedRevert = true; - // // turn off the RD forcely - // is_routability_need_ = false; - // } else - if (!npVars_.disableRevertIfDiverge && is_diverge_snapshot_saved) { - // In case diverged and not in routability mode, finish with min hpwl - // stored since overflow below 0.25 + if (!npVars_.disableRevertIfDiverge + && tryRoutabilityDivergeRecovery(curA)) { + num_region_diverged_ = 0; + } else if (!npVars_.disableRevertIfDiverge && is_diverge_snapshot_saved_ + && diverge_revert_count_ < kMaxDivergeReverts) { + // Go back to the min hpwl placement stored since overflow below 0.25 and + // descend from there again. + ++diverge_revert_count_; log_->warn(GPL, 998, - "Divergence detected, reverting to snapshot with min hpwl."); + "Divergence detected, reverting to snapshot with min hpwl " + "and resuming ({} of {} reverts allowed).", + diverge_revert_count_, + kMaxDivergeReverts); log_->warn(GPL, 999, "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; + diverge_snapshot_hpwl_); + wireLengthCoefX_ = diverge_snapshot_wl_coef_x_; + wireLengthCoefY_ = diverge_snapshot_wl_coef_y_; nbc_->updateWireLengthForceWA(wireLengthCoefX_, wireLengthCoefY_); for (auto& nb : nbVec_) { - nb->revertToSnapshot(); + nb->revertToSnapshot(NesterovBase::SnapshotSlot::Diverge); + nb->resetMinSumOverflow(); } + // Reset momentum due to divergence. + curA = 1.0; + num_region_diverged_ = 0; } else { divergeMsg_ @@ -678,21 +722,17 @@ void NesterovPlace::routabilitySnapshot( float curA, const std::string& routability_driven_dir, int routability_driven_revert_count, - int timing_driven_count, - bool& is_routability_snapshot_saved, - float& route_snapshot_WlCoefX, - float& route_snapshot_WlCoefY, - float& route_snapshotA) + int timing_driven_count) { - if (!is_routability_snapshot_saved && npVars_.routability_driven_mode + if (!is_routability_snapshot_saved_ && npVars_.routability_driven_mode && npVars_.routability_snapshot_overflow >= average_overflow_unscaled_) { - route_snapshot_WlCoefX = wireLengthCoefX_; - route_snapshot_WlCoefY = wireLengthCoefY_; - route_snapshotA = curA; - is_routability_snapshot_saved = true; + route_snapshot_wl_coef_x_ = wireLengthCoefX_; + route_snapshot_wl_coef_y_ = wireLengthCoefY_; + route_snapshot_a_ = curA; + is_routability_snapshot_saved_ = true; for (auto& nb : nbVec_) { - nb->saveSnapshot(); + nb->saveSnapshot(NesterovBase::SnapshotSlot::Routability); } log_->info(GPL, 38, "Routability snapshot saved at iter = {}", iter + 1); @@ -726,9 +766,6 @@ void NesterovPlace::routabilitySnapshot( void NesterovPlace::runRoutability(int iter, int timing_driven_count, const std::string& routability_driven_dir, - const float route_snapshotA, - const float route_snapshot_WlCoefX, - const float route_snapshot_WlCoefY, int& routability_driven_revert_count, float& curA) { @@ -745,9 +782,41 @@ void NesterovPlace::runRoutability(int iter, // // This can only ever delay the trigger, so a design already settled at its // overflow gate is unaffected. - if (npVars_.routability_driven_mode && is_routability_need_ - && average_overflow_unscaled_ <= npVars_.routability_end_overflow - && isPlacementSettled()) { + const bool is_routability_active + = npVars_.routability_driven_mode && is_routability_need_ + && average_overflow_unscaled_ <= npVars_.routability_end_overflow; + const bool is_routability_settled + = is_routability_active && isPlacementSettled(); + + if (is_routability_active && !is_routability_settled + && routability_settle_wait_start_iter_ == -1) { + routability_settle_wait_start_iter_ = iter; + log_->info(GPL, + 99, + "Routability end extended at iter = {}: overflow {:.4f} " + "reached {:.4f}, but cells are still moving at {:.0f}% of " + "peak displacement (waiting for {:.0f}%).", + iter + 1, + average_overflow_unscaled_, + npVars_.routability_end_overflow, + getWorstSettleRatio() * 100.0f, + NesterovBase::getSettleFraction() * 100.0f); + } + + if (is_routability_settled) { + if (routability_settle_wait_start_iter_ != -1) { + log_->info(GPL, + 103, + "Routability end extension finished at iter = {} after {} " + "extra iterations: overflow {:.4f}, cells moving at {:.0f}% " + "of peak displacement.", + iter + 1, + iter - routability_settle_wait_start_iter_, + average_overflow_unscaled_, + getWorstSettleRatio() * 100.0f); + routability_settle_wait_start_iter_ = -1; + } + getTopLevelNB()->setTrueReprintIterHeader(); ++routability_driven_revert_count; @@ -814,6 +883,8 @@ void NesterovPlace::runRoutability(int iter, // GPL-0307. Start the search for a minimum over on the new design. min_hpwl_ = std::numeric_limits::max(); is_min_hpwl_ = false; + // The snapshot it produced is kept: no new one can be taken until + // overflow drops back under 0.25, and a divergence before then needs it. if (graphics_ && graphics_->enabled()) { graphics_->addRoutabilityIter(iter, isRevertInitNeeded); @@ -822,14 +893,14 @@ void NesterovPlace::runRoutability(int iter, // if routability is needed if (is_routability_need_ || isRevertInitNeeded) { // revert back the current density penality - curA = route_snapshotA; - wireLengthCoefX_ = route_snapshot_WlCoefX; - wireLengthCoefY_ = route_snapshot_WlCoefY; + curA = route_snapshot_a_; + wireLengthCoefX_ = route_snapshot_wl_coef_x_; + wireLengthCoefY_ = route_snapshot_wl_coef_y_; nbc_->updateWireLengthForceWA(wireLengthCoefX_, wireLengthCoefY_); for (auto& nb : nbVec_) { - nb->revertToSnapshot(); + nb->revertToSnapshot(NesterovBase::SnapshotSlot::Routability); nb->resetMinSumOverflow(); } } @@ -877,6 +948,15 @@ bool NesterovPlace::isPlacementSettled() const return true; } +float NesterovPlace::getWorstSettleRatio() const +{ + float worst = 0; + for (const auto& nb : nbVec_) { + worst = std::max(worst, nb->getSettleRatio()); + } + return worst; +} + bool NesterovPlace::isConverged(int gpl_iter_count, int routability_gpl_iter_count) { @@ -900,7 +980,7 @@ bool NesterovPlace::isConverged(int gpl_iter_count, NesterovBase* NesterovPlace::getTopLevelNB() const { if (nbVec_.empty()) { - log_->error(GPL, 103, "Top-level NesterovBase is not initialized."); + log_->error(GPL, 111, "Top-level NesterovBase is not initialized."); } return nbVec_[0].get(); } @@ -1083,15 +1163,18 @@ int NesterovPlace::doNesterovPlace(int start_iter) } // routability snapshot info - bool is_routability_snapshot_saved = false; - float route_snapshotA = 0; - float route_snapshot_WlCoefX = 0; - float route_snapshot_WlCoefY = 0; + is_routability_snapshot_saved_ = false; + route_snapshot_a_ = 0; + route_snapshot_wl_coef_x_ = 0; + route_snapshot_wl_coef_y_ = 0; + routability_diverge_attempt_count_ = 0; // divergence snapshot info - bool is_diverge_snapshot_saved = false; - float diverge_snapshot_WlCoefX = 0; - float diverge_snapshot_WlCoefY = 0; + is_diverge_snapshot_saved_ = false; + diverge_snapshot_wl_coef_x_ = 0; + diverge_snapshot_wl_coef_y_ = 0; + diverge_snapshot_hpwl_ = 0; + diverge_revert_count_ = 0; // backTracking variable. float curA = 1.0; @@ -1174,7 +1257,7 @@ int NesterovPlace::doNesterovPlace(int start_iter) final_routability_image_saved); bool is_routability_gpl_iter - = is_routability_snapshot_saved + = is_routability_snapshot_saved_ && average_overflow_unscaled_ > npVars_.routability_end_overflow; if (is_routability_gpl_iter) { ++routability_gpl_iter_count_; @@ -1189,28 +1272,23 @@ int NesterovPlace::doNesterovPlace(int start_iter) is_routability_gpl_iter, virtual_cts_count); - if (isDiverged(diverge_snapshot_WlCoefX, - diverge_snapshot_WlCoefY, - is_diverge_snapshot_saved)) { - break; + if (isDiverged(curA)) { + if (num_region_diverged_ > 0) { + break; + } + // Skip due to snapshot revert. + continue; } routabilitySnapshot(nesterov_iter, curA, routability_driven_dir, routability_driven_revert_count, - timing_driven_count, - is_routability_snapshot_saved, - route_snapshot_WlCoefX, - route_snapshot_WlCoefY, - route_snapshotA); + timing_driven_count); runRoutability(nesterov_iter, timing_driven_count, routability_driven_dir, - route_snapshotA, - route_snapshot_WlCoefX, - route_snapshot_WlCoefY, routability_driven_revert_count, curA); diff --git a/src/gpl/src/nesterovPlace.h b/src/gpl/src/nesterovPlace.h index a9fb6cd9042..c5307d4ac43 100644 --- a/src/gpl/src/nesterovPlace.h +++ b/src/gpl/src/nesterovPlace.h @@ -95,29 +95,25 @@ class NesterovPlace int64_t& td_accumulated_delta_area, bool is_routability_gpl_iter, int& virtual_cts_count); - bool isDiverged(float& diverge_snapshot_WlCoefX, - float& diverge_snapshot_WlCoefY, - bool& is_diverge_snapshot_saved); + bool isDiverged(float& curA); void routabilitySnapshot(int iter, float curA, const std::string& routability_driven_dir, int routability_driven_count, - int timing_driven_count, - bool& is_routability_snapshot_saved, - float& route_snapshot_WlCoefX, - float& route_snapshot_WlCoefY, - float& route_snapshotA); + int timing_driven_count); void runRoutability(int iter, int timing_driven_count, const std::string& routability_driven_dir, - float route_snapshotA, - float route_snapshot_WlCoefX, - float route_snapshot_WlCoefY, int& routability_driven_count, float& curA); + // Recover from a divergence by rolling back to the routability snapshot with + // a different inflation in place. Returns false when no attempt is left or + // there is no routability snapshot to go to. + bool tryRoutabilityDivergeRecovery(float& curA); // True when the per-iteration cell displacement has come off its peak in // every region, i.e. the placement is close to where it is going. bool isPlacementSettled() const; + float getWorstSettleRatio() const; bool isConverged(int gpl_iter_count, int routability_gpl_iter_count); // The top-level (unfenced/full-die) region is always nbVec_[0]. @@ -152,6 +148,28 @@ class NesterovPlace int64_t min_hpwl_ = INT64_MAX; int diverge_snapshot_iter_ = 0; bool is_min_hpwl_ = false; + bool is_diverge_snapshot_saved_ = false; + float diverge_snapshot_wl_coef_x_ = 0; + float diverge_snapshot_wl_coef_y_ = 0; + // min_hpwl_ at save time; a routability pass clears min_hpwl_ but keeps + // the snapshot. + int64_t diverge_snapshot_hpwl_ = 0; + + // Repeats only help while the resumed descent keeps finding a better + // snapshot. Bounded so a diverging run reports GPL-0307, not max iterations. + static constexpr int kMaxDivergeReverts = 3; + int diverge_revert_count_ = 0; + + // Snapshot saving for routability + bool is_routability_snapshot_saved_ = false; + float route_snapshot_a_ = 0; + float route_snapshot_wl_coef_x_ = 0; + float route_snapshot_wl_coef_y_ = 0; + + // Two attempts because there are two inflation states to try: min + // congestion with routability on, then the same with it off. + static constexpr int kMaxRoutabilityDivergeAttempts = 2; + int routability_diverge_attempt_count_ = 0; // densityPenalty stor std::vector densityPenaltyStor_; @@ -171,6 +189,7 @@ class NesterovPlace int num_region_diverged_ = 0; bool is_routability_need_ = true; + int routability_settle_wait_start_iter_ = -1; std::string divergeMsg_; int divergeCode_ = 0; diff --git a/src/gpl/src/routeBase.cpp b/src/gpl/src/routeBase.cpp index cd592add83f..e0216307ed4 100644 --- a/src/gpl/src/routeBase.cpp +++ b/src/gpl/src/routeBase.cpp @@ -136,7 +136,12 @@ void TileGrid::initTiles(bool use_rudy) debugPrint( log_, GPL, "rudy", 1, "{:9} {:6} {:4}", "TileCnt:", tileCntX_, tileCntY_); if (!use_rudy) { - log_->info(GPL, 39, "Number of routing layers: {}", numRoutingLayers_); + debugPrint(log_, + GPL, + "routability", + 1, + "Number of routing layers: {}", + numRoutingLayers_); } // 2D tile grid structure init @@ -270,16 +275,19 @@ void RouteBase::revertToMinCongestion() { log_->info(GPL, 55, - "Reverting inflation values and target density from the " - "iteration with " - "minimum observed routing congestion."); - log_->info(GPL, 56, "Minimum observed routing congestion: {:.4f}", minRc_); + "Reverting inflation and target density to the pass with the " + "minimum observed routing congestion ({:.4f}), target density " + "{:.4f}.", + minRc_, + minRcTargetDensity_.empty() ? 0.0f : minRcTargetDensity_[0]); // revert nbc_->revertGCellSizeToMinRc(); for (int j = 0; j < nbVec_.size(); j++) { - log_->info(GPL, - 57, + debugPrint(log_, + GPL, + "routability", + 1, "Target density at minimum routing congestion: {:.4f}{}", minRcTargetDensity_[j], nbVec_[j]->getGroup() @@ -613,8 +621,10 @@ bool RouteBase::scaleInflationToBudget() tile->setInflatedRatio(1.0 + scale * (tile->inflatedRatio() - 1.0)); } } - log_->info(GPL, - 99, + debugPrint(log_, + GPL, + "routability", + 1, "Routability inflation trimmed to {:.2f}% of what this iteration " "asked for; {:.2f}% of the {:.2f}% budget still unspent.", 100.0 * scale, @@ -872,6 +882,21 @@ std::pair RouteBase::routability( curRc = getGrtRC(); } + log_->info(GPL, + 40, + "Routability pass {}: weighted congestion {:.4f} (target {:.4f}), " + "{} of {} actionable tiles overflowed ({:.1f}%).", + revert_count_, + curRc, + rbVars_.targetRC, + overflowed_tiles_count_, + actionable_tiles_count_, + actionable_tiles_count_ > 0 + ? (static_cast(overflowed_tiles_count_) + / actionable_tiles_count_) + * 100 + : 0.0); + if (curRc < rbVars_.targetRC) { log_->info(GPL, 50, @@ -891,9 +916,8 @@ std::pair RouteBase::routability( is_min_rc_ = true; log_->info(GPL, 48, - "Routing congestion ({:.4f}) lower than previous minimum " - "({:.4g}). Updating minimum.", - curRc, + "Congestion improved on previous minimum ({:.4g}); updating " + "minimum.", minRc_); minRc_ = curRc; min_RC_violated_cnt_ = 0; @@ -911,9 +935,8 @@ std::pair RouteBase::routability( min_RC_violated_cnt_++; log_->info(GPL, 49, - "Routing congestion ({:.4f}) higher than minimum ({:.4f}). " - "Consecutive non-improvement count: {}.", - curRc, + "No improvement on minimum ({:.4f}); consecutive " + "non-improvement count: {}.", minRc_, min_RC_violated_cnt_); } @@ -997,15 +1020,6 @@ std::pair RouteBase::routability( = (static_cast(inflatedAreaDelta_[nb_index]) / nbVec_[nb_index]->getNesterovInstsArea()) * 100.0f; - log_->info(GPL, - 86, - "Inflated area: {:10.3f} um^2 ({:+.2f}%)", - inflated_area_delta_microns, - inflated_area_delta_percentage); - log_->info(GPL, - 52, - "Placement target density: {:10.4f}", - nbVec_[nb_index]->getTargetDensity()); prev_white_space_area[nb_index] = nbVec_[nb_index]->getWhiteSpaceArea(); prev_movable_area[nb_index] = nbVec_[nb_index]->getMovableArea(); @@ -1017,6 +1031,22 @@ std::pair RouteBase::routability( nbVec_[nb_index]->cutFillerCells(inflatedAreaDelta_[nb_index]); + log_->info( + GPL, + 86, + "Inflation {:+.3f} um^2 ({:+.2f}% of movable), {:.2f}% of the " + "{:.2f}% budget spent; target density {:.4f}{}.", + inflated_area_delta_microns, + inflated_area_delta_percentage, + original_movable_area_ > 0 + ? 100.0 * getTotalInflation() / original_movable_area_ + : 0.0, + 100.0 * rbVars_.maxInflationTotal, + nbVec_[nb_index]->getTargetDensity(), + nbVec_[nb_index]->getGroup() + ? " in group " + string(nbVec_[nb_index]->getGroup()->getName()) + : ""); + // max density detection if (nbVec_[nb_index]->getTargetDensity() > rbVars_.maxDensity) { log_->info( @@ -1074,41 +1104,53 @@ std::pair RouteBase::routability( return ((new_value - old_value) / old_value) * 100.0; }; - log_->info( + debugPrint( + log_, GPL, - 58, + "routability", + 1, "White space area: {:10.3f} um^2 ({:+.2f}%)", block->dbuAreaToMicrons(nbVec_[i]->getWhiteSpaceArea()), percentDiff(prev_white_space_area[i], nbVec_[i]->getWhiteSpaceArea())); - log_->info(GPL, - 59, + debugPrint(log_, + GPL, + "routability", + 1, "Movable instances area: {:10.3f} um^2 ({:+.2f}%)", block->dbuAreaToMicrons(nbVec_[i]->getMovableArea()), percentDiff(prev_movable_area[i], nbVec_[i]->getMovableArea())); - log_->info(GPL, - 60, + debugPrint(log_, + GPL, + "routability", + 1, "Total filler area: {:10.3f} um^2 ({:+.2f}%)", block->dbuAreaToMicrons(nbVec_[i]->getTotalFillerArea()), percentDiff(prev_total_filler_area[i], nbVec_[i]->getTotalFillerArea())); - log_->info(GPL, - 61, + debugPrint(log_, + GPL, + "routability", + 1, "Total non-inflated area: {:10.3f} um^2 ({:+.2f}%)", block->dbuAreaToMicrons(new_total_gcells_area), percentDiff(prev_total_gcells_area[i], new_total_gcells_area)); - log_->info( + debugPrint( + log_, GPL, - 62, + "routability", + 1, "Total inflated area: {:10.3f} um^2 ({:+.2f}%)", block->dbuAreaToMicrons(new_expected_gcells_area), percentDiff(prev_expected_gcells_area[i], new_expected_gcells_area)); - log_->info(GPL, - 63, + debugPrint(log_, + GPL, + "routability", + 1, "New Target Density: {:10.4f}", nbVec_[i]->getTargetDensity()); @@ -1167,18 +1209,26 @@ void RouteBase::updateRudyAverage(bool verbose) actionable_tiles_count_ = edge_cong_array.size(); if (verbose) { - log_->info( + debugPrint( + log_, GPL, - 88, + "routability", + 1, "Tiles the placer can act on: {} of {} ({:.2f}%)", actionable_tiles_count_, tg_->tiles().size(), (static_cast(actionable_tiles_count_) / tg_->tiles().size()) * 100); - log_->info( - GPL, 41, "Total routing overflow: {:.4f}", total_route_overflow_); - log_->info(GPL, - 42, + debugPrint(log_, + GPL, + "routability", + 1, + "Total routing overflow: {:.4f}", + total_route_overflow_); + debugPrint(log_, + GPL, + "routability", + 1, "Number of overflowed tiles: {} ({:.2f}%)", overflowed_tiles_count_, actionable_tiles_count_ > 0 @@ -1226,23 +1276,41 @@ void RouteBase::updateRudyAverage(bool verbose) / (rbVars_.rcK1 + rbVars_.rcK2 + rbVars_.rcK3 + rbVars_.rcK4); if (verbose) { - log_->info( - GPL, 43, "Average top 0.5% routing congestion: {:.4f}", avg005RC); - log_->info( - GPL, 44, "Average top 1.0% routing congestion: {:.4f}", avg010RC); - log_->info( - GPL, 45, "Average top 2.0% routing congestion: {:.4f}", avg020RC); - log_->info( - GPL, 46, "Average top 5.0% routing congestion: {:.4f}", avg050RC); - log_->info(GPL, - 47, + debugPrint(log_, + GPL, + "routability", + 1, + "Average top 0.5% routing congestion: {:.4f}", + avg005RC); + debugPrint(log_, + GPL, + "routability", + 1, + "Average top 1.0% routing congestion: {:.4f}", + avg010RC); + debugPrint(log_, + GPL, + "routability", + 1, + "Average top 2.0% routing congestion: {:.4f}", + avg020RC); + debugPrint(log_, + GPL, + "routability", + 1, + "Average top 5.0% routing congestion: {:.4f}", + avg050RC); + debugPrint(log_, + GPL, + "routability", + 1, "Routability iteration weighted routing congestion: {:.4f}", final_average_rc_); } } // extract RC values -float RouteBase::getGrtRC() const +float RouteBase::getGrtRC() { double totalRouteOverflowH2 = 0; double totalRouteOverflowV2 = 0; @@ -1251,11 +1319,19 @@ float RouteBase::getGrtRC() const std::vector horEdgeCongArray; std::vector verEdgeCongArray; + // Tile counts, as opposed to the per-layer edge counts above: a tile is + // overflowed if any of its layers is. These feed the pass header, which + // reads the same on either congestion backend. + overflowed_tiles_count_ = 0; + actionable_tiles_count_ = 0; + odb::dbGCellGrid* gGrid = db_->getChip()->getBlock()->getGCellGrid(); for (auto& tile : tg_->tiles()) { if (!tile->isActionable()) { continue; } + ++actionable_tiles_count_; + bool tile_overflowed = false; int min_routing_layer, max_routing_layer; grouter_->getMinMaxLayer(min_routing_layer, max_routing_layer); for (int i = 1; i <= tg_->numRoutingLayers(); i++) { @@ -1281,14 +1357,31 @@ float RouteBase::getGrtRC() const if (ratio > 1.0) { overflowTileCnt2++; + tile_overflowed = true; } } } + if (tile_overflowed) { + ++overflowed_tiles_count_; + } } - log_->info(GPL, 64, "TotalRouteOverflowH2: {:.4f}", totalRouteOverflowH2); - log_->info(GPL, 65, "TotalRouteOverflowV2: {:.4f}", totalRouteOverflowV2); - log_->info(GPL, 66, "OverflowTileCnt2: {}", overflowTileCnt2); + total_route_overflow_ = totalRouteOverflowH2 + totalRouteOverflowV2; + + debugPrint(log_, + GPL, + "routability", + 1, + "TotalRouteOverflowH2: {:.4f}", + totalRouteOverflowH2); + debugPrint(log_, + GPL, + "routability", + 1, + "TotalRouteOverflowV2: {:.4f}", + totalRouteOverflowV2); + debugPrint( + log_, GPL, "routability", 1, "OverflowTileCnt2: {}", overflowTileCnt2); int horArraySize = horEdgeCongArray.size(); int verArraySize = verEdgeCongArray.size(); @@ -1343,15 +1436,19 @@ float RouteBase::getGrtRC() const verAvg020RC /= ceil(0.020 * verArraySize); verAvg050RC /= ceil(0.050 * verArraySize); - log_->info(GPL, 67, "0.5%RC: {:.4f}", std::fmax(horAvg005RC, verAvg005RC)); - log_->info(GPL, 68, "1.0%RC: {:.4f}", std::fmax(horAvg010RC, verAvg010RC)); - log_->info(GPL, 69, "2.0%RC: {:.4f}", std::fmax(horAvg020RC, verAvg020RC)); - log_->info(GPL, 70, "5.0%RC: {:.4f}", std::fmax(horAvg050RC, verAvg050RC)); + auto debug = [this](const char* msg, auto value) { + debugPrint(log_, GPL, "routability", 1, msg, value); + }; - log_->info(GPL, 71, "0.5rcK: {:.2f}", rbVars_.rcK1); - log_->info(GPL, 72, "1.0rcK: {:.2f}", rbVars_.rcK2); - log_->info(GPL, 73, "2.0rcK: {:.2f}", rbVars_.rcK3); - log_->info(GPL, 74, "5.0rcK: {:.2f}", rbVars_.rcK4); + debug("0.5%RC: {:.4f}", std::fmax(horAvg005RC, verAvg005RC)); + debug("1.0%RC: {:.4f}", std::fmax(horAvg010RC, verAvg010RC)); + debug("2.0%RC: {:.4f}", std::fmax(horAvg020RC, verAvg020RC)); + debug("5.0%RC: {:.4f}", std::fmax(horAvg050RC, verAvg050RC)); + + debug("0.5rcK: {:.2f}", rbVars_.rcK1); + debug("1.0rcK: {:.2f}", rbVars_.rcK2); + debug("2.0rcK: {:.2f}", rbVars_.rcK3); + debug("5.0rcK: {:.2f}", rbVars_.rcK4); float finalRC = (rbVars_.rcK1 * std::fmax(horAvg005RC, verAvg005RC) + rbVars_.rcK2 * std::fmax(horAvg010RC, verAvg010RC) @@ -1359,15 +1456,13 @@ float RouteBase::getGrtRC() const + rbVars_.rcK4 * std::fmax(horAvg050RC, verAvg050RC)) / (rbVars_.rcK1 + rbVars_.rcK2 + rbVars_.rcK3 + rbVars_.rcK4); - log_->info(GPL, 75, "Final routing congestion: {}", finalRC); + debug("Final routing congestion: {}", finalRC); return finalRC; } void RouteBase::increaseCounter() { revert_count_++; - - log_->info(GPL, 40, "Routability iteration: {}", revert_count_); } void RouteBase::printGCellInflation() const diff --git a/src/gpl/src/routeBase.h b/src/gpl/src/routeBase.h index 74c7083a049..fdf62d4470d 100644 --- a/src/gpl/src/routeBase.h +++ b/src/gpl/src/routeBase.h @@ -171,7 +171,10 @@ class RouteBase // TODO: understand why this function is breaking RUDY. // Allow for grt heatmap during gpl execution. void loadGrt(); - float getGrtRC() const; + // Not const: fills the same overflow/tile counters updateRudyAverage() sets, + // so the routability pass header reads the same on either congestion + // backend. + float getGrtRC(); void calculateRudyTiles(); void updateRudyAverage(bool verbose = true); @@ -192,6 +195,11 @@ class RouteBase int64_t getTotalInflation() const; int getRevertCount() const; + // Roll cell sizes, target density, fillers, accumulated inflation and net + // weights back to the pass that saw the least congestion. Callers must check + // getRevertCount() >= 1. + void revertToMinCongestion(); + void printGCellInflation() const; private: @@ -242,7 +250,6 @@ class RouteBase void init(); void resetRoutabilityResources(); - void revertToMinCongestion(); // The tile holding the given point, or nullptr if it falls outside the grid. Tile* getTile(int x, int y) const; diff --git a/src/gpl/test/simple01-rd.ok b/src/gpl/test/simple01-rd.ok index 61c8524abdc..a8bbd3699ab 100644 --- a/src/gpl/test/simple01-rd.ok +++ b/src/gpl/test/simple01-rd.ok @@ -79,20 +79,7 @@ Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group 260 | 0.4052 | 2.408343e+03 | -0.40% | 1.93e-08 | 270 | 0.3522 | 2.422198e+03 | +0.58% | 3.15e-08 | 280 | 0.3190 | 2.437331e+03 | +0.62% | 4.74e-08 | -[INFO GPL-0040] Routability iteration: 1 -[INFO GPL-0039] Number of routing layers: 10 -[INFO GPL-0064] TotalRouteOverflowH2: 0.0000 -[INFO GPL-0065] TotalRouteOverflowV2: 0.0000 -[INFO GPL-0066] OverflowTileCnt2: 0 -[INFO GPL-0067] 0.5%RC: 0.8000 -[INFO GPL-0068] 1.0%RC: 0.7333 -[INFO GPL-0069] 2.0%RC: 0.6583 -[INFO GPL-0070] 5.0%RC: 0.5719 -[INFO GPL-0071] 0.5rcK: 1.00 -[INFO GPL-0072] 1.0rcK: 1.00 -[INFO GPL-0073] 2.0rcK: 0.00 -[INFO GPL-0074] 5.0rcK: 0.00 -[INFO GPL-0075] Final routing congestion: 0.76666665 +[INFO GPL-0040] Routability pass 1: weighted congestion 0.7667 (target 1.2500), 0 of 73 actionable tiles overflowed (0.0%). [INFO GPL-0050] Weighted routing congestion is lower than target routing congestion(1.2500), end routability optimization. [INFO GPL-0090] Routability finished. Target routing congestion achieved succesfully. Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group @@ -108,7 +95,6 @@ Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group --------------------------------------------------------------- [INFO GPL-1001] Global placement finished at iteration 357 [INFO GPL-1017] Routability mode iteration count: 64 -[INFO GPL-0039] Number of routing layers: 0 [INFO GPL-1005] Routability final weighted congestion: 0.2670 [INFO GPL-1002] Placed Cell Area 619.7347 [INFO GPL-1003] Available Free Area 953.8760 diff --git a/src/gpl/test/simple02-rd.ok b/src/gpl/test/simple02-rd.ok index 242de1ed760..4ee9b721da8 100644 --- a/src/gpl/test/simple02-rd.ok +++ b/src/gpl/test/simple02-rd.ok @@ -79,20 +79,7 @@ Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group 260 | 0.4052 | 2.408343e+03 | -0.40% | 1.93e-08 | 270 | 0.3522 | 2.422198e+03 | +0.58% | 3.15e-08 | 280 | 0.3190 | 2.437331e+03 | +0.62% | 4.74e-08 | -[INFO GPL-0040] Routability iteration: 1 -[INFO GPL-0039] Number of routing layers: 10 -[INFO GPL-0064] TotalRouteOverflowH2: 0.0000 -[INFO GPL-0065] TotalRouteOverflowV2: 0.0000 -[INFO GPL-0066] OverflowTileCnt2: 0 -[INFO GPL-0067] 0.5%RC: 0.8000 -[INFO GPL-0068] 1.0%RC: 0.7333 -[INFO GPL-0069] 2.0%RC: 0.6583 -[INFO GPL-0070] 5.0%RC: 0.5719 -[INFO GPL-0071] 0.5rcK: 1.00 -[INFO GPL-0072] 1.0rcK: 1.00 -[INFO GPL-0073] 2.0rcK: 0.00 -[INFO GPL-0074] 5.0rcK: 0.00 -[INFO GPL-0075] Final routing congestion: 0.76666665 +[INFO GPL-0040] Routability pass 1: weighted congestion 0.7667 (target 1.0000), 0 of 73 actionable tiles overflowed (0.0%). [INFO GPL-0050] Weighted routing congestion is lower than target routing congestion(1.0000), end routability optimization. [INFO GPL-0090] Routability finished. Target routing congestion achieved succesfully. Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group @@ -108,7 +95,6 @@ Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group --------------------------------------------------------------- [INFO GPL-1001] Global placement finished at iteration 357 [INFO GPL-1017] Routability mode iteration count: 64 -[INFO GPL-0039] Number of routing layers: 0 [INFO GPL-1005] Routability final weighted congestion: 0.2670 [INFO GPL-1002] Placed Cell Area 619.7347 [INFO GPL-1003] Available Free Area 953.8760 diff --git a/src/gpl/test/simple03-rd.ok b/src/gpl/test/simple03-rd.ok index e8f9a0f6c65..e951f277eea 100644 --- a/src/gpl/test/simple03-rd.ok +++ b/src/gpl/test/simple03-rd.ok @@ -79,15 +79,7 @@ Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group 260 | 0.4052 | 2.408343e+03 | -0.40% | 1.93e-08 | 270 | 0.3522 | 2.422198e+03 | +0.58% | 3.15e-08 | 280 | 0.3190 | 2.437331e+03 | +0.62% | 4.74e-08 | -[INFO GPL-0040] Routability iteration: 1 -[INFO GPL-0088] Tiles the placer can act on: 73 of 100 (73.00%) -[INFO GPL-0041] Total routing overflow: 0.0000 -[INFO GPL-0042] Number of overflowed tiles: 0 (0.00%) -[INFO GPL-0043] Average top 0.5% routing congestion: 0.2979 -[INFO GPL-0044] Average top 1.0% routing congestion: 0.2979 -[INFO GPL-0045] Average top 2.0% routing congestion: 0.2847 -[INFO GPL-0046] Average top 5.0% routing congestion: 0.2749 -[INFO GPL-0047] Routability iteration weighted routing congestion: 0.2979 +[INFO GPL-0040] Routability pass 1: weighted congestion 0.2979 (target 1.2500), 0 of 73 actionable tiles overflowed (0.0%). [INFO GPL-0050] Weighted routing congestion is lower than target routing congestion(1.2500), end routability optimization. [INFO GPL-0090] Routability finished. Target routing congestion achieved succesfully. Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group diff --git a/src/gpl/test/simple04-rd.ok b/src/gpl/test/simple04-rd.ok index 2328cd54047..a3446809c08 100644 --- a/src/gpl/test/simple04-rd.ok +++ b/src/gpl/test/simple04-rd.ok @@ -79,15 +79,7 @@ Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group 260 | 0.4052 | 2.408343e+03 | -0.40% | 1.93e-08 | 270 | 0.3522 | 2.422198e+03 | +0.58% | 3.15e-08 | 280 | 0.3190 | 2.437331e+03 | +0.62% | 4.74e-08 | -[INFO GPL-0040] Routability iteration: 1 -[INFO GPL-0088] Tiles the placer can act on: 73 of 100 (73.00%) -[INFO GPL-0041] Total routing overflow: 0.0000 -[INFO GPL-0042] Number of overflowed tiles: 0 (0.00%) -[INFO GPL-0043] Average top 0.5% routing congestion: 0.2979 -[INFO GPL-0044] Average top 1.0% routing congestion: 0.2979 -[INFO GPL-0045] Average top 2.0% routing congestion: 0.2847 -[INFO GPL-0046] Average top 5.0% routing congestion: 0.2749 -[INFO GPL-0047] Routability iteration weighted routing congestion: 0.2979 +[INFO GPL-0040] Routability pass 1: weighted congestion 0.2979 (target 0.6700), 0 of 73 actionable tiles overflowed (0.0%). [INFO GPL-0050] Weighted routing congestion is lower than target routing congestion(0.6700), end routability optimization. [INFO GPL-0090] Routability finished. Target routing congestion achieved succesfully. Iteration | Overflow | HPWL (um) | HPWL(%) | Penalty | Group