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
|
||||
# ---------------
|
||||
|
||||
# --disable-debug: remove -g and -Wall option to the compiler
|
||||
# --enable-debug: add -g and -Wall option to the compiler
|
||||
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
|
||||
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
|
||||
# --disable-xspice: define XSPICE in the code. This is for xspice support
|
||||
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],
|
||||
[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
|
||||
AC_ARG_ENABLE([cider],
|
||||
[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
|
||||
AC_ARG_ENABLE([pss],
|
||||
[AS_HELP_STRING([--enable-pss], [Enable PSS Analysis, (experimental)])])
|
||||
|
|
@ -171,9 +163,9 @@ AC_ARG_ENABLE([sp],
|
|||
AC_ARG_ENABLE([relpath],
|
||||
[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],
|
||||
[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".
|
||||
AC_ARG_WITH([editline],
|
||||
|
|
@ -195,8 +187,20 @@ AC_ARG_ENABLE([utf8],
|
|||
AC_ARG_ENABLE([shortcheck],
|
||||
[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
|
||||
|
||||
# --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
|
||||
AC_ARG_ENABLE([ansi],
|
||||
[AS_HELP_STRING([--enable-ansi], [Force --ansi option for compilation])])
|
||||
|
|
@ -293,10 +297,6 @@ AC_ARG_ENABLE([cmathtests],
|
|||
AC_ARG_ENABLE([help],
|
||||
[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
|
||||
if test "x$with_editline" = xyes; then
|
||||
if test "x$with_readline" = xyes; then
|
||||
|
|
@ -304,16 +304,14 @@ if test "x$with_editline" = xyes; then
|
|||
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
|
||||
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_MSG_WARN([KLU solver enabled])
|
||||
AC_MSG_RESULT([KLU solver enabled])
|
||||
else
|
||||
AC_MSG_RESULT([KLU solver disabled!])
|
||||
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
|
||||
|
|
@ -329,26 +327,28 @@ AM_MAINTAINER_MODE([enable])
|
|||
# the above AC_PROG_CC may set CFLAGS to "-O2 -g"
|
||||
if test "x$ext_CFLAGS" != xyes; then
|
||||
|
||||
if test "x$enable_debug" = xno; then
|
||||
AC_MSG_WARN([Removing debugging option!])
|
||||
if test "x$GCC" = xyes; then
|
||||
CFLAGS="-O2 -s"
|
||||
else
|
||||
CFLAGS="-O2"
|
||||
fi
|
||||
else
|
||||
if test "x$enable_debug" = xyes; then
|
||||
AC_DEFINE([NGDEBUG], [1], [Compile with debug info])
|
||||
AC_MSG_WARN([Compile with debugging option -g!])
|
||||
if test "x$GCC" = xyes; then
|
||||
CFLAGS="-g -O0"
|
||||
else
|
||||
CFLAGS="-g"
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([Debugging option -g removed])
|
||||
if test "x$GCC" = xyes; then
|
||||
CFLAGS="-O2 -s"
|
||||
else
|
||||
CFLAGS="-O2"
|
||||
fi
|
||||
fi
|
||||
|
||||
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"
|
||||
fi
|
||||
|
||||
else
|
||||
AC_MSG_RESULT([Use external CFLAGS])
|
||||
fi
|
||||
|
||||
# the profiling option
|
||||
|
|
@ -1103,10 +1103,23 @@ AM_CONDITIONAL([CMATHTESTS], [test "x$enable_cmathtests" = xyes])
|
|||
################# XSPICE ##################################################
|
||||
# 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=""
|
||||
AC_MSG_RESULT([X-Spice features included])
|
||||
AC_DEFINE([XSPICE], [1], [The xspice enhancements])
|
||||
AC_MSG_RESULT([XSPICE features included])
|
||||
AC_DEFINE([XSPICE], [1], [The XSPICE enhancements])
|
||||
case $host_os in
|
||||
*mingw* | *msys* )
|
||||
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_HEADERS([libintl.h malloc.h])
|
||||
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
|
||||
|
||||
AC_SUBST([XSPICEINIT])
|
||||
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])
|
||||
|
||||
|
||||
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_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
|
||||
|
|
@ -1201,7 +1204,7 @@ if test "x$enable_osdi" = xyes; then
|
|||
AC_DEFINE([OSDI], [1], [The OSDI enhancements])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([OSDI_WANTED], [test "x$enable_osdi" = xyes])
|
||||
AM_CONDITIONAL([OSDI_WANTED], [test "x$enable_osdi" != xno])
|
||||
|
||||
# Add CIDER enhancements to ngspice.
|
||||
if test "x$enable_cider" = xyes; then
|
||||
|
|
@ -1252,10 +1255,10 @@ fi
|
|||
# ---- Default: disabled. ----
|
||||
# ---- 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.])
|
||||
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
|
||||
AC_MSG_RESULT([Checking for readline:])
|
||||
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])])
|
||||
|
||||
# Add OpenMP to ngspice.
|
||||
: ${enable_openmp:=no}
|
||||
: ${enable_openmp:=yes}
|
||||
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])
|
||||
CFLAGS="$CFLAGS $OPENMP_CFLAGS"
|
||||
AC_MSG_RESULT([OpenMP feature enabled])
|
||||
else
|
||||
AC_MSG_RESULT([OpenMP feature disabled])
|
||||
fi
|
||||
|
||||
# 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 *db_nodename1 = NULL;
|
||||
char db_type = 0;
|
||||
if (eq(s, "all")) {
|
||||
if (eq(s, "all") || eq(s, "nosub")) {
|
||||
switch (what) {
|
||||
case VF_PRINT:
|
||||
db_type = DB_TRACEALL;
|
||||
break;
|
||||
/* case VF_PLOT:
|
||||
db_type = DB_IPLOTALL;
|
||||
break; */
|
||||
case VF_ACCUM:
|
||||
/* db_type = DB_SAVEALL; */
|
||||
db_nodename1 = copy(s);
|
||||
db_type = DB_SAVE;
|
||||
break;
|
||||
}
|
||||
tfree(s);
|
||||
/* wrd_chtrace(NULL, TRUE, what); */
|
||||
} else {
|
||||
switch (what) {
|
||||
case VF_PRINT:
|
||||
db_type = DB_TRACENODE;
|
||||
break;
|
||||
/* case VF_PLOT:
|
||||
db_type = DB_IPLOT;
|
||||
break; */
|
||||
case VF_ACCUM:
|
||||
db_type = DB_SAVE;
|
||||
break;
|
||||
|
|
@ -98,7 +90,6 @@ settrace(wordlist *wl, int what, char *name)
|
|||
tfree(s);
|
||||
if (!db_nodename1) /* skip on error */
|
||||
continue;
|
||||
/* wrd_chtrace(s, TRUE, what); */
|
||||
}
|
||||
|
||||
/* Don't save a nodename more than once */
|
||||
|
|
|
|||
|
|
@ -8,13 +8,21 @@
|
|||
#ifdef XSPICE
|
||||
void com_codemodel(wordlist *wl)
|
||||
{
|
||||
wordlist *ww;
|
||||
for (ww = wl; ww; ww = ww->wl_next)
|
||||
if (load_opus(wl->wl_word)) {
|
||||
fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word);
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
if (wl && wl->wl_word)
|
||||
#ifdef CM_TRACE
|
||||
fprintf(stdout, "Note: loading codemodel %s\n", ww->wl_word);
|
||||
#endif
|
||||
if (load_opus(wl->wl_word)) {
|
||||
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
|
||||
|
||||
|
|
@ -25,6 +33,7 @@ void com_osdi(wordlist *wl)
|
|||
for (ww = wl; ww; ww = ww->wl_next)
|
||||
if (load_osdi(ww->wl_word)) {
|
||||
fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word);
|
||||
ft_spiniterror = TRUE;
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ struct comm spcp_coms[] = {
|
|||
NULL,
|
||||
"node node ... : Print all event nodes." },
|
||||
{ "codemodel", com_codemodel, FALSE, TRUE,
|
||||
{ 040000, 040000, 040000, 040000 }, E_BEGINNING, 1, LOTS,
|
||||
{ 040000, 040000, 040000, 040000 }, E_BEGINNING, 1, 1,
|
||||
NULL,
|
||||
"library library ... : Loads the code model libraries." } ,
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1343,10 +1343,15 @@ com_alter_common(wordlist *wl, int do_model)
|
|||
dev = NULL;
|
||||
param = NULL;
|
||||
words = wl;
|
||||
while (words != eqword) {
|
||||
while (words && words != eqword) {
|
||||
char *p = words->wl_word;
|
||||
if (param) {
|
||||
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) {
|
||||
param = words->wl_word;
|
||||
} else if (*p == '@' || *p == '#') {
|
||||
|
|
@ -1543,7 +1548,7 @@ com_alter_mod(wordlist *wl)
|
|||
}
|
||||
{
|
||||
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(input);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ void eval_opt(struct card *deck);
|
|||
|
||||
extern bool ft_batchmode;
|
||||
extern int dynmaxline;
|
||||
extern wordlist* sourceinfo;
|
||||
|
||||
/* from inpcom.c */
|
||||
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, */
|
||||
/* called with *fp == NULL and intfile: we want to load circuit from circarray */
|
||||
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 */
|
||||
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");
|
||||
/* now completely */
|
||||
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);
|
||||
}
|
||||
else
|
||||
|
|
@ -962,17 +963,17 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
|||
struct card *tc = NULL;
|
||||
fprintf(fdo, "**************** uncommented deck **************\n\n");
|
||||
/* 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 */
|
||||
for (tc = deck->nextcard; tc; tc = tc->nextcard) {
|
||||
if (*(tc->line) == '*')
|
||||
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");
|
||||
/* now completely */
|
||||
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);
|
||||
}
|
||||
else
|
||||
|
|
@ -1533,6 +1534,7 @@ inp_dodeck(
|
|||
tfree(ct->ci_filename);
|
||||
#endif
|
||||
ct->ci_filename = copy(filename);
|
||||
ct->ci_sourceinfo = sourceinfo;
|
||||
|
||||
/* load the optran data, if provided by .spiceinit or spinit.
|
||||
Return immediately, if optran is not selected.*/
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ void inp_probe(struct card* card);
|
|||
void modprobenames(INPtables* tab);
|
||||
|
||||
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 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 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
|
||||
<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) {
|
||||
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 */
|
||||
|
|
@ -256,6 +257,12 @@ void inp_probe(struct card* deck)
|
|||
else
|
||||
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;
|
||||
prevcard = card;
|
||||
/* 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);
|
||||
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(strnode2);
|
||||
|
|
@ -320,11 +327,11 @@ void inp_probe(struct card* deck)
|
|||
continue;
|
||||
}
|
||||
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' */
|
||||
if (*instname == 'x' && strstr(thisnode, "unconnected")) {
|
||||
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);
|
||||
allsaves = wl_cons(nodesaves, allsaves);
|
||||
|
|
@ -342,7 +349,7 @@ void inp_probe(struct card* deck)
|
|||
char* newline = wl_flatten(allsaves);
|
||||
wl_free(allsaves);
|
||||
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(strnode2);
|
||||
tmpcard1 = deck->nextcard;
|
||||
tmpcard1 = insert_new_line(tmpcard1, newline, 0, 0);
|
||||
tmpcard1 = insert_new_line(tmpcard1, newline, 0, tmpcard1->linenum_orig, tmpcard1->linesource);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -431,7 +438,7 @@ void inp_probe(struct card* deck)
|
|||
allsaves = wl_cons(nodesaves, allsaves);
|
||||
tfree(strnode1);
|
||||
tfree(strnode2);
|
||||
tmpcard1 = insert_new_line(tmpcard1, newline, 0, 0);
|
||||
tmpcard1 = insert_new_line(tmpcard1, newline, 0, tmpcard1->linenum_orig, tmpcard1->linesource);
|
||||
continue;
|
||||
}
|
||||
/* 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* nodesaves = tprintf("vd_%s:%s_%s:%s", instname1, nodename1, instname2, nodename2);
|
||||
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(strnode2);
|
||||
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* nodesaves = tprintf("vd_%s:%s:%s", instname1, nodename1, nodename2);
|
||||
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(strnode2);
|
||||
tfree(nodename1);
|
||||
|
|
@ -744,6 +751,12 @@ void inp_probe(struct card* deck)
|
|||
else
|
||||
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 ',' */
|
||||
if (*tmpstr == ',')
|
||||
tmpstr++;
|
||||
|
|
@ -790,8 +803,7 @@ void inp_probe(struct card* deck)
|
|||
|
||||
tfree(tmpcard->line);
|
||||
tmpcard->line = newline;
|
||||
|
||||
tmpcard = insert_new_line(tmpcard, vline, 0, 0);
|
||||
tmpcard = insert_new_line(tmpcard, vline, 0, tmpcard->linenum_orig, tmpcard->linesource);
|
||||
|
||||
tfree(strnode2);
|
||||
tfree(newnode);
|
||||
|
|
@ -845,8 +857,7 @@ void inp_probe(struct card* deck)
|
|||
|
||||
tfree(tmpcard->line);
|
||||
tmpcard->line = newline;
|
||||
|
||||
tmpcard = insert_new_line(tmpcard, vline, 0, 0);
|
||||
tmpcard = insert_new_line(tmpcard, vline, 0, tmpcard->linenum_orig, tmpcard->linesource);
|
||||
|
||||
char* nodesaves = tprintf("%s:%s#branch", instname, nodename1);
|
||||
allsaves = wl_cons(nodesaves, allsaves);
|
||||
|
|
@ -886,6 +897,12 @@ void inp_probe(struct card* deck)
|
|||
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;
|
||||
/* call fcn with power requested */
|
||||
err = setallvsources(tmpcard, instances, instname, numnodes, haveall, TRUE);
|
||||
|
|
@ -911,7 +928,7 @@ void inp_probe(struct card* deck)
|
|||
wl_free(allsaves);
|
||||
allsaves = NULL;
|
||||
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 = insert_new_line(card, vline, 0, 0);
|
||||
card = insert_new_line(card, vline, 0, card->linenum_orig, card->linesource);
|
||||
|
||||
if (power) {
|
||||
/* 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);
|
||||
allsaves = NULL;
|
||||
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) {
|
||||
cadd(&BVrefline, ')');
|
||||
card = tmpcard->nextcard;
|
||||
card = insert_new_line(card, copy(ds_get_buf(&BVrefline)), 0, 0);
|
||||
card = insert_new_line(card, copy(ds_get_buf(&Bpowerline)), 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, card->linenum_orig, card->linesource);
|
||||
}
|
||||
|
||||
ds_free(&BVrefline);
|
||||
|
|
@ -1437,3 +1454,17 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn
|
|||
ds_free(&Bpowersave);
|
||||
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 "numparam/general.h"
|
||||
|
||||
#include "com_set.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
@ -115,12 +117,14 @@ int dynMaxckt = 0; /* subckt.c 307 */
|
|||
/* number of parameter substitutions */
|
||||
long dynsubst; /* spicenum.c 221 */
|
||||
|
||||
wordlist* sourceinfo = NULL;
|
||||
|
||||
static bool has_if = FALSE; /* if we have an .if ... .endif pair */
|
||||
|
||||
static char *readline(FILE *fd);
|
||||
int get_number_terminals(char *c);
|
||||
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(
|
||||
struct names *subckt_w_params, 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);
|
||||
#endif
|
||||
|
||||
int add_to_sourcepath(const char* filepath, const char* path);
|
||||
|
||||
struct inp_read_t {
|
||||
struct card *cc;
|
||||
int line_number;
|
||||
};
|
||||
|
||||
struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
|
||||
bool comfile, bool intfile);
|
||||
static struct inp_read_t inp_read( FILE *fp, int call_depth, const char *dir_name,
|
||||
const char* file_name, bool comfile, bool intfile);
|
||||
|
||||
|
||||
#ifdef XSPICE
|
||||
|
|
@ -430,7 +436,7 @@ static int is_xspice_model(char* buf)
|
|||
*/
|
||||
|
||||
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);
|
||||
|
||||
|
|
@ -441,6 +447,7 @@ struct card *insert_new_line(
|
|||
x->linenum = linenum;
|
||||
x->linenum_orig = linenum_orig;
|
||||
x->level = card ? card->level : NULL;
|
||||
x->linesource = lineinfo;
|
||||
|
||||
if (card)
|
||||
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->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);
|
||||
}
|
||||
|
|
@ -826,7 +838,7 @@ static void inp_cider_models(struct card* working)
|
|||
}
|
||||
else {
|
||||
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->nextcard = working;
|
||||
}
|
||||
|
|
@ -1025,7 +1037,7 @@ void inp_get_w_l_x(struct card* 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)
|
||||
{
|
||||
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_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;
|
||||
|
||||
/* 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 "
|
||||
"**************\n\n");
|
||||
/* 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);
|
||||
/* here without out-commented lines */
|
||||
for (t = cc->nextcard; t; t = t->nextcard) {
|
||||
if (*(t->line) == '*')
|
||||
continue;
|
||||
fprintf(fd, "%6d %6d %s\n",
|
||||
t->linenum_orig, t->linenum, t->line);
|
||||
fprintf(fd, "%6s %6d %6d %s\n",
|
||||
t->linesource, t->linenum_orig, t->linenum, t->line);
|
||||
}
|
||||
fprintf(fd,
|
||||
"\n****************** complete deck "
|
||||
"***************\n\n");
|
||||
/* now completely */
|
||||
for (t = cc; t; t = t->nextcard)
|
||||
fprintf(fd, "%6d %6d %s\n",
|
||||
t->linenum_orig, t->linenum, t->line);
|
||||
fprintf(fd, "%6s %6d %6d %s\n",
|
||||
t->linesource, t->linenum_orig,t->linenum, t->line);
|
||||
fclose(fd);
|
||||
|
||||
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,
|
||||
bool comfile, bool intfile)
|
||||
static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
||||
const char* file_name, bool comfile, bool intfile)
|
||||
/* fp: in, pointer to file to be read,
|
||||
call_depth: in, nested call to fcn
|
||||
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 card* end = NULL, * cc = NULL;
|
||||
char* buffer = NULL;
|
||||
struct card* end = NULL, * cc = NULL, *tmpcard=NULL;
|
||||
char* buffer = NULL, *sourcelineinfo=NULL;
|
||||
/* segfault fix */
|
||||
#ifdef XSPICE
|
||||
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;
|
||||
#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 */
|
||||
for (;;) {
|
||||
/* 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;
|
||||
|
||||
inp_stripcomments_line(buffer, FALSE);
|
||||
inp_stripcomments_line(buffer, FALSE, TRUE);
|
||||
|
||||
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_dir_name;
|
||||
FILE* newfp;
|
||||
static char oldpath[512];
|
||||
|
||||
if (!y_resolved) {
|
||||
fprintf(cp_err, "Error: Could not find include file %s\n",
|
||||
y);
|
||||
if (ft_stricterror)
|
||||
/* try again with most recent .include path */
|
||||
y_resolved = inp_pathresolve_at(y, oldpath);
|
||||
if (!y_resolved) {
|
||||
fprintf(cp_err, "Error: Could not find include file %s\n", y);
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
rv.line_number = line_number;
|
||||
rv.cc = NULL;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
newfp = fopen(y_resolved, "r");
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
(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 */
|
||||
{
|
||||
end = insert_new_line(
|
||||
end, copy(buffer), line_number, line_number);
|
||||
if (end)
|
||||
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)
|
||||
cc = end;
|
||||
|
|
@ -1464,6 +1497,15 @@ struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
|
|||
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 (newcompat.lt && !newcompat.a)
|
||||
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;
|
||||
end = end->nextcard) {
|
||||
end->linenum = line_number++;
|
||||
end->linenum_orig = line_number_inc++;
|
||||
}
|
||||
end->linenum = line_number++; /* SJB - renumber last line */
|
||||
end->linenum_orig = line_number_inc++;
|
||||
/* SJB - renumber the last line */
|
||||
/* renumber the last line */
|
||||
}
|
||||
|
||||
/* 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, copy(buffer), line_number++, line_number_orig++);
|
||||
|
||||
end, copy(buffer), line_number++, line_number_orig++, sourcelineinfo);
|
||||
if (!cc)
|
||||
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 (!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
|
||||
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) {
|
||||
/* 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 (found_end == TRUE)
|
||||
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 */
|
||||
if (call_depth == 0 && !comfile && new_title) {
|
||||
|
|
@ -1908,9 +1948,99 @@ char *inp_pathresolve(const char *name)
|
|||
} /* 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)
|
||||
{
|
||||
/* 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,
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* expand "~/" */
|
||||
if (name[0] == '~' && name[1] == '/') {
|
||||
char * const y = cp_tildexpand(name);
|
||||
if (y) {
|
||||
|
|
@ -2203,8 +2334,8 @@ static int inp_chk_for_multi_in_vcvs(struct card *c, int *line_number)
|
|||
tfree(xy_values2[1]);
|
||||
|
||||
*c->line = '*';
|
||||
c = insert_new_line(c, m_instance, (*line_number)++, c->linenum_orig);
|
||||
c = insert_new_line(c, m_model, (*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->linesource);
|
||||
#endif
|
||||
return 1;
|
||||
} 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",
|
||||
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) {
|
||||
line = tprintf("a_gen_%.*s gen_node_%.*s %%%cd(%.*s %.*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));
|
||||
}
|
||||
}
|
||||
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]",
|
||||
BSTR(e),
|
||||
ri ? "r_i=true" : rad ? "rad=true" : !db ? "db=false" : "",
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -2472,12 +2603,12 @@ static void inp_add_control_section(struct card *deck, int *line_number)
|
|||
if (last_end)
|
||||
prev_card = last_end;
|
||||
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))) {
|
||||
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;
|
||||
if (ciprefix(".endc", c->line))
|
||||
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
|
||||
located at the beginning of a line. If inside of a control section,
|
||||
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 *d = s;
|
||||
|
|
@ -3241,7 +3372,18 @@ static void inp_stripcomments_line(char *s, bool cs)
|
|||
return; /* empty line */
|
||||
if (*s == '*')
|
||||
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') {
|
||||
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[-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 */
|
||||
first_param_card = c = NULL;
|
||||
while ((ptr1 = strchr(beg, '=')) != NULL) {
|
||||
|
|
@ -3409,7 +3551,7 @@ static char *inp_fix_subckt(struct names *subckt_w_params, char *s)
|
|||
|
||||
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)
|
||||
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;
|
||||
for (; t; t = t->nextcard) {
|
||||
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) {
|
||||
c->line[0] = '*';
|
||||
c->line[1] = '<';
|
||||
|
|
@ -5428,7 +5570,7 @@ static int inp_split_multi_param_lines(struct card *card, int line_num)
|
|||
*(card->line) = '*';
|
||||
// insert new param lines immediately after current line
|
||||
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);
|
||||
}
|
||||
|
|
@ -5846,8 +5988,10 @@ static void inp_compat(struct card *card)
|
|||
&cut_line, '}', TRUE, TRUE); /* expression */
|
||||
if (!expression || !str_ptr) {
|
||||
fprintf(stderr,
|
||||
"Error: bad syntax in line %d\n %s\n",
|
||||
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);
|
||||
}
|
||||
tfree(str_ptr);
|
||||
|
|
@ -5916,8 +6060,9 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable e line
|
||||
*(card->line) = '*';
|
||||
// insert new lines immediately after current line
|
||||
for (i = 0; i < 2; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 2; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ckt_array[3] = tprintf(
|
||||
|
|
@ -5927,8 +6072,9 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable e line
|
||||
*(card->line) = '*';
|
||||
// insert new lines immediately after current line
|
||||
for (i = 0; i < 4; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 4; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
}
|
||||
tfree(expression);
|
||||
tfree(title_tok);
|
||||
|
|
@ -5972,9 +6118,9 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable e line
|
||||
*(card->line) = '*';
|
||||
// insert new B source line immediately after current line
|
||||
for (i = 0; i < 2; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
tfree(title_tok);
|
||||
tfree(node1);
|
||||
tfree(node2);
|
||||
|
|
@ -6039,8 +6185,11 @@ static void inp_compat(struct card *card)
|
|||
// skip "table"
|
||||
cut_line = skip_ws(cut_line);
|
||||
if (!ciprefix("table", cut_line)) {
|
||||
fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
|
||||
card->linenum_orig, 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);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
cut_line += 5;
|
||||
|
|
@ -6051,8 +6200,11 @@ static void inp_compat(struct card *card)
|
|||
str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE);
|
||||
expression = gettok_char(&cut_line, '}', TRUE, TRUE);
|
||||
if (!expression || !str_ptr) {
|
||||
fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
|
||||
card->linenum_orig, 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);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
tfree(str_ptr);
|
||||
|
|
@ -6129,8 +6281,9 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable e line
|
||||
*(card->line) = '*';
|
||||
// insert new lines immediately after current line
|
||||
for (i = 0; i < 2; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 2; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
}
|
||||
else {
|
||||
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
|
||||
*(card->line) = '*';
|
||||
// insert new lines immediately after current line
|
||||
for (i = 0; i < 4; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 4; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
}
|
||||
|
||||
tfree(expression);
|
||||
|
|
@ -6195,8 +6349,9 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable g line
|
||||
*(card->line) = '*';
|
||||
// insert new B source line immediately after current line
|
||||
for (i = 0; i < 2; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 2; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
|
||||
tfree(title_tok);
|
||||
tfree(m_token);
|
||||
|
|
@ -6241,8 +6396,9 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable f line
|
||||
*(card->line) = '*';
|
||||
// insert new three lines immediately after current line
|
||||
for (i = 0; i < 3; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 3; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
|
||||
tfree(title_tok);
|
||||
tfree(vnamstr);
|
||||
|
|
@ -6287,8 +6443,9 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable h line
|
||||
*(card->line) = '*';
|
||||
// insert new three lines immediately after current line
|
||||
for (i = 0; i < 3; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 3; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
|
||||
tfree(title_tok);
|
||||
tfree(vnamstr);
|
||||
|
|
@ -6359,11 +6516,11 @@ static void inp_compat(struct card *card)
|
|||
// comment out current old R line
|
||||
*(card->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) {
|
||||
card = insert_new_line(card, x2line, 2, currlinenumber);
|
||||
card = insert_new_line(card, x3line, 3, currlinenumber);
|
||||
card = insert_new_line(card, x4line, 4, currlinenumber);
|
||||
card = insert_new_line(card, x2line, 2, currlinenumber, card->linesource);
|
||||
card = insert_new_line(card, x3line, 3, currlinenumber, card->linesource);
|
||||
card = insert_new_line(card, x4line, 4, currlinenumber, card->linesource);
|
||||
}
|
||||
|
||||
tfree(title_tok);
|
||||
|
|
@ -6438,8 +6595,9 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable capacitor line
|
||||
*(card->line) = '*';
|
||||
// insert new B source line immediately after current line
|
||||
for (i = 0; i < 3; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 3; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
|
||||
tfree(title_tok);
|
||||
tfree(node1);
|
||||
|
|
@ -6497,14 +6655,53 @@ static void inp_compat(struct card *card)
|
|||
// comment out current variable inductor line
|
||||
*(card->line) = '*';
|
||||
// insert new B source line immediately after current line
|
||||
for (i = 0; i < 3; i++)
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber);
|
||||
for (i = 0; i < 3; i++) {
|
||||
card = insert_new_line(card, ckt_array[i], (int)i + 1, currlinenumber, card->linesource);
|
||||
}
|
||||
|
||||
tfree(title_tok);
|
||||
tfree(node1);
|
||||
tfree(node2);
|
||||
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
|
||||
.print, .plot, .save, .four,
|
||||
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);
|
||||
// insert new B source line immediately after current line
|
||||
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;
|
||||
}
|
||||
|
|
@ -6753,7 +6950,7 @@ static void inp_compat(struct card *card)
|
|||
// *(ckt_array[0]) = '*';
|
||||
// insert new B source line immediately after current line
|
||||
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;
|
||||
// continue;
|
||||
|
|
@ -6854,7 +7051,7 @@ static void inp_bsource_compat(struct card *card)
|
|||
// insert new B source line immediately after current line
|
||||
/* Copy old line numbers into new B source 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);
|
||||
} /* end of if 'b' */
|
||||
|
|
@ -7215,8 +7412,8 @@ static void inp_add_series_resistor(struct card *deck)
|
|||
*(card->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, newR, 2, currlinenumber);
|
||||
card = insert_new_line(card, newL, 1, currlinenumber, card->linesource);
|
||||
card = insert_new_line(card, newR, 2, currlinenumber, card->linesource);
|
||||
|
||||
tfree(title_tok);
|
||||
tfree(node1);
|
||||
|
|
@ -7252,7 +7449,7 @@ static void subckt_params_to_param(struct card *card)
|
|||
/* card->line ends with subcircuit name */
|
||||
cut_line[-1] = '\0';
|
||||
/* 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 {
|
||||
/* 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 = '*';
|
||||
}
|
||||
}
|
||||
|
|
@ -7821,7 +8018,7 @@ static void inp_fix_agauss_in_param(struct card *deck, char *fcn)
|
|||
|
||||
*card->line = '*';
|
||||
/* 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 */
|
||||
|
|
@ -7890,7 +8087,7 @@ static struct func_temper *inp_new_func(char *funcname, char *funcbody,
|
|||
new_str = tprintf(".func %s() %s", funcname, funcbody);
|
||||
|
||||
*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;
|
||||
}
|
||||
|
|
@ -8393,7 +8590,7 @@ static void inp_meas_current(struct card *deck)
|
|||
new_line = tprintf("%s %s %s_vmeas_%d 0",
|
||||
new_tok, node1, node1, sn);
|
||||
/* 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++;
|
||||
tfree(new_tok);
|
||||
|
|
@ -8431,8 +8628,8 @@ static void inp_check_syntax(struct card *deck)
|
|||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
|
||||
/* When '.probe alli' is set, disable auto bridging and set a flag */
|
||||
cp_remvar("probe_alli_given");
|
||||
for (card = deck; card; card = card->nextcard) {
|
||||
char* cut_line = card->line;
|
||||
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
|
||||
if (nesting_once && check_subs > 0 && strchr(cut_line, '=')) {
|
||||
if (ft_ngdebug && nesting_once && check_subs > 0 && strchr(cut_line, '=')) {
|
||||
fprintf(cp_err,
|
||||
"\nWarning: Nesting of subcircuits with parameters "
|
||||
"is only marginally supported!\n\n");
|
||||
|
|
@ -9294,3 +9491,45 @@ static int inp_poly_2g6_compat(struct card* deck) {
|
|||
return 0;
|
||||
}
|
||||
#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
|
||||
|
||||
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);
|
||||
|
||||
extern char* inp_remove_ws(char* s);
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ static void replace_table(struct card *startcard)
|
|||
tfree(begline);
|
||||
tfree(card->line);
|
||||
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 */
|
||||
ftablebeg = strstr(cut_line, "table(");
|
||||
}
|
||||
|
|
@ -377,7 +377,7 @@ static bool del_models(struct vsmodels *vsmodel)
|
|||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct card* card;
|
||||
|
|
@ -389,7 +389,7 @@ static void rem_double_braces(struct card* newcard)
|
|||
slevel++;
|
||||
else if (ciprefix(".ends", cut_line))
|
||||
slevel--;
|
||||
if (ciprefix(".model", cut_line) || slevel > 0) {
|
||||
if (ciprefix(".model", cut_line) || slevel > 0 || ciprefix(".param", cut_line)) {
|
||||
cut_line = strchr(cut_line, '{');
|
||||
if (cut_line) {
|
||||
int level = 1;
|
||||
|
|
@ -505,6 +505,12 @@ static struct card *u_instances(struct card *startcard)
|
|||
newcard = replacement_udevice_cards();
|
||||
if (newcard) {
|
||||
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);
|
||||
/* Pspice definition of .subckt card:
|
||||
.SUBCKT <name> [node]*
|
||||
|
|
@ -671,26 +677,26 @@ struct card *pspice_compat(struct card *oldcard)
|
|||
|
||||
/* add predefined params TEMP, VT, GMIN to beginning of deck */
|
||||
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'");
|
||||
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");
|
||||
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 */
|
||||
/* LIMIT( Output Expression, Limit1, Limit2)
|
||||
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)) }");
|
||||
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) }");
|
||||
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) }");
|
||||
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) }");
|
||||
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 )}");
|
||||
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)) }");
|
||||
nextcard = insert_new_line(nextcard, new_str, 9, 0);
|
||||
nextcard = insert_new_line(nextcard, new_str, 9, 0, "internal");
|
||||
nextcard->nextcard = oldcard;
|
||||
|
||||
#ifdef INTEGRATE_UDEVICES
|
||||
|
|
@ -714,9 +720,9 @@ struct card *pspice_compat(struct card *oldcard)
|
|||
char *cut_line = card->line;
|
||||
if (ciprefix(".subckt", cut_line)) {
|
||||
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'");
|
||||
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.
|
||||
Do nothing if you are inside of { }. */
|
||||
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",
|
||||
card->linenum, cut_line);
|
||||
fprintf(stderr, " Please correct the input file\n");
|
||||
if (ft_stricterror)
|
||||
controlled_exit(1);
|
||||
else
|
||||
continue;
|
||||
controlled_exit(1);
|
||||
}
|
||||
char *tctok = search_plain_identifier(ntok, "tc");
|
||||
if (tctok) {
|
||||
|
|
@ -1363,7 +1366,11 @@ struct card *pspice_compat(struct card *oldcard)
|
|||
for (i = 0; i < 6; i++) {
|
||||
stoks[i] = gettok_node(&cut_line);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1726,16 +1733,16 @@ struct card *ltspice_compat(struct card *oldcard)
|
|||
char *new_str =
|
||||
copy(".func uplim(x, pos, z) { min(x, pos - z) + (1 - "
|
||||
"(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 - "
|
||||
"(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) + "
|
||||
"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) - "
|
||||
"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;
|
||||
|
||||
/* remove .backanno, replace 'noiseless' by 'moisy=0' */
|
||||
|
|
@ -1869,7 +1876,7 @@ struct card *ltspice_compat(struct card *oldcard)
|
|||
for (i = 0; i < 4; i++) {
|
||||
stoks[i] = gettok_node(&cut_line);
|
||||
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");
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,8 +93,10 @@ com_quit(wordlist *wl)
|
|||
|
||||
/* Destroy CKT when quit. */
|
||||
if (!ft_nutmeg) {
|
||||
while(ft_curckt)
|
||||
while (ft_curckt) {
|
||||
wl_delete(ft_curckt->ci_sourceinfo);
|
||||
com_remcirc(NULL);
|
||||
}
|
||||
}
|
||||
cp_destroy_keywords();
|
||||
destroy_ivars();
|
||||
|
|
@ -102,8 +104,10 @@ com_quit(wordlist *wl)
|
|||
/* remove plotting parameters */
|
||||
pl_rempar();
|
||||
|
||||
while (ft_curckt)
|
||||
while (ft_curckt) {
|
||||
// wl_delete(ft_curckt->ci_sourceinfo);
|
||||
com_remcirc(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
tfree(errMsg);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ inp_nutsource(FILE *fp, bool comfile, char *filename)
|
|||
wordlist *controls = NULL;
|
||||
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)
|
||||
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_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = 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 struct variable *cp_enqvec_as_var(const char *vec_name,
|
||||
|
|
@ -327,6 +327,11 @@ cp_usrset(struct variable *var, bool isset)
|
|||
ft_strictnumparse = isset;
|
||||
} else if (eq(var->va_name, "strict_errorhandling")) {
|
||||
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")) {
|
||||
if ((var->va_type == CP_BOOL) && (isset == FALSE))
|
||||
raw_prec = -1;
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
|
|||
char *ch, tmpname[BSIZE_SP];
|
||||
bool saveall = TRUE;
|
||||
bool savealli = FALSE;
|
||||
bool savenosub = FALSE;
|
||||
char *an_name;
|
||||
int initmem;
|
||||
/*to resume a run saj
|
||||
|
|
@ -213,6 +214,13 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
|
|||
saves[i].used = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cieq(saves[i].name, "nosub")) {
|
||||
savenosub = TRUE;
|
||||
savesused[i] = TRUE;
|
||||
saves[i].used = 1;
|
||||
continue;
|
||||
}
|
||||
#ifdef SHARED_MODULE
|
||||
/* this may happen if shared ngspice*/
|
||||
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;
|
||||
else
|
||||
initmem = numNames;
|
||||
|
|
@ -245,7 +253,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
|
|||
|
||||
|
||||
/* Pass 1. */
|
||||
if (numsaves && !saveall) {
|
||||
if (numsaves && !saveall && !savenosub) {
|
||||
for (i = 0; i < numsaves; i++) {
|
||||
if (!savesused[i]) {
|
||||
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++)
|
||||
if (!refName || !name_eq(dataNames[i], refName))
|
||||
/* 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], "#drain") &&
|
||||
!strstr(dataNames[i], "#collector") &&
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ extern struct INPmodel *modtab;
|
|||
extern NGHASHPTR modtabhash;
|
||||
extern struct dbcomm *dbs;
|
||||
extern void NIresetwarnmsg(void);
|
||||
extern wordlist* sourceinfo;
|
||||
|
||||
/* Routines for the commands op, tran, ac, dc, listing, device, state,
|
||||
* resume, stop, trace, run, end. Op, tran, ac, and dc cause the action
|
||||
|
|
@ -109,6 +110,8 @@ com_scirc(wordlist *wl)
|
|||
ft_curckt = p;
|
||||
/* get the model table for the current circuit, store it in the global variable modtab */
|
||||
modtab = ft_curckt->ci_modtab;
|
||||
/* get the current input file names */
|
||||
sourceinfo = ft_curckt->ci_sourceinfo;
|
||||
modtabhash = ft_curckt->ci_modtabhash;
|
||||
/* get the database for save, iplot, stop */
|
||||
dbs = ft_curckt->ci_dbs;
|
||||
|
|
|
|||
|
|
@ -841,6 +841,8 @@ struct card * inp_deckcopy(struct card *deck) {
|
|||
nd = d = TMALLOC(struct card, 1);
|
||||
}
|
||||
d->linenum = deck->linenum;
|
||||
d->linenum_orig = deck->linenum_orig;
|
||||
d->linesource = deck->linesource;
|
||||
d->w = deck->w;
|
||||
d->l = deck->l;
|
||||
d->nf = deck->nf;
|
||||
|
|
@ -889,7 +891,8 @@ struct card *inp_deckcopy_oc(struct card * deck)
|
|||
d->w = deck->w;
|
||||
d->l = deck->l;
|
||||
d->nf = deck->nf;
|
||||
d->linenum_orig = deck->linenum;
|
||||
d->linenum_orig = deck->linenum_orig;
|
||||
d->linesource = deck->linesource;
|
||||
d->linenum = i++;
|
||||
d->line = copy(deck->line);
|
||||
if (deck->error) {
|
||||
|
|
@ -947,6 +950,7 @@ struct card* inp_deckcopy_ln(struct card* deck)
|
|||
d->l = deck->l;
|
||||
d->nf = deck->nf;
|
||||
d->linenum_orig = deck->linenum_orig;
|
||||
d->linesource = deck->linesource;
|
||||
d->linenum = deck->linenum;
|
||||
d->line = copy(deck->line);
|
||||
if (deck->error) {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
#include "ngspice/hash.h"
|
||||
|
||||
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 */
|
||||
#define D_AND 0
|
||||
|
|
@ -845,13 +845,13 @@ struct card *replacement_udevice_cards(void)
|
|||
new_str = copy(x->translated);
|
||||
if (count == 0) {
|
||||
count++;
|
||||
newcard = insert_new_line(NULL, new_str, 0, 0);
|
||||
newcard = insert_new_line(NULL, new_str, 0, 0, NULL);
|
||||
} else if (count == 1) {
|
||||
count++;
|
||||
nextcard = insert_new_line(newcard, new_str, 0, 0);
|
||||
nextcard = insert_new_line(newcard, new_str, 0, 0, NULL);
|
||||
} else {
|
||||
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)) {
|
||||
|
|
|
|||
|
|
@ -107,9 +107,6 @@ typedef struct SPICEdev {
|
|||
/* noise routine */
|
||||
int (*DEVsoaCheck)(CKTcircuit*,GENmodel*);
|
||||
/* subroutine to call on soa check */
|
||||
int *DEVinstSize; /* size of an instance */
|
||||
int *DEVmodSize; /* size of a model */
|
||||
|
||||
#ifdef CIDER
|
||||
void (*DEVdump)(GENmodel *, CKTcircuit *);
|
||||
void (*DEVacct)(GENmodel *, CKTcircuit *, FILE *);
|
||||
|
|
@ -117,6 +114,8 @@ typedef struct SPICEdev {
|
|||
* now used only by cider numerical devices
|
||||
*/
|
||||
#endif
|
||||
int *DEVinstSize; /* size of an instance */
|
||||
int *DEVmodSize; /* size of a model */
|
||||
|
||||
#ifdef KLU
|
||||
int (*DEVbindCSC)(GENmodel *, CKTcircuit *);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ struct circ {
|
|||
struct ccom *ci_nodes; /* ccom structs for the nodes... */
|
||||
struct ccom *ci_devices; /* and devices in the circuit. */
|
||||
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_specTask; /* special task for command line jobs */
|
||||
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);
|
||||
extern void inp_casefix(char *string);
|
||||
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);
|
||||
extern FILE *inp_pathopen(const char *name, const char *mode);
|
||||
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_nginfo;
|
||||
extern bool ft_stricterror;
|
||||
extern bool ft_spiniterror;
|
||||
extern bool ft_skywaterpdk;
|
||||
|
||||
/* parse.c */
|
||||
|
|
|
|||
|
|
@ -282,8 +282,6 @@ struct IFdevice {
|
|||
int *numModelParms; /* number 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 */
|
||||
/* by new parser */
|
||||
#ifdef XSPICE
|
||||
|
|
@ -300,6 +298,8 @@ struct IFdevice {
|
|||
/* gtri - end - wbk - 10/11/90 */
|
||||
#endif
|
||||
|
||||
int flags; /* DEV_ */
|
||||
|
||||
#ifdef OSDI
|
||||
const void *registry_entry;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ struct card_assoc {
|
|||
struct card {
|
||||
int linenum;
|
||||
int linenum_orig;
|
||||
char* linesource;
|
||||
char *line;
|
||||
char *error;
|
||||
struct card *nextcard;
|
||||
|
|
@ -96,7 +97,9 @@ struct INPmodel {
|
|||
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 */
|
||||
#define LOGICAL 1
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ void wl_delete_slice(wordlist *from, wordlist *to);
|
|||
wordlist *wl_find(const char *string, const wordlist *wlist);
|
||||
char * wl_flatten(const wordlist *wl);
|
||||
void wl_free(wordlist *wlist);
|
||||
void wl_delete(wordlist *wlist);
|
||||
wordlist *wl_from_string(const char *sz);
|
||||
int wl_length(const wordlist *wlist);
|
||||
char ** wl_mkvec(const wordlist *wl);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ tmalloc(size_t num)
|
|||
mutex_unlock(&allocMutex);
|
||||
#endif
|
||||
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
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
#else
|
||||
|
|
@ -119,7 +120,8 @@ trealloc(const void *ptr, size_t num)
|
|||
#endif
|
||||
}
|
||||
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
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
#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. */
|
||||
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
|
||||
* 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 */
|
||||
|
||||
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");
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,8 +86,17 @@ ACan(CKTcircuit* ckt, int restart)
|
|||
fprintf(stderr, "ERROR: AC startfreq <= 0\n");
|
||||
return E_PARMVAL;
|
||||
}
|
||||
double num_steps = floor(fabs(log10(job->ACstopFreq / job->ACstartFreq)) * job->ACnumberSteps);
|
||||
job->ACfreqDelta = exp((log(job->ACstopFreq / job->ACstartFreq)) / num_steps);
|
||||
if (job->ACstopFreq / 10. < job->ACstartFreq) {
|
||||
/* 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;
|
||||
case OCTAVE:
|
||||
|
|
|
|||
|
|
@ -256,7 +256,8 @@ DCtran(CKTcircuit *ckt,
|
|||
fprintf(stdout,"\n");
|
||||
fflush(stdout);
|
||||
} 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);
|
||||
} else if (!ft_noacctprint && !ft_noinitprint) {
|
||||
fprintf(stdout,"\nInitial Transient Solution\n");
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ typedef void * funptr_t;
|
|||
#else /* ifdef HAS_WINGUI */
|
||||
#undef BOOLEAN
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <libloaderapi.h>
|
||||
typedef FARPROC funptr_t;
|
||||
void *dlopen(const char *, int);
|
||||
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)
|
||||
{
|
||||
void *lib;
|
||||
void *lib = NULL;
|
||||
char *msg;
|
||||
int num;
|
||||
SPICEdev **devs;
|
||||
|
|
@ -428,9 +430,10 @@ int load_opus(const char *name)
|
|||
funptr_t fetch;
|
||||
|
||||
lib = dlopen(name, RTLD_NOW);
|
||||
// fprintf(stdout, "Lib %s has handle %p\n", name, lib);
|
||||
if (!lib) {
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -445,7 +448,7 @@ int load_opus(const char *name)
|
|||
}
|
||||
else {
|
||||
msg = dlerror();
|
||||
printf("Error getting the list of devices: %s\n",
|
||||
fprintf(stderr, "Error getting the list of devices: %s\n",
|
||||
msg);
|
||||
FREE_DLERR_MSG(msg);
|
||||
return 1;
|
||||
|
|
@ -453,7 +456,7 @@ int load_opus(const char *name)
|
|||
}
|
||||
else {
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -474,7 +477,7 @@ int load_opus(const char *name)
|
|||
}
|
||||
else {
|
||||
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);
|
||||
FREE_DLERR_MSG(msg);
|
||||
return 1;
|
||||
|
|
@ -482,7 +485,7 @@ int load_opus(const char *name)
|
|||
}
|
||||
else {
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -501,7 +504,7 @@ int load_opus(const char *name)
|
|||
}
|
||||
else {
|
||||
msg = dlerror();
|
||||
printf("Error getting interface pointer: %s\n", msg);
|
||||
fprintf(stderr, "Error getting interface pointer: %s\n", msg);
|
||||
FREE_DLERR_MSG(msg);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -522,7 +525,33 @@ static char errstr[sizeof errstr_fmt - 3 + 3 * sizeof(unsigned long)];
|
|||
void *dlopen(const char *name, int 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)
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ IFparm DIOmPTable[] = { /* model parameters */
|
|||
IOP( "tlev", DIO_MOD_TLEV, 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( "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( "cta", DIO_MOD_CTA, IF_REAL, "Area junction 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( "fcs", DIO_MOD_FCS, IF_REAL, "Forward bias sidewall junction fit parameter"),
|
||||
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"),
|
||||
IOPR( "ib", DIO_MOD_IBV, IF_REAL, "Current at reverse breakdown voltage"),
|
||||
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( "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( "xw", DIO_MOD_XW, IF_REAL, "Masking and etching effects (level=3)"),
|
||||
|
||||
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 DIOtlevcGiven : 1;
|
||||
unsigned DIOactivationEnergyGiven : 1;
|
||||
unsigned DIOfirstBGcorrFactorGiven : 1;
|
||||
unsigned DIOsecndBGcorrFactorGiven : 1;
|
||||
unsigned DIOsaturationCurrentExpGiven : 1;
|
||||
unsigned DIOctaGiven : 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 DIOmetalMaskOffsetGiven : 1; /* Masking and etching effects in metal (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 */
|
||||
double DIOsatCur; /* saturation current */
|
||||
|
|
@ -331,6 +334,8 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
|||
int DIOtlev; /* Diode temperature equation selector */
|
||||
int DIOtlevc; /* Diode temperature equation selector */
|
||||
double DIOactivationEnergy; /* activation energy (EG) */
|
||||
double DIOfirstBGcorrFactor; /* First bandgap correction factor */
|
||||
double DIOsecndBGcorrFactor; /* Second bandgap correction factor */
|
||||
double DIOsaturationCurrentExp; /* Saturation current exponential (XTI) */
|
||||
double DIOcta; /* Area 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 DIOmetalMaskOffset; /* Masking and etching effects in metal (level=3)") */
|
||||
double DIOpolyMaskOffset; /* Masking and etching effects in polysilicon (level=3) */
|
||||
double DIOmaskOffset; /* Masking and etching effects (level=3) */
|
||||
|
||||
} DIOmodel;
|
||||
|
||||
|
|
@ -418,6 +424,8 @@ enum {
|
|||
DIO_MOD_VJ,
|
||||
DIO_MOD_M,
|
||||
DIO_MOD_EG,
|
||||
DIO_MOD_GAP1,
|
||||
DIO_MOD_GAP2,
|
||||
DIO_MOD_XTI,
|
||||
DIO_MOD_FC,
|
||||
DIO_MOD_BV,
|
||||
|
|
@ -474,6 +482,7 @@ enum {
|
|||
DIO_MOD_XOI,
|
||||
DIO_MOD_XM,
|
||||
DIO_MOD_XP,
|
||||
DIO_MOD_XW,
|
||||
};
|
||||
|
||||
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:
|
||||
value->rValue = model->DIOactivationEnergy;
|
||||
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:
|
||||
value->rValue = model->DIOsaturationCurrentExp;
|
||||
return(OK);
|
||||
|
|
@ -218,6 +224,9 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value)
|
|||
case DIO_MOD_XP:
|
||||
value->rValue = model->DIOpolyMaskOffset;
|
||||
return(OK);
|
||||
case DIO_MOD_XW:
|
||||
value->rValue = model->DIOmaskOffset;
|
||||
return(OK);
|
||||
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
|
|
|
|||
|
|
@ -133,6 +133,14 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->DIOactivationEnergy = value->rValue;
|
||||
model->DIOactivationEnergyGiven = TRUE;
|
||||
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:
|
||||
model->DIOsaturationCurrentExp = value->rValue;
|
||||
model->DIOsaturationCurrentExpGiven = TRUE;
|
||||
|
|
@ -270,6 +278,10 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->DIOpolyMaskOffset = value->rValue;
|
||||
model->DIOpolyMaskOffsetGiven = TRUE;
|
||||
break;
|
||||
case DIO_MOD_XW:
|
||||
model->DIOmaskOffset = value->rValue;
|
||||
model->DIOmaskOffsetGiven = TRUE;
|
||||
break;
|
||||
|
||||
case DIO_MOD_D:
|
||||
/* 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->DIOforwardKneeCurrent < ckt->CKTepsmin) {
|
||||
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->DIOreverseKneeCurrent < ckt->CKTepsmin) {
|
||||
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) {
|
||||
|
|
@ -112,7 +114,17 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
model->DIOtlevc = 0;
|
||||
}
|
||||
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) {
|
||||
model->DIOsaturationCurrentExp = 3;
|
||||
|
|
@ -243,6 +255,9 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
if(!model->DIOpolyMaskOffsetGiven) {
|
||||
model->DIOpolyMaskOffset = 0.0;
|
||||
}
|
||||
if(!model->DIOmaskOffsetGiven) {
|
||||
model->DIOmaskOffset = 0.0;
|
||||
}
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (here = DIOinstances(model); here != NULL ;
|
||||
|
|
@ -273,8 +288,8 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
if (model->DIOlevel == 3) {
|
||||
double wm, lm, wp, lp;
|
||||
if((here->DIOwGiven) && (here->DIOlGiven)) {
|
||||
here->DIOarea = here->DIOw * here->DIOl * here->DIOm;
|
||||
here->DIOpj = (2 * here->DIOw + 2 * here->DIOl) * here->DIOm;
|
||||
here->DIOarea = (here->DIOw+model->DIOmaskOffset) * (here->DIOl+model->DIOmaskOffset) * here->DIOm;
|
||||
here->DIOpj = (2 * (here->DIOw+model->DIOmaskOffset) + 2 * (here->DIOl+model->DIOmaskOffset)) * here->DIOm;
|
||||
}
|
||||
here->DIOarea = here->DIOarea * scale * 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 fact2,pbfact,arg,egfet,gmanew,gmaSWnew;
|
||||
double arg1_dT, arg2, arg2_dT;
|
||||
double gclimit;
|
||||
|
||||
if (!cp_getvar("DIOgradingCoeffMax", CP_REAL, &gclimit, 0))
|
||||
gclimit = 0.9;
|
||||
double lnTRatio, egfet_dT, arg0, vte_dT, vts_dT, vtt_dT, vtr_dT;
|
||||
|
||||
vt = CONSTKoverQ * Temp;
|
||||
vte = model->DIOemissionCoeff * vt;
|
||||
vte_dT = CONSTKoverQ * model->DIOemissionCoeff;
|
||||
vts = model->DIOswEmissionCoeff * vt;
|
||||
vts_dT = CONSTKoverQ * model->DIOswEmissionCoeff;
|
||||
vtt = model->DIOtunEmissionCoeff * vt;
|
||||
vtt_dT = CONSTKoverQ * model->DIOtunEmissionCoeff;
|
||||
vtr = model->DIOrecEmissionCoeff * vt;
|
||||
vtr_dT = CONSTKoverQ * model->DIOrecEmissionCoeff;
|
||||
vtnom = CONSTKoverQ * model->DIOnomTemp;
|
||||
dt = Temp - model->DIOnomTemp;
|
||||
lnTRatio = log(Temp / model->DIOnomTemp);
|
||||
|
||||
/* Junction grading temperature adjust */
|
||||
factor = 1.0 + (model->DIOgradCoeffTemp1 * dt)
|
||||
+ (model->DIOgradCoeffTemp2 * dt * dt);
|
||||
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
|
||||
* 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;
|
||||
egfet = 1.16-(7.02e-4*Temp*Temp)/
|
||||
(Temp+1108);
|
||||
arg = -egfet/(2*CONSTboltz*Temp) +
|
||||
1.1150877/(CONSTboltz*(REFTEMP+REFTEMP));
|
||||
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) +
|
||||
1.1150877/(2*CONSTboltz*REFTEMP);
|
||||
fact1 = model->DIOnomTemp/REFTEMP;
|
||||
|
|
@ -108,45 +110,77 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
|
|||
(1+model->DIOctp*(Temp-REFTEMP));
|
||||
}
|
||||
|
||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vte;
|
||||
arg1_dT = model->DIOactivationEnergy / (vte*model->DIOnomTemp)
|
||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vte*Temp);
|
||||
arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * log(Temp / model->DIOnomTemp);
|
||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp;
|
||||
here->DIOtSatCur = model->DIOsatCur * here->DIOarea * exp(arg1 + arg2);
|
||||
here->DIOtSatCur_dT = model->DIOsatCur * here->DIOarea * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
||||
if ((model->DIOtlev == 0) || (model->DIOtlev == 1)) {
|
||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vte;
|
||||
arg1_dT = model->DIOactivationEnergy / (vte*model->DIOnomTemp)
|
||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vte*Temp);
|
||||
arg2 = model->DIOsaturationCurrentExp / model->DIOemissionCoeff * lnTRatio;
|
||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOemissionCoeff / Temp;
|
||||
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_dT = model->DIOactivationEnergy / (vts*model->DIOnomTemp)
|
||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vts*Temp);
|
||||
arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * log(Temp / model->DIOnomTemp);
|
||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp;
|
||||
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(arg1 + arg2);
|
||||
here->DIOtSatSWCur_dT = model->DIOsatSWCur * here->DIOpj * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vts;
|
||||
arg1_dT = model->DIOactivationEnergy / (vts*model->DIOnomTemp)
|
||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vts*Temp);
|
||||
arg2 = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff * lnTRatio;
|
||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOswEmissionCoeff / Temp;
|
||||
here->DIOtSatSWCur = model->DIOsatSWCur * here->DIOpj * exp(arg1 + arg2);
|
||||
here->DIOtSatSWCur_dT = here->DIOtSatSWCur * (arg1_dT + arg2_dT);
|
||||
|
||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / vtt;
|
||||
arg1_dT = model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / (vtt*model->DIOnomTemp)
|
||||
- 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->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(arg1 + arg2);
|
||||
here->DIOtTunSatCur_dT = model->DIOtunSatCur * here->DIOarea * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
||||
arg1 = ((Temp/model->DIOnomTemp)-1) * model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / vtt;
|
||||
arg1_dT = model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / (vtt*model->DIOnomTemp)
|
||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtt*Temp);
|
||||
arg2 = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff * lnTRatio;
|
||||
arg2_dT = model->DIOtunSaturationCurrentExp / model->DIOtunEmissionCoeff / Temp;
|
||||
here->DIOtTunSatCur = model->DIOtunSatCur * here->DIOarea * exp(arg1 + arg2);
|
||||
here->DIOtTunSatCur_dT = here->DIOtTunSatCur * (arg1_dT + arg2_dT);
|
||||
|
||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / vtt;
|
||||
arg1_dT = model->DIOtunEGcorrectionFactor*model->DIOactivationEnergy / (vtt*model->DIOnomTemp)
|
||||
- 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);
|
||||
here->DIOtTunSatSWCur = model->DIOtunSatSWCur * here->DIOpj * exp(arg1 + arg2);
|
||||
here->DIOtTunSatSWCur_dT = here->DIOtTunSatSWCur * (arg1_dT + arg2_dT);
|
||||
|
||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vtr;
|
||||
arg1_dT = model->DIOactivationEnergy / (vtr*model->DIOnomTemp)
|
||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtr*Temp);
|
||||
arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * log(Temp / model->DIOnomTemp);
|
||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp;
|
||||
here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * exp(arg1 + arg2);
|
||||
here->DIOtRecSatCur_dT = model->DIOrecSatCur * here->DIOarea * exp(arg1 + arg2) * (arg1_dT + arg2_dT);
|
||||
arg1 = ((Temp / model->DIOnomTemp) - 1) * model->DIOactivationEnergy / vtr;
|
||||
arg1_dT = model->DIOactivationEnergy / (vtr*model->DIOnomTemp)
|
||||
- model->DIOactivationEnergy*(Temp/model->DIOnomTemp -1)/(vtr*Temp);
|
||||
arg2 = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff * lnTRatio;
|
||||
arg2_dT = model->DIOsaturationCurrentExp / model->DIOrecEmissionCoeff / Temp;
|
||||
here->DIOtRecSatCur = model->DIOrecSatCur * here->DIOarea * exp(arg1 + arg2);
|
||||
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);
|
||||
xfcs=log(1-model->DIOdepletionSWcapCoeff);
|
||||
|
|
@ -162,27 +196,8 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
|
|||
here->DIOtDepSWCap=model->DIOdepletionSWcapCoeff*
|
||||
here->DIOtJctSWPot;
|
||||
/* and Vcrit */
|
||||
vte=model->DIOemissionCoeff*vt;
|
||||
|
||||
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
|
||||
* temperature adjusted basic parameters */
|
||||
if (model->DIObreakdownVoltageGiven){
|
||||
|
|
|
|||
|
|
@ -128,10 +128,13 @@ MOS1noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
|
|||
/* linear region */
|
||||
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);
|
||||
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],
|
||||
|
|
|
|||
|
|
@ -117,10 +117,13 @@ MOS2noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
|
|||
/* linear region */
|
||||
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);
|
||||
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],
|
||||
|
|
|
|||
|
|
@ -117,10 +117,13 @@ MOS3noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
|
|||
/* linear region */
|
||||
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);
|
||||
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],
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ Author: 1985 Thomas L. Quarles
|
|||
/* gtri - end - wbk - 11/9/90 */
|
||||
#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 */
|
||||
/*#define TRACE*/
|
||||
|
|
@ -41,10 +44,6 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
|
|||
printf("Entered INPpas2 . . . .\n");
|
||||
#endif
|
||||
|
||||
#ifdef XSPICE
|
||||
if (!ckt->CKTadevFlag) ckt->CKTadevFlag = 0;
|
||||
#endif
|
||||
|
||||
error = INPgetTok(&groundname, &gname, 1);
|
||||
if (error)
|
||||
data->error =
|
||||
|
|
@ -81,12 +80,15 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task)
|
|||
#endif
|
||||
|
||||
#ifdef HAS_PROGREP
|
||||
if (linecount > 0) {
|
||||
if (linecount > 0) {
|
||||
SetAnalyse( "Parse", (int) (1000.*actcount/linecount));
|
||||
actcount++;
|
||||
}
|
||||
#endif
|
||||
|
||||
Current_parse_line = current->linenum_orig;
|
||||
Sourcefile = current->linesource;
|
||||
|
||||
c = *(current->line);
|
||||
if(islower_c(c))
|
||||
c = toupper_c(c);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/inpptree.h"
|
||||
#include "ngspice/inpdefs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -143,5 +144,11 @@ PTerror (YYLTYPE *locp, char **line, struct INPparseNode **retval, void *ckt, ch
|
|||
NG_IGNORE(retval);
|
||||
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;
|
||||
|
||||
if (p->funcnum != PTF_PWL) {
|
||||
fprintf(stderr, "PWL-INFO: %s, very unexpected\n", __func__);
|
||||
controlled_exit(1);
|
||||
fprintf(stderr, "PWL-INFO: %s, very unexpected at line %d\nfrom file\n %s\n\n",
|
||||
__func__, Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
#ifdef TRACE
|
||||
|
|
@ -1041,8 +1042,11 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
|||
i++;
|
||||
|
||||
if (i<2 || (i%1)) {
|
||||
fprintf(stderr, "Error: PWL(expr, points...) needs an even and >=2 number of constant args\n");
|
||||
return mkfirst(NULL, p);
|
||||
fprintf(stderr,
|
||||
"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);
|
||||
|
|
@ -1060,11 +1064,13 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
|||
w->right->left->type == PT_CONSTANT) {
|
||||
data->vals[i] = - w->right->left->constant;
|
||||
} else {
|
||||
fprintf(stderr, "PWL-ERROR: %s, not a constant\n", __func__);
|
||||
fprintf(stderr, " type = %d\n", w->right->type);
|
||||
//Breakpoint;
|
||||
fprintf(stderr, "Error: PWL(expr, points...) only *literal* points are supported\n");
|
||||
return mkfirst(NULL, p);
|
||||
fprintf(stderr,
|
||||
"Error: PWL(expr, points...) only *literal* points "
|
||||
"are supported at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
// 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
|
||||
|
|
@ -1072,11 +1078,31 @@ static INPparseNode *prepare_PTF_PWL(INPparseNode *p)
|
|||
fprintf(stderr, " (%lf %lf)\n", data->vals[i], data->vals[i+1]);
|
||||
#endif
|
||||
|
||||
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\n");
|
||||
return mkfirst(NULL, p);
|
||||
}
|
||||
/* check for monotonic abscissa */
|
||||
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 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,
|
||||
* 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];
|
||||
|
||||
if (!fname) {
|
||||
fprintf(stderr, "Error: bogus function name \n");
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error: bogus function name at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
fprintf(stderr, "Error: bad function arguments \n");
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error: bad function arguments at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
/* Make sure the case is ok. */
|
||||
|
|
@ -1144,8 +1172,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
|||
return mkfirst(p, arg);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Error: bogus ternary_fcn form\n");
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error: bogus ternary_fcn form at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (a2 == 0.0 || a3 == 0.0) {
|
||||
fprintf(stderr, "Error: bogus gauss form\n");
|
||||
return mkfirst(NULL, arg); //return mkcon(a1);
|
||||
fprintf(stderr, "Error: bogus gauss form at line %d\nfrom file\n %s\n",
|
||||
Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
return mkcon(gauss(a1, a2, a3));
|
||||
|
|
@ -1177,10 +1207,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
|||
break;
|
||||
|
||||
if (i == NUM_FUNCS) {
|
||||
fprintf(stderr, "Error: no such function '%s'\n", buf);
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error: no such function '%s' at line %d\nfrom file\n %s\n",
|
||||
buf, Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
|
||||
p = TMALLOC(INPparseNode, 1);
|
||||
|
|
@ -1197,10 +1226,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg)
|
|||
if (p->funcnum == PTF_PWL) {
|
||||
p = prepare_PTF_PWL(p);
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "Error while parsing function '%s'\n", buf);
|
||||
if (ft_stricterror)
|
||||
controlled_exit(EXIT_BAD);
|
||||
return mkfirst(NULL, arg);
|
||||
fprintf(stderr, "Error while parsing function '%s' at line %d\nfrom file\n %s\n",
|
||||
buf, Current_parse_line, Sourcefile);
|
||||
controlled_exit(EXIT_BAD);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -351,14 +351,27 @@ PTpwl(double arg, void *data)
|
|||
int k0 = 0;
|
||||
int k1 = thing->n/2 - 1;
|
||||
|
||||
while(k1-k0 > 1) {
|
||||
int k = (k0+k1)/2;
|
||||
if(thing->vals[2*k] > arg)
|
||||
k1 = k;
|
||||
else
|
||||
k0 = k;
|
||||
/* monotonically increasing abscissa */
|
||||
if (thing->vals[0] < thing->vals[2]) {
|
||||
while (k1 - k0 > 1) {
|
||||
int k = (k0 + k1) / 2;
|
||||
if (thing->vals[2 * k] > arg)
|
||||
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] +
|
||||
(thing->vals[2*k1+1] - thing->vals[2*k0+1]) *
|
||||
(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. */
|
||||
|
||||
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);
|
||||
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);
|
||||
bridge->count = 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,
|
||||
copy("* Auto-bridge sub-deck."),
|
||||
BIG + ln++, 0);
|
||||
BIG + ln++, (lastcard ? lastcard->linenum_orig : 0),
|
||||
(lastcard ? lastcard->linesource : NULL));
|
||||
lastcard = head;
|
||||
}
|
||||
|
||||
|
|
@ -748,7 +749,8 @@ bool Evtcheck_nodes(
|
|||
*/
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -563,8 +563,8 @@ static void EVTprocess_output(
|
|||
|
||||
if (g_mif_info.circuit.anal_type == MIF_TRAN) {
|
||||
delay = port->delay;
|
||||
if(delay <= 0.0) {
|
||||
printf("\nERROR - Output delay <= 0 not allowed - output ignored!\n");
|
||||
if(delay < 0.0) {
|
||||
printf("\nERROR - Output delay < 0 not allowed - output ignored!\n");
|
||||
printf(" Instance: %s\n Node: %s\n Time: %f \n",
|
||||
g_mif_info.instance->MIFname, node_table[node_index]->name,
|
||||
g_mif_info.ckt->CKTtime);
|
||||
|
|
|
|||
|
|
@ -345,7 +345,8 @@ void ucm_d_cosim(ARGS)
|
|||
{
|
||||
struct instance *ip;
|
||||
Digital_t *in_vals; // XSPICE rotating memory
|
||||
unsigned int i, index;
|
||||
unsigned int i;
|
||||
int index;
|
||||
|
||||
if (INIT) {
|
||||
unsigned int ins, outs, inouts;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ fi
|
|||
SPICE=$1
|
||||
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`
|
||||
testdir=`dirname $TEST`
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#
|
||||
# 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.0 05/13/11 Dietmar Warning Initial version
|
||||
#
|
||||
|
|
@ -88,7 +89,7 @@ sub runNoiseTest {
|
|||
print OF "rin dummy 0 1.0 noise=0";
|
||||
foreach $pin (@main::Pin) {
|
||||
if ($main::isFloatingPin{$pin}) {
|
||||
print OF "i_$pin $pin 0 0";
|
||||
print OF "r_$pin $pin 0 1e15";
|
||||
} elsif ($pin eq $main::biasListPin) {
|
||||
print OF "v_$pin $pin 0 $biasVoltage";
|
||||
} elsif ($pin eq $main::biasSweepPin) {
|
||||
|
|
@ -206,6 +207,7 @@ sub runAcTest {
|
|||
print OF "* AC simulation for $main::simulatorName";
|
||||
&generateCommonNetlistInfo($variant,$temperature);
|
||||
foreach $fPin (@main::Pin) {
|
||||
next if (!$main::needAcStimulusFor{$fPin});
|
||||
foreach $mPin (@main::Pin) {
|
||||
if ($mPin eq $fPin) {
|
||||
$acStim=" ac 1";
|
||||
|
|
@ -213,7 +215,7 @@ sub runAcTest {
|
|||
$acStim="";
|
||||
}
|
||||
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) {
|
||||
print OF "v_${mPin}_$fPin ${mPin}_$fPin 0 $biasVoltage$acStim";
|
||||
} elsif ($mPin eq $main::biasSweepPin) {
|
||||
|
|
@ -226,7 +228,9 @@ sub runAcTest {
|
|||
}
|
||||
print OF ".ac $main::frequencySpec";
|
||||
foreach $mPin (@main::Pin) {
|
||||
next if (!$main::needAcStimulusFor{$mPin});
|
||||
foreach $fPin (@main::Pin) {
|
||||
next if (!$main::needAcStimulusFor{$fPin});
|
||||
print OF ".print ac i(v_${mPin}_$fPin)";
|
||||
}
|
||||
}
|
||||
|
|
@ -349,7 +353,7 @@ sub runDcTest {
|
|||
&generateCommonNetlistInfo($variant,$temperature);
|
||||
foreach $pin (@main::Pin) {
|
||||
if ($main::isFloatingPin{$pin}) {
|
||||
print OF "i_$pin $pin 0 0";
|
||||
print OF "r_$pin $pin 0 1e15";
|
||||
} elsif ($pin eq $main::biasListPin) {
|
||||
print OF "v_$pin $pin 0 $biasVoltage";
|
||||
} elsif ($pin eq $main::biasSweepPin) {
|
||||
|
|
@ -361,7 +365,9 @@ sub runDcTest {
|
|||
print OF "x1 ".join(" ",@main::Pin)." mysub";
|
||||
print OF ".dc v_$main::biasSweepPin $main::biasSweepSpec";
|
||||
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)";
|
||||
} else {
|
||||
print OF ".print dc i(v_$pin)";
|
||||
|
|
@ -381,6 +387,7 @@ sub runDcTest {
|
|||
while (<SIMULATE>) {
|
||||
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+\@.*\[(.+)\]/i) {$inResults=1;$pin="OP($1)";<SIMULATE>;next}
|
||||
@Field=split;
|
||||
if ($#Field != 2) {$inResults=0}
|
||||
next if (!$inResults);
|
||||
|
|
@ -402,7 +409,9 @@ sub runDcTest {
|
|||
}
|
||||
printf OF ("V($main::biasSweepPin)");
|
||||
foreach $pin (@main::Outputs) {
|
||||
if ($main::isFloatingPin{$pin}) {
|
||||
if ($pin =~ /^OP/) {
|
||||
printf OF " $pin";
|
||||
} elsif ($main::isFloatingPin{$pin}) {
|
||||
printf OF (" V($pin)");
|
||||
} else {
|
||||
printf OF (" I($pin)");
|
||||
|
|
@ -434,8 +443,18 @@ sub runDcTest {
|
|||
sub generateCommonNetlistInfo {
|
||||
my($variant,$temperature)=@_;
|
||||
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")}
|
||||
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$/) {
|
||||
die("ERROR: there is no scale or shrink option for ngspice, stopped");
|
||||
}
|
||||
|
|
@ -454,8 +473,25 @@ sub generateCommonNetlistInfo {
|
|||
$fFactor/=$main::mFactor;
|
||||
}
|
||||
}
|
||||
my $opvars="";
|
||||
foreach $pin (@main::Outputs) {
|
||||
if ($pin =~ /^OP\((.*)\)/) {
|
||||
$opvars .= " \@${main::keyLetter}.x1.${main::keyLetter}1[$1]";
|
||||
}
|
||||
}
|
||||
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);
|
||||
foreach $pin (@main::Pin) {
|
||||
|
|
@ -491,7 +527,11 @@ sub generateCommonNetlistInfo {
|
|||
print OF "+ $name=$value";
|
||||
}
|
||||
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/) {
|
||||
print OF ".model mymodel $main::pTypeSelectionArguments";
|
||||
|
|
@ -505,3 +545,4 @@ sub generateCommonNetlistInfo {
|
|||
}
|
||||
|
||||
1;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
|
||||
|
||||
|
||||
INFO: success
|
||||
|
|
|
|||
Loading…
Reference in New Issue