diff --git a/CMakeLists.txt b/CMakeLists.txt index e36cc3e0..e5226978 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,6 +116,7 @@ set(STA_SOURCE parasitics/NullParasitics.cc parasitics/Parasitics.cc parasitics/ReduceParasitics.cc + parasitics/ReportParasiticAnnotation.cc parasitics/SpefNamespace.cc parasitics/SpefReader.cc parasitics/SpefReaderPvt.hh diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc index a10acf57..d0218973 100644 --- a/dcalc/LumpedCapDelayCalc.cc +++ b/dcalc/LumpedCapDelayCalc.cc @@ -163,6 +163,9 @@ LumpedCapDelayCalc::gateDelay(const LibertyCell *drvr_cell, ArcDelay gate_delay1; Slew drvr_slew1; float in_slew1 = delayAsFloat(in_slew); + // NaNs cause seg faults during table lookup. + if (isnan(load_cap) || isnan(related_out_cap) || isnan(in_slew)) + report_->error(705, "gate delay input variable is NaN"); model->gateDelay(drvr_cell, pvt, in_slew1, load_cap, related_out_cap, pocv_enabled_, gate_delay1, drvr_slew1); gate_delay = gate_delay1; diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index 3b5951e6..14101458 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -3,6 +3,10 @@ OpenSTA Timing Analyzer Release Notes This file summarizes user visible changes for each release. +The report_parasitics_annotation command reports SPEF annotation completeness. + + report_parasitics_annotation [-report_unannotated] + Release 2.3.2 2022/07/03 ------------------------- diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index 5f73688b..5cd1d7de 100644 Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ diff --git a/doc/OpenSTA.pdf b/doc/OpenSTA.pdf index e9ed33ce..d42867bb 100644 Binary files a/doc/OpenSTA.pdf and b/doc/OpenSTA.pdf differ diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 838922cc..7ebdc882 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -46,8 +46,10 @@ class TimingArcAttrs; class InternalPowerAttrs; class LibertyPgPort; class StaState; +class Corner; +class Corners; +class DcalcAnalysisPt; -typedef Set LibrarySet; typedef Map TableTemplateMap; typedef Vector TableTemplateSeq; typedef Map BusDclMap; @@ -294,6 +296,10 @@ public: bool link, int ap_index, Report *report); + static void + checkCorners(LibertyCell *cell, + Corners *corners, + Report *report); protected: float degradeWireSlew(const LibertyCell *cell, @@ -443,6 +449,9 @@ public: RiseFall *&enable_rf) const; RiseFall *latchCheckEnableEdge(TimingArcSet *check_set); bool isDisabledConstraint() const { return is_disabled_constraint_; } + LibertyCell *cornerCell(const Corner *corner, + const MinMax *min_max); + LibertyCell *cornerCell(const DcalcAnalysisPt *dcalc_ap); LibertyCell *cornerCell(int ap_index); // AOCV @@ -489,6 +498,9 @@ public: void bufferPorts(// Return values. LibertyPort *&input, LibertyPort *&output) const; + // Check all liberty cells to make sure they exist + // for all the defined corners. + static void checkLibertyCorners(); protected: void addPort(ConcretePort *port); @@ -515,6 +527,8 @@ protected: const LibertyPort *output) const; bool hasInverterFunc(const LibertyPort *input, const LibertyPort *output) const; + bool checkCornerCell(const Corner *corner, + const MinMax *min_max) const; LibertyLibrary *liberty_library_; float area_; @@ -712,6 +726,12 @@ public: RiseFall *sense); bool isDisabledConstraint() const { return is_disabled_constraint_; } void setIsDisabledConstraint(bool is_disabled); + LibertyPort *cornerPort(const Corner *corner, + const MinMax *min_max); + const LibertyPort *cornerPort(const Corner *corner, + const MinMax *min_max) const; + LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap); + const LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap) const; LibertyPort *cornerPort(int ap_index); const LibertyPort *cornerPort(int ap_index) const; void setCornerPort(LibertyPort *corner_port, diff --git a/include/sta/Network.hh b/include/sta/Network.hh index e209f898..ec399403 100644 --- a/include/sta/Network.hh +++ b/include/sta/Network.hh @@ -127,6 +127,11 @@ public: // This corresponds to a link_path of '*'. LibertyLibrary *defaultLibertyLibrary() const; void setDefaultLibertyLibrary(LibertyLibrary *library); + // Check liberty cells used by the network to make sure they exist + // for all the defined corners. + void checkNetworkLibertyCorners(); + // Check liberty cells to make sure they exist for all the defined corners. + void checkLibertyCorners(); //////////////////////////////////////////////////////////////// // Cell functions. @@ -514,7 +519,6 @@ public: virtual void mergeInto(Net *net, Net *into_net) = 0; virtual Net *mergedInto(Net *net) = 0; - }; // Network API to support the Parallax readers. diff --git a/include/sta/Parasitics.hh b/include/sta/Parasitics.hh index 63cbc33e..276098ca 100644 --- a/include/sta/Parasitics.hh +++ b/include/sta/Parasitics.hh @@ -39,10 +39,11 @@ typedef Iterator ParasiticNodeIterator; // Parasitic annotation for a pin or net may exist for one analysis point // and not another. // If there is only one parasitic for both rise and fall transitions -// the sta parasitic readers will save it under the rise transition. +// the parasitic readers will save it under the rise transition. class Parasitics : public StaState { public: + Parasitics(StaState *sta); virtual ~Parasitics() {} virtual bool haveParasitics() = 0; // Clear all state. @@ -137,7 +138,7 @@ public: virtual void poleResidue(const Parasitic *parasitic, int pole_index, ComplexFloat &pole, - ComplexFloat &residue) const=0; + ComplexFloat &residue) const = 0; //////////////////////////////////////////////////////////////// // Parasitic Network (detailed parasitics). @@ -300,7 +301,6 @@ protected: float fanout, const ParasiticAnalysisPt *ap); - Parasitics(StaState *sta); Net *findParasiticNet(const Pin *pin) const; }; diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index ec2e9cf7..3c66a73d 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1113,13 +1113,14 @@ public: Instance *instance, const Corner *corner, const MinMaxAll *min_max, - bool increment, bool pin_cap_included, bool keep_coupling_caps, float coupling_cap_factor, ReducedParasiticType reduce_to, bool delete_after_reduce, bool quiet); + void reportParasiticAnnotation(bool report_unannotated, + const Corner *corner); // Parasitics. void findPiElmore(Pin *drvr_pin, const RiseFall *rf, @@ -1398,6 +1399,8 @@ protected: CornerSeq makeCornerSeq(Corner *corner) const; void makeParasiticAnalysisPts(); void clkSkewPreamble(); + void setCmdNamespace1(CmdNamespace namespc); + void setThreadCount1(int thread_count); CmdNamespace cmd_namespace_; Instance *current_instance_; diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index e0a8ed0f..2e14c888 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -195,7 +195,6 @@ public: static int wireArcCount() { return 2; } protected: - void init(LibertyCell *cell); TimingArcSet(TimingRole *role, TimingArcAttrsPtr attrs); diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index d901c2b3..e87ba253 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -36,11 +36,11 @@ #include "EquivCells.hh" #include "Network.hh" #include "PortDirection.hh" +#include "Corner.hh" +#include "DcalcAnalysisPt.hh" namespace sta { -typedef Set TimingModelSet; -typedef Set FuncExprSet; typedef Set LatchEnableSet; void @@ -782,6 +782,23 @@ LibertyLibrary::makeCornerMap(LibertyCell *cell1, } } +void +LibertyLibrary::checkCorners(LibertyCell *cell, + Corners *corners, + Report *report) +{ + for (const Corner *corner : *corners) { + for (auto min_max : MinMax::range()) { + if (!cell->checkCornerCell(corner, min_max)) + report->error(705, "Liberty cell %s/%s for corner %s/%s not found", + cell->libertyLibrary()->name(), + cell->name(), + corner->name(), + min_max->asString()); + } + } +} + //////////////////////////////////////////////////////////////// float @@ -1497,15 +1514,40 @@ LibertyCell::setIsDisabledConstraint(bool is_disabled) is_disabled_constraint_ = is_disabled; } +LibertyCell * +LibertyCell::cornerCell(const Corner *corner, + const MinMax *min_max) +{ + return cornerCell(corner->libertyIndex(min_max)); +} + +LibertyCell * +LibertyCell::cornerCell(const DcalcAnalysisPt *dcalc_ap) +{ + return cornerCell(dcalc_ap->libertyIndex()); +} + LibertyCell * LibertyCell::cornerCell(int ap_index) { - if (ap_index < static_cast(corner_cells_.size())) + if (corner_cells_.empty()) + return this; + else if (ap_index < static_cast(corner_cells_.size())) return corner_cells_[ap_index]; else return nullptr; } +bool +LibertyCell::checkCornerCell(const Corner *corner, + const MinMax *min_max) const +{ + int lib_index = corner->libertyIndex(min_max); + return corner_cells_.empty() + || (lib_index <= static_cast(corner_cells_.size()) + && corner_cells_[lib_index]); +} + void LibertyCell::setCornerCell(LibertyCell *corner_cell, int ap_index) @@ -2323,26 +2365,52 @@ LibertyPort::setIsDisabledConstraint(bool is_disabled) is_disabled_constraint_ = is_disabled; } +LibertyPort * +LibertyPort::cornerPort(const Corner *corner, + const MinMax *min_max) +{ + return cornerPort(corner->libertyIndex(min_max)); +} + +const LibertyPort * +LibertyPort::cornerPort(const Corner *corner, + const MinMax *min_max) const +{ + return cornerPort(corner->libertyIndex(min_max)); +} + +LibertyPort * +LibertyPort::cornerPort(const DcalcAnalysisPt *dcalc_ap) +{ + return cornerPort(dcalc_ap->libertyIndex()); +} + +const LibertyPort * +LibertyPort::cornerPort(const DcalcAnalysisPt *dcalc_ap) const +{ + return cornerPort(dcalc_ap->libertyIndex()); +} + LibertyPort * LibertyPort::cornerPort(int ap_index) { - if (ap_index < static_cast(corner_ports_.size())) { - LibertyPort *corner_port = corner_ports_[ap_index]; - if (corner_port) - return corner_port; - } - return this; + if (corner_ports_.empty()) + return this; + else if (ap_index < static_cast(corner_ports_.size())) + return corner_ports_[ap_index]; + else + return nullptr; } const LibertyPort * LibertyPort::cornerPort(int ap_index) const { - if (ap_index < static_cast(corner_ports_.size())) { - LibertyPort *corner_port = corner_ports_[ap_index]; - if (corner_port) - return corner_port; - } - return this; + if (corner_ports_.empty()) + return this; + else if (ap_index < static_cast(corner_ports_.size())) + return corner_ports_[ap_index]; + else + return nullptr; } void diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc index 706f8792..50835c8b 100644 --- a/liberty/LibertyBuilder.cc +++ b/liberty/LibertyBuilder.cc @@ -406,16 +406,11 @@ LibertyBuilder::makeFromTransitionArcs(LibertyCell *cell, { TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port, related_out, role, attrs); - TimingModel *model; - RiseFall *to_rf; - to_rf = RiseFall::rise(); - model = attrs->model(to_rf); - if (model) - makeTimingArc(arc_set, from_rf, to_rf, model); - to_rf = RiseFall::fall(); - model = attrs->model(to_rf); - if (model) - makeTimingArc(arc_set, from_rf, to_rf, model); + for (auto to_rf : RiseFall::range()) { + TimingModel *model = attrs->model(to_rf); + if (model) + makeTimingArc(arc_set, from_rf, to_rf, model); + } return arc_set; } diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 921d2a88..4fd2fbe0 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -2266,6 +2266,8 @@ LibertyReader::makeTimingArcs(const char *from_port_name, // one -> one if (from_port_iter.hasNext()) { LibertyPort *from_port = from_port_iter.next(); + if (from_port->direction()->isOutput()) + libWarn(164, timing->line(), "timing group from output port."); builder_->makeTimingArcs(cell_, from_port, to_port, related_out_port, timing->attrs()); } @@ -2274,6 +2276,8 @@ LibertyReader::makeTimingArcs(const char *from_port_name, // bus -> one while (from_port_iter.hasNext()) { LibertyPort *from_port = from_port_iter.next(); + if (from_port->direction()->isOutput()) + libWarn(165, timing->line(), "timing group from output port."); builder_->makeTimingArcs(cell_, from_port, to_port, related_out_port, timing->attrs()); } @@ -2282,6 +2286,8 @@ LibertyReader::makeTimingArcs(const char *from_port_name, // one -> bus if (from_port_iter.hasNext()) { LibertyPort *from_port = from_port_iter.next(); + if (from_port->direction()->isOutput()) + libWarn(166, timing->line(), "timing group from output port."); LibertyPortMemberIterator bit_iter(to_port); while (bit_iter.hasNext()) { LibertyPort *to_port_bit = bit_iter.next(); @@ -2298,6 +2304,8 @@ LibertyReader::makeTimingArcs(const char *from_port_name, while (from_port_iter.hasNext() && to_iter.hasNext()) { LibertyPort *from_port_bit = from_port_iter.next(); LibertyPort *to_port_bit = to_iter.next(); + if (from_port_bit->direction()->isOutput()) + libWarn(167, timing->line(), "timing group from output port."); builder_->makeTimingArcs(cell_, from_port_bit, to_port_bit, related_out_port, timing->attrs()); } @@ -2311,6 +2319,8 @@ LibertyReader::makeTimingArcs(const char *from_port_name, else { while (from_port_iter.hasNext()) { LibertyPort *from_port_bit = from_port_iter.next(); + if (from_port_bit->direction()->isOutput()) + libWarn(168, timing->line(), "timing group from output port."); LibertyPortMemberIterator to_iter(to_port); while (to_iter.hasNext()) { LibertyPort *to_port_bit = to_iter.next(); diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 1ec88ed3..6d440394 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -190,10 +190,12 @@ TimingArcSet::TimingArcSet(LibertyCell *cell, role_(role), attrs_(attrs), is_cond_default_(false), - index_(0), - is_disabled_constraint_(false) + index_(cell->addTimingArcSet(this)), + is_disabled_constraint_(false), + from_arc1_{nullptr, nullptr}, + from_arc2_{nullptr, nullptr}, + to_arc_{nullptr, nullptr} { - init(cell); } TimingArcSet::TimingArcSet(TimingRole *role, @@ -205,22 +207,11 @@ TimingArcSet::TimingArcSet(TimingRole *role, attrs_(attrs), is_cond_default_(false), index_(0), - is_disabled_constraint_(false) + is_disabled_constraint_(false), + from_arc1_{nullptr, nullptr}, + from_arc2_{nullptr, nullptr}, + to_arc_{nullptr, nullptr} { - init(nullptr); -} - -void -TimingArcSet::init(LibertyCell *cell) -{ - if (cell) - index_ = cell->addTimingArcSet(this); - - for (auto tr_index : RiseFall::rangeIndex()) { - from_arc1_[tr_index] = nullptr; - from_arc2_[tr_index] = nullptr; - to_arc_[tr_index] = nullptr; - } } TimingArcSet::~TimingArcSet() diff --git a/messages.txt b/messages.txt index a7a15ae5..d4424f32 100644 --- a/messages.txt +++ b/messages.txt @@ -1,28 +1,29 @@ -0001 DmpCeff.cc:1595 cell %s delay model not supported on SPF parasitics by DMP delay calculator -0002 Liberty.cc:739 cell %s/%s port %s not found in cell %s/%s. -0003 Liberty.cc:762 cell %s/%s %s -> %s timing group %s not found in cell %s/%s. -0004 Liberty.cc:1657 cell %s/%s %s -> %s latch enable %s_edge timing arc is inconsistent with %s -> %s setup_%s check. -0005 Liberty.cc:1672 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense. -0006 Liberty.cc:1680 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense. +Warning: 705 duplicated +0001 DmpCeff.cc:1597 cell %s delay model not supported on SPF parasitics by DMP delay calculator +0002 Liberty.cc:748 cell %s/%s port %s not found in cell %s/%s. +0003 Liberty.cc:774 cell %s/%s %s -> %s timing group %s not found in cell %s/%s. +0004 Liberty.cc:1680 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with %s -> %s setup_%s check. +0005 Liberty.cc:1694 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense. +0006 Liberty.cc:1702 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense. 0007 LibertyExpr.cc:78 %s references unknown port %s. -0008 ConcreteNetwork.cc:1855 cell type %s can not be linked. +0008 ConcreteNetwork.cc:1857 cell type %s can not be linked. 0009 CycleAccting.cc:87 No common period was found between clocks %s and %s. 0010 Genclks.cc:287 no master clock found for generated clock %s. 0011 Genclks.cc:329 generated clock %s is in the fanout of multiple clocks. -0013 Genclks.cc:991 generated clock %s source pin %s missing paths from master clock %s. +0013 Genclks.cc:987 generated clock %s source pin %s missing paths from master clock %s. 0015 Sim.cc:871 propagated logic value %c differs from constraint value of %c on pin %s. 0016 LibertyReader.cc:996 default_max_fanout is 0.0. -0017 Sta.cc:2083 '%s' is not a valid endpoint. -0018 Sta.cc:2007 '%s' is not a valid startoint. +0017 Sta.cc:2094 '%s' is not a valid endpoint. +0018 Sta.cc:2018 '%s' is not a valid start point. 0021 SpefParse.yy:805 %d is not positive. 0022 SpefParse.yy:814 %.4f is not positive. 0023 SpefParse.yy:820 %.4f is not positive. 0024 WritePathSpice.cc:425 pg_pin %s/%s voltage %s not found, 0025 WritePathSpice.cc:432 Liberty pg_port %s/%s missing voltage_name attribute, -0026 WritePathSpice.cc:962 %s pg_port %s not found, -0027 WritePathSpice.cc:1017 no register/latch found for path from %s to %s, -0028 WritePathSpice.cc:1384 The following subkcts are missing from %s -0029 WritePathSpice.cc:1442 subckt %s port %s has no corresponding liberty port, pg_port and is not power or ground. +0026 WritePathSpice.cc:960 %s pg_port %s not found, +0027 WritePathSpice.cc:1015 no register/latch found for path from %s to %s, +0028 WritePathSpice.cc:1382 The following subkcts are missing from %s +0029 WritePathSpice.cc:1440 subckt %s port %s has no corresponding liberty port, pg_port and is not power or ground. 0030 LibertyReader.cc:575 library missing name. 0031 LibertyReader.cc:607 default_wire_load %s not found. 0032 LibertyReader.cc:618 default_wire_selection %s not found. @@ -57,123 +58,128 @@ 0059 LibertyReader.cc:1114 default_wire_load_mode %s not found. 0060 LibertyReader.cc:630 default_operating_condition %s not found. 0061 LibertyReader.cc:1285 table template missing name. -0062 LibertyReader.cc:1330 missing variable_%d attribute. -0063 LibertyReader.cc:1372 axis type %s not supported. -0064 LibertyReader.cc:1432 bus type %s missing bit_from. -0065 LibertyReader.cc:1434 bus type %s missing bit_to. -0066 LibertyReader.cc:1438 type missing name. -0067 LibertyReader.cc:1465 scaling_factors do not have a name. -0068 LibertyReader.cc:1633 operating_conditions missing name. -0069 LibertyReader.cc:1703 wire_load missing name. -0070 LibertyReader.cc:1746 fanout_length is missing length and fanout. -0071 LibertyReader.cc:1761 wire_load_selection missing name. -0072 LibertyReader.cc:1792 wireload %s not found. -0074 LibertyReader.cc:1799 wire_load_from_area min not a float. -0075 LibertyReader.cc:1802 wire_load_from_area max not a float. -0076 LibertyReader.cc:1805 wire_load_from_area missing parameters. -0077 LibertyReader.cc:1808 wire_load_from_area missing parameters. -0078 LibertyReader.cc:1825 cell missing name. -0079 LibertyReader.cc:1848 cell %s ocv_derate_group %s not found. -0080 LibertyReader.cc:1884 port %s function size does not match port size. -0081 LibertyReader.cc:1953 %s %s bus width mismatch. -0082 LibertyReader.cc:1964 %s %s bus width mismatch. -0083 LibertyReader.cc:1974 clear -0084 LibertyReader.cc:1984 preset -0085 LibertyReader.cc:2020 latch enable function is non-unate for port %s. -0086 LibertyReader.cc:2025 latch enable function is unknown for port %s. -0087 LibertyReader.cc:2101 operating conditions %s not found. -0088 LibertyReader.cc:2104 scaled_cell missing operating condition. -0089 LibertyReader.cc:2107 scaled_cell cell %s has not been defined. -0090 LibertyReader.cc:2110 scaled_cell missing name. -0091 LibertyReader.cc:2136 scaled_cell %s, %s port functions do not match cell port functions. -0092 LibertyReader.cc:2141 scaled_cell ports do not match cell ports. -0093 LibertyReader.cc:2143 scaled_cell %s, %s timing does not match cell timing. -0094 LibertyReader.cc:2162 combinational timing to an input port. -0095 LibertyReader.cc:2249 missing %s_transition. -0096 LibertyReader.cc:2251 missing cell_%s. -0099 LibertyReader.cc:2517 scaling_factors %s not found. -0100 LibertyReader.cc:2560 pin name is not a string. -0101 LibertyReader.cc:2579 pin name is not a string. -0102 LibertyReader.cc:2601 pin name is not a string. -0103 LibertyReader.cc:2679 bus %s bus_type not found. -0104 LibertyReader.cc:2736 bus_type %s not found. -0105 LibertyReader.cc:2739 bus_type is not a string. -0106 LibertyReader.cc:2757 bundle %s member not found. -0107 LibertyReader.cc:2784 member is not a string. -0108 LibertyReader.cc:2791 members attribute is missing values. -0109 LibertyReader.cc:2834 unknown port direction. -0110 LibertyReader.cc:3204 pulse_latch unknown pulse type. -0111 LibertyReader.cc:3581 unknown timing_type %s. -0112 LibertyReader.cc:3601 unknown timing_sense %s. -0113 LibertyReader.cc:3641 mode value is not a string. -0114 LibertyReader.cc:3644 missing mode value. -0115 LibertyReader.cc:3647 mode name is not a string. -0116 LibertyReader.cc:3650 mode missing values. -0117 LibertyReader.cc:3653 mode missing mode name and value. -0118 LibertyReader.cc:3729 unsupported model axis. -0119 LibertyReader.cc:3758 unsupported model axis. -0120 LibertyReader.cc:3789 unsupported model axis. -0121 LibertyReader.cc:3826 unsupported model axis. -0122 LibertyReader.cc:3878 table template %s not found. -0123 LibertyReader.cc:3965 %s is missing values. -0124 LibertyReader.cc:3990 %s is not a list of floats. -0125 LibertyReader.cc:3992 table row has %u columns but axis has %d. -0126 LibertyReader.cc:4002 table has %u rows but axis has %d. -0127 LibertyReader.cc:4056 lut output is not a string. -0128 LibertyReader.cc:4094 mode definition missing name. -0129 LibertyReader.cc:4111 mode value missing name. -0130 LibertyReader.cc:4125 when attribute inside table model. -0131 LibertyReader.cc:4174 %s attribute is not a string. -0132 LibertyReader.cc:4177 %s is not a simple attribute. -0133 LibertyReader.cc:4200 %s is not a simple attribute. -0134 LibertyReader.cc:4213 %s is not a simple attribute. -0135 LibertyReader.cc:4237 %s value %s is not a float. -0136 LibertyReader.cc:4266 %s missing values. -0137 LibertyReader.cc:4270 %s missing values. -0138 LibertyReader.cc:4273 %s is not a complex attribute. -0139 LibertyReader.cc:4299 %s is not a float. -0140 LibertyReader.cc:4318 %s is missing values. -0141 LibertyReader.cc:4321 %s has more than one string. -0142 LibertyReader.cc:4330 %s is missing values. -0143 LibertyReader.cc:4355 %s attribute is not boolean. -0144 LibertyReader.cc:4358 %s attribute is not boolean. -0145 LibertyReader.cc:4361 %s is not a simple attribute. -0146 LibertyReader.cc:4377 attribute %s value %s not recognized. -0147 LibertyReader.cc:4407 unknown early/late value. -0148 LibertyReader.cc:4633 OCV derate group named %s not found. -0149 LibertyReader.cc:4649 ocv_derate missing name. -0150 LibertyReader.cc:4702 unknown rise/fall. -0151 LibertyReader.cc:4722 unknown derate type. -0152 LibertyReader.cc:4754 unsupported model axis. -0153 LibertyReader.cc:4788 unsupported model axis. -0154 LibertyReader.cc:4822 unsupported model axis. -0155 LibertyReader.cc:4895 unknown pg_type. -0156 LibertyReader.cc:5272 port %s subscript out of range. -0157 LibertyReader.cc:5276 port range %s of non-bus port %s. -0158 LibertyReader.cc:5290 port %s not found. -0159 LibertyReader.cc:5360 port %s not found. +0062 LibertyReader.cc:1327 missing variable_%d attribute. +0063 LibertyReader.cc:1370 axis type %s not supported. +0064 LibertyReader.cc:1430 bus type %s missing bit_from. +0065 LibertyReader.cc:1432 bus type %s missing bit_to. +0066 LibertyReader.cc:1436 type missing name. +0067 LibertyReader.cc:1463 scaling_factors do not have a name. +0068 LibertyReader.cc:1631 operating_conditions missing name. +0069 LibertyReader.cc:1701 wire_load missing name. +0070 LibertyReader.cc:1744 fanout_length is missing length and fanout. +0071 LibertyReader.cc:1759 wire_load_selection missing name. +0072 LibertyReader.cc:1790 wireload %s not found. +0074 LibertyReader.cc:1797 wire_load_from_area min not a float. +0075 LibertyReader.cc:1800 wire_load_from_area max not a float. +0076 LibertyReader.cc:1803 wire_load_from_area missing parameters. +0077 LibertyReader.cc:1806 wire_load_from_area missing parameters. +0078 LibertyReader.cc:1823 cell missing name. +0079 LibertyReader.cc:1846 cell %s ocv_derate_group %s not found. +0080 LibertyReader.cc:1882 port %s function size does not match port size. +0081 LibertyReader.cc:1950 %s %s bus width mismatch. +0082 LibertyReader.cc:1961 %s %s bus width mismatch. +0083 LibertyReader.cc:1971 clear +0084 LibertyReader.cc:1981 preset +0085 LibertyReader.cc:2017 latch enable function is non-unate for port %s. +0086 LibertyReader.cc:2022 latch enable function is unknown for port %s. +0087 LibertyReader.cc:2098 operating conditions %s not found. +0088 LibertyReader.cc:2101 scaled_cell missing operating condition. +0089 LibertyReader.cc:2104 scaled_cell cell %s has not been defined. +0090 LibertyReader.cc:2107 scaled_cell missing name. +0091 LibertyReader.cc:2133 scaled_cell %s, %s port functions do not match cell port functions. +0092 LibertyReader.cc:2138 scaled_cell ports do not match cell ports. +0093 LibertyReader.cc:2140 scaled_cell %s, %s timing does not match cell timing. +0094 LibertyReader.cc:2159 combinational timing to an input port. +0095 LibertyReader.cc:2247 missing %s_transition. +0096 LibertyReader.cc:2249 missing cell_%s. +0099 LibertyReader.cc:2525 scaling_factors %s not found. +0100 LibertyReader.cc:2568 pin name is not a string. +0101 LibertyReader.cc:2587 pin name is not a string. +0102 LibertyReader.cc:2609 pin name is not a string. +0103 LibertyReader.cc:2687 bus %s bus_type not found. +0104 LibertyReader.cc:2743 bus_type %s not found. +0105 LibertyReader.cc:2746 bus_type is not a string. +0106 LibertyReader.cc:2764 bundle %s member not found. +0107 LibertyReader.cc:2791 member is not a string. +0108 LibertyReader.cc:2798 members attribute is missing values. +0109 LibertyReader.cc:2841 unknown port direction. +0110 LibertyReader.cc:3211 pulse_latch unknown pulse type. +0111 LibertyReader.cc:3588 unknown timing_type %s. +0112 LibertyReader.cc:3608 unknown timing_sense %s. +0113 LibertyReader.cc:3648 mode value is not a string. +0114 LibertyReader.cc:3651 missing mode value. +0115 LibertyReader.cc:3654 mode name is not a string. +0116 LibertyReader.cc:3657 mode missing values. +0117 LibertyReader.cc:3660 mode missing mode name and value. +0118 LibertyReader.cc:3736 unsupported model axis. +0119 LibertyReader.cc:3765 unsupported model axis. +0120 LibertyReader.cc:3796 unsupported model axis. +0121 LibertyReader.cc:3833 unsupported model axis. +0122 LibertyReader.cc:3885 table template %s not found. +0123 LibertyReader.cc:3960 %s is missing values. +0124 LibertyReader.cc:3985 %s is not a list of floats. +0125 LibertyReader.cc:3987 table row has %u columns but axis has %d. +0126 LibertyReader.cc:3997 table has %u rows but axis has %d. +0127 LibertyReader.cc:4050 lut output is not a string. +0128 LibertyReader.cc:4088 mode definition missing name. +0129 LibertyReader.cc:4105 mode value missing name. +0130 LibertyReader.cc:4119 when attribute inside table model. +0131 LibertyReader.cc:4168 %s attribute is not a string. +0132 LibertyReader.cc:4171 %s is not a simple attribute. +0133 LibertyReader.cc:4194 %s is not a simple attribute. +0134 LibertyReader.cc:4207 %s is not a simple attribute. +0135 LibertyReader.cc:4231 %s value %s is not a float. +0136 LibertyReader.cc:4260 %s missing values. +0137 LibertyReader.cc:4264 %s missing values. +0138 LibertyReader.cc:4267 %s is not a complex attribute. +0139 LibertyReader.cc:4293 %s is not a float. +0140 LibertyReader.cc:4312 %s is missing values. +0141 LibertyReader.cc:4315 %s has more than one string. +0142 LibertyReader.cc:4324 %s is missing values. +0143 LibertyReader.cc:4349 %s attribute is not boolean. +0144 LibertyReader.cc:4352 %s attribute is not boolean. +0145 LibertyReader.cc:4355 %s is not a simple attribute. +0146 LibertyReader.cc:4371 attribute %s value %s not recognized. +0147 LibertyReader.cc:4401 unknown early/late value. +0148 LibertyReader.cc:4627 OCV derate group named %s not found. +0149 LibertyReader.cc:4643 ocv_derate missing name. +0150 LibertyReader.cc:4696 unknown rise/fall. +0151 LibertyReader.cc:4716 unknown derate type. +0152 LibertyReader.cc:4748 unsupported model axis. +0153 LibertyReader.cc:4782 unsupported model axis. +0154 LibertyReader.cc:4816 unsupported model axis. +0155 LibertyReader.cc:4889 unknown pg_type. +0156 LibertyReader.cc:5263 port %s subscript out of range. +0157 LibertyReader.cc:5267 port range %s of non-bus port %s. +0158 LibertyReader.cc:5281 port %s not found. +0159 LibertyReader.cc:5351 port %s not found. 0160 LibertyReader.cc:981 default_max_transition is 0.0. -0161 LibertyReader.cc:3092 max_transition is 0.0. -0162 LibertyReader.cc:4197 %s attribute is not an integer. +0161 LibertyReader.cc:3099 max_transition is 0.0. +0162 LibertyReader.cc:4191 %s attribute is not an integer. 0163 LibertyReader.cc:1086 default_fanout_load is 0.0. -0179 SpefReader.cc:728 %s. +0164 LibertyReader.cc:2270 timing group from output port. +0165 LibertyReader.cc:2280 timing group from output port. +0166 LibertyReader.cc:2290 timing group from output port. +0167 LibertyReader.cc:2308 timing group from output port. +0168 LibertyReader.cc:2323 timing group from output port. +0179 SpefReader.cc:725 %s. 0190 VerilogReader.cc:1728 %s is not a verilog module. 0191 VerilogReader.cc:1733 %s is not a verilog module. 0201 StaTcl.i:129 no network has been linked. 0202 StaTcl.i:143 network does not support edits. 0204 StaTcl.i:4182 POCV support requires compilation with SSTA=1. 0206 LibertyExpr.cc:171 %s %s. -0207 GraphDelayCalc1.cc:742 port not found in cell -0208 Graph.cc:795 arc_delay_annotated array bounds exceeded -0209 Graph.cc:810 arc_delay_annotated array bounds exceeded -0210 Graph.cc:822 arc_delay_annotated array bounds exceeded +0207 GraphDelayCalc1.cc:738 port not found in cell +0208 Graph.cc:793 arc_delay_annotated array bounds exceeded +0209 Graph.cc:808 arc_delay_annotated array bounds exceeded +0210 Graph.cc:820 arc_delay_annotated array bounds exceeded 0211 SdcNetwork.cc:1026 inst path string lenth estimate busted 0212 SdcNetwork.cc:1098 inst path string lenth estimate exceeded -0213 Sdc.cc:4114 group path name and is_default are mutually exclusive. +0213 Sdc.cc:4101 group path name and is_default are mutually exclusive. 0214 WriteSdc.cc:1317 unknown exception type 0215 WriteSdc.cc:1888 illegal set_logic value 0216 WriteSdc.cc:1932 invalid set_case_analysis value -0228 Graph.cc:835 arc_delay_annotated array bounds exceeded +0228 Graph.cc:833 arc_delay_annotated array bounds exceeded 0251 PathEnumed.cc:126 enumerated path required time 0252 PathEnumed.cc:135 enumerated path required time 0253 PathGroup.cc:402 unknown path end type @@ -183,16 +189,16 @@ 0257 ReportPath.cc:349 unsupported path type 0258 ReportPath.cc:2228 generated clock pll source path too short. 0259 ReportPath.cc:2392 unsupported path type -0260 Search.cc:2668 max tag group index exceeded -0261 Search.cc:2900 max tag index exceeded -0262 Search.cc:3595 unexpected filter path -0263 Search.cc:3763 tns incr existing vertex -0264 Sta.cc:4132 corresponding timing arc set not found in equiv cells +0260 Search.cc:2637 max tag group index exceeded +0261 Search.cc:2869 max tag index exceeded +0262 Search.cc:3561 unexpected filter path +0263 Search.cc:3729 tns incr existing vertex +0264 Sta.cc:4150 corresponding timing arc set not found in equiv cells 0265 TagGroup.cc:297 tag group missing tag -0266 Sta.cc:2080 '%s' is not a valid endpoint. -0267 Sta.cc:2004 '%s' is not a valid startpoint. +0266 Sta.cc:2091 '%s' is not a valid endpoint. +0267 Sta.cc:2015 '%s' is not a valid start point. 0272 StaTcl.i:4168 unknown common clk pessimism mode. -0273 StaTcl.i:5176 unknown clock sense +0273 StaTcl.i:5187 unknown clock sense 0300 Util.tcl:218 no commands match '$pattern'. 0301 Power.tcl:215 activity should be 0.0 to 1.0 or 2.0 0302 Power.tcl:223 duty should be 0.0 to 1.0 @@ -203,7 +209,7 @@ 0314 Cmds.tcl:850 $arg_name must be a single net. 0315 Cmds.tcl:856 $arg_name '$object_type' is not a net. 0316 Cmds.tcl:861 $arg_name '$arg' not found. -0318 Search.tcl:1045 unknown path group '$name'. +0318 Search.tcl:1073 unknown path group '$name'. 0319 Sdc.tcl:279 $unit scale [format %.0e $scale] does not match library scale [format %.0e $unit_scale]. 0320 Sdc.tcl:480 current_design for other than top cell not supported. 0321 Sdc.tcl:517 patterns argument not supported with -of_objects. @@ -232,32 +238,32 @@ 0345 Sdc.tcl:1575 -pulse argument not supported. 0346 Sdc.tcl:1584 -positive, -negative, -stop_propagation and -pulse are mutually exclusive. 0347 Sdc.tcl:1597 hierarchical pin '[get_full_name $pin]' not supported. -0348 Sdc.tcl:1799 -from/-to keywords ignored for lib_pin, port and pin arguments. +0348 Sdc.tcl:1805 -from/-to keywords ignored for lib_pin, port and pin arguments. 0349 Sdc.tcl:1467 unknown keyword argument $arg. -0350 Sdc.tcl:1947 -from, -through or -to required. -0351 Sdc.tcl:2026 -source_latency_included ignored with -reference_pin. -0352 Sdc.tcl:2029 -network_latency_included ignored with -reference_pin. -0353 Sdc.tcl:2048 $cmd not allowed on [pin_direction $pin] port '[get_full_name $pin]'. -0354 Sdc.tcl:2050 $cmd relative to a clock defined on the same port/pin not allowed. -0355 Sdc.tcl:2093 '$args' ignored. -0356 Sdc.tcl:2223 '$args' ignored. -0357 Sdc.tcl:2270 virtual clock [get_name $clk] can not be propagated. -0358 Sdc.tcl:2419 -multiply_by ignored. -0359 Sdc.tcl:2422 -dont_scale ignored. -0360 Sdc.tcl:2425 -no_design_rule ignored. -0361 Sdc.tcl:2466 -clock not supported. -0362 Sdc.tcl:2469 -clock_fall not supported. -0363 Sdc.tcl:2515 -pin_load not allowed for net objects. -0364 Sdc.tcl:2518 -wire_load not allowed for net objects. -0365 Sdc.tcl:2521 -rise/-fall not allowed for net objects. -0366 Sdc.tcl:2654 -data_path, -clock_path, -rise, -fall ignored for ports and designs. -0367 Sdc.tcl:2724 derating factor greater than 2.0. -0368 Sdc.tcl:2761 -cell_delay and -cell_check flags ignored for net objects. -0369 Sdc.tcl:2820 no valid objects specified for $key. -0370 Sdc.tcl:2853 no valid objects specified for $key -0371 Sdc.tcl:3014 set_wire_load_min_block_size not supported. +0350 Sdc.tcl:1953 -from, -through or -to required. +0351 Sdc.tcl:2032 -source_latency_included ignored with -reference_pin. +0352 Sdc.tcl:2035 -network_latency_included ignored with -reference_pin. +0353 Sdc.tcl:2054 $cmd not allowed on [pin_direction $pin] port '[get_full_name $pin]'. +0354 Sdc.tcl:2056 $cmd relative to a clock defined on the same port/pin not allowed. +0355 Sdc.tcl:2099 '$args' ignored. +0356 Sdc.tcl:2229 '$args' ignored. +0357 Sdc.tcl:2276 virtual clock [get_name $clk] can not be propagated. +0358 Sdc.tcl:2425 -multiply_by ignored. +0359 Sdc.tcl:2428 -dont_scale ignored. +0360 Sdc.tcl:2431 -no_design_rule ignored. +0361 Sdc.tcl:2472 -clock not supported. +0362 Sdc.tcl:2475 -clock_fall not supported. +0363 Sdc.tcl:2521 -pin_load not allowed for net objects. +0364 Sdc.tcl:2524 -wire_load not allowed for net objects. +0365 Sdc.tcl:2527 -rise/-fall not allowed for net objects. +0366 Sdc.tcl:2660 -data_path, -clock_path, -rise, -fall ignored for ports and designs. +0367 Sdc.tcl:2730 derating factor greater than 2.0. +0368 Sdc.tcl:2767 -cell_delay and -cell_check flags ignored for net objects. +0369 Sdc.tcl:2826 no valid objects specified for $key. +0370 Sdc.tcl:2859 no valid objects specified for $key +0371 Sdc.tcl:3020 set_wire_load_min_block_size not supported. 0372 NetworkEdit.tcl:80 connect_pins is deprecated. Use connect_pin. -0373 Sdc.tcl:3164 define_corners must be called before read_liberty. +0373 Sdc.tcl:3170 define_corners must be called before read_liberty. 0400 Util.tcl:44 $cmd $key missing value. 0401 Util.tcl:61 $cmd $key missing value. 0402 Util.tcl:71 $cmd $arg is not a known keyword or flag. @@ -286,18 +292,18 @@ 0425 Search.tcl:207 positional arguments not supported. 0426 Search.tcl:526 analysis type single is not consistent with doing both setup/max and hold/min checks. 0427 Search.tcl:531 positional arguments not supported. -0428 Sta.tcl:867 set_assigned_transition transition is not a float. +0428 Sta.tcl:861 set_assigned_transition transition is not a float. 0430 Sdf.tcl:46 -cond_use min_max cannot be used with analysis type single. 0432 Sdf.tcl:157 SDF -divider must be / or . -0433 Parasitics.tcl:47 path instance '$path' not found. -0434 Parasitics.tcl:65 -reduce_to must be pi_elmore or pi_pole_residue2. +0433 Parasitics.tcl:45 path instance '$path' not found. +0434 Parasitics.tcl:62 -reduce_to must be pi_elmore or pi_pole_residue2. 0435 DelayCalc.tcl:119 delay calculator $alg not found. 0436 Variables.tcl:45 sta_report_default_digits must be a positive integer. 0437 Variables.tcl:70 sta_crpr_mode must be pin or transition. 0438 Variables.tcl:187 $var_name value must be 0 or 1. -0439 Sta.tcl:941 unsupported object type $list_type. -0440 Sta.tcl:1239 -from/-to arguments not supported with -of_objects. -0441 Sta.tcl:1377 unsupported -filter expression. +0439 Sta.tcl:935 unsupported object type $list_type. +0440 Sta.tcl:1233 -from/-to arguments not supported with -of_objects. +0441 Sta.tcl:1361 unsupported -filter expression. 0442 Sta.tcl:657 $cmd missing -from argument. 0443 Sta.tcl:662 $cmd missing -to argument. 0444 Sta.tcl:667 $cmd delay is not a float. @@ -305,11 +311,11 @@ 0446 Sta.tcl:678 $cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]. 0447 Sta.tcl:683 $cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst] 0448 Sta.tcl:688 $cmd -cell or -net required. -0449 Sta.tcl:757 $cmd missing -from argument. -0450 Sta.tcl:766 $cmd -clock must be rise or fall. -0451 Sta.tcl:773 $cmd missing -to argument. -0452 Sta.tcl:788 $cmd missing -setup|-hold|-recovery|-removal check type.. -0453 Sta.tcl:796 $cmd check_value is not a float. +0449 Sta.tcl:754 $cmd missing -from argument. +0450 Sta.tcl:763 $cmd -clock must be rise or fall. +0451 Sta.tcl:770 $cmd missing -to argument. +0452 Sta.tcl:785 $cmd missing -setup|-hold|-recovery|-removal check type.. +0453 Sta.tcl:793 $cmd check_value is not a float. 0454 Sta.tcl:100 the -all and -name options are mutually exclusive. 0455 Sta.tcl:103 either -all or -name options must be specified. 0456 Sta.tcl:111 one of -logically_exclusive, -physically_exclusive or -asynchronous is required. @@ -347,23 +353,23 @@ 0488 Cmds.tcl:727 $arg_name type '$object_type' is not a pin or port. 0489 Cmds.tcl:734 pin '$arg' not found. 0490 Cmds.tcl:754 $arg_name type '$object_type' is not a port. -0491 Sta.tcl:1091 $cmd object is null. -0492 Sta.tcl:1096 $cmd $type_key must be specified with object name argument. -0493 Sta.tcl:1139 get_property $object is not an object. -0494 Sta.tcl:1162 $object_type not supported. -0495 Sta.tcl:1165 $object_type '$object_name' not found. -0496 Sta.tcl:1492 Directory $spice_dir not found. -0497 Sta.tcl:1495 $spice_dir is not a directory. -0498 Sta.tcl:1498 Cannot write in $spice_dir. -0499 Sta.tcl:1501 No -spice_directory specified. -0500 Sta.tcl:1507 -lib_subckt_file $lib_subckt_file is not readable. -0501 Sta.tcl:1510 No -lib_subckt_file specified. -0502 Sta.tcl:1516 -model_file $model_file is not readable. -0503 Sta.tcl:1519 No -model_file specified. -0504 Sta.tcl:1525 No -power specified. -0505 Sta.tcl:1531 No -ground specified. -0506 Sta.tcl:1535 No -path_args specified. -0507 Sta.tcl:1540 No paths found for -path_args $path_args. +0491 Sta.tcl:1085 $cmd object is null. +0492 Sta.tcl:1090 $cmd $type_key must be specified with object name argument. +0493 Sta.tcl:1133 get_property $object is not an object. +0494 Sta.tcl:1156 $object_type not supported. +0495 Sta.tcl:1159 $object_type '$object_name' not found. +0496 Sta.tcl:1476 Directory $spice_dir not found. +0497 Sta.tcl:1479 $spice_dir is not a directory. +0498 Sta.tcl:1482 Cannot write in $spice_dir. +0499 Sta.tcl:1485 No -spice_directory specified. +0500 Sta.tcl:1491 -lib_subckt_file $lib_subckt_file is not readable. +0501 Sta.tcl:1494 No -lib_subckt_file specified. +0502 Sta.tcl:1500 -model_file $model_file is not readable. +0503 Sta.tcl:1503 No -model_file specified. +0504 Sta.tcl:1509 No -power specified. +0505 Sta.tcl:1515 No -ground specified. +0506 Sta.tcl:1519 No -path_args specified. +0507 Sta.tcl:1524 No paths found for -path_args $path_args. 0508 Search.tcl:794 -min and -max cannot both be specified. 0509 Search.tcl:814 pin '$pin_arg' is hierarchical. 0510 Search.tcl:880 -format $format not recognized. @@ -417,31 +423,31 @@ 0558 Sdc.tcl:1552 set_sense -type clock|data 0559 Sdc.tcl:1621 transition time can not be specified for virtual clocks. 0560 Sdc.tcl:1642 missing uncertainty value. -0561 Sdc.tcl:1684 -from/-to must be used together. -0562 Sdc.tcl:1704 -rise, -fall options not allowed for single clock uncertainty. -0563 Sdc.tcl:1745 missing -from, -rise_from or -fall_from argument. -0564 Sdc.tcl:1757 missing -to, -rise_to or -fall_to argument. -0565 Sdc.tcl:1829 -from/-to hierarchical instance not supported. -0566 Sdc.tcl:1861 pin '[get_full_name $inst]${hierarchy_separator}${port_name}' not found. -0567 Sdc.tcl:1902 pin '[get_name $cell]${hierarchy_separator}${port_name}' not found. -0568 Sdc.tcl:2087 missing delay argument. -0569 Sdc.tcl:2218 missing path multiplier argument. -0570 Sdc.tcl:2230 cannot use -start with -end. -0571 Sdc.tcl:2298 value must be 0, zero, 1, one, rise, rising, fall, or falling. -0572 Sdc.tcl:2356 cell '$lib_name:$cell_name' not found. -0573 Sdc.tcl:2362 '$cell_name' not found. -0574 Sdc.tcl:2366 missing -lib_cell argument. -0575 Sdc.tcl:2374 port '$to_port_name' not found. -0576 Sdc.tcl:2386 -pin argument required for cells with multiple outputs. -0577 Sdc.tcl:2401 port '$from_port_name' not found. -0578 Sdc.tcl:2608 port '[get_name $port]' is not an input. -0579 Sdc.tcl:2970 operating condition '$op_cond_name' not found. -0580 Sdc.tcl:2988 operating condition '$op_cond_name' not found. -0581 Sdc.tcl:3002 -analysis_type must be single, bc_wc or on_chip_variation. -0582 Sdc.tcl:3027 mode must be top, enclosed or segmented. -0583 Sdc.tcl:3042 no wire load model specified. -0584 Sdc.tcl:3103 wire load selection group '$selection_name' not found. -0585 Sdc.tcl:3234 no default operating conditions found. +0561 Sdc.tcl:1690 -from/-to must be used together. +0562 Sdc.tcl:1710 -rise, -fall options not allowed for single clock uncertainty. +0563 Sdc.tcl:1751 missing -from, -rise_from or -fall_from argument. +0564 Sdc.tcl:1763 missing -to, -rise_to or -fall_to argument. +0565 Sdc.tcl:1835 -from/-to hierarchical instance not supported. +0566 Sdc.tcl:1867 pin '[get_full_name $inst]${hierarchy_separator}${port_name}' not found. +0567 Sdc.tcl:1908 pin '[get_name $cell]${hierarchy_separator}${port_name}' not found. +0568 Sdc.tcl:2093 missing delay argument. +0569 Sdc.tcl:2224 missing path multiplier argument. +0570 Sdc.tcl:2236 cannot use -start with -end. +0571 Sdc.tcl:2304 value must be 0, zero, 1, one, rise, rising, fall, or falling. +0572 Sdc.tcl:2362 cell '$lib_name:$cell_name' not found. +0573 Sdc.tcl:2368 '$cell_name' not found. +0574 Sdc.tcl:2372 missing -lib_cell argument. +0575 Sdc.tcl:2380 port '$to_port_name' not found. +0576 Sdc.tcl:2392 -pin argument required for cells with multiple outputs. +0577 Sdc.tcl:2407 port '$from_port_name' not found. +0578 Sdc.tcl:2614 port '[get_name $port]' is not an input. +0579 Sdc.tcl:2976 operating condition '$op_cond_name' not found. +0580 Sdc.tcl:2994 operating condition '$op_cond_name' not found. +0581 Sdc.tcl:3008 -analysis_type must be single, bc_wc or on_chip_variation. +0582 Sdc.tcl:3033 mode must be top, enclosed or segmented. +0583 Sdc.tcl:3048 no wire load model specified. +0584 Sdc.tcl:3109 wire load selection group '$selection_name' not found. +0585 Sdc.tcl:3240 no default operating conditions found. 0586 NetworkEdit.tcl:50 unsupported object type $object_type. 0587 NetworkEdit.tcl:119 unsupported object type $object_type. 0588 NetworkEdit.tcl:135 unsupported object type $object_type. @@ -454,13 +460,13 @@ 0595 DelayNormal2.cc:378 unknown early/late value. 0596 Sim.cc:205 unknown function operator 0597 EstimateParasitics.cc:188 load pin not leaf or top level -0600 Sdc.tcl:1943 '$args' ignored. -0601 Sdc.tcl:2442 set_fanout_load not supported. -0602 Sdc.tcl:2902 no valid objects specified for $key. +0600 Sdc.tcl:1949 '$args' ignored. +0601 Sdc.tcl:2448 set_fanout_load not supported. +0602 Sdc.tcl:2908 no valid objects specified for $key. 0603 NetworkEdit.tcl:172 disconnect_pins is deprecated. Use disconnect_pin. 0604 Sdc.tcl:272 unknown $unit prefix '$prefix'. -0605 Sdc.tcl:3064 wire load model '$model_name' not found. -0606 Sta.tcl:1136 get_property unsupported object type $object_type. +0605 Sdc.tcl:3070 wire load model '$model_name' not found. +0606 Sta.tcl:1130 get_property unsupported object type $object_type. 0607 StaTcl.i:4418 unknown report path field %s 0608 StaTcl.i:4430 unknown report path field %s 0609 Search.tcl:427 -all_violators is deprecated. Use -violators @@ -469,13 +475,16 @@ 0612 Sdf.tcl:41 -cond_use must be min, max or min_max. 0616 Search.tcl:1024 specify one of -setup and -hold. 0617 Sdf.tcl:50 -analysis_type is deprecated. Use set_operating_conditions -analysis_type. -0618 DmpCeff.cc:1579 parasitic Pi model has NaNs. -0619 PathEnum.cc:477 path diversion missing edge. +0618 DmpCeff.cc:1581 parasitic Pi model has NaNs. +0619 PathEnum.cc:474 path diversion missing edge. 0620 PathVertex.cc:236 missing arrivals. 0621 PathVertex.cc:250 missing arrivals. 0622 PathVertex.cc:279 missing requireds. 0623 PathVertexRep.cc:153 missing arrivals. 0624 PathVertexRep.cc:150 missing arrivals -0701 LibertyWriter.cc:360 %s/%s/%s timing model not supported. -0702 LibertyWriter.cc:379 3 axis table models not supported. -0703 LibertyWriter.cc:504 %s/%s/%s timing arc type %s not supported. +0701 LibertyWriter.cc:416 %s/%s/%s timing model not supported. +0702 LibertyWriter.cc:436 3 axis table models not supported. +0703 LibertyWriter.cc:576 %s/%s/%s timing arc type %s not supported. +0704 LibertyWriter.cc:289 %s/%s bundled ports not supported. +0705 LumpedCapDelayCalc.cc:168 gate delay input variable is NaN +0705 Liberty.cc:793 Liberty cell %s/%s for corner %s/%s not found diff --git a/network/ConcreteNetwork.cc b/network/ConcreteNetwork.cc index a5b4e276..825f322d 100644 --- a/network/ConcreteNetwork.cc +++ b/network/ConcreteNetwork.cc @@ -1849,6 +1849,8 @@ ConcreteNetwork::linkNetwork(const char *top_cell_name, clearConstantNets(); deleteTopInstance(); top_instance_ = link_func_(top_cell_name, make_black_boxes, report, this); + if (top_instance_) + checkNetworkLibertyCorners(); return top_instance_ != nullptr; } else { diff --git a/network/Network.cc b/network/Network.cc index 07753312..da692e11 100644 --- a/network/Network.cc +++ b/network/Network.cc @@ -21,6 +21,7 @@ #include "PatternMatch.hh" #include "Liberty.hh" #include "PortDirection.hh" +#include "Corner.hh" namespace sta { @@ -94,6 +95,47 @@ Network::setDefaultLibertyLibrary(LibertyLibrary *library) default_liberty_ = library; } +void +Network::checkLibertyCorners() +{ + if (corners_->count() > 1) { + LibertyLibraryIterator *lib_iter = libertyLibraryIterator(); + LibertyCellSet cells; + while (lib_iter->hasNext()) { + LibertyLibrary *lib = lib_iter->next(); + LibertyCellIterator cell_iter(lib); + while (cell_iter.hasNext()) { + LibertyCell *cell = cell_iter.next(); + LibertyCell *link_cell = findLibertyCell(cell->name()); + cells.insert(link_cell); + } + } + delete lib_iter; + + for (LibertyCell *cell : cells) + LibertyLibrary::checkCorners(cell, corners_, report_); + } +} + +void +Network::checkNetworkLibertyCorners() +{ + if (corners_->count() > 1) { + LibertyCellSet network_cells; + LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator(); + while (leaf_iter->hasNext()) { + const Instance *inst = leaf_iter->next(); + LibertyCell *cell = libertyCell(inst); + if (cell) + network_cells.insert(cell); + } + delete leaf_iter; + + for (LibertyCell *cell : network_cells) + LibertyLibrary::checkCorners(cell, corners_, report_); + } +} + // Only used by Sta::setMinLibrary so linear search is acceptable. LibertyLibrary * Network::findLibertyFilename(const char *filename) diff --git a/parasitics/Parasitics.i b/parasitics/Parasitics.i index 4344fbe5..2f923f86 100644 --- a/parasitics/Parasitics.i +++ b/parasitics/Parasitics.i @@ -38,7 +38,6 @@ read_spef_cmd(const char *filename, Instance *instance, const Corner *corner, const MinMaxAll *min_max, - bool increment, bool pin_cap_included, bool keep_coupling_caps, float coupling_cap_factor, @@ -48,9 +47,17 @@ read_spef_cmd(const char *filename, { cmdLinkedNetwork(); return Sta::sta()->readSpef(filename, instance, corner, min_max, - increment, pin_cap_included, - keep_coupling_caps, coupling_cap_factor, - reduce_to, delete_after_reduce, quiet); + pin_cap_included, keep_coupling_caps, + coupling_cap_factor, reduce_to, + delete_after_reduce, quiet); +} + +void +report_parasitic_annotation_cmd(bool report_unannotated, + const Corner *corner) +{ + cmdLinkedNetwork(); + Sta::sta()->reportParasiticAnnotation(report_unannotated, corner); } TmpFloatSeq * diff --git a/parasitics/Parasitics.tcl b/parasitics/Parasitics.tcl index eb628759..0022f371 100644 --- a/parasitics/Parasitics.tcl +++ b/parasitics/Parasitics.tcl @@ -21,7 +21,6 @@ define_cmd_args "read_spef" \ [-min]\ [-max]\ [-path path]\ - [-increment]\ [-pin_cap_included]\ [-keep_capacitive_coupling]\ [-coupling_reduction_factor factor]\ @@ -34,8 +33,7 @@ define_cmd_args "read_spef" \ proc_redirect read_spef { parse_key_args "read_spef" args \ keys {-path -coupling_reduction_factor -reduce_to -corner} \ - flags {-min -max -increment -pin_cap_included \ - -keep_capacitive_coupling \ + flags {-min -max -increment -pin_cap_included -keep_capacitive_coupling \ -delete_after_reduce -quiet -save} check_argc_eq1 "report_spef" $args @@ -49,7 +47,6 @@ proc_redirect read_spef { } set corner [parse_corner_or_all keys] set min_max [parse_min_max_all_flags flags] - set increment [info exists flags(-increment)] set coupling_reduction_factor 1.0 if [info exists keys(-coupling_reduction_factor)] { set coupling_reduction_factor $keys(-coupling_reduction_factor) @@ -69,11 +66,25 @@ proc_redirect read_spef { set quiet [info exists flags(-quiet)] set save [info exists flags(-save)] set filename [file nativename [lindex $args 0]] - return [read_spef_cmd $filename $instance $corner $min_max $increment \ + if { [info exists flags(-increment)] } { + sta_warn 706 "read_spef -increment is deprecated." + } + return [read_spef_cmd $filename $instance $corner $min_max \ $pin_cap_included $keep_coupling_caps $coupling_reduction_factor \ $reduce_to $delete_after_reduce $quiet] } +define_cmd_args "report_parasitic_annotation" {} + +proc_redirect report_parasitic_annotation { + parse_key_args "report_parasitic_annotation" args \ + keys {} flags {-report_unannotated} + check_argc_eq0 "report_parasitic_annotation" $args + + set report_unannotated [info exists flags(-report_unannotated)] + report_parasitic_annotation_cmd $report_unannotated [sta::cmd_corner] +} + # set_pi_model [-min] [-max] drvr_pin c2 rpi c1 proc set_pi_model { args } { parse_key_args "set_pi_model" args keys {} flags {-max -min} diff --git a/parasitics/ReportParasiticAnnotation.cc b/parasitics/ReportParasiticAnnotation.cc new file mode 100644 index 00000000..442f284a --- /dev/null +++ b/parasitics/ReportParasiticAnnotation.cc @@ -0,0 +1,151 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2022, 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 . + +#include "ReportParasiticAnnotation.hh" + +#include "Report.hh" +#include "Network.hh" +#include "Graph.hh" +#include "Corner.hh" +#include "Parasitics.hh" +#include "DcalcAnalysisPt.hh" +#include "ArcDelayCalc.hh" + +namespace sta { + +class ReportParasiticAnnotation : public StaState +{ +public: + ReportParasiticAnnotation(bool report_unannotated, + const Corner *corner, + StaState *sta); + void report(); + +private: + void reportAnnotationCounts(); + void findCounts(); + void findCounts(Instance *inst); + void findCounts(Net *net); + + bool report_unannotated_; + const Corner *corner_; + const MinMax *min_max_; + const DcalcAnalysisPt *dcalc_ap_; + const ParasiticAnalysisPt *parasitics_ap_; + NetSet unannotated_nets_; + VertexSet partially_annotated_drvrs_; +}; + +void +reportParasiticAnnotation(bool report_unannotated, + const Corner *corner, + StaState *sta) +{ + ReportParasiticAnnotation report_annotation(report_unannotated, corner, sta); + report_annotation.report(); +} + +ReportParasiticAnnotation::ReportParasiticAnnotation(bool report_unannotated, + const Corner *corner, + StaState *sta) : + StaState(sta), + report_unannotated_(report_unannotated), + corner_(corner), + min_max_(MinMax::max()), + dcalc_ap_(corner_->findDcalcAnalysisPt(min_max_)), + parasitics_ap_(corner_->findParasiticAnalysisPt(min_max_)), + partially_annotated_drvrs_(graph_) +{ +} + +void +ReportParasiticAnnotation::report() +{ + findCounts(); + reportAnnotationCounts(); +} + +void +ReportParasiticAnnotation::reportAnnotationCounts() +{ + report_->reportLine("Found %lu unannotated nets.", unannotated_nets_.size()); + if (report_unannotated_) { + for (const Net *net : unannotated_nets_) + report_->reportLine(" %s", network_->pathName(net)); + } + + report_->reportLine("Found %lu partially unannotated nets.", + partially_annotated_drvrs_.size()); + if (report_unannotated_) { + const RiseFall *rf = RiseFall::rise(); + for (Vertex *vertex : partially_annotated_drvrs_) { + Pin *drvr_pin = vertex->pin(); + Net *net = network_->isTopLevelPort(drvr_pin) + ? network_->net(network_->term(drvr_pin)) + : network_->net(drvr_pin); + report_->reportLine(" %s", network_->pathName(net)); + + Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, rf, dcalc_ap_); + VertexOutEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + Vertex *load_vertex = edge->to(graph_); + Pin *load_pin = load_vertex->pin(); + bool elmore_exists = false; + float elmore = 0.0; + parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists); + if (!elmore_exists) + report_->reportLine(" %s", network_->pathName(load_pin)); + } + } + } +} + +void +ReportParasiticAnnotation::findCounts() +{ + const RiseFall *rf = RiseFall::rise(); + VertexIterator vertex_iter(graph_); + while (vertex_iter.hasNext()) { + Vertex *vertex = vertex_iter.next(); + if (vertex->isDriver(network_)) { + Pin *drvr_pin = vertex->pin(); + Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, rf, dcalc_ap_); + if (parasitic) { + VertexOutEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + Vertex *load_vertex = edge->to(graph_); + Pin *load_pin = load_vertex->pin(); + bool elmore_exists = false; + float elmore = 0.0; + parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists); + if (!elmore_exists) + partially_annotated_drvrs_.insert(vertex); + } + } + else { + Net *net = network_->isTopLevelPort(drvr_pin) + ? network_->net(network_->term(drvr_pin)) + : network_->net(drvr_pin); + if (net) + unannotated_nets_.insert(net); + } + } + } +} + +} // namespace diff --git a/parasitics/ReportParasiticAnnotation.hh b/parasitics/ReportParasiticAnnotation.hh new file mode 100644 index 00000000..8e711c0c --- /dev/null +++ b/parasitics/ReportParasiticAnnotation.hh @@ -0,0 +1,29 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2022, 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 . + +#pragma once + +namespace sta { + +class StaState; +class Corner; + +void +reportParasiticAnnotation(bool report_unannotated, + const Corner *corner, + StaState *sta); + +} // namespace diff --git a/parasitics/SpefReader.cc b/parasitics/SpefReader.cc index b6eb8aeb..688a5054 100644 --- a/parasitics/SpefReader.cc +++ b/parasitics/SpefReader.cc @@ -45,7 +45,6 @@ bool readSpefFile(const char *filename, Instance *instance, ParasiticAnalysisPt *ap, - bool increment, bool pin_cap_included, bool keep_coupling_caps, float coupling_cap_factor, @@ -63,7 +62,7 @@ readSpefFile(const char *filename, // Use zlib to uncompress gzip'd files automagically. gzFile stream = gzopen(filename, "rb"); if (stream) { - SpefReader reader(filename, stream, instance, ap, increment, + SpefReader reader(filename, stream, instance, ap, pin_cap_included, keep_coupling_caps, coupling_cap_factor, reduce_to, delete_after_reduce, op_cond, corner, cnst_min_max, quiet, report, network, parasitics); @@ -83,7 +82,6 @@ SpefReader::SpefReader(const char *filename, gzFile stream, Instance *instance, ParasiticAnalysisPt *ap, - bool increment, bool pin_cap_included, bool keep_coupling_caps, float coupling_cap_factor, @@ -99,7 +97,6 @@ SpefReader::SpefReader(const char *filename, filename_(filename), instance_(instance), ap_(ap), - increment_(increment), pin_cap_included_(pin_cap_included), keep_coupling_caps_(keep_coupling_caps), reduce_to_(reduce_to), @@ -391,7 +388,7 @@ void SpefReader::rspfBegin(Net *net, SpefTriple *total_cap) { - if (net && !increment_) + if (net) parasitics_->deleteParasitics(net, ap_); // Net total capacitance is ignored. delete total_cap; @@ -407,19 +404,15 @@ SpefReader::rspfDrvrBegin(Pin *drvr_pin, SpefRspfPi *pi) { if (drvr_pin) { - // Incremental parasitics do not overwrite existing parasitics. - if (!(increment_ && - parasitics_->findPiElmore(drvr_pin, RiseFall::rise(), ap_))) { - float c2 = pi->c2()->value(triple_index_) * cap_scale_; - float rpi = pi->r1()->value(triple_index_) * res_scale_; - float c1 = pi->c1()->value(triple_index_) * cap_scale_; - // Delete pi model and elmore delays. - parasitics_->deleteParasitics(drvr_pin, ap_); - // Only one parasitic, save it under rise transition. - parasitic_ = parasitics_->makePiElmore(drvr_pin, - RiseFall::rise(), - ap_, c2, rpi, c1); - } + float c2 = pi->c2()->value(triple_index_) * cap_scale_; + float rpi = pi->r1()->value(triple_index_) * res_scale_; + float c1 = pi->c1()->value(triple_index_) * cap_scale_; + // Delete pi model and elmore delays. + parasitics_->deleteParasitics(drvr_pin, ap_); + // Only one parasitic, save it under rise transition. + parasitic_ = parasitics_->makePiElmore(drvr_pin, + RiseFall::rise(), + ap_, c2, rpi, c1); } delete pi; } @@ -447,14 +440,23 @@ SpefReader::dspfBegin(Net *net, SpefTriple *total_cap) { if (net) { - // Incremental parasitics do not overwrite existing parasitics. - if (increment_ - && parasitics_->findParasiticNetwork(net, ap_)) - parasitic_ = nullptr; - else { + if (network_->isTopInstance(instance_)) { parasitics_->deleteReducedParasitics(net, ap_); - parasitic_ = parasitics_->makeParasiticNetwork(net, pin_cap_included_, - ap_); + parasitic_ = parasitics_->makeParasiticNetwork(net, pin_cap_included_, ap_); + } + else { + Net *parasitic_owner = net; + NetTermIterator *term_iter = network_->termIterator(net); + if (term_iter->hasNext()) { + Term *term = term_iter->next(); + Pin *hpin = network_->pin(term); + parasitic_owner = network_->net(hpin); + } + delete term_iter; + parasitic_ = parasitics_->findParasiticNetwork(parasitic_owner, ap_); + if (parasitic_ == nullptr) + parasitic_ = parasitics_->makeParasiticNetwork(parasitic_owner, + pin_cap_included_, ap_); } net_ = net; } @@ -469,7 +471,6 @@ void SpefReader::dspfFinish() { if (parasitic_) { - // Checking "should" be done by report_annotated_parasitics. if (!quiet_) parasitics_->check(parasitic_); if (reduce_to_ != ReducedParasiticType::none) { diff --git a/parasitics/SpefReader.hh b/parasitics/SpefReader.hh index 06d37b61..e3191382 100644 --- a/parasitics/SpefReader.hh +++ b/parasitics/SpefReader.hh @@ -39,7 +39,6 @@ bool readSpefFile(const char *filename, Instance *instance, ParasiticAnalysisPt *ap, - bool increment, bool pin_cap_included, bool keep_coupling_caps, float coupling_cap_factor, diff --git a/parasitics/SpefReaderPvt.hh b/parasitics/SpefReaderPvt.hh index 66697db7..81c34103 100644 --- a/parasitics/SpefReaderPvt.hh +++ b/parasitics/SpefReaderPvt.hh @@ -49,7 +49,6 @@ public: gzFile stream, Instance *instance, ParasiticAnalysisPt *ap, - bool increment, bool pin_cap_included, bool keep_coupling_caps, float coupling_cap_factor, @@ -143,7 +142,6 @@ private: const char *filename_; Instance *instance_; const ParasiticAnalysisPt *ap_; - bool increment_; bool pin_cap_included_; bool keep_coupling_caps_; ReducedParasiticType reduce_to_; diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index f1fd1a83..6c9fdf5c 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -3296,7 +3296,7 @@ Sdc::portCapacitance(Instance *inst, Pvt *inst_pvt = nullptr; if (inst) inst_pvt = pvt(inst, min_max); - LibertyPort *corner_port = port->cornerPort(corner->libertyIndex(min_max)); + LibertyPort *corner_port = port->cornerPort(corner, min_max); return corner_port->capacitance(rf, min_max, op_cond, inst_pvt); } diff --git a/sdf/SdfReader.cc b/sdf/SdfReader.cc index 0815744e..1ad8598f 100644 --- a/sdf/SdfReader.cc +++ b/sdf/SdfReader.cc @@ -248,14 +248,16 @@ SdfReader::findWireEdge(Pin *from_pin, { Vertex *to_vertex, *to_vertex_bidirect_drvr; graph_->pinVertices(to_pin, to_vertex, to_vertex_bidirect_drvr); - // Fanin < fanout, so search for driver from load. - VertexInEdgeIterator edge_iter(to_vertex, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - const TimingRole *edge_role = edge->role(); - if (edge->from(graph_)->pin() == from_pin - && edge_role->sdfRole()->isWire()) - return edge; + if (to_vertex) { + // Fanin < fanout, so search for driver from load. + VertexInEdgeIterator edge_iter(to_vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + const TimingRole *edge_role = edge->role(); + if (edge->from(graph_)->pin() == from_pin + && edge_role->sdfRole()->isWire()) + return edge; + } } return nullptr; } diff --git a/search/CheckCapacitanceLimits.cc b/search/CheckCapacitanceLimits.cc index 49b203cf..0d915e3b 100644 --- a/search/CheckCapacitanceLimits.cc +++ b/search/CheckCapacitanceLimits.cc @@ -174,7 +174,7 @@ CheckCapacitanceLimits::findLimit(const Pin *pin, LibertyPort *to_port; drive->driveCell(rf, min_max, cell, from_port, from_slews, to_port); if (to_port) { - LibertyPort *corner_port = to_port->cornerPort(corner->libertyIndex(min_max)); + LibertyPort *corner_port = to_port->cornerPort(corner, min_max); corner_port->capacitanceLimit(min_max, limit1, exists1); if (!exists1 && corner_port->direction()->isAnyOutput() @@ -202,7 +202,7 @@ CheckCapacitanceLimits::findLimit(const Pin *pin, } LibertyPort *port = network->libertyPort(pin); if (port) { - LibertyPort *corner_port = port->cornerPort(corner->libertyIndex(min_max)); + LibertyPort *corner_port = port->cornerPort(corner, min_max); corner_port->capacitanceLimit(min_max, limit1, exists1); if (!exists1 && port->direction()->isAnyOutput()) diff --git a/search/CheckSlewLimits.cc b/search/CheckSlewLimits.cc index f4aa76b6..609f5584 100644 --- a/search/CheckSlewLimits.cc +++ b/search/CheckSlewLimits.cc @@ -224,7 +224,7 @@ CheckSlewLimits::findLimit(const Pin *pin, LibertyPort *to_port; drive->driveCell(rf, min_max, cell, from_port, from_slews, to_port); if (to_port) { - LibertyPort *corner_port = to_port->cornerPort(corner->libertyIndex(min_max)); + LibertyPort *corner_port = to_port->cornerPort(corner, min_max); corner_port->slewLimit(min_max, limit1, exists1); if (!exists1 && corner_port->direction()->isAnyOutput() @@ -268,7 +268,7 @@ CheckSlewLimits::findLimit(const LibertyPort *port, } if (port) { - const LibertyPort *corner_port = port->cornerPort(corner->libertyIndex(min_max)); + const LibertyPort *corner_port = port->cornerPort(corner, min_max); corner_port->slewLimit(min_max, limit1, exists1); if (!exists1 // default_max_transition only applies to outputs. diff --git a/search/ClkSkew.cc b/search/ClkSkew.cc index 77816dab..11d26538 100644 --- a/search/ClkSkew.cc +++ b/search/ClkSkew.cc @@ -172,16 +172,21 @@ ClkSkews::findWorstClkSkew(const Corner *corner, ClockSet clks; for (Clock *clk : *sdc_->clocks()) clks.insert(clk); - float worst_skew = INF; ClkSkewMap skews; findClkSkew(&clks, corner, setup_hold, skews); - for (auto clk_skew_itr : skews) { - ClkSkew *clk_skew = clk_skew_itr.second; - float skew = clk_skew->skew(); - if (skew < worst_skew) - worst_skew = skew; + if (!skews.empty()) { + float worst_skew = INF; + for (auto clk_skew_itr : skews) { + ClkSkew *clk_skew = clk_skew_itr.second; + float skew = clk_skew->skew(); + if (skew < worst_skew) + worst_skew = skew; + } + return worst_skew; } - return worst_skew; + else + // Degenerate design without launch/capture registers. + return 0.0; } void diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index 9a0a42d7..33b17eac 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -208,30 +208,32 @@ void MakeEndTimingArcs::visit(PathEnd *path_end) { ClockEdge *tgt_clk_edge = path_end->targetClkEdge(sta_); - Debug *debug = sta_->debug(); - const MinMax *min_max = path_end->minMax(sta_); - debugPrint(debug, "make_timing_model", 2, "%s %s -> clock %s %s %s", - sta_->network()->pathName(input_pin_), - input_rf_->shortName(), - tgt_clk_edge->name(), - path_end->typeName(), - min_max->asString()); - if (debug->check("make_timing_model", 3)) - sta_->reportPathEnd(path_end); - Arrival data_delay = path_end->path()->arrival(sta_); - Delay clk_latency = path_end->targetClkDelay(sta_); - ArcDelay check_margin = path_end->margin(sta_); - Delay margin = min_max == MinMax::max() - ? data_delay - clk_latency + check_margin - : clk_latency - data_delay + check_margin; - float delay1 = delayAsFloat(margin, MinMax::max(), sta_); - RiseFallMinMax &margins = margins_[tgt_clk_edge]; - float max_margin; - bool max_exists; - margins.value(input_rf_, min_max, max_margin, max_exists); - // Always max margin, even for min/hold checks. - margins.setValue(input_rf_, min_max, - max_exists ? max(max_margin, delay1) : delay1); + if (tgt_clk_edge) { + Debug *debug = sta_->debug(); + const MinMax *min_max = path_end->minMax(sta_); + debugPrint(debug, "make_timing_model", 2, "%s %s -> clock %s %s %s", + sta_->network()->pathName(input_pin_), + input_rf_->shortName(), + tgt_clk_edge->name(), + path_end->typeName(), + min_max->asString()); + if (debug->check("make_timing_model", 3)) + sta_->reportPathEnd(path_end); + Arrival data_delay = path_end->path()->arrival(sta_); + Delay clk_latency = path_end->targetClkDelay(sta_); + ArcDelay check_margin = path_end->margin(sta_); + Delay margin = min_max == MinMax::max() + ? data_delay - clk_latency + check_margin + : clk_latency - data_delay + check_margin; + float delay1 = delayAsFloat(margin, MinMax::max(), sta_); + RiseFallMinMax &margins = margins_[tgt_clk_edge]; + float max_margin; + bool max_exists; + margins.value(input_rf_, min_max, max_margin, max_exists); + // Always max margin, even for min/hold checks. + margins.setValue(input_rf_, min_max, + max_exists ? max(max_margin, delay1) : delay1); + } } // input -> register setup/hold diff --git a/search/Power.cc b/search/Power.cc index eecb4086..ea4e91ef 100644 --- a/search/Power.cc +++ b/search/Power.cc @@ -337,6 +337,8 @@ PropActivityVisitor::visit(Vertex *vertex) vertex->name(network_), activity.activity(), activity.duty()); + if (!power_->hasActivity(pin)) + input_without_activity = true; power_->setActivity(pin, activity); } else { @@ -567,12 +569,15 @@ Power::seedRegOutputActivities(const Instance *reg, LibertyPort *output, bool invert) { - PwrActivity activity = evalActivity(seq->data(), reg); - if (invert) - activity.set(activity.activity(), - 1.0 - activity.duty(), - activity.origin()); - setSeqActivity(reg, output, activity); + const Pin *out_pin = network_->findPin(reg, output); + if (!hasUserActivity(out_pin)) { + PwrActivity activity = evalActivity(seq->data(), reg); + if (invert) + activity.set(activity.activity(), + 1.0 - activity.duty(), + activity.origin()); + setSeqActivity(reg, output, activity); + } } //////////////////////////////////////////////////////////////// @@ -636,9 +641,9 @@ Power::findInputInternalPower(const Pin *pin, // Return values. PowerResult &result) { - int lib_ap_index = corner->libertyIndex(MinMax::max()); - LibertyCell *corner_cell = cell->cornerCell(lib_ap_index); - const LibertyPort *corner_port = port->cornerPort(lib_ap_index); + const MinMax *min_max = MinMax::max(); + LibertyCell *corner_cell = cell->cornerCell(corner, min_max); + const LibertyPort *corner_port = port->cornerPort(corner, min_max); if (corner_cell && corner_port) { const InternalPowerSeq &internal_pwrs = corner_cell->internalPowers(corner_port); if (!internal_pwrs.empty()) { @@ -779,9 +784,8 @@ Power::findOutputInternalPower(const Pin *to_pin, cell->name()); const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(MinMax::max()); const Pvt *pvt = dcalc_ap->operatingConditions(); - int lib_ap_index = corner->libertyIndex(MinMax::max()); - LibertyCell *corner_cell = cell->cornerCell(lib_ap_index); - const LibertyPort *to_corner_port = to_port->cornerPort(lib_ap_index); + LibertyCell *corner_cell = cell->cornerCell(dcalc_ap); + const LibertyPort *to_corner_port = to_port->cornerPort(dcalc_ap); debugPrint(debug_, "power", 2, " cap = %s", units_->capacitanceUnit()->asString(load_cap)); FuncExpr *func = to_port->function(); @@ -931,8 +935,7 @@ Power::findLeakagePower(const Instance *, // Return values. PowerResult &result) { - int lib_ap_index = corner->libertyIndex(MinMax::max()); - LibertyCell *corner_cell = cell->cornerCell(lib_ap_index); + LibertyCell *corner_cell = cell->cornerCell(corner, MinMax::max()); float cond_leakage = 0.0; bool found_cond = false; float default_leakage = 0.0; @@ -995,8 +998,7 @@ Power::findSwitchingPower(LibertyCell *cell, { MinMax *mm = MinMax::max(); const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(mm); - int lib_ap_index = corner->libertyIndex(MinMax::max()); - LibertyCell *corner_cell = cell->cornerCell(lib_ap_index); + LibertyCell *corner_cell = cell->cornerCell(dcalc_ap); float volt = portVoltage(corner_cell, to_port, dcalc_ap); float switching = .5 * load_cap * volt * volt * activity.activity(); debugPrint(debug_, "power", 2, "switching %s/%s activity = %.2e volt = %.2f %.3e", diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 66909d47..67801d74 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -2760,14 +2760,16 @@ ReportPath::drvrFanout(Vertex *drvr, VertexOutEdgeIterator iter(drvr, graph_); while (iter.hasNext()) { Edge *edge = iter.next(); - Pin *pin = edge->to(graph_)->pin(); - if (network_->isTopLevelPort(pin)) { - // Output port counts as a fanout. - Port *port = network_->port(pin); - fanout += sdc_->portExtFanout(port, min_max) + 1; + if (edge->isWire()) { + Pin *pin = edge->to(graph_)->pin(); + if (network_->isTopLevelPort(pin)) { + // Output port counts as a fanout. + Port *port = network_->port(pin); + fanout += sdc_->portExtFanout(port, min_max) + 1; + } + else + fanout++; } - else - fanout++; } return fanout; } diff --git a/search/Sta.cc b/search/Sta.cc index f5ffb127..f8ed0584 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -41,6 +41,7 @@ #include "MakeConcreteParasitics.hh" #include "Parasitics.hh" #include "parasitics/SpefReader.hh" +#include "parasitics/ReportParasiticAnnotation.hh" #include "DelayCalc.hh" #include "ArcDelayCalc.hh" #include "dcalc/GraphDelayCalc1.hh" @@ -296,13 +297,13 @@ Sta::makeComponents() makeSdcNetwork(); makeReportPath(); makePower(); - setCmdNamespace(CmdNamespace::sdc); + setCmdNamespace1(CmdNamespace::sdc); + setThreadCount1(defaultThreadCount()); updateComponentsState(); makeObservers(); // This must follow updateComponentsState. makeParasiticAnalysisPts(); - setThreadCount(defaultThreadCount()); } void @@ -321,20 +322,24 @@ Sta::defaultThreadCount() const void Sta::setThreadCount(int thread_count) +{ + setThreadCount1(thread_count); + updateComponentsState(); +} + +void +Sta::setThreadCount1(int thread_count) { thread_count_ = thread_count; if (dispatch_queue_) dispatch_queue_->setThreadCount(thread_count); else if (thread_count > 1) dispatch_queue_ = new DispatchQueue(thread_count); - updateComponentsState(); } void Sta::updateComponentsState() { - // These components do not use StaState: - // units_ network_->copyState(this); cmd_network_->copyState(this); sdc_network_->copyState(this); @@ -610,6 +615,13 @@ Sta::cmdNamespace() void Sta::setCmdNamespace(CmdNamespace namespc) +{ + setCmdNamespace1(namespc); + updateComponentsState(); +} + +void +Sta::setCmdNamespace1(CmdNamespace namespc) { cmd_namespace_ = namespc; switch (cmd_namespace_) { @@ -620,7 +632,6 @@ Sta::setCmdNamespace(CmdNamespace namespc) cmd_network_ = sdc_network_; break; } - updateComponentsState(); } Instance * @@ -3774,8 +3785,7 @@ Sta::capacitance(const LibertyPort *port, OperatingConditions *op_cond = operatingConditions(min_max); float cap = min_max->initValue(); for (const Corner *corner : makeCornerSeq(corner)) { - int lib_ap = corner->libertyIndex(min_max); - const LibertyPort *corner_port = port->cornerPort(lib_ap); + const LibertyPort *corner_port = port->cornerPort(corner, min_max); for (RiseFall *rf : RiseFall::range()) cap = min_max->minMax(cap, corner_port->capacitance(rf, min_max, op_cond, op_cond)); } @@ -3817,7 +3827,6 @@ Sta::readSpef(const char *filename, Instance *instance, const Corner *corner, const MinMaxAll *min_max, - bool increment, bool pin_cap_included, bool keep_coupling_caps, float coupling_cap_factor, @@ -3835,9 +3844,9 @@ Sta::readSpef(const char *filename, ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(cnst_min_max); const OperatingConditions *op_cond = sdc_->operatingConditions(cnst_min_max); - bool success = readSpefFile(filename, instance, ap, increment, - pin_cap_included, - keep_coupling_caps, coupling_cap_factor, + bool success = readSpefFile(filename, instance, ap, + pin_cap_included, keep_coupling_caps, + coupling_cap_factor, reduce_to, delete_after_reduce, op_cond, corner, cnst_min_max, quiet, report_, network_, parasitics_); @@ -3866,6 +3875,15 @@ Sta::makeParasiticAnalysisPts() parasitics_per_min_max_); } +void +Sta::reportParasiticAnnotation(bool report_unannotated, + const Corner *corner) +{ + ensureGraph(); + findDelays(); + sta::reportParasiticAnnotation(report_unannotated, corner, this); +} + void Sta::findPiElmore(Pin *drvr_pin, const RiseFall *rf, diff --git a/search/VisitPathEnds.cc b/search/VisitPathEnds.cc index 5735f5a5..0e487f88 100644 --- a/search/VisitPathEnds.cc +++ b/search/VisitPathEnds.cc @@ -344,6 +344,7 @@ VisitPathEnds::visitOutputDelayEnd1(OutputDelay *output_delay, // but the exception may be -to clk. ExceptionPath *exception = exceptionTo(path, pin, end_rf, tgt_clk_edge, min_max); + ClockEdge *src_clk_edge = path->clkEdge(this); if (exception && exception->isPathDelay()) { PathDelay *path_delay = dynamic_cast(exception); @@ -351,7 +352,11 @@ VisitPathEnds::visitOutputDelayEnd1(OutputDelay *output_delay, visitor->visit(&path_end); is_constrained = true; } - else if (tgt_clk_edge + else if (src_clk_edge + && (search_->checkDefaultArrivalPaths() + || src_clk_edge + != sdc_->defaultArrivalClockEdge()) + && tgt_clk_edge && sdc_->sameClockGroup(path->clock(this), tgt_clk_edge->clock()) // False paths and path delays override. && (exception == nullptr diff --git a/test/example2.ok b/test/example2.ok index d08def84..22311ab9 100644 --- a/test/example2.ok +++ b/test/example2.ok @@ -9,10 +9,10 @@ Path Type: max 0.00 0.00 clock network delay (ideal) 0.00 0.00 ^ r2/CK (DFF_X1) 0.23 0.23 v r2/Q (DFF_X1) - 0.08 0.32 v u1/Z (BUF_X1) - 0.10 0.42 v u2/ZN (AND2_X1) - 0.00 0.42 v r3/D (DFF_X1) - 0.42 data arrival time + 0.08 0.31 v u1/Z (BUF_X1) + 0.10 0.41 v u2/ZN (AND2_X1) + 0.00 0.41 v r3/D (DFF_X1) + 0.41 data arrival time 10.00 10.00 clock clk (rise edge) 0.00 10.00 clock network delay (ideal) @@ -22,7 +22,7 @@ Path Type: max 9.84 data required time --------------------------------------------------------- 9.84 data required time - -0.42 data arrival time + -0.41 data arrival time --------------------------------------------------------- 9.43 slack (MET) diff --git a/test/example3.ok b/test/example3.ok index 0d6c9c4b..532bbdba 100644 --- a/test/example3.ok +++ b/test/example3.ok @@ -36,10 +36,10 @@ Path Type: max 0.00 0.00 clock network delay (ideal) 0.00 0.00 ^ r2/CK (DFF_X1) 0.23 0.23 v r2/Q (DFF_X1) - 0.08 0.32 v u1/Z (BUF_X1) - 0.10 0.42 v u2/ZN (AND2_X1) - 0.00 0.42 v r3/D (DFF_X1) - 0.42 data arrival time + 0.08 0.31 v u1/Z (BUF_X1) + 0.10 0.41 v u2/ZN (AND2_X1) + 0.00 0.41 v r3/D (DFF_X1) + 0.41 data arrival time 10.00 10.00 clock clk (rise edge) 0.00 10.00 clock network delay (ideal) @@ -49,7 +49,7 @@ Path Type: max 9.84 data required time --------------------------------------------------------- 9.84 data required time - -0.42 data arrival time + -0.41 data arrival time --------------------------------------------------------- 9.43 slack (MET) diff --git a/test/example5.ok b/test/example5.ok index 8f0e82b9..1a68f0b9 100644 --- a/test/example5.ok +++ b/test/example5.ok @@ -39,9 +39,9 @@ Corner: ss 0.00 0.00 ^ r2/CK (DFF_X1) 0.26 0.26 v r2/Q (DFF_X1) 0.09 0.35 v u1/Z (BUF_X1) - 0.11 0.46 v u2/ZN (AND2_X1) - 0.00 0.46 v r3/D (DFF_X1) - 0.46 data arrival time + 0.11 0.45 v u2/ZN (AND2_X1) + 0.00 0.45 v r3/D (DFF_X1) + 0.45 data arrival time 10.00 10.00 clock clk (rise edge) 0.00 10.00 clock network delay (ideal) @@ -51,9 +51,9 @@ Corner: ss 9.84 data required time --------------------------------------------------------- 9.84 data required time - -0.46 data arrival time + -0.45 data arrival time --------------------------------------------------------- - 9.38 slack (MET) + 9.39 slack (MET) Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) @@ -67,7 +67,7 @@ Corner: tt 0.00 0.00 clock clk (rise edge) 0.00 0.00 clock network delay (ideal) 0.00 0.00 ^ r2/CK (DFF_X1) - 0.09 0.09 v r2/Q (DFF_X1) + 0.08 0.08 v r2/Q (DFF_X1) 0.03 0.11 v u1/Z (BUF_X1) 0.03 0.14 v u2/ZN (AND2_X1) 0.00 0.14 v r3/D (DFF_X1) diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index e69de29b..163ddc4d 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -0,0 +1,111 @@ +# OpenSTA, Static Timing Analyzer +# Copyright (c) 2022, 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 . + +# Regression variables. + +# Application program to run tests on. +set app "sta" +set sta_dir [file dirname $test_dir] +set app_path [file join $sta_dir "app" $app] +# Application options. +set app_options "-no_init -no_splash -exit" +# Log files for each test are placed in result_dir. +set result_dir [file join $test_dir "results"] +# Collective diffs. +set diff_file [file join $result_dir "diffs"] +# File containing list of failed tests. +set failure_file [file join $result_dir "failures"] +# Use the DIFF_OPTIONS envar to change the diff options +# (Solaris diff doesn't support this envar) +set diff_options "-c" +if [info exists env(DIFF_OPTIONS)] { + set diff_options $env(DIFF_OPTIONS) +} + +set valgrind_suppress [file join $test_dir valgrind.suppress] +set valgrind_options "--num-callers=20 --leak-check=full --freelist-vol=100000000 --leak-resolution=high --suppressions=$valgrind_suppress" +if { [exec "uname"] == "Darwin" } { + append valgrind_options " --dsymutil=yes" +} + +proc cleanse_logfile { test log_file } { + # Nothing to be done here. +} + +################################################################ + +# Record a test in the regression suite. +proc record_test { test cmd_dir } { + global cmd_dirs test_groups + set cmd_dirs($test) $cmd_dir + lappend test_groups(all) $test + return $test +} + +# Record a test in the $STA/examples directory. +proc record_example_tests { tests } { + global test_dir test_groups + set example_dir [file join $test_dir ".." "examples"] + foreach test $tests { + # Prune commented tests from the list. + if { [string index $test 0] != "#" } { + record_test $test $example_dir + } + } +} + +################################################################ + +proc define_test_group { name tests } { + global test_groups + set test_groups($name) $tests +} + +proc group_tests { name } { + global test_groups + return $test_groups($name) +} + +# Clear the test lists. +proc clear_tests {} { + global test_groups + unset test_groups +} + +proc list_delete { list delete } { + set result {} + foreach item $list { + if { [lsearch $delete $item] == -1 } { + lappend result $item + } + } + return $result +} + +################################################################ + +# Regression test lists. + +# Record tests in sta/examples +record_example_tests { + example1 + example2 + example3 + example4 + example5 +} + +define_test_group fast [group_tests all]