diff --git a/NEWS b/NEWS index 50f5f5101..4def20b82 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 @@ -18,9 +18,11 @@ 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 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/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/examples/paranoia/README.txt b/examples/paranoia/README.txt index fe15da086..de7825868 100644 --- a/examples/paranoia/README.txt +++ b/examples/paranoia/README.txt @@ -4,8 +4,8 @@ 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 unzipped directory to a name without spaces which would otherwise -confuse valgrind. +Rename the unzipped directory to a name without spaces which would +otherwise confuse valgrind. 3. cd into the renamed unzipped directory. 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; 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) diff --git a/src/include/ngspice/Makefile.am b/src/include/ngspice/Makefile.am index 2e8073a95..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 \ @@ -63,7 +67,9 @@ noinst_HEADERS = \ ipcproto.h \ ipctiein.h \ jobdefs.h \ - logicexp.h \ + klu.h \ + klu-binding.h \ + logicexp.h \ lsort.h \ macros.h \ material.h \ @@ -123,6 +129,7 @@ noinst_HEADERS = \ twomesh.h \ typedefs.h \ udevices.h \ + UFconfig.h \ wordlist.h \ 1-f-code.h \ FastNorm3.h \ diff --git a/src/include/ngspice/sharedspice.h b/src/include/ngspice/sharedspice.h index d25c2c798..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. ** @@ -82,6 +85,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 primary thread, while the simulation in the +background thread is moving on. + ** Additional basics: No memory mallocing and freeing across the interface: @@ -97,7 +107,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/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 \ 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 \ 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 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 diff --git a/src/spicelib/analysis/cktsens.c b/src/spicelib/analysis/cktsens.c index 555462857..8f70c174c 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,378 @@ 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 ; + /* FIXME: needs better understanding what makes SMPkluMatrix NULL */ + if(delta_Y->SMPkluMatrix) + 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 +439,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 +603,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 +616,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 +631,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 +640,344 @@ 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 */ +/* Set 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 (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); - } + /* 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; + } - return error; + 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; } 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); } 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 *); 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 { 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; + } + } } 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) { 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"