diff --git a/CMakeLists.txt b/CMakeLists.txt index 99a94864..055927fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.14) cmake_policy(SET CMP0086 NEW) endif() -project(STA VERSION 3.0.0 +project(STA VERSION 3.0.1 LANGUAGES CXX ) @@ -82,13 +82,17 @@ endif() set(STA_SOURCE app/StaMain.cc - dcalc/ArcDelayCalc.cc dcalc/ArcDcalcWaveforms.cc + dcalc/ArcDelayCalc.cc dcalc/ArnoldiDelayCalc.cc dcalc/ArnoldiReduce.cc dcalc/CcsCeffDelayCalc.cc + dcalc/Delay.cc dcalc/DelayCalc.cc dcalc/DelayCalcBase.cc + dcalc/DelayNormal.cc + dcalc/DelayScalar.cc + dcalc/DelaySkewNormal.cc dcalc/DmpCeff.cc dcalc/DmpDelayCalc.cc dcalc/FindRoot.cc @@ -99,9 +103,6 @@ set(STA_SOURCE dcalc/PrimaDelayCalc.cc dcalc/UnitDelayCalc.cc - graph/DelayFloat.cc - graph/DelayNormal1.cc - graph/DelayNormal2.cc graph/Graph.cc graph/GraphCmp.cc @@ -199,6 +200,7 @@ set(STA_SOURCE search/PathEnum.cc search/PathExpanded.cc search/PathGroup.cc + search/PocvMode.cc search/Property.cc search/ReportPath.cc search/Search.cc @@ -403,11 +405,6 @@ find_package(Eigen3 REQUIRED) include(cmake/FindCUDD.cmake) -if("${SSTA}" STREQUAL "") - set(SSTA 0) -endif() -message(STATUS "SSTA: ${SSTA}") - # configure a header file to pass some of the CMake settings configure_file(${STA_HOME}/util/StaConfig.hh.cmake ${CMAKE_CURRENT_BINARY_DIR}/include/sta/StaConfig.hh @@ -554,7 +551,7 @@ endif() # common to gcc/clang set(CXX_FLAGS -Wall -Wextra -pedantic -Wcast-qual -Wredundant-decls - -Wformat-security -Werror=misleading-indentation) + -Wformat-security -Werror=misleading-indentation -Wundef) if(ENABLE_TSAN) message(STATUS "Thread sanitizer: ${ENABLE_TSAN}") diff --git a/dcalc/ArcDcalcWaveforms.cc b/dcalc/ArcDcalcWaveforms.cc index 4c0fe95b..6c1e7560 100644 --- a/dcalc/ArcDcalcWaveforms.cc +++ b/dcalc/ArcDcalcWaveforms.cc @@ -61,7 +61,8 @@ ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg, library->supplyVoltage("VDD", vdd, vdd_exists); if (!vdd_exists) report->error(1751, "VDD not defined in library %s", library->name()); - Waveform in_waveform = driver_waveform->waveform(delayAsFloat(in_slew)); + float slew1 = delayAsFloat(in_slew, min_max, sta); + Waveform in_waveform = driver_waveform->waveform(slew1); // Delay time axis. FloatSeq time_values; for (float time : in_waveform.axis1()->values()) diff --git a/dcalc/ArcDelayCalc.cc b/dcalc/ArcDelayCalc.cc index a17ab9a9..54143b28 100644 --- a/dcalc/ArcDelayCalc.cc +++ b/dcalc/ArcDelayCalc.cc @@ -257,18 +257,18 @@ ArcDcalcResult::ArcDcalcResult(size_t load_count) : } void -ArcDcalcResult::setGateDelay(ArcDelay gate_delay) +ArcDcalcResult::setGateDelay(const ArcDelay &gate_delay) { gate_delay_ = gate_delay; } void -ArcDcalcResult::setDrvrSlew(Slew drvr_slew) +ArcDcalcResult::setDrvrSlew(const Slew &drvr_slew) { drvr_slew_ = drvr_slew; } -ArcDelay +const ArcDelay & ArcDcalcResult::wireDelay(size_t load_idx) const { return wire_delays_[load_idx]; @@ -276,7 +276,7 @@ ArcDcalcResult::wireDelay(size_t load_idx) const void ArcDcalcResult::setWireDelay(size_t load_idx, - ArcDelay wire_delay) + const ArcDelay &wire_delay) { wire_delays_[load_idx] = wire_delay; } @@ -288,7 +288,7 @@ ArcDcalcResult::setLoadCount(size_t load_count) load_slews_.resize(load_count); } -Slew +const Slew & ArcDcalcResult::loadSlew(size_t load_idx) const { return load_slews_[load_idx]; @@ -296,7 +296,7 @@ ArcDcalcResult::loadSlew(size_t load_idx) const void ArcDcalcResult::setLoadSlew(size_t load_idx, - Slew load_slew) + const Slew &load_slew) { load_slews_[load_idx] = load_slew; } diff --git a/dcalc/ArnoldiDelayCalc.cc b/dcalc/ArnoldiDelayCalc.cc index 970c91f1..2b44188e 100644 --- a/dcalc/ArnoldiDelayCalc.cc +++ b/dcalc/ArnoldiDelayCalc.cc @@ -237,7 +237,6 @@ private: ArnoldiReduce *reduce_; delay_work *delay_work_; std::vector unsaved_parasitics_; - bool pocv_enabled_; }; ArcDelayCalc * @@ -397,7 +396,6 @@ ArnoldiDelayCalc::gateDelay(const Pin *drvr_pin, ConcreteParasitic *cparasitic = reinterpret_cast(const_cast(parasitic)); rcmodel_ = dynamic_cast(cparasitic); - pocv_enabled_ = variables_->pocvEnabled(); GateTableModel *table_model = arc->gateTableModel(scene, min_max); if (table_model && rcmodel_) { const Pvt *pvt = pinPvt(drvr_pin, scene, min_max); @@ -453,8 +451,8 @@ ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell, auto load_idx_itr = load_pin_index_map.find(load_pin); if (load_idx_itr != load_pin_index_map.end()) { size_t load_idx = load_idx_itr->second; - ArcDelay wire_delay = _delayV[i] - _delayV[0]; - Slew load_slew = _slewV[i]; + double wire_delay = _delayV[i] - _delayV[0]; + double load_slew = _slewV[i]; thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew); dcalc_result.setWireDelay(load_idx, wire_delay); dcalc_result.setLoadSlew(load_idx, load_slew); @@ -1325,9 +1323,8 @@ ArnoldiDelayCalc::ra_get_r(delay_work *D, float c1; double tlohi,r; c1 = ctot; - ArcDelay d1; - Slew s1; - tab->table->gateDelay(tab->pvt, tab->in_slew, c1, pocv_enabled_, d1, s1); + float d1, s1; + tab->table->gateDelay(tab->pvt, tab->in_slew, c1, d1, s1); tlohi = slew_derate*delayAsFloat(s1); r = tlohi/(c_log*c1); if (rdelay>0.0 && r > rdelay) @@ -1346,9 +1343,8 @@ ArnoldiDelayCalc::ra_get_s(delay_work *D, double c_log = con->vlg; double c_smin = con->smin; double tlohi,smin,s; - ArcDelay d1; - Slew s1; - tab->table->gateDelay(tab->pvt, tab->in_slew, c, pocv_enabled_, d1, s1); + float d1, s1; + tab->table->gateDelay(tab->pvt, tab->in_slew, c, d1, s1); tlohi = slew_derate*delayAsFloat(s1); smin = r*c*c_smin; // c_smin = ra_hinv((1-vhi)/vhi-log(vhi)) + log(vhi); if (c_log*r*c >= tlohi) { @@ -1378,10 +1374,9 @@ ArnoldiDelayCalc::ra_rdelay_1(timing_table *tab, float c2 = 0.5*c1; if (c1==c2) return 0.0; - ArcDelay d1, d2; - Slew s1, s2; - tab->table->gateDelay(tab->pvt, tab->in_slew, c1, pocv_enabled_, d1, s1); - tab->table->gateDelay(tab->pvt, tab->in_slew, c2, pocv_enabled_, d2, s2); + float d1, d2, s1, s2; + tab->table->gateDelay(tab->pvt, tab->in_slew, c1, d1, s1); + tab->table->gateDelay(tab->pvt, tab->in_slew, c2, d2, s2); double dt50 = delayAsFloat(d1)-delayAsFloat(d2); if (dt50 <= 0.0) return 0.0; @@ -1402,8 +1397,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D, double vlo = con->vlo; double ctot = mod->ctot; double ceff,tlohi,t50_sy,r,s,t50_sr,rdelay; - ArcDelay df; - Slew sf; + float df, sf; debugPrint(debug_, "arnoldi", 1, "ctot=%s", units_->capacitanceUnit()->asString(ctot)); @@ -1432,7 +1426,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D, units_->timeUnit()->asString(s)); thix = ra_solve_for_t(p,s,vhi); tlox = ra_solve_for_t(p,s,vlo); - tab->table->gateDelay(tab->pvt,tab->in_slew, ctot, pocv_enabled_, df, sf); + tab->table->gateDelay(tab->pvt,tab->in_slew, ctot, df, sf); debugPrint(debug_, "arnoldi", 1, "table slew (in_slew %s ctot %s) = %s", units_->timeUnit()->asString(tab->in_slew), units_->capacitanceUnit()->asString(ctot), @@ -1443,8 +1437,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D, units_->timeUnit()->asString(tlox-thix)); } ceff = ctot; - tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, pocv_enabled_, - df, sf); + tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, df, sf); t50_sy = delayAsFloat(df); t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5); @@ -1485,7 +1478,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D, units_->timeUnit()->asString(ceff_time), units_->capacitanceUnit()->asString(ceff)); - tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, pocv_enabled_, df, sf); + tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, df, sf); t50_sy = delayAsFloat(df); t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5); for (j=0;jn;j++) { diff --git a/dcalc/CcsCeffDelayCalc.cc b/dcalc/CcsCeffDelayCalc.cc index 95156145..31762fd0 100644 --- a/dcalc/CcsCeffDelayCalc.cc +++ b/dcalc/CcsCeffDelayCalc.cc @@ -113,14 +113,12 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin, vh_ = drvr_library->slewUpperThreshold(drvr_rf_) * vdd_; drvr_cell->ensureVoltageWaveforms(scenes_); - in_slew_ = delayAsFloat(in_slew); output_waveforms_ = output_waveforms; ref_time_ = output_waveforms_->referenceTime(in_slew_); debugPrint(debug_, "ccs_dcalc", 1, "%s %s", drvr_cell->name(), drvr_rf_->shortName()); - ArcDelay gate_delay; - Slew drvr_slew; + double gate_delay, drvr_slew; gateDelaySlew(drvr_library, drvr_rf_, gate_delay, drvr_slew); return makeResult(drvr_library,drvr_rf_,gate_delay,drvr_slew,load_pin_index_map); } @@ -133,8 +131,8 @@ void CcsCeffDelayCalc::gateDelaySlew(const LibertyLibrary *drvr_library, const RiseFall *rf, // Return values. - ArcDelay &gate_delay, - Slew &drvr_slew) + double &gate_delay, + double &drvr_slew) { initRegions(drvr_library, rf); findCsmWaveform(); @@ -145,7 +143,7 @@ CcsCeffDelayCalc::gateDelaySlew(const LibertyLibrary *drvr_library, "gate_delay %s drvr_slew %s (initial)", delayAsString(gate_delay, this), delayAsString(drvr_slew, this)); - float prev_drvr_slew = delayAsFloat(drvr_slew); + float prev_drvr_slew = drvr_slew; constexpr int max_iterations = 5; for (int iter = 0; iter < max_iterations; iter++) { debugPrint(debug_, "ccs_dcalc", 2, "iteration %d", iter); @@ -185,9 +183,9 @@ CcsCeffDelayCalc::gateDelaySlew(const LibertyLibrary *drvr_library, "gate_delay %s drvr_slew %s", delayAsString(gate_delay, this), delayAsString(drvr_slew, this)); - if (std::abs(delayAsFloat(drvr_slew) - prev_drvr_slew) < .01 * prev_drvr_slew) + if (std::abs(drvr_slew - prev_drvr_slew) < .01 * prev_drvr_slew) break; - prev_drvr_slew = delayAsFloat(drvr_slew); + prev_drvr_slew = drvr_slew; } } @@ -309,8 +307,8 @@ CcsCeffDelayCalc::findCsmWaveform() ArcDcalcResult CcsCeffDelayCalc::makeResult(const LibertyLibrary *drvr_library, const RiseFall *rf, - ArcDelay &gate_delay, - Slew &drvr_slew, + double &gate_delay, + double &drvr_slew, const LoadPinIndexMap &load_pin_index_map) { ArcDcalcResult dcalc_result(load_pin_index_map.size()); @@ -322,8 +320,7 @@ CcsCeffDelayCalc::makeResult(const LibertyLibrary *drvr_library, dcalc_result.setDrvrSlew(drvr_slew); for (const auto &[load_pin, load_idx] : load_pin_index_map) { - ArcDelay wire_delay; - Slew load_slew; + double wire_delay, load_slew; loadDelaySlew(load_pin, drvr_library, rf, drvr_slew, wire_delay, load_slew); dcalc_result.setWireDelay(load_idx, wire_delay); dcalc_result.setLoadSlew(load_idx, load_slew); @@ -335,13 +332,14 @@ void CcsCeffDelayCalc::loadDelaySlew(const Pin *load_pin, const LibertyLibrary *drvr_library, const RiseFall *rf, - Slew &drvr_slew, + double &drvr_slew, // Return values. - ArcDelay &wire_delay, - Slew &load_slew) + double &wire_delay, + double &load_slew) { wire_delay = 0.0; load_slew = drvr_slew; + bool elmore_exists = false; float elmore = 0.0; if (parasitic_ @@ -351,7 +349,7 @@ CcsCeffDelayCalc::loadDelaySlew(const Pin *load_pin, if (elmore_exists && (elmore == 0.0 // Elmore delay is small compared to driver slew. - || elmore < delayAsFloat(drvr_slew) * 1e-3)) { + || elmore < drvr_slew * 1e-3)) { wire_delay = elmore; load_slew = drvr_slew; } @@ -363,11 +361,11 @@ CcsCeffDelayCalc::loadDelaySlew(const Pin *load_pin, void CcsCeffDelayCalc::loadDelaySlew(const Pin *load_pin, - Slew &drvr_slew, + double &drvr_slew, float elmore, // Return values. - ArcDelay &delay, - Slew &slew) + double &delay, + double &slew) { for (size_t i = 0; i <= region_count_; i++) { region_ramp_times_[i] = region_times_[i]; diff --git a/dcalc/CcsCeffDelayCalc.hh b/dcalc/CcsCeffDelayCalc.hh index 83a72911..53a103bb 100644 --- a/dcalc/CcsCeffDelayCalc.hh +++ b/dcalc/CcsCeffDelayCalc.hh @@ -73,29 +73,29 @@ protected: void gateDelaySlew(const LibertyLibrary *drvr_library, const RiseFall *rf, // Return values. - ArcDelay &gate_delay, - Slew &drvr_slew); + double &gate_delay, + double &drvr_slew); void initRegions(const LibertyLibrary *drvr_library, const RiseFall *rf); void findCsmWaveform(); ArcDcalcResult makeResult(const LibertyLibrary *drvr_library, const RiseFall *rf, - ArcDelay &gate_delay, - Slew &drvr_slew, + double &gate_delay, + double &drvr_slew, const LoadPinIndexMap &load_pin_index_map); void loadDelaySlew(const Pin *load_pin, const LibertyLibrary *drvr_library, const RiseFall *rf, - Slew &drvr_slew, + double &drvr_slew, // Return values. - ArcDelay &wire_delay, - Slew &load_slew); + double &wire_delay, + double &load_slew); void loadDelaySlew(const Pin *load_pin, - Slew &drvr_slew, + double &drvr_slew, float elmore, // Return values. - ArcDelay &delay, - Slew &slew); + double &delay, + double &slew); double findVlTime(double v, double elmore); bool makeWaveformPreamble(const Pin *in_pin, diff --git a/dcalc/Delay.cc b/dcalc/Delay.cc new file mode 100644 index 00000000..7154e3d8 --- /dev/null +++ b/dcalc/Delay.cc @@ -0,0 +1,515 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#include "Delay.hh" + +#include + +#include "StaConfig.hh" +#include "Fuzzy.hh" +#include "Units.hh" +#include "StaState.hh" +#include "Variables.hh" + +namespace sta { + +static Delay delay_init_values[MinMax::index_count]; + +void +initDelayConstants() +{ + delay_init_values[MinMax::minIndex()] = MinMax::min()->initValue(); + delay_init_values[MinMax::maxIndex()] = MinMax::max()->initValue(); +} + +Delay::Delay() : + values_{0.0, 0.0, 0.0, 0.0} +{ +} + +Delay::Delay(float mean) : + values_{mean, 0.0, 0.0, 0.0} +{ +} + +Delay::Delay(float mean, + float std_dev2) : + values_{mean, 0.0, std_dev2, 0.0} +{ +} + +Delay::Delay(float mean, + float mean_shift, + float std_dev2, + float skewness) : + values_{mean, mean_shift, std_dev2, skewness} +{ +} + +void +Delay::operator=(float delay) +{ + values_[0] = delay; + values_[1] = 0.0; + values_[2] = 0.0; + values_[3] = 0.0; +} + +void +Delay::setValues(float mean, + float mean_shift, + float std_dev2, + float skewnes) +{ + values_[0] = mean; + values_[1] = mean_shift; + values_[2] = std_dev2; + values_[3] = skewnes; +} + +void +Delay::setMean(float mean) +{ + values_[0] = mean; +} + +void +Delay::setMeanShift(float mean_shift) +{ + values_[1] = mean_shift; +} + +float +Delay::stdDev() const +{ + float std_dev2 = values_[2]; + if (std_dev2 < 0.0) + // std_dev is negative for crpr to offset std_dev in the common + // clock path. + return -std::sqrt(-std_dev2); + else + return std::sqrt(std_dev2); +} + +void +Delay::setStdDev(float std_dev) +{ + values_[2] = square(std_dev); +} + +void +Delay::setSkewness(float skewness) +{ + values_[3] = skewness; +} + +//////////////////////////////////////////////////////////////// + +DelayDbl::DelayDbl() : + values_{0.0, 0.0, 0.0, 0.0} +{ +} + +DelayDbl::DelayDbl(double mean) : + values_{mean, 0.0, 0.0, 0.0} +{ +} + +void +DelayDbl::setMean(double mean) +{ + values_[0] = mean; +} + +double +DelayDbl::stdDev() const +{ + float std_dev2 = values_[2]; + if (std_dev2 < 0.0) + // std_dev is negative for crpr to offset std_dev in the common + // clock path. + return -std::sqrt(-std_dev2); + else + return std::sqrt(std_dev2); +} + +void +DelayDbl::setValues(double mean, + double mean_shift, + double std_dev2, + double skewnes) +{ + values_[0] = mean; + values_[1] = mean_shift; + values_[2] = std_dev2; + values_[3] = skewnes; +} + +void +DelayDbl::operator=(double delay) +{ + values_[0] = delay; + values_[1] = 0.0; + values_[2] = 0.0; + values_[3] = 0.0; +} + +//////////////////////////////////////////////////////////////// + +Delay +makeDelay(float mean, + float mean_shift, + float std_dev, + float skewness) +{ + return Delay(mean, mean_shift, square(std_dev), skewness); +} + +Delay +makeDelay(float mean, + float std_dev) +{ + return Delay(mean, 0.0, square(std_dev), 0.0); +} + +Delay +makeDelay2(float mean, + float std_dev) +{ + return Delay(mean, 0.0, std_dev, 0.0); +} + +void +delaySetMean(Delay &delay, + float mean) +{ + delay.setMean(mean); +} + +//////////////////////////////////////////////////////////////// + +Delay +delayDblAsDelay(DelayDbl &delay) +{ + return Delay(delay.mean(), delay.meanShift(), delay.stdDev2(), delay.skewness()); +} + +const char * +delayAsString(const Delay &delay, + const StaState *sta) +{ + return delayAsString(delay, EarlyLate::late(), + sta->units()->timeUnit()->digits(), sta); +} + +const char * +delayAsString(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) +{ + return delayAsString(delay, early_late, sta->units()->timeUnit()->digits(), sta); +} + +const char * +delayAsString(const Delay &delay, + const EarlyLate *early_late, + int digits, + const StaState *sta) +{ + const Unit *unit = sta->units()->timeUnit(); + float mean_std_dev = delayAsFloat(delay, early_late, sta); + return unit->asString(mean_std_dev, digits); +} + +const char * +delayAsString(const Delay &delay, + const EarlyLate *early_late, + bool report_variance, + int digits, + const StaState *sta) +{ + if (report_variance) + return sta->delayOps()->asStringVariance(delay, digits, sta); + else + return delayAsString(delay, early_late, digits, sta); +} + +float +delayAsFloat(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) +{ + return sta->delayOps()->asFloat(delay, early_late, sta); +} + +float +delayAsFloat(const DelayDbl &delay, + const EarlyLate *early_late, + const StaState *sta) +{ + return sta->delayOps()->asFloat(delay, early_late, sta); +} + +float +delayAsFloat(const Delay &delay) +{ + return delay.mean(); +} + +const Delay & +delayInitValue(const MinMax *min_max) +{ + return delay_init_values[min_max->index()]; +} + +bool +delayIsInitValue(const Delay &delay, + const MinMax *min_max) +{ + return fuzzyEqual(delay.mean(), min_max->initValue()); +} + +bool +delayZero(const Delay &delay, + const StaState *sta) +{ + return sta->delayOps()->isZero(delay); +} + +bool +delayInf(const Delay &delay, + const StaState *sta) +{ + return sta->delayOps()->isInf(delay); +} + +bool +delayEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->equal(delay1, delay2, sta); +} + +bool +delayLess(const Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->less(delay1, delay2, sta); +} + +bool +delayLess(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *sta) +{ + return sta->delayOps()->less(delay1, delay2, sta); +} + +bool +delayLess(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max, + const StaState *sta) +{ + if (min_max == MinMax::max()) + return sta->delayOps()->less(delay1, delay2, sta); + else + return sta->delayOps()->greater(delay1, delay2, sta); +} + +bool +delayLessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->lessEqual(delay1, delay2, sta); +} + +bool +delayLessEqual(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max, + const StaState *sta) +{ + if (min_max == MinMax::max()) + return sta->delayOps()->lessEqual(delay1, delay2, sta); + else + return sta->delayOps()->greaterEqual(delay1, delay2, sta); +} + +bool +delayGreater(const Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->greater(delay1, delay2, sta); +} + +bool +delayGreater(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max, + const StaState *sta) +{ + if (min_max == MinMax::max()) + return sta->delayOps()->greater(delay1, delay2, sta); + else + return sta->delayOps()->less(delay1, delay2, sta); +} + +bool +delayGreaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->greaterEqual(delay1, delay2, sta); +} + +bool +delayGreaterEqual(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max, + const StaState *sta) +{ + if (min_max == MinMax::max()) + return sta->delayOps()->greaterEqual(delay1, delay2, sta); + else + return sta->delayOps()->lessEqual(delay1, delay2, sta); +} + +Delay +delayRemove(const Delay &delay1, + const Delay &delay2) +{ + return makeDelay2(delay1.mean() - delay2.mean(), + delay1.stdDev2() - delay2.stdDev2()); +} + +Delay +delaySum(const Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->sum(delay1, delay2); +} + +Delay +delaySum(const Delay &delay1, + float delay2, + const StaState *sta) +{ + return sta->delayOps()->sum(delay1, delay2); +} + +Delay +delayDiff(const Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->diff(delay1, delay2); +} + +Delay +delayDiff(const Delay &delay1, + float delay2, + const StaState *sta) +{ + return sta->delayOps()->diff(delay1, delay2); +} + +Delay +delayDiff(float delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->diff(delay1, delay2); +} + +void +delayIncr(Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + sta->delayOps()->incr(delay1, delay2); +} + +void +delayIncr(DelayDbl &delay1, + const Delay &delay2, + const StaState *sta) +{ + sta->delayOps()->incr(delay1, delay2); +} + +void +delayIncr(Delay &delay1, + float delay2, + const StaState *sta) +{ + sta->delayOps()->incr(delay1, delay2); +} + +void +delayDecr(Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + sta->delayOps()->decr(delay1, delay2); +} + +void +delayDecr(DelayDbl &delay1, + const Delay &delay2, + const StaState *sta) +{ + sta->delayOps()->decr(delay1, delay2); +} + +Delay +delayProduct(const Delay &delay1, + float delay2, + const StaState *sta) +{ + return sta->delayOps()->product(delay1, delay2); +} + +Delay +delayDiv(float delay1, + const Delay &delay2, + const StaState *sta) +{ + return sta->delayOps()->div(delay1, delay2); +} + +float +delayStdDev2(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) +{ + return sta->delayOps()->stdDev2(delay, early_late); +} + +} // namespace diff --git a/dcalc/DelayCalc.tcl b/dcalc/DelayCalc.tcl index 967039aa..7d15b5a9 100644 --- a/dcalc/DelayCalc.tcl +++ b/dcalc/DelayCalc.tcl @@ -135,8 +135,6 @@ proc set_delay_calculator { alg } { } } -define_cmd_args "set_pocv_sigma_factor" { factor } - ################################################################ define_cmd_args "set_assigned_delay" \ @@ -382,22 +380,31 @@ proc set_assigned_transition { args } { ################################################################ -define_cmd_args "report_slews" {[-scenes scenes] pin} +define_cmd_args "report_slews" {[-scenes scenes] [-digits digits]\ + [-report_variance] pin} proc report_slews { args } { global sta_report_default_digits - parse_key_args "report_slews" args keys {-corner -scenes} flags {} + parse_key_args "report_slews" args keys {-corner -scenes -digits} \ + flags {-report_variance} check_argc_eq1 "report_slews" $args set scenes [parse_scenes_or_all keys] set pin [get_port_pin_error "pin" [lindex $args 0]] - set digits $sta_report_default_digits + if [info exists keys(-digits)] { + set digits $keys(-digits) + check_positive_integer "-digits" $digits + } else { + set digits $sta_report_default_digits + } + set report_variance [info exists flags(-report_variance)] + foreach vertex [$pin vertices] { - set rise_min [format_time [$vertex slew_scenes rise $scenes min] $digits] - set rise_max [format_time [$vertex slew_scenes rise $scenes max] $digits] - set fall_min [format_time [$vertex slew_scenes fall $scenes min] $digits] - set fall_max [format_time [$vertex slew_scenes fall $scenes max] $digits] + set rise_min [$vertex slew_scenes_string rise $scenes min $report_variance $digits] + set rise_max [$vertex slew_scenes_string rise $scenes max $report_variance $digits] + set fall_min [$vertex slew_scenes_string fall $scenes min $report_variance $digits] + set fall_max [$vertex slew_scenes_string fall $scenes max $report_variance $digits] report_line "[vertex_path_name $vertex] [rise_short_name] $rise_min:$rise_max [fall_short_name] $fall_min:$fall_max" } } diff --git a/dcalc/DelayCalcBase.cc b/dcalc/DelayCalcBase.cc index bc5b77e0..25429d68 100644 --- a/dcalc/DelayCalcBase.cc +++ b/dcalc/DelayCalcBase.cc @@ -81,10 +81,10 @@ DelayCalcBase::finishDrvrPin() void DelayCalcBase::dspfWireDelaySlew(const Pin *load_pin, const RiseFall *rf, - Slew drvr_slew, + double drvr_slew, float elmore, - ArcDelay &wire_delay, - Slew &load_slew) + double &wire_delay, + double &load_slew) { LibertyLibrary *load_library = thresholdLibrary(load_pin); @@ -107,8 +107,8 @@ void DelayCalcBase::thresholdAdjust(const Pin *load_pin, const LibertyLibrary *drvr_library, const RiseFall *rf, - ArcDelay &load_delay, - Slew &load_slew) + double &wire_delay, + double &load_slew) { LibertyLibrary *load_library = thresholdLibrary(load_pin); if (load_library @@ -118,11 +118,11 @@ DelayCalcBase::thresholdAdjust(const Pin *load_pin, float load_vth = load_library->inputThreshold(rf); float drvr_slew_delta = drvr_library->slewUpperThreshold(rf) - drvr_library->slewLowerThreshold(rf); - float load_delay_delta = + float wire_delay_delta = delayAsFloat(load_slew) * ((load_vth - drvr_vth) / drvr_slew_delta); - load_delay += (rf == RiseFall::rise()) - ? load_delay_delta - : -load_delay_delta; + wire_delay += (rf == RiseFall::rise()) + ? wire_delay_delta + : -wire_delay_delta; float load_slew_delta = load_library->slewUpperThreshold(rf) - load_library->slewLowerThreshold(rf); float drvr_slew_derate = drvr_library->slewDerateFromLibrary(); @@ -162,9 +162,8 @@ DelayCalcBase::checkDelay(const Pin *check_pin, float from_slew1 = delayAsFloat(from_slew); float to_slew1 = delayAsFloat(to_slew); return model->checkDelay(pinPvt(check_pin, scene, min_max), - from_slew1, to_slew1, - related_out_cap, - variables_->pocvEnabled()); + from_slew1, to_slew1, related_out_cap, + min_max, variables_->pocvMode()); } else return delay_zero; @@ -187,8 +186,8 @@ DelayCalcBase::reportCheckDelay(const Pin *check_pin, float to_slew1 = delayAsFloat(to_slew); return model->reportCheckDelay(pinPvt(check_pin, scene, min_max), from_slew1, from_slew_annotation, - to_slew1, related_out_cap, false, - digits); + to_slew1, related_out_cap, min_max, + PocvMode::scalar, digits); } return ""; } diff --git a/dcalc/DelayCalcBase.hh b/dcalc/DelayCalcBase.hh index 6d641c7e..faaa4358 100644 --- a/dcalc/DelayCalcBase.hh +++ b/dcalc/DelayCalcBase.hh @@ -72,16 +72,16 @@ protected: void thresholdAdjust(const Pin *load_pin, const LibertyLibrary *drvr_library, const RiseFall *rf, - ArcDelay &load_delay, - Slew &load_slew); + double &load_delay, + double &load_slew); // Helper function for input ports driving dspf parasitic. void dspfWireDelaySlew(const Pin *load_pin, const RiseFall *rf, - Slew drvr_slew, + double drvr_slew, float elmore, // Return values. - ArcDelay &wire_delay, - Slew &load_slew); + double &wire_delay, + double &load_slew); const Pvt *pinPvt(const Pin *pin, const Scene *scene, const MinMax *min_max); diff --git a/dcalc/DelayNormal.cc b/dcalc/DelayNormal.cc new file mode 100644 index 00000000..31f03a52 --- /dev/null +++ b/dcalc/DelayNormal.cc @@ -0,0 +1,231 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#include "DelayNormal.hh" + +#include // sqrt + +#include "Error.hh" +#include "Fuzzy.hh" +#include "Units.hh" +#include "StaState.hh" +#include "Variables.hh" + +namespace sta { + +float +DelayOpsNormal::stdDev2(const Delay &delay, + const EarlyLate *) const +{ + return delay.stdDev2(); +} + +float +DelayOpsNormal::asFloat(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) const +{ + float quantile = sta->variables()->pocvQuantile(); + if (early_late == EarlyLate::early()) + return delay.mean() - delay.stdDev() * quantile; + else // (early_late == EarlyLate::late()) + return delay.mean() + delay.stdDev() * quantile; +} + +double +DelayOpsNormal::asFloat(const DelayDbl &delay, + const EarlyLate *early_late, + const StaState *sta) const +{ + double quantile = sta->variables()->pocvQuantile(); + if (early_late == EarlyLate::early()) + return delay.mean() - delay.stdDev() * quantile; + else // (early_late == EarlyLate::late()) + return delay.mean() + delay.stdDev() * quantile; +} + +bool +DelayOpsNormal::isZero(const Delay &delay) const +{ + return fuzzyZero(delay.mean()) + && fuzzyZero(delay.stdDev2()); +} + +bool +DelayOpsNormal::isInf(const Delay &delay) const +{ + return fuzzyInf(delay.mean()); +} + +bool +DelayOpsNormal::equal(const Delay &delay1, + const Delay &delay2, + const StaState *) const +{ + return fuzzyEqual(delay1.mean(), delay2.mean()) + && fuzzyEqual(delay1.stdDev2(), delay2.stdDev2()); +} + +bool +DelayOpsNormal::less(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const +{ + return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta), + delayAsFloat(delay2, EarlyLate::early(), sta)); +} + +bool +DelayOpsNormal::less(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *sta) const +{ + return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta), + delayAsFloat(delay2, EarlyLate::early(), sta)); +} + +bool +DelayOpsNormal::lessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const +{ + return fuzzyLessEqual(delayAsFloat(delay1, EarlyLate::early(), sta), + delayAsFloat(delay2, EarlyLate::early(), sta)); +} + +bool +DelayOpsNormal::greater(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const +{ + return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta), + delayAsFloat(delay2, EarlyLate::late(), sta)); +} + +bool +DelayOpsNormal::greaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const +{ + return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), + delayAsFloat(delay2, EarlyLate::late(), sta)); +} + +Delay +DelayOpsNormal::sum(const Delay &delay1, + const Delay &delay2) const +{ + return Delay(delay1.mean() + delay2.mean(), + delay1.stdDev2() + delay2.stdDev2()); +} + +Delay +DelayOpsNormal::sum(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() + delay2, + delay1.stdDev2()); +} + +Delay +DelayOpsNormal::diff(const Delay &delay1, + const Delay &delay2) const +{ + return Delay(delay1.mean() - delay2.mean(), + delay1.stdDev2() + delay2.stdDev2()); +} + +Delay +DelayOpsNormal::diff(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() - delay2, + delay1.stdDev2()); +} + +Delay +DelayOpsNormal::diff(float delay1, + const Delay &delay2) const +{ + return Delay(delay1 - delay2.mean(), + delay2.stdDev2()); +} + +void +DelayOpsNormal::incr(Delay &delay1, + const Delay &delay2) const +{ + delay1.setValues(delay1.mean() + delay2.mean(), 0.0, + delay1.stdDev2() + delay2.stdDev2(), 0.0); +} + +void +DelayOpsNormal::incr(DelayDbl &delay1, + const Delay &delay2) const +{ + delay1.setValues(delay1.mean() + delay2.mean(), 0.0, + delay1.stdDev2() + delay2.stdDev2(), 0.0); +} + +void +DelayOpsNormal::decr(Delay &delay1, + const Delay &delay2) const +{ + delay1.setMean(delay1.mean() - delay2.mean()); +} + +void +DelayOpsNormal::decr(DelayDbl &delay1, + const Delay &delay2) const +{ + delay1.setMean(delay1.mean() - delay2.mean()); +} + +Delay +DelayOpsNormal::product(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() * delay2, + delay1.stdDev2() * square(delay2)); +} + +Delay +DelayOpsNormal::div(float delay1, + const Delay &delay2) const +{ + return Delay(delay1 / delay2.mean()); +} + +const char * +DelayOpsNormal::asStringVariance(const Delay &delay, + int digits, + const StaState *sta) const +{ + const Unit *unit = sta->units()->timeUnit(); + return stringPrintTmp("%s[%s]", + unit->asString(delay.mean(), digits), + unit->asString(delay.stdDev(), digits)); +} + +} // namespace diff --git a/dcalc/DelayScalar.cc b/dcalc/DelayScalar.cc new file mode 100644 index 00000000..69346355 --- /dev/null +++ b/dcalc/DelayScalar.cc @@ -0,0 +1,206 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +// Delay as floats, non-SSTA. + +#include "DelayScalar.hh" + +#include "Fuzzy.hh" +#include "Units.hh" +#include "StaState.hh" + +namespace sta { + +float +DelayOpsScalar::stdDev2(const Delay &, + const EarlyLate *) const +{ + return 0.0; +} + +float +DelayOpsScalar::asFloat(const Delay &delay, + const EarlyLate *, + const StaState *) const +{ + return delay.mean(); +} + +double +DelayOpsScalar::asFloat(const DelayDbl &delay, + const EarlyLate *, + const StaState *) const +{ + return delay.mean(); +} + +bool +DelayOpsScalar::isZero(const Delay &delay) const +{ + return fuzzyZero(delay.mean()); +} + +bool +DelayOpsScalar::isInf(const Delay &delay) const +{ + return fuzzyInf(delay.mean()); +} + +bool +DelayOpsScalar::equal(const Delay &delay1, + const Delay &delay2, + const StaState *) const +{ + return fuzzyEqual(delay1.mean(), delay2.mean()); +} + +bool +DelayOpsScalar::less(const Delay &delay1, + const Delay &delay2, + const StaState *) const +{ + return fuzzyLess(delay1.mean(), delay2.mean()); +} + +bool +DelayOpsScalar::less(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *) const +{ + return fuzzyLess(delay1.mean(), delay2.mean()); +} + +bool +DelayOpsScalar::lessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *) const +{ + return fuzzyLessEqual(delay1.mean(), delay2.mean()); +} + +bool +DelayOpsScalar::greater(const Delay &delay1, + const Delay &delay2, + const StaState *) const +{ + return fuzzyGreater(delay1.mean(), delay2.mean()); +} + +bool +DelayOpsScalar::greaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *) const +{ + return fuzzyGreaterEqual(delay1.mean(), delay2.mean()); +} + +Delay +DelayOpsScalar::sum(const Delay &delay1, + const Delay &delay2) const +{ + return Delay(delay1.mean() + delay2.mean()); +} + +Delay +DelayOpsScalar::sum(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() + delay2); +} + +Delay +DelayOpsScalar::diff(const Delay &delay1, + const Delay &delay2) const +{ + return Delay(delay1.mean() - delay2.mean()); +} + +Delay +DelayOpsScalar::diff(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() - delay2); +} + +Delay +DelayOpsScalar::diff(float delay1, + const Delay &delay2) const +{ + return Delay(delay1 - delay2.mean()); +} + + +void +DelayOpsScalar::incr(Delay &delay1, + const Delay &delay2) const +{ + delay1.setMean(delay1.mean() + delay2.mean()); +} + +void +DelayOpsScalar::incr(DelayDbl &delay1, + const Delay &delay2) const +{ + delay1.setMean(delay1.mean() + delay2.mean()); +} + +void +DelayOpsScalar::decr(Delay &delay1, + const Delay &delay2) const +{ + delay1.setMean(delay1.mean() - delay2.mean()); +} + +void +DelayOpsScalar::decr(DelayDbl &delay1, + const Delay &delay2) const +{ + delay1.setMean(delay1.mean() - delay2.mean()); +} + +Delay +DelayOpsScalar::product(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() * delay2); +} + +Delay +DelayOpsScalar::div(float delay1, + const Delay &delay2) const +{ + return Delay(delay1 / delay2.mean()); +} + +const char * +DelayOpsScalar::asStringVariance(const Delay &delay, + int digits, + const StaState *sta) const +{ + const Unit *unit = sta->units()->timeUnit(); + return unit->asString(delay.mean(), digits); +} + +} // namespace + diff --git a/dcalc/DelaySkewNormal.cc b/dcalc/DelaySkewNormal.cc new file mode 100644 index 00000000..82bdfbe4 --- /dev/null +++ b/dcalc/DelaySkewNormal.cc @@ -0,0 +1,292 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#include "DelaySkewNormal.hh" + +#include // sqrt + +#include "Error.hh" +#include "Fuzzy.hh" +#include "Units.hh" +#include "StaState.hh" +#include "Variables.hh" + +namespace sta { + +float +DelayOpsSkewNormal::stdDev2(const Delay &delay, + const EarlyLate *) const +{ + return delay.stdDev2(); +} + +float +DelayOpsSkewNormal::asFloat(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) const +{ + // LVF: mean + mean_shift + sigma * sigma_factor with skewness consideration. + float quantile = sta->variables()->pocvQuantile(); + if (early_late == EarlyLate::early()) + return delay.mean() + delay.meanShift() + - delay.stdDev() * (quantile + delay.skewness() * (square(quantile)-1.0) / 6.0); + else // (early_late == EarlyLate::late()) + return delay.mean() + delay.meanShift() + + delay.stdDev() * (quantile + delay.skewness() * (square(quantile)-1.0) / 6.0); +} + +double +DelayOpsSkewNormal::asFloat(const DelayDbl &delay, + const EarlyLate *early_late, + const StaState *sta) const +{ + // LVF: mean + mean_shift + sigma * sigma_factor with skewness consideration. + double quantile = sta->variables()->pocvQuantile(); + if (early_late == EarlyLate::early()) + return delay.mean() + delay.meanShift() + - delay.stdDev() * (quantile + delay.skewness() * (square(quantile)-1.0) / 6.0); + else // (early_late == EarlyLate::late()) + return delay.mean() + delay.meanShift() + + delay.stdDev() * (quantile + delay.skewness() * (square(quantile)-1.0) / 6.0); +} + +bool +DelayOpsSkewNormal::isZero(const Delay &delay) const +{ + return fuzzyZero(delay.mean()) + && fuzzyZero(delay.meanShift()) + && fuzzyZero(delay.stdDev2()) + && fuzzyZero(delay.skewness()); +} + +bool +DelayOpsSkewNormal::isInf(const Delay &delay) const +{ + return fuzzyInf(delay.mean()); +} + +bool +DelayOpsSkewNormal::equal(const Delay &delay1, + const Delay &delay2, + const StaState *) const +{ + return fuzzyEqual(delay1.mean(), delay2.mean()) + && fuzzyEqual(delay1.meanShift(), delay2.meanShift()) + && fuzzyEqual(delay1.stdDev2(), delay2.stdDev2()) + && fuzzyEqual(delay1.skewness(), delay2.skewness()); +} + +bool +DelayOpsSkewNormal::less(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const +{ + return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta), + delayAsFloat(delay2, EarlyLate::early(), sta)); +} + +bool +DelayOpsSkewNormal::less(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *sta) const +{ + return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta), + delayAsFloat(delay2, EarlyLate::early(), sta)); +} + +bool +DelayOpsSkewNormal::lessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const +{ + return fuzzyLessEqual(delayAsFloat(delay1, EarlyLate::early(), sta), + delayAsFloat(delay2, EarlyLate::early(), sta)); +} + +bool +DelayOpsSkewNormal::greater(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const +{ + return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta), + delayAsFloat(delay2, EarlyLate::late(), sta)); +} + +bool +DelayOpsSkewNormal::greaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const +{ + return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), + delayAsFloat(delay2, EarlyLate::late(), sta)); +} + +Delay +DelayOpsSkewNormal::sum(const Delay &delay1, + const Delay &delay2) const +{ + return Delay(delay1.mean() + delay2.mean(), + delay1.meanShift() + delay2.meanShift(), + delay1.stdDev2() + delay2.stdDev2(), + skewnessSum(delay1, delay2)); +} + +float +DelayOpsSkewNormal::skewnessSum(const Delay &delay1, + const Delay &delay2) const +{ + return skewnessSum(delay1.stdDev(), delay1.skewness(), + delay2.stdDev(), delay2.skewness()); +} + +// Helper function to compute combined skewness from std dev and skewness values. +double +DelayOpsSkewNormal::skewnessSum(double std_dev1, + double skewness1, + double std_dev2, + double skewness2) const +{ + double std_dev_sum = square(std_dev1) + square(std_dev2); + if (std_dev_sum == 0.0) + return 0.0; + else { + // Un-normalize the skews so they are third moments so they can be added. + double skew = (skewness1 * cube(std_dev1) + skewness2 * cube(std_dev2)) + // std_dev_sum^(3/2) + / (std_dev_sum * std::sqrt(std_dev_sum)); + return skew; + } +} + +Delay +DelayOpsSkewNormal::sum(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() + delay2, + delay1.meanShift(), + delay1.stdDev2(), + delay1.skewness()); +} + +Delay +DelayOpsSkewNormal::diff(const Delay &delay1, + const Delay &delay2) const +{ + return Delay(delay1.mean() - delay2.mean(), + delay1.meanShift() - delay2.meanShift(), + delay1.stdDev2() + delay2.stdDev2(), + skewnessSum(delay1, delay2)); +} + +Delay +DelayOpsSkewNormal::diff(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() - delay2, + delay1.meanShift(), + delay1.stdDev2(), + delay1.skewness()); +} + +Delay +DelayOpsSkewNormal::diff(float delay1, + const Delay &delay2) const +{ + return Delay(delay1 - delay2.mean(), + delay2.meanShift(), + delay2.stdDev2(), + delay2.skewness()); +} + +void +DelayOpsSkewNormal::incr(Delay &delay1, + const Delay &delay2) const +{ + delay1.setValues(delay1.mean() + delay2.mean(), + delay1.meanShift() + delay2.meanShift(), + delay1.stdDev2() + delay2.stdDev2(), + skewnessSum(delay1, delay2)); +} + +void +DelayOpsSkewNormal::incr(DelayDbl &delay1, + const Delay &delay2) const +{ + delay1.setValues(delay1.mean() + delay2.mean(), + delay1.meanShift() + delay2.meanShift(), + delay1.stdDev2() + delay2.stdDev2(), + skewnessSum(delay1.stdDev(), delay1.skewness())); +} + +void +DelayOpsSkewNormal::decr(Delay &delay1, + const Delay &delay2) const +{ + delay1.setValues(delay1.mean() - delay2.mean(), + delay1.meanShift() + delay2.meanShift(), + delay1.stdDev2() + delay2.stdDev2(), + skewnessSum(delay1, delay2)); +} + +void +DelayOpsSkewNormal::decr(DelayDbl &delay1, + const Delay &delay2) const +{ + delay1.setValues(delay1.mean() - delay2.mean(), + delay1.meanShift() + delay2.meanShift(), + delay1.stdDev2() + delay2.stdDev2(), + skewnessSum(delay1.stdDev(), delay1.skewness())); +} + +Delay +DelayOpsSkewNormal::product(const Delay &delay1, + float delay2) const +{ + return Delay(delay1.mean() * delay2, + delay1.meanShift() * delay2, + delay1.stdDev2() * square(delay2), + delay1.skewness() * cube(delay2)); +} + +Delay +DelayOpsSkewNormal::div(float delay1, + const Delay &delay2) const +{ + return Delay(delay1 / delay2.mean()); +} + +const char * +DelayOpsSkewNormal::asStringVariance(const Delay &delay, + int digits, + const StaState *sta) const +{ + const Unit *unit = sta->units()->timeUnit(); + return stringPrintTmp("%s[%s,%s,%s]", + unit->asString(delay.mean(), digits), + unit->asString(delay.meanShift(), digits), + unit->asString(delay.stdDev(), digits), + sta->units()->scalarUnit()->asString(delay.skewness(), digits)); +} + +} // namespace diff --git a/dcalc/DmpCeff.cc b/dcalc/DmpCeff.cc index 4619bc97..48114895 100644 --- a/dcalc/DmpCeff.cc +++ b/dcalc/DmpCeff.cc @@ -90,8 +90,7 @@ gateModelRd(const LibertyCell *cell, double in_slew, double c2, double c1, - const Pvt *pvt, - bool pocv_enabled); + const Pvt *pvt); static void newtonRaphson(const int max_iter, double x[], @@ -143,8 +142,8 @@ public: virtual void loadDelaySlew(const Pin *load_pin, double elmore, // Return values. - ArcDelay &delay, - Slew &slew); + double &delay, + double &slew); double ceff() { return ceff_; } // Given x_ as a vector of input parameters, fill fvec_ with the @@ -348,13 +347,10 @@ DmpAlg::gateCapDelaySlew(double ceff, double &delay, double &slew) { - ArcDelay model_delay; - Slew model_slew; - gate_model_->gateDelay(pvt_, in_slew_, ceff, - variables_->pocvEnabled(), - model_delay, model_slew); - delay = delayAsFloat(model_delay); - slew = delayAsFloat(model_slew); + float model_delay, model_slew; + gate_model_->gateDelay(pvt_, in_slew_, ceff, model_delay, model_slew); + delay = model_delay; + slew = model_slew; } void @@ -543,8 +539,8 @@ DmpAlg::showVo() void DmpAlg::loadDelaySlew(const Pin *, double elmore, - ArcDelay &delay, - Slew &slew) + double &delay, + double &slew) { if (!driver_valid_ || elmore == 0.0 @@ -700,8 +696,8 @@ public: void loadDelaySlew(const Pin *, double elmore, // Return values. - ArcDelay &delay, - Slew &slew) override; + double &delay, + double &slew) override; void evalDmpEqns() override; double voCrossingUpperBound() override; @@ -753,8 +749,8 @@ DmpCap::gateDelaySlew(// Return values. void DmpCap::loadDelaySlew(const Pin *, double elmore, - ArcDelay &delay, - Slew &slew) + double &delay, + double &slew) { delay = elmore; slew = drvr_slew_; @@ -1498,21 +1494,36 @@ DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin, parasitics_->piModel(parasitic, c2, rpi, c1); if (std::isnan(c2) || std::isnan(c1) || std::isnan(rpi)) report_->error(1040, "parasitic Pi model has NaNs."); - setCeffAlgorithm(drvr_library, drvr_cell, pinPvt(drvr_pin, scene, min_max), + const Pvt *pvt = pinPvt(drvr_pin, scene, min_max); + setCeffAlgorithm(drvr_library, drvr_cell, pvt, table_model, rf, in_slew1, c2, rpi, c1); double gate_delay, drvr_slew; gateDelaySlew(gate_delay, drvr_slew); + + // Fill in pocv parameters. + double ceff = dmp_alg_->ceff(); + ArcDelay gate_delay2(gate_delay); + Slew drvr_slew2(drvr_slew); + if (variables_->pocvEnabled()) + table_model->gateDelayPocv(pvt, in_slew1, ceff, min_max, + variables_->pocvMode(), + gate_delay2, drvr_slew2); ArcDcalcResult dcalc_result(load_pin_index_map.size()); - dcalc_result.setGateDelay(gate_delay); - dcalc_result.setDrvrSlew(drvr_slew); + dcalc_result.setGateDelay(gate_delay2); + dcalc_result.setDrvrSlew(drvr_slew2); for (const auto &[load_pin, load_idx] : load_pin_index_map) { - ArcDelay wire_delay; - Slew load_slew; + double wire_delay; + double load_slew; loadDelaySlew(load_pin, drvr_slew, rf, drvr_library, parasitic, wire_delay, load_slew); - dcalc_result.setWireDelay(load_idx, wire_delay); - dcalc_result.setLoadSlew(load_idx, load_slew); + // Copy pocv params from driver. + ArcDelay wire_delay2(gate_delay2); + Slew load_slew2(drvr_slew2); + delaySetMean(wire_delay2, wire_delay); + delaySetMean(load_slew2, load_slew); + dcalc_result.setWireDelay(load_idx, wire_delay2); + dcalc_result.setLoadSlew(load_idx, load_slew2); } return dcalc_result; } @@ -1543,8 +1554,7 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library, { double rd = 0.0; if (gate_model) { - rd = gateModelRd(drvr_cell, gate_model, rf, in_slew, c2, c1, - pvt, variables_->pocvEnabled()); + rd = gateModelRd(drvr_cell, gate_model, rf, in_slew, c2, c1, pvt); // Zero Rd means the table is constant and thus independent of load cap. if (rd < 1e-2 // Rpi is small compared to Rd, which makes the load capacitive. @@ -1612,14 +1622,12 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin, else c_eff = load_cap; if (model) { - const Unit *time_unit = units->timeUnit(); float in_slew1 = delayAsFloat(in_slew); result += model->reportGateDelay(pinPvt(drvr_pin, scene, min_max), - in_slew1, c_eff, - variables_->pocvEnabled(), digits); + in_slew1, c_eff, min_max, + variables_->pocvMode(), digits); result += "Driver waveform slew = "; - float drvr_slew = delayAsFloat(dcalc_result.drvrSlew()); - result += time_unit->asString(drvr_slew, digits); + result += delayAsString(dcalc_result.drvrSlew(), min_max, digits, this); result += '\n'; } return result; @@ -1632,18 +1640,15 @@ gateModelRd(const LibertyCell *cell, double in_slew, double c2, double c1, - const Pvt *pvt, - bool pocv_enabled) + const Pvt *pvt) { float cap1 = c1 + c2; float cap2 = cap1 + 1e-15; - ArcDelay d1, d2; - Slew s1, s2; - gate_model->gateDelay(pvt, in_slew, cap1, pocv_enabled, d1, s1); - gate_model->gateDelay(pvt, in_slew, cap2, pocv_enabled, d2, s2); + float d1, d2, s1, s2; + gate_model->gateDelay(pvt, in_slew, cap1, d1, s1); + gate_model->gateDelay(pvt, in_slew, cap2, d2, s2); double vth = cell->libertyLibrary()->outputThreshold(rf); - float rd = -std::log(vth) * std::abs(delayAsFloat(d1) - delayAsFloat(d2)) - / (cap2 - cap1); + float rd = -std::log(vth) * std::abs(d1 - d2) / (cap2 - cap1); return rd; } @@ -1658,8 +1663,8 @@ DmpCeffDelayCalc::gateDelaySlew(// Return values. void DmpCeffDelayCalc::loadDelaySlewElmore(const Pin *load_pin, double elmore, - ArcDelay &delay, - Slew &slew) + double &delay, + double &slew) { if (dmp_alg_) dmp_alg_->loadDelaySlew(load_pin, elmore, delay, slew); diff --git a/dcalc/DmpCeff.hh b/dcalc/DmpCeff.hh index d1931517..4d3b7fd5 100644 --- a/dcalc/DmpCeff.hh +++ b/dcalc/DmpCeff.hh @@ -69,15 +69,15 @@ protected: const LibertyLibrary *drvr_library, const Parasitic *parasitic, // Return values. - ArcDelay &wire_delay, - Slew &load_slew) = 0; + double &wire_delay, + double &load_slew) = 0; void gateDelaySlew(// Return values. double &delay, double &slew); void loadDelaySlewElmore(const Pin *load_pin, double elmore, - ArcDelay &delay, - Slew &slew); + double &delay, + double &slew); // Select the appropriate special case Dartu/Menezes/Pileggi algorithm. void setCeffAlgorithm(const LibertyLibrary *library, const LibertyCell *cell, diff --git a/dcalc/DmpDelayCalc.cc b/dcalc/DmpDelayCalc.cc index e0a350d2..aece357e 100644 --- a/dcalc/DmpDelayCalc.cc +++ b/dcalc/DmpDelayCalc.cc @@ -59,8 +59,8 @@ protected: const LibertyLibrary *drvr_library, const Parasitic *parasitic, // Return values. - ArcDelay &wire_delay, - Slew &load_slew) override; + double &wire_delay, + double &load_slew) override; }; ArcDelayCalc * @@ -93,8 +93,8 @@ DmpCeffElmoreDelayCalc::inputPortDelay(const Pin *, ArcDcalcResult dcalc_result(load_pin_index_map.size()); LibertyLibrary *drvr_library = network_->defaultLibertyLibrary(); for (auto [load_pin, load_idx] : load_pin_index_map) { - ArcDelay wire_delay = 0.0; - Slew load_slew = in_slew; + double wire_delay = 0.0; + double load_slew = in_slew; bool elmore_exists = false; float elmore = 0.0; if (parasitic) @@ -116,8 +116,8 @@ DmpCeffElmoreDelayCalc::loadDelaySlew(const Pin *load_pin, const LibertyLibrary *drvr_library, const Parasitic *parasitic, // Return values. - ArcDelay &wire_delay, - Slew &load_slew) + double &wire_delay, + double &load_slew) { wire_delay = 0.0; load_slew = drvr_slew; @@ -143,14 +143,14 @@ public: Parasitic *findParasitic(const Pin *drvr_pin, const RiseFall *rf, const Scene *scene, - const MinMax *min_max) override; + const MinMax *min_max) override; ArcDcalcResult inputPortDelay(const Pin *port_pin, float in_slew, const RiseFall *rf, const Parasitic *parasitic, const LoadPinIndexMap &load_pin_index_map, const Scene *scene, - const MinMax *min_max) override; + const MinMax *min_max) override; ArcDcalcResult gateDelay(const Pin *drvr_pin, const TimingArc *arc, const Slew &in_slew, @@ -158,7 +158,7 @@ public: const Parasitic *parasitic, const LoadPinIndexMap &load_pin_index_map, const Scene *scene, - const MinMax *min_max) override; + const MinMax *min_max) override; private: void loadDelaySlew(const Pin *load_pin, @@ -167,14 +167,14 @@ private: const LibertyLibrary *drvr_library, const Parasitic *parasitic, // Return values. - ArcDelay &wire_delay, - Slew &load_slew) override; + double &wire_delay, + double &load_slew) override; void loadDelay(double drvr_slew, Parasitic *pole_residue, double p1, double k1, - ArcDelay &wire_delay, - Slew &load_slew); + double &wire_delay, + double &load_slew); float loadDelay(double vth, double p1, double p2, @@ -267,8 +267,8 @@ DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *, { const Parasitics *parasitics = scene->parasitics(min_max); ArcDcalcResult dcalc_result(load_pin_index_map.size()); - ArcDelay wire_delay = 0.0; - Slew load_slew = in_slew; + double wire_delay = 0.0; + double load_slew = in_slew; LibertyLibrary *drvr_library = network_->defaultLibertyLibrary(); for (const auto [load_pin, load_idx] : load_pin_index_map) { if (parasitics->isPiPoleResidue(parasitic)) { @@ -323,8 +323,8 @@ DmpCeffTwoPoleDelayCalc::loadDelaySlew(const Pin *load_pin, const LibertyLibrary *drvr_library, const Parasitic *parasitic, // Return values. - ArcDelay &wire_delay, - Slew &load_slew) + double &wire_delay, + double &load_slew) { parasitic_is_pole_residue_ = parasitics_->isPiPoleResidue(parasitic); // Should handle PiElmore parasitic. @@ -362,12 +362,12 @@ DmpCeffTwoPoleDelayCalc::loadDelay(double drvr_slew, double p1, double k1, // Return values. - ArcDelay &wire_delay, - Slew &load_slew) + double &wire_delay, + double &load_slew) { ComplexFloat pole2, residue2; parasitics_->poleResidue(pole_residue, 1, pole2, residue2); - if (!delayZero(drvr_slew) + if (!delayZero(drvr_slew, this) && pole2.imag() == 0.0 && residue2.imag() == 0.0) { double p2 = pole2.real(); diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index e33067d2..10c64e93 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -646,17 +646,17 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin, ArcDcalcResult intrinsic_result = arc_delay_calc_->gateDelay(drvr_pin, arc, Slew(from_slew), 0.0, nullptr, load_pin_index_map, scene, min_max); - ArcDelay intrinsic_delay = intrinsic_result.gateDelay(); + const ArcDelay &intrinsic_delay = intrinsic_result.gateDelay(); ArcDcalcResult gate_result = arc_delay_calc_->gateDelay(drvr_pin, arc, Slew(from_slew), load_cap, parasitic, load_pin_index_map, scene, min_max); - ArcDelay gate_delay = gate_result.gateDelay(); - Slew gate_slew = gate_result.drvrSlew(); + const ArcDelay &gate_delay = gate_result.gateDelay(); + const Slew &gate_slew = gate_result.drvrSlew(); - ArcDelay load_delay = gate_delay - intrinsic_delay; + const ArcDelay load_delay = delayDiff(gate_delay, intrinsic_delay, this); debugPrint(debug_, "delay_calc", 3, " gate delay = %s intrinsic = %s slew = %s", delayAsString(gate_delay, this), @@ -729,9 +729,8 @@ GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map) Vertex *load_vertex = graph_->pinLoadVertex(pin); SlewSeq &slews = load_slews[index];; slews.resize(slew_count); - Slew *vertex_slews = load_vertex->slews(); for (size_t i = 0; i < slew_count; i++) - slews[i] = vertex_slews[i]; + slews[i] = graph_->slew(load_vertex, i); } return load_slews; } @@ -744,9 +743,9 @@ GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &load_slews_prev, for (auto const [pin, index] : load_pin_index_map) { Vertex *load_vertex = graph_->pinLoadVertex(pin); SlewSeq &slews_prev = load_slews_prev[index];; - const Slew *slews = load_vertex->slews(); for (size_t i = 0; i < slew_count; i++) { - if (!delayEqual(slews[i], slews_prev[i])) + const Slew &slew = graph_->slew(load_vertex, i); + if (!delayEqual(slew, slews_prev[i], this)) return true; } } @@ -915,19 +914,18 @@ GraphDelayCalc::initLoadSlews(Vertex *drvr_vertex) Edge *wire_edge = edge_iter.next(); if (wire_edge->isWire()) { Vertex *load_vertex = wire_edge->to(graph_); - for (Scene *scene : scenes_) { for (const MinMax *min_max : MinMax::range()) { DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); Slew slew_init_value(min_max->initValue()); - for (const RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { if (!load_vertex->slewAnnotated(rf, min_max)) - graph_->setSlew(load_vertex, rf, ap_index, slew_init_value); + graph_->setSlew(load_vertex, rf, ap_index, slew_init_value); + } } } } } - } } bool @@ -965,12 +963,12 @@ GraphDelayCalc::initRootSlews(Vertex *vertex) for (Scene *scene : scenes_) { for (const MinMax *min_max : MinMax::range()) { DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); - for (const RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { if (!vertex->slewAnnotated(rf, min_max)) - graph_->setSlew(vertex, rf, ap_index, default_slew); + graph_->setSlew(vertex, rf, ap_index, default_slew); + } } } - } } void @@ -1195,8 +1193,8 @@ GraphDelayCalc::annotateDelaysSlews(Edge *edge, bool GraphDelayCalc::annotateDelaySlew(Edge *edge, const TimingArc *arc, - ArcDelay &gate_delay, - Slew &gate_slew, + const ArcDelay &gate_delay, + const Slew &gate_slew, const Scene *scene, const MinMax *min_max) { @@ -1258,8 +1256,8 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, Vertex *load_vertex = wire_edge->to(graph_); Pin *load_pin = load_vertex->pin(); size_t load_idx = load_pin_index_map[load_pin]; - ArcDelay wire_delay = dcalc_result.wireDelay(load_idx); - Slew load_slew = dcalc_result.loadSlew(load_idx); + const ArcDelay &wire_delay = dcalc_result.wireDelay(load_idx); + const Slew &load_slew = dcalc_result.loadSlew(load_idx); debugPrint(debug_, "delay_calc", 3, " %s load delay = %s slew = %s", load_vertex->to_string(this).c_str(), @@ -1287,7 +1285,7 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, // annotate the same wire edges so they must be combined // rather than set. const ArcDelay &delay = graph_->wireArcDelay(wire_edge, drvr_rf, ap_index); - Delay wire_delay_extra = extra_delay + wire_delay; + Delay wire_delay_extra = delaySum(extra_delay, wire_delay, this); if (!merge || delayGreater(wire_delay_extra, delay, min_max, this)) { graph_->setWireArcDelay(wire_edge, drvr_rf, ap_index, wire_delay_extra); diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc index 4c4a1251..07a68e5b 100644 --- a/dcalc/LumpedCapDelayCalc.cc +++ b/dcalc/LumpedCapDelayCalc.cc @@ -118,7 +118,7 @@ LumpedCapDelayCalc::inputPortDelay(const Pin *, const MinMax *) { const LibertyLibrary *drvr_library = network_->defaultLibertyLibrary(); - return makeResult(drvr_library,rf, 0.0, in_slew, load_pin_index_map); + return makeResult(drvr_library,rf, delay_zero, in_slew, load_pin_index_map); } ArcDcalcResult @@ -139,16 +139,22 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin, const RiseFall *rf = arc->toEdge()->asRiseFall(); const LibertyLibrary *drvr_library = arc->to()->libertyLibrary(); if (model) { - ArcDelay gate_delay; - Slew drvr_slew; + float gate_delay, drvr_slew; float in_slew1 = delayAsFloat(in_slew); // NaNs cause seg faults during table lookup. - if (std::isnan(load_cap) || std::isnan(delayAsFloat(in_slew))) + if (std::isnan(load_cap) || std::isnan(in_slew.mean())) report_->error(1350, "gate delay input variable is NaN"); - model->gateDelay(pinPvt(drvr_pin, scene, min_max), in_slew1, load_cap, - variables_->pocvEnabled(), - gate_delay, drvr_slew); - return makeResult(drvr_library, rf, gate_delay, drvr_slew, load_pin_index_map); + const Pvt *pvt = pinPvt(drvr_pin, scene, min_max); + model->gateDelay(pvt, in_slew1, load_cap, gate_delay, drvr_slew); + + // Fill in pocv parameters. + ArcDelay gate_delay2(gate_delay); + Slew drvr_slew2(drvr_slew); + if (variables_->pocvEnabled()) + model->gateDelayPocv(pvt, in_slew1, load_cap, min_max, variables_->pocvMode(), + gate_delay2, drvr_slew2); + + return makeResult(drvr_library, rf, gate_delay2, drvr_slew2, load_pin_index_map); } else return makeResult(drvr_library, rf, delay_zero, delay_zero, load_pin_index_map); @@ -157,17 +163,18 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin, ArcDcalcResult LumpedCapDelayCalc::makeResult(const LibertyLibrary *drvr_library, const RiseFall *rf, - ArcDelay gate_delay, - Slew drvr_slew, + const ArcDelay &gate_delay, + const Slew &drvr_slew, const LoadPinIndexMap &load_pin_index_map) { ArcDcalcResult dcalc_result(load_pin_index_map.size()); dcalc_result.setGateDelay(gate_delay); dcalc_result.setDrvrSlew(drvr_slew); + double drvr_slew1 = delayAsFloat(drvr_slew); for (const auto [load_pin, load_idx] : load_pin_index_map) { - ArcDelay wire_delay = 0.0; - Slew load_slew = drvr_slew; + double wire_delay = 0.0; + double load_slew = drvr_slew1; thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew); dcalc_result.setWireDelay(load_idx, wire_delay); dcalc_result.setLoadSlew(load_idx, load_slew); @@ -190,7 +197,8 @@ LumpedCapDelayCalc::reportGateDelay(const Pin *check_pin, if (model) { float in_slew1 = delayAsFloat(in_slew); return model->reportGateDelay(pinPvt(check_pin, scene, min_max), - in_slew1, load_cap, false, digits); + in_slew1, load_cap, min_max, + PocvMode::scalar, digits); } return ""; } diff --git a/dcalc/LumpedCapDelayCalc.hh b/dcalc/LumpedCapDelayCalc.hh index ac631f3a..752edea9 100644 --- a/dcalc/LumpedCapDelayCalc.hh +++ b/dcalc/LumpedCapDelayCalc.hh @@ -74,8 +74,8 @@ public: protected: ArcDcalcResult makeResult(const LibertyLibrary *drvr_library, const RiseFall *rf, - ArcDelay gate_delay, - Slew drvr_slew, + const ArcDelay &gate_delay, + const Slew &drvr_slew, const LoadPinIndexMap &load_pin_index_map); using ArcDelayCalc::reduceParasitic; diff --git a/dcalc/ParallelDelayCalc.cc b/dcalc/ParallelDelayCalc.cc index 512ea9f5..38b71c32 100644 --- a/dcalc/ParallelDelayCalc.cc +++ b/dcalc/ParallelDelayCalc.cc @@ -88,13 +88,13 @@ ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args, load_pin_index_map, scene, min_max); ArcDelay gate_delay = gate_result.gateDelay(); Slew drvr_slew = gate_result.drvrSlew(); - ArcDelay load_delay = gate_delay - intrinsic_delay; + ArcDelay load_delay = delayDiff(gate_delay, intrinsic_delay, this); load_delays[drvr_idx] = load_delay; - if (!delayZero(load_delay)) - load_delay_sum += 1.0 / load_delay; - if (!delayZero(drvr_slew)) - slew_sum += 1.0 / drvr_slew; + if (!delayZero(load_delay, this)) + delayIncr(load_delay_sum, delayDiv(1.0, load_delay, this), this); + if (!delayZero(drvr_slew, this)) + delayIncr(slew_sum, delayDiv(1.0, drvr_slew, this), this); dcalc_result.setLoadCount(load_pin_index_map.size()); for (const auto &[load_pin, load_idx] : load_pin_index_map) { @@ -103,14 +103,16 @@ ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args, } } - ArcDelay gate_load_delay = delayZero(load_delay_sum) + ArcDelay gate_load_delay = delayZero(load_delay_sum, this) ? delay_zero - : 1.0 / load_delay_sum; - ArcDelay drvr_slew = delayZero(slew_sum) ? delay_zero : 1.0 / slew_sum; + : delayDiv(1.0, load_delay_sum, this); + ArcDelay drvr_slew = delayZero(slew_sum, this) + ? delay_zero + : delayDiv(1.0, slew_sum, this); for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) { ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx]; - dcalc_result.setGateDelay(intrinsic_delays[drvr_idx] + gate_load_delay); + dcalc_result.setGateDelay(delaySum(intrinsic_delays[drvr_idx], gate_load_delay, this)); dcalc_result.setDrvrSlew(drvr_slew); } return dcalc_results; diff --git a/dcalc/PrimaDelayCalc.cc b/dcalc/PrimaDelayCalc.cc index b8b5c85c..90e31ed3 100644 --- a/dcalc/PrimaDelayCalc.cc +++ b/dcalc/PrimaDelayCalc.cc @@ -166,8 +166,8 @@ PrimaDelayCalc::inputPortDelay(const Pin *drvr_pin, for (auto load_pin_index : load_pin_index_map) { const Pin *load_pin = load_pin_index.first; size_t load_idx = load_pin_index.second; - ArcDelay wire_delay = 0.0; - Slew load_slew = in_slew; + double wire_delay = 0.0; + double load_slew = in_slew; bool elmore_exists = false; float elmore = 0.0; if (pi_elmore) @@ -722,8 +722,8 @@ PrimaDelayCalc::dcalcResults() size_t drvr_node = pin_node_map_[drvr_pin]; ThresholdTimes &drvr_times = threshold_times_[drvr_node]; float ref_time = output_waveforms_[drvr_idx]->referenceTime(dcalc_arg.inSlewFlt()); - ArcDelay gate_delay = drvr_times[threshold_vth] - ref_time; - Slew drvr_slew = std::abs(drvr_times[threshold_vh] - drvr_times[threshold_vl]); + double gate_delay = drvr_times[threshold_vth] - ref_time; + double drvr_slew = std::abs(drvr_times[threshold_vh] - drvr_times[threshold_vl]); dcalc_result.setGateDelay(gate_delay); dcalc_result.setDrvrSlew(drvr_slew); debugPrint(debug_, "ccs_dcalc", 2, @@ -739,8 +739,8 @@ PrimaDelayCalc::dcalcResults() size_t load_node = pin_node_map_[load_pin]; ThresholdTimes &wire_times = threshold_times_[load_node]; ThresholdTimes &drvr_times = threshold_times_[drvr_node]; - ArcDelay wire_delay = wire_times[threshold_vth] - drvr_times[threshold_vth]; - Slew load_slew = std::abs(wire_times[threshold_vh] - wire_times[threshold_vl]); + double wire_delay = wire_times[threshold_vth] - drvr_times[threshold_vth]; + double load_slew = std::abs(wire_times[threshold_vh] - wire_times[threshold_vl]); debugPrint(debug_, "ccs_dcalc", 2, "load %s %s delay %s slew %s", network_->pathName(load_pin), @@ -920,7 +920,8 @@ PrimaDelayCalc::reportGateDelay(const Pin *drvr_pin, if (model) { float in_slew1 = delayAsFloat(in_slew); return model->reportGateDelay(pinPvt(drvr_pin, scene, min_max), - in_slew1, load_cap, false, digits); + in_slew1, load_cap, min_max, + PocvMode::scalar, digits); } return ""; } diff --git a/doc/ApiChanges.txt b/doc/ApiChanges.txt index 23c9e11f..0ac6caa8 100644 --- a/doc/ApiChanges.txt +++ b/doc/ApiChanges.txt @@ -62,6 +62,8 @@ The Vector/Map/Set/UnorderedSet classes have been removed and replaced by the std containers. The member functions are now templated functions found in ContainerHelpers.hh. +The Graph slew_rf_count option is no longer supported. + Release 2.6.2 2025/03/30 ------------------------ diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index 8d695f63..1f1871b9 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -3,6 +3,134 @@ OpenSTA Timing Analyzer Release Notes This file summarizes user visible changes for each release. +Release 3.0.1 2026/03/12 +------------------------ + +Statistical timing (SSTA) with Liberty LVF (Liberty Variation Format) +models is now supported. Statistical timing uses a probaility +distribution to represent a delay or slew ranther than a single +number. + +Normal and skew normal probability distributions are supported. + +SSTA is enabled with the sta_pocv_mode variaable. + + set sta_pocv_mode scalar|normal|skew_normal + +scalar mode is for non-SSTA analysis +normal mode uses gaussian normal distributions +skew_normal'mode is for skew normal LVF moment based distributions + +The target quantile of a delay probability distribution (confidence level) is +set with the sta_pocv_quantile variable. + + sta_pocv_quantile + +The default value is 3 standard deviations, or sigma. + +Use the variance field with report_checks or report_check_types to see +distribution parameters in timing reports. + +A command file for analyzing a design with statisical timing with an +LVF library is shown below. + +read_liberty lvf_library.lib.gz +read_verilog design.v +link_design top +create_clock -period 50 clk +set_input_delay -clock clk 1 {in1 in2} +set sta_pocv_mode skew_normal +report_checks -fields {slew variation input_pin variation} -digits 3 + +Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Slew Delay Variation Time Description +--------------------------------------------------------------------------- + 0.000 0.000 0.000 clock clk (rise edge) + 0.000 0.000 clock network delay (ideal) + 0.000 0.000 0.000 ^ r2/CK (FDPQ1) + 12.026 mean + 0.017 mean_shift + 0.366 std_dev + 0.000 skewness + 4.648 12.409 12.409 v r2/Q (FFQ1) + 4.648 0.000 12.409 v u1/A (BUF1) + 6.084 mean + 0.007 mean_shift + 0.188 std_dev + 0.000 skewness + 2.513 6.137 18.546 v u1/X (BUF1) + 2.513 0.000 18.546 v u2/A2 (AN21) + 6.447 mean + 0.008 mean_shift + 0.191 std_dev + 0.000 skewness + 2.565 6.497 25.043 v u2/X (AN21) + 2.565 0.000 25.043 v r3/D (FFQ1) + 25.043 data arrival time + + 0.000 50.000 50.000 clock clk (rise edge) + 0.000 50.000 clock network delay (ideal) + 0.000 50.000 clock reconvergence pessimism + 50.000 ^ r3/CK (FFQ1) + -9.376 40.624 library setup time + 40.624 data required time +--------------------------------------------------------------------------- + 40.624 data required time + -25.043 data arrival time +--------------------------------------------------------------------------- + 15.581 slack (MET) + + +The following commands now support a -report_variance arggument. + + report_arrival [-report_variance] + report_required [-report_variance] + report_slack [-report_variance] + report_slews [-report_variance] + report_edges [-report_variance] + +The following commands now support a -digits option. + + report_edges [-digits digits] + report_slews [-digits digits] + +The standard deviation for normal distributions is specified with the +following liberty timing groups. + + ocv_sigma_cell_rise + ocv_sigma_cell_fall + ocv_sigma_rise_transition + ocv_sigma_fall_transition + ocv_sigma_rise_constraint + ocv_sigma_fall_constraint + +LVF skew normal distributions are specified with liberty groups below. + + ocv_std_dev_cell_rise + ocv_std_dev_cell_fall + ocv_mean_shift_cell_rise + ocv_mean_shift_cell_fall + ocv_skewness_cell_rise + ocv_skewness_cell_fall + + ocv_std_dev_rise_transition + ocv_std_dev_fall_transition + ocv_skewness_rise_transition + ocv_skewness_fall_transition + ocv_mean_shift_rise_transition + ocv_mean_shift_fall_transition + + ocv_std_dev_rise_constraint + ocv_std_dev_fall_constraint + ocv_skewness_rise_constraint + ocv_skewness_fall_constraint + ocv_mean_shift_rise_constraint + ocv_mean_shift_fall_constraint + 2026/02/24 ---------- diff --git a/doc/OpenSTA.fodt b/doc/OpenSTA.fodt index fb9ea3b6..56bfdfc2 100644 --- a/doc/OpenSTA.fodt +++ b/doc/OpenSTA.fodt @@ -1,24 +1,24 @@ - Parallax STA documentationJames Cherry5192025-03-17T12:59:52.4638705382010-07-31T21:07:002026-03-07T17:12:46.349252000P123DT1H24M11SLibreOffice/25.8.1.1$MacOSX_AARCH64 LibreOffice_project/54047653041915e595ad4e45cccea684809c77b5PDF files: James CherryJames Cherry12.00000falsefalsefalsefalse + Parallax STA documentationJames Cherry5272025-03-17T12:59:52.4638705382010-07-31T21:07:002026-03-13T08:23:12.816774000P123DT2H11M52SLibreOffice/25.8.1.1$MacOSX_AARCH64 LibreOffice_project/54047653041915e595ad4e45cccea684809c77b5PDF files: James CherryJames Cherry12.00000falsefalsefalsefalse - 1488348 - 1956 - 19290 - 17736 + 138335 + 12 + 21890 + 20512 true false view2 - 17619 - 1497110 - 1956 - 1488348 - 21244 - 1506082 + 5793 + 99330 + 12 + 138335 + 21900 + 158845 0 1 false @@ -89,7 +89,7 @@ false true false - 26953533 + 27526206 0 false @@ -198,7 +198,7 @@ - + @@ -4029,6 +4029,21 @@ + + + + + + + + + + + + + + + @@ -4175,267 +4190,289 @@ - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + - - + + + - - + + + - + - + - - + - - + + - - + - - + + - - + + - - + + - - + + - + - - + + - + - - + + - - + - - + + - + + - - + + - + - + - - + - + - + - + - + - + + - + - + + - - + + + - + - - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -4444,864 +4481,883 @@ - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - + + - - + + + - - + - + - + - - - + + - + - - + + + - - + + - - + + - + - + - + - - - - - - - - + + + + + + + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - + - - - + + + - - + + + - - + - + - - - + + - - + + - - + + - - - + + - - - + + - - + + - - + + - + + - + - - + + + - - + + - - + + + - + - + - - + + - - + + + - - + - - - - + - + + + + - - + + - - + + - - + + - + - - - - - + - - + + - + - + + + + - - + + - - + + + - - + - - + + - + - - + + + - + - - - - - + - - + + + + + + - - + + - - + + - + - - + + + - + - - - + + - - + + - + - - + + + - - - + + - - + + - - + - - + - - + + + - + - - + + - + - + - - + + - + - - + + + - - + + + - - + + + - + - - - + + - - - + + - - + + - + - + - - - - + - - + + - - - + + - - - + + + + + - + - + - + - + - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + - + - - + + - - + + - - - + + - - - + + - - + + - - + - - - + + + - + - - + + + - + - - + + - + - - + - + - + - + - - + + + - - + + + - - + + + - + - - - + + - + - - - + + - + - + - - - - - - - + - + - + - + - - - + + - - + + + + + + + + + - + - + - - + + - + - - - - + - - + + + + + - + - - - - - - - + - + - + + + + + + + + - + + + + + - + - - + + + - - - - - + + - + + - - + + - + - + - - - + + - + + - - - - + - - - + + + - - - + + - - - + + + + + - - + - - - + + - - + + - + - - + + + - - + + - - + - + - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + - + - + - + @@ -5345,1044 +5401,1077 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6518,85 +6607,101 @@ Variables85 - Command Line Arguments + Command Line Arguments The command line arguments for sta are shown below. sta -help show help and exit -version show version and exit -no_init do not read ~/.sta -no_splash do not print the splash message -threads count|max use count threads -exit exit after reading cmd_file cmd_file source cmd_file When OpenSTA starts up, commands are first read from the user initialization file ~/.sta if it exists. If a TCL command file cmd_file is specified on the command line, commands are read from the file and executed before entering an interactive TCL command interpreter. If -exit is specified the application exits after reading cmd_file. Use the TCL exit command to exit the application. The –threads option specifies how many parallel threads to use. Use –threads max to use one thread per processor. - Example Command Scripts + Example Command Scripts To read a design into OpenSTA use the read_liberty command to read Liberty library files. Next, read hierarchical structural Verilog files with the read_verilog command. The link_design command links the Verilog to the Liberty timing cells. Any number of Liberty and Verilog files can be read before linking the design. Delays used for timing analysis are calculated using the Liberty timing models. If no parasitics are read only the pin capacitances of the timing models are used in delay calculation. Use the read_spef command to read parasitics from an extractor, or read_sdf to use delays calculated by an external delay calculator. Timing constraints can be entered as TCL commands or read using the read_sdc command. The units used by OpenSTA for all command arguments and reports are taken from the first Liberty file that is read. Use the set_cmd_units command to override the default units. Use the report_units command to see the ccmmand units. - Timing Analysis using SDF + Timing Analysis using SDF A sample command file that reads a library and a Verilog netlist and reports timing checks is shown below. read_liberty example1_slow.libread_verilog example1.vlink_design topread_sdf example1.sdfcreate_clock -name clk -period 10 {clk1 clk2 clk3}set_input_delay -clock clk 0 {in1 in2}report_checks This example can be found in examples/sdf_delays.tcl. - Timing Analysis with Multiple Process Corners + Timing Analysis with Multiple Process Corners An example command script using three process corners and +/-10% min/max derating is shown below. read_liberty nangate45_slow.lib.gzread_liberty nangate45_typ.lib.gzread_liberty nangate45_fast.lib.gzread_verilog example1.link_design topset_timing_derate -early 0.9set_timing_derate -late 1.1create_clock -name clk -period 10 {clk1 clk2 clk3}set_input_delay -clock clk 0 {in1 in2}define_scene ss -liberty nangate45_slowdefine_scene tt -liberty nangate45_typdefine_scene ff -liberty nangate45_fast# report all scenesreport_checks -path_delay min_max# report typical scenereport_checks -scene tt This example can be found in examples/multi_corner.tcl. Other examples can be found in the examples directory. - Timing Analysis with Multiple Corners and Modes + Timing Analysis with Multiple Corners and Modes OpenSTA supports multi-corner, multi-mode analysis. Each corner/mode combination is called a “scene”. The SDC constraints in each mode describe a different operating mode, such as mission mode or scan mode. Each corner has min/max Liberty libraries and SPEF parasitics. A mode named “default” is initially created for SDC commands. It is deleted when a mode is defined with set_mode or read_sdc -mode. Similartly, a named “default” is initially created that is deleted when define_scene is used to define a scene. An example command script using two process corners two modes is shown below. read_liberty asap7_small_ff.lib.gzread_liberty asap7_small_ss.lib.gzread_verilog reg1_asap7.vlink_design topread_sdc -mode mode1 mcmm2_mode1.sdcread_sdc -mode mode2 mcmm2_mode2.sdcread_spef -name reg1_ff reg1_asap7.spefread_spef -name reg1_ss reg1_asap7_ss.spefdefine_scene scene1 -mode mode1 -liberty asap7_small_ff -spef reg1_ffdefine_scene scene2 -mode mode2 -liberty asap7_small_ss -spef reg1_ssreport_checks -scenes scene1report_checks -scenes scene2report_checks -group_path_count 4 This example can be found in examples/mcmm3.tcl.In the example show above the SDC for the modes is in separate files. Alternatively, the SDC can be defined in the command file using the set_mode command between SDC command groups. set_mode mode1create_clock -name m1_clk -period 1000 {clk1 clk2 clk3}set_input_delay -clock m1_clk 100 {in1 in2}set_mode mode2create_clock -name m2_clk -period 500 {clk1 clk3}set_output_delay -clock m2_clk 100 out - Power Analysis - OpenSTA also supports static power analysis with the report_power command. Probabalistic switching activities are propagated from the input ports to determine switching activities for internal pins. - read_liberty sky130hd_tt.libread_verilog gcd_sky130hd.vlink_design gcdread_sdc gcd_sky130hd.sdcread_spef gcd_sky130hd.spefset_power_activity -input -activity 0.1set_power_activity -input_port reset -activity 0report_power - In this example the activity for all inputs is set to 0.1, and then the activity for the reset signal is set to zero because it does not switch during steady state operation. - Group Internal Switching Leakage Total Power Power Power Power (Watts)----------------------------------------------------------------Sequential 3.27e-04 7.87e-05 2.96e-10 4.06e-04 36.4%Combinational 2.34e-04 3.10e-04 6.95e-10 5.43e-04 48.7%Clock 4.68e-05 1.20e-04 2.30e-11 1.67e-04 15.0%Macro 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%Pad 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%----------------------------------------------------------------Total 6.07e-04 5.09e-04 1.01e-09 1.12e-03 100.0% 54.4% 45.6% 0.0% - This example can be found in examples/power.tcl. - Gate level simulation results can be used to get a more accurate power estimate. For example, the Icarus verilog simulator can be used to run the the test bench examples/gcd_tb.v for the gcd design in the previous example. + Statistical Timing Analysis + OpenSTA also supports statistical timing .anallysis with Liberty Variation Format (LVF) libraries. Statistical timing uses a probaility distribution to represent a delay or slew ranther than a single number. + Normal and skew normal probability distributions are supported. SSTA is enabled with the sta_pocv_mode variaable. + set sta_pocv_mode scalar|normal|skew_normalscalar mode is for non-SSTA analysisnormal mode uses gaussian normal distributionsskew_normal mode is for skew normal LVF moment based distributions + The target quantile of a delay probability distribution (confidence level) is set with the sta_pocv_quantile variable. + set sta_pocv_quantile <float> + The default value is 3 standard deviations, or sigma. + Use the variance field with the report_checks and report_check_types commands to see distribution parameters in timing reports. + A command file for analyzing a design with statisical timing is shown below. + read_liberty lvf_library.lib.gzread_verilog design.vlink_design topcreate_clock -period 50 clkset_input_delay -clock clk 1 {in1 in2}set sta_pocv_mode skew_normalreport_checks -fields {slew variation input_pin variation} -digits 3 + Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)Path Group: clkPath Type: max Slew Delay Variation Time Description--------------------------------------------------------------------------- 0.000 0.000 0.000 clock clk (rise edge) 0.000 0.000 clock network delay (ideal) 0.000 0.000 0.000 ^ r2/CK (FDPQ1) 12.026 mean 0.017 mean_shift 0.366 std_dev 0.000 skewness 4.648 12.409 12.409 v r2/Q (FFQ1) 4.648 0.000 12.409 v u1/A (BUF1) 6.084 mean 0.007 mean_shift 0.188 std_dev 0.000 skewness 2.513 6.137 18.546 v u1/X (BUF1) 2.513 0.000 18.546 v u2/A2 (AN21) 6.447 mean 0.008 mean_shift 0.191 std_dev 0.000 skewness 2.565 6.497 25.043 v u2/X (AN21) 2.565 0.000 25.043 v r3/D (FFQ1) 25.043 data arrival time 0.000 50.000 50.000 clock clk (rise edge) 0.000 50.000 clock network delay (ideal) 0.000 50.000 clock reconvergence pessimism 50.000 ^ r3/CK (FFQ1) -9.376 40.624 library setup time 40.624 data required time--------------------------------------------------------------------------- 40.624 data required time -25.043 data arrival time--------------------------------------------------------------------------- 15.581 slack (MET) + The standard deviation for normal distributions is specified with the following liberty timing groups. + ocv_sigma_cell_riseocv_sigma_cell_fallocv_sigma_rise_transitionocv_sigma_fall_transitionocv_sigma_rise_constraintocv_sigma_fall_constraint + LVF skew normal distributions are specified with liberty groups below. + ocv_std_dev_cell_riseocv_std_dev_cell_fallocv_mean_shift_cell_riseocv_mean_shift_cell_fallocv_skewness_cell_riseocv_skewness_cell_fallocv_std_dev_rise_transitionocv_std_dev_fall_transitionocv_skewness_rise_transitionocv_skewness_fall_transitionocv_mean_shift_rise_transitionocv_mean_shift_fall_transitionocv_std_dev_rise_constraintocv_std_dev_fall_constraintocv_skewness_rise_constraintocv_skewness_fall_constraintocv_mean_shift_rise_constraintocv_mean_shift_fall_constraint + + Power Analysis + OpenSTA also supports static power analysis with the report_power command. Probabalistic switching activities are propagated from the input ports to determine switching activities for internal pins. + read_liberty sky130hd_tt.libread_verilog gcd_sky130hd.vlink_design gcdread_sdc gcd_sky130hd.sdcread_spef gcd_sky130hd.spefset_power_activity -input -activity 0.1set_power_activity -input_port reset -activity 0report_power + In this example the activity for all inputs is set to 0.1, and then the activity for the reset signal is set to zero because it does not switch during steady state operation. + Group Internal Switching Leakage Total Power Power Power Power (Watts)----------------------------------------------------------------Sequential 3.27e-04 7.87e-05 2.96e-10 4.06e-04 36.4%Combinational 2.34e-04 3.10e-04 6.95e-10 5.43e-04 48.7%Clock 4.68e-05 1.20e-04 2.30e-11 1.67e-04 15.0%Macro 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%Pad 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%----------------------------------------------------------------Total 6.07e-04 5.09e-04 1.01e-09 1.12e-03 100.0% 54.4% 45.6% 0.0% + This example can be found in examples/power.tcl. + Gate level simulation results can be used to get a more accurate power estimate. For example, the Icarus verilog simulator can be used to run the the test bench examples/gcd_tb.v for the gcd design in the previous example. iverilog -o gcd_tb gcd_tb.vvvp gcd_tb - The test bench writes the VCD (Value Change Data) file gcd_sky130hd.vcd which can then be read with the read_vcd command. - read_liberty sky130hd_tt.libread_verilog gcd_sky130hd.vlink_design gcdread_sdc gcd_sky130hd.sdcread_spef gcd_sky130hd.spefread_vcd -scope gcd_tb/gcd1 gcd_sky130hd.vcd.gzreport_power - This example can be found in examples/power_vcd.tcl. - Note that in this simple example design simulation based activities does not significantly change the results. - TCL Interpreter + The test bench writes the VCD (Value Change Data) file gcd_sky130hd.vcd which can then be read with the read_vcd command. + read_liberty sky130hd_tt.libread_verilog gcd_sky130hd.vlink_design gcdread_sdc gcd_sky130hd.sdcread_spef gcd_sky130hd.spefread_vcd -scope gcd_tb/gcd1 gcd_sky130hd.vcd.gzreport_power + This example can be found in examples/power_vcd.tcl. + Note that in this simple example design simulation based activities does not significantly change the results. + TCL Interpreter Keyword arguments to commands may be abbreviated. For example, report_checks -unique is equivalent to the following command. - report_checks -unique_paths_to_endpoint - The help command lists matching commands and their arguments. - > help report*report_annotated_check [-setup] [-hold] [-recovery] [-removal] [-nochange] [-width] [-period] [-max_skew] [-max_lines liness] [-list_annotated]group_path_count [-list_not_annotated] [-constant_arcs]report_annotated_delay [-cell] [-net] [-from_in_ports] [-to_out_ports] [-max_lines liness] [-list_annotated] [-list_not_annotated] [-constant_arcs]report_arrival pinreport_check_types [-violators] [-verbose] [-scene scene] [-format slack_only|end] [-max_delay] [-min_delay] [-recovery] [-removal] [-clock_gating_setup] [-clock_gating_hold] [-max_slew] [-min_slew] [-max_fanout] [-min_fanout] [-max_capacitance] [-min_capacitance [-min_pulse_width] [-min_period] [-max_skew] [-net net] [-digits digits [-no_line_splits] [> filename] [>> filename]report_checks [-from from_list|-rise_from from_list|-fall_from from_list] [-through through_list|-rise_through through_list|-fall_through through_list] [-to to_list|-rise_to to_list|-fall_to to_list] [-unconstrained] [-path_delay min|min_rise|min_fall|max|max_rise|max_fall|min_max] [-scene scene] [-group_path_count path_count] [-endpoint_path_count path_count] [-unique_paths_to_endpoint] [-slack_max slack_max] [-slack_min slack_min] [-sort_by_slack] [-path_group group_name] [-format full|full_clock|full_clock_expanded|short|end|summary]... - Many reporting commands support redirection of the output to a file much like a Unix shell. - report_checks -to out1 > path.logreport_checks -to out2 >> path.log - Debugging Timing - Here are some guidelines for debugging your design if static timing does not report any paths, or does not report the expected paths. - Debugging timing problems generally involves using the following commands to follow the propagation of arrival times from a known arrival downstream to understand why the arrival times are not propagating: - report_edgesreport_arrivalsreport_net - report_edges -from can be used to walk forward and report_edges -to to walk backward in the netlist/timing graph. report_arrivals shows the min/max rise/fall arrival times with respect to each clock that has a path to the pin. report_net shows connections to a net across hierarchy levels. + report_checks -unique_paths_to_endpoint + The help command lists matching commands and their arguments. + > help report*report_annotated_check [-setup] [-hold] [-recovery] [-removal] [-nochange] [-width] [-period] [-max_skew] [-max_lines liness] [-list_annotated]group_path_count [-list_not_annotated] [-constant_arcs]report_annotated_delay [-cell] [-net] [-from_in_ports] [-to_out_ports] [-max_lines liness] [-list_annotated] [-list_not_annotated] [-constant_arcs]report_arrival pinreport_check_types [-violators] [-verbose] [-scene scene] [-format slack_only|end] [-max_delay] [-min_delay] [-recovery] [-removal] [-clock_gating_setup] [-clock_gating_hold] [-max_slew] [-min_slew] [-max_fanout] [-min_fanout] [-max_capacitance] [-min_capacitance [-min_pulse_width] [-min_period] [-max_skew] [-net net] [-digits digits [-no_line_splits] [> filename] [>> filename]report_checks [-from from_list|-rise_from from_list|-fall_from from_list] [-through through_list|-rise_through through_list|-fall_through through_list] [-to to_list|-rise_to to_list|-fall_to to_list] [-unconstrained] [-path_delay min|min_rise|min_fall|max|max_rise|max_fall|min_max] [-scene scene] [-group_path_count path_count] [-endpoint_path_count path_count] [-unique_paths_to_endpoint] [-slack_max slack_max] [-slack_min slack_min] [-sort_by_slack] [-path_group group_name] [-format full|full_clock|full_clock_expanded|short|end|summary]... + Many reporting commands support redirection of the output to a file much like a Unix shell. + report_checks -to out1 > path.logreport_checks -to out2 >> path.log + Debugging Timing + Here are some guidelines for debugging your design if static timing does not report any paths, or does not report the expected paths. + Debugging timing problems generally involves using the following commands to follow the propagation of arrival times from a known arrival downstream to understand why the arrival times are not propagating: + report_edgesreport_arrivalsreport_net + report_edges -from can be used to walk forward and report_edges -to to walk backward in the netlist/timing graph. report_arrivals shows the min/max rise/fall arrival times with respect to each clock that has a path to the pin. report_net shows connections to a net across hierarchy levels. No paths found - The report_checks command only reports paths that are constrained by timing checks or SDC commands such as set_output_delay. If the design has only combinational logic (no registers or latches), there are no timing checks, so no paths are reported. Use the -unconstrained option to report_checks to see unconstrained paths. + The report_checks command only reports paths that are constrained by timing checks or SDC commands such as set_output_delay. If the design has only combinational logic (no registers or latches), there are no timing checks, so no paths are reported. Use the -unconstrained option to report_checks to see unconstrained paths. % report_checks -unconstrained - If the design is sequential (has registers or latches) and no paths are reported, it is likely that there is a problem with the clock propagation. Check the timing at an register in the design with the report_arrivals command. - % report_arrivals r1/CP (clk ^) r 0.00:0.00 f INF:-INF (clk v) r INF:-INF f 5.00:5.00 - In this example the rising edge of the clock "clk" causes the rising arrival min:max time at 0.00, and the falling edge arrives at 5.00. Since the rising edge of the clock causes the rising edge of the register clock pin, the clock path is positive unate. - The clock path should be positive or negative unate. Something is probably wrong with the clock network if it is non-unate. A non-unate clock path will report arrivals similar to the foillowing: + If the design is sequential (has registers or latches) and no paths are reported, it is likely that there is a problem with the clock propagation. Check the timing at an register in the design with the report_arrivals command. + % report_arrivals r1/CP (clk ^) r 0.00:0.00 f INF:-INF (clk v) r INF:-INF f 5.00:5.00 + In this example the rising edge of the clock "clk" causes the rising arrival min:max time at 0.00, and the falling edge arrives at 5.00. Since the rising edge of the clock causes the rising edge of the register clock pin, the clock path is positive unate. + The clock path should be positive or negative unate. Something is probably wrong with the clock network if it is non-unate. A non-unate clock path will report arrivals similar to the foillowing: % report_arrivals r1/CP (clk ^) r 0.00:0.00 f 0.00:0.00 (clk v) r 5.00:5.00 f 5.00:5.00 - Notice that each clock edge causes both rise and fall arrivals at the register clock pin. - If there are no paths to the register clock pin, nothing is printed. Use the report_edges -to command to find the gate driving the clock pin. - % report_edges -to r1/CPi1/ZN -> CP wire ^ -> ^ 0.00:0.00 v -> v 0.00:0.00 - This shows that the gate/pin i1/ZN is driving the clock pin. The report_edges -to commond can be used to walk backward or forward through the netlist one gate/net at a time. By checking the arrivals with the report_arrival command you can determine where the path is broken. - No path reported an endpoint - In order for a timing check to be reported, there must be an arrival time at the data pin (the constrained pin) as well as the timing check clock pin. If report_checks -to a register input does not report any paths, check that the input is constrained by a timing check with report_edges -to. + Notice that each clock edge causes both rise and fall arrivals at the register clock pin. + If there are no paths to the register clock pin, nothing is printed. Use the report_edges -to command to find the gate driving the clock pin. + % report_edges -to r1/CPi1/ZN -> CP wire ^ -> ^ 0.00:0.00 v -> v 0.00:0.00 + This shows that the gate/pin i1/ZN is driving the clock pin. The report_edges -to commond can be used to walk backward or forward through the netlist one gate/net at a time. By checking the arrivals with the report_arrival command you can determine where the path is broken. + No path reported an endpoint + In order for a timing check to be reported, there must be an arrival time at the data pin (the constrained pin) as well as the timing check clock pin. If report_checks -to a register input does not report any paths, check that the input is constrained by a timing check with report_edges -to. % report_edges -to r1/DCP -> D hold ^ -> ^ -0.04:-0.04 ^ -> v -0.03:-0.03CP -> D setup ^ -> ^ 0.09:0.0 ^ -> v 0.08:0.08in1 -> D wire ^ -> ^ 0.00:0.00 v -> v 0.00:0.00 - This reports the setup and hold checks for the D pin of r1. - Next, check the arrival times at the D and CP pins of the register with report_arrivals. + This reports the setup and hold checks for the D pin of r1. + Next, check the arrival times at the D and CP pins of the register with report_arrivals. % report_arrivals r1/D (clk1 ^) r 1.00:1.00 f 1.00:1.00% report_arrivals r1/CP (clk1 ^) r 0.00:0.00 f INF:-INF (clk1 v) r INF:-INF f 5.00:5.00 - If there are no arrivals on an input port of the design, use the set_input_delay command to specify the arrival times on the port. - Commands + If there are no arrivals on an input port of the design, use the set_input_delay command to specify the arrival times on the port. + Commands - all_clocks + all_clocks - + @@ -6606,16 +6711,15 @@ - all_inputs + all_inputs - [-no_clocks] + [-no_clocks] - - -no_clocks + -no_clocks Exclude inputs defined as clock sources. @@ -6628,10 +6732,10 @@ - all_outputs + all_outputs - + @@ -6639,95 +6743,95 @@ + - all_registers + all_registers - [-clock clock_names][-cells | -data_pins | -clock_pins | -async_pins | ‑output_pins][-level_sensitive][-edge_triggered] + [-clock clock_names][-cells | -data_pins | -clock_pins | -async_pins | ‑output_pins][-level_sensitive][-edge_triggered] - -clock clock_names + -clock clock_names - A list of clock names. Only registers clocked by these clocks are returned. + A list of clock names. Only registers clocked by these clocks are returned. - -cells + -cells - Return a list of register instances. + Return a list of register instances. - -data_pins + -data_pins - Return the register data pins. + Return the register data pins. - -clock_pins + -clock_pins - Return the register clock pins. + Return the register clock pins. - -async_pins + -async_pins - Return the register set/clear pins. + Return the register set/clear pins. - -output_pins + -output_pins - Return the register output pins. + Return the register output pins. - -level_sensitive + -level_sensitive - Return level-sensitive latches. + Return level-sensitive latches. - -edge_triggered + -edge_triggered - Return edge-triggered registers. + Return edge-triggered registers. - The all_registers command returns a list of register instances or register pins in the design. Options allow the list of registers to be restricted in various ways. The -clock keyword restrcts the registers to those that are clocked by a set of clocks. The -cells option returns the list of registers or latches (the default). The -‑data_pins, -clock_pins, -async_pins and -output_pins options cause all_registers to return a list of register pins rather than instances. + The all_registers command returns a list of register instances or register pins in the design. Options allow the list of registers to be restricted in various ways. The -clock keyword restrcts the registers to those that are clocked by a set of clocks. The -cells option returns the list of registers or latches (the default). The -‑data_pins, -clock_pins, -async_pins and -output_pins options cause all_registers to return a list of register pins rather than instances. - - check_setup + check_setup - [-verbose][-unconstrained_endpoints][-multiple_clock][-no_clock][-no_input_delay][-loops][-generated_clocks][> filename][>> filename] + [-verbose][-unconstrained_endpoints][-multiple_clock][-no_clock][-no_input_delay][-loops][-generated_clocks][> filename][>> filename] - -verbose + -verbose Show offending objects rather than just error counts. @@ -6735,7 +6839,7 @@ - -unconstrained_endpoints + -unconstrained_endpoints Check path endpoints for timing constraints (timing check or set_output_delay). @@ -6743,15 +6847,16 @@ - -multiple_clock + -multiple_clock Check register/latch clock pins for multiple clocks. + - -no_clock + -no_clock Check register/latch clock pins for a clock. @@ -6759,7 +6864,7 @@ - -no_input_delay + -no_input_delay Check for inputs that do not have a set_input_delay command. @@ -6767,7 +6872,7 @@ - -loops + -loops Check for combinational logic loops. @@ -6775,28 +6880,28 @@ - -generated_clocks + -generated_clocks Check that generated clock source pins have been defined as clocks. - The check_setup command performs sanity checks on the design. Individual checks can be performed with the keywords. If no check keywords are specified all checks are performed. Checks that fail are reported as warnings. If no checks fail nothing is reported. The command returns 1 if there are no warnings for use in scripts. + The check_setup command performs sanity checks on the design. Individual checks can be performed with the keywords. If no check keywords are specified all checks are performed. Checks that fail are reported as warnings. If no checks fail nothing is reported. The command returns 1 if there are no warnings for use in scripts. - connect_pin + connect_pin - netport|pin + netport|pin - net + net A net to add connections to. @@ -6804,7 +6909,7 @@ - port + port A port to connect to net. @@ -6812,29 +6917,28 @@ - Pin + Pin A pin to connect to net. - The connect_pin command connects a port or instance pin to a net. + The connect_pin command connects a port or instance pin to a net. - - create_clock + create_clock - -period period[-name clock_name][-waveform edge_list][-add][pin_list] + -period period[-name clock_name][-waveform edge_list][-add][pin_list] - -period period + -period period The clock period. @@ -6842,7 +6946,7 @@ - -name clock_name + -name clock_name The name of the clock. @@ -6850,7 +6954,7 @@ - -waveform edge_list + -waveform edge_list A list of edge rise and fall time. @@ -6858,15 +6962,15 @@ - -add + -add - Add this clock to the clocks on pin_list. + Add this clock to the clocks on pin_list. - pin_list + pin_list A list of pins driven by the clock. @@ -6874,28 +6978,28 @@ The create_clock command defines the waveform of a clock used by the design. - If no pin_list is specified the clock is virtual. A virtual clock can be refered to by name in input arrival and departure time commands but is not attached to any pins in the design. - If no clock name is specified the name of the first pin is used as the clock name. + If no pin_list is specified the clock is virtual. A virtual clock can be refered to by name in input arrival and departure time commands but is not attached to any pins in the design. + If no clock name is specified the name of the first pin is used as the clock name. If a wavform is not specified the clock rises at zero and falls at half the clock period. The waveform is a list with time the clock rises as the first element and the time it falls as the second element. If a clock is already defined on a pin the clock is redefined using the new clock parameters. If multiple clocks drive the same pin, use the -add option to prevent the existing definition from being overwritten. The following command creates a clock with a period of 10 time units that rises at time 0 and falls at 5 time units on the pin named clk1. create_clock -period 10 clk1 The following command creates a clock with a period of 10 time units that is high at time zero, falls at time 2 and rises at time 8. The clock drives three pins named clk1, clk2, and clk3. - create_clock -period 10 -waveform {8 2} -name clk {clk1 clk2 clk3} + create_clock -period 10 -waveform {8 2} -name clk {clk1 clk2 clk3} - create_generated_clock + create_generated_clock - [-name clock_name]-source master_pin[-master_clock master_clock][-divide_by divisor][-multiply_by multiplier][-duty_cycle duty_cycle][-invert][-edges edge_list][-edge_shift shift_list][-add]pin_list + [-name clock_name]-source master_pin[-master_clock master_clock][-divide_by divisor][-multiply_by multiplier][-duty_cycle duty_cycle][-invert][-edges edge_list][-edge_shift shift_list][-add]pin_list - -name clock_name + -name clock_name The name of the generated clock. @@ -6903,39 +7007,39 @@ - -source master_pin + -source master_pin - A pin or port in the fanout of the master clock that is the source of the generated clock. + A pin or port in the fanout of the master clock that is the source of the generated clock. - -master_clock master_clock + -master_clock master_clock - Use -master_clock to specify which source clock to use when multiple clocks are present on master_pin. + Use -master_clock to specify which source clock to use when multiple clocks are present on master_pin. - -divide_by divisor + -divide_by divisor - Divide the master clock period by divisor. + Divide the master clock period by divisor. - -multiply_by multiplier + -multiply_by multiplier - Multiply the master clock period by multiplier. + Multiply the master clock period by multiplier. - -duty_cycle duty_cycle + -duty_cycle duty_cycle The percent of the period that the generated clock is high (between 0 and 100). @@ -6943,23 +7047,24 @@ - -invert + -invert Invert the master clock. + - -edges edge_list + -edges edge_list - List of master clock edges to use in the generated clock. Edges are numbered from 1. edge_list must be 3 edges long. + List of master clock edges to use in the generated clock. Edges are numbered from 1. edge_list must be 3 edges long. - -edge_shift shift_list + -edge_shift shift_list Not supported. @@ -6967,46 +7072,46 @@ - -add + -add - Add this clock to the existing clocks on pin_list. + Add this clock to the existing clocks on pin_list. - pin_list + pin_list - A list of pins driven by the generated clock. + A list of pins driven by the generated clock. The create_generated_clock command is used to generate a clock from an existing clock definition. It is used to model clock generation circuits such as clock dividers and phase locked loops. The -divide_by, -multiply_by and -edges arguments are mutually exclusive. - The -multiply_by option is used to generate a higher frequency clock from the source clock. The period of the generated clock is divided by multiplier. The clock multiplier must be a positive integer. If a duty cycle is specified the generated clock rises at zero and falls at period * duty_cycle / 100. If no duty cycle is specified the source clock edge times are divided by multiplier. + The -multiply_by option is used to generate a higher frequency clock from the source clock. The period of the generated clock is divided by multiplier. The clock multiplier must be a positive integer. If a duty cycle is specified the generated clock rises at zero and falls at period * duty_cycle / 100. If no duty cycle is specified the source clock edge times are divided by multiplier. The -divide_by option is used to generate a lower frequency clock from the source clock. The clock divisor must be a positive integer. If the clock divisor is a power of two the source clock period is multiplied by divisor, the clock rise time is the same as the source clock, and the clock fall edge is one half period later. If the clock divisor is not a power of two the source clock waveform edge times are multiplied by divisor. The -edges option forms the generated clock waveform by selecting edges from the source clock waveform. If the -invert option is specified the waveform derived above is inverted. If a clock is already defined on a pin the clock is redefined using the new clock parameters. If multiple clocks drive the same pin, use the -add option to prevent the existing definition from being overwritten. - In the example show below generates a clock named gclk1 on register output pin r1/Q by dividing it by four. + In the example show below generates a clock named gclk1 on register output pin r1/Q by dividing it by four. create_clock -period 10 -waveform {1 8} clk1create_generated_clock -name gclk1 -source clk1 -divide_by 4 r1/Q The generated clock has a period of 40, rises at time 1 and falls at time 21. In the example shown below the duty cycle is used to define the derived clock waveform. create_generated_clock -name gclk1 -source clk1 -duty_cycle 50 \ -multiply_by 2 r1/Q The generated clock has a period of 5, rises at time .5 and falls at time 3. In the example shown below the first, third and fifth source clock edges are used to define the derived clock waveform. - create_generated_clock -name gclk1 -source clk1 -edges {1 3 5} r1/Q + create_generated_clock -name gclk1 -source clk1 -edges {1 3 5} r1/Q The generated clock has a period of 20, rises at time 1 and falls at time 11. - create_voltage_area + create_voltage_area - [-name name][-coordinate coordinates][-guard_band_x guard_x][-guard_band_y guard_y]cells + [-name name][-coordinate coordinates][-guard_band_x guard_x][-guard_band_y guard_y]cells @@ -7016,90 +7121,91 @@ - current_design + current_design - [design] + [design] - + - current_instance + current_instance - [instance] + [instance] - instance + instance - Not supported. + Not supported. - + - define_scene + define_scene - -mode mode_name -liberty liberty_files|-liberty_min liberty_min_files -liberty_max liberty_max_files-spef spef_file| -spef_min spef_min_file -spef_max spef_max_file + -mode mode_name -liberty liberty_files|-liberty_min liberty_min_files -liberty_max liberty_max_files-spef spef_file| -spef_min spef_min_file -spef_max spef_max_file - mode_name + mode_name - The SDC mode to use. + The SDC mode to use. - liberty_files + liberty_files - List of Liberty files to use. + List of Liberty files to use. - spef_file + spef_file - The SPEF parasitics file to use. + The SPEF parasitics file to use. - The define_scene command defines a scene for a mode (SDC), liberty files and spef parasitics. Define scenes after reading Liberty libraries and SPEF parasitics.Liberty files are specifiec with the name of the liberty library or the filename of the liberty file. If a filename is used, it must be the same as the filename used to read the library with read_liberty.. - Use get_scenes to find defined scenes. + The define_scene command defines a scene for a mode (SDC), liberty files and spef parasitics. Define scenes after reading Liberty libraries and SPEF parasitics.Liberty files are specifiec with the name of the liberty library or the filename of the liberty file. If a filename is used, it must be the same as the filename used to read the library with read_liberty.. + Use get_scenes to find defined scenes. + - delete_clock + delete_clock - [-all] clocks + [-all] clocks - clocks + clocks - A list of clocks to remove. + A list of clocks to remove. @@ -7109,26 +7215,26 @@ - delete_from_list + delete_from_list - list objects + list objects - list + list - A list of objects. + A list of objects. - objects + objects - A list of objects to delete from list. + A list of objects to delete from list. @@ -7136,21 +7242,20 @@ - - delete_generated_clock + delete_generated_clock - [-all] clocks + [-all] clocks - clocks + clocks - A list of generated clocks to remove. + A list of generated clocks to remove. @@ -7160,18 +7265,18 @@ - delete_instance + delete_instance - instance + instance - instance + instance - Instance to delete. + Instance to delete. @@ -7181,18 +7286,18 @@ - delete_net + delete_net - net + net - net + net - Net to delete. + Net to delete. @@ -7202,23 +7307,23 @@ - disconnect_pin + disconnect_pin - netport | pin | -all + netport | pin | -all - net + net - The net to disconnect pins from. + The net to disconnect pins from. - port + port A port to connect to net. @@ -7226,18 +7331,19 @@ - pin + pin A pin to connect to net. + - -all + -all - Disconnect all pins from the net. + Disconnect all pins from the net. @@ -7247,10 +7353,10 @@ - elapsed_run_time + elapsed_run_time - + @@ -7258,99 +7364,98 @@ - - find_timing_paths + find_timing_paths - [-from from_list |-rise_from from_list |-fall_from from_list][-through through_list |-rise_through through_list |-fall_through through_list][-to to_list |-rise_to to_list |-fall_to to_list][-unconstrained][-path_delay min|min_rise|min_fall |max|max_rise|max_fall |min_max][-group_path_count path_count][-endpoint_path_count endpoint_path_count][-unique_paths_to_endpoint][-scene scene][-slack_max max_slack][-slack_min min_slack][-sort_by_slack][-path_group groups] + [-from from_list |-rise_from from_list |-fall_from from_list][-through through_list |-rise_through through_list |-fall_through through_list][-to to_list |-rise_to to_list |-fall_to to_list][-unconstrained][-path_delay min|min_rise|min_fall |max|max_rise|max_fall |min_max][-group_path_count path_count][-endpoint_path_count endpoint_path_count][-unique_paths_to_endpoint][-scene scene][-slack_max max_slack][-slack_min min_slack][-sort_by_slack][-path_group groups] - -from from_list + -from from_list - Return paths from a list of clocks, instances, ports, register clock pins, or latch data pins. + Return paths from a list of clocks, instances, ports, register clock pins, or latch data pins. - -rise_from from_list + -rise_from from_list - Return paths from the rising edge of clocks, instances, ports, register clock pins, or latch data pins. + Return paths from the rising edge of clocks, instances, ports, register clock pins, or latch data pins. - -fall_from from_list + -fall_from from_list - Return paths from the falling edge of clocks, instances, ports, register clock pins, or latch data pins. + Return paths from the falling edge of clocks, instances, ports, register clock pins, or latch data pins. - -through through_list + -through through_list - Return paths through a list of instances, pins or nets. + Return paths through a list of instances, pins or nets. - -rise_through through_list + -rise_through through_list - Return rising paths through a list of instances, pins or nets. - - - - - -fall_through through_list - - - Return falling paths through a list of instances, pins or nets. - - - - - -to to_list - - - Return paths to a list of clocks, instances, ports or pins. - - - - - -rise_to to_list - - - Return rising paths to a list of clocks, instances, ports or pins. - - - - - -fall_to to_list - - - Return falling paths to a list of clocks, instances, ports or pins. - - - - - -unconstrained - - - Report unconstrained paths also. + Return rising paths through a list of instances, pins or nets. - -path_delay min + -fall_through through_list + + + Return falling paths through a list of instances, pins or nets. + + + + + -to to_list + + + Return paths to a list of clocks, instances, ports or pins. + + + + + -rise_to to_list + + + Return rising paths to a list of clocks, instances, ports or pins. + + + + + -fall_to to_list + + + Return falling paths to a list of clocks, instances, ports or pins. + + + + + -unconstrained + + + Report unconstrained paths also. + + + + + -path_delay min Return min path (hold) checks. @@ -7358,7 +7463,7 @@ - -path_delay min_rise + -path_delay min_rise Return min path (hold) checks for rising endpoints. @@ -7366,7 +7471,7 @@ - -path_delay min_fall + -path_delay min_fall Return min path (hold) checks for falling endpoints. @@ -7374,7 +7479,7 @@ - -path_delay max + -path_delay max Return max path (setup) checks. @@ -7382,7 +7487,7 @@ - -path_delay max_rise + -path_delay max_rise Return max path (setup) checks for rising endpoints. @@ -7390,7 +7495,7 @@ - -path_delay max_fall + -path_delay max_fall Return max path (setup) checks for falling endpoints. @@ -7398,7 +7503,7 @@ - -path_delay min_max + -path_delay min_max Return max and max path (setup and hold) checks. @@ -7406,23 +7511,23 @@ - -group_path_count path_count + -group_path_count path_count - The number of paths to return in each path group. + The number of paths to return in each path group. - -endpoint_path_count endpoint_path_count + -endpoint_path_count endpoint_path_count - The number of paths to return for each endpoint. + The number of paths to return for each endpoint. - ‑unique_paths_to_endpoint + ‑unique_paths_to_endpoint Return multiple paths to an endpoint that traverse different pins without showing multiple paths with different rise/fall transitions. @@ -7430,7 +7535,7 @@ - -scene scene + -scene scene Return paths for one process corner. @@ -7438,109 +7543,108 @@ - -slack_max max_slack + -slack_max max_slack - Return paths with slack less than max_slack. + Return paths with slack less than max_slack. - -slack_min min_slack + -slack_min min_slack - Return paths with slack greater than min_slack. + Return paths with slack greater than min_slack. - -sort_by_slack + -sort_by_slack - Sort paths by slack rather than slack within path groups. + Sort paths by slack rather than slack within path groups. - -path_group groups + -path_group groups - Return paths in path groups. Paths in all groups are returned if this option is not specified. + Return paths in path groups. Paths in all groups are returned if this option is not specified. - The find_timing_paths command returns a list of path objects for scripting. Use the get_property function to access properties of the paths. + The find_timing_paths command returns a list of path objects for scripting. Use the get_property function to access properties of the paths. - - get_cells + get_cells - [-hierarchical][-hsc separator][-filter expr][-regexp][-nocase][-quiet][-of_objects objects][patterns] + [-hierarchical][-hsc separator][-filter expr][-regexp][-nocase][-quiet][-of_objects objects][patterns] - -hierarchical + -hierarchical - Searches hierarchy levels below the current instance for matches. + Searches hierarchy levels below the current instance for matches. - -hsc separator + -hsc separator - Character to use to separate hierarchical instance names in patterns. + Character to use to separate hierarchical instance names in patterns. - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - -regexp + -regexp - Use regular expression matching instead of glob pattern matching. + Use regular expression matching instead of glob pattern matching. - -nocase + -nocase - Ignore case when matching. Only valid with –regexp. + Ignore case when matching. Only valid with –regexp. - -quiet + -quiet - Do not warn if no matches are found. + Do not warn if no matches are found. - -of_objects objects + -of_objects objects - The name of a pin or net, a list of pins returned by get_pins, or a list of nets returned by get_nets. The –hierarchical option cannot be used with ‑of_objects. + The name of a pin or net, a list of pins returned by get_pins, or a list of nets returned by get_nets. The –hierarchical option cannot be used with ‑of_objects. - patterns + patterns A list of instance name patterns. @@ -7553,48 +7657,48 @@ - get_clocks + get_clocks - [-regexp][-nocase][-filter expr][-quiet]patterns + [-regexp][-nocase][-filter expr][-quiet]patterns - -regexp + -regexp - Use regular expression matching instead of glob pattern matching. + Use regular expression matching instead of glob pattern matching. - -nocase + -nocase - Ignore case when matching. Only valid with –regexp. + Ignore case when matching. Only valid with –regexp. - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - -quiet + -quiet - Do not warn if no matches are found. + Do not warn if no matches are found. - patterns + patterns A list of clock name patterns. @@ -7607,15 +7711,15 @@ - get_fanin + get_fanin - -to sink_list[-flat][-only_cells][-startpoints_only][-levels level_count][-pin_levels pin_count][-trace_arcs timing|enabled|all] + -to sink_list[-flat][-only_cells][-startpoints_only][-levels level_count][-pin_levels pin_count][-trace_arcs timing|enabled|all] - -to sink_list + -to sink_list List of pins, ports, or nets to find the fanin of. For nets, the fanin of driver pins on the nets are returned. @@ -7623,15 +7727,15 @@ - -flat + -flat - With –flat pins in the fanin at any hierarchy level are returned. Without ‑flat only pins at the same hierarchy level as the sinks are returned. + With –flat pins in the fanin at any hierarchy level are returned. Without ‑flat only pins at the same hierarchy level as the sinks are returned. - -only_cells + -only_cells Return the instances connected to the pins in the fanin. @@ -7639,7 +7743,7 @@ - -startpoints_only + -startpoints_only Only return pins that are startpoints. @@ -7647,7 +7751,7 @@ - -level level_count + -level level_count Only return pins within level_count instance traversals. @@ -7655,7 +7759,7 @@ - -pin_levels pin_count + -pin_levels pin_count Only return pins within pin_count pin traversals. @@ -7663,26 +7767,26 @@ - -trace_arcs timing + -trace_arcs timing - Only trace through timing arcs that are not disabled. + Only trace through timing arcs that are not disabled. - -trace_arcs enabled + -trace_arcs enabled - Only trace through timing arcs that are not disabled. + Only trace through timing arcs that are not disabled. - -trace_arcs all + -trace_arcs all - Trace through all arcs, including disabled ones. + Trace through all arcs, including disabled ones. @@ -7693,15 +7797,15 @@ - get_fanout + get_fanout - -from source_list[-flat][-only_cells][-endpoints_only][-levels level_count][-pin_levels pin_count][-trace_arcs timing|enabled|all] + -from source_list[-flat][-only_cells][-endpoints_only][-levels level_count][-pin_levels pin_count][-trace_arcs timing|enabled|all] - -from source_list + -from source_list List of pins, ports, or nets to find the fanout of. For nets, the fanout of load pins on the nets are returned. @@ -7709,15 +7813,15 @@ - -flat + -flat - With –flat pins in the fanin at any hierarchy level are returned. Without ‑flat only pins at the same hierarchy level as the sinks are returned. + With –flat pins in the fanin at any hierarchy level are returned. Without ‑flat only pins at the same hierarchy level as the sinks are returned. - -only_cells + -only_cells Return the instances connected to the pins in the fanout. @@ -7725,7 +7829,7 @@ - -endpoints_only + -endpoints_only Only return pins that are endpoints. @@ -7733,7 +7837,7 @@ - -level level_count + -level level_count Only return pins within level_count instance traversals. @@ -7741,7 +7845,7 @@ - -pin_levels pin_count + -pin_levels pin_count Only return pins within pin_count pin traversals. @@ -7749,26 +7853,26 @@ - -trace_arcs timing + -trace_arcs timing - Only trace through timing arcs that are not disabled. + Only trace through timing arcs that are not disabled. - -trace_arcs enabled + -trace_arcs enabled - Only trace through timing arcs that are not disabled. + Only trace through timing arcs that are not disabled. - -trace_arcs all + -trace_arcs all - Trace through all arcs, including disabled ones. + Trace through all arcs, including disabled ones. @@ -7778,85 +7882,85 @@ - get_full_name + get_full_name - object + object - object + object - A library, cell, port, instance, pin or timing arc object. + A library, cell, port, instance, pin or timing arc object. - Return the name of object. Equivalent to [get_property object full_name]. + Return the name of object. Equivalent to [get_property object full_name]. - get_lib_cells + get_lib_cells - [-of_objects objects][-hsc separator][-filter expr][-regexp][-nocase][-quiet]patterns + [-of_objects objects][-hsc separator][-filter expr][-regexp][-nocase][-quiet]patterns - -of_objects objects + -of_objects objects - A list of instance objects. + A list of instance objects. - -hsc separator + -hsc separator - Character that separates the library name and cell name in patterns. Defaults to ‘/’. + Character that separates the library name and cell name in patterns. Defaults to ‘/’. - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - -regexp + -regexp - Use regular expression matching instead of glob pattern matching. + Use regular expression matching instead of glob pattern matching. - -nocase + -nocase - Ignore case when matching. Only valid with –regexp. + Ignore case when matching. Only valid with –regexp. - -quiet + -quiet - Do not warn if no matches are found. + Do not warn if no matches are found. - patterns + patterns A list of library cell name patterns of the form library_name/cell_name. @@ -7869,64 +7973,64 @@ - get_lib_pins + get_lib_pins - [-of_objects objects][-hsc separator][-filter expr][-regexp][-nocase][-quiet]patterns + [-of_objects objects][-hsc separator][-filter expr][-regexp][-nocase][-quiet]patterns - -of_objects objects + -of_objects objects - A list of library cell objects. + A list of library cell objects. - -hsc separator + -hsc separator - Character that separates the library name, cell name and port name in pattern. Defaults to ‘/’. + Character that separates the library name, cell name and port name in pattern. Defaults to ‘/’. - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - -regexp + -regexp - Use regular expression matching instead of glob pattern matching. + Use regular expression matching instead of glob pattern matching. - -nocase + -nocase - Ignore case when matching. Only valid with –regexp. + Ignore case when matching. Only valid with –regexp. - -quiet + -quiet - Do not warn if no matches are found. + Do not warn if no matches are found. - patterns + patterns A list of library port name patterns of the form library_name/cell_name/port_name. @@ -7939,117 +8043,117 @@ - get_libs + get_libs - [-filter expr][-regexp][-nocase][-quiet]patterns + [-filter expr][-regexp][-nocase][-quiet]patterns - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - -regexp + -regexp - Use regular expression matching instead of glob pattern matching. + Use regular expression matching instead of glob pattern matching. - -nocase + -nocase - Ignore case when matching. Only valid with –regexp. + Ignore case when matching. Only valid with –regexp. - -quiet + -quiet - Do not warn if no matches are found. + Do not warn if no matches are found. - patterns + patterns A list of library name patterns. - The get_libs command returns a list of clocks that match patterns. + The get_libs command returns a list of clocks that match patterns. - get_nets + get_nets - [-hierarchical][-hsc separator][-filter expr][-regexp][-nocase][-quiet][-of_objects objects][patterns] + [-hierarchical][-hsc separator][-filter expr][-regexp][-nocase][-quiet][-of_objects objects][patterns] - -hierarchical + -hierarchical - Searches hierarchy levels below the current instance for matches. + Searches hierarchy levels below the current instance for matches. - -hsc separator + -hsc separator - Character that separates the library name, cell name and port name in pattern. Defaults to ‘/’. + Character that separates the library name, cell name and port name in pattern. Defaults to ‘/’. - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - -regexp + -regexp - Use regular expression matching instead of glob pattern matching. + Use regular expression matching instead of glob pattern matching. - -nocase + -nocase - Ignore case when matching. Only valid with –regexp. + Ignore case when matching. Only valid with –regexp. - -quiet + -quiet - Do not warn if no matches are found. + Do not warn if no matches are found. - -of_objects objects + -of_objects objects The name of a pin or instance, a list of pins returned by get_pins, or a list of instances returned by get_cells. The –hierarchical option cannot be used with –of_objects. @@ -8057,7 +8161,7 @@ - patterns + patterns A list of net name patterns. @@ -8070,15 +8174,15 @@ - get_name + get_name - object + object - object + object A library, cell, port, instance, pin or timing arc object. @@ -8092,63 +8196,63 @@ - get_pins + get_pins - [-hierarchical][-hsc separator][-filter expr][-regexp][-nocase][-quiet][-of_objects objects][patterns] + [-hierarchical][-hsc separator][-filter expr][-regexp][-nocase][-quiet][-of_objects objects][patterns] - -hierarchical + -hierarchical - Searches hierarchy levels below the current instance for matches. + Searches hierarchy levels below the current instance for matches. - -hsc separator + -hsc separator - Character that separates the library name, cell name and port name in pattern. Defaults to ‘/’. + Character that separates the library name, cell name and port name in pattern. Defaults to ‘/’. - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - -nocase + -nocase - Ignore case when matching. Only valid with –regexp. + Ignore case when matching. Only valid with –regexp. - -quiet + -quiet - Do not warn if no matches are found. + Do not warn if no matches are found. - -of_objects objects + -of_objects objects - The name of a net or instance, a list of nets returned by get_nets, or a list of instances returned by get_cells. The –hierarchical option cannot be used with –of_objects. + The name of a net or instance, a list of nets returned by get_nets, or a list of instances returned by get_cells. The –hierarchical option cannot be used with –of_objects. - patterns + patterns A list of pin name patterns. @@ -8156,63 +8260,63 @@ The get_pins command returns a list of all instance pins that match patterns. - A useful idiom to find the driver pin for a net is the following. - get_pins -of_objects [get_net net_name] -filter “direction==output” + A useful idiom to find the driver pin for a net is the following. + get_pins -of_objects [get_net net_name] -filter “direction==output” - get_ports + get_ports - [-filter expr][-regexp][-nocase][-quiet][-of_objects objects][patterns] + [-filter expr][-regexp][-nocase][-quiet][-of_objects objects][patterns] - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - -regexp + -regexp - Use regular expression matching instead of glob pattern matching. + Use regular expression matching instead of glob pattern matching. - -nocase + -nocase - Ignore case when matching. Only valid with –regexp. + Ignore case when matching. Only valid with –regexp. - -quiet + -quiet - Do not warn if no matches are found. + Do not warn if no matches are found. - -of_objects objects + -of_objects objects - The name of net or a list of nets returned by get_nets. + The name of net or a list of nets returned by get_nets. - patterns + patterns A list of port name patterns. @@ -8225,31 +8329,31 @@ - get_property + get_property - [-object_type object_type]objectproperty + [-object_type object_type]objectproperty - -object_type object_type + -object_type object_type - The type of object when it is specified as a name.cell|pin|net|port|clock|library|library_cell|library_pin|timing_arc + The type of object when it is specified as a name.cell|pin|net|port|clock|library|library_cell|library_pin|timing_arc - object + object - An object returned by get_cells, get_pins, get_nets, get_ports, get_clocks, get_libs, get_lib_cells, get_lib_pins, or get_timing_arcs, or object name. ‑object_type is required if object is a name. + An object returned by get_cells, get_pins, get_nets, get_ports, get_clocks, get_libs, get_lib_cells, get_lib_pins, or get_timing_arcs, or object name. ‑object_type is required if object is a name. - property + property A property name. @@ -8257,120 +8361,120 @@ The properties for different objects types are shown below. - cell (SDC lib_cell) - base_namefilenamefull_namelibraryname - clock - full_nameis_generatedis_propagatedis_virtualnameperiodsources - edge - delay_max_falldelay_min_falldelay_max_risedelay_min_risefull_namefrom_pinsenseto_pin - instance (SDC cell) - cellfull_nameis_bufferis_clock_gateis_hierarchicalis_inverteris_macrois_memoryliberty_cellnameref_name - liberty_cell (SDC lib_cell) - areabase_namedont_usefilenamefull_nameis_bufferis_inverteris_memorylibraryname - liberty_port (SDC lib_pin) - capacitancedirectiondrive_resistancedrive_resistance_max_falldrive_resistance_max_risedrive_resistance_min_falldrive_resistance_min_risefull_nameintrinsic_delayintrinsic_delay_max_fallintrinsic_delay_max_riseintrinsic_delay_min_fallintrinsic_delay_min_riseis_register_clocklib_cellname - library - filename (Liberty library only)namefull_name - net - full_namename - path (PathEnd) + cell (SDC lib_cell) + base_namefilenamefull_namelibraryname + clock + full_nameis_generatedis_propagatedis_virtualnameperiodsources + edge + delay_max_falldelay_min_falldelay_max_risedelay_min_risefull_namefrom_pinsenseto_pin + instance (SDC cell) + cellfull_nameis_bufferis_clock_gateis_hierarchicalis_inverteris_macrois_memoryliberty_cellnameref_name + liberty_cell (SDC lib_cell) + areabase_namedont_usefilenamefull_nameis_bufferis_inverteris_memorylibraryname + liberty_port (SDC lib_pin) + capacitancedirectiondrive_resistancedrive_resistance_max_falldrive_resistance_max_risedrive_resistance_min_falldrive_resistance_min_risefull_nameintrinsic_delayintrinsic_delay_max_fallintrinsic_delay_max_riseintrinsic_delay_min_fallintrinsic_delay_min_riseis_register_clocklib_cellname + library + filename (Liberty library only)namefull_name + net + full_namename + path (PathEnd) endpointendpoint_clockendpoint_clock_pinslackstartpointstartpoint_clockpoints - pin - activity (activity in transitions per second, duty cycle, origin)origin is one ofglobalset_power_activity -globalinputset_power_activity -inputuserset_power_activity -input_ports -pinsvcdread_vcdsaifread_saifpropagatedpropagated from upstream activitiesclockSDC create_clock or create_generated_clockconstantconstant pins propagated from verilog tie high/low, set_case_analysis, set_logic_one/zero/dc - slew_max_fallslew_max_riseslew_min_fallslew_min_riseclocksclock_domainsdirectionfull_nameis_hierarchicalis_portis_register_clocklib_pin_namenameslack_maxslack_max_fallslack_max_riseslack_minslack_min_fallslack_min_rise - port - activityslew_max_fallslew_max_riseslew_min_fallslew_min_risedirectionfull_nameliberty_portnameslack_maxslack_max_fallslack_max_riseslack_minslack_min_fallslack_min_rise - point (PathRef) - arrivalpinrequiredslack + pin + activity (activity in transitions per second, duty cycle, origin)origin is one ofglobalset_power_activity -globalinputset_power_activity -inputuserset_power_activity -input_ports -pinsvcdread_vcdsaifread_saifpropagatedpropagated from upstream activitiesclockSDC create_clock or create_generated_clockconstantconstant pins propagated from verilog tie high/low, set_case_analysis, set_logic_one/zero/dc + slew_max_fallslew_max_riseslew_min_fallslew_min_riseclocksclock_domainsdirectionfull_nameis_hierarchicalis_portis_register_clocklib_pin_namenameslack_maxslack_max_fallslack_max_riseslack_minslack_min_fallslack_min_rise + port + activityslew_max_fallslew_max_riseslew_min_fallslew_min_risedirectionfull_nameliberty_portnameslack_maxslack_max_fallslack_max_riseslack_minslack_min_fallslack_min_rise + point (PathRef) + arrivalpinrequiredslack - get_scenes + get_scenes - [-mode mode_name]scene_name + [-mode mode_name]scene_name - mode_name + mode_name - Get the scenes for mode_name. + Get the scenes for mode_name. - scene_name + scene_name - A scene name pattern. + A scene name pattern. - The get_scenes command is used to find the scenes matching a pattern or that use an SDC mode. + The get_scenes command is used to find the scenes matching a pattern or that use an SDC mode. - get_timing_edges + get_timing_edges - [-from from_pins][-to to_pins][-of_objects objects][-filter expr][patterns] + [-from from_pins][-to to_pins][-of_objects objects][-filter expr][patterns] - -from from_pin + -from from_pin - A list of pins. + A list of pins. - -to to_pin + -to to_pin - A list of pins. + A list of pins. - -of_objects objects + -of_objects objects - A list of instances or library cells. The –from and -to options cannot be used with –of_objects. + A list of instances or library cells. The –from and -to options cannot be used with –of_objects. - -filter expr + -filter expr - A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. + A filter expression of the form property==value”where property is a property supported by the get_property command. See the section “Filter Expressions” for additional forms. - The get_timing_edges command returns a list of timing edges (arcs) to, from or between pins. The result can be passed to get_property or set_disable_timing. + The get_timing_edges command returns a list of timing edges (arcs) to, from or between pins. The result can be passed to get_property or set_disable_timing. - group_path + group_path - -name group_name[-weight weight][-critical_range range][-from from_list |-rise_from from_list |-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list |-rise_to to_list |-fall_to to_list][-default] + -name group_name[-weight weight][-critical_range range][-from from_list |-rise_from from_list |-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list |-rise_to to_list |-fall_to to_list][-default] - -name group_name + -name group_name The name of the path group. @@ -8378,7 +8482,7 @@ - -weight weight + -weight weight Not supported. @@ -8386,7 +8490,7 @@ - -critical_range range + -critical_range range Not supported. @@ -8394,82 +8498,82 @@ - -from from_list + -from from_list - Group paths from a list of clocks, instances, ports, register clock pins, or latch data pins. + Group paths from a list of clocks, instances, ports, register clock pins, or latch data pins. - -rise_from from_list + -rise_from from_list - Group paths from the rising edge of clocks, instances, ports, register clock pins, or latch data pins. + Group paths from the rising edge of clocks, instances, ports, register clock pins, or latch data pins. - -fall_from from_list + -fall_from from_list - Group paths from the falling edge of clocks, instances, ports, register clock pins, or latch data pins. + Group paths from the falling edge of clocks, instances, ports, register clock pins, or latch data pins. - -through through_list + -through through_list - Group paths through a list of instances, pins or nets. + Group paths through a list of instances, pins or nets. - -rise_through through_list + -rise_through through_list - Group rising paths through a list of instances, pins or nets. + Group rising paths through a list of instances, pins or nets. - -fall_through through_list + -fall_through through_list - Group falling paths through a list of instances, pins or nets. + Group falling paths through a list of instances, pins or nets. - -to to_list + -to to_list - Group paths to a list of clocks, instances, ports or pins. + Group paths to a list of clocks, instances, ports or pins. - -rise_to to_list + -rise_to to_list - Group rising paths to a list of clocks, instances, ports or pins. + Group rising paths to a list of clocks, instances, ports or pins. - -fall_to to_list + -fall_to to_list - Group falling paths to a list of clocks, instances, port-s or pins. + Group falling paths to a list of clocks, instances, port-s or pins. - -default + -default - Restore the paths in the path group -from/-to/-through/-to to their default path group. + Restore the paths in the path group -from/-to/-through/-to to their default path group. @@ -8479,84 +8583,84 @@ - include + include - [-echo|-e][-verbose|-v]filename[> log_filename][>> log_filename] + [-echo|-e][-verbose|-v]filename[> log_filename][>> log_filename] - -echo|-e + -echo|-e - Print each command before evaluating it. + Print each command before evaluating it. - -verbose|-v + -verbose|-v - Print each command before evaluating it as well as the result it returns. + Print each command before evaluating it as well as the result it returns. - filename + filename - The name of the file containing commands to read. + The name of the file containing commands to read. - > log_filename + > log_filename - Redirect command output to log_filename. + Redirect command output to log_filename. - >> log_filename + >> log_filename - Redirect command output and append log_filename. + Redirect command output and append log_filename. - Read STA/SDC/Tcl commands from filename. - The include command stops and reports any errors encountered while reading a file unless sta_continue_on_error is 1. + Read STA/SDC/Tcl commands from filename. + The include command stops and reports any errors encountered while reading a file unless sta_continue_on_error is 1. - link_design + link_design - [-no_black_boxes][cell_name] + [-no_black_boxes][cell_name] - -no_black_boxes + -no_black_boxes - Do not make empty “black box” cells for instances that reference undefined cells. + Do not make empty “black box” cells for instances that reference undefined cells. - cell_name + cell_name - The top level module/cell name of the design hierarchy to link. + The top level module/cell name of the design hierarchy to link. - Link (elaborate, flatten) the the top level cell cell_name. The design must be linked after reading netlist and library files. The default value of cell_name is the current design. + Link (elaborate, flatten) the the top level cell cell_name. The design must be linked after reading netlist and library files. The default value of cell_name is the current design. The linker creates empty "block box" cells for instances the reference undefined cells when the variable link_create_black_boxes is true. When link_create_black_boxes is false an error is reported and the link fails. The link_design command returns 1 if the link succeeds and 0 if it fails. @@ -8564,15 +8668,15 @@ - make_instance + make_instance - inst_pathlib_cell + inst_pathlib_cell - inst_path + inst_path A hierarchical instance name. @@ -8581,28 +8685,28 @@ - lib_cell + lib_cell The library cell of the new instance. - The make_instance command makes an instance of library cell lib_cell. + The make_instance command makes an instance of library cell lib_cell. - make_net + make_net - net_name_list + net_name_list - net_name_list + net_name_list A list of net names. @@ -8615,47 +8719,47 @@ - read_liberty + read_liberty - [-corner corner][-min][-max][-infer_latches]filename + [-corner corner][-min][-max][-infer_latches]filename - -corner corner + -corner corner - Use the library for process corner corner delay calculation. + Use the library for process corner corner delay calculation. - -min + -min - Use library for min delay calculation. + Use library for min delay calculation. - -max + -max - Use library for max delay calculation. + Use library for max delay calculation. - filename + filename - The liberty file name to read. + The liberty file name to read. The read_liberty command reads a Liberty format library file. The first library that is read sets the units used by SDC/TCL commands and reporting. The include_file attribute is supported. - Some Liberty libraries do not include latch groups for cells that are describe transparent latches. In that situation the -infer_latches command flag can be used to infer the latches. The timing arcs required for a latch to be inferred should look like the following: + Some Liberty libraries do not include latch groups for cells that are describe transparent latches. In that situation the -infer_latches command flag can be used to infer the latches. The timing arcs required for a latch to be inferred should look like the following: cell (infered_latch) { pin(D) { direction : input ; timing () { related_pin : "E" ; timing_type : setup_falling ; } timing () { related_pin : "E" ; timing_type : hold_falling ; } } pin(E) { direction : input; } pin(Q) { direction : output ; timing () { related_pin : "D" ; } timing () { related_pin : "E" ; timing_type : rising_edge ; } }} In this example a positive level-sensitive latch is inferred. Files compressed with gzip are automatically uncompressed. @@ -8664,69 +8768,69 @@ - read_saif + read_saif - [-scope scope]filename + [-scope scope]filename - scope + scope - The SAIF scope of the current design to extract simulation data. Typically the test bench name and design under test instance name. Scope levels are separated with ‘/’. + The SAIF scope of the current design to extract simulation data. Typically the test bench name and design under test instance name. Scope levels are separated with ‘/’. - filename + filename - The name of the SAIF file to read. + The name of the SAIF file to read. - The read_saif command reads a SAIF (Switching Activity Interchange Format) file from a Verilog simulation and extracts pin activities and duty cycles for use in power estimation. Files compressed with gzip are supported. Annotated activities are propagated to the fanout of the annotated pins. + The read_saif command reads a SAIF (Switching Activity Interchange Format) file from a Verilog simulation and extracts pin activities and duty cycles for use in power estimation. Files compressed with gzip are supported. Annotated activities are propagated to the fanout of the annotated pins. - read_sdc + read_sdc - [-mode mode_name][-echo]filename + [-mode mode_name][-echo]filename - mode_name + mode_name - Mode for the SDC commands in the file. + Mode for the SDC commands in the file. - -echo + -echo - Print each command before evaluating it. + Print each command before evaluating it. - filename + filename - SDC command file. + SDC command file. - Read SDC commands from filename. - If the mode does not exist it is created. Multiple SDC files can append commands to a mode by using the -mode_name argument for each one. If no -mode arguement is is used the commands are added to the current mode. + Read SDC commands from filename. + If the mode does not exist it is created. Multiple SDC files can append commands to a mode by using the -mode_name argument for each one. If no -mode arguement is is used the commands are added to the current mode. The read_sdc command stops and reports any errors encountered while reading a file unless sta_continue_on_error is 1. Files compressed with gzip are automatically uncompressed. @@ -8734,23 +8838,23 @@ - read_sdf + read_sdf - [-scene scene][-unescaped_dividers]filename + [-scene scene][-unescaped_dividers]filename - scene + scene - Scene delays to annotate. + Scene delays to annotate. - -unescaped_dividers + -unescaped_dividers With this option path names in the SDF do not have to escape hierarchy dividers when the path name is escaped. For example, the escaped Verilog name "\inst1/inst2 " can be referenced as "inst1/inst2". The correct SDF name is "inst1\/inst2", since the divider does not represent a change in hierarchy in this case. @@ -8758,138 +8862,138 @@ - filename + filename - The name of the SDF file to read. + The name of the SDF file to read. - Read SDF delays from a file. The min and max values in the SDF tuples are used to annotate the delays for corner. The typical values in the SDF tuples are ignored. If multiple scenes are defined -scene must be specified. SDC annotation for mcmm analysis must follow the scene definitions. + Read SDF delays from a file. The min and max values in the SDF tuples are used to annotate the delays for corner. The typical values in the SDF tuples are ignored. If multiple scenes are defined -scene must be specified. SDC annotation for mcmm analysis must follow the scene definitions. Files compressed with gzip are automatically uncompressed. INCREMENT is supported as an alias for INCREMENTAL. - The following SDF statements are not supported. + The following SDF statements are not supported. PORTINSTANCE wildcards - read_spef + read_spef - [-name name][-keep_capacitive_coupling][-coupling_reduction_factor factor][-reduce][-path path]filename + [-name name][-keep_capacitive_coupling][-coupling_reduction_factor factor][-reduce][-path path]filename - name + name - The name of the SPEF parasitics to use for defining scenes. The default is the base name of filename. + The name of the SPEF parasitics to use for defining scenes. The default is the base name of filename. - path + path - Hierarchical block instance path to annotate with parasitics. + Hierarchical block instance path to annotate with parasitics. - ‑keep_capacitive_coupling + ‑keep_capacitive_coupling - Keep coupling capacitors in parasitic networks rather than converting them to grounded capacitors. + Keep coupling capacitors in parasitic networks rather than converting them to grounded capacitors. - ‑coupling_reduction_factorfactor + ‑coupling_reduction_factorfactor - Factor to multiply coupling capacitance by when reducing parasitic networks. The default value is 1.0. + Factor to multiply coupling capacitance by when reducing parasitic networks. The default value is 1.0. - filename + filename - The name of the parasitics file to read. + The name of the parasitics file to read. - The read_spef command reads a file of net parasitics in SPEF format. Use the report_parasitic_annotation command to check for nets that are not annotated. + The read_spef command reads a file of net parasitics in SPEF format. Use the report_parasitic_annotation command to check for nets that are not annotated. Files compressed with gzip are automatically uncompressed. - Separate min/max parasitics can be annotated for each scene mode/corner. - read_spef -name min spef1read_spef -name max spef2define_scene -mode mode1 -spef_min min -spef_max max - Coupling capacitors are multiplied by the –coupling_reduction_factor when a parasitic network is reduced. + Separate min/max parasitics can be annotated for each scene mode/corner. + read_spef -name min spef1read_spef -name max spef2define_scene -mode mode1 -spef_min min -spef_max max + Coupling capacitors are multiplied by the –coupling_reduction_factor when a parasitic network is reduced. The following SPEF constructs are ignored. *DESIGN_FLOW (all values are ignored)*S slews*D driving cell*I pin capacitances (library cell capacitances are used instead)*Q r_net load poles*K r_net load residues - If the SPEF file contains triplet values the first value is used. - Parasitic networks (DSPEF) can be annotated on hierarchical blocks using the -path argument to specify the instance path to the block. Parasitic networks in the higher level netlist are stitched together at the hierarchical pins of the blocks. + If the SPEF file contains triplet values the first value is used. + Parasitic networks (DSPEF) can be annotated on hierarchical blocks using the -path argument to specify the instance path to the block. Parasitic networks in the higher level netlist are stitched together at the hierarchical pins of the blocks. - read_vcd + read_vcd - [-scope scope][-mode mode_name]filename + [-scope scope][-mode mode_name]filename - scope + scope - The VCD scope of the current design to extract simulation data. Typically the test bench name and design under test instance name. Scope levels are separated with ‘/’. + The VCD scope of the current design to extract simulation data. Typically the test bench name and design under test instance name. Scope levels are separated with ‘/’. - mode_name + mode_name - Mode to annotate activities. + Mode to annotate activities. - filename + filename - The name of the VCD file to read. + The name of the VCD file to read. - The read_vcd command reads a VCD (Value Change Dump) file from a Verilog simulation and extracts pin activities and duty cycles for use in power estimation. Files compressed with gzip are supported. Annotated activities are propagated to the fanout of the annotated pins. + The read_vcd command reads a VCD (Value Change Dump) file from a Verilog simulation and extracts pin activities and duty cycles for use in power estimation. Files compressed with gzip are supported. Annotated activities are propagated to the fanout of the annotated pins. - read_verilog + read_verilog - filename + filename - filename + filename - The name of the verilog file to read. + The name of the verilog file to read. - The read_verilog command reads a gate level verilog netlist. After all verilog netlist and Liberty libraries are read the design must be linked with the link_design command. - Verilog 2001 module port declaratations are supported. An example is shown below. + The read_verilog command reads a gate level verilog netlist. After all verilog netlist and Liberty libraries are read the design must be linked with the link_design command. + Verilog 2001 module port declaratations are supported. An example is shown below. module top (input in1, in2, clk1, clk2, clk3, output out); Files compressed with gzip are automatically uncompressed. @@ -8897,707 +9001,715 @@ - replace_cell + replace_cell - instance_listreplacement_cell + instance_listreplacement_cell - instance_list + instance_list - A list of instances to swap the cell. + A list of instances to swap the cell. - replacement_cell + replacement_cell - The replacement lib cell. + The replacement lib cell. - The replace_cell command changes the cell of an instance. The replacement cell must have the same port list (number, name, and order) as the instance's existing cell for the replacement to be successful. + The replace_cell command changes the cell of an instance. The replacement cell must have the same port list (number, name, and order) as the instance's existing cell for the replacement to be successful. - replace_activity_annotation + replace_activity_annotation - [-report_unannotated][-report_annotated] + [-report_unannotated][-report_annotated] - -report_unannotated + -report_unannotated - Report unannotated pins. + Report unannotated pins. - -report_unannotated + -report_unannotated - Report annotated pins. + Report annotated pins. - Report a summary of pins that are annotated by read_vcd, read_saif or set_power_activity. Sequential internal pins and hierarchical pins are ignored. + Report a summary of pins that are annotated by read_vcd, read_saif or set_power_activity. Sequential internal pins and hierarchical pins are ignored. - report_annotated_check + report_annotated_check - [-setup][-hold][-recovery][-removal][-nochange][-width][-period][-max_skew][-max_line lines][-report_annotated][-report_unannotated][-constant_arcs] + [-setup][-hold][-recovery][-removal][-nochange][-width][-period][-max_skew][-max_line lines][-report_annotated][-report_unannotated][-constant_arcs] - -setup + -setup - Report annotated setup checks. + Report annotated setup checks. - -hold + -hold - Report annotated hold checks. + Report annotated hold checks. - -recovery + -recovery - Report annotated recovery checks. + Report annotated recovery checks. - -removal + -removal - Report annotated removal checks. + Report annotated removal checks. - -nochange + -nochange - Report annotated nochange checks. + Report annotated nochange checks. - -width + -width - Report annotated width checks. + Report annotated width checks. - -period + -period - Report annotated period checks. + Report annotated period checks. - -max_skew + -max_skew - Report annotated max skew checks. + Report annotated max skew checks. - -max_line lines + -max_line lines - Maximum number of lines listed by the report_annotated and ‑report_unannotated options. + Maximum number of lines listed by the report_annotated and ‑report_unannotated options. - -report_annotated + -report_annotated - Report annotated timing arcs. + Report annotated timing arcs. - -report_unannotated + -report_unannotated - Report unannotated timing arcs. + Report unannotated timing arcs. - -constant_arcs + -constant_arcs - Report separate annotation counts for arcs disabled by logic constants (set_logic_one, set_logic_zero). + Report separate annotation counts for arcs disabled by logic constants (set_logic_one, set_logic_zero). - The report_annotated_check command reports a summary of SDF timing check annotation. The -report_annotated and report_annotated options can be used to list arcs that are annotated or not annotated. + The report_annotated_check command reports a summary of SDF timing check annotation. The -report_annotated and report_annotated options can be used to list arcs that are annotated or not annotated. - report_annotated_delay + report_annotated_delay - [-cell][-net][-from_in_ports][-to_out_ports][-max_lines lines][-report_annotated][-report_unannotated][-constant_arcs] + [-cell][-net][-from_in_ports][-to_out_ports][-max_lines lines][-report_annotated][-report_unannotated][-constant_arcs] - -cell + -cell - Report annotated cell delays. + Report annotated cell delays. - -net + -net - Report annotated internal net delays. + Report annotated internal net delays. - -from_in_ports + -from_in_ports - Report annotated delays from input ports. + Report annotated delays from input ports. - -to_out_ports + -to_out_ports - Report annotated delays to output ports. + Report annotated delays to output ports. - -max_lines lines + -max_lines lines - Maximum number of lines listed by the report_annotated and ‑report_unannotated options. + Maximum number of lines listed by the report_annotated and ‑report_unannotated options. - -report_annotated + -report_annotated - Report annotated timing arcs. + Report annotated timing arcs. - -report_unannotated + -report_unannotated - Report unannotated timing arcs. + Report unannotated timing arcs. - -constant_arcs + -constant_arcs Report separate annotation counts for arcs disabled by logic constants (set_logic_one, set_logic_zero). - The report_annotated_delay command reports a summary of SDF delay annotation. Without the ‑from_in_ports and –to_out_ports options arcs to and from top level ports are not reported. The ‑report_annotated and report_unannotated options can be used to list arcs that are annotated or not annotated. + The report_annotated_delay command reports a summary of SDF delay annotation. Without the ‑from_in_ports and –to_out_ports options arcs to and from top level ports are not reported. The ‑report_annotated and report_unannotated options can be used to list arcs that are annotated or not annotated. - report_checks + report_checks - [-from from_list |-rise_from from_list |-fall_from from_list][-through through_list |-rise_through through_list |-fall_through through_list][-to to_list |-rise_to to_list |-fall_to to_list][-unconstrained][-path_delay min|min_rise|min_fall |max|max_rise|max_fall |min_max][-group_path_count path_count][-endpoint_path_count endpoint_path_count][-unique_paths_to_endpoint][-unique_edges_to_endpoint][-scenes scenes][-slack_max max_slack][-slack_min min_slack][-sort_by_slack][-path_group groups][-format end|full|short|summary |full_clock|full_clock_expanded |json][-fields fields][-digits digits][-no_line_split][> filename][>> filename] + [-from from_list |-rise_from from_list |-fall_from from_list][-through through_list |-rise_through through_list |-fall_through through_list][-to to_list |-rise_to to_list |-fall_to to_list][-unconstrained][-path_delay min|min_rise|min_fall |max|max_rise|max_fall |min_max][-group_path_count path_count][-endpoint_path_count endpoint_path_count][-unique_paths_to_endpoint][-unique_edges_to_endpoint][-scenes scenes][-slack_max max_slack][-slack_min min_slack][-sort_by_slack][-path_group groups][-format end|full|short|summary |full_clock|full_clock_expanded |json][-fields fields][-digits digits][-no_line_split][> filename][>> filename] - -from from_list + -from from_list - Report paths from a list of clocks, instances, ports, register clock pins, or latch data pins. + Report paths from a list of clocks, instances, ports, register clock pins, or latch data pins. - -rise_from from_list + -rise_from from_list - Report paths from the rising edge of clocks, instances, ports, register clock pins, or latch data pins. + Report paths from the rising edge of clocks, instances, ports, register clock pins, or latch data pins. - -fall_from from_list + -fall_from from_list - Report paths from the falling edge of clocks, instances, ports, register clock pins, or latch data pins. + Report paths from the falling edge of clocks, instances, ports, register clock pins, or latch data pins. - -through through_list + -through through_list - Report paths through a list of instances, pins or nets. + Report paths through a list of instances, pins or nets. - -rise_through through_list + -rise_through through_list - Report rising paths through a list of instances, pins or nets. + Report rising paths through a list of instances, pins or nets. - -fall_through through_list + -fall_through through_list - Report falling paths through a list of instances, pins or nets. + Report falling paths through a list of instances, pins or nets. - -to to_list + -to to_list - Report paths to a list of clocks, instances, ports or pins. + Report paths to a list of clocks, instances, ports or pins. - -rise_to to_list + -rise_to to_list - Report rising paths to a list of clocks, instances, ports or pins. + Report rising paths to a list of clocks, instances, ports or pins. - -fall_to to_list + -fall_to to_list - Report falling paths to a list of clocks, instances, ports or pins. + Report falling paths to a list of clocks, instances, ports or pins. - -unconstrained + -unconstrained - Report unconstrained paths also. The unconstrained path group is not reported without this option. + Report unconstrained paths also. The unconstrained path group is not reported without this option. - -path_delay min + -path_delay min - Report min path (hold) checks. + Report min path (hold) checks. - -path_delay min_rise + -path_delay min_rise - Report min path (hold) checks for rising endpoints. + Report min path (hold) checks for rising endpoints. - -path_delay min_fall + -path_delay min_fall - Report min path (hold) checks for falling endpoints. + Report min path (hold) checks for falling endpoints. - -path_delay max + -path_delay max - Report max path (setup) checks. + Report max path (setup) checks. - -path_delay max_rise + -path_delay max_rise - Report max path (setup) checks for rising endpoints. + Report max path (setup) checks for rising endpoints. - -path_delay max_fall + -path_delay max_fall - Report max path (setup) checks for falling endpoints. + Report max path (setup) checks for falling endpoints. - -path_delay min_max + -path_delay min_max - Report max and max path (setup and hold) checks. + Report max and max path (setup and hold) checks. - -group_path_count path_count + -group_path_count path_count - The number of paths to report in each path group. The default is 1. + The number of paths to report in each path group. The default is 1. - -endpoint_path_count endpoint_path_count + -endpoint_path_count endpoint_path_count - The number of paths to report for each endpoint. The default is 1. + The number of paths to report for each endpoint. The default is 1. - ‑unique_paths_to_endpoint + ‑unique_paths_to_endpoint - When multiple paths to an endpoint are specified with ‑endpoint_path_count, many of the paths may differ only in the rise/fall edges of the pins in the paths. With this option only the worst path through the set of pins is reported. + When multiple paths to an endpoint are specified with ‑endpoint_path_count, many of the paths may differ only in the rise/fall edges of the pins in the paths. With this option only the worst path through the set of pins is reported. - ‑unique_edges_to_endpoint + ‑unique_edges_to_endpoint - When multiple paths to an endpoint are specified with ‑endpoint_path_count, conditional timing arcs result in paths that through the same pins and rise/fall edges. With this option only the worst path through the set of pins and rise/fall edges is reported. + When multiple paths to an endpoint are specified with ‑endpoint_path_count, conditional timing arcs result in paths that through the same pins and rise/fall edges. With this option only the worst path through the set of pins and rise/fall edges is reported. - scenes + scenes - Report paths for one process corner. The default is to report paths for all process corners. + Report paths for one process corner. The default is to report paths for all process corners. - max_slack + max_slack - Only report paths with less slack than max_slack. + Only report paths with less slack than max_slack. - min_slack + min_slack - Only report paths with more slack than min_slack. + Only report paths with more slack than min_slack. - -sort_by_slack + -sort_by_slack - Sort paths by slack rather than slack grouped by path group. + Sort paths by slack rather than slack grouped by path group. - groups + groups - List of path groups to report. The default is to report all path groups. + List of path groups to report. The default is to report all path groups. - -format end + -format end - Report path ends in one line with delay, required time and slack. + Report path ends in one line with delay, required time and slack. - -format full + -format full - Report path start and end points and the path. This is the default path type. + Report path start and end points and the path. This is the default path type. - -format full_clock + -format full_clock - Report path start and end points, the path, and the source and and target clock paths. + Report path start and end points, the path, and the source and and target clock paths. - -format full_clock_expanded + -format full_clock_expanded - Report path start and end points, the path, and the source and and target clock paths. If the clock is generated and propagated, the path from the clock source pin is also reported. + Report path start and end points, the path, and the source and and target clock paths. If the clock is generated and propagated, the path from the clock source pin is also reported. - -format short + -format short - Report only path start and end points. + Report only path start and end points. - -format summary + -format summary - Report only path ends with delay. + Report only path ends with delay. - -format json + -format json - Report in json format. -fields is ignored. + Report in json format. -fields is ignored. - fields + fields - List of capacitance|slew|input_pins|hierarchical_pins|nets|fanout|src_attr + List of capacitance|slew|input_pins|hierarchical_pins|nets|fanout|src_attr|variance - digits + digits - The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. - -no_line_splits + -no_line_splits - Do not split long lines into multiple lines. + Do not split long lines into multiple lines. - The report_checks command reports paths in the design. Paths are reported in groups by capture clock, unclocked path delays, gated clocks and unconstrained. - See set_false_path for a description of allowed from_list, through_list and to_list objects. + The report_checks command reports paths in the design. Paths are reported in groups by capture clock, unclocked path delays, gated clocks and unconstrained. + See set_false_path for a description of allowed from_list, through_list and to_list objects. - report_check_types + report_check_types - [-scenes scenes][-violators][-verbose][-format slack_only|end][-max_delay][-min_delay][-recovery][-removal][-clock_gating_setup][-clock_gating_hold][-max_slew][-min_slew][-min_pulse_width][-min_period][-digits digits][-no_split_lines][> filename][>> filename] + [-scenes scenes][-violators][-verbose][-fields fields][-format slack_only|end][-max_delay][-min_delay][-recovery][-removal][-clock_gating_setup][-clock_gating_hold][-max_slew][-min_slew][-min_pulse_width][-min_period][-digits digits][-no_split_lines][> filename][>> filename] - scenes + scenes - Report checks for some scens. The default value is all scenes. + Report checks for some scenes. The default value is all scenes. - -violators + -violators - Report all violated timing and design rule constraints. + Report all violated timing and design rule constraints. - -verbose + -verbose - Use a verbose output format. + Use a verbose output format. - -format slack_only + -format slack_only - Report the minimum slack for each timing check. + Report the minimum slack for each timing check. - -format end + -format end - Report the endpoint for each check. + Report the endpoint for each check. - -max_delay + fields - Report setup and max delay path delay constraints. + List of capacitance|slew|input_pins|hierarchical_pins|nets|fanout|src_attr|variance - -min_delay + -max_delay - Report hold and min delay path delay constraints. + Report setup and max delay path delay constraints. - -recovery + -min_delay - Report asynchronous recovery checks. + Report hold and min delay path delay constraints. - -removal + -recovery - Report asynchronous removal checks. + Report asynchronous recovery checks. - -clock_gating_setup + -removal - Report gated clock enable setup checks. + Report asynchronous removal checks. - -clock_gating_hold + -clock_gating_setup - Report gated clock hold setup checks. + Report gated clock enable setup checks. - -max_slew + -clock_gating_hold - Report max transition design rule checks. + Report gated clock hold setup checks. - -max_skew + -max_slew - Report max skew design rule checks. + Report max transition design rule checks. - -min_pulse_width + -max_skew - Report min pulse width design rule checks. + Report max skew design rule checks. - -min_period + -min_pulse_width - Report min period design rule checks. + Report min pulse width design rule checks. - -min_slew + -min_period - Report min slew design rule checks. + Report min period design rule checks. - -digits digits + -min_slew - The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + Report min slew design rule checks. - -no_split_lines + -digits digits - Do not split long lines into multiple lines. + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + + + + + -no_split_lines + + + Do not split long lines into multiple lines. @@ -9607,93 +9719,92 @@ - report_clock_latency + report_clock_latency - [-clocks clocks][-scenes scenes][-include_internal_latency][-digits digits] + [-clocks clocks][-scenes scenes][-include_internal_latency][-digits digits] - clocks + clocks - The clocks to report. The default value is all c + The clocks to report. The default value is all c - scenes + scenes - Report clocks for scenes. The default value is all clocks in scenes modes. + Report clocks for scenes. The default value is all clocks in scenes modes. - -include_internal_latency + -include_internal_latency - Include internal clock latency from liberty min/max_clock_tree_path timing groups. + Include internal clock latency from liberty min/max_clock_tree_path timing groups. - digits + digits - The number of digits to report for delays. + The number of digits to report for delays. - Report the clock network latency. + Report the clock network latency. - report_clock_min_period + report_clock_min_period - [-clocks clocks][-scenes scenes][-include_port_paths] + [-clocks clocks][-scenes scenes][-include_port_paths] - clocks + clocks - The clocks to report. + The clocks to report. - -include_port_paths + -include_port_paths - Include paths from input port and to output ports. + Include paths from input port and to output ports. - Report the minimum period and maximum frequency for clocks. If the -clocks argument is not specified all clocks are reported. The minimum period is determined by examining the smallest slack paths between registers the rising edges of the clock or between falling edges of the clock. Paths between different clocks, different clock edges of the same clock, level sensitive latches, or paths constrained by set_multicycle_path, set_max_path are not considered. + Report the minimum period and maximum frequency for clocks. If the -clocks argument is not specified all clocks are reported. The minimum period is determined by examining the smallest slack paths between registers the rising edges of the clock or between falling edges of the clock. Paths between different clocks, different clock edges of the same clock, level sensitive latches, or paths constrained by set_multicycle_path, set_max_path are not considered. - - report_clock_properties + report_clock_properties - [clock_names] + [clock_names] - clock_names + clock_names - List of clock names to report. + List of clock names to report. @@ -9703,120 +9814,120 @@ - report_clock_skew + report_clock_skew - [-setup|-hold][-clocks clocks][-scenes scenes][-include_internal_latency][-digits digits] + [-setup|-hold][-clocks clocks][-scenes scenes][-include_internal_latency][-digits digits] - -setup + -setup - Report skew for setup checks. + Report skew for setup checks. - -hold + -hold - Report skew for hold checks. + Report skew for hold checks. - clocks + clocks - The clocks to report. The default value is all clocks in scenes modes. + The clocks to report. The default value is all clocks in scenes modes. - scenes + scenes - Report clocks for scenes. The default value is all scenes. + Report clocks for scenes. The default value is all scenes. - -include_internal_latency + -include_internal_latency - Include internal clock latency from liberty min/max_clock_tree_path timing groups. + Include internal clock latency from liberty min/max_clock_tree_path timing groups. - -digits digits + -digits digits - The number of digits to report for delays. + The number of digits to report for delays. - Report the maximum difference in clock arrival between every source and target register that has a path between the source and target registers. + Report the maximum difference in clock arrival between every source and target register that has a path between the source and target registers. - report_dcalc + report_dcalc - [-from from_pin][-to to_pin][-scene scene][-min][-max][-digits digits][> filename][>> filename] + [-from from_pin][-to to_pin][-scene scene][-min][-max][-digits digits][> filename][>> filename] - from_pin + from_pin - Report delay calculations for timing arcs from instance input pin from_pin. + Report delay calculations for timing arcs from instance input pin from_pin. - to_pin + to_pin - Report delay calculations for timing arcs to instance output pin to_pin. - - - - - scene - - - Report paths for process scene. The -scene keyword is required if more than one process corner is defined. + Report delay calculations for timing arcs to instance output pin to_pin. - -min + scene - Report delay calculation for min delays. + Report paths for process scene. The -scene keyword is required if more than one process corner is defined. - -max + -min - Report delay calculation for max delays. + Report delay calculation for min delays. - -digits digits + -max - The number of digits after the decimal point to report. The default is sta_report_default_digits. + Report delay calculation for max delays. + + + + + -digits digits + + + The number of digits after the decimal point to report. The default is sta_report_default_digits. @@ -9826,61 +9937,78 @@ - report_disabled_edges + report_disabled_edges - + The report_disabled_edges command reports disabled timing arcs along with the reason they are disabled. Each disabled timing arc is reported as the instance name along with the from and to ports of the arc. The disable reason is shown next. Arcs that are disabled with set_disable_timing are reported with constraint as the reason. Arcs that are disabled by constants are reported with constant as the reason along with the constant instance pin and value. Arcs that are disabled to break combinational feedback loops are reported with loop as the reason. - > report_disabled_edgesu1 A B constant B=0 + > report_disabled_edgesu1 A B constant B=0 - report_edges + report_edges - [-from from_pin][-to to_pin] + [-from from_pin][-to to_pin][-report_variation][-digits digits] - -from from_pin + from_pin - Report edges/timing arcs from pin from_pin. + Report edges/timing arcs from pin from_pin. - -to to_pin + to_pin - Report edges/timing arcs to pin to_pin. + Report edges/timing arcs to pin to_pin. + + + + + -report_variation + + + + + + + + digits + + + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. - Report the edges/timing arcs and their delays in the timing graph from/to/between pins. + Report the edges/timing arcs and their delays in the timing graph from/to/between pins. + - report_instance + report_instance - instance_path[> filename][>> filename] + instance_path[> filename][>> filename] - instance_path + instance_path - Hierarchical path to an instance. + Hierarchical path to an instance. @@ -9890,262 +10018,280 @@ - report_lib_cell + report_lib_cell - cell_name[> filename][>> filename] + cell_name[> filename][>> filename] - - cell_name + cell_name - The name of a library cell. + The name of a library cell. - Describe the liberty library cell cell_name. + Describe the liberty library cell cell_name. - report_net + report_net - [-digits digits]net_path[> filename][>> filename] + [-digits digits]net_path[> filename][>> filename] - -digits digits + digits - The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. - net_path + net_path - Hierarchical path to a net. + Hierarchical path to a net. - Report the connections and capacitance of a net. + Report the connections and capacitance of a net. - report_parasitic_annotation + report_parasitic_annotation - [-report_unannotated][> filename][>> filename] + [-report_unannotated][> filename][>> filename] - -report_unannotated + -report_unannotated - Report unannotated and partially annotated nets. + Report unannotated and partially annotated nets. - Report SPEF parasitic annotation completeness. + Report SPEF parasitic annotation completeness. - report_power + report_power - [-instances instances][-highest_power_instances count][-digits digits][> filename][>> filename] + [-instances instances][-highest_power_instances count][-digits digits][> filename][>> filename] + + + + + + -instances instances + + + Report the power for each instance of instances. If the instance is hierarchical the total power for the instances inside the hierarchical instance is reported. - -instances instances + -highest_power_instances count - Report the power for each instance of instances. If the instance is hierarchical the total power for the instances inside the hierarchical instance is reported. + Report the power for the count highest power instances. - -highest_power_instances count + -digits digits - Report the power for the count highest power instances. - - - - - -digits digits - - - The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. - The report_power command uses static power analysis based on propagated or annotated pin activities in the circuit using Liberty power models. The internal, switching, leakage and total power are reported. Design power is reported separately for combinational, sequential, macro and pad groups. Power values are reported in watts. - The read_vcd or read_saif commands can be used to read activities from a file based on simulation. If no simulation activities are available, the set_power_activity command should be used to set the activity of input ports or pins in the design. The default input activity and duty for inputs are 0.1 and 0.5 respectively. The activities are propagated from annotated input ports or pins through gates and used in the power calculations. + The report_power command uses static power analysis based on propagated or annotated pin activities in the circuit using Liberty power models. The internal, switching, leakage and total power are reported. Design power is reported separately for combinational, sequential, macro and pad groups. Power values are reported in watts. + The read_vcd or read_saif commands can be used to read activities from a file based on simulation. If no simulation activities are available, the set_power_activity command should be used to set the activity of input ports or pins in the design. The default input activity and duty for inputs are 0.1 and 0.5 respectively. The activities are propagated from annotated input ports or pins through gates and used in the power calculations. Group Internal Switching Leakage Total Power Power Power Power----------------------------------------------------------------Sequential 3.29e-06 3.41e-08 2.37e-07 3.56e-06 92.4%Combinational 1.86e-07 3.31e-08 7.51e-08 2.94e-07 7.6%Macro 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%Pad 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%---------------------------------------------------------------Total 3.48e-06 6.72e-08 3.12e-07 3.86e-06 100.0% 90.2% 1.7% 8.1% - report_slews + report_slews - [-scenes scenes]pin + [-scenes scenes][-report_variation][-digits digits]pin - scenes + scenes - Report slews for process for scenes process corners.. + Report slews for process for scenes process corners. - pin + -report_variation - + Report SSTA distribution parameters. + + + + + -digits digits + + + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + + + + + pin + + + - Report the slews at pin + Report the slews at pin + - report_tns + report_tns - [-min][-max][-digits digits] + [-min][-max][-digits digits] - -max + -max - Report the total max/setup slack. + Report the total max/setup slack. - -min + -min - Report the total min/hold slack. + Report the total min/hold slack. - -digits digits + -digits digits - The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. - Report the total negative slack. + Report the total negative slack. - report_units + report_units - + - Report the units used for command arguments and reporting. - report_units time 1ns capacitance 1pF resistance 1kohm voltage 1v current 1A power 1pW distance 1um + Report the units used for command arguments and reporting. + report_units time 1ns capacitance 1pF resistance 1kohm voltage 1v current 1A power 1pW distance 1um - report_wns + report_wns - [-min][-max][-digits digits] + [-min][-max][-digits digits] - -max + -max - Report the worst max/setup slack. + Report the worst max/setup slack. - -min + -min - Report the worst min/hold slack. + Report the worst min/hold slack. - -digits digits + -digits digits - The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. - Report the worst negative slack. If the worst slack is positive, zero is reported. + Report the worst negative slack. If the worst slack is positive, zero is reported. - report_worst_slack + report_worst_slack - [-min][-max][-digits digits] + [-min][-max][-digits digits] + + + + + + -max + + + Report the worst max/setup slack. - -max + -min - Report the worst max/setup slack. + Report the worst min/hold slack. - -min + -digits digits - Report the worst min/hold slack. - - - - - -digits digits - - - The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. + The number of digits after the decimal point to report. The default value is the variable sta_report_default_digits. @@ -10153,117 +10299,117 @@ + + + set_assigned_check + + + -setup|-hold|-recovery|-removal[-rise][-fall][-scene scene][-min][-max][-from from_pins][-to to_pins][-clock rise|fall][-cond sdf_cond][-worst]margin + + + + + -setup + + + Annotate setup timing checks. + + + + + -hold + + + Annotate hold timing checks. + + + + + -recovery + + + Annotate recovery timing checks. + + + + + -removal + + + Annotate removal timing checks. + + + + + -rise + + + Annotate rising delays. + + + + + -fall + + + Annotate falling delays. + + + + + scene + + + The name of a scene. The -scene keyword is required if more than one scene is defined. + + + + + -min + + + Annotate the minimum value of the process corner. + + + + + -max + + + Annotate the maximum value of the process corner. + + + + + from_pins + + + A list of pins for the clock. + + + + + to_pins + + + A list of pins for the data. + + - - set_assigned_check + + -clock rise|fall - - -setup|-hold|-recovery|-removal[-rise][-fall][-scene scene][-min][-max][-from from_pins][-to to_pins][-clock rise|fall][-cond sdf_cond][-worst]margin + + The timing check clock pin transition. - -setup + margin - Annotate setup timing checks. - - - - - -hold - - - Annotate hold timing checks. - - - - - -recovery - - - Annotate recovery timing checks. - - - - - -removal - - - Annotate removal timing checks. - - - - - -rise - - - Annotate rising delays. - - - - - -fall - - - Annotate falling delays. - - - - - scene - - - The name of a scene. The -scene keyword is required if more than one scene is defined. - - - - - -min - - - Annotate the minimum value of the process corner. - - - - - -max - - - Annotate the maximum value of the process corner. - - - - - from_pins - - - A list of pins for the clock. - - - - - to_pins - - - A list of pins for the data. - - - - - -clock rise|fall - - - The timing check clock pin transition. - - - - - margin - - - The timing check margin. + The timing check margin. @@ -10271,93 +10417,92 @@ - - set_assigned_delay + set_assigned_delay - -cell|-net[-rise][-fall][-scene scene][-min][-max][-from from_pins][-to to_pins]delay + -cell|-net[-rise][-fall][-scene scene][-min][-max][-from from_pins][-to to_pins]delay - -cell + -cell - Annotate the delays between two pins on an instance. + Annotate the delays between two pins on an instance. - -net + -net - Annotate the delays between two pins on a net. + Annotate the delays between two pins on a net. - -rise + -rise - Annotate the rising delays. + Annotate the rising delays. - -fall + -fall - Annotate the falling delays. + Annotate the falling delays. - scene + scene - The name of a scene. The -scene keyword is required if more than one scene is defined. + The name of a scene. The -scene keyword is required if more than one scene is defined. - -min + -min - Annotate the minimum delays. + Annotate the minimum delays. - -max + -max - Annotate the maximum delays. + Annotate the maximum delays. - from_pins + from_pins - A list of pins. + A list of pins. - to_pins + to_pins - A list of pins. + A list of pins. - delay + delay - The delay between from_pins and to_pins. + The delay between from_pins and to_pins. @@ -10365,69 +10510,69 @@ - - - set_assigned_transition - - - [-rise][-fall][-scene scene][-min][-max]slewpin_list - - - - - -rise - - - Annotate the rising transition. - - - - -fall + + set_assigned_transition - - Annotate the falling transition. + + [-rise][-fall][-scene scene][-min][-max]slewpin_list - scene + -rise - Annotate delays for scene. + Annotate the rising transition. - -min + -fall - Annotate the minimum transition time. + Annotate the falling transition. - -max + scene - Annotate the maximum transition time. + Annotate delays for scene. - slew + -min - The pin transition time. + Annotate the minimum transition time. - pin_list + -max - A list of pins. + Annotate the maximum transition time. + + + + + slew + + + The pin transition time. + + + + + pin_list + + + A list of pins. @@ -10437,89 +10582,89 @@ - set_case_analysis + set_case_analysis - 0|1|zero|one|rise|rising|fall|fallingport_or_pin_list + 0|1|zero|one|rise|rising|fall|fallingport_or_pin_list - port_or_pin_list + port_or_pin_list - A list of ports or pins. + A list of ports or pins. The set_case_analysis command sets the signal on a port or pin to a constant logic value. No paths are propagated from constant pins. Constant values set with the set_case_analysis command are propagated through downstream gates. - Conditional timing arcs with mode groups are controlled by logic values on the instance pins. + Conditional timing arcs with mode groups are controlled by logic values on the instance pins. - set_clock_gating_check + set_clock_gating_check - [-setup setup_time][-hold hold_time][-rise][-fall][-high][-low][objects] - - - - - -setup setup_time - - - Clock enable setup margin. - - - - - -hold hold_time - - - Clock enable hold margin. - - - - - -rise - - - The setup/hold margin is for the rising edge of the clock enable. - - - - - -fall - - - The setup/hold margin is for the falling edge of the clock enable. - - - - - -high - - - The gating clock is active high (pin and instance objects only). + [-setup setup_time][-hold hold_time][-rise][-fall][-high][-low][objects] - -low + -setup setup_time - The gating clock is active low (pin and instance objects only). + Clock enable setup margin. - objects + -hold hold_time - A list of clocks, instances, pins or ports. + Clock enable hold margin. + + + + + -rise + + + The setup/hold margin is for the rising edge of the clock enable. + + + + + -fall + + + The setup/hold margin is for the falling edge of the clock enable. + + + + + -high + + + The gating clock is active high (pin and instance objects only). + + + + + -low + + + The gating clock is active low (pin and instance objects only). + + + + + objects + + + A list of clocks, instances, pins or ports. @@ -10533,197 +10678,197 @@ - set_clock_groups + set_clock_groups - [-name name][-logically_exclusive][-physically_exclusive][-asynchronous][-allow_paths]-group clocks + [-name name][-logically_exclusive][-physically_exclusive][-asynchronous][-allow_paths]-group clocks - -name name + -name name - The clock group name. + The clock group name. - -logically_exclusive + -logically_exclusive - The clocks in different groups do not interact logically but can be physically present on the same chip. Paths between clock groups are considered for noise analysis. + The clocks in different groups do not interact logically but can be physically present on the same chip. Paths between clock groups are considered for noise analysis. + + + + + + -physically_exclusive + + + The clocks in different groups cannot be present at the same time on a chip. Paths between clock groups are not considered for noise analysis. - -physically_exclusive + -asynchronous - The clocks in different groups cannot be present at the same time on a chip. Paths between clock groups are not considered for noise analysis. + The clock groups are asynchronous. Paths between clock groups are considered for noise analysis. - -asynchronous + -allow_paths - The clock groups are asynchronous. Paths between clock groups are considered for noise analysis. - - - - - -allow_paths - - - + - clocks + clocks - A list of clocks in the group. + A list of clocks in the group. - The set_clock_groups command is used to define groups of clocks that interact with each other. Clocks in different groups do not interact and paths between them are not reported. Use a –group argument for each clock group. + The set_clock_groups command is used to define groups of clocks that interact with each other. Clocks in different groups do not interact and paths between them are not reported. Use a –group argument for each clock group. - set_clock_latency + set_clock_latency - [-source][-clock clock][-rise][-fall][-min][-max]delayobjects + [-source][-clock clock][-rise][-fall][-min][-max]delayobjects - -source + -source - The latency is at the clock source. + The latency is at the clock source. - -clock clock + -clock clock - If multiple clocks are defined at a pin this use this option to specify the latency for a specific clock. + If multiple clocks are defined at a pin this use this option to specify the latency for a specific clock. - -rise + -rise - The latency is for the rising edge of the clock. + The latency is for the rising edge of the clock. - -fall + -fall - The latency is for the falling edge of the clock. + The latency is for the falling edge of the clock. - -min + -min - delay is the minimum latency. + delay is the minimum latency. - -max + -max - delay is the maximum latency. + delay is the maximum latency. - delay + delay - Clock source or insertion delay. + Clock source or insertion delay. - objects + objects - A list of clocks, pins or ports. + A list of clocks, pins or ports. - The set_clock_latency command describes expected delays of the clock tree when anxsalyzing a design using ideal clocks. Use the -source option to specify latency at the clock source, also known as insertion delay. Source latency is delay in the clock tree that is external to the design or a clock tree internal to an instance that implements a complex logic function.set_clock_latency removes propagated clock properties for the clocks and pins objects. + The set_clock_latency command describes expected delays of the clock tree when anxsalyzing a design using ideal clocks. Use the -source option to specify latency at the clock source, also known as insertion delay. Source latency is delay in the clock tree that is external to the design or a clock tree internal to an instance that implements a complex logic function.set_clock_latency removes propagated clock properties for the clocks and pins objects. - set_clock_transition + set_clock_transition - [-rise][-fall][-min][-max]transitionclocks + [-rise][-fall][-min][-max]transitionclocks - -rise + -rise - Set the transition time for the rising edge of the clock. - - - - - - -fall - - - Set the transition time for the falling edge of the clock. + Set the transition time for the rising edge of the clock. - -min + -fall - Set the min transition time. + Set the transition time for the falling edge of the clock. - -max + -min - Set the min transition time. + Set the min transition time. - transition + -max - Clock transition time (slew). + Set the min transition time. - clocks + transition - A list of clocks. + Clock transition time (slew). + + + + + clocks + + + A list of clocks. @@ -10733,154 +10878,155 @@ - set_clock_uncertainty + set_clock_uncertainty - [-from|-rise_from|-fall_from from_clock][-to|-rise_to|-fall_to to_clock][-rise][-fall][-setup][-hold]uncertainty[objects] + [-from|-rise_from|-fall_from from_clock][-to|-rise_to|-fall_to to_clock][-rise][-fall][-setup][-hold]uncertainty[objects] - -from from_clock + -from from_clock - Inter-clock uncertainty source clock. + Inter-clock uncertainty source clock. - -to to_clock + -to to_clock - Inter-clock uncertainty target clock. + Inter-clock uncertainty target clock. - -rise + -rise - Inter-clock target clock rise edge, alternative to ‑rise_to.Inter-clock target clock rise edge, alternative to ‑rise_to. + Inter-clock target clock rise edge, alternative to ‑rise_to.Inter-clock target clock rise edge, alternative to ‑rise_to. - -fall + -fall - Inter-clock target clock rise edge, alternative to ‑fall_to. + Inter-clock target clock rise edge, alternative to ‑fall_to. - -setup + -setup - uncertainty is for setup checks. + uncertainty is for setup checks. + + + + + + -hold + + + uncertainty is for hold checks. - -hold + uncertainty - uncertainty is for hold checks. + Clock uncertainty. - uncertainty + objects - Clock uncertainty. - - - - - objects - - - A list of clocks, ports or pins. + A list of clocks, ports or pins. - The set_clock_uncertainty command specifies the uncertainty or jitter in a clock. The uncertainty for a clock can be specified on its source pin or port, or the clock itself. - set_clock_uncertainty .1 [get_clock clk1] - Inter-clock uncertainty between the source and target clocks of timing checks is specified with the ‑from|‑rise_from|-fall_from andto|‑rise_to|-fall_to arguments . - set_clock_uncertainty -from [get_clock clk1] -to [get_clocks clk2] .1 - The following commands are equivalent. - set_clock_uncertainty -from [get_clock clk1] -rise_to [get_clocks clk2] .1set_clock_uncertainty -from [get_clock clk1] -to [get_clocks clk2] -rise .1 + The set_clock_uncertainty command specifies the uncertainty or jitter in a clock. The uncertainty for a clock can be specified on its source pin or port, or the clock itself. + set_clock_uncertainty .1 [get_clock clk1] + Inter-clock uncertainty between the source and target clocks of timing checks is specified with the ‑from|‑rise_from|-fall_from andto|‑rise_to|-fall_to arguments . + set_clock_uncertainty -from [get_clock clk1] -to [get_clocks clk2] .1 + The following commands are equivalent. + set_clock_uncertainty -from [get_clock clk1] -rise_to [get_clocks clk2] .1set_clock_uncertainty -from [get_clock clk1] -to [get_clocks clk2] -rise .1 - set_cmd_units + set_cmd_units - [-capacitance cap_unit][-resistance res_unit][-time time_unit][-voltage voltage_unit][-current current_unit][-power power_unit][-distance distance_unit] + [-capacitance cap_unit][-resistance res_unit][-time time_unit][-voltage voltage_unit][-current current_unit][-power power_unit][-distance distance_unit] - -capacitance cap_unit + -capacitance cap_unit - The capacitance scale factor followed by 'f'. + The capacitance scale factor followed by 'f'. - -resistance res_unit + -resistance res_unit - The resistance scale factor followed by 'ohm'. + The resistance scale factor followed by 'ohm'. - -time time_unit + -time time_unit - The time scale factor followed by 's'. + The time scale factor followed by 's'. - -voltage voltage_unit + -voltage voltage_unit - The voltage scale factor followed by 'v'. + The voltage scale factor followed by 'v'. - -current current_unit + -current current_unit - The current scale factor followed by 'A'. + The current scale factor followed by 'A'. - -power power_unit + -power power_unit - The power scale factor followed by 'w'. + The power scale factor followed by 'w'. - -distance distance_unit + -distance distance_unit - The distance scale factor followed by 'm'. + The distance scale factor followed by 'm'. - The set_cmd_units command is used to change the units used by the STA command interpreter when parsing commands and reporting results. The default units are the units specified in the first Liberty library file that is read. + The set_cmd_units command is used to change the units used by the STA command interpreter when parsing commands and reporting results. The default units are the units specified in the first Liberty library file that is read. Units are specified as a scale factor followed by a unit name. The scale factors are as follows. - M 1E+6k 1E+3m 1E-3u 1E-6n 1E-9p 1E-12f 1E-15 + M 1E+6k 1E+3m 1E-3u 1E-6n 1E-9p 1E-12f 1E-15 An example of the set_units command is shown below. set_cmd_units -time ns -capacitance pF -current mA -voltage V -resistance kOhm -distance um @@ -10888,58 +11034,58 @@ - set_data_check + set_data_check - [-from|-rise_from|-fall_from from_pin][-to|-rise_to|-fall_to to_pin][-setup][-hold][-clock clock]margin + [-from|-rise_from|-fall_from from_pin][-to|-rise_to|-fall_to to_pin][-setup][-hold][-clock clock]margin - -from from_pin + -from from_pin - A pin used as the timing check reference. + A pin used as the timing check reference. - -to to_pin + -to to_pin - A pin that the setup/hold check is applied to. + A pin that the setup/hold check is applied to. - -setup + -setup - Add a setup timing check. + Add a setup timing check. - -hold + -hold - Add a hold timing check. + Add a hold timing check. - -clock clock + -clock clock - The setup/hold check clock. + The setup/hold check clock. - margin + margin - The setup or hold time margin. + The setup or hold time margin. @@ -10949,123 +11095,121 @@ - set_disable_inferred_clock_gating + set_disable_inferred_clock_gating - objects + objects - objects + objects - A list of clock gating instances, clock gating pins, or clock enable pins. + A list of clock gating instances, clock gating pins, or clock enable pins. - The set_disable_inferred_clock_gating command disables clock gating checks on a clock gating instance, clock gating pin, or clock gating enable pin. + The set_disable_inferred_clock_gating command disables clock gating checks on a clock gating instance, clock gating pin, or clock gating enable pin. - - set_disable_timing + set_disable_timing - [-from from_port][-to to_port]objects + [-from from_port][-to to_port]objects - -from from_port + -from from_port - + - -to to_port + -to to_port - + - objects + objects - A list of instances, ports, pins, cells, cell/port, or library/cell/port. + A list of instances, ports, pins, cells, cell/port, or library/cell/port. The set_disable_timing command is used to disable paths though pins in the design. There are many different forms of the command depending on the objects specified in objects. - All timing paths though an instance are disabled when objects contains an instance. Timing checks in the instance are not disabled. + All timing paths though an instance are disabled when objects contains an instance. Timing checks in the instance are not disabled. set_disable_timing u2 The -from and -to options can be used to restrict the disabled path to those from, to or between specific pins on the instance. set_disable_timing -from A u2set_disable_timing -to Z u2set_disable_timing -from A -to Z u2 A list of top level ports or instance pins can also be disabled. set_disable_timing u2/Zset_disable_timing in1 Timing paths though all instances of a library cell in the design can be disabled by naming the cell using a hierarchy separator between the library and cell name. Paths from or to a cell port can be disabled with the -from and -to options or a port name after library and cell names. - set_disable_timing liberty1/snl_bufx2set_disable_timing -from A liberty1/snl_bufxset_disable_timing -to Z liberty1/snl_bufxset_disable_timing liberty1/snl_bufx2/A + set_disable_timing liberty1/snl_bufx2set_disable_timing -from A liberty1/snl_bufxset_disable_timing -to Z liberty1/snl_bufxset_disable_timing liberty1/snl_bufx2/A - set_drive + set_drive - [-rise][-fall][-max][-min]resistanceports - - - - - - -rise - - - Set the drive rise resistance. + [-rise][-fall][-max][-min]resistanceports - -fall + -rise - Set the drive fall resistance. + Set the drive rise resistance. - -max + -fall - Set the maximum resistance. + Set the drive fall resistance. - -min + -max - Set the minimum resistance. + Set the maximum resistance. - resistance + -min - The external drive resistance. + Set the minimum resistance. - ports + resistance + + + The external drive resistance. + + + + + ports A list of ports. @@ -11078,96 +11222,96 @@ - set_driving_cell + set_driving_cell - [-lib_cell cell_name][-library library][-rise][-fall][-min][-max][-pin pin][-from_pin from_pin][-input_transition_rise trans_rise][-input_transition_fall trans_fall]ports + [-lib_cell cell_name][-library library][-rise][-fall][-min][-max][-pin pin][-from_pin from_pin][-input_transition_rise trans_rise][-input_transition_fall trans_fall]ports - -lib_cell cell_name + -lib_cell cell_name - The driving cell. + The driving cell. - -library library + -library library - The driving cell library. + The driving cell library. - -rise + -rise - Set the driving cell for a rising edge. - - - - - -fall - - - Set the driving cell for a falling edge. - - - - - -max - - - Set the driving cell for max delays. - - - - - -min - - - Set the driving cell for min delays. - - - - - -pin pin - - - The output port of the driving cell. - - - - - -from_pin from_pin - - - Use timing arcs from from_pin to the output pin. + Set the driving cell for a rising edge. - -input_transition_rise trans_rise + -fall - The transition time for a rising input at from_pin. + Set the driving cell for a falling edge. - -input_transition_fall trans_fall + -max - The transition time for a falling input at from_pin. + Set the driving cell for max delays. - ports + -min + + + Set the driving cell for min delays. + + + + + -pin pin + + + The output port of the driving cell. + + + + + -from_pin from_pin + + + Use timing arcs from from_pin to the output pin. + + + + + -input_transition_rise trans_rise + + + The transition time for a rising input at from_pin. + + + + + -input_transition_fall trans_fall + + + The transition time for a falling input at from_pin. + + + + + ports A list of ports. @@ -11180,47 +11324,48 @@ - set_false_path + set_false_path - [-setup][-hold][-rise][-fall][-from from_list][-rise_from from_list][-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list][-rise_to to_list][-fall_to to_list][-reset_path] + [-setup][-hold][-rise][-fall][-from from_list][-rise_from from_list][-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list][-rise_to to_list][-fall_to to_list][-reset_path] - -setup + -setup - Apply to setup checks. + Apply to setup checks. - -hold + -hold - Apply to hold checks. + Apply to hold checks. - -rise + -rise - Apply to rising path edges. + Apply to rising path edges. - -fall + -fall - Apply to falling path edges. + Apply to falling path edges. + - -reset_path + -reset_path Remove any matching set_false_path, set_multicycle_path, set_max_delay, set_min_delay exceptions first. @@ -11228,7 +11373,7 @@ - -from from_list + -from from_list A list of clocks, instances, ports or pins. @@ -11236,7 +11381,7 @@ - -through through_list + -through through_list A list of instances, pins or nets. @@ -11244,7 +11389,7 @@ - -to to_list + -to to_list A list of clocks, instances, ports or pins. @@ -11252,7 +11397,7 @@ The set_false_path command disables timing along a path from, through and to a group of design objects. - Objects in from_list can be clocks, register/latch instances, or register/latch clock pins. The -rise_from and -fall_from keywords restrict the false paths to a specific clock edge. + Objects in from_list can be clocks, register/latch instances, or register/latch clock pins. The -rise_from and -fall_from keywords restrict the false paths to a specific clock edge. Objects in through_list can be nets, instances, instance pins, or hierarchical pins,. The -rise_through and -fall_through keywords restrict the false paths to a specific path edge that traverses through the object. Objects in to_list can be clocks, register/latch instances, or register/latch clock pins. The -rise_to and -fall_to keywords restrict the false paths to a specific transition at the path end. @@ -11260,10 +11405,10 @@ - set_fanout_load + set_fanout_load - fanoutport_list + fanoutport_list @@ -11273,18 +11418,18 @@ - set_hierarchy_separator + set_hierarchy_separator - separator + separator - separator + separator - Character used to separate hierarchical names. + Character used to separate hierarchical names. @@ -11294,10 +11439,10 @@ - set_ideal_latency + set_ideal_latency - [-rise] [-fall] [-min] [-max] delay objects + [-rise] [-fall] [-min] [-max] delay objects @@ -11307,10 +11452,10 @@ - set_ideal_network + set_ideal_network - [-no_propagation] objects + [-no_propagation] objects @@ -11320,187 +11465,186 @@ - set_ideal_transition + set_ideal_transition - [-rise] [-fall] [-min] [-max] transition_time objects + [-rise] [-fall] [-min] [-max] transition_time objects - The set_ideal_transition command is parsed but ignored. + The set_ideal_transition command is parsed but ignored. - - set_input_delay + set_input_delay - [-rise][-fall][-max][-min][-clock clock][-clock_fall][-reference_pin ref_pin][-source_latency_included][-network_latency_included][-add_delay]delayport_pin_list + [-rise][-fall][-max][-min][-clock clock][-clock_fall][-reference_pin ref_pin][-source_latency_included][-network_latency_included][-add_delay]delayport_pin_list - -rise + -rise - Set the arrival time for the rising edge of the input. + Set the arrival time for the rising edge of the input. - -fall + -fall - Set the arrival time for the falling edge of the input. + Set the arrival time for the falling edge of the input. - -max + -max - Set the maximum arrival time. + Set the maximum arrival time. - -min + -min - Set the minimum arrival time. + Set the minimum arrival time. - -clock clock + -clock clock - The arrival time is from clock. + The arrival time is from clock. - -clock_fall + -clock_fall - The arrival time is from the falling edge of clock. + The arrival time is from the falling edge of clock. - -reference_pin ref_pin + -reference_pin ref_pin - The arrival time is with respect to the clock that arrives at ref_pin. + The arrival time is with respect to the clock that arrives at ref_pin. - -source_latency_included + -source_latency_included - D no add the clock source latency (insertion delay) to the delay value. + D no add the clock source latency (insertion delay) to the delay value. - -network_latency_included + -network_latency_included - Do not add the clock latency to the delay value when the clock is ideal. + Do not add the clock latency to the delay value when the clock is ideal. - -add_delay + -add_delay - Add this arrival to any existing arrivals. + Add this arrival to any existing arrivals. - delay + delay - The arrival time after clock. + The arrival time after clock. - pin_port_list + pin_port_list - A list of pins or ports. + A list of pins or ports. - The set_input_delay command is used to specify the arrival time of an input signal. - The following command sets the min, max, rise and fall times on the in1 input port 1.0 time units after the rising edge of clk1. - set_input_delay -clock clk1 1.0 [get_ports in1] - Use multiple commands with the -add_delay option to specify separate arrival times for min, max, rise and fall times or multiple clocks. For example, the following specifies separate arrival times with respect to clocks clk1 and clk2. - set_input_delay -clock clk1 1.0 [get_ports in1]set_input_delay -add_delay -clock clk2 2.0 [get_ports in1] - The –reference_pin option is used to specify an arrival time with respect to the arrival on a pin in the clock network. For propagated clocks, the input arrival time is relative to the clock arrival time at the reference pin (the clock source latency and network latency from the clock source to the reference pin). For ideal clocks, input arrival time is relative to the reference pin clock source latency. With the -clock_fall flag the arrival time is relative to the falling transition at the reference pin. If no clocks arrive at the reference pin the set_input_delay command is ignored. If no -clock is specified the arrival time is with respect to all clocks that arrive at the reference pin. The -source_latency_included and -network_latency_included options cannot be used with -reference_pin. - Paths from inputs that do not have an arrival time defined by set_input_delay are not reported. Set the sta_input_port_default_clock variable to 1 to report paths from inputs without a set_input_delay. + The set_input_delay command is used to specify the arrival time of an input signal. + The following command sets the min, max, rise and fall times on the in1 input port 1.0 time units after the rising edge of clk1. + set_input_delay -clock clk1 1.0 [get_ports in1] + Use multiple commands with the -add_delay option to specify separate arrival times for min, max, rise and fall times or multiple clocks. For example, the following specifies separate arrival times with respect to clocks clk1 and clk2. + set_input_delay -clock clk1 1.0 [get_ports in1]set_input_delay -add_delay -clock clk2 2.0 [get_ports in1] + The –reference_pin option is used to specify an arrival time with respect to the arrival on a pin in the clock network. For propagated clocks, the input arrival time is relative to the clock arrival time at the reference pin (the clock source latency and network latency from the clock source to the reference pin). For ideal clocks, input arrival time is relative to the reference pin clock source latency. With the -clock_fall flag the arrival time is relative to the falling transition at the reference pin. If no clocks arrive at the reference pin the set_input_delay command is ignored. If no -clock is specified the arrival time is with respect to all clocks that arrive at the reference pin. The -source_latency_included and -network_latency_included options cannot be used with -reference_pin. + Paths from inputs that do not have an arrival time defined by set_input_delay are not reported. Set the sta_input_port_default_clock variable to 1 to report paths from inputs without a set_input_delay. - set_input_transition + set_input_transition - [-rise][-fall][-max][-min]transitionport_list + [-rise][-fall][-max][-min]transitionport_list - -rise + -rise - Set the rising edge transition. + Set the rising edge transition. - -fall + -fall - Set the falling edge transition. + Set the falling edge transition. - -max + -max - Set the minimum transition time. + Set the minimum transition time. - -min + -min - Set the maximum transition time. + Set the maximum transition time. - transition + transition - The transition time (slew). + The transition time (slew). - port_list + port_list - A list of ports. + A list of ports. @@ -11510,10 +11654,10 @@ - set_level_shifter_strategy + set_level_shifter_strategy - [-rule rule_type] + [-rule rule_type] @@ -11524,10 +11668,10 @@ - set_level_shifter_threshold + set_level_shifter_threshold - [-voltage voltage] + [-voltage voltage] @@ -11537,55 +11681,55 @@ - set_load + set_load - [-rise][-fall][-max][-min][-subtract_pin_load][-pin_load][-wire_load]capacitanceobjects + [-rise][-fall][-max][-min][-subtract_pin_load][-pin_load][-wire_load]capacitanceobjects - -rise + -rise - Set the external port rising capacitance (ports only). + Set the external port rising capacitance (ports only). - -fall + -fall - Set the external port falling capacitance (ports only). + Set the external port falling capacitance (ports only). - -max + -max - Set the max capacitance. + Set the max capacitance. - -min + -min - Set the min capacitance. + Set the min capacitance. - -subtract_pin_load + -subtract_pin_load - Subtract the capacitance of all instance pins connected to the net from capacitance (nets only). If the resulting capacitance is negative, zero is used. Pin capacitances are ignored by delay calculation when this option is used. + Subtract the capacitance of all instance pins connected to the net from capacitance (nets only). If the resulting capacitance is negative, zero is used. Pin capacitances are ignored by delay calculation when this option is used. - -pin_load + -pin_load capacitance is external instance pin capacitance (ports only). @@ -11593,7 +11737,7 @@ - -wire_load + -wire_load capacitance is external wire capacitance (ports only). @@ -11601,7 +11745,7 @@ - capacitance + capacitance The capacitance, in library capacitance units. @@ -11609,34 +11753,34 @@ - objects + objects A list of nets or ports. - The set_load command annotates wire capacitance on a net or external capacitance on a port. There are four different uses for the set_load commanc: - set_load -wire_load port external port wire capacitanceset_load -pin_load port external port pin capacitanceset_load port same as -pin_loadset_load net net wire capacitance - External port capacitance can be annotated separately with the -pin_load and ‑wire_load options. Without the -pin_load and -wire_load options pin capacitance is annotated. - When annotating net wire capacitance with the -subtract_pin_load option the capacitance of all instance pins connected to the net is subtracted from capacitance. Setting the capacitance on a net overrides SPEF parasitics for delay calculation. + The set_load command annotates wire capacitance on a net or external capacitance on a port. There are four different uses for the set_load commanc: + set_load -wire_load port external port wire capacitanceset_load -pin_load port external port pin capacitanceset_load port same as -pin_loadset_load net net wire capacitance + External port capacitance can be annotated separately with the -pin_load and ‑wire_load options. Without the -pin_load and -wire_load options pin capacitance is annotated. + When annotating net wire capacitance with the -subtract_pin_load option the capacitance of all instance pins connected to the net is subtracted from capacitance. Setting the capacitance on a net overrides SPEF parasitics for delay calculation. - set_logic_dc + set_logic_dc - port_list + port_list - port_pin_list + port_pin_list - List of ports or pins. + List of ports or pins. @@ -11646,60 +11790,60 @@ - set_logic_one + set_logic_one - port_list + port_list - port_pin_list + port_pin_list - List of ports or pins. + List of ports or pins. - Set a port or pin to a constant logic one value. No paths are propagated from constant pins. Constant values set with the set_logic_one command are not propagated through downstream gates. + Set a port or pin to a constant logic one value. No paths are propagated from constant pins. Constant values set with the set_logic_one command are not propagated through downstream gates. - set_logic_zero + set_logic_zero - port_list + port_list - port_pin_list + port_pin_list - List of ports or pins. + List of ports or pins. - Set a port or pin to a constant logic zero value. No paths are propagated from constant pins. Constant values set with the set_logic_zero command are not propagated through downstream gates. + Set a port or pin to a constant logic zero value. No paths are propagated from constant pins. Constant values set with the set_logic_zero command are not propagated through downstream gates. - set_max_area + set_max_area - area + area - area + area - + @@ -11709,27 +11853,27 @@ - set_max_capacitance + set_max_capacitance - capacitanceobjects + capacitanceobjects - capacitance + capacitance - + - objects + objects - List of ports or cells. + List of ports or cells. @@ -11739,31 +11883,31 @@ - set_max_delay + set_max_delay - [-rise][-fall][-from from_list][-rise_from from_list][-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list][-rise_to to_list][-fall_to to_list][-ignore_clock_latency][-probe][-reset_path]delay + [-rise][-fall][-from from_list][-rise_from from_list][-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list][-rise_to to_list][-fall_to to_list][-ignore_clock_latency][-probe][-reset_path]delay - -rise + -rise - Set max delay for rising paths. + Set max delay for rising paths. - -fall + -fall - Set max delay for falling paths. + Set max delay for falling paths. - -from from_list + -from from_list A list of clocks, instances, ports or pins. @@ -11771,7 +11915,7 @@ - -through through_list + -through through_list A list of instances, pins or nets. @@ -11779,7 +11923,7 @@ - -to to_list + -to to_list A list of clocks, instances, ports or pins. @@ -11787,7 +11931,7 @@ - -ignore_clock_latency + -ignore_clock_latency Ignore clock latency at the source and target registers. @@ -11795,15 +11939,15 @@ - -probe + -probe - Do not break paths at internal pins (non startpoints). + Do not break paths at internal pins (non startpoints). - -reset_path + -reset_path Remove any matching set_false_path, set_multicycle_path, set_max_delay, set_min_delay exceptions first. @@ -11811,7 +11955,7 @@ - delay + delay The maximum delay. @@ -11825,10 +11969,10 @@ - set_max_dynamic_power + set_max_dynamic_power - power [unit] + power [unit] @@ -11838,26 +11982,26 @@ - set_max_fanout + set_max_fanout - fanoutobjects + fanoutobjects - fanout + fanout - + - objects + objects - List of ports or cells. + List of ports or cells. @@ -11867,10 +12011,10 @@ - set_max_leakage_power + set_max_leakage_power - power [unit] + power [unit] @@ -11880,92 +12024,92 @@ - set_max_time_borrow + set_max_time_borrow - delayobjects + delayobjects - delay + delay - The maximum time the latches can borrow. + The maximum time the latches can borrow. - objects + objects - List of clocks, instances or pins. + List of clocks, instances or pins. - The set_max_time_borrow command specifies the maximum amount of time that latches can borrow. Time borrowing is the time that a data input to a transparent latch arrives after the latch opens. + The set_max_time_borrow command specifies the maximum amount of time that latches can borrow. Time borrowing is the time that a data input to a transparent latch arrives after the latch opens. - set_max_transition + set_max_transition - [-data_path][-clock_path][-rise][-fall]transitionobjects + [-data_path][-clock_path][-rise][-fall]transitionobjects - -data_path + -data_path - Set the max slew for data paths. + Set the max slew for data paths. - -clock_path + -clock_path - Set the max slew for clock paths. + Set the max slew for clock paths. - -rise + -rise - Set the max slew for rising paths. + Set the max slew for rising paths. - -fall + -fall - Set the max slew for falling paths. + Set the max slew for falling paths. - transition + transition - The maximum slew/transition time. + The maximum slew/transition time. - objects + objects - List of clocks, ports or designs. + List of clocks, ports or designs. - The set_max_transition command is specifies the maximum transition time (slew) design rule checked by the report_check_types –max_transition command. + The set_max_transition command is specifies the maximum transition time (slew) design rule checked by the report_check_types –max_transition command. If specified for a design, the default maximum transition is set for the design. If specified for a clock, the maximum transition is applied to all pins in the clock domain. The –clock_path option restricts the maximum transition to clocks in clock paths. The -data_path option restricts the maximum transition to clocks data paths. The –clock_path, -data_path, -rise and –fall options only apply to clock objects. @@ -11973,26 +12117,26 @@ - set_min_capacitance + set_min_capacitance - capacitanceobjects + capacitanceobjects - capacitance + capacitance - Minimum capacitance. + Minimum capacitance. - objects + objects - List of ports or cells. + List of ports or cells. @@ -12002,32 +12146,32 @@ - set_min_delay + set_min_delay - [-rise][-fall][-from from_list][-rise_from from_list][-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list][-rise_to to_list][-fall_to to_list][-ignore_clock_latency][-probe][-reset_path]delay + [-rise][-fall][-from from_list][-rise_from from_list][-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list][-rise_to to_list][-fall_to to_list][-ignore_clock_latency][-probe][-reset_path]delay - -rise + -rise - Set min delay for rising paths. + Set min delay for rising paths. - -fall + -fall - Set min delay for falling paths. + Set min delay for falling paths. - -from from_list + -from from_list A list of clocks, instances, ports or pins. @@ -12035,7 +12179,7 @@ - -through through_list + -through through_list A list of instances, pins or nets. @@ -12043,7 +12187,7 @@ - -to to_list + -to to_list A list of clocks, instances, ports or pins. @@ -12051,7 +12195,7 @@ - -ignore_clock_latency + -ignore_clock_latency Ignore clock latency at the source and target registers. @@ -12059,15 +12203,15 @@ - -probe + -probe - Do not break paths at internal pins (non startpoints). + Do not break paths at internal pins (non startpoints). - -reset_path + -reset_path Remove any matching set_false_path, set_multicycle_path, set_max_delay, set_min_delay exceptions first. @@ -12075,10 +12219,10 @@ - delay + delay - The minimum delay. + The minimum delay. @@ -12089,42 +12233,42 @@ - set_min_pulse_width + set_min_pulse_width - [-high][-low]min_widthobjects + [-high][-low]min_widthobjects - -high + -high - Set the minimum high pulse width. + Set the minimum high pulse width. - -low + -low - Set the minimum low pulse width. + Set the minimum low pulse width. - min_width + min_width - + - objects + objects - List of pins, instances or clocks. + List of pins, instances or clocks. @@ -12134,61 +12278,61 @@ - set_mode + set_mode - mode_name + mode_name - The the mode for SDC c ommands in the TCL interpreter. If mode mode_name does not exist, it is created. When modes are created the default mode is deleted. + The the mode for SDC c ommands in the TCL interpreter. If mode mode_name does not exist, it is created. When modes are created the default mode is deleted. - set_multicycle_path + set_multicycle_path - [-setup][-hold][-rise][-fall][-start][-end][-from from_list][-rise_from from_list][-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list][-rise_to to_list][-fall_to to_list][-reset_path]path_multiplier + [-setup][-hold][-rise][-fall][-start][-end][-from from_list][-rise_from from_list][-fall_from from_list][-through through_list][-rise_through through_list][-fall_through through_list][-to to_list][-rise_to to_list][-fall_to to_list][-reset_path]path_multiplier - -setup + -setup - Set cycle count for setup checks. + Set cycle count for setup checks. - -hold + -hold - Set cycle count for hold checks. + Set cycle count for hold checks. - -rise + -rise - Set cycle count for rising path edges. + Set cycle count for rising path edges. - -fall + -fall - Set cycle count for falling path edges. + Set cycle count for falling path edges. - -start + -start Multiply the source clock period by period_multiplier. @@ -12196,7 +12340,7 @@ - -end + -end Multiply the target clock period by period_multiplier. @@ -12204,7 +12348,7 @@ - -from from_list + -from from_list A list of clocks, instances, ports or pins. @@ -12212,7 +12356,7 @@ - -through through_list + -through through_list A list of instances, pins or nets. @@ -12220,7 +12364,7 @@ - -to to_list + -to to_list A list of clocks, instances, ports or pins. @@ -12228,7 +12372,7 @@ - -reset_path + -reset_path Remove any matching set_false_path, set_multicycle_path, set_max_delay, set_min_delay exceptions first. @@ -12236,7 +12380,7 @@ - path_multiplier + path_multiplier The number of clock periods to add to the path required time. @@ -12250,82 +12394,82 @@ - set_operating_conditions + set_operating_conditions - [-analysis_type single|bc_wc|on_chip_variation][-library lib][condition][-min min_condition][-max max_condition][-min_library min_lib][-max_library max_lib] + [-analysis_type single|bc_wc|on_chip_variation][-library lib][condition][-min min_condition][-max max_condition][-min_library min_lib][-max_library max_lib] - -analysis_type single + -analysis_type single - Use one operating condition for min and max paths. + Use one operating condition for min and max paths. - -analysis_type bc_wc + -analysis_type bc_wc - Best case, worst case analysis. Setup checks use max_condition for clock and data paths. Hold checks use the min_condition for clock and data paths. + Best case, worst case analysis. Setup checks use max_condition for clock and data paths. Hold checks use the min_condition for clock and data paths. - ‑analysis_type on_chip_variation + ‑analysis_type on_chip_variation - The min and max operating conditions represent variations on the chip that can occur simultaneously. Setup checks use max_condition for data paths and min_condition for clock paths. Hold checks use min_condition for data paths and max_condition for clock paths. This is the default analysis type. + The min and max operating conditions represent variations on the chip that can occur simultaneously. Setup checks use max_condition for data paths and min_condition for clock paths. Hold checks use min_condition for data paths and max_condition for clock paths. This is the default analysis type. - -library lib + -library lib - The name of the library that contains condition. + The name of the library that contains condition. - condition + condition - The operating condition for analysis type single. + The operating condition for analysis type single. - -min min_condition + -min min_condition - The operating condition to use for min paths and hold checks. + The operating condition to use for min paths and hold checks. - -max max_condition + -max max_condition - The operating condition to use for max paths and setup checks. + The operating condition to use for max paths and setup checks. - -min_library min_lib + -min_library min_lib - The name of the library that contains min_condition. + The name of the library that contains min_condition. - -max_library max_lib + -max_library max_lib - The name of the library that contains max_condition. + The name of the library that contains max_condition. @@ -12335,237 +12479,237 @@ - set_output_delay + set_output_delay - [-rise][-fall][-max][-min][-clock clock][-clock_fall][-reference_pin ref_pin][-source_latency_included][-network_latency_included][-add_delay]delayport_pin_list + [-rise][-fall][-max][-min][-clock clock][-clock_fall][-reference_pin ref_pin][-source_latency_included][-network_latency_included][-add_delay]delayport_pin_list - -rise + -rise - Set the output delay for the rising edge of the input. + Set the output delay for the rising edge of the input. - -fall + -fall - Set the output delay for the falling edge of the input. + Set the output delay for the falling edge of the input. - -max + -max - Set the maximum output delay. + Set the maximum output delay. - -min + -min - Set the minimum output delay. + Set the minimum output delay. - -clock clock + -clock clock - The external check is to clock. The default clock edge is rising. + The external check is to clock. The default clock edge is rising. - -clock_fall + -clock_fall - The external check is to the falling edge of clock. + The external check is to the falling edge of clock. - -reference_pin ref_pin + -reference_pin ref_pin - The external check is clocked by the clock that arrives at ref_pin. + The external check is clocked by the clock that arrives at ref_pin. - -add_delay + -add_delay - Add this output delay to any existing output delays. + Add this output delay to any existing output delays. - delay + delay - The external delay to the check clocked by clock. + The external delay to the check clocked by clock. - pin_port_list + pin_port_list - A list of pins or ports. + A list of pins or ports. - The set_output_delay command is used to specify the external delay to a setup/hold check on an output port or internal pin that is clocked by clock. Unless the -add_delay option is specified any existing output delays are replaced. - The –reference_pin option is used to specify a timing check with respect to the arrival on a pin in the clock network. For propagated clocks, the timing check is relative to the clock arrival time at the reference pin (the clock source latency and network latency from the clock source to the reference pin). For ideal clocks, the timing check is relative to the reference pin clock source latency. With the -clock_fall flag the timing check is relative to the falling edge of the reference pin. If no clocks arrive at the reference pin the set_output_delay command is ignored. If no -clock is specified the timing check is with respect to all clocks that arrive at the reference pin. The -source_latency_included and -network_latency_included options cannot be used with -reference_pin. + The set_output_delay command is used to specify the external delay to a setup/hold check on an output port or internal pin that is clocked by clock. Unless the -add_delay option is specified any existing output delays are replaced. + The –reference_pin option is used to specify a timing check with respect to the arrival on a pin in the clock network. For propagated clocks, the timing check is relative to the clock arrival time at the reference pin (the clock source latency and network latency from the clock source to the reference pin). For ideal clocks, the timing check is relative to the reference pin clock source latency. With the -clock_fall flag the timing check is relative to the falling edge of the reference pin. If no clocks arrive at the reference pin the set_output_delay command is ignored. If no -clock is specified the timing check is with respect to all clocks that arrive at the reference pin. The -source_latency_included and -network_latency_included options cannot be used with -reference_pin. - set_port_fanout_number + set_port_fanout_number - [-min][-max]fanoutports + [-min][-max]fanoutports - -min + -min - Set the min fanout. + Set the min fanout. - -max + -max - Set the max fanout. + Set the max fanout. - fanout + fanout - The external fanout of the ports. + The external fanout of the ports. - port_list + port_list - A list of ports. + A list of ports. - Set the external fanout for ports. + Set the external fanout for ports. - set_power_activity + set_power_activity - [-global][-input][-input_ports ports][-pins pins][-activity activity | -density density][-duty duty][-clock clock] + [-global][-input][-input_ports ports][-pins pins][-activity activity | -density density][-duty duty][-clock clock] - -global + -global - Set the activity/duty for all non-clock pins. + Set the activity/duty for all non-clock pins. - -input + -input - Set the default input port activity/duty. + Set the default input port activity/duty. - -input_ports input_ports + -input_ports input_ports - Set the input port activity/duty. + Set the input port activity/duty. - -pins pins + -pins pins - Set the pin activity/duty. + Set the pin activity/duty. - -activity activity + -activity activity - The activity, or number of transitions per clock cycle. If clock is not specified the clock with the minimum period is used. If no clocks are defined an error is reported. + The activity, or number of transitions per clock cycle. If clock is not specified the clock with the minimum period is used. If no clocks are defined an error is reported. - -density density + -density density - Transitions per library time unit. + Transitions per library time unit. - -duty duty + -duty duty - The duty, or probability the signal is high (0 <= duty <= 1.0). Defaults to 0.5. + The duty, or probability the signal is high (0 <= duty <= 1.0). Defaults to 0.5. - -clock clock + -clock clock - The clock to use for the period with -activity. This option is ignored if -density is used. + The clock to use for the period with -activity. This option is ignored if -density is used. - The set_power_activity command is used to set the activity and duty used for power analysis globally or for input ports or pins in the design. - The default input activity for inputs is 0.1 transitions per minimum clock period if a clock is defined or 0.0 if there are no clocks defined. The default input duty is 0.5. This is equivalent to the following command: - set_power_activity -input -activity 0.1 -duty 0.5 + The set_power_activity command is used to set the activity and duty used for power analysis globally or for input ports or pins in the design. + The default input activity for inputs is 0.1 transitions per minimum clock period if a clock is defined or 0.0 if there are no clocks defined. The default input duty is 0.5. This is equivalent to the following command: + set_power_activity -input -activity 0.1 -duty 0.5 - set_propagated_clock + set_propagated_clock - objects + objects - objects + objects - A list of clocks, ports or pins. + A list of clocks, ports or pins. @@ -12576,59 +12720,59 @@ - set_pvt + set_pvt - [-min][-max][-process process][-voltage voltage] - [-temperature temperature]instances + [-min][-max][-process process][-voltage voltage] + [-temperature temperature]instances - -min + -min - Set the PVT values for max delays. + Set the PVT values for max delays. - -max + -max - Set the PVT values for min delays. + Set the PVT values for min delays. - -process process + -process process - A process value (float). + A process value (float). - -voltage voltage + -voltage voltage - A voltage value (float). + A voltage value (float). - -temperature temperature + -temperature temperature - A temperature value (float). + A temperature value (float). - instances + instances - A list instances. + A list instances. @@ -12638,177 +12782,177 @@ - set_sense + set_sense - [-type clock|data][-positive][-negative][-pulse pulse_type][-stop_propagation][-clock clocks]pins + [-type clock|data][-positive][-negative][-pulse pulse_type][-stop_propagation][-clock clocks]pins - -type clock + -type clock - Set the sense for clock paths. + Set the sense for clock paths. - -type data + -type data - Set the sense for data paths (not supported). + Set the sense for data paths (not supported). - -positive + -positive - The clock sense is positive unate. + The clock sense is positive unate. - -negative + -negative - The clock sense is negative unate. + The clock sense is negative unate. - -pulse pulse_type + -pulse pulse_type - rise_triggered_high_pulserise_triggered_low_pulsefall_triggered_high_pulsefall_triggered_low_pulseNot supported. + rise_triggered_high_pulserise_triggered_low_pulsefall_triggered_high_pulsefall_triggered_low_pulseNot supported. - -stop_propagation + -stop_propagation - Stop propagating clocks at pins. + Stop propagating clocks at pins. - clocks + clocks - A list of clocks to apply the sense. + A list of clocks to apply the sense. - pins + pins - A list of pins. + A list of pins. - The set_sense command is used to modify the propagation of a clock signal. The clock sense is set with the ‑positive and –negative flags. Use the –stop_propagation flag to stop the clock from propagating beyond a pin. The –positive, -negative, -stop_propagation, and –pulse options are mutually exclusive. If the –clock option is not used the command applies to all clocks that traverse pins. The –pulse option is currently not supported. + The set_sense command is used to modify the propagation of a clock signal. The clock sense is set with the ‑positive and –negative flags. Use the –stop_propagation flag to stop the clock from propagating beyond a pin. The –positive, -negative, -stop_propagation, and –pulse options are mutually exclusive. If the –clock option is not used the command applies to all clocks that traverse pins. The –pulse option is currently not supported. - set_timing_derate + set_timing_derate - [-rise][-fall][-early][-late][-clock][-data][-net_delay][-cell_delay][-cell_check]derate[objects] + [-rise][-fall][-early][-late][-clock][-data][-net_delay][-cell_delay][-cell_check]derate[objects] - -rise + -rise - Set the derating for rising delays. + Set the derating for rising delays. - -fall + -fall - Set the derating for falling delays. + Set the derating for falling delays. - -early + -early - Derate early (min) paths. + Derate early (min) paths. - -late + -late - Derate late (max) paths. + Derate late (max) paths. - -clock + -clock - Derate paths in the clock network. + Derate paths in the clock network. - -data + -data - Derate data paths. + Derate data paths. - -net_delay + -net_delay - Derate net (interconnect) delays. + Derate net (interconnect) delays. - -cell_delay + -cell_delay - Derate cell delays. + Derate cell delays. - -cell_check + -cell_check - Derate cell timing check margins. + Derate cell timing check margins. - derate + derate - The derating factor to apply to delays. + The derating factor to apply to delays. - objects + objects - A list of instances, library cells, or nets. + A list of instances, library cells, or nets. @@ -12819,42 +12963,42 @@ - set_resistance + set_resistance - [-max][-min]resistancenets + [-max][-min]resistancenets - -min + -min - The resistance for minimum path delay calculation. + The resistance for minimum path delay calculation. - -max + -max - The resistance for maximum path delay calculation. + The resistance for maximum path delay calculation. - resistance + resistance - The net resistance. + The net resistance. - nets + nets - A list of nets. + A list of nets. @@ -12864,76 +13008,76 @@ - set_units + set_units - [-capacitance cap_unit][-resistance res_unit][-time time_unit][-voltage voltage_unit][-current current_unit][-power power_unit][-distance distance_unit] + [-capacitance cap_unit][-resistance res_unit][-time time_unit][-voltage voltage_unit][-current current_unit][-power power_unit][-distance distance_unit] - -capacitance cap_unit + -capacitance cap_unit - The capacitance scale factor followed by 'f'. + The capacitance scale factor followed by 'f'. - -resistance res_unit + -resistance res_unit - The resistance scale factor followed by 'ohm'. + The resistance scale factor followed by 'ohm'. - -time time_unit + -time time_unit - The time scale factor followed by 's'. + The time scale factor followed by 's'. - -voltage voltage_unit + -voltage voltage_unit - The voltage scale factor followed by 'v'. + The voltage scale factor followed by 'v'. - -current current_unit + -current current_unit - The current scale factor followed by 'A'. + The current scale factor followed by 'A'. - -power power_unit + -power power_unit - The power scale factor followed by 'w'. + The power scale factor followed by 'w'. - The set_units command is used to check the units used by the STA command interpreter when parsing commands and reporting results. If the current units differ from the set_unit value a warning is printed. Use the set_cmd_units command to change the command units. + The set_units command is used to check the units used by the STA command interpreter when parsing commands and reporting results. If the current units differ from the set_unit value a warning is printed. Use the set_cmd_units command to change the command units. Units are specified as a scale factor followed by a unit name. The scale factors are as follows. - M 1E+6k 1E+3m 1E-3u 1E-6n 1E-9p 1E-12f 1E-15 + M 1E+6k 1E+3m 1E-3u 1E-6n 1E-9p 1E-12f 1E-15 An example of the set_units command is shown below. - set_units -time ns -capacitance pF -current mA -voltage V -resistance kOhm + set_units -time ns -capacitance pF -current mA -voltage V -resistance kOhm - set_wire_load_min_block_size + set_wire_load_min_block_size - size + size @@ -12943,34 +13087,34 @@ - set_wire_load_mode + set_wire_load_mode - top|enclosed|segmented + top|enclosed|segmented - top + top - + - enclosed + enclosed - + - segmented + segmented - + @@ -12980,51 +13124,51 @@ - set_wire_load_model + set_wire_load_model - -name model_name[-library library][-max][-min][objects] + -name model_name[-library library][-max][-min][objects] - -name model_name + -name model_name - The name of a wire load model. + The name of a wire load model. - -library library + -library library - Library to look for model_name. + Library to look for model_name. - -max + -max - The wire load model is for maximum path delays. + The wire load model is for maximum path delays. - -min + -min - The wire load model is for minimum path delays. + The wire load model is for minimum path delays. - objects + objects - Not supported. + Not supported. @@ -13034,50 +13178,50 @@ - set_wire_load_selection_group + set_wire_load_selection_group - [-library library][-max][-min]group_name[objects] + [-library library][-max][-min]group_name[objects] - library + library - Library to look for group_name. + Library to look for group_name. - -max + -max - The wire load selection is for maximum path delays. + The wire load selection is for maximum path delays. - -min + -min - The wire load selection is for minimum path delays. + The wire load selection is for minimum path delays. - group_name + group_name - A wire load selection group name. + A wire load selection group name. - objects + objects - Not supported. + Not supported. @@ -13087,39 +13231,39 @@ - suppress_msg + suppress_msg - msg_ids + msg_ids - msg_ids + msg_ids - A list of error/warning message IDs to suppress. + A list of error/warning message IDs to suppress. - The suppress_msg command suppresses specified error/warning messages by ID. The list of message IDs can be found in doc/messages.txt. + The suppress_msg command suppresses specified error/warning messages by ID. The list of message IDs can be found in doc/messages.txt. - unset_case_analysis + unset_case_analysis - port_or_pin_list + port_or_pin_list - port_or_pin_list + port_or_pin_list - A list of ports or pins. + A list of ports or pins. @@ -13129,26 +13273,26 @@ - unset_clock_latency + unset_clock_latency - [-source]objects + [-source]objects - -source + -source - Specifies source clock latency (clock insertion delay). + Specifies source clock latency (clock insertion delay). - objects + objects - A list of clocks, pins or ports. + A list of clocks, pins or ports. @@ -13158,18 +13302,18 @@ - unset_clock_transition + unset_clock_transition - clocks + clocks - clocks + clocks - A list of clocks. + A list of clocks. @@ -13179,74 +13323,74 @@ - unset_clock_uncertainty + unset_clock_uncertainty - [-from|-rise_from|-fall_from from_clock][-to|-rise_to|-fall_to to_clock][-rise][-fall][-setup][-hold][objects] + [-from|-rise_from|-fall_from from_clock][-to|-rise_to|-fall_to to_clock][-rise][-fall][-setup][-hold][objects] - -from from_clock + -from from_clock - + - -to to_clock + -to to_clock - + - -rise + -rise - The uncertainty is for the rising edge of the clock. + The uncertainty is for the rising edge of the clock. - -fall + -fall - The uncertainty is for the falling edge of the clock. + The uncertainty is for the falling edge of the clock. - -setup + -setup - uncertainty is the setup check uncertainty. + uncertainty is the setup check uncertainty. - -hold + -hold - uncertainty is the hold uncertainty. + uncertainty is the hold uncertainty. - uncertainty + uncertainty - Clock uncertainty. + Clock uncertainty. - objects + objects - A list of clocks, ports or pins. + A list of clocks, ports or pins. @@ -13256,50 +13400,50 @@ - unset_data_check + unset_data_check - [-from|-rise_from|-fall_from from_object][-to|-rise_to|-fall_to to_object][-setup][-hold][-clock clock] + [-from|-rise_from|-fall_from from_object][-to|-rise_to|-fall_to to_object][-setup][-hold][-clock clock] - -from from_object + -from from_object - A pin used as the timing check reference. + A pin used as the timing check reference. - -to to_object + -to to_object - A pin that the setup/hold check is applied to. + A pin that the setup/hold check is applied to. - -setup + -setup - Add a setup timing check. + Add a setup timing check. - -hold + -hold - Add a hold timing check. + Add a hold timing check. - clock + clock - The setup/hold check clock. + The setup/hold check clock. @@ -13309,52 +13453,52 @@ - unset_disable_inferred_clock_gating + unset_disable_inferred_clock_gating - objects + objects - objects + objects - A list of clock gating instances, clock gating pins, or clock enable pins. + A list of clock gating instances, clock gating pins, or clock enable pins. - The unset_disable_inferred_clock_gating command removes a previous set_disable_inferred_clock_gating command. + The unset_disable_inferred_clock_gating command removes a previous set_disable_inferred_clock_gating command. - unset_disable_timing + unset_disable_timing - [-from from_port][-to to_port]objects + [-from from_port][-to to_port]objects - from_port + from_port - + - to_port + to_port - + - objects + objects A list of instances, ports, pins, cells or [library/]cell/port. @@ -13368,66 +13512,66 @@ - unset_input_delay + unset_input_delay - [-rise][-fall][-max][-min][-clock clock][-clock_fall]port_pin_list + [-rise][-fall][-max][-min][-clock clock][-clock_fall]port_pin_list - -rise + -rise - Unset the arrival time for the rising edge of the input. + Unset the arrival time for the rising edge of the input. - -fall + -fall - Unset the arrival time for the falling edge of the input. + Unset the arrival time for the falling edge of the input. - -max + -max - Unset the minimum arrival time. + Unset the minimum arrival time. - -min + -min - Unset the maximum arrival time. + Unset the maximum arrival time. - clock + clock - Unset the arrival time from clock. + Unset the arrival time from clock. - -clock_fall + -clock_fall - Unset the arrival time from the falling edge of clock + Unset the arrival time from the falling edge of clock - pin_port_list + pin_port_list - A list of pins or ports. + A list of pins or ports. @@ -13437,67 +13581,67 @@ - unset_output_delay + unset_output_delay - [-rise][-fall][-max][-min][-clock clock][-clock_fall]port_pin_list + [-rise][-fall][-max][-min][-clock clock][-clock_fall]port_pin_list - -rise + -rise - This is the arrival time for the rising edge of the input. + This is the arrival time for the rising edge of the input. - -fall + -fall - This is the arrival time for the falling edge of the input. + This is the arrival time for the falling edge of the input. - -max + -max - This is the minimum arrival time. + This is the minimum arrival time. - -min + -min - This is the maximum arrival time. + This is the maximum arrival time. - clock + clock - The arrival time is from this clock. + The arrival time is from this clock. - -clock_fall + -clock_fall - The arrival time is from the falling edge of clock + The arrival time is from the falling edge of clock - pin_port_list + pin_port_list - A list of pins or ports. + A list of pins or ports. @@ -13507,47 +13651,47 @@ - unset_path_exceptions + unset_path_exceptions - [-setup][-hold][-rise][-fall][-from|-rise_from|-fall_from from][-through|-rise_through|-fall_through through][-to|-rise_to|-fall_to to] + [-setup][-hold][-rise][-fall][-from|-rise_from|-fall_from from][-through|-rise_through|-fall_through through][-to|-rise_to|-fall_to to] - -setup + -setup - Unset path exceptions for setup checks. + Unset path exceptions for setup checks. - -hold + -hold - Unset path exceptions for hold checks. + Unset path exceptions for hold checks. - -rise + -rise - Unset path exceptions for rising path edges. + Unset path exceptions for rising path edges. - -fall + -fall - Unset path exceptions for falling path edges. + Unset path exceptions for falling path edges. - -from from + -from from A list of clocks, instances, ports or pins. @@ -13555,7 +13699,7 @@ - -through through + -through through A list of instances, pins or nets. @@ -13563,7 +13707,7 @@ - -to to + -to to A list of clocks, instances, ports or pins. @@ -13571,75 +13715,75 @@ The unset_path_exceptions command removes any matching set_false_path, set_multicycle_path, set_max_delay, and set_min_delay exceptions. - + - unset_power_activity + unset_power_activity - [-global][-input][-input_ports ports][-pins pins] + [-global][-input][-input_ports ports][-pins pins] - -global + -global - Set the activity/duty for all non-clock pins. + Set the activity/duty for all non-clock pins. - -input + -input - Set the default input port activity/duty. + Set the default input port activity/duty. - -input_ports input_ports + -input_ports input_ports - Set the input port activity/duty. + Set the input port activity/duty. - -pins pins + -pins pins - Set the pin activity/duty. + Set the pin activity/duty. - -activity activity + -activity activity - The activity, or number of transitions per clock cycle. If clock is not specified the clock with the minimum period is used. If no clocks are defined an error is reported. + The activity, or number of transitions per clock cycle. If clock is not specified the clock with the minimum period is used. If no clocks are defined an error is reported. - The unset_power_activity_command is used to undo the effects of the set_power_activity command. + The unset_power_activity_command is used to undo the effects of the set_power_activity command. - unset_propagated_clock + unset_propagated_clock - objects + objects - objects + objects A list of clocks, ports or pins. @@ -13652,44 +13796,44 @@ - unset_timing_derate + unset_timing_derate - + - Remove all derating factors set with the set_timing_derate command. + Remove all derating factors set with the set_timing_derate command. - unsuppress_msg + unsuppress_msg - msg_ids + msg_ids - msg_ids + msg_ids - A list of error/warning message IDs to unsuppress. + A list of error/warning message IDs to unsuppress. - The unsuppress_msg command removes suppressions for the specified error/warning messages by ID. The list of message IDs can be found in doc/messages.txt. + The unsuppress_msg command removes suppressions for the specified error/warning messages by ID. The list of message IDs can be found in doc/messages.txt. - user_run_time + user_run_time - + @@ -13699,147 +13843,147 @@ - with_output_to_variable + with_output_to_variable - var { commands } + var { commands } - var + var - The name of a variable to save the output of commands to. + The name of a variable to save the output of commands to. - commands + commands - TCL commands that the output will be redirected from. + TCL commands that the output will be redirected from. - The with_output_to_variable command redirects the output of TCL commands to a variable. + The with_output_to_variable command redirects the output of TCL commands to a variable. - write_path_spice + write_path_spice - -path_args path_args-spice_directory spice_directory-lib_subckt_file lib_subckts_file-model_file model_file-power power-ground ground[-simulator hspice|ngspice|xyce] + -path_args path_args-spice_directory spice_directory-lib_subckt_file lib_subckts_file-model_file model_file-power power-ground ground[-simulator hspice|ngspice|xyce] - path_args + path_args - -from|-through|-to arguments as in report_checks. + -from|-through|-to arguments as in report_checks. - spice_directory + spice_directory - Directory for spice to write output files. + Directory for spice to write output files. - lib_subckts_file + lib_subckts_file - Cell transistor level subckts. + Cell transistor level subckts. - model_file + model_file - Transistor model definitions .included by spice_file. + Transistor model definitions .included by spice_file. - power + power - Voltage supply name in voltage_map of the default liberty library. + Voltage supply name in voltage_map of the default liberty library. - ground + ground - Ground supply name in voltage_map of the default liberty library. + Ground supply name in voltage_map of the default liberty library. - -simulator + -simulator - Simulator that will read the spice netlist. + Simulator that will read the spice netlist. The write_path_spice command writes a spice netlist for timing paths. Use path_args to specify -from/-through/-to as arguments to the find_timing_paths command. For each path, a spice netlist and the subckts referenced by the path are written in spice_directory. The spice netlist is written in path_<id>.sp and subckt file is path_<id>.subckt. The spice netlists used by the path are written to subckt_file, which spice_file .includes. The device models used by the spice subckt netlists in model_file are also .included in spice_file. Power and ground names are specified with the -power and -ground arguments. The spice netlist includes a piecewise linear voltage source at the input and .measure statement for each gate delay and pin slew. - Example command: - write_path_spice -path_args {-from "in0" -to "out1" -unconstrained} \ -spice_directory $result_dir \ -lib_subckt_file "write_spice1.subckt" \ -model_file "write_spice1.models" \ -power VDD -ground VSS - When the simulator is hspice, .measure statements will be added to the spice netlist. - When the simulator is Xyce, the .print statement selects the CSV format and writes the waveform data to a file name path_<id>.csv so the results can be used by gnuplot. + Example command: + write_path_spice -path_args {-from "in0" -to "out1" -unconstrained} \ -spice_directory $result_dir \ -lib_subckt_file "write_spice1.subckt" \ -model_file "write_spice1.models" \ -power VDD -ground VSS + When the simulator is hspice, .measure statements will be added to the spice netlist. + When the simulator is Xyce, the .print statement selects the CSV format and writes the waveform data to a file name path_<id>.csv so the results can be used by gnuplot. - write_sdc + write_sdc - [-digits digits][-gzip][-no_timestamp]filename + [-digits digits][-gzip][-no_timestamp]filename - digits + digits - The number of digits after the decimal point to report. The default is 4. + The number of digits after the decimal point to report. The default is 4. - -gzip + -gzip - Compress the SDC with gzip. + Compress the SDC with gzip. - -no_timestamp + -no_timestamp - Do not include a time and date in the SDC file. + Do not include a time and date in the SDC file. - filename + filename - The name of the file to write the constraints to. + The name of the file to write the constraints to. @@ -13849,242 +13993,242 @@ - write_sdf + write_sdf - [-scene scene][-divider /|.][-include_typ][-digits digits][-gzip][-no_timestamp][-no_version]filename + [-scene scene][-divider /|.][-include_typ][-digits digits][-gzip][-no_timestamp][-no_version]filename - scene + scene - Write delays for scene. + Write delays for scene. - -divider + -divider - Divider to use between hierarchy levels in pin and instance names. + Divider to use between hierarchy levels in pin and instance names. - -include_typ + -include_typ - Include a 'typ' value in the SDF triple that is the average of min and max delays to satisfy some Verilog simulators that require three values in the delay triples. + Include a 'typ' value in the SDF triple that is the average of min and max delays to satisfy some Verilog simulators that require three values in the delay triples. - -digits digits + -digits digits - The number of digits after the decimal point to report. The default is 4. + The number of digits after the decimal point to report. The default is 4. - -gzip + -gzip - Compress the SDF using gzip. + Compress the SDF using gzip. - -no_timestamp + -no_timestamp - Do not write a DATE statement. + Do not write a DATE statement. - -no_version + -no_version - Do not write a VERSION statement. + Do not write a VERSION statement. - filename + filename - The SDF filename to write. + The SDF filename to write. - Write the delay calculation delays for the design in SDF format to filename. If -corner is not specified the min/max delays are across all corners. With -corner the min/max delays for corner are written. The SDF TIMESCALE is same as the time_unit in the first liberty file read. + Write the delay calculation delays for the design in SDF format to filename. If -corner is not specified the min/max delays are across all corners. With -corner the min/max delays for corner are written. The SDF TIMESCALE is same as the time_unit in the first liberty file read. - write_timing_model + write_timing_model - [-library_name lib_name][-cell_name cell_name] - [-scene scene]filename + [-library_name lib_name][-cell_name cell_name] + [-scene scene]filename - lib_name + lib_name - The name to use for the liberty library. Defaults to cell_name. + The name to use for the liberty library. Defaults to cell_name. - cell_name + cell_name - The name to use for the liberty cell. Defaults to the top level module name. + The name to use for the liberty cell. Defaults to the top level module name. - scene + scene - The scene to use for extracting the model. + The scene to use for extracting the model. - filename + filename - Filename for the liberty timing model. + Filename for the liberty timing model. - The write_timing_model command constructs a liberty timing model for the current design and writes it to filename. cell_name defaults to the cell name of the top level block in the design. - The SDC used to extract the block should include the clock definitions. If the block contains a clock network set_propagated_clock should be used so the clock delays are included in the timing model. The following SDC commands are ignored when building the timing model. - set_input_delayset_output_delayset_loadset_timing_derate - Using set_input_transition with the slew from the block context will be used will improve the match between the timing model and the block netlist. Paths defined on clocks that are defined on internal pins are ignored because the model has no way to include the clock definition. + The write_timing_model command constructs a liberty timing model for the current design and writes it to filename. cell_name defaults to the cell name of the top level block in the design. + The SDC used to extract the block should include the clock definitions. If the block contains a clock network set_propagated_clock should be used so the clock delays are included in the timing model. The following SDC commands are ignored when building the timing model. + set_input_delayset_output_delayset_loadset_timing_derate + Using set_input_transition with the slew from the block context will be used will improve the match between the timing model and the block netlist. Paths defined on clocks that are defined on internal pins are ignored because the model has no way to include the clock definition. The resulting timing model can be used in a hierarchical timing flow as a replacement for the block to speed up timing analysis. This hierarchical timing methodology does not handle timing exceptions that originate or terminate inside the block. The timing model includes: - combinational paths between inputs and outputssetup and hold timing constraints on inputsclock to output timing paths - Resistance of long wires on inputs and outputs of the block cannot be modeled in Liberty. To reduce inaccuracies from wire resistance in technologies with resistive wires place buffers on inputs and ouputs. + combinational paths between inputs and outputssetup and hold timing constraints on inputsclock to output timing paths + Resistance of long wires on inputs and outputs of the block cannot be modeled in Liberty. To reduce inaccuracies from wire resistance in technologies with resistive wires place buffers on inputs and ouputs. The extracted timing model setup/hold checks are scalar (no input slew dependence). Delay timing arcs are load dependent but do not include input slew dependency. - write_verilog + write_verilog - [-include_pwr_gnd][-remove_cells lib_cells]filename + [-include_pwr_gnd][-remove_cells lib_cells]filename - -include_pwr_gnd + -include_pwr_gnd - Include power and ground pins on instances. + Include power and ground pins on instances. - -remove_cells lib_cells + -remove_cells lib_cells - Liberty cells to remove from the Verilog netlist. Use get_lib_cells, a list of cells names, or a cell name with wildcards. + Liberty cells to remove from the Verilog netlist. Use get_lib_cells, a list of cells names, or a cell name with wildcards. - filename + filename - Filename for the liberty library. + Filename for the liberty library. - The write_verilog command writes a Verilog netlist to filename. Use -sort to sort the instances so the results are reproducible across operating systems. Use -remove_cells to remove instances of lib_cells from the netlist. - Filter Expressions - The get_cells, get_pins, get_ports and get_timing_edges functions support filtering the returned objects by property values. Supported filter expressions are shown below. + The write_verilog command writes a Verilog netlist to filename. Use -sort to sort the instances so the results are reproducible across operating systems. Use -remove_cells to remove instances of lib_cells from the netlist. + Filter Expressions + The get_cells, get_pins, get_ports and get_timing_edges functions support filtering the returned objects by property values. Supported filter expressions are shown below. - property + property - Return objects with property value equal to 1. + Return objects with property value equal to 1. - property==value + property==value - Return objects with property value equal to value. + Return objects with property value equal to value. - property=~pattern + property=~pattern - Return objects with property value that matches pattern. + Return objects with property value that matches pattern. - property!=value + property!=value - Return objects with property value not equal to value. + Return objects with property value not equal to value. - property!~value + property!~value - Return objects with property value that does not match pattern. + Return objects with property value that does not match pattern. - expr1&&expr2 + expr1&&expr2 - Return objects with expr1 and expr2. expr1 and expr2 are one of the first three property value forms shown above. + Return objects with expr1 and expr2. expr1 and expr2 are one of the first three property value forms shown above. - expr1||expr2 + expr1||expr2 - Return objects with expr1 or expr2. expr1 and expr2 are one of the first three property value forms shown above. + Return objects with expr1 or expr2. expr1 and expr2 are one of the first three property value forms shown above. - Where property is a property supported by the get_property command. Note that if there are spaces in the expression it must be enclosed in quotes so that it is a single argument. - Variables + Where property is a property supported by the get_property command. Note that if there are spaces in the expression it must be enclosed in quotes so that it is a single argument. + Variables - hierarchy_separator + hierarchy_separator - Any character. + Any character. @@ -14094,37 +14238,37 @@ - sta_continue_on_error + sta_continue_on_error - 0|1 + 0|1 - The include and read_sdc commands stop and report any errors encountered while reading a file unless sta_continue_on_error is 1. The default value is 0. + The include and read_sdc commands stop and report any errors encountered while reading a file unless sta_continue_on_error is 1. The default value is 0. - sta_crpr_mode + sta_crpr_mode - same_pin|same_transition + same_pin|same_transition - When the data and clock paths of a timing check overlap (see sta_crpr_enabled), pessimism is removed independent of whether of the path rise/fall transitions. When sta_crpr_mode is same_transition, the pessimism is only removed if the path rise/fall transitions are the same. The default value is same_pin. + When the data and clock paths of a timing check overlap (see sta_crpr_enabled), pessimism is removed independent of whether of the path rise/fall transitions. When sta_crpr_mode is same_transition, the pessimism is only removed if the path rise/fall transitions are the same. The default value is same_pin. - sta_cond_default_arcs_enabled + sta_cond_default_arcs_enabled - 0|1 + 0|1 @@ -14134,10 +14278,10 @@ - sta_crpr_enabled + sta_crpr_enabled - 0|1 + 0|1 @@ -14147,10 +14291,10 @@ - sta_dynamic_loop_breaking + sta_dynamic_loop_breaking - 0|1 + 0|1 @@ -14160,23 +14304,23 @@ - sta_gated_clock_checks_enabled + sta_gated_clock_checks_enabled - 0|1 + 0|1 - When sta_gated_clock_checks_enabled is 1, clock gating setup and hold timing checks are checked. The default value is 1. + When sta_gated_clock_checks_enabled is 1, clock gating setup and hold timing checks are checked. The default value is 1. - sta_input_port_default_clock + sta_input_port_default_clock - 0|1 + 0|1 @@ -14186,10 +14330,10 @@ - sta_internal_bidirect_instance_paths_enabled + sta_internal_bidirect_instance_paths_enabled - 0|1 + 0|1 @@ -14199,27 +14343,40 @@ - sta_pocv_enabled + sta_pocv_mode - 0|1 + scalar|normal|skew_normal - Enable parametric on chip variation using statistical timing analysis. The default value is 0. + Enable parametric on chip variation using statistical timing analysis. The default value is scalar. + + + + + + sta_pocv_quartile + + + quartile + + + + The target quantile of a delay probability distribution (confidence level).The default value is 3 standard deviations, or sigma. - sta_propagate_all_clocks + sta_propagate_all_clocks - 0|1 + 0|1 - All clocks defined after sta_propagate_all_clocks is set to 1 are propagated. If it is set before any clocks are defined it has the same effect as + All clocks defined after sta_propagate_all_clocks is set to 1 are propagated. If it is set before any clocks are defined it has the same effect as set_propagated_clock [all_clocks] After all clocks have been defined. The default value is 0. @@ -14227,36 +14384,36 @@ - sta_propagate_gated_clock_enable + sta_propagate_gated_clock_enable - 0|1 + 0|1 - When set to 1, paths of gated clock enables are propagated through the clock gating instances. If the gated clock controls sequential elements setting sta_propagate_gated_clock_enable to 0 prevents spurious paths from the clock enable. The default value is 1. + When set to 1, paths of gated clock enables are propagated through the clock gating instances. If the gated clock controls sequential elements setting sta_propagate_gated_clock_enable to 0 prevents spurious paths from the clock enable. The default value is 1. - sta_recovery_removal_checks_enabled + sta_recovery_removal_checks_enabled - 0|1 + 0|1 - When sta_recovery_removal_checks_enabled is 0, recovery and removal timing checks are disabled. The default value is 1. + When sta_recovery_removal_checks_enabled is 0, recovery and removal timing checks are disabled. The default value is 1. - sta_report_default_digits + sta_report_default_digits - integer + integer @@ -14266,10 +14423,10 @@ - sta_preset_clear_arcs_enabled + sta_preset_clear_arcs_enabled - 0|1 + 0|1 @@ -14299,186 +14456,186 @@ - Alphabetical Index + Alphabetical Index - all_clocks7 - all_inputs7 - all_outputs8 - all_registers8 - check_setup9 - Command Line Arguments1 - Commands7 - connect_pin9 - create_generated_clock11 - create_voltage_area12 - current_design12 - current_instance13 - define_scene13 - delete_clock13 - delete_from_list13 - delete_generated_clock14 - delete_instance14 - delete_net14 - disconnect_pin14 - elapsed_run_time14 - Example Command Scripts1 - Filter Expressions84 - find_timing_paths15 - get_cells17 - get_clocks17 - get_fanin18 - get_fanout19 - get_full_name19 - get_lib_pins20 - get_libs21 - get_name22 - get_nets22 - get_pins23 - get_ports23 - get_property24 - get_scenes28 - get_timing_edges28 - group_path29 - hierarchy_separator85 - include30 - link_design30 - make_instance30 - make_net31 - Power Analysis3 - read_liberty31 - read_saif32 - read_sdc33 - read_sdf33 - read_spef34 - read_vcd35 - read_verilog35 - redirection5 - replace_activity_annotation36 - replace_cell35 - report_annotated_check36 - report_annotated_delay37 - report_check_types41 - report_checks38 - report_clock_latency42 - report_clock_min_period42 - report_clock_properties43 - report_clock_skew43 - report_dcalc43 - report_disabled_edges44 - report_edges44 - report_instance44 - report_lib_cell44 - report_net45 - report_parasitic_annotation45 - report_power45 - report_slews46 - report_tns46 - report_units46 - report_wns47 - report_worst_slack47 - set_assigned_check48 - set_assigned_delay49 - set_assigned_transition49 - set_case_analysis50 - set_clock_gating_check50 - set_clock_groups51 - set_clock_latency52 - set_clock_transition52 - set_clock_uncertainty53 - set_cmd_units54 - set_data_check55 - set_disable_inferred_clock_gating55 - set_disable_timing55 - set_drive56 - set_driving_cell57 - set_false_path58 - set_fanout_load59 - set_hierarchy_separator59 - set_ideal_latency59 - set_ideal_network59 - set_ideal_transition59 - set_input_delay59 - set_input_transition61 - set_level_shifter_strategy61 - set_level_shifter_threshold61 - set_load61 - set_logic_dc62 - set_logic_one62 - set_logic_zero63 - set_max_area63 - set_max_capacitance63 - set_max_delay63 - set_max_dynamic_power64 - set_max_fanout64 - set_max_leakage_power64 - set_max_time_borrow64 - set_max_transition65 - set_min_capacitance65 - set_min_delay66 - set_min_pulse_width67 - set_mode67 - set_multicycle_path67 - set_operating_conditions68 - set_output_delay69 - set_port_fanout_number70 - set_power_activity70 - set_propagated_clock71 - set_pvt71 - set_resistance73 - set_sense72 - set_timing_derate73 - set_units74 - set_wire_load_min_block_size75 - set_wire_load_mode75 - set_wire_load_model75 - set_wire_load_selection_group75 - SPEF34 - sta_cond_default_arcs_enabled85 - sta_continue_on_error85 - sta_crpr_enabled85 - sta_crpr_mode85 - sta_dynamic_loop_breaking85 - sta_gated_clock_checks_enabled85 - sta_input_port_default_clock86 - sta_internal_bidirect_instance_paths_enabled86 - sta_pocv_enabled86 - sta_preset_clear_arcs_enabled87 - sta_propagate_all_clocks86 - sta_propagate_gated_clock_enable86 - sta_recovery_removal_checks_enabled86 - sta_report_default_digits86 - suppress_msg76 - TCL Interpreter5 - Timing Analysis using SDF2 - Timing Analysis with Multiple Corners and Modes3 - Timing Analysis with Multiple Process Corners2 - unset_case_analysis76 - unset_clock_latency76 - unset_clock_transition76 - unset_clock_uncertainty77 - unset_data_check77 - unset_disable_inferred_clock_gating78 - unset_disable_timing78 - unset_input_delay78 - unset_output_delay79 - unset_path_exceptions79 - unset_power_activity80 - unset_propagated_clock80 - unset_timing_derate80 - unsuppress_msg81 - user_run_time81 - Variables85 - verilog netlist35 - with_output_to_variable81 - write_path_spice81 - write_sdc82 - write_sdf82 - write_timing_model83 - write_verilog84 + all_clocks7 + all_inputs7 + all_outputs8 + all_registers8 + check_setup9 + Command Line Arguments1 + Commands7 + connect_pin9 + create_generated_clock11 + create_voltage_area12 + current_design12 + current_instance13 + define_scene13 + delete_clock13 + delete_from_list13 + delete_generated_clock14 + delete_instance14 + delete_net14 + disconnect_pin14 + elapsed_run_time14 + Example Command Scripts1 + Filter Expressions84 + find_timing_paths15 + get_cells17 + get_clocks17 + get_fanin18 + get_fanout19 + get_full_name19 + get_lib_pins20 + get_libs21 + get_name22 + get_nets22 + get_pins23 + get_ports23 + get_property24 + get_scenes28 + get_timing_edges28 + group_path29 + hierarchy_separator85 + include30 + link_design30 + make_instance30 + make_net31 + Power Analysis3 + read_liberty31 + read_saif32 + read_sdc33 + read_sdf33 + read_spef34 + read_vcd35 + read_verilog35 + redirection5 + replace_activity_annotation36 + replace_cell35 + report_annotated_check36 + report_annotated_delay37 + report_check_types41 + report_checks38 + report_clock_latency42 + report_clock_min_period42 + report_clock_properties43 + report_clock_skew43 + report_dcalc43 + report_disabled_edges44 + report_edges44 + report_instance44 + report_lib_cell44 + report_net45 + report_parasitic_annotation45 + report_power45 + report_slews46 + report_tns46 + report_units46 + report_wns47 + report_worst_slack47 + set_assigned_check48 + set_assigned_delay49 + set_assigned_transition49 + set_case_analysis50 + set_clock_gating_check50 + set_clock_groups51 + set_clock_latency52 + set_clock_transition52 + set_clock_uncertainty53 + set_cmd_units54 + set_data_check55 + set_disable_inferred_clock_gating55 + set_disable_timing55 + set_drive56 + set_driving_cell57 + set_false_path58 + set_fanout_load59 + set_hierarchy_separator59 + set_ideal_latency59 + set_ideal_network59 + set_ideal_transition59 + set_input_delay59 + set_input_transition61 + set_level_shifter_strategy61 + set_level_shifter_threshold61 + set_load61 + set_logic_dc62 + set_logic_one62 + set_logic_zero63 + set_max_area63 + set_max_capacitance63 + set_max_delay63 + set_max_dynamic_power64 + set_max_fanout64 + set_max_leakage_power64 + set_max_time_borrow64 + set_max_transition65 + set_min_capacitance65 + set_min_delay66 + set_min_pulse_width67 + set_mode67 + set_multicycle_path67 + set_operating_conditions68 + set_output_delay69 + set_port_fanout_number70 + set_power_activity70 + set_propagated_clock71 + set_pvt71 + set_resistance73 + set_sense72 + set_timing_derate73 + set_units74 + set_wire_load_min_block_size75 + set_wire_load_mode75 + set_wire_load_model75 + set_wire_load_selection_group75 + SPEF34 + sta_cond_default_arcs_enabled85 + sta_continue_on_error85 + sta_crpr_enabled85 + sta_crpr_mode85 + sta_dynamic_loop_breaking85 + sta_gated_clock_checks_enabled85 + sta_input_port_default_clock86 + sta_internal_bidirect_instance_paths_enabled86 + sta_pocv_enabled86 + sta_preset_clear_arcs_enabled87 + sta_propagate_all_clocks86 + sta_propagate_gated_clock_enable86 + sta_recovery_removal_checks_enabled86 + sta_report_default_digits86 + suppress_msg76 + TCL Interpreter5 + Timing Analysis using SDF2 + Timing Analysis with Multiple Corners and Modes3 + Timing Analysis with Multiple Process Corners2 + unset_case_analysis76 + unset_clock_latency76 + unset_clock_transition76 + unset_clock_uncertainty77 + unset_data_check77 + unset_disable_inferred_clock_gating78 + unset_disable_timing78 + unset_input_delay78 + unset_output_delay79 + unset_path_exceptions79 + unset_power_activity80 + unset_propagated_clock80 + unset_timing_derate80 + unsuppress_msg81 + user_run_time81 + Variables85 + verilog netlist35 + with_output_to_variable81 + write_path_spice81 + write_sdc82 + write_sdf82 + write_timing_model83 + write_verilog84 - - Version 3.0.0, Mar 7, 2026Copyright (c) 2026, Parallax Software, Inc. + + Version 3.0.0, Mar 7, 2026Copyright (c) 2026, 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 <https://www.gnu.org/licenses/>. diff --git a/doc/OpenSTA.pdf b/doc/OpenSTA.pdf index 77ebd937..5cfe2789 100644 Binary files a/doc/OpenSTA.pdf and b/doc/OpenSTA.pdf differ diff --git a/doc/StaApi.txt b/doc/StaApi.txt index 30a16a9c..ecf7d35a 100644 --- a/doc/StaApi.txt +++ b/doc/StaApi.txt @@ -323,28 +323,6 @@ net have wire edges between the pin vertices. Timing arc sets in the leaf instance timing models have corresponding edges in the graph between pins on the instance. -The Graph class constructor option slew_tr_count is used to prevent -the grpah from reserving memory to store slews. Similarly, if the -have_arc_delays option is false no memory is reserved for storing arc -delay values. This is useful if an external delay calculator is used -to annotate delays on the graph. In this case the Graph functions -arcDelay and wireDelay should be overloaded to return delay values -stored outside of the STA. - -A graph with no slews or delays is constructed using: - - Graph(this, 0, false, ap_count); - -A graph with one slew for rising and falling edges is constructed using: - - Graph(this, 1, true, ap_count); - -A graph with separate rising and falling slews (the default) is -constructed using: - - Graph(this, 2, true, ap_count); - - SDC --- diff --git a/graph/DelayFloat.cc b/graph/DelayFloat.cc deleted file mode 100644 index cdb19f9c..00000000 --- a/graph/DelayFloat.cc +++ /dev/null @@ -1,199 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2026, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "Delay.hh" - -#include "StaConfig.hh" -#include "Fuzzy.hh" -#include "Units.hh" -#include "StaState.hh" - -// Non-SSTA compilation. -#if !SSTA - -namespace sta { - -static Delay delay_init_values[MinMax::index_count]; - -void -initDelayConstants() -{ - delay_init_values[MinMax::minIndex()] = MinMax::min()->initValue(); - delay_init_values[MinMax::maxIndex()] = MinMax::max()->initValue(); -} - -const char * -delayAsString(const Delay &delay, - const StaState *sta) -{ - return delayAsString(delay, sta, sta->units()->timeUnit()->digits()); -} - -const char * -delayAsString(const Delay &delay, - const StaState *sta, - int digits) -{ - return sta->units()->timeUnit()->asString(delay, digits); -} - -const char * -delayAsString(const Delay &delay, - const EarlyLate *, - const StaState *sta, - int digits) -{ - const Unit *unit = sta->units()->timeUnit(); - return unit->asString(delay, digits); -} - -const Delay & -delayInitValue(const MinMax *min_max) -{ - return delay_init_values[min_max->index()]; -} - -bool -delayIsInitValue(const Delay &delay, - const MinMax *min_max) -{ - return fuzzyEqual(delay, min_max->initValue()); -} - -bool -delayZero(const Delay &delay) -{ - return fuzzyZero(delay); -} - -bool -delayInf(const Delay &delay) -{ - return fuzzyInf(delay); -} - -bool -delayEqual(const Delay &delay1, - const Delay &delay2) -{ - return fuzzyEqual(delay1, delay2); -} - -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const StaState *) -{ - return fuzzyLess(delay1, delay2); -} - -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *) -{ - if (min_max == MinMax::max()) - return fuzzyLess(delay1, delay2); - else - return fuzzyGreater(delay1, delay2); -} - -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const StaState *) -{ - return fuzzyLessEqual(delay1, delay2); -} - -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *) -{ - if (min_max == MinMax::max()) - return fuzzyLessEqual(delay1, delay2); - else - return fuzzyGreaterEqual(delay1, delay2); -} - -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const StaState *) -{ - return fuzzyGreater(delay1, delay2); -} - -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *) -{ - if (min_max == MinMax::max()) - return fuzzyGreater(delay1, delay2); - else - return fuzzyLess(delay1, delay2); -} - -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const StaState *) -{ - return fuzzyGreaterEqual(delay1, delay2); -} - -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *) -{ - if (min_max == MinMax::max()) - return fuzzyGreaterEqual(delay1, delay2); - else - return fuzzyLessEqual(delay1, delay2); -} - -Delay -delayRemove(const Delay &delay1, - const Delay &delay2) -{ - return delay1 - delay2; -} - -float -delayRatio(const Delay &delay1, - const Delay &delay2) -{ - return delay1 / delay2; -} - -} // namespace - -#endif // !SSTA diff --git a/graph/DelayNormal1.cc b/graph/DelayNormal1.cc deleted file mode 100644 index f13518e0..00000000 --- a/graph/DelayNormal1.cc +++ /dev/null @@ -1,483 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2026, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "Delay.hh" - -#include // sqrt - -#include "StaConfig.hh" -#include "Error.hh" -#include "StringUtil.hh" -#include "Fuzzy.hh" -#include "Units.hh" -#include "StaState.hh" -#include "Variables.hh" - -// SSTA compilation. -#if (SSTA == 1) - -namespace sta { - -inline float -square(float x) -{ - return x * x; -} - -static Delay delay_init_values[MinMax::index_count]; - -void -initDelayConstants() -{ - delay_init_values[MinMax::minIndex()] = MinMax::min()->initValue(); - delay_init_values[MinMax::maxIndex()] = MinMax::max()->initValue(); -} - -const Delay & -delayInitValue(const MinMax *min_max) -{ - return delay_init_values[min_max->index()]; -} - -Delay::Delay() : - mean_(0.0), - sigma2_(0.0) -{ -} - -Delay::Delay(const Delay &delay) : - mean_(delay.mean_), - sigma2_(delay.sigma2_) -{ -} - -Delay::Delay(const DelayDbl &delay) : - mean_(delay.mean_), - sigma2_(delay.sigma2_) -{ -} - -Delay::Delay(float mean) : - mean_(mean), - sigma2_(0.0) -{ -} - -Delay::Delay(float mean, - float sigma2) : - mean_(mean), - sigma2_(sigma2) -{ -} - -float -Delay::sigma() const -{ - if (sigma2_ < 0.0) - // Sigma is negative for crpr to offset sigmas in the common - // clock path. - return -sqrt(-sigma2_); - else - return sqrt(sigma2_); -} - -float -Delay::sigma2() const -{ - return sigma2_; -} - -void -Delay::operator=(const Delay &delay) -{ - mean_ = delay.mean_; - sigma2_ = delay.sigma2_; -} - -void -Delay::operator=(float delay) -{ - mean_ = delay; - sigma2_ = 0.0; -} - -void -Delay::operator+=(const Delay &delay) -{ - mean_ += delay.mean_; - sigma2_ += delay.sigma2_; -} - -void -Delay::operator+=(float delay) -{ - mean_ += delay; -} - -Delay -Delay::operator+(const Delay &delay) const -{ - return Delay(mean_ + delay.mean_, - sigma2_ + delay.sigma2_); -} - -Delay -Delay::operator+(float delay) const -{ - return Delay(mean_ + delay, sigma2_); -} - -Delay -Delay::operator-(const Delay &delay) const -{ - return Delay(mean_ - delay.mean_, - sigma2_ + delay.sigma2_); -} - -Delay -Delay::operator-(float delay) const -{ - return Delay(mean_ - delay, sigma2_); -} - -Delay -Delay::operator-() const -{ - return Delay(-mean_, sigma2_); -} - -void -Delay::operator-=(float delay) -{ - mean_ -= delay; -} - -void -Delay::operator-=(const Delay &delay) -{ - mean_ -= delay.mean_; - sigma2_ += delay.sigma2_; -} - -bool -Delay::operator==(const Delay &delay) const -{ - return delayEqual(*this, delay); -} - -//////////////////////////////////////////////////////////////// - -DelayDbl::DelayDbl() : - mean_(0.0), - sigma2_(0.0) -{ -} - -void -DelayDbl::operator=(float delay) -{ - mean_ = delay; - sigma2_ = 0.0; -} - -void -DelayDbl::operator+=(const Delay &delay) -{ - mean_ += delay.mean_; - sigma2_ += delay.sigma2_; -} - -void -DelayDbl::operator-=(const Delay &delay) -{ - mean_ -= delay.mean_; - sigma2_ += delay.sigma2_; -} - -//////////////////////////////////////////////////////////////// - -Delay -makeDelay(float delay, - float sigma, - float) -{ - return Delay(delay, square(sigma)); -} - -Delay -makeDelay2(float delay, - float sigma2, - float ) -{ - return Delay(delay, sigma2); -} - -float -delayAsFloat(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta) -{ - if (sta->variables()->pocvEnabled()) { - if (early_late == EarlyLate::early()) - return delay.mean() - delay.sigma() * sta->sigmaFactor(); - else if (early_late == EarlyLate::late()) - return delay.mean() + delay.sigma() * sta->sigmaFactor(); - else - sta->report()->critical(1020, "unknown early/late value."); - } - return delay.mean(); -} - -float -delaySigma2(const Delay &delay, - const EarlyLate *) -{ - return delay.sigma2(); -} - -const char * -delayAsString(const Delay &delay, - const StaState *sta) -{ - return delayAsString(delay, sta, sta->units()->timeUnit()->digits()); -} - -const char * -delayAsString(const Delay &delay, - const StaState *sta, - int digits) -{ - const Unit *unit = sta->units()->timeUnit(); - if (sta->variables()->pocvEnabled()) { - float sigma = delay.sigma(); - return stringPrintTmp("%s[%s]", - unit->asString(delay.mean(), digits), - unit->asString(sigma, digits)); - } - else - return unit->asString(delay.mean(), digits); -} - -const char * -delayAsString(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta, - int digits) -{ - float mean_sigma = delayAsFloat(delay, early_late, sta); - return sta->units()->timeUnit()->asString(mean_sigma, digits); -} - -bool -delayIsInitValue(const Delay &delay, - const MinMax *min_max) -{ - return fuzzyEqual(delay.mean(), min_max->initValue()) - && delay.sigma2() == 0.0; -} - -bool -delayZero(const Delay &delay) -{ - return fuzzyZero(delay.mean()) - && fuzzyZero(delay.sigma2()); -} - -bool -delayInf(const Delay &delay) -{ - return fuzzyInf(delay.mean()); -} - -bool -delayEqual(const Delay &delay1, - const Delay &delay2) -{ - return fuzzyEqual(delay1.mean(), delay2.mean()) - && fuzzyEqual(delay1.sigma2(), delay2.sigma2()); -} - -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const StaState *sta) -{ - return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta), - delayAsFloat(delay2, EarlyLate::early(), sta)); -} - -bool -delayLess(const Delay &delay1, - float delay2, - const StaState *sta) -{ - return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta), - delay2); -} - -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta) -{ - if (min_max == MinMax::max()) - return delayLess(delay1, delay2, sta); - else - return delayGreater(delay1, delay2, sta); -} - -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta) -{ - return fuzzyLessEqual(delayAsFloat(delay1, EarlyLate::early(), sta), - delayAsFloat(delay2, EarlyLate::early(), sta)); -} - -bool -delayLessEqual(const Delay &delay1, - float delay2, - const StaState *sta) -{ - return fuzzyLessEqual(delayAsFloat(delay1, EarlyLate::early(), sta), - delay2); -} - -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta) -{ - if (min_max == MinMax::max()) - return delayLessEqual(delay1, delay2, sta); - else - return delayGreaterEqual(delay1, delay2, sta); -} - -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const StaState *sta) - -{ - return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta), - delayAsFloat(delay2, EarlyLate::late(), sta)); -} - -bool -delayGreater(const Delay &delay1, - float delay2, - const StaState *sta) -{ - return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta), - delay2); -} - -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta) -{ - return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), - delayAsFloat(delay2, EarlyLate::late(), sta)); -} - -bool -delayGreaterEqual(const Delay &delay1, - float delay2, - const StaState *sta) -{ - return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), - delay2); -} - -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta) -{ - if (min_max == MinMax::max()) - return delayGreater(delay1, delay2, sta); - else - return delayLess(delay1, delay2, sta); -} - -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta) -{ - if (min_max == MinMax::max()) - return delayGreaterEqual(delay1, delay2, sta); - else - return delayLessEqual(delay1, delay2, sta); -} - -Delay -delayRemove(const Delay &delay1, - const Delay &delay2) -{ - return Delay(delay1.mean() - delay2.mean(), - delay1.sigma2() - delay2.sigma2()); -} - -float -delayRatio(const Delay &delay1, - const Delay &delay2) -{ - return delay1.mean() / delay2.mean(); -} - -Delay -operator+(float delay1, - const Delay &delay2) -{ - return Delay(delay1 + delay2.mean(), - delay2.sigma2()); -} - -Delay -operator/(float delay1, - const Delay &delay2) -{ - return Delay(delay1 / delay2.mean(), - delay2.sigma2()); -} - -Delay -operator*(const Delay &delay1, - float delay2) -{ - return Delay(delay1.mean() * delay2, - delay1.sigma2() * delay2 * delay2); -} - -} // namespace - -#endif // (SSTA == 1) diff --git a/graph/DelayNormal2.cc b/graph/DelayNormal2.cc deleted file mode 100644 index be8936a0..00000000 --- a/graph/DelayNormal2.cc +++ /dev/null @@ -1,517 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2026, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "Delay.hh" - -#include // sqrt - -#include "StaConfig.hh" -#include "Error.hh" -#include "StringUtil.hh" -#include "Fuzzy.hh" -#include "Units.hh" -#include "StaState.hh" - -// SSTA compilation. -#if (SSTA == 2) - -namespace sta { - -inline float -square(float x) -{ - return x * x; -} - -static Delay delay_init_values[MinMax::index_count]; - -void -initDelayConstants() -{ - delay_init_values[MinMax::minIndex()] = MinMax::min()->initValue(); - delay_init_values[MinMax::maxIndex()] = MinMax::max()->initValue(); -} - -const Delay & -delayInitValue(const MinMax *min_max) -{ - return delay_init_values[min_max->index()]; -} - -Delay::Delay() : - mean_(0.0), - sigma2_{0.0, 0.0} -{ -} - -Delay::Delay(const Delay &delay) : - mean_(delay.mean_) -{ - sigma2_[EarlyLate::earlyIndex()] = delay.sigma2_[EarlyLate::earlyIndex()]; - sigma2_[EarlyLate::lateIndex()] = delay.sigma2_[EarlyLate::lateIndex()]; -} - -Delay::Delay(const DelayDbl &delay) : - mean_(delay.mean_) -{ - sigma2_[EarlyLate::earlyIndex()] = delay.sigma2_[EarlyLate::earlyIndex()]; - sigma2_[EarlyLate::lateIndex()] = delay.sigma2_[EarlyLate::lateIndex()]; -} - -Delay::Delay(float mean) : - mean_(mean), - sigma2_{0.0, 0.0} -{ -} - -Delay::Delay(float mean, - float sigma2_early, - float sigma2_late) : - mean_(mean), - sigma2_{sigma2_early, sigma2_late} -{ -} - -float -Delay::sigma(const EarlyLate *early_late) const -{ - float sigma = sigma2_[early_late->index()]; - if (sigma < 0.0) - // Sigma is negative for crpr to offset sigmas in the common - // clock path. - return -sqrt(-sigma); - else - return sqrt(sigma); -} - -float -Delay::sigma2(const EarlyLate *early_late) const -{ - return sigma2_[early_late->index()]; -} - -float -Delay::sigma2Early() const -{ - return sigma2_[early_index]; -} - -float -Delay::sigma2Late() const -{ - return sigma2_[late_index]; -} - -void -Delay::operator=(const Delay &delay) -{ - mean_ = delay.mean_; - sigma2_[early_index] = delay.sigma2_[early_index]; - sigma2_[late_index] = delay.sigma2_[late_index]; -} - -void -Delay::operator=(float delay) -{ - mean_ = delay; - sigma2_[early_index] = 0.0; - sigma2_[late_index] = 0.0; -} - -void -Delay::operator+=(const Delay &delay) -{ - mean_ += delay.mean_; - sigma2_[early_index] += delay.sigma2_[early_index]; - sigma2_[late_index] += delay.sigma2_[late_index]; -} - -void -Delay::operator+=(float delay) -{ - mean_ += delay; -} - -Delay -Delay::operator+(const Delay &delay) const -{ - return Delay(mean_ + delay.mean_, - sigma2_[early_index] + delay.sigma2_[early_index], - sigma2_[late_index] + delay.sigma2_[late_index]); -} - -Delay -Delay::operator+(float delay) const -{ - return Delay(mean_ + delay, sigma2_[early_index], sigma2_[late_index]); -} - -Delay -Delay::operator-(const Delay &delay) const -{ - return Delay(mean_ - delay.mean_, - sigma2_[early_index] + delay.sigma2_[late_index], - sigma2_[late_index] + delay.sigma2_[early_index]); -} - -Delay -Delay::operator-(float delay) const -{ - return Delay(mean_ - delay, sigma2_[early_index], sigma2_[late_index]); -} - -Delay -Delay::operator-() const -{ - return Delay(-mean_, sigma2_[late_index], sigma2_[early_index]); -} - -void -Delay::operator-=(float delay) -{ - mean_ -= delay; -} - -void -Delay::operator-=(const Delay &delay) -{ - mean_ -= delay.mean_; - sigma2_[early_index] += delay.sigma2_[early_index]; - sigma2_[late_index] += delay.sigma2_[late_index]; -} - -bool -Delay::operator==(const Delay &delay) const -{ - return mean_ == delay.mean_ - && sigma2_[early_index] == delay.sigma2_[late_index] - && sigma2_[late_index] == delay.sigma2_[early_index]; -} - -//////////////////////////////////////////////////////////////// - -DelayDbl::DelayDbl() : - mean_(0.0), - sigma2_{0.0, 0.0} -{ -} - -void -DelayDbl::operator=(float delay) -{ - mean_ = delay; - sigma2_[early_index] = 0.0; - sigma2_[late_index] = 0.0; -} - -void -DelayDbl::operator+=(const Delay &delay) -{ - mean_ += delay.mean_; - sigma2_[early_index] += delay.sigma2_[early_index]; - sigma2_[late_index] += delay.sigma2_[late_index]; -} - -void -DelayDbl::operator-=(const Delay &delay) -{ - mean_ -= delay.mean_; - sigma2_[early_index] += delay.sigma2_[early_index]; - sigma2_[late_index] += delay.sigma2_[late_index]; -} - -//////////////////////////////////////////////////////////////// - -Delay -makeDelay(float delay, - float sigma_early, - float sigma_late) -{ - return Delay(delay, square(sigma_early), square(sigma_late)); -} - -Delay -makeDelay2(float delay, - float sigma2_early, - float sigma2_late) -{ - return Delay(delay, sigma2_early, sigma2_late); -} - -bool -delayIsInitValue(const Delay &delay, - const MinMax *min_max) -{ - return fuzzyEqual(delay.mean(), min_max->initValue()) - && fuzzyZero(delay.sigma2Early()) - && fuzzyZero(delay.sigma2Late()); -} - -bool -delayZero(const Delay &delay) -{ - return fuzzyZero(delay.mean()) - && fuzzyZero(delay.sigma2Early()) - && fuzzyZero(delay.sigma2Late()); -} - -bool -delayInf(const Delay &delay) -{ - return fuzzyInf(delay.mean()); -} - -bool -delayEqual(const Delay &delay1, - const Delay &delay2) -{ - return fuzzyEqual(delay1.mean(), delay2.mean()) - && fuzzyEqual(delay1.sigma2Early(), delay2.sigma2Early()) - && fuzzyEqual(delay1.sigma2Late(), delay2.sigma2Late()); -} - -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const StaState *sta) -{ - return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta), - delayAsFloat(delay2, EarlyLate::early(), sta)); -} - -bool -delayLess(const Delay &delay1, - float delay2, - const StaState *sta) -{ - return fuzzyLess(delayAsFloat(delay1, EarlyLate::early(), sta), - delay2); -} - -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta) -{ - if (min_max == MinMax::max()) - return delayLess(delay1, delay2, sta); - else - return delayGreater(delay1, delay2, sta); -} - -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta) -{ - return fuzzyLessEqual(delayAsFloat(delay1, EarlyLate::early(), sta), - delayAsFloat(delay2, EarlyLate::early(), sta)); -} - -bool -delayLessEqual(const Delay &delay1, - float delay2, - const StaState *sta) -{ - return fuzzyLessEqual(delayAsFloat(delay1, EarlyLate::early(), sta), - delay2); -} - -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta) -{ - if (min_max == MinMax::max()) - return delayLessEqual(delay1, delay2, sta); - else - return delayGreaterEqual(delay1, delay2, sta); -} - -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const StaState *sta) -{ - return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta), - delayAsFloat(delay2, EarlyLate::late(), sta)); -} - -bool -delayGreater(const Delay &delay1, - float delay2, - const StaState *sta) -{ - return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), - delayAsFloat(delay2, EarlyLate::late(), sta)); -} - -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta) -{ - return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), - delayAsFloat(delay2, EarlyLate::late(), sta)); -} - -bool -delayGreaterEqual(const Delay &delay1, - float delay2, - const StaState *sta) -{ - return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), - delay2); -} - -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta) -{ - if (min_max == MinMax::max()) - return delayGreater(delay1, delay2, sta); - else - return delayLess(delay1, delay2, sta); -} - -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta) -{ - if (min_max == MinMax::max()) - return delayGreaterEqual(delay1, delay2, sta); - else - return delayLessEqual(delay1, delay2, sta); -} - -float -delayAsFloat(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta) -{ - if (sta->pocvEnabled()) { - if (early_late == EarlyLate::early()) - return delay.mean() - delay.sigma(early_late) * sta->sigmaFactor(); - else if (early_late == EarlyLate::late()) - return delay.mean() + delay.sigma(early_late) * sta->sigmaFactor(); - else - sta->report()->critical(1030, "unknown early/late value."); - } - return delay.mean(); -} - -float -delaySigma2(const Delay &delay, - const EarlyLate *early_late) -{ - return delay.sigma2(early_late); -} - -const char * -delayAsString(const Delay &delay, - const StaState *sta) -{ - return delayAsString(delay, sta, sta->units()->timeUnit()->digits()); -} - -const char * -delayAsString(const Delay &delay, - const StaState *sta, - int digits) -{ - const Unit *unit = sta->units()->timeUnit(); - if (sta->pocvEnabled()) { - float sigma_early = delay.sigma(EarlyLate::early()); - float sigma_late = delay.sigma(EarlyLate::late()); - return stringPrintTmp("%s[%s:%s]", - unit->asString(delay.mean(), digits), - unit->asString(sigma_early, digits), - unit->asString(sigma_late, digits)); - } - else - return unit->asString(delay.mean(), digits); -} - -const char * -delayAsString(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta, - int digits) -{ - float mean_sigma = delayAsFloat(delay, early_late, sta); - return sta->units()->timeUnit()->asString(mean_sigma, digits); -} - -Delay -delayRemove(const Delay &delay1, - const Delay &delay2) -{ - return Delay(delay1.mean() - delay2.mean(), - delay1.sigma2Early() - delay2.sigma2Early(), - delay1.sigma2Late() - delay2.sigma2Late()); -} - -float -delayRatio(const Delay &delay1, - const Delay &delay2) -{ - return delay1.mean() / delay2.mean(); -} - -Delay -operator+(float delay1, - const Delay &delay2) -{ - return Delay(delay1 + delay2.mean(), - delay2.sigma2Early(), - delay2.sigma2Late()); -} - -Delay -operator/(float delay1, - const Delay &delay2) -{ - return Delay(delay1 / delay2.mean(), - delay2.sigma2Early(), - delay2.sigma2Late()); -} - -Delay -operator*(const Delay &delay1, - float delay2) -{ - return Delay(delay1.mean() * delay2, - delay1.sigma2Early() * delay2 * delay2, - delay1.sigma2Late() * delay2 * delay2); -} - -} // namespace - -#endif // (SSTA == 2) diff --git a/graph/Graph.cc b/graph/Graph.cc index b397b7b2..e0c2102d 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -36,6 +36,7 @@ #include "PortDirection.hh" #include "Network.hh" #include "FuncExpr.hh" +#include "Variables.hh" namespace sta { @@ -46,12 +47,10 @@ namespace sta { //////////////////////////////////////////////////////////////// Graph::Graph(StaState *sta, - int slew_rf_count, DcalcAPIndex ap_count) : StaState(sta), vertices_(nullptr), edges_(nullptr), - slew_rf_count_(slew_rf_count), ap_count_(ap_count), period_check_annotations_(nullptr), reg_clk_vertices_(makeVertexSet(this)) @@ -583,15 +582,31 @@ Graph::slew(const Vertex *vertex, const RiseFall *rf, DcalcAPIndex ap_index) { - if (slew_rf_count_) { - const Slew *slews = vertex->slews(); - size_t slew_index = (slew_rf_count_ == 1) - ? ap_index - : ap_index*slew_rf_count_+rf->index(); + size_t slew_index = ap_index * RiseFall::index_count + rf->index(); + const float *slews_flt = vertex->slewsFloat(); + if (variables_->pocvEnabled()) { + const Slew *slews = std::bit_cast(slews_flt); return slews[slew_index]; } else { - static Slew slew(0.0); + static Slew slew; + slew = slews_flt[slew_index]; + return slew; + } +} + +const Slew & +Graph::slew(const Vertex *vertex, + size_t index) +{ + const float *slews_flt = vertex->slewsFloat(); + if (variables_->pocvEnabled()) { + const Slew *slews = std::bit_cast(slews_flt); + return slews[index]; + } + else { + static Slew slew; + slew = slews_flt[index]; return slew; } } @@ -602,18 +617,15 @@ Graph::setSlew(Vertex *vertex, DcalcAPIndex ap_index, const Slew &slew) { - if (slew_rf_count_) { + size_t slew_index = ap_index * RiseFall::index_count + rf->index(); + if (variables_->pocvEnabled()) { Slew *slews = vertex->slews(); - if (slews == nullptr) { - int slew_count = slew_rf_count_ * ap_count_; - slews = new Slew[slew_count]; - vertex->setSlews(slews); - } - size_t slew_index = (slew_rf_count_ == 1) - ? ap_index - : ap_index*slew_rf_count_+rf->index(); slews[slew_index] = slew; } + else { + float *slews_flt = vertex->slewsFloat(); + slews_flt[slew_index] = slew.mean(); + } } //////////////////////////////////////////////////////////////// @@ -665,25 +677,39 @@ Graph::deleteEdge(Edge *edge) edges_->destroy(edge); } -ArcDelay +const ArcDelay & Graph::arcDelay(const Edge *edge, const TimingArc *arc, DcalcAPIndex ap_index) const { - ArcDelay *delays = edge->arcDelays(); size_t index = arc->index() * ap_count_ + ap_index; - return delays[index]; + if (variables_->pocvEnabled()) { + ArcDelay *delays = std::bit_cast(edge->arcDelays()); + return delays[index]; + } + else { + const float *delays = edge->arcDelays(); + static ArcDelay delay; + delay = delays[index]; + return delay; + } } void Graph::setArcDelay(Edge *edge, const TimingArc *arc, DcalcAPIndex ap_index, - ArcDelay delay) + const ArcDelay &delay) { - ArcDelay *arc_delays = edge->arcDelays(); size_t index = arc->index() * ap_count_ + ap_index; - arc_delays[index] = delay; + if (variables_->pocvEnabled()) { + ArcDelay *delays = std::bit_cast(edge->arcDelays()); + delays[index] = delay; + } + else { + float *delays = edge->arcDelays(); + delays[index] = delay.mean(); + } } const ArcDelay & @@ -691,9 +717,17 @@ Graph::wireArcDelay(const Edge *edge, const RiseFall *rf, DcalcAPIndex ap_index) { - ArcDelay *delays = edge->arcDelays(); size_t index = rf->index() * ap_count_ + ap_index; - return delays[index]; + if (variables_->pocvEnabled()) { + ArcDelay *delays = std::bit_cast(edge->arcDelays()); + return delays[index]; + } + else { + const float *delays = edge->arcDelays(); + static ArcDelay delay; + delay = delays[index]; + return delay; + } } void @@ -702,9 +736,15 @@ Graph::setWireArcDelay(Edge *edge, DcalcAPIndex ap_index, const ArcDelay &delay) { - ArcDelay *delays = edge->arcDelays(); size_t index = rf->index() * ap_count_ + ap_index; - delays[index] = delay; + if (variables_->pocvEnabled()) { + ArcDelay *delays = std::bit_cast(edge->arcDelays()); + delays[index] = delay; + } + else { + float *delays = edge->arcDelays(); + delays[index] = delay.mean(); + } } //////////////////////////////////////////////////////////////// @@ -788,16 +828,20 @@ void Graph::initSlews(Vertex *vertex) { size_t slew_count = slewCount(); - Slew *slews = new Slew[slew_count]; - vertex->setSlews(slews); - for (size_t i = 0; i < slew_count; i++) - slews[i] = 0.0; + if (variables_->pocvEnabled()) { + float *slews = std::bit_cast(new Slew[slew_count]{}); + vertex->setSlews(slews); + } + else { + float *slews = new float[slew_count]{}; + vertex->setSlews(slews); + } } size_t Graph::slewCount() { - return slew_rf_count_ * ap_count_; + return RiseFall::index_count * ap_count_; } void @@ -805,10 +849,14 @@ Graph::initArcDelays(Edge *edge) { size_t arc_count = edge->timingArcSet()->arcCount(); size_t delay_count = arc_count * ap_count_; - ArcDelay *arc_delays = new ArcDelay[delay_count]; - edge->setArcDelays(arc_delays); - for (size_t i = 0; i < delay_count; i++) - arc_delays[i] = 0.0; + if (variables_->pocvEnabled()) { + float *delays = std::bit_cast(new ArcDelay[delay_count]{}); + edge->setArcDelays(delays); + } + else { + float *delays = new float[delay_count]{}; + edge->setArcDelays(delays); + } } //////////////////////////////////////////////////////////////// @@ -1040,7 +1088,7 @@ Vertex::setVisited2(bool visited) } void -Vertex::setSlews(Slew *slews) +Vertex::setSlews(float *slews) { delete [] slews_; slews_ = slews; @@ -1251,10 +1299,10 @@ Edge::setTimingArcSet(TimingArcSet *set) } void -Edge::setArcDelays(ArcDelay *arc_delays) +Edge::setArcDelays(float *delays) { delete [] arc_delays_; - arc_delays_ = arc_delays; + arc_delays_ = delays; } bool diff --git a/graph/Graph.i b/graph/Graph.i index 5c16e5f8..cd8188c9 100644 --- a/graph/Graph.i +++ b/graph/Graph.i @@ -132,21 +132,24 @@ bool is_bidirect_driver() { return self->isBidirectDriver(); } int level() { return Sta::sta()->vertexLevel(self); } int tag_group_index() { return self->tagGroupIndex(); } -Slew +float slew(const RiseFallBoth *rf, const MinMax *min_max) { Sta *sta = Sta::sta(); - return sta->slew(self, rf, sta->scenes(), min_max); + return delayAsFloat(sta->slew(self, rf, sta->scenes(), min_max), min_max, sta); } -Slew -slew_scenes(const RiseFallBoth *rf, - const SceneSeq scenes, - const MinMax *min_max) +std::string +slew_scenes_string(const RiseFallBoth *rf, + const SceneSeq scenes, + const MinMax *min_max, + bool report_variance, + int digits) { Sta *sta = Sta::sta(); - return sta->slew(self, rf, scenes, min_max); + Slew slew = sta->slew(self, rf, scenes, min_max); + return delayAsString(slew, min_max, report_variance, digits, sta); } VertexOutEdgeIterator * @@ -223,22 +226,29 @@ arc_delays(TimingArc *arc) { Sta *sta = Sta::sta(); FloatSeq delays; - DcalcAPIndex ap_count = sta->dcalcAnalysisPtCount(); - for (DcalcAPIndex ap_index = 0; ap_index < ap_count; ap_index++) - delays.push_back(delayAsFloat(sta->arcDelay(self, arc, ap_index))); + for (Scene *scene : sta->scenes()) { + for (const MinMax *min_max : MinMax::range()) { + DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); + delays.push_back(delayAsFloat(sta->arcDelay(self, arc, ap_index), min_max, sta)); + } + } return delays; } StringSeq arc_delay_strings(TimingArc *arc, + bool report_variance, int digits) { Sta *sta = Sta::sta(); StringSeq delays; - DcalcAPIndex ap_count = sta->dcalcAnalysisPtCount(); - for (DcalcAPIndex ap_index = 0; ap_index < ap_count; ap_index++) - delays.push_back(delayAsString(sta->arcDelay(self, arc, ap_index), - sta, digits)); + for (Scene *scene : sta->scenes()) { + for (const MinMax *min_max : MinMax::range()) { + DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); + delays.push_back(delayAsString(sta->arcDelay(self, arc, ap_index), + min_max, report_variance, digits, sta)); + } + } return delays; } @@ -255,8 +265,9 @@ arc_delay(TimingArc *arc, const Scene *scene, const MinMax *min_max) { + Sta *sta = Sta::sta(); DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); - return delayAsFloat(Sta::sta()->arcDelay(self, arc, ap_index)); + return delayAsFloat(Sta::sta()->arcDelay(self, arc, ap_index), min_max, sta); } std::string diff --git a/graph/Graph.tcl b/graph/Graph.tcl index 27ea5f19..3d04bf68 100644 --- a/graph/Graph.tcl +++ b/graph/Graph.tcl @@ -26,51 +26,64 @@ namespace eval sta { -define_cmd_args "report_edges" {[-from from_pin] [-to to_pin]} +define_cmd_args "report_edges" {[-from from_pin] [-to to_pin]\ + [-digits digits] [-report_variance]} proc report_edges { args } { - parse_key_args "report_edges" args keys {-from -to} flags {} + global sta_report_default_digits + + parse_key_args "report_edges" args keys {-from -to -digits} flags {-report_variance} check_argc_eq0 "report_edges" $args + if [info exists keys(-digits)] { + set digits $keys(-digits) + check_positive_integer "-digits" $digits + } else { + set digits $sta_report_default_digits + } + + set report_variance [info exists flags(-report_variance)] + if { [info exists keys(-from)] && [info exists keys(-to)] } { set from_pin [get_port_pin_error "from_pin" $keys(-from)] set to_pin [get_port_pin_error "to_pin" $keys(-to)] foreach from_vertex [$from_pin vertices] { foreach to_vertex [$to_pin vertices] { - report_edges_between_ $from_vertex $to_vertex + report_edges_between_ $from_vertex $to_vertex $digits $report_variance } } } elseif [info exists keys(-from)] { set from_pin [get_port_pin_error "from_pin" $keys(-from)] foreach from_vertex [$from_pin vertices] { report_edges_ $from_vertex out_edge_iterator \ - vertex_port_name vertex_path_name + vertex_port_name vertex_path_name $digits $report_variance } } elseif [info exists keys(-to)] { set to_pin [get_port_pin_error "to_pin" $keys(-to)] foreach to_vertex [$to_pin vertices] { report_edges_ $to_vertex in_edge_iterator \ - vertex_path_name vertex_port_name + vertex_path_name vertex_port_name $digits $report_variance } } } -proc report_edges_between_ { from_vertex to_vertex } { +proc report_edges_between_ { from_vertex to_vertex digits report_variance } { set iter [$from_vertex out_edge_iterator] while {[$iter has_next]} { set edge [$iter next] if { [$edge to] == $to_vertex } { if { [$edge role] == "wire" } { - report_edge_ $edge vertex_path_name vertex_path_name + report_edge_ $edge vertex_path_name vertex_path_name $digits $report_variance } else { - report_edge_ $edge vertex_port_name vertex_port_name + report_edge_ $edge vertex_port_name vertex_port_name $digits $report_variance } } } $iter finish } -proc report_edges_ { vertex iter_proc wire_from_name_proc wire_to_name_proc } { +proc report_edges_ { vertex iter_proc wire_from_name_proc wire_to_name_proc \ + digits report_variance } { # First report edges internal to the device. set device_header 0 set iter [$vertex $iter_proc] @@ -84,7 +97,7 @@ proc report_edges_ { vertex iter_proc wire_from_name_proc wire_to_name_proc } { } set device_header 1 } - report_edge_ $edge vertex_port_name vertex_port_name + report_edge_ $edge vertex_port_name vertex_port_name $digits $report_variance } } $iter finish @@ -94,15 +107,14 @@ proc report_edges_ { vertex iter_proc wire_from_name_proc wire_to_name_proc } { while {[$iter has_next]} { set edge [$iter next] if { [$edge role] == "wire" } { - report_edge_ $edge $wire_from_name_proc $wire_to_name_proc + report_edge_ $edge $wire_from_name_proc $wire_to_name_proc $digits $report_variance } } $iter finish } -proc report_edge_ { edge vertex_from_name_proc vertex_to_name_proc } { - global sta_report_default_digits - +proc report_edge_ { edge vertex_from_name_proc vertex_to_name_proc \ + digits report_variance } { set latch_enable [$edge latch_d_to_q_en] if { $latch_enable != "" } { set latch_enable " enable $latch_enable" @@ -125,7 +137,7 @@ proc report_edge_ { edge vertex_from_name_proc vertex_to_name_proc } { } foreach arc [$edge timing_arcs] { - set delays [$edge arc_delay_strings $arc $sta_report_default_digits] + set delays [$edge arc_delay_strings $arc $report_variance $digits] set delays_fmt [format_delays $delays] set disable_reason "" if { [timing_arc_disabled $edge $arc] } { @@ -135,18 +147,6 @@ proc report_edge_ { edge vertex_from_name_proc vertex_to_name_proc } { } } -# Separate list elements with colons. -proc format_times { values digits } { - set result "" - foreach value $values { - if { $result != "" } { - append result ":" - } - append result [format_time $value $digits] - } - return $result -} - # Separate delay list elements with colons. proc format_delays { values } { set result "" diff --git a/include/sta/ArcDelayCalc.hh b/include/sta/ArcDelayCalc.hh index d2b99012..45dcbae3 100644 --- a/include/sta/ArcDelayCalc.hh +++ b/include/sta/ArcDelayCalc.hh @@ -119,15 +119,15 @@ public: ArcDcalcResult(size_t load_count); void setLoadCount(size_t load_count); ArcDelay &gateDelay() { return gate_delay_; } - void setGateDelay(ArcDelay gate_delay); + void setGateDelay(const ArcDelay &gate_delay); Slew &drvrSlew() { return drvr_slew_; } - void setDrvrSlew(Slew drvr_slew); - ArcDelay wireDelay(size_t load_idx) const; + void setDrvrSlew(const Slew &drvr_slew); + const ArcDelay &wireDelay(size_t load_idx) const; void setWireDelay(size_t load_idx, - ArcDelay wire_delay); - Slew loadSlew(size_t load_idx) const; + const ArcDelay &wire_delay); + const Slew &loadSlew(size_t load_idx) const; void setLoadSlew(size_t load_idx, - Slew load_slew); + const Slew &load_slew); protected: ArcDelay gate_delay_; diff --git a/include/sta/Delay.hh b/include/sta/Delay.hh index 860b23da..24b97c60 100644 --- a/include/sta/Delay.hh +++ b/include/sta/Delay.hh @@ -24,27 +24,326 @@ #pragma once -#include "StaConfig.hh" +#include +#include -// IWYU pragma: begin_exports -#if (SSTA == 1) - // Delays are Normal PDFs. - #include "DelayNormal1.hh" -#elif (SSTA == 2) - // Delays are Normal PDFs with early/late sigma. - #include "DelayNormal2.hh" -#else - // Delays are floats. - #include "DelayFloat.hh" -#endif -// IWYU pragma: end_exports +#include "StaConfig.hh" +#include "MinMax.hh" namespace sta { +class StaState; + +class Delay +{ +public: + Delay(); + Delay(float mean); + Delay(float mean, + // std_dev^2 + float std_dev2); + Delay(float mean, + float mean_shift, + // std_dev^2 + float std_dev2, + float skewness); + void setValues(float mean, + float mean_shift, + float std_dev2, + float skewnes); + float mean() const { return values_[0]; } + void setMean(float mean); + float meanShift() const { return values_[1]; } + void setMeanShift(float mean_shift); + float stdDev() const; + // std_dev ^ 2 + float stdDev2() const { return values_[2]; } + void setStdDev(float std_dev); + float skewness() const { return values_[3]; } + void setSkewness(float skewness); + + void operator=(float delay); + +private: + std::array values_; +}; + +// Delay with doubles for accumulating Delays. +// Only a subset of operations are required for DelayDbl. +class DelayDbl +{ +public: + DelayDbl(); + DelayDbl(double value); + double mean() const { return values_[0]; } + void setMean(double mean); + double meanShift() const { return values_[1]; } + // std_dev ^ 2 + double stdDev2() const { return values_[2]; } + double stdDev() const; + double skewness() const { return values_[3]; } + void setValues(double mean, + double mean_shift, + double std_dev2, + double skewnes); + + void operator=(double delay); + +private: + std::array values_; +}; + using ArcDelay = Delay; using Slew = Delay; using Arrival = Delay; using Required = Delay; using Slack = Delay; +const Delay delay_zero(0.0); + +class DelayOps +{ +public: + virtual ~DelayOps() {} + virtual float stdDev2(const Delay &delay, + const EarlyLate *early_late) const = 0; + virtual float asFloat(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) const = 0; + virtual double asFloat(const DelayDbl &delay, + const EarlyLate *early_late, + const StaState *sta) const = 0; + virtual bool isZero(const Delay &delay) const = 0; + virtual bool isInf(const Delay &delay) const = 0; + virtual bool equal(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const = 0; + virtual bool less(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const = 0; + virtual bool less(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *sta) const = 0; + virtual bool lessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const = 0; + virtual bool greater(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const = 0; + virtual bool greaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const = 0; + virtual Delay sum(const Delay &delay1, + const Delay &delay2) const = 0; + virtual Delay sum(const Delay &delay1, + float delay2) const = 0; + virtual Delay diff(const Delay &delay1, + const Delay &delay2) const = 0; + virtual Delay diff(const Delay &delay1, + float delay2) const = 0; + virtual Delay diff(float delay1, + const Delay &delay2) const = 0; + virtual void incr(Delay &delay1, + const Delay &delay2) const = 0; + virtual void incr(DelayDbl &delay1, + const Delay &delay2) const = 0; + virtual void decr(Delay &delay1, + const Delay &delay2) const = 0; + virtual void decr(DelayDbl &delay1, + const Delay &delay2) const = 0; + virtual Delay product(const Delay &delay1, + float delay2) const = 0; + virtual Delay div(float delay1, + const Delay &delay2) const = 0; + virtual const char *asStringVariance(const Delay &delay, + int digits, + const StaState *sta) const = 0; + +}; + +void +initDelayConstants(); + +inline float +square(float x) +{ + return x * x; +} + +inline double +square(double x) +{ + return x * x; +} + +inline float +cube(float x) +{ + return x * x * x; +} + +inline double +cube(double x) +{ + return x * x * x; +} + +Delay +makeDelay(float mean, + float mean_shift, + float std_dev, + float skewness); +Delay +makeDelay(float mean, + float std_dev); +Delay +makeDelay2(float mean, + float std_dev); +void +delaySetMean(Delay &delay, + float mean); + +const char * +delayAsString(const Delay &delay, + const StaState *sta); +const char * +delayAsString(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta); +const char * +delayAsString(const Delay &delay, + const EarlyLate *early_late, + int digits, + const StaState *sta); +const char * +delayAsString(const Delay &delay, + const EarlyLate *early_late, + bool report_variance, + int digits, + const StaState *sta); + +float +delayAsFloat(const Delay &delay); +float +delayAsFloat(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta); +float +delayAsFloat(const DelayDbl &delay, + const EarlyLate *early_late, + const StaState *sta); + +Delay +delayDblAsDelay(DelayDbl &delay); + +Delay +delaySum(const Delay &delay1, + const Delay &delay2, + const StaState *sta); +Delay +delaySum(const Delay &delay1, + float delay2, + const StaState *sta); +Delay +delayDiff(const Delay &delay1, + const Delay &delay2, + const StaState *sta); +Delay +delayDiff(const Delay &delay1, + float delay2, + const StaState *sta); +Delay +delayDiff(float delay1, + const Delay &delay2, + const StaState *sta); +void +delayIncr(Delay &delay1, + const Delay &delay2, + const StaState *sta); +void +delayIncr(DelayDbl &delay1, + const Delay &delay2, + const StaState *sta); +void +delayIncr(Delay &delay1, + float delay2, + const StaState *sta); +void +delayDecr(Delay &delay1, + const Delay &delay2, + const StaState *sta); +void +delayDecr(DelayDbl &delay1, + const Delay &delay2, + const StaState *sta); +Delay +delayProduct(const Delay &delay1, + float delay2, + const StaState *sta); +Delay +delayDiv(float delay1, + const Delay &delay2, + const StaState *sta); + +const Delay & +delayInitValue(const MinMax *min_max); +bool +delayIsInitValue(const Delay &delay, + const MinMax *min_max); +bool +delayZero(const Delay &delay, + const StaState *sta); +bool +delayInf(const Delay &delay, + const StaState *sta); +bool +delayEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta); +bool +delayLess(const Delay &delay1, + const Delay &delay2, + const StaState *sta); +bool +delayLess(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *sta); +bool +delayLess(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max, + const StaState *sta); +bool +delayLessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta); +bool +delayLessEqual(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max, + const StaState *sta); +bool +delayGreater(const Delay &delay1, + const Delay &delay2, + const StaState *sta); +bool +delayGreaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta); +bool +delayGreaterEqual(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max, + const StaState *sta); +bool +delayGreater(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max, + const StaState *sta); + +// delay1-delay2 subtracting sigma instead of addiing. +Delay +delayRemove(const Delay &delay1, + const Delay &delay2); + } // namespace diff --git a/include/sta/DelayFloat.hh b/include/sta/DelayFloat.hh deleted file mode 100644 index 81f047b9..00000000 --- a/include/sta/DelayFloat.hh +++ /dev/null @@ -1,152 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2026, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "MinMax.hh" - -// Delay values defined as floats. - -namespace sta { - -class StaState; - -using Delay = float; -// Delay double for accumulating Delays. -using DelayDbl = double; - -const Delay delay_zero = 0.0; - -void -initDelayConstants(); - -const char * -delayAsString(const Delay &delay, - const StaState *sta); -const char * -delayAsString(const Delay &delay, - const StaState *sta, - int digits); -const char * -delayAsString(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta, - int digits); - -inline Delay -makeDelay(float delay, - float, - float) -{ - return delay; -} - -inline Delay -makeDelay2(float delay, - float, - float) -{ - return delay; -} - -inline float -delayAsFloat(const Delay &delay) -{ - return delay; -} - -// mean late+/early- sigma -inline float -delayAsFloat(const Delay &delay, - const EarlyLate *, - const StaState *) -{ - return delay; -} - -inline float -delaySigma2(const Delay &, - const EarlyLate *) -{ - return 0.0; -} - -const Delay & -delayInitValue(const MinMax *min_max); -bool -delayIsInitValue(const Delay &delay, - const MinMax *min_max); -bool -delayZero(const Delay &delay); -bool -delayInf(const Delay &delay); -bool -delayEqual(const Delay &delay1, - const Delay &delay2); -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); - -// delay1-delay2 subtracting sigma instead of addiing. -Delay -delayRemove(const Delay &delay1, - const Delay &delay2); -float -delayRatio(const Delay &delay1, - const Delay &delay2); - -} // namespace diff --git a/include/sta/DelayNormal.hh b/include/sta/DelayNormal.hh new file mode 100644 index 00000000..0d102962 --- /dev/null +++ b/include/sta/DelayNormal.hh @@ -0,0 +1,90 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#pragma once + +#include "Delay.hh" + +namespace sta { + +class DelayOpsNormal : public DelayOps +{ +public: + float stdDev2(const Delay &delay, + const EarlyLate *early_late) const override; + float asFloat(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) const override; + double asFloat(const DelayDbl &delay, + const EarlyLate *early_late, + const StaState *sta) const override; + + bool isZero(const Delay &delay) const override; + bool isInf(const Delay &delay) const override; + bool equal(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool less(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool less(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *sta) const override; + bool lessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool greater(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool greaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + Delay sum(const Delay &delay1, + const Delay &delay2) const override; + Delay sum(const Delay &delay1, + float delay2) const override; + Delay diff(const Delay &delay1, + const Delay &delay2) const override; + Delay diff(const Delay &delay1, + float delay2) const override; + Delay diff(float delay1, + const Delay &delay2) const override; + void incr(Delay &delay1, + const Delay &delay2) const override; + void incr(DelayDbl &delay1, + const Delay &delay2) const override; + void decr(Delay &delay1, + const Delay &delay2) const override; + void decr(DelayDbl &delay1, + const Delay &delay2) const override; + Delay product(const Delay &delay1, + float delay2) const override; + Delay div(float delay1, + const Delay &delay2) const override; + const char *asStringVariance(const Delay &delay, + int digits, + const StaState *sta) const override; +}; + +} // namespace diff --git a/include/sta/DelayNormal1.hh b/include/sta/DelayNormal1.hh deleted file mode 100644 index 5787797f..00000000 --- a/include/sta/DelayNormal1.hh +++ /dev/null @@ -1,203 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2026, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "MinMax.hh" - -namespace sta { - -class Delay; -class DelayDbl; -class StaState; - -// Normal distribution with std deviation. -class Delay -{ -public: - Delay(); - Delay(const Delay &delay); - Delay(const DelayDbl &delay); - Delay(float mean); - Delay(float mean, - float sigma2); - float mean() const { return mean_; } - float sigma() const; - // sigma^2 - float sigma2() const; - void operator=(const Delay &delay); - void operator=(float delay); - void operator+=(const Delay &delay); - void operator+=(float delay); - Delay operator+(const Delay &delay) const; - Delay operator+(float delay) const; - Delay operator-(const Delay &delay) const; - Delay operator-(float delay) const; - Delay operator-() const; - void operator-=(float delay); - void operator-=(const Delay &delay); - bool operator==(const Delay &delay) const; - -private: - float mean_; - // Sigma^2 - float sigma2_; - - friend class DelayDbl; -}; - -// Dwlay with doubles for accumulating delays. -class DelayDbl -{ -public: - DelayDbl(); - float mean() const { return mean_; } - float sigma() const; - // sigma^2 - float sigma2() const; - void operator=(float delay); - void operator+=(const Delay &delay); - void operator-=(const Delay &delay); - -private: - double mean_; - // Sigma^2 - double sigma2_; - - friend class Delay; -}; - -const Delay delay_zero(0.0); - -void -initDelayConstants(); - -const char * -delayAsString(const Delay &delay, - const StaState *sta); -const char * -delayAsString(const Delay &delay, - const StaState *sta, - int digits); -const char * -delayAsString(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta, - int digits); - -Delay -makeDelay(float delay, - float sigma_early, - float sigma_late); - -Delay -makeDelay2(float delay, - // sigma^2 - float sigma_early, - float sigma_late); - -inline float -delayAsFloat(const Delay &delay) -{ - return delay.mean(); -} - -// mean late+/early- sigma -float -delayAsFloat(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta); -float -delaySigma2(const Delay &delay, - const EarlyLate *early_late); -const Delay & -delayInitValue(const MinMax *min_max); -bool -delayIsInitValue(const Delay &delay, - const MinMax *min_max); -bool -delayZero(const Delay &delay); -bool -delayInf(const Delay &delay); -bool -delayEqual(const Delay &delay1, - const Delay &delay2); -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); - -// delay1-delay2 subtracting sigma instead of addiing. -Delay delayRemove(const Delay &delay1, - const Delay &delay2); -float -delayRatio(const Delay &delay1, - const Delay &delay2); - -// Most non-operator functions on Delay are not defined as member -// functions so they can be defined on floats, where there is no class -// to define them. - -Delay operator+(float delay1, - const Delay &delay2); -// Used for parallel gate delay calc. -Delay operator/(float delay1, - const Delay &delay2); -// Used for parallel gate delay calc. -Delay operator*(const Delay &delay1, - float delay2); - -} // namespace diff --git a/include/sta/DelayNormal2.hh b/include/sta/DelayNormal2.hh deleted file mode 100644 index 7355fd77..00000000 --- a/include/sta/DelayNormal2.hh +++ /dev/null @@ -1,214 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2026, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "MinMax.hh" - -namespace sta { - -class Delay; -class DelayDbl; -class StaState; - -// Normal distribution with early(left)/late(right) std deviations. -class Delay -{ -public: - Delay(); - Delay(const Delay &delay); - Delay(const DelayDbl &delay); - Delay(float mean); - Delay(float mean, - float sigma2_early, - float sigma2_late); - float mean() const { return mean_; } - float sigma(const EarlyLate *early_late) const; - // sigma^2 - float sigma2(const EarlyLate *early_late) const; - float sigma2Early() const; - float sigma2Late() const; - void operator=(const Delay &delay); - void operator=(float delay); - void operator+=(const Delay &delay); - void operator+=(float delay); - Delay operator+(const Delay &delay) const; - Delay operator+(float delay) const; - Delay operator-(const Delay &delay) const; - Delay operator-(float delay) const; - Delay operator-() const; - void operator-=(float delay); - void operator-=(const Delay &delay); - bool operator==(const Delay &delay) const; - -protected: - static const int early_index = 0; - static const int late_index = 1; - -private: - float mean_; - // Sigma^2 - float sigma2_[EarlyLate::index_count]; - - friend class DelayDbl; -}; - -// Dwlay with doubles for accumulating delays. -class DelayDbl -{ -public: - DelayDbl(); - float mean() const { return mean_; } - float sigma() const; - // sigma^2 - float sigma2() const; - void operator=(float delay); - void operator+=(const Delay &delay); - void operator-=(const Delay &delay); - -protected: - static const int early_index = 0; - static const int late_index = 1; - -private: - double mean_; - // Sigma^2 - double sigma2_[EarlyLate::index_count]; - - friend class Delay; -}; - -const Delay delay_zero(0.0); - -void -initDelayConstants(); - -const char * -delayAsString(const Delay &delay, - const StaState *sta); -const char * -delayAsString(const Delay &delay, - const StaState *sta, - int digits); -const char * -delayAsString(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta, - int digits); - -Delay -makeDelay(float delay, - float sigma_early, - float sigma_late); - -Delay -makeDelay2(float delay, - // sigma^2 - float sigma_early, - float sigma_late); - -inline float -delayAsFloat(const Delay &delay) -{ - return delay.mean(); -} - -// mean late+/early- sigma -float -delayAsFloat(const Delay &delay, - const EarlyLate *early_late, - const StaState *sta); -float -delaySigma2(const Delay &delay, - const EarlyLate *early_late); -const Delay & -delayInitValue(const MinMax *min_max); -bool -delayIsInitValue(const Delay &delay, - const MinMax *min_max); -bool -delayZero(const Delay &delay); -bool -delayInf(const Delay &delay); -bool -delayEqual(const Delay &delay1, - const Delay &delay2); -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayLess(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayLessEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const StaState *sta); -bool -delayGreaterEqual(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); -bool -delayGreater(const Delay &delay1, - const Delay &delay2, - const MinMax *min_max, - const StaState *sta); - -// delay1-delay2 subtracting sigma instead of addiing. -Delay delayRemove(const Delay &delay1, - const Delay &delay2); -float -delayRatio(const Delay &delay1, - const Delay &delay2); - -// Most non-operator functions on Delay are not defined as member -// functions so they can be defined on floats, where there is no class -// to define them. - -Delay operator+(float delay1, - const Delay &delay2); -// Used for parallel gate delay calc. -Delay operator/(float delay1, - const Delay &delay2); -// Used for parallel gate delay calc. -Delay operator*(const Delay &delay1, - float delay2); - -} // namespace diff --git a/include/sta/DelayScalar.hh b/include/sta/DelayScalar.hh new file mode 100644 index 00000000..c7bd07a9 --- /dev/null +++ b/include/sta/DelayScalar.hh @@ -0,0 +1,90 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#pragma once + +#include "Delay.hh" + +namespace sta { + +class DelayOpsScalar : public DelayOps +{ +public: + float stdDev2(const Delay &delay, + const EarlyLate *early_late) const override; + float asFloat(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) const override; + double asFloat(const DelayDbl &delay, + const EarlyLate *early_late, + const StaState *sta) const override; + + bool isZero(const Delay &delay) const override; + bool isInf(const Delay &delay) const override; + bool equal(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool less(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool less(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *sta) const override; + bool lessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool greater(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool greaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + Delay sum(const Delay &delay1, + const Delay &delay2) const override; + Delay sum(const Delay &delay1, + float delay2) const override; + Delay diff(const Delay &delay1, + const Delay &delay2) const override; + Delay diff(const Delay &delay1, + float delay2) const override; + Delay diff(float delay1, + const Delay &delay2) const override; + void incr(Delay &delay1, + const Delay &delay2) const override; + void incr(DelayDbl &delay1, + const Delay &delay2) const override; + void decr(Delay &delay1, + const Delay &delay2) const override; + void decr(DelayDbl &delay1, + const Delay &delay2) const override; + Delay product(const Delay &delay1, + float delay2) const override; + Delay div(float delay1, + const Delay &delay2) const override; + const char *asStringVariance(const Delay &delay, + int digits, + const StaState *sta) const override; +}; + +} // namespace diff --git a/include/sta/DelaySkewNormal.hh b/include/sta/DelaySkewNormal.hh new file mode 100644 index 00000000..090f5701 --- /dev/null +++ b/include/sta/DelaySkewNormal.hh @@ -0,0 +1,98 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#pragma once + +#include "Delay.hh" + +namespace sta { + +class DelayOpsSkewNormal : public DelayOps +{ +public: + float stdDev2(const Delay &delay, + const EarlyLate *early_late) const override; + float asFloat(const Delay &delay, + const EarlyLate *early_late, + const StaState *sta) const override; + double asFloat(const DelayDbl &delay, + const EarlyLate *early_late, + const StaState *sta) const override; + + bool isZero(const Delay &delay) const override; + bool isInf(const Delay &delay) const override; + bool equal(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool less(const Delay &delay1, + const Delay &delay2, + const StaState *sta) const override; + bool less(const DelayDbl &delay1, + const DelayDbl &delay2, + const StaState *sta) const override; + bool lessEqual(const Delay &delay1, + const Delay &delay2, + const StaState *) const override; + bool greater(const Delay &delay1, + const Delay &delay2, + const StaState *) const override; + bool greaterEqual(const Delay &delay1, + const Delay &delay2, + const StaState *) const override; + Delay sum(const Delay &delay1, + const Delay &delay2) const override; + Delay sum(const Delay &delay1, + float delay2) const override; + Delay diff(const Delay &delay1, + const Delay &delay2) const override; + Delay diff(const Delay &delay1, + float delay2) const override; + Delay diff(float delay1, + const Delay &delay2) const override; + void incr(Delay &delay1, + const Delay &delay2) const override; + void incr(DelayDbl &delay1, + const Delay &delay2) const override; + void decr(Delay &delay1, + const Delay &delay2) const override; + void decr(DelayDbl &delay1, + const Delay &delay2) const override; + Delay product(const Delay &delay1, + float delay2) const override; + Delay div(float delay1, + const Delay &delay2) const override; + const char *asStringVariance(const Delay &delay, + int digits, + const StaState *sta) const override; + +private: + float skewnessSum(const Delay &delay1, + const Delay &delay2) const; + double skewnessSum(double std_dev1, + double skewness1, + double std_dev2, + double skewness2) const; +}; + +} // namespace diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index e96a2c64..18a50015 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -58,13 +58,7 @@ static constexpr ObjectIdx vertex_idx_null = object_idx_null; class Graph : public StaState { public: - // slew_rf_count is - // 0 no slews - // 1 one slew for rise/fall - // 2 rise/fall slews - // ap_count is the dcalc analysis point count. Graph(StaState *sta, - int slew_rf_count, DcalcAPIndex ap_count); void makeGraph(); ~Graph(); @@ -100,6 +94,8 @@ public: const Slew &slew(const Vertex *vertex, const RiseFall *rf, DcalcAPIndex ap_index); + const Slew &slew(const Vertex *vertex, + size_t index); void setSlew(Vertex *vertex, const RiseFall *rf, DcalcAPIndex ap_index, @@ -128,13 +124,13 @@ public: Edge *&edge, const TimingArc *&arc) const; - ArcDelay arcDelay(const Edge *edge, - const TimingArc *arc, - DcalcAPIndex ap_index) const; + const ArcDelay &arcDelay(const Edge *edge, + const TimingArc *arc, + DcalcAPIndex ap_index) const; void setArcDelay(Edge *edge, const TimingArc *arc, DcalcAPIndex ap_index, - ArcDelay delay); + const ArcDelay &delay); // Alias for arcDelays using library wire arcs. const ArcDelay &wireArcDelay(const Edge *edge, const RiseFall *rf, @@ -222,7 +218,6 @@ protected: // driver/source (top level input, instance pin output) vertex // in pin_bidirect_drvr_vertex_map PinVertexMap pin_bidirect_drvr_vertex_map_; - int slew_rf_count_; DcalcAPIndex ap_count_; // Sdf period check annotations. PeriodCheckAnnotations *period_check_annotations_; @@ -258,8 +253,6 @@ public: [[nodiscard]] bool isRoot() const{ return level_ == 0; } [[nodiscard]] bool hasFanin() const; [[nodiscard]] bool hasFanout() const; - Slew *slews() { return slews_; } - const Slew *slews() const { return slews_; } Path *paths() const { return paths_; } Path *makePaths(uint32_t count); void setPaths(Path *paths); @@ -298,14 +291,18 @@ protected: bool is_bidirect_drvr, bool is_reg_clk); void clear(); - void setSlews(Slew *slews); + Slew *slews() { return std::bit_cast(slews_); } + const Slew *slews() const { return std::bit_cast(slews_); } + float *slewsFloat() { return slews_; } + const float *slewsFloat() const { return slews_; } + void setSlews(float *slews); Pin *pin_; EdgeId in_edges_; // Edges to this vertex. EdgeId out_edges_; // Edges from this vertex. // Delay calc - Slew *slews_; + float *slews_; // Search Path *paths_; @@ -356,8 +353,9 @@ public: TimingSense sense() const; TimingArcSet *timingArcSet() const { return arc_set_; } void setTimingArcSet(TimingArcSet *set); - ArcDelay *arcDelays() const { return arc_delays_; } - void setArcDelays(ArcDelay *arc_delays); + float *arcDelays() { return arc_delays_; } + const float *arcDelays() const { return arc_delays_; } + void setArcDelays(float *delays); bool delay_Annotation_Is_Incremental() const {return delay_annotation_is_incremental_;}; void setDelayAnnotationIsIncremental(bool is_incr); // Edge is disabled to break combinational loops. @@ -398,7 +396,7 @@ protected: EdgeId vertex_in_link_; // Vertex in edges list. EdgeId vertex_out_next_; // Vertex out edges doubly linked list. EdgeId vertex_out_prev_; - ArcDelay *arc_delays_; + float *arc_delays_; union { uintptr_t bits_; std::vector *seq_; diff --git a/include/sta/GraphDelayCalc.hh b/include/sta/GraphDelayCalc.hh index a1f5373a..60c12d43 100644 --- a/include/sta/GraphDelayCalc.hh +++ b/include/sta/GraphDelayCalc.hh @@ -245,8 +245,8 @@ protected: bool annotateDelaySlew(Edge *edge, const TimingArc *arc, - ArcDelay &gate_delay, - Slew &gate_slew, + const ArcDelay &gate_delay, + const Slew &gate_slew, const Scene *scene, const MinMax *min_max); bool annotateLoadDelays(Vertex *drvr_vertex, diff --git a/include/sta/InternalPower.hh b/include/sta/InternalPower.hh index e37003ac..30d20ebb 100644 --- a/include/sta/InternalPower.hh +++ b/include/sta/InternalPower.hh @@ -33,44 +33,11 @@ namespace sta { -class InternalPowerModel; - -using InternalPowerModels = - std::array, RiseFall::index_count>; - -class InternalPower -{ -public: - InternalPower(LibertyPort *port, - LibertyPort *related_port, - LibertyPort *related_pg_pin, - const std::shared_ptr &when, - InternalPowerModels &models); - //InternalPower(InternalPower &&other) noexcept; - LibertyCell *libertyCell() const; - LibertyPort *port() const { return port_; } - LibertyPort *relatedPort() const { return related_port_; } - FuncExpr *when() const { return when_.get(); } - LibertyPort *relatedPgPin() const { return related_pg_pin_; } - float power(const RiseFall *rf, - const Pvt *pvt, - float in_slew, - float load_cap) const; - const InternalPowerModel *model(const RiseFall *rf) const; - -protected: - LibertyPort *port_; - LibertyPort *related_port_; - LibertyPort *related_pg_pin_; - std::shared_ptr when_; - InternalPowerModels models_; -}; - class InternalPowerModel { public: - InternalPowerModel(TableModel *model); - ~InternalPowerModel(); + InternalPowerModel(); + InternalPowerModel(std::shared_ptr model); float power(const LibertyCell *cell, const Pvt *pvt, float in_slew, @@ -80,7 +47,7 @@ public: float in_slew, float load_cap, int digits) const; - const TableModel *model() const { return model_; } + const TableModel *model() const { return model_.get(); } protected: void findAxisValues(float in_slew, @@ -95,7 +62,36 @@ protected: bool checkAxes(const TableModel *model); bool checkAxis(const TableAxis *axis); - TableModel *model_; + std::shared_ptr model_; +}; + +using InternalPowerModels = std::array; + +class InternalPower +{ +public: + InternalPower(LibertyPort *port, + LibertyPort *related_port, + LibertyPort *related_pg_pin, + const std::shared_ptr &when, + const InternalPowerModels &models); + LibertyCell *libertyCell() const; + LibertyPort *port() const { return port_; } + LibertyPort *relatedPort() const { return related_port_; } + FuncExpr *when() const { return when_.get(); } + LibertyPort *relatedPgPin() const { return related_pg_pin_; } + float power(const RiseFall *rf, + const Pvt *pvt, + float in_slew, + float load_cap) const; + const InternalPowerModel &model(const RiseFall *rf) const; + +protected: + LibertyPort *port_; + LibertyPort *related_port_; + LibertyPort *related_pg_pin_; + std::shared_ptr when_; + InternalPowerModels models_; }; } // namespace diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 76bc763e..450f1dff 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -589,7 +589,7 @@ public: LibertyPort *related_port, LibertyPort *related_pg_pin, const std::shared_ptr &when, - InternalPowerModels &models); + const InternalPowerModels &models); void makeLeakagePower(LibertyPort *related_pg_port, FuncExpr *when, float power); diff --git a/include/sta/LinearModel.hh b/include/sta/LinearModel.hh index aa7ba59e..07251739 100644 --- a/include/sta/LinearModel.hh +++ b/include/sta/LinearModel.hh @@ -37,14 +37,22 @@ public: void gateDelay(const Pvt *pvt, float in_slew, float load_cap, - bool pocv_enabled, // Return values. - ArcDelay &gate_delay, - Slew &drvr_slew) const override; + float &gate_delay, + float &drvr_slew) const override; + void gateDelayPocv(const Pvt *pvt, + float in_slew, + float load_cap, + const MinMax *min_max, + PocvMode pocv_mode, + // Return values. + ArcDelay &gate_delay, + Slew &drvr_slew) const override; std::string reportGateDelay(const Pvt *pvt, float in_slew, float load_cap, - bool pocv_enabled, + const MinMax *min_max, + PocvMode pocv_mode, int digits) const override; float driveResistance(const Pvt *pvt) const override; @@ -64,13 +72,15 @@ public: float from_slew, float to_slew, float related_out_cap, - bool pocv_enabled) const override; + const MinMax *min_max, + PocvMode pocv_mode) const override; std::string reportCheckDelay(const Pvt *pvt, float from_slew, const char *from_slew_annotation, float to_slew, float related_out_cap, - bool pocv_enabled, + const MinMax *min_max, + PocvMode pocv_mode, int digits) const override; protected: diff --git a/include/sta/Path.hh b/include/sta/Path.hh index 6ca1d8cc..c12c080b 100644 --- a/include/sta/Path.hh +++ b/include/sta/Path.hh @@ -45,14 +45,14 @@ public: const StaState *sta); Path(Vertex *vertex, Tag *tag, - Arrival arrival, + const Arrival &arrival, Path *prev_path, Edge *prev_edge, TimingArc *prev_arc, const StaState *sta); Path(Vertex *vertex, Tag *tag, - Arrival arrival, + const Arrival &arrival, Path *prev_path, Edge *prev_edge, TimingArc *prev_arc, @@ -62,11 +62,11 @@ public: bool isNull() const; // prev_path null void init(Vertex *vertex, - Arrival arrival, + const Arrival &arrival, const StaState *sta); void init(Vertex *vertex, Tag *tag, - Arrival arrival, + const Arrival &arrival, Path *prev_path, Edge *prev_edge, TimingArc *prev_arc, @@ -76,7 +76,7 @@ public: const StaState *sta); void init(Vertex *vertex, Tag *tag, - Arrival arrival, + const Arrival &arrival, const StaState *sta); Vertex *vertex(const StaState *sta) const; @@ -98,14 +98,12 @@ public: const MinMax *minMax(const StaState *sta) const; PathAPIndex pathAnalysisPtIndex(const StaState *sta) const; DcalcAPIndex dcalcAnalysisPtIndex(const StaState *sta) const; - Arrival &arrival() { return arrival_; } const Arrival &arrival() const { return arrival_; } void setArrival(Arrival arrival); - Required &required() { return required_; } const Required &required() const {return required_; } void setRequired(const Required &required); Slack slack(const StaState *sta) const; - Slew slew(const StaState *sta) const; + const Slew &slew(const StaState *sta) const; // This takes the same time as prevPath and prevArc combined. Path *prevPath() const; void setPrevPath(Path *prev_path); diff --git a/include/sta/PathEnd.hh b/include/sta/PathEnd.hh index 899c96ac..8fc1a1dc 100644 --- a/include/sta/PathEnd.hh +++ b/include/sta/PathEnd.hh @@ -98,7 +98,7 @@ public: virtual const char *typeName() const = 0; virtual int exceptPathCmp(const PathEnd *path_end, const StaState *sta) const; - virtual Arrival dataArrivalTime(const StaState *sta) const; + virtual const Arrival &dataArrivalTime(const StaState *sta) const; // Arrival time with source clock offset. Arrival dataArrivalTimeOffset(const StaState *sta) const; virtual Required requiredTime(const StaState *sta) const = 0; diff --git a/graph/Delay.cc b/include/sta/PocvMode.hh similarity index 81% rename from graph/Delay.cc rename to include/sta/PocvMode.hh index 2f538a30..29d19a63 100644 --- a/graph/Delay.cc +++ b/include/sta/PocvMode.hh @@ -22,19 +22,15 @@ // // This notice may not be removed or altered from any source distribution. -#include "Machine.hh" -#include "StringUtil.hh" -#include "Units.hh" -#include "StaState.hh" -#include "Delay.hh" +#pragma once namespace sta { +enum class PocvMode { scalar, normal, skew_normal }; + const char * -delayAsString(const Delay &delay, - const StaState *sta) -{ - return delayAsString(delay, sta, sta->units()->timeUnit()->digits()); -} +pocvModeName(PocvMode mode); +PocvMode +findPocvMode(const char *mode_name); } // namespace diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 7b39c47e..1464aa06 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -982,11 +982,11 @@ public: bool report_cap, bool report_slew, bool report_fanout, + bool report_variation, bool report_src_attr); ReportField *findReportPathField(const char *name); void setReportPathDigits(int digits); void setReportPathNoSplit(bool no_split); - void setReportPathSigmas(bool report_sigmas); void reportPathEnd(PathEnd *end); void reportPathEnds(PathEndSeq *ends); ReportPath *reportPath() { return report_path_; } @@ -998,7 +998,7 @@ public: const SetupHold *setup_hold, bool include_internal_latency, int digits); - float findWorstClkSkew(const SetupHold *setup_hold, + Delay findWorstClkSkew(const SetupHold *setup_hold, bool include_internal_latency); void reportClkLatency(ConstClockSeq &clks, @@ -1126,12 +1126,15 @@ public: void reportArrivalWrtClks(const Pin *pin, const Scene *scene, + bool report_variance, int digits); void reportRequiredWrtClks(const Pin *pin, const Scene *scene, + bool report_variance, int digits); void reportSlackWrtClks(const Pin *pin, const Scene *scene, + bool report_variance, int digits); Slew slew(Vertex *vertex, @@ -1139,9 +1142,9 @@ public: const SceneSeq &scenes, const MinMax *min_max); - ArcDelay arcDelay(Edge *edge, - TimingArc *arc, - DcalcAPIndex ap_index); + const ArcDelay &arcDelay(Edge *edge, + TimingArc *arc, + DcalcAPIndex ap_index); // True if the timing arc has been back-annotated. bool arcDelayAnnotated(Edge *edge, TimingArc *arc, @@ -1403,12 +1406,13 @@ public: // TCL variable sta_crpr_mode. CrprMode crprMode() const; void setCrprMode(CrprMode mode); - // TCL variable sta_pocv_enabled. + // TCL variable sta_pocv_mode. // Parametric on chip variation (statisical sta). - bool pocvEnabled() const; - void setPocvEnabled(bool enabled); + PocvMode pocvMode() const; + void setPocvMode(PocvMode mode); // Number of std deviations from mean to use for normal distributions. - void setSigmaFactor(float factor); + float pocvQuantile(); + void setPocvQuantile(float quantile); // TCL variable sta_propagate_gated_clock_enable. // Propagate gated clock enable arrivals. bool propagateGatedClockEnable() const; @@ -1505,17 +1509,20 @@ protected: void reportDelaysWrtClks(const Pin *pin, const Scene *scene, + bool report_variance, int digits, bool find_required, PathDelayFunc get_path_delay); void reportDelaysWrtClks(Vertex *vertex, const Scene *scene, + bool report_variance, int digits, bool find_required, PathDelayFunc get_path_delay); void reportDelaysWrtClks(Vertex *vertex, const ClockEdge *clk_edge, const Scene *scene, + bool report_variance, int digits, PathDelayFunc get_path_delay); RiseFallMinMaxDelay findDelaysWrtClks(Vertex *vertex, @@ -1525,6 +1532,7 @@ protected: std::string formatDelay(const RiseFall *rf, const MinMax *min_max, const RiseFallMinMaxDelay &delays, + bool report_variance, int digits); void connectDrvrPinAfter(Vertex *vertex); diff --git a/include/sta/StaState.hh b/include/sta/StaState.hh index 2cfbede4..8f96e137 100644 --- a/include/sta/StaState.hh +++ b/include/sta/StaState.hh @@ -47,6 +47,7 @@ class GraphDelayCalc; class Latches; class DispatchQueue; class Variables; +class DelayOps; using ModeSeq = std::vector; using ModeSet = std::set; @@ -96,10 +97,10 @@ public: GraphDelayCalc *graphDelayCalc() const { return graph_delay_calc_; } Search *search() { return search_; } Search *search() const { return search_; } + const DelayOps *delayOps() const { return delay_ops_; } Latches *latches() { return latches_; } Latches *latches() const { return latches_; } unsigned threadCount() const { return thread_count_; } - float sigmaFactor() const { return sigma_factor_; } bool crprActive(const Mode *mode) const; Variables *variables() { return variables_; } const Variables *variables() const { return variables_; } @@ -133,11 +134,11 @@ protected: ArcDelayCalc *arc_delay_calc_; GraphDelayCalc *graph_delay_calc_; Search *search_; + DelayOps *delay_ops_; Latches *latches_; Variables *variables_; int thread_count_; DispatchQueue *dispatch_queue_; - float sigma_factor_; }; } // namespace diff --git a/include/sta/TableModel.hh b/include/sta/TableModel.hh index 59e26ba0..95b51132 100644 --- a/include/sta/TableModel.hh +++ b/include/sta/TableModel.hh @@ -33,12 +33,14 @@ #include "Transition.hh" #include "LibertyClass.hh" #include "TimingModel.hh" +#include "Variables.hh" namespace sta { class Unit; class Units; class Report; +class TableModels; class Table; class TableModel; class TableAxis; @@ -63,43 +65,41 @@ class GateTableModel : public GateTimingModel { public: GateTableModel(LibertyCell *cell, - TableModel *delay_model, - TableModelsEarlyLate delay_sigma_models, - TableModel *slew_model, - TableModelsEarlyLate slew_sigma_models, + TableModels *delay_models, + TableModels *slew_models, ReceiverModelPtr receiver_model, OutputWaveforms *output_waveforms); GateTableModel(LibertyCell *cell, - TableModel *delay_model, - TableModel *slew_model); + TableModels *delay_models, + TableModels *slew_models); ~GateTableModel() override; void gateDelay(const Pvt *pvt, float in_slew, float load_cap, - bool pocv_enabled, // Return values. - ArcDelay &gate_delay, - Slew &drvr_slew) const override; - // deprecated 2024-01-07 - // related_out_cap arg removed. - void gateDelay(const Pvt *pvt, - float in_slew, - float load_cap, - float related_out_cap, - bool pocv_enabled, - ArcDelay &gate_delay, - Slew &drvr_slew) const __attribute__ ((deprecated)); + float &gate_delay, + float &drvr_slew) const override; + // Fill in pocv parameters in gate_delay, drvr_slew. + void gateDelayPocv(const Pvt *pvt, + float in_slew, + float load_cap, + const MinMax *min_max, + PocvMode pocv_mode, + // Return values. + ArcDelay &gate_delay, + Slew &drvr_slew) const override; std::string reportGateDelay(const Pvt *pvt, float in_slew, float load_cap, - bool pocv_enabled, + const MinMax *min_max, + PocvMode pocv_mode, int digits) const override; float driveResistance(const Pvt *pvt) const override; - const TableModel *delayModel() const { return delay_model_.get(); } - const TableModel *slewModel() const { return slew_model_.get(); } - const TableModel *delaySigmaModel(const EarlyLate *el) const; - const TableModel *slewSigmaModel(const EarlyLate *el) const; + const TableModels *delayModels() const { return delay_models_.get(); } + const TableModel *delayModel() const; + const TableModels *slewModels() const { return slew_models_.get(); } + const TableModel *slewModel() const; const ReceiverModel *receiverModel() const { return receiver_model_.get(); } OutputWaveforms *outputWaveforms() const { return output_waveforms_.get(); } // Check the axes before making the model. @@ -138,10 +138,8 @@ protected: float &axis_value3) const; static bool checkAxis(const TableAxis *axis); - std::unique_ptr delay_model_; - TableModelsEarlyLate delay_sigma_models_; - std::unique_ptr slew_model_; - TableModelsEarlyLate slew_sigma_models_; + std::unique_ptr delay_models_; + std::unique_ptr slew_models_; ReceiverModelPtr receiver_model_; std::unique_ptr output_waveforms_; }; @@ -150,25 +148,24 @@ class CheckTableModel : public CheckTimingModel { public: CheckTableModel(LibertyCell *cell, - TableModel *model, - TableModelsEarlyLate sigma_models); - CheckTableModel(LibertyCell *cell, - TableModel *model); + TableModels *check_models); ~CheckTableModel() override; ArcDelay checkDelay(const Pvt *pvt, float from_slew, float to_slew, float related_out_cap, - bool pocv_enabled) const override; + const MinMax *min_max, + PocvMode pocv_mode) const override; std::string reportCheckDelay(const Pvt *pvt, float from_slew, const char *from_slew_annotation, float to_slew, float related_out_cap, - bool pocv_enabled, + const MinMax *min_max, + PocvMode pocv_mode, int digits) const override; - const TableModel *model() const { return model_.get(); } - const TableModel *sigmaModel(const EarlyLate *el) const; + const TableModels *checkModels() const { return check_models_.get(); } + const TableModel *checkModel() const; // Check the axes before making the model. // Return true if the model axes are supported. @@ -202,8 +199,7 @@ protected: int digits) const; static bool checkAxis(const TableAxis *axis); - std::unique_ptr model_; - TableModelsEarlyLate sigma_models_; + std::unique_ptr check_models_; }; class TableAxis @@ -311,6 +307,8 @@ public: private: void clear(); + float findValueOrder2(float axis_value1, float axis_value2) const; + float findValueOrder3(float axis_value1, float axis_value2, float axis_value3) const; std::string reportValueOrder0(const char *result_name, const char *comment1, const Unit *table_unit, @@ -408,6 +406,34 @@ protected: bool is_scaled_:1; }; +// cell/transition/check nldm/ocv/lvf models for one rise/fall edge. +class TableModels +{ +public: + TableModels(); + TableModels(TableModel *model); + ~TableModels(); + TableModel *model() const { return model_.get(); } + void setModel(TableModel *model); + TableModel *sigma(const EarlyLate *early_late) const; + void setSigma(TableModel *table, + const EarlyLate *early_late); + TableModel *meanShift() const { return mean_shift_.get(); } + void setMeanShift(TableModel *table); + TableModel *skewness() const { return skewness_.get(); } + void setSkewness(TableModel *table); + TableModel *stdDev() const { return std_dev_.get(); } + void setStdDev(TableModel *table); + +protected: + std::unique_ptr model_; + // Note early/late can point to the same model. + std::array sigma_; + std::unique_ptr std_dev_; + std::unique_ptr mean_shift_; + std::unique_ptr skewness_; +}; + //////////////////////////////////////////////////////////////// class ReceiverModel diff --git a/include/sta/TimingModel.hh b/include/sta/TimingModel.hh index db9caf08..0ff157f2 100644 --- a/include/sta/TimingModel.hh +++ b/include/sta/TimingModel.hh @@ -28,6 +28,7 @@ #include "Delay.hh" #include "LibertyClass.hh" +#include "Variables.hh" namespace sta { @@ -52,14 +53,23 @@ public: virtual void gateDelay(const Pvt *pvt, float in_slew, float load_cap, - bool pocv_enabled, // Return values. - ArcDelay &gate_delay, - Slew &drvr_slew) const = 0; + float &gate_delay, + float &drvr_slew) const = 0; + // Fill in pocv parameters in gate_delay, drvr_slew. + virtual void gateDelayPocv(const Pvt *pvt, + float in_slew, + float load_cap, + const MinMax *min_max, + PocvMode pocv_mode, + // Return values. + ArcDelay &gate_delay, + Slew &drvr_slew) const = 0; virtual std::string reportGateDelay(const Pvt *pvt, float in_slew, float load_cap, - bool pocv_enabled, + const MinMax *min_max, + PocvMode pocv_mode, int digits) const = 0; virtual float driveResistance(const Pvt *pvt) const = 0; }; @@ -74,13 +84,15 @@ public: float from_slew, float to_slew, float related_out_cap, - bool pocv_enabled) const = 0; + const MinMax *min_max, + PocvMode pocv_mode) const = 0; virtual std::string reportCheckDelay(const Pvt *pvt, float from_slew, const char *from_slew_annotation, float to_slew, float related_out_cap, - bool pocv_enabled, + const MinMax *min_max, + PocvMode pocv_mode, int digits) const = 0; }; diff --git a/include/sta/Variables.hh b/include/sta/Variables.hh index 9e553193..7e8e7a69 100644 --- a/include/sta/Variables.hh +++ b/include/sta/Variables.hh @@ -24,6 +24,8 @@ #pragma once +#include "PocvMode.hh" + namespace sta { enum class CrprMode { same_pin, same_transition }; @@ -72,8 +74,11 @@ public: // TCL variable sta_input_port_default_clock. bool useDefaultArrivalClock() { return use_default_arrival_clock_; } void setUseDefaultArrivalClock(bool enable); - bool pocvEnabled() const { return pocv_enabled_; } - void setPocvEnabled(bool enabled); + bool pocvEnabled() const; + PocvMode pocvMode() const { return pocv_mode_; } + void setPocvMode(PocvMode mode); + float pocvQuantile() const { return pocv_quantile_; } + void setPocvQuantile(float quartile); private: bool crpr_enabled_; @@ -88,7 +93,8 @@ private: bool dynamic_loop_breaking_; bool propagate_all_clks_; bool use_default_arrival_clock_; - bool pocv_enabled_; + PocvMode pocv_mode_; + float pocv_quantile_; }; } // namespace diff --git a/liberty/InternalPower.cc b/liberty/InternalPower.cc index 5380a359..d9ecd617 100644 --- a/liberty/InternalPower.cc +++ b/liberty/InternalPower.cc @@ -37,7 +37,7 @@ InternalPower::InternalPower(LibertyPort *port, LibertyPort *related_port, LibertyPort *related_pg_pin, const std::shared_ptr &when, - InternalPowerModels &models) : + const InternalPowerModels &models) : port_(port), related_port_(related_port), related_pg_pin_(related_pg_pin), @@ -52,36 +52,32 @@ InternalPower::libertyCell() const return port_->libertyCell(); } +const InternalPowerModel & +InternalPower::model(const RiseFall *rf) const +{ + return models_[rf->index()]; +} + float InternalPower::power(const RiseFall *rf, const Pvt *pvt, float in_slew, float load_cap) const { - const std::shared_ptr &model = models_[rf->index()]; - if (model) - return model->power(libertyCell(), pvt, in_slew, load_cap); - else - return 0.0; -} - -const InternalPowerModel * -InternalPower::model(const RiseFall *rf) const -{ - const std::shared_ptr &m = models_[rf->index()]; - return m.get(); + const InternalPowerModel &model = models_[rf->index()]; + return model.power(libertyCell(), pvt, in_slew, load_cap); } //////////////////////////////////////////////////////////////// -InternalPowerModel::InternalPowerModel(TableModel *model) : - model_(model) +InternalPowerModel::InternalPowerModel() : + model_(nullptr) { } -InternalPowerModel::~InternalPowerModel() +InternalPowerModel::InternalPowerModel(std::shared_ptr model) : + model_(model) { - delete model_; } float diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index de019009..1c659ad8 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -1262,7 +1262,7 @@ LibertyCell::makeInternalPower(LibertyPort *port, LibertyPort *related_port, LibertyPort *related_pg_pin, const std::shared_ptr &when, - InternalPowerModels &models) + const InternalPowerModels &models) { internal_powers_.emplace_back(port, related_port, related_pg_pin, when, models); port_internal_powers_[port].push_back(internal_powers_.size() - 1); diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 32e551b4..e95ed876 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -2122,80 +2122,76 @@ LibertyReader::makeTableModels(LibertyCell *cell, { bool found_model = false; for (const RiseFall *rf : RiseFall::range()) { - std::string delay_attr_name = "cell_" + rf->to_string(); - TableModel *delay = readGateTableModel(timing_group, delay_attr_name.c_str(), rf, - TableTemplateType::delay, time_scale_, - ScaleFactorType::cell); - std::string transition_attr_name = rf->to_string() + "_transition"; - TableModel *transition = readGateTableModel(timing_group, - transition_attr_name.c_str(), - rf, TableTemplateType::delay, - time_scale_, - ScaleFactorType::transition); - if (delay || transition) { - std::string delay_sigma_attr_name = "ocv_sigma_cell_" + rf->to_string(); - TableModelsEarlyLate delay_sigmas = - readEarlyLateTableModels(timing_group, - delay_sigma_attr_name.c_str(), - rf, TableTemplateType::delay, - time_scale_, - ScaleFactorType::unknown); + TableModel *delay_model = readTableModel(timing_group, + "cell_" + rf->to_string(), + rf, TableTemplateType::delay, + time_scale_, + ScaleFactorType::cell, + GateTableModel::checkAxes); + TableModel *slew_model = readTableModel(timing_group, + rf->to_string() + "_transition", + rf, TableTemplateType::delay, + time_scale_, + ScaleFactorType::transition, + GateTableModel::checkAxes); + if (delay_model || slew_model) { + TableModels *delay_models = new TableModels(delay_model); + readLvfModels(timing_group, + "ocv_sigma_cell_" + rf->to_string(), + "ocv_std_dev_cell_" + rf->to_string(), + "ocv_mean_shift_cell_" + rf->to_string(), + "ocv_skewness_cell_" + rf->to_string(), + rf, delay_models, GateTableModel::checkAxes); - std::string slew_sigma_attr_name = "ocv_sigma_" + rf->to_string() - + "_transition"; - TableModelsEarlyLate slew_sigmas = - readEarlyLateTableModels(timing_group, - slew_sigma_attr_name.c_str(), - rf, TableTemplateType::delay, - time_scale_, - ScaleFactorType::unknown); + TableModels *slew_models = new TableModels(slew_model); + readLvfModels(timing_group, + "ocv_sigma_" + rf->to_string() + "_transition", + "ocv_std_dev_" + rf->to_string() + "_transition", + "ocv_mean_shift_" + rf->to_string() + "_transition", + "ocv_skewness_" + rf->to_string() + "_transition", + rf, slew_models, GateTableModel::checkAxes); ReceiverModelPtr receiver_model = readReceiverCapacitance(timing_group, rf); OutputWaveforms *output_waveforms = readOutputWaveforms(timing_group, rf); - timing_attrs->setModel(rf, new GateTableModel(cell, delay, - std::move(delay_sigmas), - transition, - std::move(slew_sigmas), + timing_attrs->setModel(rf, new GateTableModel(cell, delay_models, + slew_models, receiver_model, output_waveforms)); TimingType timing_type = timing_attrs->timingType(); if (isGateTimingType(timing_type)) { - if (transition == nullptr) + if (slew_model == nullptr) libWarn(1210, timing_group, "missing %s_transition.", rf->name()); - if (delay == nullptr) + if (delay_model == nullptr) libWarn(1211, timing_group, "missing cell_%s.", rf->name()); } found_model = true; } - else { - std::string constraint_attr_name = rf->to_string() + "_constraint"; - ScaleFactorType scale_factor_type = - timingTypeScaleFactorType(timing_attrs->timingType()); - TableModel *constraint = readCheckTableModel(timing_group, - constraint_attr_name.c_str(), - rf, TableTemplateType::delay, - time_scale_, scale_factor_type); - if (constraint) { - std::string constraint_sigma_attr_name = "ocv_sigma_" + rf->to_string() - + "_constraint"; - TableModelsEarlyLate constraint_sigmas = - readEarlyLateTableModels(timing_group, - constraint_sigma_attr_name.c_str(), - rf, TableTemplateType::delay, - time_scale_, - ScaleFactorType::unknown); - timing_attrs->setModel(rf, new CheckTableModel(cell, constraint, - std::move(constraint_sigmas))); - found_model = true; - } + + std::string constraint_attr_name = rf->to_string() + "_constraint"; + ScaleFactorType scale_factor_type = + timingTypeScaleFactorType(timing_attrs->timingType()); + TableModel *check_model = readTableModel(timing_group, + constraint_attr_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, scale_factor_type, + CheckTableModel::checkAxes); + if (check_model) { + TableModels *check_models = new TableModels(check_model); + readLvfModels(timing_group, + "ocv_sigma_" + rf->to_string() + "_constraint", + "ocv_std_dev_" + rf->to_string() + "_constraint", + "ocv_mean_shift_" + rf->to_string() + "_constraint", + "ocv_skewness_" + rf->to_string() + "_constraint", + rf, check_models, CheckTableModel::checkAxes); + timing_attrs->setModel(rf, new CheckTableModel(cell, check_models)); + found_model = true; } } if (!found_model) libWarn(1311, timing_group, "no table models found in timing group."); } - bool LibertyReader::isGateTimingType(TimingType timing_type) { @@ -2215,41 +2211,66 @@ LibertyReader::isGateTimingType(TimingType timing_type) } TableModel * -LibertyReader::readGateTableModel(const LibertyGroup *timing_group, - const char *table_group_name, - const RiseFall *rf, - TableTemplateType template_type, - float scale, - ScaleFactorType scale_factor_type) +LibertyReader::readTableModel(const LibertyGroup *timing_group, + const std::string &table_group_name, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type, + const std::function check_axes) { const LibertyGroup *table_group = timing_group->findSubgroup(table_group_name); - if (table_group) { - TableModel *model = readTableModel(table_group, rf, template_type, scale, - scale_factor_type); - if (model && !GateTableModel::checkAxes(model)) - libWarn(1251, table_group, "unsupported model axis."); - return model; - } + if (table_group) + return readTableModel(table_group, rf, template_type, scale, + scale_factor_type, check_axes); return nullptr; } -TableModel * -LibertyReader::readCheckTableModel(const LibertyGroup *timing_group, - const char *table_group_name, - const RiseFall *rf, - TableTemplateType template_type, - float scale, - ScaleFactorType scale_factor_type) +void +LibertyReader::readLvfModels(const LibertyGroup *timing_group, + const std::string &sigma_group_name, + const std::string &std_dev_group_name, + const std::string &mean_shift_group_name, + const std::string &skewness_group_name, + const RiseFall *rf, + TableModels *table_models, + const std::function check_axes) { - const LibertyGroup *table_group = timing_group->findSubgroup(table_group_name); - if (table_group) { - TableModel *model = readTableModel(table_group, rf, template_type, scale, - scale_factor_type); - if (model && !CheckTableModel::checkAxes(model)) - libWarn(1252, table_group, "unsupported model axis."); - return model; + TableModelsEarlyLate sigmas = + readEarlyLateTableModels(timing_group, + sigma_group_name.c_str(), + rf, TableTemplateType::delay, + time_scale_, + ScaleFactorType::unknown, + check_axes); + for (const EarlyLate *early_late : EarlyLate::range()) + table_models->setSigma(sigmas[early_late->index()], early_late); + + const LibertyGroup *std_dev_group = timing_group->findSubgroup(std_dev_group_name); + if (std_dev_group) { + TableModel *std_dev = readTableModel(std_dev_group, rf, TableTemplateType::delay, + time_scale_, ScaleFactorType::unknown, + check_axes); + table_models->setStdDev(std_dev); + } + + const LibertyGroup *mean_shift_group=timing_group->findSubgroup(mean_shift_group_name); + if (mean_shift_group) { + TableModel *mean_shift = readTableModel(mean_shift_group, rf, + TableTemplateType::delay, + time_scale_, ScaleFactorType::unknown, + check_axes); + table_models->setMeanShift(mean_shift); + } + + const LibertyGroup *skewness_group = timing_group->findSubgroup(skewness_group_name); + if (skewness_group) { + TableModel *skewness = readTableModel(skewness_group, rf, + TableTemplateType::delay, + 1.0, ScaleFactorType::unknown, + check_axes); + table_models->setSkewness(skewness); } - return nullptr; } TableModelsEarlyLate @@ -2258,12 +2279,13 @@ LibertyReader::readEarlyLateTableModels(const LibertyGroup *timing_group, const RiseFall *rf, TableTemplateType template_type, float scale, - ScaleFactorType scale_factor_type) + ScaleFactorType scale_factor_type, + const std::function check_axes) { TableModelsEarlyLate models{}; for (const LibertyGroup *table_group : timing_group->findSubgroups(table_group_name)) { TableModel *model = readTableModel(table_group, rf, template_type, scale, - scale_factor_type); + scale_factor_type, check_axes); const std::string *early_late = table_group->findAttrString("sigma_type"); if (early_late == nullptr || *early_late == "early_and_late") { @@ -2274,9 +2296,6 @@ LibertyReader::readEarlyLateTableModels(const LibertyGroup *timing_group, models[EarlyLate::early()->index()] = model; else if (*early_late == "late") models[EarlyLate::late()->index()] = model; - - //if (model && !GateTableModel::checkAxes(model)) - // libWarn(1182, table_group, "unsupported model axis."); } return models; } @@ -2445,7 +2464,8 @@ LibertyReader::readTableModel(const LibertyGroup *table_group, const RiseFall *rf, TableTemplateType template_type, float scale, - ScaleFactorType scale_factor_type) + ScaleFactorType scale_factor_type, + const std::function &check_axes) { const char *template_name = table_group->firstName(); if (library_ && template_name) { @@ -2456,6 +2476,9 @@ LibertyReader::readTableModel(const LibertyGroup *table_group, if (table) { TableModel *table_model = new TableModel(table, tbl_template, scale_factor_type, rf); + if (!check_axes(table_model)) { + libWarn(1251, table_group, "unsupported model axis."); + } return table_model; } } @@ -2682,7 +2705,7 @@ LibertyReader::readInternalPowerGroups(LibertyCell *cell, FuncExpr *when1 = readFuncExpr(cell, ipwr_group, "when"); if (when1) when = std::shared_ptr(when1); - InternalPowerModels models; + InternalPowerModels models{}; // rise/fall_power group for (const RiseFall *rf : RiseFall::range()) { std::string pwr_attr_name = rf->to_string() + "_power"; @@ -2691,7 +2714,9 @@ LibertyReader::readInternalPowerGroups(LibertyCell *cell, TableModel *model = readTableModel(pwr_group, rf, TableTemplateType::power, energyScale(), ScaleFactorType::internal_power); - models[rf->index()] = std::make_shared(model); + std::shared_ptr table_model(model); + InternalPowerModel pwr_model(table_model); + models[rf->index()] = pwr_model; } } // power group (rise/fall power are the same) @@ -2701,9 +2726,11 @@ LibertyReader::readInternalPowerGroups(LibertyCell *cell, TableTemplateType::power, energyScale(), ScaleFactorType::internal_power); - auto pwr_model = std::make_shared(model); - for (const RiseFall *rf : RiseFall::range()) + std::shared_ptr table_model(model); + for (const RiseFall *rf : RiseFall::range()) { + InternalPowerModel pwr_model(table_model); models[rf->index()] = pwr_model; + } } if (related_ports.empty()) cell->makeInternalPower(port, nullptr, related_pg_port, when, models); @@ -2792,9 +2819,9 @@ LibertyReader::makeScalarCheckModel(LibertyCell *cell, library_->findTableTemplate("scalar", TableTemplateType::delay); TableModel *table_model = new TableModel(table, tbl_template, scale_factor_type, rf); - TableModelsEarlyLate sigmas{}; - CheckTableModel *check_model = new CheckTableModel(cell, table_model, - std::move(sigmas)); + + TableModels *check_models = new TableModels(table_model); + TimingModel *check_model = new CheckTableModel(cell, check_models); return check_model; } @@ -3713,7 +3740,7 @@ PortNameBitIterator::init(const char *port_name) range_bit_ = from; findRangeBusNameNext(); } - size_ = abs(from - to) + 1; + size_ = std::abs(from - to) + 1; } else visitor_->libWarn(1294, line_, "port %s not found.", port_name); diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 474cc799..070b28e7 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -232,25 +232,21 @@ protected: const LibertyPortSeq &ports, const LibertyGroup *port_group); bool isGateTimingType(TimingType timing_type); - TableModel *readGateTableModel(const LibertyGroup *timing_group, - const char *table_group_name, - const RiseFall *rf, - TableTemplateType template_type, - float scale, - ScaleFactorType scale_factor_type); + TableModel *readTableModel(const LibertyGroup *timing_group, + const std::string &table_group_name, + const RiseFall *rf, + TableTemplateType template_type, + float scale, + ScaleFactorType scale_factor_type, + const std::function check_axes); TableModelsEarlyLate readEarlyLateTableModels(const LibertyGroup *timing_group, const char *table_group_name, const RiseFall *rf, TableTemplateType template_type, float scale, - ScaleFactorType scale_factor_type); - TableModel *readCheckTableModel(const LibertyGroup *timing_group, - const char *table_group_name, - const RiseFall *rf, - TableTemplateType template_type, - float scale, - ScaleFactorType scale_factor_type); + ScaleFactorType scale_factor_type, + const std::function check_axes); ReceiverModelPtr readReceiverCapacitance(const LibertyGroup *timing_group, const RiseFall *rf); void readReceiverCapacitance(const LibertyGroup *timing_group, @@ -268,7 +264,9 @@ protected: const RiseFall *rf, TableTemplateType template_type, float scale, - ScaleFactorType scale_factor_type); + ScaleFactorType scale_factor_type, + const std::function &check_axes = + [](TableModel *) { return true; }); TablePtr readTableModel(const LibertyGroup *table_group, const TableTemplate *tbl_template, float scale); @@ -281,6 +279,14 @@ protected: void makeTableModels(LibertyCell *cell, const LibertyGroup *timing_group, TimingArcAttrsPtr timing_attrs); + void readLvfModels(const LibertyGroup *timing_group, + const std::string &sigma_group_name, + const std::string &std_dev_group_name, + const std::string &mean_shift_group_name, + const std::string &skewness_group_name, + const RiseFall *rf, + TableModels *table_models, + const std::function check_axes); TableAxisPtr makeTableAxis(const LibertyGroup *table_group, const char *index_attr_name, diff --git a/liberty/LibertyWriter.cc b/liberty/LibertyWriter.cc index 19e08729..ada26b09 100644 --- a/liberty/LibertyWriter.cc +++ b/liberty/LibertyWriter.cc @@ -466,13 +466,14 @@ LibertyWriter::writeTimingModels(const TimingArc *arc, const TableModel *slew_model = gate_model->slewModel(); if (slew_model) { const std::string &slew_template_name = slew_model->tblTemplate()->name(); - fprintf(stream_, " %s_transition(%s) {\n", rf->name(), slew_template_name.c_str()); + fprintf(stream_, " %s_transition(%s) {\n", rf->name(), + slew_template_name.c_str()); writeTableModel(slew_model); fprintf(stream_, " }\n"); } } else if (check_model) { - const TableModel *model = check_model->model(); + const TableModel *model = check_model->checkModel(); const std::string &template_name = model->tblTemplate()->name(); fprintf(stream_, " %s_constraint(%s) {\n", rf->name(), template_name.c_str()); writeTableModel(model); diff --git a/liberty/LinearModel.cc b/liberty/LinearModel.cc index 85d158e7..b8e6a78c 100644 --- a/liberty/LinearModel.cc +++ b/liberty/LinearModel.cc @@ -42,20 +42,32 @@ void GateLinearModel::gateDelay(const Pvt *, float, float load_cap, - bool, // return values - ArcDelay &gate_delay, - Slew &drvr_slew) const + float &gate_delay, + float &drvr_slew) const { gate_delay = intrinsic_ + resistance_ * load_cap; drvr_slew = 0.0; } +void +GateLinearModel::gateDelayPocv(const Pvt *, + float, + float, + const MinMax *, + PocvMode, + // return values + ArcDelay &, + Slew &) const +{ +} + std::string GateLinearModel::reportGateDelay(const Pvt *, float, float load_cap, - bool, + const MinMax *, + PocvMode, int digits) const { const LibertyLibrary *library = cell_->libertyLibrary(); @@ -98,7 +110,8 @@ CheckLinearModel::checkDelay(const Pvt *, float, float, float, - bool) const + const MinMax *, + PocvMode) const { return intrinsic_; } @@ -109,7 +122,8 @@ CheckLinearModel::reportCheckDelay(const Pvt *, const char *, float, float, - bool, + const MinMax *, + PocvMode, int digits) const { const LibertyLibrary *library = cell_->libertyLibrary(); diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index 0d5257a8..a235dcb4 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -38,8 +38,6 @@ namespace sta { size_t findValueIndex(float value, const FloatSeq *values); -static void -sigmaModelsDelete(TableModelsEarlyLate &models); static std::string reportPvt(const LibertyCell *cell, const Pvt *pvt, @@ -53,139 +51,189 @@ TimingModel::TimingModel(LibertyCell *cell) : { } +//////////////////////////////////////////////////////////////// + GateTableModel::GateTableModel(LibertyCell *cell, - TableModel *delay_model, - TableModelsEarlyLate delay_sigma_models, - TableModel *slew_model, - TableModelsEarlyLate slew_sigma_models, + TableModels *delay_models, + TableModels *slew_models, ReceiverModelPtr receiver_model, OutputWaveforms *output_waveforms) : GateTimingModel(cell), - delay_model_(delay_model), - delay_sigma_models_(std::move(delay_sigma_models)), - slew_model_(slew_model), - slew_sigma_models_(std::move(slew_sigma_models)), + delay_models_(delay_models), + slew_models_(slew_models), receiver_model_(receiver_model), output_waveforms_(output_waveforms) { } GateTableModel::GateTableModel(LibertyCell *cell, - TableModel *delay_model, - TableModel *slew_model) : + TableModels *delay_models, + TableModels *slew_models) : GateTimingModel(cell), - delay_model_(delay_model), - delay_sigma_models_{}, - slew_model_(slew_model), - slew_sigma_models_{}, + delay_models_(delay_models), + slew_models_(slew_models), receiver_model_(nullptr), output_waveforms_(nullptr) { } -GateTableModel::~GateTableModel() +GateTableModel::~GateTableModel() = default; + +const TableModel * +GateTableModel::delayModel() const { - sigmaModelsDelete(slew_sigma_models_); - sigmaModelsDelete(delay_sigma_models_); + return delay_models_ ? delay_models_->model() : nullptr; } -static void -sigmaModelsDelete(TableModelsEarlyLate &models) +const TableModel * +GateTableModel::slewModel() const { - TableModel *early_model = models[EarlyLate::earlyIndex()]; - TableModel *late_model = models[EarlyLate::lateIndex()]; - if (early_model == late_model) - delete early_model; - else { - delete early_model; - delete late_model; - } + return slew_models_ ? slew_models_->model() : nullptr;; } void GateTableModel::setIsScaled(bool is_scaled) { - if (delay_model_) - delay_model_->setIsScaled(is_scaled); - if (slew_model_) - slew_model_->setIsScaled(is_scaled); + if (delay_models_) + delay_models_->model()->setIsScaled(is_scaled); + if (slew_models_) + slew_models_->model()->setIsScaled(is_scaled); } void GateTableModel::gateDelay(const Pvt *pvt, float in_slew, float load_cap, - bool pocv_enabled, // return values - ArcDelay &gate_delay, - Slew &drvr_slew) const + float &gate_delay, + float &drvr_slew) const { - float delay = findValue(pvt, delay_model_.get(), in_slew, load_cap, 0.0); - float sigma_early = 0.0; - float sigma_late = 0.0; - if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()]) - sigma_early = findValue(pvt, delay_sigma_models_[EarlyLate::earlyIndex()], - in_slew, load_cap, 0.0); - if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()]) - sigma_late = findValue(pvt, delay_sigma_models_[EarlyLate::lateIndex()], - in_slew, load_cap, 0.0); - gate_delay = makeDelay(delay, sigma_early, sigma_late); - - float slew = findValue(pvt, slew_model_.get(), in_slew, load_cap, 0.0); - if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()]) - sigma_early = findValue(pvt, slew_sigma_models_[EarlyLate::earlyIndex()], - in_slew, load_cap, 0.0); - if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()]) - sigma_late = findValue(pvt, slew_sigma_models_[EarlyLate::lateIndex()], - in_slew, load_cap, 0.0); + if (delay_models_) + gate_delay = findValue(pvt, delay_models_->model(), in_slew, load_cap, 0.0); + else + gate_delay = 0.0; + if (slew_models_) + drvr_slew = findValue(pvt, slew_models_->model(), in_slew, load_cap, 0.0); + else + drvr_slew = 0.0; // Clip negative slews to zero. - if (slew < 0.0) - slew = 0.0; - drvr_slew = makeDelay(slew, sigma_early, sigma_late); + if (drvr_slew < 0.0) + drvr_slew = 0.0; } void -GateTableModel::gateDelay(const Pvt *pvt, - float in_slew, - float load_cap, - float, - bool pocv_enabled, - ArcDelay &gate_delay, - Slew &drvr_slew) const +GateTableModel::gateDelayPocv(const Pvt *pvt, + float in_slew, + float load_cap, + const MinMax *min_max, + PocvMode pocv_mode, + // return values + ArcDelay &gate_delay, + Slew &drvr_slew) const { - gateDelay(pvt, in_slew, load_cap, pocv_enabled, gate_delay, drvr_slew); + switch (pocv_mode) { + case PocvMode::normal: { + // Delay + TableModel *std_dev_model = delay_models_->stdDev(); + if (std_dev_model == nullptr) + std_dev_model = delay_models_->sigma(min_max); + if (std_dev_model) { + float std_dev = findValue(pvt, std_dev_model, in_slew, load_cap, 0.0); + gate_delay.setStdDev(std_dev); + } + + // Slew + std_dev_model = slew_models_->stdDev(); + if (std_dev_model == nullptr) + std_dev_model = slew_models_->sigma(min_max); + if (std_dev_model) { + float std_dev = findValue(pvt, std_dev_model, in_slew, load_cap, 0.0); + drvr_slew.setStdDev(std_dev); + } + break; + } + case PocvMode::skew_normal: { + // Delay + if (delay_models_->meanShift()) { + float mean_shift = findValue(pvt, delay_models_->meanShift(), + in_slew, load_cap, 0.0); + gate_delay.setMeanShift(mean_shift); + } + + if (delay_models_->stdDev()) { + float std_dev = findValue(pvt, delay_models_->stdDev(), in_slew, load_cap, 0.0); + gate_delay.setStdDev(std_dev); + } + + if (delay_models_->skewness()) { + float skewness = findValue(pvt, delay_models_->skewness(), in_slew, load_cap, 0.0); + gate_delay.setSkewness(skewness); + } + + // Slew + if (slew_models_->meanShift()) { + float mean_shift = findValue(pvt, slew_models_->meanShift(), + in_slew, load_cap, 0.0); + drvr_slew.setMeanShift(mean_shift); + } + + if (slew_models_->stdDev()) { + float std_dev = findValue(pvt, slew_models_->stdDev(), in_slew, load_cap, 0.0); + drvr_slew.setStdDev(std_dev); + } + + if (slew_models_->skewness()) { + float skewness = findValue(pvt, slew_models_->skewness(), in_slew, load_cap, 0.0); + drvr_slew.setSkewness(skewness); + } + break; + } + default: + break; + } } std::string GateTableModel::reportGateDelay(const Pvt *pvt, float in_slew, float load_cap, - bool pocv_enabled, + const MinMax *min_max, + PocvMode pocv_mode, int digits) const { std::string result = reportPvt(cell_, pvt, digits); - result += reportTableLookup("Delay", pvt, delay_model_.get(), in_slew, + result += reportTableLookup("Delay", pvt, delay_models_->model(), in_slew, load_cap, 0.0, digits); - if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()]) - result += reportTableLookup("Delay sigma(early)", pvt, - delay_sigma_models_[EarlyLate::earlyIndex()], - in_slew, load_cap, 0.0, digits); - if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()]) - result += reportTableLookup("Delay sigma(late)", pvt, - delay_sigma_models_[EarlyLate::lateIndex()], - in_slew, load_cap, 0.0, digits); - result += '\n'; - result += reportTableLookup("Slew", pvt, slew_model_.get(), in_slew, - load_cap, 9.0, digits); - if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()]) - result += reportTableLookup("Slew sigma(early)", pvt, - slew_sigma_models_[EarlyLate::earlyIndex()], - in_slew, load_cap, 0.0, digits); - if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()]) - result += reportTableLookup("Slew sigma(late)", pvt, - slew_sigma_models_[EarlyLate::lateIndex()], - in_slew, load_cap, 0.0, digits); - float drvr_slew = findValue(pvt, slew_model_.get(), in_slew, load_cap, 0.0); + if (pocv_mode != PocvMode::scalar) { + if (delay_models_->sigma(min_max)) + result += reportTableLookup("Delay sigma(early)", pvt, + delay_models_->sigma(min_max), + in_slew, load_cap, 0.0, digits); + if (delay_models_->sigma(EarlyLate::late())) + result += reportTableLookup("Delay sigma(late)", pvt, + delay_models_->sigma(min_max), + in_slew, load_cap, 0.0, digits); + result += '\n'; + + result += reportTableLookup("Slew", pvt, slew_models_->model(), in_slew, + load_cap, 9.0, digits); + + if (slew_models_->sigma(EarlyLate::early())) + result += reportTableLookup("Slew sigma(early)", pvt, + slew_models_->sigma(min_max), + in_slew, load_cap, 0.0, digits); + if (slew_models_->sigma(EarlyLate::late())) + result += reportTableLookup("Slew sigma(late)", pvt, + slew_models_->sigma(min_max), + in_slew, load_cap, 0.0, digits); + } + else { + result += '\n'; + result += reportTableLookup("Slew", pvt, slew_models_->model(), in_slew, + load_cap, 9.0, digits); + } + + float drvr_slew = findValue(pvt, slew_models_->model(), in_slew, load_cap, 0.0); if (drvr_slew < 0.0) result += "Negative slew clipped to 0.0\n"; return result; @@ -284,46 +332,30 @@ GateTableModel::driveResistance(const Pvt *pvt) const return slew / cap; } -const TableModel * -GateTableModel::delaySigmaModel(const EarlyLate *el) const -{ - return delay_sigma_models_[el->index()]; -} - -const TableModel * -GateTableModel::slewSigmaModel(const EarlyLate *el) const -{ - return slew_sigma_models_[el->index()]; -} - void GateTableModel::maxCapSlew(float in_slew, const Pvt *pvt, float &slew, float &cap) const { - if (!slew_model_) { - cap = 1.0; - slew = 0.0; - return; - } - const TableAxis *axis1 = slew_model_->axis1(); - const TableAxis *axis2 = slew_model_->axis2(); - const TableAxis *axis3 = slew_model_->axis3(); + TableModel *model = slew_models_->model(); + const TableAxis *axis1 = model->axis1(); + const TableAxis *axis2 = model->axis2(); + const TableAxis *axis3 = model->axis3(); if (axis1 && axis1->variable() == TableAxisVariable::total_output_net_capacitance) { cap = axis1->axisValue(axis1->size() - 1); - slew = findValue(pvt, slew_model_.get(), in_slew, cap, 0.0); + slew = findValue(pvt, model, in_slew, cap, 0.0); } else if (axis2 && axis2->variable()==TableAxisVariable::total_output_net_capacitance) { cap = axis2->axisValue(axis2->size() - 1); - slew = findValue(pvt, slew_model_.get(), in_slew, cap, 0.0); + slew = findValue(pvt, model, in_slew, cap, 0.0); } else if (axis3 && axis3->variable()==TableAxisVariable::total_output_net_capacitance) { cap = axis3->axisValue(axis3->size() - 1); - slew = findValue(pvt, slew_model_.get(), in_slew, cap, 0.0); + slew = findValue(pvt, model, in_slew, cap, 0.0); } else { // Table not dependent on capacitance. @@ -416,38 +448,24 @@ ReceiverModel::checkAxes(const TableModel *table) //////////////////////////////////////////////////////////////// CheckTableModel::CheckTableModel(LibertyCell *cell, - TableModel *model, - TableModelsEarlyLate sigma_models) : + TableModels *check_models) : CheckTimingModel(cell), - model_(model), - sigma_models_(std::move(sigma_models)) + check_models_(check_models) { } -CheckTableModel::CheckTableModel(LibertyCell *cell, - TableModel *model) : - CheckTimingModel(cell), - model_(model), - sigma_models_{} -{ -} +CheckTableModel::~CheckTableModel() = default; -CheckTableModel::~CheckTableModel() +const TableModel * +CheckTableModel::checkModel() const { - sigmaModelsDelete(sigma_models_); + return check_models_ ? check_models_->model() : nullptr; } void CheckTableModel::setIsScaled(bool is_scaled) { - if (model_) - model_->setIsScaled(is_scaled); -} - -const TableModel * -CheckTableModel::sigmaModel(const EarlyLate *el) const -{ - return sigma_models_[el->index()]; + check_models_->model()->setIsScaled(is_scaled); } ArcDelay @@ -455,22 +473,51 @@ CheckTableModel::checkDelay(const Pvt *pvt, float from_slew, float to_slew, float related_out_cap, - bool pocv_enabled) const + const MinMax *min_max, + PocvMode pocv_mode) const { - if (model_) { - float mean = findValue(pvt, model_.get(), from_slew, to_slew, related_out_cap); - float sigma_early = 0.0; - float sigma_late = 0.0; - if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()]) - sigma_early = findValue(pvt, sigma_models_[EarlyLate::earlyIndex()], - from_slew, to_slew, related_out_cap); - if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()]) - sigma_late = findValue(pvt, sigma_models_[EarlyLate::lateIndex()], - from_slew, to_slew, related_out_cap); - return makeDelay(mean, sigma_early, sigma_late); + ArcDelay check_delay; + if (check_models_) { + float margin = findValue(pvt, check_models_->model(), from_slew, + to_slew, related_out_cap); + check_delay.setMean(margin); + + switch (pocv_mode) { + case PocvMode::normal: { + TableModel *std_dev_model = check_models_->stdDev(); + if (std_dev_model == nullptr) + std_dev_model = check_models_->sigma(min_max); + if (std_dev_model) { + float std_dev = findValue(pvt, std_dev_model, from_slew, to_slew, related_out_cap); + check_delay.setStdDev(std_dev); + } + break; + } + case PocvMode::skew_normal: { + if (check_models_->meanShift()) { + float mean_shift = findValue(pvt, check_models_->meanShift(), + from_slew, to_slew, related_out_cap); + check_delay.setMeanShift(mean_shift); + } + + if (check_models_->stdDev()) { + float std_dev = findValue(pvt, check_models_->stdDev(), + from_slew, to_slew, related_out_cap); + check_delay.setStdDev(std_dev); + } + + if (check_models_->skewness()) { + float skewness = findValue(pvt, check_models_->skewness(), + from_slew, to_slew, related_out_cap); + check_delay.setSkewness(skewness); + } + break; + } + default: + break; + } } - else - return 0.0; + return check_delay; } float @@ -496,22 +543,28 @@ CheckTableModel::reportCheckDelay(const Pvt *pvt, const char *from_slew_annotation, float to_slew, float related_out_cap, - bool pocv_enabled, + const MinMax *min_max, + PocvMode pocv_mode, int digits) const { - std::string result = reportTableDelay("Check", pvt, model_.get(), - from_slew, from_slew_annotation, to_slew, - related_out_cap, digits); - if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()]) - result += reportTableDelay("Check sigma early", pvt, - sigma_models_[EarlyLate::earlyIndex()], - from_slew, from_slew_annotation, to_slew, - related_out_cap, digits); - if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()]) - result += reportTableDelay("Check sigma late", pvt, - sigma_models_[EarlyLate::lateIndex()], - from_slew, from_slew_annotation, to_slew, - related_out_cap, digits); + std::string result = reportTableDelay("Check", pvt, check_models_->model(), + from_slew, from_slew_annotation, to_slew, + related_out_cap, digits); + switch (pocv_mode) { + case PocvMode::normal: + case PocvMode::skew_normal: { + TableModel *check_table = check_models_->stdDev(); + if (check_table == nullptr) + check_table = check_models_->sigma(min_max); + if (check_table) + result += reportTableDelay("Check sigma", pvt, check_table, + from_slew, from_slew_annotation, to_slew, + related_out_cap, digits); + break; + } + default: + break; + } return result; } @@ -530,10 +583,11 @@ CheckTableModel::reportTableDelay(const char *result_name, findAxisValues(from_slew, to_slew, related_out_cap, axis_value1, axis_value2, axis_value3); std::string result = reportPvt(cell_, pvt, digits); - result += model_->reportValue(result_name, cell_, pvt, - axis_value1, from_slew_annotation, axis_value2, - axis_value3, - cell_->libertyLibrary()->units()->timeUnit(), digits); + const Unit *time_unit = cell_->libertyLibrary()->units()->timeUnit(); + result += check_models_->model()->reportValue(result_name, cell_, pvt, + axis_value1, from_slew_annotation, + axis_value2, axis_value3, + time_unit, digits); return result; } return ""; @@ -548,31 +602,32 @@ CheckTableModel::findAxisValues(float from_slew, float &axis_value2, float &axis_value3) const { - switch (model_->order()) { + TableModel *model = check_models_->model(); + switch (model->order()) { case 0: axis_value1 = 0.0; axis_value2 = 0.0; axis_value3 = 0.0; break; case 1: - axis_value1 = axisValue(model_->axis1(), from_slew, to_slew, + axis_value1 = axisValue(model->axis1(), from_slew, to_slew, related_out_cap); axis_value2 = 0.0; axis_value3 = 0.0; break; case 2: - axis_value1 = axisValue(model_->axis1(), from_slew, to_slew, + axis_value1 = axisValue(model->axis1(), from_slew, to_slew, related_out_cap); - axis_value2 = axisValue(model_->axis2(), from_slew, to_slew, + axis_value2 = axisValue(model->axis2(), from_slew, to_slew, related_out_cap); axis_value3 = 0.0; break; case 3: - axis_value1 = axisValue(model_->axis1(), from_slew, to_slew, + axis_value1 = axisValue(model->axis1(), from_slew, to_slew, related_out_cap); - axis_value2 = axisValue(model_->axis2(), from_slew, to_slew, + axis_value2 = axisValue(model->axis2(), from_slew, to_slew, related_out_cap); - axis_value3 = axisValue(model_->axis3(), from_slew, to_slew, + axis_value3 = axisValue(model->axis3(), from_slew, to_slew, related_out_cap); break; default: @@ -626,6 +681,75 @@ CheckTableModel::checkAxis(const TableAxis *axis) //////////////////////////////////////////////////////////////// +TableModels::TableModels() : + model_(nullptr), + sigma_{}, + std_dev_(nullptr), + mean_shift_(nullptr), + skewness_(nullptr) +{ +} + +TableModels::TableModels(TableModel *model) : + model_(model), + sigma_{}, + std_dev_(nullptr), + mean_shift_(nullptr), + skewness_(nullptr) +{ +} + +TableModels::~TableModels() +{ + TableModel *sigma_early = sigma_[EarlyLate::earlyIndex()]; + TableModel *sigma_late = sigma_[EarlyLate::lateIndex()]; + if (sigma_early == sigma_late) + delete sigma_early; + else { + delete sigma_early; + delete sigma_late; + } +} + +void +TableModels::setModel(TableModel *model) +{ + model_.reset(model); +} + +TableModel * +TableModels::sigma(const EarlyLate *early_late) const +{ + return sigma_[early_late->index()]; +} + +void +TableModels::setSigma(TableModel *table, + const EarlyLate *early_late) +{ + sigma_[early_late->index()] = table; +} + +void +TableModels::setMeanShift(TableModel *table) +{ + mean_shift_.reset(table); +} + +void +TableModels::setSkewness(TableModel *table) +{ + skewness_.reset(table); +} + +void +TableModels::setStdDev(TableModel *table) +{ + std_dev_.reset(table); +} + +//////////////////////////////////////////////////////////////// + TableModel::TableModel() : table_(nullptr), tbl_template_(nullptr), @@ -959,51 +1083,65 @@ Table::findValue(float axis_value1, return value_; if (order_ == 1) return findValue(axis_value1); - if (order_ == 2) { - size_t size1 = axis1_->size(); - size_t size2 = axis2_->size(); - if (size1 == 1) { - if (size2 == 1) - return value(0, 0); - size_t axis_index2 = axis2_->findAxisIndex(axis_value2); - double x2 = axis_value2; - double y00 = value(0, axis_index2); - double x2l = axis2_->axisValue(axis_index2); - double x2u = axis2_->axisValue(axis_index2 + 1); - double dx2 = (x2 - x2l) / (x2u - x2l); - double y01 = value(0, axis_index2 + 1); - return (1 - dx2) * y00 + dx2 * y01; - } - if (size2 == 1) { - size_t axis_index1 = axis1_->findAxisIndex(axis_value1); - double x1 = axis_value1; - double y00 = value(axis_index1, 0); - double x1l = axis1_->axisValue(axis_index1); - double x1u = axis1_->axisValue(axis_index1 + 1); - double dx1 = (x1 - x1l) / (x1u - x1l); - double y10 = value(axis_index1 + 1, 0); - return (1 - dx1) * y00 + dx1 * y10; - } - size_t axis_index1 = axis1_->findAxisIndex(axis_value1); + if (order_ == 2) + return findValueOrder2(axis_value1, axis_value2); + else + return findValueOrder3(axis_value1, axis_value2, axis_value3); +} + +float +Table::findValueOrder2(float axis_value1, + float axis_value2) const +{ + size_t size1 = axis1_->size(); + size_t size2 = axis2_->size(); + if (size1 == 1) { + if (size2 == 1) + return value(0, 0); size_t axis_index2 = axis2_->findAxisIndex(axis_value2); - double x1 = axis_value1; double x2 = axis_value2; - double y00 = value(axis_index1, axis_index2); - double x1l = axis1_->axisValue(axis_index1); - double x1u = axis1_->axisValue(axis_index1 + 1); - double dx1 = (x1 - x1l) / (x1u - x1l); - double y10 = value(axis_index1 + 1, axis_index2); - double y11 = value(axis_index1 + 1, axis_index2 + 1); + double y00 = value(0, axis_index2); double x2l = axis2_->axisValue(axis_index2); double x2u = axis2_->axisValue(axis_index2 + 1); double dx2 = (x2 - x2l) / (x2u - x2l); - double y01 = value(axis_index1, axis_index2 + 1); - return (1 - dx1) * (1 - dx2) * y00 - + dx1 * (1 - dx2) * y10 - + dx1 * dx2 * y11 - + (1 - dx1) * dx2 * y01; + double y01 = value(0, axis_index2 + 1); + return (1 - dx2) * y00 + dx2 * y01; } - // order_ == 3 - trilinear interpolation + if (size2 == 1) { + size_t axis_index1 = axis1_->findAxisIndex(axis_value1); + double x1 = axis_value1; + double y00 = value(axis_index1, 0); + double x1l = axis1_->axisValue(axis_index1); + double x1u = axis1_->axisValue(axis_index1 + 1); + double dx1 = (x1 - x1l) / (x1u - x1l); + double y10 = value(axis_index1 + 1, 0); + return (1 - dx1) * y00 + dx1 * y10; + } + size_t axis_index1 = axis1_->findAxisIndex(axis_value1); + size_t axis_index2 = axis2_->findAxisIndex(axis_value2); + double x1 = axis_value1; + double x2 = axis_value2; + double y00 = value(axis_index1, axis_index2); + double x1l = axis1_->axisValue(axis_index1); + double x1u = axis1_->axisValue(axis_index1 + 1); + double dx1 = (x1 - x1l) / (x1u - x1l); + double y10 = value(axis_index1 + 1, axis_index2); + double y11 = value(axis_index1 + 1, axis_index2 + 1); + double x2l = axis2_->axisValue(axis_index2); + double x2u = axis2_->axisValue(axis_index2 + 1); + double dx2 = (x2 - x2l) / (x2u - x2l); + double y01 = value(axis_index1, axis_index2 + 1); + return (1 - dx1) * (1 - dx2) * y00 + + dx1 * (1 - dx2) * y10 + + dx1 * dx2 * y11 + + (1 - dx1) * dx2 * y01; +} + +float +Table::findValueOrder3(float axis_value1, + float axis_value2, + float axis_value3) const +{ size_t axis_index1 = axis1_->findAxisIndex(axis_value1); size_t axis_index2 = axis2_->findAxisIndex(axis_value2); size_t axis_index3 = axis3_->findAxisIndex(axis_value3); diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 5d77e931..375ad68e 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -152,9 +152,8 @@ TimingArc::intrinsicDelay() const { GateTimingModel *model = dynamic_cast(model_); if (model) { - ArcDelay arc_delay; - Slew slew; - model->gateDelay(nullptr, 0.0, 0.0, false, arc_delay, slew); + float arc_delay, slew; + model->gateDelay(nullptr, 0.0, 0.0, arc_delay, slew); return arc_delay; } else diff --git a/power/Power.cc b/power/Power.cc index eb8d40cc..7a3de2af 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -1173,7 +1173,7 @@ Power::findInputInternalPower(const Pin *pin, int rf_count = 0; for (const RiseFall *rf : RiseFall::range()) { float slew = getSlew(vertex, rf, scene); - if (!delayInf(slew)) { + if (!delayInf(slew, this)) { float table_energy = pwr->power(rf, pvt, slew, load_cap); energy += table_energy; rf_count++; @@ -1238,17 +1238,18 @@ Power::getMinRfSlew(const Pin *pin) graph_->pinVertices(pin, vertex, bidir_vertex); if (vertex) { const MinMax *min_max = MinMax::min(); - Slew mm_slew = min_max->initValue(); + float mm_slew = min_max->initValue(); for (DcalcAPIndex ap_index = 0; ap_index < dcalcAnalysisPtCount(); ap_index++) { const Slew &slew1 = graph_->slew(vertex, RiseFall::rise(), ap_index); const Slew &slew2 = graph_->slew(vertex, RiseFall::fall(), ap_index); - Slew slew = delayAsFloat(slew1 + slew2) / 2.0; - if (delayGreater(slew, mm_slew, min_max, this)) - mm_slew = slew; + float slew_avg = (delayAsFloat(slew1, min_max, this) + + delayAsFloat(slew2, min_max, this)) / 2.0; + if (delayGreater(slew_avg, mm_slew, min_max, this)) + mm_slew = slew_avg; } - return delayAsFloat(mm_slew); + return mm_slew; } return 0.0; } @@ -1343,7 +1344,7 @@ Power::findOutputInternalPower(const LibertyPort *to_port, float slew = from_vertex ? getSlew(from_vertex, from_rf, scene) : 0.0; - if (!delayInf(slew)) { + if (!delayInf(slew, this)) { float table_energy = pwr->power(to_rf, pvt, slew, load_cap); energy += table_energy; rf_count++; diff --git a/sdc/Variables.cc b/sdc/Variables.cc index 6aae9894..f877fc45 100644 --- a/sdc/Variables.cc +++ b/sdc/Variables.cc @@ -39,7 +39,8 @@ Variables::Variables() : dynamic_loop_breaking_(false), propagate_all_clks_(false), use_default_arrival_clock_(false), - pocv_enabled_(false) + pocv_mode_(PocvMode::scalar), + pocv_quantile_(3.0) { } @@ -115,10 +116,24 @@ Variables::setUseDefaultArrivalClock(bool enable) use_default_arrival_clock_ = enable; } -void -Variables::setPocvEnabled(bool enabled) +//////////////////////////////////////////////////////////////// + +bool +Variables::pocvEnabled() const { - pocv_enabled_ = enabled; + return pocv_mode_ != PocvMode::scalar; } - + +void +Variables::setPocvMode(PocvMode mode) +{ + pocv_mode_ = mode; +} + +void +Variables::setPocvQuantile(float quantile) +{ + pocv_quantile_ = quantile; +} + } // namespace diff --git a/sdf/SdfReader.cc b/sdf/SdfReader.cc index 93804d87..81818127 100644 --- a/sdf/SdfReader.cc +++ b/sdf/SdfReader.cc @@ -735,7 +735,7 @@ SdfReader::setEdgeArcDelays(Edge *edge, if (value_ptr) { ArcDelay delay; if (in_incremental_) - delay = *value_ptr + graph_->arcDelay(edge, arc, arc_delay_index); + delay = delaySum(graph_->arcDelay(edge, arc, arc_delay_index), *value_ptr, this); else delay = *value_ptr; graph_->setArcDelay(edge, arc, arc_delay_index, delay); @@ -784,7 +784,7 @@ SdfReader::setEdgeArcDelaysCondUse(Edge *edge, && triple_index != null_index_) { ArcDelay delay(*value); if (!is_incremental_only_ && in_incremental_) - delay = graph_->arcDelay(edge, arc, arc_delay_index) + *value; + delay = delaySum(graph_->arcDelay(edge, arc, arc_delay_index), *value, this); else if (graph_->arcDelayAnnotated(edge, arc, arc_delay_index)) { ArcDelay prev_value = graph_->arcDelay(edge, arc, arc_delay_index); if (delayGreater(prev_value, delay, min_max, this)) diff --git a/sdf/SdfWriter.cc b/sdf/SdfWriter.cc index 6cc3cd1d..db7af6b0 100644 --- a/sdf/SdfWriter.cc +++ b/sdf/SdfWriter.cc @@ -430,11 +430,11 @@ SdfWriter::writeArcDelays(Edge *edge) TimingArcSet *arc_set = edge->timingArcSet(); for (TimingArc *arc : arc_set->arcs()) { const RiseFall *rf = arc->toEdge()->asRiseFall(); - ArcDelay min_delay = graph_->arcDelay(edge, arc, arc_delay_min_index_); - delays.setValue(rf, MinMax::min(), delayAsFloat(min_delay)); + const ArcDelay &min_delay = graph_->arcDelay(edge, arc, arc_delay_min_index_); + delays.setValue(rf, MinMax::min(), delayAsFloat(min_delay, MinMax::min(), this)); - ArcDelay max_delay = graph_->arcDelay(edge, arc, arc_delay_max_index_); - delays.setValue(rf, MinMax::max(), delayAsFloat(max_delay)); + const ArcDelay &max_delay = graph_->arcDelay(edge, arc, arc_delay_max_index_); + delays.setValue(rf, MinMax::max(), delayAsFloat(max_delay, MinMax::max(), this)); } if (delays.hasValue(RiseFall::rise(), MinMax::min()) @@ -527,8 +527,10 @@ SdfWriter::writeTimingChecks(const Instance *inst, 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_)); + min_width = delayAsFloat(graph_->arcDelay(edge, arc, arc_delay_min_index_), + MinMax::min(), this); + max_width = delayAsFloat(graph_->arcDelay(edge, arc, arc_delay_max_index_), + MinMax::max(), this); ensureTimingCheckheaders(check_header, inst, inst_header); writeWidthCheck(pin, hi_low, min_width, max_width); } @@ -615,30 +617,37 @@ SdfWriter::writeEdgeCheck(Edge *edge, if (arcs[clk_rf_index][RiseFall::riseIndex()] && arcs[clk_rf_index][RiseFall::fallIndex()] && arcs[clk_rf_index][RiseFall::riseIndex()] - && arcs[clk_rf_index][RiseFall::fallIndex()] - && delayEqual(graph_->arcDelay(edge, - arcs[clk_rf_index][RiseFall::riseIndex()], - arc_delay_min_index_), - graph_->arcDelay(edge, - arcs[clk_rf_index][RiseFall::fallIndex()], - arc_delay_min_index_)) - && delayEqual(graph_->arcDelay(edge, - arcs[clk_rf_index][RiseFall::riseIndex()], - arc_delay_max_index_), - graph_->arcDelay(edge, - arcs[clk_rf_index][RiseFall::fallIndex()], - arc_delay_max_index_))) - // Rise/fall margins are the same, so no data edge specifier is required. - writeCheck(edge, arcs[clk_rf_index][RiseFall::riseIndex()], - sdf_check, false, true); - else { - if (arcs[clk_rf_index][RiseFall::riseIndex()]) - writeCheck(edge, arcs[clk_rf_index][RiseFall::riseIndex()], - sdf_check, true, true); - if (arcs[clk_rf_index][RiseFall::fallIndex()]) - writeCheck(edge, arcs[clk_rf_index][RiseFall::fallIndex()], - sdf_check, true, true); + && arcs[clk_rf_index][RiseFall::fallIndex()]) { + float rise_min=delayAsFloat(graph_->arcDelay(edge, + arcs[clk_rf_index][RiseFall::riseIndex()], + arc_delay_min_index_), + MinMax::min(), this); + float fall_min=delayAsFloat(graph_->arcDelay(edge, + arcs[clk_rf_index][RiseFall::fallIndex()], + arc_delay_min_index_), + MinMax::min(), this); + float rise_max=delayAsFloat(graph_->arcDelay(edge, + arcs[clk_rf_index][RiseFall::riseIndex()], + arc_delay_max_index_), + MinMax::max(), this); + float fall_max=delayAsFloat(graph_->arcDelay(edge, + arcs[clk_rf_index][RiseFall::fallIndex()], + arc_delay_max_index_), + MinMax::max(), this); + if (fuzzyEqual(rise_min, fall_min) + && fuzzyEqual(rise_max, fall_max)) { + // Rise/fall margins are the same, so no data edge specifier is required. + writeCheck(edge, arcs[clk_rf_index][RiseFall::riseIndex()], + sdf_check, false, true); + return; + } } + if (arcs[clk_rf_index][RiseFall::riseIndex()]) + writeCheck(edge, arcs[clk_rf_index][RiseFall::riseIndex()], + sdf_check, true, true); + if (arcs[clk_rf_index][RiseFall::fallIndex()]) + writeCheck(edge, arcs[clk_rf_index][RiseFall::fallIndex()], + sdf_check, true, true); } void @@ -689,9 +698,11 @@ SdfWriter::writeCheck(Edge *edge, gzprintf(stream_, " "); - ArcDelay min_delay = graph_->arcDelay(edge, arc, arc_delay_min_index_); - ArcDelay max_delay = graph_->arcDelay(edge, arc, arc_delay_max_index_); - writeSdfTriple(delayAsFloat(min_delay), delayAsFloat(max_delay)); + float min_delay = delayAsFloat(graph_->arcDelay(edge, arc, arc_delay_min_index_), + MinMax::min(), this); + float max_delay = delayAsFloat(graph_->arcDelay(edge, arc, arc_delay_max_index_), + MinMax::max(), this); + writeSdfTriple(min_delay, max_delay); gzprintf(stream_, ")\n"); } diff --git a/search/CheckMaxSkews.cc b/search/CheckMaxSkews.cc index 8682f6f1..20cb5224 100644 --- a/search/CheckMaxSkews.cc +++ b/search/CheckMaxSkews.cc @@ -178,15 +178,15 @@ MaxSkewCheck::maxSkew(const StaState *sta) const } Delay -MaxSkewCheck::skew() const +MaxSkewCheck::skew(const StaState *sta) const { - return Delay(clk_path_->arrival() - ref_path_->arrival()); + return delayDiff(clk_path_->arrival(), ref_path_->arrival(), sta); } Slack MaxSkewCheck::slack(const StaState *sta) const { - return maxSkew(sta) - skew(); + return delayDiff(maxSkew(sta), skew(sta), sta); } //////////////////////////////////////////////////////////////// @@ -203,7 +203,7 @@ MaxSkewSlackLess::operator()(const MaxSkewCheck &check1, Slack slack1 = check1.slack(sta_); Slack slack2 = check2.slack(sta_); return delayLess(slack1, slack2, sta_) - || (delayEqual(slack1, slack2) + || (delayEqual(slack1, slack2, sta_) // Break ties based on constrained pin names. && sta_->network()->pinLess(check1.clkPin(sta_), check2.clkPin(sta_))); } diff --git a/search/CheckMaxSkews.hh b/search/CheckMaxSkews.hh index ac1660cc..dc64f0c0 100644 --- a/search/CheckMaxSkews.hh +++ b/search/CheckMaxSkews.hh @@ -48,7 +48,7 @@ public: Pin *clkPin(const StaState *sta) const; const Path *refPath() const { return ref_path_; } Pin *refPin(const StaState *sta) const; - Delay skew() const; + Delay skew(const StaState *sta) const; ArcDelay maxSkew(const StaState *sta) const; Slack slack(const StaState *sta) const; TimingArc *checkArc() const { return check_arc_; } diff --git a/search/CheckMinPeriods.cc b/search/CheckMinPeriods.cc index bb9b9282..195187c5 100644 --- a/search/CheckMinPeriods.cc +++ b/search/CheckMinPeriods.cc @@ -198,7 +198,7 @@ MinPeriodSlackLess::operator()(const MinPeriodCheck &check1, const Pin *pin2 = check2.pin(); return delayLess(slack1, slack2, sta_) // Break ties based on pin and clock names. - || (delayEqual(slack1, slack2) + || (delayEqual(slack1, slack2, sta_) && (sta_->network()->pinLess(pin1, pin2) || (pin1 == pin2 && ClockNameLess()(check1.clk(), diff --git a/search/CheckMinPulseWidths.cc b/search/CheckMinPulseWidths.cc index 0f7ff320..12c795ea 100644 --- a/search/CheckMinPulseWidths.cc +++ b/search/CheckMinPulseWidths.cc @@ -252,13 +252,13 @@ MinPulseWidthCheck::closeArrival(const StaState *sta) const Arrival MinPulseWidthCheck::openDelay(const StaState *sta) const { - return openArrival(sta) - openClkEdge(sta)->time(); + return delayDiff(openArrival(sta), openClkEdge(sta)->time(), sta); } Arrival MinPulseWidthCheck::closeDelay(const StaState *sta) const { - return closeArrival(sta) - closeClkEdge(sta)->time(); + return delayDiff(closeArrival(sta), closeClkEdge(sta)->time(), sta); } const ClockEdge * @@ -289,9 +289,11 @@ MinPulseWidthCheck::closeOffset(const StaState *sta) const Arrival MinPulseWidthCheck::width(const StaState *sta) const { - return closeArrival(sta) + closeOffset(sta) - - open_path_->arrival() - + checkCrpr(sta); + Arrival close_with_offset = delaySum(closeArrival(sta), + closeOffset(sta), + sta); + Arrival minus_open = delayDiff(close_with_offset, open_path_->arrival(), sta); + return delaySum(minus_open, checkCrpr(sta), sta); } float @@ -323,6 +325,7 @@ minPulseWidth(const Path *path, // set_min_pulse_width command. sdc->minPulseWidth(pin, clk, rf, min_width, exists); if (!exists) { + const MinMax *min_max = path->minMax(sta); DcalcAPIndex dcalc_ap = path->dcalcAnalysisPtIndex(sta); Vertex *vertex = path->vertex(sta); Graph *graph = sta->graph(); @@ -330,7 +333,7 @@ minPulseWidth(const Path *path, TimingArc *arc; graph->minPulseWidthArc(vertex, rf, edge, arc); if (edge) { - min_width = delayAsFloat(graph->arcDelay(edge, arc, dcalc_ap)); + min_width = delayAsFloat(graph->arcDelay(edge, arc, dcalc_ap), min_max, sta); exists = true; } } @@ -350,7 +353,7 @@ MinPulseWidthCheck::checkCrpr(const StaState *sta) const Slack MinPulseWidthCheck::slack(const StaState *sta) const { - return width(sta) - minWidth(sta); + return delayDiff(width(sta), minWidth(sta), sta); } Scene * @@ -375,7 +378,7 @@ MinPulseWidthSlackLess::operator()(const MinPulseWidthCheck &check1, const Pin *pin1 = check1.pin(sta_); const Pin *pin2 = check2.pin(sta_); return delayLess(slack1, slack2, sta_) - || (delayEqual(slack1, slack2) + || (delayEqual(slack1, slack2, sta_) // Break ties for the sake of regression stability. && (sta_->network()->pinLess(pin1, pin2) || (pin1 == pin2 diff --git a/search/ClkDelays.hh b/search/ClkDelays.hh index 2b9d6a36..e8a15749 100644 --- a/search/ClkDelays.hh +++ b/search/ClkDelays.hh @@ -61,9 +61,9 @@ public: StaState *sta); private: - static float insertionDelay(Path *clk_path, + static Delay insertionDelay(Path *clk_path, StaState *sta); - static float delay(Path *clk_path, + static Delay delay(Path *clk_path, StaState *sta); static float clkTreeDelay(Path *clk_path, StaState *sta); diff --git a/search/ClkInfo.cc b/search/ClkInfo.cc index 767a44a1..e3e3a05a 100644 --- a/search/ClkInfo.cc +++ b/search/ClkInfo.cc @@ -102,7 +102,7 @@ ClkInfo::findHash(const StaState *sta) hashIncr(hash_, hash_float(uncertainty)); } hashIncr(hash_, hash_float(latency_)); - hashIncr(hash_, hash_float(delayAsFloat(insertion_))); + hashIncr(hash_, hash_float(insertion_.mean())); hashIncr(hash_, is_propagated_); hashIncr(hash_, is_gen_clk_src_path_); hashIncr(hash_, is_pulse_clk_); @@ -152,9 +152,10 @@ ClkInfo::to_string(const StaState *sta) const Network *network = sta->network(); std::string result; + const MinMax *min_max = minMax(); result += scene_->name(); result += "/"; - result += minMax()->to_string(); + result += min_max->to_string(); result += " "; if (clk_edge_) @@ -186,7 +187,7 @@ ClkInfo::to_string(const StaState *sta) const if (delayGreater(insertion_, 0.0, sta)) { result += " insert"; - result += delayAsString(insertion_, sta); + result += delayAsString(insertion_, min_max, sta); } if (uncertainties_) { diff --git a/search/ClkLatency.cc b/search/ClkLatency.cc index 0c186704..b7b4bac5 100644 --- a/search/ClkLatency.cc +++ b/search/ClkLatency.cc @@ -116,15 +116,15 @@ ClkLatency::reportClkLatency(const Clock *clk, report_->reportLine(" min max"); report_->reportLine("%7s %7s source latency", - delayAsString(insertion_min, this, digits), - delayAsString(insertion_max, this, digits)); + delayAsString(insertion_min, MinMax::min(), digits, this), + delayAsString(insertion_max, MinMax::max(), digits, this)); report_->reportLine("%7s %7s network latency %s", - delayAsString(delay_min, this, digits), + delayAsString(delay_min, MinMax::min(), digits, this), "", sdc_network_->pathName(path_min.pin(this))); report_->reportLine("%7s %7s network latency %s", "", - delayAsString(delay_max, this, digits), + delayAsString(delay_max, MinMax::max(), digits, this), sdc_network_->pathName(path_max.pin(this))); if (internal_latency_min != 0.0 || internal_latency_max != 0.0) @@ -133,11 +133,11 @@ ClkLatency::reportClkLatency(const Clock *clk, time_unit->asString(internal_latency_max, digits)); report_->reportLine("---------------"); report_->reportLine("%7s %7s latency", - delayAsString(latency_min, this, digits), - delayAsString(latency_max, this, digits)); - Delay skew = latency_max - latency_min; + delayAsString(latency_min, MinMax::min(), digits, this), + delayAsString(latency_max, MinMax::max(), digits, this)); + Delay skew = delayDiff(latency_max, latency_min, this); report_->reportLine(" %7s skew", - delayAsString(skew, this, digits)); + delayAsString(skew, MinMax::max(), digits, this)); report_->reportBlankLine(); } } @@ -255,10 +255,10 @@ ClkDelays::setLatency(const RiseFall *src_rf, int end_rf_index = end_rf->index(); int mm_index = min_max->index(); - float insertion = insertionDelay(path, sta); + Delay insertion = insertionDelay(path, sta); insertion_[src_rf_index][end_rf_index][mm_index] = insertion; - float delay1 = delay(path, sta); + Delay delay1 = delay(path, sta); delay_[src_rf_index][end_rf_index][mm_index] = delay1; float internal_latency = 0.0; @@ -267,7 +267,7 @@ ClkDelays::setLatency(const RiseFall *src_rf, internal_latency_[src_rf_index][end_rf_index][mm_index] = internal_latency; } - float latency = insertion + delay1 + internal_latency; + Delay latency = delaySum(delay1, delaySum(insertion, internal_latency, sta), sta); latency_[src_rf_index][end_rf_index][mm_index] = latency; path_[src_rf_index][end_rf_index][mm_index] = *path; @@ -279,22 +279,22 @@ ClkDelays::latency(Path *clk_path, StaState *sta) { - float insertion = insertionDelay(clk_path, sta); - float delay1 = delay(clk_path, sta); + Delay insertion = insertionDelay(clk_path, sta); + Delay delay1 = delay(clk_path, sta); float lib_clk_delay = clkTreeDelay(clk_path, sta); - return insertion + delay1 + lib_clk_delay; + return delaySum(delay1, delaySum(insertion, lib_clk_delay, sta), sta); } -float +Delay ClkDelays::delay(Path *clk_path, StaState *sta) { Arrival arrival = clk_path->arrival(); const ClockEdge *path_clk_edge = clk_path->clkEdge(sta); - return delayAsFloat(arrival) - path_clk_edge->time(); + return delayDiff(arrival, path_clk_edge->time(), sta); } -float +Delay ClkDelays::insertionDelay(Path *clk_path, StaState *sta) { @@ -305,8 +305,7 @@ ClkDelays::insertionDelay(Path *clk_path, const Pin *src_pin = clk_info->clkSrc(); const MinMax *min_max = clk_path->minMax(sta); const Mode *mode = clk_path->mode(sta); - return delayAsFloat(sta->search()->clockInsertion(clk, src_pin, clk_rf, min_max, - min_max, mode)); + return sta->search()->clockInsertion(clk, src_pin, clk_rf, min_max, min_max, mode); } float @@ -318,7 +317,7 @@ ClkDelays::clkTreeDelay(Path *clk_path, const LibertyPort *port = sta->network()->libertyPort(pin); const MinMax *min_max = clk_path->minMax(sta); const RiseFall *rf = clk_path->transition(sta); - float slew = delayAsFloat(clk_path->slew(sta)); + float slew = delayAsFloat(clk_path->slew(sta), min_max, sta); return port->clkTreeDelay(slew, rf, min_max); } diff --git a/search/ClkSkew.cc b/search/ClkSkew.cc index ddbeb397..56590fc4 100644 --- a/search/ClkSkew.cc +++ b/search/ClkSkew.cc @@ -95,16 +95,17 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew, Unit *time_unit = units_->timeUnit(); Path *src_path = clk_skew.srcPath(); Path *tgt_path = clk_skew.tgtPath(); - float src_latency = clk_skew.srcLatency(this); + const MinMax *src_min_max = src_path->minMax(this); + Arrival src_latency = clk_skew.srcLatency(this); float tgt_latency = clk_skew.tgtLatency(this); float src_internal_clk_latency = clk_skew.srcInternalClkLatency(this); float tgt_internal_clk_latency = clk_skew.tgtInternalClkLatency(this); float uncertainty = clk_skew.uncertainty(this); if (src_internal_clk_latency != 0.0) - src_latency -= src_internal_clk_latency; + delayDecr(src_latency, src_internal_clk_latency, this); report_->reportLine("%7s source latency %s %s", - time_unit->asString(src_latency, digits), + delayAsString(src_latency, src_min_max, digits, this), sdc_network_->pathName(src_path->pin(this)), src_path->transition(this)->shortName()); if (src_internal_clk_latency != 0.0) @@ -124,15 +125,32 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew, report_->reportLine("%7s clock uncertainty", time_unit->asString(uncertainty, digits)); report_->reportLine("%7s CRPR", - time_unit->asString(delayAsFloat(-clk_skew.crpr(this)), - digits)); + delayAsString(delayDiff(0.0, clk_skew.crpr(this), this), + MinMax::max(), digits, this)); report_->reportLine("--------------"); report_->reportLine("%7s %s skew", - time_unit->asString(clk_skew.skew(), digits), + delayAsString(clk_skew.skew(), MinMax::max(), digits, this), src_path->minMax(this) == MinMax::max() ? "setup" : "hold"); } -float +static float +delayAbsMax(const Delay &delay, + const StaState *sta) +{ + float min = delayAsFloat(delay, MinMax::min(), sta); + float max = delayAsFloat(delay, MinMax::max(), sta); + return std::max(std::abs(min), std::abs(max)); +} + +static bool +delayAbsGreater(const Delay &delay1, + const Delay &delay2, + const StaState *sta) +{ + return delayAbsMax(delay1, sta) > delayAbsMax(delay2, sta); +} + +Delay ClkSkews::findWorstClkSkew(const SceneSeq &scenes, const SetupHold *setup_hold, bool include_internal_latency) @@ -143,10 +161,10 @@ ClkSkews::findWorstClkSkew(const SceneSeq &scenes, clks.push_back(clk); } findClkSkew(clks, scenes, include_internal_latency); - float worst_skew = 0.0; + Delay worst_skew = 0.0; for (const auto& [clk, clk_skews] : skews_) { - float skew = clk_skews[setup_hold->index()].skew(); - if (std::abs(skew) > std::abs(worst_skew)) + Delay skew = clk_skews[setup_hold->index()].skew(); + if (delayAbsGreater(skew, worst_skew, this)) worst_skew = skew; } return worst_skew; @@ -206,10 +224,12 @@ ClkSkews::findClkSkew(ConstClockSeq &clks, for (int setup_hold_idx : SetupHold::rangeIndex()) { ClkSkew &final_skew = itr->second[setup_hold_idx]; ClkSkew &partial_skew_val = partial_skew[setup_hold_idx]; - float partial_skew1 = partial_skew_val.skew(); - float final_skew1 = final_skew.skew(); - if (std::abs(partial_skew1) > std::abs(final_skew1) - || (fuzzyEqual(std::abs(partial_skew1), std::abs(final_skew1)) + Delay partial_skew1 = partial_skew_val.skew(); + Delay final_skew1 = final_skew.skew(); + float partial_skew_max = delayAbsMax(partial_skew1, this); + float final_skew_max = delayAbsMax(final_skew1, this); + if (partial_skew_max > final_skew_max + || (fuzzyEqual(partial_skew_max, final_skew_max) // Break ties based on source/target path names. && ClkSkew::srcTgtPathNameLess(partial_skew_val, final_skew, this))) final_skew = partial_skew_val; @@ -299,7 +319,8 @@ ClkSkews::findClkSkew(Vertex *src_vertex, && src_rf->matches(src_path->transition(this)) && clk_set_.contains(src_clk) && scenes_set_.contains(src_scene)) { - const MinMax *tgt_min_max = src_path->minMax(this)->opposite(); + const MinMax *src_min_max = src_path->minMax(this); + const MinMax *tgt_min_max = src_min_max->opposite(); VertexPathIterator tgt_iter(tgt_vertex, this); while (tgt_iter.hasNext()) { Path *tgt_path = tgt_iter.next(); @@ -316,14 +337,14 @@ ClkSkews::findClkSkew(Vertex *src_vertex, "%s %s %s -> %s %s %s crpr = %s skew = %s", network_->pathName(src_path->pin(this)), src_path->transition(this)->shortName(), - time_unit->asString(probe.srcLatency(this)), + delayAsString(probe.srcLatency(this), src_min_max, this), network_->pathName(tgt_path->pin(this)), tgt_path->transition(this)->shortName(), time_unit->asString(probe.tgtLatency(this)), delayAsString(probe.crpr(this), this), - time_unit->asString(probe.skew())); + delayAsString(probe.skew(), MinMax::max(), this)); if (clk_skew.srcPath() == nullptr - || std::abs(probe.skew()) > std::abs(clk_skew.skew())) + || delayAbsGreater(probe.skew(), clk_skew.skew(), this)) clk_skew = probe; } } @@ -380,10 +401,8 @@ ClkSkew::ClkSkew(Path *src_path, tgt_path_(tgt_path), include_internal_latency_(include_internal_latency) { - skew_ = srcLatency(sta) - - tgtLatency(sta) - - delayAsFloat(crpr(sta)) - + uncertainty(sta); + skew_ = delayDiff(delaySum(srcLatency(sta), uncertainty(sta), sta), + delaySum(tgtLatency(sta), crpr(sta), sta), sta); } ClkSkew::ClkSkew(const ClkSkew &clk_skew) @@ -403,12 +422,11 @@ ClkSkew::operator=(const ClkSkew &clk_skew) skew_ = clk_skew.skew_; } -float +Arrival ClkSkew::srcLatency(const StaState *sta) { - Arrival src_arrival = src_path_->arrival(); - return delayAsFloat(src_arrival) - src_path_->clkEdge(sta)->time() - + clkTreeDelay(src_path_, sta); + return delayDiff(delaySum(src_path_->arrival(), clkTreeDelay(src_path_, sta), sta), + src_path_->clkEdge(sta)->time(), sta); } float @@ -421,8 +439,8 @@ float ClkSkew::tgtLatency(const StaState *sta) { Arrival tgt_arrival = tgt_path_->arrival(); - return delayAsFloat(tgt_arrival) - tgt_path_->clkEdge(sta)->time() - + clkTreeDelay(tgt_path_, sta); + return delayAsFloat(delaySum(delayDiff(tgt_arrival, tgt_path_->clkEdge(sta)->time(),sta), + clkTreeDelay(tgt_path_, sta), sta)); } float @@ -441,7 +459,7 @@ ClkSkew::clkTreeDelay(Path *clk_path, const LibertyPort *port = sta->network()->libertyPort(pin); const MinMax *min_max = clk_path->minMax(sta); const RiseFall *rf = clk_path->transition(sta); - float slew = delayAsFloat(clk_path->slew(sta)); + float slew = delayAsFloat(clk_path->slew(sta), min_max, sta); return port->clkTreeDelay(slew, rf, min_max); } else diff --git a/search/ClkSkew.hh b/search/ClkSkew.hh index 349589e3..1ce1cf43 100644 --- a/search/ClkSkew.hh +++ b/search/ClkSkew.hh @@ -52,13 +52,13 @@ public: void operator=(const ClkSkew &clk_skew); Path *srcPath() { return src_path_; } Path *tgtPath() { return tgt_path_; } - float srcLatency(const StaState *sta); + Arrival srcLatency(const StaState *sta); float tgtLatency(const StaState *sta); float srcInternalClkLatency(const StaState *sta); float tgtInternalClkLatency(const StaState *sta); Crpr crpr(const StaState *sta); float uncertainty(const StaState *sta); - float skew() const { return skew_; } + Delay skew() const { return skew_; } static bool srcTgtPathNameLess(ClkSkew &clk_skew1, ClkSkew &clk_skew2, const StaState *sta); @@ -70,7 +70,7 @@ private: Path *src_path_; Path *tgt_path_; bool include_internal_latency_; - float skew_; + Delay skew_; }; using ClkSkewMap = std::map; @@ -97,7 +97,7 @@ public: bool include_internal_latency, int digits); // Find worst clock skew between src/target registers. - float findWorstClkSkew(const SceneSeq &scenes, + Delay findWorstClkSkew(const SceneSeq &scenes, const SetupHold *setup_hold, bool include_internal_latency); diff --git a/search/Crpr.cc b/search/Crpr.cc index 4d1bc3a0..21361ed2 100644 --- a/search/Crpr.cc +++ b/search/Crpr.cc @@ -273,19 +273,16 @@ CheckCrpr::findCrpr1(const Path *src_clk_path, if (variables_->pocvEnabled()) { // Remove variation on the common path. // Note that the crpr sigma is negative to offset the - // sigma of the common clock path. - const EarlyLate *src_el = src_clk_path->minMax(this); - const EarlyLate *tgt_el = tgt_clk_path->minMax(this); - Arrival src_arrival = src_clk_path->arrival(); - Arrival tgt_arrival = tgt_clk_path->arrival(); + // std_dev of the common clock path. + const Arrival &src_arrival = src_clk_path->arrival(); + const Arrival &tgt_arrival = tgt_clk_path->arrival(); float src_clk_time = src_clk_path->clkEdge(this)->time(); float tgt_clk_time = tgt_clk_path->clkEdge(this)->time(); - float crpr_mean = std::abs(delayAsFloat(src_arrival) - src_clk_time - - (delayAsFloat(tgt_arrival) - tgt_clk_time)); + float crpr_mean = std::abs(src_arrival.mean() - src_clk_time + - (tgt_arrival.mean() - tgt_clk_time)); // Remove the sigma from both source and target path arrivals. - float crpr_sigma2 = delaySigma2(src_arrival, src_el) - + delaySigma2(tgt_arrival, tgt_el); - return makeDelay2(crpr_mean, -crpr_sigma2, -crpr_sigma2); + float crpr_sigma2 = src_arrival.stdDev2() + tgt_arrival.stdDev2(); + return makeDelay2(crpr_mean, -crpr_sigma2); } else { // The source and target edges are different so the crpr @@ -308,8 +305,9 @@ float CheckCrpr::crprArrivalDiff(const Path *path) { Arrival other_arrival = otherMinMaxArrival(path); - float crpr_diff = std::abs(delayAsFloat(path->arrival()) - - delayAsFloat(other_arrival)); + const MinMax *min_max = path->minMax(this); + float crpr_diff = std::abs(delayAsFloat(path->arrival(), min_max, this) + - delayAsFloat(other_arrival, min_max->opposite(), this)); return crpr_diff; } diff --git a/search/Latches.cc b/search/Latches.cc index 8389c9c1..16bde088 100644 --- a/search/Latches.cc +++ b/search/Latches.cc @@ -70,7 +70,7 @@ Latches::latchRequired(const Path *data_path, ignore_clk_latency = path_delay->ignoreClkLatency(); } if (ignore_clk_latency) { - required = max_delay + src_clk_latency; + required = delaySum(src_clk_latency, max_delay, this); borrow = 0.0; adjusted_data_arrival = data_arrival; time_given_to_startpoint = 0.0; @@ -98,13 +98,15 @@ Latches::latchRequired(const Path *data_path, // checkTgtClkTime float tgt_clk_time = path_delay ? 0.0 : acct->requiredTime(check_role); // checkTgtClkArrival broken down into components. - Arrival enable_arrival = max_delay - + tgt_clk_time - + open_latency - + open_uncertainty - + PathEnd::checkSetupMcpAdjustment(data_clk_edge, enable_clk_edge, mcp, - 1, sdc) - + open_crpr; + Arrival enable_arrival = delaySum(max_delay + + tgt_clk_time + + open_uncertainty + + PathEnd::checkSetupMcpAdjustment(data_clk_edge, + enable_clk_edge, + mcp, 1, sdc), + open_latency, + this); + enable_arrival = delaySum(enable_arrival, open_crpr, this); debugPrint(debug_, "latch", 1, "data %s enable %s", delayAsString(data_arrival, this), delayAsString(enable_arrival, this)); @@ -117,25 +119,31 @@ Latches::latchRequired(const Path *data_path, } else { // Data arrives while latch is transparent. - borrow = data_arrival - enable_arrival; + borrow = delayDiff(data_arrival, enable_arrival, this); if (delayLessEqual(borrow, max_borrow, this)) required = data_arrival; else { borrow = max_borrow; - required = enable_arrival + max_borrow; + required = delaySum(enable_arrival, max_borrow, this); } - time_given_to_startpoint = borrow + open_uncertainty + open_crpr; + time_given_to_startpoint = delaySum(delaySum(borrow, + open_uncertainty, + this), + open_crpr, this); // Cycle accounting for required time is with respect to the // data clock zeroth cycle. The data departs the latch // with respect to the enable clock zeroth cycle. float data_shift_to_enable_clk = acct->sourceTimeOffset(check_role) - acct->targetTimeOffset(check_role); - adjusted_data_arrival = required + data_shift_to_enable_clk; + adjusted_data_arrival = delaySum(required, data_shift_to_enable_clk, this); } } else if (disable_path) { - required = max_delay + search_->clkPathArrival(disable_path) - margin; + required = delayDiff(delaySum(max_delay, + search_->clkPathArrival(disable_path), + this), + margin, this); // Borrow cannot be determined without enable path. borrow = 0.0; adjusted_data_arrival = data_arrival; @@ -176,7 +184,7 @@ Latches::latchBorrowInfo(const Path *data_path, const ClockEdge *enable_clk_edge = enable_path->clkEdge(this); const ClockEdge *disable_clk_edge = disable_path->clkEdge(this); bool is_pulse_clk = enable_path->clkInfo(this)->isPulseClk(); - nom_pulse_width = is_pulse_clk ? 0.0F : enable_clk_edge->pulseWidth(); + nom_pulse_width = is_pulse_clk ? 0.0 : enable_clk_edge->pulseWidth(); open_uncertainty = PathEnd::checkClkUncertainty(data_clk_edge, enable_clk_edge, enable_path, TimingRole::latchSetup(), sdc); @@ -190,14 +198,14 @@ Latches::latchBorrowInfo(const Path *data_path, CheckCrpr *check_crpr = search_->checkCrpr(); open_crpr = check_crpr->checkCrpr(data_path, enable_path); Crpr close_crpr = check_crpr->checkCrpr(data_path, disable_path); - crpr_diff = open_crpr - close_crpr; + crpr_diff = delayDiff(open_crpr, close_crpr, this); open_latency = PathEnd::checkTgtClkDelay(enable_path, enable_clk_edge, TimingRole::setup(), this); Arrival close_latency = PathEnd::checkTgtClkDelay(disable_path, disable_clk_edge, TimingRole::latchSetup(), this); - latency_diff = open_latency - close_latency; + latency_diff = delayDiff(open_latency, close_latency, this); } float borrow_limit; sdc->latchBorrowLimit(data_path->pin(this), disable_path->pin(this), @@ -206,8 +214,9 @@ Latches::latchBorrowInfo(const Path *data_path, if (borrow_limit_exists) max_borrow = borrow_limit; else - max_borrow = nom_pulse_width - delayAsFloat(latency_diff) - - delayAsFloat(crpr_diff) - delayAsFloat(margin); + max_borrow = delayDiff(nom_pulse_width, + delaySum(delaySum(latency_diff, crpr_diff, this), + margin, this), this); } else { nom_pulse_width = 0.0; @@ -349,7 +358,7 @@ Latches::latchOutArrival(const Path *data_path, if (!(excpt && excpt->isFalse())) { arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge, false, min_max, dcalc_ap, sdc); - q_arrival = data_path->arrival() + arc_delay; + q_arrival = delaySum(data_path->arrival(), arc_delay, this); // Copy the data tag but remove the drprClkPath. // Levelization does not traverse latch D->Q edges, so in some cases // level(Q) < level(D) @@ -405,7 +414,7 @@ Latches::latchOutArrival(const Path *data_path, // Latch is transparent when data arrives. arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge, false, min_max, dcalc_ap, sdc); - q_arrival = adjusted_data_arrival + arc_delay; + q_arrival = delaySum(adjusted_data_arrival, arc_delay, this); // Tag switcheroo - data passing thru gets latch enable tag. // States and path ap come from Q, everything else from enable. Path *crpr_clk_path = crprActive(mode) ? enable_path : nullptr; diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index e1f9cba7..39f712fe 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -281,9 +281,9 @@ MakeEndTimingArcs::visit(PathEnd *path_end) Arrival data_delay = src_path->arrival(); 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; + Delay margin = (min_max == MinMax::max()) + ? delaySum(delayDiff(data_delay, clk_latency, sta_), check_margin, sta_) + : delaySum(delayDiff(clk_latency, data_delay, sta_), check_margin, sta_); float delay1 = delayAsFloat(margin, MinMax::max(), sta_); debugPrint(debug, "make_timing_model", 2, "%s -> %s clock %s %s %s %s", input_rf_->shortName(), @@ -605,10 +605,10 @@ MakeTimingModel::makeScalarCheckModel(float value, TablePtr table = std::make_shared(value); TableTemplate *tbl_template = library_->findTableTemplate("scalar", TableTemplateType::delay); - TableModel *table_model = new TableModel(table, tbl_template, - scale_factor_type, rf); - CheckTableModel *check_model = new CheckTableModel(cell_, table_model); - return check_model; + TableModel *check_table = new TableModel(table, tbl_template, scale_factor_type, rf); + TableModels *check_tables = new TableModels(check_table); + CheckTableModel *check = new CheckTableModel(cell_, check_tables); + return check; } TimingModel * @@ -622,9 +622,12 @@ MakeTimingModel::makeGateModelScalar(Delay delay, library_->findTableTemplate("scalar", TableTemplateType::delay); TableModel *delay_model = new TableModel(delay_table, tbl_template, ScaleFactorType::cell, rf); + TableModels *delay_models = new TableModels(delay_model); TableModel *slew_model = new TableModel(slew_table, tbl_template, ScaleFactorType::cell, rf); - GateTableModel *gate_model = new GateTableModel(cell_, delay_model, slew_model); + TableModels *slew_models = new TableModels(slew_model); + GateTableModel *gate_model = new GateTableModel(cell_, delay_models, slew_models, + nullptr, nullptr); return gate_model; } @@ -637,7 +640,9 @@ MakeTimingModel::makeGateModelScalar(Delay delay, library_->findTableTemplate("scalar", TableTemplateType::delay); TableModel *delay_model = new TableModel(delay_table, tbl_template, ScaleFactorType::cell, rf); - GateTableModel *gate_model = new GateTableModel(cell_, delay_model, nullptr); + TableModels *models = new TableModels(delay_model); + GateTableModel *gate_model = new GateTableModel(cell_, models, nullptr, + nullptr, nullptr); return gate_model; } @@ -674,12 +679,11 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin, float output_load_cap = graph_delay_calc_->loadCap(output_pin, scene_, min_max_); - ArcDelay drvr_self_delay; - Slew drvr_self_slew; - drvr_gate_model->gateDelay(pvt, in_slew1, output_load_cap, false, + float drvr_self_delay, drvr_self_slew; + drvr_gate_model->gateDelay(pvt, in_slew1, output_load_cap, drvr_self_delay, drvr_self_slew); - const TableModel *drvr_table = drvr_gate_model->delayModel(); + const TableModel *drvr_table = drvr_gate_model->delayModels()->model(); const TableTemplate *drvr_template = drvr_table->tblTemplate(); const TableAxis *drvr_load_axis = loadCapacitanceAxis(drvr_table); if (drvr_load_axis) { @@ -689,13 +693,13 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin, for (size_t i = 0; i < drvr_axis_values.size(); i++) { float load_cap = drvr_axis_values[i]; // get slew from driver input pin - ArcDelay gate_delay; - Slew gate_slew; - drvr_gate_model->gateDelay(pvt, in_slew1, load_cap, false, + float gate_delay, gate_slew; + drvr_gate_model->gateDelay(pvt, in_slew1, load_cap, gate_delay, gate_slew); // Remove the self delay driving the output pin net load cap. - load_values->push_back(delayAsFloat(delay + gate_delay - - drvr_self_delay)); + load_values->push_back(delayAsFloat(delay) + + gate_delay + - drvr_self_delay); slew_values->push_back(delayAsFloat(gate_slew)); } @@ -711,10 +715,14 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin, load_axis); TableModel *delay_model = new TableModel(delay_table, model_template, ScaleFactorType::cell, rf); + TableModels *delay_models = new TableModels(delay_model); TableModel *slew_model = new TableModel(slew_table, model_template, ScaleFactorType::cell, rf); - GateTableModel *gate_model = new GateTableModel(cell_, delay_model, - slew_model); + TableModels *slew_models = new TableModels(slew_model); + GateTableModel *gate_model = new GateTableModel(cell_, + delay_models, + slew_models, + nullptr, nullptr); return gate_model; } } diff --git a/search/Path.cc b/search/Path.cc index 8ec27d20..84b4764b 100644 --- a/search/Path.cc +++ b/search/Path.cc @@ -75,7 +75,7 @@ Path::Path(Vertex *vertex, Path::Path(Vertex *vertex, Tag *tag, - Arrival arrival, + const Arrival &arrival, Path *prev_path, Edge *prev_edge, TimingArc *prev_arc, @@ -99,7 +99,7 @@ Path::Path(Vertex *vertex, Path::Path(Vertex *vertex, Tag *tag, - Arrival arrival, + const Arrival &arrival, Path *prev_path, Edge *prev_edge, TimingArc *prev_arc, @@ -124,7 +124,7 @@ Path::Path(Vertex *vertex, void Path::init(Vertex *vertex, - Arrival arrival, + const Arrival &arrival, const StaState *sta) { const Graph *graph = sta->graph(); @@ -155,7 +155,7 @@ Path::init(Vertex *vertex, void Path::init(Vertex *vertex, Tag *tag, - Arrival arrival, + const Arrival &arrival, const StaState *sta) { const Graph *graph = sta->graph(); @@ -171,7 +171,7 @@ Path::init(Vertex *vertex, void Path::init(Vertex *vertex, Tag *tag, - Arrival arrival, + const Arrival &arrival, Path *prev_path, Edge *prev_edge, TimingArc *prev_arc, @@ -330,7 +330,7 @@ Path::pathAnalysisPtIndex(const StaState *sta) const return scene(sta)->pathIndex(minMax(sta)); } -Slew +const Slew & Path::slew(const StaState *sta) const { DcalcAPIndex slew_index = scene(sta)->dcalcAnalysisPtIndex(minMax(sta)); @@ -365,9 +365,9 @@ Slack Path::slack(const StaState *sta) const { if (minMax(sta) == MinMax::max()) - return required_ - arrival_; + return delayDiff(required_, arrival_, sta); else - return arrival_ - required_; + return delayDiff(arrival_, required_, sta); } Path * diff --git a/search/PathEnd.cc b/search/PathEnd.cc index 6c644592..13e23fea 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -102,7 +102,7 @@ PathEnd::sourceClkEdge(const StaState *sta) const return path_->clkEdge(sta); } -Arrival +const Arrival & PathEnd::dataArrivalTime(const StaState *) const { return path_->arrival(); @@ -111,13 +111,17 @@ PathEnd::dataArrivalTime(const StaState *) const Arrival PathEnd::dataArrivalTimeOffset(const StaState *sta) const { - return dataArrivalTime(sta) + sourceClkOffset(sta); + return delaySum(dataArrivalTime(sta), + sourceClkOffset(sta), + sta); } Required PathEnd::requiredTimeOffset(const StaState *sta) const { - return requiredTime(sta) + sourceClkOffset(sta); + return delaySum(requiredTime(sta), + sourceClkOffset(sta), + sta); } const RiseFall * @@ -259,9 +263,9 @@ Crpr PathEnd::checkCrpr(const StaState *sta) const { if (checkRole(sta)->genericRole() == TimingRole::hold()) - return -crpr(sta); + return delayDiff(delay_zero, crpr(sta), sta); else - return crpr(sta);; + return crpr(sta); } Crpr @@ -301,7 +305,7 @@ PathEnd::checkTgtClkDelay(const Path *tgt_clk_path, Delay insertion, latency; checkTgtClkDelay(tgt_clk_path, tgt_clk_edge, check_role, sta, insertion, latency); - return Delay(insertion + latency); + return delaySum(insertion, latency, sta); } void @@ -334,7 +338,8 @@ PathEnd::checkTgtClkDelay(const Path *tgt_clk_path, Delay path_insertion = search->clockInsertion(tgt_clk, tgt_src_pin, tgt_clk_rf, min_max, min_max, mode); - latency = delayRemove(clk_arrival - tgt_clk_edge->time(), path_insertion); + latency = delayRemove(delayDiff(clk_arrival, tgt_clk_edge->time(), sta), + path_insertion); } else // Ideal clock. @@ -615,21 +620,25 @@ PathEndClkConstrained::targetClkTime(const StaState *sta) const Arrival PathEndClkConstrained::targetClkArrival(const StaState *sta) const { - return targetClkArrivalNoCrpr(sta) - + checkCrpr(sta); + return delaySum(targetClkArrivalNoCrpr(sta), + checkCrpr(sta), + sta); } Arrival PathEndClkConstrained::targetClkArrivalNoCrpr(const StaState *sta) const { Sdc *sdc = path_->sdc(sta); - return targetClkTime(sta) - + targetClkDelay(sta) - + checkClkUncertainty(sourceClkEdge(sta), - targetClkEdge(sta), - targetClkPath(), - checkRole(sta), sdc) - + targetClkMcpAdjustment(sta); + Arrival clk_arrival = delaySum(targetClkDelay(sta), + targetClkTime(sta), + sta); + float uncertainty = checkClkUncertainty(sourceClkEdge(sta), + targetClkEdge(sta), + targetClkPath(), + checkRole(sta), + sdc); + return delaySum(delaySum(clk_arrival, uncertainty, sta), + targetClkMcpAdjustment(sta), sta); } Delay @@ -704,8 +713,9 @@ PathEndClkConstrained::crpr(const StaState *sta) const Required PathEndClkConstrained::requiredTime(const StaState *sta) const { - return requiredTimeNoCrpr(sta) - + checkCrpr(sta); + return delaySum(requiredTimeNoCrpr(sta), + checkCrpr(sta), + sta); } Required @@ -714,9 +724,9 @@ PathEndClkConstrained::requiredTimeNoCrpr(const StaState *sta) const Arrival tgt_clk_arrival = targetClkArrivalNoCrpr(sta); ArcDelay check_margin = margin(sta); if (checkGenericRole(sta) == TimingRole::setup()) - return tgt_clk_arrival - check_margin; + return delayDiff(tgt_clk_arrival, check_margin, sta); else - return tgt_clk_arrival + check_margin; + return delaySum(tgt_clk_arrival, check_margin, sta); } Slack @@ -725,9 +735,9 @@ PathEndClkConstrained::slack(const StaState *sta) const Arrival arrival = dataArrivalTime(sta); Required required = requiredTime(sta); if (checkGenericRole(sta) == TimingRole::setup()) - return required - arrival; + return delayDiff(required, arrival, sta); else - return arrival - required; + return delayDiff(arrival, required, sta); } int @@ -862,9 +872,9 @@ PathEndClkConstrained::slackNoCrpr(const StaState *sta) const Arrival arrival = dataArrivalTime(sta); Required required = requiredTimeNoCrpr(sta); if (checkGenericRole(sta) == TimingRole::setup()) - return required - arrival; + return delayDiff(required, arrival, sta); else - return arrival - required; + return delayDiff(arrival, required, sta); } void @@ -1017,10 +1027,18 @@ PathEndCheck::exceptPathCmp(const PathEnd *path_end, Delay PathEndCheck::clkSkew(const StaState *sta) { - return sourceClkDelay(sta) - targetClkDelay(sta) - crpr(sta) - // Uncertainty decreases slack, but increases skew. - - checkTgtClkUncertainty(clk_path_, clk_path_->clkEdge(sta), - checkRole(sta), sta); + Delay skew = delayDiff(sourceClkDelay(sta), + targetClkDelay(sta), + sta); + skew = delayDiff(skew, crpr(sta), sta); + // Uncertainty decreases slack, but increases skew. + skew = delayDiff(skew, + checkTgtClkUncertainty(clk_path_, + clk_path_->clkEdge(sta), + checkRole(sta), + sta), + sta); + return skew; } Delay @@ -1035,7 +1053,8 @@ PathEndCheck::sourceClkDelay(const StaState *sta) const Arrival clk_arrival = src_clk_path->arrival(); const ClockEdge *src_clk_edge = src_clk_info->clkEdge(); Delay insertion = sourceClkInsertionDelay(sta); - return delayRemove(clk_arrival - src_clk_edge->time(), insertion); + return delayRemove(delayDiff(clk_arrival, src_clk_edge->time(), sta), + insertion); } else // Ideal clock. @@ -1052,9 +1071,17 @@ PathEndCheck::requiredTimeNoCrpr(const StaState *sta) const ArcDelay check_margin = margin(sta); float macro_clk_tree_delay = macroClkTreeDelay(sta); if (checkGenericRole(sta) == TimingRole::setup()) - return tgt_clk_arrival - (check_margin + macro_clk_tree_delay); + return delayDiff(tgt_clk_arrival, + delaySum(check_margin, + macro_clk_tree_delay, + sta), + sta); else - return tgt_clk_arrival + (check_margin - macro_clk_tree_delay); + return delaySum(tgt_clk_arrival, + delayDiff(check_margin, + macro_clk_tree_delay, + sta), + sta); } float @@ -1072,7 +1099,7 @@ PathEndCheck::macroClkTreeDelay(const StaState *sta) const if (clk_port) { const MinMax *min_max = clk_path_->minMax(sta); const RiseFall *rf = clk_path_->transition(sta); - float slew = delayAsFloat(clk_path_->slew(sta)); + float slew = delayAsFloat(clk_path_->slew(sta), min_max, sta); return clk_port->clkTreeDelay(slew, rf, min_max); } } @@ -1276,14 +1303,16 @@ PathEndLatchCheck::targetClkWidth(const StaState *sta) const Arrival enable_arrival = search->clkPathArrival(clk_path_); const ClkInfo *enable_clk_info = clk_path_->clkInfo(sta); if (enable_clk_info->isPulseClk()) - return disable_arrival - enable_arrival; + return delayDiff(disable_arrival, enable_arrival, sta); else { if (delayGreater(enable_arrival, disable_arrival, sta)) { const Clock *disable_clk = enable_clk_info->clock(); if (disable_clk) - disable_arrival += disable_clk->period(); + disable_arrival = delaySum(disable_arrival, + disable_clk->period(), + sta); } - return disable_arrival - enable_arrival; + return delayDiff(disable_arrival, enable_arrival, sta); } } @@ -1416,10 +1445,14 @@ PathEndOutputDelay::targetClkArrivalNoCrpr(const StaState *sta) const else { const ClockEdge *tgt_clk_edge = targetClkEdge(sta); const TimingRole *check_role = checkRole(sta); - return targetClkTime(sta) - + tgtClkDelay(tgt_clk_edge, check_role, sta) - + targetClkUncertainty(sta) - + checkMcpAdjustment(path_, tgt_clk_edge, sta); + Arrival base = delaySum(targetClkTime(sta), + tgtClkDelay(tgt_clk_edge, check_role, sta), + sta); + return delaySum(delaySum(base, + targetClkUncertainty(sta), + sta), + checkMcpAdjustment(path_, tgt_clk_edge, sta), + sta); } } @@ -1451,7 +1484,7 @@ PathEndOutputDelay::tgtClkDelay(const ClockEdge *tgt_clk_edge, Arrival insertion, latency; tgtClkDelay(tgt_clk_edge, check_role, sta, insertion, latency); - return insertion + latency; + return delaySum(insertion, latency, sta); } void @@ -1691,17 +1724,23 @@ PathEndDataCheck::requiredTimeNoCrpr(const StaState *sta) const { Arrival data_clk_arrival = data_clk_path_->arrival(); float data_clk_time = data_clk_path_->clkEdge(sta)->time(); - Arrival data_clk_delay = data_clk_arrival - data_clk_time; - Arrival tgt_clk_arrival = targetClkTime(sta) - + data_clk_delay - + targetClkUncertainty(sta) - + targetClkMcpAdjustment(sta); + Arrival data_clk_delay = delayDiff(data_clk_arrival, + data_clk_time, + sta); + Arrival tgt_clk_arrival = + delaySum(delaySum(targetClkTime(sta), + data_clk_delay, + sta), + delaySum(targetClkUncertainty(sta), + targetClkMcpAdjustment(sta), + sta), + sta); ArcDelay check_margin = margin(sta); if (checkGenericRole(sta) == TimingRole::setup()) - return tgt_clk_arrival - check_margin; + return delayDiff(tgt_clk_arrival, check_margin, sta); else - return tgt_clk_arrival + check_margin; + return delaySum(tgt_clk_arrival, check_margin, sta); } ArcDelay @@ -1917,7 +1956,7 @@ PathEnd::pathDelaySrcClkOffset(const Path *path, const ClockEdge *clk_edge = path->clkEdge(sta); if (clk_edge) { if (ignoreClkLatency(path, path_delay, sta)) - offset = -delayAsFloat(src_clk_arrival); + offset = -delayAsFloat(src_clk_arrival, path->minMax(sta), sta); else // Arrival includes src clock edge time that is not counted in the // path delay. @@ -1960,8 +1999,9 @@ PathEndPathDelay::targetClkArrivalNoCrpr(const StaState *sta) const { const ClockEdge *tgt_clk_edge = targetClkEdge(sta); if (tgt_clk_edge) - return targetClkDelay(sta) - + targetClkUncertainty(sta); + return delaySum(targetClkDelay(sta), + targetClkUncertainty(sta), + sta); else if (clk_path_) return clk_path_->arrival(); else @@ -1979,19 +2019,29 @@ PathEndPathDelay::requiredTime(const StaState *sta) const { float delay = path_delay_->delay(); if (path_delay_->ignoreClkLatency()) { - Required src_offset = path_->isClock(sta) - ? path_->clkEdge(sta)->time() - : src_clk_arrival_; - return src_offset + delay - + ((minMax(sta) == MinMax::max()) ? -margin(sta) : margin(sta)); + Delay with_delay = path_->isClock(sta) + ? Delay(path_->clkEdge(sta)->time() + delay) + : delaySum(src_clk_arrival_, delay, sta); + ArcDelay m = margin(sta); + return (minMax(sta) == MinMax::max()) + ? delayDiff(with_delay, m, sta) + : delaySum(with_delay, m, sta); } else { Arrival tgt_clk_arrival = targetClkArrival(sta); float src_clk_offset = sourceClkOffset(sta); // Path delay includes target clk latency and timing check setup/hold // margin or external departure at target. - return delay - src_clk_offset + tgt_clk_arrival - + ((minMax(sta) == MinMax::max()) ? -margin(sta) : margin(sta)); + Delay base = delaySum(tgt_clk_arrival, + delay, + sta); + Delay with_src = delayDiff(base, + src_clk_offset, + sta); + ArcDelay m = margin(sta); + return (minMax(sta) == MinMax::max()) + ? delayDiff(with_src, m, sta) + : delaySum(with_src, m, sta); } } @@ -2073,22 +2123,22 @@ PathEnd::cmpSlack(const PathEnd *path_end1, { Slack slack1 = path_end1->slack(sta); Slack slack2 = path_end2->slack(sta); - if (delayZero(slack1) - && delayZero(slack2) + if (delayZero(slack1, sta) + && delayZero(slack2, sta) && path_end1->isLatchCheck() && path_end2->isLatchCheck()) { Arrival borrow1 = path_end1->borrow(sta); Arrival borrow2 = path_end2->borrow(sta); // Latch slack is zero if there is borrowing so break ties // based on borrow time. - if (delayEqual(borrow1, borrow2)) + if (delayEqual(borrow1, borrow2, sta)) return 0; else if (delayGreater(borrow1, borrow2, sta)) return -1; else return 1; } - else if (delayEqual(slack1, slack2)) + else if (delayEqual(slack1, slack2, sta)) return 0; else if (delayLess(slack1, slack2, sta)) return -1; @@ -2104,7 +2154,7 @@ PathEnd::cmpArrival(const PathEnd *path_end1, Arrival arrival1 = path_end1->dataArrivalTime(sta); Arrival arrival2 = path_end2->dataArrivalTime(sta); const MinMax *min_max = path_end1->minMax(sta); - if (delayEqual(arrival1, arrival2)) + if (delayEqual(arrival1, arrival2, sta)) return 0; else if (delayLess(arrival1, arrival2, min_max, sta)) return -1; diff --git a/search/PathEnum.cc b/search/PathEnum.cc index ed57ed28..c5e11778 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -511,9 +511,11 @@ PathEnumFaninVisitor::reportDiversion(const Edge *div_edge, Arrival path_delay = path_enum_->cmp_slack_ ? path_end_->slack(this) : path_end_->dataArrivalTime(this); - Arrival div_delay = path_delay - path_enum_->divSlack(before_div_, - after_div, div_edge, - div_arc); + Arrival div_delay = delayDiff(path_delay, + path_enum_->divSlack(before_div_, + after_div, div_edge, + div_arc), + this); Path *div_prev = before_div_->prevPath(); report_->reportLine("path_enum: diversion %s %s %s -> %s", path->to_string(this).c_str(), @@ -580,7 +582,7 @@ PathEnum::divSlack(Path *before_div, Tag *q_tag; latches_->latchOutArrival(after_div, div_arc, div_edge, q_tag, div_delay, div_arrival); - return div_arrival - before_div_arrival; + return delayDiff(div_arrival, before_div_arrival, this); } else { DcalcAPIndex dcalc_ap = before_div->dcalcAnalysisPtIndex(this); @@ -589,8 +591,8 @@ PathEnum::divSlack(Path *before_div, false, before_div->minMax(this), dcalc_ap, before_div->sdc(this)); - Arrival div_arrival = search_->clkPathArrival(after_div) + div_delay; - return div_arrival - before_div_arrival; + Arrival div_arrival = delaySum(search_->clkPathArrival(after_div), div_delay, this); + return delayDiff(div_arrival, before_div_arrival, this); } } else { @@ -719,7 +721,7 @@ PathEnum::updatePathHeadDelays(PathSeq &paths, path->minMax(this), path->dcalcAnalysisPtIndex(this), path->sdc(this)); - arrival = prev_arrival + arc_delay; + arrival = delaySum(prev_arrival, arc_delay, this); path->setArrival(arrival); const Tag *tag = path->tag(this); const ClkInfo *clk_info = tag->clkInfo(); diff --git a/search/PocvMode.cc b/search/PocvMode.cc new file mode 100644 index 00000000..57186138 --- /dev/null +++ b/search/PocvMode.cc @@ -0,0 +1,48 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#include "PocvMode.hh" + +#include "EnumNameMap.hh" + +namespace sta { + +static EnumNameMap pocv_mode_map = + {{PocvMode::scalar, "scalar"}, + {PocvMode::normal, "normal"}, + {PocvMode::skew_normal, "skew_normal"}}; + +const char * +pocvModeName(PocvMode mode) +{ + return pocv_mode_map.find(mode); +} + +PocvMode +findPocvMode(const char *mode_name) +{ + return pocv_mode_map.find(mode_name, PocvMode::scalar); +} + +} // namespace diff --git a/search/Property.cc b/search/Property.cc index 3a2a973b..dc37d4b3 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -1133,7 +1133,7 @@ Properties::edgeDelay(Edge *edge, if (to_rf == rf) { for (const Scene *scene : sta_->scenes()) { DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); - ArcDelay arc_delay = sta_->arcDelay(edge, arc, ap_index); + const ArcDelay &arc_delay = sta_->arcDelay(edge, arc, ap_index); if (!delay_exists || delayGreater(arc_delay, delay, min_max, sta_)) { delay = arc_delay; diff --git a/search/ReportPath.cc b/search/ReportPath.cc index b7d3c9d2..664af765 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -134,20 +134,18 @@ ReportField::setEnabled(bool enabled) //////////////////////////////////////////////////////////////// -const float ReportPath::field_blank_ = -1.0; - ReportPath::ReportPath(StaState *sta) : StaState(sta), format_(ReportPathFormat::full), no_split_(false), - report_sigmas_(false), start_end_pt_width_(80), + field_width_extra_(5), plus_zero_(nullptr), minus_zero_(nullptr) { - setDigits(2); makeFields(); - setReportFields(false, false, false, false, false, false, false); + setDigits(2); + setReportFields(false, false, false, false, false, false, false, false); } ReportPath::~ReportPath() @@ -158,6 +156,7 @@ ReportPath::~ReportPath() delete field_capacitance_; delete field_slew_; delete field_fanout_; + delete field_variation_; delete field_src_attr_; delete field_edge_; delete field_case_; @@ -169,6 +168,7 @@ ReportPath::~ReportPath() void ReportPath::makeFields() { + // The order corresponds to the default field order. field_fanout_ = makeField("fanout", "Fanout", 6, false, nullptr, true); field_capacitance_ = makeField("capacitance", "Cap", 6, false, units_->capacitanceUnit(), true); @@ -176,6 +176,8 @@ ReportPath::makeFields() true); field_incr_ = makeField("incr", "Delay", 6, false, units_->timeUnit(), true); + field_variation_ = makeField("variation", "Variation", 6, false, + units_->timeUnit(), false); field_total_ = makeField("total", "Time", 6, false, units_->timeUnit(), true); field_edge_ = makeField("edge", "", 1, false, nullptr, true); @@ -243,6 +245,7 @@ ReportPath::setReportFields(bool report_input_pin, bool report_cap, bool report_slew, bool report_fanout, + bool report_variation, bool report_src_attr) { report_input_pin_ = report_input_pin; @@ -252,6 +255,7 @@ ReportPath::setReportFields(bool report_input_pin, field_capacitance_->setEnabled(report_cap); field_slew_->setEnabled(report_slew); field_fanout_->setEnabled(report_fanout); + field_variation_->setEnabled(report_variation); field_src_attr_->setEnabled(report_src_attr); // for debug field_case_->setEnabled(false); @@ -278,12 +282,14 @@ ReportPath::setDigits(int digits) stringDelete(minus_zero_); minus_zero_ = stringPrint("-%.*f", digits_, 0.0); plus_zero_ = stringPrint("%.*f", digits_, 0.0); -} -void -ReportPath::setReportSigmas(bool report) -{ - report_sigmas_ = report; + // Numeric field width expands with digits. + int field_width = digits + field_width_extra_; + field_capacitance_->setWidth(field_width); + field_slew_->setWidth(field_width); + field_variation_->setWidth(field_width); + field_incr_->setWidth(field_width); + field_total_->setWidth(field_width); } //////////////////////////////////////////////////////////////// @@ -556,7 +562,7 @@ ReportPath::reportFull(const PathEndLatchCheck *end) const end->latchRequired(this, req_time, borrow, adjusted_data_arrival, time_given_to_startpoint); // Adjust required to requiredTimeOffset. - req_time += end->sourceClkOffset(this); + req_time = delaySum(req_time, end->sourceClkOffset(this), this); if (path_delay) { float delay = path_delay->delay(); reportLine("max_delay", delay, delay, early_late); @@ -630,7 +636,7 @@ ReportPath::reportBorrowing(const PathEndLatchCheck *end, if (tgt_clk_path->clkInfo(search_)->isPropagated()) { auto width_msg = stdstrPrint("%s nominal pulse width", tgt_clk_name.c_str()); reportLineTotal(width_msg.c_str(), nom_pulse_width, early_late); - if (!delayZero(latency_diff)) + if (!delayZero(latency_diff, this)) reportLineTotalMinus("clock latency difference", latency_diff, early_late); } else { @@ -640,18 +646,18 @@ ReportPath::reportBorrowing(const PathEndLatchCheck *end, ArcDelay margin = end->margin(this); reportLineTotalMinus("library setup time", margin, early_late); reportDashLineTotal(); - if (!delayZero(crpr_diff)) + if (!delayZero(crpr_diff, this)) reportLineTotalMinus("CRPR difference", crpr_diff, early_late); reportLineTotal("max time borrow", max_borrow, early_late); } if (delayGreater(borrow, delay_zero, this) && (!fuzzyZero(open_uncertainty) - || !delayZero(open_crpr))) { + || !delayZero(open_crpr, this))) { reportDashLineTotal(); reportLineTotal("actual time borrow", borrow, early_late); if (!fuzzyZero(open_uncertainty)) reportLineTotal("open edge uncertainty", open_uncertainty, early_late); - if (!delayZero(open_crpr)) + if (!delayZero(open_crpr, this)) reportLineTotal("open edge CRPR", open_crpr, early_late); reportDashLineTotal(); reportLineTotal("time given to startpoint", time_given_to_startpoint, early_late); @@ -720,7 +726,7 @@ ReportPath::reportFull(const PathEndPathDelay *end) const ArcDelay margin = end->margin(this); const MinMax *min_max = path_delay->minMax()->asMinMax(); if (min_max == MinMax::max()) - margin = -margin; + margin = delayDiff(delay_zero, margin, this); std::string delay_msg = min_max->to_string() + "_delay"; float delay = path_delay->delay(); @@ -734,8 +740,8 @@ ReportPath::reportFull(const PathEndPathDelay *end) const reportTgtClk(end, delay, 0.0, true); else { Arrival tgt_clk_delay = end->targetClkDelay(this); - Arrival tgt_clk_arrival = delay + tgt_clk_delay; - if (!delayZero(tgt_clk_delay)) + Arrival tgt_clk_arrival = delaySum(tgt_clk_delay, delay, this); + if (!delayZero(tgt_clk_delay, this)) reportLine(clkNetworkDelayIdealProp(isPropagated(tgt_clk_path)), tgt_clk_delay, tgt_clk_arrival, early_late); reportClkUncertainty(end, tgt_clk_arrival); @@ -924,10 +930,11 @@ ReportPath::reportFull(const PathEndDataCheck *end) const PathExpanded clk_expanded(data_clk_path, this); float src_offset = end->sourceClkOffset(this); Delay clk_delay = end->targetClkDelay(this); + const MinMax *min_max = data_clk_path->minMax(this); Arrival clk_arrival = end->targetClkArrival(this); const ClockEdge *tgt_clk_edge = end->targetClkEdge(this); - float prev = delayAsFloat(clk_arrival) + src_offset; - float offset = prev - delayAsFloat(clk_delay) - tgt_clk_edge->time(); + float prev = delayAsFloat(clk_arrival, min_max, this) + src_offset; + float offset = prev - delayAsFloat(clk_delay, min_max, this) - tgt_clk_edge->time(); // Delay to startpoint is already included. reportPath6(data_clk_path, clk_expanded, clk_expanded.startIndex(), true, false, prev, offset); @@ -1397,13 +1404,15 @@ ReportPath::reportVerbose(const MinPulseWidthCheck &check) const float close_clk_time = close_clk_edge->time() + close_offset; auto close_clk_msg = stdstrPrint("clock %s (%s edge)", close_clk_name, close_rise_fall); reportLine(close_clk_msg.c_str(), close_clk_time, close_clk_time, close_el); - Arrival close_arrival = check.closeArrival(this) + close_offset; + + Arrival close_arrival = delaySum(check.closeArrival(this), close_offset, this); reportLine(clk_ideal_prop, check.closeDelay(this), close_arrival, close_el); + reportLine(pin_name, delay_zero, close_arrival, close_el); if (variables_->crprEnabled()) { Crpr pessimism = check.checkCrpr(this); - close_arrival += pessimism; + close_arrival = delaySum(close_arrival, pessimism, this); reportLine("clock reconvergence pessimism", pessimism, close_arrival, close_el); } reportLine("close edge arrival time", close_arrival, close_el); @@ -1578,7 +1587,7 @@ ReportPath::reportShort(const MaxSkewCheck &check) const reportDescription(what.c_str(), line); const EarlyLate *early_late = EarlyLate::early(); reportSpaceFieldDelay(check.maxSkew(this), early_late, line); - reportSpaceFieldDelay(check.skew(), early_late, line); + reportSpaceFieldDelay(check.skew(this), early_late, line); reportSpaceSlack(check.slack(this), line); report_->reportLineString(line); } @@ -1607,7 +1616,7 @@ ReportPath::reportVerbose(const MaxSkewCheck &check) const reportDashLine(); reportLine("allowable skew", check.maxSkew(this), EarlyLate::early()); - reportLine("actual skew", check.skew(), EarlyLate::late()); + reportLine("actual skew", check.skew(this), EarlyLate::late()); reportDashLine(); reportSlack(check.slack(this)); } @@ -1625,7 +1634,9 @@ ReportPath::reportSkewClkPath(const char *arrival_msg, std::string clk_name = clkName(clk, clk_end_rf != clk_rf); float clk_time = clk_edge->time(); const Arrival &clk_arrival = search_->clkPathArrival(clk_path); - Arrival clk_delay = clk_arrival - clk_time; + Arrival clk_delay = delayDiff(clk_arrival, + clk_time, + this); const MinMax *min_max = clk_path->minMax(this); Vertex *clk_vertex = clk_path->vertex(this); reportClkLine(clk, clk_name.c_str(), clk_end_rf, clk_time, min_max); @@ -2066,15 +2077,19 @@ ReportPath::reportSrcClkAndPath(const Path *path, const Path *clk_path = expanded.clkPath(); const RiseFall *clk_end_rf; if (clk_path) { - clk_end_time = search_->clkPathArrival(clk_path) + time_offset; - clk_delay = clk_end_time - clk_time; + clk_end_time = delaySum(search_->clkPathArrival(clk_path), + time_offset, + this); + clk_delay = delayDiff(clk_end_time, + clk_time, + this); clk_end_rf = clk_path->transition(this); } else { // Path from input port or clk used as data. clk_end_rf = clk_rf; - clk_delay = clk_insertion + clk_latency; - clk_end_time = clk_time + clk_delay; + clk_delay = delaySum(clk_insertion, clk_latency, this); + clk_end_time = delaySum(clk_time, clk_delay, this); const Path *first_path = expanded.startPath(); const InputDelay *input_delay = pathInputDelay(first_path); @@ -2086,8 +2101,12 @@ ReportPath::reportSrcClkAndPath(const Path *path, pathInputDelayRefPath(first_path, input_delay, ref_path); if (!ref_path.isNull()) { const Arrival &ref_end_time = ref_path.arrival(); - clk_delay = ref_end_time - clk_time; - clk_end_time = ref_end_time + time_offset; + clk_delay = delayDiff(ref_end_time, + clk_time, + this); + clk_end_time = delaySum(ref_end_time, + time_offset, + this); input_has_ref_path = true; } } @@ -2127,8 +2146,10 @@ ReportPath::reportSrcClkAndPath(const Path *path, reportPath1(path, expanded, true, time_offset); else { Arrival clk_arrival = clk_end_time; - Arrival end_arrival = path->arrival() + time_offset; - Delay clk_delay = end_arrival - clk_arrival; + Arrival end_arrival = delaySum(path->arrival(), + time_offset, + this); + Delay clk_delay = delayDiff(end_arrival, clk_arrival, this); reportLine("clock network delay", clk_delay, end_arrival, early_late); Vertex *end_vertex = path->vertex(this); @@ -2187,7 +2208,7 @@ ReportPath::reportTgtClk(const PathEnd *end, bool is_prop) const { const ClockEdge *clk_edge = end->targetClkEdge(this); - Clock *clk = clk_edge->clock(); + const Clock *clk = clk_edge->clock(); const RiseFall *clk_rf = clk_edge->transition(); const RiseFall *clk_end_rf = end->targetClkEndTrans(this); std::string clk_name = clkName(clk, clk_end_rf != clk_rf); @@ -2196,7 +2217,7 @@ ReportPath::reportTgtClk(const PathEnd *end, + end->targetClkMcpAdjustment(this) + src_offset; Arrival clk_delay = end->targetClkDelay(this); - Arrival clk_arrival = clk_time + clk_delay; + Arrival clk_arrival = delaySum(clk_delay, clk_time, this); const MinMax *min_max = end->path()->tgtClkMinMax(this); const Path *clk_path = end->targetClkPath(); reportClkLine(clk, clk_name.c_str(), clk_end_rf, prev_time, clk_time, min_max); @@ -2225,7 +2246,7 @@ ReportPath::reportTgtClk(const PathEnd *end, } else { // Output departure. - Arrival clk_arrival = clk_time + clk_delay; + Arrival clk_arrival = delaySum(clk_time, clk_delay, this); reportLine(clkNetworkDelayIdealProp(clk->isPropagated()), clk_delay, clk_arrival, min_max); } @@ -2241,9 +2262,11 @@ ReportPath::reportTgtClk(const PathEnd *end, if (clk_path) { Vertex *clk_vertex = clk_path->vertex(this); reportLine(descriptionField(clk_vertex).c_str(), - prev_time - + end->targetClkArrival(this) - + end->sourceClkOffset(this), + delaySum(delaySum(prev_time, + end->targetClkArrival(this), + this), + end->sourceClkOffset(this), + this), min_max, clk_end_rf); } } @@ -2264,7 +2287,7 @@ ReportPath::tgtClkInsertionOffet(const Path *clk_path, min_max, min_max, mode); Arrival tgt_insertion = search_->clockInsertion(clk, src_pin, clk_rf, min_max, early_late, mode); - return delayAsFloat(tgt_insertion - path_insertion); + return delayAsFloat(delayDiff(tgt_insertion, path_insertion, this)); } bool @@ -2327,11 +2350,18 @@ ReportPath::reportClkLine(const Clock *clk, const char *rise_fall = asRiseFall(clk_rf); auto clk_msg = stdstrPrint("clock %s (%s edge)", clk_name, rise_fall); if (clk->isPropagated()) - reportLine(clk_msg.c_str(), clk_time - prev_time, clk_time, min_max); + reportLine(clk_msg.c_str(), + delayDiff(clk_time, prev_time, this), + clk_time, + min_max); else { // Report ideal clock slew. float clk_slew = clk->slew(clk_rf, min_max); - reportLine(clk_msg.c_str(), clk_slew, clk_time - prev_time, clk_time, min_max); + reportLine(clk_msg.c_str(), + clk_slew, + delayDiff(clk_time, prev_time, this), + clk_time, + min_max); } } @@ -2433,13 +2463,16 @@ ReportPath::reportClkSrcLatency(Arrival insertion, float clk_time, const EarlyLate *early_late) const { - reportLine("clock source latency", insertion, clk_time + insertion, early_late); + Arrival clk_arrival = delaySum(clk_time, + insertion, + this); + reportLine("clock source latency", insertion, clk_arrival, early_late); } void ReportPath::reportPathLine(const Path *path, - Arrival incr, - Arrival time, + const Delay &incr, + const Arrival &time, const char *line_case) const { Vertex *vertex = path->vertex(this); @@ -2461,7 +2494,7 @@ ReportPath::reportPathLine(const Path *path, if (is_driver && field_capacitance_->enabled()) cap = graph_delay_calc_->loadCap(pin, rf, scene, min_max); reportLine(what.c_str(), cap, slew, field_blank_, - incr, time, false, early_late, rf, src_attr, + incr, field_blank_, time, false, early_late, rf, src_attr, line_case); } @@ -2474,13 +2507,16 @@ ReportPath::reportRequired(const PathEnd *end, float macro_clk_tree_delay = end->macroClkTreeDelay(this); ArcDelay margin = end->margin(this); if (end->minMax(this) == MinMax::min()) { - margin = -margin; + margin = delayDiff(delay_zero, margin, this); macro_clk_tree_delay = -macro_clk_tree_delay; } if (macro_clk_tree_delay != 0.0) reportLine("macro clock tree delay", -macro_clk_tree_delay, - req_time + margin, early_late); - reportLine(margin_msg.c_str(), -margin, req_time, early_late); + delaySum(req_time, margin, this), early_late); + reportLine(margin_msg.c_str(), + delayDiff(delay_zero, margin, this), + req_time, + early_late); reportLine("data required time", req_time, early_late); reportDashLine(); } @@ -2531,7 +2567,7 @@ ReportPath::reportCommonClkPessimism(const PathEnd *end, { if (variables_->crprEnabled()) { Crpr pessimism = end->checkCrpr(this); - clk_arrival += pessimism; + clk_arrival = delaySum(clk_arrival, pessimism, this); reportLine("clock reconvergence pessimism", pessimism, clk_arrival, end->clkEarlyLate(this)); } @@ -2543,11 +2579,15 @@ ReportPath::reportClkUncertainty(const PathEnd *end, { const EarlyLate *early_late = end->clkEarlyLate(this); float uncertainty = end->targetNonInterClkUncertainty(this); - clk_arrival += uncertainty; + clk_arrival = delaySum(clk_arrival, + uncertainty, + this); if (uncertainty != 0.0) reportLine("clock uncertainty", uncertainty, clk_arrival, early_late); float inter_uncertainty = end->interClkUncertainty(this); - clk_arrival += inter_uncertainty; + clk_arrival = delaySum(clk_arrival, + inter_uncertainty, + this); if (inter_uncertainty != 0.0) reportLine("inter-clock uncertainty", inter_uncertainty, clk_arrival, early_late); @@ -2659,7 +2699,9 @@ ReportPath::reportPath4(const Path *path, reportPath5(latch_enable_path, enable_expanded, skip_first_path, propagated_clk, report_clk_path, time_offset); } - Arrival time = latch_enable_time + latch_time_given; + Arrival time = delaySum(latch_enable_time, + latch_time_given, + this); Arrival incr = latch_time_given; if (delayGreaterEqual(incr, 0.0, this)) reportLine("time given to startpoint", incr, time, early_late); @@ -2668,7 +2710,10 @@ ReportPath::reportPath4(const Path *path, // Override latch D arrival with enable + given. reportPathLine(expanded.path(0), delay_zero, time, "latch_D"); reportPath6(path, expanded, 1, propagated_clk, report_clk_path, - latch_enable_time + latch_time_given, time_offset); + delaySum(latch_enable_time, + latch_time_given, + this), + time_offset); } } else @@ -2689,7 +2734,9 @@ ReportPath::reportPath5(const Path *path, if (skip_first_path) { path_first_index = 1; const Path *start = expanded.path(0); - prev_time = start->arrival() + time_offset; + prev_time = delaySum(start->arrival(), + time_offset, + this); } reportPath6(path, expanded, path_first_index, propagated_clk, report_clk_path, prev_time, time_offset); @@ -2717,7 +2764,7 @@ ReportPath::reportPath6(const Path *path, const TimingArc *prev_arc = path1->prevArc(this); Vertex *vertex = path1->vertex(this); Pin *pin = vertex->pin(); - Arrival time = path1->arrival() + time_offset; + Arrival time = delaySum(path1->arrival(), time_offset, this); Delay incr = 0.0; const char *line_case = nullptr; bool is_clk_start = path1->vertex(this) == clk_start; @@ -2746,7 +2793,9 @@ ReportPath::reportPath6(const Path *path, // The delay calculator annotates wire delays on the edges // from the input to the loads. Report the wire delay on the // input pin instead. - Arrival next_time = next_path->arrival() + time_offset; + Arrival next_time = delaySum(next_path->arrival(), + time_offset, + this); incr = delayIncr(next_time, time, min_max); time = next_time; line_case = "input_drive"; @@ -2755,7 +2804,7 @@ ReportPath::reportPath6(const Path *path, if (!propagated_clk) // Clock latency at path endpoint in case latency was set // on a clock pin other than the clock source. - time = search_->clkPathArrival(path1) + time_offset; + time = delaySum(search_->clkPathArrival(path1), time_offset, this); incr = 0.0; line_case = "clk_first"; } @@ -2772,7 +2821,9 @@ ReportPath::reportPath6(const Path *path, if (!propagated_clk) { // Ideal clock. const ClockEdge *src_clk_edge = path->clkEdge(this); - time = search_->clkPathArrival(path1) + time_offset; + time = delaySum(search_->clkPathArrival(path1), + time_offset, + this); if (src_clk_edge) { Clock *src_clk = src_clk_edge->clock(); const RiseFall *src_clk_rf = src_clk_edge->transition(); @@ -2803,6 +2854,8 @@ ReportPath::reportPath6(const Path *path, } if (vertex->isDriver(network_)) { + // Report delay arc pocv variation between input and driver. + reportVariation(path1); float cap = field_blank_; float fanout = field_blank_; if (field_capacitance_->enabled()) @@ -2811,13 +2864,13 @@ ReportPath::reportPath6(const Path *path, fanout = drvrFanout(vertex, scene, min_max); const std::string what = descriptionField(vertex); reportLine(what.c_str(), cap, slew, fanout, - incr, time, false, min_max, rf, src_attr, + incr, field_blank_, time, false, min_max, rf, src_attr, line_case); if (report_net_) { const std::string what2 = descriptionNet(pin); reportLine(what2.c_str(), field_blank_, field_blank_, field_blank_, - field_blank_, field_blank_, false, min_max, + field_blank_, field_blank_, field_blank_, false, min_max, nullptr, src_attr, ""); } prev_time = time; @@ -2830,7 +2883,7 @@ ReportPath::reportPath6(const Path *path, || is_clk_start) { const std::string what = descriptionField(vertex); reportLine(what.c_str(), field_blank_, slew, field_blank_, - incr, time, false, min_max, rf, src_attr, + incr, field_blank_, time, false, min_max, rf, src_attr, line_case); prev_time = time; } @@ -2841,6 +2894,59 @@ ReportPath::reportPath6(const Path *path, } } +void +ReportPath::reportVariation(const Path *path) const +{ + if (field_variation_->enabled()) { + const Edge *prev_edge = path->prevEdge(this); + if (prev_edge) { + const TimingArc *prev_arc = path->prevArc(this); + const MinMax *min_max = path->minMax(this); + DcalcAPIndex slew_index = path->dcalcAnalysisPtIndex(this); + const ArcDelay &arc_delay=graph_->arcDelay(prev_edge, prev_arc,slew_index); + switch (variables_->pocvMode()) { + case PocvMode::normal: { + float std_dev = arc_delay.stdDev(); + reportLine("sigma", field_blank_, field_blank_, field_blank_, + field_blank_, std_dev, field_blank_, true, min_max, nullptr, + "", nullptr); + break; + } + case PocvMode::skew_normal: { + float mean = arc_delay.mean(); + reportLine("mean", field_blank_, field_blank_, field_blank_, + field_blank_, mean, field_blank_, true, min_max, nullptr, + "", nullptr); + float mean_shift = arc_delay.meanShift(); + reportLine("mean_shift", field_blank_, field_blank_, field_blank_, + field_blank_, mean_shift, field_blank_, true, min_max, nullptr, + "", nullptr); + float std_dev = arc_delay.stdDev(); + reportLine("std_dev", field_blank_, field_blank_, field_blank_, + field_blank_, std_dev, field_blank_, true, min_max, nullptr, + "", nullptr); + // skewness is dimensionless, so scale it to the field's time units. + float skewness = arc_delay.skewness() * units_->timeUnit()->scale(); + reportLine("skewness", field_blank_, field_blank_, field_blank_, + field_blank_, skewness, field_blank_, true, min_max, nullptr, + "", nullptr); + break; + } + default: + break; + } + } + } +} + +Delay +ReportPath::delayIncr(const Delay &time, + const Delay &prev, + const MinMax *min_max) const +{ + return delayAsFloat(time, min_max, this) - delayAsFloat(prev, min_max, this); +} + void ReportPath::reportHierPinsThru(const Path *path) const { @@ -2850,24 +2956,13 @@ ReportPath::reportHierPinsThru(const Path *path) const for (const Pin *hpin : hierPinsThruEdge(prev_edge, network_, graph_)) { const std::string what = descriptionField(hpin); reportLine(what.c_str(), field_blank_, field_blank_, field_blank_, - field_blank_, field_blank_, false, path->minMax(this), + field_blank_, field_blank_, field_blank_, false, path->minMax(this), nullptr, "", ""); } } } } -Delay -ReportPath::delayIncr(Delay time, - Delay prev, - const MinMax *min_max) const -{ - if (report_sigmas_) - return delayRemove(time, prev); - else - return delayAsFloat(time, min_max, this) - delayAsFloat(prev, min_max, this); -} - bool ReportPath::nextArcAnnotated(const Path *next_path, size_t next_index, @@ -2974,7 +3069,9 @@ ReportPath::reportInputExternalDelay(const Path *first_path, const Pin *first_pin = first_path->pin(graph_); if (!pathFromClkPin(first_path, first_pin)) { const RiseFall *rf = first_path->transition(this); - Arrival time = first_path->arrival() + time_offset; + Arrival time = delaySum(first_path->arrival(), + time_offset, + this); const EarlyLate *early_late = first_path->minMax(this); InputDelay *input_delay = pathInputDelay(first_path); if (input_delay) { @@ -3054,7 +3151,7 @@ ReportPath::reportLine(const char *what, Delay total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, total, false, early_late, nullptr, "", nullptr); } @@ -3066,8 +3163,8 @@ ReportPath::reportLineNegative(const char *what, const EarlyLate *early_late) const { reportLine(what, field_blank_, field_blank_, field_blank_, - field_blank_, total, true, early_late, nullptr, - "", nullptr); + field_blank_, field_blank_, total, true /* tota_with_minus */, + early_late, nullptr, "", nullptr); } // Report total, and transition suffix. @@ -3078,55 +3175,56 @@ ReportPath::reportLine(const char *what, const RiseFall *rf) const { reportLine(what, field_blank_, field_blank_, field_blank_, - field_blank_, total, false, early_late, rf, "", + field_blank_, field_blank_, total, false, early_late, rf, "", nullptr); } // Report increment, and total. void ReportPath::reportLine(const char *what, - Delay incr, - Delay total, + const Delay &incr, + const Delay &total, const EarlyLate *early_late) const { reportLine(what, field_blank_, field_blank_, field_blank_, - incr, total, false, early_late, nullptr, "", + incr, field_blank_, total, false, early_late, nullptr, "", nullptr); } // Report increment, total, and transition suffix. void ReportPath::reportLine(const char *what, - Delay incr, - Delay total, + const Delay &incr, + const Delay &total, const EarlyLate *early_late, const RiseFall *rf) const { reportLine(what, field_blank_, field_blank_, field_blank_, - incr, total, false, early_late, rf, "", + incr, field_blank_, total, false, early_late, rf, "", nullptr); } // Report slew, increment, and total. void ReportPath::reportLine(const char *what, - Slew slew, - Delay incr, - Delay total, + const Slew &slew, + const Delay &incr, + const Delay &total, const EarlyLate *early_late) const { reportLine(what, field_blank_, slew, field_blank_, - incr, total, false, early_late, nullptr, + incr, field_blank_, total, false, early_late, nullptr, "", nullptr); } void ReportPath::reportLine(const char *what, float cap, - Slew slew, + const Slew &slew, float fanout, - Delay incr, - Delay total, + const Delay &incr, + float variation, + const Delay &total, bool total_with_minus, const EarlyLate *early_late, const RiseFall *rf, @@ -3159,6 +3257,8 @@ ReportPath::reportLine(const char *what, reportFieldDelay(slew, early_late, field, line); else if (field == field_incr_) reportFieldDelay(incr, early_late, field, line); + else if (field == field_variation_) + reportFieldDelay(variation, early_late, field, line); else if (field == field_total_) { if (total_with_minus) reportFieldDelayMinus(total, early_late, field, line); @@ -3171,6 +3271,8 @@ ReportPath::reportLine(const char *what, else reportFieldBlank(field, line); } + else if (field == field_variation_) + reportFieldBlank(field, line); else if (field == field_src_attr_) { if (src_attr != "") reportField(src_attr.c_str(), field, line); @@ -3195,7 +3297,7 @@ ReportPath::reportLine(const char *what, // Only the total field. void ReportPath::reportLineTotal(const char *what, - Delay incr, + const Delay &incr, const EarlyLate *early_late) const { reportLineTotal1(what, incr, false, early_late); @@ -3204,7 +3306,7 @@ ReportPath::reportLineTotal(const char *what, // Only the total field and always with leading minus sign. void ReportPath::reportLineTotalMinus(const char *what, - Delay decr, + const Delay &decr, const EarlyLate *early_late) const { reportLineTotal1(what, decr, true, early_late); @@ -3212,7 +3314,7 @@ ReportPath::reportLineTotalMinus(const char *what, void ReportPath::reportLineTotal1(const char *what, - Delay incr, + const Delay &incr, bool incr_with_minus, const EarlyLate *early_late) const { @@ -3287,7 +3389,7 @@ ReportPath::reportSpaceFieldTime(float value, } void -ReportPath::reportSpaceFieldDelay(Delay value, +ReportPath::reportSpaceFieldDelay(const Delay &value, const EarlyLate *early_late, std::string &line) const { @@ -3296,11 +3398,11 @@ ReportPath::reportSpaceFieldDelay(Delay value, } void -ReportPath::reportTotalDelay(Delay value, +ReportPath::reportTotalDelay(const Delay &value, const EarlyLate *early_late, std::string &line) const { - const char *str = delayAsString(value, early_late, this, digits_); + const char *str = delayAsString(value, early_late, digits_, this); if (stringEq(str, minus_zero_)) // Filter "-0.00" fields. str = plus_zero_; @@ -3309,7 +3411,7 @@ ReportPath::reportTotalDelay(Delay value, // Total time always with leading minus sign. void -ReportPath::reportFieldDelayMinus(Delay value, +ReportPath::reportFieldDelayMinus(const Delay &value, const EarlyLate *early_late, const ReportField *field, std::string &line) const @@ -3317,10 +3419,9 @@ ReportPath::reportFieldDelayMinus(Delay value, if (delayAsFloat(value) == field_blank_) reportFieldBlank(field, line); else { - const char *str = report_sigmas_ - ? delayAsString(-value, this, digits_) - // Opposite min/max for negative value. - : delayAsString(-value, early_late->opposite(), this, digits_); + // Opposite min/max for negative value. + const char *str = delayAsString(delayDiff(delay_zero, value, this), + early_late->opposite(), digits_, this); if (stringEq(str, plus_zero_)) // Force leading minus sign. str = minus_zero_; @@ -3329,17 +3430,15 @@ ReportPath::reportFieldDelayMinus(Delay value, } void -ReportPath::reportFieldDelay(Delay value, +ReportPath::reportFieldDelay(const Delay &value, const EarlyLate *early_late, const ReportField *field, std::string &line) const { - if (delayAsFloat(value) == field_blank_) + if (value.mean() == field_blank_) reportFieldBlank(field, line); else { - const char *str = report_sigmas_ - ? delayAsString(value, this, digits_) - : delayAsString(value, early_late, this, digits_); + const char *str = delayAsString(value, early_late, digits_, this); if (stringEq(str, minus_zero_)) // Filter "-0.00" fields. str = plus_zero_; diff --git a/search/ReportPath.hh b/search/ReportPath.hh index 642d4314..cad81c74 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -56,12 +56,11 @@ public: bool report_cap, bool report_slew, bool report_fanout, + bool report_variation, bool report_src_attr); int digits() const { return digits_; } void setDigits(int digits); void setNoSplit(bool no_split); - bool reportSigmas() const { return report_sigmas_; } - void setReportSigmas(bool report); ReportField *findField(const char *name) const; // Header above reportPathEnd results. @@ -267,8 +266,8 @@ protected: float clk_time, const EarlyLate *early_late) const; void reportPathLine(const Path *path, - Delay incr, - Arrival time, + const Delay &incr, + const Arrival &time, const char *line_case) const; void reportCommonClkPessimism(const PathEnd *end, Arrival &clk_arrival) const ; @@ -331,6 +330,7 @@ protected: bool report_clk_path, Arrival prev_time, float time_offset) const; + void reportVariation(const Path *path) const; void reportHierPinsThru(const Path *path) const; void reportInputExternalDelay(const Path *path, float time_offset) const; @@ -345,38 +345,39 @@ protected: const EarlyLate *early_late, const RiseFall *rf) const; void reportLine(const char *what, - Delay incr, - Delay total, + const Delay &incr, + const Delay &total, const EarlyLate *early_late) const; void reportLine(const char *what, - Delay incr, - Delay total, + const Delay &incr, + const Delay &total, const EarlyLate *early_late, const RiseFall *rf) const; void reportLine(const char *what, - Slew slew, - Delay incr, - Delay total, + const Slew &slew, + const Delay &incr, + const Delay &total, const EarlyLate *early_late) const; void reportLine(const char *what, float cap, - Slew slew, + const Slew &slew, float fanout, - Delay incr, - Delay total, + const Delay &incr, + float variation, + const Delay &total, bool total_with_minus, const EarlyLate *early_late, const RiseFall *rf, std::string src_attr, const char *line_case) const; void reportLineTotal(const char *what, - Delay incr, + const Delay &incr, const EarlyLate *early_late) const; void reportLineTotalMinus(const char *what, - Delay decr, + const Delay &decr, const EarlyLate *early_late) const; void reportLineTotal1(const char *what, - Delay incr, + const Delay &incr, bool incr_with_minus, const EarlyLate *early_late) const; void reportDashLineTotal() const; @@ -391,17 +392,17 @@ protected: std::string &result) const; void reportSpaceFieldTime(float value, std::string &result) const; - void reportSpaceFieldDelay(Delay value, + void reportSpaceFieldDelay(const Delay &value, const EarlyLate *early_late, std::string &result) const; - void reportFieldDelayMinus(Delay value, + void reportFieldDelayMinus(const Delay &value, const EarlyLate *early_late, const ReportField *field, std::string &result) const; - void reportTotalDelay(Delay value, + void reportTotalDelay(const Delay &value, const EarlyLate *early_late, std::string &result) const; - void reportFieldDelay(Delay value, + void reportFieldDelay(const Delay &value, const EarlyLate *early_late, const ReportField *field, std::string &result) const; @@ -465,8 +466,8 @@ protected: Path &ref_path) const; const char *asRisingFalling(const RiseFall *rf) const; const char *asRiseFall(const RiseFall *rf) const; - Delay delayIncr(Delay time, - Delay prev, + Delay delayIncr(const Delay &time, + const Delay &prev, const MinMax *min_max) const; // Path options. @@ -477,7 +478,6 @@ protected: bool report_net_; bool no_split_; int digits_; - bool report_sigmas_; int start_end_pt_width_; @@ -487,15 +487,15 @@ protected: ReportField *field_capacitance_; ReportField *field_slew_; ReportField *field_fanout_; + ReportField *field_variation_; ReportField *field_src_attr_; ReportField *field_edge_; ReportField *field_case_; + static constexpr float field_blank_ = -1; + int field_width_extra_; const char *plus_zero_; const char *minus_zero_; - - static const float field_blank_; - static const float field_skip_; }; class ReportField diff --git a/search/Search.cc b/search/Search.cc index 92fe7f7d..eeafaace 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -1334,7 +1334,7 @@ Search::arrivalsChanged(Vertex *vertex, Path *path2 = tag_bldr->tagMatchPath(tag1); if (path2 == nullptr || path1->tag(this) != path2->tag(this) - || !delayEqual(path1->arrival(), path2->arrival()) + || !delayEqual(path1->arrival(), path2->arrival(), this) || path1->prevEdge(this) != path2->prevEdge(this) || path1->prevArc(this) != path2->prevArc(this) || path1->prevPath() != path2->prevPath()) @@ -1420,8 +1420,8 @@ ArrivalVisitor::pruneCrprArrivals() const ClkInfo *clk_info_no_crpr = path_no_crpr->clkInfo(this); Arrival max_crpr = crpr->maxCrpr(clk_info_no_crpr); Arrival max_arrival_max_crpr = (min_max == MinMax::max()) - ? max_arrival - max_crpr - : max_arrival + max_crpr; + ? delayDiff(max_arrival, max_crpr, this) + : delaySum(max_arrival, max_crpr, this); debugPrint(debug_, "search", 4, " cmp %s %s - %s = %s", tag->to_string(this).c_str(), delayAsString(max_arrival, this), @@ -1622,7 +1622,7 @@ Search::seedClkArrival(const Pin *pin, sdc->exceptionFromClkStates(pin,rf,clk,rf,min_max,states); Tag *tag = findTag(scene, rf, min_max, clk_info, true, nullptr, false, states, true, nullptr); - Arrival arrival(clk_edge->time() + insertion); + Arrival arrival = delaySum(insertion, clk_edge->time(), this); tag_bldr->setArrival(tag, arrival); } @@ -1639,7 +1639,7 @@ Search::seedClkDataArrival(const Pin *pin, Tag *tag = clkDataTag(pin, clk, rf, clk_edge, insertion, min_max, scene); if (tag) { // Data arrivals include insertion delay. - Arrival arrival(clk_edge->time() + insertion); + Arrival arrival = delaySum(insertion, clk_edge->time(), this); tag_bldr->setArrival(tag, arrival); } } @@ -1878,8 +1878,8 @@ Search::inputDelayRefPinArrival(Path *ref_path, Clock *clk = clk_edge->clock(); if (clk->isPropagated()) { const ClkInfo *clk_info = ref_path->clkInfo(this); - ref_arrival = delayAsFloat(ref_path->arrival()); - ref_insertion = delayAsFloat(clk_info->insertion()); + ref_arrival = delayAsFloat(ref_path->arrival(), min_max, this); + ref_insertion = delayAsFloat(clk_info->insertion(), min_max, this); ref_latency = clk_info->latency(); } else { @@ -2186,13 +2186,12 @@ PathVisitor::visitFromPath(const Pin *from_pin, true, min_max, dcalc_ap, sdc); - bool arc_delay_min_max_eq = - fuzzyEqual(delayAsFloat(arc_delay), delayAsFloat(arc_delay_opp)); + bool arc_delay_min_max_eq = delayEqual(arc_delay, arc_delay_opp, this); to_tag = search_->thruClkTag(from_path, from_vertex, from_tag, true, edge, to_rf, arc_delay_min_max_eq, min_max, scene); - if (to_tag) - to_arrival = from_arrival + arc_delay; + if (to_tag) + to_arrival = delaySum(from_arrival, arc_delay, this); } } } @@ -2210,7 +2209,9 @@ PathVisitor::visitFromPath(const Pin *from_pin, const LibertyCell *inst_cell = clk_port->libertyCell(); if (inst_cell->isMacro()) { float slew = delayAsFloat(from_path->slew(this)); - arc_delay -= clk_port->clkTreeDelay(slew, from_rf, min_max); + arc_delay = delayDiff(arc_delay, + clk_port->clkTreeDelay(slew, from_rf, min_max), + this); } } @@ -2237,7 +2238,7 @@ PathVisitor::visitFromPath(const Pin *from_pin, to_tag = search_->thruTag(to_tag, edge, to_rf, tag_cache_); from_arrival = search_->clkPathArrival(from_path, from_clk_info, clk_edge, min_max); - to_arrival = from_arrival + arc_delay; + to_arrival = delaySum(from_arrival, arc_delay, this); } else to_tag = nullptr; @@ -2309,7 +2310,7 @@ PathVisitor::visitFromPath(const Pin *from_pin, to_propagates_clk, edge, to_rf, arc_delay_min_max_eq, min_max, scene); - to_arrival = from_arrival + arc_delay; + to_arrival = delaySum(from_arrival, arc_delay, this); } } else { @@ -2317,8 +2318,8 @@ PathVisitor::visitFromPath(const Pin *from_pin, || sdc->isPathDelayInternalToBreak(from_pin))) { arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, min_max, dcalc_ap, sdc); - if (!delayInf(arc_delay)) { - to_arrival = from_arrival + arc_delay; + if (!delayInf(arc_delay, this)) { + to_arrival = delaySum(from_arrival, arc_delay, this); to_tag = search_->thruTag(from_tag, edge, to_rf, tag_cache_); } } @@ -2355,11 +2356,11 @@ Search::clkPathArrival(const Path *clk_path, && !clk_info->isPropagated()) { // Ideal clock, apply ideal insertion delay and latency. const EarlyLate *early_late = min_max; - return clk_edge->time() - + clockInsertion(clk_edge->clock(), clk_info->clkSrc(), - clk_edge->transition(), min_max, - early_late, scene->mode()) - + clk_info->latency(); + Arrival insertion = clockInsertion(clk_edge->clock(), clk_info->clkSrc(), + clk_edge->transition(), min_max, + early_late, scene->mode()); + return delaySum(delaySum(insertion, clk_edge->time(), this), + clk_info->latency(), this); } else return clk_path->arrival(); @@ -3166,8 +3167,8 @@ Search::deratedDelay(const Vertex *from_vertex, const Sdc *sdc) { float derate = timingDerate(from_vertex, arc, edge, is_clk, sdc, min_max); - ArcDelay delay = graph_->arcDelay(edge, arc, dcalc_ap); - return delay * derate; + const ArcDelay &delay = graph_->arcDelay(edge, arc, dcalc_ap); + return delayProduct(delay, derate, this);; } float @@ -3568,9 +3569,9 @@ RequiredCmp::requiredsSave(Vertex *vertex, while (path_iter.hasNext()) { Path *path = path_iter.next(); size_t path_index = path->pathIndex(sta); - Required req = requireds_[path_index]; - Required &prev_req = path->required(); - bool changed = !delayEqual(prev_req, req); + const Required req = requireds_[path_index]; + const Required &prev_req = path->required(); + bool changed = !delayEqual(prev_req, req, sta); debugPrint(debug, "search", 3, "required %s save %s -> %s%s", path->to_string(sta).c_str(), delayAsString(prev_req, sta), @@ -3669,8 +3670,8 @@ RequiredVisitor::visitFromToPath(const Pin *, if (to_tag_group && to_tag_group->hasTag(to_tag)) { size_t to_path_index = to_tag_group->pathIndex(to_tag); Path &to_path = to_vertex->paths()[to_path_index]; - Required &to_required = to_path.required(); - Required from_required = to_required - arc_delay; + const Required &to_required = to_path.required(); + Required from_required = delayDiff(to_required, arc_delay, this); debugPrint(debug_, "search", 3, " to tag %2u: %s", to_tag->index(), to_tag->to_string(this).c_str()); @@ -3694,7 +3695,7 @@ RequiredVisitor::visitFromToPath(const Pin *, Tag *to_path_tag = to_path->tag(this); if (Tag::matchNoCrpr(to_path_tag, to_tag)) { Required to_required = to_path->required(); - Required from_required = to_required - arc_delay; + Required from_required = delayDiff(to_required, arc_delay, this); debugPrint(debug_, "search", 3, " to tag %2u: %s", to_path_tag->index(), to_path_tag->to_string(this).c_str()); @@ -3873,14 +3874,14 @@ Slack Search::totalNegativeSlack(const MinMax *min_max) { tnsPreamble(); - Slack tns = 0.0; + DelayDbl tns = 0.0; for (Scene *scene : scenes_) { size_t path_index = scene->pathIndex(min_max); - Slack tns1 = tns_[path_index]; + DelayDbl tns1 = tns_[path_index]; if (delayLess(tns1, tns, this)) tns = tns1; } - return tns; + return delayDblAsDelay(tns); } Slack @@ -3889,7 +3890,7 @@ Search::totalNegativeSlack(const Scene *scene, { tnsPreamble(); PathAPIndex path_ap_index = scene->pathIndex(min_max); - return tns_[path_ap_index]; + return delayDblAsDelay(tns_[path_ap_index]); } void @@ -3976,7 +3977,7 @@ Search::tnsIncr(Vertex *vertex, debugPrint(debug_, "tns", 3, "tns+ %s %s", delayAsString(slack, this), vertex->to_string(this).c_str()); - tns_[path_ap_index] += slack; + delayIncr(tns_[path_ap_index], slack, this); if (tns_slacks_[path_ap_index].contains(vertex)) report_->critical(1513, "tns incr existing vertex"); tns_slacks_[path_ap_index][vertex] = slack; @@ -3995,7 +3996,7 @@ Search::tnsDecr(Vertex *vertex, debugPrint(debug_, "tns", 3, "tns- %s %s", delayAsString(slack, this), vertex->to_string(this).c_str()); - tns_[path_ap_index] -= slack; + delayDecr(tns_[path_ap_index], slack, this); tns_slacks_[path_ap_index].erase(vertex); } } diff --git a/search/Search.i b/search/Search.i index 90ac5e47..f83399b5 100644 --- a/search/Search.i +++ b/search/Search.i @@ -39,6 +39,7 @@ #include "Bfs.hh" #include "Scene.hh" #include "Sta.hh" +#include "StaConfig.hh" using namespace sta; @@ -155,26 +156,29 @@ find_requireds() Sta::sta()->findRequireds(); } -Slack +float total_negative_slack_cmd(const MinMax *min_max) { - return Sta::sta()->totalNegativeSlack(min_max); + Sta *sta = Sta::sta(); + return delayAsFloat(sta->totalNegativeSlack(min_max), min_max, sta); } -Slack +float total_negative_slack_scene_cmd(const Scene *scene, const MinMax *min_max) { - return Sta::sta()->totalNegativeSlack(scene, min_max); + Sta *sta = Sta::sta(); + return delayAsFloat(sta->totalNegativeSlack(scene, min_max), min_max, sta); } -Slack +float worst_slack_cmd(const MinMax *min_max) { + Sta *sta = Sta::sta(); Slack worst_slack; Vertex *worst_vertex; - Sta::sta()->worstSlack(min_max, worst_slack, worst_vertex); - return worst_slack; + sta->worstSlack(min_max, worst_slack, worst_vertex); + return delayAsFloat(worst_slack, min_max, sta); } Vertex * @@ -186,14 +190,15 @@ worst_slack_vertex(const MinMax *min_max) return worst_vertex;; } -Slack +float worst_slack_scene(const Scene *scene, const MinMax *min_max) { + Sta *sta = Sta::sta(); Slack worst_slack; Vertex *worst_vertex; - Sta::sta()->worstSlack(scene, min_max, worst_slack, worst_vertex); - return worst_slack; + sta->worstSlack(scene, min_max, worst_slack, worst_vertex); + return delayAsFloat(worst_slack, min_max, sta); } Path * @@ -224,7 +229,7 @@ vertex_worst_slack_path(Vertex *vertex, return sta->vertexWorstSlackPath(vertex, min_max); } -Slack +float endpoint_slack(const Pin *pin, const char *path_group_name, const MinMax *min_max) @@ -233,7 +238,7 @@ endpoint_slack(const Pin *pin, sta->ensureLibLinked(); if (sta->isGroupPathName(path_group_name, sta->cmdSdc())) { Slack slack = sta->endpointSlack(pin, std::string(path_group_name), min_max); - return sta->units()->timeUnit()->staToUser(delayAsFloat(slack)); + return sta->units()->timeUnit()->staToUser(delayAsFloat(slack, min_max, sta)); } else { sta->report()->error(1577, "%s is not a known path group name.", @@ -407,6 +412,7 @@ set_report_path_fields(bool report_input_pin, bool report_cap, bool report_slew, bool report_fanout, + bool report_variation, bool report_src_attr) { Sta::sta()->setReportPathFields(report_input_pin, @@ -415,6 +421,7 @@ set_report_path_fields(bool report_input_pin, report_cap, report_slew, report_fanout, + report_variation, report_src_attr); } @@ -432,18 +439,6 @@ set_report_path_field_properties(const char *field_name, sta->report()->warn(1575, "unknown report path field %s", field_name); } -void -set_report_path_field_width(const char *field_name, - int width) -{ - Sta *sta = Sta::sta(); - ReportField *field = sta->findReportPathField(field_name); - if (field) - field->setWidth(width); - else - sta->report()->warn(1576, "unknown report path field %s", field_name); -} - void set_report_path_digits(int digits) { @@ -456,12 +451,6 @@ set_report_path_no_split(bool no_split) Sta::sta()->setReportPathNoSplit(no_split); } -void -set_report_path_sigmas(bool report_sigmas) -{ - Sta::sta()->setReportPathSigmas(report_sigmas); -} - void report_path_cmd(Path *path) { @@ -480,25 +469,28 @@ report_path_ends(PathEndSeq *ends) void report_arrival_wrt_clks(const Pin *pin, const Scene *scene, + bool report_variance, int digits) { - Sta::sta()->reportArrivalWrtClks(pin, scene, digits); + Sta::sta()->reportArrivalWrtClks(pin, scene, report_variance, digits); } void report_required_wrt_clks(const Pin *pin, const Scene *scene, + bool report_variance, int digits) { - Sta::sta()->reportRequiredWrtClks(pin, scene, digits); + Sta::sta()->reportRequiredWrtClks(pin, scene, report_variance, digits); } void report_slack_wrt_clks(const Pin *pin, const Scene *scene, + bool report_variance, int digits) { - Sta::sta()->reportSlackWrtClks(pin, scene, digits); + Sta::sta()->reportSlackWrtClks(pin, scene, report_variance, digits); } //////////////////////////////////////////////////////////////// @@ -518,7 +510,9 @@ float worst_clk_skew_cmd(const SetupHold *setup_hold, bool include_internal_latency) { - return Sta::sta()->findWorstClkSkew(setup_hold, include_internal_latency); + Sta *sta = Sta::sta(); + Delay skew = sta->findWorstClkSkew(setup_hold, include_internal_latency); + return delayAsFloat(skew, MinMax::max(), sta); } //////////////////////////////////////////////////////////////// @@ -571,7 +565,7 @@ report_max_skew_checks(const Net *net, //////////////////////////////////////////////////////////////// -Slack +float find_clk_min_period(const Clock *clk, bool ignore_port_paths) { @@ -963,39 +957,37 @@ set_crpr_mode(const char *mode) { Sta *sta = Sta::sta(); if (stringEq(mode, "same_pin")) - Sta::sta()->setCrprMode(CrprMode::same_pin); + sta->setCrprMode(CrprMode::same_pin); else if (stringEq(mode, "same_transition")) - Sta::sta()->setCrprMode(CrprMode::same_transition); + sta->setCrprMode(CrprMode::same_transition); else - sta->report()->critical(1573, "unknown common clk pessimism mode."); + sta->report()->error(1573, "unknown common clk pessimism mode."); } -bool -pocv_enabled() +const char * +pocv_mode() { - return Sta::sta()->pocvEnabled(); + return pocvModeName(Sta::sta()->pocvMode()); } void -set_pocv_enabled(bool enabled) +set_pocv_mode(const char *mode_name) { -#if !SSTA - if (enabled) - Sta::sta()->report()->error(1574, "POCV support requires compilation with SSTA=1."); -#endif - return Sta::sta()->setPocvEnabled(enabled); + Sta *sta = Sta::sta(); + PocvMode mode = findPocvMode(mode_name); + sta->setPocvMode(mode); } float -pocv_sigma_factor() +pocv_quantile() { - return Sta::sta()->sigmaFactor(); + return Sta::sta()->pocvQuantile(); } void -set_pocv_sigma_factor(float factor) +set_pocv_quantile(float quantile) { - Sta::sta()->setSigmaFactor(factor); + Sta::sta()->setPocvQuantile(quantile); } bool @@ -1141,58 +1133,83 @@ Vertex *vertex() { return self->vertex(Sta::sta()); } Path *path() { return self->path(); } RiseFall *end_transition() { return const_cast(self->path()->transition(Sta::sta())); } -Slack slack() { return self->slack(Sta::sta()); } -ArcDelay margin() { return self->margin(Sta::sta()); } -Required data_required_time() { return self->requiredTimeOffset(Sta::sta()); } -Arrival data_arrival_time() { return self->dataArrivalTimeOffset(Sta::sta()); } + +float +slack() +{ + Sta *sta = Sta::sta(); + return delayAsFloat(self->slack(sta), self->minMax(sta), sta); +} + +float +margin() +{ + Sta *sta = Sta::sta(); + return delayAsFloat(self->margin(sta), self->minMax(sta), sta); +} + +float +data_required_time() +{ + Sta *sta = Sta::sta(); + return delayAsFloat(self->requiredTimeOffset(sta), self->minMax(sta), sta); +} + +float +data_arrival_time() +{ + Sta *sta = Sta::sta(); + return delayAsFloat(self->dataArrivalTimeOffset(sta), self->minMax(sta), sta); +} + +float +target_clk_delay() +{ + Sta *sta = Sta::sta(); + return delayAsFloat(self->targetClkDelay(sta), self->minMax(sta), sta); +} + +float +source_clk_latency() +{ + Sta *sta = Sta::sta(); + return delayAsFloat(self->sourceClkLatency(sta), self->minMax(sta), sta); +} + +float +clk_skew() +{ + Sta *sta = Sta::sta(); + return delayAsFloat(self->clkSkew(sta), self->minMax(sta), sta); +} + const TimingRole *check_role() { return self->checkRole(Sta::sta()); } MinMax *min_max() { return const_cast(self->minMax(Sta::sta())); } -float source_clk_offset() { return self->sourceClkOffset(Sta::sta()); } -Arrival source_clk_latency() { return self->sourceClkLatency(Sta::sta()); } -Arrival source_clk_insertion_delay() -{ return self->sourceClkInsertionDelay(Sta::sta()); } const Clock *target_clk() { return self->targetClk(Sta::sta()); } const ClockEdge *target_clk_edge() { return self->targetClkEdge(Sta::sta()); } Path *target_clk_path() { return self->targetClkPath(); } -float target_clk_time() { return self->targetClkTime(Sta::sta()); } -float target_clk_offset() { return self->targetClkOffset(Sta::sta()); } -float target_clk_mcp_adjustment() -{ return self->targetClkMcpAdjustment(Sta::sta()); } -Arrival target_clk_delay() { return self->targetClkDelay(Sta::sta()); } -Arrival target_clk_insertion_delay() -{ return self->targetClkInsertionDelay(Sta::sta()); } -float target_clk_uncertainty() -{ return self->targetNonInterClkUncertainty(Sta::sta()); } -float inter_clk_uncertainty() -{ return self->interClkUncertainty(Sta::sta()); } -Arrival target_clk_arrival() { return self->targetClkArrival(Sta::sta()); } -bool path_delay_margin_is_external() -{ return self->pathDelayMarginIsExternal();} -Crpr check_crpr() { return self->checkCrpr(Sta::sta()); } -RiseFall *target_clk_end_trans() -{ return const_cast(self->targetClkEndTrans(Sta::sta())); } -Delay clk_skew() { return self->clkSkew(Sta::sta()); } - } %extend Path { float arrival() { - return delayAsFloat(self->arrival()); + Sta *sta = Sta::sta(); + return delayAsFloat(self->arrival(), self->minMax(sta), sta); } float required() { - return delayAsFloat(self->required()); + Sta *sta = Sta::sta(); + return delayAsFloat(self->required(), self->minMax(sta), sta); } float slack() { Sta *sta = Sta::sta(); - return delayAsFloat(self->slack(sta)); + return delayAsFloat(self->slack(sta), self->minMax(sta), sta); } const Pin * diff --git a/search/Search.tcl b/search/Search.tcl index f7a548c5..73ef64b3 100644 --- a/search/Search.tcl +++ b/search/Search.tcl @@ -683,7 +683,6 @@ proc_redirect report_path { proc parse_report_path_options { cmd args_var default_format unknown_key_is_error } { variable path_options - variable report_path_field_width_extra global sta_report_default_digits upvar 1 $args_var args @@ -691,7 +690,7 @@ proc parse_report_path_options { cmd args_var default_format unset path_options } parse_key_args $cmd args path_options {-format -digits -fields} \ - path_options {-no_line_splits -report_sigmas} $unknown_key_is_error + path_options {-no_line_splits} $unknown_key_is_error set format $default_format if [info exists path_options(-format)] { @@ -712,24 +711,8 @@ proc parse_report_path_options { cmd args_var default_format check_positive_integer "-digits" $digits } - set report_sigmas [info exists path_options(-report_sigmas)] - set_report_path_sigmas $report_sigmas - set path_options(num_fmt) "%.${digits}f" set_report_path_digits $digits - # Numeric field width expands with digits. - set field_width [expr $digits + $report_path_field_width_extra] - if { $report_sigmas } { - set delay_field_width [expr $field_width * 3 + $report_path_field_width_extra] - } else { - set delay_field_width $field_width - } - foreach field {total incr} { - set_report_path_field_width $field $delay_field_width - } - foreach field {capacitance slew} { - set_report_path_field_width $field $field_width - } set report_input_pin 0 set report_hier_pins 0 @@ -737,6 +720,7 @@ proc parse_report_path_options { cmd args_var default_format set report_net 0 set report_slew 0 set report_fanout 0 + set report_variation 0 set report_src_attr 0 if { [info exists path_options(-fields)] } { foreach field $path_options(-fields) { @@ -752,6 +736,8 @@ proc parse_report_path_options { cmd args_var default_format set report_slew 1 } elseif { [string match "fanout" $field] } { set report_fanout 1 + } elseif { [string match "variation" $field] } { + set report_variation 1 } elseif { [string match "src*" $field] } { set report_src_attr 1 } else { @@ -759,20 +745,21 @@ proc parse_report_path_options { cmd args_var default_format } } } + set_report_path_fields $report_input_pin $report_hier_pins $report_net \ - $report_cap $report_slew $report_fanout $report_src_attr + $report_cap $report_slew $report_fanout $report_variation $report_src_attr set_report_path_no_split [info exists path_options(-no_line_splits)] } ################################################################ -define_cmd_args "report_arrival" {[-scene scene] [-digits digits] pin} +define_cmd_args "report_arrival" {[-scene scene] [-report_variance] [-digits digits] pin} proc report_arrival { args } { global sta_report_default_digits - parse_key_args "report_arrival" args keys {-scene -digits} flags {} + parse_key_args "report_arrival" args keys {-scene -digits} flags {-report_variance} check_argc_eq1 "report_arrival" $args set pin [get_port_pin_error "pin" [lindex $args 0]] @@ -783,17 +770,18 @@ proc report_arrival { args } { } else { set digits $sta_report_default_digits } - report_arrival_wrt_clks $pin $scene $digits + set report_variance [info exists flags(-report_variance)] + report_arrival_wrt_clks $pin $scene $report_variance $digits } ################################################################ -define_cmd_args "report_required" {[-scene scene] [-digits digits] pin} +define_cmd_args "report_required" {[-scene scene] [-report_variance] [-digits digits] pin} proc report_required { args } { global sta_report_default_digits - parse_key_args "report_required" args keys {-scene -digits} flags {} + parse_key_args "report_required" args keys {-scene -digits} flags {-report_variance} check_argc_eq1 "report_required" $args set pin [get_port_pin_error "pin" [lindex $args 0]] @@ -804,17 +792,18 @@ proc report_required { args } { } else { set digits $sta_report_default_digits } - report_required_wrt_clks $pin $scene $digits + set report_variance [info exists flags(-report_variance)] + report_required_wrt_clks $pin $scene $report_variance $digits } ################################################################ -define_cmd_args "report_slack" {[-scene scene] [-digits digits] pin} +define_cmd_args "report_slack" {[-scene scene] [-report_variance] [-digits digits] pin} proc report_slack { args } { global sta_report_default_digits - parse_key_args "report_slack" args keys {-scene -digits} flags {} + parse_key_args "report_slack" args keys {-scene -digits} flags {-report_variance} check_argc_eq1 "report_slack" $args set pin [get_port_pin_error "pin" [lindex $args 0]] @@ -825,7 +814,8 @@ proc report_slack { args } { } else { set digits $sta_report_default_digits } - report_slack_wrt_clks $pin $scene $digits + set report_variance [info exists flags(-report_variance)] + report_slack_wrt_clks $pin $scene $report_variance $digits } ################################################################ diff --git a/search/Sta.cc b/search/Sta.cc index d0d643ee..e8fe636c 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -87,6 +87,9 @@ #include "MakeTimingModel.hh" #include "parasitics/ConcreteParasitics.hh" #include "spice/WritePathSpice.hh" +#include "DelayScalar.hh" +#include "DelayNormal.hh" +#include "DelaySkewNormal.hh" namespace sta { @@ -300,6 +303,7 @@ Sta::makeComponents() makePower(); makeClkSkews(); makeCheckTiming(); + delay_ops_ = new DelayOpsScalar(); setCmdNamespace1(CmdNamespace::sdc); setThreadCount1(defaultThreadCount()); @@ -526,6 +530,7 @@ Sta::~Sta() delete equiv_cells_; delete dispatch_queue_; delete variables_; + delete delay_ops_; deleteContents(parasitics_name_map_); deleteContents(modes_); deleteContents(scenes_); @@ -2262,25 +2267,47 @@ Sta::setCrprMode(CrprMode mode) variables_->setCrprMode(mode); } -bool -Sta::pocvEnabled() const +PocvMode +Sta::pocvMode() const { - return variables_->pocvEnabled(); + return variables_->pocvMode(); } void -Sta::setPocvEnabled(bool enabled) +Sta::setPocvMode(PocvMode mode) { - if (enabled != variables_->pocvEnabled()) + if (mode != variables_->pocvMode()) { + variables_->setPocvMode(mode); + + delete delay_ops_; + switch (mode) { + case PocvMode::scalar: + default: + delay_ops_ = new DelayOpsScalar(); + break; + case PocvMode::normal: + delay_ops_ = new DelayOpsNormal(); + break; + case PocvMode::skew_normal: + delay_ops_ = new DelayOpsSkewNormal(); + break; + } + updateComponentsState(); delaysInvalid(); - variables_->setPocvEnabled(enabled); + } +} + +float +Sta::pocvQuantile() +{ + return variables_->pocvQuantile(); } void -Sta::setSigmaFactor(float factor) +Sta::setPocvQuantile(float quantile) { - if (!fuzzyEqual(factor, sigma_factor_)) { - sigma_factor_ = factor; + if (!fuzzyEqual(quantile, variables_->pocvQuantile())) { + variables_->setPocvQuantile(quantile); search_->arrivalsInvalid(); updateComponentsState(); } @@ -2739,11 +2766,12 @@ Sta::setReportPathFields(bool report_input_pin, bool report_cap, bool report_slew, bool report_fanout, + bool report_variation, bool report_src_attr) { report_path_->setReportFields(report_input_pin, report_hier_pins, report_net, report_cap, report_slew, report_fanout, - report_src_attr); + report_variation, report_src_attr); } ReportField * @@ -2764,12 +2792,6 @@ Sta::setReportPathNoSplit(bool no_split) report_path_->setNoSplit(no_split); } -void -Sta::setReportPathSigmas(bool report_sigmas) -{ - report_path_->setReportSigmas(report_sigmas); -} - void Sta::reportPathEnd(PathEnd *end) { @@ -2811,7 +2833,7 @@ Sta::reportClkSkew(ConstClockSeq &clks, include_internal_latency, digits); } -float +Delay Sta::findWorstClkSkew(const SetupHold *setup_hold, bool include_internal_latency) { @@ -3246,10 +3268,11 @@ Sta::endpointSlack(const Pin *pin, void Sta::reportArrivalWrtClks(const Pin *pin, const Scene *scene, + bool report_variance, int digits) { searchPreamble(); - reportDelaysWrtClks(pin, scene, digits, false, + reportDelaysWrtClks(pin, scene, report_variance, digits, false, [] (const Path *path) { return path->arrival(); }); @@ -3258,9 +3281,10 @@ Sta::reportArrivalWrtClks(const Pin *pin, void Sta::reportRequiredWrtClks(const Pin *pin, const Scene *scene, + bool report_variance, int digits) { - reportDelaysWrtClks(pin, scene, digits, true, + reportDelaysWrtClks(pin, scene, report_variance, digits, true, [] (const Path *path) { return path->required(); }); @@ -3269,9 +3293,10 @@ Sta::reportRequiredWrtClks(const Pin *pin, void Sta::reportSlackWrtClks(const Pin *pin, const Scene *scene, + bool report_variance, int digits) { - reportDelaysWrtClks(pin, scene, digits, true, + reportDelaysWrtClks(pin, scene, report_variance, digits, true, [this] (const Path *path) { return path->slack(this); }); @@ -3280,6 +3305,7 @@ Sta::reportSlackWrtClks(const Pin *pin, void Sta::reportDelaysWrtClks(const Pin *pin, const Scene *scene, + bool report_variance, int digits, bool find_required, PathDelayFunc get_path_delay) @@ -3288,14 +3314,17 @@ Sta::reportDelaysWrtClks(const Pin *pin, Vertex *vertex, *bidir_vertex; graph_->pinVertices(pin, vertex, bidir_vertex); if (vertex) - reportDelaysWrtClks(vertex, scene, digits, find_required, get_path_delay); + reportDelaysWrtClks(vertex, scene, report_variance, digits, + find_required, get_path_delay); if (bidir_vertex) - reportDelaysWrtClks(vertex, scene, digits, find_required, get_path_delay); + reportDelaysWrtClks(vertex, scene, report_variance, digits, + find_required, get_path_delay); } void Sta::reportDelaysWrtClks(Vertex *vertex, const Scene *scene, + bool report_variance, int digits, bool find_required, PathDelayFunc get_path_delay) @@ -3305,13 +3334,15 @@ Sta::reportDelaysWrtClks(Vertex *vertex, else search_->findArrivals(vertex->level()); const Sdc *sdc = scene->sdc(); - reportDelaysWrtClks(vertex, nullptr, scene, digits, get_path_delay); + reportDelaysWrtClks(vertex, nullptr, scene, report_variance, digits, get_path_delay); const ClockEdge *default_clk_edge = sdc->defaultArrivalClock()->edge(RiseFall::rise()); - reportDelaysWrtClks(vertex, default_clk_edge, scene, digits, get_path_delay); + reportDelaysWrtClks(vertex, default_clk_edge, scene, report_variance, + digits, get_path_delay); for (const Clock *clk : sdc->sortedClocks()) { for (const RiseFall *rf : RiseFall::range()) { const ClockEdge *clk_edge = clk->edge(rf); - reportDelaysWrtClks(vertex, clk_edge, scene, digits, get_path_delay); + reportDelaysWrtClks(vertex, clk_edge, scene, report_variance, digits, + get_path_delay); } } } @@ -3320,6 +3351,7 @@ void Sta::reportDelaysWrtClks(Vertex *vertex, const ClockEdge *clk_edge, const Scene *scene, + bool report_variance, int digits, PathDelayFunc get_path_delay) { @@ -3335,13 +3367,13 @@ Sta::reportDelaysWrtClks(Vertex *vertex, report_->reportLine("%s r %s:%s f %s:%s", clk_name.c_str(), formatDelay(RiseFall::rise(), MinMax::min(), - delays, digits).c_str(), + delays, report_variance, digits).c_str(), formatDelay(RiseFall::rise(), MinMax::max(), - delays, digits).c_str(), + delays, report_variance, digits).c_str(), formatDelay(RiseFall::fall(), MinMax::min(), - delays, digits).c_str(), + delays, report_variance, digits).c_str(), formatDelay(RiseFall::fall(), MinMax::max(), - delays, digits).c_str()); + delays, report_variance, digits).c_str()); } } @@ -3360,7 +3392,7 @@ Sta::findDelaysWrtClks(Vertex *vertex, const MinMax *min_max = path->minMax(this); const ClockEdge *path_clk_edge = path->clkEdge(this); if (path_clk_edge == clk_edge - && !delayInf(delay)) + && !delayInf(delay, this)) delays.mergeValue(rf, min_max, delay, this); } return delays; @@ -3370,13 +3402,14 @@ std::string Sta::formatDelay(const RiseFall *rf, const MinMax *min_max, const RiseFallMinMaxDelay &delays, + bool report_variance, int digits) { Delay delay; bool exists; delays.value(rf, min_max, delay, exists); if (exists) - return delayAsString(delay, this, digits); + return delayAsString(delay, min_max, report_variance, digits, this); else return "---"; } @@ -3439,7 +3472,7 @@ MinPeriodEndVisitor::visit(PathEnd *path_end) || !(network->isTopLevelPort(path->pin(sta_)) || pathIsFromInputPort(path_end)))) { Slack slack = path_end->slack(sta_); - float period = clk_->period() - delayAsFloat(slack); + float period = clk_->period() - delayAsFloat(slack, MinMax::min(), sta_); min_period_ = std::max(min_period_, period); } } @@ -3589,7 +3622,7 @@ Sta::setIncrementalDelayTolerance(float tol) graph_delay_calc_->setIncrementalDelayTolerance(tol); } -ArcDelay +const ArcDelay& Sta::arcDelay(Edge *edge, TimingArc *arc, DcalcAPIndex ap_index) @@ -3684,7 +3717,7 @@ Sta::ensureGraph() void Sta::makeGraph() { - graph_ = new Graph(this, 2, dcalcAnalysisPtCount()); + graph_ = new Graph(this, dcalcAnalysisPtCount()); graph_->makeGraph(); } @@ -5535,12 +5568,12 @@ Sta::reportSlewChecks(const Net *net, if (verbose) report_path_->reportLimitVerbose(report_path_->fieldSlew(), check.pin(), check.edge(), - delayAsFloat(check.slew()), + delayAsFloat(check.slew(), min_max, this), check.limit(), check.slack(), check.scene(), min_max); else report_path_->reportLimitShort(report_path_->fieldSlew(), check.pin(), - delayAsFloat(check.slew()), + delayAsFloat(check.slew(), min_max, this), check.limit(), check.slack()); } report_->reportLine(""); diff --git a/search/StaState.cc b/search/StaState.cc index 6ba49123..661c02c9 100644 --- a/search/StaState.cc +++ b/search/StaState.cc @@ -49,11 +49,11 @@ StaState::StaState() : arc_delay_calc_(nullptr), graph_delay_calc_(nullptr), search_(nullptr), + delay_ops_(nullptr), latches_(nullptr), variables_(nullptr), thread_count_(1), - dispatch_queue_(nullptr), - sigma_factor_(1.0) + dispatch_queue_(nullptr) { } diff --git a/search/WorstSlack.cc b/search/WorstSlack.cc index d2e6d5ce..8a19ca57 100644 --- a/search/WorstSlack.cc +++ b/search/WorstSlack.cc @@ -166,7 +166,7 @@ WorstSlack::initQueue(PathAPIndex path_ap_index) slack_threshold_ = slack_init_; for(Vertex *vertex : search_->endpoints()) { Slack slack = search_->wnsSlack(vertex, path_ap_index); - if (!delayEqual(slack, slack_init_)) { + if (!delayEqual(slack, slack_init_, this)) { if (delayLess(slack, worst_slack_, this)) setWorstSlack(vertex, slack); if (delayLessEqual(slack, slack_threshold_, this)) @@ -177,8 +177,8 @@ WorstSlack::initQueue(PathAPIndex path_ap_index) } } debugPrint(debug_, "wns", 3, "threshold %s", - delayAsString(slack_threshold_, this)); -// checkQueue(); + delayAsString(slack_threshold_, MinMax::max(), this)); + //checkQueue(); } void @@ -199,7 +199,7 @@ WorstSlack::sortQueue(PathAPIndex path_ap_index) Vertex *threshold_vertex = vertices[threshold_index]; slack_threshold_ = search_->wnsSlack(threshold_vertex, path_ap_index); debugPrint(debug_, "wns", 3, "threshold %s", - delayAsString(slack_threshold_, this)); + delayAsString(slack_threshold_, MinMax::max(), this)); // Reinsert vertices with slack < threshold. queue_->clear(); @@ -281,7 +281,7 @@ WorstSlack::updateWorstSlack(Vertex *vertex, // Mark worst slack as unknown (updated by findWorstSlack(). worst_vertex_ = nullptr; - if (!delayEqual(slack, slack_init_) + if (!delayEqual(slack, slack_init_, this) && delayLessEqual(slack, slack_threshold_, this)) { debugPrint(debug_, "wns", 3, "insert %s %s", vertex->to_string(this).c_str(), diff --git a/spice/WriteSpice.cc b/spice/WriteSpice.cc index 3e646bea..1e844ed5 100644 --- a/spice/WriteSpice.cc +++ b/spice/WriteSpice.cc @@ -484,7 +484,7 @@ WriteSpice::slewAxisMinValue(const TimingArc *arc) { GateTableModel *gate_model = arc->gateTableModel(scene_, min_max_); if (gate_model) { - const TableModel *model = gate_model->delayModel(); + const TableModel *model = gate_model->delayModels()->model(); const TableAxis *axis1 = model->axis1(); TableAxisVariable var1 = axis1->variable(); if (var1 == TableAxisVariable::input_transition_time diff --git a/tcl/StaTclTypes.i b/tcl/StaTclTypes.i index e29d5a6b..732a651a 100644 --- a/tcl/StaTclTypes.i +++ b/tcl/StaTclTypes.i @@ -1198,32 +1198,8 @@ using namespace sta; Tcl_SetObjResult(interp, obj); } -%typemap(out) Delay { - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); -} - -%typemap(out) Arrival { - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); -} - -%typemap(out) Required { - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); -} - -%typemap(out) Slack { - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); -} - -%typemap(out) ArcDelay { - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); -} - -%typemap(out) Slew { - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); -} - -%typemap(out) Crpr { - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); +%typemap(in) StringSet* { + $1 = tclListSetConstChar($input, interp); } %typemap(out) Mode* { diff --git a/tcl/TclTypeHelpers.cc b/tcl/TclTypeHelpers.cc index 8667048b..0de899c5 100644 --- a/tcl/TclTypeHelpers.cc +++ b/tcl/TclTypeHelpers.cc @@ -170,7 +170,7 @@ tclArcDcalcArg(ArcDcalcArg &gate, obj = Tcl_NewStringObj(to_edge, strlen(to_edge)); Tcl_ListObjAppendElement(interp, list, obj); - const char *input_delay = delayAsString(gate.inputDelay(), sta, 3); + const char *input_delay = delayAsString(gate.inputDelay(), sta); obj = Tcl_NewStringObj(input_delay, strlen(input_delay)); Tcl_ListObjAppendElement(interp, list, obj); diff --git a/tcl/Variables.tcl b/tcl/Variables.tcl index e37f7396..ba8f37b3 100644 --- a/tcl/Variables.tcl +++ b/tcl/Variables.tcl @@ -152,16 +152,42 @@ proc trace_propagate_gated_clock_enable { name1 name2 op } { propagate_gated_clock_enable set_propagate_gated_clock_enable } -trace variable ::sta_pocv_enabled "rw" \ - sta::trace_pocv_enabled +trace variable ::sta_pocv_mode "rw" \ + sta::trace_pocv_mode -proc trace_pocv_enabled { name1 name2 op } { - trace_boolean_var $op ::sta_pocv_enabled \ - pocv_enabled set_pocv_enabled +proc trace_pocv_mode { name1 name2 op } { + global sta_pocv_mode + + if { $op == "r" } { + set sta_pocv_mode [pocv_mode] + } elseif { $op == "w" } { + if { $sta_pocv_mode == "scalar" \ + || $sta_pocv_mode == "normal" \ + || $sta_pocv_mode == "skew_normal" } { + set_pocv_mode $sta_pocv_mode + } else { + sta_error 593 "sta_pocv_mode must be scalar, normal, or skew_normal." + } + } } -# Report path numeric field width is digits + extra. -set report_path_field_width_extra 5 +trace variable ::sta_pocv_quantile "rw" \ + sta::trace_pocv_quantile + +proc trace_pocv_quantile { name1 name2 op } { + global sta_pocv_quantile + + if { $op == "r" } { + set sta_pocv_quantile [pocv_quantile] + } elseif { $op == "w" } { + if { [string is double $sta_pocv_quantile] \ + && $sta_pocv_quantile >= 0.0 } { + set_pocv_quantile $sta_pocv_quantile + } else { + sta_error 594 "sta_pocv_quantile must be a positive floating point number." + } + } +} ################################################################ diff --git a/util/StaConfig.hh.cmake b/util/StaConfig.hh.cmake index 78d2e304..2efd9720 100644 --- a/util/StaConfig.hh.cmake +++ b/util/StaConfig.hh.cmake @@ -6,6 +6,4 @@ #cmakedefine ZLIB_FOUND -#define SSTA ${SSTA} - #define TCL_READLINE ${TCL_READLINE} diff --git a/verilog/VerilogReader.cc b/verilog/VerilogReader.cc index 3d402e79..e018fae9 100644 --- a/verilog/VerilogReader.cc +++ b/verilog/VerilogReader.cc @@ -1032,7 +1032,7 @@ VerilogDclBus::VerilogDclBus(PortDirection *dir, int VerilogDclBus::size() const { - return abs(to_index_ - from_index_) + 1; + return std::abs(to_index_ - from_index_) + 1; } VerilogDclArg::VerilogDclArg(const std::string &net_name) :