From d53acbed8e73797f8639928603c284a3de6aca7b Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 29 Mar 2023 14:28:48 +0200 Subject: [PATCH] Add noise capability to XSPICE code models Coded according to acan., AC analysis MIF_NOI is not yet supported by any code model, so MIF_AC is used (code models behave like in ac mode, they are noiseless. --- src/include/ngspice/ipc.h | 3 +- src/include/ngspice/miftypes.h | 1 + src/spicelib/analysis/noisean.c | 124 ++++++++++++++++++++++++++++++-- 3 files changed, 122 insertions(+), 6 deletions(-) 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/noisean.c b/src/spicelib/analysis/noisean.c index a53f55a73..ec5d0c281 100644 --- a/src/spicelib/analysis/noisean.c +++ b/src/spicelib/analysis/noisean.c @@ -21,6 +21,16 @@ Modified: 2001 AlansFixes #include "vsrc/vsrcdefs.h" #include "isrc/isrcdefs.h" +#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; @@ -44,6 +54,24 @@ NOISEan(CKTcircuit* ckt, int restart) double freqTol; /* tolerence parameter for finding final frequency; hack */ int i, src_type; + 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); @@ -134,18 +162,92 @@ NOISEan(CKTcircuit* ckt, int restart) 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); + 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; data->freq = job->NstartFreq; @@ -243,6 +345,18 @@ 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) {