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