From 9435640d5aa9a8c8dec8a163285c7ba91f34681d Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 1 Jan 2019 12:25:25 -0800 Subject: [PATCH] write_spice alpha --- .gitignore | 21 +- INSTALL | 33 + app/Makefile.am | 2 +- configure.ac | 40 +- doc/OpenSTA.odt | Bin 72212 -> 72183 bytes etc/TclEncode.tcl | 9 +- graph/DelayNormal2.hh | 4 +- liberty/Liberty.cc | 6 +- liberty/Liberty.hh | 5 +- liberty/LibertyReader.cc | 3 +- parasitics/ConcreteParasitics.cc | 12 + parasitics/ConcreteParasitics.hh | 4 + parasitics/ConcreteParasiticsPvt.hh | 4 +- parasitics/Parasitics.hh | 4 + search/Makefile.am | 6 +- search/PathExpanded.cc | 5 + search/PathExpanded.hh | 5 +- search/WriteSpice.cc | 946 ++++++++++++++++++++++++++++ search/WriteSpice.hh | 37 ++ tcl/StaTcl.i | 14 + tcl/Util.tcl | 180 +++++- util/Vector.hh | 1 + 22 files changed, 1270 insertions(+), 71 deletions(-) create mode 100644 search/WriteSpice.cc create mode 100644 search/WriteSpice.hh diff --git a/.gitignore b/.gitignore index 37210dd6..8730b7a1 100644 --- a/.gitignore +++ b/.gitignore @@ -18,12 +18,16 @@ Makefile.in .libs .deps -# / /build /configure /m4 /compile -/config.* +/config.h +/config.guess +/config.h.in +/config.log +/config.sub +/config.status /libtool /ltmain.sh /install-sh @@ -50,9 +54,11 @@ Makefile.in # /liberty/ /liberty/LibertyExprLex.cc +/liberty/LibertyExprLex.hh /liberty/LibertyExprParse.cc /liberty/LibertyExprParse.h /liberty/LibertyLex.cc +/liberty/LibertyLex.hh /liberty/LibertyParse.cc /liberty/LibertyParse.h /liberty/LibertyExprParse.hh @@ -60,18 +66,18 @@ Makefile.in # /parasitics/ /parasitics/SpefLex.cc +/parasitics/SpefLex.hh /parasitics/SpefParse.cc -/parasitics/SpefParse.h -/parasitics/SpfLex.cc -/parasitics/SpfParse.cc -/parasitics/SpfParse.h /parasitics/SpefParse.hh +/parasitics/SpfLex.cc +/parasitics/SpfLex.hh +/parasitics/SpfParse.cc /parasitics/SpfParse.hh # /sdf/ /sdf/SdfLex.cc +/sdf/SdfLex.hh /sdf/SdfParse.cc -/sdf/SdfParse.h /sdf/SdfParse.hh # /tcl/ @@ -85,6 +91,7 @@ Makefile.in /test_native # /verilog/ +/verilog/VerilogLex.hh /verilog/VerilogLex.cc /verilog/VerilogParse.cc /verilog/VerilogParse.h diff --git a/INSTALL b/INSTALL index 239eea33..d41da109 100644 --- a/INSTALL +++ b/INSTALL @@ -148,3 +148,36 @@ 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= 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= + +or use the DESTDIR variable with make. + + make DESTDIR= install diff --git a/app/Makefile.am b/app/Makefile.am index d63620f4..fd7b30a1 100644 --- a/app/Makefile.am +++ b/app/Makefile.am @@ -42,7 +42,7 @@ StaApp_wrap.cc: $(SWIG_DEPEND) StaApp.i ../verilog/Verilog.i # so that they do not have to be installed on the client host. TclInitVar.cc: ../etc/TclEncode.tcl $(TCL_INIT_FILES) - ../etc/TclEncode.tcl TclInitVar.cc "tcl_inits" $(TCL_INIT_DIR) \ + ../etc/TclEncode.tcl TclInitVar.cc "tcl_inits" \ $(TCL_INIT_FILES) ../verilog/Verilog.tcl EXTRA_DIST = \ diff --git a/configure.ac b/configure.ac index d42cb79f..3b405290 100644 --- a/configure.ac +++ b/configure.ac @@ -50,7 +50,6 @@ case "${HOST_OS}" in INCLUDE_DIRS="/usr/include" LIB_DIRS="/usr/lib /usr/local/lib /usr/lib/i386-linux-gnu" LIB_EXTS="a so .so.1" - TCL_INIT_DIRS="/usr/lib/tcl /usr/lib /usr/share/tcltk" ;; x86_64) @@ -58,7 +57,6 @@ case "${HOST_OS}" in INCLUDE_DIRS="/usr/include" LIB_DIRS="/usr/lib64 /usr/lib /usr/lib/x86_64-linux-gnu" LIB_EXTS="a so" - TCL_INIT_DIRS="/usr/lib64/tcl /usr/lib /usr/share/tcltk /usr/share" ;; *) @@ -66,7 +64,6 @@ case "${HOST_OS}" in INCLUDE_DIRS="/usr/include" LIB_DIRS="/usr/lib" LIB_EXTS="a so" - TCL_INIT_DIRS="/usr/lib/tcl /usr/lib" ;; esac ;; @@ -76,7 +73,6 @@ case "${HOST_OS}" in INCLUDE_DIRS="/usr/include" LIB_DIRS="/usr/lib" LIB_EXTS="a so" - TCL_INIT_DIRS="/usr/share" ;; Darwin) @@ -88,14 +84,12 @@ case "${HOST_OS}" in CC=clang++ INCLUDE_DIRS="/usr/local/include /usr/include" LIB_DIRS="/usr/local/lib /usr/lib" - TCL_INIT_DIRS="/usr/local/lib/tcl8.6" else # gcc CXX=g++ CC=g++ INCLUDE_DIRS="/usr/local/opt/tcl-tk/include /usr/local/opt/zlib/include /usr/include" LIB_DIRS="/usr/local/opt/tcl-tk/lib /usr/local/opt/zlib/lib /usr/local/lib" - TCL_INIT_DIRS="/usr/local/opt/tcl-tk/lib/tcl8.6" fi LIB_EXTS="dylib" ;; @@ -105,7 +99,6 @@ case "${HOST_OS}" in INCLUDE_DIRS="/usr/include /usr/local/include" LIB_DIRS="/usr/lib /usr/local/lib" LIB_EXTS="a so" - TCL_INIT_DIRS="/usr/lib/tcl /usr/share /usr/share/tcl" ;; esac @@ -167,11 +160,6 @@ AC_ARG_WITH(lib, [LIB_DIRS="${withval}"], []) -AC_ARG_WITH(tcl, - [AS_HELP_STRING([--with-tcl=dirs],[directories to search for Tcl init files])], - [TCL_INIT_DIRS="${withval}"], - []) - AC_ARG_WITH(cudd, [AS_HELP_STRING([--with-cudd=path],[use CUDD BDD package, defaults to $CUDD])], [CUDD_ARG="${withval}"], @@ -274,39 +262,13 @@ for tcl_minor in $tcl_minors; do AC_MSG_RESULT(not found) fi - AC_MSG_CHECKING(for Tcl $tcl_major.$tcl_minor init files) - TCL_INIT_DIR="" - for dir in $TCL_INIT_DIRS ; do - init_dir=$dir - init_path="$dir/init.tcl" - if test -r $init_path; then - AC_MSG_RESULT($init_path) - TCL_INIT_DIR="$init_dir" - break - fi - - init_dir="$dir/tcl$tcl_major.$tcl_minor" - init_path="$init_dir/init.tcl" - if test -r $init_path; then - AC_MSG_RESULT($init_path) - TCL_INIT_DIR="$init_dir" - break - fi - done - if test -z "$TCL_INIT_DIR"; then - AC_MSG_RESULT(not found) - fi - if test $found_tcl_header = true && - test -n "$TCL_LIB" && - test -n "$TCL_INIT_DIR"; then + test -n "$TCL_LIB"; then break fi done -AC_SUBST(TCL_INIT_DIR, $TCL_INIT_DIR) - #-------------------------------------------------------------------- # Locate the Zlib package #-------------------------------------------------------------------- diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index bc0eec2680dc6105ec9047af731eab0faffad165..411c8025a1c4ebb0558ac2626ee1023e34e229a1 100644 GIT binary patch delta 40898 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

    =RWOAE3D14Yx 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±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. -#ifndef STA_DELAY_FLOAT_CLASS_H -#define STA_DELAY_FLOAT_CLASS_H +#ifndef STA_DELAY_NORMAL2_H +#define STA_DELAY_NORMAL2_H #include "MinMax.hh" diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 3afe7c5d..55915c70 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -2714,10 +2714,12 @@ OcvDerate::setDerateTable(const TransRiseFall *tr, //////////////////////////////////////////////////////////////// -LibertyPgPort::LibertyPgPort(const char *name) : +LibertyPgPort::LibertyPgPort(const char *name, + LibertyCell *cell) : name_(stringCopy(name)), pg_type_(unknown), - voltage_name_(NULL) + voltage_name_(NULL), + cell_(cell) { } diff --git a/liberty/Liberty.hh b/liberty/Liberty.hh index d705aa62..eae35871 100644 --- a/liberty/Liberty.hh +++ b/liberty/Liberty.hh @@ -1021,9 +1021,11 @@ public: internal_power, internal_ground, nwell, pwell, deepnwell, deeppwell}; - LibertyPgPort(const char *name); + LibertyPgPort(const char *name, + LibertyCell *cell); ~LibertyPgPort(); const char *name() { return name_; } + LibertyCell *cell() const { return cell_; } PgType pgType() const { return pg_type_; } void setPgType(PgType type); const char *voltageName() const { return voltage_name_; } @@ -1033,6 +1035,7 @@ private: const char *name_; PgType pg_type_; const char *voltage_name_; + LibertyCell *cell_; }; } // namespace diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index ab92fb6c..9a9408e2 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -289,7 +289,6 @@ LibertyReader::defineVisitors() &LibertyReader::endScaledCell); defineAttrVisitor("clock_gating_integrated_cell", &LibertyReader::visitClockGatingIntegratedCell); - defineAttrVisitor("area", &LibertyReader::visitArea); defineAttrVisitor("dont_use", &LibertyReader::visitDontUse); defineAttrVisitor("is_macro", &LibertyReader::visitIsMacro); @@ -4730,7 +4729,7 @@ LibertyReader::beginPgPin(LibertyGroup *group) { if (cell_) { const char *name = group->firstName(); - pg_port_ = new LibertyPgPort(name); + pg_port_ = new LibertyPgPort(name, cell_); cell_->addPgPort(pg_port_); } } diff --git a/parasitics/ConcreteParasitics.cc b/parasitics/ConcreteParasitics.cc index cbaa87e0..2e428844 100644 --- a/parasitics/ConcreteParasitics.cc +++ b/parasitics/ConcreteParasitics.cc @@ -1885,6 +1885,18 @@ ConcreteParasitics::value(const ParasiticDevice *device, return cdevice->value(); } +void +ConcreteParasitics::resistorNodes(const ParasiticDevice *device, + // Return values. + ParasiticNode *&node1, + ParasiticNode *&node2) const +{ + const ConcreteParasiticResistor *cdevice = + static_cast(device); + node1 = cdevice->node1(); + node2 = cdevice->node2(); +} + ParasiticNode * ConcreteParasitics::otherNode(const ParasiticDevice *device, ParasiticNode *node) const diff --git a/parasitics/ConcreteParasitics.hh b/parasitics/ConcreteParasitics.hh index 8a1b9949..868999ed 100644 --- a/parasitics/ConcreteParasitics.hh +++ b/parasitics/ConcreteParasitics.hh @@ -175,6 +175,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; diff --git a/parasitics/ConcreteParasiticsPvt.hh b/parasitics/ConcreteParasiticsPvt.hh index f92a6c47..16fa5967 100644 --- a/parasitics/ConcreteParasiticsPvt.hh +++ b/parasitics/ConcreteParasiticsPvt.hh @@ -322,8 +322,8 @@ public: virtual ParasiticNode *otherNode(ParasiticNode *node) const; virtual void replaceNode(ConcreteParasiticNode *from_node, ConcreteParasiticNode *to_node); - ConcreteParasiticNode *node1() { return node_; } - ConcreteParasiticNode *node2() { return other_node_; } + ConcreteParasiticNode *node1() const { return node_; } + ConcreteParasiticNode *node2() const { return other_node_; } private: ConcreteParasiticNode *other_node_; diff --git a/parasitics/Parasitics.hh b/parasitics/Parasitics.hh index 95561550..b6362919 100644 --- a/parasitics/Parasitics.hh +++ b/parasitics/Parasitics.hh @@ -248,6 +248,10 @@ 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 *otherNode(const ParasiticDevice *device, ParasiticNode *node) const = 0; diff --git a/search/Makefile.am b/search/Makefile.am index 2ccddb94..6742ab81 100644 --- a/search/Makefile.am +++ b/search/Makefile.am @@ -56,7 +56,8 @@ include_HEADERS = \ VertexVisitor.hh \ VisitPathEnds.hh \ VisitPathGroupVertices.hh \ - WorstSlack.hh + WorstSlack.hh \ + WriteSpice.hh libsearch_la_SOURCES = \ Bfs.cc \ @@ -97,7 +98,8 @@ libsearch_la_SOURCES = \ VertexVisitor.cc \ VisitPathEnds.cc \ VisitPathGroupVertices.cc \ - WorstSlack.cc + WorstSlack.cc \ + WriteSpice.cc libs: $(lib_LTLIBRARIES) diff --git a/search/PathExpanded.cc b/search/PathExpanded.cc index 3be4cc17..6345634a 100644 --- a/search/PathExpanded.cc +++ b/search/PathExpanded.cc @@ -27,6 +27,11 @@ namespace sta { +PathExpanded::PathExpanded(const StaState *sta) : + sta_(sta) +{ +} + PathExpanded::PathExpanded(const Path *path, // Expand generated clk source paths. bool expand_genclks, diff --git a/search/PathExpanded.hh b/search/PathExpanded.hh index 6467ec69..b0982684 100644 --- a/search/PathExpanded.hh +++ b/search/PathExpanded.hh @@ -28,6 +28,7 @@ namespace sta { class PathExpanded { public: + PathExpanded(const StaState *sta); // Expand path for lookup by index. PathExpanded(const Path *path, const StaState *sta); @@ -35,6 +36,8 @@ public: // Expand generated clk source paths. bool expand_genclks, const StaState *sta); + void expand(const Path *path, + bool expand_genclks); size_t size() const { return paths_.size(); } // path(0) is the startpoint. // path(size()-1) is the endpoint. @@ -55,8 +58,6 @@ public: Edge *&d_q_edge); protected: - void expand(const Path *path, - bool expand_genclks); void expandGenclk(PathRef *clk_path); // Convert external index that starts at the path root // and increases to an index for paths_ (reversed). diff --git a/search/WriteSpice.cc b/search/WriteSpice.cc new file mode 100644 index 00000000..a3a9ea08 --- /dev/null +++ b/search/WriteSpice.cc @@ -0,0 +1,946 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2018, 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 . + +#include +#include +#include +#include +#include "Machine.hh" +#include "Debug.hh" +#include "Error.hh" +#include "Report.hh" +#include "StringUtil.hh" +#include "FuncExpr.hh" +#include "Liberty.hh" +#include "TimingArc.hh" +#include "Network.hh" +#include "Graph.hh" +#include "Sdc.hh" +#include "DcalcAnalysisPt.hh" +#include "Parasitics.hh" +#include "PathAnalysisPt.hh" +#include "Path.hh" +#include "PathRef.hh" +#include "PathExpanded.hh" +#include "StaState.hh" +#include "WriteSpice.hh" + +namespace sta { + +using std::string; +using std::ofstream; +using std::ifstream; + +typedef Vector StringVector; +typedef Map CellSpicePortNames; +typedef int Stage; +typedef Map ParasiticNodeMap; + +void +split(const string &text, + const string &delims, + // Return values. + StringVector &tokens); +void +streamPrint(ofstream &stream, + const char *fmt, + ...) __attribute__((format (printf, 2, 3))); +void +stringPrint(string &str, + const char *fmt, + ...) __attribute__((format (printf, 2, 3))); + +//////////////////////////////////////////////////////////////// + +class WriteSpice : public StaState +{ +public: + WriteSpice(Path *path, + const char *spice_filename, + const char *subckts_filename, + const char *lib_subckts_filename, + const char *models_filename, + const StaState *sta); + ~WriteSpice(); + void writeSpice();; + +private: + void writeHeader(); + void writeStageInstances(); + void writeInputSource(); + void writeStageSubckts(); + void writeInputStage(Stage stage); + void writeMeasureStmts(); + void writeGateStage(Stage stage); + void writeStageVoltageSources(LibertyCell *cell, + StringVector *spice_port_names, + const char *inst_name, + LibertyPort *from_port, + LibertyPort *drvr_port); + void writeStageParasitics(Stage stage); + void writeSubckts(); + void findPathCellnames(// Return values. + StringSet &path_cell_names); + void recordSpicePortNames(const char *cell_name, + StringVector &tokens); + float pgPortVoltage(const char *pg_port_name, + LibertyCell *cell); + float pgPortVoltage(LibertyPgPort *pg_port); + float maxTime(); + const char *nodeName(ParasiticNode *node); + void initNodeMap(const char *net_name); + + // Stage "accessors". + // Internally a stage index from stageFirst() to stageLast() + // is turned into an index into path_expanded_. + Stage stageFirst(); + Stage stageLast(); + string stageName(Stage stage); + int stageGateInputPathIndex(Stage stage); + int stageDrvrPathIndex(Stage stage); + int stageLoadPathIndex(Stage stage); + PathRef *stageGateInputPath(Stage stage); + PathRef *stageDrvrPath(Stage stage); + PathRef *stageLoadPath(Stage stage); + TimingArc *stageGateArc(Stage stage); + TimingArc *stageWireArc(Stage stage); + Edge *stageGateEdge(Stage stage); + Edge *stageWireEdge(Stage stage); + Pin *stageInputPin(Stage stage); + Pin *stageDrvrPin(Stage stage); + Pin *stageLoadPin(Stage stage); + const char *stageInputPinName(Stage stage); + const char *stageDrvrPinName(Stage stage); + const char *stageLoadPinName(Stage stage); + + Path *path_; + const char *spice_filename_; + const char *subckts_filename_; + const char *lib_subckts_filename_; + const char *models_filename_; + + ofstream spice_stream_; + PathExpanded path_expanded_; + CellSpicePortNames cell_spice_port_names_; + ParasiticNodeMap node_map_; + int next_node_index_; + const char *net_name_; + + // Resistance to use to simulate a short circuit between spice nodes. + static const float short_ckt_resistance_; +}; + +//////////////////////////////////////////////////////////////// + +class SubcktEndsMissing : public StaException +{ +public: + SubcktEndsMissing(const char *cell_name, + const char *subckt_filename);; + const char *what() const throw(); + +protected: + string what_; +}; + +SubcktEndsMissing::SubcktEndsMissing(const char *cell_name, + const char *subckt_filename) +{ + what_ = "Error: spice subckt for cell "; + what_ += cell_name; + what_ += " missing .ends in "; + what_ += subckt_filename; +} + +const char * +SubcktEndsMissing::what() const throw() +{ + return what_.c_str(); +} + +//////////////////////////////////////////////////////////////// + +void +writeSpice (Path *path, + const char *spice_filename, + const char *subckts_filename, + const char *lib_subckts_filename, + const char *models_filename, + StaState *sta) +{ + WriteSpice writer(path, spice_filename, subckts_filename, + lib_subckts_filename, models_filename, sta); + writer.writeSpice(); +} + +const float WriteSpice::short_ckt_resistance_ = .0001; + +WriteSpice::WriteSpice(Path *path, + const char *spice_filename, + const char *subckts_filename, + const char *lib_subckts_filename, + const char *models_filename, + const StaState *sta) : + StaState(sta), + path_(path), + spice_filename_(spice_filename), + subckts_filename_(subckts_filename), + lib_subckts_filename_(lib_subckts_filename), + models_filename_(models_filename), + path_expanded_(sta), + net_name_(NULL) +{ +} + +WriteSpice::~WriteSpice() +{ + cell_spice_port_names_.deleteContents(); +} + +void +WriteSpice::writeSpice() +{ + spice_stream_.open(spice_filename_); + if (spice_stream_.is_open()) { + path_expanded_.expand(path_, true); + // Find subckt port names as a side-effect of writeSubckts. + writeSubckts(); + writeHeader(); + writeStageInstances(); + writeInputSource(); + writeStageSubckts(); + streamPrint(spice_stream_, ".end\n"); + spice_stream_.close(); + } + else + throw FileNotWritable(spice_filename_); +} + +void +WriteSpice::writeHeader() +{ + const MinMax *min_max = path_->minMax(this); + const Pvt *pvt = sdc_->operatingConditions(min_max); + if (pvt == NULL) + pvt = network_->defaultLibertyLibrary()->defaultOperatingConditions(); + float temp = pvt->temperature(); + streamPrint(spice_stream_, ".temp %.1f\n", temp); + streamPrint(spice_stream_, ".include \"%s\"\n", models_filename_); + streamPrint(spice_stream_, ".include \"%s\"\n", subckts_filename_); + + float max_time = maxTime(); + float time_step = max_time / 1e+3; + streamPrint(spice_stream_, ".tran %.3g %.3g\n\n", + time_step, max_time); +} + +float +WriteSpice::maxTime() +{ + float end_slew = path_->slew(this); + float max_time = (path_->arrival(this) + end_slew * 2) * 1.5; + return max_time; +} + +void +WriteSpice::writeStageInstances() +{ + streamPrint(spice_stream_, "*****************\n"); + streamPrint(spice_stream_, "* Stage instances\n"); + streamPrint(spice_stream_, "*****************\n\n"); + + for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { + const char *stage_name = stageName(stage).c_str(); + if (stage == stageFirst()) + streamPrint(spice_stream_, "x%s %s %s %s\n", + stage_name, + stageDrvrPinName(stage), + stageLoadPinName(stage), + stage_name); + else + streamPrint(spice_stream_, "x%s %s %s %s %s\n", + stage_name, + stageInputPinName(stage), + stageDrvrPinName(stage), + stageLoadPinName(stage), + stage_name); + } + streamPrint(spice_stream_, "\n"); +} + +float +WriteSpice::pgPortVoltage(const char *pg_port_name, + LibertyCell *cell) +{ + auto pg_port = cell->findPgPort(pg_port_name); + return pgPortVoltage(pg_port); +} + +float +WriteSpice::pgPortVoltage(LibertyPgPort *pg_port) +{ + auto cell = pg_port->cell(); + auto voltage_name = pg_port->voltageName(); + auto lib = cell->libertyLibrary(); + float voltage = lib->supplyVoltage(voltage_name); + return voltage; +} + +void +WriteSpice::writeInputSource() +{ + streamPrint(spice_stream_, "**************\n"); + streamPrint(spice_stream_, "* Input source\n"); + streamPrint(spice_stream_, "**************\n\n"); + + Stage input_stage = stageFirst(); + streamPrint(spice_stream_, "v1 %s 0 pwl(\n", + stageDrvrPinName(input_stage)); + auto wire_arc = stageWireArc(input_stage); + auto load_pin = stageLoadPin(input_stage); + auto cell = network_->libertyCell(network_->instance(load_pin)); + auto load_port = network_->libertyPort(load_pin); + const char *pg_gnd_port_name = load_port->relatedGroundPin(); + const char *pg_pwr_port_name = load_port->relatedPowerPin(); + auto gnd_volt = pgPortVoltage(pg_gnd_port_name, cell); + auto pwr_volt = pgPortVoltage(pg_pwr_port_name, cell); + float volt0, volt1; + if (wire_arc->fromTrans()->asRiseFall() == TransRiseFall::rise()) { + volt0 = gnd_volt; + volt1 = pwr_volt; + } + else { + volt0 = pwr_volt; + volt1 = gnd_volt; + } + float time0 = .1e-9; + float time1 = .2e-9; + streamPrint(spice_stream_, "+%.3e %.3e\n", 0.0, volt0); + streamPrint(spice_stream_, "+%.3e %.3e\n", time0, volt0); + streamPrint(spice_stream_, "+%.3e %.3e\n", time1, volt1); + streamPrint(spice_stream_, "+%.3e %.3e\n", maxTime(), volt1); + streamPrint(spice_stream_, "+)\n\n"); +} + +void +WriteSpice::writeMeasureStmts() +{ + streamPrint(spice_stream_, "********************\n"); + streamPrint(spice_stream_, "* Measure statements\n"); + streamPrint(spice_stream_, "********************\n\n"); +} + +void +WriteSpice::writeStageSubckts() +{ + streamPrint(spice_stream_, "***************\n"); + streamPrint(spice_stream_, "* Stage subckts\n"); + streamPrint(spice_stream_, "***************\n\n"); + + for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { + if (stage == stageFirst()) + writeInputStage(stage); + else + writeGateStage(stage); + } +} + +// Input port to first gate input. +void +WriteSpice::writeInputStage(Stage stage) +{ + // Input arc. + // External driver not handled. + auto drvr_pin_name = stageDrvrPinName(stage); + auto load_pin_name = stageLoadPinName(stage); + streamPrint(spice_stream_, ".subckt %s %s %s\n", + stageName(stage).c_str(), + drvr_pin_name, + load_pin_name); + writeStageParasitics(stage); + streamPrint(spice_stream_, ".ends\n\n"); +} + +// Gate and load parasitics. +void +WriteSpice::writeGateStage(Stage stage) +{ + auto input_pin = stageInputPin(stage); + auto input_pin_name = stageInputPinName(stage); + auto drvr_pin = stageDrvrPin(stage); + auto drvr_pin_name = stageDrvrPinName(stage); + auto load_pin_name = stageLoadPinName(stage); + streamPrint(spice_stream_, ".subckt stage%d %s %s %s\n", + stage, + input_pin_name, + drvr_pin_name, + load_pin_name); + Instance *inst = network_->instance(input_pin); + const char *inst_name = network_->pathName(inst); + LibertyCell *cell = network_->libertyCell(inst); + const char *cell_name = cell->name(); + auto spice_port_names = cell_spice_port_names_[cell_name]; + + // Instance subckt call. + streamPrint(spice_stream_, "x%s", inst_name); + StringVector::Iterator port_iter(spice_port_names); + while (port_iter.hasNext()) { + const char *subckt_port_name = port_iter.next().c_str(); + auto pin = network_->findPin(inst, subckt_port_name); + auto pg_port = cell->findPgPort(subckt_port_name); + const char *pin_name; + if (pin) { + pin_name = network_->pathName(pin); + streamPrint(spice_stream_, " %s", pin_name); + } + else if (pg_port) + streamPrint(spice_stream_, " %s/%s", inst_name, subckt_port_name); + } + streamPrint(spice_stream_, " %s\n", cell_name); + + writeStageVoltageSources(cell, spice_port_names, + inst_name, + network_->libertyPort(input_pin), + network_->libertyPort(drvr_pin)); + writeStageParasitics(stage); + streamPrint(spice_stream_, ".ends\n\n"); +} + +typedef Map LibertyPortLogicValues; + +// Find the logic values for expression inputs to enable paths from_port. +void +sensitizationValues(FuncExpr *expr, + LibertyPort *from_port, + // Return values. + LibertyPortLogicValues &port_values) +{ + switch (expr->op()) { + case FuncExpr::op_port: { + break; + } + case FuncExpr::op_not: { + sensitizationValues(expr->left(), from_port, port_values); + break; + } + case FuncExpr::op_or: { + FuncExpr *left = expr->left(); + FuncExpr *right = expr->right(); + if (left->port() == from_port + && right->op() == FuncExpr::op_port) + port_values[right->port()] = logic_zero; + else if (right->port() == from_port + && left->op() == FuncExpr::op_port) + port_values[left->port()] = logic_zero; + break; + } + case FuncExpr::op_and: { + FuncExpr *left = expr->left(); + FuncExpr *right = expr->right(); + if (left->port() == from_port + && right->op() == FuncExpr::op_port) + port_values[right->port()] = logic_one; + else if (right->port() == from_port + && left->op() == FuncExpr::op_port) + port_values[left->port()] = logic_one; + break; + } + case FuncExpr::op_xor: { + // Need to know timing arc sense to get this right. + FuncExpr *left = expr->left(); + FuncExpr *right = expr->right(); + if (left->port() == from_port + && right->op() == FuncExpr::op_port) + port_values[right->port()] = logic_zero; + else if (right->port() == from_port + && left->op() == FuncExpr::op_port) + port_values[left->port()] = logic_zero; + break; + } + case FuncExpr::op_one: + case FuncExpr::op_zero: + break; + } +} + +// Power/ground and input voltage sources. +void +WriteSpice::writeStageVoltageSources(LibertyCell *cell, + StringVector *spice_port_names, + const char *inst_name, + LibertyPort *from_port, + LibertyPort *drvr_port) +{ + auto from_port_name = from_port->name(); + auto drvr_port_name = drvr_port->name(); + LibertyLibrary *lib = cell->libertyLibrary(); + LibertyPortLogicValues port_values; + sensitizationValues(drvr_port->function(), from_port, port_values); + int volt_source = 1; + debugPrint1(debug_, "write_spice", 2, "subckt %s\n", cell->name()); + StringVector::Iterator port_iter(spice_port_names); + while (port_iter.hasNext()) { + auto subckt_port_name = port_iter.next().c_str(); + auto pg_port = cell->findPgPort(subckt_port_name); + debugPrint2(debug_, "write_spice", 2, " port %s%s\n", + subckt_port_name, + pg_port ? " pwr/gnd" : ""); + if (pg_port) { + auto voltage = pgPortVoltage(pg_port); + streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n", + volt_source, + inst_name, subckt_port_name, + voltage); + volt_source++; + } else if (!(stringEq(subckt_port_name, from_port_name) + || stringEq(subckt_port_name, drvr_port_name))) { + // Input voltage to sensitize path from gate input to output. + LibertyPort *port = cell->findLibertyPort(subckt_port_name); + if (port) { + const char *pg_port_name = NULL; + bool port_has_value; + LogicValue port_value; + port_values.findKey(port, port_value, port_has_value); + if (port_has_value) { + switch (port_value) { + case logic_zero: + pg_port_name = port->relatedGroundPin(); + break; + case logic_one: + pg_port_name = port->relatedPowerPin(); + break; + default: + break; + } + if (pg_port_name) { + auto pg_port = cell->findPgPort(pg_port_name); + if (pg_port) { + auto voltage_name = pg_port->voltageName(); + if (voltage_name) { + float voltage = lib->supplyVoltage(voltage_name); + streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n", + volt_source, + inst_name, subckt_port_name, + voltage); + volt_source++; + } + else + report_->error("port %s %s voltage %s not found,\n", + subckt_port_name, + pg_port_name, + voltage_name); + } + else + report_->error("port %s %s not found,\n", + subckt_port_name, + pg_port_name); + } + } + } + } + } +} + +typedef Set ParasiticDeviceSet; +typedef Set ParasiticNodeSet; + +void +findParasiticDevicesNodes(ParasiticNode *node, + Parasitics *parasitics, + // Return values. + ParasiticNodeSet &nodes, + ParasiticDeviceSet &devices) +{ + nodes.insert(node); + auto device_iter = parasitics->deviceIterator(node); + while (device_iter->hasNext()) { + auto device = device_iter->next(); + if (!devices.hasKey(device)) { + devices.insert(device); + auto other_node = parasitics->otherNode(device, node); + findParasiticDevicesNodes(other_node, parasitics, nodes, devices); + } + } + delete device_iter; +} + +void +WriteSpice::writeStageParasitics(Stage stage) +{ + auto drvr_path = stageDrvrPath(stage); + auto drvr_pin = stageDrvrPin(stage); + auto load_pin = stageLoadPin(stage); + auto dcalc_ap = drvr_path->dcalcAnalysisPt(this); + auto parasitic_ap = dcalc_ap->parasiticAnalysisPt(); + auto parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); + int resistor_index = 1; + int cap_index = 1; + if (parasitic) { + Net *net = network_->net(drvr_pin); + auto net_name = + net ? network_->pathName(net) : network_->pathName(drvr_pin); + initNodeMap(net_name); + streamPrint(spice_stream_, "* Net %s\n", net_name); + auto node = parasitics_->findNode(parasitic, drvr_pin); + ParasiticNodeSet nodes; + ParasiticDeviceSet devices; + findParasiticDevicesNodes(node, parasitics_, nodes, devices); + ParasiticDeviceSet::Iterator device_iter(devices); + while (device_iter.hasNext()) { + auto device = device_iter.next(); + auto resistance = parasitics_->value(device, parasitic_ap); + if (parasitics_->isResistor(device)) { + ParasiticNode *node1, *node2; + parasitics_->resistorNodes(device, node1, node2); + streamPrint(spice_stream_, "R%d %s %s %.3e\n", + resistor_index, + nodeName(node1), + nodeName(node2), + resistance); + resistor_index++; + } + else if (parasitics_->isCouplingCap(device)) { + } + } + ParasiticNodeSet::Iterator node_iter(nodes); + while (node_iter.hasNext()) { + auto node = node_iter.next(); + auto cap = parasitics_->nodeGndCap(node, parasitic_ap); + streamPrint(spice_stream_, "C%d %s 0 %.3e\n", + cap_index, + nodeName(node), + cap); + cap_index++; + } + } + else + streamPrint(spice_stream_, "R1 %s %s %.3e\n", + network_->pathName(drvr_pin), + network_->pathName(load_pin), + short_ckt_resistance_); +} + +void +WriteSpice::initNodeMap(const char *net_name) +{ + stringDelete(net_name_); + node_map_.clear(); + next_node_index_ = 1; + net_name_ = stringCopy(net_name); +} + +const char * +WriteSpice::nodeName(ParasiticNode *node) +{ + auto pin = parasitics_->connectionPin(node); + if (pin) + return parasitics_->name(node); + else { + int node_index; + bool node_index_exists; + node_map_.findKey(node, node_index, node_index_exists); + if (!node_index_exists) { + node_index = next_node_index_++; + node_map_[node] = node_index; + } + return stringPrintTmp(strlen(net_name_) + 10, "%s/%d", + net_name_, node_index); + } +} + +//////////////////////////////////////////////////////////////// + +// Copy the subckt definition from lib_subckts_filename for +// each cell in path to path_subckts_filename. +void +WriteSpice::writeSubckts() +{ + StringSet path_cell_names; + findPathCellnames(path_cell_names); + + ifstream lib_subckts_stream(lib_subckts_filename_); + if (lib_subckts_stream.is_open()) { + ofstream subckts_stream(subckts_filename_); + if (subckts_stream.is_open()) { + string line; + while (getline(lib_subckts_stream, line)) { + // .subckt [args..] + StringVector tokens; + split(line, " \t", tokens); + if (tokens.size() >= 2 + && stringEqual(tokens[0].c_str(), ".subckt")) { + const char *cell_name = tokens[1].c_str(); + if (path_cell_names.hasKey(cell_name)) { + subckts_stream << line << "\n"; + bool found_ends = false; + while (getline(lib_subckts_stream, line)) { + subckts_stream << line << "\n"; + if (stringEqual(line.c_str(), ".ends")) { + subckts_stream << "\n"; + found_ends = true; + break; + } + } + if (!found_ends) + throw SubcktEndsMissing(cell_name, lib_subckts_filename_); + path_cell_names.eraseKey(cell_name); + } + recordSpicePortNames(cell_name, tokens); + } + } + subckts_stream.close(); + lib_subckts_stream.close(); + + if (!path_cell_names.empty()) { + StringSet::Iterator cell_iter(path_cell_names); + report_->error("The following subkcts are missing from %s\n", + lib_subckts_filename_); + while (cell_iter.hasNext()) { + const char *cell_name = cell_iter.next(); + report_->printError(" %s\n", cell_name); + } + } + } + else { + lib_subckts_stream.close(); + throw FileNotWritable(subckts_filename_); + } + } + else + throw FileNotReadable(lib_subckts_filename_); +} + +void +WriteSpice::findPathCellnames(// Return values. + StringSet &path_cell_names) +{ + for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { + auto arc = stageGateArc(stage); + if (arc) { + LibertyCell *cell = arc->set()->libertyCell(); + if (cell) { + debugPrint1(debug_, "write_spice", 2, "cell %s\n", cell->name()); + path_cell_names.insert(cell->name()); + } + } + } +} + +void +WriteSpice::recordSpicePortNames(const char *cell_name, + StringVector &tokens) +{ + auto cell = network_->findLibertyCell(cell_name); + auto spice_port_names = new StringVector; + for (int i = 2; i < tokens.size(); i++) { + const char *port_name = tokens[i].c_str(); + auto port = cell->findLibertyPort(port_name); + auto pg_port = cell->findPgPort(port_name); + if (port == NULL && pg_port == NULL) + report_->error("subckt %s port %s has no corresponding liberty port or pg_port.\n", + cell_name, port_name); + spice_port_names->push_back(port_name); + } + cell_spice_port_names_[cell_name] = spice_port_names; +} + +//////////////////////////////////////////////////////////////// + +Stage +WriteSpice::stageFirst() +{ + return 1; +} + +Stage +WriteSpice::stageLast() +{ + return (path_expanded_.size() + 1) / 2; +} + +string +WriteSpice::stageName(Stage stage) +{ + string name; + stringPrint(name, "stage%d", stage); + return name; +} + +int +WriteSpice::stageGateInputPathIndex(Stage stage) +{ + return stage * 2 - 3; +} + +int +WriteSpice::stageDrvrPathIndex(Stage stage) +{ + return stage * 2 - 2; +} + +int +WriteSpice::stageLoadPathIndex(Stage stage) +{ + return stage * 2 - 1; +} + +PathRef * +WriteSpice::stageGateInputPath(Stage stage) +{ + int path_index = stageGateInputPathIndex(stage); + return path_expanded_.path(path_index); +} + +PathRef * +WriteSpice::stageDrvrPath(Stage stage) +{ + int path_index = stageDrvrPathIndex(stage); + return path_expanded_.path(path_index); +} + +PathRef * +WriteSpice::stageLoadPath(Stage stage) +{ + int path_index = stageLoadPathIndex(stage); + return path_expanded_.path(path_index); +} + +TimingArc * +WriteSpice::stageGateArc(Stage stage) +{ + int path_index = stageDrvrPathIndex(stage); + if (path_index >= 0) + return path_expanded_.prevArc(path_index); + else + return NULL; +} + +TimingArc * +WriteSpice::stageWireArc(Stage stage) +{ + int path_index = stageLoadPathIndex(stage); + return path_expanded_.prevArc(path_index); +} + +Edge * +WriteSpice::stageGateEdge(Stage stage) +{ + PathRef *path = stageGateInputPath(stage); + TimingArc *arc = stageGateArc(stage); + return path->prevEdge(arc, this); +} + +Edge * +WriteSpice::stageWireEdge(Stage stage) +{ + PathRef *path = stageLoadPath(stage); + TimingArc *arc = stageWireArc(stage); + return path->prevEdge(arc, this); +} + +Pin * +WriteSpice::stageInputPin(Stage stage) +{ + PathRef *path = stageGateInputPath(stage); + return path->pin(this); +} + +Pin * +WriteSpice::stageDrvrPin(Stage stage) +{ + PathRef *path = stageDrvrPath(stage); + return path->pin(this); +} + +Pin * +WriteSpice::stageLoadPin(Stage stage) +{ + PathRef *path = stageLoadPath(stage); + return path->pin(this); +} + +const char * +WriteSpice::stageInputPinName(Stage stage) +{ + const Pin *pin = stageInputPin(stage); + return network_->pathName(pin); +} + +const char * +WriteSpice::stageDrvrPinName(Stage stage) +{ + Pin *pin = stageDrvrPin(stage); + return network_->pathName(pin); +} + +const char * +WriteSpice::stageLoadPinName(Stage stage) +{ + const Pin *pin = stageLoadPin(stage); + return network_->pathName(pin); +} + +//////////////////////////////////////////////////////////////// + +void +split(const string &text, + const string &delims, + // Return values. + StringVector &tokens) +{ + auto start = text.find_first_not_of(delims); + auto end = text.find_first_of(delims, start); + while (end != string::npos) { + tokens.push_back(text.substr(start, end - start)); + start = text.find_first_not_of(delims, end); + end = text.find_first_of(delims, start); + } + if (start != string::npos) + tokens.push_back(text.substr(start)); +} + +// fprintf for c++ streams. +// Yes, I hate formatted output to ostream THAT much. +void +streamPrint(ofstream &stream, + const char *fmt, + ...) +{ + va_list args; + va_start(args, fmt); + char *result; + vasprintf(&result, fmt, args); + stream << result; + free(result); + va_end(args); +} + +// print for c++ strings. +void +stringPrint(string &str, + const char *fmt, + ...) +{ + va_list args; + va_start(args, fmt); + char *result; + vasprintf(&result, fmt, args); + str = result; + free(result); + va_end(args); +} + +} // namespace diff --git a/search/WriteSpice.hh b/search/WriteSpice.hh new file mode 100644 index 00000000..74c22b6b --- /dev/null +++ b/search/WriteSpice.hh @@ -0,0 +1,37 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2018, 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 . + +#ifndef STA_WRITE_SPICE_H +#define STA_WRITE_SPICE_H + +namespace sta { + +// Write a spice deck for path. +// Throws FileNotReadable, FileNotWritable, SubcktEndsMissing +void +writeSpice(Path *path, + // Spice file written for path. + const char *spice_filename, + // Subckts used by path included in spice file. + const char *subckts_filename, + // File of all cell spice subckt definitions. + const char *lib_subckts_filename, + // Device model file included in spice file. + const char *models_filename, + StaState *sta); + +} // namespace +#endif diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index caf13fa2..6e19a447 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -78,6 +78,7 @@ #include "ReportPath.hh" #include "Power.hh" #include "Property.hh" +#include "WriteSpice.hh" #include "Sta.hh" namespace sta { @@ -4585,6 +4586,19 @@ write_sdc_cmd(const char *filename, Sta::sta()->writeSdc(filename, native, no_timestamp, digits); } +void +write_spice(PathRef *path, + const char *spice_filename, + const char *subckts_filename, + const char *lib_subckts_filename, + const char *models_filename) +{ + cmdLinkedNetwork(); + Sta *sta = Sta::sta(); + writeSpice(path, spice_filename, subckts_filename, + lib_subckts_filename, models_filename, sta); +} + void set_cmd_unit_scale(const char *unit_name, float scale) diff --git a/tcl/Util.tcl b/tcl/Util.tcl index 926c4903..43d68db9 100644 --- a/tcl/Util.tcl +++ b/tcl/Util.tcl @@ -391,15 +391,13 @@ proc check_percent { cmd_arg arg } { ################################################################ # The builtin Tcl "source" and "unknown" commands are redefined by sta. -# The original definition is not clobbered until Final.tcl. # 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[*]. -proc unknown { args } { +proc sta_unknown { args } { global errorCode errorInfo set name [lindex $args 0] @@ -434,3 +432,179 @@ proc 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 diff --git a/util/Vector.hh b/util/Vector.hh index 3b1ac463..d83775ae 100644 --- a/util/Vector.hh +++ b/util/Vector.hh @@ -30,6 +30,7 @@ public: Vector() : std::vector() {} Vector(size_t n) : std::vector(n) {} Vector(size_t n, const OBJ &obj) : std::vector(n, obj) {} + // Erase an object from the vector (slow). void eraseObject(OBJ obj)