diff --git a/INSTALL b/INSTALL index b57448a0f..716c3e55d 100644 --- a/INSTALL +++ b/INSTALL @@ -242,6 +242,10 @@ This file describes the procedures to install ngspice from sources. of readline. See http://www.thrysoee.dk/editline/ + --enable-shortcheck + Enables a 'make check' with strongly reduced runtime. Besides some + regression tests only BSIM3 and BSM4 devices are checked. + 1.5.2 Options Specific to Enable Ngspice as a shared library --with-ngshared diff --git a/Makefile.am b/Makefile.am index 5c9f3e8b8..f0f40c8e3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,7 +11,7 @@ EXTRA_DIST = FAQ autogen.sh Stuarts_Poly_Notes \ examples m4 visualc \ cross-compile.sh cross-compile-shared.sh \ compile_min.sh compile_linux.sh compile_min_shared.sh \ - compile_linux_shared.sh \ + compile_linux_shared.sh compile_cyg_make_short_check_64.sh \ compile_macos_clang.sh compile_macos_gcc.sh \ ngspice.pc.in .gitignore diff --git a/compile_cyg_make_short_check_64.sh b/compile_cyg_make_short_check_64.sh new file mode 100644 index 000000000..c56ef1822 --- /dev/null +++ b/compile_cyg_make_short_check_64.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# ngspice build script for CYGWIN console (X11), release version, 64 bit +# compile_cyg_make_check.sh + +# short version, cd into release64_cyg, then call make, make install, make check + +#Procedure: +# Install CYGWIN, plus bison, flex, auto tools, perl, libiconv, libintl +# Install gcc, activate OpenMP support +# start compiling with +# './compile_cyg_auto.sh' + +# Options: +# --adms and --enable-adms will install extra HICUM, EKV and MEXTRAM models via the +# adms interface. +# Please see http://ngspice.sourceforge.net/admshowto.html for more info on adms. +# CIDER, XSPICE, and OpenMP may be selected at will. +# --disable-debug will give O2 optimization (versus O0 for debug) and removes all debugging info. +# --enable-oldapps will make ngnutmeg ngsconvert ngproc2mod ngmultidec ngmakeidx in addition to ngspice + +if [ ! -d "release64_cyg" ]; then + mkdir release64_cyg + if [ $? -ne 0 ]; then echo "mkdir release64_cyg failed"; exit 1 ; fi +fi + +# If compiling sources from CVS, you may need to uncomment the following two lines: +./autogen.sh +if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi + +# Alternatively, if compiling sources from CVS, and want to add adms created devices, +# you may need to uncomment the following two lines (and don't forget to add adms option +# to the ../configure statement): +#./autogen.sh --adms +#if [ $? -ne 0 ]; then echo "./autogen.sh --adms failed"; exit 1 ; fi + +echo +cd release64_cyg +if [ $? -ne 0 ]; then echo "cd release64_cyg failed"; exit 1 ; fi +echo +# You may add --enable-adms to the following command for adding adms generated devices +../configure --with-x=yes --with-readline=yes --disable-debug --enable-cider --enable-openmp --enable-xspice --enable-shortcheck CFLAGS="-O2 -m64" LDFLAGS="-s -m64" +#../configure --with-x=no --with-readline=yes --disable-debug --enable-xspice --enable-cider --enable-openmp + +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 +echo "installing (see make_install.log)" +make install 2>&1 -j8 | tee make_install.log +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then echo "make install failed"; exit 1 ; fi +echo "run make check" +make check 2>&1 -j8 | tee make_check.log +exitcode=${PIPESTATUS[0]} +if [ $exitcode -ne 0 ]; then + echo "make check failed"; + echo "Did you consider setting 'set ngbehavior=mc' in .spiceinit?"; + exit 1 ; +fi + +echo "success" +exit 0 diff --git a/examples/ddt/ddt-test1.cir b/examples/ddt/ddt-test1.cir new file mode 100644 index 000000000..4a07d3503 --- /dev/null +++ b/examples/ddt/ddt-test1.cir @@ -0,0 +1,14 @@ +dd test + +V1 1 0 dc 0 pulse 0 2 0 1 1 1 4 + +B2 2 0 v = ddt(V(1)) + +.tran 1m 8 + +.control +run +plot v(1) v(2) +.endc + +.end diff --git a/examples/ddt/ddt-test2.cir b/examples/ddt/ddt-test2.cir new file mode 100644 index 000000000..9dd596cdc --- /dev/null +++ b/examples/ddt/ddt-test2.cir @@ -0,0 +1,18 @@ +ddt test 2 with .func + +V1 1 0 dc 0 pulse 0 2 0 1 1 1 4 + +B2 2 0 v = ddt(V(1)) + +B3 3 0 v = border(v(1)) + +.func border(x) if (ddt(x) > 0, 1, 0) + +.tran 1m 8 + +.control +run +plot v(1) v(2) v(3) +.endc + +.end diff --git a/examples/ddt/ddt-test3.cir b/examples/ddt/ddt-test3.cir new file mode 100644 index 000000000..35ead98df --- /dev/null +++ b/examples/ddt/ddt-test3.cir @@ -0,0 +1,17 @@ +ddt test 3 with RC + +V1 1 0 dc 0 pulse 0 2 1u 1n 1n 100u 200u +R1 1 2 1k +C1 2 0 1u + +B2 22 0 v = ddt(V(2))/1000 + +.tran 100n 3m + +.control +run +plot v(2) v(22) +*print v(22) +.endc + +.end diff --git a/examples/various/nmos_pmos_plotting.sp b/examples/various/nmos_pmos_plotting.sp index 3ff611265..6870d7b99 100644 --- a/examples/various/nmos_pmos_plotting.sp +++ b/examples/various/nmos_pmos_plotting.sp @@ -1,14 +1,16 @@ -*****Single NMOS and PMOS Transistor For BSIM3 threshold voltage check (Id-Vgs) (Id-Vds) *** +** Single NMOS and PMOS, BSIM3, (Id-Vgs) (Id-Vds) ** M1 2 1 3 4 n1 W=1u L=0.35u Pd=1.5u Ps=1.5u ad=1.5p as=1.5p -vgs 1 0 3.5 -vds 2 0 0.1 -vss 3 0 0 -vbs 4 0 0 +vgsn 1 0 3.5 +vdsn 102 0 0.1 +Rdn 102 2 1k +vssn 3 0 0 +vbsn 4 0 0 M2 22 11 33 44 p1 W=2.5u L=0.35u Pd=3u Ps=3u ad=2.5p as=2.5p -vgsp 11 0 -3.5 -vdsp 22 0 -0.1 +vgsp 11 0 -3.5 +vdsp 222 0 -0.1 +Rdp 222 22 1k vssp 33 0 0 vbsp 44 0 0 @@ -27,18 +29,18 @@ vbsp 44 0 0 .control * various plot font sizes -dc vgs 0 1.5 0.05 vbs 0 -2.5 -0.5 -plot vss#branch ylabel 'output current' -set wfont_size=18 -dc vds 0 2 0.05 vgs 0 2 0.4 -plot vss#branch ylabel 'output current' -set wfont_size=20 -dc vgsp 0 -1.5 -0.05 vbsp 0 2.5 0.5 +dc vgsn 0 1.5 0.02 vbsn 0 -2.5 -0.5 +plot vssn#branch ylabel 'output current' +set wfont_size=16 +dc vdsn 0 2 0.05 vgsn 0 2 0.4 +plot vssn#branch vs v(2) ylabel 'output current' +set wfont_size=24 +dc vgsp 0 -1.5 -0.02 vbsp 0 2.5 0.5 plot vssp#branch ylabel 'output current' set wfont=Times -set wfont_size=18 +set wfont_size=22 dc vdsp 0 -2 -0.05 vgsp 0 -2 -0.4 -plot vssp#branch ylabel 'output current' +plot vssp#branch vs v(22) ylabel 'output current' .endc .end diff --git a/examples/vbic/vbic99_tran.sp b/examples/vbic/vbic99_tran.sp index 4d24e39cc..1d1355e8d 100644 --- a/examples/vbic/vbic99_tran.sp +++ b/examples/vbic/vbic99_tran.sp @@ -9,6 +9,7 @@ r2 c vp 1k .control op tran 50p 100n +set xbrushwidth=2 plot v(in) v(b) v(c) v(vp) settype temperature v(t) plot v(t) diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 4f9fef46c..e43bd2256 100644 --- a/src/frontend/inpc_probe.c +++ b/src/frontend/inpc_probe.c @@ -1215,23 +1215,25 @@ static char* get_terminal_number(char* element, char* namestr) Called from inp.c*/ void modprobenames(INPtables* tab) { GENinstance* GENinst; - for (GENinst = tab->defVmod->GENinstances; GENinst; GENinst = GENinst->GENnextInstance) { - char* name = GENinst->GENname; - if (prefix("vcurr_", name)) { - /* copy from char no. 6 to (and excluding) second colon */ - char* endname = strchr(name, ':'); - char* endname2 = strchr(endname + 1, ':'); - /* two-terminal device, one colon, copy all from char no. 6 to (and excluding) colon */ - if (!endname2) { - char* newname = copy_substring(name + 6, endname); - memcpy(name, newname, strlen(newname) + 1); - tfree(newname); - } - /* copy from char no. 6 to (and excluding) second colon */ - else { - char* newname = copy_substring(name + 6, endname2); - memcpy(name, newname, strlen(newname) + 1); - tfree(newname); + if (tab->defVmod) { + for (GENinst = tab->defVmod->GENinstances; GENinst; GENinst = GENinst->GENnextInstance) { + char* name = GENinst->GENname; + if (prefix("vcurr_", name)) { + /* copy from char no. 6 to (and excluding) second colon */ + char* endname = strchr(name, ':'); + char* endname2 = strchr(endname + 1, ':'); + /* two-terminal device, one colon, copy all from char no. 6 to (and excluding) colon */ + if (!endname2) { + char* newname = copy_substring(name + 6, endname); + memcpy(name, newname, strlen(newname) + 1); + tfree(newname); + } + /* copy from char no. 6 to (and excluding) second colon */ + else { + char* newname = copy_substring(name + 6, endname2); + memcpy(name, newname, strlen(newname) + 1); + tfree(newname); + } } } } diff --git a/src/frontend/plotting/plotcurv.c b/src/frontend/plotting/plotcurv.c index fc871a241..acd07a53d 100644 --- a/src/frontend/plotting/plotcurv.c +++ b/src/frontend/plotting/plotcurv.c @@ -20,7 +20,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group static void plotinterval(struct dvec *v, double lo, double hi, register double *coeffs, int degree, bool rotated); - +static int get_xdirection(struct dvec *xs, int len, bool mn); /* Plot the vector v, with scale xs. If we are doing curve-fitting, then * do some tricky stuff. @@ -146,7 +146,7 @@ ft_graf(struct dvec *v, struct dvec *xs, bool nostart) Then everything is plotted. */ bool mono = (currentgraph->plottype != PLOT_RETLIN); - int dir = 0; + int dir = get_xdirection(xs, length, mono); for (i = 0; i < length; i++) { dx = isreal(xs) ? xs->v_realdata[i] : realpart(xs->v_compdata[i]); @@ -158,8 +158,6 @@ ft_graf(struct dvec *v, struct dvec *xs, bool nostart) gr_point(v, dx, dy, lx, ly, 0); } else { gr_point(v, dx, dy, lx, ly, i); - if (!dir) - dir = lx > dx ? -1 : lx < dx ? 1 : 0; } lx = dx; ly = dy; @@ -358,3 +356,40 @@ plotinterval(struct dvec *v, double lo, double hi, register double *coeffs, int /* fprintf(cp_err, "plot (%G, %G)\n\r", dx, dy); */ } } + +/* Check if the majority of the x-axis data points are increasing or decreasing. + If more than 10% of the data points deviate from the majority direction, issue a warning, + if 'retraceplot' is not set. +*/ +static int get_xdirection(struct dvec* xs, int len, bool mn) { + int i, dir = 1, inc = 0, dec = 0; + double dx, lx; + static bool msgsent = FALSE; + + lx = isreal(xs) ? xs->v_realdata[0] : + realpart(xs->v_compdata[0]); + + for (i = 1; i < len; i++) { + dx = isreal(xs) ? xs->v_realdata[i] : + realpart(xs->v_compdata[i]); + if (dx > lx) + inc++; + else if (dx < lx) + dec++; + lx = dx; + } + + if (inc < 2 && dec < 2) + fprintf(stderr, "Warning, (new) x axis seems to have one data point only\n"); + + if (mn && !msgsent && (((double)inc / len > 0.1 && inc < dec) || ((double)dec / len > 0.1 && inc > dec))) { + fprintf(stderr, "Warning, more than 10%% of scale vector %s data points are not monotonic.\n", xs->v_name); + fprintf(stderr, " Please consider using the 'retraceplot' flag to the plot command to plot all data.\n"); + msgsent = TRUE; + } + + if (inc < dec) + dir = -1; + + return dir; +} diff --git a/src/include/ngspice/inpptree.h b/src/include/ngspice/inpptree.h index 81686a492..7fc00cae6 100644 --- a/src/include/ngspice/inpptree.h +++ b/src/include/ngspice/inpptree.h @@ -129,6 +129,7 @@ void INPptPrint(char *str, IFparseTree * ptree); #define PTF_CEIL 34 #define PTF_FLOOR 35 #define PTF_NINT 36 +#define PTF_DDT 37 /* The following things are used by the parser -- these are the token types the * lexer returns. diff --git a/src/main.c b/src/main.c index 7923c6201..11dfc27e3 100644 --- a/src/main.c +++ b/src/main.c @@ -365,6 +365,12 @@ com_snsave(wordlist *wl) NG_IGNORE(wl); } +void +com_optran(wordlist *wl) +{ + NG_IGNORE(wl); +} + void SMPprint(SMPmatrix *n1, char *n2) { @@ -428,6 +434,12 @@ EVTswitch_plot(CKTcircuit* ckt, const char* plottypename) return 1; }; +void +EVTsave(wordlist* wl) +{ + NG_IGNORE(wl); +} + int load_opus(const char *name) { diff --git a/src/ngsconvert.c b/src/ngsconvert.c index 79d5563ae..00dca03c7 100644 --- a/src/ngsconvert.c +++ b/src/ngsconvert.c @@ -38,6 +38,7 @@ struct plot *plot_cur = NULL; int cp_maxhistlength = 0; bool cp_no_histsubst = FALSE; struct compat newcompat; +bool cx_degrees = FALSE; char *cp_program = "sconvert"; diff --git a/src/spicelib/parser/inpptree.c b/src/spicelib/parser/inpptree.c index 4d725077b..1f97cf082 100644 --- a/src/spicelib/parser/inpptree.c +++ b/src/spicelib/parser/inpptree.c @@ -171,6 +171,7 @@ static struct func { { "pwr", PTF_PWR, (void(*)(void)) PTpwr}, { "min", PTF_MIN, (void(*)(void)) PTmin}, { "max", PTF_MAX, (void(*)(void)) PTmax}, + { "ddt", PTF_DDT, (void(*)(void)) PTddt}, } ; #define NUM_FUNCS (int)NUMELEMS(funcs) @@ -566,6 +567,11 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum) arg1 = mkcon(0.0); break; + case PTF_DDT: + arg1 = mkcon(0.0); + arg1->data = p->data; + break; + case PTF_MIN: case PTF_MAX: /* min(a,b) --> (avals = TMALLOC(double, 7); + for (ii = 0; ii < 7; ii++) { + data->vals[ii] = 0; + } + p->data = (void*)data; + return (p); +} INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg) { @@ -1140,6 +1160,9 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg) if(p->funcnum == PTF_PWL) p = prepare_PTF_PWL(p); + if (p->funcnum == PTF_DDT) + p = prepare_PTF_DDT(p); + return (p); } @@ -1573,6 +1596,14 @@ void free_tree(INPparseNode *pt) } } + if (pt->type == PT_FUNCTION && (pt->funcnum == PTF_DDT)) { + struct ddtdata { int n; double* vals; } *data = (struct ddtdata*)(pt->data); + if (data) { + txfree(data->vals); + txfree(data); + } + } + txfree(pt); } diff --git a/src/spicelib/parser/inpxx.h b/src/spicelib/parser/inpxx.h index 77e4a2143..81e9355db 100644 --- a/src/spicelib/parser/inpxx.h +++ b/src/spicelib/parser/inpxx.h @@ -78,5 +78,6 @@ double PTle0(double arg); double PTceil(double arg); double PTfloor(double arg); double PTnint(double arg); +double PTddt(double arg, void* data); #endif diff --git a/src/spicelib/parser/ptfuncs.c b/src/spicelib/parser/ptfuncs.c index e0211e74c..55e8ec161 100644 --- a/src/spicelib/parser/ptfuncs.c +++ b/src/spicelib/parser/ptfuncs.c @@ -13,12 +13,10 @@ Author: 1987 Wayne A. Christopher, U. C. Berkeley CAD Group #include "ngspice/fteext.h" #include "ngspice/ifsim.h" #include "ngspice/inpptree.h" +#include "ngspice/cktdefs.h" #include "inpxx.h" #include "ngspice/compatmode.h" -/* XXX These should be in math.h */ - - double PTfudge_factor; #define MODULUS(NUM,LIMIT) ((NUM) - ((int) ((NUM) / (LIMIT))) * (LIMIT)) @@ -414,3 +412,55 @@ PTnint(double arg1) */ return nearbyint(arg1); } + + +/* Calculate the derivative during a transient simulation. + If time == 0, return 0. + If not transient sim, return 0. + The derivative is then (y2-y1)/(t2-t1). + */ +double +PTddt(double arg, void* data) +{ + struct ddtdata { int n; double* vals; } *thing = (struct ddtdata*)data; + double y, time; + + CKTcircuit* ckt = ft_curckt->ci_ckt; + + time = ckt->CKTtime; + + if (time == 0) { + thing->vals[3] = arg; + return 0; + } + + if (!(ckt->CKTmode & MODETRAN)) + return 0; + + if (time > thing->vals[0]) { + thing->vals[4] = thing->vals[2]; + thing->vals[5] = thing->vals[3]; + thing->vals[2] = thing->vals[0]; + thing->vals[3] = thing->vals[1]; + thing->vals[0] = time; + thing->vals[1] = arg; + +/* // Some less effective smoothing option + if (thing->vals[2] > 0) { + thing->vals[6] = 0.5 * ((arg - thing->vals[3]) / (time - thing->vals[2]) + thing->vals[6]); + } +*/ + if (thing->n > 1) { + thing->vals[6] = (thing->vals[1] - thing->vals[3]) / (thing->vals[2] - thing->vals[4]); + } + else { + thing->vals[6] = 0; + thing->vals[3] = arg; + } + thing->n += 1; + } + + y = thing->vals[6]; + + return y; +}