diff --git a/include/sta/EquivCells.hh b/include/sta/EquivCells.hh index d695b79b..400e1ec7 100644 --- a/include/sta/EquivCells.hh +++ b/include/sta/EquivCells.hh @@ -73,4 +73,8 @@ bool equivCellSequentials(const LibertyCell *cell1, const LibertyCell *cell2); +bool +equivCellFootprints(const LibertyCell *cell1, + const LibertyCell *cell2); + } // namespace diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 4763a8d0..8b568ae3 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -83,6 +83,8 @@ typedef Map SupplyVoltageMap; typedef Map LibertyPgPortMap; typedef Map DriverWaveformMap; typedef Vector DcalcAnalysisPtSeq; +typedef int LibertyCellFootprintIndex; +typedef Vector LibertyCellFootprintSeq; enum class ClockGateType { none, latch_posedge, latch_negedge, other }; @@ -142,6 +144,7 @@ public: // Liberty cells that are buffers. LibertyCellSeq *buffers(); LibertyCellSeq *inverters(); + void addFootprint(const char *footprint); DelayModelType delayModelType() const { return delay_model_type_; } void setDelayModelType(DelayModelType type); @@ -371,6 +374,7 @@ protected: SupplyVoltageMap supply_voltage_map_; LibertyCellSeq *buffers_; LibertyCellSeq *inverters_; + LibertyCellFootprintSeq footprints_; DriverWaveformMap driver_waveform_map_; // Unnamed driver waveform. DriverWaveform *driver_waveform_default_; @@ -541,6 +545,8 @@ public: // for all the defined corners. static void checkLibertyCorners(); void ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps); + void setFootprintIndex(LibertyCellFootprintIndex footprint_index); + const char *footprint() const; protected: void addPort(ConcretePort *port); @@ -631,6 +637,7 @@ protected: bool has_internal_ports_; bool have_voltage_waveforms_; std::mutex waveform_lock_; + LibertyCellFootprintIndex footprint_index_; private: friend class LibertyLibrary; diff --git a/liberty/EquivCells.cc b/liberty/EquivCells.cc index 5e43cb98..a9a74130 100644 --- a/liberty/EquivCells.cc +++ b/liberty/EquivCells.cc @@ -325,7 +325,8 @@ equivCells(const LibertyCell *cell1, && equivCellPgPorts(cell1, cell2) && equivCellSequentials(cell1, cell2) && equivCellStatetables(cell1, cell2) - && equivCellTimingArcSets(cell1, cell2); + && equivCellTimingArcSets(cell1, cell2) + && equivCellFootprints(cell1, cell2); } bool @@ -525,4 +526,11 @@ equivCellTimingArcSets(const LibertyCell *cell1, } } +bool +equivCellFootprints(const LibertyCell *cell1, + const LibertyCell *cell2) +{ + return strcmp(cell1->footprint(), cell2->footprint()) == 0; +} + } // namespace diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index ac15e702..173b233d 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -128,6 +128,9 @@ LibertyLibrary::~LibertyLibrary() delete inverters_; driver_waveform_map_.deleteContents(); delete driver_waveform_default_; + + for (auto footprint : footprints_) + stringDelete(footprint); } LibertyCell * @@ -181,6 +184,12 @@ LibertyLibrary::buffers() return buffers_; } +void +LibertyLibrary::addFootprint(const char *footprint) +{ + footprints_.push_back(stringCopy(footprint)); +} + void LibertyLibrary::setDelayModelType(DelayModelType type) { @@ -940,7 +949,8 @@ LibertyCell::LibertyCell(LibertyLibrary *library, leakage_power_(0.0), leakage_power_exists_(false), has_internal_ports_(false), - have_voltage_waveforms_(false) + have_voltage_waveforms_(false), + footprint_index_(-1) { liberty_cell_ = this; } @@ -1989,6 +1999,21 @@ LibertyCell::ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps) } } +void +LibertyCell::setFootprintIndex(LibertyCellFootprintIndex footprint_index) +{ + footprint_index_ = footprint_index; +} + +const char* +LibertyCell::footprint() const +{ + if (footprint_index_ != -1) { + return libertyLibrary()->footprints_[footprint_index_]; + } + return ""; +} + //////////////////////////////////////////////////////////////// LibertyCellPortIterator::LibertyCellPortIterator(const LibertyCell *cell) : diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index b5033005..1bc00da2 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -310,6 +310,7 @@ LibertyReader::defineVisitors() defineAttrVisitor("switch_cell_type", &LibertyReader::visitSwitchCellType); defineAttrVisitor("interface_timing", &LibertyReader::visitInterfaceTiming); defineAttrVisitor("scaling_factors", &LibertyReader::visitScalingFactors); + defineAttrVisitor("cell_footprint", &LibertyReader::visitCellFootprint); // Pins defineGroupVisitor("pin", &LibertyReader::beginPin,&LibertyReader::endPin); @@ -725,6 +726,9 @@ LibertyReader::endLibraryAttrs(LibertyGroup *group) if (missing_threshold) libError(1149, group, "Library %s is missing one or more thresholds.", library_->name()); + + for (auto [footprint, footprint_index] : footprint_index_map_) + stringDelete(footprint); } void @@ -3065,6 +3069,27 @@ LibertyReader::visitClockGatingIntegratedCell(LibertyAttr *attr) } } +void +LibertyReader::visitCellFootprint(LibertyAttr *attr) +{ + if (cell_) { + const char *footprint = getAttrString(attr); + if (!footprint) { + return; + } + LibertyCellFootprintIndex footprint_index; + auto itr = footprint_index_map_.find(footprint); + if (itr != footprint_index_map_.end()) { + footprint_index = itr->second; + } else { + footprint_index = static_cast(footprint_index_map_.size()); + footprint_index_map_[stringCopy(footprint)] = footprint_index; + library()->addFootprint(stringCopy(footprint)); + } + cell_->setFootprintIndex(footprint_index); + } +} + //////////////////////////////////////////////////////////////// void diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 9a812f3c..de146e74 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -65,6 +65,8 @@ typedef Vector LeakagePowerGroupSeq; typedef void (LibertyPort::*LibertyPortBoolSetter)(bool value); typedef Vector OutputWaveformSeq; typedef vector StdStringSeq; +typedef Map LibertyCellFootprintIndexMap; class LibertyReader : public LibertyGroupVisitor { @@ -205,6 +207,7 @@ public: virtual void visitInterfaceTiming(LibertyAttr *attr); virtual void visitScalingFactors(LibertyAttr *attr); virtual void visitCellLeakagePower(LibertyAttr *attr); + virtual void visitCellFootprint(LibertyAttr *attr); virtual void beginPin(LibertyGroup *group); virtual void endPin(LibertyGroup *group); @@ -663,6 +666,7 @@ protected: float reference_time_; bool reference_time_exists_; const char *driver_waveform_name_; + LibertyCellFootprintIndexMap footprint_index_map_; static constexpr char escape_ = '\\';