// 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()); } std::string delayAsString(const Delay &delay, const StaState *sta) { return delayAsString(delay, EarlyLate::late(), sta->units()->timeUnit()->digits(), sta); } std::string delayAsString(const Delay &delay, int digits, const StaState *sta) { return delayAsString(delay, EarlyLate::late(), digits, sta); } std::string delayAsString(const Delay &delay, const EarlyLate *early_late, const StaState *sta) { return delayAsString(delay, early_late, sta->units()->timeUnit()->digits(), sta); } std::string 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); } std::string 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