Merge branch 'pre-master-43' into bt_dev

This commit is contained in:
Brian Taylor 2024-06-19 10:31:23 -07:00
commit 4f4a303c3c
51 changed files with 1056 additions and 711 deletions

82
compile_linux_new.sh Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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.*/

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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") &&

View File

@ -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;

View File

@ -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) {

View File

@ -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)) {

View File

@ -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 *);

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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 *

View File

@ -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);
}

View File

@ -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:

View File

@ -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");

View File

@ -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)

View File

@ -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")
};

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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){

View File

@ -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],

View File

@ -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],

View File

@ -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],

View File

@ -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);

View File

@ -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.
}

View File

@ -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);
}
}

View File

@ -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]);

View File

@ -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.
}

View File

@ -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);

View File

@ -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;

View File

@ -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`

View File

@ -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;

View File

@ -1,4 +1,5 @@
INFO: success