From 8287aec5f66b880441b9d3ccd3aedd21f0fdd69f Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 7 Nov 2025 11:55:43 -0700 Subject: [PATCH 1/5] Verilog make pins for liberty pg_pins resolves #326 commit b4a89c93965c49a8685fd41cb6aee10635d7a7f3 Author: James Cherry Date: Fri Nov 7 11:48:10 2025 -0700 pg_ -> PwrGnd Signed-off-by: James Cherry commit 12ddba4bf220cec8459c15e483a871b13e507bf2 Author: James Cherry Date: Fri Nov 7 08:56:02 2025 -0700 pg_port Signed-off-by: James Cherry Signed-off-by: James Cherry --- doc/ApiChanges.txt | 3 + doc/ChangeLog.txt | 2 + include/sta/Liberty.hh | 71 +++++++--------------- liberty/EquivCells.cc | 49 --------------- liberty/Liberty.cc | 116 +++++++++++++++--------------------- liberty/Liberty.i | 1 + liberty/LibertyReader.cc | 51 +++++++--------- liberty/LibertyReaderPvt.hh | 2 +- liberty/LibertyWriter.cc | 14 ++++- network/Network.i | 9 +++ power/Power.cc | 12 +++- power/SaifReader.cc | 5 +- power/VcdReader.cc | 20 ++++--- sdc/Sdc.tcl | 31 ++++++++-- sdf/SdfWriter.cc | 70 +++++++++++----------- search/Sta.cc | 3 +- spice/WriteSpice.cc | 22 +++---- spice/WriteSpice.hh | 2 +- verilog/VerilogReader.cc | 18 ++---- 19 files changed, 226 insertions(+), 275 deletions(-) diff --git a/doc/ApiChanges.txt b/doc/ApiChanges.txt index d243dee0..9cda8fa7 100644 --- a/doc/ApiChanges.txt +++ b/doc/ApiChanges.txt @@ -50,6 +50,9 @@ The following classes now return const objects. Transition TimingRole +Liberty PgPorts are now LibertyPorts with additional member functions for +liberty pg_pins. + Release 2.6.1 2025/03/?? ------------------------- diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index bd554c93..932339f8 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -17,6 +17,8 @@ to remove paths through identical pins and rise/fall edges. report_checks [-unique_edges_to_endpoint] +Instances now have pins for verilog netlist power/ground connections, + Release 2.6.1 2025/03/30 ------------------------- diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 7fe410bb..09b4579a 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -43,7 +43,6 @@ class WriteTimingModel; class LibertyCellIterator; class LibertyCellPortIterator; class LibertyCellPortBitIterator; -class LibertyCellPgPortIterator; class LibertyPortMemberIterator; class ModeValueDef; class TestCell; @@ -56,7 +55,6 @@ class LibertyReader; class OcvDerate; class TimingArcAttrs; class InternalPowerAttrs; -class LibertyPgPort; class StaState; class Corner; class Corners; @@ -90,7 +88,6 @@ typedef Vector LatchEnableSeq; typedef Map OcvDerateMap; typedef Vector InternalPowerAttrsSeq; typedef Map SupplyVoltageMap; -typedef Map LibertyPgPortMap; typedef Map DriverWaveformMap; typedef Vector DcalcAnalysisPtSeq; @@ -100,6 +97,12 @@ enum class DelayModelType { cmos_linear, cmos_pwl, cmos2, table, polynomial, dcm enum class ScanSignalType { enable, enable_inverted, clock, clock_a, clock_b, input, input_inverted, output, output_inverted, none }; +enum class PwrGndType { none, + primary_power, primary_ground, + backup_power, backup_ground, + internal_power, internal_ground, + nwell, pwell, + deepnwell, deeppwell}; enum class ScaleFactorPvt { process, volt, temp, unknown }; constexpr int scale_factor_pvt_count = int(ScaleFactorPvt::unknown) + 1; @@ -423,8 +426,6 @@ public: LibertyPort *findLibertyPort(const char *name) const; LibertyPortSeq findLibertyPortsMatching(PatternMatch *pattern) const; bool hasInternalPorts() const { return has_internal_ports_; } - 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); @@ -533,7 +534,6 @@ public: void setOcvArcDepth(float depth); void setOcvDerate(OcvDerate *derate); void addOcvDerate(OcvDerate *derate); - void addPgPort(LibertyPgPort *pg_port); void setTestCell(TestCell *test); void setHasInferedRegTimingArcs(bool infered); void setIsDisabledConstraint(bool is_disabled); @@ -643,7 +643,6 @@ protected: Vector corner_cells_; float leakage_power_; bool leakage_power_exists_; - LibertyPgPortMap pg_port_map_; bool has_internal_ports_; std::atomic have_voltage_waveforms_; std::mutex waveform_lock_; @@ -653,7 +652,6 @@ protected: private: friend class LibertyLibrary; friend class LibertyCellPortIterator; - friend class LibertyCellPgPortIterator; friend class LibertyPort; friend class LibertyBuilder; }; @@ -681,17 +679,6 @@ private: ConcreteCellPortBitIterator *iter_; }; -class LibertyCellPgPortIterator : public Iterator -{ -public: - LibertyCellPgPortIterator(const LibertyCell *cell); - bool hasNext(); - LibertyPgPort *next(); - -private: - LibertyPgPortMap::Iterator iter_; -}; - //////////////////////////////////////////////////////////////// class LibertyPort : public ConcretePort @@ -704,6 +691,16 @@ public: LibertyPort *bundlePort() const; BusDcl *busDcl() const { return bus_dcl_; } void setDirection(PortDirection *dir); + + //////////////////////////////////////////////////////////////// + // pg_pin functions + bool isPwrGnd() const; + PwrGndType pwrGndType() const { return pwr_gnd_type_; } + void setPwrGndType(PwrGndType type); + const char *voltageName() const { return voltage_name_.c_str(); } + void setVoltageName(const char *voltage_name); + //////////////////////////////////////////////////////////////// + ScanSignalType scanSignalType() const { return scan_signal_type_; } void setScanSignalType(ScanSignalType type); void fanoutLoad(// Return values. @@ -887,8 +884,10 @@ protected: LibertyCell *liberty_cell_; BusDcl *bus_dcl_; - FuncExpr *function_; + PwrGndType pwr_gnd_type_; + std::string voltage_name_; ScanSignalType scan_signal_type_; + FuncExpr *function_; FuncExpr *tristate_enable_; ScaledPortMap *scaled_ports_; RiseFallMinMax capacitance_; @@ -1136,37 +1135,13 @@ private: TablePtr derate_[RiseFall::index_count][EarlyLate::index_count][path_type_count]; }; -// Power/ground port. -class LibertyPgPort -{ -public: - enum PgType { unknown, - primary_power, primary_ground, - backup_power, backup_ground, - internal_power, internal_ground, - nwell, pwell, - deepnwell, deeppwell}; - LibertyPgPort(const char *name, - LibertyCell *cell); - const char *name() const { return name_.c_str(); } - LibertyCell *cell() const { return cell_; } - PgType pgType() const { return pg_type_; } - void setPgType(PgType type); - const char *voltageName() const { return voltage_name_.c_str(); } - void setVoltageName(const char *voltage_name); - static bool equiv(const LibertyPgPort *port1, - const LibertyPgPort *port2); - -private: - std::string name_; - PgType pg_type_; - std::string voltage_name_; - LibertyCell *cell_; -}; - std::string portLibertyToSta(const char *port_name); const char * scanSignalTypeName(ScanSignalType scan_type); +const char * +pwrGndTypeName(PwrGndType pwr_gnd_type); +PwrGndType +findPwrGndType(const char *pg_name); } // namespace diff --git a/liberty/EquivCells.cc b/liberty/EquivCells.cc index da960f9c..f8910791 100644 --- a/liberty/EquivCells.cc +++ b/liberty/EquivCells.cc @@ -67,17 +67,9 @@ 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 cellHasFuncs(const LibertyCell *cell); -static bool -equivCellPgPorts(const LibertyCell *cell1, - const LibertyCell *cell2); - static float cellDriveResistance(const LibertyCell *cell) { @@ -201,7 +193,6 @@ static unsigned hashCell(const LibertyCell *cell) { return hashCellPorts(cell) - + hashCellPgPorts(cell) + hashCellSequentials(cell); } @@ -226,25 +217,6 @@ 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) { @@ -333,7 +305,6 @@ equivCells(const LibertyCell *cell1, { return equivCellPorts(cell1, cell2) && equivCellFuncs(cell1, cell2) - && equivCellPgPorts(cell1, cell2) && equivCellSequentials(cell1, cell2) && equivCellStatetables(cell1, cell2) // Reqwuire timing arc equivalence if there are no functions. @@ -347,7 +318,6 @@ equivCellsArcs(const LibertyCell *cell1, { return equivCellPorts(cell1, cell2) && equivCellFuncs(cell1, cell2) - && equivCellPgPorts(cell1, cell2) && equivCellSequentials(cell1, cell2) && equivCellStatetables(cell1, cell2) // Reqwuire timing arc equivalence if there are no functions. @@ -403,25 +373,6 @@ 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 ecf81f24..c4d9fdd3 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -975,8 +975,6 @@ LibertyCell::~LibertyCell() delete test_cell_; ocv_derate_map_.deleteContents(); - - pg_port_map_.deleteContents(); } LibertyPort * @@ -1021,18 +1019,6 @@ LibertyCell::setHasInternalPorts(bool has_internal) has_internal_ports_ = has_internal; } -void -LibertyCell::addPgPort(LibertyPgPort *pg_port) -{ - pg_port_map_[pg_port->name()] = pg_port; -} - -LibertyPgPort * -LibertyCell::findPgPort(const char *name) const -{ - return pg_port_map_.findKey(name); -} - ModeDef * LibertyCell::makeModeDef(const char *name) { @@ -2093,8 +2079,9 @@ LibertyPort::LibertyPort(LibertyCell *cell, ConcretePort(name, is_bus, from_index, to_index, is_bundle, members, cell), liberty_cell_(cell), bus_dcl_(bus_dcl), - function_(nullptr), + pwr_gnd_type_(PwrGndType::none), scan_signal_type_(ScanSignalType::none), + function_(nullptr), tristate_enable_(nullptr), scaled_ports_(nullptr), fanout_load_(0.0), @@ -2168,6 +2155,50 @@ static EnumNameMap scan_signal_type_map = {ScanSignalType::output_inverted, "output_inverted"}, {ScanSignalType::none, "none"}}; +bool +LibertyPort::isPwrGnd() const +{ + return pwr_gnd_type_ != PwrGndType::none; +} + +void +LibertyPort::setPwrGndType(PwrGndType type) +{ + pwr_gnd_type_ = type; +} + +void +LibertyPort::setVoltageName(const char *voltage_name) +{ + voltage_name_ = voltage_name; +} + +static EnumNameMap pwr_gnd_type_map = + {{PwrGndType::none, "node"}, + {PwrGndType::primary_power, "primary_power"}, + {PwrGndType::primary_ground, "primary_ground"}, + {PwrGndType::backup_power, "backup_power"}, + {PwrGndType::backup_ground, "backup_ground"}, + {PwrGndType::internal_power, "internal_power"}, + {PwrGndType::internal_ground, "internal_ground"}, + {PwrGndType::nwell, "nwell"}, + {PwrGndType::pwell, "pwell"}, + {PwrGndType::deepnwell, "deepnwell"}, + {PwrGndType::deeppwell, "deeppwell"}}; + +const char * +pwrGndTypeName(PwrGndType pg_type) +{ + return pwr_gnd_type_map.find(pg_type); +} + +PwrGndType +findPwrGndType(const char *pg_name) +{ + return pwr_gnd_type_map.find(pg_name, PwrGndType::none); +} + +//////////////////////////////////////////////////////////////// const char * scanSignalTypeName(ScanSignalType scan_type) @@ -2526,7 +2557,8 @@ LibertyPort::equiv(const LibertyPort *port1, return (port1 == nullptr && port2 == nullptr) || (port1 != nullptr && port2 != nullptr && stringEq(port1->name(), port2->name()) - && port1->direction() == port2->direction()); + && port1->direction() == port2->direction() + && port1->pwr_gnd_type_ == port2->pwr_gnd_type_); } bool @@ -3330,56 +3362,4 @@ OcvDerate::setDerateTable(const RiseFall *rf, derate_[rf->index()][early_late->index()][int(path_type)] = derate; } -//////////////////////////////////////////////////////////////// - -LibertyPgPort::LibertyPgPort(const char *name, - LibertyCell *cell) : - name_(name), - pg_type_(unknown), - cell_(cell) -{ -} - -void -LibertyPgPort::setPgType(PgType type) -{ - pg_type_ = type; -} - -void -LibertyPgPort::setVoltageName(const char *voltage_name) -{ - voltage_name_ = voltage_name; -} - -bool -LibertyPgPort::equiv(const LibertyPgPort *port1, - const LibertyPgPort *port2) -{ - return 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() -{ - string name; - LibertyPgPort *port; - iter_.next(name, port); - return port; -} - } // namespace diff --git a/liberty/Liberty.i b/liberty/Liberty.i index 4dd5d7a8..e56891e2 100644 --- a/liberty/Liberty.i +++ b/liberty/Liberty.i @@ -317,6 +317,7 @@ bool has_members() { return self->hasMembers(); } LibertyPortMemberIterator * member_iterator() { return new LibertyPortMemberIterator(self); } LibertyPort *bundle_port() { return self->bundlePort(); } +bool is_pwr_gnd() { return self->isPwrGnd(); } string function() diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index df789154..f294244f 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -5670,8 +5670,7 @@ LibertyReader::beginPgPin(LibertyGroup *group) { if (cell_) { const char *name = group->firstName(); - pg_port_ = new LibertyPgPort(name, cell_); - cell_->addPgPort(pg_port_); + pg_port_ = builder_.makePort(cell_, name); } } @@ -5686,35 +5685,27 @@ LibertyReader::visitPgType(LibertyAttr *attr) { if (pg_port_) { const char *type_name = getAttrString(attr); - LibertyPgPort::PgType type = LibertyPgPort::PgType::unknown; - if (stringEqual(type_name, "primary_ground")) - type = LibertyPgPort::PgType::primary_ground; - else if (stringEqual(type_name, "primary_power")) - type = LibertyPgPort::PgType::primary_power; - - else if (stringEqual(type_name, "backup_ground")) - type = LibertyPgPort::PgType::backup_ground; - else if (stringEqual(type_name, "backup_power")) - type = LibertyPgPort::PgType::backup_power; - - else if (stringEqual(type_name, "internal_ground")) - type = LibertyPgPort::PgType::internal_ground; - else if (stringEqual(type_name, "internal_power")) - type = LibertyPgPort::PgType::internal_power; - - else if (stringEqual(type_name, "nwell")) - type = LibertyPgPort::PgType::nwell; - else if (stringEqual(type_name, "pwell")) - type = LibertyPgPort::PgType::pwell; - - else if (stringEqual(type_name, "deepnwell")) - type = LibertyPgPort::PgType::deepnwell; - else if (stringEqual(type_name, "deeppwell")) - type = LibertyPgPort::PgType::deeppwell; - - else + PwrGndType type = findPwrGndType(type_name); + PortDirection *dir = PortDirection::unknown(); + switch (type) { + case PwrGndType::primary_ground:; + case PwrGndType::backup_ground: + case PwrGndType::internal_ground: + dir = PortDirection::ground(); + break; + case PwrGndType::primary_power: + case PwrGndType::backup_power: + case PwrGndType::internal_power: + dir = PortDirection::power(); + break; + case PwrGndType::none: libError(1291, attr, "unknown pg_type."); - pg_port_->setPgType(type); + break; + default: + break; + } + pg_port_->setPwrGndType(type); + pg_port_->setDirection(dir); } } diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 28751eac..c31888f7 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -651,7 +651,7 @@ protected: const EarlyLateAll *derate_type_; const EarlyLateAll *sigma_type_; PathType path_type_; - LibertyPgPort *pg_port_; + LibertyPort *pg_port_; ScaleFactorType scale_factor_type_; TableAxisPtr axis_[3]; TablePtr table_; diff --git a/liberty/LibertyWriter.cc b/liberty/LibertyWriter.cc index e3d31312..10cce09b 100644 --- a/liberty/LibertyWriter.cc +++ b/liberty/LibertyWriter.cc @@ -59,6 +59,7 @@ protected: void writeCells(); void writeCell(const LibertyCell *cell); void writePort(const LibertyPort *port); + void writePwrGndPort(const LibertyPort *port); void writeBusPort(const LibertyPort *port); void writePortAttrs(const LibertyPort *port); void writeTimingArcSet(const TimingArcSet *arc_set); @@ -310,7 +311,9 @@ LibertyWriter::writeCell(const LibertyCell *cell) while (port_iter.hasNext()) { const LibertyPort *port = port_iter.next(); if (!port->direction()->isInternal()) { - if (port->isBus()) + if (port->isPwrGnd()) + writePwrGndPort(port); + else if (port->isBus()) writeBusPort(port); else if (port->isBundle()) report_->error(1340, "%s/%s bundled ports not supported.", @@ -394,6 +397,15 @@ LibertyWriter::writePortAttrs(const LibertyPort *port) } } +void +LibertyWriter::writePwrGndPort(const LibertyPort *port) +{ + fprintf(stream_, " pg_pin(\"%s\") {\n", port->name()); + fprintf(stream_, " pg_type : \"%s\";\n", pwrGndTypeName(port->pwrGndType())); + fprintf(stream_, " voltage_name : \"%s\";\n", port->voltageName()); + fprintf(stream_, " }\n"); +} + // Check if arc is added for port min_pulse_width_high/low attribute. bool LibertyWriter::isAutoWidthArc(const LibertyPort *port, diff --git a/network/Network.i b/network/Network.i index 2d63b9e2..52bf1ca0 100644 --- a/network/Network.i +++ b/network/Network.i @@ -753,6 +753,15 @@ bool is_top_level_port() { return Sta::sta()->ensureLinked()->isTopLevelPort(sel PinConnectedPinIterator *connected_pin_iterator() { return Sta::sta()->ensureLinked()->connectedPinIterator(self); } +bool +is_pwr_gnd() +{ + sta::Sta *sta = Sta::sta(); + Network *network = sta->network(); + LibertyPort *lib_port = network->libertyPort(self); + return lib_port && lib_port->isPwrGnd(); +} + Vertex ** vertices() { diff --git a/power/Power.cc b/power/Power.cc index dbf55a27..25e19e9d 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -1368,7 +1368,7 @@ Power::pgNameVoltage(LibertyCell *cell, const DcalcAnalysisPt *dcalc_ap) { if (pg_port_name) { - LibertyPgPort *pg_port = cell->findPgPort(pg_port_name); + LibertyPort *pg_port = cell->findLibertyPort(pg_port_name); if (pg_port) { const char *volt_name = pg_port->voltageName(); LibertyLibrary *library = cell->libertyLibrary(); @@ -1484,14 +1484,17 @@ Power::findUnannotatedPins(const Instance *inst, InstancePinIterator *pin_iter = network_->pinIterator(inst); while (pin_iter->hasNext()) { const Pin *pin = pin_iter->next(); + LibertyPort *liberty_port = sdc_network_->libertyPort(pin); if (!network_->direction(pin)->isInternal() + && !network_->direction(pin)->isPowerGround() + && !(liberty_port && liberty_port->isPwrGnd()) && user_activity_map_.find(pin) == user_activity_map_.end()) unannotated_pins.push_back(pin); } delete pin_iter; } -// leaf pins - internal pins + top instance pins +// leaf pins - internal pins - power/ground pins + top instance pins size_t Power::pinCount() { @@ -1502,7 +1505,10 @@ Power::pinCount() InstancePinIterator *pin_iter = network_->pinIterator(leaf); while (pin_iter->hasNext()) { const Pin *pin = pin_iter->next(); - if (!network_->direction(pin)->isInternal()) + LibertyPort *liberty_port = sdc_network_->libertyPort(pin); + if (!network_->direction(pin)->isInternal() + && !network_->direction(pin)->isPowerGround() + && !(liberty_port && liberty_port->isPwrGnd())) count++; } delete pin_iter; diff --git a/power/SaifReader.cc b/power/SaifReader.cc index 8571189e..ecd14277 100644 --- a/power/SaifReader.cc +++ b/power/SaifReader.cc @@ -33,6 +33,7 @@ #include "Report.hh" #include "Network.hh" #include "PortDirection.hh" +#include "Liberty.hh" #include "Sdc.hh" #include "Power.hh" #include "power/SaifReaderPvt.hh" @@ -168,9 +169,11 @@ SaifReader::setNetDurations(const char *net_name, if (parent) { string unescaped_name = unescaped(net_name); const Pin *pin = sdc_network_->findPin(parent, unescaped_name.c_str()); + LibertyPort *liberty_port = pin ? sdc_network_->libertyPort(pin) : nullptr; if (pin && !sdc_network_->isHierarchical(pin) - && !sdc_network_->direction(pin)->isInternal()) { + && !sdc_network_->direction(pin)->isInternal() + && !(liberty_port && liberty_port->isPwrGnd())) { double t1 = durations[static_cast(SaifState::T1)]; float duty = t1 / duration_; double tc = durations[static_cast(SaifState::TC)]; diff --git a/power/VcdReader.cc b/power/VcdReader.cc index fba64872..77059615 100644 --- a/power/VcdReader.cc +++ b/power/VcdReader.cc @@ -30,6 +30,7 @@ #include "VcdParse.hh" #include "Debug.hh" #include "Network.hh" +#include "Liberty.hh" #include "PortDirection.hh" #include "VerilogNamespace.hh" #include "ParseBus.hh" @@ -284,13 +285,16 @@ VcdCountReader::addVarPin(const string &pin_name, size_t bit_idx) { const Pin *pin = sdc_network_->findPin(pin_name.c_str()); + LibertyPort *liberty_port = pin ? sdc_network_->libertyPort(pin) : nullptr; if (pin && !sdc_network_->isHierarchical(pin) - && !sdc_network_->direction(pin)->isInternal()) { + && !sdc_network_->direction(pin)->isInternal() + && !sdc_network_->direction(pin)->isPowerGround() + && !(liberty_port && liberty_port->isPwrGnd())) { VcdCounts &vcd_counts = vcd_count_map_[id]; vcd_counts.resize(width); vcd_counts[bit_idx].addPin(pin); - debugPrint(debug_, "read_vcd_activities", 2, "id %s pin %s", + debugPrint(debug_, "read_vcd", 2, "id %s pin %s", id.c_str(), pin_name.c_str()); } @@ -304,11 +308,11 @@ VcdCountReader::varAppendValue(const string &id, const auto &itr = vcd_count_map_.find(id); if (itr != vcd_count_map_.end()) { VcdCounts &vcd_counts = itr->second; - if (debug_->check("read_vcd_activities", 3)) { + if (debug_->check("read_vcd", 3)) { for (size_t bit_idx = 0; bit_idx < vcd_counts.size(); bit_idx++) { VcdCount &vcd_count = vcd_counts[bit_idx]; for (const Pin *pin : vcd_count.pins()) { - debugPrint(debug_, "read_vcd_activities", 3, "%s time %" PRIu64 " value %c", + debugPrint(debug_, "read_vcd", 3, "%s time %" PRIu64 " value %c", sdc_network_->pathName(pin), time, value); @@ -333,9 +337,9 @@ VcdCountReader::varAppendBusValue(const string &id, for (size_t bit_idx = 0; bit_idx < vcd_counts.size(); bit_idx++) { char bit_value = ((bus_value >> bit_idx) & 0x1) ? '1' : '0'; VcdCount &vcd_count = vcd_counts[bit_idx]; - if (debug_->check("read_vcd_activities", 3)) { + if (debug_->check("read_vcd", 3)) { for (const Pin *pin : vcd_count.pins()) { - debugPrint(debug_, "read_vcd_activities", 3, "%s time %" PRIu64 " value %c", + debugPrint(debug_, "read_vcd", 3, "%s time %" PRIu64 " value %c", sdc_network_->pathName(pin), time, bit_value); @@ -420,9 +424,9 @@ ReadVcdActivities::setActivities() VcdTime high_time = vcd_count.highTime(time_max); float duty = static_cast(high_time) / time_delta; float density = transition_count / (time_delta * time_scale); - if (debug_->check("read_vcd_activities", 1)) { + if (debug_->check("read_vcd", 1)) { for (const Pin *pin : vcd_count.pins()) { - debugPrint(debug_, "read_vcd_activities", 1, + debugPrint(debug_, "read_vcd", 1, "%s transitions %.1f activity %.2f duty %.2f", sdc_network_->pathName(pin), transition_count, diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index 7c846cd6..d61b3ddd 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -578,7 +578,12 @@ proc get_lib_pins { args } { } set libcells [get_libcells_error "objects" $keys(-of_objects)] foreach libcell $libcells { - lappend ports {*}[$libcell find_liberty_ports_matching * 0 1] + foreach port [$libcell find_liberty_ports_matching * 0 1] { + # Filter pg ports. + if { ![$port is_pwr_gnd] } { + lappend ports $port + } + } } } else { foreach pattern $patterns { @@ -610,8 +615,11 @@ proc get_lib_pins { args } { set matches [$cell find_liberty_ports_matching $port_pattern \ $regexp $nocase] foreach match $matches { - lappend ports $match - set found_match 1 + # Filter pg ports. + if { ![$match is_pwr_gnd] } { + lappend ports $match + set found_match 1 + } } } } @@ -814,7 +822,10 @@ proc get_pins { args } { set pin_iter [$inst pin_iterator] while { [$pin_iter has_next] } { set pin [$pin_iter next] - lappend pins $pin + # Filter pg ports. + if { ![$pin is_pwr_gnd] } { + lappend pins $pin + } } $pin_iter finish } @@ -822,7 +833,10 @@ proc get_pins { args } { set pin_iter [$net pin_iterator] while { [$pin_iter has_next] } { set pin [$pin_iter next] - lappend pins $pin + # Filter pg ports. + if { ![$pin is_pwr_gnd] } { + lappend pins $pin + } } $pin_iter finish } @@ -852,7 +866,12 @@ proc get_pins { args } { } else { set matches [find_pins_matching $pattern $regexp $nocase] } - set pins [concat $pins $matches] + foreach match $matches { + # Filter pg ports. + if { ![$match is_pwr_gnd] } { + lappend pins $match + } + } if { $matches == {} && !$quiet } { sta_warn 363 "pin '$pattern' not found." } diff --git a/sdf/SdfWriter.cc b/sdf/SdfWriter.cc index 81b64396..2c2bfa82 100644 --- a/sdf/SdfWriter.cc +++ b/sdf/SdfWriter.cc @@ -514,42 +514,44 @@ SdfWriter::writeTimingChecks(const Instance *inst, while (pin_iter->hasNext()) { Pin *pin = pin_iter->next(); Vertex *vertex = graph_->pinLoadVertex(pin); - VertexOutEdgeIterator edge_iter(vertex, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - const TimingRole *role = edge->role(); - const char *sdf_check = nullptr; - if (role == TimingRole::setup()) - sdf_check = "SETUP"; - else if (role == TimingRole::hold()) - sdf_check = "HOLD"; - else if (role == TimingRole::recovery()) - sdf_check = "RECOVERY"; - else if (role == TimingRole::removal()) - sdf_check = "REMOVAL"; - if (sdf_check) { - ensureTimingCheckheaders(check_header, inst, inst_header); - writeCheck(edge, sdf_check); + if (vertex) { + VertexOutEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + const TimingRole *role = edge->role(); + const char *sdf_check = nullptr; + if (role == TimingRole::setup()) + sdf_check = "SETUP"; + else if (role == TimingRole::hold()) + sdf_check = "HOLD"; + else if (role == TimingRole::recovery()) + sdf_check = "RECOVERY"; + else if (role == TimingRole::removal()) + sdf_check = "REMOVAL"; + if (sdf_check) { + ensureTimingCheckheaders(check_header, inst, inst_header); + writeCheck(edge, sdf_check); + } } - } - for (auto hi_low : RiseFall::range()) { - float min_width, max_width; - Edge *edge; - TimingArc *arc; - graph_->minPulseWidthArc(vertex, hi_low, edge, arc); - if (edge) { - min_width = delayAsFloat(graph_->arcDelay(edge, arc, arc_delay_min_index_)); - max_width = delayAsFloat(graph_->arcDelay(edge, arc, arc_delay_max_index_)); - ensureTimingCheckheaders(check_header, inst, inst_header); - writeWidthCheck(pin, hi_low, min_width, max_width); + for (auto hi_low : RiseFall::range()) { + float min_width, max_width; + Edge *edge; + TimingArc *arc; + graph_->minPulseWidthArc(vertex, hi_low, edge, arc); + if (edge) { + min_width = delayAsFloat(graph_->arcDelay(edge, arc, arc_delay_min_index_)); + max_width = delayAsFloat(graph_->arcDelay(edge, arc, arc_delay_max_index_)); + ensureTimingCheckheaders(check_header, inst, inst_header); + writeWidthCheck(pin, hi_low, min_width, max_width); + } + } + float min_period; + bool exists; + graph_delay_calc_->minPeriod(pin, corner_, min_period, exists); + if (exists) { + ensureTimingCheckheaders(check_header, inst, inst_header); + writePeriodCheck(pin, min_period); } - } - float min_period; - bool exists; - graph_delay_calc_->minPeriod(pin, corner_, min_period, exists); - if (exists) { - ensureTimingCheckheaders(check_header, inst, inst_header); - writePeriodCheck(pin, min_period); } } delete pin_iter; diff --git a/search/Sta.cc b/search/Sta.cc index 75c1c26a..44da4a79 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -4303,7 +4303,8 @@ Sta::replaceEquivCellBefore(const Instance *inst, else { // Force delay calculation on output pins. Vertex *vertex = graph_->pinDrvrVertex(pin); - graph_delay_calc_->delayInvalid(vertex); + if (vertex) + graph_delay_calc_->delayInvalid(vertex); } } } diff --git a/spice/WriteSpice.cc b/spice/WriteSpice.cc index 6fddecf3..2d4296e7 100644 --- a/spice/WriteSpice.cc +++ b/spice/WriteSpice.cc @@ -261,7 +261,7 @@ WriteSpice::recordSpicePortNames(const char *cell_name, for (size_t i = 2; i < tokens.size(); i++) { const char *port_name = tokens[i].c_str(); LibertyPort *port = cell->findLibertyPort(port_name); - LibertyPgPort *pg_port = cell->findPgPort(port_name); + LibertyPort *pg_port = cell->findLibertyPort(port_name); if (port == nullptr && pg_port == nullptr && !stringEqual(port_name, power_name_) @@ -326,7 +326,7 @@ WriteSpice::writeSubcktInst(const Instance *inst) for (string subckt_port_name : spice_port_names) { const char *subckt_port_cname = subckt_port_name.c_str(); Pin *pin = network_->findPin(inst, subckt_port_cname); - LibertyPgPort *pg_port = cell->findPgPort(subckt_port_cname); + LibertyPort *pg_port = cell->findLibertyPort(subckt_port_cname); const char *pin_name; if (pin) { pin_name = network_->pathName(pin); @@ -357,13 +357,13 @@ WriteSpice::writeSubcktInstVoltSrcs(const Instance *inst, const char *subckt_port_name = subckt_port_sname.c_str(); LibertyPort *port = cell->findLibertyPort(subckt_port_name); const Pin *pin = port ? network_->findPin(inst, port) : nullptr; - LibertyPgPort *pg_port = cell->findPgPort(subckt_port_name); + bool is_pg_port = port && port->isPwrGnd(); debugPrint(debug_, "write_spice", 2, " port %s%s", subckt_port_name, - pg_port ? " pwr/gnd" : ""); - if (pg_port) + is_pg_port ? " pwr/gnd" : ""); + if (is_pg_port) writeVoltageSource(inst_name, subckt_port_name, - pgPortVoltage(pg_port)); + pgPortVoltage(port)); else if (stringEq(subckt_port_name, power_name_)) writeVoltageSource(inst_name, subckt_port_name, power_voltage_); else if (stringEq(subckt_port_name, gnd_name_)) @@ -420,7 +420,7 @@ WriteSpice::writeVoltageSource(LibertyCell *cell, float voltage) { if (pg_port_name) { - LibertyPgPort *pg_port = cell->findPgPort(pg_port_name); + LibertyPort *pg_port = cell->findLibertyPort(pg_port_name); if (pg_port) voltage = pgPortVoltage(pg_port); else @@ -433,9 +433,9 @@ WriteSpice::writeVoltageSource(LibertyCell *cell, } float -WriteSpice::pgPortVoltage(LibertyPgPort *pg_port) +WriteSpice::pgPortVoltage(LibertyPort *pg_port) { - LibertyLibrary *liberty = pg_port->cell()->libertyLibrary(); + LibertyLibrary *liberty = pg_port->libertyCell()->libertyLibrary(); float voltage = 0.0; bool exists; const char *voltage_name = pg_port->voltageName(); @@ -448,14 +448,14 @@ WriteSpice::pgPortVoltage(LibertyPgPort *pg_port) voltage = gnd_voltage_; else report_->error(1601 , "pg_pin %s/%s voltage %s not found,", - pg_port->cell()->name(), + pg_port->libertyCell()->name(), pg_port->name(), voltage_name); } } else report_->error(1602, "Liberty pg_port %s/%s missing voltage_name attribute,", - pg_port->cell()->name(), + pg_port->libertyCell()->name(), pg_port->name()); return voltage; } diff --git a/spice/WriteSpice.hh b/spice/WriteSpice.hh index 05be3912..98995a44 100644 --- a/spice/WriteSpice.hh +++ b/spice/WriteSpice.hh @@ -73,7 +73,7 @@ protected: void writeSubcktInstVoltSrcs(const Instance *inst, LibertyPortLogicValues &port_values, const PinSet &excluded_input_pins); - float pgPortVoltage(LibertyPgPort *pg_port); + float pgPortVoltage(LibertyPort *pg_port); void writeVoltageSource(const char *inst_name, const char *port_name, float voltage); diff --git a/verilog/VerilogReader.cc b/verilog/VerilogReader.cc index 96fe9ca6..b7e0260f 100644 --- a/verilog/VerilogReader.cc +++ b/verilog/VerilogReader.cc @@ -1900,19 +1900,11 @@ VerilogReader::makeNamedInstPins(Cell *cell, delete net_name_iter; } } - else { - LibertyPgPort *pg_port = nullptr; - LibertyCell *lib_cell = network_->libertyCell(cell); - if (lib_cell) - pg_port = lib_cell->findPgPort(port_name); - // Do not warn about connections to pg ports (which are ignored). - if (pg_port == nullptr) { - linkWarn(201, parent_module->filename(), mod_inst->line(), - "instance %s port %s not found.", - inst_vname.c_str(), - port_name); - } - } + else + linkWarn(201, parent_module->filename(), mod_inst->line(), + "instance %s port %s not found.", + inst_vname.c_str(), + port_name); } } From 82a37d0777006d5584be6f90b4d57de075f19b95 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 8 Nov 2025 13:38:07 -0700 Subject: [PATCH 2/5] sdc ExceptionPathSet*->ExceptionPathSet commit 277de17b34f4b36b9c889f883872c604b39a7558 Author: James Cherry Date: Sat Nov 8 12:53:22 2025 -0700 ExceptionPathSet Set -> std::set Signed-off-by: James Cherry commit ce9afb6d29a5532b9b5fdadcdaf48aeaf1ba9c99 Author: James Cherry Date: Sat Nov 8 12:17:01 2025 -0700 ExceptionPathSet*->ExceptionPathSet Signed-off-by: James Cherry Signed-off-by: James Cherry --- include/sta/Sdc.hh | 15 +- include/sta/SdcClass.hh | 2 +- sdc/Sdc.cc | 397 ++++++++++++++++++++++------------------ sdc/WriteSdc.cc | 2 +- search/CheckTiming.cc | 5 +- 5 files changed, 230 insertions(+), 191 deletions(-) diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index 84914596..622ca6b7 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -136,15 +136,15 @@ typedef Set InputDelaySet; typedef Map InputDelaysPinMap; typedef Set OutputDelaySet; typedef Map OutputDelaysPinMap; -typedef UnorderedMap PinExceptionsMap; -typedef Map ClockExceptionsMap; -typedef Map InstanceExceptionsMap; -typedef Map NetExceptionsMap; -typedef UnorderedMap PinExceptionsMap; +typedef UnorderedMap ClockExceptionsMap; +typedef UnorderedMap InstanceExceptionsMap; +typedef UnorderedMap NetExceptionsMap; +typedef UnorderedMap EdgeExceptionsMap; typedef Vector ExceptionThruSeq; typedef Map InputDriveMap; -typedef Map > ExceptionPathPtHash; +typedef Map> ExceptionPathPtHash; typedef Set ClockLatencies; typedef Map PinClockUncertaintyMap; typedef Set InterClockUncertaintySet; @@ -1018,7 +1018,7 @@ public: const PinSet &pathDelayInternalFrom() const; bool isPathDelayInternalTo(const Pin *pin) const; bool isPathDelayInternalToBreak(const Pin *pin) const; - ExceptionPathSet *exceptions() { return &exceptions_; } + ExceptionPathSet &exceptions() { return exceptions_; } void deleteExceptions(); void deleteException(ExceptionPath *exception); void recordException(ExceptionPath *exception); @@ -1043,7 +1043,6 @@ protected: void removeLibertyAnnotations(); void deleteExceptionsReferencing(Clock *clk); void deleteClkPinMappings(Clock *clk); - void deleteExceptionPtHashMapSets(ExceptionPathPtHash &map); void makeClkPinMappings(Clock *clk); void deletePinClocks(Clock *defining_clk, PinSet *pins); diff --git a/include/sta/SdcClass.hh b/include/sta/SdcClass.hh index a6a5a49a..cb5e6712 100644 --- a/include/sta/SdcClass.hh +++ b/include/sta/SdcClass.hh @@ -95,7 +95,7 @@ typedef Set LibertyPortPairSet; typedef Map DisabledInstancePortsMap; typedef Map DisabledCellPortsMap; typedef MinMaxValues ClockUncertainties; -typedef Set ExceptionPathSet; +typedef std::set ExceptionPathSet; typedef PinPair EdgePins; typedef PinPairSet EdgePinsSet; typedef Map LogicValueMap; diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index b10a7add..d44979a9 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -3957,13 +3957,29 @@ Sdc::unrecordPathDelayInternalFrom(ExceptionPath *exception) } } +template +const ExceptionPathSet * +findExceptions(const UnorderedMap &map, + const OBJ *obj) +{ + const auto itr = map.find(obj); + if (itr != map.end()) + return &itr->second; + else + return nullptr; +} + bool Sdc::pathDelayFrom(const Pin *pin) { - ExceptionPathSet *exceptions = first_from_pin_exceptions_.findKey(pin); - for (ExceptionPath *exception : *exceptions) { - if (exception->isPathDelay()) - return true; + + const ExceptionPathSet *exceptions = + findExceptions(first_from_pin_exceptions_, pin); + if (exceptions) { + for (ExceptionPath *exception : *exceptions) { + if (exception->isPathDelay()) + return true; + } } return false; } @@ -4042,10 +4058,13 @@ Sdc::hasLibertyCheckTo(const Pin *pin) bool Sdc::pathDelayTo(const Pin *pin) { - ExceptionPathSet *exceptions = first_to_pin_exceptions_.findKey(pin); - for (ExceptionPath *exception : *exceptions) { - if (exception->isPathDelay()) - return true; + const ExceptionPathSet *exceptions = + findExceptions(first_to_pin_exceptions_, pin); + if (exceptions) { + for (ExceptionPath *exception : *exceptions) { + if (exception->isPathDelay()) + return true; + } } return false; } @@ -4210,11 +4229,14 @@ void Sdc::deleteLoopExceptions() { // erase prevents range iteration. - ExceptionPathSet::Iterator except_iter(exceptions_); - while (except_iter.hasNext()) { - ExceptionPath *except = except_iter.next(); - if (except->isLoop()) - deleteException(except); + for (auto itr = exceptions_.begin(); itr != exceptions_.end(); ) { + ExceptionPath *except = *itr; + if (except->isLoop()) { + itr = exceptions_.erase(itr); + deleteException(except); + } + else + itr++; } } @@ -4420,10 +4442,10 @@ Sdc::findMatchingExceptionsFirstThru(ExceptionPath *exception, for (const Net *net : *thru->nets()) { // Potential matches includes exceptions that match net that are not // the first exception point. - ExceptionPathSet *potential_matches = - first_thru_net_exceptions_.findKey(net); + const ExceptionPathSet *potential_matches = + findExceptions(first_thru_net_exceptions_, net); if (potential_matches) { - for (ExceptionPath *match : *potential_matches) { + for (ExceptionPath *match : *potential_matches) { ExceptionThru *match_thru = (*match->thrus())[0]; if (match_thru->nets()->hasKey(net) && match->overrides(exception) @@ -4457,8 +4479,11 @@ Sdc::findMatchingExceptionsClks(ExceptionPath *exception, { if (clks) { ExceptionPathSet clks_matches; - for (Clock *clk : *clks) - clks_matches.insertSet(exception_map.findKey(clk)); + for (Clock *clk : *clks) { + auto itr = exception_map.find(clk); + if (itr != exception_map.end()) + clks_matches.insert(itr->second.begin(), itr->second.end()); + } findMatchingExceptions(exception, &clks_matches, matches); } } @@ -4471,8 +4496,11 @@ Sdc::findMatchingExceptionsPins(ExceptionPath *exception, { if (pins) { ExceptionPathSet pins_matches; - for (const Pin *pin : *pins) - pins_matches.insertSet(exception_map.findKey(pin)); + for (const Pin *pin : *pins) { + auto itr = exception_map.find(pin); + if (itr != exception_map.end()) + pins_matches.insert(itr->second.begin(), itr->second.end()); + } findMatchingExceptions(exception, &pins_matches, matches); } } @@ -4484,10 +4512,13 @@ Sdc::findMatchingExceptionsInsts(ExceptionPath *exception, ExceptionPathSet &matches) { if (insts) { - ExceptionPathSet insts_matches; - for (const Instance *inst : *insts) - insts_matches.insertSet(exception_map.findKey(inst)); - findMatchingExceptions(exception, &insts_matches, matches); + ExceptionPathSet inst_matches; + for (const Instance *inst : *insts) { + auto itr = exception_map.find(inst); + if (itr != exception_map.end()) + inst_matches.insert(itr->second.begin(), itr->second.end()); + } + findMatchingExceptions(exception, &inst_matches, matches); } } @@ -4639,12 +4670,8 @@ Sdc::recordMergeHash(ExceptionPath *exception, hash, exception->asString(network_), missing_pt->asString(network_)); - ExceptionPathSet *set = exception_merge_hash_.findKey(hash); - if (set == nullptr) { - set = new ExceptionPathSet; - exception_merge_hash_[hash] = set; - } - set->insert(exception); + ExceptionPathSet &set = exception_merge_hash_[hash]; + set.insert(exception); } // Record a mapping from first pin/clock/instance's to a set of exceptions. @@ -4716,12 +4743,8 @@ Sdc::recordExceptionClks(ExceptionPath *exception, { if (clks) { for (Clock *clk : *clks) { - ExceptionPathSet *set = exception_map.findKey(clk); - if (set == nullptr) { - set = new ExceptionPathSet; - exception_map[clk] = set; - } - set->insert(exception); + ExceptionPathSet &set = exception_map[clk]; + set.insert(exception); } } } @@ -4733,12 +4756,8 @@ Sdc::recordExceptionEdges(ExceptionPath *exception, { if (edges) { for (const EdgePins &edge : *edges) { - ExceptionPathSet *set = exception_map.findKey(edge); - if (set == nullptr) { - set = new ExceptionPathSet; - exception_map.insert(edge, set); - } - set->insert(exception); + ExceptionPathSet &set = exception_map[edge]; + set.insert(exception); } } } @@ -4750,12 +4769,8 @@ Sdc::recordExceptionPins(ExceptionPath *exception, { if (pins) { for (const Pin *pin : *pins) { - ExceptionPathSet *set = exception_map.findKey(pin); - if (set == nullptr) { - set = new ExceptionPathSet; - exception_map.insert(pin, set); - } - set->insert(exception); + ExceptionPathSet &set = exception_map[pin]; + set.insert(exception); } } } @@ -4765,12 +4780,8 @@ Sdc::recordExceptionHpin(ExceptionPath *exception, Pin *pin, PinExceptionsMap &exception_map) { - ExceptionPathSet *set = exception_map.findKey(pin); - if (set == nullptr) { - set = new ExceptionPathSet; - exception_map.insert(pin, set); - } - set->insert(exception); + ExceptionPathSet &set = exception_map[pin]; + set.insert(exception); } void @@ -4780,12 +4791,8 @@ Sdc::recordExceptionInsts(ExceptionPath *exception, { if (insts) { for (const Instance *inst : *insts) { - ExceptionPathSet *set = exception_map.findKey(inst); - if (set == nullptr) { - set = new ExceptionPathSet; - exception_map[inst] = set; - } - set->insert(exception); + ExceptionPathSet &set = exception_map[inst]; + set.insert(exception); } } } @@ -4797,12 +4804,8 @@ Sdc::recordExceptionNets(ExceptionPath *exception, { if (nets) { for (const Net *net : *nets) { - ExceptionPathSet *set = exception_map.findKey(net); - if (set == nullptr) { - set = new ExceptionPathSet; - exception_map[net] = set; - } - set->insert(exception); + ExceptionPathSet &set = exception_map[net]; + set.insert(exception); } } } @@ -4836,9 +4839,10 @@ Sdc::findMergeMatch(ExceptionPath *exception) while (missing_pt_iter.hasNext()) { ExceptionPt *missing_pt = missing_pt_iter.next(); size_t hash = exception->hash(missing_pt); - ExceptionPathSet *matches = exception_merge_hash_.findKey(hash); - if (matches) { - for (ExceptionPath *match : *matches) { + auto itr = exception_merge_hash_.find(hash); + if (itr != exception_merge_hash_.end()) { + ExceptionPathSet &matches = itr->second; + for (ExceptionPath *match : matches) { ExceptionPt *match_missing_pt; if (match != exception // Exceptions are not merged if their priorities are @@ -4876,59 +4880,52 @@ Sdc::findMergeMatch(ExceptionPath *exception) void Sdc::deleteExceptions() { - exceptions_.deleteContentsClear(); + exceptions_.clear(); exception_id_ = 0; - first_from_pin_exceptions_.deleteContentsClear(); - first_from_clk_exceptions_.deleteContentsClear(); - first_from_inst_exceptions_.deleteContentsClear(); - first_to_pin_exceptions_.deleteContentsClear(); - first_to_clk_exceptions_.deleteContentsClear(); - first_to_inst_exceptions_.deleteContentsClear(); - first_thru_pin_exceptions_.deleteContentsClear(); - first_thru_inst_exceptions_.deleteContentsClear(); - first_thru_net_exceptions_.deleteContentsClear(); - first_thru_edge_exceptions_.deleteContentsClear(); + first_from_pin_exceptions_.clear(); + first_from_clk_exceptions_.clear(); + first_from_inst_exceptions_.clear(); + first_to_pin_exceptions_.clear(); + first_to_clk_exceptions_.clear(); + first_to_inst_exceptions_.clear(); + first_thru_pin_exceptions_.clear(); + first_thru_inst_exceptions_.clear(); + first_thru_net_exceptions_.clear(); + first_thru_edge_exceptions_.clear(); first_thru_edge_exceptions_.clear(); path_delay_internal_from_.clear(); path_delay_internal_from_break_.clear(); path_delay_internal_to_.clear(); path_delay_internal_to_break_.clear(); - pin_exceptions_.deleteContentsClear(); + pin_exceptions_.clear(); - deleteExceptionPtHashMapSets(exception_merge_hash_); + exception_merge_hash_.clear(); exception_merge_hash_.clear(); have_thru_hpin_exceptions_ = false; } -void -Sdc::deleteExceptionPtHashMapSets(ExceptionPathPtHash &map) -{ - map.deleteContents(); -} - //////////////////////////////////////////////////////////////// void Sdc::deleteExceptionsReferencing(Clock *clk) { // erase prevents range iteration. - ExceptionPathSet::ConstIterator exception_iter(exceptions_); - while (exception_iter.hasNext()) { - ExceptionPath *exception = exception_iter.next(); + for (auto itr = exceptions_.begin(); itr != exceptions_.end(); ) { + ExceptionPath *exception = *itr; bool deleted = false; ExceptionFrom *from = exception->from(); if (from) { ClockSet *clks = from->clks(); if (clks && clks->hasKey(clk)) { + itr = exceptions_.erase(itr); unrecordException(exception); + deleted = true; from->deleteClock(clk); if (from->hasObjects()) recordException(exception); - else { + else deleteException(exception); - deleted = true; - } } } @@ -4937,6 +4934,8 @@ Sdc::deleteExceptionsReferencing(Clock *clk) if (to) { ClockSet *clks = to->clks(); if (clks && clks->hasKey(clk)) { + itr = exceptions_.erase(itr); + deleted = true; unrecordException(exception); to->deleteClock(clk); if (to->hasObjects()) @@ -4946,6 +4945,8 @@ Sdc::deleteExceptionsReferencing(Clock *clk) } } } + if (!deleted) + itr++; } } @@ -4986,9 +4987,11 @@ Sdc::unrecordMergeHash(ExceptionPath *exception, hash, exception->asString(network_), missing_pt->asString(network_)); - ExceptionPathSet *matches = exception_merge_hash_.findKey(hash); - if (matches) - matches->erase(exception); + auto itr = exception_merge_hash_.find(hash); + if (itr != exception_merge_hash_.end()) { + ExceptionPathSet &matches = itr->second; + matches.erase(exception); + } } void @@ -5026,9 +5029,11 @@ Sdc::unrecordExceptionClks(ExceptionPath *exception, { if (clks) { for (Clock *clk : *clks) { - ExceptionPathSet *set = exception_map.findKey(clk); - if (set) - set->erase(exception); + auto itr = exception_map.find(clk); + if (itr != exception_map.end()) { + ExceptionPathSet &set = itr->second; + set.erase(exception); + } } } } @@ -5040,9 +5045,11 @@ Sdc::unrecordExceptionPins(ExceptionPath *exception, { if (pins) { for (const Pin *pin : *pins) { - ExceptionPathSet *set = exception_map.findKey(pin); - if (set) - set->erase(exception); + auto itr = exception_map.find(pin); + if (itr != exception_map.end()) { + ExceptionPathSet &set = itr->second; + set.erase(exception); + } } } } @@ -5054,9 +5061,11 @@ Sdc::unrecordExceptionInsts(ExceptionPath *exception, { if (insts) { for (const Instance *inst : *insts) { - ExceptionPathSet *set = exception_map.findKey(inst); - if (set) - set->erase(exception); + auto itr = exception_map.find(inst); + if (itr != exception_map.end()) { + ExceptionPathSet &set = itr->second; + set.erase(exception); + } } } } @@ -5068,9 +5077,11 @@ Sdc::unrecordExceptionEdges(ExceptionPath *exception, { if (edges) { for (const EdgePins &edge : *edges) { - ExceptionPathSet *set = exception_map.findKey(edge); - if (set) - set->erase(exception); + auto itr = exception_map.find(edge); + if (itr != exception_map.end()) { + ExceptionPathSet &set = itr->second; + set.erase(exception); + } } } } @@ -5082,9 +5093,11 @@ Sdc::unrecordExceptionNets(ExceptionPath *exception, { if (nets) { for (const Net *net : *nets) { - ExceptionPathSet *set = exception_map.findKey(net); - if (set) - set->erase(exception); + auto itr = exception_map.find(net); + if (itr != exception_map.end()) { + ExceptionPathSet &set = itr->second; + set.erase(exception); + } } } } @@ -5094,9 +5107,11 @@ Sdc::unrecordExceptionHpin(ExceptionPath *exception, Pin *pin, PinExceptionsMap &exception_map) { - ExceptionPathSet *set = exception_map.findKey(pin); - if (set) - set->erase(exception); + auto itr = exception_map.find(pin); + if (itr != exception_map.end()) { + ExceptionPathSet &set = itr->second; + set.erase(exception); + } } //////////////////////////////////////////////////////////////// @@ -5166,18 +5181,18 @@ Sdc::resetPath(ExceptionFrom *from, const MinMaxAll *min_max) { checkFromThrusTo(from, thrus, to); - ExceptionPathSet::Iterator except_iter(exceptions_); - while (except_iter.hasNext()) { - ExceptionPath *match = except_iter.next(); + // erase prevents range iteration. + for (auto itr = exceptions_.begin(); itr != exceptions_.end(); ) { + ExceptionPath *match = *itr; if (match->resetMatch(from, thrus, to, min_max, network_)) { debugPrint(debug_, "exception_match", 3, "reset match %s", match->asString(network_)); ExceptionPathSet expansions; expandException(match, expansions); + itr = exceptions_.erase(itr); deleteException(match); - ExceptionPathSet::Iterator expand_iter(expansions); - while (expand_iter.hasNext()) { - ExceptionPath *expand = expand_iter.next(); + + for (ExceptionPath *expand : expansions) { if (expand->resetMatch(from, thrus, to, min_max, network_)) { unrecordPathDelayInternalFrom(expand); unrecordPathDelayInternalTo(expand); @@ -5187,6 +5202,8 @@ Sdc::resetPath(ExceptionFrom *from, addException(expand); } } + else + itr++; } } @@ -5214,33 +5231,38 @@ Sdc::exceptionFromStates(const Pin *pin, { bool srch_from = true; if (pin) { - if (srch_from && !first_from_pin_exceptions_.empty()) - srch_from &= exceptionFromStates(first_from_pin_exceptions_.findKey(pin), - pin, rf, min_max, include_filter, - states); - if (srch_from && !first_thru_pin_exceptions_.empty()) - srch_from &= exceptionFromStates(first_thru_pin_exceptions_.findKey(pin), - pin, rf, min_max, include_filter, - states); - + if (srch_from) { + const ExceptionPathSet *exceptions = + findExceptions(first_from_pin_exceptions_, pin); + srch_from &= exceptionFromStates(exceptions, pin, rf, min_max, + include_filter, states); + } + if (srch_from) { + const ExceptionPathSet *exceptions = + findExceptions(first_thru_pin_exceptions_, pin); + srch_from &= exceptionFromStates(exceptions, pin, rf, min_max, + include_filter, states); + } if (srch_from && (!first_from_inst_exceptions_.empty() || !first_thru_inst_exceptions_.empty())) { Instance *inst = network_->instance(pin); - if (srch_from && !first_from_inst_exceptions_.empty()) - srch_from &= exceptionFromStates(first_from_inst_exceptions_.findKey(inst), - pin, rf, min_max, include_filter, - states); - if (srch_from && !first_thru_inst_exceptions_.empty()) - srch_from &= exceptionFromStates(first_thru_inst_exceptions_.findKey(inst), - pin, rf, min_max, include_filter, - states); + const ExceptionPathSet *exceptions = + findExceptions(first_from_inst_exceptions_, inst); + srch_from &= exceptionFromStates(exceptions, pin, rf, min_max, + include_filter, states); + const ExceptionPathSet *exceptions2 = + findExceptions(first_thru_inst_exceptions_, inst); + srch_from &= exceptionFromStates(exceptions2, pin, rf, min_max, + include_filter, states); } } - if (srch_from && clk && !first_from_clk_exceptions_.empty()) - srch_from &= exceptionFromStates(first_from_clk_exceptions_.findKey(clk), - pin, clk_rf, min_max, include_filter, - states); + if (srch_from && clk) { + const ExceptionPathSet *exceptions = + findExceptions(first_from_clk_exceptions_, clk); + srch_from &= exceptionFromStates(exceptions, pin, clk_rf, min_max, + include_filter, states); + } if (!srch_from) { delete states; states = nullptr; @@ -5299,20 +5321,22 @@ Sdc::exceptionFromClkStates(const Pin *pin, ExceptionStateSet *&states) const { if (pin) { - if (!first_from_pin_exceptions_.empty()) - exceptionFromStates(first_from_pin_exceptions_.findKey(pin), - nullptr, rf, min_max, true, states); + const ExceptionPathSet *exceptions = + findExceptions(first_from_pin_exceptions_, pin); + exceptionFromStates(exceptions, nullptr, rf, min_max, true, states); if (!first_from_inst_exceptions_.empty()) { Instance *inst = network_->instance(pin); - exceptionFromStates(first_from_inst_exceptions_.findKey(inst), - pin, rf, min_max, true, states); + const ExceptionPathSet *exceptions = + findExceptions(first_from_inst_exceptions_, inst); + exceptionFromStates(exceptions, pin, rf, min_max, true, states); } - exceptionThruStates(first_thru_pin_exceptions_.findKey(pin), - rf, min_max, states); + const ExceptionPathSet *exceptions2 = + findExceptions(first_thru_pin_exceptions_, pin); + exceptionThruStates(exceptions2, rf, min_max, states); } - if (!first_from_clk_exceptions_.empty()) - exceptionFromStates(first_from_clk_exceptions_.findKey(clk), - pin, clk_rf, min_max, true, states); + const ExceptionPathSet *exceptions = + findExceptions(first_from_clk_exceptions_, clk); + exceptionFromStates(exceptions, pin, clk_rf, min_max, true, states); } void @@ -5322,10 +5346,10 @@ Sdc::filterRegQStates(const Pin *to_pin, ExceptionStateSet *&states) const { if (!first_from_pin_exceptions_.empty()) { - const ExceptionPathSet *exceptions = - first_from_pin_exceptions_.findKey(to_pin); - if (exceptions) { - for (ExceptionPath *exception : *exceptions) { + auto itr = first_from_pin_exceptions_.find(to_pin); + if (itr != first_from_pin_exceptions_.end()) { + const ExceptionPathSet &exceptions = itr->second; + for (ExceptionPath *exception : exceptions) { // Hack for filter -from reg/Q. if (exception->isFilter() && exception->matchesFirstPt(to_rf, min_max)) { @@ -5346,19 +5370,25 @@ Sdc::exceptionThruStates(const Pin *from_pin, const MinMax *min_max, ExceptionStateSet *&states) const { - exceptionThruStates(first_thru_pin_exceptions_.findKey(to_pin), - to_rf, min_max, states); + const ExceptionPathSet *exceptions = + findExceptions(first_thru_pin_exceptions_, to_pin); + exceptionThruStates(exceptions, to_rf, min_max, states); + if (!first_thru_edge_exceptions_.empty()) { EdgePins edge_pins(from_pin, to_pin); - exceptionThruStates(first_thru_edge_exceptions_.findKey(edge_pins), - to_rf, min_max, states); + auto itr = first_thru_edge_exceptions_.find(edge_pins); + if (itr != first_thru_edge_exceptions_.end()) { + const ExceptionPathSet *exceptions = &itr->second; + exceptionThruStates(exceptions, to_rf, min_max, states); + } } if (!first_thru_inst_exceptions_.empty() && (network_->direction(to_pin)->isAnyOutput() || network_->isLatchData(to_pin))) { const Instance *to_inst = network_->instance(to_pin); - exceptionThruStates(first_thru_inst_exceptions_.findKey(to_inst), - to_rf, min_max, states); + const ExceptionPathSet *exceptions = + findExceptions(first_thru_inst_exceptions_, to_inst); + exceptionThruStates(exceptions, to_rf, min_max, states); } } @@ -5396,18 +5426,26 @@ Sdc::exceptionTo(ExceptionPathType type, { if (!first_to_inst_exceptions_.empty()) { Instance *inst = network_->instance(pin); - exceptionTo(first_to_inst_exceptions_.findKey(inst), type, pin, rf, + const ExceptionPathSet *exceptions = + findExceptions(first_to_inst_exceptions_, inst); + exceptionTo(exceptions, type, pin, rf, clk_edge, min_max, match_min_max_exactly, hi_priority_exception, hi_priority); } - if (!first_to_pin_exceptions_.empty()) - exceptionTo(first_to_pin_exceptions_.findKey(pin), type, pin, rf, + if (!first_to_pin_exceptions_.empty()) { + const ExceptionPathSet *exceptions = + findExceptions(first_to_pin_exceptions_, pin); + exceptionTo(exceptions, type, pin, rf, clk_edge, min_max, match_min_max_exactly, hi_priority_exception, hi_priority); - if (clk_edge && !first_to_clk_exceptions_.empty()) - exceptionTo(first_to_clk_exceptions_.findKey(clk_edge->clock()), - type, pin, rf, clk_edge, min_max, match_min_max_exactly, + } + if (clk_edge && !first_to_clk_exceptions_.empty()) { + const ExceptionPathSet *exceptions = + findExceptions(first_to_clk_exceptions_, clk_edge->clock()); + exceptionTo(exceptions, type, pin, rf, clk_edge, + min_max, match_min_max_exactly, hi_priority_exception, hi_priority); + } } void @@ -5515,15 +5553,20 @@ Sdc::groupPathsTo(const Pin *pin, { if (!first_to_inst_exceptions_.empty()) { Instance *inst = network_->instance(pin); - groupPathsTo(first_to_inst_exceptions_.findKey(inst), pin, rf, - clk_edge, min_max, group_paths); + const ExceptionPathSet *exceptions = + findExceptions(first_to_inst_exceptions_, inst); + groupPathsTo(exceptions, pin, rf, clk_edge, min_max, group_paths); + } + if (!first_to_pin_exceptions_.empty()) { + const ExceptionPathSet *exceptions = + findExceptions(first_to_pin_exceptions_, pin); + groupPathsTo(exceptions, pin, rf, clk_edge, min_max, group_paths); + } + if (clk_edge && !first_to_clk_exceptions_.empty()) { + const ExceptionPathSet *exceptions = + findExceptions(first_to_clk_exceptions_, clk_edge->clock()); + groupPathsTo(exceptions, pin, rf, clk_edge, min_max, group_paths); } - if (!first_to_pin_exceptions_.empty()) - groupPathsTo(first_to_pin_exceptions_.findKey(pin), pin, rf, - clk_edge, min_max, group_paths); - if (clk_edge && !first_to_clk_exceptions_.empty()) - groupPathsTo(first_to_clk_exceptions_.findKey(clk_edge->clock()), - pin, rf, clk_edge, min_max, group_paths); } void @@ -5627,7 +5670,7 @@ Sdc::disconnectPinBefore(const Pin *pin) { auto itr = pin_exceptions_.find(pin); if (itr != pin_exceptions_.end()) { - for (ExceptionPath *exception : *itr->second) { + for (ExceptionPath *exception : itr->second) { ExceptionFrom *from = exception->from(); if (from) from->disconnectPinBefore(pin, network_); diff --git a/sdc/WriteSdc.cc b/sdc/WriteSdc.cc index 5c448a8c..32c2450c 100644 --- a/sdc/WriteSdc.cc +++ b/sdc/WriteSdc.cc @@ -1196,7 +1196,7 @@ void WriteSdc::writeExceptions() const { ExceptionPathSeq exceptions; - for (ExceptionPath *exception : *sdc_->exceptions()) + for (ExceptionPath *exception : sdc_->exceptions()) exceptions.push_back(exception); sort(exceptions, ExceptionPathLess(network_)); for (ExceptionPath *exception : exceptions) { diff --git a/search/CheckTiming.cc b/search/CheckTiming.cc index 4ff5ee24..76e11698 100644 --- a/search/CheckTiming.cc +++ b/search/CheckTiming.cc @@ -273,10 +273,7 @@ CheckTiming::hasClkedDepature(Pin *pin) bool CheckTiming::hasMaxDelay(Pin *pin) { - ExceptionPathSet *exceptions = sdc_->exceptions(); - ExceptionPathSet::Iterator exception_iter(exceptions); - while (exception_iter.hasNext()) { - ExceptionPath *exception = exception_iter.next(); + for (ExceptionPath *exception : sdc_->exceptions()) { ExceptionTo *to = exception->to(); if (exception->isPathDelay() && exception->minMax() == MinMaxAll::max() From 2fc4ece17f07afb41b99039640bc7ea5ed916a65 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 8 Nov 2025 18:42:41 -0700 Subject: [PATCH 3/5] rm Sta:findGroupPathPins Signed-off-by: James Cherry --- CMakeLists.txt | 1 - include/sta/Sta.hh | 3 - sdc/Sdc.i | 13 -- search/Sta.cc | 31 --- search/VisitPathGroupVertices.cc | 313 ------------------------------- search/VisitPathGroupVertices.hh | 40 ---- 6 files changed, 401 deletions(-) delete mode 100644 search/VisitPathGroupVertices.cc delete mode 100644 search/VisitPathGroupVertices.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index 35caa594..f41fcac0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,7 +202,6 @@ set(STA_SOURCE search/TagGroup.cc search/VertexVisitor.cc search/VisitPathEnds.cc - search/VisitPathGroupVertices.cc search/WorstSlack.cc spice/WritePathSpice.cc diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 6f29c7ac..f7b233da 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -907,9 +907,6 @@ public: PinSet endpointPins(); VertexSet *endpoints(); int endpointViolationCount(const MinMax *min_max); - // Find the fanin vertices for a group path. - // Vertices in the clock network are NOT included. - PinSet findGroupPathPins(const char *group_path_name); // Find all required times after updateTiming(). void findRequireds(); std::string reportDelayCalc(Edge *edge, diff --git a/sdc/Sdc.i b/sdc/Sdc.i index bf2effd0..2c66e43d 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -1355,19 +1355,6 @@ set_voltage_net(const Net *net, //////////////////////////////////////////////////////////////// -PinSet -group_path_pins(const char *group_path_name) -{ - Sta *sta = Sta::sta(); - Sdc *sdc = sta->sdc(); - if (sdc->isGroupPathName(group_path_name)) - return sta->findGroupPathPins(group_path_name); - else - return PinSet(sta->network()); -} - -//////////////////////////////////////////////////////////////// - char pin_case_logic_value(const Pin *pin) { diff --git a/search/Sta.cc b/search/Sta.cc index 44da4a79..87fe14a9 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -75,7 +75,6 @@ #include "ClkLatency.hh" #include "FindRegister.hh" #include "ReportPath.hh" -#include "VisitPathGroupVertices.hh" #include "Genclks.hh" #include "ClkNetwork.hh" #include "power/Power.hh" @@ -2721,36 +2720,6 @@ Sta::endpointViolationCount(const MinMax *min_max) return violations; } -PinSet -Sta::findGroupPathPins(const char *group_path_name) -{ - if (!(search_->havePathGroups() - && search_->arrivalsValid())) { - PathEndSeq path_ends = findPathEnds(// from, thrus, to, unconstrained - nullptr, nullptr, nullptr, false, - // corner, min_max, - nullptr, MinMaxAll::max(), - // group_path_count, endpoint_path_count - 1, 1, - // unique_pins, unique_edges - true, true, - -INF, INF, // slack_min, slack_max, - false, // sort_by_slack - nullptr, // group_names - // setup, hold, recovery, removal, - true, true, true, true, - // clk_gating_setup, clk_gating_hold - true, true); - } - - PathGroup *path_group = search_->findPathGroup(group_path_name, - MinMax::max()); - PinSet pins(network_); - VertexPinCollector visitor(pins); - visitPathGroupVertices(path_group, &visitor, this); - return pins; -} - //////////////////////////////////////////////////////////////// void diff --git a/search/VisitPathGroupVertices.cc b/search/VisitPathGroupVertices.cc deleted file mode 100644 index c733f9b8..00000000 --- a/search/VisitPathGroupVertices.cc +++ /dev/null @@ -1,313 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "VisitPathGroupVertices.hh" - -#include "Debug.hh" -#include "Graph.hh" -#include "Bfs.hh" -#include "Search.hh" -#include "Path.hh" -#include "PathEnd.hh" -#include "Tag.hh" -#include "VisitPathEnds.hh" - -namespace sta { - -typedef Set PathSet; -typedef Map VertexPathSetMap; - -static void -vertexPathSetMapInsertPath(VertexPathSetMap *matching_path_map, - Vertex *vertex, - Tag *tag, - const StaState *sta); - -// Visit each path end for a vertex and add the worst one in each -// path group to the group. -class VisitPathGroupEnds : public PathEndVisitor -{ -public: - VisitPathGroupEnds(PathGroup *path_group, - VertexVisitor *vertex_visitor, - VertexPathSetMap *matching_path_map, - BfsBkwdIterator *bkwd_iter, - StaState *sta); - VisitPathGroupEnds(const VisitPathGroupEnds&) = default; - virtual PathEndVisitor *copy() const; - virtual void visit(PathEnd *path_end); - virtual void vertexBegin(Vertex *vertex); - virtual void vertexEnd(Vertex *vertex); - -private: - PathGroup *path_group_; - VertexVisitor *vertex_visitor_; - BfsBkwdIterator *bkwd_iter_; - VertexPathSetMap *matching_path_map_; - bool vertex_matches_; - StaState *sta_; -}; - -class PathGroupPathVisitor : public PathVisitor -{ -public: - PathGroupPathVisitor(VertexVisitor *visitor, - BfsBkwdIterator *bkwd_iter, - VertexPathSetMap *matching_path_map, - const StaState *sta); - virtual ~PathGroupPathVisitor(); - virtual VertexVisitor *copy() const; - virtual void visit(Vertex *vertex); - -protected: - // Return false to stop visiting. - virtual bool visitFromToPath(const Pin *from_pin, - Vertex *from_vertex, - const RiseFall *from_rf, - Tag *from_tag, - Path *from_path, - const Arrival &from_arrival, - Edge *edge, - TimingArc *arc, - ArcDelay arc_delay, - Vertex *to_vertex, - const RiseFall *to_rf, - Tag *to_tag, - Arrival &to_arrival, - const MinMax *min_max, - const PathAnalysisPt *path_ap); - void fromMatches(Vertex *from_vertex, - Tag *from_tag); - -private: - VertexVisitor *visitor_; - BfsBkwdIterator *bkwd_iter_; - VertexPathSetMap *matching_path_map_; - bool vertex_matches_; -}; - -//////////////////////////////////////////////////////////////// - -// Visit the fanin vertices for the path group. -// Vertices in the clock network are NOT visited. -void -visitPathGroupVertices(PathGroup *path_group, - VertexVisitor *visitor, - StaState *sta) -{ - Search *search = sta->search(); - VertexPathSetMap matching_path_map; - // Do not visit clock network. - SearchPredNonReg2 srch_non_reg(sta); - BfsBkwdIterator bkwd_iter(BfsIndex::other, &srch_non_reg, sta); - // Visit the path ends and filter by path_group to seed the backward search. - VisitPathGroupEnds end_visitor(path_group, visitor, &matching_path_map, - &bkwd_iter, sta); - VisitPathEnds visit_path_ends(sta); - for(Vertex *vertex : *search->endpoints()) - visit_path_ends.visitPathEnds(vertex, &end_visitor); - - // Search backward from the path ends thru vertices that have arrival tags - // that match path_group end paths. - PathGroupPathVisitor path_visitor(visitor, &bkwd_iter, &matching_path_map, - sta); - bkwd_iter.visit(0, &path_visitor); - - // Cleanup. - VertexPathSetMap::Iterator matching_iter(matching_path_map); - while (matching_iter.hasNext()) { - PathSet *paths = matching_iter.next(); - PathSet::Iterator path_iter(paths); - while (path_iter.hasNext()) { - Path *path = path_iter.next(); - delete path; - } - delete paths; - } -} - -//////////////////////////////////////////////////////////////// - -VisitPathGroupEnds::VisitPathGroupEnds(PathGroup *path_group, - VertexVisitor *vertex_visitor, - VertexPathSetMap *matching_path_map, - BfsBkwdIterator *bkwd_iter, - StaState *sta) : - path_group_(path_group), - vertex_visitor_(vertex_visitor), - bkwd_iter_(bkwd_iter), - matching_path_map_(matching_path_map), - sta_(sta) -{ -} - -PathEndVisitor * -VisitPathGroupEnds::copy() const -{ - return new VisitPathGroupEnds(*this); -} - -void -VisitPathGroupEnds::vertexBegin(Vertex *) -{ - vertex_matches_ = false; -} - -void -VisitPathGroupEnds::visit(PathEnd *path_end) -{ - PathGroupSeq groups = sta_->search()->pathGroups(path_end); - for (PathGroup *group : groups) { - if (group == path_group_) { - Path *path = path_end->path(); - Vertex *vertex = path->vertex(sta_); - vertexPathSetMapInsertPath(matching_path_map_, vertex, path->tag(sta_), sta_); - vertex_matches_ = true; - } - } -} - -static void -vertexPathSetMapInsertPath(VertexPathSetMap *matching_path_map, - Vertex *vertex, - Tag *tag, - const StaState *sta) -{ - PathSet *matching_paths = matching_path_map->findKey(vertex); - if (matching_paths == nullptr) { - PathLess path_less(sta); - matching_paths = new PathSet(path_less); - (*matching_path_map)[vertex] = matching_paths; - } - Path *vpath = new Path(vertex, tag, sta); - matching_paths->insert(vpath); -} - -void -VisitPathGroupEnds::vertexEnd(Vertex *vertex) -{ - if (vertex_matches_) { - vertex_visitor_->visit(vertex); - // Seed backward bfs fanin search. - bkwd_iter_->enqueueAdjacentVertices(vertex); - } -} - -//////////////////////////////////////////////////////////////// - -PathGroupPathVisitor::PathGroupPathVisitor(VertexVisitor *visitor, - BfsBkwdIterator *bkwd_iter, - VertexPathSetMap *matching_path_map, - const StaState *sta) : - PathVisitor(sta), - visitor_(visitor), - bkwd_iter_(bkwd_iter), - matching_path_map_(matching_path_map) -{ -} - -PathGroupPathVisitor::~PathGroupPathVisitor() -{ -} - -VertexVisitor * -PathGroupPathVisitor::copy() const -{ - return new PathGroupPathVisitor(visitor_, bkwd_iter_, - matching_path_map_, this); -} - -void -PathGroupPathVisitor::visit(Vertex *vertex) -{ - vertex_matches_ = false; - visitFanoutPaths(vertex); - if (vertex_matches_) { - debugPrint(debug_, "visit_path_group", 1, "visit %s", - vertex->to_string(this).c_str()); - visitor_->visit(vertex); - bkwd_iter_->enqueueAdjacentVertices(vertex); - } -} - -bool -PathGroupPathVisitor::visitFromToPath(const Pin *, - Vertex *from_vertex, - const RiseFall *, - Tag *from_tag, - Path *, - const Arrival &, - Edge *, - TimingArc *, - ArcDelay , - Vertex *to_vertex, - const RiseFall *to_rf, - Tag *to_tag, - Arrival &, - const MinMax *, - const PathAnalysisPt *path_ap) -{ - PathSet *matching_paths = matching_path_map_->findKey(to_vertex); - if (matching_paths) { - Path to_path(to_vertex, to_tag, this); - if (!to_path.isNull()) { - if (matching_paths->hasKey(&to_path)) { - debugPrint(debug_, "visit_path_group", 2, "match %s %s -> %s %s", - from_vertex->to_string(this).c_str(), - from_tag->to_string(this).c_str(), - to_vertex->to_string(this).c_str(), - to_tag->to_string(this).c_str()); - fromMatches(from_vertex, from_tag); - } - } - else { - VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this); - while (to_iter.hasNext()) { - Path *to_path = to_iter.next(); - if (Tag::matchNoCrpr(to_path->tag(this), to_tag) - && matching_paths->hasKey(to_path)) { - debugPrint(debug_, "visit_path_group", 2, - "match crpr %s %s -> %s %s", - from_vertex->to_string(this).c_str(), - from_tag->to_string(this).c_str(), - to_vertex->to_string(this).c_str(), - to_tag->to_string(this).c_str()); - fromMatches(from_vertex, from_tag); - } - } - } - } - return true; -} - -void -PathGroupPathVisitor::fromMatches(Vertex *from_vertex, - Tag *from_tag) -{ - vertex_matches_ = true; - vertexPathSetMapInsertPath(matching_path_map_, from_vertex, - from_tag, this); -} - -} // namespace diff --git a/search/VisitPathGroupVertices.hh b/search/VisitPathGroupVertices.hh deleted file mode 100644 index 55f585ef..00000000 --- a/search/VisitPathGroupVertices.hh +++ /dev/null @@ -1,40 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -namespace sta { - -class PathGroup; -class VertexVisitor; -class StaState; - -// Visit the fanin vertices for the path group. -// Vertices in the clock network are NOT visited. -void -visitPathGroupVertices(PathGroup *path_group, - VertexVisitor *visitor, - StaState *sta); - -} // namespace From cf903f4db688e6f89d732ef28cce7b8185587201 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sun, 9 Nov 2025 08:23:53 -0700 Subject: [PATCH 4/5] suppress rapidus liberty warning Signed-off-by: James Cherry --- liberty/LibertyReader.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index f294244f..3fc2ffdf 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -559,6 +559,8 @@ LibertyReader::defineVisitors() &LibertyReader::endEcsmWaveform); defineGroupVisitor("ecsm_waveform_set", &LibertyReader::beginEcsmWaveform, &LibertyReader::endEcsmWaveform); + defineGroupVisitor("ecsm_capacitance", &LibertyReader::beginEcsmWaveform, + &LibertyReader::endEcsmWaveform); } void From 771050b0de0cc3093239150a00d5d1e0fc31f539 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sun, 9 Nov 2025 17:15:05 -0700 Subject: [PATCH 5/5] cache instance power results Signed-off-by: James Cherry --- power/Power.cc | 77 ++++++++++++++++++++++++++++++++++++-------------- power/Power.hh | 6 ++++ search/Sta.cc | 2 ++ 3 files changed, 64 insertions(+), 21 deletions(-) diff --git a/power/Power.cc b/power/Power.cc index 25e19e9d..cc596820 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -100,7 +100,8 @@ Power::Power(StaState *sta) : input_activity_(), // default set in ensureActivities() seq_activity_map_(100, SeqPinHash(network_), SeqPinEqual()), activities_valid_(false), - bdd_(sta) + bdd_(sta), + corner_(nullptr) { } @@ -113,6 +114,8 @@ Power::clear() seq_activity_map_.clear(); activity_map_.clear(); activities_valid_ = false; + instance_powers_.clear(); + corner_ = nullptr; } void @@ -286,13 +289,10 @@ Power::power(const Corner *corner, pad.clear(); ensureActivities(); - Stats stats(debug_, report_); - LeafInstanceIterator *inst_iter = network_->leafInstanceIterator(); - while (inst_iter->hasNext()) { - Instance *inst = inst_iter->next(); + ensureInstPowers(corner); + for (auto [inst, inst_power] : instance_powers_) { LibertyCell *cell = network_->libertyCell(inst); if (cell) { - PowerResult inst_power = power(inst, cell, corner); if (cell->isMacro() || cell->isMemory() || cell->interfaceTiming()) @@ -308,8 +308,6 @@ Power::power(const Corner *corner, total.incr(inst_power); } } - delete inst_iter; - stats.report("Find power"); } bool @@ -332,17 +330,15 @@ PowerResult Power::power(const Instance *inst, const Corner *corner) { + ensureActivities(); + ensureInstPowers(corner); if (network_->isHierarchical(inst)) { PowerResult result; powerInside(inst, corner, result); return result; } - LibertyCell *cell = network_->libertyCell(inst); - if (cell) { - ensureActivities(); - return power(inst, cell, corner); - } - return PowerResult(); + else + return instance_powers_[inst]; } void @@ -355,13 +351,8 @@ Power::powerInside(const Instance *hinst, Instance *child = child_iter->next(); if (network_->isHierarchical(child)) powerInside(child, corner, result); - else { - LibertyCell *cell = network_->libertyCell(child); - if (cell) { - PowerResult inst_power = power(child, cell, corner); - result.incr(inst_power); - } - } + else + result.incr(instance_powers_[child]); } delete child_iter; } @@ -707,6 +698,7 @@ Power::evalBddActivity(DdNode *bdd, void Power::ensureActivities() { + Stats stats(debug_, report_); // No need to propagate activites if global activity is set. if (!global_activity_.isSet()) { if (!activities_valid_) { @@ -750,6 +742,7 @@ Power::ensureActivities() activities_valid_ = true; } } + stats.report("Power activities"); } void @@ -841,6 +834,32 @@ Power::seedRegOutputActivities(const Instance *reg, //////////////////////////////////////////////////////////////// +void +Power::ensureInstPowers(const Corner *corner) +{ + if (instance_powers_.empty() + || corner != corner_) + findInstPowers(corner); +} + +void +Power::findInstPowers(const Corner *corner) +{ + Stats stats(debug_, report_); + LeafInstanceIterator *inst_iter = network_->leafInstanceIterator(); + while (inst_iter->hasNext()) { + Instance *inst = inst_iter->next(); + LibertyCell *cell = network_->libertyCell(inst); + if (cell) { + PowerResult inst_power = power(inst, cell, corner); + instance_powers_[inst] = inst_power; + } + } + delete inst_iter; + corner_ = corner; + stats.report("Find power"); +} + PowerResult Power::power(const Instance *inst, LibertyCell *cell, @@ -1539,6 +1558,22 @@ Power::clockMinPeriod() return 0.0; } +void +Power::deleteInstanceBefore(const Instance *) +{ + activities_valid_ = false; + instance_powers_.clear(); + corner_ = nullptr; +} + +void +Power::deletePinBefore(const Pin *) +{ + activities_valid_ = false; + instance_powers_.clear(); + corner_ = nullptr; +} + //////////////////////////////////////////////////////////////// PowerResult::PowerResult() : diff --git a/power/Power.hh b/power/Power.hh index 18bc3ab9..e51ce285 100644 --- a/power/Power.hh +++ b/power/Power.hh @@ -107,6 +107,8 @@ public: float clockMinPeriod(); InstanceSeq highestPowerInstances(size_t count, const Corner *corner); + void deleteInstanceBefore(const Instance *inst); + void deletePinBefore(const Pin *pin); protected: PwrActivity &activity(const Pin *pin); @@ -129,6 +131,8 @@ protected: PwrActivity &activity); PwrActivity findActivity(const Pin *pin); + void ensureInstPowers(const Corner *corner); + void findInstPowers(const Corner *corner); PowerResult power(const Instance *inst, LibertyCell *cell, const Corner *corner); @@ -229,6 +233,8 @@ private: PwrSeqActivityMap seq_activity_map_; bool activities_valid_; Bdd bdd_; + std::map instance_powers_; + const Corner *corner_; static constexpr int max_activity_passes_ = 100; diff --git a/search/Sta.cc b/search/Sta.cc index 87fe14a9..d51ecae9 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -4588,6 +4588,7 @@ Sta::deleteLeafInstanceBefore(const Instance *inst) { sim_->deleteInstanceBefore(inst); sdc_->deleteInstanceBefore(inst); + power_->deleteInstanceBefore(inst); } void @@ -4664,6 +4665,7 @@ Sta::deletePinBefore(const Pin *pin) } sim_->deletePinBefore(pin); clk_network_->deletePinBefore(pin); + power_->deletePinBefore(pin); } void