diff --git a/examples/noise/baker-252-gain.cir b/examples/noise/baker-252-gain.cir new file mode 100644 index 000000000..f35002dba --- /dev/null +++ b/examples/noise/baker-252-gain.cir @@ -0,0 +1,25 @@ +baker-252 enhanced +* simple noiseless opamp with RC feedback +* compare E source and code model gain stage +* ngspice-40+ required + +.control +set sqrnoise +noise V(vout) Vplus dec 100 1 1000G +print all +noise V(vouta) Vplusa dec 100 1 1000G +print all +.endc + +Vplus Vplus 0 dc 0 ac 1 +Rf vout vminus 100k +Cf vout vminus 1000p +Eopamp vout 0 vplus vminus 100Meg + +Vplusa Vplusa 0 dc 0 ac 1 +Rfa vouta vminusa 100k +Cfa vouta vminusa 1000p +a1 %vd(vplusa, vminusa) vouta amp +.model amp gain(gain=1e8) + +.end diff --git a/examples/noise/resdiv.cir b/examples/noise/resdiv.cir new file mode 100644 index 000000000..1ba3ec9e1 --- /dev/null +++ b/examples/noise/resdiv.cir @@ -0,0 +1,41 @@ +* noise of a resistive divider +* noise of a resistive divider, lower resistor noiseless +* noise of a resistive divider with filter +* 'set behavior = lta' is required + +V1 1 0 dc 0 ac 1 +R1 1 2 10k +R2 2 0 10k + +V11 11 0 dc 0 ac 1 +R11 11 12 10k +R12 12 0 10k noiseless + +V21 21 0 dc 0 ac 1 +R21 21 22 10k +R22 22 0 10k +C22 22 0 1u + +.control +noise v(2) V1 dec 10 1 100k +echo **resistive divider** +print onoise_total inoise_total +setplot noise1 +print onoise_spectrum[0] inoise_spectrum[0] +noise v(12) V11 dec 10 1 100k +echo **resistive divider, lower resistor noiseless** +print onoise_total inoise_total +setplot noise3 +print onoise_spectrum[0] inoise_spectrum[0] +noise v(22) V21 dec 10 1 100k +echo **resistive divider with filter** +print onoise_total inoise_total +setplot noise5 +print onoise_spectrum[0] inoise_spectrum[0] +set xbrushwidth=2 +plot onoise_spectrum inoise_spectrum xlimit 1 1e5 +.endc + +.end + + diff --git a/examples/noise/resdiv_gain.cir b/examples/noise/resdiv_gain.cir new file mode 100644 index 000000000..7ccb978e9 --- /dev/null +++ b/examples/noise/resdiv_gain.cir @@ -0,0 +1,48 @@ +*noise of a resistive divider +*noise of a resistive divider with filter +*noise as above after a noiseless amplifier with gain 5 + +V1 1 0 dc 0 ac 1 +R1 1 2 10k +R2 2 0 10k + +V21 21 0 dc 0 ac 1 +R21 21 22 10k +R22 22 0 10k +C22 22 0 1u + +a1 2 3 amp +.model amp gain(in_offset = 0 gain = 5.0 ++ out_offset = 0) + +a2 22 23 amp + +.control + +noise v(2) V1 dec 10 1 100k +print onoise_total inoise_total +setplot noise1 +print onoise_spectrum[0] inoise_spectrum[0] + +noise v(3) V1 dec 10 1 100k +print onoise_total inoise_total +setplot noise3 +print onoise_spectrum[0] inoise_spectrum[0] + +noise v(22) V21 dec 10 1 100k +print onoise_total inoise_total +setplot noise5 +print onoise_spectrum[0] inoise_spectrum[0] + +noise v(23) V21 dec 10 1 100k +print onoise_total inoise_total +setplot noise7 +print onoise_spectrum[0] inoise_spectrum[0] +set xbrushwidth = 2 +plot onoise_spectrum noise5.onoise_spectrum inoise_spectrum xlimit 1 1e5 + +.endc + +.end + + diff --git a/src/include/ngspice/ipc.h b/src/include/ngspice/ipc.h index 7dd36621f..b52241770 100644 --- a/src/include/ngspice/ipc.h +++ b/src/include/ngspice/ipc.h @@ -113,8 +113,9 @@ typedef enum { IPC_ANAL_AC, IPC_ANAL_TRAN, #ifdef RFSPICE - IPC_ANAL_SP + IPC_ANAL_SP, #endif + IPC_ANAL_NOI } Ipc_Anal_t; diff --git a/src/include/ngspice/miftypes.h b/src/include/ngspice/miftypes.h index a9ae17c96..aa8c6f4b5 100644 --- a/src/include/ngspice/miftypes.h +++ b/src/include/ngspice/miftypes.h @@ -87,6 +87,7 @@ typedef enum { MIF_DC, /* A DC or DCOP analysis */ MIF_AC, /* A swept AC analysis */ MIF_TRAN, /* A transient analysis */ + MIF_NOI, /* A noise analysis */ } Mif_Analysis_t; diff --git a/src/spicelib/analysis/acan.c b/src/spicelib/analysis/acan.c index 1c45856c9..3312a9591 100644 --- a/src/spicelib/analysis/acan.c +++ b/src/spicelib/analysis/acan.c @@ -13,7 +13,7 @@ Modified 2001: AlansFixes #ifdef XSPICE #include "ngspice/evt.h" #include "ngspice/enh.h" -/* gtri - add - wbk - 12/19/90 - Add headers */ +/* gtri - add - wbk - 12/19/90 - Add headers */ #include "ngspice/mif.h" #include "ngspice/evtproto.h" #include "ngspice/ipctiein.h" @@ -42,9 +42,9 @@ do { \ int -ACan(CKTcircuit *ckt, int restart) +ACan(CKTcircuit* ckt, int restart) { - ACAN *job = (ACAN *) ckt->CKTcurJob; + ACAN* job = (ACAN*)ckt->CKTcurJob; double freq; double freqTol; /* tolerence parameter for finding final frequency */ @@ -55,23 +55,23 @@ ACan(CKTcircuit *ckt, int restart) double startTime; int error; int numNames; - IFuid *nameList; /* va: tmalloc'ed list of names */ + IFuid* nameList; /* va: tmalloc'ed list of names */ IFuid freqUid; - static runDesc *acPlot = NULL; - runDesc *plot = NULL; + static runDesc* acPlot = NULL; + runDesc* plot = NULL; #ifdef XSPICE -/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */ + /* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */ - /* Tell the beginPlot routine what mode we're in */ + /* Tell the beginPlot routine what mode we're in */ g_ipc.anal_type = IPC_ANAL_AC; /* Tell the code models what mode we're in */ g_mif_info.circuit.anal_type = MIF_DC; g_mif_info.circuit.anal_init = MIF_TRUE; -/* gtri - end - wbk */ + /* gtri - end - wbk */ #endif /* start at beginning */ @@ -86,8 +86,8 @@ ACan(CKTcircuit *ckt, int restart) fprintf(stderr, "ERROR: AC startfreq <= 0\n"); return E_PARMVAL; } - double num_steps = floor(fabs(log10(job->ACstopFreq/job->ACstartFreq))*job->ACnumberSteps); - job->ACfreqDelta = exp((log(job->ACstopFreq/job->ACstartFreq))/ num_steps); + double num_steps = floor(fabs(log10(job->ACstopFreq / job->ACstartFreq)) * job->ACnumberSteps); + job->ACfreqDelta = exp((log(job->ACstopFreq / job->ACstartFreq)) / num_steps); break; case OCTAVE: @@ -96,133 +96,134 @@ ACan(CKTcircuit *ckt, int restart) return E_PARMVAL; } job->ACfreqDelta = - exp(log(2.0)/job->ACnumberSteps); + exp(log(2.0) / job->ACnumberSteps); break; case LINEAR: - if (job->ACnumberSteps-1 > 1) + if (job->ACnumberSteps - 1 > 1) job->ACfreqDelta = - (job->ACstopFreq - - job->ACstartFreq) / - (job->ACnumberSteps - 1); + (job->ACstopFreq - + job->ACstartFreq) / + (job->ACnumberSteps - 1); else - /* Patch from: Richard McRoberts - * This patch is for a rather pathological case: - * a linear step with only one point */ + /* Patch from: Richard McRoberts + * This patch is for a rather pathological case: + * a linear step with only one point */ job->ACfreqDelta = 0; break; default: return(E_BADPARM); - } -#ifdef XSPICE -/* gtri - begin - wbk - Call EVTop if event-driven instances exist */ - - if(ckt->evt->counts.num_insts != 0) { - error = EVTop(ckt, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, - ckt->CKTdcMaxIter, - MIF_TRUE); - EVTdump(ckt, IPC_ANAL_DCOP, 0.0); - EVTop_save(ckt, MIF_TRUE, 0.0); - } - else -#endif - /* If no event-driven instances, do what SPICE normally does */ - if (!ckt->CKTnoopac) { /* skip OP if option NOOPAC is set and circuit is linear */ - error = CKTop(ckt, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, - ckt->CKTdcMaxIter); - - if(error){ - fprintf(stdout,"\nAC operating point failed -\n"); - CKTncDump(ckt); - return(error); } - } - else - fprintf(stdout,"\n Linear circuit, option noopac given: no OP analysis\n"); - #ifdef XSPICE -/* gtri - add - wbk - 12/19/90 - Add IPC stuff */ + /* gtri - begin - wbk - Call EVTop if event-driven instances exist */ - /* Send the operating point results for Mspice compatibility */ - if(g_ipc.enabled) - { - /* Call CKTnames to get names of nodes/branches used by - BeginPlot */ - /* Probably should free nameList after this block since - called again... */ - error = CKTnames(ckt,&numNames,&nameList); - if(error) return(error); + if (ckt->evt->counts.num_insts != 0) { + error = EVTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter, + MIF_TRUE); + EVTdump(ckt, IPC_ANAL_DCOP, 0.0); + EVTop_save(ckt, MIF_TRUE, 0.0); + } + else +#endif + /* If no event-driven instances, do what SPICE normally does */ + if (!ckt->CKTnoopac) { /* skip OP if option NOOPAC is set and circuit is linear */ + error = CKTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter); - /* We have to do a beginPlot here since the data to return is - * different for the DCOP than it is for the AC analysis. - * Moreover the begin plot has not even been done yet at this - * point... - */ - SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - NULL, IF_REAL, - numNames, nameList, IF_REAL, - &acPlot); - txfree(nameList); + if (error) { + fprintf(stdout, "\nAC operating point failed -\n"); + CKTncDump(ckt); + return(error); + } + } + else + fprintf(stdout, "\n Linear circuit, option noopac given: no OP analysis\n"); - ipc_send_dcop_prefix(); - CKTdump(ckt, 0.0, acPlot); - ipc_send_dcop_suffix(); +#ifdef XSPICE + /* gtri - add - wbk - 12/19/90 - Add IPC stuff */ - SPfrontEnd->OUTendPlot (acPlot); - } -/* gtri - end - wbk */ + /* Send the operating point results for Mspice compatibility */ + if (g_ipc.enabled) + { + /* Call CKTnames to get names of nodes/branches used by + BeginPlot */ + /* Probably should free nameList after this block since + called again... */ + error = CKTnames(ckt, &numNames, &nameList); + if (error) return(error); + + /* We have to do a beginPlot here since the data to return is + * different for the DCOP than it is for the AC analysis. + * Moreover the begin plot has not even been done yet at this + * point... + */ + SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &acPlot); + txfree(nameList); + + ipc_send_dcop_prefix(); + CKTdump(ckt, 0.0, acPlot); + ipc_send_dcop_suffix(); + + SPfrontEnd->OUTendPlot(acPlot); + } + /* gtri - end - wbk */ #endif ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); - if(error) return(error); + if (error) return(error); - error = CKTnames(ckt,&numNames,&nameList); - if(error) return(error); + error = CKTnames(ckt, &numNames, &nameList); + if (error) return(error); - if (ckt->CKTkeepOpInfo) { - /* Dump operating point. */ - error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, - "AC Operating Point", - NULL, IF_REAL, - numNames, nameList, IF_REAL, - &plot); - if(error) return(error); - CKTdump(ckt, 0.0, plot); - SPfrontEnd->OUTendPlot (plot); - plot = NULL; - } + if (ckt->CKTkeepOpInfo) { + /* Dump operating point. */ + error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob, + "AC Operating Point", + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &plot); + if (error) return(error); + CKTdump(ckt, 0.0, plot); + SPfrontEnd->OUTendPlot(plot); + plot = NULL; + } - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); - error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, - ckt->CKTcurJob->JOBname, - freqUid, IF_REAL, - numNames, nameList, IF_COMPLEX, - &acPlot); - tfree(nameList); - if(error) return(error); + SPfrontEnd->IFnewUid(ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + freqUid, IF_REAL, + numNames, nameList, IF_COMPLEX, + &acPlot); + tfree(nameList); + if (error) return(error); if (job->ACstepType != LINEAR) { - SPfrontEnd->OUTattributes (acPlot, NULL, OUT_SCALE_LOG, NULL); - } + SPfrontEnd->OUTattributes(acPlot, NULL, OUT_SCALE_LOG, NULL); + } freq = job->ACstartFreq; - } else { /* continue previous analysis */ + } + else { /* continue previous analysis */ freq = job->ACsaveFreq; job->ACsaveFreq = 0; /* clear the 'old' frequency */ - /* fix resume? saj, indeed !*/ - error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, - NULL, - NULL, 0, - 666, NULL, 666, - &acPlot); - /* saj*/ + /* fix resume? saj, indeed !*/ + error = SPfrontEnd->OUTpBeginPlot(NULL, NULL, + NULL, + NULL, 0, + 666, NULL, 666, + &acPlot); + /* saj*/ } - + switch (job->ACstepType) { case DECADE: case OCTAVE: @@ -238,14 +239,14 @@ ACan(CKTcircuit *ckt, int restart) #ifdef XSPICE -/* gtri - add - wbk - 12/19/90 - Set anal_init and anal_type */ + /* gtri - add - wbk - 12/19/90 - Set anal_init and anal_type */ g_mif_info.circuit.anal_init = MIF_TRUE; /* Tell the code models what mode we're in */ g_mif_info.circuit.anal_type = MIF_AC; -/* gtri - end - wbk */ + /* gtri - end - wbk */ #endif INIT_STATS(); @@ -254,19 +255,19 @@ ACan(CKTcircuit *ckt, int restart) /* main loop through all scheduled frequencies */ while (freq <= job->ACstopFreq + freqTol) { - if(SPfrontEnd->IFpauseTest()) { + if (SPfrontEnd->IFpauseTest()) { /* user asked us to pause via an interrupt */ job->ACsaveFreq = freq; return(E_PAUSE); } - ckt->CKTomega = 2.0 * M_PI *freq; + ckt->CKTomega = 2.0 * M_PI * freq; /* Update opertating point, if variable 'hertz' is given */ if (ckt->CKTvarHertz) { #ifdef XSPICE /* Call EVTop if event-driven instances exist */ - if(ckt->evt->counts.num_insts != 0) { + if (ckt->evt->counts.num_insts != 0) { error = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, @@ -275,25 +276,25 @@ ACan(CKTcircuit *ckt, int restart) EVTdump(ckt, IPC_ANAL_DCOP, 0.0); EVTop_save(ckt, MIF_TRUE, 0.0); } - else + else #endif -// If no event-driven instances, do what SPICE normally does + // If no event-driven instances, do what SPICE normally does error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); - if(error){ - fprintf(stdout,"\nAC operating point failed -\n"); + if (error) { + fprintf(stdout, "\nAC operating point failed -\n"); CKTncDump(ckt); return(error); - } + } ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); - if(error) return(error); + if (error) return(error); } - ckt->CKTmode = (ckt->CKTmode&MODEUIC) | MODEAC; + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEAC; error = NIacIter(ckt); if (error) { UPDATE_STATS(DOING_AC); @@ -301,18 +302,18 @@ ACan(CKTcircuit *ckt, int restart) } #ifdef WANT_SENSE2 - if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode&ACSEN) ){ + if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & ACSEN)) { long save; int save1; save = ckt->CKTmode; - ckt->CKTmode=(ckt->CKTmode&MODEUIC)|MODEDCOP|MODEINITSMSIG; + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; save1 = ckt->CKTsenInfo->SENmode; ckt->CKTsenInfo->SENmode = ACSEN; if (freq == job->ACstartFreq) { ckt->CKTsenInfo->SENacpertflag = 1; } - else{ + else { ckt->CKTsenInfo->SENacpertflag = 0; } error = CKTsenAC(ckt); @@ -324,24 +325,24 @@ ACan(CKTcircuit *ckt, int restart) #endif #ifdef XSPICE -/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ + /* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ - if(g_ipc.enabled) + if (g_ipc.enabled) ipc_send_data_prefix(freq); - error = CKTacDump(ckt,freq,acPlot); + error = CKTacDump(ckt, freq, acPlot); - if(g_ipc.enabled) + if (g_ipc.enabled) ipc_send_data_suffix(); -/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ + /* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ #else - error = CKTacDump(ckt,freq,acPlot); + error = CKTacDump(ckt, freq, acPlot); #endif if (error) { - UPDATE_STATS(DOING_AC); - return(error); - } + UPDATE_STATS(DOING_AC); + return(error); + } /* increment frequency */ @@ -349,90 +350,90 @@ ACan(CKTcircuit *ckt, int restart) case DECADE: case OCTAVE: -/* inserted again 14.12.2001 */ + /* inserted again 14.12.2001 */ #ifdef HAS_PROGREP - { - double endfreq = job->ACstopFreq; - double startfreq = job->ACstartFreq; - endfreq = log(endfreq); - if (startfreq == 0.0) - startfreq = 1e-12; - startfreq = log(startfreq); + { + double endfreq = job->ACstopFreq; + double startfreq = job->ACstartFreq; + endfreq = log(endfreq); + if (startfreq == 0.0) + startfreq = 1e-12; + startfreq = log(startfreq); - if (freq > 0.0) - SetAnalyse( "ac", (int)((log(freq)-startfreq) * 1000.0 / (endfreq-startfreq))); - } + if (freq > 0.0) + SetAnalyse("ac", (int)((log(freq) - startfreq) * 1000.0 / (endfreq - startfreq))); + } #endif - freq *= job->ACfreqDelta; - if (job->ACfreqDelta == 1) goto endsweep; + freq *= job->ACfreqDelta; + if (job->ACfreqDelta == 1) goto endsweep; break; case LINEAR: #ifdef HAS_PROGREP - { - double endfreq = job->ACstopFreq; - double startfreq = job->ACstartFreq; - SetAnalyse( "ac", (int)((freq - startfreq)* 1000.0 / (endfreq-startfreq))); - } + { + double endfreq = job->ACstopFreq; + double startfreq = job->ACstartFreq; + SetAnalyse("ac", (int)((freq - startfreq) * 1000.0 / (endfreq - startfreq))); + } #endif - freq += job->ACfreqDelta; - if (job->ACfreqDelta == 0) goto endsweep; - break; + freq += job->ACfreqDelta; + if (job->ACfreqDelta == 0) goto endsweep; + break; default: return(E_INTERN); - + } } endsweep: - SPfrontEnd->OUTendPlot (acPlot); + SPfrontEnd->OUTendPlot(acPlot); acPlot = NULL; UPDATE_STATS(0); return(0); } - /* CKTacLoad(ckt) - * this is a driver program to iterate through all the various - * ac load functions provided for the circuit elements in the - * given circuit - */ +/* CKTacLoad(ckt) + * this is a driver program to iterate through all the various + * ac load functions provided for the circuit elements in the + * given circuit + */ int -CKTacLoad(CKTcircuit *ckt) +CKTacLoad(CKTcircuit* ckt) { int i; int size; int error; double startTime; - startTime = SPfrontEnd->IFseconds(); + startTime = SPfrontEnd->IFseconds(); size = SMPmatSize(ckt->CKTmatrix); - for (i=0;i<=size;i++) { - ckt->CKTrhs[i]=0; - ckt->CKTirhs[i]=0; + for (i = 0; i <= size; i++) { + ckt->CKTrhs[i] = 0; + ckt->CKTirhs[i] = 0; } SMPcClear(ckt->CKTmatrix); - for (i=0;iDEVacLoad && ckt->CKThead[i] ) { - error = DEVices[i]->DEVacLoad (ckt->CKThead[i], ckt); - if(error) return(error); + for (i = 0; i < DEVmaxnum; i++) { + if (DEVices[i] && DEVices[i]->DEVacLoad && ckt->CKThead[i]) { + error = DEVices[i]->DEVacLoad(ckt->CKThead[i], ckt); + if (error) return(error); } } - -#ifdef XSPICE - /* gtri - begin - Put resistors to ground at all nodes. */ - /* Value of resistor is set by new "rshunt" option. */ - if(ckt->enh->rshunt_data.enabled) { - for(i = 0; i < ckt->enh->rshunt_data.num_nodes; i++) { - *(ckt->enh->rshunt_data.diag[i]) += - ckt->enh->rshunt_data.gshunt; - } +#ifdef XSPICE + /* gtri - begin - Put resistors to ground at all nodes. */ + /* Value of resistor is set by new "rshunt" option. */ + + if (ckt->enh->rshunt_data.enabled) { + for (i = 0; i < ckt->enh->rshunt_data.num_nodes; i++) { + *(ckt->enh->rshunt_data.diag[i]) += + ckt->enh->rshunt_data.gshunt; + } } /* gtri - end - Put resistors to ground at all nodes */ @@ -451,7 +452,7 @@ CKTacLoad(CKTcircuit *ckt) /* gtri - end - wbk - 11/26/90 */ #endif - + ckt->CKTstat->STATloadTime += SPfrontEnd->IFseconds() - startTime; return(OK); } diff --git a/src/spicelib/analysis/noisean.c b/src/spicelib/analysis/noisean.c index d4824ce49..ec5d0c281 100644 --- a/src/spicelib/analysis/noisean.c +++ b/src/spicelib/analysis/noisean.c @@ -21,18 +21,28 @@ Modified: 2001 AlansFixes #include "vsrc/vsrcdefs.h" #include "isrc/isrcdefs.h" -// fixme -// ugly hack to work around missing api to specify the "type" of signals +#ifdef XSPICE +#include "ngspice/evt.h" +#include "ngspice/enh.h" + /* gtri - add - wbk - 12/19/90 - Add headers */ +#include "ngspice/mif.h" +#include "ngspice/evtproto.h" +#include "ngspice/ipctiein.h" +/* gtri - end - wbk */ +#endif + + // fixme + // ugly hack to work around missing api to specify the "type" of signals extern int fixme_onoise_type; extern int fixme_inoise_type; int -NOISEan (CKTcircuit *ckt, int restart) +NOISEan(CKTcircuit* ckt, int restart) { /* variable must be static, for continuation of interrupted (Ctrl-C), longer lasting noise anlysis */ - static Ndata *data; + static Ndata* data; double realVal; double imagVal; @@ -44,32 +54,52 @@ NOISEan (CKTcircuit *ckt, int restart) double freqTol; /* tolerence parameter for finding final frequency; hack */ int i, src_type; - NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; - GENinstance *inst = CKTfndDev(ckt, job->input); + int numNames; + IFuid* nameList; /* va: tmalloc'ed list of names */ + static runDesc* noiPlot = NULL; + runDesc* plot = NULL; + +#ifdef XSPICE + /* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */ + + /* Tell the beginPlot routine what mode we're in */ + g_ipc.anal_type = IPC_ANAL_NOI; + + /* Tell the code models what mode we're in */ + g_mif_info.circuit.anal_type = MIF_DC; + g_mif_info.circuit.anal_init = MIF_TRUE; + + /* gtri - end - wbk */ +#endif + + NOISEAN* job = (NOISEAN*)ckt->CKTcurJob; + GENinstance* inst = CKTfndDev(ckt, job->input); bool frequequal = AlmostEqualUlps(job->NstartFreq, job->NstopFreq, 3); - posOutNode = (job->output) -> number; - negOutNode = (job->outputRef) -> number; + posOutNode = (job->output)->number; + negOutNode = (job->outputRef)->number; if (job->NnumSteps < 1) { SPfrontEnd->IFerrorf(ERR_WARNING, - "Number of steps for noise measurement has to be larger than 0,\n but currently is %d\n", - job->NnumSteps); + "Number of steps for noise measurement has to be larger than 0,\n but currently is %d\n", + job->NnumSteps); return(E_PARMVAL); - } else if ((job->NnumSteps == 1) && (job->NstpType == LINEAR)) { + } + else if ((job->NnumSteps == 1) && (job->NstpType == LINEAR)) { if (!frequequal) { job->NstopFreq = job->NstartFreq; SPfrontEnd->IFerrorf(ERR_WARNING, - "Noise measurement at a single frequency %g only!\n", - job->NstartFreq); + "Noise measurement at a single frequency %g only!\n", + job->NstartFreq); } - } else { + } + else { if (frequequal) { job->NstopFreq = job->NstartFreq; job->NnumSteps = 1; SPfrontEnd->IFerrorf(ERR_WARNING, - "Noise measurement at a single frequency %g only!\n", - job->NstartFreq); + "Noise measurement at a single frequency %g only!\n", + job->NstartFreq); } } /* see if the source specified is AC */ @@ -77,45 +107,47 @@ NOISEan (CKTcircuit *ckt, int restart) bool ac_given = FALSE; if (!inst || inst->GENmodPtr->GENmodType < 0) { - SPfrontEnd->IFerrorf (ERR_WARNING, - "Noise input source %s not in circuit", - job->input); + SPfrontEnd->IFerrorf(ERR_WARNING, + "Noise input source %s not in circuit", + job->input); return E_NOTFOUND; } if (inst->GENmodPtr->GENmodType == CKTtypelook("Vsource")) { - ac_given = ((VSRCinstance *)inst) -> VSRCacGiven; + ac_given = ((VSRCinstance*)inst)->VSRCacGiven; src_type = SV_VOLTAGE; - } else if(inst->GENmodPtr->GENmodType == CKTtypelook("Isource")) { - ac_given = ((ISRCinstance *)inst) -> ISRCacGiven; + } + else if (inst->GENmodPtr->GENmodType == CKTtypelook("Isource")) { + ac_given = ((ISRCinstance*)inst)->ISRCacGiven; src_type = SV_CURRENT; - } else { - SPfrontEnd->IFerrorf (ERR_WARNING, - "Noise input source %s is not of proper type", - job->input); + } + else { + SPfrontEnd->IFerrorf(ERR_WARNING, + "Noise input source %s is not of proper type", + job->input); return E_NOTFOUND; } if (!ac_given) { - SPfrontEnd->IFerrorf (ERR_WARNING, - "Noise input source %s has no AC value", - job->input); + SPfrontEnd->IFerrorf(ERR_WARNING, + "Noise input source %s has no AC value", + job->input); return E_NOACINPUT; } } - if ( (job->NsavFstp == 0.0) || restart) { /* va, NsavFstp is double */ + if ((job->NsavFstp == 0.0) || restart) { /* va, NsavFstp is double */ switch (job->NstpType) { case DECADE: - job->NfreqDelta = exp(log(10.0)/ - job->NnumSteps); + job->NfreqDelta = exp(log(10.0) / + job->NnumSteps); break; case OCTAVE: - job->NfreqDelta = exp(log(2.0)/ - job->NnumSteps); + job->NfreqDelta = exp(log(2.0) / + job->NnumSteps); break; case LINEAR: @@ -123,24 +155,98 @@ NOISEan (CKTcircuit *ckt, int restart) job->NfreqDelta = 0; else job->NfreqDelta = (job->NstopFreq - - job->NstartFreq) / (job->NnumSteps - 1); + job->NstartFreq) / (job->NnumSteps - 1); break; default: return(E_BADPARM); } - /* error = DCop(ckt); */ - error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, - ckt->CKTdcMaxIter); +#ifdef XSPICE + /* gtri - begin - wbk - Call EVTop if event-driven instances exist */ + + if (ckt->evt->counts.num_insts != 0) { + error = EVTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter, + MIF_TRUE); + EVTdump(ckt, IPC_ANAL_DCOP, 0.0); + EVTop_save(ckt, MIF_TRUE, 0.0); + } + else +#endif + /* If no event-driven instances, do what SPICE normally does */ + if (!ckt->CKTnoopac) { /* skip OP if option NOOPAC is set and circuit is linear */ + error = CKTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter); + + if (error) { + fprintf(stdout, "\nNOISE operating point failed -\n"); + CKTncDump(ckt); + return(error); + } + } + else + fprintf(stdout, "\n Linear circuit, option noopac given: no OP analysis\n"); + +#ifdef XSPICE + /* gtri - add - wbk - 12/19/90 - Add IPC stuff */ + + /* Send the operating point results for Mspice compatibility */ + if (g_ipc.enabled) + { + /* Call CKTnames to get names of nodes/branches used by + BeginPlot */ + /* Probably should free nameList after this block since + called again... */ + error = CKTnames(ckt, &numNames, &nameList); + if (error) return(error); + + /* We have to do a beginPlot here since the data to return is + * different for the DCOP than it is for the AC analysis. + * Moreover the begin plot has not even been done yet at this + * point... + */ + SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob, + ckt->CKTcurJob->JOBname, + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &noiPlot); + txfree(nameList); + + ipc_send_dcop_prefix(); + CKTdump(ckt, 0.0, noiPlot); + ipc_send_dcop_suffix(); + + SPfrontEnd->OUTendPlot(noiPlot); + } + /* gtri - end - wbk */ +#endif - if (error) return(error); /* Patch to noisean.c by Richard D. McRoberts. */ ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); - if(error) return(error); + if (error) return(error); + + error = CKTnames(ckt, &numNames, &nameList); + if (error) return(error); + + if (ckt->CKTkeepOpInfo) { + /* Dump operating point. */ + error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob, + "NOISE Operating Point", + NULL, IF_REAL, + numNames, nameList, IF_REAL, + &plot); + if (error) return(error); + CKTdump(ckt, 0.0, plot); + SPfrontEnd->OUTendPlot(plot); + plot = NULL; + } data = TMALLOC(Ndata, 1); step = 0; @@ -152,10 +258,10 @@ NOISEan (CKTcircuit *ckt, int restart) /* the current front-end needs the namelist to be fully declared before an OUTpBeginplot */ - SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); + SPfrontEnd->IFnewUid(ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); data->numPlots = 0; /* we don't have any plots yet */ - error = CKTnoise(ckt,N_DENS,N_OPEN,data); + error = CKTnoise(ckt, N_DENS, N_OPEN, data); if (error) return(error); /* @@ -165,10 +271,10 @@ NOISEan (CKTcircuit *ckt, int restart) if (src_type == SV_VOLTAGE) fixme_inoise_type = - data->squared ? SV_SQR_VOLTAGE_DENSITY : SV_VOLTAGE_DENSITY; + data->squared ? SV_SQR_VOLTAGE_DENSITY : SV_VOLTAGE_DENSITY; else fixme_inoise_type = - data->squared ? SV_SQR_CURRENT_DENSITY : SV_CURRENT_DENSITY; + data->squared ? SV_SQR_CURRENT_DENSITY : SV_CURRENT_DENSITY; fixme_onoise_type = data->squared ? SV_SQR_VOLTAGE_DENSITY : SV_VOLTAGE_DENSITY; @@ -176,36 +282,37 @@ NOISEan (CKTcircuit *ckt, int restart) if (!data->squared) for (i = 0; i < data->numPlots; i++) data->squared_value[i] = - ciprefix("inoise", data->namelist[i]) || - ciprefix("onoise", data->namelist[i]); + ciprefix("inoise", data->namelist[i]) || + ciprefix("onoise", data->namelist[i]); - error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, - data->squared - ? "Noise Spectral Density Curves - (V^2 or A^2)/Hz" + error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob, + data->squared + ? "Noise Spectral Density Curves - (V^2 or A^2)/Hz" - : "Noise Spectral Density Curves", - freqUid, IF_REAL, - data->numPlots, data->namelist, IF_REAL, - &(data->NplotPtr)); + : "Noise Spectral Density Curves", + freqUid, IF_REAL, + data->numPlots, data->namelist, IF_REAL, + &(data->NplotPtr)); if (error) return(error); if (job->NstpType != LINEAR) { - SPfrontEnd->OUTattributes (data->NplotPtr, NULL, OUT_SCALE_LOG, NULL); + SPfrontEnd->OUTattributes(data->NplotPtr, NULL, OUT_SCALE_LOG, NULL); } - } else { /* we must have paused before. pick up where we left off */ + } + else { /* we must have paused before. pick up where we left off */ step = (int)(job->NsavFstp); switch (job->NstpType) { case DECADE: case OCTAVE: - data->freq = job->NstartFreq * exp (step * - log (job->NfreqDelta)); + data->freq = job->NstartFreq * exp(step * + log(job->NfreqDelta)); break; case LINEAR: data->freq = job->NstartFreq + step * - job->NfreqDelta; + job->NfreqDelta; break; default: @@ -216,11 +323,11 @@ NOISEan (CKTcircuit *ckt, int restart) data->outNoiz = job->NsavOnoise; data->inNoise = job->NsavInoise; /* saj resume rawfile fix*/ - error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, - NULL, - NULL, 0, - 666, NULL, 666, - &(data->NplotPtr)); + error = SPfrontEnd->OUTpBeginPlot(NULL, NULL, + NULL, + NULL, 0, + 666, NULL, 666, + &(data->NplotPtr)); /*saj*/ } @@ -238,10 +345,22 @@ NOISEan (CKTcircuit *ckt, int restart) data->lstFreq = data->freq; +#ifdef XSPICE + /* gtri - add - wbk - 12/19/90 - Set anal_init and anal_type */ + + g_mif_info.circuit.anal_init = MIF_TRUE; + + /* Tell the code models what mode we're in */ + /* MIF_NOI is not yet supported by code models, so use their AC capabilities */ + g_mif_info.circuit.anal_type = MIF_AC; + + /* gtri - end - wbk */ +#endif + /* do the noise analysis over all frequencies */ while (data->freq <= job->NstopFreq + freqTol) { - if(SPfrontEnd->IFpauseTest()) { + if (SPfrontEnd->IFpauseTest()) { job->NsavFstp = step; /* save our results */ job->NsavOnoise = data->outNoiz; /* up until now */ job->NsavInoise = data->inNoise; @@ -257,12 +376,12 @@ NOISEan (CKTcircuit *ckt, int restart) */ NIacIter(ckt); - realVal = ckt->CKTrhsOld [posOutNode] - - ckt->CKTrhsOld [negOutNode]; - imagVal = ckt->CKTirhsOld [posOutNode] - - ckt->CKTirhsOld [negOutNode]; - data->GainSqInv = 1.0 / MAX(((realVal*realVal) - + (imagVal*imagVal)),N_MINGAIN); + realVal = ckt->CKTrhsOld[posOutNode] + - ckt->CKTrhsOld[negOutNode]; + imagVal = ckt->CKTirhsOld[posOutNode] + - ckt->CKTirhsOld[negOutNode]; + data->GainSqInv = 1.0 / MAX(((realVal * realVal) + + (imagVal * imagVal)), N_MINGAIN); data->lnGainInv = log(data->GainSqInv); /* set up a block of "common" data so we don't have to @@ -270,13 +389,14 @@ NOISEan (CKTcircuit *ckt, int restart) */ data->delFreq = data->freq - data->lstFreq; - data->lnFreq = log(MAX(data->freq,N_MINLOG)); - data->lnLastFreq = log(MAX(data->lstFreq,N_MINLOG)); + data->lnFreq = log(MAX(data->freq, N_MINLOG)); + data->lnLastFreq = log(MAX(data->lstFreq, N_MINLOG)); data->delLnFreq = data->lnFreq - data->lnLastFreq; if ((job->NStpsSm != 0) && ((step % (job->NStpsSm)) == 0)) { data->prtSummary = TRUE; - } else { + } + else { data->prtSummary = FALSE; } @@ -289,13 +409,13 @@ NOISEan (CKTcircuit *ckt, int restart) * it will be given in refVal.rValue (see later) */ - NInzIter(ckt,posOutNode,negOutNode); /* solve the adjoint system */ + NInzIter(ckt, posOutNode, negOutNode); /* solve the adjoint system */ /* now we use the adjoint system to calculate the noise * contributions of each generator in the circuit */ - error = CKTnoise(ckt,N_DENS,N_CALC,data); + error = CKTnoise(ckt, N_DENS, N_CALC, data); if (error) return(error); data->lstFreq = data->freq; @@ -321,23 +441,23 @@ NOISEan (CKTcircuit *ckt, int restart) break; } - error = CKTnoise(ckt,N_DENS,N_CLOSE,data); + error = CKTnoise(ckt, N_DENS, N_CLOSE, data); if (error) return(error); data->numPlots = 0; data->outNumber = 0; if (job->NstartFreq != job->NstopFreq) { - error = CKTnoise(ckt,INT_NOIZ,N_OPEN,data); + error = CKTnoise(ckt, INT_NOIZ, N_OPEN, data); if (error) return(error); if (src_type == SV_VOLTAGE) fixme_inoise_type = - data->squared ? SV_SQR_VOLTAGE : SV_VOLTAGE; + data->squared ? SV_SQR_VOLTAGE : SV_VOLTAGE; else fixme_inoise_type = - data->squared ? SV_SQR_CURRENT : SV_CURRENT; + data->squared ? SV_SQR_CURRENT : SV_CURRENT; fixme_onoise_type = data->squared ? SV_SQR_VOLTAGE : SV_VOLTAGE; @@ -345,21 +465,21 @@ NOISEan (CKTcircuit *ckt, int restart) if (!data->squared) for (i = 0; i < data->numPlots; i++) data->squared_value[i] = - ciprefix("inoise", data->namelist[i]) || - ciprefix("onoise", data->namelist[i]); + ciprefix("inoise", data->namelist[i]) || + ciprefix("onoise", data->namelist[i]); - SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, - data->squared - ? "Integrated Noise - V^2 or A^2" - : "Integrated Noise", - NULL, 0, - data->numPlots, data->namelist, IF_REAL, - &(data->NplotPtr)); + SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob, + data->squared + ? "Integrated Noise - V^2 or A^2" + : "Integrated Noise", + NULL, 0, + data->numPlots, data->namelist, IF_REAL, + &(data->NplotPtr)); - error = CKTnoise(ckt,INT_NOIZ,N_CALC,data); + error = CKTnoise(ckt, INT_NOIZ, N_CALC, data); if (error) return(error); - error = CKTnoise(ckt,INT_NOIZ,N_CLOSE,data); + error = CKTnoise(ckt, INT_NOIZ, N_CLOSE, data); if (error) return(error); } diff --git a/src/spicelib/devices/vbic/vbicsetup.c b/src/spicelib/devices/vbic/vbicsetup.c index bbb90f7ae..e679fcf74 100644 --- a/src/spicelib/devices/vbic/vbicsetup.c +++ b/src/spicelib/devices/vbic/vbicsetup.c @@ -487,11 +487,16 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) } } - if((model->VBICthermalResistGiven) && (model->VBICthermalResist > 0.0) - && model->VBICselftGiven && model->VBICselft == 1) - here->VBIC_selfheat = 1; + if(model->VBICselftGiven) + if(model->VBICselft == 1) + here->VBIC_selfheat = 1; + else + here->VBIC_selfheat = 0; else - here->VBIC_selfheat = 0; + if((model->VBICthermalResistGiven) && (model->VBICthermalResist > 0.0)) + here->VBIC_selfheat = 1; + else + here->VBIC_selfheat = 0; if((model->VBICthermalResistGiven) && (model->VBICthermalCapacitance < 1e-12)) model->VBICthermalCapacitance = 1e-12; diff --git a/src/spicelib/devices/vbic/vbicsoachk.c b/src/spicelib/devices/vbic/vbicsoachk.c index c436b16d7..4b5a26ee7 100644 --- a/src/spicelib/devices/vbic/vbicsoachk.c +++ b/src/spicelib/devices/vbic/vbicsoachk.c @@ -72,7 +72,7 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) if (vsub > model->VBICvsubMax) if (warns_vsub < maxwarns) { soa_printf(ckt, (GENinstance*)here, - "|Vce|=%g has exceeded Vce_max=%g\n", + "|Vcs|=%g has exceeded Vcs_max=%g\n", vsub, model->VBICvsubMax); warns_vsub++; }