Liberty equiv cells in LibertyCell instead of map

This commit is contained in:
James Cherry 2019-05-28 07:45:05 -07:00
parent 53df9472d7
commit 736a977a6d
5 changed files with 64 additions and 72 deletions

View File

@ -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);

View File

@ -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.

View File

@ -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
{

View File

@ -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_;

View File

@ -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