From 7e83526d813d75036718d4978df03db537d0da80 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 5 Dec 2023 16:25:55 +0100 Subject: [PATCH 01/33] Prepare ngspice-42 --- NEWS | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/NEWS b/NEWS index bedb63582..e10b6f63b 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,29 @@ +Ngspice-42, Dec 24th, 2023 +============ +- New features: + + New optional matrix solver KLU (select by 'option klu') + + improve error messages (more verbose, user centric) + + Add variable wr_onspace to allow printing the vetor name with + one space delimiter + + Re-write of the code model PWM generator + + Linked list modtab has been enhanced by a hash table + modtabhash + + Add a code model function cm_cexit(const int exitcode). + + PSP103 model pspnqs103va is now standard + + Add Isotel d_process xspice digital model (enable C models). + + OSDI interface allows small signal noise simulation in Verilog-A + compact models compiled by current OpenVAF. + + Add series resistance 1e-4 Ohms to diode model, if RS is not given + + Generate seed numbers from a microseconds clock, not a seconds clock + + Add functions ngSpice_LockRealloc and ngSpice_UnlockRealloc + + Add new code model function cm_irreversible(). + + Add XSPICE code model d_cosim, a generic adaptor for digital cosimulation. + + New interpreter commands strstr, strslice, fopen, fread and fclose. + + Recognise *ng_script_with_params" + + Add scripts for running the paranoia tests in parallel on Linux with valgrind. + + + Ngspice-41, Aug 13th, 2023 ============ - New features: From a98cfcd8cb787a9c329c138967ba60c945c45929 Mon Sep 17 00:00:00 2001 From: dwarning Date: Tue, 5 Dec 2023 10:48:11 +0100 Subject: [PATCH 02/33] allow compile w/o NEWCONV defined --- src/spicelib/devices/bsim3v1/b3v1ld.c | 5 ++++- src/spicelib/devices/bsimsoi/b4soild.c | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/spicelib/devices/bsim3v1/b3v1ld.c b/src/spicelib/devices/bsim3v1/b3v1ld.c index 61362a3d0..79629f3eb 100644 --- a/src/spicelib/devices/bsim3v1/b3v1ld.c +++ b/src/spicelib/devices/bsim3v1/b3v1ld.c @@ -121,7 +121,10 @@ double Cgg1, Cgb1, Cgd1, Cbg1, Cbb1, Cbd1, Qac0, Qsub0; double dQac0_dVg, dQac0_dVd, dQac0_dVb, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb; double m = 1.0; - +#ifndef NEWCONV +double tol; +#endif + struct bsim3v1SizeDependParam *pParam; int ByPass, Check, ChargeComputationNeeded = 0, error; diff --git a/src/spicelib/devices/bsimsoi/b4soild.c b/src/spicelib/devices/bsimsoi/b4soild.c index 29e4a7caa..f0379fd3c 100644 --- a/src/spicelib/devices/bsimsoi/b4soild.c +++ b/src/spicelib/devices/bsimsoi/b4soild.c @@ -487,6 +487,9 @@ int B4SOILoadOMP(B4SOIinstance *here, CKTcircuit *ckt) { double eggbcp2, eggdep, agb1, bgb1, agb2, bgb2, agbc2n, agbc2p, bgbc2n, bgbc2p, Vtm00; /* v4.3.1 bugfix for mtrlMod=1 -Tanvir */ double m; +#ifndef NEWCONV + double tol; +#endif #ifndef USE_OMP for (; model != NULL; model = B4SOInextModel(model)) From 6ad0a6ad382adf73cb3cad411009b924baafb8a9 Mon Sep 17 00:00:00 2001 From: dwarning Date: Tue, 5 Dec 2023 17:02:51 +0100 Subject: [PATCH 03/33] hisim2: allow compile w/o NEWCONV defined --- src/spicelib/devices/hisim2/hsm2ld.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/spicelib/devices/hisim2/hsm2ld.c b/src/spicelib/devices/hisim2/hsm2ld.c index cf694177a..d72a8459b 100644 --- a/src/spicelib/devices/hisim2/hsm2ld.c +++ b/src/spicelib/devices/hisim2/hsm2ld.c @@ -853,7 +853,6 @@ tm0 = gtodsecld() ; isConv = 0; } } - } #endif /* NEWCONV */ } } From c69018fe8276a96c7352bd162d10a4a9192e4a02 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 8 Dec 2023 10:32:15 +0100 Subject: [PATCH 04/33] =?UTF-8?q?Enable=20measurements=20with=20=3F-sweep?= =?UTF-8?q?=20(v,=20i,=20temp,=20or=20res).=20Improve=20error=20messages.?= =?UTF-8?q?=20Prevent=20crash=20is=20comp=C3=BCdata=20is=20not=20available?= =?UTF-8?q?.=20Add=20to=20examples=20for=20measure=20failures.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/measure/buggy-meas-tran.sp | 2 + src/frontend/com_measure2.c | 63 +++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/examples/measure/buggy-meas-tran.sp b/examples/measure/buggy-meas-tran.sp index a2a3906af..36277ebe8 100644 --- a/examples/measure/buggy-meas-tran.sp +++ b/examples/measure/buggy-meas-tran.sp @@ -91,5 +91,7 @@ meas tran tdiff TRIG v(1) VAL=0.5 RISE=1 TARG VAL=0.5 RISE=2 meas tran tdiff TRIG v(1) VAL=0.5 RISE=1 TARG v(1) RISE=2 meas tran tdiff TRIG v(1) VAL= RISE=1 TARG v(1) VAL=0.5 RISE=2 meas tran tdiff TRIG v(1) VAL=0.5 RISE= TARG v(1) VAL=0.5 RISE=2 +meas sp tmax MAX v(2) from=2m to=3m +meas dc ymax MAX v(2) from=2m to=3m .endc .end diff --git a/src/frontend/com_measure2.c b/src/frontend/com_measure2.c index 7033abbec..29dd6e9e6 100644 --- a/src/frontend/com_measure2.c +++ b/src/frontend/com_measure2.c @@ -432,7 +432,10 @@ com_measure_when( value = get_value(meas, d, i); //d->v_compdata[i].cx_real; else value = d->v_realdata[i]; - scaleValue = dScale->v_compdata[i].cx_real; + if (dScale->v_compdata) + scaleValue = dScale->v_compdata[i].cx_real; + else + scaleValue = dScale->v_realdata[i]; } else if (sp_check) { if (d->v_compdata) value = get_value(meas, d, i); //d->v_compdata[i].cx_real; @@ -768,20 +771,38 @@ measure_minMaxAvg( if (ac_check || sp_check) { dScale = vec_get("frequency"); + if (dScale == NULL) { + fprintf(cp_err, "Error: meas %s ...\n", meas->m_analysis); + fprintf(cp_err, " no such scale vector as frequency.\n"); + return MEASUREMENT_FAILURE; + } } else if (tran_check) { dScale = vec_get("time"); + if (dScale == NULL) { + fprintf(cp_err, "Error: meas %s ...\n", meas->m_analysis); + fprintf(cp_err, " no such scale vector as time.\n"); + return MEASUREMENT_FAILURE; + } } else if (dc_check) { dScale = vec_get("v-sweep"); + if (!dScale) { + dScale = vec_get("i-sweep"); + if (!dScale) { + dScale = vec_get("temp-sweep"); + if (!dScale) + dScale = vec_get("res-sweep"); + } + } + if (dScale == NULL) { + fprintf(cp_err, "Error: meas %s ...\n", meas->m_analysis); + fprintf(cp_err, " no such scale vector as v-sweep, i-sweep, temp-sweep, or res-sweep.\n"); + return MEASUREMENT_FAILURE; + } } else { /* error */ fprintf(cp_err, "Error: no such analysis type as %s.\n", meas->m_analysis); return MEASUREMENT_FAILURE; } - if (dScale == NULL) { - fprintf(cp_err, "Error: no such vector as time, frequency or v-sweep.\n"); - return MEASUREMENT_FAILURE; - } - if (dScale->v_realdata == NULL && dScale->v_compdata == NULL) { fprintf(cp_err, "Error: scale vector time, frequency or v-sweep has no data.\n"); return MEASUREMENT_FAILURE; @@ -949,22 +970,40 @@ measure_rms_integral( if (ac_check || sp_check) { xScale = vec_get("frequency"); + if (xScale == NULL) { + fprintf(cp_err, "Error: meas %s ...\n", meas->m_analysis); + fprintf(cp_err, " no such scale vector as frequency.\n"); + return MEASUREMENT_FAILURE; + } } else if (tran_check) { xScale = vec_get("time"); + if (xScale == NULL) { + fprintf(cp_err, "Error: meas %s ...\n", meas->m_analysis); + fprintf(cp_err, " no such scale vector as time.\n"); + return MEASUREMENT_FAILURE; + } } else if (dc_check) { xScale = vec_get("v-sweep"); + if (!xScale) { + xScale = vec_get("i-sweep"); + if (!xScale) { + xScale = vec_get("temp-sweep"); + if (!xScale) + xScale = vec_get("res-sweep"); + } + } + if (xScale == NULL) { + fprintf(cp_err, "Error: meas %s ...\n", meas->m_analysis); + fprintf(cp_err, " no such scale vector as v-sweep, i-sweep, temp-sweep, or res-sweep.\n"); + return MEASUREMENT_FAILURE; + } } else { /* error */ fprintf(cp_err, "Error: no such analysis type as %s.\n", meas->m_analysis); return MEASUREMENT_FAILURE; } - if (xScale == NULL) { - fprintf(cp_err, "Error: no such vector as time, frequency or v-sweep.\n"); - return MEASUREMENT_FAILURE; - } - if (xScale->v_realdata == NULL && xScale->v_compdata == NULL) { - fprintf(cp_err, "Error: scale vector time, frequency or v-sweep has no data.\n"); + fprintf(cp_err, "Error: scale vector time, frequency or ?-sweep has no data.\n"); return MEASUREMENT_FAILURE; } From 732c12c93f15cf957721ea4967f885850e9ef42c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 8 Dec 2023 10:40:33 +0100 Subject: [PATCH 05/33] Remove another potential crash if buggy user input --- src/frontend/com_measure2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/frontend/com_measure2.c b/src/frontend/com_measure2.c index 29dd6e9e6..b36a510ce 100644 --- a/src/frontend/com_measure2.c +++ b/src/frontend/com_measure2.c @@ -691,7 +691,10 @@ measure_at( value = d->v_realdata[i]; // fprintf(cp_err, "Warning: 'meas ac' input vector is real!\n"); } - svalue = dScale->v_compdata[i].cx_real; + if (dScale->v_compdata) + svalue = dScale->v_compdata[i].cx_real; + else + svalue = dScale->v_realdata[i]; //prevent crash in case if buggy input } else if (sp_check) { if (d->v_compdata) value = get_value(meas, d, i); //d->v_compdata[i].cx_real; @@ -804,7 +807,7 @@ measure_minMaxAvg( } if (dScale->v_realdata == NULL && dScale->v_compdata == NULL) { - fprintf(cp_err, "Error: scale vector time, frequency or v-sweep has no data.\n"); + fprintf(cp_err, "Error: scale vector time, frequency or ?-sweep has no data.\n"); return MEASUREMENT_FAILURE; } From b76c3203f7e69036af86906f422fb3d95908f7d3 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 9 Dec 2023 15:47:00 +0100 Subject: [PATCH 06/33] prepare ngspice-42 --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index e10b6f63b..50f5f5101 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,8 @@ Ngspice-42, Dec 24th, 2023 + Add XSPICE code model d_cosim, a generic adaptor for digital cosimulation. + New interpreter commands strstr, strslice, fopen, fread and fclose. + Recognise *ng_script_with_params" + + Add a predifined variable 'skywaterpdk' to speed up circuit + loading and parsing. + Add scripts for running the paranoia tests in parallel on Linux with valgrind. From 6459fed460abb1c8c31a4a45c3b33a752b993211 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 10 Dec 2023 15:15:44 +0100 Subject: [PATCH 07/33] Don't prescribe a different resistance value if the user has given one > 0. --- src/spicelib/devices/res/resmpar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spicelib/devices/res/resmpar.c b/src/spicelib/devices/res/resmpar.c index 8166b6bff..35df4c7ce 100644 --- a/src/spicelib/devices/res/resmpar.c +++ b/src/spicelib/devices/res/resmpar.c @@ -79,7 +79,7 @@ RESmParam(int param, IFvalue *value, GENmodel *inModel) model->RESefGiven = TRUE; break; case RES_MOD_R: - if ( value->rValue > 1e-03 ) { + if ( value->rValue > 0 ) { model->RESres = value->rValue; model->RESresGiven = TRUE; } From 7cd4f003ff661964f842da323fbd4d89eb1b5f2b Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 10 Dec 2023 15:16:05 +0100 Subject: [PATCH 08/33] typo --- src/spicelib/devices/res/restemp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spicelib/devices/res/restemp.c b/src/spicelib/devices/res/restemp.c index 993a7795f..0d0a0b61f 100644 --- a/src/spicelib/devices/res/restemp.c +++ b/src/spicelib/devices/res/restemp.c @@ -69,7 +69,7 @@ RESupdate_conduct(RESinstance *here, bool spill_warnings) } else { if (spill_warnings) SPfrontEnd->IFerrorf (ERR_WARNING, - "%s: resistance to low, set to 1 mOhm", here->RESname); + "%s: resistance too low or not given, set to 1 mOhm", here->RESname); here->RESresist = 1e-03; } } From 45850c07dcd71e63749e2ee39a33f37e962e6ba6 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 10 Dec 2023 15:18:17 +0100 Subject: [PATCH 09/33] Don't silently accept wrong user input (missing nodes, values). Check for at leat 4 tokens (name, n1, n2, val/model/...). If the instance has not been set up correctly, bail out, prevent crash. --- src/spicelib/parser/inp2c.c | 29 ++++++++++++++++++++++++----- src/spicelib/parser/inp2l.c | 34 +++++++++++++++++++++++++--------- src/spicelib/parser/inp2r.c | 24 +++++++++++++++++++++--- 3 files changed, 70 insertions(+), 17 deletions(-) diff --git a/src/spicelib/parser/inp2c.c b/src/spicelib/parser/inp2c.c index 7ef15766f..3fc4da4ed 100644 --- a/src/spicelib/parser/inp2c.c +++ b/src/spicelib/parser/inp2c.c @@ -32,7 +32,7 @@ void INP2C(CKTcircuit *ckt, INPtables * tab, struct card *current) int error1; /* secondary error code temporary */ INPmodel *thismodel; /* pointer to model structure describing our model */ GENmodel *mdfast = NULL; /* pointer to the actual model */ - GENinstance *fast; /* pointer to the actual instance */ + GENinstance *fast = NULL;/* pointer to the actual instance */ IFvalue ptemp; /* a value structure to package resistance into */ int waslead; /* flag to indicate that funny unlabeled number was found */ double leadval; /* actual value of unlabeled number */ @@ -49,11 +49,25 @@ void INP2C(CKTcircuit *ckt, INPtables * tab, struct card *current) } } line = current->line; - INPgetNetTok(&line, &name, 1); + + INPgetNetTok(&line, &name, 1); /* Cname */ + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid capacitor instance line, ignored!\n\n", current->line); + return; + } + INPgetNetTok(&line, &nname1, 1); /* */ + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid capacitor instance line, ignored!\n\n", current->line); + return; + } + INPgetNetTok(&line, &nname2, 1); /* */ + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid capacitor instance line, ignored!\n\n", current->line); + return; + } + INPinsert(&name, tab); - INPgetNetTok(&line, &nname1, 1); INPtermInsert(ckt, &nname1, tab, &node1); - INPgetNetTok(&line, &nname2, 1); INPtermInsert(ckt, &nname2, tab, &node2); /* enable reading values like 4u7 */ @@ -109,7 +123,12 @@ void INP2C(CKTcircuit *ckt, INPtables * tab, struct card *current) #endif } } - + + if (!fast || !fast->GENmodPtr) { + fprintf(stderr, "\nWarning: Instance for capacitor '%s' could not be set up properly, ignored!\n\n", current->line); + return; + } + if (error1 == 0) { /* Looks like a number */ ptemp.rValue = val; GCA(INPpName, ("capacitance", &ptemp, ckt, type, fast)); diff --git a/src/spicelib/parser/inp2l.c b/src/spicelib/parser/inp2l.c index da66650f0..adfd885b3 100644 --- a/src/spicelib/parser/inp2l.c +++ b/src/spicelib/parser/inp2l.c @@ -32,7 +32,7 @@ void INP2L(CKTcircuit *ckt, INPtables * tab, struct card *current) int error1; /* secondary error code temporary */ INPmodel *thismodel; /* pointer to model structure describing our model */ GENmodel *mdfast = NULL; /* pointer to the actual model */ - GENinstance *fast; /* pointer to the actual instance */ + GENinstance *fast = NULL;/* pointer to the actual instance */ IFvalue ptemp; /* a value structure to package inductance into */ int waslead; /* flag to indicate that funny unlabeled number was found */ double leadval; /* actual value of unlabeled number */ @@ -49,14 +49,25 @@ void INP2L(CKTcircuit *ckt, INPtables * tab, struct card *current) } } line = current->line; - INPgetNetTok(&line, &name, 1); - INPinsert(&name, tab); - INPgetNetTok(&line, &nname1, 1); - INPtermInsert(ckt, &nname1, tab, &node1); - INPgetNetTok(&line, &nname2, 1); - INPtermInsert(ckt, &nname2, tab, &node2); + INPgetNetTok(&line, &name, 1); /* Lname */ + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid inductor instance line, ignored!\n\n", current->line); + return; + } + INPgetNetTok(&line, &nname1, 1); /* */ + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid inductor instance line, ignored!\n\n", current->line); + return; + } + INPgetNetTok(&line, &nname2, 1); /* */ + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid inductor instance line, ignored!\n\n", current->line); + return; + } -// val = INPevaluate(&line, &error1, 1); + INPinsert(&name, tab); + INPtermInsert(ckt, &nname1, tab, &node1); + INPtermInsert(ckt, &nname2, tab, &node2); /* enable reading values like 4u7 */ if (newcompat.lt) @@ -110,7 +121,12 @@ void INP2L(CKTcircuit *ckt, INPtables * tab, struct card *current) #endif } } - + + if (!fast || !fast->GENmodPtr) { + fprintf(stderr, "\nWarning: Instance for inductor '%s' could not be set up properly, ignored!\n\n", current->line); + return; + } + if (error1 == 0) { /* Looks like a number */ ptemp.rValue = val; GCA(INPpName, ("inductance", &ptemp, ckt, type, fast)); diff --git a/src/spicelib/parser/inp2r.c b/src/spicelib/parser/inp2r.c index 587f940a5..5241b3035 100644 --- a/src/spicelib/parser/inp2r.c +++ b/src/spicelib/parser/inp2r.c @@ -39,7 +39,7 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, struct card *current) int error1; /* secondary error code temporary */ INPmodel *thismodel; /* pointer to model structure describing our model */ GENmodel *mdfast = NULL; /* pointer to the actual model */ - GENinstance *fast; /* pointer to the actual instance */ + GENinstance *fast = NULL; /* pointer to the actual instance */ IFvalue ptemp; /* a value structure to package resistance into */ int waslead; /* flag to indicate that funny unlabeled number was found */ double leadval; /* actual value of unlabeled number */ @@ -59,10 +59,23 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, struct card *current) } line = current->line; INPgetNetTok(&line, &name, 1); /* Rname */ - INPinsert(&name, tab); + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid resistor instance line, ignored!\n\n", current->line); + return; + } INPgetNetTok(&line, &nname1, 1); /* */ - INPtermInsert(ckt, &nname1, tab, &node1); + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid resistor instance line, ignored!\n\n", current->line); + return; + } INPgetNetTok(&line, &nname2, 1); /* */ + if (*line == '\0') { + fprintf(stderr, "\nWarning: '%s' is not a valid resistor instance line, ignored!\n\n", current->line); + return; + } + + INPinsert(&name, tab); + INPtermInsert(ckt, &nname1, tab, &node1); INPtermInsert(ckt, &nname2, tab, &node2); /* enable reading values like 4k7 */ @@ -197,6 +210,11 @@ void INP2R(CKTcircuit *ckt, INPtables * tab, struct card *current) } } + if (!fast || !fast->GENmodPtr) { + fprintf(stderr, "\nWarning: Instance for resistor '%s' could not be set up properly, ignored!\n\n", current->line); + return; + } + if (error1 == 0) { /* got a resistance above */ ptemp.rValue = val; GCA(INPpName, ("resistance", &ptemp, ckt, type, fast)); From 7f30055f2243467d8bb4e1e93005a8c121be610b Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 10 Dec 2023 18:01:07 +0100 Subject: [PATCH 10/33] Prevent crash if port number is less than 1. --- src/spicelib/devices/vsrc/vsrctemp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spicelib/devices/vsrc/vsrctemp.c b/src/spicelib/devices/vsrc/vsrctemp.c index 413e356e9..359e0bdc6 100644 --- a/src/spicelib/devices/vsrc/vsrctemp.c +++ b/src/spicelib/devices/vsrc/vsrctemp.c @@ -76,7 +76,7 @@ VSRCtemp(GENmodel *inModel, CKTcircuit *ckt) if (!here->VSRCportZ0Given) here->VSRCportZ0 = 50.0; - here->VSRCisPort = here->VSRCportZ0 > 0.0; + here->VSRCisPort = here->VSRCportZ0 > 0.0 && here->VSRCportNum > 0; } else here->VSRCisPort = FALSE; From 2e56f3a0633d0551fcdf89945dbb949476db931f Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 12 Dec 2023 17:02:19 +0100 Subject: [PATCH 11/33] Add short description of the new interface functions ngSpice_LockRealloc(void) ad ngSpice_UnlockRealloc(void) --- src/include/ngspice/sharedspice.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index d25c2c798..1082d0c24 100644 --- a/src/include/ngspice/sharedspice.h +++ b/src/include/ngspice/sharedspice.h @@ -82,6 +82,13 @@ char** ngSpice_AllVecs(char*); returns to the caller a pointer to an array of vector names in the plot named by the string in the argument. +** +int ngSpice_LockRealloc(void) +int ngSpice_UnlockRealloc(void) +Locking and unlocking the realloc of output vectors during simulation. May be set +during reading output vectors in the primaty thread, while the simulation in the +background thread is moving on. + ** Additional basics: No memory mallocing and freeing across the interface: From ce8f6c5017440f6f42d53ecd7681e6ba96ed192d Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 12 Dec 2023 17:08:58 +0100 Subject: [PATCH 12/33] prepare ngspice-42 --- configure.ac | 6 +++--- src/include/ngspice/sharedspice.h | 2 +- visualc/src/include/ngspice/config.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 35739eb81..0cda21fc6 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,7 @@ # problem to the user. AC_PREREQ([2.59]) -m4_define([ngspice_major_version], [41+]) +m4_define([ngspice_major_version], [42]) m4_define([ngspice_minor_version], [0]) m4_define([ngspice_version], [ngspice_major_version]) @@ -117,8 +117,8 @@ LT_INIT([shared static]) # --> Set 'LT_NGSPICE_AGE' to 0. LT_NGSPICE_CURRENT=0 -LT_NGSPICE_REVISION=8 -LT_NGSPICE_AGE=1 +LT_NGSPICE_REVISION=9 +LT_NGSPICE_AGE=2 LIBNGSPICE_SO_VERSION=$LT_NGSPICE_CURRENT.$LT_NGSPICE_REVISION.$LT_NGSPICE_AGE # Announce the libtool version diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index 1082d0c24..6719533f5 100644 --- a/src/include/ngspice/sharedspice.h +++ b/src/include/ngspice/sharedspice.h @@ -104,7 +104,7 @@ are of type bool if sharedspice.h is used externally. */ #ifndef NGSPICE_PACKAGE_VERSION -#define NGSPICE_PACKAGE_VERSION "41+" +#define NGSPICE_PACKAGE_VERSION "42" #endif /* we have NG_BOOL instead of BOOL */ #ifndef HAS_NG_BOOL diff --git a/visualc/src/include/ngspice/config.h b/visualc/src/include/ngspice/config.h index 65874de17..43e4aa7ad 100644 --- a/visualc/src/include/ngspice/config.h +++ b/visualc/src/include/ngspice/config.h @@ -15,7 +15,7 @@ #define PACKAGE "ngspice" /* Version number of package */ -#define VERSION "41+" +#define VERSION "42" /* Define the directory for executables */ #define NGSPICEBINDIR "../bin" From 9a50f8b7495bacd28794301f9cc9631c1ec0d1ed Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 12 Dec 2023 17:24:23 +0100 Subject: [PATCH 13/33] typo --- src/include/ngspice/sharedspice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index 6719533f5..dc44da26c 100644 --- a/src/include/ngspice/sharedspice.h +++ b/src/include/ngspice/sharedspice.h @@ -86,7 +86,7 @@ named by the string in the argument. int ngSpice_LockRealloc(void) int ngSpice_UnlockRealloc(void) Locking and unlocking the realloc of output vectors during simulation. May be set -during reading output vectors in the primaty thread, while the simulation in the +during reading output vectors in the primary thread, while the simulation in the background thread is moving on. ** From c46866d688d3fd7ec01cd079d937fa157cfb486d Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 18 Dec 2023 20:13:06 +0100 Subject: [PATCH 14/33] Fix some typos. Thanks to Brian for checking. --- NEWS | 6 +++--- examples/paranoia/README.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 50f5f5101..c2059e94c 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,7 @@ Ngspice-42, Dec 24th, 2023 - New features: + New optional matrix solver KLU (select by 'option klu') + improve error messages (more verbose, user centric) - + Add variable wr_onspace to allow printing the vetor name with + + Add variable wr_onspace to allow printing the vector name with one space delimiter + Re-write of the code model PWM generator + Linked list modtab has been enhanced by a hash table @@ -19,8 +19,8 @@ Ngspice-42, Dec 24th, 2023 + Add new code model function cm_irreversible(). + Add XSPICE code model d_cosim, a generic adaptor for digital cosimulation. + New interpreter commands strstr, strslice, fopen, fread and fclose. - + Recognise *ng_script_with_params" - + Add a predifined variable 'skywaterpdk' to speed up circuit + + Recognise *ng_script_with_params + + Add a predefined variable 'skywaterpdk' to speed up circuit loading and parsing. + Add scripts for running the paranoia tests in parallel on Linux with valgrind. diff --git a/examples/paranoia/README.txt b/examples/paranoia/README.txt index 515b742ef..de7825868 100644 --- a/examples/paranoia/README.txt +++ b/examples/paranoia/README.txt @@ -4,7 +4,7 @@ To run the paranoia test suite in parallel on Linux with valgrind: 1. Download the paranoia tests (paranoia.7z) from the ngspice Quality web page. 2. p7zip -d paranoia.7z -Rename the the unzipped directory to a name without spaces which would +Rename the unzipped directory to a name without spaces which would otherwise confuse valgrind. 3. cd into the renamed unzipped directory. From ffcf3b24d9f348ef45cde1c15cc79ccc72c823bc Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Mon, 18 Dec 2023 11:37:39 +0000 Subject: [PATCH 15/33] Improve efficiency and irreversible CM support in EVTcall_hybrids() by halting calls to code models as soon as the timestep is chenged. This should have been included in 508fad0f55dcda3545305d6582c367ef7dca06ac. --- src/xspice/evt/evtcall_hybrids.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/xspice/evt/evtcall_hybrids.c b/src/xspice/evt/evtcall_hybrids.c index a45f2506e..7b1988e87 100644 --- a/src/xspice/evt/evtcall_hybrids.c +++ b/src/xspice/evt/evtcall_hybrids.c @@ -45,6 +45,7 @@ NON-STANDARD FEATURES #include "ngspice/ngspice.h" #include "ngspice/cktdefs.h" +#include "ngspice/mif.h" #include "ngspice/evt.h" #include "ngspice/evtproto.h" @@ -74,6 +75,12 @@ void EVTcall_hybrids( /* Call EVTload for all hybrids */ - for(i = 0; i < num_hybrids; i++) + for(i = 0; i < num_hybrids; i++) { EVTload_with_event(ckt, hybrids[i], MIF_STEP_PENDING); + if (g_mif_info.breakpoint.current < ckt->CKTtime) { + /* An XSPICE instance rejected the time-step. */ + + break; + } + } } From 81351555dabcc7a9212646415d1faafccbd698a7 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Mon, 18 Dec 2023 11:42:12 +0000 Subject: [PATCH 16/33] Mention the vlnggen script and Verilog-controlled XSPICE models. --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index c2059e94c..4def20b82 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,8 @@ Ngspice-42, Dec 24th, 2023 + Add functions ngSpice_LockRealloc and ngSpice_UnlockRealloc + Add new code model function cm_irreversible(). + Add XSPICE code model d_cosim, a generic adaptor for digital cosimulation. + + Script 'vlnggen' may be used with Verilator and d_cosim to create + XSPICE code models controlled by HDL code. + New interpreter commands strstr, strslice, fopen, fread and fclose. + Recognise *ng_script_with_params + Add a predefined variable 'skywaterpdk' to speed up circuit From af31904f99ebdc1a67328db46e1faa91ab5f0633 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Mon, 18 Dec 2023 18:14:28 +0000 Subject: [PATCH 17/33] The previous fix for Bug #467 - ".OPTION INTERP has accuracy issue" (359e3d46) updated variable timeold inside a loop so that all interpolations after the first caused division by zero. That caused the xspice/delta-sigma example to fail. Set the variable once at the end of the function. --- src/frontend/outitf.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index b4d6955ac..29d3fb54f 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -1469,21 +1469,18 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) if (run->refIndex != -1) { /* Save first time step */ if (refValue->rValue == run->circuit->CKTinitTime) { - timeold = refValue->rValue; fileStartPoint(run->fp, run->binary, run->pointCount); fileAddRealValue(run->fp, run->binary, run->circuit->CKTinitTime); interpolatenow = nodata = FALSE; } /* Save last time step */ else if (refValue->rValue == run->circuit->CKTfinalTime) { - timeold = refValue->rValue; fileStartPoint(run->fp, run->binary, run->pointCount); fileAddRealValue(run->fp, run->binary, run->circuit->CKTfinalTime); interpolatenow = nodata = FALSE; } /* Save exact point */ else if (refValue->rValue == timestep) { - timeold = refValue->rValue; fileStartPoint(run->fp, run->binary, run->pointCount); fileAddRealValue(run->fp, run->binary, timestep); timestep += run->circuit->CKTstep; @@ -1501,7 +1498,6 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) else { /* Do not save this step */ run->pointCount--; - timeold = refValue->rValue; nodata = TRUE; interpolatenow = FALSE; } @@ -1542,7 +1538,6 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; fileAddRealValue(run->fp, run->binary, newval); valueold[i] = valuenew[i]; - timeold = refValue->rValue; } else if (nodata) /* Just keep the transient output value corresponding to timeold, @@ -1574,7 +1569,6 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; fileAddRealValue(run->fp, run->binary, newval); valueold[i] = valuenew[i]; - timeold = refValue->rValue; } else if (nodata) /* Just keep the transient output value corresponding to timeold, @@ -1587,7 +1581,7 @@ InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) #endif } - + timeold = refValue->rValue; fileEndPoint(run->fp, run->binary); /* Check that the write to disk completed successfully, otherwise abort */ @@ -1634,19 +1628,16 @@ InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) /* Save first time step */ if (refValue->rValue == run->circuit->CKTinitTime) { - timeold = refValue->rValue; plotAddRealValue(&run->data[iscale], refValue->rValue); interpolatenow = nodata = FALSE; } /* Save last time step */ else if (refValue->rValue == run->circuit->CKTfinalTime) { - timeold = refValue->rValue; plotAddRealValue(&run->data[iscale], run->circuit->CKTfinalTime); interpolatenow = nodata = FALSE; } /* Save exact point */ else if (refValue->rValue == timestep) { - timeold = refValue->rValue; plotAddRealValue(&run->data[iscale], timestep); timestep += run->circuit->CKTstep; interpolatenow = nodata = FALSE; @@ -1662,7 +1653,6 @@ InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) else { /* Do not save this step */ run->pointCount--; - timeold = refValue->rValue; nodata = TRUE; interpolatenow = FALSE; } @@ -1707,7 +1697,6 @@ InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; plotAddRealValue(&run->data[i], newval); valueold[i] = valuenew[i]; - timeold = refValue->rValue; } else if (nodata) /* Just keep the transient output value corresponding to timeold, @@ -1730,7 +1719,6 @@ InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i]; plotAddRealValue(&run->data[i], newval); valueold[i] = valuenew[i]; - timeold = refValue->rValue; } else if (nodata) /* Just keep the transient output value corresponding to timeold, @@ -1744,7 +1732,7 @@ InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr) #endif } - + timeold = refValue->rValue; gr_iplot(run->runPlot); if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE) From 8f52a67786c613eeb1b9d5e3699b80d61368496a Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Mon, 18 Dec 2023 09:46:44 -0800 Subject: [PATCH 18/33] Fix set but not used warning. --- src/frontend/udevices.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index f4433e70a..69675b66d 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -2341,7 +2341,7 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) char **inarr, **outarr, *itype, *iname, *enable, *tmodel; char *xspice = NULL, *connector = NULL; BOOL vector = FALSE, tristate_gate = FALSE, simple_gate = FALSE; - BOOL tristate_array = FALSE, simple_array = FALSE; + BOOL tristate_array = FALSE; BOOL add_tristate = FALSE; char *modelnm = NULL, *startvec = NULL, *endvec = NULL; char *instance_name = NULL; @@ -2519,7 +2519,6 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) char *primary_model = NULL, *s1 = NULL, *s2 = NULL, *s3 = NULL; DS_CREATE(input_dstr, 128); /* arrays of gates */ - simple_array = is_gate_array(itype); tristate_array = is_tristate_array(itype); inv3a_to_buf3a = (!withinv && eq(itype, "inv3a")); From c53b32ffa8d893f64f5dce1f44e08ce9795c251f Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 19 Dec 2023 15:30:44 +0100 Subject: [PATCH 19/33] Plug a potential memory leak --- src/spicelib/analysis/cktsetup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/spicelib/analysis/cktsetup.c b/src/spicelib/analysis/cktsetup.c index 6e22c3b0a..d858fca55 100644 --- a/src/spicelib/analysis/cktsetup.c +++ b/src/spicelib/analysis/cktsetup.c @@ -127,6 +127,7 @@ CKTsetup(CKTcircuit *ckt) /* Allocate space for the matrix diagonal data */ if(num_nodes > 0) { + FREE(ckt->enh->rshunt_data.diag); ckt->enh->rshunt_data.diag = TMALLOC(double *, num_nodes); } From d1abc8f6c7c57c9a524ddff1df9d141606c027aa Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 22 Dec 2023 13:11:21 +0100 Subject: [PATCH 20/33] typo --- src/xspice/icm/dlmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xspice/icm/dlmain.c b/src/xspice/icm/dlmain.c index 6c93d4c4b..b86839e34 100644 --- a/src/xspice/icm/dlmain.c +++ b/src/xspice/icm/dlmain.c @@ -467,7 +467,7 @@ FILE *fopen_with_path(const char *path, const char *mode) { FILE *fp; - if((path[0] != '/') && (path[1] != ':')) { /* path absolue (probably) */ + if((path[0] != '/') && (path[1] != ':')) { /* path is (probably) not absolute */ // const char *x = getenv("ngspice_vpath"); const char *x = cm_get_path(); if (x) { From 5154fd3fd7bc155a908e4fbc49247f4e12c96777 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 22 Dec 2023 17:14:22 +0100 Subject: [PATCH 21/33] Allways export function ngCM_Input_Path, independently from XSPICE Update comment --- src/sharedspice.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sharedspice.c b/src/sharedspice.c index 523f1c2bf..54bdc5b90 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -1102,13 +1102,15 @@ int ngSpice_Command(char* comexec) return 1; } -#ifdef XSPICE -/* Set the input path for files loaded by code models. +/* Set the input path for files loaded by code models + like d_state, file_source, d_source. + Useful when netlist is sent by ngSpice_Circ and therefore + Infile_Path cannot be retrieved automatically. If NULL is sent, return the current Infile_Path. */ IMPEXP char *ngCM_Input_Path(const char* path) { - /* delete existing command memory */ + /* override existing path */ if (path) { txfree(Infile_Path); Infile_Path = copy(path); @@ -1116,7 +1118,6 @@ char *ngCM_Input_Path(const char* path) fprintf(stdout, "Note: Codel model file loading path is %s\n", Infile_Path); return Infile_Path; } -#endif /* Return information about a vector to the caller */ IMPEXP @@ -1357,6 +1358,7 @@ int ngSpice_UnlockRealloc(void) return 1; } + /* add the preliminary breakpoints to the list. called from dctran.c */ int From 4671b588b67750e1c9fcf6cbc2083e2eefdbf86d Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 22 Dec 2023 17:14:43 +0100 Subject: [PATCH 22/33] Update comment --- src/include/ngspice/sharedspice.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index dc44da26c..3f37f6be2 100644 --- a/src/include/ngspice/sharedspice.h +++ b/src/include/ngspice/sharedspice.h @@ -47,7 +47,10 @@ not modify them). ***************** If XSPICE is enabled ************************************* ** ngCM_Input_Path(const char*) -sets the input path for files loaded by code models. +Set the input path for files loaded by code models +like d_state, file_source, d_source. +Useful when netlist is sent by ngSpice_Circ and therefore +Infile_Path cannot be retrieved automatically. If NULL is sent, return the current Infile_Path. ** From 37944bd7c4cf05e54e1522d109c8f0b848595c2e Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 22 Dec 2023 17:18:43 +0100 Subject: [PATCH 23/33] Preliminary fix to bug 650 Don't omit replacement, when independent nested subcircuit has been checked. FIXME: Better use the cards level parameter. --- src/frontend/inpcom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 327311b71..026d43661 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -8165,6 +8165,9 @@ static void inp_meas_current(struct card *deck) else if (ciprefix(".ends", curr_line)) { subs--; subc_start = subc_prev; + /* FIXME: just a hack, needs proper levelling */ + if (subs == 0) + subc_start = NULL; } else continue; From 03905433bb25ac702172afd77b4291b8c83f6f0e Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 22 Dec 2023 17:21:55 +0100 Subject: [PATCH 24/33] If compatmode hs is set, don't run an extra iteration with differing mode settings, but go directly to CKTop(). If other or none compat modes, keep existing behavior, as for example CIDER example may otherwise slow down significantly. This is to keep dc sim in accordance with other simulators. --- src/spicelib/analysis/dctrcurv.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/spicelib/analysis/dctrcurv.c b/src/spicelib/analysis/dctrcurv.c index 2f53734c9..3ef5986d6 100644 --- a/src/spicelib/analysis/dctrcurv.c +++ b/src/spicelib/analysis/dctrcurv.c @@ -14,6 +14,7 @@ Modified: 1999 Paolo Nenzi #include "ngspice/const.h" #include "ngspice/sperror.h" #include "ngspice/fteext.h" +#include "ngspice/compatmode.h" #ifdef XSPICE #include "ngspice/evt.h" @@ -297,8 +298,8 @@ DCtrCurv(CKTcircuit *ckt, int restart) if (ckt->evt->counts.num_insts == 0) { /* If no event-driven instances, do what SPICE normally does */ #endif - converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter); - if (converged != 0) { + + if (newcompat.hs) { converged = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, @@ -306,6 +307,17 @@ DCtrCurv(CKTcircuit *ckt, int restart) if (converged != 0) return(converged); } + else { + converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter); + if (converged != 0) { + converged = CKTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, + ckt->CKTdcMaxIter); + if (converged != 0) + return(converged); + } + } #ifdef XSPICE } else { From db5e5b08eba2ea1e3950d71fb9324228fcf25418 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 22 Dec 2023 18:16:26 +0100 Subject: [PATCH 25/33] Don't switch display to "op", if called from a dc simulation. --- src/spicelib/analysis/cktop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index 1b52c296b..06983ff6e 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -30,7 +30,8 @@ CKTop (CKTcircuit *ckt, long int firstmode, long int continuemode, int converged; #ifdef HAS_PROGREP - if (!ckt->CKTnoOpIter || ckt->CKTnumGminSteps >= 1 || ckt->CKTnumSrcSteps >= 1) + /* If this is called from dc simulation, don't set "op" */ + if (ckt->CKTcurJob->JOBtype != 2 && (!ckt->CKTnoOpIter || ckt->CKTnumGminSteps >= 1 || ckt->CKTnumSrcSteps >= 1)) SetAnalyse("op", 0); #endif From f307586d89a8509f22263e4b6607fa0d9f41c60a Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Dec 2023 10:42:07 +0100 Subject: [PATCH 26/33] Formatting --- src/spicelib/analysis/cktsens.c | 1304 ++++++++++++++++--------------- 1 file changed, 656 insertions(+), 648 deletions(-) diff --git a/src/spicelib/analysis/cktsens.c b/src/spicelib/analysis/cktsens.c index 555462857..34e33e0d7 100644 --- a/src/spicelib/analysis/cktsens.c +++ b/src/spicelib/analysis/cktsens.c @@ -24,14 +24,14 @@ char SF2[] = "dc"; char SF3[] = "bf"; #endif -char *Sfilter = NULL; +char* Sfilter = NULL; double Sens_Delta = 0.000001; double Sens_Abs_Delta = 0.000001; -static int sens_setp(sgen *sg, CKTcircuit *ckt, IFvalue *val); -static int sens_load(sgen *sg, CKTcircuit *ckt, int is_dc); -static int sens_temp(sgen *sg, CKTcircuit *ckt); -static int count_steps(int type, double low, double high, int steps, double *stepsize); +static int sens_setp(sgen* sg, CKTcircuit* ckt, IFvalue* val); +static int sens_load(sgen* sg, CKTcircuit* ckt, int is_dc); +static int sens_temp(sgen* sg, CKTcircuit* ckt); +static int count_steps(int type, double low, double high, int steps, double* stepsize); static double inc_freq(double freq, int type, double step_size); #define save_context(thing, place) { \ @@ -40,8 +40,8 @@ static double inc_freq(double freq, int type, double step_size); #define release_context(thing, place) \ if(place) { \ - thing = place; \ - place = NULL; \ + thing = place; \ + place = NULL; \ } @@ -60,372 +60,376 @@ static double inc_freq(double freq, int type, double step_size); */ static int error; -int sens_sens(CKTcircuit *ckt, int restart) +int sens_sens(CKTcircuit* ckt, int restart) { -/* -#ifdef KLU - if (ckt->CKTkluMODE) - { - fprintf (stderr, "\n\n\tThe Sensitivity Analysis is not supported in KLU environment\n\tPlease add '.options sparse' in you netlist\n\n\n") ; - return OK ; - } else { -#endif -*/ - SENS_AN *job = (SENS_AN *) ckt->CKTcurJob; + /* + #ifdef KLU + if (ckt->CKTkluMODE) + { + fprintf (stderr, "\n\n\tThe Sensitivity Analysis is not supported in KLU environment\n\tPlease add '.options sparse' in you netlist\n\n\n") ; + return OK ; + } else { + #endif + */ + SENS_AN* job = (SENS_AN*)ckt->CKTcurJob; - static int size; - static double *delta_I, *delta_iI, - *delta_I_delta_Y, *delta_iI_delta_Y; - sgen *sg; - static double freq; - static int nfreqs; - static int i; - static SMPmatrix *delta_Y = NULL, *Y; - static double step_size; - double *E, *iE; - IFvalue value, nvalue; - double *output_values; - IFcomplex *output_cvalues; - double delta_var; - int (*fn) (SMPmatrix *, GENmodel *, CKTcircuit *, int *); - static int is_dc; - int k, j, n; - int num_vars, branch_eq=0; - runDesc *sen_data = NULL; - char namebuf[513]; - IFuid *output_names, freq_name; - int bypass; - int type; - double *saved_rhs = NULL, - *saved_irhs = NULL; - SMPmatrix *saved_matrix = NULL; + static int size; + static double* delta_I, * delta_iI, + * delta_I_delta_Y, * delta_iI_delta_Y; + sgen* sg; + static double freq; + static int nfreqs; + static int i; + static SMPmatrix* delta_Y = NULL, * Y; + static double step_size; + double* E, * iE; + IFvalue value, nvalue; + double* output_values; + IFcomplex* output_cvalues; + double delta_var; + int (*fn) (SMPmatrix*, GENmodel*, CKTcircuit*, int*); + static int is_dc; + int k, j, n; + int num_vars, branch_eq = 0; + runDesc* sen_data = NULL; + char namebuf[513]; + IFuid* output_names, freq_name; + int bypass; + int type; + double* saved_rhs = NULL, + * saved_irhs = NULL; + SMPmatrix* saved_matrix = NULL; #ifdef KLU - int size_CSC ; + int size_CSC; #endif #ifndef notdef #ifdef notdef - for (sg = sgen_init(ckt, 0); sg; sgen_next(&sg)) { - if (sg->is_instparam) - printf("%s:%s:%s -> param %s\n", - DEVices[sg->dev]->DEVpublic.name, - sg->model->GENmodName, - sg->instance->GENname, - sg->ptable[sg->param].keyword); - else - printf("%s:%s:%s -> mparam %s\n", - DEVices[sg->dev]->DEVpublic.name, - sg->model->GENmodName, - sg->instance->GENname, - sg->ptable[sg->param].keyword); - } + for (sg = sgen_init(ckt, 0); sg; sgen_next(&sg)) { + if (sg->is_instparam) + printf("%s:%s:%s -> param %s\n", + DEVices[sg->dev]->DEVpublic.name, + sg->model->GENmodName, + sg->instance->GENname, + sg->ptable[sg->param].keyword); + else + printf("%s:%s:%s -> mparam %s\n", + DEVices[sg->dev]->DEVpublic.name, + sg->model->GENmodName, + sg->instance->GENname, + sg->ptable[sg->param].keyword); + } #endif #ifdef ASDEBUG - DEBUG(1) - printf(">>> restart : %d\n", restart); + DEBUG(1) + printf(">>> restart : %d\n", restart); #endif - /* get to work */ + /* get to work */ - restart = 1; - if (restart) { + restart = 1; + if (restart) { - freq = 0.0; - is_dc = (job->step_type == SENS_DC); - nfreqs = count_steps(job->step_type, job->start_freq, - job->stop_freq, job->n_freq_steps, - &step_size); + freq = 0.0; + is_dc = (job->step_type == SENS_DC); + nfreqs = count_steps(job->step_type, job->start_freq, + job->stop_freq, job->n_freq_steps, + &step_size); - if (!is_dc) - freq = job->start_freq; + if (!is_dc) + freq = job->start_freq; - error = CKTop(ckt, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, - ckt->CKTdcMaxIter); + error = CKTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter); #ifdef notdef - ckt->CKTmode = (ckt->CKTmode & MODEUIC) - | MODEDCOP | MODEINITSMSIG; + ckt->CKTmode = (ckt->CKTmode & MODEUIC) + | MODEDCOP | MODEINITSMSIG; #endif - if (error) - return error; + if (error) + return error; - size = SMPmatSize(ckt->CKTmatrix); + size = SMPmatSize(ckt->CKTmatrix); - /* Create the perturbation matrix */ - delta_Y = TMALLOC(SMPmatrix, 1); + /* Create the perturbation matrix */ + delta_Y = TMALLOC(SMPmatrix, 1); - error = SMPnewMatrix(delta_Y, size); - if (error) - return error; + error = SMPnewMatrix(delta_Y, size); + if (error) + return error; #ifdef KLU - delta_Y->SMPkluMatrix->KLUmatrixDiag = NULL ; + delta_Y->SMPkluMatrix->KLUmatrixDiag = NULL; #endif -// SMPprint(delta_Y, NULL); - size += 1; + // SMPprint(delta_Y, NULL); + size += 1; - /* Create an extra rhs */ - delta_I = TMALLOC(double, size); - delta_iI = TMALLOC(double, size); + /* Create an extra rhs */ + delta_I = TMALLOC(double, size); + delta_iI = TMALLOC(double, size); - delta_I_delta_Y = TMALLOC(double, size); - delta_iI_delta_Y = TMALLOC(double, size); + delta_I_delta_Y = TMALLOC(double, size); + delta_iI_delta_Y = TMALLOC(double, size); + num_vars = 0; + for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) { + num_vars += 1; + } - num_vars = 0; - for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) { - num_vars += 1; - } + if (!num_vars) + return OK; /* XXXX Should be E_ something */ - if (!num_vars) - return OK; /* XXXX Should be E_ something */ + k = 0; + output_names = TMALLOC(IFuid, num_vars); + for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) { + if (!sg->is_instparam) { + sprintf(namebuf, "%s:%s", + sg->instance->GENname, + sg->ptable[sg->param].keyword); + } + else if ((sg->ptable[sg->param].dataType + & IF_PRINCIPAL) && sg->is_principle == 1) + { + sprintf(namebuf, "%s", sg->instance->GENname); + } + else { + sprintf(namebuf, "%s_%s", + sg->instance->GENname, + sg->ptable[sg->param].keyword); + } - k = 0; - output_names = TMALLOC(IFuid, num_vars); - for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) { - if (!sg->is_instparam) { - sprintf(namebuf, "%s:%s", - sg->instance->GENname, - sg->ptable[sg->param].keyword); - } else if ((sg->ptable[sg->param].dataType - & IF_PRINCIPAL) && sg->is_principle == 1) - { - sprintf(namebuf, "%s", sg->instance->GENname); - } else { - sprintf(namebuf, "%s_%s", - sg->instance->GENname, - sg->ptable[sg->param].keyword); - } + SPfrontEnd->IFnewUid(ckt, + output_names + k, NULL, + namebuf, UID_OTHER, NULL); + k += 1; + } - SPfrontEnd->IFnewUid (ckt, - output_names + k, NULL, - namebuf, UID_OTHER, NULL); - k += 1; - } + if (is_dc) { + type = IF_REAL; + freq_name = NULL; + } + else { + type = IF_COMPLEX; + SPfrontEnd->IFnewUid(ckt, + &freq_name, NULL, + "frequency", UID_OTHER, NULL); + } - if (is_dc) { - type = IF_REAL; - freq_name = NULL; - } else { - type = IF_COMPLEX; - SPfrontEnd->IFnewUid (ckt, - &freq_name, NULL, - "frequency", UID_OTHER, NULL); - } + error = SPfrontEnd->OUTpBeginPlot( + ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + freq_name, IF_REAL, + num_vars, output_names, type, &sen_data); + if (error) + return error; - error = SPfrontEnd->OUTpBeginPlot ( - ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - freq_name, IF_REAL, - num_vars, output_names, type, &sen_data); - if (error) - return error; + FREE(output_names); + if (is_dc) { + output_values = TMALLOC(double, num_vars); + output_cvalues = NULL; + } + else { + output_values = NULL; + output_cvalues = TMALLOC(IFcomplex, num_vars); + if (job->step_type != SENS_LINEAR) + SPfrontEnd->OUTattributes(sen_data, NULL, OUT_SCALE_LOG, NULL); - FREE(output_names); - if (is_dc) { - output_values = TMALLOC(double, num_vars); - output_cvalues = NULL; - } else { - output_values = NULL; - output_cvalues = TMALLOC(IFcomplex, num_vars); - if (job->step_type != SENS_LINEAR) - SPfrontEnd->OUTattributes (sen_data, NULL, OUT_SCALE_LOG, NULL); + } - } - - } else { - /*XXX Restore saved state */ - output_values = NULL; - output_cvalues = NULL; - fprintf(stderr, "ERROR: restore is not implemented for cktsens\n"); - controlled_exit(1); - } + } + else { + /*XXX Restore saved state */ + output_values = NULL; + output_cvalues = NULL; + fprintf(stderr, "ERROR: restore is not implemented for cktsens\n"); + controlled_exit(1); + } #ifdef ASDEBUG - DEBUG(1) - printf("start: %f, num: %d, dc: %d\n", freq, nfreqs, is_dc); + DEBUG(1) + printf("start: %f, num: %d, dc: %d\n", freq, nfreqs, is_dc); #endif - if (!job->output_volt) - branch_eq = CKTfndBranch(ckt, job->output_src); - bypass = ckt->CKTbypass; - ckt->CKTbypass = 0; + if (!job->output_volt) + branch_eq = CKTfndBranch(ckt, job->output_src); + bypass = ckt->CKTbypass; + ckt->CKTbypass = 0; - /* CKTop solves into CKTrhs and CKTmatrix->SPmatrix, - * CKTirhs is hopefully zero (fresh allocated ?) */ + /* CKTop solves into CKTrhs and CKTmatrix->SPmatrix, + * CKTirhs is hopefully zero (fresh allocated ?) */ - E = ckt->CKTrhs; - iE = ckt->CKTirhs; - Y = ckt->CKTmatrix; + E = ckt->CKTrhs; + iE = ckt->CKTirhs; + Y = ckt->CKTmatrix; #ifdef KLU - if (ckt->CKTkluMODE) { + if (ckt->CKTkluMODE) { - /* Convert the KLU Circuit Matrix to Complex */ - for (i = 0 ; i < (int)Y->SMPkluMatrix->KLUmatrixNZ ; i++) { - Y->SMPkluMatrix->KLUmatrixAxComplex [2 * i] = Y->SMPkluMatrix->KLUmatrixAx [i] ; - Y->SMPkluMatrix->KLUmatrixAxComplex [2 * i + 1] = 0.0 ; - } + /* Convert the KLU Circuit Matrix to Complex */ + for (i = 0; i < (int)Y->SMPkluMatrix->KLUmatrixNZ; i++) { + Y->SMPkluMatrix->KLUmatrixAxComplex[2 * i] = Y->SMPkluMatrix->KLUmatrixAx[i]; + Y->SMPkluMatrix->KLUmatrixAxComplex[2 * i + 1] = 0.0; + } - Y->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ; + Y->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex; - SMPcReorder (Y, ckt->CKTpivotAbsTol, ckt->CKTpivotRelTol, &size_CSC) ; // size_CSC is just a placeholder here - } + SMPcReorder(Y, ckt->CKTpivotAbsTol, ckt->CKTpivotRelTol, &size_CSC); // size_CSC is just a placeholder here + } #endif #ifdef ASDEBUG - DEBUG(1) { - printf("Operating point:\n"); - for (i = 0; i < size; i++) - printf(" E [%d] = %20.15g\n", i, E[i]); - } + DEBUG(1) { + printf("Operating point:\n"); + for (i = 0; i < size; i++) + printf(" E [%d] = %20.15g\n", i, E[i]); + } #endif #ifdef notdef - for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) { - save_states[j] = ckt->CKTstates[j]; - ckt->CKTstates[j] = NULL; - } + for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) { + save_states[j] = ckt->CKTstates[j]; + ckt->CKTstates[j] = NULL; + } #endif - for (i = 0; i < nfreqs; i++) { - /* XXX handle restart */ + for (i = 0; i < nfreqs; i++) { + /* XXX handle restart */ - n = 0; + n = 0; - if (SPfrontEnd->IFpauseTest()) { - /* XXX Save State */ - return E_PAUSE; - } + if (SPfrontEnd->IFpauseTest()) { + /* XXX Save State */ + return E_PAUSE; + } - for (j = 0; j < size; j++) { - delta_I[j] = 0.0; - delta_iI[j] = 0.0; - } + for (j = 0; j < size; j++) { + delta_I[j] = 0.0; + delta_iI[j] = 0.0; + } - if (freq != 0.0) { + if (freq != 0.0) { - /* This generates Y in LU form */ - ckt->CKTomega = 2.0 * M_PI * freq; + /* This generates Y in LU form */ + ckt->CKTomega = 2.0 * M_PI * freq; - /* Yes, all this has to be re-done */ - /* XXX Free old states */ - error = CKTunsetup(ckt); - if (error) - return error; + /* Yes, all this has to be re-done */ + /* XXX Free old states */ + error = CKTunsetup(ckt); + if (error) + return error; - /* XXX ckt->CKTmatrix->SPmatrix = Y; */ + /* XXX ckt->CKTmatrix->SPmatrix = Y; */ - error = CKTsetup(ckt); - if (error) - return error; + error = CKTsetup(ckt); + if (error) + return error; #ifdef notdef - for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) { - /* XXX Free new states */ - ckt->CKTstates[j] = save_states[j]; - } + for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) { + /* XXX Free new states */ + ckt->CKTstates[j] = save_states[j]; + } #endif - error = CKTtemp(ckt); - if (error) - return error; - error = CKTload(ckt); /* INITSMSIGS */ - if (error) - return error; + error = CKTtemp(ckt); + if (error) + return error; + error = CKTload(ckt); /* INITSMSIGS */ + if (error) + return error; #ifdef KLU - if (ckt->CKTmatrix->CKTkluMODE) - { - /* ReOrder */ - error = SMPpreOrder (ckt->CKTmatrix) ; + if (ckt->CKTmatrix->CKTkluMODE) + { + /* ReOrder */ + error = SMPpreOrder(ckt->CKTmatrix); - /* Conversion from Real Circuit Matrix to Complex Circuit Matrix */ - if (!ckt->CKTmatrix->SMPkluMatrix->KLUmatrixIsComplex) - { - for (i = 0 ; i < DEVmaxnum ; i++) - if (DEVices [i] && DEVices [i]->DEVbindCSCComplex && ckt->CKThead [i]) - DEVices [i]->DEVbindCSCComplex (ckt->CKThead [i], ckt) ; + /* Conversion from Real Circuit Matrix to Complex Circuit Matrix */ + if (!ckt->CKTmatrix->SMPkluMatrix->KLUmatrixIsComplex) + { + for (i = 0; i < DEVmaxnum; i++) + if (DEVices[i] && DEVices[i]->DEVbindCSCComplex && ckt->CKThead[i]) + DEVices[i]->DEVbindCSCComplex(ckt->CKThead[i], ckt); - ckt->CKTmatrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ; - } - } + ckt->CKTmatrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex; + } + } #endif - error = NIacIter(ckt); - if (error) - return error; + error = NIacIter(ckt); + if (error) + return error; #ifdef notdef - /* XXX Why? */ - for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) { - ckt->CKTstates[j] = NULL; - } + /* XXX Why? */ + for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) { + ckt->CKTstates[j] = NULL; + } #endif - /* NIacIter solves into CKTrhsOld, CKTirhsOld and CKTmatrix->SPmatrix */ - E = ckt->CKTrhsOld; - iE = ckt->CKTirhsOld; - Y = ckt->CKTmatrix; - } + /* NIacIter solves into CKTrhsOld, CKTirhsOld and CKTmatrix->SPmatrix */ + E = ckt->CKTrhsOld; + iE = ckt->CKTirhsOld; + Y = ckt->CKTmatrix; + } - /* Use a different vector & matrix */ + /* Use a different vector & matrix */ - save_context(ckt->CKTrhs, saved_rhs); - save_context(ckt->CKTirhs, saved_irhs); - save_context(ckt->CKTmatrix, saved_matrix); + save_context(ckt->CKTrhs, saved_rhs); + save_context(ckt->CKTirhs, saved_irhs); + save_context(ckt->CKTmatrix, saved_matrix); - ckt->CKTrhs = delta_I; - ckt->CKTirhs = delta_iI; - ckt->CKTmatrix = delta_Y; + ckt->CKTrhs = delta_I; + ckt->CKTirhs = delta_iI; + ckt->CKTmatrix = delta_Y; - /* calc. effect of each param */ - for (sg = sgen_init(ckt, is_dc /* job->plist */); - sg; sgen_next(&sg)) - { + /* calc. effect of each param */ + for (sg = sgen_init(ckt, is_dc /* job->plist */); + sg; sgen_next(&sg)) + { #ifdef ASDEBUG - DEBUG(2) { - printf("E/iE: %x/%x; delta_I/iI: %x/%x\n", - E, iE, delta_I, delta_iI); - printf("cktrhs/irhs: %x/%x\n", - ckt->CKTrhs, ckt->CKTirhs); + DEBUG(2) { + printf("E/iE: %x/%x; delta_I/iI: %x/%x\n", + E, iE, delta_I, delta_iI); + printf("cktrhs/irhs: %x/%x\n", + ckt->CKTrhs, ckt->CKTirhs); - if (sg->is_instparam) - printf("%s:%s:%s -> param %s\n", - DEVices[sg->dev]->DEVpublic.name, - sg->model->GENmodName, - sg->instance->GENname, - sg->ptable[sg->param].keyword); - else - printf("%s:%s:%s -> mparam %s\n", - DEVices[sg->dev]->DEVpublic.name, - sg->model->GENmodName, - sg->instance->GENname, - sg->ptable[sg->param].keyword); - } + if (sg->is_instparam) + printf("%s:%s:%s -> param %s\n", + DEVices[sg->dev]->DEVpublic.name, + sg->model->GENmodName, + sg->instance->GENname, + sg->ptable[sg->param].keyword); + else + printf("%s:%s:%s -> mparam %s\n", + DEVices[sg->dev]->DEVpublic.name, + sg->model->GENmodName, + sg->instance->GENname, + sg->ptable[sg->param].keyword); + } #endif - SMPcClear(delta_Y); + SMPcClear(delta_Y); - for (j = 0; j < size; j++) { - delta_I[j] = 0.0; - delta_iI[j] = 0.0; - } + for (j = 0; j < size; j++) { + delta_I[j] = 0.0; + delta_iI[j] = 0.0; + } - /* ? should this just call CKTsetup - * ? but then CKThead would have to get fiddled with */ + /* ? should this just call CKTsetup + * ? but then CKThead would have to get fiddled with */ - ckt->CKTnumStates = sg->istate; + ckt->CKTnumStates = sg->istate; - fn = DEVices[sg->dev]->DEVsetup; - if (fn) { - CKTnode *node = ckt->CKTlastNode; + fn = DEVices[sg->dev]->DEVsetup; + if (fn) { + CKTnode* node = ckt->CKTlastNode; /* XXXX insert old state base here ?? */ - fn (delta_Y, sg->model, ckt, &ckt->CKTnumStates); + fn(delta_Y, sg->model, ckt, &ckt->CKTnumStates); if (node != ckt->CKTlastNode) { fprintf(stderr, "Internal Error: node allocation in DEVsetup() during sensitivity analysis, this will cause serious troubles !, please report this issue !\n"); controlled_exit(EXIT_FAILURE); @@ -433,162 +437,162 @@ int sens_sens(CKTcircuit *ckt, int restart) } #ifdef KLU - if (ckt->CKTmatrix->CKTkluMODE) - { - /* Populate the delta_Y KLU Matrix */ + if (ckt->CKTmatrix->CKTkluMODE) + { + /* Populate the delta_Y KLU Matrix */ - /* Convert the COO Storage to CSC for KLU and Fill the Binding Table */ - SMPconvertCOOtoCSC (delta_Y) ; + /* Convert the COO Storage to CSC for KLU and Fill the Binding Table */ + SMPconvertCOOtoCSC(delta_Y); - /* KLU Pointers Assignment */ - if (DEVices [sg->dev]->DEVbindCSC) - DEVices [sg->dev]->DEVbindCSC (sg->model, ckt) ; + /* KLU Pointers Assignment */ + if (DEVices[sg->dev]->DEVbindCSC) + DEVices[sg->dev]->DEVbindCSC(sg->model, ckt); - delta_Y->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ; + delta_Y->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal; - /* Clear KLU Vectors */ - for (i = 0 ; i < (int)delta_Y->SMPkluMatrix->KLUmatrixNZ ; i++) - { - delta_Y->SMPkluMatrix->KLUmatrixAx [i] = 0 ; - delta_Y->SMPkluMatrix->KLUmatrixAxComplex [2 * i] = 0 ; - delta_Y->SMPkluMatrix->KLUmatrixAxComplex [2 * i + 1] = 0 ; - } - } + /* Clear KLU Vectors */ + for (i = 0; i < (int)delta_Y->SMPkluMatrix->KLUmatrixNZ; i++) + { + delta_Y->SMPkluMatrix->KLUmatrixAx[i] = 0; + delta_Y->SMPkluMatrix->KLUmatrixAxComplex[2 * i] = 0; + delta_Y->SMPkluMatrix->KLUmatrixAxComplex[2 * i + 1] = 0; + } + } #endif - /* ? CKTsetup would call NIreinit instead */ - ckt->CKTniState = NISHOULDREORDER | NIACSHOULDREORDER; + /* ? CKTsetup would call NIreinit instead */ + ckt->CKTniState = NISHOULDREORDER | NIACSHOULDREORDER; - /* XXX instead of calling temp here, just swap - * back to the original states */ - (void) sens_temp(sg, ckt); + /* XXX instead of calling temp here, just swap + * back to the original states */ + (void)sens_temp(sg, ckt); - /* XXX Leave original E until here!! so that temp reads - * the right node voltages */ + /* XXX Leave original E until here!! so that temp reads + * the right node voltages */ #ifdef KLU - if (ckt->CKTkluMODE) - { - if (!is_dc) - { - if (DEVices [sg->dev]->DEVbindCSCComplex) - DEVices [sg->dev]->DEVbindCSCComplex (sg->model, ckt) ; + if (ckt->CKTkluMODE) + { + if (!is_dc) + { + if (DEVices[sg->dev]->DEVbindCSCComplex) + DEVices[sg->dev]->DEVbindCSCComplex(sg->model, ckt); - delta_Y->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ; - } - } + delta_Y->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex; + } + } #endif - if (sens_load(sg, ckt, is_dc)) { - if (error && error != E_BADPARM) - return error; /* XXX */ - continue; - } + if (sens_load(sg, ckt, is_dc)) { + if (error && error != E_BADPARM) + return error; /* XXX */ + continue; + } - /* Alter the parameter */ + /* Alter the parameter */ #ifdef ASDEBUG - DEBUG(1) printf("Original value: %g\n", sg->value); + DEBUG(1) printf("Original value: %g\n", sg->value); #endif #ifdef ASDEBUG - DEBUG(2) { - printf("Effect of device:\n"); - SMPprint(delta_Y, NULL); - printf("LHS:\n"); - for (j = 0; j < size; j++) - printf("%d: %g, %g\n", j, - delta_I[j], delta_iI[j]); - } + DEBUG(2) { + printf("Effect of device:\n"); + SMPprint(delta_Y, NULL); + printf("LHS:\n"); + for (j = 0; j < size; j++) + printf("%d: %g, %g\n", j, + delta_I[j], delta_iI[j]); + } #endif - if (sg->value != 0.0) - delta_var = sg->value * Sens_Delta; - else - delta_var = Sens_Abs_Delta; + if (sg->value != 0.0) + delta_var = sg->value * Sens_Delta; + else + delta_var = Sens_Abs_Delta; - nvalue.rValue = sg->value + delta_var; + nvalue.rValue = sg->value + delta_var; #ifdef ASDEBUG - DEBUG(1) - printf("New value: %g\n", nvalue.rValue); + DEBUG(1) + printf("New value: %g\n", nvalue.rValue); #endif - sens_setp(sg, ckt, &nvalue); - if (error && error != E_BADPARM) - return error; + sens_setp(sg, ckt, &nvalue); + if (error && error != E_BADPARM) + return error; - SMPconstMult(delta_Y, -1.0); + SMPconstMult(delta_Y, -1.0); - for (j = 0; j < size; j++) { - delta_I[j] *= -1.0; - delta_iI[j] *= -1.0; - } + for (j = 0; j < size; j++) { + delta_I[j] *= -1.0; + delta_iI[j] *= -1.0; + } #ifdef ASDEBUG - DEBUG(2) { - printf("Effect of negating matrix:\n"); - SMPprint(delta_Y, NULL); - for (j = 0; j < size; j++) - printf("%d: %g, %g\n", j, - delta_I[j], delta_iI[j]); - } + DEBUG(2) { + printf("Effect of negating matrix:\n"); + SMPprint(delta_Y, NULL); + for (j = 0; j < size; j++) + printf("%d: %g, %g\n", j, + delta_I[j], delta_iI[j]); + } #endif - /* XXX swap back to temp states ?? Naw ... */ - (void) sens_temp(sg, ckt); + /* XXX swap back to temp states ?? Naw ... */ + (void)sens_temp(sg, ckt); #ifdef ASDEBUG - DEBUG(1) { - if (sens_getp(sg, ckt, &value)) { - continue; - } + DEBUG(1) { + if (sens_getp(sg, ckt, &value)) { + continue; + } - printf("New value in device: %g\n", - value.rValue); - } + printf("New value in device: %g\n", + value.rValue); + } #endif - sens_load(sg, ckt, is_dc); + sens_load(sg, ckt, is_dc); #ifdef ASDEBUG - DEBUG(2) { - printf("Effect of changing the parameter:\n"); - SMPprint(delta_Y, NULL); - for (j = 0; j < size; j++) - printf("%d: %g, %g\n", j, - delta_I[j], delta_iI[j]); - } + DEBUG(2) { + printf("Effect of changing the parameter:\n"); + SMPprint(delta_Y, NULL); + for (j = 0; j < size; j++) + printf("%d: %g, %g\n", j, + delta_I[j], delta_iI[j]); + } #endif - /* Set the perturbed variable back to it's - * original value - */ + /* Set the perturbed variable back to it's + * original value + */ - value.rValue = sg->value; - sens_setp(sg, ckt, &value); - (void) sens_temp(sg, ckt); /* XXX is this necessary? */ + value.rValue = sg->value; + sens_setp(sg, ckt, &value); + (void)sens_temp(sg, ckt); /* XXX is this necessary? */ - /* Back to business . . . */ + /* Back to business . . . */ #ifdef ASDEBUG - DEBUG(2) - for (j = 0; j < size; j++) - printf(" E [%d] = %20.15g\n", - j, E[j]); + DEBUG(2) + for (j = 0; j < size; j++) + printf(" E [%d] = %20.15g\n", + j, E[j]); #endif - /* delta_Y E */ -// fprintf(stderr, "\n\nPRIMA\n"); -// SMPprint(delta_Y, NULL); - SMPmultiply(delta_Y, delta_I_delta_Y, E, - delta_iI_delta_Y, iE); -// fprintf(stderr, "\n\nDOPO\n"); -// SMPprint(delta_Y, NULL); + /* delta_Y E */ +// fprintf(stderr, "\n\nPRIMA\n"); +// SMPprint(delta_Y, NULL); + SMPmultiply(delta_Y, delta_I_delta_Y, E, + delta_iI_delta_Y, iE); +// fprintf(stderr, "\n\nDOPO\n"); +// SMPprint(delta_Y, NULL); #ifdef ASDEBUG - DEBUG(2) - for (j = 0; j < size; j++) - printf("delta_Y * E [%d] = %20.15g\n", - j, delta_I_delta_Y[j]); + DEBUG(2) + for (j = 0; j < size; j++) + printf("delta_Y * E [%d] = %20.15g\n", + j, delta_I_delta_Y[j]); #endif // fprintf (stderr, "\n\nPRIMA 1\n") ; @@ -597,11 +601,11 @@ int sens_sens(CKTcircuit *ckt, int restart) // fprintf (stderr, "RHS [%d]: %-.9g j%-.9g\n", j, delta_I [j], delta_iI [j]) ; // } - /* delta_I - delta_Y E */ - for (j = 0; j < size; j++) { - delta_I[j] -= delta_I_delta_Y[j]; - delta_iI[j] -= delta_iI_delta_Y[j]; - } + /* delta_I - delta_Y E */ + for (j = 0; j < size; j++) { + delta_I[j] -= delta_I_delta_Y[j]; + delta_iI[j] -= delta_iI_delta_Y[j]; + } // fprintf (stderr, "\n\nDOPO 1\n") ; // for (j = 0 ; j < size ; j++) @@ -610,13 +614,13 @@ int sens_sens(CKTcircuit *ckt, int restart) // } #ifdef ASDEBUG - DEBUG(2) { - printf(">>> Y:\n"); - SMPprint(Y, NULL); - for (j = 0; j < size; j++) - printf("%d: %g, %g\n", j, - delta_I[j], delta_iI[j]); - } + DEBUG(2) { + printf(">>> Y:\n"); + SMPprint(Y, NULL); + for (j = 0; j < size; j++) + printf("%d: %g, %g\n", j, + delta_I[j], delta_iI[j]); + } #endif // fprintf (stderr, "\n\nPRIMA\n") ; @@ -625,8 +629,8 @@ int sens_sens(CKTcircuit *ckt, int restart) // fprintf (stderr, "RHS [%d]: %-.14g j%-.14g\n", j, delta_I [j], delta_iI [j]) ; // } - /* Solve; Y already factored */ - SMPcSolve(Y, delta_I, delta_iI, NULL, NULL); + /* Solve; Y already factored */ + SMPcSolve(Y, delta_I, delta_iI, NULL, NULL); // fprintf (stderr, "\n\nDOPO\n") ; // for (j = 0 ; j < size ; j++) @@ -634,336 +638,340 @@ int sens_sens(CKTcircuit *ckt, int restart) // fprintf (stderr, "RHS [%d]: %-.14g j%-.14g\n", j, delta_I [j], delta_iI [j]) ; // } - /* the special `0' node - * the matrix indizes are [1..n] - * yet the vector indizes are [0..n] - * with [0] being implicit === 0 - */ - delta_I[0] = 0.0; - delta_iI[0] = 0.0; + /* the special `0' node + * the matrix indizes are [1..n] + * yet the vector indizes are [0..n] + * with [0] being implicit === 0 + */ + delta_I[0] = 0.0; + delta_iI[0] = 0.0; #ifdef ASDEBUG - DEBUG(2) { - for (j = 1; j < size; j++) { + DEBUG(2) { + for (j = 1; j < size; j++) { - if (sg->is_instparam) - printf("%d/%s.%s = %g, %g\n", - j, - sg->instance->GENname, - sg->ptable[sg->param].keyword, - delta_I[j], delta_iI[j]); - else - printf("%d/%s:%s = %g, %g\n", - j, - sg->instance->GENname, - sg->ptable[sg->param].keyword, - delta_I[j], delta_iI[j]); + if (sg->is_instparam) + printf("%d/%s.%s = %g, %g\n", + j, + sg->instance->GENname, + sg->ptable[sg->param].keyword, + delta_I[j], delta_iI[j]); + else + printf("%d/%s:%s = %g, %g\n", + j, + sg->instance->GENname, + sg->ptable[sg->param].keyword, + delta_I[j], delta_iI[j]); - } - } + } + } #endif - /* delta_I is now equal to delta_E */ + /* delta_I is now equal to delta_E */ - if (is_dc) { - if (job->output_volt) { - output_values[n] = - delta_I [job->output_pos->number] - - delta_I [job->output_neg->number]; + if (is_dc) { + if (job->output_volt) { + output_values[n] = + delta_I[job->output_pos->number] + - delta_I[job->output_neg->number]; // fprintf (stderr, "Pos: %d\tNeg: %d\n", job->output_pos->number, job->output_neg->number) ; - } - else { - output_values[n] = delta_I[branch_eq]; - } -// fprintf (stderr, "output_values real PRIMA: %-.14g\n", output_values [n]) ; - output_values[n] /= delta_var; -// fprintf(stderr, "output_values real DOPO: %-.14g - delta_var: %-.9g\n", output_values [n], delta_var); - } else { - if (job->output_volt) { - output_cvalues[n].real = - delta_I [job->output_pos->number] - - delta_I [job->output_neg->number]; - output_cvalues[n].imag = - delta_iI [job->output_pos->number] - - delta_iI [job->output_neg->number]; - } else { - output_cvalues[n].real = - delta_I[branch_eq]; - output_cvalues[n].imag = - delta_iI[branch_eq]; - } + } + else { + output_values[n] = delta_I[branch_eq]; + } +// fprintf (stderr, "output_values real PRIMA: %-.14g\n", output_values [n]) ; + output_values[n] /= delta_var; +// fprintf(stderr, "output_values real DOPO: %-.14g - delta_var: %-.9g\n", output_values [n], delta_var); + } + else { + if (job->output_volt) { + output_cvalues[n].real = + delta_I[job->output_pos->number] + - delta_I[job->output_neg->number]; + output_cvalues[n].imag = + delta_iI[job->output_pos->number] + - delta_iI[job->output_neg->number]; + } + else { + output_cvalues[n].real = + delta_I[branch_eq]; + output_cvalues[n].imag = + delta_iI[branch_eq]; + } // fprintf (stderr, "output_values complex: %-.9g j%-.9g\n", output_cvalues [n].real, output_cvalues [n].imag) ; - output_cvalues[n].real /= delta_var; - output_cvalues[n].imag /= delta_var; - } + output_cvalues[n].real /= delta_var; + output_cvalues[n].imag /= delta_var; + } + n += 1; + } - n += 1; + release_context(ckt->CKTrhs, saved_rhs); + release_context(ckt->CKTirhs, saved_irhs); - } + release_context(ckt->CKTmatrix, saved_matrix); - release_context(ckt->CKTrhs, saved_rhs); - release_context(ckt->CKTirhs, saved_irhs); + if (is_dc) + nvalue.v.vec.rVec = output_values; + else + nvalue.v.vec.cVec = output_cvalues; - release_context(ckt->CKTmatrix, saved_matrix); + value.rValue = freq; - if (is_dc) - nvalue.v.vec.rVec = output_values; - else - nvalue.v.vec.cVec = output_cvalues; + SPfrontEnd->OUTpData(sen_data, &value, &nvalue); - value.rValue = freq; + freq = inc_freq(freq, job->step_type, step_size); - SPfrontEnd->OUTpData (sen_data, &value, &nvalue); + } - freq = inc_freq(freq, job->step_type, step_size); + SPfrontEnd->OUTendPlot(sen_data); - } + if (is_dc) { + FREE(output_values); /* XXX free various vectors */ + } + else { + FREE(output_cvalues); /* XXX free various vectors */ + } - SPfrontEnd->OUTendPlot (sen_data); + release_context(ckt->CKTrhs, saved_rhs); + release_context(ckt->CKTirhs, saved_irhs); - if (is_dc) { - FREE(output_values); /* XXX free various vectors */ - } else { - FREE(output_cvalues); /* XXX free various vectors */ - } + release_context(ckt->CKTmatrix, saved_matrix); - release_context(ckt->CKTrhs, saved_rhs); - release_context(ckt->CKTirhs, saved_irhs); + SMPdestroy(delta_Y); + FREE(delta_I); + FREE(delta_iI); - release_context(ckt->CKTmatrix, saved_matrix); + FREE(delta_I_delta_Y); + FREE(delta_iI_delta_Y); - SMPdestroy(delta_Y); - FREE(delta_I); - FREE(delta_iI); - - FREE(delta_I_delta_Y); - FREE(delta_iI_delta_Y); - - ckt->CKTbypass = bypass; + ckt->CKTbypass = bypass; #ifdef notdef - for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) { - if (ckt->CKTstates[j]) - FREE(ckt->CKTstates[j]); - ckt->CKTstates[j] = save_states[j]; - } + for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) { + if (ckt->CKTstates[j]) + FREE(ckt->CKTstates[j]); + ckt->CKTstates[j] = save_states[j]; + } #endif #endif - return OK; -/* -#ifdef KLU - } -#endif -*/ + return OK; + /* + #ifdef KLU + } + #endif + */ } double inc_freq(double freq, int type, double step_size) { - if (type != LINEAR) - freq *= step_size; - else - freq += step_size; + if (type != LINEAR) + freq *= step_size; + else + freq += step_size; - return freq; + return freq; } /* static double next_freq(int type, double freq, double stepsize) { - double s=0; + double s=0; - switch (type) { - case SENS_DC: - s = 0; - break; + switch (type) { + case SENS_DC: + s = 0; + break; - case SENS_LINEAR: - s = freq + stepsize; - break; + case SENS_LINEAR: + s = freq + stepsize; + break; - case SENS_DECADE: - case SENS_OCTAVE: - s = freq * stepsize; - break; - } - return s; + case SENS_DECADE: + case SENS_OCTAVE: + s = freq * stepsize; + break; + } + return s; } */ int -count_steps(int type, double low, double high, int steps, double *stepsize) +count_steps(int type, double low, double high, int steps, double* stepsize) { - double s; - int n; + double s; + int n; - if (steps < 1) - steps = 1; + if (steps < 1) + steps = 1; - switch (type) { - default: - case SENS_DC: - n = 0; - s = 0; - break; + switch (type) { + default: + case SENS_DC: + n = 0; + s = 0; + break; - case SENS_LINEAR: - n = steps; - s = (high - low) / steps; - break; + case SENS_LINEAR: + n = steps; + s = (high - low) / steps; + break; - case SENS_DECADE: - if (low <= 0.0) - low = 1e-3; - if (high <= low) - high = 10.0 * low; - n = (int)(steps * log10(high/low) + 1.01); - s = pow(10.0, 1.0 / steps); - break; + case SENS_DECADE: + if (low <= 0.0) + low = 1e-3; + if (high <= low) + high = 10.0 * low; + n = (int)(steps * log10(high / low) + 1.01); + s = pow(10.0, 1.0 / steps); + break; - case SENS_OCTAVE: - if (low <= 0.0) - low = 1e-3; - if (high <= low) - high = 2.0 * low; - n = (int)(steps * log(high/low) / M_LOG2E + 1.01); - s = pow(2.0, 1.0 / steps); - break; - } + case SENS_OCTAVE: + if (low <= 0.0) + low = 1e-3; + if (high <= low) + high = 2.0 * low; + n = (int)(steps * log(high / low) / M_LOG2E + 1.01); + s = pow(2.0, 1.0 / steps); + break; + } - if (n <= 0) - n = 1; + if (n <= 0) + n = 1; - *stepsize = s; - return n; + *stepsize = s; + return n; } static int -sens_load(sgen *sg, CKTcircuit *ckt, int is_dc) -{//fprintf (stderr, "LOAD - is_dc: %d\n", is_dc) ; - int (*fn) (GENmodel *, CKTcircuit *); +sens_load(sgen* sg, CKTcircuit* ckt, int is_dc) +{ +// fprintf (stderr, "LOAD - is_dc: %d\n", is_dc) ; + int (*fn) (GENmodel*, CKTcircuit*); - error = 0; + error = 0; - if (!is_dc) - fn = DEVices[sg->dev]->DEVacLoad; - else - fn = DEVices[sg->dev]->DEVload; + if (!is_dc) + fn = DEVices[sg->dev]->DEVacLoad; + else + fn = DEVices[sg->dev]->DEVload; - if (fn) - error = fn (sg->model, ckt); - else - return 1; + if (fn) + error = fn(sg->model, ckt); + else + return 1; - return error; + return error; } static int -sens_temp(sgen *sg, CKTcircuit *ckt) +sens_temp(sgen* sg, CKTcircuit* ckt) { - int (*fn) (GENmodel *, CKTcircuit *); + int (*fn) (GENmodel*, CKTcircuit*); - error = 0; + error = 0; - fn = DEVices[sg->dev]->DEVtemperature; + fn = DEVices[sg->dev]->DEVtemperature; - if (fn) - error = fn (sg->model, ckt); - else - return 1; + if (fn) + error = fn(sg->model, ckt); + else + return 1; - return error; + return error; } /* Get parameter value */ int -sens_getp(sgen *sg, CKTcircuit *ckt, IFvalue *val) +sens_getp(sgen* sg, CKTcircuit* ckt, IFvalue* val) { - int pid; + int pid; - NG_IGNORE(ckt); + NG_IGNORE(ckt); - error = 0; + error = 0; - if (sg->is_instparam) { - int (*fn) (CKTcircuit*, GENinstance*, int, IFvalue*, IFvalue*); - fn = DEVices[sg->dev]->DEVask; - pid = DEVices[sg->dev]->DEVpublic.instanceParms[sg->param].id; - if (fn) - error = fn (ckt, sg->instance, pid, val, NULL); - else - return 1; - } else { - int (*fn) (CKTcircuit*, GENmodel*, int, IFvalue*); - fn = DEVices[sg->dev]->DEVmodAsk; - pid = DEVices[sg->dev]->DEVpublic.modelParms[sg->param].id; - if (fn) - error = fn (ckt, sg->model, pid, val); - else - return 1; - } + if (sg->is_instparam) { + int (*fn) (CKTcircuit*, GENinstance*, int, IFvalue*, IFvalue*); + fn = DEVices[sg->dev]->DEVask; + pid = DEVices[sg->dev]->DEVpublic.instanceParms[sg->param].id; + if (fn) + error = fn(ckt, sg->instance, pid, val, NULL); + else + return 1; + } + else { + int (*fn) (CKTcircuit*, GENmodel*, int, IFvalue*); + fn = DEVices[sg->dev]->DEVmodAsk; + pid = DEVices[sg->dev]->DEVpublic.modelParms[sg->param].id; + if (fn) + error = fn(ckt, sg->model, pid, val); + else + return 1; + } - if (error) { - if (sg->is_instparam) - printf("GET ERROR: %s:%s:%s -> param %s (%d)\n", - DEVices[sg->dev]->DEVpublic.name, - sg->model->GENmodName, - sg->instance->GENname, - sg->ptable[sg->param].keyword, pid); - else - printf("GET ERROR: %s:%s:%s -> mparam %s (%d)\n", - DEVices[sg->dev]->DEVpublic.name, - sg->model->GENmodName, - sg->instance->GENname, - sg->ptable[sg->param].keyword, pid); - } + if (error) { + if (sg->is_instparam) + printf("GET ERROR: %s:%s:%s -> param %s (%d)\n", + DEVices[sg->dev]->DEVpublic.name, + sg->model->GENmodName, + sg->instance->GENname, + sg->ptable[sg->param].keyword, pid); + else + printf("GET ERROR: %s:%s:%s -> mparam %s (%d)\n", + DEVices[sg->dev]->DEVpublic.name, + sg->model->GENmodName, + sg->instance->GENname, + sg->ptable[sg->param].keyword, pid); + } - return error; + return error; } /* Get parameter value */ int -sens_setp(sgen *sg, CKTcircuit *ckt, IFvalue *val) +sens_setp(sgen* sg, CKTcircuit* ckt, IFvalue* val) { - int pid; + int pid; - NG_IGNORE(ckt); + NG_IGNORE(ckt); - error = 0; + error = 0; - if (sg->is_instparam) { - int (*fn) (int, IFvalue *, GENinstance *, IFvalue *); - fn = DEVices[sg->dev]->DEVparam; - pid = DEVices[sg->dev]->DEVpublic.instanceParms[sg->param].id; - if (fn) - error = fn (pid, val, sg->instance, NULL); - else - return 1; - } else { - int (*fn) (int, IFvalue *, GENmodel *); - fn = DEVices[sg->dev]->DEVmodParam; - pid = DEVices[sg->dev]->DEVpublic.modelParms[sg->param].id; - if (fn) - error = fn (pid, val, sg->model); - else - return 1; - } + if (sg->is_instparam) { + int (*fn) (int, IFvalue*, GENinstance*, IFvalue*); + fn = DEVices[sg->dev]->DEVparam; + pid = DEVices[sg->dev]->DEVpublic.instanceParms[sg->param].id; + if (fn) + error = fn(pid, val, sg->instance, NULL); + else + return 1; + } + else { + int (*fn) (int, IFvalue*, GENmodel*); + fn = DEVices[sg->dev]->DEVmodParam; + pid = DEVices[sg->dev]->DEVpublic.modelParms[sg->param].id; + if (fn) + error = fn(pid, val, sg->model); + else + return 1; + } - if (error) { - if (sg->is_instparam) - printf("SET ERROR: %s:%s:%s -> param %s (%d)\n", - DEVices[sg->dev]->DEVpublic.name, - sg->model->GENmodName, - sg->instance->GENname, - sg->ptable[sg->param].keyword, pid); - else - printf("SET ERROR: %s:%s:%s -> mparam %s (%d)\n", - DEVices[sg->dev]->DEVpublic.name, - sg->model->GENmodName, - sg->instance->GENname, - sg->ptable[sg->param].keyword, pid); - } + if (error) { + if (sg->is_instparam) + printf("SET ERROR: %s:%s:%s -> param %s (%d)\n", + DEVices[sg->dev]->DEVpublic.name, + sg->model->GENmodName, + sg->instance->GENname, + sg->ptable[sg->param].keyword, pid); + else + printf("SET ERROR: %s:%s:%s -> mparam %s (%d)\n", + DEVices[sg->dev]->DEVpublic.name, + sg->model->GENmodName, + sg->instance->GENname, + sg->ptable[sg->param].keyword, pid); + } - return error; + return error; } From ca7c6cce71deb271fa6590381f2d971cc90ea8c5 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Dec 2023 11:32:31 +0100 Subject: [PATCH 27/33] Avoid crash, when sensitivity analysis is called --- src/spicelib/analysis/cktsens.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/spicelib/analysis/cktsens.c b/src/spicelib/analysis/cktsens.c index 34e33e0d7..763cc57a6 100644 --- a/src/spicelib/analysis/cktsens.c +++ b/src/spicelib/analysis/cktsens.c @@ -162,7 +162,9 @@ int sens_sens(CKTcircuit* ckt, int restart) return error; #ifdef KLU - delta_Y->SMPkluMatrix->KLUmatrixDiag = NULL; + /* FIXME: needs better understanding what makes SMPkluMatrix NULL */ + if(delta_Y->SMPkluMatrix) + delta_Y->SMPkluMatrix->KLUmatrixDiag = NULL; #endif // SMPprint(delta_Y, NULL); From c1effe3b33051e51d7924f6a0f2ac804ab97ff98 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Dec 2023 12:26:56 +0100 Subject: [PATCH 28/33] Just a hack to avoid a crash during sensitivity analysis: Exclude parameter RCO from sens code, if not given, as sens sets mods->BJTintCollResistGiven to TRUE, which fails due to missing memory allocation for the extra nodes. --- src/spicelib/analysis/cktsens.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/spicelib/analysis/cktsens.c b/src/spicelib/analysis/cktsens.c index 763cc57a6..8f70c174c 100644 --- a/src/spicelib/analysis/cktsens.c +++ b/src/spicelib/analysis/cktsens.c @@ -931,7 +931,7 @@ sens_getp(sgen* sg, CKTcircuit* ckt, IFvalue* val) return error; } -/* Get parameter value */ +/* Set parameter value */ int sens_setp(sgen* sg, CKTcircuit* ckt, IFvalue* val) { @@ -954,7 +954,11 @@ sens_setp(sgen* sg, CKTcircuit* ckt, IFvalue* val) int (*fn) (int, IFvalue*, GENmodel*); fn = DEVices[sg->dev]->DEVmodParam; pid = DEVices[sg->dev]->DEVpublic.modelParms[sg->param].id; - if (fn) + + /* FIXME: just a preliminary hack. + * Exclude bipolar parameter RCO, as it crashes ngspice + * during sensitivity analysis due to missing node allocations */ + if (fn && !(sg->dev == 2 && pid == 147)) error = fn(pid, val, sg->model); else return 1; From 009249eafefc11604793d8e0007ea64071a58d97 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Dec 2023 12:27:31 +0100 Subject: [PATCH 29/33] Short title --- src/spicelib/analysis/cktsgen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spicelib/analysis/cktsgen.c b/src/spicelib/analysis/cktsgen.c index 7d3a082d6..249e99964 100644 --- a/src/spicelib/analysis/cktsgen.c +++ b/src/spicelib/analysis/cktsgen.c @@ -9,7 +9,8 @@ Copyright 1991 Regents of the University of California. All rights reserved. #include "ngspice/ifsim.h" #include "ngspice/sensgen.h" - /* XXX */ +/* Used by sensitivity code in cktsens.c */ + extern char *Sfilter; int set_model(sgen *); From a08f1046e40c91305cc9e2675d39020518fd9364 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Dec 2023 16:18:36 +0100 Subject: [PATCH 30/33] Add KLU headers to enable their distribution --- src/include/ngspice/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/include/ngspice/Makefile.am b/src/include/ngspice/Makefile.am index 2e8073a95..927496b94 100644 --- a/src/include/ngspice/Makefile.am +++ b/src/include/ngspice/Makefile.am @@ -63,7 +63,9 @@ noinst_HEADERS = \ ipcproto.h \ ipctiein.h \ jobdefs.h \ - logicexp.h \ + klu.h \ + klu-binding.h \ + logicexp.h \ lsort.h \ macros.h \ material.h \ From f4c560ba71f306677416684e1faa60efd9144c05 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Dec 2023 16:42:37 +0100 Subject: [PATCH 31/33] Add more KLU headers to enable their distribution --- src/maths/KLU/Makefile.am | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/maths/KLU/Makefile.am b/src/maths/KLU/Makefile.am index 66bedada8..dfda227d7 100644 --- a/src/maths/KLU/Makefile.am +++ b/src/maths/KLU/Makefile.am @@ -1,7 +1,16 @@ ## Process this file with automake to produce Makefile.in +EXTRA_DIST = SuiteSparse.org + noinst_LTLIBRARIES = libKLU_real.la libKLU_complex.la libKLU.la +noinst_HEADERS = \ + amd_internal.h \ + btf_internal.h \ + klu_internal.h \ + klu_version.h + + libKLU_real_la_SOURCES = \ klu.c \ klu_diagnostics.c \ From f8e77d08d064de7fb0b85fadf9cc44fe5577a13c Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Dec 2023 17:12:15 +0100 Subject: [PATCH 32/33] More headers distributed --- src/include/ngspice/Makefile.am | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/include/ngspice/Makefile.am b/src/include/ngspice/Makefile.am index 927496b94..1783a9df1 100644 --- a/src/include/ngspice/Makefile.am +++ b/src/include/ngspice/Makefile.am @@ -3,8 +3,10 @@ noinst_HEADERS = \ tclspice.h \ acdefs.h \ + amd.h \ bdrydefs.h \ bool.h \ + btf.h \ carddefs.h \ ciderinp.h \ cidersupt.h \ @@ -14,10 +16,12 @@ noinst_HEADERS = \ cm.h \ cmproto.h \ cmtypes.h \ + colamd.h \ compatmode.h \ complex.h \ const.h \ contdefs.h \ + cosim.h \ cpdefs.h \ cpextern.h \ cpstd.h \ @@ -125,6 +129,7 @@ noinst_HEADERS = \ twomesh.h \ typedefs.h \ udevices.h \ + UFconfig.h \ wordlist.h \ 1-f-code.h \ FastNorm3.h \ From 902a62d2f442a1d8322ae4fcad35c143c7a14561 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 27 Dec 2023 19:41:13 +0100 Subject: [PATCH 33/33] win_time.c as extra distribution, used only by MSVC --- src/misc/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/misc/Makefile.am b/src/misc/Makefile.am index ad8b9a58a..efaaf5e24 100644 --- a/src/misc/Makefile.am +++ b/src/misc/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libmisc.la +EXTRA_DIST = win_time.c libmisc_la_SOURCES = \ getopt_long_bsd.c \