sync
This commit is contained in:
parent
de5c3a6400
commit
3d8d088b89
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required (VERSION 3.9)
|
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_VERBOSE_MAKEFILE ON)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
@ -422,40 +422,62 @@ set(STA_SWIG_FILES
|
||||||
)
|
)
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
#
|
||||||
# Library dependencies
|
# Library dependencies
|
||||||
|
#
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
|
# Pthreads
|
||||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
set(HAVE_PTHREADS ${CMAKE_USE_PTHREADS_INIT})
|
set(HAVE_PTHREADS ${CMAKE_USE_PTHREADS_INIT})
|
||||||
message(STATUS "Found pthreads: ${HAVE_PTHREADS}")
|
if (HAVE_PTHREADS)
|
||||||
|
message(STATUS "Found pthreads")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Zlib
|
||||||
include(FindZLIB)
|
include(FindZLIB)
|
||||||
|
|
||||||
if(NOT "$ENV{CUDD}" STREQUAL "")
|
################################################################
|
||||||
set(CUDD_INCLUDE $ENV{CUDD}/include)
|
#
|
||||||
find_library(CUDD_LIB NAMES cudd PATHS $ENV{CUDD}/lib)
|
# Locate CUDD bdd packagte
|
||||||
if (CUDD_LIB)
|
|
||||||
set(CUDD_FOUND TRUE)
|
# CUDD variable has precidence over environment variable.
|
||||||
message(STATUS "CUDD library: ${CUDD_LIB}")
|
if("${CUDD}" STREQUAL "")
|
||||||
endif()
|
set(CUDD $ENV{CUDD})
|
||||||
else()
|
endif()
|
||||||
|
|
||||||
|
if("${CUDD}" STREQUAL "")
|
||||||
set(CUDD_INCLUDE "")
|
set(CUDD_INCLUDE "")
|
||||||
set(CUDD_LIB "")
|
set(CUDD_LIB "")
|
||||||
set(CUDD_FOUND FALSE)
|
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()
|
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 a header file to pass some of the CMake settins
|
||||||
configure_file(
|
configure_file(${STA_HOME}/config.h.cmake
|
||||||
"${STA_HOME}/config.h.cmake"
|
${STA_HOME}/config.h
|
||||||
"${STA_HOME}/config.h"
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
#
|
||||||
# Locate TCL library.
|
# 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
|
# because there doesn't appear to be a way to override
|
||||||
# searching OSX system directories before unix directories.
|
# searching OSX system directories before unix directories.
|
||||||
|
|
||||||
|
|
@ -494,7 +516,7 @@ if (NOT TCL_LIB)
|
||||||
PATHS ${TCL_LIB_PATHS}
|
PATHS ${TCL_LIB_PATHS}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif (NOT TCL_LIB)
|
endif()
|
||||||
message(STATUS "TCL lib: ${TCL_LIB}")
|
message(STATUS "TCL lib: ${TCL_LIB}")
|
||||||
|
|
||||||
get_filename_component(TCL_LIB_DIR "${TCL_LIB}" PATH)
|
get_filename_component(TCL_LIB_DIR "${TCL_LIB}" PATH)
|
||||||
|
|
@ -508,10 +530,14 @@ if (NOT TCL_HEADER)
|
||||||
PATH_SUFFIXES include include/tcl
|
PATH_SUFFIXES include include/tcl
|
||||||
NO_DEFAULT_PATH
|
NO_DEFAULT_PATH
|
||||||
)
|
)
|
||||||
endif (NOT TCL_HEADER)
|
endif()
|
||||||
message(STATUS "TCL header: ${TCL_HEADER}")
|
message(STATUS "TCL header: ${TCL_HEADER}")
|
||||||
get_filename_component(TCL_HEADER_DIR "${TCL_HEADER}" PATH)
|
get_filename_component(TCL_HEADER_DIR "${TCL_HEADER}" PATH)
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
#
|
||||||
|
# Flex/bison scanner/parsers
|
||||||
|
#
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
find_package(FLEX)
|
find_package(FLEX)
|
||||||
|
|
@ -672,7 +698,7 @@ target_link_libraries(sta
|
||||||
)
|
)
|
||||||
if (ZLIB_FOUND)
|
if (ZLIB_FOUND)
|
||||||
target_link_libraries(sta ${ZLIB_LIBRARIES})
|
target_link_libraries(sta ${ZLIB_LIBRARIES})
|
||||||
endif(ZLIB_FOUND)
|
endif()
|
||||||
|
|
||||||
message(STATUS "STA executable: ${STA_HOME}/app/sta")
|
message(STATUS "STA executable: ${STA_HOME}/app/sta")
|
||||||
|
|
||||||
|
|
|
||||||
139
INSTALL
139
INSTALL
|
|
@ -14,32 +14,81 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Builds are supported by dist tarfiles or from the git repository.
|
Builds are supported with cmake. Builds with Autotools are supported
|
||||||
Building from a dist tarfile does not require the GNU Autotools, Bison
|
for compatibility but are deprecated.
|
||||||
or Flex to be installed and is the recommended method unless you are a
|
|
||||||
developer.
|
|
||||||
|
|
||||||
Builds are also supported with cmake described later in this file.
|
Building with Cmake
|
||||||
Autotools based builds are currently supported for compatibility but
|
-------------------
|
||||||
are deprecated.
|
|
||||||
|
|
||||||
Building from a tarfile
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
The build dependency versions are show below. Other versions may
|
The build dependency versions are show below. Other versions may
|
||||||
work, but these are the versions used for development.
|
work, but these are the versions used for development.
|
||||||
|
|
||||||
from Ubuntu Xcode
|
from Ubuntu Xcode
|
||||||
18.04.1 10.1
|
18.04.1 10.1
|
||||||
clang 9.1.0 10.0.0
|
clang 9.1.0 10.0.0
|
||||||
gcc 3.3.2 7.3.0
|
gcc 3.3.2 7.3.0
|
||||||
tcl 8.2 8.6 8.6.6
|
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:
|
These packages are optional:
|
||||||
|
|
||||||
libz 1.1.4 1.2.5 1.2.8
|
libz 1.1.4 1.2.5 1.2.8
|
||||||
cudd 2.4.1 3.0.0
|
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<var>=<value> 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=<prefix_path>
|
||||||
|
|
||||||
|
or use the DESTDIR variable with make.
|
||||||
|
|
||||||
|
make DESTDIR=<prefix_path> install
|
||||||
|
|
||||||
|
Building from a tarfile
|
||||||
|
-----------------------
|
||||||
|
|
||||||
Use the following commands to unpack the dist file and compile it.
|
Use the following commands to unpack the dist file and compile it.
|
||||||
|
|
||||||
tar zvfz opensta-<version>.tgz
|
tar zvfz opensta-<version>.tgz
|
||||||
|
|
@ -63,20 +112,6 @@ configure options:
|
||||||
--with-cudd=path use Cudd BDD package, defaults to $CUDD
|
--with-cudd=path use Cudd BDD package, defaults to $CUDD
|
||||||
--with-visualstudio use Microcruft Visual Studio C++ compiler
|
--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
|
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
|
files, use the --with-include, --with-lib, --with-tcl, --with-cudd
|
||||||
options to add directories to search for the files.
|
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
|
shared libraries. To build with shared libraries use the
|
||||||
--enable-shared option.
|
--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.
|
shown below.
|
||||||
|
|
||||||
from Ubuntu Xcode
|
from Ubuntu Xcode
|
||||||
|
|
@ -97,15 +132,6 @@ shown below.
|
||||||
autoconf 2.53 2.69 2.69
|
autoconf 2.53 2.69 2.69
|
||||||
automake 1.6.3 1.15.1 1.16.1
|
automake 1.6.3 1.15.1 1.16.1
|
||||||
libtool 1.4.2 2.4.6 2.4.6
|
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
|
Use the following commands to checkout the git repository and compile
|
||||||
it.
|
it.
|
||||||
|
|
@ -116,43 +142,9 @@ it.
|
||||||
./configure [options...]
|
./configure [options...]
|
||||||
make
|
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<var>=<value> 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=<prefix_path>
|
|
||||||
|
|
||||||
or use the DESTDIR variable with make.
|
|
||||||
|
|
||||||
make DESTDIR=<prefix_path> install
|
|
||||||
|
|
||||||
Building on Windoz
|
Building on Windoz
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
The Win32 API does not natively support the pthreads API. The
|
The Win32 API does not natively support the pthreads API. The
|
||||||
pthreads-win32 package is one way to get support for pthreads for 32
|
pthreads-win32 package is one way to get support for pthreads for 32
|
||||||
bit builds. It is available from www.sourceware.org/pthreads-win32.
|
bit builds. It is available from www.sourceware.org/pthreads-win32.
|
||||||
|
|
@ -169,6 +161,9 @@ tcsh-startup.bat
|
||||||
set path=c:\cygwin\bin;%PATH%
|
set path=c:\cygwin\bin;%PATH%
|
||||||
c:\cygwin\bin\tcsh
|
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
|
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.
|
built with the Visual C++ compiler to link to the sta libraries.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,5 @@
|
||||||
#if ${CUDD_FOUND}==TRUE
|
#if ${CUDD_FOUND}==TRUE
|
||||||
#define CUDD
|
#define CUDD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SSTA ${SSTA}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
# Process this file with autoconf to produce a configure script.
|
# 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
|
AM_INIT_AUTOMAKE
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_HEADERS(config.h)
|
AC_CONFIG_HEADERS(config.h)
|
||||||
|
|
|
||||||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -1885,16 +1885,20 @@ ConcreteParasitics::value(const ParasiticDevice *device,
|
||||||
return cdevice->value();
|
return cdevice->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
ParasiticNode *
|
||||||
ConcreteParasitics::resistorNodes(const ParasiticDevice *device,
|
ConcreteParasitics::node1(const ParasiticDevice *device) const
|
||||||
// Return values.
|
|
||||||
ParasiticNode *&node1,
|
|
||||||
ParasiticNode *&node2) const
|
|
||||||
{
|
{
|
||||||
const ConcreteParasiticResistor *cdevice =
|
const ConcreteParasiticDevice *cdevice =
|
||||||
static_cast<const ConcreteParasiticResistor*>(device);
|
static_cast<const ConcreteParasiticDevice*>(device);
|
||||||
node1 = cdevice->node1();
|
return cdevice->node1();
|
||||||
node2 = cdevice->node2();
|
}
|
||||||
|
|
||||||
|
ParasiticNode *
|
||||||
|
ConcreteParasitics::node2(const ParasiticDevice *device) const
|
||||||
|
{
|
||||||
|
const ConcreteParasiticDevice *cdevice =
|
||||||
|
static_cast<const ConcreteParasiticDevice*>(device);
|
||||||
|
return cdevice->node2();
|
||||||
}
|
}
|
||||||
|
|
||||||
ParasiticNode *
|
ParasiticNode *
|
||||||
|
|
|
||||||
|
|
@ -175,10 +175,8 @@ public:
|
||||||
virtual const char *name(const ParasiticDevice *device) const;
|
virtual const char *name(const ParasiticDevice *device) const;
|
||||||
virtual float value(const ParasiticDevice *device,
|
virtual float value(const ParasiticDevice *device,
|
||||||
const ParasiticAnalysisPt *ap) const;
|
const ParasiticAnalysisPt *ap) const;
|
||||||
virtual void resistorNodes(const ParasiticDevice *device,
|
virtual ParasiticNode *node1(const ParasiticDevice *device) const;
|
||||||
// Return values.
|
virtual ParasiticNode *node2(const ParasiticDevice *device) const;
|
||||||
ParasiticNode *&node1,
|
|
||||||
ParasiticNode *&node2) const;
|
|
||||||
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
||||||
ParasiticNode *node) const;
|
ParasiticNode *node) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -299,6 +299,8 @@ public:
|
||||||
virtual bool isCouplingCap() const { return false; }
|
virtual bool isCouplingCap() const { return false; }
|
||||||
const char *name() const { return name_; }
|
const char *name() const { return name_; }
|
||||||
float value() const { return value_; }
|
float value() const { return value_; }
|
||||||
|
ConcreteParasiticNode *node1() const { return node_; }
|
||||||
|
virtual ConcreteParasiticNode *node2() const = 0;
|
||||||
virtual ParasiticNode *otherNode(ParasiticNode *node) const = 0;
|
virtual ParasiticNode *otherNode(ParasiticNode *node) const = 0;
|
||||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||||
ConcreteParasiticNode *to_node) = 0;
|
ConcreteParasiticNode *to_node) = 0;
|
||||||
|
|
@ -319,11 +321,10 @@ public:
|
||||||
ConcreteParasiticNode *other_node,
|
ConcreteParasiticNode *other_node,
|
||||||
float res);
|
float res);
|
||||||
virtual bool isResistor() const { return true; }
|
virtual bool isResistor() const { return true; }
|
||||||
|
virtual ConcreteParasiticNode *node2() const { return other_node_; }
|
||||||
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
|
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
|
||||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||||
ConcreteParasiticNode *to_node);
|
ConcreteParasiticNode *to_node);
|
||||||
ConcreteParasiticNode *node1() const { return node_; }
|
|
||||||
ConcreteParasiticNode *node2() const { return other_node_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteParasiticNode *other_node_;
|
ConcreteParasiticNode *other_node_;
|
||||||
|
|
@ -337,6 +338,7 @@ public:
|
||||||
ConcreteParasiticNode *node,
|
ConcreteParasiticNode *node,
|
||||||
float cap);
|
float cap);
|
||||||
virtual bool isCouplingCap() const { return true; }
|
virtual bool isCouplingCap() const { return true; }
|
||||||
|
virtual ConcreteParasiticNode *node2() const { return NULL; }
|
||||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||||
ConcreteParasiticNode *to_node);
|
ConcreteParasiticNode *to_node);
|
||||||
};
|
};
|
||||||
|
|
@ -349,6 +351,7 @@ public:
|
||||||
ConcreteParasiticNode *other_node,
|
ConcreteParasiticNode *other_node,
|
||||||
float cap);
|
float cap);
|
||||||
virtual bool isCouplingCap() const { return true; }
|
virtual bool isCouplingCap() const { return true; }
|
||||||
|
virtual ConcreteParasiticNode *node2() const { return other_node_; }
|
||||||
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
|
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
|
||||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||||
ConcreteParasiticNode *to_node);
|
ConcreteParasiticNode *to_node);
|
||||||
|
|
|
||||||
|
|
@ -424,12 +424,16 @@ NullParasitics::value(const ParasiticDevice *,
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
ParasiticNode *
|
||||||
NullParasitics::resistorNodes(const ParasiticDevice *,
|
NullParasitics::node1(const ParasiticDevice *) const
|
||||||
// Return values.
|
|
||||||
ParasiticNode *&,
|
|
||||||
ParasiticNode *&) const
|
|
||||||
{
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParasiticNode *
|
||||||
|
NullParasitics::node2(const ParasiticDevice *) const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParasiticNode *
|
ParasiticNode *
|
||||||
|
|
|
||||||
|
|
@ -164,10 +164,8 @@ public:
|
||||||
virtual const char *name(const ParasiticDevice *device) const;
|
virtual const char *name(const ParasiticDevice *device) const;
|
||||||
virtual float value(const ParasiticDevice *device,
|
virtual float value(const ParasiticDevice *device,
|
||||||
const ParasiticAnalysisPt *ap) const;
|
const ParasiticAnalysisPt *ap) const;
|
||||||
virtual void resistorNodes(const ParasiticDevice *device,
|
virtual ParasiticNode *node1(const ParasiticDevice *device) const;
|
||||||
// Return values.
|
virtual ParasiticNode *node2(const ParasiticDevice *device) const;
|
||||||
ParasiticNode *&node1,
|
|
||||||
ParasiticNode *&node2) const;
|
|
||||||
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
||||||
ParasiticNode *node) const;
|
ParasiticNode *node) const;
|
||||||
// Reduce parasitic network to reduce_to model.
|
// Reduce parasitic network to reduce_to model.
|
||||||
|
|
|
||||||
|
|
@ -248,10 +248,8 @@ public:
|
||||||
// Device "value" (resistance, capacitance).
|
// Device "value" (resistance, capacitance).
|
||||||
virtual float value(const ParasiticDevice *device,
|
virtual float value(const ParasiticDevice *device,
|
||||||
const ParasiticAnalysisPt *ap) const = 0;
|
const ParasiticAnalysisPt *ap) const = 0;
|
||||||
virtual void resistorNodes(const ParasiticDevice *device,
|
virtual ParasiticNode *node1(const ParasiticDevice *device) const = 0;
|
||||||
// Return values.
|
virtual ParasiticNode *node2(const ParasiticDevice *device) const = 0;
|
||||||
ParasiticNode *&node1,
|
|
||||||
ParasiticNode *&node2) const = 0;
|
|
||||||
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
||||||
ParasiticNode *node) const = 0;
|
ParasiticNode *node) const = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -498,12 +498,14 @@ exceptionToEmpty(ExceptionTo *to);
|
||||||
|
|
||||||
PathEndSeq *
|
PathEndSeq *
|
||||||
PathGroups::makePathEnds(ExceptionTo *to,
|
PathGroups::makePathEnds(ExceptionTo *to,
|
||||||
|
bool unconstrained_paths,
|
||||||
const Corner *corner,
|
const Corner *corner,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
bool sort_by_slack)
|
bool sort_by_slack)
|
||||||
{
|
{
|
||||||
Stats stats(this->debug());
|
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;
|
PathEndSeq *path_ends = new PathEndSeq;
|
||||||
pushGroupPathEnds(path_ends);
|
pushGroupPathEnds(path_ends);
|
||||||
|
|
@ -513,7 +515,7 @@ PathGroups::makePathEnds(ExceptionTo *to,
|
||||||
path_ends->resize(group_count_);
|
path_ends->resize(group_count_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (search_->reportUnconstrainedPaths()
|
if (unconstrained_paths
|
||||||
&& path_ends->empty())
|
&& path_ends->empty())
|
||||||
// No constrained paths, so report unconstrained paths.
|
// No constrained paths, so report unconstrained paths.
|
||||||
pushUnconstrainedPathEnds(path_ends, min_max);
|
pushUnconstrainedPathEnds(path_ends, min_max);
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ public:
|
||||||
// Returned PathEndSeq is owned by the caller.
|
// Returned PathEndSeq is owned by the caller.
|
||||||
// The PathEnds in the vector are owned by the PathGroups.
|
// The PathEnds in the vector are owned by the PathGroups.
|
||||||
PathEndSeq *makePathEnds(ExceptionTo *to,
|
PathEndSeq *makePathEnds(ExceptionTo *to,
|
||||||
|
bool unconstrained_paths,
|
||||||
const Corner *corner,
|
const Corner *corner,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
bool sort_by_slack);
|
bool sort_by_slack);
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ void
|
||||||
Search::init(StaState *sta)
|
Search::init(StaState *sta)
|
||||||
{
|
{
|
||||||
crpr_path_pruning_enabled_ = true;
|
crpr_path_pruning_enabled_ = true;
|
||||||
report_unconstrained_paths_ = false;
|
unconstrained_paths_ = false;
|
||||||
search_adj_ = new SearchThru(NULL, sta);
|
search_adj_ = new SearchThru(NULL, sta);
|
||||||
eval_pred_ = new EvalPred(sta);
|
eval_pred_ = new EvalPred(sta);
|
||||||
check_crpr_ = new CheckCrpr(sta);
|
check_crpr_ = new CheckCrpr(sta);
|
||||||
|
|
@ -329,14 +329,6 @@ Search::setCrprpathPruningEnabled(bool enabled)
|
||||||
crpr_path_pruning_enabled_ = enabled;
|
crpr_path_pruning_enabled_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Search::setReportUnconstrainedPaths(bool report)
|
|
||||||
{
|
|
||||||
if (report_unconstrained_paths_ != report)
|
|
||||||
arrivalsInvalid();
|
|
||||||
report_unconstrained_paths_ = report;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Search::deleteTags()
|
Search::deleteTags()
|
||||||
{
|
{
|
||||||
|
|
@ -430,6 +422,7 @@ PathEndSeq *
|
||||||
Search::findPathEnds(ExceptionFrom *from,
|
Search::findPathEnds(ExceptionFrom *from,
|
||||||
ExceptionThruSeq *thrus,
|
ExceptionThruSeq *thrus,
|
||||||
ExceptionTo *to,
|
ExceptionTo *to,
|
||||||
|
bool unconstrained,
|
||||||
const Corner *corner,
|
const Corner *corner,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
int group_count,
|
int group_count,
|
||||||
|
|
@ -446,6 +439,7 @@ Search::findPathEnds(ExceptionFrom *from,
|
||||||
bool clk_gating_setup,
|
bool clk_gating_setup,
|
||||||
bool clk_gating_hold)
|
bool clk_gating_hold)
|
||||||
{
|
{
|
||||||
|
unconstrained_paths_ = unconstrained;
|
||||||
// Delete results from last findPathEnds.
|
// Delete results from last findPathEnds.
|
||||||
// Filtered arrivals are deleted by Sta::searchPreamble.
|
// Filtered arrivals are deleted by Sta::searchPreamble.
|
||||||
deletePathGroups();
|
deletePathGroups();
|
||||||
|
|
@ -474,7 +468,8 @@ Search::findPathEnds(ExceptionFrom *from,
|
||||||
recovery, removal,
|
recovery, removal,
|
||||||
clk_gating_setup, clk_gating_hold);
|
clk_gating_setup, clk_gating_hold);
|
||||||
ensureDownstreamClkPins();
|
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);
|
sort_by_slack);
|
||||||
sdc_->reportClkToClkMaxCycleWarnings();
|
sdc_->reportClkToClkMaxCycleWarnings();
|
||||||
return path_ends;
|
return path_ends;
|
||||||
|
|
@ -1462,7 +1457,7 @@ Search::seedArrival(Vertex *vertex)
|
||||||
bool is_reg_clk = vertex->isRegClk();
|
bool is_reg_clk = vertex->isRegClk();
|
||||||
if (is_reg_clk
|
if (is_reg_clk
|
||||||
// Internal roots isolated by disabled pins are seeded with no clock.
|
// Internal roots isolated by disabled pins are seeded with no clock.
|
||||||
|| (report_unconstrained_paths_
|
|| (unconstrained_paths_
|
||||||
&& !network_->isTopLevelPort(pin))) {
|
&& !network_->isTopLevelPort(pin))) {
|
||||||
debugPrint1(debug_, "search", 2, "arrival seed unclked root %s\n",
|
debugPrint1(debug_, "search", 2, "arrival seed unclked root %s\n",
|
||||||
network_->pathName(pin));
|
network_->pathName(pin));
|
||||||
|
|
@ -3236,7 +3231,7 @@ Search::isEndpoint(Vertex *vertex,
|
||||||
|| sdc_->isPathDelayInternalEndpoint(pin)
|
|| sdc_->isPathDelayInternalEndpoint(pin)
|
||||||
|| !hasFanout(vertex, pred, graph_)
|
|| !hasFanout(vertex, pred, graph_)
|
||||||
// Unconstrained paths at register clk pins.
|
// Unconstrained paths at register clk pins.
|
||||||
|| (report_unconstrained_paths_
|
|| (unconstrained_paths_
|
||||||
&& vertex->isRegClk()));
|
&& vertex->isRegClk()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4026,7 +4021,7 @@ Search::makePathGroups(int group_count,
|
||||||
setup, hold,
|
setup, hold,
|
||||||
recovery, removal,
|
recovery, removal,
|
||||||
clk_gating_setup, clk_gating_hold,
|
clk_gating_setup, clk_gating_hold,
|
||||||
report_unconstrained_paths_,
|
unconstrained_paths_,
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,9 +75,7 @@ public:
|
||||||
// non-critical paths on intermediate pins may be incorrect.
|
// non-critical paths on intermediate pins may be incorrect.
|
||||||
bool crprPathPruningEnabled() const;
|
bool crprPathPruningEnabled() const;
|
||||||
void setCrprpathPruningEnabled(bool enabled);
|
void setCrprpathPruningEnabled(bool enabled);
|
||||||
// Report unconstrained paths.
|
bool unconstrainedPaths() const { return unconstrained_paths_; }
|
||||||
bool reportUnconstrainedPaths() const { return report_unconstrained_paths_; }
|
|
||||||
void setReportUnconstrainedPaths(bool report);
|
|
||||||
// from/thrus/to are owned and deleted by Search.
|
// from/thrus/to are owned and deleted by Search.
|
||||||
// Use corner NULL to report timing for all corners.
|
// Use corner NULL to report timing for all corners.
|
||||||
// Returned sequence is owned by the caller.
|
// Returned sequence is owned by the caller.
|
||||||
|
|
@ -85,6 +83,7 @@ public:
|
||||||
PathEndSeq *findPathEnds(ExceptionFrom *from,
|
PathEndSeq *findPathEnds(ExceptionFrom *from,
|
||||||
ExceptionThruSeq *thrus,
|
ExceptionThruSeq *thrus,
|
||||||
ExceptionTo *to,
|
ExceptionTo *to,
|
||||||
|
bool unconstrained,
|
||||||
const Corner *corner,
|
const Corner *corner,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
int group_count,
|
int group_count,
|
||||||
|
|
@ -524,7 +523,8 @@ protected:
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool report_unconstrained_paths_;
|
// findPathEnds arg.
|
||||||
|
bool unconstrained_paths_;
|
||||||
bool have_paths_;
|
bool have_paths_;
|
||||||
// Search predicates.
|
// Search predicates.
|
||||||
SearchPred *search_adj_;
|
SearchPred *search_adj_;
|
||||||
|
|
|
||||||
|
|
@ -2281,18 +2281,6 @@ Sta::setUseDefaultArrivalClock(bool enable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Sta::reportUnconstrainedPaths() const
|
|
||||||
{
|
|
||||||
return search_->reportUnconstrainedPaths();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Sta::setReportUnconstrainedPaths(bool report)
|
|
||||||
{
|
|
||||||
search_->setReportUnconstrainedPaths(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Sta::propagateAllClocks() const
|
Sta::propagateAllClocks() const
|
||||||
{
|
{
|
||||||
|
|
@ -2374,6 +2362,7 @@ PathEndSeq *
|
||||||
Sta::findPathEnds(ExceptionFrom *from,
|
Sta::findPathEnds(ExceptionFrom *from,
|
||||||
ExceptionThruSeq *thrus,
|
ExceptionThruSeq *thrus,
|
||||||
ExceptionTo *to,
|
ExceptionTo *to,
|
||||||
|
bool unconstrained,
|
||||||
const Corner *corner,
|
const Corner *corner,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
int group_count,
|
int group_count,
|
||||||
|
|
@ -2391,7 +2380,7 @@ Sta::findPathEnds(ExceptionFrom *from,
|
||||||
bool clk_gating_hold)
|
bool clk_gating_hold)
|
||||||
{
|
{
|
||||||
searchPreamble();
|
searchPreamble();
|
||||||
return search_->findPathEnds(from, thrus, to,
|
return search_->findPathEnds(from, thrus, to, unconstrained,
|
||||||
corner, min_max, group_count, endpoint_count,
|
corner, min_max, group_count, endpoint_count,
|
||||||
unique_pins, slack_min, slack_max,
|
unique_pins, slack_min, slack_max,
|
||||||
sort_by_slack, group_names,
|
sort_by_slack, group_names,
|
||||||
|
|
@ -2552,8 +2541,8 @@ PinSet *
|
||||||
Sta::findGroupPathPins(const char *group_path_name)
|
Sta::findGroupPathPins(const char *group_path_name)
|
||||||
{
|
{
|
||||||
if (!search_->havePathGroups()) {
|
if (!search_->havePathGroups()) {
|
||||||
PathEndSeq *path_ends = findPathEnds(// from, thrus, to
|
PathEndSeq *path_ends = findPathEnds(// from, thrus, to, unconstrained
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL, false,
|
||||||
// corner, min_max,
|
// corner, min_max,
|
||||||
NULL, MinMaxAll::max(),
|
NULL, MinMaxAll::max(),
|
||||||
// group_count, endpoint_count, unique_pins
|
// group_count, endpoint_count, unique_pins
|
||||||
|
|
|
||||||
|
|
@ -721,9 +721,6 @@ public:
|
||||||
bool no_version);
|
bool no_version);
|
||||||
// Remove all delay and slew annotations.
|
// Remove all delay and slew annotations.
|
||||||
void removeDelaySlewAnnotations();
|
void removeDelaySlewAnnotations();
|
||||||
// TCL variable sta_report_unconstrained_paths.
|
|
||||||
bool reportUnconstrainedPaths() const;
|
|
||||||
void setReportUnconstrainedPaths(bool report);
|
|
||||||
// TCL variable sta_crpr_enabled.
|
// TCL variable sta_crpr_enabled.
|
||||||
// Common Reconvergent Clock Removal (CRPR).
|
// Common Reconvergent Clock Removal (CRPR).
|
||||||
// Timing check source/target common clock path overlap for search
|
// Timing check source/target common clock path overlap for search
|
||||||
|
|
@ -787,6 +784,7 @@ public:
|
||||||
virtual PathEndSeq *findPathEnds(ExceptionFrom *from,
|
virtual PathEndSeq *findPathEnds(ExceptionFrom *from,
|
||||||
ExceptionThruSeq *thrus,
|
ExceptionThruSeq *thrus,
|
||||||
ExceptionTo *to,
|
ExceptionTo *to,
|
||||||
|
bool unconstrained,
|
||||||
// Use corner NULL to report timing
|
// Use corner NULL to report timing
|
||||||
// for all corners.
|
// for all corners.
|
||||||
const Corner *corner,
|
const Corner *corner,
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ VisitPathEnds::visitPathEnds(Vertex *vertex,
|
||||||
bool is_constrained = false;
|
bool is_constrained = false;
|
||||||
visitClkedPathEnds(pin, vertex, corner, min_max, filtered, visitor,
|
visitClkedPathEnds(pin, vertex, corner, min_max, filtered, visitor,
|
||||||
is_constrained);
|
is_constrained);
|
||||||
if (search_->reportUnconstrainedPaths()
|
if (search_->unconstrainedPaths()
|
||||||
&& !is_constrained
|
&& !is_constrained
|
||||||
&& !vertex->isDisabledConstraint())
|
&& !vertex->isDisabledConstraint())
|
||||||
visitUnconstrainedPathEnds(pin, vertex, corner, min_max, filtered,
|
visitUnconstrainedPathEnds(pin, vertex, corner, min_max, filtered,
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,9 @@ WritePathSpice::maxTime()
|
||||||
Path *input_path = stageDrvrPath(input_stage);
|
Path *input_path = stageDrvrPath(input_stage);
|
||||||
auto input_slew = input_path->slew(this);
|
auto input_slew = input_path->slew(this);
|
||||||
auto end_slew = 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;
|
return max_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,7 +350,7 @@ WritePathSpice::writeInputSource()
|
||||||
volt1 = gnd_voltage_;
|
volt1 = gnd_voltage_;
|
||||||
}
|
}
|
||||||
Path *input_path = stageDrvrPath(input_stage);
|
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)
|
if (input_slew == 0.0)
|
||||||
input_slew = maxTime() / 1e+3;
|
input_slew = maxTime() / 1e+3;
|
||||||
// Arbitrary offset.
|
// Arbitrary offset.
|
||||||
|
|
@ -732,8 +734,8 @@ WritePathSpice::writeStageParasitics(Stage stage)
|
||||||
auto device = device_iter.next();
|
auto device = device_iter.next();
|
||||||
auto resistance = parasitics_->value(device, parasitic_ap);
|
auto resistance = parasitics_->value(device, parasitic_ap);
|
||||||
if (parasitics_->isResistor(device)) {
|
if (parasitics_->isResistor(device)) {
|
||||||
ParasiticNode *node1, *node2;
|
ParasiticNode *node1 = parasitics_->node1(device);
|
||||||
parasitics_->resistorNodes(device, node1, node2);
|
ParasiticNode *node2 = parasitics_->node2(device);
|
||||||
streamPrint(spice_stream_, "R%d %s %s %.3e\n",
|
streamPrint(spice_stream_, "R%d %s %s %.3e\n",
|
||||||
resistor_index,
|
resistor_index,
|
||||||
nodeName(node1),
|
nodeName(node1),
|
||||||
|
|
@ -742,6 +744,14 @@ WritePathSpice::writeStageParasitics(Stage stage)
|
||||||
resistor_index++;
|
resistor_index++;
|
||||||
}
|
}
|
||||||
else if (parasitics_->isCouplingCap(device)) {
|
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);
|
ParasiticNodeSet::Iterator node_iter(nodes);
|
||||||
|
|
|
||||||
|
|
@ -1930,7 +1930,7 @@ proc write_path_spice { args } {
|
||||||
sta_error "No -path_args specified.\n"
|
sta_error "No -path_args specified.\n"
|
||||||
}
|
}
|
||||||
set path_args $keys(-path_args)
|
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 == {} } {
|
if { $path_ends == {} } {
|
||||||
sta_error "No paths found for -path_args $path_args.\n"
|
sta_error "No paths found for -path_args $path_args.\n"
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
26
tcl/Sta.tcl
26
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]\
|
[-through through_list|-rise_through through_list|-fall_through through_list]\
|
||||||
[-to to_list|-rise_to to_list|-fall_to to_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]\
|
[-path_delay min|min_rise|min_fall|max|max_rise|max_fall|min_max]\
|
||||||
|
[-unconstrained]
|
||||||
[-corner corner_name]\
|
[-corner corner_name]\
|
||||||
[-group_count path_count] \
|
[-group_count path_count] \
|
||||||
[-endpoint_count path_count]\
|
[-endpoint_count path_count]\
|
||||||
|
|
@ -158,13 +159,14 @@ proc find_timing_paths { args } {
|
||||||
}
|
}
|
||||||
|
|
||||||
proc find_timing_paths_cmd { cmd args_var } {
|
proc find_timing_paths_cmd { cmd args_var } {
|
||||||
|
global sta_report_unconstrained_paths
|
||||||
upvar 1 $args_var args
|
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 \
|
keys {-from -rise_from -fall_from -to -rise_to -fall_to \
|
||||||
-path_delay -corner -group_count -endpoint_count \
|
-path_delay -corner -group_count -endpoint_count \
|
||||||
-slack_max -slack_min -path_group} \
|
-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 min_max "max"
|
||||||
set end_tr "rise_fall"
|
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" } {
|
} elseif { $mm_key == "min" || $mm_key == "max" || $mm_key == "min_max" } {
|
||||||
set min_max $mm_key
|
set min_max $mm_key
|
||||||
} else {
|
} 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
|
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 corner [parse_corner_or_all keys]
|
||||||
|
|
||||||
set endpoint_count 1
|
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 \
|
$group_count $endpoint_count $unique_pins \
|
||||||
$slack_min $slack_max \
|
$slack_min $slack_max \
|
||||||
$sort_by_slack $groups \
|
$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]\
|
{[-from from_list|-rise_from from_list|-fall_from from_list]\
|
||||||
[-through through_list|-rise_through through_list|-fall_through through_list]\
|
[-through through_list|-rise_through through_list|-fall_through through_list]\
|
||||||
[-to to_list|-rise_to to_list|-fall_to to_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]\
|
[-path_delay min|min_rise|min_fall|max|max_rise|max_fall|min_max]\
|
||||||
[-corner corner_name]\
|
[-corner corner_name]\
|
||||||
[-group_count path_count] \
|
[-group_count path_count] \
|
||||||
|
|
@ -286,11 +298,7 @@ proc_redirect report_checks {
|
||||||
parse_report_path_options "report_checks" args "full" 0
|
parse_report_path_options "report_checks" args "full" 0
|
||||||
set path_ends [find_timing_paths_cmd "report_checks" args]
|
set path_ends [find_timing_paths_cmd "report_checks" args]
|
||||||
if { $path_ends == {} } {
|
if { $path_ends == {} } {
|
||||||
if { $sta_report_unconstrained_paths } {
|
puts "No paths found."
|
||||||
puts "No paths."
|
|
||||||
} else {
|
|
||||||
puts "No constrained paths."
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
report_path_ends $path_ends
|
report_path_ends $path_ends
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
tcl/StaTcl.i
42
tcl/StaTcl.i
|
|
@ -2123,18 +2123,6 @@ net_is_constrained(Net *net)
|
||||||
return Sta::sta()->sdc()->isConstrained(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
|
bool
|
||||||
clk_thru_tristate_enabled()
|
clk_thru_tristate_enabled()
|
||||||
{
|
{
|
||||||
|
|
@ -4104,6 +4092,7 @@ PathEndSeq *
|
||||||
find_path_ends(ExceptionFrom *from,
|
find_path_ends(ExceptionFrom *from,
|
||||||
ExceptionThruSeq *thrus,
|
ExceptionThruSeq *thrus,
|
||||||
ExceptionTo *to,
|
ExceptionTo *to,
|
||||||
|
bool unconstrained,
|
||||||
Corner *corner,
|
Corner *corner,
|
||||||
const MinMaxAll *delay_min_max,
|
const MinMaxAll *delay_min_max,
|
||||||
int group_count,
|
int group_count,
|
||||||
|
|
@ -4122,7 +4111,7 @@ find_path_ends(ExceptionFrom *from,
|
||||||
{
|
{
|
||||||
cmdLinkedNetwork();
|
cmdLinkedNetwork();
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
PathEndSeq *ends = sta->findPathEnds(from, thrus, to,
|
PathEndSeq *ends = sta->findPathEnds(from, thrus, to, unconstrained,
|
||||||
corner, delay_min_max,
|
corner, delay_min_max,
|
||||||
group_count, endpoint_count, unique_pins,
|
group_count, endpoint_count, unique_pins,
|
||||||
slack_min, slack_max,
|
slack_min, slack_max,
|
||||||
|
|
@ -4422,6 +4411,17 @@ worst_slack(const MinMax *min_max)
|
||||||
return worst_slack;
|
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
|
Slack
|
||||||
worst_slack_corner(const Corner *corner,
|
worst_slack_corner(const Corner *corner,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
|
|
@ -6051,6 +6051,22 @@ tag()
|
||||||
return self->tag(sta)->asString(sta);
|
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 {
|
%extend VertexPathIterator {
|
||||||
|
|
|
||||||
|
|
@ -160,14 +160,6 @@ proc trace_propagate_gated_clock_enable { name1 name2 op } {
|
||||||
propagate_gated_clock_enable set_propagate_gated_clock_enable
|
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 } {
|
proc trace_boolean_var { op var_name get_proc set_proc } {
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@ port_dcl_type:
|
||||||
| INOUT REG { $$ = sta::PortDirection::bidirect(); }
|
| INOUT REG { $$ = sta::PortDirection::bidirect(); }
|
||||||
| INOUT WIRE { $$ = sta::PortDirection::bidirect(); }
|
| INOUT WIRE { $$ = sta::PortDirection::bidirect(); }
|
||||||
| OUTPUT { $$ = sta::PortDirection::output(); }
|
| OUTPUT { $$ = sta::PortDirection::output(); }
|
||||||
|
| OUTPUT WIRE { $$ = sta::PortDirection::output(); }
|
||||||
| OUTPUT REG { $$ = sta::PortDirection::output(); }
|
| OUTPUT REG { $$ = sta::PortDirection::output(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue