Liberty equiv cells in LibertyCell instead of map
This commit is contained in:
parent
53df9472d7
commit
736a977a6d
|
|
@ -30,12 +30,13 @@
|
|||
namespace sta {
|
||||
|
||||
typedef UnorderedMap<unsigned, LibertyCellSeq*> LibertyCellHashMap;
|
||||
typedef Set<LibertyCellSeq*> LibertyCellSeqSet;
|
||||
typedef Set<LibertyCell*> 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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue