From 3c41ab1190dd3365c9b722b2cf0ddcde621518b5 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 29 Mar 2023 14:25:35 +0200 Subject: [PATCH 1/6] Formatting with MSVC2022 --- src/spicelib/analysis/acan.c | 363 ++++++++++++++++---------------- src/spicelib/analysis/noisean.c | 182 ++++++++-------- 2 files changed, 276 insertions(+), 269 deletions(-) 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..a53f55a73 100644 --- a/src/spicelib/analysis/noisean.c +++ b/src/spicelib/analysis/noisean.c @@ -21,18 +21,18 @@ 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 + // 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 +44,34 @@ 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); + 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 +79,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,7 +127,7 @@ 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: @@ -132,15 +136,15 @@ NOISEan (CKTcircuit *ckt, int restart) /* error = DCop(ckt); */ error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, - (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, - ckt->CKTdcMaxIter); + (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, + ckt->CKTdcMaxIter); 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); data = TMALLOC(Ndata, 1); step = 0; @@ -152,10 +156,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 +169,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 +180,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 +221,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*/ } @@ -241,7 +246,7 @@ NOISEan (CKTcircuit *ckt, int restart) /* 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 +262,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 +275,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 +295,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 +327,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 +351,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); } From d53acbed8e73797f8639928603c284a3de6aca7b Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 29 Mar 2023 14:28:48 +0200 Subject: [PATCH 2/6] 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) { From a3bc6ae744397cd1302869aa9a4661c7d44a433b Mon Sep 17 00:00:00 2001 From: dwarning Date: Sun, 2 Apr 2023 17:22:52 +0200 Subject: [PATCH 3/6] vbic: selfheating switch selft has priority, but keep compatibility --- src/spicelib/devices/vbic/vbicsetup.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) 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; From 33e17fa96932fc26c6dad6ec5e5c9fd1ddfceb54 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 2 Apr 2023 22:56:49 +0200 Subject: [PATCH 4/6] noise simulation examples --- examples/noise/baker-252-gain.cir | 25 ++++++++++++++++ examples/noise/resdiv.cir | 41 ++++++++++++++++++++++++++ examples/noise/resdiv_gain.cir | 48 +++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 examples/noise/baker-252-gain.cir create mode 100644 examples/noise/resdiv.cir create mode 100644 examples/noise/resdiv_gain.cir 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 + + From a531d8428c8b9c4fb5157444a5475eff2f8e57da Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Sat, 1 Apr 2023 10:28:04 -0700 Subject: [PATCH 5/6] Use ~ on the input of a tristate buffer for INV3, and avoid creating an extra inverter. For ff/latch use ~ on set/reset and jkff clock inputs to avoid creating extra inverters. --- examples/digital/digital_devices/ex5.cir | 5 +- src/frontend/udevices.c | 429 +++++++++++++++-------- 2 files changed, 293 insertions(+), 141 deletions(-) diff --git a/examples/digital/digital_devices/ex5.cir b/examples/digital/digital_devices/ex5.cir index 059cc6c30..b87218cef 100644 --- a/examples/digital/digital_devices/ex5.cir +++ b/examples/digital/digital_devices/ex5.cir @@ -78,7 +78,7 @@ x2 oeb clk 1in 2in 3in 4in 5in 6in 7in 8in q1 q2 q3 q4 q5 q6 q7 q8 74lv574a a1 [oeb clk 1in 2in 3in 4in 5in 6in 7in 8in] input_vec1 .model input_vec1 d_source(input_file = "ex5.stim") -x3 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 74als242b +x3 oeb oeb 1in 2in 3in 4in 1006 1007 1008 1009 74als242b * ----------------------------------------------------------- 74ALS242B ------ * Quad Bus Transceivers With 3-State Outputs @@ -119,12 +119,13 @@ uf2 inv3a(4) DPWR DGND .save all .control -listing expand +listing r expand run *display *edisplay eprint o1 o2 o3 o4 o5 o6 o7 o8 eprint q1 q2 q3 q4 q5 q6 q7 q8 +eprint 1006 1007 1008 1009 *set xbrushwidth=2 plot o1 o2 o3 o4 o5 o6 o7 o8 q1 q2 q3 q4 q5 q6 q7 q8 digitop *quit diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index 09a3ddf3e..60677cea4 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -302,6 +302,9 @@ static int ps_udevice_msgs = 0; // Controls the verbosity of U* warnings If ps_udevice_exit is non-zero then exit when u_process_instance fails */ static int ps_udevice_exit = 0; +static int ps_tpz_delays = 0; // For tristate delays +static int ps_with_inverters = 0; // For ff/latch control inputs +static int ps_with_tri_inverters = 0; // For inv3/inv3a data inputs static NAME_ENTRY new_names_list = NULL; static NAME_ENTRY input_names_list = NULL; static NAME_ENTRY output_names_list = NULL; @@ -881,6 +884,21 @@ void initialize_udevice(char *subckt_line) if (!cp_getvar("ps_udevice_exit", CP_NUM, &ps_udevice_exit, 0)) { ps_udevice_exit = 0; } + /* + Use tpzh.., tpzl.., tphz.., tplz.. for tristates + if they are the only delays. + */ + if (!cp_getvar("ps_tpz_delays", CP_NUM, &ps_tpz_delays, 0)) { + ps_tpz_delays = 0; + } + /* If non-zero use inverters with ff/latch control inputs */ + if (!cp_getvar("ps_with_inverters", CP_NUM, &ps_with_inverters, 0)) { + ps_with_inverters = 0; + } + /* If non-zero use inverters for inv3/inv3a, instead use ~ */ + if (!cp_getvar("ps_with_tri_inverters", CP_NUM, &ps_with_tri_inverters, 0)) { + ps_with_tri_inverters = 0; + } if (subckt_line && strncmp(subckt_line, ".subckt", 7) == 0) { add_all_port_names(subckt_line); current_subckt = TMALLOC(char, strlen(subckt_line) + 1); @@ -1635,7 +1653,7 @@ static BOOL gen_timing_model( } -static Xlatorp gen_dff_instance(struct dff_instance *ip) +static Xlatorp gen_dff_instance(struct dff_instance *ip, int withinv) { char *itype, *iname, **darr, **qarr, **qbarr; char *preb, *clrb, *clk, *tmodel, *qout, *qbout; @@ -1644,8 +1662,12 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip) Xlatorp xxp = NULL; Xlatep xdata = NULL; BOOL need_preb_inv = FALSE, need_clrb_inv = FALSE; + DS_CREATE(tmpdstr, 128); - if (!ip) { return NULL; } + if (!ip) { + ds_free(&tmpdstr); + return NULL; + } itype = ip->hdrp->instance_type; iname = ip->hdrp->instance_name; num_gates = ip->num_gates; @@ -1656,20 +1678,24 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip) clrb = ip->clrbar; xxp = create_xlator(); - add_input_pin(preb); if (eq(preb, "$d_hi")) { preb = "NULL"; } else { + add_input_pin(preb); need_preb_inv = TRUE; - preb = new_inverter(iname, preb, xxp); + if (withinv) { + preb = new_inverter(iname, preb, xxp); + } } - add_input_pin(clrb); if (eq(clrb, "$d_hi")) { clrb = "NULL"; } else { + add_input_pin(clrb); need_clrb_inv = TRUE; - clrb = new_inverter(iname, clrb, xxp); + if (withinv) { + clrb = new_inverter(iname, clrb, xxp); + } } clk = ip->clk; @@ -1679,41 +1705,67 @@ static Xlatorp gen_dff_instance(struct dff_instance *ip) modelnm = tprintf("d_a%s_%s", iname, itype); for (i = 0; i < num_gates; i++) { char *instance_name = NULL; + ds_clear(&tmpdstr); qout = qarr[i]; - add_output_pin(qout); if (eq(qout, "$d_nc")) { qout = "NULL"; + } else { + add_output_pin(qout); } qbout = qbarr[i]; - add_output_pin(qbout); if (eq(qbout, "$d_nc")) { qbout = "NULL"; + } else { + add_output_pin(qbout); } add_input_pin(darr[i]); instance_name = tprintf("a%s_%d", iname, i); - s1 = tprintf( "%s %s %s %s %s %s %s %s", - instance_name, darr[i], clk, preb, clrb, qout, qbout, modelnm - ); - xdata = create_xlate_instance(s1, " d_dff", tmodel, modelnm); - xxp = add_xlator(xxp, xdata); - tfree(s1); + if (withinv) { + s1 = tprintf( "%s %s %s %s %s %s %s %s", + instance_name, darr[i], clk, preb, clrb, qout, qbout, modelnm + ); + xdata = create_xlate_instance(s1, " d_dff", tmodel, modelnm); + xxp = add_xlator(xxp, xdata); + tfree(s1); + } else { + if (need_preb_inv) { + ds_cat_printf(&tmpdstr, "%s %s %s ~%s", + instance_name, darr[i], clk, preb); + } else { + ds_cat_printf(&tmpdstr, "%s %s %s %s", + instance_name, darr[i], clk, preb); + } + if (need_clrb_inv) { + ds_cat_printf(&tmpdstr, " ~%s %s %s %s", + clrb, qout, qbout, modelnm); + } else { + ds_cat_printf(&tmpdstr, " %s %s %s %s", + clrb, qout, qbout, modelnm); + } + xdata = create_xlate_instance(ds_get_buf(&tmpdstr), " d_dff", + tmodel, modelnm); + xxp = add_xlator(xxp, xdata); + } tfree(instance_name); } if (!gen_timing_model(tmodel, "ueff", "d_dff", modelnm, xxp)) { printf("WARNING unable to find tmodel %s for %s d_dff\n", tmodel, modelnm); } - if (need_preb_inv || need_clrb_inv) { - add_zero_delay_inverter_model = TRUE; + if (withinv) { + if (need_preb_inv || need_clrb_inv) { + add_zero_delay_inverter_model = TRUE; + } + if (need_preb_inv) { tfree(preb); } + if (need_clrb_inv) { tfree(clrb); } } - if (need_preb_inv) { tfree(preb); } - if (need_clrb_inv) { tfree(clrb); } + ds_free(&tmpdstr); tfree(modelnm); return xxp; } -static Xlatorp gen_jkff_instance(struct jkff_instance *ip) +static Xlatorp gen_jkff_instance(struct jkff_instance *ip, int withinv) { char *itype, *iname, **jarr, **karr, **qarr, **qbarr; char *preb, *clrb, *clkb, *tmodel, *qout, *qbout; @@ -1722,8 +1774,12 @@ static Xlatorp gen_jkff_instance(struct jkff_instance *ip) Xlatorp xxp = NULL; Xlatep xdata = NULL; BOOL need_preb_inv = FALSE, need_clrb_inv = FALSE; + DS_CREATE(tmpdstr, 128); - if (!ip) { return NULL; } + if (!ip) { + ds_free(&tmpdstr); + return NULL; + } itype = ip->hdrp->instance_type; iname = ip->hdrp->instance_name; num_gates = ip->num_gates; @@ -1735,68 +1791,100 @@ static Xlatorp gen_jkff_instance(struct jkff_instance *ip) clrb = ip->clrbar; xxp = create_xlator(); - add_input_pin(preb); if (eq(preb, "$d_hi")) { preb = "NULL"; } else { + add_input_pin(preb); need_preb_inv = TRUE; - preb = new_inverter(iname, preb, xxp); + if (withinv) { + preb = new_inverter(iname, preb, xxp); + } } - add_input_pin(clrb); if (eq(clrb, "$d_hi")) { clrb = "NULL"; } else { + add_input_pin(clrb); need_clrb_inv = TRUE; - clrb = new_inverter(iname, clrb, xxp); + if (withinv) { + clrb = new_inverter(iname, clrb, xxp); + } } /* require a positive edge clock */ clkb = ip->clkbar; add_input_pin(clkb); - clkb = new_inverter(iname, clkb, xxp); + if (withinv) { + clkb = new_inverter(iname, clkb, xxp); + } tmodel = ip->tmodel; /* model name, same for each jkff */ modelnm = tprintf("d_a%s_%s", iname, itype); for (i = 0; i < num_gates; i++) { char *instance_name = NULL; + ds_clear(&tmpdstr); qout = qarr[i]; - add_output_pin(qout); if (eq(qout, "$d_nc")) { qout = "NULL"; + } else { + add_output_pin(qout); } qbout = qbarr[i]; - add_output_pin(qbout); if (eq(qbout, "$d_nc")) { qbout = "NULL"; + } else { + add_output_pin(qbout); } add_input_pin(jarr[i]); add_input_pin(karr[i]); instance_name = tprintf("a%s_%d", iname, i); - s1 = tprintf("%s %s %s %s %s %s %s %s %s", - instance_name, jarr[i], karr[i], clkb, preb, clrb, - qout, qbout, modelnm - ); - xdata = create_xlate_instance(s1, " d_jkff", tmodel, modelnm); - xxp = add_xlator(xxp, xdata); - tfree(s1); + if (withinv) { + s1 = tprintf("%s %s %s %s %s %s %s %s %s", + instance_name, jarr[i], karr[i], clkb, preb, clrb, + qout, qbout, modelnm + ); + xdata = create_xlate_instance(s1, " d_jkff", tmodel, modelnm); + xxp = add_xlator(xxp, xdata); + tfree(s1); + } else { + if (need_preb_inv) { + ds_cat_printf(&tmpdstr, "%s %s %s ~%s ~%s", + instance_name, jarr[i], karr[i], clkb, preb); + } else { + ds_cat_printf(&tmpdstr, "%s %s %s ~%s %s", + instance_name, jarr[i], karr[i], clkb, preb); + } + if (need_clrb_inv) { + ds_cat_printf(&tmpdstr, " ~%s %s %s %s", + clrb, qout, qbout, modelnm); + } else { + ds_cat_printf(&tmpdstr, " %s %s %s %s", + clrb, qout, qbout, modelnm); + } + xdata = create_xlate_instance(ds_get_buf(&tmpdstr), " d_jkff", + tmodel, modelnm); + xxp = add_xlator(xxp, xdata); + } tfree(instance_name); } if (!gen_timing_model(tmodel, "ueff", "d_jkff", modelnm, xxp)) { printf("WARNING unable to find tmodel %s for %s d_jkff\n", tmodel, modelnm); } - add_zero_delay_inverter_model = TRUE; - tfree(clkb); - if (need_preb_inv) { tfree(preb); } - if (need_clrb_inv) { tfree(clrb); } + if (withinv) { + add_zero_delay_inverter_model = TRUE; + tfree(clkb); + if (need_preb_inv) { tfree(preb); } + if (need_clrb_inv) { tfree(clrb); } + } + ds_free(&tmpdstr); tfree(modelnm); return xxp; } -static Xlatorp gen_dltch_instance(struct dltch_instance *ip) +static Xlatorp gen_dltch_instance(struct dltch_instance *ip, int withinv) { char *itype, *iname, **darr, **qarr, **qbarr; char *preb, *clrb, *gate, *tmodel, *qout, *qbout; @@ -1817,20 +1905,24 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip) clrb = ip->clrbar; xxp = create_xlator(); - add_input_pin(preb); if (eq(preb, "$d_hi")) { preb = "NULL"; } else { + add_input_pin(preb); need_preb_inv = TRUE; - preb = new_inverter(iname, preb, xxp); + if (withinv) { + preb = new_inverter(iname, preb, xxp); + } } - add_input_pin(clrb); if (eq(clrb, "$d_hi")) { clrb = "NULL"; } else { + add_input_pin(clrb); need_clrb_inv = TRUE; - clrb = new_inverter(iname, clrb, xxp); + if (withinv) { + clrb = new_inverter(iname, clrb, xxp); + } } gate = ip->gate; add_input_pin(gate); @@ -1840,31 +1932,49 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip) for (i = 0; i < num_gates; i++) { char *instance_name = NULL; qout = qarr[i]; - add_output_pin(qout); instance_name = tprintf("a%s_%d", iname, i); if (eq(qout, "$d_nc")) { /* NULL not allowed??? */ - s1 = tprintf("%s %s %s %s %s nco_%s_%d", - instance_name, darr[i], gate, preb, clrb, iname, i); s3 = tprintf("nco_%s_%d", iname, i); check_name_unused(s3); - tfree(s3); } else { - s1 = tprintf("%s %s %s %s %s %s", - instance_name, darr[i], gate, preb, clrb, qout); + add_output_pin(qout); + s3 = tprintf("%s", qout); } + if (withinv) { + s1 = tprintf("%s %s %s %s %s %s", + instance_name, darr[i], gate, preb, clrb, s3); + } else { + if (need_preb_inv) { + if (need_clrb_inv) { + s1 = tprintf("%s %s %s ~%s ~%s %s", + instance_name, darr[i], gate, preb, clrb, s3); + } else { + s1 = tprintf("%s %s %s ~%s %s %s", + instance_name, darr[i], gate, preb, clrb, s3); + } + } else if (need_clrb_inv) { + s1 = tprintf("%s %s %s %s ~%s %s", + instance_name, darr[i], gate, preb, clrb, s3); + } else { + s1 = tprintf("%s %s %s %s %s %s", + instance_name, darr[i], gate, preb, clrb, s3); + } + } + tfree(s3); add_input_pin(darr[i]); qbout = qbarr[i]; - add_output_pin(qbout); if (eq(qbout, "$d_nc")) { /* NULL not allowed??? */ - s2 = tprintf(" ncn_%s_%d %s", iname, i, modelnm); s3 = tprintf("ncn_%s_%d", iname, i); check_name_unused(s3); - tfree(s3); } else { - s2 = tprintf(" %s %s", qbout, modelnm); + add_output_pin(qbout); + s3 = tprintf("%s", qbout); } + s2 = tprintf(" %s %s", s3, modelnm); + tfree(s3); + s3 = tprintf("%s%s", s1, s2); xdata = create_xlate_instance(s3, " d_dlatch", tmodel, modelnm); xxp = add_xlator(xxp, xdata); @@ -1877,17 +1987,19 @@ static Xlatorp gen_dltch_instance(struct dltch_instance *ip) printf("WARNING unable to find tmodel %s for %s d_dlatch\n", tmodel, modelnm); } - if (need_preb_inv || need_clrb_inv) { - add_zero_delay_inverter_model = TRUE; + if (withinv) { + if (need_preb_inv || need_clrb_inv) { + add_zero_delay_inverter_model = TRUE; + } + if (need_preb_inv) { tfree(preb); } + if (need_clrb_inv) { tfree(clrb); } } - if (need_preb_inv) { tfree(preb); } - if (need_clrb_inv) { tfree(clrb); } tfree(modelnm); return xxp; } -static Xlatorp gen_srff_instance(struct srff_instance *srffp) +static Xlatorp gen_srff_instance(struct srff_instance *srffp, int withinv) { char *itype, *iname, **sarr, **rarr, **qarr, **qbarr; char *preb, *clrb, *gate, *tmodel, *qout, *qbout; @@ -1909,20 +2021,24 @@ static Xlatorp gen_srff_instance(struct srff_instance *srffp) clrb = srffp->clrbar; xxp = create_xlator(); - add_input_pin(preb); if (eq(preb, "$d_hi")) { preb = "NULL"; } else { + add_input_pin(preb); need_preb_inv = TRUE; - preb = new_inverter(iname, preb, xxp); + if (withinv) { + preb = new_inverter(iname, preb, xxp); + } } - add_input_pin(clrb); if (eq(clrb, "$d_hi")) { clrb = "NULL"; } else { + add_input_pin(clrb); need_clrb_inv = TRUE; - clrb = new_inverter(iname, clrb, xxp); + if (withinv) { + clrb = new_inverter(iname, clrb, xxp); + } } gate = srffp->gate; add_input_pin(gate); @@ -1932,32 +2048,51 @@ static Xlatorp gen_srff_instance(struct srff_instance *srffp) for (i = 0; i < num_gates; i++) { char *instance_name = NULL; qout = qarr[i]; - add_output_pin(qout); instance_name = tprintf("a%s_%d", iname, i); add_input_pin(sarr[i]); add_input_pin(rarr[i]); if (eq(qout, "$d_nc")) { /* NULL not allowed??? */ - s1 = tprintf("%s %s %s %s %s %s nco_%s_%d", - instance_name, sarr[i], rarr[i], gate, preb, clrb, iname, i); s3 = tprintf("nco_%s_%d", iname, i); check_name_unused(s3); - tfree(s3); } else { - s1 = tprintf("%s %s %s %s %s %s %s", - instance_name, sarr[i], rarr[i], gate, preb, clrb, qout); + add_output_pin(qout); + s3 = tprintf("%s", qout); } + if (withinv) { + s1 = tprintf("%s %s %s %s %s %s %s", + instance_name, sarr[i], rarr[i], gate, preb, clrb, s3); + } else { + if (need_preb_inv) { + if (need_clrb_inv) { + s1 = tprintf("%s %s %s %s ~%s ~%s %s", + instance_name, sarr[i], rarr[i], gate, preb, clrb, s3); + } else { + s1 = tprintf("%s %s %s %s ~%s %s %s", + instance_name, sarr[i], rarr[i], gate, preb, clrb, s3); + } + } else if (need_clrb_inv) { + s1 = tprintf("%s %s %s %s %s ~%s %s", + instance_name, sarr[i], rarr[i], gate, preb, clrb, s3); + } else { + s1 = tprintf("%s %s %s %s %s %s %s", + instance_name, sarr[i], rarr[i], gate, preb, clrb, s3); + } + } + tfree(s3); + qbout = qbarr[i]; - add_output_pin(qbout); if (eq(qbout, "$d_nc")) { /* NULL not allowed??? */ - s2 = tprintf(" ncn_%s_%d %s", iname, i, modelnm); s3 = tprintf("ncn_%s_%d", iname, i); check_name_unused(s3); - tfree(s3); } else { - s2 = tprintf(" %s %s", qbout, modelnm); + add_output_pin(qbout); + s3 = tprintf("%s", qbout); } + s2 = tprintf(" %s %s", s3, modelnm); + tfree(s3); + s3 = tprintf("%s%s", s1, s2); xdata = create_xlate_instance(s3, " d_srlatch", tmodel, modelnm); xxp = add_xlator(xxp, xdata); @@ -1970,11 +2105,13 @@ static Xlatorp gen_srff_instance(struct srff_instance *srffp) printf("WARNING unable to find tmodel %s for %s d_srlatch\n", tmodel, modelnm); } - if (need_preb_inv || need_clrb_inv) { - add_zero_delay_inverter_model = TRUE; + if (withinv) { + if (need_preb_inv || need_clrb_inv) { + add_zero_delay_inverter_model = TRUE; + } + if (need_preb_inv) { tfree(preb); } + if (need_clrb_inv) { tfree(clrb); } } - if (need_preb_inv) { tfree(preb); } - if (need_clrb_inv) { tfree(clrb); } tfree(modelnm); return xxp; @@ -2123,11 +2260,13 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) BOOL tristate_array = FALSE, simple_array = FALSE; BOOL add_tristate = FALSE; char *modelnm = NULL, *startvec = NULL, *endvec = NULL; - char *input_buf = NULL, *instance_name = NULL; + char *instance_name = NULL; int i, j, k, width, num_gates, num_ins, num_outs; - size_t sz; Xlatorp xxp = NULL; Xlatep xdata = NULL; + int withinv = ps_with_tri_inverters; + BOOL inv3_to_buf3 = FALSE; + BOOL inv3a_to_buf3a = FALSE; if (!gip) { return NULL; } itype = gip->hdrp->instance_type; @@ -2158,16 +2297,24 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) if (num_gates == 1) { char *inst_begin = NULL; + DS_CREATE(input_dstr, 128); simple_gate = is_gate(itype); tristate_gate = is_tristate(itype); - if (!simple_gate && !tristate_gate) { return NULL; } + if (!simple_gate && !tristate_gate) { + ds_free(&input_dstr); + return NULL; + } + + inv3_to_buf3 = (!withinv && eq(itype, "inv3")); add_tristate = FALSE; - if (simple_gate) { - xspice = find_xspice_for_delay(itype); - } else if (tristate_gate) { - xspice = find_xspice_for_delay(itype); + xspice = find_xspice_for_delay(itype); + if (tristate_gate) { if (!eq(itype, "buf3")) { - add_tristate = TRUE; + if (inv3_to_buf3) { + add_tristate = FALSE; + } else { + add_tristate = TRUE; + } } } xxp = create_xlator(); @@ -2180,46 +2327,46 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) endvec = ""; } /* inputs */ - /* First calculate the space */ - sz = 0; + ds_clear(&input_dstr); for (i = 0; i < width; i++) { - sz += strlen(inarr[i]) + 4; // Extra 4 spaces separating - } - input_buf = TMALLOC(char, sz); - input_buf[0] = '\0'; - for (i = 0; i < width; i++) { - sprintf(input_buf + strlen(input_buf), " %s", inarr[i]); + /* Note that width == 1 for inv3/buf3 */ + ds_cat_printf(&input_dstr, " %s", inarr[i]); } /* instance name and inputs */ /* add the tristate enable if required on original */ if (enable) { if (!add_tristate) { - /* Warning: changing the format string affects input_buf sz */ - inst_begin = tprintf("a%s %s%s%s %s", - iname, startvec, input_buf, endvec, enable); + if (inv3_to_buf3) { + inst_begin = tprintf("a%s %s ~%s %s %s", + iname, startvec, ds_get_buf(&input_dstr), endvec, enable); + } else { + inst_begin = tprintf("a%s %s%s%s %s", + iname, startvec, ds_get_buf(&input_dstr), endvec, enable); + } } else { - /* Warning: changing the format string affects input_buf sz */ inst_begin = tprintf("a%s %s%s%s", - iname, startvec, input_buf, endvec); + iname, startvec, ds_get_buf(&input_dstr), endvec); } } else { - /* Warning: changing the format string affects input_buf sz */ inst_begin = tprintf("a%s %s%s%s", - iname, startvec, input_buf, endvec); + iname, startvec, ds_get_buf(&input_dstr), endvec); } - tfree(input_buf); - - /* connector if required for tristate */ - connector = tprintf("con_a%s_%s", iname, outarr[0]); /* keep a copy of the model name of original gate */ - modelnm = tprintf("d_a%s_%s", iname, itype); + if (inv3_to_buf3) { + modelnm = tprintf("d_a%s_%s", iname, "buf3"); + } else { + modelnm = tprintf("d_a%s_%s", iname, itype); + } if (!add_tristate) { char *instance_stmt = NULL; /* add output + model name => translated instance */ instance_stmt = tprintf("%s %s %s", inst_begin, outarr[0], modelnm); + if (inv3_to_buf3) { + xspice = find_xspice_for_delay("buf3"); + } xdata = create_xlate_instance(instance_stmt, xspice, tmodel, modelnm); xxp = add_xlator(xxp, xdata); @@ -2230,7 +2377,7 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) printf("WARNING unable to find tmodel %s for %s %s\n", tmodel, modelnm, xspice); } - } else { /* must be trstate gate buf3 */ + } else { /* must be tristate gate buf3 */ if (!gen_timing_model(tmodel, "utgate", xspice, modelnm, xxp)) { printf("WARNING unable to find tmodel %s for %s %s\n", @@ -2241,6 +2388,7 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) char *new_model_nm = NULL; char *new_stmt = NULL; char *zero_rise_fall = NULL; + connector = tprintf("con_a%s_%s", iname, outarr[0]); /* Use connector as original gate output and tristate input; tristate has original gate output and utgate delay; @@ -2276,25 +2424,29 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) tmodel, new_model_nm, xspice); } tfree(new_model_nm); + tfree(connector); } - tfree(connector); tfree(modelnm); tfree(inst_begin); + ds_free(&input_dstr); return xxp; - } else { + } else { // start of array of gates char *primary_model = NULL, *s1 = NULL, *s2 = NULL, *s3 = NULL; - int ksave; + DS_CREATE(input_dstr, 128); /* arrays of gates */ simple_array = is_gate_array(itype); tristate_array = is_tristate_array(itype); + + inv3a_to_buf3a = (!withinv && eq(itype, "inv3a")); add_tristate = FALSE; - if (simple_array) { - xspice = find_xspice_for_delay(itype); - } else if (tristate_array) { - xspice = find_xspice_for_delay(itype); + xspice = find_xspice_for_delay(itype); + if (tristate_array) { if (eq(itype, "buf3a")) { add_tristate = FALSE; + } else if (inv3a_to_buf3a) { + xspice = find_xspice_for_delay("buf3a"); + add_tristate = FALSE; } else { add_tristate = TRUE; } @@ -2315,24 +2467,22 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) primary gates have zero delay models and utgate delay is added to the model of a trailing tristate buffer. */ - primary_model = tprintf("d_a%s_%s", iname, itype); - for (i = 0; i < num_gates; i++) { + if (inv3a_to_buf3a) { + primary_model = tprintf("d_a%s_%s", iname, "buf3a"); + } else { + primary_model = tprintf("d_a%s_%s", iname, itype); + } + for (i = 0; i < num_gates; i++) { // start of for each gate /* inputs */ - /* First calculate the space */ - ksave = k; - sz = 0; + ds_clear(&input_dstr); for (j = 0; j < width; j++) { /* inputs for primary gate */ - sz += strlen(inarr[k]) + 4; // Extra 4 spaces separating - k++; - } - k = ksave; - input_buf = TMALLOC(char, sz); - input_buf[0] = '\0'; - for (j = 0; j < width; j++) { - /* inputs for primary gate */ - /* Warning: changing the format string affects input_buf sz */ - sprintf(input_buf + strlen(input_buf), " %s", inarr[k]); + if (inv3a_to_buf3a && j == 0) { + /* width must be 1 */ + ds_cat_printf(&input_dstr, " ~%s", inarr[k]); + } else { + ds_cat_printf(&input_dstr, " %s", inarr[k]); + } k++; } /* create new instance name for primary gate */ @@ -2341,12 +2491,12 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) /* primary gate instance name + inputs + enable */ /* this is the buf3a case */ s1 = tprintf("a%s_%d %s%s%s %s", - iname, i, startvec, input_buf, endvec, enable); + iname, i, startvec, ds_get_buf(&input_dstr), endvec, enable); } else { /* primary gate instance name + inputs */ /* enable is added later to trailing tristate buffer */ s1 = tprintf("a%s_%d %s%s%s", - iname, i, startvec, input_buf, endvec); + iname, i, startvec, ds_get_buf(&input_dstr), endvec); /* connector if required for tristate */ connector = tprintf("con_a%s_%d_%s", iname, i, outarr[i]); check_name_unused(connector); @@ -2354,9 +2504,8 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) } else { /* primary gate instance name + inputs */ s1 = tprintf("a%s_%d %s%s%s", - iname, i, startvec, input_buf, endvec); + iname, i, startvec, ds_get_buf(&input_dstr), endvec); } - tfree(input_buf); /* output of primary gate */ if (add_tristate) { s2 = tprintf(" %s %s", connector, primary_model); @@ -2431,10 +2580,11 @@ static Xlatorp gen_gate_instance(struct gate_instance *gip) tfree(modname); tfree(connector); } - } + } // end of for each gate + ds_free(&input_dstr); tfree(primary_model); return xxp; - } + } // end of array of gates } static void extract_model_param(char *rem, char *param_name, char *buf) @@ -2681,7 +2831,7 @@ static char *get_delays_utgate(char *rem) } } else if (has_falling) { delays = tprintf("(inertial_delay=true delay = %s)", falling); - } else if (use_zdelays) { + } else if (use_zdelays || (ps_tpz_delays & 1)) { /* No lh/hl delays, so try the largest lz/hz/zl/zh delay */ tdp3 = create_min_typ_max("tplz", rem); estimate_typ(tdp3); @@ -2734,7 +2884,7 @@ static char *get_delays_utgate(char *rem) delete_timing_data(tdp4); delete_timing_data(tdp5); delete_timing_data(tdp6); - } else { // Not use_zdelays + } else { // Not use_zdelays or (ps_tpz_delays & 1) delays = tprintf("(inertial_delay=true delay=1.0e-12)"); } delete_timing_data(tdp1); @@ -3579,33 +3729,34 @@ static Xlatorp translate_ff_latch(struct instance_hdr *hdr, char *start) struct srff_instance *srffp = NULL; struct dltch_instance *dltchp = NULL; Xlatorp xp; + int withinv = ps_with_inverters; itype = hdr->instance_type; if (eq(itype, "dff")) { dffp = add_dff_inout_timing_model(hdr, start); if (dffp) { - xp = gen_dff_instance(dffp); + xp = gen_dff_instance(dffp, withinv); delete_dff_instance(dffp); return xp; } } else if (eq(itype, "jkff")) { jkffp = add_jkff_inout_timing_model(hdr, start); if (jkffp) { - xp = gen_jkff_instance(jkffp); + xp = gen_jkff_instance(jkffp, withinv); delete_jkff_instance(jkffp); return xp; } } else if (eq(itype, "srff")) { srffp = add_srff_inout_timing_model(hdr, start); if (srffp) { - xp = gen_srff_instance(srffp); + xp = gen_srff_instance(srffp, withinv); delete_srff_instance(srffp); return xp; } } else if (eq(itype, "dltch")) { dltchp = add_dltch_inout_timing_model(hdr, start); if (dltchp) { - xp = gen_dltch_instance(dltchp); + xp = gen_dltch_instance(dltchp, withinv); delete_dltch_instance(dltchp); return xp; } From 51802b8df2827d9830011213328c0058b8ad7fc7 Mon Sep 17 00:00:00 2001 From: dwarning Date: Mon, 3 Apr 2023 11:29:55 +0200 Subject: [PATCH 6/6] vbic: correct soa-check warning for C-S branch --- src/spicelib/devices/vbic/vbicsoachk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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++; }