diff --git a/.gitignore b/.gitignore index 62177c06b..baf091d01 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ Makefile.in *.lo *.la .libs +*.exe *.orig *~ @@ -90,3 +91,6 @@ src/spicelib/parser/inpptree-parser.h test_cases/diode/__pycache__/* test_cases/diode/test_osdi/* test_cases/diode/test_built_in/* + +build*/ +prof/ \ No newline at end of file diff --git a/NEWS b/NEWS index 0fe64626d..678d22750 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +Ngspice-44.2, January 11th, 2025 +============ +- Bug fix release, no new features + + Ngspice-44, December 29th, 2024 ============ - New features: diff --git a/configure.ac b/configure.ac index 93a9c37ad..f97a93ea6 100644 --- a/configure.ac +++ b/configure.ac @@ -14,7 +14,7 @@ # Ensure a recent version of Autoconf is in use # Older versions may not work with this script and this will report the # problem to the user. -AC_PREREQ([2.59]) +AC_PREREQ([2.70]) m4_define([ngspice_major_version], [44+]) m4_define([ngspice_minor_version], [0]) @@ -967,11 +967,12 @@ fi # A trivial AC_CHECK_FUNCS(sigsetjmp) won't do because sigsetjmp() might be a # macro declared in . (joze) AC_MSG_CHECKING([for sigsetjmp]) -AC_TRY_LINK([#include ],[jmp_buf env; sigsetjmp(env, 1);], - [AC_MSG_RESULT([yes]) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[jmp_buf env; sigsetjmp(env, 1);]])], + [AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_SIGSETJMP], [], [Define if we have sigsetjmp().])], - [AC_MSG_RESULT([no])]) - + [AC_MSG_RESULT([no])]) # Check for the snprintf function: AC_CHECK_FUNCS([snprintf]) @@ -1101,7 +1102,7 @@ AC_PATH_PROG([BISON], [bison]) AX_PROG_BISON_VERSION([2.7], [], [AC_DEFINE([OLD_BISON], [], [Bison is older than 2.7]), AC_MSG_WARN([Bison is older than 2.7])]) -AC_PROG_LEX +AC_PROG_LEX(noyywrap) AM_CONDITIONAL([CMATHTESTS], [test "x$enable_cmathtests" = xyes]) @@ -1183,7 +1184,7 @@ 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 + [AC_PREREQ([2.70])dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS @@ -1286,16 +1287,16 @@ else $with_readline do if test "x$with_tcl" = x || test "x$with_tcl" = xno ; then - AC_MSG_RESULT([Checking for readline:]) - AC_CHECK_HEADERS([$dir/include/readline/readline.h $dir/include/readline/history.h], - [AC_DEFINE([HAVE_GNUREADLINE], [], [Define if we have GNU readline])], - [AC_MSG_ERROR([Couldn't find GNU readline headers.])]) - AC_SEARCH_LIBS([tputs], [ncurses tinfo termcap], - [AC_DEFINE([HAVE_TERMCAP], [], [Define if we have ncurses/terminfo or termcap])], - [AC_MSG_ERROR([Found neither ncurses/terminfo or termcap])]) - AC_CHECK_LIB([readline], [readline], - [LIBS="$LIBS -lreadline"], - [AC_MSG_ERROR([Couldn't find readline libraries.])]) + if test -f $dir/include/readline/readline.h && test -f $dir/include/readline/history.h ; then + + AC_DEFINE([HAVE_GNUREADLINE], [], [Define if we have GNU readline]) + AC_SEARCH_LIBS([tputs], [ncurses tinfo termcap], + [AC_DEFINE([HAVE_TERMCAP], [], [Define if we have ncurses/terminfo or termcap])], + [AC_MSG_ERROR([Found neither ncurses/terminfo or termcap])]) + AC_CHECK_LIB([readline], [readline], + [LIBS="$LIBS -lreadline"], + [AC_MSG_ERROR([Couldn't find readline libraries.])]) + fi fi done fi @@ -1325,11 +1326,6 @@ fi AC_CHECK_HEADERS([ncurses/termcap.h termcap.h]) AC_CHECK_HEADERS([sys/sysctl.h]) - -# --enable-openmp: Use OpenMP on multi-core processors -AC_ARG_ENABLE([openmp], - [AS_HELP_STRING([--enable-openmp], [Use OpenMP parallel processing])]) - # Add OpenMP to ngspice. : ${enable_openmp:=yes} m4_ifdef([AC_OPENMP], [AC_OPENMP]) diff --git a/examples/osdi/psp103/c7552_ann_psp.net b/examples/osdi/psp103/c7552_ann_psp.net index 78c0a5fc7..36e79e42f 100644 --- a/examples/osdi/psp103/c7552_ann_psp.net +++ b/examples/osdi/psp103/c7552_ann_psp.net @@ -7,7 +7,7 @@ .include Modelcards/psp103_nmos-2.mod .include Modelcards/psp103_pmos-2.mod -.OPTIONS GMIN=1e-015 ABSTOL=1e-13 ACCT noopiter +*.OPTIONS GMIN=1e-015 ABSTOL=1e-13 ACCT noopiter *.options vntol=10u **** the input ports: g110_0 g21_0 g18_1 g189_1 g172_2 g70_1 g103_0 g114_0 g92_1 g150_1 g198_1 g125_0 g30_0 g69_1 g45_0 g83_1 g157_0 g182_1 g82_0 g63_1 g42_1 g51_2 g99_1 g62_0 g169_2 g39_0 g128_1 g130_0 g78_1 g195_2 g38_1 g134_1 g191_2 g5_1 g176_1 g117_1 g35_1 g194_1 g41_0 g97_0 g147_1 g14_2 g137_0 g66_2 g26_1 g140_1 g154_1 g185_0 g48_0 g87_0 g106_1 g151_0 g158_0 g15_0 g7_1 g74_1 g122_0 g86_1 g56_1 g165_0 g34_0 g206_6 g57_1 g138_1 g168_0 g17_0 g27_1 g93_0 g199_0 g180_0 g202_0 g173_0 g22_1 g131_0 g192_1 g135_1 g4_1 g77_1 g111_1 g126_1 g52_2 g79_1 g81_1 g156_1 g64_1 g43_0 g183_1 g23_1 g13_2 g53_1 g90_0 g143_0 g153_1 g177_2 g98_0 g19_1 g118_1 g146_1 g102_1 g186_2 g6_4 g1_2 g28_0 g164_1 g33_0 g49_1 g123_0 g205_1 g105_0 g73_1 g170_1 g85_1 g44_0 g67_1 g204_1 g163_1 g159_0 g76_0 g94_0 g139_1 g193_2 g58_1 g100_0 g32_2 g50_0 g132_1 g174_0 g149_1 g12_2 g112_1 g101_0 g119_1 g24_1 g127_1 g201_2 g37_0 g9_2 g207_1 g120_1 g60_1 g108_1 g171_2 g72_2 g46_1 g3_1 g80_1 g59_1 g54_0 g10_1 g152_1 g115_0 g166_2 g95_0 g167_1 g178_2 g187_1 g142_1 g196_0 g113_1 g31_1 g124_1 g190_0 g175_2 g84_0 g133_0 g68_1 g203_2 g75_0 g162_0 g11_1 g144_1 g136_0 g129_1 g91_1 g161_1 g29_1 g155_0 g200_0 g89_1 g141_0 g20_1 g188_2 g104_1 g148_0 g61_1 g65_2 g2_0 g184_3 g109_0 g71_2 g40_0 g47_1 g107_0 g36_1 g121_1 g8_0 g88_0 g16_1 g160_0 g179_0 g96_0 g55_1 g181_3 g25_0 g197_2 g116_0 g145_1 **** @@ -89222,7 +89222,7 @@ c2 z vss 0.834f .options noopiter ; gminsteps=500 srcsteps=0 noinit * simulation command: -*.tran 1ps 1ns uic +.tran 1ps 1ns uic *.print tran V(g7529_1) V(g7509_0) V(g7484_1) V(g7477_1) V(g7460_0) V(g7503_1) V(g7522_0) V(g7485_1) V(g7453_0) V(g7474_0) V(g7500_0) V(g7514_0) V(g7546_1) V(g7549_0) V(g7467_0) V(g7491_0) V(g7456_0) V(g7495_1) V(g7545_0) V(g7473_0) V(g7541_0) V(g7448_1) V(g7525_1) V(g7550_1) V(g165_1) V(g7510_1) V(g7535_1) V(g7534_1) V(g7469_1) V(g7476_0) V(g7517_1) V(g7537_0) V(g7489_1) V(g7521_1) V(g7486_0) V(g7533_1) V(g7449_0) V(g7447_0) V(g7528_0) V(g7513_1) V(g7548_0) V(g7544_1) V(g7552_0) V(g7540_1) V(g7507_0) V(g7481_0) V(g7455_0) V(g7502_1) V(g7446_1) V(g7478_1) V(g7470_0) V(g7526_0) V(g7494_1) V(g7452_1) V(g7463_0) V(g7532_1) V(g7512_0) V(g7527_0) V(g7451_0) V(g7472_0) V(g7498_1) V(g7475_0) V(g7536_0) V(g7488_1) V(g7493_1) V(g7551_1) V(g7482_0) V(g7487_1) V(g7501_1) V(g7520_1) V(g7516_1) V(g7450_1) V(g7508_0) V(g7458_1) V(g7479_1) V(g7506_1) V(g7499_0) V(g7471_0) V(g7465_1) V(g7464_1) V(g7543_1) V(g7524_0) V(g7539_1) V(g7468_1) V(g7459_0) V(g7504_1) V(g7515_1) V(g7492_1) V(g7511_0) V(g7462_1) V(g7530_0) V(g7497_1) V(g7454_1) V(g7519_1) V(g7531_0) V(g7547_0) V(g7483_1) V(g7466_1) V(g7480_1) V(g7523_1) V(g7496_0) V(g7538_0) V(g7490_1) V(g7518_1) V(g7461_0) V(g7542_0) V(g7457_0) V(g7505_1) .control @@ -89231,7 +89231,8 @@ unset ngdebug save V(g7529_1) V(g7509_0) V(g7484_1) V(g7477_1) V(g7460_0) V(g7503_1) V(g7522_0) V(g7485_1) V(g7453_0) V(g7474_0) V(g7500_0) V(g7514_0) V(g7546_1) V(g7549_0) V(g7467_0) V(g7491_0) V(g7456_0) V(g7495_1) V(g7545_0) V(g7473_0) V(g7541_0) V(g7448_1) V(g7525_1) V(g7550_1) V(g165_1) V(g7510_1) V(g7535_1) V(g7534_1) V(g7469_1) V(g7476_0) V(g7517_1) V(g7537_0) V(g7489_1) V(g7521_1) V(g7486_0) V(g7533_1) V(g7449_0) V(g7447_0) V(g7528_0) V(g7513_1) V(g7548_0) V(g7544_1) V(g7552_0) V(g7540_1) V(g7507_0) V(g7481_0) V(g7455_0) V(g7502_1) V(g7446_1) V(g7478_1) V(g7470_0) V(g7526_0) V(g7494_1) V(g7452_1) V(g7463_0) V(g7532_1) V(g7512_0) V(g7527_0) V(g7451_0) V(g7472_0) V(g7498_1) V(g7475_0) V(g7536_0) V(g7488_1) V(g7493_1) V(g7551_1) V(g7482_0) V(g7487_1) V(g7501_1) V(g7520_1) V(g7516_1) V(g7450_1) V(g7508_0) V(g7458_1) V(g7479_1) V(g7506_1) V(g7499_0) V(g7471_0) V(g7465_1) V(g7464_1) V(g7543_1) V(g7524_0) V(g7539_1) V(g7468_1) V(g7459_0) V(g7504_1) V(g7515_1) V(g7492_1) V(g7511_0) V(g7462_1) V(g7530_0) V(g7497_1) V(g7454_1) V(g7519_1) V(g7531_0) V(g7547_0) V(g7483_1) V(g7466_1) V(g7480_1) V(g7523_1) V(g7496_0) V(g7538_0) V(g7490_1) V(g7518_1) V(g7461_0) V(g7542_0) V(g7457_0) V(g7505_1) option noinit nolegend -tran 1ps 15ns 0 10p uic +*tran 1ps 15ns 0 10p uic +run set nolegend plot allv rusage all diff --git a/examples/xspice/icarus_verilog/README.txt b/examples/xspice/icarus_verilog/README.txt index f61f9498b..b4d1f0602 100644 --- a/examples/xspice/icarus_verilog/README.txt +++ b/examples/xspice/icarus_verilog/README.txt @@ -5,6 +5,10 @@ so that its simulation engine is available as a dynamic library. The Verilog source code and included parts of the circuit definitions can be found in the adjacent "verilator" directory. +The circuits and steps below are intended to be used from the directory +containing this file, certainly ouput files from iverilog should be in +the current directory when simulating. + The example circuits are: 555.cir: The probably familiar NE555 oscillator provides a minimal example diff --git a/examples/xspice/verilator/adc.v b/examples/xspice/verilator/adc.v index c063f1794..52905ca24 100644 --- a/examples/xspice/verilator/adc.v +++ b/examples/xspice/verilator/adc.v @@ -3,12 +3,12 @@ `timescale 100ns/100ns module adc(Clk, Comp, Start, Sample, Done, Result); + parameter Bits=6; + input wire Clk, Comp, Start; output reg Sample, Done; output reg [Bits - 1 : 0] Result; - parameter Bits=6; - reg [Bits - 1 : 0] SR; reg Running; diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 4712f221f..47ed8a8fe 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -738,7 +738,11 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) } /* end if (comfile) */ else { /* must be regular deck . . . . */ - /* loop through deck and handle control cards */ + /* Loop through deck and handle control cards. + * Pointer ld refers to the last card processed that has not + * been deleted. + */ + for (dd = deck->nextcard; dd; dd = ld->nextcard) { /* Ignore comment lines, but not lines begining with '*#', but remove them, if they are in a .control ... .endc section */ @@ -781,19 +785,17 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) /* Special control lines outside of .control section? */ - if (prefix("*#", s)) { + if (prefix("*#", s)) s = skip_ws(s + 2); - if (!*s) - continue; - } - - /* assemble all commands starting with pre_ after stripping - * pre_, to be executed before circuit parsing */ if (ciprefix("pre_", s)) { + /* Assemble all commands starting with pre_ after stripping + * pre_, to be executed before circuit parsing. + */ + s = s + 4; pre_controls = wl_cons(copy(s), pre_controls); - } else { + } else if (*s) { /* Assemble all other commands to be executed * after circuit parsing */ @@ -832,10 +834,10 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) ld->nextcard = dd->nextcard; line_free(dd, FALSE); } else { - ld = dd; + ld = dd; // Keep this card } } else { - ld = dd; + ld = dd; // ... and this. } } } /* end for (dd = deck->nextcard . . . . */ diff --git a/src/frontend/inpc_probe.c b/src/frontend/inpc_probe.c index 45bf790b4..f71a72e63 100644 --- a/src/frontend/inpc_probe.c +++ b/src/frontend/inpc_probe.c @@ -1399,8 +1399,11 @@ static int setallvsources(struct card *tmpcard, NGHASHPTR instances, char *instn newline = tprintf("%s %s %s", begstr, newnode, instline); - char* vline = tprintf("vcurr_%s:probe_int_%s:%s_%s %s %s 0", instname, nodename1, nodenumstr, strnode1name, strnode1, newnode); - + char* vline; + if (power) + vline= tprintf("vcurr_%s:probe_int_%s:%s_%s %s %s 0", instname, nodename1, nodenumstr, strnode1name, strnode1, newnode); + else + vline= tprintf("vcurr_%s:%s:%s_%s %s %s 0", instname, nodename1, nodenumstr, strnode1name, strnode1, newnode); tfree(tmpcard->line); tmpcard->line = newline; diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 7f97966bd..fd076ea9f 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -1222,20 +1222,33 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name, /*debug: print into file*/ struct card *t; fprintf(fd, - "**************** uncommented deck " + "\n\n**************** uncommented deck without source file info " "**************\n\n"); /* always print first line */ - fprintf(fd, "%6s %6d %6d %s\n", cc->linesource, cc->linenum_orig, cc->linenum, + fprintf(fd, "%6d %s\n", cc->linenum, cc->line); /* here without out-commented lines */ for (t = cc->nextcard; t; t = t->nextcard) { if (*(t->line) == '*') continue; - fprintf(fd, "%6s %6d %6d %s\n", - t->linesource, t->linenum_orig, t->linenum, t->line); + fprintf(fd, "%6d %s\n", + t->linenum, t->line); } fprintf(fd, - "\n****************** complete deck " + "\n\n**************** uncommented deck " + "**************\n\n"); + /* always print first line */ + 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, "%6s %6d %6d %s\n", + t->linesource, t->linenum_orig, t->linenum, t->line); + } + fprintf(fd, + "\n\n****************** complete deck " "***************\n\n"); /* now completely */ for (t = cc; t; t = t->nextcard) @@ -4113,13 +4126,25 @@ static int inp_fix_subckt_multiplier(struct names *subckt_w_params, for (card = subckt_card->nextcard; card && !ciprefix(".ends", card->line); card = card->nextcard) { char *curr_line = card->line; - /* no 'm' for comment line, B, V, E, H and some others that are not - * using 'm' in their model description */ - if (strchr("*bvehaknopstuwy", curr_line[0])) + /* no 'm' for comment line, V, E, H and some others that are not + using 'm' in their model description. + B source will get 'm' only when it is a current source. */ + if (strchr("*vehaknopstuwy", curr_line[0])) continue; /* no 'm' for model cards */ if (ciprefix(".model", curr_line)) continue; + /* Special treatment for B source: + Skip voltage source */ + if (curr_line[0] == 'b') { + char* tmpstr = curr_line; + /* Skip Bxxx, node1, node2 */ + tmpstr = nexttok(tmpstr); + tmpstr = nexttok(tmpstr); + tmpstr = nexttok(tmpstr); + if (ciprefix("v=", tmpstr)) + continue; + } if (newcompat.hs && card->compmod == 0) { /* if there is already an m=xx in the instance line, multiply it with the new m */ char* mult = strstr(curr_line, " m="); @@ -6687,26 +6712,26 @@ static void inp_compat(struct card *card) /* evaluate m */ char* mstr = eval_mvalue(cut_line, card->line); - if (strstr(curr_line, "c=")) { /* capacitance formulation */ - // Exxx n-aux 0 n2 n1 1 - ckt_array[0] = tprintf("e%s %s_int1 0 %s %s %s", title_tok, - title_tok, node2, node1, mstr); - // Cxxx n-aux 0 1 - ckt_array[1] = tprintf("c%s %s_int1 0 1", title_tok, title_tok); - // Bxxx n1 n2 I = i(Exxx) * equation - ckt_array[2] = tprintf("b%s %s %s i = i(e%s) * (%s) " - "%s reciproctc=1", - title_tok, node1, node2, title_tok, equation, tcrstr); - } else { /* charge formulation */ + if (strstr(curr_line, "q=")) { /* charge formulation */ // Gxxx n1 n2 n-aux 0 1 ckt_array[0] = tprintf("g%s %s %s %s_int1 0 %s", - title_tok, node1, node2, title_tok, mstr); + title_tok, node1, node2, title_tok, mstr); // Lxxx n-aux 0 1 ckt_array[1] = tprintf("l%s %s_int1 0 1", title_tok, title_tok); // Bxxx 0 n-aux I = equation ckt_array[2] = tprintf("b%s 0 %s_int1 i = (%s) " - "%s reciproctc=1", - title_tok, title_tok, equation, tcrstr); + "%s reciproctc=1", + title_tok, title_tok, equation, tcrstr); + } else { /* capacitance formulation */ + // Exxx n-aux 0 n2 n1 1 + ckt_array[0] = tprintf("e%s %s_int1 0 %s %s %s", title_tok, + title_tok, node2, node1, mstr); + // Cxxx n-aux 0 1 + ckt_array[1] = tprintf("c%s %s_int1 0 1", title_tok, title_tok); + // Bxxx n1 n2 I = i(Exxx) * equation + ckt_array[2] = tprintf("b%s %s %s i = i(e%s) * (%s) " + "%s reciproctc=1", + title_tok, node1, node2, title_tok, equation, tcrstr); } tfree(tcrstr); tfree(mstr); diff --git a/src/frontend/inpcompat.c b/src/frontend/inpcompat.c index b92bf1fab..4813c03b4 100644 --- a/src/frontend/inpcompat.c +++ b/src/frontend/inpcompat.c @@ -1373,12 +1373,17 @@ struct card *pspice_compat(struct card *oldcard) for (i = 0; i < 6; i++) { stoks[i] = gettok_node(&cut_line); if (!stoks[i]) { + int ii; 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; + /* null the rest of stoks */ + for (ii = i + 1; ii < 6; ii++) { + stoks[ii] = NULL; + } break; } } diff --git a/src/frontend/parse.c b/src/frontend/parse.c index ebe22d309..4c31a3fbe 100644 --- a/src/frontend/parse.c +++ b/src/frontend/parse.c @@ -117,6 +117,12 @@ struct pnode* ft_getpnames_quotes(wordlist* wl, bool check) tmpstr += 2; /* get the complete zzz of v(zzz) */ char* tpartoken = tmpstr2 = gettok_char(&tmpstr, ')', FALSE, FALSE); + /* Bail out in case of missing closing paren */ + if (!tpartoken) { + fprintf(stderr, "Error: Missing ')' in token %s\n", sz); + fprintf(stderr, " Cannot parse the token!\n"); + return NULL; + } /* check if this is v(zzz) or v(xx,yy) */ char* partoken1 = gettok_char(&tpartoken, ',', FALSE, FALSE); sadd(&ds1, "v("); diff --git a/src/frontend/plotting/x11.c b/src/frontend/plotting/x11.c index ca468cd24..5a18939d9 100644 --- a/src/frontend/plotting/x11.c +++ b/src/frontend/plotting/x11.c @@ -894,7 +894,7 @@ int X11_Update(void) { if (X11_Open) - XSync(display, 0); + XFlush(display); return 0; } diff --git a/src/frontend/postcoms.c b/src/frontend/postcoms.c index 1e6e51d71..a19160ae9 100644 --- a/src/frontend/postcoms.c +++ b/src/frontend/postcoms.c @@ -469,6 +469,7 @@ com_write(wordlist *wl) names = ft_getpnames_quotes(&all, TRUE); if (names == NULL) { + fprintf(stderr, "Error during 'write': no writable vector found.\n"); return; } diff --git a/src/frontend/rawfile.c b/src/frontend/rawfile.c index 389ace51e..4a1359163 100644 --- a/src/frontend/rawfile.c +++ b/src/frontend/rawfile.c @@ -826,9 +826,9 @@ spar_write(char *name, struct plot *pl, double Rbaseval) fprintf(fp, "!Generated by ngspice at %s\n", pl->pl_date); fprintf(fp, "# Hz S RI R %g\n", Rbaseval); fprintf(fp, "!%-*.5s %-*.5s %-*.5s %-*.5s %-*.5s %-*.5s %-*.5s %-*.5s %-*.5s\n", - prec+8, "freq", - prec+8, "ReS11", prec+8, "ImS11", prec+8, "ReS21", prec+8, "ImS21", - prec+8, "ReS12", prec+8, "ImS12", prec+8, "ReS22", prec+8, "ImS22"); + prec+7, "freq", + prec+7, "ReS11", prec+7, "ImS11", prec+7, "ReS21", prec+7, "ImS21", + prec+7, "ReS12", prec+7, "ImS12", prec+7, "ReS22", prec+7, "ImS22"); /* Before we write the stuff out, make sure that the scale is the first * in the list. diff --git a/src/frontend/resource.c b/src/frontend/resource.c index 60cd0d620..4f0478d07 100644 --- a/src/frontend/resource.c +++ b/src/frontend/resource.c @@ -14,6 +14,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include "ngspice/ngspice.h" #include "ngspice/cpdefs.h" #include "ngspice/ftedefs.h" +#include "ngspice/devdefs.h" #include "circuits.h" #include "resource.h" @@ -325,7 +326,22 @@ printres(char *name) /* Now get all the spice resource stuff. */ if (ft_curckt && ft_curckt->ci_ckt) { - + if (name && eq(name, "devtimes")) { + /* Per-device timings */ + for(int i=0; i<=DEVmaxnum; i++) { + if (ft_curckt->ci_ckt->CKTstat->devCounts[i]==0) { + continue; + } + fprintf(cp_out, "%s: t=%f n=%ld t/n=%e\n", + (i==DEVmaxnum ? "\noverhead" : DEVices[i]->DEVpublic.name), + ft_curckt->ci_ckt->CKTstat->devTimes[i], + ft_curckt->ci_ckt->CKTstat->devCounts[i], + ft_curckt->ci_ckt->CKTstat->devTimes[i]/(double)(ft_curckt->ci_ckt->CKTstat->devCounts[i]) + ); + } + } + yy = TRUE; + #ifdef CIDER /* begin cider integration */ if (!name || eq(name, "circuit") || eq(name, "task")) diff --git a/src/include/ngspice/optdefs.h b/src/include/ngspice/optdefs.h index 6e8a5549f..3455a2454 100644 --- a/src/include/ngspice/optdefs.h +++ b/src/include/ngspice/optdefs.h @@ -7,6 +7,8 @@ Modified: 2000 AlansFixes #ifndef ngspice_OPTDEFS_H #define ngspice_OPTDEFS_H +#include + /* structure used to describe the statistics to be collected */ typedef struct sSTATdevList { @@ -46,6 +48,8 @@ typedef struct { double STATacLoadTime; /* time spent in AC device loading */ double STATacSyncTime; /* time spent in transient sync'ing */ STATdevList *STATdevNum; /* PN: Number of instances and models for each device */ + double *devTimes; /* Per-device load times, last entry is overhead */ + size_t *devCounts; /* Per-device load counts, last entry is overhead */ } STATistics; enum { diff --git a/src/osdi/osdiload.c b/src/osdi/osdiload.c index a36673d62..3180d5f31 100644 --- a/src/osdi/osdiload.c +++ b/src/osdi/osdiload.c @@ -25,8 +25,8 @@ #define NUM_SIM_PARAMS 10 char *sim_params[NUM_SIM_PARAMS + 1] = { - "gdev", "gmin", "tnom", - "simulatorVersion", "sourceScaleFactor", "initializeLimiting", + "iniLim", "gmin", "gdev", "tnom", + "simulatorVersion", "sourceScaleFactor", "epsmin", "reltol", "vntol", "abstol", NULL}; char *sim_params_str[1] = {NULL}; @@ -44,7 +44,7 @@ OsdiSimParas get_simparams(const CKTcircuit *ckt) { double sim_param_vals_[NUM_SIM_PARAMS] = { // Verilog-A tnom is in degrees Celsius - gdev, gmin, ckt->CKTnomTemp-CONSTCtoK, simulatorVersion, sourceScaleFactor, initializeLimiting, + initializeLimiting, gmin, gdev, ckt->CKTnomTemp-CONSTCtoK, simulatorVersion, sourceScaleFactor, ckt->CKTepsmin, ckt->CKTreltol, ckt->CKTvoltTol, ckt->CKTabstol }; memcpy(&sim_param_vals, &sim_param_vals_, sizeof(double) * NUM_SIM_PARAMS); OsdiSimParas sim_params_ = {.names = sim_params, diff --git a/src/sharedspice.c b/src/sharedspice.c index 06f806334..a89faaa09 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -1169,6 +1169,9 @@ pvector_info ngGet_Vec_Info(char* vecname) { struct dvec* newvec; + if (ft_ngdebug) + fprintf(stdout, "\nGet vector info: searching for vector '%s'\n", vecname); + if (!is_initialized) { fprintf(stderr, no_init); return NULL; @@ -1186,11 +1189,11 @@ pvector_info ngGet_Vec_Info(char* vecname) newvec = vec_get(vecname); if (newvec == NULL) { - fprintf(stderr, "Error: vector %s not found!\n", vecname); + fprintf(stderr, "Warning: vector %s not or not yet available!\n", vecname); return NULL; } if (newvec->v_numdims > 1) { - fprintf(stderr, "Error: vector %s is multidimensional!\n This is not yet handled\n!", vecname); + fprintf(stderr, "Warning: vector %s is multidimensional!\n This is not yet handled\n!", vecname); return NULL; } diff --git a/src/spicelib/analysis/cktdest.c b/src/spicelib/analysis/cktdest.c index 24ed208d8..8a868a5f4 100644 --- a/src/spicelib/analysis/cktdest.c +++ b/src/spicelib/analysis/cktdest.c @@ -98,6 +98,8 @@ CKTdestroy(CKTcircuit *ckt) #endif FREE(ckt->CKTstat->STATdevNum); + FREE(ckt->CKTstat->devCounts); + FREE(ckt->CKTstat->devTimes); FREE(ckt->CKTstat); FREE(ckt->CKThead); diff --git a/src/spicelib/analysis/cktload.c b/src/spicelib/analysis/cktload.c index b56f7e255..3088efcfa 100644 --- a/src/spicelib/analysis/cktload.c +++ b/src/spicelib/analysis/cktload.c @@ -27,12 +27,13 @@ Modified: 2000 AlansFixes static int ZeroNoncurRow(SMPmatrix *matrix, CKTnode *nodes, int rownum); +// #define PER_DEVICE_STATS int CKTload(CKTcircuit *ckt) { int i; int size; - double startTime; + double startTime, td0; CKTnode *node; int error; #ifdef STEPDEBUG @@ -49,6 +50,13 @@ CKTload(CKTcircuit *ckt) /* gtri - begin - Put resistors to ground at all nodes */ #endif + td0 = SPfrontEnd->IFseconds(); + +#ifdef PER_DEVICE_STATS + ckt->CKTstat->devTimes[DEVmaxnum] += SPfrontEnd->IFseconds() - td0; + ckt->CKTstat->devCounts[DEVmaxnum]++; +#endif + startTime = SPfrontEnd->IFseconds(); size = SMPmatSize(ckt->CKTmatrix); for (i = 0; i <= size; i++) { @@ -61,7 +69,14 @@ CKTload(CKTcircuit *ckt) for (i = 0; i < DEVmaxnum; i++) { if (DEVices[i] && DEVices[i]->DEVload && ckt->CKThead[i]) { +#ifdef PER_DEVICE_STATS + td0 = SPfrontEnd->IFseconds(); +#endif error = DEVices[i]->DEVload (ckt->CKThead[i], ckt); +#ifdef PER_DEVICE_STATS + ckt->CKTstat->devTimes[i] += SPfrontEnd->IFseconds() - td0; + ckt->CKTstat->devCounts[i]++; +#endif if (ckt->CKTnoncon) ckt->CKTtroubleNode = 0; #ifdef STEPDEBUG diff --git a/src/spicelib/analysis/cktpzset.c b/src/spicelib/analysis/cktpzset.c index ae8da2928..e0293b7ed 100644 --- a/src/spicelib/analysis/cktpzset.c +++ b/src/spicelib/analysis/cktpzset.c @@ -91,7 +91,7 @@ CKTpzSetup(CKTcircuit *ckt, int type) #ifdef KLU if (matrix->CKTkluMODE) { - fprintf (stderr, "Using KLU as Direct Linear Solver\n") ; + fprintf (stdout, "Using KLU as Direct Linear Solver\n") ; /* Convert the COO Storage to CSC for KLU and Fill the Binding Table */ SMPconvertCOOtoCSC (matrix) ; @@ -146,7 +146,7 @@ CKTpzSetup(CKTcircuit *ckt, int type) job->PZdrive_nptr = matched->CSC_Complex ; } } else { - fprintf (stderr, "Using SPARSE 1.3 as Direct Linear Solver\n") ; + fprintf (stdout, "Using SPARSE 1.3 as Direct Linear Solver\n") ; } #endif diff --git a/src/spicelib/analysis/cktspdum.c b/src/spicelib/analysis/cktspdum.c index 349647081..dd663aa3b 100644 --- a/src/spicelib/analysis/cktspdum.c +++ b/src/spicelib/analysis/cktspdum.c @@ -29,6 +29,9 @@ extern double Rn; extern cplx Sopt; extern double Fmin; +#ifdef TRACE +cplx cdet(CMat* M); +#endif int CKTmatrixIndex(CKTcircuit* ckt, int source, int dest) { @@ -39,26 +42,42 @@ int CKTspCalcSMatrix(CKTcircuit* ckt) { CMat* Ainv = cinverse(ckt->CKTAmat); if (Ainv == NULL) return (E_NOMEM); - cmultiplydest(ckt->CKTBmat, Ainv, ckt->CKTSmat); + cmultiplydest(ckt->CKTBmat, Ainv, ckt->CKTSmat); // S = B * A-1 freecmat(Ainv); - // Calculate Y matrix - CMat* temp = cmultiply(ckt->CKTSmat, zref); - CMat* temp2 = csum(temp, zref); - CMat* temp3 = cmultiply(temp2, gn); - - CMat* temp4 = cminus(eyem, ckt->CKTSmat); - CMat* temp5 = cinverse(temp4); - - cmultiplydest(temp5, temp3, temp); - cmultiplydest(gninv, temp, ckt->CKTZmat); - cinversedest(ckt->CKTZmat, ckt->CKTYmat); + // Calculate Z matrix 1. Formula + CMat* SxZ0 = cmultiply(ckt->CKTSmat, zref); // S * Z0 + CMat* SxZ0pZ0 = csum(SxZ0, zref); // S * Z0 + Z0 + CMat* SxZ0pZ0xGn = cmultiply(SxZ0pZ0, gn); // (S * Z0 + Z0) * Gn + CMat* EmS = cminus(eyem, ckt->CKTSmat); // E - S + CMat* EmSinv = cinverse(EmS); // (E - S)-1 + CMat* EmSinvxSxZ0pZ0xGn = cmultiply(EmSinv, SxZ0pZ0xGn); // (E - S)-1 * (S * Z0 + Z0) * Gn + cmultiplydest(gninv, EmSinvxSxZ0pZ0xGn, ckt->CKTZmat); // Z = Gn-1 * (E - S)-1 * (S * Z0 + Z0) * Gn +#ifdef TRACE + cplx de = cdet(ckt->CKTZmat); + printf("spCalcSMatrix: CKTZmat det: %g %g\n", de.re, de.im); + showcmat(ckt->CKTZmat); +#endif + // Calculate Y matrix 1. Formula + CMat* EmSxGn = cmultiply(EmS, gn); // (E - S) * Gn + CMat* SxZ0pZ0inv = cinverse(SxZ0pZ0); // (S * Z0 + Z0)-1 + CMat* SxZ0pZ0invxEmSxGn = cmultiply(SxZ0pZ0inv, EmSxGn); // (S * Z0 + Z0)-1 * (E - S) * Gn + cmultiplydest(gninv, SxZ0pZ0invxEmSxGn, ckt->CKTYmat); // Y = Gn-1 * (S * Z0 + Z0)-1 * (E - S) * Gn +#ifdef TRACE + de = cdet(ckt->CKTYmat); + printf("spCalcSMatrix: CKTYmat det: %g %g\n", de.re, de.im); + showcmat(ckt->CKTYmat); +#endif - freecmat(temp); - freecmat(temp2); - freecmat(temp3); - freecmat(temp4); - freecmat(temp5); + freecmat(SxZ0); + freecmat(SxZ0pZ0); + freecmat(SxZ0pZ0xGn); + freecmat(EmS); + freecmat(EmSinv); + freecmat(EmSinvxSxZ0pZ0xGn); + freecmat(EmSxGn); + freecmat(SxZ0pZ0inv); + freecmat(SxZ0pZ0invxEmSxGn); return (OK); } @@ -96,7 +115,6 @@ int CKTspCalcPowerWave(CKTcircuit* ckt) return (OK); } - int CKTspDump(CKTcircuit *ckt, double freq, runDesc *plot, int doNoise) { diff --git a/src/spicelib/analysis/span.c b/src/spicelib/analysis/span.c index fcdabd28a..46c7756fe 100644 --- a/src/spicelib/analysis/span.c +++ b/src/spicelib/analysis/span.c @@ -116,13 +116,23 @@ CKTspnoise(CKTcircuit* ckt, int mode, int operation, Ndata* data, NOISEAN* noise // Equations from Stephen Maas 'Noise' double knorm = 4.0 * CONSTboltz * (ckt->CKTtemp); CMat* tempCy = cscalarmultiply(ckt->CKTNoiseCYmat, 1.0 / knorm); // cmultiply(, YConj); - - +#ifdef TRACE + printf("spnoise: CKTNoiseCYmat / (4*k*T)\n"); + showcmat(tempCy); +#endif if (ckt->CKTportCount == 2) { double Y21mod = cmodsqr(ckt->CKTYmat->d[1][0]); Rn = (tempCy->d[1][1].re / Y21mod); + if (fabs(Rn) < 1e-30) + Rn = 1e-30; + + if ((fabs(tempCy->d[1][1].re) < 1e-30) && (fabs(tempCy->d[1][1].im) < 1e-30)) + { + tempCy->d[1][1].re = 1e-30; + } + cplx Ycor = csubco(ckt->CKTYmat->d[0][0], cmultco( cdivco(tempCy->d[0][1], tempCy->d[1][1]), @@ -869,7 +879,12 @@ SPan(CKTcircuit* ckt, int restart) } //active ports cycle - +#ifdef TRACE + printf("SPan: CKTAmat\n"); + showcmat(ckt->CKTAmat); + printf("SPan: CKTBmat\n"); + showcmat(ckt->CKTBmat); +#endif // Now we can calculate the full S-Matrix CKTspCalcSMatrix(ckt); diff --git a/src/spicelib/devices/asrc/asrcask.c b/src/spicelib/devices/asrc/asrcask.c index 7fd19e152..27aa58171 100644 --- a/src/spicelib/devices/asrc/asrcask.c +++ b/src/spicelib/devices/asrc/asrcask.c @@ -58,7 +58,7 @@ ASRCask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalu if (here->ASRCtype == ASRC_VOLTAGE) value->rValue = ckt->CKTrhsOld[here->ASRCbranch]; else - value->rValue = here->ASRCprev_value; + value->rValue = here->ASRCprev_value * here->ASRCm; return(OK); case ASRC_OUTPUTVOLTAGE: value->rValue = diff --git a/src/spicelib/devices/cktinit.c b/src/spicelib/devices/cktinit.c index ea4ed0c29..ad1cce399 100644 --- a/src/spicelib/devices/cktinit.c +++ b/src/spicelib/devices/cktinit.c @@ -82,6 +82,9 @@ CKTinit(CKTcircuit **ckt) /* new circuit to create */ sckt->CKTstat->STATdevNum = TMALLOC(STATdevList, DEVmaxnum); if(sckt->CKTstat->STATdevNum == NULL) return(E_NOMEM); + /* Per-device timings */ + sckt->CKTstat->devTimes = TMALLOC(double, DEVmaxnum+1); + sckt->CKTstat->devCounts = TMALLOC(size_t, DEVmaxnum+1); sckt->CKTtroubleNode = 0; sckt->CKTtroubleElt = NULL; sckt->CKTtimePoints = NULL; diff --git a/src/spicelib/devices/jfet/jfetnoi.c b/src/spicelib/devices/jfet/jfetnoi.c index c0934c266..3b43275e2 100644 --- a/src/spicelib/devices/jfet/jfetnoi.c +++ b/src/spicelib/devices/jfet/jfetnoi.c @@ -94,13 +94,13 @@ JFETnoise(int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *d NevalSrcInstanceTemp(&noizDens[JFETRSNOIZ],&lnNdens[JFETRSNOIZ], ckt, THERMNOISE, inst->JFETsourcePrimeNode, inst->JFETsourceNode, model->JFETsourceConduct * - inst->JFETarea * inst->JFETm, inst->JFETdtemp); + inst->JFETarea * inst->JFETm, dtemp); if (model->JFETnlev < 3) { NevalSrcInstanceTemp(&noizDens[JFETIDNOIZ],&lnNdens[JFETIDNOIZ], ckt, THERMNOISE, inst->JFETdrainPrimeNode, inst->JFETsourcePrimeNode, - (2.0 / 3.0 * inst->JFETm * fabs(*(ckt->CKTstate0 + inst->JFETgm))), inst->JFETdtemp); + (2.0 / 3.0 * inst->JFETm * fabs(*(ckt->CKTstate0 + inst->JFETgm))), dtemp); } else { vgs = *(ckt->CKTstate0 + inst->JFETvgs); vds = vgs - *(ckt->CKTstate0 + inst->JFETvgd); @@ -114,7 +114,7 @@ JFETnoise(int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *d NevalSrcInstanceTemp(&noizDens[JFETIDNOIZ],&lnNdens[JFETIDNOIZ], ckt, THERMNOISE, inst->JFETdrainPrimeNode, inst->JFETsourcePrimeNode, - (2.0 / 3.0*beta*vgst*(1 + alpha + alpha*alpha) / (1 + alpha) * model->JFETgdsnoi), inst->JFETdtemp); + (2.0 / 3.0*beta*vgst*(1 + alpha + alpha*alpha) / (1 + alpha) * model->JFETgdsnoi), dtemp); } NevalSrc(&noizDens[JFETFLNOIZ], NULL, ckt, diff --git a/src/spicelib/devices/vdmos/vdmosdset.c b/src/spicelib/devices/vdmos/vdmosdset.c index af2378ed5..23f587c79 100644 --- a/src/spicelib/devices/vdmos/vdmosdset.c +++ b/src/spicelib/devices/vdmos/vdmosdset.c @@ -99,7 +99,7 @@ VDMOSdSetup(GENmodel *inModel, CKTcircuit *ckt) /* scale vds with mtr (except with lambda) */ double vdss = vds*mtr*here->VDMOSmode; double t0 = 1 + lambda*vds; - double t1 = 1 + theta*vgs; + double t1 = 1 + theta*vgst; double betap = Beta*t0/t1; double dbetapdvgs = -Beta*theta*t0/(t1*t1); double dbetapdvds = Beta*lambda/t1; diff --git a/src/spicelib/devices/vdmos/vdmosload.c b/src/spicelib/devices/vdmos/vdmosload.c index 644487245..a690e3963 100644 --- a/src/spicelib/devices/vdmos/vdmosload.c +++ b/src/spicelib/devices/vdmos/vdmosload.c @@ -364,7 +364,7 @@ VDMOSload(GENmodel *inModel, CKTcircuit *ckt) /* scale vds with mtr (except with lambda) */ double vdss = vds*mtr*here->VDMOSmode; double t0 = 1 + lambda*vds; - double t1 = 1 + theta*vgs; + double t1 = 1 + theta*vgst; double betap = Beta*t0/t1; double dbetapdvgs = -Beta*theta*t0/(t1*t1); double dbetapdvds = Beta*lambda/t1; diff --git a/src/xspice/verilog/Makefile.am b/src/xspice/verilog/Makefile.am index cd7674934..262d63384 100644 --- a/src/xspice/verilog/Makefile.am +++ b/src/xspice/verilog/Makefile.am @@ -19,11 +19,11 @@ initdata2_DATA = ../../include/ngspice/cosim.h \ pkglib_LTLIBRARIES = ivlng.la ivlngvpi.la ivlng_la_SOURCES = icarus_shim.c icarus_shim.h coroutine_shim.h -ivlng_la_CFLAGS = -I../../../../src/include +ivlng_la_CFLAGS = -I$(top_srcdir)/src/include ivlng_la_LDFLAGS = -module -shared -avoid-version ivlngvpi_la_SOURCES = vpi.c icarus_shim.h vpi_user_dummy.h coroutine.h coroutine_cosim.h -ivlngvpi_la_CFLAGS = -I../../../../src/include +ivlngvpi_la_CFLAGS = -I$(top_srcdir)/src/include ivlngvpi_la_LDFLAGS = -module -shared -avoid-version # On Windows, symbols in DLLs must be fully resolved. diff --git a/visualc/xspice/aux-digital.bat b/visualc/xspice/aux-digital.bat index 26920bb3b..ec56e0b19 100644 --- a/visualc/xspice/aux-digital.bat +++ b/visualc/xspice/aux-digital.bat @@ -11,7 +11,7 @@ CL.EXE /O2 /LD /EHsc /Feivlng.DLL /I%src% /I%inc% %src%\icarus_shim.c ^ rem Make a dummy libvvp.obj, needed for shim.vpi (to be renamed ivlng.vpi). -lib.exe /def:%src%\libvvp.def /machine:X64 +lib.exe /def:%src%\libvvp.def /machine:%2 CL.EXE /O2 /LD /EHsc /Feshim.vpi /I. /I%inc% %src%\vpi.c libvvp.lib ivlng.lib /link /DLL /EXPORT:vlog_startup_routines dir popd diff --git a/visualc/xspice/digital.vcxproj b/visualc/xspice/digital.vcxproj index 1585a1551..5acbad969 100644 --- a/visualc/xspice/digital.vcxproj +++ b/visualc/xspice/digital.vcxproj @@ -88,7 +88,7 @@ Generate Iverilog support, cfunc.c and ifspec.c files - call .\aux-digital.bat $(ProjectName) + call .\aux-digital.bat $(ProjectName) $(PlatformTarget) @@ -400,4 +400,4 @@ - + \ No newline at end of file