Merge branch 'pre-master-43' into bt_dev
This commit is contained in:
commit
4f4a303c3c
|
|
@ -0,0 +1,82 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# ngspice build script for Linux, release or debug version, 64 bit
|
||||||
|
# compile_linux.sh <d>
|
||||||
|
|
||||||
|
# Procedure:
|
||||||
|
# Install gcc, bison, flex, libtool, autoconf, automake,
|
||||||
|
# libx11 and libx11-dev (headers), libXaw and libXaw-dev, libreadline and dev
|
||||||
|
# xmu, xet, xt, libxft, libxrender, libfreetype, libfontconfig
|
||||||
|
# for details please see the ngspice manual, chapt. 32.1.
|
||||||
|
# Declare 'compile_linux.sh' executable and start compiling with
|
||||||
|
# './compile_linux.sh' or './compile_linux.sh d' from the ngspice directory.
|
||||||
|
# CentOS users may need to add -std=c99 to the CFLAGS in the ../configure
|
||||||
|
# statement.
|
||||||
|
# Options:
|
||||||
|
# --enable-osdi will enable the OSDI interface, which, in conjuction with the
|
||||||
|
# external OpenVAF Verilig-A compiler, will allow access to advanced compact
|
||||||
|
# device models writen in Verilog-A.
|
||||||
|
# Please see the ngspice manual, chapt. 13, for more info on using OSDI/OpenVAF.
|
||||||
|
# --enable-klu will add the new matrix solver in addition to Sparse 1.3.
|
||||||
|
# CIDER, XSPICE, KLU, and OpenMP may be selected at will.
|
||||||
|
# --disable-debug will give O2 optimization (versus O0 for debug) and removes all debugging info.
|
||||||
|
|
||||||
|
# ngspice as shared library:
|
||||||
|
# Replace --with-x by --with-ngshared in line ../configure ... .
|
||||||
|
# Add (optionally) --enable-relpath to avoid absolute paths when searching for code models.
|
||||||
|
# It might be necessary to uncomment and run ./autogen.sh .
|
||||||
|
|
||||||
|
SECONDS=0
|
||||||
|
|
||||||
|
if test "$1" = "d"; then
|
||||||
|
if [ ! -d "debug" ]; then
|
||||||
|
mkdir debug
|
||||||
|
if [ $? -ne 0 ]; then echo "mkdir debug failed"; exit 1 ; fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ ! -d "release" ]; then
|
||||||
|
mkdir release
|
||||||
|
if [ $? -ne 0 ]; then echo "mkdir release failed"; exit 1 ; fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If compiling sources from git, you may need to uncomment the following two lines:
|
||||||
|
./autogen.sh
|
||||||
|
if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
if test "$1" = "d"; then
|
||||||
|
cd debug
|
||||||
|
if [ $? -ne 0 ]; then echo "cd debug failed"; exit 1 ; fi
|
||||||
|
echo "configuring for 64 bit debug"
|
||||||
|
echo
|
||||||
|
../configure --with-x --disable-dependency-tracking --enable-cider --prefix="/usr/local" --libdir="/usr/local/lib" CFLAGS="-g -m64 -O0 -Wall -Wno-unused-but-set-variable" LDFLAGS="-m64 -g"
|
||||||
|
else
|
||||||
|
cd release
|
||||||
|
if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi
|
||||||
|
echo "configuring for 64 bit release"
|
||||||
|
echo
|
||||||
|
../configure --with-x --disable-dependency-tracking --enable-cider --prefix="/usr/local" --libdir="/usr/local/lib" CFLAGS="-m64 -O2" LDFLAGS="-m64 -s"
|
||||||
|
fi
|
||||||
|
if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
# make clean is required for properly making the code models
|
||||||
|
echo "cleaning (see make_clean.log)"
|
||||||
|
make clean 2>&1 -j8 | tee make_clean.log
|
||||||
|
exitcode=${PIPESTATUS[0]}
|
||||||
|
if [ $exitcode -ne 0 ]; then echo "make clean failed"; exit 1 ; fi
|
||||||
|
echo "compiling (see make.log)"
|
||||||
|
make 2>&1 -j8 | tee make.log
|
||||||
|
exitcode=${PIPESTATUS[0]}
|
||||||
|
if [ $exitcode -ne 0 ]; then echo "make failed"; exit 1 ; fi
|
||||||
|
# Install to /usr/local
|
||||||
|
echo "installing (see make_install.log)"
|
||||||
|
make install 2>&1 | tee make_install.log
|
||||||
|
exitcode=${PIPESTATUS[0]}
|
||||||
|
if [ $exitcode -ne 0 ]; then echo "make install failed"; exit 1 ; fi
|
||||||
|
|
||||||
|
ELAPSED="Elapsed compile time: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"
|
||||||
|
echo
|
||||||
|
echo $ELAPSED
|
||||||
|
echo "success"
|
||||||
|
exit 0
|
||||||
121
configure.ac
121
configure.ac
|
|
@ -134,30 +134,22 @@ AC_SUBST(LIBNGSPICE_API_VERSION)
|
||||||
# Package Options
|
# Package Options
|
||||||
# ---------------
|
# ---------------
|
||||||
|
|
||||||
# --disable-debug: remove -g and -Wall option to the compiler
|
# --enable-debug: add -g and -Wall option to the compiler
|
||||||
AC_ARG_ENABLE([debug],
|
AC_ARG_ENABLE([debug],
|
||||||
[AS_HELP_STRING([--disable-debug], [Remove -g option for compilation (default is -g)])])
|
[AS_HELP_STRING([--enable-debug], [Add -g option for compilation (default is without -g)])])
|
||||||
|
|
||||||
# --enable-oldapps: define OLDAPPS
|
# --disable-xspice: define XSPICE in the code. This is for xspice support
|
||||||
AC_ARG_ENABLE([oldapps],
|
|
||||||
[AS_HELP_STRING([--enable-oldapps], [Enable making old, outdated apps.])])
|
|
||||||
|
|
||||||
# --enable-xspice: define XSPICE in the code. This is for xspice support
|
|
||||||
AC_ARG_ENABLE([xspice],
|
AC_ARG_ENABLE([xspice],
|
||||||
[AS_HELP_STRING([--enable-xspice], [Enable XSPICE enhancements])])
|
[AS_HELP_STRING([--disable-xspice], [Disable XSPICE enhancements])])
|
||||||
|
|
||||||
# --enable-osdi: define OSDI in the code. This is for osdi support
|
# --disable-osdi: undefine OSDI in the code. This is for osdi support
|
||||||
AC_ARG_ENABLE([osdi],
|
AC_ARG_ENABLE([osdi],
|
||||||
[AS_HELP_STRING([--enable-osdi], [Enable OSDI integration])])
|
[AS_HELP_STRING([--disable-osdi], [Disable OSDI integration])])
|
||||||
|
|
||||||
# --enable-cider: define CIDER in the code. This is for CIDER support
|
# --enable-cider: define CIDER in the code. This is for CIDER support
|
||||||
AC_ARG_ENABLE([cider],
|
AC_ARG_ENABLE([cider],
|
||||||
[AS_HELP_STRING([--enable-cider], [Enable CIDER enhancements])])
|
[AS_HELP_STRING([--enable-cider], [Enable CIDER enhancements])])
|
||||||
|
|
||||||
# --enable-adms: ADMS is no longer supported
|
|
||||||
AC_ARG_ENABLE([adms],
|
|
||||||
[AS_HELP_STRING([--enable-adms], [ADMS is no longer supported])])
|
|
||||||
|
|
||||||
# --enable-pss: enable PSS Analysis
|
# --enable-pss: enable PSS Analysis
|
||||||
AC_ARG_ENABLE([pss],
|
AC_ARG_ENABLE([pss],
|
||||||
[AS_HELP_STRING([--enable-pss], [Enable PSS Analysis, (experimental)])])
|
[AS_HELP_STRING([--enable-pss], [Enable PSS Analysis, (experimental)])])
|
||||||
|
|
@ -171,9 +163,9 @@ AC_ARG_ENABLE([sp],
|
||||||
AC_ARG_ENABLE([relpath],
|
AC_ARG_ENABLE([relpath],
|
||||||
[AS_HELP_STRING([--enable-relpath], [Enable relative paths for spinit etc. Default=no])])
|
[AS_HELP_STRING([--enable-relpath], [Enable relative paths for spinit etc. Default=no])])
|
||||||
|
|
||||||
# --with-readline: Includes GNU readline support into CLI. Default is "no".
|
# --with-readline: Includes GNU readline support into CLI. Default is "yes".
|
||||||
AC_ARG_WITH([readline],
|
AC_ARG_WITH([readline],
|
||||||
[AS_HELP_STRING([--with-readline[=yes/no]], [Enable GNU readline support for CLI. Default=no.])])
|
[AS_HELP_STRING([--with-readline[=yes/no]], [Enable GNU readline support for CLI. Default=yes.])])
|
||||||
|
|
||||||
# --with-editline: Includes BSD Editline support into CLI. Default is "no".
|
# --with-editline: Includes BSD Editline support into CLI. Default is "no".
|
||||||
AC_ARG_WITH([editline],
|
AC_ARG_WITH([editline],
|
||||||
|
|
@ -195,8 +187,20 @@ AC_ARG_ENABLE([utf8],
|
||||||
AC_ARG_ENABLE([shortcheck],
|
AC_ARG_ENABLE([shortcheck],
|
||||||
[AS_HELP_STRING([--enable-shortcheck], [CMC QA check only for BSIM4/4])])
|
[AS_HELP_STRING([--enable-shortcheck], [CMC QA check only for BSIM4/4])])
|
||||||
|
|
||||||
|
# --with-fftw3: Use fftw3 for Fourier transforms. Default is "yes".
|
||||||
|
AC_ARG_WITH([fftw3],
|
||||||
|
[AS_HELP_STRING([--with-fftw3[=yes/no]], [Use fftw3 for Fourier transforms. Default=yes.])])
|
||||||
|
|
||||||
|
# --disable-klu: Do not use the KLU linear systems solver
|
||||||
|
AC_ARG_ENABLE([klu],
|
||||||
|
[AS_HELP_STRING([--disable-klu], [Use KLU linear systems solver. Default=yes.])])
|
||||||
|
|
||||||
# old options, not maintained, may even not work at all
|
# old options, not maintained, may even not work at all
|
||||||
|
|
||||||
|
# --enable-oldapps: define OLDAPPS
|
||||||
|
AC_ARG_ENABLE([oldapps],
|
||||||
|
[AS_HELP_STRING([--enable-oldapps], [Enable making old, outdated apps.])])
|
||||||
|
|
||||||
# --enable-ansi: try to force --ansi option to the compiler
|
# --enable-ansi: try to force --ansi option to the compiler
|
||||||
AC_ARG_ENABLE([ansi],
|
AC_ARG_ENABLE([ansi],
|
||||||
[AS_HELP_STRING([--enable-ansi], [Force --ansi option for compilation])])
|
[AS_HELP_STRING([--enable-ansi], [Force --ansi option for compilation])])
|
||||||
|
|
@ -293,10 +297,6 @@ AC_ARG_ENABLE([cmathtests],
|
||||||
AC_ARG_ENABLE([help],
|
AC_ARG_ENABLE([help],
|
||||||
[AS_HELP_STRING([--enable-help], [Force building nghelp (deprecated)])])
|
[AS_HELP_STRING([--enable-help], [Force building nghelp (deprecated)])])
|
||||||
|
|
||||||
# --with-fftw3: Use fftw3 for Fourier transforms. Default is "yes".
|
|
||||||
AC_ARG_WITH([fftw3],
|
|
||||||
[AS_HELP_STRING([--with-fftw3[=yes/no]], [Use fftw3 for Fourier transforms. Default=yes.])])
|
|
||||||
|
|
||||||
# readline and editline cannot both be enabled
|
# readline and editline cannot both be enabled
|
||||||
if test "x$with_editline" = xyes; then
|
if test "x$with_editline" = xyes; then
|
||||||
if test "x$with_readline" = xyes; then
|
if test "x$with_readline" = xyes; then
|
||||||
|
|
@ -304,16 +304,14 @@ if test "x$with_editline" = xyes; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --enable-klu: Use KLU linear systems solver
|
|
||||||
AC_ARG_ENABLE([klu],
|
|
||||||
[AS_HELP_STRING([--enable-klu], [Use KLU linear systems solver])])
|
|
||||||
|
|
||||||
# Add KLU solver to ngspice
|
# Add KLU solver to ngspice
|
||||||
if test "x$enable_klu" = xyes; then
|
if test "x$enable_klu" = xyes || test "x$enable_klu" = x ; then
|
||||||
AC_DEFINE(KLU, [], [Define if we want KLU linear systems solver])
|
AC_DEFINE(KLU, [], [Define if we want KLU linear systems solver])
|
||||||
AC_MSG_WARN([KLU solver enabled])
|
AC_MSG_RESULT([KLU solver enabled])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([KLU solver disabled!])
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL([KLU_WANTED], [test "x$enable_klu" = xyes])
|
AM_CONDITIONAL([KLU_WANTED], [test "x$enable_klu" = xyes || test "x$enable_klu" = x])
|
||||||
|
|
||||||
|
|
||||||
# Enable maintainer commands only if requested
|
# Enable maintainer commands only if requested
|
||||||
|
|
@ -329,26 +327,28 @@ AM_MAINTAINER_MODE([enable])
|
||||||
# the above AC_PROG_CC may set CFLAGS to "-O2 -g"
|
# the above AC_PROG_CC may set CFLAGS to "-O2 -g"
|
||||||
if test "x$ext_CFLAGS" != xyes; then
|
if test "x$ext_CFLAGS" != xyes; then
|
||||||
|
|
||||||
if test "x$enable_debug" = xno; then
|
if test "x$enable_debug" = xyes; then
|
||||||
AC_MSG_WARN([Removing debugging option!])
|
|
||||||
if test "x$GCC" = xyes; then
|
|
||||||
CFLAGS="-O2 -s"
|
|
||||||
else
|
|
||||||
CFLAGS="-O2"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
AC_DEFINE([NGDEBUG], [1], [Compile with debug info])
|
AC_DEFINE([NGDEBUG], [1], [Compile with debug info])
|
||||||
|
AC_MSG_WARN([Compile with debugging option -g!])
|
||||||
if test "x$GCC" = xyes; then
|
if test "x$GCC" = xyes; then
|
||||||
CFLAGS="-g -O0"
|
CFLAGS="-g -O0"
|
||||||
else
|
else
|
||||||
CFLAGS="-g"
|
CFLAGS="-g"
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([Debugging option -g removed])
|
||||||
|
if test "x$GCC" = xyes; then
|
||||||
|
CFLAGS="-O2 -s"
|
||||||
|
else
|
||||||
|
CFLAGS="-O2"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$GCC" = xyes; then
|
if test "x$GCC" = xyes; then
|
||||||
CFLAGS="$CFLAGS -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wnested-externs -Wold-style-definition -Wredundant-decls -Wconversion -Wno-unused-but-set-variable"
|
CFLAGS="$CFLAGS -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wnested-externs -Wold-style-definition -Wredundant-decls -Wconversion -Wno-unused-but-set-variable"
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([Use external CFLAGS])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# the profiling option
|
# the profiling option
|
||||||
|
|
@ -1103,10 +1103,23 @@ AM_CONDITIONAL([CMATHTESTS], [test "x$enable_cmathtests" = xyes])
|
||||||
################# XSPICE ##################################################
|
################# XSPICE ##################################################
|
||||||
# Add new code models to the build by pointing to them here.
|
# Add new code models to the build by pointing to them here.
|
||||||
|
|
||||||
if test "x$enable_xspice" = xyes; then
|
if test "x$enable_xspice" = xno; then
|
||||||
|
AC_MSG_RESULT([XSPICE features disabled])
|
||||||
|
XSPICEINIT="*"
|
||||||
|
if test "x$enable_osdi" = xyes || test "x$enable_osdi" = x ; then\
|
||||||
|
case $host_os in
|
||||||
|
*mingw* | *msys* | *cygwin* | *solaris* )
|
||||||
|
XSPICEDLLIBS=""
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
XSPICEDLLIBS="-ldl"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
else
|
||||||
VIS_CFLAGS=""
|
VIS_CFLAGS=""
|
||||||
AC_MSG_RESULT([X-Spice features included])
|
AC_MSG_RESULT([XSPICE features included])
|
||||||
AC_DEFINE([XSPICE], [1], [The xspice enhancements])
|
AC_DEFINE([XSPICE], [1], [The XSPICE enhancements])
|
||||||
case $host_os in
|
case $host_os in
|
||||||
*mingw* | *msys* )
|
*mingw* | *msys* )
|
||||||
AC_DEFINE([IPC_DEBUG_VIA_STDIO], [1], [Client-Server only via stdio.])
|
AC_DEFINE([IPC_DEBUG_VIA_STDIO], [1], [Client-Server only via stdio.])
|
||||||
|
|
@ -1151,29 +1164,19 @@ if test "x$enable_xspice" = xyes; then
|
||||||
AC_CHECK_FUNCS([modf])
|
AC_CHECK_FUNCS([modf])
|
||||||
AC_CHECK_HEADERS([libintl.h malloc.h])
|
AC_CHECK_HEADERS([libintl.h malloc.h])
|
||||||
AC_SUBST([VIS_CFLAGS])
|
AC_SUBST([VIS_CFLAGS])
|
||||||
else
|
|
||||||
XSPICEINIT="*"
|
|
||||||
if test "x$enable_osdi" = xyes; then\
|
|
||||||
case $host_os in
|
|
||||||
*mingw* | *msys* | *cygwin* | *solaris* )
|
|
||||||
XSPICEDLLIBS=""
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
XSPICEDLLIBS="-ldl"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST([XSPICEINIT])
|
AC_SUBST([XSPICEINIT])
|
||||||
AC_SUBST([XSPICEDLLIBS])
|
AC_SUBST([XSPICEDLLIBS])
|
||||||
|
|
||||||
AM_CONDITIONAL([XSPICE_WANTED], [test "x$enable_xspice" = xyes])
|
AM_CONDITIONAL([XSPICE_WANTED], [test "x$enable_xspice" = xyes || test "x$enable_xspice" = x])
|
||||||
|
|
||||||
AM_CONDITIONAL([SHORT_CHECK_WANTED], [test "x$enable_shortcheck" = xyes])
|
AM_CONDITIONAL([SHORT_CHECK_WANTED], [test "x$enable_shortcheck" = xyes])
|
||||||
|
|
||||||
|
|
||||||
if test "x$enable_osdi" = xyes; then
|
if test "x$enable_osdi" = xno; then
|
||||||
|
AC_MSG_RESULT([OSDI interface disabled])
|
||||||
|
else
|
||||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
||||||
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
||||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
||||||
|
|
@ -1201,7 +1204,7 @@ if test "x$enable_osdi" = xyes; then
|
||||||
AC_DEFINE([OSDI], [1], [The OSDI enhancements])
|
AC_DEFINE([OSDI], [1], [The OSDI enhancements])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AM_CONDITIONAL([OSDI_WANTED], [test "x$enable_osdi" = xyes])
|
AM_CONDITIONAL([OSDI_WANTED], [test "x$enable_osdi" != xno])
|
||||||
|
|
||||||
# Add CIDER enhancements to ngspice.
|
# Add CIDER enhancements to ngspice.
|
||||||
if test "x$enable_cider" = xyes; then
|
if test "x$enable_cider" = xyes; then
|
||||||
|
|
@ -1252,10 +1255,10 @@ fi
|
||||||
# ---- Default: disabled. ----
|
# ---- Default: disabled. ----
|
||||||
# ---- Hope to see in the future readline replacement. ----
|
# ---- Hope to see in the future readline replacement. ----
|
||||||
|
|
||||||
if test "x$with_readline" = x || test "x$with_readline" = xno ; then
|
if test "x$with_readline" = xno ; then
|
||||||
AC_MSG_RESULT([GNU readline disabled.])
|
AC_MSG_RESULT([GNU readline disabled.])
|
||||||
else
|
else
|
||||||
if test "x$with_readline" = xyes; then
|
if test "x$with_readline" = x || test "x$with_readline" = xyes ; then
|
||||||
if test "x$with_tcl" = x || test "x$with_tcl" = xno ; then
|
if test "x$with_tcl" = x || test "x$with_tcl" = xno ; then
|
||||||
AC_MSG_RESULT([Checking for readline:])
|
AC_MSG_RESULT([Checking for readline:])
|
||||||
AC_CHECK_HEADERS([readline/readline.h readline/history.h],
|
AC_CHECK_HEADERS([readline/readline.h readline/history.h],
|
||||||
|
|
@ -1318,13 +1321,15 @@ AC_ARG_ENABLE([openmp],
|
||||||
[AS_HELP_STRING([--enable-openmp], [Use OpenMP parallel processing])])
|
[AS_HELP_STRING([--enable-openmp], [Use OpenMP parallel processing])])
|
||||||
|
|
||||||
# Add OpenMP to ngspice.
|
# Add OpenMP to ngspice.
|
||||||
: ${enable_openmp:=no}
|
: ${enable_openmp:=yes}
|
||||||
m4_ifdef([AC_OPENMP], [AC_OPENMP])
|
m4_ifdef([AC_OPENMP], [AC_OPENMP])
|
||||||
|
|
||||||
if test "x$enable_openmp" = xyes; then
|
if test "x$enable_openmp" = xyes || test "x$enable_openmp" = x ; then
|
||||||
AC_DEFINE([USE_OMP], [1], [OpenMP parallel processing])
|
AC_DEFINE([USE_OMP], [1], [OpenMP parallel processing])
|
||||||
CFLAGS="$CFLAGS $OPENMP_CFLAGS"
|
CFLAGS="$CFLAGS $OPENMP_CFLAGS"
|
||||||
AC_MSG_RESULT([OpenMP feature enabled])
|
AC_MSG_RESULT([OpenMP feature enabled])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([OpenMP feature disabled])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Output Files
|
# Output Files
|
||||||
|
|
|
||||||
|
|
@ -1,287 +0,0 @@
|
||||||
***************************************************************
|
|
||||||
* Comments for the user:
|
|
||||||
* The VBIC Model includes the self heating effect and the user can switch selfheating on or off.
|
|
||||||
* a) no self heating: set Rth = 0
|
|
||||||
* b) with self heating: set Rth=80K/W + Rth_PCB (customer)
|
|
||||||
* Note: Rth = 80 K/W includes only the thermal resistance of die and package and
|
|
||||||
* the thermal resistance of the customer PCB must be added (Rth=80K/W + Rth_PCB)
|
|
||||||
|
|
||||||
* Infineon Technologies AG
|
|
||||||
* VBIC MODEL IN SPICE 2G6 SYNTAX
|
|
||||||
* VALID UP TO 10 GHZ
|
|
||||||
* >>> BFP780 <<<
|
|
||||||
* (C) 2015 Infineon Technologies AG
|
|
||||||
* Version 1.1 October 2015
|
|
||||||
***************************************************************
|
|
||||||
*.OPTION TNOM=25, GMIN= 1.00e-12
|
|
||||||
*BFP780 C B E1 E2
|
|
||||||
.SUBCKT BFP780 1 2 3 4
|
|
||||||
*
|
|
||||||
CCEPAR 11 33 800E-015
|
|
||||||
*
|
|
||||||
LEx 30 35 3E-011
|
|
||||||
LBx 20 2 3E-011
|
|
||||||
LCx 10 1 3E-011
|
|
||||||
*
|
|
||||||
CBPAD 22 44 30E-015
|
|
||||||
CCPAD 11 44 30E-015
|
|
||||||
CEPAD 33 44 30E-015
|
|
||||||
*
|
|
||||||
LB 22 20 777E-12
|
|
||||||
LC 10 11 777E-12
|
|
||||||
*
|
|
||||||
CBEPCK 20 30 5.703E-015
|
|
||||||
CBCPCK 10 20 1.497E-014
|
|
||||||
CCEPCK 10 30 6.032E-014
|
|
||||||
*
|
|
||||||
RE1 35 3 1E-03
|
|
||||||
RE2 35 4 1E-03
|
|
||||||
*
|
|
||||||
Rsub1 44 30 0.2144
|
|
||||||
Rps 44 33 0.07306
|
|
||||||
*
|
|
||||||
D1 33 22 Diode_fb
|
|
||||||
D2 44 22 Diode_fbd
|
|
||||||
*
|
|
||||||
.MODEL Diode_fb D(
|
|
||||||
+ IS=3.5E-015
|
|
||||||
+ N=1
|
|
||||||
+ CJO=10e-15
|
|
||||||
+ RS=6.1
|
|
||||||
+ Tnom=25)
|
|
||||||
*
|
|
||||||
.MODEL Diode_fbd D(
|
|
||||||
+ IS=1E-015
|
|
||||||
+ N=1
|
|
||||||
+ CJO=10E-15
|
|
||||||
+ RS=1
|
|
||||||
+ Tnom=25)
|
|
||||||
*
|
|
||||||
Q1 11 22 33 44 M_BFP780
|
|
||||||
*
|
|
||||||
.ENDS BFP780
|
|
||||||
.MODEL M_BFP780 NPN (Level=4
|
|
||||||
+ Tnom=25
|
|
||||||
+ Cbeo=2.47E-012
|
|
||||||
+ Cje=561.3E-015
|
|
||||||
+ Pe=0.7
|
|
||||||
+ Me=0.333
|
|
||||||
+ Aje=-1
|
|
||||||
+ Wbe=1
|
|
||||||
+ Cbco=10E-015
|
|
||||||
+ Cjc=668.6E-015
|
|
||||||
+ Pc=0.54
|
|
||||||
+ Mc=0.333
|
|
||||||
+ Ajc=-1
|
|
||||||
+ Cjep=2.616E-015
|
|
||||||
+ Cjcp=900E-015
|
|
||||||
+ Ps=0.6
|
|
||||||
+ Ms=0.3
|
|
||||||
+ Ajs=-0.5
|
|
||||||
+ Fc=0.94
|
|
||||||
+ Vef=545.4
|
|
||||||
+ Ver=3.291
|
|
||||||
+ Is=2.3E-015
|
|
||||||
+ Nf=0.9855
|
|
||||||
+ Ibei=1.893E-018
|
|
||||||
+ Nei=0.9399
|
|
||||||
+ Iben=4.77E-015
|
|
||||||
+ Nen=1.361
|
|
||||||
+ Ikf=1
|
|
||||||
+ Nr=0.9912
|
|
||||||
+ Ibci=157.5E-018
|
|
||||||
+ Nci=1.1
|
|
||||||
+ Ibcn=4.929E-015
|
|
||||||
+ Ncn=1.463
|
|
||||||
+ Ikr=0.01178
|
|
||||||
+ Wsp=1
|
|
||||||
+ Isp=1E-015
|
|
||||||
+ Nfp=1
|
|
||||||
+ Ibcip=1E-015
|
|
||||||
+ Ncip=1.029
|
|
||||||
+ Ibcnp=1E-015
|
|
||||||
+ Ncnp=1
|
|
||||||
+ Ikp=1E-3
|
|
||||||
+ Ibeip=1E-015
|
|
||||||
+ Ibenp=1E-015
|
|
||||||
+ Re=0.15
|
|
||||||
+ Rcx=0.01
|
|
||||||
+ Rci=2.665
|
|
||||||
+ Qco=1E-015
|
|
||||||
+ Vo=0.0005022
|
|
||||||
+ Gamm=5.659E-012
|
|
||||||
+ Hrcf=0.21
|
|
||||||
+ Rbx=5
|
|
||||||
+ Rbi=1.964
|
|
||||||
+ Rbp=265.5
|
|
||||||
+ Rs=26.56
|
|
||||||
+ Avc1=3.97
|
|
||||||
+ Avc2=29.52
|
|
||||||
+ Tf=1.6E-012
|
|
||||||
+ Qtf=50E-3
|
|
||||||
+ Xtf=30
|
|
||||||
+ Vtf=0.7
|
|
||||||
+ Itf=1
|
|
||||||
+ Tr=1E-015
|
|
||||||
+ Td=500E-015
|
|
||||||
+ Cth=0
|
|
||||||
+ Rth=0
|
|
||||||
+ Ea=1.12
|
|
||||||
+ Eaie=1.12
|
|
||||||
+ Eaic=1.12
|
|
||||||
+ Eais=1
|
|
||||||
+ Eane=1.12
|
|
||||||
+ Eanc=1.12
|
|
||||||
+ Eans=1
|
|
||||||
+ Xre=0
|
|
||||||
+ Xrb=0
|
|
||||||
+ Xrc=0
|
|
||||||
+ Xrs=0
|
|
||||||
+ Xvo=0
|
|
||||||
+ Xis=-1.631
|
|
||||||
+ Xii=0
|
|
||||||
+ Xin=0
|
|
||||||
+ Tnf=0
|
|
||||||
+ Tavc=0.002613
|
|
||||||
+ Kfn=0
|
|
||||||
+ Afn=1
|
|
||||||
+ Bfn=1 )
|
|
||||||
***************************************************************
|
|
||||||
*
|
|
||||||
*.ENDS BFP780
|
|
||||||
***************************************************************
|
|
||||||
* Comments for the user:
|
|
||||||
* The VBIC Model includes the self heating effect and the user can switch selfheating on or off.
|
|
||||||
* a) no self heating: set Rth = 0
|
|
||||||
* b) with self heating: set Rth=20K/W + Rth_PCB (customer)
|
|
||||||
* Note: Rth = 20 K/W includes only the thermal resistance of die and package and
|
|
||||||
* the thermal resistance of the customer PCB must be added (Rth=20K/W + Rth_PCB)
|
|
||||||
|
|
||||||
* Infineon Technologies AG
|
|
||||||
* VBIC MODEL
|
|
||||||
* VALID UP TO 6 GHZ
|
|
||||||
* >>> BFQ790 <<<
|
|
||||||
* (C) 2015 Infineon Technologies AG
|
|
||||||
* Version 1.0 Juni 2015
|
|
||||||
***************************************************************
|
|
||||||
*.OPTION TNOM=25, GMIN= 1.00e-12
|
|
||||||
*BFQ790 C B E
|
|
||||||
|
|
||||||
* without access to the external thermal node (Rth to be adjusted by the customer in the model parameter list for the transistor
|
|
||||||
.SUBCKT BFQ790 1 2 3
|
|
||||||
*
|
|
||||||
* with access to external thermal node
|
|
||||||
*.SUBCKT BFQ790 1 2 3 55
|
|
||||||
*
|
|
||||||
CCSPAR 11 44 1.375E-012
|
|
||||||
LEx 30 3 4.36882E-011
|
|
||||||
LBx 20 2 2.77681E-011
|
|
||||||
LCx 10 1 4.265E-011
|
|
||||||
CBEPCK 20 30 1.105E-013
|
|
||||||
CBCPCK 10 20 1E-014
|
|
||||||
CCEPCK 10 30 1E-015
|
|
||||||
LB 222 20 1.02449E-009
|
|
||||||
LC 10 11 1.89901E-009
|
|
||||||
*
|
|
||||||
RBL 222 22 45
|
|
||||||
CBL 222 22 3E-011
|
|
||||||
*
|
|
||||||
Rsub1 44 30 0.000500184
|
|
||||||
Rps 44 33 0.102733
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* without access to the external thermal node
|
|
||||||
Q1 11 22 33 44 M_BFQ790
|
|
||||||
*
|
|
||||||
* with access to the thermal node
|
|
||||||
* Q1 11 22 33 44 55 M_BFQ790
|
|
||||||
*
|
|
||||||
.MODEL M_BFQ790 NPN Level=4(
|
|
||||||
+ Tnom=25
|
|
||||||
+ Cbeo=9.31E-012
|
|
||||||
+ Cje=7.693E-013
|
|
||||||
+ Pe=0.5892
|
|
||||||
+ Me=0.3115
|
|
||||||
+ Aje=-0.5
|
|
||||||
+ Wbe=1
|
|
||||||
+ Cbco=1.966E-013
|
|
||||||
+ Cjc=1E-015
|
|
||||||
+ Pc=0.5095
|
|
||||||
+ Mc=0.2797
|
|
||||||
+ Ajc=-0.5
|
|
||||||
+ Cjep=1.875E-012
|
|
||||||
+ Cjcp=2.067E-012
|
|
||||||
+ Ps=0.5086
|
|
||||||
+ Ms=0.2865
|
|
||||||
+ Ajs=-0.5
|
|
||||||
+ Fc=0.93
|
|
||||||
+ Vef=615.1
|
|
||||||
+ Ver=5.61838
|
|
||||||
+ Is=9.704E-015
|
|
||||||
+ Nf=1.001
|
|
||||||
+ Ibei=5E-017
|
|
||||||
+ Nei=1.013
|
|
||||||
+ Iben=3.609E-014
|
|
||||||
+ Nen=1.46
|
|
||||||
+ Ikf=2
|
|
||||||
+ Nr=0.9958
|
|
||||||
+ Ibci=1.001E-017
|
|
||||||
+ Nci=1.015
|
|
||||||
+ Ibcn=2.918E-014
|
|
||||||
+ Ncn=1.399
|
|
||||||
+ Ikr=0.2301
|
|
||||||
+ Wsp=1
|
|
||||||
+ Isp=1E-015
|
|
||||||
+ Nfp=1
|
|
||||||
+ Ibcip=2E-017
|
|
||||||
+ Ncip=1
|
|
||||||
+ Ibcnp=1.7E-015
|
|
||||||
+ Ncnp=1.67
|
|
||||||
+ Ikp=0.0002
|
|
||||||
+ Ibeip=7E-017
|
|
||||||
+ Ibenp=2.4E-014
|
|
||||||
+ Re=0.2
|
|
||||||
+ Rcx=0.02559
|
|
||||||
+ Rci=1.168
|
|
||||||
+ Qco=4E-015
|
|
||||||
+ Vo=0.4234
|
|
||||||
+ Gamm=2.199E-012
|
|
||||||
+ Hrcf=0.1907
|
|
||||||
+ Rbx=0.2825
|
|
||||||
+ Rbi=1.868
|
|
||||||
+ Rbp=0.001
|
|
||||||
+ Rs=10
|
|
||||||
+ Avc1=1
|
|
||||||
+ Avc2=25.84
|
|
||||||
+ Tf=3E-012
|
|
||||||
+ Qtf=0.6758
|
|
||||||
+ Xtf=0.01293
|
|
||||||
+ Vtf=0.5
|
|
||||||
+ Itf=0.1948
|
|
||||||
+ Tr=1E-015
|
|
||||||
+ Td=1E-015
|
|
||||||
+ Cth=0
|
|
||||||
+ Rth=0
|
|
||||||
+ Ea=1.12
|
|
||||||
+ Eaie=1.12
|
|
||||||
+ Eaic=1.12
|
|
||||||
+ Eais=1.12
|
|
||||||
+ Eane=1.12
|
|
||||||
+ Eanc=1.12
|
|
||||||
+ Eans=1.12
|
|
||||||
+ Xre=0
|
|
||||||
+ Xrb=0
|
|
||||||
+ Xrc=0
|
|
||||||
+ Xrs=0
|
|
||||||
+ Xvo=0
|
|
||||||
+ Xis=1.907
|
|
||||||
+ Xii=4.963
|
|
||||||
+ Xin=-2.837
|
|
||||||
+ Tnf=1E-006
|
|
||||||
+ Tavc=0.006705
|
|
||||||
+ Kfn=0
|
|
||||||
+ Afn=1
|
|
||||||
+ Bfn=1 )
|
|
||||||
***************************************************************
|
|
||||||
*
|
|
||||||
.ENDS BFQ790
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
VBIC Output Test Ic=f(Vc,Ib) vs self heating
|
|
||||||
vc c 0 0
|
|
||||||
ib 0 b 10u
|
|
||||||
ve e 0 0
|
|
||||||
vs s 0 0
|
|
||||||
vc1 c c1 0
|
|
||||||
vb1 b b1 0
|
|
||||||
ve1 e e1 0
|
|
||||||
vs1 s s1 0
|
|
||||||
.temp 27
|
|
||||||
Q1 c1 b1 e1 s1 dt M_BFP780 area=1
|
|
||||||
|
|
||||||
.include Infineon_VBIC_RTH_0.lib
|
|
||||||
|
|
||||||
.control
|
|
||||||
dc vc 0.0 5.0 0.05 ib 50u 500u 50u
|
|
||||||
settype temperature v(dt)
|
|
||||||
plot v(dt)
|
|
||||||
altermod @M_BFP780[RTH]=0
|
|
||||||
dc vc 0.0 5.0 0.05 ib 50u 500u 50u
|
|
||||||
plot dc1.vc1#branch dc2.vc1#branch
|
|
||||||
.endc
|
|
||||||
.end
|
|
||||||
|
|
@ -65,30 +65,22 @@ settrace(wordlist *wl, int what, char *name)
|
||||||
char *s = cp_unquote(wl->wl_word);
|
char *s = cp_unquote(wl->wl_word);
|
||||||
char *db_nodename1 = NULL;
|
char *db_nodename1 = NULL;
|
||||||
char db_type = 0;
|
char db_type = 0;
|
||||||
if (eq(s, "all")) {
|
if (eq(s, "all") || eq(s, "nosub")) {
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case VF_PRINT:
|
case VF_PRINT:
|
||||||
db_type = DB_TRACEALL;
|
db_type = DB_TRACEALL;
|
||||||
break;
|
break;
|
||||||
/* case VF_PLOT:
|
|
||||||
db_type = DB_IPLOTALL;
|
|
||||||
break; */
|
|
||||||
case VF_ACCUM:
|
case VF_ACCUM:
|
||||||
/* db_type = DB_SAVEALL; */
|
|
||||||
db_nodename1 = copy(s);
|
db_nodename1 = copy(s);
|
||||||
db_type = DB_SAVE;
|
db_type = DB_SAVE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tfree(s);
|
tfree(s);
|
||||||
/* wrd_chtrace(NULL, TRUE, what); */
|
|
||||||
} else {
|
} else {
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case VF_PRINT:
|
case VF_PRINT:
|
||||||
db_type = DB_TRACENODE;
|
db_type = DB_TRACENODE;
|
||||||
break;
|
break;
|
||||||
/* case VF_PLOT:
|
|
||||||
db_type = DB_IPLOT;
|
|
||||||
break; */
|
|
||||||
case VF_ACCUM:
|
case VF_ACCUM:
|
||||||
db_type = DB_SAVE;
|
db_type = DB_SAVE;
|
||||||
break;
|
break;
|
||||||
|
|
@ -98,7 +90,6 @@ settrace(wordlist *wl, int what, char *name)
|
||||||
tfree(s);
|
tfree(s);
|
||||||
if (!db_nodename1) /* skip on error */
|
if (!db_nodename1) /* skip on error */
|
||||||
continue;
|
continue;
|
||||||
/* wrd_chtrace(s, TRUE, what); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't save a nodename more than once */
|
/* Don't save a nodename more than once */
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,21 @@
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
void com_codemodel(wordlist *wl)
|
void com_codemodel(wordlist *wl)
|
||||||
{
|
{
|
||||||
wordlist *ww;
|
if (wl && wl->wl_word)
|
||||||
for (ww = wl; ww; ww = ww->wl_next)
|
#ifdef CM_TRACE
|
||||||
if (load_opus(wl->wl_word)) {
|
fprintf(stdout, "Note: loading codemodel %s\n", ww->wl_word);
|
||||||
fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word);
|
#endif
|
||||||
if (ft_stricterror)
|
if (load_opus(wl->wl_word)) {
|
||||||
controlled_exit(EXIT_BAD);
|
fprintf(stderr, "Error: Library %s couldn't be loaded!\n", wl->wl_word);
|
||||||
}
|
ft_spiniterror = TRUE;
|
||||||
|
if (ft_stricterror) /* if set in spinit */
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
#ifdef CM_TRACE
|
||||||
|
else {
|
||||||
|
fprintf(stdout, "Codemodel %s is loaded\n", wl->wl_word);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -25,6 +33,7 @@ void com_osdi(wordlist *wl)
|
||||||
for (ww = wl; ww; ww = ww->wl_next)
|
for (ww = wl; ww; ww = ww->wl_next)
|
||||||
if (load_osdi(ww->wl_word)) {
|
if (load_osdi(ww->wl_word)) {
|
||||||
fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word);
|
fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word);
|
||||||
|
ft_spiniterror = TRUE;
|
||||||
if (ft_stricterror)
|
if (ft_stricterror)
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -266,7 +266,7 @@ struct comm spcp_coms[] = {
|
||||||
NULL,
|
NULL,
|
||||||
"node node ... : Print all event nodes." },
|
"node node ... : Print all event nodes." },
|
||||||
{ "codemodel", com_codemodel, FALSE, TRUE,
|
{ "codemodel", com_codemodel, FALSE, TRUE,
|
||||||
{ 040000, 040000, 040000, 040000 }, E_BEGINNING, 1, LOTS,
|
{ 040000, 040000, 040000, 040000 }, E_BEGINNING, 1, 1,
|
||||||
NULL,
|
NULL,
|
||||||
"library library ... : Loads the code model libraries." } ,
|
"library library ... : Loads the code model libraries." } ,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1343,10 +1343,15 @@ com_alter_common(wordlist *wl, int do_model)
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
param = NULL;
|
param = NULL;
|
||||||
words = wl;
|
words = wl;
|
||||||
while (words != eqword) {
|
while (words && words != eqword) {
|
||||||
char *p = words->wl_word;
|
char *p = words->wl_word;
|
||||||
if (param) {
|
if (param) {
|
||||||
fprintf(cp_err, "Warning: excess parameter name \"%s\" ignored.\n", p);
|
fprintf(cp_err, "Warning: excess parameter name \"%s\" ignored.\n", p);
|
||||||
|
char* line = wl_flatten(wl_head->wl_prev);
|
||||||
|
if (line) {
|
||||||
|
fprintf(cp_err, " in line: %s\n", line);
|
||||||
|
tfree(line);
|
||||||
|
}
|
||||||
} else if (dev) {
|
} else if (dev) {
|
||||||
param = words->wl_word;
|
param = words->wl_word;
|
||||||
} else if (*p == '@' || *p == '#') {
|
} else if (*p == '@' || *p == '#') {
|
||||||
|
|
@ -1543,7 +1548,7 @@ com_alter_mod(wordlist *wl)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char *dir_name = ngdirname(filename);
|
char *dir_name = ngdirname(filename);
|
||||||
modeldeck = inp_readall(modfile, dir_name, 0, 0, NULL);
|
modeldeck = inp_readall(modfile, dir_name, filename, 0, 0, NULL);
|
||||||
tfree(dir_name);
|
tfree(dir_name);
|
||||||
}
|
}
|
||||||
tfree(input);
|
tfree(input);
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ void eval_opt(struct card *deck);
|
||||||
|
|
||||||
extern bool ft_batchmode;
|
extern bool ft_batchmode;
|
||||||
extern int dynmaxline;
|
extern int dynmaxline;
|
||||||
|
extern wordlist* sourceinfo;
|
||||||
|
|
||||||
/* from inpcom.c */
|
/* from inpcom.c */
|
||||||
extern struct nscope* inp_add_levels(struct card *deck);
|
extern struct nscope* inp_add_levels(struct card *deck);
|
||||||
|
|
@ -532,7 +533,7 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
||||||
/* inp_source() called with fp: load from file, */
|
/* inp_source() called with fp: load from file, */
|
||||||
/* called with *fp == NULL and intfile: we want to load circuit from circarray */
|
/* called with *fp == NULL and intfile: we want to load circuit from circarray */
|
||||||
if (fp || intfile) {
|
if (fp || intfile) {
|
||||||
deck = inp_readall(fp, dir_name, comfile, intfile, &expr_w_temper);
|
deck = inp_readall(fp, dir_name, filename, comfile, intfile, &expr_w_temper);
|
||||||
|
|
||||||
/* files starting with *ng_script are user supplied command files */
|
/* files starting with *ng_script are user supplied command files */
|
||||||
if (deck && ciprefix("*ng_script", deck->line))
|
if (deck && ciprefix("*ng_script", deck->line))
|
||||||
|
|
@ -580,7 +581,7 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
||||||
fprintf(fdo, "****************** complete mc deck ***************\n\n");
|
fprintf(fdo, "****************** complete mc deck ***************\n\n");
|
||||||
/* now completely */
|
/* now completely */
|
||||||
for (tc = deck; tc; tc = tc->nextcard)
|
for (tc = deck; tc; tc = tc->nextcard)
|
||||||
fprintf(fdo, "%6d %6d %s\n", tc->linenum_orig, tc->linenum, tc->line);
|
fprintf(fdo, "%6s %6d %6d %s\n", tc->linesource, tc->linenum_orig, tc->linenum, tc->line);
|
||||||
fclose(fdo);
|
fclose(fdo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -962,17 +963,17 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
||||||
struct card *tc = NULL;
|
struct card *tc = NULL;
|
||||||
fprintf(fdo, "**************** uncommented deck **************\n\n");
|
fprintf(fdo, "**************** uncommented deck **************\n\n");
|
||||||
/* always print first line */
|
/* always print first line */
|
||||||
fprintf(fdo, "%6d %6d %s\n", deck->linenum_orig, deck->linenum, deck->line);
|
fprintf(fdo, "%6s %6d %6d %s\n", deck->linesource, deck->linenum_orig, deck->linenum, deck->line);
|
||||||
/* here without out-commented lines */
|
/* here without out-commented lines */
|
||||||
for (tc = deck->nextcard; tc; tc = tc->nextcard) {
|
for (tc = deck->nextcard; tc; tc = tc->nextcard) {
|
||||||
if (*(tc->line) == '*')
|
if (*(tc->line) == '*')
|
||||||
continue;
|
continue;
|
||||||
fprintf(fdo, "%6d %6d %s\n", tc->linenum_orig, tc->linenum, tc->line);
|
fprintf(fdo, "%6s %6d %6d %s\n", tc->linesource, tc->linenum_orig, tc->linenum, tc->line);
|
||||||
}
|
}
|
||||||
fprintf(fdo, "\n****************** complete deck ***************\n\n");
|
fprintf(fdo, "\n****************** complete deck ***************\n\n");
|
||||||
/* now completely */
|
/* now completely */
|
||||||
for (tc = deck; tc; tc = tc->nextcard)
|
for (tc = deck; tc; tc = tc->nextcard)
|
||||||
fprintf(fdo, "%6d %6d %s\n", tc->linenum_orig, tc->linenum, tc->line);
|
fprintf(fdo, "%6s %6d %6d %s\n", tc->linesource, tc->linenum_orig, tc->linenum, tc->line);
|
||||||
fclose(fdo);
|
fclose(fdo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1533,6 +1534,7 @@ inp_dodeck(
|
||||||
tfree(ct->ci_filename);
|
tfree(ct->ci_filename);
|
||||||
#endif
|
#endif
|
||||||
ct->ci_filename = copy(filename);
|
ct->ci_filename = copy(filename);
|
||||||
|
ct->ci_sourceinfo = sourceinfo;
|
||||||
|
|
||||||
/* load the optran data, if provided by .spiceinit or spinit.
|
/* load the optran data, if provided by .spiceinit or spinit.
|
||||||
Return immediately, if optran is not selected.*/
|
Return immediately, if optran is not selected.*/
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ void inp_probe(struct card* card);
|
||||||
void modprobenames(INPtables* tab);
|
void modprobenames(INPtables* tab);
|
||||||
|
|
||||||
extern struct card* insert_new_line(
|
extern struct card* insert_new_line(
|
||||||
struct card* card, char* line, int linenum, int linenum_orig);
|
struct card* card, char* line, int linenum, int linenum_orig, char *lineinfo);
|
||||||
extern int get_number_terminals(char* c);
|
extern int get_number_terminals(char* c);
|
||||||
extern char* search_plain_identifier(char* str, const char* identifier);
|
extern char* search_plain_identifier(char* str, const char* identifier);
|
||||||
|
|
||||||
|
|
@ -24,6 +24,7 @@ static char* get_terminal_name(char* element, char* numberstr, NGHASHPTR instanc
|
||||||
static char* get_terminal_number(char* element, char* numberstr);
|
static char* get_terminal_number(char* element, char* numberstr);
|
||||||
static int setallvsources(struct card* tmpcard, NGHASHPTR instances, char* instname, int numnodes, bool haveall, bool power);
|
static int setallvsources(struct card* tmpcard, NGHASHPTR instances, char* instname, int numnodes, bool haveall, bool power);
|
||||||
|
|
||||||
|
static int check_for_nodes(char* instance, int numnodes);
|
||||||
|
|
||||||
/* Find any line starting with .probe: assemble all parameters like
|
/* Find any line starting with .probe: assemble all parameters like
|
||||||
<empty> add V(0) current measure sources to all device nodes in addition to .save all
|
<empty> add V(0) current measure sources to all device nodes in addition to .save all
|
||||||
|
|
@ -90,7 +91,7 @@ void inp_probe(struct card* deck)
|
||||||
|
|
||||||
if (!havesave) {
|
if (!havesave) {
|
||||||
char* vline = copy(".save all");
|
char* vline = copy(".save all");
|
||||||
deck = insert_new_line(deck, vline, 0, 0);
|
deck = insert_new_line(deck, vline, 0, deck->linenum_orig, deck->linesource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set a variable if .probe command is given */
|
/* set a variable if .probe command is given */
|
||||||
|
|
@ -256,6 +257,12 @@ void inp_probe(struct card* deck)
|
||||||
else
|
else
|
||||||
numnodes = get_number_terminals(card->line);
|
numnodes = get_number_terminals(card->line);
|
||||||
|
|
||||||
|
if (check_for_nodes(card->line, numnodes)) {
|
||||||
|
fprintf(stderr, "Error: Not enough tokens in line %d\n%s\n", card->linenum_orig, card->line);
|
||||||
|
fprintf(stderr, " Please correct your input file\n");
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
char* thisline = curr_line;
|
char* thisline = curr_line;
|
||||||
prevcard = card;
|
prevcard = card;
|
||||||
/* all elements with 2 nodes: add a voltage source to the second node in the elements line */
|
/* all elements with 2 nodes: add a voltage source to the second node in the elements line */
|
||||||
|
|
@ -284,7 +291,7 @@ void inp_probe(struct card* deck)
|
||||||
tfree(card->line);
|
tfree(card->line);
|
||||||
card->line = newline;
|
card->line = newline;
|
||||||
|
|
||||||
card = insert_new_line(card, vline, 0, 0);
|
card = insert_new_line(card, vline, 0, card->linenum_orig, card->linesource);
|
||||||
|
|
||||||
tfree(strnode1);
|
tfree(strnode1);
|
||||||
tfree(strnode2);
|
tfree(strnode2);
|
||||||
|
|
@ -320,11 +327,11 @@ void inp_probe(struct card* deck)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char* vline = tprintf("vcurr_%s:%s:%s_%s %s %s 0", instname, nodename, thisnode, nodebuf, thisnode, newnode);
|
char* vline = tprintf("vcurr_%s:%s:%s_%s %s %s 0", instname, nodename, thisnode, nodebuf, thisnode, newnode);
|
||||||
card = insert_new_line(card, vline, 0, 0);
|
card = insert_new_line(card, vline, 0, card->linenum_orig, card->linesource);
|
||||||
/* special for KiCad: add shunt resistor if thisnode contains 'unconnected' */
|
/* special for KiCad: add shunt resistor if thisnode contains 'unconnected' */
|
||||||
if (*instname == 'x' && strstr(thisnode, "unconnected")) {
|
if (*instname == 'x' && strstr(thisnode, "unconnected")) {
|
||||||
char *rline = tprintf("R%s %s 0 1e15", thisnode, thisnode);
|
char *rline = tprintf("R%s %s 0 1e15", thisnode, thisnode);
|
||||||
card = insert_new_line(card, rline, 0, 0);
|
card = insert_new_line(card, rline, 0, card->linenum_orig, card->linesource);
|
||||||
}
|
}
|
||||||
char* nodesaves = tprintf("%s:%s#branch", instname, nodename);
|
char* nodesaves = tprintf("%s:%s#branch", instname, nodename);
|
||||||
allsaves = wl_cons(nodesaves, allsaves);
|
allsaves = wl_cons(nodesaves, allsaves);
|
||||||
|
|
@ -342,7 +349,7 @@ void inp_probe(struct card* deck)
|
||||||
char* newline = wl_flatten(allsaves);
|
char* newline = wl_flatten(allsaves);
|
||||||
wl_free(allsaves);
|
wl_free(allsaves);
|
||||||
allsaves = NULL;
|
allsaves = NULL;
|
||||||
card = insert_new_line(card, newline, 0, 0);
|
card = insert_new_line(card, newline, 0, card->linenum_orig, card->linesource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -396,7 +403,7 @@ void inp_probe(struct card* deck)
|
||||||
tfree(strnode1);
|
tfree(strnode1);
|
||||||
tfree(strnode2);
|
tfree(strnode2);
|
||||||
tmpcard1 = deck->nextcard;
|
tmpcard1 = deck->nextcard;
|
||||||
tmpcard1 = insert_new_line(tmpcard1, newline, 0, 0);
|
tmpcard1 = insert_new_line(tmpcard1, newline, 0, tmpcard1->linenum_orig, tmpcard1->linesource);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -431,7 +438,7 @@ void inp_probe(struct card* deck)
|
||||||
allsaves = wl_cons(nodesaves, allsaves);
|
allsaves = wl_cons(nodesaves, allsaves);
|
||||||
tfree(strnode1);
|
tfree(strnode1);
|
||||||
tfree(strnode2);
|
tfree(strnode2);
|
||||||
tmpcard1 = insert_new_line(tmpcard1, newline, 0, 0);
|
tmpcard1 = insert_new_line(tmpcard1, newline, 0, tmpcard1->linenum_orig, tmpcard1->linesource);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* node containing ':'
|
/* node containing ':'
|
||||||
|
|
@ -584,7 +591,7 @@ void inp_probe(struct card* deck)
|
||||||
char *newline = tprintf("Ediff%d_%s_%s vd_%s:%s_%s:%s 0 %s %s 1", ee, instname1, instname2, instname1, nodename1, instname2, nodename2, strnode1, strnode2);
|
char *newline = tprintf("Ediff%d_%s_%s vd_%s:%s_%s:%s 0 %s %s 1", ee, instname1, instname2, instname1, nodename1, instname2, nodename2, strnode1, strnode2);
|
||||||
char* nodesaves = tprintf("vd_%s:%s_%s:%s", instname1, nodename1, instname2, nodename2);
|
char* nodesaves = tprintf("vd_%s:%s_%s:%s", instname1, nodename1, instname2, nodename2);
|
||||||
allsaves = wl_cons(nodesaves, allsaves);
|
allsaves = wl_cons(nodesaves, allsaves);
|
||||||
tmpcard1 = insert_new_line(tmpcard1, newline, 0, 0);
|
tmpcard1 = insert_new_line(tmpcard1, newline, 0, tmpcard1->linenum_orig, tmpcard1->linesource);
|
||||||
tfree(strnode1);
|
tfree(strnode1);
|
||||||
tfree(strnode2);
|
tfree(strnode2);
|
||||||
tfree(nodename1);
|
tfree(nodename1);
|
||||||
|
|
@ -706,7 +713,7 @@ void inp_probe(struct card* deck)
|
||||||
char* newline = tprintf("Ediff%d_%s vd_%s:%s:%s 0 %s %s 1", ee, instname1, instname1, nodename1, nodename2, strnode1, strnode2);
|
char* newline = tprintf("Ediff%d_%s vd_%s:%s:%s 0 %s %s 1", ee, instname1, instname1, nodename1, nodename2, strnode1, strnode2);
|
||||||
char* nodesaves = tprintf("vd_%s:%s:%s", instname1, nodename1, nodename2);
|
char* nodesaves = tprintf("vd_%s:%s:%s", instname1, nodename1, nodename2);
|
||||||
allsaves = wl_cons(nodesaves, allsaves);
|
allsaves = wl_cons(nodesaves, allsaves);
|
||||||
tmpcard1 = insert_new_line(tmpcard1, newline, 0, 0);
|
tmpcard1 = insert_new_line(tmpcard1, newline, 0, tmpcard1->linenum_orig, tmpcard1->linesource);
|
||||||
tfree(strnode1);
|
tfree(strnode1);
|
||||||
tfree(strnode2);
|
tfree(strnode2);
|
||||||
tfree(nodename1);
|
tfree(nodename1);
|
||||||
|
|
@ -744,6 +751,12 @@ void inp_probe(struct card* deck)
|
||||||
else
|
else
|
||||||
numnodes = get_number_terminals(thisline);
|
numnodes = get_number_terminals(thisline);
|
||||||
|
|
||||||
|
if (check_for_nodes(tmpcard->line, numnodes)) {
|
||||||
|
fprintf(stderr, "Error: Not enough tokens in line %d\n%s\n", tmpcard->linenum_orig, tmpcard->line);
|
||||||
|
fprintf(stderr, " Please correct your input file\n");
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
/* skip ',' */
|
/* skip ',' */
|
||||||
if (*tmpstr == ',')
|
if (*tmpstr == ',')
|
||||||
tmpstr++;
|
tmpstr++;
|
||||||
|
|
@ -790,8 +803,7 @@ void inp_probe(struct card* deck)
|
||||||
|
|
||||||
tfree(tmpcard->line);
|
tfree(tmpcard->line);
|
||||||
tmpcard->line = newline;
|
tmpcard->line = newline;
|
||||||
|
tmpcard = insert_new_line(tmpcard, vline, 0, tmpcard->linenum_orig, tmpcard->linesource);
|
||||||
tmpcard = insert_new_line(tmpcard, vline, 0, 0);
|
|
||||||
|
|
||||||
tfree(strnode2);
|
tfree(strnode2);
|
||||||
tfree(newnode);
|
tfree(newnode);
|
||||||
|
|
@ -845,8 +857,7 @@ void inp_probe(struct card* deck)
|
||||||
|
|
||||||
tfree(tmpcard->line);
|
tfree(tmpcard->line);
|
||||||
tmpcard->line = newline;
|
tmpcard->line = newline;
|
||||||
|
tmpcard = insert_new_line(tmpcard, vline, 0, tmpcard->linenum_orig, tmpcard->linesource);
|
||||||
tmpcard = insert_new_line(tmpcard, vline, 0, 0);
|
|
||||||
|
|
||||||
char* nodesaves = tprintf("%s:%s#branch", instname, nodename1);
|
char* nodesaves = tprintf("%s:%s#branch", instname, nodename1);
|
||||||
allsaves = wl_cons(nodesaves, allsaves);
|
allsaves = wl_cons(nodesaves, allsaves);
|
||||||
|
|
@ -886,6 +897,12 @@ void inp_probe(struct card* deck)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_for_nodes(tmpcard->line, numnodes)) {
|
||||||
|
fprintf(stderr, "Error: Not enough tokens in line %d\n%s\n", tmpcard->linenum_orig, tmpcard->line);
|
||||||
|
fprintf(stderr, " Please correct your input file\n");
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
/* call fcn with power requested */
|
/* call fcn with power requested */
|
||||||
err = setallvsources(tmpcard, instances, instname, numnodes, haveall, TRUE);
|
err = setallvsources(tmpcard, instances, instname, numnodes, haveall, TRUE);
|
||||||
|
|
@ -911,7 +928,7 @@ void inp_probe(struct card* deck)
|
||||||
wl_free(allsaves);
|
wl_free(allsaves);
|
||||||
allsaves = NULL;
|
allsaves = NULL;
|
||||||
card = deck->nextcard;
|
card = deck->nextcard;
|
||||||
card = insert_new_line(card, newline, 0, 0);
|
card = insert_new_line(card, newline, 0, card->linenum_orig, card->linesource);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1379,7 +1396,7 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn
|
||||||
|
|
||||||
card = tmpcard->nextcard;
|
card = tmpcard->nextcard;
|
||||||
|
|
||||||
card = insert_new_line(card, vline, 0, 0);
|
card = insert_new_line(card, vline, 0, card->linenum_orig, card->linesource);
|
||||||
|
|
||||||
if (power) {
|
if (power) {
|
||||||
/* For example V(1)+V(2)+V(3)*/
|
/* For example V(1)+V(2)+V(3)*/
|
||||||
|
|
@ -1422,14 +1439,14 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn
|
||||||
wl_free(allsaves);
|
wl_free(allsaves);
|
||||||
allsaves = NULL;
|
allsaves = NULL;
|
||||||
card = tmpcard->nextcard;
|
card = tmpcard->nextcard;
|
||||||
card = insert_new_line(card, newsaveline, 0, 0);
|
card = insert_new_line(card, newsaveline, 0, card->linenum_orig, card->linesource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (power) {
|
if (power) {
|
||||||
cadd(&BVrefline, ')');
|
cadd(&BVrefline, ')');
|
||||||
card = tmpcard->nextcard;
|
card = tmpcard->nextcard;
|
||||||
card = insert_new_line(card, copy(ds_get_buf(&BVrefline)), 0, 0);
|
card = insert_new_line(card, copy(ds_get_buf(&BVrefline)), 0, card->linenum_orig, card->linesource);
|
||||||
card = insert_new_line(card, copy(ds_get_buf(&Bpowerline)), 0, 0);
|
card = insert_new_line(card, copy(ds_get_buf(&Bpowerline)), 0, card->linenum_orig, card->linesource);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds_free(&BVrefline);
|
ds_free(&BVrefline);
|
||||||
|
|
@ -1437,3 +1454,17 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn
|
||||||
ds_free(&Bpowersave);
|
ds_free(&Bpowersave);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if there are enough tokens in an instance line */
|
||||||
|
static int check_for_nodes(char* instance, int numnodes) {
|
||||||
|
int i;
|
||||||
|
char* tmpinst = instance;
|
||||||
|
tmpinst = nexttok(tmpinst); /* instance name */
|
||||||
|
for (i = 0; i < numnodes; i++) {
|
||||||
|
tmpinst = nexttok(tmpinst);
|
||||||
|
if (!tmpinst || *tmpinst == '\0') {
|
||||||
|
return 1;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ Author: 1985 Wayne A. Christopher
|
||||||
#include "ngspice/fteinp.h"
|
#include "ngspice/fteinp.h"
|
||||||
#include "numparam/general.h"
|
#include "numparam/general.h"
|
||||||
|
|
||||||
|
#include "com_set.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
@ -115,12 +117,14 @@ int dynMaxckt = 0; /* subckt.c 307 */
|
||||||
/* number of parameter substitutions */
|
/* number of parameter substitutions */
|
||||||
long dynsubst; /* spicenum.c 221 */
|
long dynsubst; /* spicenum.c 221 */
|
||||||
|
|
||||||
|
wordlist* sourceinfo = NULL;
|
||||||
|
|
||||||
static bool has_if = FALSE; /* if we have an .if ... .endif pair */
|
static bool has_if = FALSE; /* if we have an .if ... .endif pair */
|
||||||
|
|
||||||
static char *readline(FILE *fd);
|
static char *readline(FILE *fd);
|
||||||
int get_number_terminals(char *c);
|
int get_number_terminals(char *c);
|
||||||
static void inp_stripcomments_deck(struct card *deck, bool cs);
|
static void inp_stripcomments_deck(struct card *deck, bool cs);
|
||||||
static void inp_stripcomments_line(char *s, bool cs);
|
static void inp_stripcomments_line(char *s, bool cs, bool inc);
|
||||||
static void inp_fix_for_numparam(
|
static void inp_fix_for_numparam(
|
||||||
struct names *subckt_w_params, struct card *deck);
|
struct names *subckt_w_params, struct card *deck);
|
||||||
static void inp_remove_excess_ws(struct card *deck);
|
static void inp_remove_excess_ws(struct card *deck);
|
||||||
|
|
@ -191,13 +195,15 @@ extern void inp_probe(struct card* card);
|
||||||
static void utf8_syntax_check(struct card *deck);
|
static void utf8_syntax_check(struct card *deck);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int add_to_sourcepath(const char* filepath, const char* path);
|
||||||
|
|
||||||
struct inp_read_t {
|
struct inp_read_t {
|
||||||
struct card *cc;
|
struct card *cc;
|
||||||
int line_number;
|
int line_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
|
static struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
|
||||||
bool comfile, bool intfile);
|
const char* file_name, bool comfile, bool intfile);
|
||||||
|
|
||||||
|
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
|
|
@ -430,7 +436,7 @@ static int is_xspice_model(char* buf)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct card *insert_new_line(
|
struct card *insert_new_line(
|
||||||
struct card *card, char *line, int linenum, int linenum_orig)
|
struct card *card, char *line, int linenum, int linenum_orig, char *lineinfo)
|
||||||
{
|
{
|
||||||
struct card *x = TMALLOC(struct card, 1);
|
struct card *x = TMALLOC(struct card, 1);
|
||||||
|
|
||||||
|
|
@ -441,6 +447,7 @@ struct card *insert_new_line(
|
||||||
x->linenum = linenum;
|
x->linenum = linenum;
|
||||||
x->linenum_orig = linenum_orig;
|
x->linenum_orig = linenum_orig;
|
||||||
x->level = card ? card->level : NULL;
|
x->level = card ? card->level : NULL;
|
||||||
|
x->linesource = lineinfo;
|
||||||
|
|
||||||
if (card)
|
if (card)
|
||||||
card->nextcard = x;
|
card->nextcard = x;
|
||||||
|
|
@ -580,7 +587,12 @@ static struct library *read_a_lib(const char *y, const char *dir_name)
|
||||||
lib->habitat = ngdirname(yy);
|
lib->habitat = ngdirname(yy);
|
||||||
|
|
||||||
lib->deck =
|
lib->deck =
|
||||||
inp_read(newfp, 1 /*dummy*/, lib->habitat, FALSE, FALSE).cc;
|
inp_read(newfp, 1 /*dummy*/, lib->habitat, lib->realpath, FALSE, FALSE).cc;
|
||||||
|
|
||||||
|
struct card* tmpdeck;
|
||||||
|
int cnumber = 1;
|
||||||
|
for (tmpdeck = lib->deck; tmpdeck; tmpdeck = tmpdeck->nextcard)
|
||||||
|
tmpdeck->linenum_orig = cnumber++;
|
||||||
|
|
||||||
fclose(newfp);
|
fclose(newfp);
|
||||||
}
|
}
|
||||||
|
|
@ -826,7 +838,7 @@ static void inp_cider_models(struct card* working)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prev->actualLine =
|
prev->actualLine =
|
||||||
insert_new_line(NULL, s, prev->linenum, 0);
|
insert_new_line(NULL, s, prev->linenum, prev->linenum_orig, prev->linesource);
|
||||||
prev->actualLine->level = prev->level;
|
prev->actualLine->level = prev->level;
|
||||||
prev->actualLine->nextcard = working;
|
prev->actualLine->nextcard = working;
|
||||||
}
|
}
|
||||||
|
|
@ -1025,7 +1037,7 @@ void inp_get_w_l_x(struct card* card) {
|
||||||
remove the 'level' entries from each card
|
remove the 'level' entries from each card
|
||||||
*-------------------------------------------------------------------------*/
|
*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
struct card *inp_readall(FILE *fp, const char *dir_name,
|
struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
|
||||||
bool comfile, bool intfile, bool *expr_w_temper_p)
|
bool comfile, bool intfile, bool *expr_w_temper_p)
|
||||||
{
|
{
|
||||||
struct card *cc;
|
struct card *cc;
|
||||||
|
|
@ -1035,7 +1047,7 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
|
||||||
/* set the members of the compatibility structure */
|
/* set the members of the compatibility structure */
|
||||||
set_compat_mode();
|
set_compat_mode();
|
||||||
|
|
||||||
rv = inp_read(fp, 0, dir_name, comfile, intfile);
|
rv = inp_read(fp, 0, dir_name, file_name, comfile, intfile);
|
||||||
cc = rv.cc;
|
cc = rv.cc;
|
||||||
|
|
||||||
/* skip all pre-processing for expanded input files created by 'listing r' */
|
/* skip all pre-processing for expanded input files created by 'listing r' */
|
||||||
|
|
@ -1205,22 +1217,22 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
|
||||||
"**************** uncommented deck "
|
"**************** uncommented deck "
|
||||||
"**************\n\n");
|
"**************\n\n");
|
||||||
/* always print first line */
|
/* always print first line */
|
||||||
fprintf(fd, "%6d %6d %s\n", cc->linenum_orig, cc->linenum,
|
fprintf(fd, "%6s %6d %6d %s\n", cc->linesource, cc->linenum_orig, cc->linenum,
|
||||||
cc->line);
|
cc->line);
|
||||||
/* here without out-commented lines */
|
/* here without out-commented lines */
|
||||||
for (t = cc->nextcard; t; t = t->nextcard) {
|
for (t = cc->nextcard; t; t = t->nextcard) {
|
||||||
if (*(t->line) == '*')
|
if (*(t->line) == '*')
|
||||||
continue;
|
continue;
|
||||||
fprintf(fd, "%6d %6d %s\n",
|
fprintf(fd, "%6s %6d %6d %s\n",
|
||||||
t->linenum_orig, t->linenum, t->line);
|
t->linesource, t->linenum_orig, t->linenum, t->line);
|
||||||
}
|
}
|
||||||
fprintf(fd,
|
fprintf(fd,
|
||||||
"\n****************** complete deck "
|
"\n****************** complete deck "
|
||||||
"***************\n\n");
|
"***************\n\n");
|
||||||
/* now completely */
|
/* now completely */
|
||||||
for (t = cc; t; t = t->nextcard)
|
for (t = cc; t; t = t->nextcard)
|
||||||
fprintf(fd, "%6d %6d %s\n",
|
fprintf(fd, "%6s %6d %6d %s\n",
|
||||||
t->linenum_orig, t->linenum, t->line);
|
t->linesource, t->linenum_orig,t->linenum, t->line);
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
|
|
||||||
fprintf(stdout,
|
fprintf(stdout,
|
||||||
|
|
@ -1240,8 +1252,8 @@ struct card *inp_readall(FILE *fp, const char *dir_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
bool comfile, bool intfile)
|
const char* file_name, bool comfile, bool intfile)
|
||||||
/* fp: in, pointer to file to be read,
|
/* fp: in, pointer to file to be read,
|
||||||
call_depth: in, nested call to fcn
|
call_depth: in, nested call to fcn
|
||||||
dir_name: in, name of directory of file to be read
|
dir_name: in, name of directory of file to be read
|
||||||
|
|
@ -1250,8 +1262,8 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
struct inp_read_t rv;
|
struct inp_read_t rv;
|
||||||
struct card* end = NULL, * cc = NULL;
|
struct card* end = NULL, * cc = NULL, *tmpcard=NULL;
|
||||||
char* buffer = NULL;
|
char* buffer = NULL, *sourcelineinfo=NULL;
|
||||||
/* segfault fix */
|
/* segfault fix */
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
char big_buff[5000];
|
char big_buff[5000];
|
||||||
|
|
@ -1269,6 +1281,15 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
static int in_cider_model = 0;
|
static int in_cider_model = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (intfile)
|
||||||
|
sourcelineinfo = copy("circbyline");
|
||||||
|
else {
|
||||||
|
sourcelineinfo = copy(file_name);
|
||||||
|
add_to_sourcepath(sourcelineinfo, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_append_word(&sourceinfo, &sourceinfo, sourcelineinfo);
|
||||||
|
|
||||||
/* First read in all lines & put them in the struct cc */
|
/* First read in all lines & put them in the struct cc */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* derive lines from circarray */
|
/* derive lines from circarray */
|
||||||
|
|
@ -1402,7 +1423,7 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
|
|
||||||
struct card* newcard;
|
struct card* newcard;
|
||||||
|
|
||||||
inp_stripcomments_line(buffer, FALSE);
|
inp_stripcomments_line(buffer, FALSE, TRUE);
|
||||||
|
|
||||||
s = skip_non_ws(buffer); /* advance past non-space chars */
|
s = skip_non_ws(buffer); /* advance past non-space chars */
|
||||||
|
|
||||||
|
|
@ -1418,21 +1439,22 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
char* y_resolved = inp_pathresolve_at(y, dir_name);
|
char* y_resolved = inp_pathresolve_at(y, dir_name);
|
||||||
char* y_dir_name;
|
char* y_dir_name;
|
||||||
FILE* newfp;
|
FILE* newfp;
|
||||||
|
static char oldpath[512];
|
||||||
|
|
||||||
if (!y_resolved) {
|
if (!y_resolved) {
|
||||||
fprintf(cp_err, "Error: Could not find include file %s\n",
|
/* try again with most recent .include path */
|
||||||
y);
|
y_resolved = inp_pathresolve_at(y, oldpath);
|
||||||
if (ft_stricterror)
|
if (!y_resolved) {
|
||||||
|
fprintf(cp_err, "Error: Could not find include file %s\n", y);
|
||||||
controlled_exit(EXIT_FAILURE);
|
controlled_exit(EXIT_FAILURE);
|
||||||
rv.line_number = line_number;
|
}
|
||||||
rv.cc = NULL;
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newfp = fopen(y_resolved, "r");
|
newfp = fopen(y_resolved, "r");
|
||||||
|
|
||||||
if (!newfp) {
|
if (!newfp) {
|
||||||
fprintf(cp_err, "Error: .include statement failed.\n");
|
fprintf(cp_err, "Error: .include statement failed.\n"
|
||||||
|
"Could not open file\n%s\n", y_resolved);
|
||||||
tfree(buffer); /* allocated by readline() above */
|
tfree(buffer); /* allocated by readline() above */
|
||||||
controlled_exit(EXIT_FAILURE);
|
controlled_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
@ -1440,11 +1462,18 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
y_dir_name = ngdirname(y_resolved);
|
y_dir_name = ngdirname(y_resolved);
|
||||||
|
|
||||||
newcard = inp_read(
|
newcard = inp_read(
|
||||||
newfp, call_depth + 1, y_dir_name, FALSE, FALSE)
|
newfp, call_depth + 1, y_dir_name, NULL, FALSE, FALSE)
|
||||||
.cc; /* read stuff in include file into
|
.cc; /* read stuff in include file into
|
||||||
netlist */
|
netlist */
|
||||||
|
|
||||||
tfree(y_dir_name);
|
strncpy(oldpath, y_dir_name, 511);
|
||||||
|
|
||||||
|
/* if we don't have dir_name, e.g. when the netlist is loaded via
|
||||||
|
circbyline, then set dir_name to first .include path found. */
|
||||||
|
if (dir_name)
|
||||||
|
tfree(y_dir_name);
|
||||||
|
else
|
||||||
|
dir_name = y_dir_name;
|
||||||
tfree(y_resolved);
|
tfree(y_resolved);
|
||||||
|
|
||||||
(void)fclose(newfp);
|
(void)fclose(newfp);
|
||||||
|
|
@ -1455,8 +1484,12 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
|
|
||||||
/* append `buffer' to the (cc, end) chain of decks */
|
/* append `buffer' to the (cc, end) chain of decks */
|
||||||
{
|
{
|
||||||
end = insert_new_line(
|
if (end)
|
||||||
end, copy(buffer), line_number, line_number);
|
end = insert_new_line(
|
||||||
|
end, copy(buffer), line_number, end->linenum_orig, end->linesource);
|
||||||
|
else
|
||||||
|
end = insert_new_line(
|
||||||
|
end, copy(buffer), line_number, 1, file_name);
|
||||||
|
|
||||||
if (!cc)
|
if (!cc)
|
||||||
cc = end;
|
cc = end;
|
||||||
|
|
@ -1464,6 +1497,15 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
line_number++;
|
line_number++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* tmpstr = copy(nexttok(buffer));
|
||||||
|
wl_append_word(&sourceinfo, &sourceinfo, tmpstr);
|
||||||
|
|
||||||
|
/* Add source of netlist data, for use in verbose error messages */
|
||||||
|
for (tmpcard = newcard; tmpcard; tmpcard = tmpcard->nextcard) {
|
||||||
|
/* skip *include */
|
||||||
|
tmpcard->linesource = tmpstr;
|
||||||
|
}
|
||||||
|
|
||||||
if (newcard) {
|
if (newcard) {
|
||||||
if (newcompat.lt && !newcompat.a)
|
if (newcompat.lt && !newcompat.a)
|
||||||
newcard = ltspice_compat(newcard);
|
newcard = ltspice_compat(newcard);
|
||||||
|
|
@ -1476,11 +1518,10 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
for (end = newcard; end && end->nextcard;
|
for (end = newcard; end && end->nextcard;
|
||||||
end = end->nextcard) {
|
end = end->nextcard) {
|
||||||
end->linenum = line_number++;
|
end->linenum = line_number++;
|
||||||
end->linenum_orig = line_number_inc++;
|
|
||||||
}
|
}
|
||||||
end->linenum = line_number++; /* SJB - renumber last line */
|
end->linenum = line_number++; /* SJB - renumber last line */
|
||||||
end->linenum_orig = line_number_inc++;
|
end->linenum_orig = line_number_inc++;
|
||||||
/* SJB - renumber the last line */
|
/* renumber the last line */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix the buffer up a bit. */
|
/* Fix the buffer up a bit. */
|
||||||
|
|
@ -1683,8 +1724,7 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
|
|
||||||
{
|
{
|
||||||
end = insert_new_line(
|
end = insert_new_line(
|
||||||
end, copy(buffer), line_number++, line_number_orig++);
|
end, copy(buffer), line_number++, line_number_orig++, sourcelineinfo);
|
||||||
|
|
||||||
if (!cc)
|
if (!cc)
|
||||||
cc = end;
|
cc = end;
|
||||||
}
|
}
|
||||||
|
|
@ -1705,10 +1745,10 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
|
|
||||||
if (call_depth == 0 && !comfile) {
|
if (call_depth == 0 && !comfile) {
|
||||||
if (!cp_getvar("no_auto_gnd", CP_BOOL, NULL, 0))
|
if (!cp_getvar("no_auto_gnd", CP_BOOL, NULL, 0))
|
||||||
insert_new_line(cc, copy(".global gnd"), 1, 0);
|
insert_new_line(cc, copy(".global gnd"), 1, 0, "internal");
|
||||||
else
|
else
|
||||||
insert_new_line(
|
insert_new_line(
|
||||||
cc, copy("* gnd is not set to 0 automatically "), 1, 0);
|
cc, copy("* gnd is not set to 0 automatically "), 1, 0, "internal");
|
||||||
|
|
||||||
if (!newcompat.lt && !newcompat.ps && !newcompat.s3) {
|
if (!newcompat.lt && !newcompat.ps && !newcompat.s3) {
|
||||||
/* process all library section references */
|
/* process all library section references */
|
||||||
|
|
@ -1723,7 +1763,7 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||||
if (call_depth == 0 && !comfile)
|
if (call_depth == 0 && !comfile)
|
||||||
if (found_end == TRUE)
|
if (found_end == TRUE)
|
||||||
end = insert_new_line(
|
end = insert_new_line(
|
||||||
end, copy(".end"), line_number++, line_number_orig++);
|
end, copy(".end"), line_number++, line_number_orig++, end->linesource);
|
||||||
|
|
||||||
/* Replace first line with the new title, if available */
|
/* Replace first line with the new title, if available */
|
||||||
if (call_depth == 0 && !comfile && new_title) {
|
if (call_depth == 0 && !comfile && new_title) {
|
||||||
|
|
@ -1908,9 +1948,99 @@ char *inp_pathresolve(const char *name)
|
||||||
} /* end of function inp_pathresolve */
|
} /* end of function inp_pathresolve */
|
||||||
|
|
||||||
|
|
||||||
|
/* Figure out if name starts with: environmental variables (replace them),
|
||||||
|
~/ (expand the tilde), absolute path name, all others and return the
|
||||||
|
path, if file exists. */
|
||||||
static char *inp_pathresolve_at(const char *name, const char *dir)
|
static char *inp_pathresolve_at(const char *name, const char *dir)
|
||||||
{
|
{
|
||||||
|
/* the string might contain one or two environmental variables at its front:
|
||||||
|
.lib $ENV1/filename
|
||||||
|
.lib $ENV1\$ENV2\dirs\filename
|
||||||
|
.lib $ENV1
|
||||||
|
.lib $ENV1/$ENV2
|
||||||
|
*/
|
||||||
|
if (name[0] == '$') {
|
||||||
|
char* s, * s1 = NULL, * tmpnam, * tmpcurr, * tmpcurr2 = NULL;
|
||||||
|
char* envvar, * envvar2 = NULL;
|
||||||
|
bool secenv = FALSE;
|
||||||
|
tmpcurr = tmpnam = copy(name);
|
||||||
|
while (*tmpcurr != '\0') {
|
||||||
|
if (*tmpcurr == '\\')
|
||||||
|
*tmpcurr = '/';
|
||||||
|
tmpcurr++;
|
||||||
|
}
|
||||||
|
tmpcurr = tmpnam;
|
||||||
|
/* extract env variable, add rest of token to its contents */
|
||||||
|
/* MS Windows directory separators */
|
||||||
|
envvar = gettok_char(&tmpcurr, '/', FALSE, FALSE);
|
||||||
|
if (envvar && ciprefix("/$", tmpcurr)) {
|
||||||
|
tmpcurr2 = tmpcurr + 1;
|
||||||
|
envvar2 = gettok_char(&tmpcurr2, '/', FALSE, FALSE);
|
||||||
|
secenv = TRUE;
|
||||||
|
}
|
||||||
|
if (envvar && !secenv) {
|
||||||
|
s = getenv(envvar + 1);
|
||||||
|
if (s) {
|
||||||
|
cp_vset(s, CP_STRING, envvar + 1);
|
||||||
|
char* newname = tprintf("%s%s", s, tmpcurr);
|
||||||
|
char* const r = inp_pathresolve(newname);
|
||||||
|
tfree(newname);
|
||||||
|
tfree(envvar);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar + 1);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
else if (envvar && envvar2) {
|
||||||
|
s = getenv(envvar + 1);
|
||||||
|
s1 = getenv(envvar2 + 1);
|
||||||
|
if (s && s1) {
|
||||||
|
char* newname = tprintf("%s/%s%s", s, s1, tmpcurr2);
|
||||||
|
char* const r = inp_pathresolve(newname);
|
||||||
|
tfree(newname);
|
||||||
|
tfree(envvar);
|
||||||
|
tfree(envvar2);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (!s)
|
||||||
|
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar + 1);
|
||||||
|
if (!s1)
|
||||||
|
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar2 + 1);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
else if (envvar && !envvar2 && secenv) {
|
||||||
|
s = getenv(envvar + 1);/* skip "$" */
|
||||||
|
envvar2 = copy(tmpcurr);
|
||||||
|
s1 = getenv(envvar2 + 2);/* skip "$/" */
|
||||||
|
if (s && s1) {
|
||||||
|
char* newname = tprintf("%s/%s", s, s1);
|
||||||
|
char* const r = inp_pathresolve(newname);
|
||||||
|
tfree(newname);
|
||||||
|
tfree(envvar);
|
||||||
|
tfree(envvar2);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (!s)
|
||||||
|
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar + 1);
|
||||||
|
if (!s1)
|
||||||
|
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar2 + 1);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no directory separator found, just use the env entry (must include file name) */
|
||||||
|
envvar = tmpnam;
|
||||||
|
s = getenv(envvar + 1);/* skip '$' */
|
||||||
|
if (s) {
|
||||||
|
cp_vset(s, CP_STRING, envvar + 1);
|
||||||
|
char* const r = inp_pathresolve(s);
|
||||||
|
tfree(envvar);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Error: Cannot read environmental variable %s\n", envvar + 1);
|
||||||
|
tfree(envvar);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
/* if name is an absolute path name,
|
/* if name is an absolute path name,
|
||||||
* or if we haven't anything to prepend anyway
|
* or if we haven't anything to prepend anyway
|
||||||
*/
|
*/
|
||||||
|
|
@ -1918,6 +2048,7 @@ static char *inp_pathresolve_at(const char *name, const char *dir)
|
||||||
return inp_pathresolve(name);
|
return inp_pathresolve(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* expand "~/" */
|
||||||
if (name[0] == '~' && name[1] == '/') {
|
if (name[0] == '~' && name[1] == '/') {
|
||||||
char * const y = cp_tildexpand(name);
|
char * const y = cp_tildexpand(name);
|
||||||
if (y) {
|
if (y) {
|
||||||
|
|
@ -2203,8 +2334,8 @@ static int inp_chk_for_multi_in_vcvs(struct card *c, int *line_number)
|
||||||
tfree(xy_values2[1]);
|
tfree(xy_values2[1]);
|
||||||
|
|
||||||
*c->line = '*';
|
*c->line = '*';
|
||||||
c = insert_new_line(c, m_instance, (*line_number)++, c->linenum_orig);
|
c = insert_new_line(c, m_instance, (*line_number)++, c->linenum_orig, c->linesource);
|
||||||
c = insert_new_line(c, m_model, (*line_number)++, c->linenum_orig);
|
c = insert_new_line(c, m_model, (*line_number)++, c->linenum_orig, c->linesource);
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2384,7 +2515,7 @@ static void replace_freq(struct card *c, int *line_number)
|
||||||
|
|
||||||
line = tprintf("b_gen_%.*s gen_node_%.*s 0 v=%.*s",
|
line = tprintf("b_gen_%.*s gen_node_%.*s 0 v=%.*s",
|
||||||
BSTR(e), BSTR(e), BSTR(expr));
|
BSTR(e), BSTR(e), BSTR(expr));
|
||||||
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig);
|
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig, c->linesource);
|
||||||
if (n2) {
|
if (n2) {
|
||||||
line = tprintf("a_gen_%.*s gen_node_%.*s %%%cd(%.*s %.*s) "
|
line = tprintf("a_gen_%.*s gen_node_%.*s %%%cd(%.*s %.*s) "
|
||||||
"gen_model_%.*s",
|
"gen_model_%.*s",
|
||||||
|
|
@ -2395,13 +2526,13 @@ static void replace_freq(struct card *c, int *line_number)
|
||||||
BSTR(e), BSTR(e), pt, BSTR(n1), BSTR(e));
|
BSTR(e), BSTR(e), pt, BSTR(n1), BSTR(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig);
|
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig, c->linesource);
|
||||||
|
|
||||||
line = tprintf(".model gen_model_%.*s xfer %s table = [%.*s]",
|
line = tprintf(".model gen_model_%.*s xfer %s table = [%.*s]",
|
||||||
BSTR(e),
|
BSTR(e),
|
||||||
ri ? "r_i=true" : rad ? "rad=true" : !db ? "db=false" : "",
|
ri ? "r_i=true" : rad ? "rad=true" : !db ? "db=false" : "",
|
||||||
BSTR(list));
|
BSTR(list));
|
||||||
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig);
|
c = insert_new_line(c, line, (*line_number)++, c->linenum_orig, c->linesource);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2472,12 +2603,12 @@ static void inp_add_control_section(struct card *deck, int *line_number)
|
||||||
if (last_end)
|
if (last_end)
|
||||||
prev_card = last_end;
|
prev_card = last_end;
|
||||||
for (lp = cards; *lp; ++lp)
|
for (lp = cards; *lp; ++lp)
|
||||||
prev_card = insert_new_line(prev_card, copy(*lp), (*line_number)++, 0);
|
prev_card = insert_new_line(prev_card, copy(*lp), (*line_number)++, 0, "internal");
|
||||||
if (cp_getvar("rawfile", CP_STRING, rawfile, sizeof(rawfile))) {
|
if (cp_getvar("rawfile", CP_STRING, rawfile, sizeof(rawfile))) {
|
||||||
line = tprintf("write %s", rawfile);
|
line = tprintf("write %s", rawfile);
|
||||||
prev_card = insert_new_line(prev_card, line, (*line_number)++, 0);
|
prev_card = insert_new_line(prev_card, line, (*line_number)++, 0, "internal");
|
||||||
}
|
}
|
||||||
insert_new_line(prev_card, copy(".endc"), (*line_number)++, 0);
|
insert_new_line(prev_card, copy(".endc"), (*line_number)++, 0, "internal");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3205,7 +3336,7 @@ static void inp_stripcomments_deck(struct card *c, bool cf)
|
||||||
found_control = TRUE;
|
found_control = TRUE;
|
||||||
if (ciprefix(".endc", c->line))
|
if (ciprefix(".endc", c->line))
|
||||||
found_control = FALSE;
|
found_control = FALSE;
|
||||||
inp_stripcomments_line(c->line, found_control | cf);
|
inp_stripcomments_line(c->line, found_control | cf, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3233,7 +3364,7 @@ static void inp_stripcomments_deck(struct card *c, bool cf)
|
||||||
character, not as end-of-line comment delimiter, except for that it is
|
character, not as end-of-line comment delimiter, except for that it is
|
||||||
located at the beginning of a line. If inside of a control section,
|
located at the beginning of a line. If inside of a control section,
|
||||||
still '$ ' is read a an end-of-line comment delimiter.*/
|
still '$ ' is read a an end-of-line comment delimiter.*/
|
||||||
static void inp_stripcomments_line(char *s, bool cs)
|
static void inp_stripcomments_line(char *s, bool cs, bool inc)
|
||||||
{
|
{
|
||||||
char c = ' '; /* anything other than a comment character */
|
char c = ' '; /* anything other than a comment character */
|
||||||
char *d = s;
|
char *d = s;
|
||||||
|
|
@ -3241,7 +3372,18 @@ static void inp_stripcomments_line(char *s, bool cs)
|
||||||
return; /* empty line */
|
return; /* empty line */
|
||||||
if (*s == '*')
|
if (*s == '*')
|
||||||
return; /* line is already a comment */
|
return; /* line is already a comment */
|
||||||
/* look for comments */
|
if (*s == '#') {
|
||||||
|
*s = '*'; // Convert to widely-recognised form.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inc) {
|
||||||
|
d = nexttok(d);
|
||||||
|
if (*d == '$')
|
||||||
|
d = nexttok(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for comments in body of line. */
|
||||||
while ((c = *d) != '\0') {
|
while ((c = *d) != '\0') {
|
||||||
d++;
|
d++;
|
||||||
|
|
||||||
|
|
@ -3388,7 +3530,7 @@ static char *inp_fix_subckt(struct names *subckt_w_params, char *s)
|
||||||
beg = skip_back_non_ws(beg, s);
|
beg = skip_back_non_ws(beg, s);
|
||||||
beg[-1] = '\0'; /* fixme can be < s */
|
beg[-1] = '\0'; /* fixme can be < s */
|
||||||
|
|
||||||
head = insert_new_line(NULL, NULL, 0, 0);
|
head = insert_new_line(NULL, NULL, 0, 0, "internal");
|
||||||
/* create list of parameters that need to get sorted */
|
/* create list of parameters that need to get sorted */
|
||||||
first_param_card = c = NULL;
|
first_param_card = c = NULL;
|
||||||
while ((ptr1 = strchr(beg, '=')) != NULL) {
|
while ((ptr1 = strchr(beg, '=')) != NULL) {
|
||||||
|
|
@ -3409,7 +3551,7 @@ static char *inp_fix_subckt(struct names *subckt_w_params, char *s)
|
||||||
|
|
||||||
beg = ptr2;
|
beg = ptr2;
|
||||||
|
|
||||||
c = insert_new_line(c, copy_substring(ptr1, ptr2), 0, 0);
|
c = insert_new_line(c, copy_substring(ptr1, ptr2), 0, 0, "internal");
|
||||||
|
|
||||||
if (!first_param_card)
|
if (!first_param_card)
|
||||||
first_param_card = c;
|
first_param_card = c;
|
||||||
|
|
@ -3643,7 +3785,7 @@ static struct card *expand_section_ref(struct card *c, const char *dir_name)
|
||||||
struct card *t = section_def;
|
struct card *t = section_def;
|
||||||
for (; t; t = t->nextcard) {
|
for (; t; t = t->nextcard) {
|
||||||
c = insert_new_line(
|
c = insert_new_line(
|
||||||
c, copy(t->line), t->linenum, t->linenum_orig);
|
c, copy(t->line), t->linenum, t->linenum_orig, t->linesource);
|
||||||
if (t == section_def) {
|
if (t == section_def) {
|
||||||
c->line[0] = '*';
|
c->line[0] = '*';
|
||||||
c->line[1] = '<';
|
c->line[1] = '<';
|
||||||
|
|
@ -5428,7 +5570,7 @@ static int inp_split_multi_param_lines(struct card *card, int line_num)
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new param lines immediately after current line
|
// insert new param lines immediately after current line
|
||||||
for (i = 0; i < counter; i++)
|
for (i = 0; i < counter; i++)
|
||||||
card = insert_new_line(card, array[i], line_num++, card->linenum_orig);
|
card = insert_new_line(card, array[i], line_num++, card->linenum_orig, card->linesource);
|
||||||
|
|
||||||
tfree(array);
|
tfree(array);
|
||||||
}
|
}
|
||||||
|
|
@ -5846,8 +5988,10 @@ static void inp_compat(struct card *card)
|
||||||
&cut_line, '}', TRUE, TRUE); /* expression */
|
&cut_line, '}', TRUE, TRUE); /* expression */
|
||||||
if (!expression || !str_ptr) {
|
if (!expression || !str_ptr) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: bad syntax in line %d\n %s\n",
|
"Error: bad syntax in line %d\n %s\n"
|
||||||
card->linenum_orig, card->line);
|
"from file\n"
|
||||||
|
" %s\n",
|
||||||
|
card->linenum_orig, card->line, card->linesource);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
tfree(str_ptr);
|
tfree(str_ptr);
|
||||||
|
|
@ -5916,8 +6060,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable e line
|
// comment out current variable e line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new lines immediately after current line
|
// insert new lines immediately after current line
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ckt_array[3] = tprintf(
|
ckt_array[3] = tprintf(
|
||||||
|
|
@ -5927,8 +6072,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable e line
|
// comment out current variable e line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new lines immediately after current line
|
// insert new lines immediately after current line
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tfree(expression);
|
tfree(expression);
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
|
|
@ -5972,9 +6118,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable e line
|
// comment out current variable e line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new B source line immediately after current line
|
// insert new B source line immediately after current line
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
tfree(node1);
|
tfree(node1);
|
||||||
tfree(node2);
|
tfree(node2);
|
||||||
|
|
@ -6039,8 +6185,11 @@ static void inp_compat(struct card *card)
|
||||||
// skip "table"
|
// skip "table"
|
||||||
cut_line = skip_ws(cut_line);
|
cut_line = skip_ws(cut_line);
|
||||||
if (!ciprefix("table", cut_line)) {
|
if (!ciprefix("table", cut_line)) {
|
||||||
fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
|
fprintf(stderr,
|
||||||
card->linenum_orig, card->line);
|
"Error: bad syntax in line %d\n %s\n"
|
||||||
|
"from file\n"
|
||||||
|
" %s\n",
|
||||||
|
card->linenum_orig, card->line, card->linesource);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
cut_line += 5;
|
cut_line += 5;
|
||||||
|
|
@ -6051,8 +6200,11 @@ static void inp_compat(struct card *card)
|
||||||
str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE);
|
str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE);
|
||||||
expression = gettok_char(&cut_line, '}', TRUE, TRUE);
|
expression = gettok_char(&cut_line, '}', TRUE, TRUE);
|
||||||
if (!expression || !str_ptr) {
|
if (!expression || !str_ptr) {
|
||||||
fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
|
fprintf(stderr,
|
||||||
card->linenum_orig, card->line);
|
"Error: bad syntax in line %d\n %s\n"
|
||||||
|
"from file\n"
|
||||||
|
" %s\n",
|
||||||
|
card->linenum_orig, card->line, card->linesource);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
tfree(str_ptr);
|
tfree(str_ptr);
|
||||||
|
|
@ -6129,8 +6281,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable e line
|
// comment out current variable e line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new lines immediately after current line
|
// insert new lines immediately after current line
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ckt_array[3] = tprintf(".model xfer_%s pwl(x_array=[%s] y_array=[%s] "
|
ckt_array[3] = tprintf(".model xfer_%s pwl(x_array=[%s] y_array=[%s] "
|
||||||
|
|
@ -6138,8 +6291,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable g line
|
// comment out current variable g line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new lines immediately after current line
|
// insert new lines immediately after current line
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tfree(expression);
|
tfree(expression);
|
||||||
|
|
@ -6195,8 +6349,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable g line
|
// comment out current variable g line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new B source line immediately after current line
|
// insert new B source line immediately after current line
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
|
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
tfree(m_token);
|
tfree(m_token);
|
||||||
|
|
@ -6241,8 +6396,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable f line
|
// comment out current variable f line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new three lines immediately after current line
|
// insert new three lines immediately after current line
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
|
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
tfree(vnamstr);
|
tfree(vnamstr);
|
||||||
|
|
@ -6287,8 +6443,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable h line
|
// comment out current variable h line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new three lines immediately after current line
|
// insert new three lines immediately after current line
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
|
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
tfree(vnamstr);
|
tfree(vnamstr);
|
||||||
|
|
@ -6359,11 +6516,11 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current old R line
|
// comment out current old R line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new B source line immediately after current line
|
// insert new B source line immediately after current line
|
||||||
card = insert_new_line(card, xline, 1, currlinenumber);
|
card = insert_new_line(card, xline, 1, currlinenumber, card->linesource);
|
||||||
if (rnoise) {
|
if (rnoise) {
|
||||||
card = insert_new_line(card, x2line, 2, currlinenumber);
|
card = insert_new_line(card, x2line, 2, currlinenumber, card->linesource);
|
||||||
card = insert_new_line(card, x3line, 3, currlinenumber);
|
card = insert_new_line(card, x3line, 3, currlinenumber, card->linesource);
|
||||||
card = insert_new_line(card, x4line, 4, currlinenumber);
|
card = insert_new_line(card, x4line, 4, currlinenumber, card->linesource);
|
||||||
}
|
}
|
||||||
|
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
|
|
@ -6438,8 +6595,9 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable capacitor line
|
// comment out current variable capacitor line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new B source line immediately after current line
|
// insert new B source line immediately after current line
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
|
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
tfree(node1);
|
tfree(node1);
|
||||||
|
|
@ -6497,14 +6655,53 @@ static void inp_compat(struct card *card)
|
||||||
// comment out current variable inductor line
|
// comment out current variable inductor line
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
// insert new B source line immediately after current line
|
// insert new B source line immediately after current line
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++) {
|
||||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
|
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
tfree(node1);
|
tfree(node1);
|
||||||
tfree(node2);
|
tfree(node2);
|
||||||
tfree(equation);
|
tfree(equation);
|
||||||
}
|
}
|
||||||
|
/* K1 L1 L2 L3 1 ->
|
||||||
|
K11 L1 L2 1
|
||||||
|
K12 L1 L3 1
|
||||||
|
K13 L2 L3 1
|
||||||
|
*/
|
||||||
|
else if (*curr_line == 'k') {
|
||||||
|
int tokcount = 0;
|
||||||
|
char* kinst, **ltok, *couple;
|
||||||
|
cut_line = curr_line;
|
||||||
|
/* get number of tokens */
|
||||||
|
while (*cut_line != '\0') {
|
||||||
|
cut_line = nexttok(cut_line);
|
||||||
|
tokcount++;
|
||||||
|
}
|
||||||
|
/* number of inductors */
|
||||||
|
tokcount -= 2;
|
||||||
|
/* replacement of line by two-inductor equivalents */
|
||||||
|
if (tokcount > 2) {
|
||||||
|
cut_line = curr_line;
|
||||||
|
kinst = gettok(&cut_line);
|
||||||
|
ltok = TMALLOC(char*, tokcount);
|
||||||
|
for (i = 0; i < tokcount; i++) {
|
||||||
|
ltok[i] = gettok(&cut_line);
|
||||||
|
}
|
||||||
|
couple = gettok(&cut_line);
|
||||||
|
*curr_line = '*';
|
||||||
|
for (i = 0; i < tokcount - 1; i++)
|
||||||
|
for (ii = i + 1; ii < tokcount; ii++) {
|
||||||
|
char* newline = tprintf("%s_%d_%d %s %s %s", kinst, i + 1, ii + 1, ltok[i], ltok[ii], couple);
|
||||||
|
card = insert_new_line(card, newline, (int)i + 1, currlinenumber, card->linesource);
|
||||||
|
}
|
||||||
|
tfree(kinst);
|
||||||
|
tfree(couple);
|
||||||
|
for (i = 0; i < tokcount; i++) {
|
||||||
|
tfree(ltok[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* .probe -> .save
|
/* .probe -> .save
|
||||||
.print, .plot, .save, .four,
|
.print, .plot, .save, .four,
|
||||||
An ouput vector may be replaced by the following:
|
An ouput vector may be replaced by the following:
|
||||||
|
|
@ -6656,7 +6853,7 @@ static void inp_compat(struct card *card)
|
||||||
card->line = inp_remove_ws(curr_line);
|
card->line = inp_remove_ws(curr_line);
|
||||||
// insert new B source line immediately after current line
|
// insert new B source line immediately after current line
|
||||||
for (ii = paui; ii < pai; ii++)
|
for (ii = paui; ii < pai; ii++)
|
||||||
card = insert_new_line(card, ckt_array[ii], (int)ii + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[ii], (int)ii + 1, currlinenumber, card->linesource);
|
||||||
|
|
||||||
paui = pai;
|
paui = pai;
|
||||||
}
|
}
|
||||||
|
|
@ -6753,7 +6950,7 @@ static void inp_compat(struct card *card)
|
||||||
// *(ckt_array[0]) = '*';
|
// *(ckt_array[0]) = '*';
|
||||||
// insert new B source line immediately after current line
|
// insert new B source line immediately after current line
|
||||||
for (ii = paui; ii < pai; ii++)
|
for (ii = paui; ii < pai; ii++)
|
||||||
card = insert_new_line(card, ckt_array[ii], (int)ii + 1, currlinenumber);
|
card = insert_new_line(card, ckt_array[ii], (int)ii + 1, currlinenumber, card->linesource);
|
||||||
|
|
||||||
paui = pai;
|
paui = pai;
|
||||||
// continue;
|
// continue;
|
||||||
|
|
@ -6854,7 +7051,7 @@ static void inp_bsource_compat(struct card *card)
|
||||||
// insert new B source line immediately after current line
|
// insert new B source line immediately after current line
|
||||||
/* Copy old line numbers into new B source line */
|
/* Copy old line numbers into new B source line */
|
||||||
card = insert_new_line(
|
card = insert_new_line(
|
||||||
card, final_str, card->linenum, card->linenum_orig);
|
card, final_str, card->linenum, card->linenum_orig, card->linesource);
|
||||||
|
|
||||||
tfree(new_str);
|
tfree(new_str);
|
||||||
} /* end of if 'b' */
|
} /* end of if 'b' */
|
||||||
|
|
@ -7215,8 +7412,8 @@ static void inp_add_series_resistor(struct card *deck)
|
||||||
*(card->line) = '*';
|
*(card->line) = '*';
|
||||||
|
|
||||||
// insert new new L and R lines immediately after current line
|
// insert new new L and R lines immediately after current line
|
||||||
card = insert_new_line(card, newL, 1, currlinenumber);
|
card = insert_new_line(card, newL, 1, currlinenumber, card->linesource);
|
||||||
card = insert_new_line(card, newR, 2, currlinenumber);
|
card = insert_new_line(card, newR, 2, currlinenumber, card->linesource);
|
||||||
|
|
||||||
tfree(title_tok);
|
tfree(title_tok);
|
||||||
tfree(node1);
|
tfree(node1);
|
||||||
|
|
@ -7252,7 +7449,7 @@ static void subckt_params_to_param(struct card *card)
|
||||||
/* card->line ends with subcircuit name */
|
/* card->line ends with subcircuit name */
|
||||||
cut_line[-1] = '\0';
|
cut_line[-1] = '\0';
|
||||||
/* insert new_line after card->line */
|
/* insert new_line after card->line */
|
||||||
insert_new_line(card, new_line, card->linenum + 1, card->linenum_orig);
|
insert_new_line(card, new_line, card->linenum + 1, card->linenum_orig, card->linesource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7612,7 +7809,7 @@ static void inp_fix_temper_in_param(struct card *deck)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Or just enter new line into deck */
|
/* Or just enter new line into deck */
|
||||||
insert_new_line(card, new_str, 0, card->linenum);
|
insert_new_line(card, new_str, 0, card->linenum_orig, card->linesource);
|
||||||
*card->line = '*';
|
*card->line = '*';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7821,7 +8018,7 @@ static void inp_fix_agauss_in_param(struct card *deck, char *fcn)
|
||||||
|
|
||||||
*card->line = '*';
|
*card->line = '*';
|
||||||
/* Enter new line into deck */
|
/* Enter new line into deck */
|
||||||
insert_new_line(card, new_str, 0, card->linenum);
|
insert_new_line(card, new_str, 0, card->linenum_orig, card->linesource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* final memory clearance */
|
/* final memory clearance */
|
||||||
|
|
@ -7890,7 +8087,7 @@ static struct func_temper *inp_new_func(char *funcname, char *funcbody,
|
||||||
new_str = tprintf(".func %s() %s", funcname, funcbody);
|
new_str = tprintf(".func %s() %s", funcname, funcbody);
|
||||||
|
|
||||||
*card->line = '*';
|
*card->line = '*';
|
||||||
insert_new_line(card, new_str, 0, card->linenum);
|
insert_new_line(card, new_str, 0, card->linenum_orig, card->linesource);
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
@ -8393,7 +8590,7 @@ static void inp_meas_current(struct card *deck)
|
||||||
new_line = tprintf("%s %s %s_vmeas_%d 0",
|
new_line = tprintf("%s %s %s_vmeas_%d 0",
|
||||||
new_tok, node1, node1, sn);
|
new_tok, node1, node1, sn);
|
||||||
/* insert new_line after card->line */
|
/* insert new_line after card->line */
|
||||||
insert_new_line(card, new_line, card->linenum + 1, card->linenum_orig);
|
insert_new_line(card, new_line, card->linenum + 1, card->linenum_orig, card->linesource);
|
||||||
}
|
}
|
||||||
sn++;
|
sn++;
|
||||||
tfree(new_tok);
|
tfree(new_tok);
|
||||||
|
|
@ -8431,8 +8628,8 @@ static void inp_check_syntax(struct card *deck)
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* When '.probe alli' is set, disable auto bridging and set a flag */
|
/* When '.probe alli' is set, disable auto bridging and set a flag */
|
||||||
|
cp_remvar("probe_alli_given");
|
||||||
for (card = deck; card; card = card->nextcard) {
|
for (card = deck; card; card = card->nextcard) {
|
||||||
char* cut_line = card->line;
|
char* cut_line = card->line;
|
||||||
if (ciprefix(".probe", cut_line) && search_plain_identifier(cut_line, "alli")) {
|
if (ciprefix(".probe", cut_line) && search_plain_identifier(cut_line, "alli")) {
|
||||||
|
|
@ -8496,7 +8693,7 @@ static void inp_check_syntax(struct card *deck)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// nesting may be critical if params are involved
|
// nesting may be critical if params are involved
|
||||||
if (nesting_once && check_subs > 0 && strchr(cut_line, '=')) {
|
if (ft_ngdebug && nesting_once && check_subs > 0 && strchr(cut_line, '=')) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"\nWarning: Nesting of subcircuits with parameters "
|
"\nWarning: Nesting of subcircuits with parameters "
|
||||||
"is only marginally supported!\n\n");
|
"is only marginally supported!\n\n");
|
||||||
|
|
@ -9294,3 +9491,45 @@ static int inp_poly_2g6_compat(struct card* deck) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* add path or filepath (without file name) to variable sourcepath */
|
||||||
|
int add_to_sourcepath(const char* filepath, const char* path)
|
||||||
|
{
|
||||||
|
const char* fpath;
|
||||||
|
char buf[512];
|
||||||
|
|
||||||
|
|
||||||
|
if ((filepath && path) || (!filepath && !path))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* if filepath, remove file entry */
|
||||||
|
if (path)
|
||||||
|
fpath = path;
|
||||||
|
else
|
||||||
|
fpath = ngdirname(filepath);
|
||||||
|
|
||||||
|
/* add fpath to 'sourcepath' list variable */
|
||||||
|
if (cp_getvar("sourcepath", CP_LIST, NULL, 0)) {
|
||||||
|
wordlist* wl;
|
||||||
|
char* toklist;
|
||||||
|
wl = vareval("sourcepath");
|
||||||
|
toklist = wl_flatten(wl);
|
||||||
|
(void)snprintf(buf, 511, "sourcepath = ( %s %s )", toklist, fpath);
|
||||||
|
wl_free(wl);
|
||||||
|
tfree(toklist);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(void)snprintf(buf, 511, "sourcepath = ( %s )", fpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fprintf(stdout, "Added to variable 'sourcepath':\n %s\n", fpath);
|
||||||
|
|
||||||
|
{
|
||||||
|
wordlist* wl;
|
||||||
|
wl = cp_doglob(cp_lexer(buf));
|
||||||
|
com_set(wl);
|
||||||
|
wl_free(wl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
#define ngspice_INPCOM_H
|
#define ngspice_INPCOM_H
|
||||||
|
|
||||||
struct card *insert_new_line(struct card *card, char *line,
|
struct card *insert_new_line(struct card *card, char *line,
|
||||||
int linenum, int linenum_orig);
|
int linenum, int linenum_orig, char *linesource);
|
||||||
char *inp_pathresolve(const char *name);
|
char *inp_pathresolve(const char *name);
|
||||||
|
|
||||||
extern char* inp_remove_ws(char* s);
|
extern char* inp_remove_ws(char* s);
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ static void replace_table(struct card *startcard)
|
||||||
tfree(begline);
|
tfree(begline);
|
||||||
tfree(card->line);
|
tfree(card->line);
|
||||||
card->line = cut_line = neweline;
|
card->line = cut_line = neweline;
|
||||||
insert_new_line(card, newbline, 0, card->linenum_orig);
|
insert_new_line(card, newbline, 0, card->linenum_orig, card->linesource);
|
||||||
/* read next TABLE function in cut_line */
|
/* read next TABLE function in cut_line */
|
||||||
ftablebeg = strstr(cut_line, "table(");
|
ftablebeg = strstr(cut_line, "table(");
|
||||||
}
|
}
|
||||||
|
|
@ -377,7 +377,7 @@ static bool del_models(struct vsmodels *vsmodel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for double '{', replace the inner '{', '}' by '(', ')'
|
/* Check for double '{', replace the inner '{', '}' by '(', ')'
|
||||||
in .subckt or .model (which both may stem from external sources) */
|
in .subckt, .model, or .param (which all three may stem from external sources) */
|
||||||
static void rem_double_braces(struct card* newcard)
|
static void rem_double_braces(struct card* newcard)
|
||||||
{
|
{
|
||||||
struct card* card;
|
struct card* card;
|
||||||
|
|
@ -389,7 +389,7 @@ static void rem_double_braces(struct card* newcard)
|
||||||
slevel++;
|
slevel++;
|
||||||
else if (ciprefix(".ends", cut_line))
|
else if (ciprefix(".ends", cut_line))
|
||||||
slevel--;
|
slevel--;
|
||||||
if (ciprefix(".model", cut_line) || slevel > 0) {
|
if (ciprefix(".model", cut_line) || slevel > 0 || ciprefix(".param", cut_line)) {
|
||||||
cut_line = strchr(cut_line, '{');
|
cut_line = strchr(cut_line, '{');
|
||||||
if (cut_line) {
|
if (cut_line) {
|
||||||
int level = 1;
|
int level = 1;
|
||||||
|
|
@ -505,6 +505,12 @@ static struct card *u_instances(struct card *startcard)
|
||||||
newcard = replacement_udevice_cards();
|
newcard = replacement_udevice_cards();
|
||||||
if (newcard) {
|
if (newcard) {
|
||||||
char *tmp = NULL, *pos, *posp, *new_str = NULL, *cl;
|
char *tmp = NULL, *pos, *posp, *new_str = NULL, *cl;
|
||||||
|
struct card* tmpc;
|
||||||
|
/* replace linenum_orig and linesource */
|
||||||
|
for (tmpc = newcard; tmpc; tmpc = tmpc->nextcard) {
|
||||||
|
tmpc->linenum_orig = subcktcard->linenum_orig;
|
||||||
|
tmpc->linesource = subcktcard->linesource;
|
||||||
|
}
|
||||||
DS_CREATE(ds_tmp, 128);
|
DS_CREATE(ds_tmp, 128);
|
||||||
/* Pspice definition of .subckt card:
|
/* Pspice definition of .subckt card:
|
||||||
.SUBCKT <name> [node]*
|
.SUBCKT <name> [node]*
|
||||||
|
|
@ -671,26 +677,26 @@ struct card *pspice_compat(struct card *oldcard)
|
||||||
|
|
||||||
/* add predefined params TEMP, VT, GMIN to beginning of deck */
|
/* add predefined params TEMP, VT, GMIN to beginning of deck */
|
||||||
char *new_str = copy(".param temp = 'temper'");
|
char *new_str = copy(".param temp = 'temper'");
|
||||||
newcard = insert_new_line(NULL, new_str, 1, 0);
|
newcard = insert_new_line(NULL, new_str, 1, 0, "internal");
|
||||||
new_str = copy(".param vt = '(temper + 273.15) * 8.6173303e-5'");
|
new_str = copy(".param vt = '(temper + 273.15) * 8.6173303e-5'");
|
||||||
nextcard = insert_new_line(newcard, new_str, 2, 0);
|
nextcard = insert_new_line(newcard, new_str, 2, 0, "internal");
|
||||||
new_str = copy(".param gmin = 1e-12");
|
new_str = copy(".param gmin = 1e-12");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 3, 0);
|
nextcard = insert_new_line(nextcard, new_str, 3, 0, "internal");
|
||||||
/* add funcs limit, pwr, pwrs, stp, if, int */
|
/* add funcs limit, pwr, pwrs, stp, if, int */
|
||||||
/* LIMIT( Output Expression, Limit1, Limit2)
|
/* LIMIT( Output Expression, Limit1, Limit2)
|
||||||
Output will stay between the two limits given. */
|
Output will stay between the two limits given. */
|
||||||
new_str = copy(".func limit(x, a, b) { ternary_fcn(a > b, max(min(x, a), b), max(min(x, b), a)) }");
|
new_str = copy(".func limit(x, a, b) { ternary_fcn(a > b, max(min(x, a), b), max(min(x, b), a)) }");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 4, 0);
|
nextcard = insert_new_line(nextcard, new_str, 4, 0, "internal");
|
||||||
new_str = copy(".func pwr(x, a) { pow(x, a) }");
|
new_str = copy(".func pwr(x, a) { pow(x, a) }");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 5, 0);
|
nextcard = insert_new_line(nextcard, new_str, 5, 0, "internal");
|
||||||
new_str = copy(".func pwrs(x, a) { sgn(x) * pow(x, a) }");
|
new_str = copy(".func pwrs(x, a) { sgn(x) * pow(x, a) }");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 6, 0);
|
nextcard = insert_new_line(nextcard, new_str, 6, 0, "internal");
|
||||||
new_str = copy(".func stp(x) { u(x) }");
|
new_str = copy(".func stp(x) { u(x) }");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 7, 0);
|
nextcard = insert_new_line(nextcard, new_str, 7, 0, "internal");
|
||||||
new_str = copy(".func if(a, b, c) {ternary_fcn( a , b , c )}");
|
new_str = copy(".func if(a, b, c) {ternary_fcn( a , b , c )}");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 8, 0);
|
nextcard = insert_new_line(nextcard, new_str, 8, 0, "internal");
|
||||||
new_str = copy(".func int(x) { sign(x)*floor(abs(x)) }");
|
new_str = copy(".func int(x) { sign(x)*floor(abs(x)) }");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 9, 0);
|
nextcard = insert_new_line(nextcard, new_str, 9, 0, "internal");
|
||||||
nextcard->nextcard = oldcard;
|
nextcard->nextcard = oldcard;
|
||||||
|
|
||||||
#ifdef INTEGRATE_UDEVICES
|
#ifdef INTEGRATE_UDEVICES
|
||||||
|
|
@ -714,9 +720,9 @@ struct card *pspice_compat(struct card *oldcard)
|
||||||
char *cut_line = card->line;
|
char *cut_line = card->line;
|
||||||
if (ciprefix(".subckt", cut_line)) {
|
if (ciprefix(".subckt", cut_line)) {
|
||||||
new_str = copy(".param temp = 'temper'");
|
new_str = copy(".param temp = 'temper'");
|
||||||
nextcard = insert_new_line(card, new_str, 0, 0);
|
nextcard = insert_new_line(card, new_str, 0, card->linenum_orig, card->linesource);
|
||||||
new_str = copy(".param vt = '(temper + 273.15) * 8.6173303e-5'");
|
new_str = copy(".param vt = '(temper + 273.15) * 8.6173303e-5'");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 1, 0);
|
nextcard = insert_new_line(nextcard, new_str, 1, card->linenum_orig, card->linesource);
|
||||||
/* params: replace comma separator by space.
|
/* params: replace comma separator by space.
|
||||||
Do nothing if you are inside of { }. */
|
Do nothing if you are inside of { }. */
|
||||||
char* parastr = strstr(cut_line, "params:");
|
char* parastr = strstr(cut_line, "params:");
|
||||||
|
|
@ -912,10 +918,7 @@ struct card *pspice_compat(struct card *oldcard)
|
||||||
fprintf(stderr, "Error: Missing token in line %d:\n%s\n",
|
fprintf(stderr, "Error: Missing token in line %d:\n%s\n",
|
||||||
card->linenum, cut_line);
|
card->linenum, cut_line);
|
||||||
fprintf(stderr, " Please correct the input file\n");
|
fprintf(stderr, " Please correct the input file\n");
|
||||||
if (ft_stricterror)
|
controlled_exit(1);
|
||||||
controlled_exit(1);
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
char *tctok = search_plain_identifier(ntok, "tc");
|
char *tctok = search_plain_identifier(ntok, "tc");
|
||||||
if (tctok) {
|
if (tctok) {
|
||||||
|
|
@ -1363,7 +1366,11 @@ struct card *pspice_compat(struct card *oldcard)
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
stoks[i] = gettok_node(&cut_line);
|
stoks[i] = gettok_node(&cut_line);
|
||||||
if (!stoks[i]) {
|
if (!stoks[i]) {
|
||||||
fprintf(stderr, "Error: Bad syntax in line:\n %s\n", card->line);
|
fprintf(stderr,
|
||||||
|
"Error: bad syntax in line %d\n %s\n"
|
||||||
|
"from file\n"
|
||||||
|
" %s\n",
|
||||||
|
card->linenum_orig, card->line, card->linesource);
|
||||||
good = FALSE;
|
good = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1726,16 +1733,16 @@ struct card *ltspice_compat(struct card *oldcard)
|
||||||
char *new_str =
|
char *new_str =
|
||||||
copy(".func uplim(x, pos, z) { min(x, pos - z) + (1 - "
|
copy(".func uplim(x, pos, z) { min(x, pos - z) + (1 - "
|
||||||
"(min(max(0, x - pos + z), 2 * z) / 2 / z - 1)**2)*z }");
|
"(min(max(0, x - pos + z), 2 * z) / 2 / z - 1)**2)*z }");
|
||||||
newcard = insert_new_line(NULL, new_str, 1, 0);
|
newcard = insert_new_line(NULL, new_str, 1, 0, "internal");
|
||||||
new_str = copy(".func dnlim(x, neg, z) { max(x, neg + z) - (1 - "
|
new_str = copy(".func dnlim(x, neg, z) { max(x, neg + z) - (1 - "
|
||||||
"(min(max(0, -x + neg + z), 2 * z) / 2 / z - 1)**2)*z }");
|
"(min(max(0, -x + neg + z), 2 * z) / 2 / z - 1)**2)*z }");
|
||||||
nextcard = insert_new_line(newcard, new_str, 2, 0);
|
nextcard = insert_new_line(newcard, new_str, 2, 0, "internal");
|
||||||
new_str = copy(".func uplim_tanh(x, pos, z) { min(x, pos - z) + "
|
new_str = copy(".func uplim_tanh(x, pos, z) { min(x, pos - z) + "
|
||||||
"tanh(max(0, x - pos + z) / z)*z }");
|
"tanh(max(0, x - pos + z) / z)*z }");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 3, 0);
|
nextcard = insert_new_line(nextcard, new_str, 3, 0, "internal");
|
||||||
new_str = copy(".func dnlim_tanh(x, neg, z) { max(x, neg + z) - "
|
new_str = copy(".func dnlim_tanh(x, neg, z) { max(x, neg + z) - "
|
||||||
"tanh(max(0, neg + z - x) / z)*z }");
|
"tanh(max(0, neg + z - x) / z)*z }");
|
||||||
nextcard = insert_new_line(nextcard, new_str, 4, 0);
|
nextcard = insert_new_line(nextcard, new_str, 4, 0, "internal");
|
||||||
nextcard->nextcard = oldcard;
|
nextcard->nextcard = oldcard;
|
||||||
|
|
||||||
/* remove .backanno, replace 'noiseless' by 'moisy=0' */
|
/* remove .backanno, replace 'noiseless' by 'moisy=0' */
|
||||||
|
|
@ -1869,7 +1876,7 @@ struct card *ltspice_compat(struct card *oldcard)
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
stoks[i] = gettok_node(&cut_line);
|
stoks[i] = gettok_node(&cut_line);
|
||||||
if (stoks[i] == NULL) {
|
if (stoks[i] == NULL) {
|
||||||
fprintf(stderr, "Error in line %d: buggy diode instance line\n %s\n", card->linenum_orig, card->line);
|
fprintf(stderr, "Error in line %d: buggy diode instance line\n %s\n", card->linenum_orig, card->linesource);
|
||||||
fprintf(stderr, "At least 'Dxx n1 n2 d' is required.\n");
|
fprintf(stderr, "At least 'Dxx n1 n2 d' is required.\n");
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,10 @@ com_quit(wordlist *wl)
|
||||||
|
|
||||||
/* Destroy CKT when quit. */
|
/* Destroy CKT when quit. */
|
||||||
if (!ft_nutmeg) {
|
if (!ft_nutmeg) {
|
||||||
while(ft_curckt)
|
while (ft_curckt) {
|
||||||
|
wl_delete(ft_curckt->ci_sourceinfo);
|
||||||
com_remcirc(NULL);
|
com_remcirc(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cp_destroy_keywords();
|
cp_destroy_keywords();
|
||||||
destroy_ivars();
|
destroy_ivars();
|
||||||
|
|
@ -102,8 +104,10 @@ com_quit(wordlist *wl)
|
||||||
/* remove plotting parameters */
|
/* remove plotting parameters */
|
||||||
pl_rempar();
|
pl_rempar();
|
||||||
|
|
||||||
while (ft_curckt)
|
while (ft_curckt) {
|
||||||
|
// wl_delete(ft_curckt->ci_sourceinfo);
|
||||||
com_remcirc(NULL);
|
com_remcirc(NULL);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tfree(errMsg);
|
tfree(errMsg);
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ inp_nutsource(FILE *fp, bool comfile, char *filename)
|
||||||
wordlist *controls = NULL;
|
wordlist *controls = NULL;
|
||||||
FILE *lastin, *lastout, *lasterr;
|
FILE *lastin, *lastout, *lasterr;
|
||||||
|
|
||||||
deck = inp_readall(fp, NULL, comfile, FALSE, NULL); /* still to check if . or filename instead of NULL */
|
deck = inp_readall(fp, NULL, NULL, comfile, FALSE, NULL); /* still to check if . or filename instead of NULL */
|
||||||
if (!deck)
|
if (!deck)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
||||||
bool ft_acctprint = FALSE, ft_noacctprint = FALSE, ft_listprint = FALSE;
|
bool ft_acctprint = FALSE, ft_noacctprint = FALSE, ft_listprint = FALSE;
|
||||||
bool ft_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = FALSE;
|
bool ft_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = FALSE;
|
||||||
bool ft_norefprint = FALSE, ft_skywaterpdk = FALSE;
|
bool ft_norefprint = FALSE, ft_skywaterpdk = FALSE;
|
||||||
bool ft_ngdebug = FALSE, ft_nginfo = FALSE, ft_stricterror = FALSE;
|
bool ft_ngdebug = FALSE, ft_nginfo = FALSE, ft_stricterror = FALSE, ft_spiniterror = FALSE;
|
||||||
|
|
||||||
static void setdb(char *str);
|
static void setdb(char *str);
|
||||||
static struct variable *cp_enqvec_as_var(const char *vec_name,
|
static struct variable *cp_enqvec_as_var(const char *vec_name,
|
||||||
|
|
@ -327,6 +327,11 @@ cp_usrset(struct variable *var, bool isset)
|
||||||
ft_strictnumparse = isset;
|
ft_strictnumparse = isset;
|
||||||
} else if (eq(var->va_name, "strict_errorhandling")) {
|
} else if (eq(var->va_name, "strict_errorhandling")) {
|
||||||
ft_stricterror = isset;
|
ft_stricterror = isset;
|
||||||
|
if (ft_ngdebug)
|
||||||
|
fprintf(stdout, "Note: strict_errorhandling is set\n");
|
||||||
|
/* Immediately bail out when spinit error has occured */
|
||||||
|
if (ft_spiniterror)
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
} else if (eq(var->va_name, "rawfileprec")) {
|
} else if (eq(var->va_name, "rawfileprec")) {
|
||||||
if ((var->va_type == CP_BOOL) && (isset == FALSE))
|
if ((var->va_type == CP_BOOL) && (isset == FALSE))
|
||||||
raw_prec = -1;
|
raw_prec = -1;
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
|
||||||
char *ch, tmpname[BSIZE_SP];
|
char *ch, tmpname[BSIZE_SP];
|
||||||
bool saveall = TRUE;
|
bool saveall = TRUE;
|
||||||
bool savealli = FALSE;
|
bool savealli = FALSE;
|
||||||
|
bool savenosub = FALSE;
|
||||||
char *an_name;
|
char *an_name;
|
||||||
int initmem;
|
int initmem;
|
||||||
/*to resume a run saj
|
/*to resume a run saj
|
||||||
|
|
@ -213,6 +214,13 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
|
||||||
saves[i].used = 1;
|
saves[i].used = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cieq(saves[i].name, "nosub")) {
|
||||||
|
savenosub = TRUE;
|
||||||
|
savesused[i] = TRUE;
|
||||||
|
saves[i].used = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#ifdef SHARED_MODULE
|
#ifdef SHARED_MODULE
|
||||||
/* this may happen if shared ngspice*/
|
/* this may happen if shared ngspice*/
|
||||||
if (cieq(saves[i].name, "none")) {
|
if (cieq(saves[i].name, "none")) {
|
||||||
|
|
@ -226,7 +234,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numsaves && !saveall)
|
if (numsaves && !saveall && !savenosub)
|
||||||
initmem = numsaves;
|
initmem = numsaves;
|
||||||
else
|
else
|
||||||
initmem = numNames;
|
initmem = numNames;
|
||||||
|
|
@ -245,7 +253,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
|
||||||
|
|
||||||
|
|
||||||
/* Pass 1. */
|
/* Pass 1. */
|
||||||
if (numsaves && !saveall) {
|
if (numsaves && !saveall && !savenosub) {
|
||||||
for (i = 0; i < numsaves; i++) {
|
for (i = 0; i < numsaves; i++) {
|
||||||
if (!savesused[i]) {
|
if (!savesused[i]) {
|
||||||
for (j = 0; j < numNames; j++) {
|
for (j = 0; j < numNames; j++) {
|
||||||
|
|
@ -269,7 +277,8 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
|
||||||
for (i = 0; i < numNames; i++)
|
for (i = 0; i < numNames; i++)
|
||||||
if (!refName || !name_eq(dataNames[i], refName))
|
if (!refName || !name_eq(dataNames[i], refName))
|
||||||
/* Save the node as long as it's not an internal device node */
|
/* Save the node as long as it's not an internal device node */
|
||||||
if (!strstr(dataNames[i], "#internal") &&
|
if (!(savenosub && strchr(dataNames[i], '.')) && /* don't save subckt nodes */
|
||||||
|
!strstr(dataNames[i], "#internal") &&
|
||||||
!strstr(dataNames[i], "#source") &&
|
!strstr(dataNames[i], "#source") &&
|
||||||
!strstr(dataNames[i], "#drain") &&
|
!strstr(dataNames[i], "#drain") &&
|
||||||
!strstr(dataNames[i], "#collector") &&
|
!strstr(dataNames[i], "#collector") &&
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ extern struct INPmodel *modtab;
|
||||||
extern NGHASHPTR modtabhash;
|
extern NGHASHPTR modtabhash;
|
||||||
extern struct dbcomm *dbs;
|
extern struct dbcomm *dbs;
|
||||||
extern void NIresetwarnmsg(void);
|
extern void NIresetwarnmsg(void);
|
||||||
|
extern wordlist* sourceinfo;
|
||||||
|
|
||||||
/* Routines for the commands op, tran, ac, dc, listing, device, state,
|
/* Routines for the commands op, tran, ac, dc, listing, device, state,
|
||||||
* resume, stop, trace, run, end. Op, tran, ac, and dc cause the action
|
* resume, stop, trace, run, end. Op, tran, ac, and dc cause the action
|
||||||
|
|
@ -109,6 +110,8 @@ com_scirc(wordlist *wl)
|
||||||
ft_curckt = p;
|
ft_curckt = p;
|
||||||
/* get the model table for the current circuit, store it in the global variable modtab */
|
/* get the model table for the current circuit, store it in the global variable modtab */
|
||||||
modtab = ft_curckt->ci_modtab;
|
modtab = ft_curckt->ci_modtab;
|
||||||
|
/* get the current input file names */
|
||||||
|
sourceinfo = ft_curckt->ci_sourceinfo;
|
||||||
modtabhash = ft_curckt->ci_modtabhash;
|
modtabhash = ft_curckt->ci_modtabhash;
|
||||||
/* get the database for save, iplot, stop */
|
/* get the database for save, iplot, stop */
|
||||||
dbs = ft_curckt->ci_dbs;
|
dbs = ft_curckt->ci_dbs;
|
||||||
|
|
|
||||||
|
|
@ -841,6 +841,8 @@ struct card * inp_deckcopy(struct card *deck) {
|
||||||
nd = d = TMALLOC(struct card, 1);
|
nd = d = TMALLOC(struct card, 1);
|
||||||
}
|
}
|
||||||
d->linenum = deck->linenum;
|
d->linenum = deck->linenum;
|
||||||
|
d->linenum_orig = deck->linenum_orig;
|
||||||
|
d->linesource = deck->linesource;
|
||||||
d->w = deck->w;
|
d->w = deck->w;
|
||||||
d->l = deck->l;
|
d->l = deck->l;
|
||||||
d->nf = deck->nf;
|
d->nf = deck->nf;
|
||||||
|
|
@ -889,7 +891,8 @@ struct card *inp_deckcopy_oc(struct card * deck)
|
||||||
d->w = deck->w;
|
d->w = deck->w;
|
||||||
d->l = deck->l;
|
d->l = deck->l;
|
||||||
d->nf = deck->nf;
|
d->nf = deck->nf;
|
||||||
d->linenum_orig = deck->linenum;
|
d->linenum_orig = deck->linenum_orig;
|
||||||
|
d->linesource = deck->linesource;
|
||||||
d->linenum = i++;
|
d->linenum = i++;
|
||||||
d->line = copy(deck->line);
|
d->line = copy(deck->line);
|
||||||
if (deck->error) {
|
if (deck->error) {
|
||||||
|
|
@ -947,6 +950,7 @@ struct card* inp_deckcopy_ln(struct card* deck)
|
||||||
d->l = deck->l;
|
d->l = deck->l;
|
||||||
d->nf = deck->nf;
|
d->nf = deck->nf;
|
||||||
d->linenum_orig = deck->linenum_orig;
|
d->linenum_orig = deck->linenum_orig;
|
||||||
|
d->linesource = deck->linesource;
|
||||||
d->linenum = deck->linenum;
|
d->linenum = deck->linenum;
|
||||||
d->line = copy(deck->line);
|
d->line = copy(deck->line);
|
||||||
if (deck->error) {
|
if (deck->error) {
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
#include "ngspice/hash.h"
|
#include "ngspice/hash.h"
|
||||||
|
|
||||||
extern struct card* insert_new_line(
|
extern struct card* insert_new_line(
|
||||||
struct card* card, char* line, int linenum, int linenum_orig);
|
struct card* card, char* line, int linenum, int linenum_orig, char *lineinfo);
|
||||||
|
|
||||||
/* device types */
|
/* device types */
|
||||||
#define D_AND 0
|
#define D_AND 0
|
||||||
|
|
@ -845,13 +845,13 @@ struct card *replacement_udevice_cards(void)
|
||||||
new_str = copy(x->translated);
|
new_str = copy(x->translated);
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
count++;
|
count++;
|
||||||
newcard = insert_new_line(NULL, new_str, 0, 0);
|
newcard = insert_new_line(NULL, new_str, 0, 0, NULL);
|
||||||
} else if (count == 1) {
|
} else if (count == 1) {
|
||||||
count++;
|
count++;
|
||||||
nextcard = insert_new_line(newcard, new_str, 0, 0);
|
nextcard = insert_new_line(newcard, new_str, 0, 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
count++;
|
count++;
|
||||||
nextcard = insert_new_line(nextcard, new_str, 0, 0);
|
nextcard = insert_new_line(nextcard, new_str, 0, 0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (current_subckt && (ps_ports_and_pins & 2)) {
|
if (current_subckt && (ps_ports_and_pins & 2)) {
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,6 @@ typedef struct SPICEdev {
|
||||||
/* noise routine */
|
/* noise routine */
|
||||||
int (*DEVsoaCheck)(CKTcircuit*,GENmodel*);
|
int (*DEVsoaCheck)(CKTcircuit*,GENmodel*);
|
||||||
/* subroutine to call on soa check */
|
/* subroutine to call on soa check */
|
||||||
int *DEVinstSize; /* size of an instance */
|
|
||||||
int *DEVmodSize; /* size of a model */
|
|
||||||
|
|
||||||
#ifdef CIDER
|
#ifdef CIDER
|
||||||
void (*DEVdump)(GENmodel *, CKTcircuit *);
|
void (*DEVdump)(GENmodel *, CKTcircuit *);
|
||||||
void (*DEVacct)(GENmodel *, CKTcircuit *, FILE *);
|
void (*DEVacct)(GENmodel *, CKTcircuit *, FILE *);
|
||||||
|
|
@ -117,6 +114,8 @@ typedef struct SPICEdev {
|
||||||
* now used only by cider numerical devices
|
* now used only by cider numerical devices
|
||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
int *DEVinstSize; /* size of an instance */
|
||||||
|
int *DEVmodSize; /* size of a model */
|
||||||
|
|
||||||
#ifdef KLU
|
#ifdef KLU
|
||||||
int (*DEVbindCSC)(GENmodel *, CKTcircuit *);
|
int (*DEVbindCSC)(GENmodel *, CKTcircuit *);
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ struct circ {
|
||||||
struct ccom *ci_nodes; /* ccom structs for the nodes... */
|
struct ccom *ci_nodes; /* ccom structs for the nodes... */
|
||||||
struct ccom *ci_devices; /* and devices in the circuit. */
|
struct ccom *ci_devices; /* and devices in the circuit. */
|
||||||
char *ci_filename; /* Where this circuit came from. */
|
char *ci_filename; /* Where this circuit came from. */
|
||||||
|
wordlist* ci_sourceinfo; /* paths and names of input files */
|
||||||
TSKtask *ci_defTask; /* default task for this circuit */
|
TSKtask *ci_defTask; /* default task for this circuit */
|
||||||
TSKtask *ci_specTask; /* special task for command line jobs */
|
TSKtask *ci_specTask; /* special task for command line jobs */
|
||||||
TSKtask *ci_curTask; /* most recent task for this circuit */
|
TSKtask *ci_curTask; /* most recent task for this circuit */
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ extern void inp_source(const char *file);
|
||||||
int inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile);
|
int inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile);
|
||||||
extern void inp_casefix(char *string);
|
extern void inp_casefix(char *string);
|
||||||
extern void inp_list(FILE *file, struct card *deck, struct card *extras, int type);
|
extern void inp_list(FILE *file, struct card *deck, struct card *extras, int type);
|
||||||
struct card *inp_readall(FILE *fp, const char *dir_name,
|
struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
|
||||||
bool comfile, bool intfile, bool *expr_w_temper_p);
|
bool comfile, bool intfile, bool *expr_w_temper_p);
|
||||||
extern FILE *inp_pathopen(const char *name, const char *mode);
|
extern FILE *inp_pathopen(const char *name, const char *mode);
|
||||||
extern char *search_identifier(char *str, const char *identifier, char *str_begin);
|
extern char *search_identifier(char *str, const char *identifier, char *str_begin);
|
||||||
|
|
@ -268,6 +268,7 @@ extern struct card *inp_getoptsc(char *line, struct card *options);
|
||||||
extern bool ft_ngdebug;
|
extern bool ft_ngdebug;
|
||||||
extern bool ft_nginfo;
|
extern bool ft_nginfo;
|
||||||
extern bool ft_stricterror;
|
extern bool ft_stricterror;
|
||||||
|
extern bool ft_spiniterror;
|
||||||
extern bool ft_skywaterpdk;
|
extern bool ft_skywaterpdk;
|
||||||
|
|
||||||
/* parse.c */
|
/* parse.c */
|
||||||
|
|
|
||||||
|
|
@ -282,8 +282,6 @@ struct IFdevice {
|
||||||
int *numModelParms; /* number of model parameter descriptors */
|
int *numModelParms; /* number of model parameter descriptors */
|
||||||
IFparm *modelParms; /* array of model parameter descriptors */
|
IFparm *modelParms; /* array of model parameter descriptors */
|
||||||
|
|
||||||
int flags; /* DEV_ */
|
|
||||||
|
|
||||||
/* gtri - modify - wbk - 10/11/90 - add entries to hold data required */
|
/* gtri - modify - wbk - 10/11/90 - add entries to hold data required */
|
||||||
/* by new parser */
|
/* by new parser */
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
|
|
@ -300,6 +298,8 @@ struct IFdevice {
|
||||||
/* gtri - end - wbk - 10/11/90 */
|
/* gtri - end - wbk - 10/11/90 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int flags; /* DEV_ */
|
||||||
|
|
||||||
#ifdef OSDI
|
#ifdef OSDI
|
||||||
const void *registry_entry;
|
const void *registry_entry;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ struct card_assoc {
|
||||||
struct card {
|
struct card {
|
||||||
int linenum;
|
int linenum;
|
||||||
int linenum_orig;
|
int linenum_orig;
|
||||||
|
char* linesource;
|
||||||
char *line;
|
char *line;
|
||||||
char *error;
|
char *error;
|
||||||
struct card *nextcard;
|
struct card *nextcard;
|
||||||
|
|
@ -96,7 +97,9 @@ struct INPmodel {
|
||||||
GENmodel *INPmodfast; /* high speed pointer to model for access */
|
GENmodel *INPmodfast; /* high speed pointer to model for access */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ugly way to pass line onfo (number and source file) to lower-level error handlers.
|
||||||
|
extern int Current_parse_line;
|
||||||
|
extern char* Sourcefile;
|
||||||
|
|
||||||
/* listing types - used for debug listings */
|
/* listing types - used for debug listings */
|
||||||
#define LOGICAL 1
|
#define LOGICAL 1
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ void wl_delete_slice(wordlist *from, wordlist *to);
|
||||||
wordlist *wl_find(const char *string, const wordlist *wlist);
|
wordlist *wl_find(const char *string, const wordlist *wlist);
|
||||||
char * wl_flatten(const wordlist *wl);
|
char * wl_flatten(const wordlist *wl);
|
||||||
void wl_free(wordlist *wlist);
|
void wl_free(wordlist *wlist);
|
||||||
|
void wl_delete(wordlist *wlist);
|
||||||
wordlist *wl_from_string(const char *sz);
|
wordlist *wl_from_string(const char *sz);
|
||||||
int wl_length(const wordlist *wlist);
|
int wl_length(const wordlist *wlist);
|
||||||
char ** wl_mkvec(const wordlist *wl);
|
char ** wl_mkvec(const wordlist *wl);
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,8 @@ tmalloc(size_t num)
|
||||||
mutex_unlock(&allocMutex);
|
mutex_unlock(&allocMutex);
|
||||||
#endif
|
#endif
|
||||||
if (!s){
|
if (!s){
|
||||||
fprintf(stderr,"malloc: Internal Error: can't allocate %ld bytes. \n",(long)num);
|
fprintf(stderr, "Error: malloc: can't allocate %lld bytes.\n", (long long)num);
|
||||||
|
fprintf(stderr, " Not enough memory or heap corruption\n");
|
||||||
#if defined HAS_WINGUI || defined SHARED_MODULE
|
#if defined HAS_WINGUI || defined SHARED_MODULE
|
||||||
controlled_exit(EXIT_FAILURE);
|
controlled_exit(EXIT_FAILURE);
|
||||||
#else
|
#else
|
||||||
|
|
@ -119,7 +120,8 @@ trealloc(const void *ptr, size_t num)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (!s) {
|
if (!s) {
|
||||||
fprintf(stderr,"realloc: Internal Error: can't allocate %ld bytes.\n", (long)num);
|
fprintf(stderr,"Error: realloc: can't allocate %lld bytes.\n", (long long)num);
|
||||||
|
fprintf(stderr," Not enough memory or heap corruption\n");
|
||||||
#if defined HAS_WINGUI || defined SHARED_MODULE
|
#if defined HAS_WINGUI || defined SHARED_MODULE
|
||||||
controlled_exit(EXIT_FAILURE);
|
controlled_exit(EXIT_FAILURE);
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,18 @@ wl_free(wordlist *wl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the storage used by the word list only,
|
||||||
|
but not the wl->wl_word. */
|
||||||
|
void
|
||||||
|
wl_delete(wordlist* wl)
|
||||||
|
{
|
||||||
|
while (wl) {
|
||||||
|
wordlist* next = wl->wl_next;
|
||||||
|
tfree(wl);
|
||||||
|
wl = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Copy a wordlist and the words. */
|
/* Copy a wordlist and the words. */
|
||||||
wordlist *
|
wordlist *
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,38 @@ static char *resolve_input_path(const char *name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for NGSPICE_OSDI_DIR. If available, add file name
|
||||||
|
and try to resolve the path */
|
||||||
|
char* lbuffer = getenv("NGSPICE_OSDI_DIR");
|
||||||
|
if (lbuffer && *lbuffer) {
|
||||||
|
DS_CREATE(ds, 100);
|
||||||
|
int rc_ds = 0;
|
||||||
|
rc_ds |= ds_cat_str(&ds, lbuffer); /* copy the dir name */
|
||||||
|
const size_t n = ds_get_length(&ds); /* end of copied dir name */
|
||||||
|
|
||||||
|
/* Append a directory separator if not present already */
|
||||||
|
const char ch_last = n > 0 ? lbuffer[n - 1] : '\0';
|
||||||
|
if (ch_last != DIR_TERM
|
||||||
|
#ifdef _WIN32
|
||||||
|
&& ch_last != DIR_TERM_LINUX
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
rc_ds |= ds_cat_char(&ds, DIR_TERM);
|
||||||
|
}
|
||||||
|
rc_ds |= ds_cat_str(&ds, name); /* append the file name */
|
||||||
|
|
||||||
|
if (rc_ds != 0) {
|
||||||
|
(void)fprintf(cp_err, "Error: Unable to build \"dir\" path name "
|
||||||
|
"in inp_pathresolve_at");
|
||||||
|
controlled_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* const r = resolve_path(ds_get_buf(&ds));
|
||||||
|
ds_free(&ds);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If called from a script inputdir != NULL so try relativ to that dir
|
* If called from a script inputdir != NULL so try relativ to that dir
|
||||||
* Otherwise try relativ to the current workdir and relativ to the
|
* Otherwise try relativ to the current workdir and relativ to the
|
||||||
|
|
@ -146,7 +178,7 @@ static char *resolve_input_path(const char *name) {
|
||||||
rc_ds |= ds_cat_str(&ds, name); /* append the file name */
|
rc_ds |= ds_cat_str(&ds, name); /* append the file name */
|
||||||
|
|
||||||
if (rc_ds != 0) {
|
if (rc_ds != 0) {
|
||||||
(void)fprintf(cp_err, "Unable to build \"dir\" path name "
|
(void)fprintf(cp_err, "Error: Unable to build \"dir\" path name "
|
||||||
"in inp_pathresolve_at");
|
"in inp_pathresolve_at");
|
||||||
controlled_exit(EXIT_FAILURE);
|
controlled_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,17 @@ ACan(CKTcircuit* ckt, int restart)
|
||||||
fprintf(stderr, "ERROR: AC startfreq <= 0\n");
|
fprintf(stderr, "ERROR: AC startfreq <= 0\n");
|
||||||
return E_PARMVAL;
|
return E_PARMVAL;
|
||||||
}
|
}
|
||||||
double num_steps = floor(fabs(log10(job->ACstopFreq / job->ACstartFreq)) * job->ACnumberSteps);
|
if (job->ACstopFreq / 10. < job->ACstartFreq) {
|
||||||
job->ACfreqDelta = exp((log(job->ACstopFreq / job->ACstartFreq)) / num_steps);
|
/* start-stop frequencies less than a decade apart */
|
||||||
|
if (job->ACstopFreq == job->ACstartFreq)
|
||||||
|
job->ACfreqDelta = 1;
|
||||||
|
else
|
||||||
|
job->ACfreqDelta = exp(log(10.0) / job->ACnumberSteps);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
double num_steps = floor(fabs(log10(job->ACstopFreq / job->ACstartFreq)) * job->ACnumberSteps);
|
||||||
|
job->ACfreqDelta = exp((log(job->ACstopFreq / job->ACstartFreq)) / num_steps);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case OCTAVE:
|
case OCTAVE:
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,8 @@ DCtran(CKTcircuit *ckt,
|
||||||
fprintf(stdout,"\n");
|
fprintf(stdout,"\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (ckt->CKTmode & MODEUIC && !ft_ngdebug) {
|
} else if (ckt->CKTmode & MODEUIC && !ft_ngdebug) {
|
||||||
fprintf(stdout,"Using transient initial conditions\n");
|
fprintf(stdout,"Operating point simulation skipped by 'uic',\n");
|
||||||
|
fprintf(stdout," now using transient initial conditions.\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (!ft_noacctprint && !ft_noinitprint) {
|
} else if (!ft_noacctprint && !ft_noinitprint) {
|
||||||
fprintf(stdout,"\nInitial Transient Solution\n");
|
fprintf(stdout,"\nInitial Transient Solution\n");
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ typedef void * funptr_t;
|
||||||
#else /* ifdef HAS_WINGUI */
|
#else /* ifdef HAS_WINGUI */
|
||||||
#undef BOOLEAN
|
#undef BOOLEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#include <libloaderapi.h>
|
||||||
typedef FARPROC funptr_t;
|
typedef FARPROC funptr_t;
|
||||||
void *dlopen(const char *, int);
|
void *dlopen(const char *, int);
|
||||||
funptr_t dlsym(void *, const char *);
|
funptr_t dlsym(void *, const char *);
|
||||||
|
|
@ -420,7 +422,7 @@ int add_udn(int n,Evt_Udn_Info_t **udns){
|
||||||
|
|
||||||
int load_opus(const char *name)
|
int load_opus(const char *name)
|
||||||
{
|
{
|
||||||
void *lib;
|
void *lib = NULL;
|
||||||
char *msg;
|
char *msg;
|
||||||
int num;
|
int num;
|
||||||
SPICEdev **devs;
|
SPICEdev **devs;
|
||||||
|
|
@ -428,9 +430,10 @@ int load_opus(const char *name)
|
||||||
funptr_t fetch;
|
funptr_t fetch;
|
||||||
|
|
||||||
lib = dlopen(name, RTLD_NOW);
|
lib = dlopen(name, RTLD_NOW);
|
||||||
|
// fprintf(stdout, "Lib %s has handle %p\n", name, lib);
|
||||||
if (!lib) {
|
if (!lib) {
|
||||||
msg = dlerror();
|
msg = dlerror();
|
||||||
printf("Error opening code model \"%s\": %s\n", name, msg);
|
fprintf(stderr, "Error opening code model \"%s\"\n: %s\n", name, msg);
|
||||||
FREE_DLERR_MSG(msg);
|
FREE_DLERR_MSG(msg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -445,7 +448,7 @@ int load_opus(const char *name)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg = dlerror();
|
msg = dlerror();
|
||||||
printf("Error getting the list of devices: %s\n",
|
fprintf(stderr, "Error getting the list of devices: %s\n",
|
||||||
msg);
|
msg);
|
||||||
FREE_DLERR_MSG(msg);
|
FREE_DLERR_MSG(msg);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -453,7 +456,7 @@ int load_opus(const char *name)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg = dlerror();
|
msg = dlerror();
|
||||||
printf("Error finding the number of devices: %s\n", msg);
|
fprintf(stderr, "Error finding the number of devices: %s\n", msg);
|
||||||
FREE_DLERR_MSG(msg);
|
FREE_DLERR_MSG(msg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -474,7 +477,7 @@ int load_opus(const char *name)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg = dlerror();
|
msg = dlerror();
|
||||||
printf("Error getting the list of user-defined types: %s\n",
|
fprintf(stderr, "Error getting the list of user-defined types: %s\n",
|
||||||
msg);
|
msg);
|
||||||
FREE_DLERR_MSG(msg);
|
FREE_DLERR_MSG(msg);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -482,7 +485,7 @@ int load_opus(const char *name)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg = dlerror();
|
msg = dlerror();
|
||||||
printf("Error finding the number of user-defined types: %s\n", msg);
|
fprintf(stderr, "Error finding the number of user-defined types: %s\n", msg);
|
||||||
FREE_DLERR_MSG(msg);
|
FREE_DLERR_MSG(msg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -501,7 +504,7 @@ int load_opus(const char *name)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg = dlerror();
|
msg = dlerror();
|
||||||
printf("Error getting interface pointer: %s\n", msg);
|
fprintf(stderr, "Error getting interface pointer: %s\n", msg);
|
||||||
FREE_DLERR_MSG(msg);
|
FREE_DLERR_MSG(msg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -522,7 +525,33 @@ static char errstr[sizeof errstr_fmt - 3 + 3 * sizeof(unsigned long)];
|
||||||
void *dlopen(const char *name, int type)
|
void *dlopen(const char *name, int type)
|
||||||
{
|
{
|
||||||
NG_IGNORE(type);
|
NG_IGNORE(type);
|
||||||
return LoadLibrary(name);
|
/* Replace / by \\ */
|
||||||
|
char* tmp, * tmpdel;
|
||||||
|
tmp = tmpdel = copy(name);
|
||||||
|
while (*tmp != '\0') {
|
||||||
|
if (*tmp == '/')
|
||||||
|
*tmp = '\\';
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
|
/* LoadLibrary returns some value even if lib is not available (maybe
|
||||||
|
due to relative path given) */
|
||||||
|
void* ret;
|
||||||
|
if (PathIsRelative(tmpdel)) {
|
||||||
|
/* Replace relative by absolute path */
|
||||||
|
char ngpath[512];
|
||||||
|
GetModuleFileName(NULL, ngpath, 512);
|
||||||
|
PathRemoveFileSpec(ngpath);
|
||||||
|
PathCombine(ngpath, ngpath, tmpdel);
|
||||||
|
if (PathFileExists(ngpath))
|
||||||
|
ret = LoadLibrary(ngpath);
|
||||||
|
else
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = LoadLibrary(tmpdel);
|
||||||
|
}
|
||||||
|
tfree(tmpdel);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
funptr_t dlsym(void *hDll, const char *funcname)
|
funptr_t dlsym(void *hDll, const char *funcname)
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ IFparm DIOmPTable[] = { /* model parameters */
|
||||||
IOP( "tlev", DIO_MOD_TLEV, IF_INTEGER, "Diode temperature equation selector"),
|
IOP( "tlev", DIO_MOD_TLEV, IF_INTEGER, "Diode temperature equation selector"),
|
||||||
IOP( "tlevc", DIO_MOD_TLEVC, IF_INTEGER, "Diode temperature equation selector"),
|
IOP( "tlevc", DIO_MOD_TLEVC, IF_INTEGER, "Diode temperature equation selector"),
|
||||||
IOP( "eg", DIO_MOD_EG, IF_REAL, "Activation energy"),
|
IOP( "eg", DIO_MOD_EG, IF_REAL, "Activation energy"),
|
||||||
|
IOP( "gap1", DIO_MOD_GAP1, IF_REAL, "First bandgap correction factor"),
|
||||||
|
IOP( "gap2", DIO_MOD_GAP2, IF_REAL, "Second bandgap correction factor"),
|
||||||
IOP( "xti", DIO_MOD_XTI, IF_REAL, "Saturation current temperature exp."),
|
IOP( "xti", DIO_MOD_XTI, IF_REAL, "Saturation current temperature exp."),
|
||||||
IOP( "cta", DIO_MOD_CTA, IF_REAL, "Area junction temperature coefficient"),
|
IOP( "cta", DIO_MOD_CTA, IF_REAL, "Area junction temperature coefficient"),
|
||||||
IOPR( "ctc", DIO_MOD_CTA, IF_REAL, "Area junction capacitance temperature coefficient"),
|
IOPR( "ctc", DIO_MOD_CTA, IF_REAL, "Area junction capacitance temperature coefficient"),
|
||||||
|
|
@ -104,7 +106,9 @@ IFparm DIOmPTable[] = { /* model parameters */
|
||||||
IOP( "fc", DIO_MOD_FC, IF_REAL, "Forward bias junction fit parameter"),
|
IOP( "fc", DIO_MOD_FC, IF_REAL, "Forward bias junction fit parameter"),
|
||||||
IOP( "fcs", DIO_MOD_FCS, IF_REAL, "Forward bias sidewall junction fit parameter"),
|
IOP( "fcs", DIO_MOD_FCS, IF_REAL, "Forward bias sidewall junction fit parameter"),
|
||||||
IOP( "bv", DIO_MOD_BV, IF_REAL, "Reverse breakdown voltage"),
|
IOP( "bv", DIO_MOD_BV, IF_REAL, "Reverse breakdown voltage"),
|
||||||
IOPR( "vb", DIO_MOD_BV, IF_REAL, "Reverse breakdown voltage"),
|
IOPR( "vb", DIO_MOD_BV, IF_REAL, "Reverse breakdown voltage (level=3)"),
|
||||||
|
IOPR( "vrb", DIO_MOD_BV, IF_REAL, "Reverse breakdown voltage (level=3)"),
|
||||||
|
IOPR( "var", DIO_MOD_BV, IF_REAL, "Reverse breakdown voltage (level=3)"),
|
||||||
IOP( "ibv", DIO_MOD_IBV, IF_REAL, "Current at reverse breakdown voltage"),
|
IOP( "ibv", DIO_MOD_IBV, IF_REAL, "Current at reverse breakdown voltage"),
|
||||||
IOPR( "ib", DIO_MOD_IBV, IF_REAL, "Current at reverse breakdown voltage"),
|
IOPR( "ib", DIO_MOD_IBV, IF_REAL, "Current at reverse breakdown voltage"),
|
||||||
IOP( "tcv", DIO_MOD_TCV, IF_REAL, "Reverse breakdown voltage temperature coefficient"),
|
IOP( "tcv", DIO_MOD_TCV, IF_REAL, "Reverse breakdown voltage temperature coefficient"),
|
||||||
|
|
@ -131,6 +135,7 @@ IFparm DIOmPTable[] = { /* model parameters */
|
||||||
IOP( "xoi", DIO_MOD_XOI, IF_REAL, "Thickness of the polysilicon to bulk oxide (level=3)"),
|
IOP( "xoi", DIO_MOD_XOI, IF_REAL, "Thickness of the polysilicon to bulk oxide (level=3)"),
|
||||||
IOP( "xm", DIO_MOD_XM, IF_REAL, "Masking and etching effects in metal (level=3)"),
|
IOP( "xm", DIO_MOD_XM, IF_REAL, "Masking and etching effects in metal (level=3)"),
|
||||||
IOP( "xp", DIO_MOD_XP, IF_REAL, "Masking and etching effects in polysilicon (level=3)"),
|
IOP( "xp", DIO_MOD_XP, IF_REAL, "Masking and etching effects in polysilicon (level=3)"),
|
||||||
|
IOP( "xw", DIO_MOD_XW, IF_REAL, "Masking and etching effects (level=3)"),
|
||||||
|
|
||||||
IP( "d", DIO_MOD_D, IF_FLAG, "Diode model")
|
IP( "d", DIO_MOD_D, IF_FLAG, "Diode model")
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,8 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
||||||
unsigned DIOtlevGiven : 1;
|
unsigned DIOtlevGiven : 1;
|
||||||
unsigned DIOtlevcGiven : 1;
|
unsigned DIOtlevcGiven : 1;
|
||||||
unsigned DIOactivationEnergyGiven : 1;
|
unsigned DIOactivationEnergyGiven : 1;
|
||||||
|
unsigned DIOfirstBGcorrFactorGiven : 1;
|
||||||
|
unsigned DIOsecndBGcorrFactorGiven : 1;
|
||||||
unsigned DIOsaturationCurrentExpGiven : 1;
|
unsigned DIOsaturationCurrentExpGiven : 1;
|
||||||
unsigned DIOctaGiven : 1;
|
unsigned DIOctaGiven : 1;
|
||||||
unsigned DIOctpGiven : 1;
|
unsigned DIOctpGiven : 1;
|
||||||
|
|
@ -302,6 +304,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
||||||
unsigned DIOpolyOxideThickGiven : 1; /* Thickness of the polysilicon to bulk oxide (level=3) */
|
unsigned DIOpolyOxideThickGiven : 1; /* Thickness of the polysilicon to bulk oxide (level=3) */
|
||||||
unsigned DIOmetalMaskOffsetGiven : 1; /* Masking and etching effects in metal (level=3)") */
|
unsigned DIOmetalMaskOffsetGiven : 1; /* Masking and etching effects in metal (level=3)") */
|
||||||
unsigned DIOpolyMaskOffsetGiven : 1; /* Masking and etching effects in polysilicon (level=3) */
|
unsigned DIOpolyMaskOffsetGiven : 1; /* Masking and etching effects in polysilicon (level=3) */
|
||||||
|
unsigned DIOmaskOffsetGiven : 1; /* Masking and etching effects (level=3) */
|
||||||
|
|
||||||
int DIOlevel; /* level selector */
|
int DIOlevel; /* level selector */
|
||||||
double DIOsatCur; /* saturation current */
|
double DIOsatCur; /* saturation current */
|
||||||
|
|
@ -331,6 +334,8 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
||||||
int DIOtlev; /* Diode temperature equation selector */
|
int DIOtlev; /* Diode temperature equation selector */
|
||||||
int DIOtlevc; /* Diode temperature equation selector */
|
int DIOtlevc; /* Diode temperature equation selector */
|
||||||
double DIOactivationEnergy; /* activation energy (EG) */
|
double DIOactivationEnergy; /* activation energy (EG) */
|
||||||
|
double DIOfirstBGcorrFactor; /* First bandgap correction factor */
|
||||||
|
double DIOsecndBGcorrFactor; /* Second bandgap correction factor */
|
||||||
double DIOsaturationCurrentExp; /* Saturation current exponential (XTI) */
|
double DIOsaturationCurrentExp; /* Saturation current exponential (XTI) */
|
||||||
double DIOcta; /* Area junction temperature coefficient */
|
double DIOcta; /* Area junction temperature coefficient */
|
||||||
double DIOctp; /* Perimeter junction temperature coefficient */
|
double DIOctp; /* Perimeter junction temperature coefficient */
|
||||||
|
|
@ -372,6 +377,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
||||||
double DIOpolyOxideThick; /* Thickness of the polysilicon to bulk oxide (level=3) */
|
double DIOpolyOxideThick; /* Thickness of the polysilicon to bulk oxide (level=3) */
|
||||||
double DIOmetalMaskOffset; /* Masking and etching effects in metal (level=3)") */
|
double DIOmetalMaskOffset; /* Masking and etching effects in metal (level=3)") */
|
||||||
double DIOpolyMaskOffset; /* Masking and etching effects in polysilicon (level=3) */
|
double DIOpolyMaskOffset; /* Masking and etching effects in polysilicon (level=3) */
|
||||||
|
double DIOmaskOffset; /* Masking and etching effects (level=3) */
|
||||||
|
|
||||||
} DIOmodel;
|
} DIOmodel;
|
||||||
|
|
||||||
|
|
@ -418,6 +424,8 @@ enum {
|
||||||
DIO_MOD_VJ,
|
DIO_MOD_VJ,
|
||||||
DIO_MOD_M,
|
DIO_MOD_M,
|
||||||
DIO_MOD_EG,
|
DIO_MOD_EG,
|
||||||
|
DIO_MOD_GAP1,
|
||||||
|
DIO_MOD_GAP2,
|
||||||
DIO_MOD_XTI,
|
DIO_MOD_XTI,
|
||||||
DIO_MOD_FC,
|
DIO_MOD_FC,
|
||||||
DIO_MOD_BV,
|
DIO_MOD_BV,
|
||||||
|
|
@ -474,6 +482,7 @@ enum {
|
||||||
DIO_MOD_XOI,
|
DIO_MOD_XOI,
|
||||||
DIO_MOD_XM,
|
DIO_MOD_XM,
|
||||||
DIO_MOD_XP,
|
DIO_MOD_XP,
|
||||||
|
DIO_MOD_XW,
|
||||||
};
|
};
|
||||||
|
|
||||||
void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit *ckt);
|
void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit *ckt);
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,12 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value)
|
||||||
case DIO_MOD_EG:
|
case DIO_MOD_EG:
|
||||||
value->rValue = model->DIOactivationEnergy;
|
value->rValue = model->DIOactivationEnergy;
|
||||||
return (OK);
|
return (OK);
|
||||||
|
case DIO_MOD_GAP1:
|
||||||
|
value->rValue = model->DIOfirstBGcorrFactor;
|
||||||
|
return (OK);
|
||||||
|
case DIO_MOD_GAP2:
|
||||||
|
value->rValue = model->DIOsecndBGcorrFactor;
|
||||||
|
return (OK);
|
||||||
case DIO_MOD_XTI:
|
case DIO_MOD_XTI:
|
||||||
value->rValue = model->DIOsaturationCurrentExp;
|
value->rValue = model->DIOsaturationCurrentExp;
|
||||||
return(OK);
|
return(OK);
|
||||||
|
|
@ -218,6 +224,9 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value)
|
||||||
case DIO_MOD_XP:
|
case DIO_MOD_XP:
|
||||||
value->rValue = model->DIOpolyMaskOffset;
|
value->rValue = model->DIOpolyMaskOffset;
|
||||||
return(OK);
|
return(OK);
|
||||||
|
case DIO_MOD_XW:
|
||||||
|
value->rValue = model->DIOmaskOffset;
|
||||||
|
return(OK);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return(E_BADPARM);
|
return(E_BADPARM);
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,14 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel)
|
||||||
model->DIOactivationEnergy = value->rValue;
|
model->DIOactivationEnergy = value->rValue;
|
||||||
model->DIOactivationEnergyGiven = TRUE;
|
model->DIOactivationEnergyGiven = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case DIO_MOD_GAP1:
|
||||||
|
model->DIOfirstBGcorrFactor = value->rValue;
|
||||||
|
model->DIOfirstBGcorrFactorGiven = TRUE;
|
||||||
|
break;
|
||||||
|
case DIO_MOD_GAP2:
|
||||||
|
model->DIOsecndBGcorrFactor = value->rValue;
|
||||||
|
model->DIOsecndBGcorrFactorGiven = TRUE;
|
||||||
|
break;
|
||||||
case DIO_MOD_XTI:
|
case DIO_MOD_XTI:
|
||||||
model->DIOsaturationCurrentExp = value->rValue;
|
model->DIOsaturationCurrentExp = value->rValue;
|
||||||
model->DIOsaturationCurrentExpGiven = TRUE;
|
model->DIOsaturationCurrentExpGiven = TRUE;
|
||||||
|
|
@ -270,6 +278,10 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel)
|
||||||
model->DIOpolyMaskOffset = value->rValue;
|
model->DIOpolyMaskOffset = value->rValue;
|
||||||
model->DIOpolyMaskOffsetGiven = TRUE;
|
model->DIOpolyMaskOffsetGiven = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case DIO_MOD_XW:
|
||||||
|
model->DIOmaskOffset = value->rValue;
|
||||||
|
model->DIOmaskOffsetGiven = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
case DIO_MOD_D:
|
case DIO_MOD_D:
|
||||||
/* no action - we already know we are a diode, but this */
|
/* no action - we already know we are a diode, but this */
|
||||||
|
|
|
||||||
|
|
@ -93,13 +93,15 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||||
if(model->DIOforwardKneeCurrentGiven) {
|
if(model->DIOforwardKneeCurrentGiven) {
|
||||||
if (model->DIOforwardKneeCurrent < ckt->CKTepsmin) {
|
if (model->DIOforwardKneeCurrent < ckt->CKTepsmin) {
|
||||||
model->DIOforwardKneeCurrentGiven = FALSE;
|
model->DIOforwardKneeCurrentGiven = FALSE;
|
||||||
printf("Warning: IKF too small - model effect disabled!\n");
|
fprintf(stderr, "Warning: %s: IKF too small - model effect disabled!\n",
|
||||||
|
model->DIOmodName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(model->DIOreverseKneeCurrentGiven) {
|
if(model->DIOreverseKneeCurrentGiven) {
|
||||||
if (model->DIOreverseKneeCurrent < ckt->CKTepsmin) {
|
if (model->DIOreverseKneeCurrent < ckt->CKTepsmin) {
|
||||||
model->DIOreverseKneeCurrentGiven = FALSE;
|
model->DIOreverseKneeCurrentGiven = FALSE;
|
||||||
printf("Warning: IKK too small - model effect disabled!\n");
|
fprintf(stderr, "Warning: %s: IKR too small - model effect disabled!\n",
|
||||||
|
model->DIOmodName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!model->DIObrkdEmissionCoeffGiven) {
|
if(!model->DIObrkdEmissionCoeffGiven) {
|
||||||
|
|
@ -112,7 +114,17 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||||
model->DIOtlevc = 0;
|
model->DIOtlevc = 0;
|
||||||
}
|
}
|
||||||
if(!model->DIOactivationEnergyGiven) {
|
if(!model->DIOactivationEnergyGiven) {
|
||||||
model->DIOactivationEnergy = 1.11;
|
if(model->DIOtlev == 2) {
|
||||||
|
model->DIOactivationEnergy = 1.16;
|
||||||
|
} else {
|
||||||
|
model->DIOactivationEnergy = 1.11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!model->DIOfirstBGcorrFactorGiven) {
|
||||||
|
model->DIOfirstBGcorrFactor = 7.02e-4;
|
||||||
|
}
|
||||||
|
if(!model->DIOsecndBGcorrFactorGiven) {
|
||||||
|
model->DIOsecndBGcorrFactor = 1108.0;
|
||||||
}
|
}
|
||||||
if(!model->DIOsaturationCurrentExpGiven) {
|
if(!model->DIOsaturationCurrentExpGiven) {
|
||||||
model->DIOsaturationCurrentExp = 3;
|
model->DIOsaturationCurrentExp = 3;
|
||||||
|
|
@ -243,6 +255,9 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||||
if(!model->DIOpolyMaskOffsetGiven) {
|
if(!model->DIOpolyMaskOffsetGiven) {
|
||||||
model->DIOpolyMaskOffset = 0.0;
|
model->DIOpolyMaskOffset = 0.0;
|
||||||
}
|
}
|
||||||
|
if(!model->DIOmaskOffsetGiven) {
|
||||||
|
model->DIOmaskOffset = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
/* loop through all the instances of the model */
|
/* loop through all the instances of the model */
|
||||||
for (here = DIOinstances(model); here != NULL ;
|
for (here = DIOinstances(model); here != NULL ;
|
||||||
|
|
@ -273,8 +288,8 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||||
if (model->DIOlevel == 3) {
|
if (model->DIOlevel == 3) {
|
||||||
double wm, lm, wp, lp;
|
double wm, lm, wp, lp;
|
||||||
if((here->DIOwGiven) && (here->DIOlGiven)) {
|
if((here->DIOwGiven) && (here->DIOlGiven)) {
|
||||||
here->DIOarea = here->DIOw * here->DIOl * here->DIOm;
|
here->DIOarea = (here->DIOw+model->DIOmaskOffset) * (here->DIOl+model->DIOmaskOffset) * here->DIOm;
|
||||||
here->DIOpj = (2 * here->DIOw + 2 * here->DIOl) * here->DIOm;
|
here->DIOpj = (2 * (here->DIOw+model->DIOmaskOffset) + 2 * (here->DIOl+model->DIOmaskOffset)) * here->DIOm;
|
||||||
}
|
}
|
||||||
here->DIOarea = here->DIOarea * scale * scale;
|
here->DIOarea = here->DIOarea * scale * scale;
|
||||||
here->DIOpj = here->DIOpj * scale;
|
here->DIOpj = here->DIOpj * scale;
|
||||||
|
|
|
||||||
|
|
@ -33,44 +33,46 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
|
||||||
double egfet1,arg1,fact1,pbfact1,pbo,gmaold,pboSW,gmaSWold;
|
double egfet1,arg1,fact1,pbfact1,pbo,gmaold,pboSW,gmaSWold;
|
||||||
double fact2,pbfact,arg,egfet,gmanew,gmaSWnew;
|
double fact2,pbfact,arg,egfet,gmanew,gmaSWnew;
|
||||||
double arg1_dT, arg2, arg2_dT;
|
double arg1_dT, arg2, arg2_dT;
|
||||||
double gclimit;
|
double lnTRatio, egfet_dT, arg0, vte_dT, vts_dT, vtt_dT, vtr_dT;
|
||||||
|
|
||||||
if (!cp_getvar("DIOgradingCoeffMax", CP_REAL, &gclimit, 0))
|
|
||||||
gclimit = 0.9;
|
|
||||||
|
|
||||||
vt = CONSTKoverQ * Temp;
|
vt = CONSTKoverQ * Temp;
|
||||||
vte = model->DIOemissionCoeff * vt;
|
vte = model->DIOemissionCoeff * vt;
|
||||||
|
vte_dT = CONSTKoverQ * model->DIOemissionCoeff;
|
||||||
vts = model->DIOswEmissionCoeff * vt;
|
vts = model->DIOswEmissionCoeff * vt;
|
||||||
|
vts_dT = CONSTKoverQ * model->DIOswEmissionCoeff;
|
||||||
vtt = model->DIOtunEmissionCoeff * vt;
|
vtt = model->DIOtunEmissionCoeff * vt;
|
||||||
|
vtt_dT = CONSTKoverQ * model->DIOtunEmissionCoeff;
|
||||||
vtr = model->DIOrecEmissionCoeff * vt;
|
vtr = model->DIOrecEmissionCoeff * vt;
|
||||||
|
vtr_dT = CONSTKoverQ * model->DIOrecEmissionCoeff;
|
||||||
vtnom = CONSTKoverQ * model->DIOnomTemp;
|
vtnom = CONSTKoverQ * model->DIOnomTemp;
|
||||||
dt = Temp - model->DIOnomTemp;
|
dt = Temp - model->DIOnomTemp;
|
||||||
|
lnTRatio = log(Temp / model->DIOnomTemp);
|
||||||
|
|
||||||
/* Junction grading temperature adjust */
|
/* Junction grading temperature adjust */
|
||||||
factor = 1.0 + (model->DIOgradCoeffTemp1 * dt)
|
factor = 1.0 + (model->DIOgradCoeffTemp1 * dt)
|
||||||
+ (model->DIOgradCoeffTemp2 * dt * dt);
|
+ (model->DIOgradCoeffTemp2 * dt * dt);
|
||||||
here->DIOtGradingCoeff = model->DIOgradingCoeff * factor;
|
here->DIOtGradingCoeff = model->DIOgradingCoeff * factor;
|
||||||
|
|
||||||
/* limit temperature adjusted grading coeff
|
|
||||||
* to max of .9, or set new limit with variable DIOgradingCoeffMax
|
|
||||||
*/
|
|
||||||
if(here->DIOtGradingCoeff>gclimit) {
|
|
||||||
SPfrontEnd->IFerrorf (ERR_WARNING,
|
|
||||||
"%s: temperature adjusted grading coefficient too large, limited to %g",
|
|
||||||
here->DIOname, gclimit);
|
|
||||||
here->DIOtGradingCoeff=gclimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this part gets really ugly - I won't even try to
|
/* this part gets really ugly - I won't even try to
|
||||||
* explain these equations */
|
* explain these equations */
|
||||||
|
if ((model->DIOtlev == 0) || (model->DIOtlev == 1)) {
|
||||||
|
egfet = 1.16-(7.02e-4*Temp*Temp)/
|
||||||
|
(Temp+1108);
|
||||||
|
egfet1 = 1.16 - (7.02e-4*model->DIOnomTemp*model->DIOnomTemp)/
|
||||||
|
(model->DIOnomTemp+1108);
|
||||||
|
} else {
|
||||||
|
egfet = model->DIOactivationEnergy-(model->DIOfirstBGcorrFactor*Temp*Temp)/
|
||||||
|
(Temp+model->DIOsecndBGcorrFactor);
|
||||||
|
egfet_dT = (model->DIOfirstBGcorrFactor*Temp*Temp)/
|
||||||
|
((Temp+model->DIOsecndBGcorrFactor)*(Temp+model->DIOsecndBGcorrFactor))
|
||||||
|
- 2*model->DIOfirstBGcorrFactor*Temp/(Temp+model->DIOsecndBGcorrFactor);
|
||||||
|
egfet1 = model->DIOactivationEnergy - (model->DIOfirstBGcorrFactor*model->DIOnomTemp*model->DIOnomTemp)/
|
||||||
|
(model->DIOnomTemp+model->DIOsecndBGcorrFactor);
|
||||||
|
}
|
||||||
fact2 = Temp/REFTEMP;
|
fact2 = Temp/REFTEMP;
|
||||||
egfet = 1.16-(7.02e-4*Temp*Temp)/
|
|
||||||
(Temp+1108);
|
|
||||||
arg = -egfet/(2*CONSTboltz*Temp) +
|
arg = -egfet/(2*CONSTboltz*Temp) +
|
||||||
1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||||
pbfact = -2*vt*(1.5*log(fact2)+CHARGE*arg);
|
pbfact = -2*vt*(1.5*log(fact2)+CHARGE*arg);
|
||||||
egfet1 = 1.16 - (7.02e-4*model->DIOnomTemp*model->DIOnomTemp)/
|
|
||||||
(model->DIOnomTemp+1108);
|
|
||||||
arg1 = -egfet1/(CONSTboltz*2*model->DIOnomTemp) +
|
arg1 = -egfet1/(CONSTboltz*2*model->DIOnomTemp) +
|
||||||
1.1150877/(2*CONSTboltz*REFTEMP);
|
1.1150877/(2*CONSTboltz*REFTEMP);
|
||||||
fact1 = model->DIOnomTemp/REFTEMP;
|
fact1 = model->DIOnomTemp/REFTEMP;
|
||||||
|
|
@ -108,45 +110,77 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
|
||||||
(1+model->DIOctp*(Temp-REFTEMP));
|
(1+model->DIOctp*(Temp-REFTEMP));
|
||||||
}
|
}
|
||||||
|
|
||||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vte;
|
if ((model->DIOtlev == 0) || (model->DIOtlev == 1)) {
|
||||||
arg1_dT = model->DIOactivationEnergy / (vte*model->DIOnomTemp)
|
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vte;
|
||||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vte*Temp);
|
arg1_dT = model->DIOactivationEnergy / (vte*model->DIOnomTemp)
|
||||||
arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * log(Temp / model->DIOnomTemp);
|
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vte*Temp);
|
||||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp;
|
arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * lnTRatio;
|
||||||
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(arg1 + arg2);
|
arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp;
|
||||||
here->DIOtSatCur_dT = model->DIOsatCur * here->DIOarea * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(arg1 + arg2);
|
||||||
|
here->DIOtSatCur_dT = here->DIOtSatCur * (arg1_dT + arg2_dT);
|
||||||
|
|
||||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vts;
|
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vts;
|
||||||
arg1_dT = model->DIOactivationEnergy / (vts*model->DIOnomTemp)
|
arg1_dT = model->DIOactivationEnergy / (vts*model->DIOnomTemp)
|
||||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vts*Temp);
|
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vts*Temp);
|
||||||
arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * log(Temp / model->DIOnomTemp);
|
arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * lnTRatio;
|
||||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp;
|
arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp;
|
||||||
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(arg1 + arg2);
|
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(arg1 + arg2);
|
||||||
here->DIOtSatSWCur_dT = model->DIOsatSWCur * here->DIOpj * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
here->DIOtSatSWCur_dT = here->DIOtSatSWCur * (arg1_dT + arg2_dT);
|
||||||
|
|
||||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / vtt;
|
arg1 = ((Temp/model->DIOnomTemp)-1) * model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / vtt;
|
||||||
arg1_dT = model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / (vtt*model->DIOnomTemp)
|
arg1_dT = model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / (vtt*model->DIOnomTemp)
|
||||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtt*Temp);
|
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtt*Temp);
|
||||||
arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * log(Temp / model->DIOnomTemp);
|
arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * lnTRatio;
|
||||||
arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp;
|
arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp;
|
||||||
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(arg1 + arg2);
|
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(arg1 + arg2);
|
||||||
here->DIOtTunSatCur_dT = model->DIOtunSatCur * here->DIOarea * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
here->DIOtTunSatCur_dT = here->DIOtTunSatCur * (arg1_dT + arg2_dT);
|
||||||
|
|
||||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / vtt;
|
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(arg1 + arg2);
|
||||||
arg1_dT = model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / (vtt*model->DIOnomTemp)
|
here->DIOtTunSatSWCur_dT = here->DIOtTunSatSWCur * (arg1_dT + arg2_dT);
|
||||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtt*Temp);
|
|
||||||
arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * log(Temp / model->DIOnomTemp);
|
|
||||||
arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp;
|
|
||||||
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(arg1 + arg2);
|
|
||||||
here->DIOtTunSatSWCur_dT = model->DIOtunSatSWCur * here->DIOpj * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
|
||||||
|
|
||||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vtr;
|
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vtr;
|
||||||
arg1_dT = model->DIOactivationEnergy / (vtr*model->DIOnomTemp)
|
arg1_dT = model->DIOactivationEnergy / (vtr*model->DIOnomTemp)
|
||||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtr*Temp);
|
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtr*Temp);
|
||||||
arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * log(Temp / model->DIOnomTemp);
|
arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * lnTRatio;
|
||||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp;
|
arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp;
|
||||||
here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * exp(arg1 + arg2);
|
here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * exp(arg1 + arg2);
|
||||||
here->DIOtRecSatCur_dT = model->DIOrecSatCur * here->DIOarea * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
here->DIOtRecSatCur_dT = here->DIOtRecSatCur * (arg1_dT + arg2_dT);
|
||||||
|
} else {
|
||||||
|
arg0 = egfet1 / (model->DIOemissionCoeff * vtnom);
|
||||||
|
arg1 = egfet / vte;
|
||||||
|
arg1_dT = (egfet_dT * vte - egfet * vte_dT) / (egfet*egfet);
|
||||||
|
arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * lnTRatio;
|
||||||
|
arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp;
|
||||||
|
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(arg0 - arg1 + arg2);
|
||||||
|
here->DIOtSatCur_dT = here->DIOtSatCur * (-arg1_dT + arg2_dT);
|
||||||
|
|
||||||
|
arg0 = egfet1 / (model->DIOswEmissionCoeff * vtnom);
|
||||||
|
arg1 = egfet / vts;
|
||||||
|
arg1_dT = (egfet_dT * vts - egfet * vts_dT) / (egfet*egfet);
|
||||||
|
arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * lnTRatio;
|
||||||
|
arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp;
|
||||||
|
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(arg0 - arg1 + arg2);
|
||||||
|
here->DIOtSatSWCur_dT = here->DIOtSatSWCur * (-arg1_dT + arg2_dT);
|
||||||
|
|
||||||
|
arg0 = model->DIOtunEGcorrectionFactor * egfet1 / (model->DIOtunEmissionCoeff * vtnom);
|
||||||
|
arg1 = model->DIOtunEGcorrectionFactor * egfet / vtt;
|
||||||
|
arg1_dT = model->DIOtunEGcorrectionFactor * (egfet_dT * vtt - egfet * vtt_dT) / (egfet*egfet);
|
||||||
|
arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * lnTRatio;
|
||||||
|
arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp;
|
||||||
|
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(arg0 - arg1 + arg2);
|
||||||
|
here->DIOtTunSatCur_dT = here->DIOtTunSatCur * (-arg1_dT + arg2_dT);
|
||||||
|
|
||||||
|
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(arg0 - arg1 + arg2);
|
||||||
|
here->DIOtTunSatSWCur_dT = here->DIOtTunSatSWCur * (-arg1_dT + arg2_dT);
|
||||||
|
|
||||||
|
arg0 = egfet1 / (model->DIOrecEmissionCoeff * vtnom);
|
||||||
|
arg1 = egfet / vtr;
|
||||||
|
arg1_dT = (egfet_dT * vtr - egfet * vtr_dT) / (egfet*egfet);
|
||||||
|
arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * lnTRatio;
|
||||||
|
arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp;
|
||||||
|
here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * exp(arg0 - arg1 + arg2);
|
||||||
|
here->DIOtRecSatCur_dT = here->DIOtRecSatCur * (-arg1_dT + arg2_dT);
|
||||||
|
}
|
||||||
|
|
||||||
xfc=log(1-model->DIOdepletionCapCoeff);
|
xfc=log(1-model->DIOdepletionCapCoeff);
|
||||||
xfcs=log(1-model->DIOdepletionSWcapCoeff);
|
xfcs=log(1-model->DIOdepletionSWcapCoeff);
|
||||||
|
|
@ -162,27 +196,8 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
|
||||||
here->DIOtDepSWCap=model->DIOdepletionSWcapCoeff*
|
here->DIOtDepSWCap=model->DIOdepletionSWcapCoeff*
|
||||||
here->DIOtJctSWPot;
|
here->DIOtJctSWPot;
|
||||||
/* and Vcrit */
|
/* and Vcrit */
|
||||||
vte=model->DIOemissionCoeff*vt;
|
|
||||||
|
|
||||||
here->DIOtVcrit = vte * log(vte/(CONSTroot2*here->DIOtSatCur));
|
here->DIOtVcrit = vte * log(vte/(CONSTroot2*here->DIOtSatCur));
|
||||||
|
|
||||||
/* limit junction potential to max of 1/FC */
|
|
||||||
if(here->DIOtDepCap > 1.0) {
|
|
||||||
here->DIOtJctPot=1.0/model->DIOdepletionCapCoeff;
|
|
||||||
here->DIOtDepCap=model->DIOdepletionCapCoeff*here->DIOtJctPot;
|
|
||||||
SPfrontEnd->IFerrorf (ERR_WARNING,
|
|
||||||
"%s: junction potential VJ too large, limited to %f",
|
|
||||||
model->DIOmodName, here->DIOtJctPot);
|
|
||||||
}
|
|
||||||
/* limit sidewall junction potential to max of 1/FCS */
|
|
||||||
if(here->DIOtDepSWCap > 1.0) {
|
|
||||||
here->DIOtJctSWPot=1.0/model->DIOdepletionSWcapCoeff;
|
|
||||||
here->DIOtDepSWCap=model->DIOdepletionSWcapCoeff*here->DIOtJctSWPot;
|
|
||||||
SPfrontEnd->IFerrorf (ERR_WARNING,
|
|
||||||
"%s: junction potential VJS too large, limited to %f",
|
|
||||||
model->DIOmodName, here->DIOtJctSWPot);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* and now to compute the breakdown voltage, again, using
|
/* and now to compute the breakdown voltage, again, using
|
||||||
* temperature adjusted basic parameters */
|
* temperature adjusted basic parameters */
|
||||||
if (model->DIObreakdownVoltageGiven){
|
if (model->DIObreakdownVoltageGiven){
|
||||||
|
|
|
||||||
|
|
@ -128,10 +128,13 @@ MOS1noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
|
||||||
/* linear region */
|
/* linear region */
|
||||||
alpha = 1.0 - (vds*inst->MOS1mode/(model->MOS1type*inst->MOS1vdsat));
|
alpha = 1.0 - (vds*inst->MOS1mode/(model->MOS1type*inst->MOS1vdsat));
|
||||||
}
|
}
|
||||||
}
|
beta = inst->MOS1tTransconductance * inst->MOS1m *
|
||||||
beta = inst->MOS1tTransconductance * inst->MOS1m *
|
|
||||||
inst->MOS1w/(inst->MOS1l - 2 * model->MOS1latDiff);
|
inst->MOS1w/(inst->MOS1l - 2 * model->MOS1latDiff);
|
||||||
Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS1gdsnoi;
|
Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS1gdsnoi;
|
||||||
|
} else {
|
||||||
|
/* subthreshold region */
|
||||||
|
Sid = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NevalSrcInstanceTemp( & noizDens[MOS1IDNOIZ], & lnNdens[MOS1IDNOIZ],
|
NevalSrcInstanceTemp( & noizDens[MOS1IDNOIZ], & lnNdens[MOS1IDNOIZ],
|
||||||
|
|
|
||||||
|
|
@ -117,10 +117,13 @@ MOS2noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
|
||||||
/* linear region */
|
/* linear region */
|
||||||
alpha = 1.0 - (vds*inst->MOS2mode/(model->MOS2type*inst->MOS2vdsat));
|
alpha = 1.0 - (vds*inst->MOS2mode/(model->MOS2type*inst->MOS2vdsat));
|
||||||
}
|
}
|
||||||
}
|
beta = inst->MOS2tTransconductance * inst->MOS2m *
|
||||||
beta = inst->MOS2tTransconductance * inst->MOS2m *
|
|
||||||
inst->MOS2w/(inst->MOS2l - 2 * model->MOS2latDiff);
|
inst->MOS2w/(inst->MOS2l - 2 * model->MOS2latDiff);
|
||||||
Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS2gdsnoi;
|
Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS2gdsnoi;
|
||||||
|
} else {
|
||||||
|
/* subthreshold region */
|
||||||
|
Sid = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NevalSrcInstanceTemp( & noizDens[MOS2IDNOIZ], & lnNdens[MOS2IDNOIZ],
|
NevalSrcInstanceTemp( & noizDens[MOS2IDNOIZ], & lnNdens[MOS2IDNOIZ],
|
||||||
|
|
|
||||||
|
|
@ -117,10 +117,13 @@ MOS3noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
|
||||||
/* linear region */
|
/* linear region */
|
||||||
alpha = 1.0 - (vds*inst->MOS3mode/(model->MOS3type*inst->MOS3vdsat));
|
alpha = 1.0 - (vds*inst->MOS3mode/(model->MOS3type*inst->MOS3vdsat));
|
||||||
}
|
}
|
||||||
}
|
beta = inst->MOS3tTransconductance * inst->MOS3m *
|
||||||
beta = inst->MOS3tTransconductance * inst->MOS3m *
|
|
||||||
inst->MOS3w/(inst->MOS3l - 2 * model->MOS3latDiff);
|
inst->MOS3w/(inst->MOS3l - 2 * model->MOS3latDiff);
|
||||||
Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS3gdsnoi;
|
Sid = 2.0 / 3.0 * beta * vgst * (1.0+alpha+alpha*alpha) / (1.0+alpha) * model->MOS3gdsnoi;
|
||||||
|
} else {
|
||||||
|
/* subthreshold region */
|
||||||
|
Sid = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NevalSrcInstanceTemp( & noizDens[MOS3IDNOIZ], & lnNdens[MOS3IDNOIZ],
|
NevalSrcInstanceTemp( & noizDens[MOS3IDNOIZ], & lnNdens[MOS3IDNOIZ],
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ Author: 1985 Thomas L. Quarles
|
||||||
/* gtri - end - wbk - 11/9/90 */
|
/* gtri - end - wbk - 11/9/90 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Ugly way to pass line info (number and source file) to lower-level error handlers.
|
||||||
|
int Current_parse_line;
|
||||||
|
char* Sourcefile;
|
||||||
|
|
||||||
/* uncomment to trace in this file */
|
/* uncomment to trace in this file */
|
||||||
/*#define TRACE*/
|
/*#define TRACE*/
|
||||||
|
|
@ -41,10 +44,6 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
|
||||||
printf("Entered INPpas2 . . . .\n");
|
printf("Entered INPpas2 . . . .\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XSPICE
|
|
||||||
if (!ckt->CKTadevFlag) ckt->CKTadevFlag = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
error = INPgetTok(&groundname, &gname, 1);
|
error = INPgetTok(&groundname, &gname, 1);
|
||||||
if (error)
|
if (error)
|
||||||
data->error =
|
data->error =
|
||||||
|
|
@ -87,6 +86,9 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Current_parse_line = current->linenum_orig;
|
||||||
|
Sourcefile = current->linesource;
|
||||||
|
|
||||||
c = *(current->line);
|
c = *(current->line);
|
||||||
if(islower_c(c))
|
if(islower_c(c))
|
||||||
c = toupper_c(c);
|
c = toupper_c(c);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "ngspice/inpptree.h"
|
#include "ngspice/inpptree.h"
|
||||||
|
#include "ngspice/inpdefs.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -143,5 +144,11 @@ PTerror (YYLTYPE *locp, char **line, struct INPparseNode **retval, void *ckt, ch
|
||||||
NG_IGNORE(retval);
|
NG_IGNORE(retval);
|
||||||
NG_IGNORE(ckt);
|
NG_IGNORE(ckt);
|
||||||
|
|
||||||
fprintf (stderr, "\n%s: %s, parsing stopped at\n %s\n\n", __func__, s, locp->start);
|
fprintf (stderr,
|
||||||
|
"\nYYparse error, %s, in expression: parsing stopped at line %d"
|
||||||
|
"\n %s in %s\n"
|
||||||
|
"\nfrom file"
|
||||||
|
" %s\n\n",
|
||||||
|
s, Current_parse_line, locp->start, *line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD); // Unsafe to continue.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1029,8 +1029,9 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (p->funcnum != PTF_PWL) {
|
if (p->funcnum != PTF_PWL) {
|
||||||
fprintf(stderr, "PWL-INFO: %s, very unexpected\n", __func__);
|
fprintf(stderr, "PWL-INFO: %s, very unexpected at line %d\nfrom file\n %s\n\n",
|
||||||
controlled_exit(1);
|
__func__, Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
|
|
@ -1041,8 +1042,11 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
if (i<2 || (i%1)) {
|
if (i<2 || (i%1)) {
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) needs an even and >=2 number of constant args\n");
|
fprintf(stderr,
|
||||||
return mkfirst(NULL, p);
|
"Error: PWL(expr, points...) needs an even and >=2 number "
|
||||||
|
"of constant args at line %d\nfrom file\n %s\n\n",
|
||||||
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
data = TMALLOC(struct pwldata, 1);
|
data = TMALLOC(struct pwldata, 1);
|
||||||
|
|
@ -1060,11 +1064,13 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
w->right->left->type == PT_CONSTANT) {
|
w->right->left->type == PT_CONSTANT) {
|
||||||
data->vals[i] = - w->right->left->constant;
|
data->vals[i] = - w->right->left->constant;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "PWL-ERROR: %s, not a constant\n", __func__);
|
fprintf(stderr,
|
||||||
fprintf(stderr, " type = %d\n", w->right->type);
|
"Error: PWL(expr, points...) only *literal* points "
|
||||||
//Breakpoint;
|
"are supported at line %d\nfrom file\n %s\n",
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) only *literal* points are supported\n");
|
Current_parse_line, Sourcefile);
|
||||||
return mkfirst(NULL, p);
|
// In case #671, "Crash when loading an Infineon model: IR4427S",
|
||||||
|
// a crash occurred after this error. There can be no recovery.
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
|
|
@ -1072,11 +1078,31 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
||||||
fprintf(stderr, " (%lf %lf)\n", data->vals[i], data->vals[i+1]);
|
fprintf(stderr, " (%lf %lf)\n", data->vals[i], data->vals[i+1]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 2 ; i < data->n ; i += 2)
|
/* check for monotonic abscissa */
|
||||||
if(data->vals[i-2] >= data->vals[i]) {
|
if (data->vals[0] > data->vals[2]) {
|
||||||
fprintf(stderr, "Error: PWL(expr, points...) the abscissa of points must be ascending\n");
|
for (i = 2; i < data->n; i += 2)
|
||||||
return mkfirst(NULL, p);
|
if (data->vals[i - 2] < data->vals[i]) {
|
||||||
}
|
fprintf(stderr,
|
||||||
|
"Error: PWL(expr, points...) the abscissa of points "
|
||||||
|
"must be descending at line %d\nfrom file\n %s\n", Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (data->vals[0] < data->vals[2]) {
|
||||||
|
for (i = 2; i < data->n; i += 2)
|
||||||
|
if (data->vals[i - 2] > data->vals[i]) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: PWL(expr, points...) the abscissa of points "
|
||||||
|
"must be ascending at line %d\nfrom file\n %s\n", Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: PWL(expr, points...) the abscissa of points "
|
||||||
|
"must be monotonic at line %d\nfrom file\n %s\n", Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
/* strip all but the first arg,
|
/* strip all but the first arg,
|
||||||
* and attach the rest as opaque data to the INPparseNode
|
* and attach the rest as opaque data to the INPparseNode
|
||||||
|
|
@ -1111,13 +1137,15 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
if (!fname) {
|
if (!fname) {
|
||||||
fprintf(stderr, "Error: bogus function name \n");
|
fprintf(stderr, "Error: bogus function name at line %d\nfrom file\n %s\n",
|
||||||
return mkfirst(NULL, arg);
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
fprintf(stderr, "Error: bad function arguments \n");
|
fprintf(stderr, "Error: bad function arguments at line %d\nfrom file\n %s\n",
|
||||||
return mkfirst(NULL, arg);
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the case is ok. */
|
/* Make sure the case is ok. */
|
||||||
|
|
@ -1144,8 +1172,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
return mkfirst(p, arg);
|
return mkfirst(p, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Error: bogus ternary_fcn form\n");
|
fprintf(stderr, "Error: bogus ternary_fcn form at line %d\nfrom file\n %s\n",
|
||||||
return mkfirst(NULL, arg);
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is used only to evaluate fcn gauss(a1, a2, a3) in .model files, where
|
/* This is used only to evaluate fcn gauss(a1, a2, a3) in .model files, where
|
||||||
|
|
@ -1161,8 +1190,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
double a3 = arg3->constant;
|
double a3 = arg3->constant;
|
||||||
|
|
||||||
if (a2 == 0.0 || a3 == 0.0) {
|
if (a2 == 0.0 || a3 == 0.0) {
|
||||||
fprintf(stderr, "Error: bogus gauss form\n");
|
fprintf(stderr, "Error: bogus gauss form at line %d\nfrom file\n %s\n",
|
||||||
return mkfirst(NULL, arg); //return mkcon(a1);
|
Current_parse_line, Sourcefile);
|
||||||
|
controlled_exit(EXIT_BAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mkcon(gauss(a1, a2, a3));
|
return mkcon(gauss(a1, a2, a3));
|
||||||
|
|
@ -1177,10 +1207,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == NUM_FUNCS) {
|
if (i == NUM_FUNCS) {
|
||||||
fprintf(stderr, "Error: no such function '%s'\n", buf);
|
fprintf(stderr, "Error: no such function '%s' at line %d\nfrom file\n %s\n",
|
||||||
if (ft_stricterror)
|
buf, Current_parse_line, Sourcefile);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
return mkfirst(NULL, arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p = TMALLOC(INPparseNode, 1);
|
p = TMALLOC(INPparseNode, 1);
|
||||||
|
|
@ -1197,10 +1226,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
||||||
if (p->funcnum == PTF_PWL) {
|
if (p->funcnum == PTF_PWL) {
|
||||||
p = prepare_PTF_PWL(p);
|
p = prepare_PTF_PWL(p);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
fprintf(stderr, "Error while parsing function '%s'\n", buf);
|
fprintf(stderr, "Error while parsing function '%s' at line %d\nfrom file\n %s\n",
|
||||||
if (ft_stricterror)
|
buf, Current_parse_line, Sourcefile);
|
||||||
controlled_exit(EXIT_BAD);
|
controlled_exit(EXIT_BAD);
|
||||||
return mkfirst(NULL, arg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -351,14 +351,27 @@ PTpwl(double arg, void *data)
|
||||||
int k0 = 0;
|
int k0 = 0;
|
||||||
int k1 = thing->n/2 - 1;
|
int k1 = thing->n/2 - 1;
|
||||||
|
|
||||||
while(k1-k0 > 1) {
|
/* monotonically increasing abscissa */
|
||||||
int k = (k0+k1)/2;
|
if (thing->vals[0] < thing->vals[2]) {
|
||||||
if(thing->vals[2*k] > arg)
|
while (k1 - k0 > 1) {
|
||||||
k1 = k;
|
int k = (k0 + k1) / 2;
|
||||||
else
|
if (thing->vals[2 * k] > arg)
|
||||||
k0 = k;
|
k1 = k;
|
||||||
|
else
|
||||||
|
k0 = k;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* monotonically decreasing abscissa */
|
||||||
|
else {
|
||||||
|
while (k1 - k0 > 1) {
|
||||||
|
int k = (k0 + k1) / 2;
|
||||||
|
if (thing->vals[2 * k] < arg)
|
||||||
|
k1 = k;
|
||||||
|
else
|
||||||
|
k0 = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* interpolate the ordinate */
|
||||||
y = thing->vals[2*k0+1] +
|
y = thing->vals[2*k0+1] +
|
||||||
(thing->vals[2*k1+1] - thing->vals[2*k0+1]) *
|
(thing->vals[2*k1+1] - thing->vals[2*k0+1]) *
|
||||||
(arg - thing->vals[2*k0]) / (thing->vals[2*k1] - thing->vals[2*k0]);
|
(arg - thing->vals[2*k0]) / (thing->vals[2*k1] - thing->vals[2*k0]);
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ static struct card *expand_deck(struct card *head)
|
||||||
/* The cards are passed to _inp_readall() via a global. */
|
/* The cards are passed to _inp_readall() via a global. */
|
||||||
|
|
||||||
circarray = pointers;
|
circarray = pointers;
|
||||||
card = inp_readall(NULL, Infile_Path, FALSE, TRUE, NULL);
|
card = inp_readall(NULL, Infile_Path, "autobridge", FALSE, TRUE, NULL);
|
||||||
card = inp_subcktexpand(card);
|
card = inp_subcktexpand(card);
|
||||||
ft_ngdebug = save_debug;
|
ft_ngdebug = save_debug;
|
||||||
|
|
||||||
|
|
@ -255,7 +255,7 @@ static struct card *flush_card(struct bridge *bridge, int ln,
|
||||||
ln, bridge->held, bridge->held, bridge->vcc);
|
ln, bridge->held, bridge->held, bridge->vcc);
|
||||||
bridge->count = 0;
|
bridge->count = 0;
|
||||||
bridge->end_index = 0;
|
bridge->end_index = 0;
|
||||||
return insert_new_line(last, copy(buff), BIG + ln, 0);
|
return insert_new_line(last, copy(buff), BIG + ln, last->linenum_orig, last->linesource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -738,7 +738,8 @@ bool Evtcheck_nodes(
|
||||||
|
|
||||||
head = insert_new_line(lastcard,
|
head = insert_new_line(lastcard,
|
||||||
copy("* Auto-bridge sub-deck."),
|
copy("* Auto-bridge sub-deck."),
|
||||||
BIG + ln++, 0);
|
BIG + ln++, (lastcard ? lastcard->linenum_orig : 0),
|
||||||
|
(lastcard ? lastcard->linesource : NULL));
|
||||||
lastcard = head;
|
lastcard = head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -748,7 +749,8 @@ bool Evtcheck_nodes(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
lastcard = insert_new_line(lastcard, bridge->setup,
|
lastcard = insert_new_line(lastcard, bridge->setup,
|
||||||
BIG + ln++, 0);
|
BIG + ln++, (lastcard ? lastcard->linenum_orig : 0),
|
||||||
|
(lastcard ? lastcard->linesource : NULL));
|
||||||
bridge->setup = NULL; // Output just once.
|
bridge->setup = NULL; // Output just once.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -563,8 +563,8 @@ static void EVTprocess_output(
|
||||||
|
|
||||||
if (g_mif_info.circuit.anal_type == MIF_TRAN) {
|
if (g_mif_info.circuit.anal_type == MIF_TRAN) {
|
||||||
delay = port->delay;
|
delay = port->delay;
|
||||||
if(delay <= 0.0) {
|
if(delay < 0.0) {
|
||||||
printf("\nERROR - Output delay <= 0 not allowed - output ignored!\n");
|
printf("\nERROR - Output delay < 0 not allowed - output ignored!\n");
|
||||||
printf(" Instance: %s\n Node: %s\n Time: %f \n",
|
printf(" Instance: %s\n Node: %s\n Time: %f \n",
|
||||||
g_mif_info.instance->MIFname, node_table[node_index]->name,
|
g_mif_info.instance->MIFname, node_table[node_index]->name,
|
||||||
g_mif_info.ckt->CKTtime);
|
g_mif_info.ckt->CKTtime);
|
||||||
|
|
|
||||||
|
|
@ -345,7 +345,8 @@ void ucm_d_cosim(ARGS)
|
||||||
{
|
{
|
||||||
struct instance *ip;
|
struct instance *ip;
|
||||||
Digital_t *in_vals; // XSPICE rotating memory
|
Digital_t *in_vals; // XSPICE rotating memory
|
||||||
unsigned int i, index;
|
unsigned int i;
|
||||||
|
int index;
|
||||||
|
|
||||||
if (INIT) {
|
if (INIT) {
|
||||||
unsigned int ins, outs, inouts;
|
unsigned int ins, outs, inouts;
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ fi
|
||||||
SPICE=$1
|
SPICE=$1
|
||||||
TEST=$2
|
TEST=$2
|
||||||
|
|
||||||
FILTER="CPU|Dynamic|Note|Circuit|Trying|Reference|Date|Doing|---|v-sweep|time|est|Error|Warning|Data|Index|trans|acan|oise|nalysis|ole|Total|memory|urrent|Got|Added|BSIM|bsim|B4SOI|b4soi|codemodel|^binary raw file|^ngspice.*done"
|
FILTER="CPU|Dynamic|Note|Circuit|Trying|Reference|Date|Doing|---|v-sweep|time|est|Error|Warning|Data|Index|trans|acan|oise|nalysis|ole|Total|memory|urrent|Got|Added|BSIM|bsim|B4SOI|b4soi|codemodel|^binary raw file|^ngspice.*done|Operating"
|
||||||
|
|
||||||
testname=`basename $TEST .cir`
|
testname=`basename $TEST .cir`
|
||||||
testdir=`dirname $TEST`
|
testdir=`dirname $TEST`
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#
|
#
|
||||||
# Rel Date Who Comments
|
# Rel Date Who Comments
|
||||||
# ==== ========== ============= ========
|
# ==== ========== ============= ========
|
||||||
|
# 1.2 04/15/2024 Geoffrey Coram Support op-pt values
|
||||||
# 1.1 07/05/17 Dietmar Warning Version detection included
|
# 1.1 07/05/17 Dietmar Warning Version detection included
|
||||||
# 1.0 05/13/11 Dietmar Warning Initial version
|
# 1.0 05/13/11 Dietmar Warning Initial version
|
||||||
#
|
#
|
||||||
|
|
@ -88,7 +89,7 @@ sub runNoiseTest {
|
||||||
print OF "rin dummy 0 1.0 noise=0";
|
print OF "rin dummy 0 1.0 noise=0";
|
||||||
foreach $pin (@main::Pin) {
|
foreach $pin (@main::Pin) {
|
||||||
if ($main::isFloatingPin{$pin}) {
|
if ($main::isFloatingPin{$pin}) {
|
||||||
print OF "i_$pin $pin 0 0";
|
print OF "r_$pin $pin 0 1e15";
|
||||||
} elsif ($pin eq $main::biasListPin) {
|
} elsif ($pin eq $main::biasListPin) {
|
||||||
print OF "v_$pin $pin 0 $biasVoltage";
|
print OF "v_$pin $pin 0 $biasVoltage";
|
||||||
} elsif ($pin eq $main::biasSweepPin) {
|
} elsif ($pin eq $main::biasSweepPin) {
|
||||||
|
|
@ -206,6 +207,7 @@ sub runAcTest {
|
||||||
print OF "* AC simulation for $main::simulatorName";
|
print OF "* AC simulation for $main::simulatorName";
|
||||||
&generateCommonNetlistInfo($variant,$temperature);
|
&generateCommonNetlistInfo($variant,$temperature);
|
||||||
foreach $fPin (@main::Pin) {
|
foreach $fPin (@main::Pin) {
|
||||||
|
next if (!$main::needAcStimulusFor{$fPin});
|
||||||
foreach $mPin (@main::Pin) {
|
foreach $mPin (@main::Pin) {
|
||||||
if ($mPin eq $fPin) {
|
if ($mPin eq $fPin) {
|
||||||
$acStim=" ac 1";
|
$acStim=" ac 1";
|
||||||
|
|
@ -213,7 +215,7 @@ sub runAcTest {
|
||||||
$acStim="";
|
$acStim="";
|
||||||
}
|
}
|
||||||
if ($main::isFloatingPin{$mPin}) {
|
if ($main::isFloatingPin{$mPin}) {
|
||||||
print OF "i_${mPin}_$fPin ${mPin}_$fPin 0 0";
|
print OF "r_${mPin}_$fPin ${mPin}_$fPin 0 1e15";
|
||||||
} elsif ($mPin eq $main::biasListPin) {
|
} elsif ($mPin eq $main::biasListPin) {
|
||||||
print OF "v_${mPin}_$fPin ${mPin}_$fPin 0 $biasVoltage$acStim";
|
print OF "v_${mPin}_$fPin ${mPin}_$fPin 0 $biasVoltage$acStim";
|
||||||
} elsif ($mPin eq $main::biasSweepPin) {
|
} elsif ($mPin eq $main::biasSweepPin) {
|
||||||
|
|
@ -226,7 +228,9 @@ sub runAcTest {
|
||||||
}
|
}
|
||||||
print OF ".ac $main::frequencySpec";
|
print OF ".ac $main::frequencySpec";
|
||||||
foreach $mPin (@main::Pin) {
|
foreach $mPin (@main::Pin) {
|
||||||
|
next if (!$main::needAcStimulusFor{$mPin});
|
||||||
foreach $fPin (@main::Pin) {
|
foreach $fPin (@main::Pin) {
|
||||||
|
next if (!$main::needAcStimulusFor{$fPin});
|
||||||
print OF ".print ac i(v_${mPin}_$fPin)";
|
print OF ".print ac i(v_${mPin}_$fPin)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -349,7 +353,7 @@ sub runDcTest {
|
||||||
&generateCommonNetlistInfo($variant,$temperature);
|
&generateCommonNetlistInfo($variant,$temperature);
|
||||||
foreach $pin (@main::Pin) {
|
foreach $pin (@main::Pin) {
|
||||||
if ($main::isFloatingPin{$pin}) {
|
if ($main::isFloatingPin{$pin}) {
|
||||||
print OF "i_$pin $pin 0 0";
|
print OF "r_$pin $pin 0 1e15";
|
||||||
} elsif ($pin eq $main::biasListPin) {
|
} elsif ($pin eq $main::biasListPin) {
|
||||||
print OF "v_$pin $pin 0 $biasVoltage";
|
print OF "v_$pin $pin 0 $biasVoltage";
|
||||||
} elsif ($pin eq $main::biasSweepPin) {
|
} elsif ($pin eq $main::biasSweepPin) {
|
||||||
|
|
@ -361,7 +365,9 @@ sub runDcTest {
|
||||||
print OF "x1 ".join(" ",@main::Pin)." mysub";
|
print OF "x1 ".join(" ",@main::Pin)." mysub";
|
||||||
print OF ".dc v_$main::biasSweepPin $main::biasSweepSpec";
|
print OF ".dc v_$main::biasSweepPin $main::biasSweepSpec";
|
||||||
foreach $pin (@main::Outputs) {
|
foreach $pin (@main::Outputs) {
|
||||||
if ($main::isFloatingPin{$pin}) {
|
if ($pin =~ /^OP\((.*)\)/) {
|
||||||
|
print OF ".print dc \@${main::keyLetter}.x1.${main::keyLetter}1[$1]";
|
||||||
|
} elsif ($main::isFloatingPin{$pin}) {
|
||||||
print OF ".print dc v($pin)";
|
print OF ".print dc v($pin)";
|
||||||
} else {
|
} else {
|
||||||
print OF ".print dc i(v_$pin)";
|
print OF ".print dc i(v_$pin)";
|
||||||
|
|
@ -381,6 +387,7 @@ sub runDcTest {
|
||||||
while (<SIMULATE>) {
|
while (<SIMULATE>) {
|
||||||
chomp;s/^\s+//;s/\s+$//;s/#branch//;s/\(/_/;s/\)//;
|
chomp;s/^\s+//;s/\s+$//;s/#branch//;s/\(/_/;s/\)//;
|
||||||
if (/^Index\s+v-sweep\s+v_/i) {$inResults=1;($pin=$');<SIMULATE>;next}
|
if (/^Index\s+v-sweep\s+v_/i) {$inResults=1;($pin=$');<SIMULATE>;next}
|
||||||
|
if (/^Index\s+v-sweep\s+\@.*\[(.+)\]/i) {$inResults=1;$pin="OP($1)";<SIMULATE>;next}
|
||||||
@Field=split;
|
@Field=split;
|
||||||
if ($#Field != 2) {$inResults=0}
|
if ($#Field != 2) {$inResults=0}
|
||||||
next if (!$inResults);
|
next if (!$inResults);
|
||||||
|
|
@ -402,7 +409,9 @@ sub runDcTest {
|
||||||
}
|
}
|
||||||
printf OF ("V($main::biasSweepPin)");
|
printf OF ("V($main::biasSweepPin)");
|
||||||
foreach $pin (@main::Outputs) {
|
foreach $pin (@main::Outputs) {
|
||||||
if ($main::isFloatingPin{$pin}) {
|
if ($pin =~ /^OP/) {
|
||||||
|
printf OF " $pin";
|
||||||
|
} elsif ($main::isFloatingPin{$pin}) {
|
||||||
printf OF (" V($pin)");
|
printf OF (" V($pin)");
|
||||||
} else {
|
} else {
|
||||||
printf OF (" I($pin)");
|
printf OF (" I($pin)");
|
||||||
|
|
@ -434,8 +443,18 @@ sub runDcTest {
|
||||||
sub generateCommonNetlistInfo {
|
sub generateCommonNetlistInfo {
|
||||||
my($variant,$temperature)=@_;
|
my($variant,$temperature)=@_;
|
||||||
my(@Pin_x,$arg,$name,$value,$eFactor,$fFactor,$pin);
|
my(@Pin_x,$arg,$name,$value,$eFactor,$fFactor,$pin);
|
||||||
|
if (!defined($main::keyLetter)) {
|
||||||
|
if (defined($main::verilogaFile)) {
|
||||||
|
$main::keyLetter="N";
|
||||||
|
} else {
|
||||||
|
die("ERROR: no keyLetter specified, stopped");
|
||||||
|
}
|
||||||
|
}
|
||||||
foreach $pin (@main::Pin) {push(@Pin_x,"${pin}_x")}
|
foreach $pin (@main::Pin) {push(@Pin_x,"${pin}_x")}
|
||||||
print OF ".options temp=$temperature gmin=1e-13 abstol=1e-13 reltol=1e-3";
|
# print OF ".options temp=$temperature gmin=1e-3 abstol=1e-12 reltol=1e-6";
|
||||||
|
print OF ".options temp=$temperature abstol=1e-15 reltol=1e-5";
|
||||||
|
print OF ".option numdgt=8";
|
||||||
|
# print OF ".options temp=$temperature";
|
||||||
if ($variant=~/^scale$/) {
|
if ($variant=~/^scale$/) {
|
||||||
die("ERROR: there is no scale or shrink option for ngspice, stopped");
|
die("ERROR: there is no scale or shrink option for ngspice, stopped");
|
||||||
}
|
}
|
||||||
|
|
@ -454,8 +473,25 @@ sub generateCommonNetlistInfo {
|
||||||
$fFactor/=$main::mFactor;
|
$fFactor/=$main::mFactor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
my $opvars="";
|
||||||
|
foreach $pin (@main::Outputs) {
|
||||||
|
if ($pin =~ /^OP\((.*)\)/) {
|
||||||
|
$opvars .= " \@${main::keyLetter}.x1.${main::keyLetter}1[$1]";
|
||||||
|
}
|
||||||
|
}
|
||||||
if (defined($main::verilogaFile)) {
|
if (defined($main::verilogaFile)) {
|
||||||
die("ERROR: Verilog-A model support is not implemented for ngspice, stopped");
|
my $osdifile = $main::verilogaFile;
|
||||||
|
$osdifile =~ s/\.va$/\.osdi/;
|
||||||
|
print OF ".control";
|
||||||
|
print OF "pre_osdi $osdifile";
|
||||||
|
if ($opvars ne "") {
|
||||||
|
print OF "save $opvars";
|
||||||
|
}
|
||||||
|
print OF ".endc";
|
||||||
|
} elsif ($opvars ne "") {
|
||||||
|
print OF ".control";
|
||||||
|
print OF "save $opvars";
|
||||||
|
print OF ".endc";
|
||||||
}
|
}
|
||||||
print OF ".subckt mysub ".join(" ",@Pin_x);
|
print OF ".subckt mysub ".join(" ",@Pin_x);
|
||||||
foreach $pin (@main::Pin) {
|
foreach $pin (@main::Pin) {
|
||||||
|
|
@ -491,7 +527,11 @@ sub generateCommonNetlistInfo {
|
||||||
print OF "+ $name=$value";
|
print OF "+ $name=$value";
|
||||||
}
|
}
|
||||||
if ($variant eq "m") {
|
if ($variant eq "m") {
|
||||||
print OF "+ m=$main::mFactor";
|
if (defined($main::verilogaFile)) {
|
||||||
|
print OF "+ \$mfactor=$main::mFactor";
|
||||||
|
} else {
|
||||||
|
print OF "+ m=$main::mFactor";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($variant=~/_P/) {
|
if ($variant=~/_P/) {
|
||||||
print OF ".model mymodel $main::pTypeSelectionArguments";
|
print OF ".model mymodel $main::pTypeSelectionArguments";
|
||||||
|
|
@ -505,3 +545,4 @@ sub generateCommonNetlistInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INFO: success
|
INFO: success
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue