diff --git a/src/rsz/include/rsz/Resizer.hh b/src/rsz/include/rsz/Resizer.hh index 0cf0d743e3d..a077e6dc5d5 100644 --- a/src/rsz/include/rsz/Resizer.hh +++ b/src/rsz/include/rsz/Resizer.hh @@ -442,7 +442,7 @@ class Resizer : public dbStaState, public dbNetworkObserver void invalidateParasitics(const Pin* pin, const Net* net); void eraseParasitics(const Net* net); void eliminateDeadLogic(bool clean_nets); - std::optional cellLeakage(const LibertyCell* cell); + std::optional cellLeakage(LibertyCell* cell); // For debugging - calls getSwappableCells void reportEquivalentCells(LibertyCell* base_cell, bool match_cell_footprint); @@ -793,6 +793,7 @@ class Resizer : public dbStaState, public dbNetworkObserver std::stack cloned_gates_; std::unordered_set cloned_inst_set_; std::unordered_map removed_buffer_map_; + std::unordered_map> cell_leakage_cache_; // Need to track all changes for buffer removal InstanceSet all_sized_inst_set_; diff --git a/src/rsz/src/Resizer.cc b/src/rsz/src/Resizer.cc index edb1cdcdf47..ba3f5f01df4 100644 --- a/src/rsz/src/Resizer.cc +++ b/src/rsz/src/Resizer.cc @@ -57,6 +57,7 @@ #include "sta/Graph.hh" #include "sta/GraphDelayCalc.hh" #include "sta/InputDrive.hh" +#include "sta/LeakagePower.hh" #include "sta/Liberty.hh" #include "sta/Network.hh" #include "sta/Parasitics.hh" @@ -132,6 +133,8 @@ using sta::VertexOutEdgeIterator; using sta::BufferUse; using sta::CLOCK; +using sta::LeakagePower; +using sta::LeakagePowerSeq; Resizer::Resizer() : recover_power_(new RecoverPower(this)), @@ -1281,17 +1284,39 @@ void Resizer::resizePreamble() findTargetLoads(); } -// Convert sta results to std::optional -std::optional Resizer::cellLeakage(const LibertyCell* cell) +// Convert static cell leakage to std::optional. +// For state-dependent leakage, compute the average +// across all the power states. Cache the leakage for +// runtime. +std::optional Resizer::cellLeakage(LibertyCell* cell) { - float leakage; + auto it = cell_leakage_cache_.find(cell); + if (it != cell_leakage_cache_.end()) { + return it->second; + } + + float leakage = 0.0; bool exists; cell->leakagePower(leakage, exists); - std::optional value; if (exists) { - value = leakage; + cell_leakage_cache_[cell] = leakage; + return leakage; + } + + // Compute average leakage across power conds for state-dependent leakage + LeakagePowerSeq* leakages = cell->leakagePowers(); + if (!leakages || leakages->empty()) { + cell_leakage_cache_[cell] = std::nullopt; + return std::nullopt; } - return value; + + float total_leakage = 0.0; + for (LeakagePower* leak : *leakages) { + total_leakage += leak->power(); + } + leakage = total_leakage / leakages->size(); + cell_leakage_cache_[cell] = leakage; + return leakage; } // For debugging @@ -1305,19 +1330,26 @@ void Resizer::reportEquivalentCells(LibertyCell* base_cell, // Sort equiv cells by ascending area and leakage // STA sorts them by drive resistance - std::sort(equiv_cells.begin(), - equiv_cells.end(), - [this](const LibertyCell* a, const LibertyCell* b) { - if (!sta::fuzzyEqual(a->area(), b->area())) { - return a->area() < b->area(); - } - std::optional leakage_a = this->cellLeakage(a); - std::optional leakage_b = this->cellLeakage(b); - if (leakage_a && leakage_b) { - return *leakage_a < *leakage_b; - } - return leakage_a.has_value(); - }); + std::stable_sort(equiv_cells.begin(), + equiv_cells.end(), + [this](LibertyCell* a, LibertyCell* b) { + dbMaster* master_a = this->getDbNetwork()->staToDb(a); + dbMaster* master_b = this->getDbNetwork()->staToDb(b); + if (master_a && master_b) { + if (master_a->getArea() != master_b->getArea()) { + return master_a->getArea() < master_b->getArea(); + } + } + std::optional leakage_a = this->cellLeakage(a); + std::optional leakage_b = this->cellLeakage(b); + // Compare leakages only if they are defined + if (leakage_a && leakage_b) { + return *leakage_a < *leakage_b; + } + // Cell 'a' has a priority as it has lower + // drive resistance than 'b' after STA sort + return leakage_a.has_value() && !leakage_b.has_value(); + }); logger_->report( "The following {} cells are equivalent to {}{}", @@ -1403,7 +1435,7 @@ LibertyCellSeq Resizer::getSwappableCells(LibertyCell* source_cell) } dbMaster* master = db_network_->staToDb(source_cell); - if (master && !master->isCore()) { + if (master == nullptr || !master->isCore()) { swappable_cells_cache_[source_cell] = {}; return {}; } @@ -1673,7 +1705,6 @@ int Resizer::resizeToTargetSlew(const Pin* drvr_pin) if (target_cell != cell) { debugPrint(logger_, RSZ, - "resize", 2, "{} {} -> {}",