From 736a977a6dfac6fb25628691a6c865741dd1d884 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 28 May 2019 07:45:05 -0700 Subject: [PATCH] Liberty equiv cells in LibertyCell instead of map --- liberty/EquivCells.cc | 69 ++++++++++++++----------------------------- liberty/EquivCells.hh | 7 ++--- liberty/Liberty.cc | 49 ++++++++++++++++++++---------- liberty/Liberty.hh | 8 +++-- tcl/StaTcl.i | 3 +- 5 files changed, 64 insertions(+), 72 deletions(-) diff --git a/liberty/EquivCells.cc b/liberty/EquivCells.cc index 47b4617b..953202ee 100644 --- a/liberty/EquivCells.cc +++ b/liberty/EquivCells.cc @@ -30,12 +30,13 @@ namespace sta { typedef UnorderedMap LibertyCellHashMap; -typedef Set LibertyCellSeqSet; +typedef Set LibertyCellSet; -static LibertyCellEquivMap * -findEquivCells1(const LibertyLibrary *library); static void -sortCellEquivs(LibertyCellEquivMap *cell_equivs); +findEquivCells1(const LibertyLibrary *library, + LibertyCellSet &cell_equivs); +static void +sortCellEquivs(LibertyCellSet &cell_equivs); static float cellDriveResistance(const LibertyCell *cell); @@ -56,47 +57,24 @@ static bool equivCellSequentials(const LibertyCell *cell1, const LibertyCell *cell2); -LibertyCellEquivMap * +void findEquivCells(const LibertyLibrary *library) { - // Build a map from each cell in the library to a group (CellSeq) of - // cells with equivalent functionality. - LibertyCellEquivMap *cell_equivs = findEquivCells1(library); + LibertyCellSet cell_equivs; + findEquivCells1(library, cell_equivs); // Sort by drive strength. sortCellEquivs(cell_equivs); - return cell_equivs; } -// Delete the LibertyCellEquivMap returned by makeEquivCellMap. -void -deleteEquivCellMap(LibertyCellEquivMap *equiv_map) -{ - // Multiple cells can point to the same cell sequence, so collect - // them into a set so the are only deleted once. - LibertyCellSeqSet cells_seqs; - LibertyCellEquivMap::Iterator equiv_iter(equiv_map); - while (equiv_iter.hasNext()) { - LibertyCellSeq *cells = equiv_iter.next(); - cells_seqs.insert(cells); - } - LibertyCellSeqSet::Iterator cells_iter(cells_seqs); - while (cells_iter.hasNext()) { - LibertyCellSeq *cells = cells_iter.next(); - delete cells; - } - delete equiv_map; -} - -static LibertyCellEquivMap * -findEquivCells1(const LibertyLibrary *library) +static void +findEquivCells1(const LibertyLibrary *library, + LibertyCellSet &cell_equivs) { LibertyCellHashMap cell_hash; - LibertyCellEquivMap *cell_equivs = new LibertyCellEquivMap; LibertyCellIterator cell_iter(library); while (cell_iter.hasNext()) { LibertyCell *cell = cell_iter.next(); if (!cell->dontUse()) { - bool found_equiv = false; unsigned hash = hashCell(cell); // Use a comprehensive hash on cell properties to segregate // cells into groups of potential matches. @@ -106,10 +84,15 @@ findEquivCells1(const LibertyLibrary *library) while (match_iter.hasNext()) { LibertyCell *match = match_iter.next(); if (equivCells(match, cell)) { - LibertyCellSeq *equivs = cell_equivs->findKey(match); + LibertyCellSeq *equivs = match->equivCellsRaw(); + if (equivs == nullptr) { + equivs = new LibertyCellSeq; + equivs->push_back(match); + match->setEquivCells(equivs); + cell_equivs.insert(match); + } equivs->push_back(cell); - (*cell_equivs)[cell] = equivs; - found_equiv = true; + cell->setEquivCells(equivs); break; } } @@ -119,16 +102,9 @@ findEquivCells1(const LibertyLibrary *library) cell_hash[hash] = matches; } matches->push_back(cell); - if (!found_equiv) { - LibertyCellSeq *equivs = new LibertyCellSeq; - equivs->push_back(cell); - (*cell_equivs)[cell] = equivs; - } } } - cell_hash.deleteContents(); - return cell_equivs; } struct CellDriveResistanceLess @@ -141,11 +117,10 @@ struct CellDriveResistanceLess }; static void -sortCellEquivs(LibertyCellEquivMap *cell_equivs) +sortCellEquivs(LibertyCellSet &cell_equivs) { - LibertyCellEquivMap::Iterator equivs_iter(cell_equivs); - while (equivs_iter.hasNext()) { - LibertyCellSeq *equivs = equivs_iter.next(); + for (auto equiv : cell_equivs) { + LibertyCellSeq *equivs = equiv->equivCells(); sort(equivs, CellDriveResistanceLess()); LibertyCell *lower = nullptr; LibertyCellSeq::Iterator cell_iter(equivs); diff --git a/liberty/EquivCells.hh b/liberty/EquivCells.hh index 896fa68c..39cf8a75 100644 --- a/liberty/EquivCells.hh +++ b/liberty/EquivCells.hh @@ -23,12 +23,9 @@ namespace sta { // Find equivalent cells, sort by drive strength and -// and set cell->higherDrive/lowerDrive. -LibertyCellEquivMap * -findEquivCells(const LibertyLibrary *library); -// Delete findEquivCells return value. +// and set cell->equivCells/higherDrive/lowerDrive. void -deleteEquivCellMap(LibertyCellEquivMap *equiv_map); +findEquivCells(const LibertyLibrary *library); // Predicate that is true when the ports, functions, sequentials and // timing arcs match. diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index d324ed45..6a343eae 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -84,7 +84,7 @@ LibertyLibrary::LibertyLibrary(const char *name, default_operating_conditions_(nullptr), ocv_arc_depth_(0.0), default_ocv_derate_(nullptr), - equiv_cell_map_(nullptr), + found_equiv_cells_(false), buffers_(nullptr) { // Scalar templates are builtin. @@ -132,7 +132,6 @@ LibertyLibrary::~LibertyLibrary() const char *supply_name = name_volt.first; stringDelete(supply_name); } - deleteEquivCellMap(equiv_cell_map_); delete buffers_; } @@ -154,6 +153,15 @@ LibertyLibrary::findLibertyCellsMatching(PatternMatch *pattern, } } +void +LibertyLibrary::ensureEquivCells() +{ + if (!found_equiv_cells_) { + findEquivCells(this); + found_equiv_cells_ = true; + } +} + LibertyCellSeq * LibertyLibrary::buffers() { @@ -757,20 +765,6 @@ LibertyLibrary::makeCornerMap(LibertyCell *cell1, } } -void -LibertyLibrary::ensureEquivCells() -{ - if (equiv_cell_map_ == nullptr) - equiv_cell_map_ = sta::findEquivCells(this); -} - -LibertyCellSeq * -LibertyLibrary::findEquivCells(LibertyCell *cell) -{ - ensureEquivCells(); - return equiv_cell_map_->findKey(cell); -} - //////////////////////////////////////////////////////////////// float @@ -873,6 +867,7 @@ LibertyCell::LibertyCell(LibertyLibrary *library, is_disabled_constraint_(false), leakage_power_(0.0), leakage_power_exists_(false), + equiv_cells_(nullptr), higher_drive_(nullptr), lower_drive_(nullptr) { @@ -889,6 +884,14 @@ LibertyCell::~LibertyCell() timing_arc_set_from_map_.deleteContents(); timing_arc_set_to_map_.deleteContents(); + if (equiv_cells_) { + // equiv_cells_ is shared by all of the equivalent cells, so + // delete it once for all of them and null them. + for (auto equiv : *equiv_cells_) + equiv->setEquivCells(nullptr); + delete equiv_cells_; + } + deleteInternalPowerAttrs(); internal_powers_.deleteContents(); leakage_powers_.deleteContents(); @@ -1457,6 +1460,20 @@ LibertyCell::setCornerCell(LibertyCell *corner_cell, //////////////////////////////////////////////////////////////// +LibertyCellSeq * +LibertyCell::equivCells() +{ + if (equiv_cells_ == nullptr) + liberty_library_->ensureEquivCells(); + return equiv_cells_; +} + +void +LibertyCell::setEquivCells(LibertyCellSeq *equiv_cells) +{ + equiv_cells_ = equiv_cells; +} + LibertyCell * LibertyCell::higherDrive() const { diff --git a/liberty/Liberty.hh b/liberty/Liberty.hh index c0070056..9d1c8a91 100644 --- a/liberty/Liberty.hh +++ b/liberty/Liberty.hh @@ -118,7 +118,6 @@ public: LibertyCell *findLibertyCell(const char *name) const; void findLibertyCellsMatching(PatternMatch *pattern, LibertyCellSeq *cells); - LibertyCellSeq *findEquivCells(LibertyCell *cell); // Liberty cells that are buffers. LibertyCellSeq *buffers(); @@ -331,7 +330,7 @@ protected: OcvDerate *default_ocv_derate_; OcvDerateMap ocv_derate_map_; SupplyVoltageMap supply_voltage_map_; - LibertyCellEquivMap *equiv_cell_map_; + bool found_equiv_cells_; LibertyCellSeq *buffers_; // Set if any library has rise/fall capacitances. @@ -493,6 +492,10 @@ public: virtual void finish(bool infer_latches, Report *report, Debug *debug); + LibertyCellSeq *equivCells(); + // Internal. + LibertyCellSeq *equivCellsRaw() { return equiv_cells_; } + void setEquivCells(LibertyCellSeq *equiv_cells); void setHigherDrive(LibertyCell *cell); void setLowerDrive(LibertyCell *cell); bool isBuffer() const; @@ -565,6 +568,7 @@ protected: float leakage_power_; bool leakage_power_exists_; LibertyPgPortMap pg_port_map_; + LibertyCellSeq *equiv_cells_; // Next higher/lower drive equivalent cells. LibertyCell *higher_drive_; LibertyCell *lower_drive_; diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index c2c8cf37..b9f2c533 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -2282,8 +2282,7 @@ find_library_buffers(LibertyLibrary *library) LibertyCellSeq * equiv_cells(LibertyCell *cell) { - LibertyLibrary *library = cell->libertyLibrary(); - return library->findEquivCells(cell); + return cell->equivCells(); } bool