diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d86545b..e62cef91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,6 +215,7 @@ set(STA_SOURCE # Source files. set(STA_TCL_FILES + tcl/Init.tcl tcl/Util.tcl tcl/Graph.tcl tcl/Liberty.tcl @@ -384,6 +385,31 @@ add_custom_command(OUTPUT ${STA_TCL_INIT} # Do not use REQUIRED because it also requires TK, which is not used by OpenSTA. find_package(TCL) +option(USE_TCL_READLINE "Use TCL readliine package") + +set(TCL_READLINE 0) +# check for tclReadline +if (USE_TCL_READLINE) + find_library(TCL_READLINE_LIBRARY tclreadline) + if (TCL_READLINE_LIBRARY) + message(STATUS "TCL readline: ${TCL_READLINE_LIBRARY}") + # Referenced by StaConfig.hh.cmake + set(TCL_READLINE 1) + + get_filename_component(TCL_READLINE_LIB_DIR "${TCL_READLINE_LIBRARY}" PATH) + get_filename_component(TCL_READLINE_LIB_PARENT "${TCL_READLINE_LIB_DIR}" PATH) + find_file(TCL_READLINE_HEADER tclreadline.h + PATHS ${TCL_READLINE_LIB_PARENT} + PATH_SUFFIXES include + NO_DEFAULT_PATH + ) + message(STATUS "TCL readline header: ${TCL_READLINE_HEADER}") + get_filename_component(TCL_READLINE_INCLUDE "${TCL_READLINE_HEADER}" PATH) + else() + message(STATUS "TCL readline: not found") + endif() +endif() + # Zlib include(FindZLIB) @@ -409,7 +435,7 @@ if (USE_CUDD) if (CUDD_HEADER) get_filename_component(CUDD_INCLUDE "${CUDD_HEADER}" PATH) message(STATUS "CUDD header: ${CUDD_HEADER}") - # CUDD referenced by StaConfig.hh.cmake + # Referenced by StaConfig.hh.cmake set(CUDD 1) else() message(STATUS "CUDD header: not found") @@ -460,6 +486,7 @@ target_include_directories(OpenSTA PUBLIC include ${TCL_INCLUDE_PATH} + ${TCL_READLINE_INCLUDE} PRIVATE include/sta @@ -497,6 +524,10 @@ target_link_libraries(sta ${CMAKE_THREAD_LIBS_INIT} ) +if (TCL_READLINE_LIBRARY) + target_link_libraries(sta ${TCL_READLINE_LIBRARY}) +endif() + if (ZLIB_LIBRARIES) target_link_libraries(sta ${ZLIB_LIBRARIES}) endif() diff --git a/README.md b/README.md index 5afe6f50..4f91116f 100644 --- a/README.md +++ b/README.md @@ -79,10 +79,24 @@ are illegal in c++17. These packages are **optional**: ``` -libz 1.1.4 1.2.5 1.2.8 -cudd 2.4.1 3.0.0 +tclreadline 2.3.8 +libz 1.1.4 1.2.5 1.2.8 +cudd 2.4.1 3.0.0 ``` +The [TCL readline library](https://tclreadline.sourceforge.net/tclreadline.html) +links the GNU readline library to the TCL interpreter for command line editing +On OSX, Homebrew does not support tclreadline, but the macports system does +(see https://www.macports.org). To enable TCL readline support use the following +Cmake option: + +``` +cmake .. -DUSE_TCL_READLINE=ON +``` + +The Zlib library is an optional. If CMake finds libz, OpenSTA can +read Verilog, SDF, SPF, and SPEF files compressed with gzip. + CUDD is a binary decision diageram (BDD) package that is used to improve conditional timing arc handling. OpenSTA does not require it to be installed. It is available @@ -109,9 +123,6 @@ cd /build cmake .. -DUSE_CUDD=ON -DCUDD_DIR=$HOME/cudd ``` -The Zlib library is an optional. If CMake finds libz, OpenSTA can -read Verilog, SDF, SPF, and SPEF files compressed with gzip. - ### Installing with CMake Use the following commands to checkout the git repository and build the diff --git a/app/Main.cc b/app/Main.cc index dfcb242c..fcdf978f 100644 --- a/app/Main.cc +++ b/app/Main.cc @@ -15,15 +15,17 @@ // along with this program. If not, see . #include "StaMain.hh" +#include "StaConfig.hh" // STA_VERSION #include #include // exit #include +#if TCL_READLINE + #include +#endif -#include "StaConfig.hh" // STA_VERSION #include "Sta.hh" - namespace sta { extern const char *tcl_inits[]; } @@ -109,7 +111,16 @@ staTclAppInit(int argc, Tcl_Interp *interp) { // source init.tcl - Tcl_Init(interp); + if (Tcl_Init(interp) == TCL_ERROR) + return TCL_ERROR; + +#if TCL_READLINE + if (Tclreadline_Init(interp) == TCL_ERROR) + return TCL_ERROR; + Tcl_StaticPackage(interp, "tclreadline", Tclreadline_Init, Tclreadline_SafeInit); + if (Tcl_EvalFile(interp, TCLRL_LIBRARY "/tclreadlineInit.tcl") != TCL_OK) + printf("Failed to load tclreadline.tcl\n"); +#endif initStaApp(argc, argv, interp); @@ -146,7 +157,11 @@ staTclAppInit(int argc, } } } +#if TCL_READLINE + return Tcl_Eval(interp, "::tclreadline::Loop"); +#else return TCL_OK; +#endif } static void @@ -166,9 +181,7 @@ initStaApp(int &argc, Sta_Init(interp); // Eval encoded sta TCL sources. evalTclInit(interp, tcl_inits); - // Import exported commands from sta namespace to global namespace. - Tcl_Eval(interp, "sta::define_sta_cmds"); - Tcl_Eval(interp, "namespace import sta::*"); + Tcl_Eval(interp, "init_sta"); } static void diff --git a/app/sta.noreadline b/app/sta.noreadline new file mode 100755 index 00000000..4c3aecd3 Binary files /dev/null and b/app/sta.noreadline differ diff --git a/cmake/FindTCL.cmake b/cmake/FindTCL.cmake index cae33773..52fd8495 100644 --- a/cmake/FindTCL.cmake +++ b/cmake/FindTCL.cmake @@ -33,7 +33,7 @@ if (NOT TCL_LIB_PATHS) set(TCL_LIB_PATHS /usr/local/lib /opt/homebrew/opt/tcl-tk/lib) set(TCL_NO_DEFAULT_PATH TRUE) elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(TCL_LIB_PATHS /usr/lib /usr/local/lib) + set(TCL_LIB_PATHS /usr/lib /usr/lib64 /usr/local/lib) set(TCL_NO_DEFAULT_PATH FALSE) endif() endif() diff --git a/doc/ApiChanges.txt b/doc/ApiChanges.txt index 681f6b8d..79388b33 100644 --- a/doc/ApiChanges.txt +++ b/doc/ApiChanges.txt @@ -17,7 +17,7 @@ This file summarizes STA API changes for each release. Release 2.3.1 2022/06/12 - +------------------------- LibertyCellTimingArcSetIterator has been removed. Use range iteration as shown below: for (TimingArcSet *arc_set : cell->timingArcSets()) @@ -31,11 +31,12 @@ LibertyCellSequentialIterator has been removed. for (Sequential *seq : cell->sequentials()) Release 2.1.1 2020/12/13 +------------------------- Report::error, Report::warn functions now take a unique message ID as a first argument. InternalError has been renamed Report::cricical. Release 2.1.0 2020/04/05 - +------------------------- All public headers files have been moved to include/sta. The following iterators have been removed. diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index 14101458..89520094 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -7,6 +7,11 @@ The report_parasitics_annotation command reports SPEF annotation completeness. report_parasitics_annotation [-report_unannotated] +Release 2.3.3 2022/09/24 +------------------------- + +TCL readline support added. See README.md for build instructions. + Release 2.3.2 2022/07/03 ------------------------- diff --git a/tcl/Init.tcl b/tcl/Init.tcl new file mode 100644 index 00000000..f03b461a --- /dev/null +++ b/tcl/Init.tcl @@ -0,0 +1,33 @@ +# OpenSTA, Static Timing Analyzer +# Copyright (c) 2022, 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 . + +proc init_sta {} { + global auto_index + + # Import exported commands from sta namespace to global namespace. + sta::define_sta_cmds + namespace import sta::* + + if { [info exists tclreadline::version] } { + history + history event + eval $auto_index(::tclreadline::ScriptCompleter) + ::tclreadline::readline builtincompleter true + ::tclreadline::readline customcompleter ::tclreadline::ScriptCompleter + proc ::tclreadline::prompt1 {} { return {% } } + proc ::tclreadline::prompt2 {} { return {> } } + } +} diff --git a/tcl/Util.tcl b/tcl/Util.tcl index e9697a44..1f6af40b 100644 --- a/tcl/Util.tcl +++ b/tcl/Util.tcl @@ -437,16 +437,6 @@ proc sta_unknown { args } { return -code error \ "ambiguous command name \"$name\": [lsort $cmds]" } - } else { - # I cannot figure out why the first call to ::history add - # that presumably loads history.tcl causes the following error: - # Error: history.tcl, 306 invoked "return" outside of a proc. - # But this squashes the error. - if { [lindex $args 0] == "::history" } { - return "" - } else { - return [uplevel 1 builtin_unknown $args] - } } } } diff --git a/util/StaConfig.hh.cmake b/util/StaConfig.hh.cmake index dc4ae102..137c35ef 100644 --- a/util/StaConfig.hh.cmake +++ b/util/StaConfig.hh.cmake @@ -7,3 +7,5 @@ #define CUDD ${CUDD} #define SSTA ${SSTA} + +#define TCL_READLINE ${TCL_READLINE}