diff --git a/CMakeLists.txt b/CMakeLists.txt index 598aa9c9..b47a1bbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.9) -project(STA VERSION 2.0.3) +project(STA VERSION 2.0.4) set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_CXX_STANDARD 11) @@ -422,40 +422,62 @@ set(STA_SWIG_FILES ) ################################################################ +# # Library dependencies +# ################################################################ +# Pthreads set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads) set(HAVE_PTHREADS ${CMAKE_USE_PTHREADS_INIT}) -message(STATUS "Found pthreads: ${HAVE_PTHREADS}") +if (HAVE_PTHREADS) + message(STATUS "Found pthreads") +endif() +# Zlib include(FindZLIB) -if(NOT "$ENV{CUDD}" STREQUAL "") - set(CUDD_INCLUDE $ENV{CUDD}/include) - find_library(CUDD_LIB NAMES cudd PATHS $ENV{CUDD}/lib) - if (CUDD_LIB) - set(CUDD_FOUND TRUE) - message(STATUS "CUDD library: ${CUDD_LIB}") - endif() -else() +################################################################ +# +# Locate CUDD bdd packagte + +# CUDD variable has precidence over environment variable. +if("${CUDD}" STREQUAL "") + set(CUDD $ENV{CUDD}) +endif() + +if("${CUDD}" STREQUAL "") set(CUDD_INCLUDE "") set(CUDD_LIB "") set(CUDD_FOUND FALSE) +else() + set(CUDD_INCLUDE ${CUDD}/include) + find_library(CUDD_LIB NAMES cudd PATHS ${CUDD}/lib) + if (CUDD_LIB) + # CUDD_FOUND referenced by config.h.cmake + set(CUDD_FOUND TRUE) + message(STATUS "CUDD library: ${CUDD_LIB}") + endif() endif() +if("${SSTA}" STREQUAL "") + set(SSTA 0) +endif() +message(STATUS "Enable SSTA: ${SSTA}") + # configure a header file to pass some of the CMake settins -configure_file( - "${STA_HOME}/config.h.cmake" - "${STA_HOME}/config.h" - ) +configure_file(${STA_HOME}/config.h.cmake + ${STA_HOME}/config.h + ) +################################################################ +# # Locate TCL library. # -# Note that the cmakd findTcl module is hopeless for OSX +# Note that the cmake findTcl module is hopeless for OSX # because there doesn't appear to be a way to override # searching OSX system directories before unix directories. @@ -494,7 +516,7 @@ if (NOT TCL_LIB) PATHS ${TCL_LIB_PATHS} ) endif() -endif (NOT TCL_LIB) +endif() message(STATUS "TCL lib: ${TCL_LIB}") get_filename_component(TCL_LIB_DIR "${TCL_LIB}" PATH) @@ -508,10 +530,14 @@ if (NOT TCL_HEADER) PATH_SUFFIXES include include/tcl NO_DEFAULT_PATH ) -endif (NOT TCL_HEADER) +endif() message(STATUS "TCL header: ${TCL_HEADER}") get_filename_component(TCL_HEADER_DIR "${TCL_HEADER}" PATH) +################################################################ +# +# Flex/bison scanner/parsers +# ################################################################ find_package(FLEX) @@ -672,7 +698,7 @@ target_link_libraries(sta ) if (ZLIB_FOUND) target_link_libraries(sta ${ZLIB_LIBRARIES}) -endif(ZLIB_FOUND) +endif() message(STATUS "STA executable: ${STA_HOME}/app/sta") diff --git a/INSTALL b/INSTALL index e072e1db..24ee7769 100644 --- a/INSTALL +++ b/INSTALL @@ -14,32 +14,81 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -Builds are supported by dist tarfiles or from the git repository. -Building from a dist tarfile does not require the GNU Autotools, Bison -or Flex to be installed and is the recommended method unless you are a -developer. +Builds are supported with cmake. Builds with Autotools are supported +for compatibility but are deprecated. -Builds are also supported with cmake described later in this file. -Autotools based builds are currently supported for compatibility but -are deprecated. - -Building from a tarfile ------------------------ +Building with Cmake +------------------- The build dependency versions are show below. Other versions may work, but these are the versions used for development. - from Ubuntu Xcode + from Ubuntu Xcode 18.04.1 10.1 clang 9.1.0 10.0.0 gcc 3.3.2 7.3.0 tcl 8.2 8.6 8.6.6 +swig 1.3.28 3.0.12 3.0.12 +bison 1.35 3.0.4 2.3 +flex 2.5.4 2.6.4 2.5.35 + +Building with cmake requires bison, flex and swig. These packages are optional: libz 1.1.4 1.2.5 1.2.8 cudd 2.4.1 3.0.0 +CUDD is a BDD package that is used to improve conditional timing arc +handling. It is available here: + + https://www.davidkebo.com/source/cudd_versions/cudd-3.0.0.tar.gz + https://sourceforge.net/projects/cudd-mirror/ + +Note that the file hierarchy of the CUDD installation changed with +version 3.0. This build only supports the 3.0 layout but only small +changes to configure.ac are required to support older versions. + +The Zlib library is an optional. If the configure script finds libz, +OpenSTA can read Verilog, SDF, SPF, and SPEF files compressed with +gzip. + +Use the following commands to checkout the git repository build the +OpenSTA library and excutable. + + git clone https://xp-dev.com/git/opensta + cd opensta + mkdir build + cd build + cmake .. + make + +The resulting executable is in app/sta. +The library without a main() procedure is app/libSTA.a. + +Optional cmake variables passed as -D= arguments to cmake +are show below. + + CMAKE_BUILD_TYPE DEBUG|RELEASE + TCL_LIB - path to tcl library + TCL_HEADER - path to tcl.h + CMAKE_INSTALL_PREFIX + +If TCL_LIB is specified the cmake script will attempt to locate the +header from its path. + +The default install directory is /usr/local. +To install in a different directory with cmake use: + + cmake .. -DCMAKE_INSTALL_PREFIX= + +or use the DESTDIR variable with make. + + make DESTDIR= install + +Building from a tarfile +----------------------- + Use the following commands to unpack the dist file and compile it. tar zvfz opensta-.tgz @@ -63,20 +112,6 @@ configure options: --with-cudd=path use Cudd BDD package, defaults to $CUDD --with-visualstudio use Microcruft Visual Studio C++ compiler -CUDD is a BDD package that is used to improve conditional timing arc -handling. It is available here: - - https://www.davidkebo.com/source/cudd_versions/cudd-3.0.0.tar.gz - https://sourceforge.net/projects/cudd-mirror/ - -Note that the file hierarchy of the CUDD installation changed with -version 3.0. This build only supports the 3.0 layout but only small -changes to configure.ac are required to support older versions. - -The Zlib library is an optional. If the configure script finds libz, -OpenSTA can read Verilog, SDF, SPF, and SPEF files compressed with -gzip. - If the configure script fails to find any of the TCL, Zlib or CUDD files, use the --with-include, --with-lib, --with-tcl, --with-cudd options to add directories to search for the files. @@ -86,10 +121,10 @@ are not described above. The default arguments to configure disable shared libraries. To build with shared libraries use the --enable-shared option. -Building from the git repository --------------------------------- +Building with GNU Autotools +--------------------------- -Building from the git repository has the additional build dependencies +Building with GNU Autotools the additional build dependencies shown below. from Ubuntu Xcode @@ -97,15 +132,6 @@ shown below. autoconf 2.53 2.69 2.69 automake 1.6.3 1.15.1 1.16.1 libtool 1.4.2 2.4.6 2.4.6 -swig 1.3.28 3.0.12 3.0.12 -bison 1.35 3.0.4 2.3 -flex 2.5.4 2.6.4 2.5.35 - -These packages are optional: - -gdb 5.3 8.1 -lldb 902.0.79.7 1000.11.38.2 -valgrind 1.9.6 3.13.0 N/A Use the following commands to checkout the git repository and compile it. @@ -116,43 +142,9 @@ it. ./configure [options...] make -Building with Cmake -------------------- - -Building with cmake requires bison and flex. - - git clone https://xp-dev.com/git/opensta - cd opensta - mkdir build - cd build - cmake ../ - make - -The resulting executable is app/sta for compatibility with configure. -The library without main is app/libSTA.a. - -Optional cmake variables passed as -D= arguments to cmake. - - CMAKE_BUILD_TYPE DEBUG|RELEASE - TCL_LIB - path to tcl library - TCL_HEADER - path to tcl.h - TCL_INIT - path to init.tcl - CMAKE_INSTALL_PREFIX - -If TCL_LIB is specified the cmake script will attempt to locate -the header and init files from its path. - -Default install directory is /usr/local. -To install in a different directory with cmake use: - - cmake .. -DCMAKE_INSTALL_PREFIX= - -or use the DESTDIR variable with make. - - make DESTDIR= install - Building on Windoz ------------------ + The Win32 API does not natively support the pthreads API. The pthreads-win32 package is one way to get support for pthreads for 32 bit builds. It is available from www.sourceware.org/pthreads-win32. @@ -169,6 +161,9 @@ tcsh-startup.bat set path=c:\cygwin\bin;%PATH% c:\cygwin\bin\tcsh +cmake is supposedly more compatible with the windoz environment +so you may have better luck wih it. + Configure and build from the shell. Note that tcl and zlib must be built with the Visual C++ compiler to link to the sta libraries. diff --git a/config.h.cmake b/config.h.cmake index a5768558..082defe3 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -11,3 +11,5 @@ #if ${CUDD_FOUND}==TRUE #define CUDD #endif + +#define SSTA ${SSTA} diff --git a/configure.ac b/configure.ac index a9adc7f6..f11b57c3 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,7 @@ # Process this file with autoconf to produce a configure script. -AC_INIT(sta, 2.0.3) +AC_INIT(sta, 2.0.4) AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS(config.h) diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index 337075e0..3ab8edb4 100644 Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ diff --git a/doc/OpenSTA.pdf b/doc/OpenSTA.pdf index 9d33f260..d80c07d5 100644 Binary files a/doc/OpenSTA.pdf and b/doc/OpenSTA.pdf differ diff --git a/parasitics/ConcreteParasitics.cc b/parasitics/ConcreteParasitics.cc index c8453dc8..6db058ba 100644 --- a/parasitics/ConcreteParasitics.cc +++ b/parasitics/ConcreteParasitics.cc @@ -1885,16 +1885,20 @@ ConcreteParasitics::value(const ParasiticDevice *device, return cdevice->value(); } -void -ConcreteParasitics::resistorNodes(const ParasiticDevice *device, - // Return values. - ParasiticNode *&node1, - ParasiticNode *&node2) const +ParasiticNode * +ConcreteParasitics::node1(const ParasiticDevice *device) const { - const ConcreteParasiticResistor *cdevice = - static_cast(device); - node1 = cdevice->node1(); - node2 = cdevice->node2(); + const ConcreteParasiticDevice *cdevice = + static_cast(device); + return cdevice->node1(); +} + +ParasiticNode * +ConcreteParasitics::node2(const ParasiticDevice *device) const +{ + const ConcreteParasiticDevice *cdevice = + static_cast(device); + return cdevice->node2(); } ParasiticNode * diff --git a/parasitics/ConcreteParasitics.hh b/parasitics/ConcreteParasitics.hh index fc2eb94d..1171d00a 100644 --- a/parasitics/ConcreteParasitics.hh +++ b/parasitics/ConcreteParasitics.hh @@ -175,10 +175,8 @@ public: virtual const char *name(const ParasiticDevice *device) const; virtual float value(const ParasiticDevice *device, const ParasiticAnalysisPt *ap) const; - virtual void resistorNodes(const ParasiticDevice *device, - // Return values. - ParasiticNode *&node1, - ParasiticNode *&node2) const; + virtual ParasiticNode *node1(const ParasiticDevice *device) const; + virtual ParasiticNode *node2(const ParasiticDevice *device) const; virtual ParasiticNode *otherNode(const ParasiticDevice *device, ParasiticNode *node) const; diff --git a/parasitics/ConcreteParasiticsPvt.hh b/parasitics/ConcreteParasiticsPvt.hh index 769ff128..7bc2fca7 100644 --- a/parasitics/ConcreteParasiticsPvt.hh +++ b/parasitics/ConcreteParasiticsPvt.hh @@ -299,6 +299,8 @@ public: virtual bool isCouplingCap() const { return false; } const char *name() const { return name_; } float value() const { return value_; } + ConcreteParasiticNode *node1() const { return node_; } + virtual ConcreteParasiticNode *node2() const = 0; virtual ParasiticNode *otherNode(ParasiticNode *node) const = 0; virtual void replaceNode(ConcreteParasiticNode *from_node, ConcreteParasiticNode *to_node) = 0; @@ -319,11 +321,10 @@ public: ConcreteParasiticNode *other_node, float res); virtual bool isResistor() const { return true; } + virtual ConcreteParasiticNode *node2() const { return other_node_; } virtual ParasiticNode *otherNode(ParasiticNode *node) const; virtual void replaceNode(ConcreteParasiticNode *from_node, ConcreteParasiticNode *to_node); - ConcreteParasiticNode *node1() const { return node_; } - ConcreteParasiticNode *node2() const { return other_node_; } private: ConcreteParasiticNode *other_node_; @@ -337,6 +338,7 @@ public: ConcreteParasiticNode *node, float cap); virtual bool isCouplingCap() const { return true; } + virtual ConcreteParasiticNode *node2() const { return NULL; } virtual void replaceNode(ConcreteParasiticNode *from_node, ConcreteParasiticNode *to_node); }; @@ -349,6 +351,7 @@ public: ConcreteParasiticNode *other_node, float cap); virtual bool isCouplingCap() const { return true; } + virtual ConcreteParasiticNode *node2() const { return other_node_; } virtual ParasiticNode *otherNode(ParasiticNode *node) const; virtual void replaceNode(ConcreteParasiticNode *from_node, ConcreteParasiticNode *to_node); diff --git a/parasitics/NullParasitics.cc b/parasitics/NullParasitics.cc index f3c77061..f2151b6d 100644 --- a/parasitics/NullParasitics.cc +++ b/parasitics/NullParasitics.cc @@ -424,12 +424,16 @@ NullParasitics::value(const ParasiticDevice *, return 0.0; } -void -NullParasitics::resistorNodes(const ParasiticDevice *, - // Return values. - ParasiticNode *&, - ParasiticNode *&) const +ParasiticNode * +NullParasitics::node1(const ParasiticDevice *) const { + return NULL; +} + +ParasiticNode * +NullParasitics::node2(const ParasiticDevice *) const +{ + return NULL; } ParasiticNode * diff --git a/parasitics/NullParasitics.hh b/parasitics/NullParasitics.hh index b1767f61..3c4b14ed 100644 --- a/parasitics/NullParasitics.hh +++ b/parasitics/NullParasitics.hh @@ -164,10 +164,8 @@ public: virtual const char *name(const ParasiticDevice *device) const; virtual float value(const ParasiticDevice *device, const ParasiticAnalysisPt *ap) const; - virtual void resistorNodes(const ParasiticDevice *device, - // Return values. - ParasiticNode *&node1, - ParasiticNode *&node2) const; + virtual ParasiticNode *node1(const ParasiticDevice *device) const; + virtual ParasiticNode *node2(const ParasiticDevice *device) const; virtual ParasiticNode *otherNode(const ParasiticDevice *device, ParasiticNode *node) const; // Reduce parasitic network to reduce_to model. diff --git a/parasitics/Parasitics.hh b/parasitics/Parasitics.hh index eba324e4..c9592487 100644 --- a/parasitics/Parasitics.hh +++ b/parasitics/Parasitics.hh @@ -248,10 +248,8 @@ public: // Device "value" (resistance, capacitance). virtual float value(const ParasiticDevice *device, const ParasiticAnalysisPt *ap) const = 0; - virtual void resistorNodes(const ParasiticDevice *device, - // Return values. - ParasiticNode *&node1, - ParasiticNode *&node2) const = 0; + virtual ParasiticNode *node1(const ParasiticDevice *device) const = 0; + virtual ParasiticNode *node2(const ParasiticDevice *device) const = 0; virtual ParasiticNode *otherNode(const ParasiticDevice *device, ParasiticNode *node) const = 0; diff --git a/search/PathGroup.cc b/search/PathGroup.cc index ee0ffd9a..f8761384 100644 --- a/search/PathGroup.cc +++ b/search/PathGroup.cc @@ -498,12 +498,14 @@ exceptionToEmpty(ExceptionTo *to); PathEndSeq * PathGroups::makePathEnds(ExceptionTo *to, + bool unconstrained_paths, const Corner *corner, const MinMaxAll *min_max, bool sort_by_slack) { Stats stats(this->debug()); - makeGroupPathEnds(to, group_count_, endpoint_count_, unique_pins_, corner, min_max); + makeGroupPathEnds(to, group_count_, endpoint_count_, unique_pins_, + corner, min_max); PathEndSeq *path_ends = new PathEndSeq; pushGroupPathEnds(path_ends); @@ -513,7 +515,7 @@ PathGroups::makePathEnds(ExceptionTo *to, path_ends->resize(group_count_); } - if (search_->reportUnconstrainedPaths() + if (unconstrained_paths && path_ends->empty()) // No constrained paths, so report unconstrained paths. pushUnconstrainedPathEnds(path_ends, min_max); diff --git a/search/PathGroup.hh b/search/PathGroup.hh index 50b46551..d9f6c1af 100644 --- a/search/PathGroup.hh +++ b/search/PathGroup.hh @@ -119,6 +119,7 @@ public: // Returned PathEndSeq is owned by the caller. // The PathEnds in the vector are owned by the PathGroups. PathEndSeq *makePathEnds(ExceptionTo *to, + bool unconstrained_paths, const Corner *corner, const MinMaxAll *min_max, bool sort_by_slack); diff --git a/search/Search.cc b/search/Search.cc index f277139d..837e3744 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -228,7 +228,7 @@ void Search::init(StaState *sta) { crpr_path_pruning_enabled_ = true; - report_unconstrained_paths_ = false; + unconstrained_paths_ = false; search_adj_ = new SearchThru(NULL, sta); eval_pred_ = new EvalPred(sta); check_crpr_ = new CheckCrpr(sta); @@ -329,14 +329,6 @@ Search::setCrprpathPruningEnabled(bool enabled) crpr_path_pruning_enabled_ = enabled; } -void -Search::setReportUnconstrainedPaths(bool report) -{ - if (report_unconstrained_paths_ != report) - arrivalsInvalid(); - report_unconstrained_paths_ = report; -} - void Search::deleteTags() { @@ -430,6 +422,7 @@ PathEndSeq * Search::findPathEnds(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, + bool unconstrained, const Corner *corner, const MinMaxAll *min_max, int group_count, @@ -446,6 +439,7 @@ Search::findPathEnds(ExceptionFrom *from, bool clk_gating_setup, bool clk_gating_hold) { + unconstrained_paths_ = unconstrained; // Delete results from last findPathEnds. // Filtered arrivals are deleted by Sta::searchPreamble. deletePathGroups(); @@ -474,7 +468,8 @@ Search::findPathEnds(ExceptionFrom *from, recovery, removal, clk_gating_setup, clk_gating_hold); ensureDownstreamClkPins(); - PathEndSeq *path_ends = path_groups_->makePathEnds(to, corner, min_max, + PathEndSeq *path_ends = path_groups_->makePathEnds(to, unconstrained_paths_, + corner, min_max, sort_by_slack); sdc_->reportClkToClkMaxCycleWarnings(); return path_ends; @@ -1462,7 +1457,7 @@ Search::seedArrival(Vertex *vertex) bool is_reg_clk = vertex->isRegClk(); if (is_reg_clk // Internal roots isolated by disabled pins are seeded with no clock. - || (report_unconstrained_paths_ + || (unconstrained_paths_ && !network_->isTopLevelPort(pin))) { debugPrint1(debug_, "search", 2, "arrival seed unclked root %s\n", network_->pathName(pin)); @@ -3236,7 +3231,7 @@ Search::isEndpoint(Vertex *vertex, || sdc_->isPathDelayInternalEndpoint(pin) || !hasFanout(vertex, pred, graph_) // Unconstrained paths at register clk pins. - || (report_unconstrained_paths_ + || (unconstrained_paths_ && vertex->isRegClk())); } @@ -4026,7 +4021,7 @@ Search::makePathGroups(int group_count, setup, hold, recovery, removal, clk_gating_setup, clk_gating_hold, - report_unconstrained_paths_, + unconstrained_paths_, this); } diff --git a/search/Search.hh b/search/Search.hh index ee0de690..9fd7a114 100644 --- a/search/Search.hh +++ b/search/Search.hh @@ -75,9 +75,7 @@ public: // non-critical paths on intermediate pins may be incorrect. bool crprPathPruningEnabled() const; void setCrprpathPruningEnabled(bool enabled); - // Report unconstrained paths. - bool reportUnconstrainedPaths() const { return report_unconstrained_paths_; } - void setReportUnconstrainedPaths(bool report); + bool unconstrainedPaths() const { return unconstrained_paths_; } // from/thrus/to are owned and deleted by Search. // Use corner NULL to report timing for all corners. // Returned sequence is owned by the caller. @@ -85,6 +83,7 @@ public: PathEndSeq *findPathEnds(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, + bool unconstrained, const Corner *corner, const MinMaxAll *min_max, int group_count, @@ -524,7 +523,8 @@ protected: //////////////////////////////////////////////////////////////// - bool report_unconstrained_paths_; + // findPathEnds arg. + bool unconstrained_paths_; bool have_paths_; // Search predicates. SearchPred *search_adj_; diff --git a/search/Sta.cc b/search/Sta.cc index 6e00bff9..a02a6aa0 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2281,18 +2281,6 @@ Sta::setUseDefaultArrivalClock(bool enable) } } -bool -Sta::reportUnconstrainedPaths() const -{ - return search_->reportUnconstrainedPaths(); -} - -void -Sta::setReportUnconstrainedPaths(bool report) -{ - search_->setReportUnconstrainedPaths(report); -} - bool Sta::propagateAllClocks() const { @@ -2374,6 +2362,7 @@ PathEndSeq * Sta::findPathEnds(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, + bool unconstrained, const Corner *corner, const MinMaxAll *min_max, int group_count, @@ -2391,7 +2380,7 @@ Sta::findPathEnds(ExceptionFrom *from, bool clk_gating_hold) { searchPreamble(); - return search_->findPathEnds(from, thrus, to, + return search_->findPathEnds(from, thrus, to, unconstrained, corner, min_max, group_count, endpoint_count, unique_pins, slack_min, slack_max, sort_by_slack, group_names, @@ -2552,8 +2541,8 @@ PinSet * Sta::findGroupPathPins(const char *group_path_name) { if (!search_->havePathGroups()) { - PathEndSeq *path_ends = findPathEnds(// from, thrus, to - NULL, NULL, NULL, + PathEndSeq *path_ends = findPathEnds(// from, thrus, to, unconstrained + NULL, NULL, NULL, false, // corner, min_max, NULL, MinMaxAll::max(), // group_count, endpoint_count, unique_pins diff --git a/search/Sta.hh b/search/Sta.hh index 7e8a136e..8d6e8f18 100644 --- a/search/Sta.hh +++ b/search/Sta.hh @@ -721,9 +721,6 @@ public: bool no_version); // Remove all delay and slew annotations. void removeDelaySlewAnnotations(); - // TCL variable sta_report_unconstrained_paths. - bool reportUnconstrainedPaths() const; - void setReportUnconstrainedPaths(bool report); // TCL variable sta_crpr_enabled. // Common Reconvergent Clock Removal (CRPR). // Timing check source/target common clock path overlap for search @@ -787,6 +784,7 @@ public: virtual PathEndSeq *findPathEnds(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, + bool unconstrained, // Use corner NULL to report timing // for all corners. const Corner *corner, diff --git a/search/VisitPathEnds.cc b/search/VisitPathEnds.cc index b574b1d1..a1603006 100644 --- a/search/VisitPathEnds.cc +++ b/search/VisitPathEnds.cc @@ -62,7 +62,7 @@ VisitPathEnds::visitPathEnds(Vertex *vertex, bool is_constrained = false; visitClkedPathEnds(pin, vertex, corner, min_max, filtered, visitor, is_constrained); - if (search_->reportUnconstrainedPaths() + if (search_->unconstrainedPaths() && !is_constrained && !vertex->isDisabledConstraint()) visitUnconstrainedPathEnds(pin, vertex, corner, min_max, filtered, diff --git a/search/WritePathSpice.cc b/search/WritePathSpice.cc index f046a659..561e0265 100644 --- a/search/WritePathSpice.cc +++ b/search/WritePathSpice.cc @@ -279,7 +279,9 @@ WritePathSpice::maxTime() Path *input_path = stageDrvrPath(input_stage); auto input_slew = input_path->slew(this); auto end_slew = path_->slew(this); - auto max_time = (input_slew + path_->arrival(this) + end_slew * 2) * 1.5; + auto max_time = delayAsFloat(input_slew + + path_->arrival(this) + + end_slew * 2) * 1.5; return max_time; } @@ -348,7 +350,7 @@ WritePathSpice::writeInputSource() volt1 = gnd_voltage_; } Path *input_path = stageDrvrPath(input_stage); - auto input_slew = input_path->slew(this); + auto input_slew = delayAsFloat(input_path->slew(this)); if (input_slew == 0.0) input_slew = maxTime() / 1e+3; // Arbitrary offset. @@ -732,8 +734,8 @@ WritePathSpice::writeStageParasitics(Stage stage) auto device = device_iter.next(); auto resistance = parasitics_->value(device, parasitic_ap); if (parasitics_->isResistor(device)) { - ParasiticNode *node1, *node2; - parasitics_->resistorNodes(device, node1, node2); + ParasiticNode *node1 = parasitics_->node1(device); + ParasiticNode *node2 = parasitics_->node2(device); streamPrint(spice_stream_, "R%d %s %s %.3e\n", resistor_index, nodeName(node1), @@ -742,6 +744,14 @@ WritePathSpice::writeStageParasitics(Stage stage) resistor_index++; } else if (parasitics_->isCouplingCap(device)) { + // Ground coupling caps for now. + ParasiticNode *node1 = parasitics_->node1(device); + auto cap = parasitics_->value(device, parasitic_ap); + streamPrint(spice_stream_, "C%d %s 0 %.3e\n", + cap_index, + nodeName(node1), + cap); + cap_index++; } } ParasiticNodeSet::Iterator node_iter(nodes); diff --git a/tcl/Cmds.tcl b/tcl/Cmds.tcl index f89727c5..5c412bc7 100644 --- a/tcl/Cmds.tcl +++ b/tcl/Cmds.tcl @@ -1930,7 +1930,7 @@ proc write_path_spice { args } { sta_error "No -path_args specified.\n" } set path_args $keys(-path_args) - set path_ends [eval [concat get_timing_paths $path_args]] + set path_ends [eval [concat find_timing_paths $path_args]] if { $path_ends == {} } { sta_error "No paths found for -path_args $path_args.\n" } else { diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index 9ef71520..1909f781 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -143,6 +143,7 @@ define_sta_cmd_args "find_timing_paths" \ [-through through_list|-rise_through through_list|-fall_through through_list]\ [-to to_list|-rise_to to_list|-fall_to to_list]\ [-path_delay min|min_rise|min_fall|max|max_rise|max_fall|min_max]\ + [-unconstrained] [-corner corner_name]\ [-group_count path_count] \ [-endpoint_count path_count]\ @@ -158,13 +159,14 @@ proc find_timing_paths { args } { } proc find_timing_paths_cmd { cmd args_var } { + global sta_report_unconstrained_paths upvar 1 $args_var args - parse_key_args "find_timing_paths" args \ + parse_key_args $cmd args \ keys {-from -rise_from -fall_from -to -rise_to -fall_to \ -path_delay -corner -group_count -endpoint_count \ -slack_max -slack_min -path_group} \ - flags {-sort_by_slack -unique_paths_to_endpoint} 0 + flags {-unconstrained -sort_by_slack -unique_paths_to_endpoint} 0 set min_max "max" set end_tr "rise_fall" @@ -185,7 +187,7 @@ proc find_timing_paths_cmd { cmd args_var } { } elseif { $mm_key == "min" || $mm_key == "max" || $mm_key == "min_max" } { set min_max $mm_key } else { - sta_error "report_checks -path_delay must be min, min_rise, min_fall, max, max_rise, max_fall or min_max." + sta_error "$cmd -path_delay must be min, min_rise, min_fall, max, max_rise, max_fall or min_max." } } @@ -200,6 +202,14 @@ proc find_timing_paths_cmd { cmd args_var } { check_for_key_args $cmd args + if { [info exists flags(-unconstrained)] } { + set unconstrained 1 + } elseif { [info exists sta_report_unconstrained_paths] } { + set unconstrained $sta_report_unconstrained_paths + } else { + set unconstrained 0 + } + set corner [parse_corner_or_all keys] set endpoint_count 1 @@ -251,7 +261,8 @@ proc find_timing_paths_cmd { cmd args_var } { } } - set path_ends [find_path_ends $from $thrus $to $corner $min_max \ + set path_ends [find_path_ends $from $thrus $to $unconstrained \ + $corner $min_max \ $group_count $endpoint_count $unique_pins \ $slack_min $slack_max \ $sort_by_slack $groups \ @@ -265,6 +276,7 @@ define_sta_cmd_args "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]\ [-corner corner_name]\ [-group_count path_count] \ @@ -286,11 +298,7 @@ proc_redirect report_checks { parse_report_path_options "report_checks" args "full" 0 set path_ends [find_timing_paths_cmd "report_checks" args] if { $path_ends == {} } { - if { $sta_report_unconstrained_paths } { - puts "No paths." - } else { - puts "No constrained paths." - } + puts "No paths found." } else { report_path_ends $path_ends } diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index f9a9b43f..945064ea 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -2123,18 +2123,6 @@ net_is_constrained(Net *net) return Sta::sta()->sdc()->isConstrained(net); } -bool -report_unconstrained_paths() -{ - return Sta::sta()->reportUnconstrainedPaths(); -} - -void -set_report_unconstrained_paths(bool report) -{ - Sta::sta()->setReportUnconstrainedPaths(report); -} - bool clk_thru_tristate_enabled() { @@ -4104,6 +4092,7 @@ PathEndSeq * find_path_ends(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, + bool unconstrained, Corner *corner, const MinMaxAll *delay_min_max, int group_count, @@ -4122,7 +4111,7 @@ find_path_ends(ExceptionFrom *from, { cmdLinkedNetwork(); Sta *sta = Sta::sta(); - PathEndSeq *ends = sta->findPathEnds(from, thrus, to, + PathEndSeq *ends = sta->findPathEnds(from, thrus, to, unconstrained, corner, delay_min_max, group_count, endpoint_count, unique_pins, slack_min, slack_max, @@ -4422,6 +4411,17 @@ worst_slack(const MinMax *min_max) return worst_slack; } +Vertex * +worst_slack_vertex(const MinMax *min_max) +{ + cmdLinkedNetwork(); + Sta *sta = Sta::sta(); + Slack worst_slack; + Vertex *worst_vertex; + sta->worstSlack(min_max, worst_slack, worst_vertex); + return worst_vertex;; +} + Slack worst_slack_corner(const Corner *corner, const MinMax *min_max) @@ -6051,6 +6051,22 @@ tag() return self->tag(sta)->asString(sta); } +// mea_opt3 +TmpPinSeq * +pins() +{ + Sta *sta = Sta::sta(); + PinSeq *pins = new PinSeq; + PathRef path1(self); + while (!path1.isNull()) { + pins->push_back(path1.vertex(sta)->pin()); + PathRef prev_path; + path1.prevPath(sta, prev_path); + path1.init(prev_path); + } + return pins; +} + } %extend VertexPathIterator { diff --git a/tcl/Variables.tcl b/tcl/Variables.tcl index da0331bf..ea07f296 100644 --- a/tcl/Variables.tcl +++ b/tcl/Variables.tcl @@ -160,14 +160,6 @@ proc trace_propagate_gated_clock_enable { name1 name2 op } { propagate_gated_clock_enable set_propagate_gated_clock_enable } -trace variable ::sta_report_unconstrained_paths "rw" \ - sta::trace_report_unconstrained_paths - -proc trace_report_unconstrained_paths { ignore1 ignore2 op } { - trace_boolean_var $op ::sta_report_unconstrained_paths \ - report_unconstrained_paths set_report_unconstrained_paths -} - ################################################################ proc trace_boolean_var { op var_name get_proc set_proc } { diff --git a/verilog/VerilogParse.yy b/verilog/VerilogParse.yy index d0c5e8ee..4c9afc50 100644 --- a/verilog/VerilogParse.yy +++ b/verilog/VerilogParse.yy @@ -171,6 +171,7 @@ port_dcl_type: | INOUT REG { $$ = sta::PortDirection::bidirect(); } | INOUT WIRE { $$ = sta::PortDirection::bidirect(); } | OUTPUT { $$ = sta::PortDirection::output(); } +| OUTPUT WIRE { $$ = sta::PortDirection::output(); } | OUTPUT REG { $$ = sta::PortDirection::output(); } ;