diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fe44d6e..981c73d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ set(STA_SOURCE dcalc/UnitDelayCalc.cc graph/DelayFloat.cc + graph/DelayNormal1.cc graph/DelayNormal2.cc graph/Graph.cc graph/GraphCmp.cc @@ -227,6 +228,7 @@ set(STA_HEADERS graph/Delay.hh graph/DelayFloat.hh + graph/DelayNormal1.hh graph/DelayNormal2.hh graph/Graph.hh graph/GraphClass.hh diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index a72ceb43..12083100 100644 Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ diff --git a/doc/OpenSTA.pdf b/doc/OpenSTA.pdf index 8b617e51..8e7a3b33 100644 Binary files a/doc/OpenSTA.pdf and b/doc/OpenSTA.pdf differ diff --git a/graph/Delay.hh b/graph/Delay.hh index dd3bd551..4a3014a6 100644 --- a/graph/Delay.hh +++ b/graph/Delay.hh @@ -19,7 +19,10 @@ #ifndef STA_DELAY_H #define STA_DELAY_H -#if SSTA +#if (SSTA == 1) + // Delays are Normal PDFs with early/late sigma. + #include "DelayNormal1.hh" +#elif (SSTA == 2) // Delays are Normal PDFs with early/late sigma. #include "DelayNormal2.hh" #else diff --git a/graph/DelayNormal1.cc b/graph/DelayNormal1.cc new file mode 100644 index 00000000..1c52a889 --- /dev/null +++ b/graph/DelayNormal1.cc @@ -0,0 +1,419 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2019, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "StaConfig.hh" +#include // sqrt +#include "Machine.hh" +#include "Error.hh" +#include "StringUtil.hh" +#include "Fuzzy.hh" +#include "Units.hh" +#include "StaState.hh" +#include "Delay.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(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 mean_ == delay.mean_ + && sigma2_ == delay.sigma2_; +} + +bool +Delay::operator>(const Delay &delay) const +{ + return mean_ > delay.mean_; +} + +bool +Delay::operator>=(const Delay &delay) const +{ + return mean_ >= delay.mean_; +} + +bool +Delay::operator<(const Delay &delay) const +{ + return mean_ < delay.mean_; +} + +bool +Delay::operator<=(const Delay &delay) const +{ + return mean_ <= delay.mean_; +} + +//////////////////////////////////////////////////////////////// + +Delay +makeDelay(float delay, + float sigma, + float) +{ + return Delay(delay, square(sigma)); +} + +Delay +makeDelay2(float delay, + float sigma2, + float ) +{ + return Delay(delay, sigma2); +} + +bool +delayIsInitValue(const Delay &delay, + const MinMax *min_max) +{ + return fuzzyEqual(delay.mean(), min_max->initValue()) + && delay.sigma2() == 0.0; +} + +bool +fuzzyZero(const Delay &delay) +{ + return fuzzyZero(delay.mean()) + && fuzzyZero(delay.sigma2()); +} + +bool +fuzzyEqual(const Delay &delay1, + const Delay &delay2) +{ + return fuzzyEqual(delay1.mean(), delay2.mean()) + && fuzzyEqual(delay1.sigma2(), delay2.sigma2()); +} + +bool +fuzzyLess(const Delay &delay1, + const Delay &delay2) +{ + return fuzzyLess(delay1.mean(), delay2.mean()); +} + +bool +fuzzyLess(const Delay &delay1, + float delay2) +{ + return fuzzyLess(delay1.mean(), delay2); +} + +bool +fuzzyLessEqual(const Delay &delay1, + const Delay &delay2) +{ + return fuzzyLessEqual(delay1.mean(), delay2.mean()); +} + +bool +fuzzyLessEqual(const Delay &delay1, + float delay2) +{ + return fuzzyLessEqual(delay1.mean(), delay2); +} + +bool +fuzzyLessEqual(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max) +{ + if (min_max == MinMax::max()) + return fuzzyLessEqual(delay1.mean(), delay2.mean()); + else + return fuzzyGreaterEqual(delay1.mean(), delay2.mean()); +} + +bool +fuzzyGreater(const Delay &delay1, + const Delay &delay2) +{ + return fuzzyGreater(delay1.mean(), delay2.mean()); +} + +bool +fuzzyGreater(const Delay &delay1, + float delay2) +{ + return fuzzyGreater(delay1.mean(), delay2); +} + +bool +fuzzyGreaterEqual(const Delay &delay1, + const Delay &delay2) +{ + return fuzzyGreaterEqual(delay1.mean(), delay2.mean()); +} + +bool +fuzzyGreaterEqual(const Delay &delay1, + float delay2) +{ + return fuzzyGreaterEqual(delay1.mean(), delay2); +} + +bool +fuzzyGreater(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max) +{ + if (min_max == MinMax::max()) + return fuzzyGreater(delay1.mean(), delay2.mean()); + else + return fuzzyLess(delay1.mean(), delay2.mean()); +} + +bool +fuzzyGreaterEqual(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max) +{ + if (min_max == MinMax::max()) + return fuzzyGreaterEqual(delay1.mean(), delay2.mean()); + else + return fuzzyLessEqual(delay1.mean(), delay2.mean()); +} + +bool +fuzzyLess(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max) +{ + if (min_max == MinMax::max()) + return fuzzyLess(delay1.mean(), delay2.mean()); + else + return fuzzyGreater(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 scale) +{ + float scale2 = square(scale); + return Delay(delay1.mean() * scale, + delay1.sigma2() * scale2); +} + +float +delayRatio(const Delay &delay1, + const Delay &delay2) +{ + return delay1.mean() / delay2.mean(); +} + +float +delayAsFloat(const Delay &delay, + const EarlyLate *early_late, + float sigma_factor) +{ + if (early_late == EarlyLate::early()) + return delay.mean() - delay.sigma() * sigma_factor; + else if (early_late == EarlyLate::late()) + return delay.mean() + delay.sigma() * sigma_factor; + else + internalError("unknown early/late value."); +} + +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->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->sigmaFactor()); + return sta->units()->timeUnit()->asString(mean_sigma, digits); +} + +} // namespace +#endif diff --git a/graph/DelayNormal1.hh b/graph/DelayNormal1.hh new file mode 100644 index 00000000..a286c934 --- /dev/null +++ b/graph/DelayNormal1.hh @@ -0,0 +1,157 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2019, 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 . + +#ifndef STA_DELAY_NORMAL1_H +#define STA_DELAY_NORMAL1_H + +#include "MinMax.hh" + +namespace sta { + +class Delay; +class StaState; + +// Normal distribution with std deviation. +class Delay +{ +public: + 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; + bool operator>(const Delay &delay) const; + bool operator>=(const Delay &delay) const; + bool operator<(const Delay &delay) const; + bool operator<=(const Delay &delay) const; + +private: + float mean_; + // Sigma^2 + float sigma2_; +}; + +const Delay delay_zero(0.0); + +void +initDelayConstants(); + +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(); } + +// 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); + +// mean late+/early- sigma +float +delayAsFloat(const Delay &delay, + const EarlyLate *early_late, + float sigma_factor); +float +delaySigma2(const Delay &delay, + const EarlyLate *early_late); +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); +const Delay & +delayInitValue(const MinMax *min_max); +bool +delayIsInitValue(const Delay &delay, + const MinMax *min_max); +bool +fuzzyZero(const Delay &delay); +bool +fuzzyEqual(const Delay &delay1, + const Delay &delay2); +bool +fuzzyLess(const Delay &delay1, + const Delay &delay2); +bool +fuzzyLess(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max); +bool +fuzzyLessEqual(const Delay &delay1, + const Delay &delay2); +bool +fuzzyLessEqual(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max); +bool +fuzzyGreater(const Delay &delay1, + const Delay &delay2); +bool +fuzzyGreaterEqual(const Delay &delay1, + const Delay &delay2); +bool +fuzzyGreaterEqual(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max); +bool +fuzzyGreater(const Delay &delay1, + const Delay &delay2, + const MinMax *min_max); +float +delayRatio(const Delay &delay1, + const Delay &delay2); + +} // namespace +#endif diff --git a/graph/DelayNormal2.cc b/graph/DelayNormal2.cc index ff092c87..b18c470f 100644 --- a/graph/DelayNormal2.cc +++ b/graph/DelayNormal2.cc @@ -25,7 +25,7 @@ #include "Delay.hh" // SSTA compilation. -#if SSTA +#if (SSTA == 2) namespace sta {