sync
This commit is contained in:
parent
de5c3a6400
commit
3d8d088b89
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
139
INSTALL
139
INSTALL
|
|
@ -14,32 +14,81 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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<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.
|
||||
|
||||
tar zvfz opensta-<version>.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<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
|
||||
------------------
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
|||
|
|
@ -11,3 +11,5 @@
|
|||
#if ${CUDD_FOUND}==TRUE
|
||||
#define CUDD
|
||||
#endif
|
||||
|
||||
#define SSTA ${SSTA}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
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();
|
||||
}
|
||||
|
||||
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<const ConcreteParasiticResistor*>(device);
|
||||
node1 = cdevice->node1();
|
||||
node2 = cdevice->node2();
|
||||
const ConcreteParasiticDevice *cdevice =
|
||||
static_cast<const ConcreteParasiticDevice*>(device);
|
||||
return cdevice->node1();
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
ConcreteParasitics::node2(const ParasiticDevice *device) const
|
||||
{
|
||||
const ConcreteParasiticDevice *cdevice =
|
||||
static_cast<const ConcreteParasiticDevice*>(device);
|
||||
return cdevice->node2();
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
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]\
|
||||
[-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
|
||||
}
|
||||
|
|
|
|||
42
tcl/StaTcl.i
42
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 {
|
||||
|
|
|
|||
|
|
@ -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 } {
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue