cmake, write_path_spice
This commit is contained in:
parent
735a868e53
commit
9e5aac37f4
132
CMakeLists.txt
132
CMakeLists.txt
|
|
@ -176,7 +176,7 @@ set(STA_SOURCE
|
|||
search/VisitPathEnds.cc
|
||||
search/VisitPathGroupVertices.cc
|
||||
search/WorstSlack.cc
|
||||
search/WriteSpice.cc
|
||||
search/WritePathSpice.cc
|
||||
|
||||
util/Condition.cc
|
||||
util/Debug.cc
|
||||
|
|
@ -346,7 +346,7 @@ set(STA_HEADERS
|
|||
search/VisitPathEnds.hh
|
||||
search/VisitPathGroupVertices.hh
|
||||
search/WorstSlack.hh
|
||||
search/WriteSpice.hh
|
||||
search/WritePathSpice.hh
|
||||
|
||||
util/Condition.hh
|
||||
util/Debug.hh
|
||||
|
|
@ -514,91 +514,88 @@ get_filename_component(TCL_HEADER_DIR "${TCL_HEADER}" PATH)
|
|||
|
||||
################################################################
|
||||
|
||||
# TCL files included as part of the executable are shoved into TclInitVar.cc.
|
||||
# These files are encoded and shipped as part of the executable
|
||||
# so that they do not have to be installed on the client host.
|
||||
add_custom_command(OUTPUT ${STA_HOME}/app/TclInitVar.cc
|
||||
COMMAND etc/TclEncode.tcl app/TclInitVar.cc tcl_inits ${STA_TCL_FILES}
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
DEPENDS ${STA_TCL_FILES} etc/TclEncode.tcl
|
||||
)
|
||||
|
||||
find_package(FLEX)
|
||||
find_package(BISON)
|
||||
|
||||
# Verilog scan/parse.
|
||||
bison_target(VerilogParser verilog/VerilogParse.yy ${STA_HOME}/verilog/VerilogParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/verilog/VerilogParse.hh
|
||||
COMPILE_FLAGS --name-prefix=VerilogParse_
|
||||
)
|
||||
# LibertyExpr scan/parse.
|
||||
bison_target(LibertyExprParser liberty/LibertyExprParse.yy ${STA_HOME}/liberty/LibertyExprParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/liberty/LibertyExprParse.hh
|
||||
COMPILE_FLAGS --name-prefix=LibertyExprParse_
|
||||
)
|
||||
|
||||
# flex seems to ignore -o<file>
|
||||
add_custom_command(OUTPUT ${STA_HOME}/verilog/VerilogLex.cc ${STA_HOME}/verilog/VerilogLex.hh
|
||||
COMMAND ${FLEX_EXECUTABLE} --prefix=VerilogLex_ --header-file=${STA_HOME}/verilog/VerilogLex.hh ${STA_HOME}/verilog/VerilogLex.ll
|
||||
COMMAND mv lex.yy.c ${STA_HOME}/verilog/VerilogLex.cc
|
||||
flex_target(LibertyExprLex liberty/LibertyExprLex.ll ${STA_HOME}/liberty/LibertyExprLex.cc
|
||||
DEFINES_FILE ${STA_HOME}/liberty/LibertyExprLex.hh
|
||||
COMPILE_FLAGS --prefix=LibertyExprLex_
|
||||
)
|
||||
|
||||
add_flex_bison_dependency(LibertyExprLex LibertyExprParser)
|
||||
|
||||
# Liberty scan/parse.
|
||||
bison_target(LibertyParser liberty/LibertyParse.yy ${STA_HOME}/liberty/LibertyParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/liberty/LibertyParse.hh
|
||||
COMPILE_FLAGS --name-prefix=LibertyParse_
|
||||
)
|
||||
|
||||
# flex seems to ignore -o<file>
|
||||
add_custom_command(OUTPUT ${STA_HOME}/liberty/LibertyLex.cc ${STA_HOME}/liberty/LibertyLex.hh
|
||||
COMMAND ${FLEX_EXECUTABLE} --prefix=LibertyLex_ --header-file=${STA_HOME}/liberty/LibertyLex.hh ${STA_HOME}/liberty/LibertyLex.ll
|
||||
COMMAND mv lex.yy.c ${STA_HOME}/liberty/LibertyLex.cc
|
||||
)
|
||||
flex_target(LibertyLex liberty/LibertyLex.ll ${STA_HOME}/liberty/LibertyLex.cc
|
||||
DEFINES_FILE ${STA_HOME}/liberty/LibertyLex.hh
|
||||
COMPILE_FLAGS --prefix=LibertyLex_
|
||||
)
|
||||
|
||||
# LibertyExpr scan/parse.
|
||||
bison_target(LibertyExprParser liberty/LibertyExprParse.yy ${STA_HOME}/liberty/LibertyExprParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/liberty/LibertyExprParse.hh
|
||||
COMPILE_FLAGS --name-prefix=LibertyExprParse_
|
||||
)
|
||||
|
||||
# flex seems to ignore -o<file>
|
||||
add_custom_command(OUTPUT ${STA_HOME}/liberty/LibertyExprLex.cc ${STA_HOME}/liberty/LibertyExprLex.hh
|
||||
COMMAND ${FLEX_EXECUTABLE} --prefix=LibertyExprLex_ --header-file=${STA_HOME}/liberty/LibertyExprLex.hh ${STA_HOME}/liberty/LibertyExprLex.ll
|
||||
COMMAND mv lex.yy.c ${STA_HOME}/liberty/LibertyExprLex.cc
|
||||
)
|
||||
|
||||
# Sdf scan/parse.
|
||||
bison_target(SdfParser sdf/SdfParse.yy ${STA_HOME}/sdf/SdfParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/sdf/SdfParse.hh
|
||||
COMPILE_FLAGS --name-prefix=SdfParse_
|
||||
)
|
||||
|
||||
# flex seems to ignore -o<file>
|
||||
add_custom_command(OUTPUT ${STA_HOME}/sdf/SdfLex.cc ${STA_HOME}/sdf/SdfLex.hh
|
||||
COMMAND ${FLEX_EXECUTABLE} --prefix=SdfLex_ --header-file=${STA_HOME}/sdf/SdfLex.hh ${STA_HOME}/sdf/SdfLex.ll
|
||||
COMMAND mv lex.yy.c ${STA_HOME}/sdf/SdfLex.cc
|
||||
)
|
||||
add_flex_bison_dependency(LibertyLex LibertyParser)
|
||||
|
||||
# Spef scan/parse.
|
||||
bison_target(SpefParser parasitics/SpefParse.yy ${STA_HOME}/parasitics/SpefParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/parasitics/SpefParse.hh
|
||||
COMPILE_FLAGS --name-prefix=SpefParse_
|
||||
)
|
||||
DEFINES_FILE ${STA_HOME}/parasitics/SpefParse.hh
|
||||
COMPILE_FLAGS --name-prefix=SpefParse_
|
||||
)
|
||||
|
||||
# flex seems to ignore -o<file>
|
||||
add_custom_command(OUTPUT ${STA_HOME}/parasitics/SpefLex.cc ${STA_HOME}/parasitics/SpefLex.hh
|
||||
COMMAND ${FLEX_EXECUTABLE} --prefix=SpefLex_ --header-file=${STA_HOME}/parasitics/SpefLex.hh ${STA_HOME}/parasitics/SpefLex.ll
|
||||
COMMAND mv lex.yy.c ${STA_HOME}/parasitics/SpefLex.cc
|
||||
)
|
||||
flex_target(SpefLex parasitics/SpefLex.ll ${STA_HOME}/parasitics/SpefLex.cc
|
||||
DEFINES_FILE ${STA_HOME}/parasitics/SpefLex.hh
|
||||
COMPILE_FLAGS --prefix=SpefLex_
|
||||
)
|
||||
|
||||
add_flex_bison_dependency(SpefLex SpefParser)
|
||||
|
||||
# Spf scan/parse.
|
||||
bison_target(SpfParser parasitics/SpfParse.yy ${STA_HOME}/parasitics/SpfParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/parasitics/SpfParse.hh
|
||||
COMPILE_FLAGS --name-prefix=SpfParse_
|
||||
DEFINES_FILE ${STA_HOME}/parasitics/SpfParse.hh
|
||||
COMPILE_FLAGS --name-prefix=SpfParse_
|
||||
)
|
||||
|
||||
flex_target(SpfLex parasitics/SpfLex.ll ${STA_HOME}/parasitics/SpfLex.cc
|
||||
DEFINES_FILE ${STA_HOME}/parasitics/SpfLex.hh
|
||||
COMPILE_FLAGS --prefix=SpfLex_
|
||||
)
|
||||
|
||||
add_flex_bison_dependency(SpfLex SpfParser)
|
||||
|
||||
# Verilog scan/parse.
|
||||
bison_target(VerilogParser verilog/VerilogParse.yy ${STA_HOME}/verilog/VerilogParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/verilog/VerilogParse.hh
|
||||
COMPILE_FLAGS --name-prefix=VerilogParse_
|
||||
)
|
||||
|
||||
# flex seems to ignore -o<file>
|
||||
add_custom_command(OUTPUT ${STA_HOME}/parasitics/SpfLex.cc ${STA_HOME}/parasitics/SpfLex.hh
|
||||
COMMAND ${FLEX_EXECUTABLE} --prefix=SpfLex_ --header-file=${STA_HOME}/parasitics/SpfLex.hh ${STA_HOME}/parasitics/SpfLex.ll
|
||||
COMMAND mv lex.yy.c ${STA_HOME}/parasitics/SpfLex.cc
|
||||
flex_target(VerilogLex verilog/VerilogLex.ll ${STA_HOME}/verilog/VerilogLex.cc
|
||||
DEFINES_FILE ${STA_HOME}/verilog/VerilogLex.hh
|
||||
COMPILE_FLAGS --prefix=VerilogLex_
|
||||
)
|
||||
|
||||
add_flex_bison_dependency(VerilogLex VerilogParser)
|
||||
|
||||
# Sdf scan/parse.
|
||||
bison_target(SdfParser sdf/SdfParse.yy ${STA_HOME}/sdf/SdfParse.cc
|
||||
DEFINES_FILE ${STA_HOME}/sdf/SdfParse.hh
|
||||
COMPILE_FLAGS --name-prefix=SdfParse_
|
||||
)
|
||||
|
||||
flex_target(SdfLex sdf/SdfLex.ll ${STA_HOME}/sdf/SdfLex.cc
|
||||
DEFINES_FILE ${STA_HOME}/sdf/SdfLex.hh
|
||||
COMPILE_FLAGS --prefix=SdfLex_
|
||||
)
|
||||
|
||||
add_flex_bison_dependency(SdfLex SdfParser)
|
||||
|
||||
|
||||
################################################################
|
||||
|
||||
include(FindSWIG)
|
||||
|
|
@ -612,6 +609,17 @@ add_custom_command(OUTPUT ${STA_HOME}/app/StaApp_wrap.cc
|
|||
|
||||
################################################################
|
||||
|
||||
# TCL files included as part of the executable are shoved into TclInitVar.cc.
|
||||
# These files are encoded and shipped as part of the executable
|
||||
# so that they do not have to be installed on the client host.
|
||||
add_custom_command(OUTPUT ${STA_HOME}/app/TclInitVar.cc
|
||||
COMMAND etc/TclEncode.tcl app/TclInitVar.cc tcl_inits ${STA_TCL_FILES}
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
DEPENDS ${STA_TCL_FILES} etc/TclEncode.tcl
|
||||
)
|
||||
|
||||
################################################################
|
||||
|
||||
set(STA_INCLUDE_DIRS
|
||||
app
|
||||
dcalc
|
||||
|
|
|
|||
76
INSTALL
76
INSTALL
|
|
@ -19,6 +19,10 @@ 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 also supported with cmake described later in this file.
|
||||
Autotools based builds are currently supported for compatibility but
|
||||
are deprecated.
|
||||
|
||||
Building from a tarfile
|
||||
-----------------------
|
||||
|
||||
|
|
@ -65,6 +69,10 @@ 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.
|
||||
|
|
@ -108,6 +116,41 @@ 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.
|
||||
|
||||
MAKE_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
|
||||
|
|
@ -148,36 +191,3 @@ form:
|
|||
All commands in one .tcl file (usually run.tcl) for small cases
|
||||
No calls to "exit"
|
||||
No shell scripts to envoke the sta.
|
||||
|
||||
----------------------------------------------------------------
|
||||
Building with Cmake
|
||||
|
||||
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.
|
||||
|
||||
MAKE_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
|
||||
|
|
|
|||
|
|
@ -121,6 +121,9 @@ staTclAppInit(Tcl_Interp *interp)
|
|||
int argc = sta_argc;
|
||||
char **argv = sta_argv;
|
||||
|
||||
// source init.tcl
|
||||
Tcl_Init(interp);
|
||||
|
||||
// Define swig commands.
|
||||
sta_swig_init(interp);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@ Release 2.0 Patches
|
|||
2018/11/08 corners > 2 causes internal error
|
||||
2018/11/09 Verilog ignore attributes (* blah *)
|
||||
2018/12/24 all_fanout from input port
|
||||
2018/12/25 liberty pg_types
|
||||
2018/12/25 liberty pg_types
|
||||
2019/01/03 liberty 2D bus names
|
||||
|
|
|
|||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -778,9 +778,18 @@ LibertyLibrary::addSupplyVoltage(const char *supply_name,
|
|||
}
|
||||
|
||||
float
|
||||
LibertyLibrary::supplyVoltage(const char *supply_name)
|
||||
LibertyLibrary::supplyVoltage(const char *supply_name) const
|
||||
{
|
||||
return supply_voltage_map_[supply_name];
|
||||
float voltage;
|
||||
bool exists;
|
||||
supply_voltage_map_.findKey(supply_name, voltage, exists);
|
||||
return voltage;
|
||||
}
|
||||
|
||||
bool
|
||||
LibertyLibrary::supplyExists(const char *supply_name) const
|
||||
{
|
||||
return supply_voltage_map_.hasKey(supply_name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -268,7 +268,8 @@ public:
|
|||
void addOcvDerate(OcvDerate *derate);
|
||||
void addSupplyVoltage(const char *suppy_name,
|
||||
float voltage);
|
||||
float supplyVoltage(const char *suppy_name);
|
||||
bool supplyExists(const char *suppy_name) const;
|
||||
float supplyVoltage(const char *suppy_name) const;
|
||||
|
||||
// Make scaled cell. Call LibertyCell::addScaledCell after it is complete.
|
||||
LibertyCell *makeScaledCell(const char *name,
|
||||
|
|
|
|||
|
|
@ -43,8 +43,6 @@ libertyExprFlushBuffer()
|
|||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option prefix="LibertyExprLex_"
|
||||
%option outfile="lex.yy.c"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
|
|
|
|||
|
|
@ -44,8 +44,6 @@ libertyParseFlushBuffer()
|
|||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option prefix="LibertyLex_"
|
||||
%option outfile="lex.yy.c"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
|
|
@ -63,6 +61,7 @@ BUS_SUB {BUS_LEFT}{DIGIT}+{BUS_RIGHT}
|
|||
BUS_RANGE {BUS_LEFT}{DIGIT}+:{DIGIT}+{BUS_RIGHT}
|
||||
PIN_NAME ({ALPHA}|_)({ALPHA}|{DIGIT}|_)*
|
||||
BUS_NAME {PIN_NAME}({BUS_SUB}|{BUS_RANGE})
|
||||
BUS_NAME2 {PIN_NAME}{BUS_SUB}({BUS_SUB}|{BUS_RANGE})
|
||||
MIXED_NAME {BUS_NAME}_{PIN_NAME}
|
||||
HNAME ({PIN_NAME}|{BUS_NAME}|{MIXED_NAME})([\/.]({PIN_NAME}|{BUS_NAME}|{MIXED_NAME}))+
|
||||
/* ocv_table_template(2D_ocv_template) */
|
||||
|
|
@ -97,6 +96,7 @@ EOL \r?\n
|
|||
|
||||
{PIN_NAME}{TOKEN_END} |
|
||||
{BUS_NAME}{TOKEN_END} |
|
||||
{BUS_NAME2}{TOKEN_END} |
|
||||
{MIXED_NAME}{TOKEN_END} |
|
||||
{HNAME}{TOKEN_END} |
|
||||
{BUS_STYLE}{TOKEN_END} |
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ int LibertyParse_error(const char *msg);
|
|||
sta::LibertyStmt *stmt;
|
||||
}
|
||||
|
||||
|
||||
%token <number> FLOAT
|
||||
%token <string> STRING KEYWORD
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,12 @@ libliberty_la_SOURCES = \
|
|||
|
||||
LibertyExprLex.ll: LibertyExprParse.hh
|
||||
|
||||
LibertyExprLex.cc: LibertyExprLex.ll
|
||||
$(LEX) $(LFLAGS) -o LibertyExprLex.cc --prefix=LibertyExprLex_ --header-file=LibertyExprLex.hh LibertyExprLex.ll
|
||||
|
||||
LibertyLex.cc: LibertyLex.ll
|
||||
$(LEX) $(LFLAGS) -o LibertyLex.cc --prefix=LibertyLex_ --header-file=LibertyLex.hh LibertyLex.ll
|
||||
|
||||
LibertyLex.ll: LibertyParse.hh
|
||||
|
||||
# Rules to support automake pre 1.12 that name header .h instead of .hh
|
||||
|
|
|
|||
|
|
@ -51,8 +51,14 @@ libparasitics_la_SOURCES = \
|
|||
|
||||
SpfLex.ll: SpfParse.hh
|
||||
|
||||
SpfLex.cc: SpfLex.ll
|
||||
$(LEX) $(LFLAGS) -o SpfLex.cc --prefix=SpfLex_ --header-file=SpfLex.hh SpfLex.ll
|
||||
|
||||
SpefLex.ll: SpefParse.hh
|
||||
|
||||
SpefLex.cc: SpefLex.ll
|
||||
$(LEX) $(LFLAGS) -o SpefLex.cc --prefix=SpefLex_ --header-file=SpefLex.hh SpefLex.ll
|
||||
|
||||
# Rules to support automake pre 1.12 that name header .h instead of .hh
|
||||
SpfParse.hh: SpfParse.cc
|
||||
if test -f SpfParse.h; then \
|
||||
|
|
|
|||
|
|
@ -424,6 +424,14 @@ NullParasitics::value(const ParasiticDevice *,
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::resistorNodes(const ParasiticDevice *,
|
||||
// Return values.
|
||||
ParasiticNode *&,
|
||||
ParasiticNode *&) const
|
||||
{
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
NullParasitics::otherNode(const ParasiticDevice *,
|
||||
ParasiticNode *) const
|
||||
|
|
|
|||
|
|
@ -164,6 +164,10 @@ 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 *otherNode(const ParasiticDevice *device,
|
||||
ParasiticNode *node) const;
|
||||
// Reduce parasitic network to reduce_to model.
|
||||
|
|
|
|||
|
|
@ -43,8 +43,6 @@ spefResetScanner()
|
|||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option prefix="SpefLex_"
|
||||
%option outfile="lex.yy.c"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ spfResetScanner()
|
|||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option prefix="SpfLex_"
|
||||
%option outfile="lex.yy.c"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ libsdf_la_SOURCES = \
|
|||
|
||||
SdfLex.ll: SdfParse.hh
|
||||
|
||||
SdfLex.cc: SdfLex.ll
|
||||
$(LEX) $(LFLAGS) -o SdfLex.cc --prefix=SdfLex_ --header-file=SdfLex.hh SdfLex.ll
|
||||
|
||||
# Rules to support automake pre 1.12 that name header .h instead of .hh
|
||||
SdfParse.hh: SdfParse.cc
|
||||
if test -f SdfParse.h; then \
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ sdfFlushBuffer()
|
|||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option prefix="SdfLex_"
|
||||
%option outfile="lex.yy.c"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ include_HEADERS = \
|
|||
VisitPathEnds.hh \
|
||||
VisitPathGroupVertices.hh \
|
||||
WorstSlack.hh \
|
||||
WriteSpice.hh
|
||||
WritePathSpice.hh
|
||||
|
||||
libsearch_la_SOURCES = \
|
||||
Bfs.cc \
|
||||
|
|
@ -99,7 +99,7 @@ libsearch_la_SOURCES = \
|
|||
VisitPathEnds.cc \
|
||||
VisitPathGroupVertices.cc \
|
||||
WorstSlack.cc \
|
||||
WriteSpice.cc
|
||||
WritePathSpice.cc
|
||||
|
||||
libs: $(lib_LTLIBRARIES)
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,39 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2019, Parallax Software, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef STA_WRITE_PATH_SPICE_H
|
||||
#define STA_WRITE_PATH_SPICE_H
|
||||
|
||||
namespace sta {
|
||||
|
||||
// Write a spice deck for path.
|
||||
// Throws FileNotReadable, FileNotWritable, SubcktEndsMissing
|
||||
void
|
||||
writePathSpice(Path *path,
|
||||
// Spice file written for path.
|
||||
const char *spice_filename,
|
||||
// Subckts used by path included in spice file.
|
||||
const char *subckt_filename,
|
||||
// File of all cell spice subckt definitions.
|
||||
const char *lib_subckt_filename,
|
||||
// Device model file included in spice file.
|
||||
const char *model_filename,
|
||||
const char *power_name,
|
||||
const char *gnd_name,
|
||||
StaState *sta);
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
85
tcl/Cmds.tcl
85
tcl/Cmds.tcl
|
|
@ -1860,5 +1860,90 @@ proc object_name_cmp { obj1 obj2 } {
|
|||
return [string compare [$obj1 object_name] [$obj2 object_name]]
|
||||
}
|
||||
|
||||
################################################################
|
||||
|
||||
define_cmd_args "write_path_spice" { -path_args path_args\
|
||||
-spice_file spice_file\
|
||||
-subckt_file subckt_file\
|
||||
-lib_subckt_file lib_subckts_file\
|
||||
-model_file model_file\
|
||||
-power power\
|
||||
-ground ground}
|
||||
|
||||
proc write_path_spice { args } {
|
||||
parse_key_args "write_spice" args \
|
||||
keys {-spice_file -subckt_file -lib_subckt_file \
|
||||
-model_file -power -ground -path_args} \
|
||||
flags {}
|
||||
|
||||
if { [info exists keys(-spice_file)] } {
|
||||
set spice_file $keys(-spice_file)
|
||||
if { [file exists $spice_file] && ![file writable $spice_file] } {
|
||||
sta_error "-spice_file $spice_file is not writable.\n"
|
||||
}
|
||||
} else {
|
||||
sta_error "No -spice_file specified.\n"
|
||||
}
|
||||
|
||||
if { [info exists keys(-subckt_file)] } {
|
||||
set subckt_file $keys(-subckt_file)
|
||||
if { [file exists $subckt_file] && ![file writable $subckt_file] } {
|
||||
sta_error "-subckt_file $subckt_file is not writable.\n"
|
||||
}
|
||||
} else {
|
||||
sta_error "No -subckt_file specified.\n"
|
||||
}
|
||||
|
||||
if { [info exists keys(-lib_subckt_file)] } {
|
||||
set lib_subckt_file $keys(-lib_subckt_file)
|
||||
if { ![file readable $lib_subckt_file] } {
|
||||
sta_error "-lib_subckt_file $lib_subckt_file is not readable.\n"
|
||||
}
|
||||
} else {
|
||||
sta_error "No -lib_subckt_file specified.\n"
|
||||
}
|
||||
|
||||
if { [info exists keys(-lib_subckt_file)] } {
|
||||
set model_file $keys(-model_file)
|
||||
if { ![file readable $model_file] } {
|
||||
sta_error "-model_file $model_file is not readable.\n"
|
||||
}
|
||||
} else {
|
||||
sta_error "No -model_file specified.\n"
|
||||
}
|
||||
|
||||
if { [info exists keys(-power)] } {
|
||||
set power $keys(-power)
|
||||
if { ![liberty_supply_exists $power] } {
|
||||
sta_error "liberty $power not found.\n"
|
||||
}
|
||||
} else {
|
||||
sta_error "No -power specified.\n"
|
||||
}
|
||||
|
||||
if { [info exists keys(-ground)] } {
|
||||
set ground $keys(-ground)
|
||||
if { ![liberty_supply_exists $ground] } {
|
||||
sta_error "liberty $ground not found.\n"
|
||||
}
|
||||
} else {
|
||||
sta_error "No -ground specified.\n"
|
||||
}
|
||||
|
||||
if { ![info exists keys(-path_args)] } {
|
||||
sta_error "No -path_args specified.\n"
|
||||
}
|
||||
set path_args $keys(-path_args)
|
||||
set path_ends [eval [concat get_timing_paths $path_args]]
|
||||
if { $path_ends == {} } {
|
||||
sta_error "No paths found for -path_args $path_args.\n"
|
||||
}
|
||||
set path_end [lindex $path_ends 0]
|
||||
set path [$path_end path]
|
||||
|
||||
write_path_spice_cmd $path $spice_file $subckt_file \
|
||||
$lib_subckt_file $model_file $power $ground
|
||||
}
|
||||
|
||||
# sta namespace end.
|
||||
}
|
||||
|
|
|
|||
28
tcl/StaTcl.i
28
tcl/StaTcl.i
|
|
@ -78,7 +78,7 @@
|
|||
#include "ReportPath.hh"
|
||||
#include "Power.hh"
|
||||
#include "Property.hh"
|
||||
#include "WriteSpice.hh"
|
||||
#include "WritePathSpice.hh"
|
||||
#include "Sta.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -4587,16 +4587,26 @@ write_sdc_cmd(const char *filename,
|
|||
}
|
||||
|
||||
void
|
||||
write_spice(PathRef *path,
|
||||
const char *spice_filename,
|
||||
const char *subckts_filename,
|
||||
const char *lib_subckts_filename,
|
||||
const char *models_filename)
|
||||
write_path_spice_cmd(PathRef *path,
|
||||
const char *spice_filename,
|
||||
const char *subckt_filename,
|
||||
const char *lib_subckt_filename,
|
||||
const char *model_filename,
|
||||
const char *power_name,
|
||||
const char *gnd_name)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
Sta *sta = Sta::sta();
|
||||
writeSpice(path, spice_filename, subckts_filename,
|
||||
lib_subckts_filename, models_filename, sta);
|
||||
writePathSpice(path, spice_filename, subckt_filename,
|
||||
lib_subckt_filename, model_filename,
|
||||
power_name, gnd_name, sta);
|
||||
}
|
||||
|
||||
bool
|
||||
liberty_supply_exists(const char *supply_name)
|
||||
{
|
||||
auto network = Sta::sta()->network();
|
||||
auto lib = network->defaultLibertyLibrary();
|
||||
return lib->supplyExists(supply_name);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
175
tcl/Util.tcl
175
tcl/Util.tcl
|
|
@ -394,6 +394,7 @@ proc check_percent { cmd_arg arg } {
|
|||
# This rename provices a mechanism to refer to the original TCL
|
||||
# command.
|
||||
rename source builtin_source
|
||||
rename unknown builtin_unknown
|
||||
|
||||
# Numeric expressions eval to themselves so braces aren't required
|
||||
# around bus names like foo[2] or foo[*].
|
||||
|
|
@ -433,178 +434,4 @@ proc sta_unknown { args } {
|
|||
}
|
||||
}
|
||||
|
||||
# Copied from init.tcl
|
||||
proc builtin_unknown args {
|
||||
variable ::tcl::UnknownPending
|
||||
global auto_noexec auto_noload env tcl_interactive
|
||||
|
||||
|
||||
if {[info exists ::errorInfo]} {
|
||||
set savedErrorInfo $::errorInfo
|
||||
}
|
||||
if {[info exists ::errorCode]} {
|
||||
set savedErrorCode $::errorCode
|
||||
}
|
||||
|
||||
set name [lindex $args 0]
|
||||
if {![info exists auto_noload]} {
|
||||
#
|
||||
# Make sure we're not trying to load the same proc twice.
|
||||
#
|
||||
if {[info exists UnknownPending($name)]} {
|
||||
return -code error "self-referential recursion\
|
||||
in \"unknown\" for command \"$name\""
|
||||
}
|
||||
set UnknownPending($name) pending
|
||||
set ret [catch {
|
||||
auto_load $name [uplevel 1 {::namespace current}]
|
||||
} msg opts]
|
||||
unset UnknownPending($name)
|
||||
if {$ret != 0} {
|
||||
dict append opts -errorinfo "\n (autoloading \"$name\")"
|
||||
return -options $opts $msg
|
||||
}
|
||||
if {![array size UnknownPending]} {
|
||||
unset UnknownPending
|
||||
}
|
||||
if {$msg} {
|
||||
if {[info exists savedErrorCode]} {
|
||||
set ::errorCode $savedErrorCode
|
||||
} else {
|
||||
unset -nocomplain ::errorCode
|
||||
}
|
||||
if {[info exists savedErrorInfo]} {
|
||||
set ::errorInfo $savedErrorInfo
|
||||
} else {
|
||||
unset -nocomplain ::errorInfo
|
||||
}
|
||||
set code [catch {uplevel 1 $args} msg opts]
|
||||
if {$code == 1} {
|
||||
#
|
||||
# Compute stack trace contribution from the [uplevel].
|
||||
# Note the dependence on how Tcl_AddErrorInfo, etc.
|
||||
# construct the stack trace.
|
||||
#
|
||||
set errorInfo [dict get $opts -errorinfo]
|
||||
set errorCode [dict get $opts -errorcode]
|
||||
set cinfo $args
|
||||
if {[string bytelength $cinfo] > 150} {
|
||||
set cinfo [string range $cinfo 0 150]
|
||||
while {[string bytelength $cinfo] > 150} {
|
||||
set cinfo [string range $cinfo 0 end-1]
|
||||
}
|
||||
append cinfo ...
|
||||
}
|
||||
append cinfo "\"\n (\"uplevel\" body line 1)"
|
||||
append cinfo "\n invoked from within"
|
||||
append cinfo "\n\"uplevel 1 \$args\""
|
||||
#
|
||||
# Try each possible form of the stack trace
|
||||
# and trim the extra contribution from the matching case
|
||||
#
|
||||
set expect "$msg\n while executing\n\"$cinfo"
|
||||
if {$errorInfo eq $expect} {
|
||||
#
|
||||
# The stack has only the eval from the expanded command
|
||||
# Do not generate any stack trace here.
|
||||
#
|
||||
dict unset opts -errorinfo
|
||||
dict incr opts -level
|
||||
return -options $opts $msg
|
||||
}
|
||||
#
|
||||
# Stack trace is nested, trim off just the contribution
|
||||
# from the extra "eval" of $args due to the "catch" above.
|
||||
#
|
||||
set expect "\n invoked from within\n\"$cinfo"
|
||||
set exlen [string length $expect]
|
||||
set eilen [string length $errorInfo]
|
||||
set i [expr {$eilen - $exlen - 1}]
|
||||
set einfo [string range $errorInfo 0 $i]
|
||||
#
|
||||
# For now verify that $errorInfo consists of what we are about
|
||||
# to return plus what we expected to trim off.
|
||||
#
|
||||
if {$errorInfo ne "$einfo$expect"} {
|
||||
error "Tcl bug: unexpected stack trace in \"unknown\"" {} \
|
||||
[list CORE UNKNOWN BADTRACE $einfo $expect $errorInfo]
|
||||
}
|
||||
return -code error -errorcode $errorCode \
|
||||
-errorinfo $einfo $msg
|
||||
} else {
|
||||
dict incr opts -level
|
||||
return -options $opts $msg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {([info level] == 1) && ([info script] eq "") \
|
||||
&& [info exists tcl_interactive] && $tcl_interactive} {
|
||||
if {![info exists auto_noexec]} {
|
||||
set new [auto_execok $name]
|
||||
if {$new ne ""} {
|
||||
set redir ""
|
||||
if {[namespace which -command console] eq ""} {
|
||||
set redir ">&@stdout <@stdin"
|
||||
}
|
||||
uplevel 1 [list ::catch \
|
||||
[concat exec $redir $new [lrange $args 1 end]] \
|
||||
::tcl::UnknownResult ::tcl::UnknownOptions]
|
||||
dict incr ::tcl::UnknownOptions -level
|
||||
return -options $::tcl::UnknownOptions $::tcl::UnknownResult
|
||||
}
|
||||
}
|
||||
if {$name eq "!!"} {
|
||||
set newcmd [history event]
|
||||
} elseif {[regexp {^!(.+)$} $name -> event]} {
|
||||
set newcmd [history event $event]
|
||||
} elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $name -> old new]} {
|
||||
set newcmd [history event -1]
|
||||
catch {regsub -all -- $old $newcmd $new newcmd}
|
||||
}
|
||||
if {[info exists newcmd]} {
|
||||
tclLog $newcmd
|
||||
history change $newcmd 0
|
||||
uplevel 1 [list ::catch $newcmd \
|
||||
::tcl::UnknownResult ::tcl::UnknownOptions]
|
||||
dict incr ::tcl::UnknownOptions -level
|
||||
return -options $::tcl::UnknownOptions $::tcl::UnknownResult
|
||||
}
|
||||
|
||||
set ret [catch {set candidates [info commands $name*]} msg]
|
||||
if {$name eq "::"} {
|
||||
set name ""
|
||||
}
|
||||
if {$ret != 0} {
|
||||
dict append opts -errorinfo \
|
||||
"\n (expanding command prefix \"$name\" in unknown)"
|
||||
return -options $opts $msg
|
||||
}
|
||||
# Filter out bogus matches when $name contained
|
||||
# a glob-special char [Bug 946952]
|
||||
if {$name eq ""} {
|
||||
# Handle empty $name separately due to strangeness
|
||||
# in [string first] (See RFE 1243354)
|
||||
set cmds $candidates
|
||||
} else {
|
||||
set cmds [list]
|
||||
foreach x $candidates {
|
||||
if {[string first $name $x] == 0} {
|
||||
lappend cmds $x
|
||||
}
|
||||
}
|
||||
}
|
||||
if {[llength $cmds] == 1} {
|
||||
uplevel 1 [list ::catch [lreplace $args 0 0 [lindex $cmds 0]] \
|
||||
::tcl::UnknownResult ::tcl::UnknownOptions]
|
||||
dict incr ::tcl::UnknownOptions -level
|
||||
return -options $::tcl::UnknownOptions $::tcl::UnknownResult
|
||||
}
|
||||
if {[llength $cmds]} {
|
||||
return -code error "ambiguous command name \"$name\": [lsort $cmds]"
|
||||
}
|
||||
}
|
||||
return -code error "invalid command name \"$name\""
|
||||
}
|
||||
|
||||
namespace unknown sta_unknown
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ libverilog_la_SOURCES = \
|
|||
|
||||
VerilogLex.ll: VerilogParse.hh
|
||||
|
||||
VerilogLex.cc: VerilogLex.ll
|
||||
$(LEX) $(LFLAGS) -o VerilogLex.cc --prefix=VerilogLex_ --header-file=VerilogLex.hh VerilogLex.ll
|
||||
|
||||
# Rules to support automake pre 1.12 that name header .h instead of .hh
|
||||
VerilogParse.hh: VerilogParse.cc
|
||||
if test -f VerilogParse.h; then \
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@ verilogFlushBuffer()
|
|||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option prefix="VerilogLex_"
|
||||
%option outfile="lex.yy.c"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
|
|
|
|||
Loading…
Reference in New Issue