diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 145bdf74..d57bd911 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -31,6 +31,7 @@ namespace sta { class LibertyCellIterator; class LibertyCellPortIterator; class LibertyCellPortBitIterator; +class LibertyCellPgPortIterator; class LibertyPortMemberIterator; class ModeValueDef; class TestCell; @@ -397,7 +398,8 @@ public: void findLibertyPortsMatching(PatternMatch *pattern, LibertyPortSeq *ports) const; bool hasInternalPorts() const { return has_internal_ports_; } - LibertyPgPort *findPgPort(const char *name); + LibertyPgPort *findPgPort(const char *name) const; + size_t pgPortCount() const { return pg_port_map_.size(); } ScaleFactors *scaleFactors() const { return scale_factors_; } void setScaleFactors(ScaleFactors *scale_factors); ModeDef *makeModeDef(const char *name); @@ -580,6 +582,7 @@ private: friend class LibertyLibrary; friend class LibertyCellPortIterator; + friend class LibertyCellPgPortIterator; friend class LibertyPort; friend class LibertyBuilder; friend class LibertyCellTimingArcSetIterator; @@ -613,6 +616,19 @@ private: ConcreteCellPortBitIterator *iter_; }; +class LibertyCellPgPortIterator : public Iterator +{ +public: + LibertyCellPgPortIterator(const LibertyCell *cell); + bool hasNext(); + LibertyPgPort *next(); + +private: + DISALLOW_COPY_AND_ASSIGN(LibertyCellPgPortIterator); + + LibertyPgPortMap::Iterator iter_; +}; + class LibertyCellTimingArcSetIterator : public TimingArcSetSeq::ConstIterator { public: @@ -1065,12 +1081,14 @@ public: LibertyPgPort(const char *name, LibertyCell *cell); ~LibertyPgPort(); - const char *name() { return name_; } + const char *name() const { return name_; } LibertyCell *cell() const { return cell_; } PgType pgType() const { return pg_type_; } void setPgType(PgType type); const char *voltageName() const { return voltage_name_; } void setVoltageName(const char *voltage_name); + static bool equiv(const LibertyPgPort *port1, + const LibertyPgPort *port2); private: const char *name_; diff --git a/liberty/EquivCells.cc b/liberty/EquivCells.cc index 17c9f176..5390fdda 100644 --- a/liberty/EquivCells.cc +++ b/liberty/EquivCells.cc @@ -41,6 +41,14 @@ static unsigned hashFuncExpr(const FuncExpr *expr); static unsigned hashPort(const LibertyPort *port); +static unsigned +hashCellPgPorts(const LibertyCell *cell); +static unsigned +hashPgPort(const LibertyPgPort *port); + +static bool +equivCellPgPorts(const LibertyCell *cell1, + const LibertyCell *cell2); static float cellDriveResistance(const LibertyCell *cell) @@ -164,7 +172,9 @@ EquivCells::mapEquivCells(const LibertyLibrary *library, static unsigned hashCell(const LibertyCell *cell) { - return hashCellPorts(cell) + hashCellSequentials(cell); + return hashCellPorts(cell) + + hashCellPgPorts(cell) + + hashCellSequentials(cell); } static unsigned @@ -188,6 +198,25 @@ hashPort(const LibertyPort *port) + port->direction()->index() * 5; } +static unsigned +hashCellPgPorts(const LibertyCell *cell) +{ + unsigned hash = 0; + LibertyCellPgPortIterator port_iter(cell); + while (port_iter.hasNext()) { + LibertyPgPort *port = port_iter.next(); + hash += hashPgPort(port); + } + return hash; +} + +static unsigned +hashPgPort(const LibertyPgPort *port) +{ + return hashString(port->name()) * 3 + + static_cast(port->pgType()) * 5; +} + static unsigned hashCellSequentials(const LibertyCell *cell) { @@ -232,6 +261,7 @@ equivCells(const LibertyCell *cell1, const LibertyCell *cell2) { return equivCellPortsAndFuncs(cell1, cell2) + && equivCellPgPorts(cell1, cell2) && equivCellSequentials(cell1, cell2) && equivCellTimingArcSets(cell1, cell2); } @@ -279,6 +309,25 @@ equivCellPorts(const LibertyCell *cell1, } } +static bool +equivCellPgPorts(const LibertyCell *cell1, + const LibertyCell *cell2) +{ + if (cell1->pgPortCount() != cell2->pgPortCount()) + return false; + else { + LibertyCellPgPortIterator port_iter1(cell1); + while (port_iter1.hasNext()) { + LibertyPgPort *port1 = port_iter1.next(); + const char* name = port1->name(); + LibertyPgPort *port2 = cell2->findPgPort(name); + if (!(port2 && LibertyPgPort::equiv(port1, port2))) + return false; + } + return true; + } +} + bool equivCellSequentials(const LibertyCell *cell1, const LibertyCell *cell2) diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 280863f7..bdb8719c 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -942,7 +942,7 @@ LibertyCell::addPgPort(LibertyPgPort *pg_port) } LibertyPgPort * -LibertyCell::findPgPort(const char *name) +LibertyCell::findPgPort(const char *name) const { return pg_port_map_.findKey(name); } @@ -2930,4 +2930,34 @@ LibertyPgPort::setVoltageName(const char *voltage_name) voltage_name_ = stringCopy(voltage_name); } +bool +LibertyPgPort::equiv(const LibertyPgPort *port1, + const LibertyPgPort *port2) +{ + return stringEq(port1->name_, port2->name_) + && port1->pg_type_ == port2->pg_type_; +} + +//////////////////////////////////////////////////////////////// + +LibertyCellPgPortIterator::LibertyCellPgPortIterator(const LibertyCell *cell) : + iter_(const_cast(cell)->pg_port_map_) +{ +} + +bool +LibertyCellPgPortIterator::hasNext() +{ + return iter_.hasNext(); +} + +LibertyPgPort * +LibertyCellPgPortIterator::next() +{ + const char *name; + LibertyPgPort *port; + iter_.next(name, port); + return port; +} + } // namespace