From b8dca1b4c2e3e1b12b2dfd128be58a2fc2ed3916 Mon Sep 17 00:00:00 2001 From: pnenzi Date: Sat, 25 Jun 2005 19:11:57 +0000 Subject: [PATCH] Fixed xspice extensions. --- ChangeLog | 23 + src/spicelib/analysis/acan.c | 60 +- src/spicelib/analysis/cktdojob.c | 47 +- src/spicelib/analysis/cktload.c | 8 +- src/spicelib/analysis/cktop.c | 951 +++++++++++++++++++------------ src/spicelib/analysis/dcop.c | 65 ++- src/spicelib/analysis/dctran.c | 77 +++ src/spicelib/analysis/dctrcurv.c | 112 +++- 8 files changed, 951 insertions(+), 392 deletions(-) diff --git a/ChangeLog b/ChangeLog index b790c812e..910b10c33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2005-06-25 Paolo Nenzi + + * src/spicelib/analysis/acan.c: modified original integration of xspice + event driven algorithm into spice3 code. Now CKTncDump() is used by + xspice too. + + * src/spicelib/analysis/cktdojob.c: added ipc stuff. + + * src/spicelib/analysis/cktload.c: cosmetics. + + * src/spicelib/analysis/cktop.c: modularized the source and gmin stepping + algorithm. I have extracted the code for gmin and source stepping to + improve CKTop readability and manutenibity. + + * src/spicelib/analysis/dcop.c: added event driven algorithm and ipc stuff. + + * src/spicelib/analysis/dctran.c: added xspice breakpoint control. + + * src/spicelib/analysis/dctrcurv.c: added event driven algorithm and ipc + stuff. + + + 2005-06-12 Steven Borley * Changes supplied bt Hitoshi Tanaka to allow XSpice to compile using MinGW diff --git a/src/spicelib/analysis/acan.c b/src/spicelib/analysis/acan.c index 706134383..8cb1c86b9 100644 --- a/src/spicelib/analysis/acan.c +++ b/src/spicelib/analysis/acan.c @@ -42,17 +42,20 @@ ACan(CKTcircuit *ckt, int restart) static void *acPlot = NULL; void *plot = NULL; -/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */ + #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_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; -#endif + /* gtri - end - wbk */ +#endif + if(((ACAN*)ckt->CKTcurJob)->ACsaveFreq == 0 || restart) { /* start at beginning */ @@ -87,16 +90,8 @@ ACan(CKTcircuit *ckt, int restart) } #ifdef XSPICE /* gtri - begin - wbk - Call EVTop if event-driven instances exist */ - if(ckt->evt->counts.num_insts == 0) { - /* 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) return(error); - } - else { - /* Else, use new DCOP algorithm */ + + if(ckt->evt->counts.num_insts != 0) { error = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, @@ -104,21 +99,21 @@ ACan(CKTcircuit *ckt, int restart) MIF_TRUE); EVTdump(ckt, IPC_ANAL_DCOP, 0.0); EVTop_save(ckt, MIF_TRUE, 0.0); - if(error) - return(error); } -/* gtri - end - wbk - Call EVTop if event-driven instances exist */ -#else - error = CKTop(ckt, + else +#endif +/* 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"); CKTncDump(ckt); return(error); } -#endif #ifdef XSPICE /* gtri - add - wbk - 12/19/90 - Add IPC stuff */ @@ -126,14 +121,18 @@ ACan(CKTcircuit *ckt, int restart) /* 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... */ + /* 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... */ + /* 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))((void *)ckt,(void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,(IFuid)NULL,IF_REAL,numNames,nameList, IF_REAL,&acPlot); @@ -148,6 +147,7 @@ ACan(CKTcircuit *ckt, int restart) /* gtri - end - wbk */ #endif + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); if(error) return(error); @@ -205,14 +205,18 @@ ACan(CKTcircuit *ckt, int restart) return(E_BADPARM); } -/* gtri - add - wbk - 12/19/90 - Set anal_init and anal_type */ + #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 */ g_mif_info.circuit.anal_type = MIF_AC; -#endif + /* gtri - end - wbk */ +#endif + startTime = SPfrontEnd->IFseconds(); startdTime = ckt->CKTstat->STATdecompTime; @@ -267,8 +271,10 @@ ACan(CKTcircuit *ckt, int restart) ckt->CKTsenInfo->SENmode = save1; } #endif -/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ + #ifdef XSPICE +/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */ + if(g_ipc.enabled) ipc_send_data_prefix(freq); diff --git a/src/spicelib/analysis/cktdojob.c b/src/spicelib/analysis/cktdojob.c index b07dee15a..d039f4b3d 100644 --- a/src/spicelib/analysis/cktdojob.c +++ b/src/spicelib/analysis/cktdojob.c @@ -16,6 +16,9 @@ Modified: 2000 AlansFixes #include "mif.h" #include "evtproto.h" /* gtri - end - wbk - 11/26/90 */ +/* gtri - add - 12/12/90 - wbk - include ipc stuff */ +#include "ipctiein.h" +/* gtri - end - 12/12/90 */ #endif extern SPICEanalysis *analInfo[]; @@ -119,12 +122,52 @@ printf("Doing analysis at TEMP = %f and TNOM = %f\n", /* normal reset */ if (!error) error = CKTunsetup(ckt); + +#ifdef XSPICE + /* gtri - add - 12/12/90 - wbk - set ipc syntax error flag */ + if(error) g_ipc.syntax_error = IPC_TRUE; + /* gtri - end - 12/12/90 */ +#endif + if (!error) error = CKTsetup(ckt); + +#ifdef XSPICE + /* gtri - add - 12/12/90 - wbk - set ipc syntax error flag */ + if(error) g_ipc.syntax_error = IPC_TRUE; + /* gtri - end - 12/12/90 */ +#endif + if (!error) error = CKTtemp(ckt); - if (error) - return error; + +#ifdef XSPICE + /* gtri - add - 12/12/90 - wbk - set ipc syntax error flag */ + if(error) g_ipc.syntax_error = IPC_TRUE; + /* gtri - end - 12/12/90 */ +#endif + + if (error) { + +#ifdef XSPICE + /* gtri - add - 12/12/90 - wbk - return if syntax errors from parsing */ + if(g_ipc.enabled) { + if(g_ipc.syntax_error) + ; + else { + /* else, send (GO) errchk status if we got this far */ + /* Caller is responsible for sending NOGO status if we returned earlier */ + ipc_send_errchk(); + } + } + /* gtri - end - 12/12/90 */ +#endif + + + return error; + + + }/* if error */ } error2 = OK; diff --git a/src/spicelib/analysis/cktload.c b/src/spicelib/analysis/cktload.c index 62d34ca6d..b196d3b82 100644 --- a/src/spicelib/analysis/cktload.c +++ b/src/spicelib/analysis/cktload.c @@ -83,8 +83,10 @@ CKTload(CKTcircuit *ckt) } } - /* gtri - add - wbk - 11/26/90 - reset the MIF init flags */ + #ifdef XSPICE +/* gtri - add - wbk - 11/26/90 - reset the MIF init flags */ + /* init is set by CKTinit and should be true only for first load call */ g_mif_info.circuit.init = MIF_FALSE; @@ -104,9 +106,9 @@ CKTload(CKTcircuit *ckt) *(ckt->enh->rshunt_data.diag[i]) += gshunt; } } -#endif - /* gtri - end - Put resistors to ground at all nodes */ +/* gtri - end - Put resistors to ground at all nodes */ +#endif if(ckt->CKTmode & MODEDC) { /* consider doing nodeset & ic assignments */ diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index 1fab10816..0b64da41a 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -2,6 +2,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles Modified: 2000 AlansFixes +Modified: 2005 Paolo Nenzi - Restructured **********/ #include "ngspice.h" @@ -10,340 +11,75 @@ Modified: 2000 AlansFixes #include "sperror.h" +static int dynamic_gmin (CKTcircuit *, long int, long int, int); +static int spice3_gmin (CKTcircuit *, long int, long int, int); +static int gillespie_src (CKTcircuit *, long int, long int, int); +static int spice3_src (CKTcircuit *, long int, long int, int); + + int -CKTop(CKTcircuit *ckt, long int firstmode, long int continuemode, int iterlim) +CKTop (CKTcircuit * ckt, long int firstmode, long int continuemode, + int iterlim) { - int converged; - int i; - CKTnode *n; - double raise, ConvFact, NumNodes; - double *OldRhsOld, *OldCKTstate0; - int iters; - - ckt->CKTmode = firstmode; - if(!ckt->CKTnoOpIter) { - converged = NIiter(ckt,iterlim); + int converged; + +ckt->CKTmode = firstmode; + + if (!ckt->CKTnoOpIter){ +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + if ((ckt->CKTnumGminSteps <= 0) && (ckt->CKTnumSrcSteps <= 0)) + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + else + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + converged = NIiter (ckt, iterlim); } else { - converged = 1; /* the 'go directly to gmin stepping' option */ - } - if(converged != 0) { - /* no convergence on the first try, so we do something else */ - /* first, check if we should try gmin stepping */ - /* note that no path out of this code allows ckt->CKTdiagGmin to be - * anything but 0.000000000 - */ + converged = 1; /* the 'go directly to gmin stepping' option */ + } + + + if (converged != 0) + { + /* no convergence on the first try, so we do something else */ + /* first, check if we should try gmin stepping */ + + if (ckt->CKTnumGminSteps >= 1){ + if (ckt->CKTnumGminSteps == 1){ + converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim); + } else { + converged = spice3_gmin(ckt, firstmode, continuemode, iterlim); + } + } + if (!converged) /* If gmin-stepping worked... move out */ + return (0); + + /* ... otherwise try stepping sources ... + * now, we'll try source stepping - we scale the sources + * to 0, converge, then start stepping them up until they + * are at their normal values + */ + + if (ckt->CKTnumSrcSteps >= 1){ + if (ckt->CKTnumSrcSteps == 1) + converged = gillespie_src(ckt, firstmode, continuemode, iterlim); + else + converged = spice3_src(ckt, firstmode, continuemode, iterlim); + } +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + + } + return (converged); - if(ckt->CKTnumGminSteps ==1) { - - double OldGmin, gtarget, factor; - int success, failed; - - ckt->CKTmode = firstmode; - (*(SPfrontEnd->IFerror))(ERR_INFO, - "trying dynamic Gmin stepping",(IFuid *)NULL); - NumNodes=0; - for (n = ckt->CKTnodes; n; n = n->next) { - NumNodes++; - }; - OldRhsOld=(double *)MALLOC((NumNodes+1)*sizeof(double)); - OldCKTstate0=(double *) - MALLOC((ckt->CKTnumStates+1)*sizeof(double)); - for (n = ckt->CKTnodes; n; n = n->next) { - *(ckt->CKTrhsOld+n->number)=0; - }; - for(i=0;iCKTnumStates;i++) { - *(ckt->CKTstate0+i) = 0; - }; - factor = ckt->CKTgminFactor; - OldGmin = 1e-2; - ckt->CKTdiagGmin = OldGmin / factor; - gtarget = MAX(ckt->CKTgmin,ckt->CKTgshunt); - success = failed = 0; - - while ( (!success) && (!failed) ) { - fprintf(stderr, "\rTrying gmin = %12.4E ", ckt->CKTdiagGmin); - ckt->CKTnoncon =1; - iters = ckt->CKTstat->STATnumIter; - converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); - iters = (ckt->CKTstat->STATnumIter)-iters; - if(converged == 0) { - ckt->CKTmode=continuemode; - (*(SPfrontEnd->IFerror))(ERR_INFO, - "One successful Gmin step",(IFuid *)NULL); - if (ckt->CKTdiagGmin <= gtarget) { - success = 1; - } else { - i=0; - for (n = ckt->CKTnodes; n; n = n->next) { - OldRhsOld[i]=*(ckt->CKTrhsOld+n->number); - i++; - }; - for(i=0;iCKTnumStates;i++) { - *(OldCKTstate0+i) = *(ckt->CKTstate0+i); - }; - if (iters <= (ckt->CKTdcTrcvMaxIter/4)) { - factor *= sqrt(factor); - if (factor > ckt->CKTgminFactor) - factor = ckt->CKTgminFactor; - }; - if (iters > (3*ckt->CKTdcTrcvMaxIter/4)) { - factor = sqrt(factor); - }; - OldGmin = ckt->CKTdiagGmin; - if ((ckt->CKTdiagGmin) < (factor*gtarget)) { - factor = ckt->CKTdiagGmin / gtarget; - ckt->CKTdiagGmin = gtarget; - } else { - ckt->CKTdiagGmin /= factor; - }; - }; - } else { - if (factor < 1.00005) { - failed = 1; - (*(SPfrontEnd->IFerror))(ERR_WARNING, - "last gmin step failed",(IFuid *)NULL); - } else { - factor=sqrt(sqrt(factor)); - ckt->CKTdiagGmin = OldGmin / factor; - i=0; - for (n = ckt->CKTnodes; n; n = n->next) { - *(ckt->CKTrhsOld+n->number)=OldRhsOld[i]; - i++; - }; - for(i=0;iCKTnumStates;i++) { - *(ckt->CKTstate0+i) = *(OldCKTstate0+i); - }; - }; - } - } - ckt->CKTdiagGmin=ckt->CKTgshunt; - FREE(OldRhsOld); - FREE(OldCKTstate0); - converged = NIiter(ckt,iterlim); - if (converged!=0) { - (*(SPfrontEnd->IFerror))(ERR_WARNING, - "dynamic gmin stepping failed",(IFuid *)NULL); - } else { - (*(SPfrontEnd->IFerror))(ERR_INFO, - "Dynamic gmin stepping completed",(IFuid *)NULL); - return(0); - }; - - } else if(ckt->CKTnumGminSteps >1) { - - ckt->CKTmode = firstmode; - (*(SPfrontEnd->IFerror))(ERR_INFO, - "starting Gmin stepping",(IFuid *)NULL); - - if (ckt->CKTgshunt==0) { - ckt->CKTdiagGmin = ckt->CKTgmin; - } else { - ckt->CKTdiagGmin = ckt->CKTgshunt; - }; - - - for(i=0;iCKTnumGminSteps;i++) { - ckt->CKTdiagGmin *= ckt->CKTgminFactor; - - - } - for(i=0;i<=ckt->CKTnumGminSteps;i++) { - fprintf(stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); - ckt->CKTnoncon =1; - converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); - if(converged != 0) { - ckt->CKTdiagGmin = ckt->CKTgshunt; - - (*(SPfrontEnd->IFerror))(ERR_WARNING, - "Gmin step failed",(IFuid *)NULL); - break; - } - ckt->CKTdiagGmin /= ckt->CKTgminFactor; - ckt->CKTmode=continuemode; - (*(SPfrontEnd->IFerror))(ERR_INFO, - "One successful Gmin step",(IFuid *)NULL); - } - ckt->CKTdiagGmin = ckt->CKTgshunt; - converged = NIiter(ckt,iterlim); - if(converged == 0) { - (*(SPfrontEnd->IFerror))(ERR_INFO, - "Gmin stepping completed",(IFuid *)NULL); - return(0); - } - (*(SPfrontEnd->IFerror))(ERR_WARNING, - "Gmin stepping failed",(IFuid *)NULL); - - } - /* now, we'll try source stepping - we scale the sources - * to 0, converge, then start stepping them up until they - * are at their normal values - * - * note that no path out of this code allows ckt->CKTsrcFact to be - * anything but 1.000000000 - */ - - - if(ckt->CKTnumSrcSteps >=1) { - ckt->CKTmode = firstmode; - (*(SPfrontEnd->IFerror))(ERR_INFO, - "starting source stepping",(IFuid *)NULL); - if(ckt->CKTnumSrcSteps==1) { - ckt->CKTsrcFact=0; raise=0.001; ConvFact=0; - NumNodes=0; - for (n = ckt->CKTnodes; n; n = n->next) { - NumNodes++; - }; - OldRhsOld=(double *)MALLOC((NumNodes+1)*sizeof(double)); - OldCKTstate0=(double *) - MALLOC((ckt->CKTnumStates+1)*sizeof(double)); - for (n = ckt->CKTnodes; n; n = n->next) { - *(ckt->CKTrhsOld+n->number)=0; - }; - for(i=0;iCKTnumStates;i++) { - *(ckt->CKTstate0+i) = 0; - }; - -/* First, try a straight solution with all sources at zero */ - - fprintf(stderr, "\rSupplies reduced to %8.4f%% ", - ckt->CKTsrcFact*100); - converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); - -/* If this doesn't work, try gmin stepping as well for the first solution */ - - if(converged != 0) { - fprintf(stderr, "\n"); - if (ckt->CKTgshunt<=0) { - ckt->CKTdiagGmin = ckt->CKTgmin; - } else { - ckt->CKTdiagGmin = ckt->CKTgshunt; - }; - for(i=0;i<10;i++) { - ckt->CKTdiagGmin *= 10; - } - for(i=0;i<=10;i++) { - fprintf(stderr, "Trying gmin = %12.4E ", - ckt->CKTdiagGmin); - ckt->CKTnoncon =1; - converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); - if(converged != 0) { - ckt->CKTdiagGmin = ckt->CKTgshunt; - (*(SPfrontEnd->IFerror))(ERR_WARNING, - "Gmin step failed",(IFuid *)NULL); - break; - } - - ckt->CKTdiagGmin /= 10; - ckt->CKTmode=continuemode; - (*(SPfrontEnd->IFerror))(ERR_INFO, - "One successful Gmin step",(IFuid *)NULL); - } - ckt->CKTdiagGmin = ckt->CKTgshunt; - }; - -/* If we've got convergence, then try stepping up the sources */ - - if(converged == 0) { - i=0; - for (n = ckt->CKTnodes; n; n = n->next) { - OldRhsOld[i]=*(ckt->CKTrhsOld+n->number); - i++; - }; - for(i=0;iCKTnumStates;i++) { - *(OldCKTstate0+i) = *(ckt->CKTstate0+i); - }; - (*(SPfrontEnd->IFerror))(ERR_INFO, - "One successful source step",(IFuid *)NULL); - ckt->CKTsrcFact=ConvFact+raise; - }; - - if(converged == 0) do { - fprintf(stderr, "\rSupplies reduced to %8.4f%% ", - ckt->CKTsrcFact*100); - - iters = ckt->CKTstat->STATnumIter; - converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); - iters = (ckt->CKTstat->STATnumIter)-iters; - - ckt->CKTmode = continuemode; - if (converged == 0) { - ConvFact=ckt->CKTsrcFact; - i=0; - for (n = ckt->CKTnodes; n; n = n->next) { - OldRhsOld[i]=*(ckt->CKTrhsOld+n->number); - i++; - }; - for(i=0;iCKTnumStates;i++) { - *(OldCKTstate0+i) = *(ckt->CKTstate0+i); - }; - (*(SPfrontEnd->IFerror))(ERR_INFO, - "One successful source step",(IFuid *)NULL); - ckt->CKTsrcFact=ConvFact+raise; - if (iters <= (ckt->CKTdcTrcvMaxIter/4)) { - raise=raise*1.5; - }; - if (iters > (3*ckt->CKTdcTrcvMaxIter/4)) { - raise=raise*0.5; - }; -/* if (raise>0.01) raise=0.01; */ - } else { - if ((ckt->CKTsrcFact-ConvFact)<1e-8) break; - raise=raise/10; - if (raise>0.01) raise=0.01; - ckt->CKTsrcFact=ConvFact; - i=0; - for (n = ckt->CKTnodes; n; n = n->next) { - *(ckt->CKTrhsOld+n->number)=OldRhsOld[i]; - i++; - }; - for(i=0;iCKTnumStates;i++) { - *(ckt->CKTstate0+i) = *(OldCKTstate0+i); - }; - }; - if ((ckt->CKTsrcFact)>1) ckt->CKTsrcFact=1; - } while ((raise>=1e-7) && (ConvFact<1)); - - FREE(OldRhsOld); - FREE(OldCKTstate0); - ckt->CKTsrcFact = 1; - if (ConvFact!=1) { - ckt->CKTsrcFact = 1; - ckt->CKTcurrentAnalysis = DOING_TRAN; - (*(SPfrontEnd->IFerror))(ERR_WARNING, - "source stepping failed",(IFuid *)NULL); - return(E_ITERLIM); - } else { - (*(SPfrontEnd->IFerror))(ERR_INFO, - "Source stepping completed",(IFuid *)NULL); - return(0); - }; - } else { - for(i=0;i<=ckt->CKTnumSrcSteps;i++) { - ckt->CKTsrcFact = ((double)i)/((double)ckt->CKTnumSrcSteps); - converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); - ckt->CKTmode = continuemode; - if(converged != 0) { - ckt->CKTsrcFact = 1; - ckt->CKTcurrentAnalysis = DOING_TRAN; - (*(SPfrontEnd->IFerror))(ERR_WARNING, - "source stepping failed",(IFuid *)NULL); - return(converged); - } - (*(SPfrontEnd->IFerror))(ERR_INFO, - "One successful source step",(IFuid *)NULL); - } - (*(SPfrontEnd->IFerror))(ERR_INFO, - "Source stepping completed",(IFuid *)NULL); - ckt->CKTsrcFact = 1; - return(0); - }; - } else { - return(converged); - } - } - return(0); } + + /* CKTconvTest(ckt) * this is a driver program to iterate through all the various * convTest functions provided for the circuit elements in the @@ -351,43 +87,550 @@ CKTop(CKTcircuit *ckt, long int firstmode, long int continuemode, int iterlim) */ int -CKTconvTest(CKTcircuit *ckt) +CKTconvTest (CKTcircuit * ckt) { - extern SPICEdev **DEVices; - int i; - int error = OK; + extern SPICEdev **DEVices; + int i; + int error = OK; #ifdef PARALLEL_ARCH - int ibuf[2]; - long type = MT_CONV, length = 2; + int ibuf[2]; + long type = MT_CONV, length = 2; #endif /* PARALLEL_ARCH */ - for (i=0;iCKThead[i] != NULL)) { - error = (*((*DEVices[i]).DEVconvTest))(ckt->CKThead[i],ckt); - } + for (i = 0; i < DEVmaxnum; i++) + { + if (((*DEVices[i]).DEVconvTest != NULL) && (ckt->CKThead[i] != NULL)) + { + error = (*((*DEVices[i]).DEVconvTest)) (ckt->CKThead[i], ckt); + } #ifdef PARALLEL_ARCH - if (error || ckt->CKTnoncon) goto combine; + if (error || ckt->CKTnoncon) + goto combine; #else - if (error) return(error); - if (ckt->CKTnoncon) { - /* printf("convTest: device %s failed\n", - (*DEVices[i]).DEVpublic.name); */ - return(OK); - } + if (error) + return (error); + if (ckt->CKTnoncon) + { + /* printf("convTest: device %s failed\n", + * (*DEVices[i]).DEVpublic.name); */ + return (OK); + } #endif /* PARALLEL_ARCH */ } #ifdef PARALLEL_ARCH combine: - /* See if any of the DEVconvTest functions bailed. If not, proceed. */ - ibuf[0] = error; - ibuf[1] = ckt->CKTnoncon; - IGOP_( &type, ibuf, &length, "+" ); - ckt->CKTnoncon = ibuf[1]; - if ( ibuf[0] != error ) { - error = E_MULTIERR; + /* See if any of the DEVconvTest functions bailed. If not, proceed. */ + ibuf[0] = error; + ibuf[1] = ckt->CKTnoncon; + IGOP_ (&type, ibuf, &length, "+"); + ckt->CKTnoncon = ibuf[1]; + if (ibuf[0] != error) + { + error = E_MULTIERR; } - return (error); + return (error); #else - return(OK); + return (OK); #endif /* PARALLEL_ARCH */ } + + +/* Dynamic gmin stepping + * Algorithm by Alan Gillespie + * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) + * + * return value: + * 0 -> method converged + * 1 -> method failed + * + * Note that no path out of this code allows ckt->CKTdiagGmin to be + * anything but CKTgshunt. + */ + +static int +dynamic_gmin (CKTcircuit * ckt, long int firstmode, + long int continuemode, int iterlim) +{ + double OldGmin, gtarget, factor; + int success, failed, converged; + + int NumNodes, iters, i; + double *OldRhsOld, *OldCKTstate0; + CKTnode *n; + + ckt->CKTmode = firstmode; + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "starting dynamic Gmin stepping", (IFuid *) NULL); + + NumNodes = 0; + for (n = ckt->CKTnodes; n; n = n->next) + NumNodes++; + + OldRhsOld = (double *) MALLOC ((NumNodes + 1) * sizeof (double)); + OldCKTstate0 = + (double *) MALLOC ((ckt->CKTnumStates + 1) * sizeof (double)); + + for (n = ckt->CKTnodes; n; n = n->next) + *(ckt->CKTrhsOld + n->number) = 0; + + for (i = 0; i < ckt->CKTnumStates; i++) + *(ckt->CKTstate0 + i) = 0; + + factor = ckt->CKTgminFactor; + OldGmin = 1e-2; + ckt->CKTdiagGmin = OldGmin / factor; + gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt); + success = failed = 0; + + while ((!success) && (!failed)){ + fprintf (stderr, "\rTrying gmin = %12.4E ", ckt->CKTdiagGmin); + ckt->CKTnoncon = 1; + iters = ckt->CKTstat->STATnumIter; + + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); + iters = (ckt->CKTstat->STATnumIter) - iters; + + if (converged == 0){ + ckt->CKTmode = continuemode; + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "One successful Gmin step", (IFuid *) NULL); + + if (ckt->CKTdiagGmin <= gtarget){ + success = 1; + } else { + i = 0; + for (n = ckt->CKTnodes; n; n = n->next){ + OldRhsOld[i] = *(ckt->CKTrhsOld + n->number); + i++; + } + + for (i = 0; i < ckt->CKTnumStates; i++){ + *(OldCKTstate0 + i) = *(ckt->CKTstate0 + i); + } + + if (iters <= (ckt->CKTdcTrcvMaxIter / 4)){ + factor *= sqrt (factor); + if (factor > ckt->CKTgminFactor) + factor = ckt->CKTgminFactor; + } + + if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)) + factor = sqrt (factor); + + OldGmin = ckt->CKTdiagGmin; + + if ((ckt->CKTdiagGmin) < (factor * gtarget)){ + factor = ckt->CKTdiagGmin / gtarget; + ckt->CKTdiagGmin = gtarget; + } else { + ckt->CKTdiagGmin /= factor; + } + } + } else { + + if (factor < 1.00005){ + failed = 1; + (*(SPfrontEnd->IFerror)) (ERR_WARNING, + "Last gmin step failed", + (IFuid *) NULL); + } else { + factor = sqrt (sqrt (factor)); + ckt->CKTdiagGmin = OldGmin / factor; + i = 0; + + for (n = ckt->CKTnodes; n; n = n->next){ + *(ckt->CKTrhsOld + n->number) = OldRhsOld[i]; + i++; + } + + for (i = 0; i < ckt->CKTnumStates; i++){ + *(ckt->CKTstate0 + i) = *(OldCKTstate0 + i); + } + } + } + } + + ckt->CKTdiagGmin = ckt->CKTgshunt; + FREE (OldRhsOld); + FREE (OldCKTstate0); + +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + if (ckt->CKTnumSrcSteps <= 0) + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + else + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + + converged = NIiter (ckt, iterlim); + + if (converged != 0){ + (*(SPfrontEnd->IFerror)) (ERR_WARNING, + "Dynamic Gmin stepping failed", + (IFuid *) NULL); + } else { + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "Dynamic Gmin stepping completed", + (IFuid *) NULL); +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + } + + return (converged); +} + + +/* Spice3 gmin stepping + * Modified 2000 - Alan Gillespie (added gshunt) + * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) + * + * return value: + * 0 -> method converged + * 1 -> method failed + * + * Note that no path out of this code allows ckt->CKTdiagGmin to be + * anything but CKTgshunt. + */ + +static int +spice3_gmin (CKTcircuit * ckt, long int firstmode, + long int continuemode, int iterlim) +{ + + int converged, i; + + ckt->CKTmode = firstmode; + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "starting Gmin stepping", (IFuid *) NULL); + + if (ckt->CKTgshunt == 0) + ckt->CKTdiagGmin = ckt->CKTgmin; + else + ckt->CKTdiagGmin = ckt->CKTgshunt; + + for (i = 0; i < ckt->CKTnumGminSteps; i++) + ckt->CKTdiagGmin *= ckt->CKTgminFactor; + + + for (i = 0; i <= ckt->CKTnumGminSteps; i++){ + fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); + ckt->CKTnoncon = 1; + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); + + if (converged != 0){ + ckt->CKTdiagGmin = ckt->CKTgshunt; + (*(SPfrontEnd->IFerror)) (ERR_WARNING, + "Gmin step failed", (IFuid *) NULL); + break; + } + + ckt->CKTdiagGmin /= ckt->CKTgminFactor; + ckt->CKTmode = continuemode; + + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "One successful Gmin step", (IFuid *) NULL); + } + + ckt->CKTdiagGmin = ckt->CKTgshunt; + +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + if (ckt->CKTnumSrcSteps <= 0) + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; + else + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + + converged = NIiter (ckt, iterlim); + + if (converged == 0){ + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "Gmin stepping completed", (IFuid *) NULL); + +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + + } else { + (*(SPfrontEnd->IFerror)) (ERR_WARNING, + "Gmin stepping failed", (IFuid *) NULL); + } + + return (converged); + +} + + +/* Gillespie's Source stepping + * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) + * + * return value: + * 0 -> method converged + * 1 -> method failed + * + * Note that no path out of this code allows ckt->CKTsrcFact to be + * anything but 1.00000. + */ +static int +gillespie_src (CKTcircuit * ckt, long int firstmode, + long int continuemode, int iterlim) +{ + + int converged, NumNodes, i, iters; + double raise, ConvFact; + double *OldRhsOld, *OldCKTstate0; + CKTnode *n; + + ckt->CKTmode = firstmode; + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "starting source stepping", (IFuid *) NULL); + + ckt->CKTsrcFact = 0; + raise = 0.001; + ConvFact = 0; + + NumNodes = 0; + for (n = ckt->CKTnodes; n; n = n->next){ + NumNodes++; + } + + OldRhsOld = (double *) MALLOC ((NumNodes + 1) * sizeof (double)); + OldCKTstate0 = + (double *) MALLOC ((ckt->CKTnumStates + 1) * sizeof (double)); + + for (n = ckt->CKTnodes; n; n = n->next) + *(ckt->CKTrhsOld + n->number) = 0; + + for (i = 0; i < ckt->CKTnumStates; i++) + *(ckt->CKTstate0 + i) = 0; + +/* First, try a straight solution with all sources at zero */ + + fprintf (stderr, "\rSupplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); + +/* If this doesn't work, try gmin stepping as well for the first solution */ + + if (converged != 0){ + fprintf (stderr, "\n"); + if (ckt->CKTgshunt <= 0){ + ckt->CKTdiagGmin = ckt->CKTgmin; + } else { + ckt->CKTdiagGmin = ckt->CKTgshunt; + } + + for (i = 0; i < 10; i++) + ckt->CKTdiagGmin *= 10; + + for (i = 0; i <= 10; i++){ + fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin); + ckt->CKTnoncon = 1; + +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); + + if (converged != 0){ + ckt->CKTdiagGmin = ckt->CKTgshunt; + (*(SPfrontEnd->IFerror)) (ERR_WARNING, + "Gmin step failed", (IFuid *) NULL); + #ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + break; + } + + ckt->CKTdiagGmin /= 10; + ckt->CKTmode = continuemode; + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "One successful Gmin step", + (IFuid *) NULL); + } + ckt->CKTdiagGmin = ckt->CKTgshunt; + } + +/* If we've got convergence, then try stepping up the sources */ + + if (converged == 0){ + i = 0; + for (n = ckt->CKTnodes; n; n = n->next){ + OldRhsOld[i] = *(ckt->CKTrhsOld + n->number); + i++; + } + + for (i = 0; i < ckt->CKTnumStates; i++) + *(OldCKTstate0 + i) = *(ckt->CKTstate0 + i); + + + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "One successful source step", (IFuid *) NULL); + ckt->CKTsrcFact = ConvFact + raise; + } + + + if (converged == 0) + do { + fprintf (stderr, + "\rSupplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); + + iters = ckt->CKTstat->STATnumIter; + +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); + + iters = (ckt->CKTstat->STATnumIter) - iters; + + ckt->CKTmode = continuemode; + + if (converged == 0){ + ConvFact = ckt->CKTsrcFact; + i = 0; + + for (n = ckt->CKTnodes; n; n = n->next){ + OldRhsOld[i] = *(ckt->CKTrhsOld + n->number); + i++; + } + + for (i = 0; i < ckt->CKTnumStates; i++) + *(OldCKTstate0 + i) = *(ckt->CKTstate0 + i); + + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "One successful source step", + (IFuid *) NULL); + + ckt->CKTsrcFact = ConvFact + raise; + + if (iters <= (ckt->CKTdcTrcvMaxIter / 4)){ + raise = raise * 1.5; + } + + if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)){ + raise = raise * 0.5; + } + +/* if (raise>0.01) raise=0.01; */ + + } else { + + if ((ckt->CKTsrcFact - ConvFact) < 1e-8) + break; + + raise = raise / 10; + + if (raise > 0.01) + raise = 0.01; + + ckt->CKTsrcFact = ConvFact; + i = 0; + + for (n = ckt->CKTnodes; n; n = n->next){ + *(ckt->CKTrhsOld + n->number) = OldRhsOld[i]; + i++; + } + + for (i = 0; i < ckt->CKTnumStates; i++) + *(ckt->CKTstate0 + i) = *(OldCKTstate0 + i); + + } + + if ((ckt->CKTsrcFact) > 1) + ckt->CKTsrcFact = 1; + + } + while ((raise >= 1e-7) && (ConvFact < 1)); + + FREE (OldRhsOld); + FREE (OldCKTstate0); + ckt->CKTsrcFact = 1; + + if (ConvFact != 1) + { + ckt->CKTsrcFact = 1; + ckt->CKTcurrentAnalysis = DOING_TRAN; + (*(SPfrontEnd->IFerror)) (ERR_WARNING, + "source stepping failed", (IFuid *) NULL); + return (E_ITERLIM); + } + else + { + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "Source stepping completed", (IFuid *) NULL); + return (0); + } +} + + +/* Spice3 Source stepping + * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) + * + * return value: + * 0 -> method converged + * 1 -> method failed + * + * Note that no path out of this code allows ckt->CKTsrcFact to be + * anything but 1.00000. + */ +static int +spice3_src (CKTcircuit * ckt, long int firstmode, + long int continuemode, int iterlim) +{ + + int converged, i; + + ckt->CKTmode = firstmode; + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "starting source stepping", (IFuid *) NULL); + + for (i = 0; i <= ckt->CKTnumSrcSteps; i++) + { + ckt->CKTsrcFact = ((double) i) / ((double) ckt->CKTnumSrcSteps); +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); + ckt->CKTmode = continuemode; + if (converged != 0) + { + ckt->CKTsrcFact = 1; + ckt->CKTcurrentAnalysis = DOING_TRAN; + (*(SPfrontEnd->IFerror)) (ERR_WARNING, + "source stepping failed", (IFuid *) NULL); +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + return (converged); + } + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "One successful source step", (IFuid *) NULL); + } + (*(SPfrontEnd->IFerror)) (ERR_INFO, + "Source stepping completed", (IFuid *) NULL); + ckt->CKTsrcFact = 1; +#ifdef XSPICE +/* gtri - begin - wbk - add convergence problem reporting flags */ + ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE; +/* gtri - end - wbk - add convergence problem reporting flags */ +#endif + return (0); +} diff --git a/src/spicelib/analysis/dcop.c b/src/spicelib/analysis/dcop.c index d6c49a241..9b413a39d 100644 --- a/src/spicelib/analysis/dcop.c +++ b/src/spicelib/analysis/dcop.c @@ -9,6 +9,14 @@ Modified: 2000 AlansFixes #include "sperror.h" #include "ifsim.h" +#ifdef XSPICE +/* gtri - add - wbk - 12/19/90 - Add headers */ +#include "mif.h" +#include "evt.h" +#include "evtproto.h" +#include "ipctiein.h" +/* gtri - end - wbk */ +#endif int DCop(CKTcircuit *ckt, int notused) @@ -19,7 +27,21 @@ DCop(CKTcircuit *ckt, int notused) IFuid *nameList; /* va: tmalloc'ed list */ int numNames; void *plot = NULL; - + +#ifdef XSPICE +/* gtri - add - wbk - 12/19/90 - Add IPC stuff and initialize anal_init and anal_type */ + + /* Tell the beginPlot routine what mode we're in */ + g_ipc.anal_type = IPC_ANAL_DCOP; + + /* 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 + error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); error = (*(SPfrontEnd->OUTpBeginPlot))((void *)ckt, @@ -28,10 +50,28 @@ DCop(CKTcircuit *ckt, int notused) tfree(nameList); /* va: nameList not used any longer, it was a memory leak */ if(error) return(error); + +#ifdef XSPICE +/* gtri - begin - wbk - 6/10/91 - Call EVTop if event-driven instances exist */ + if(ckt->evt->counts.num_insts != 0) { + /* use new DCOP algorithm */ + converged = 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); + /* gtri - end - wbk - 6/10/91 - Call EVTop if event-driven instances exist */ + } else + /* If no event-driven instances, do what SPICE normally does */ +#endif converged = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); + if(converged != 0) { fprintf(stdout,"\nDC solution failed -\n"); CKTncDump(ckt); @@ -63,14 +103,15 @@ DCop(CKTcircuit *ckt, int notused) fprintf(stdout," *"); } fprintf(stdout,"\n"); - }; + } i++; - }; + } fprintf(stdout,"\n"); (*(SPfrontEnd->OUTendPlot))(plot); */ return(converged); - }; + } + ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; @@ -96,11 +137,25 @@ DCop(CKTcircuit *ckt, int notused) } #endif converged = CKTload(ckt); +#ifdef XSPICE +/* gtri - modify - wbk - 12/19/90 - Send IPC data delimiters */ + + if(g_ipc.enabled) + ipc_send_dcop_prefix(); + + CKTdump(ckt,(double)0,plot); + + if(g_ipc.enabled) + ipc_send_dcop_suffix(); + +/* gtri - end - wbk */ +#else if(converged == 0) { CKTdump(ckt,(double)0,plot); } else { fprintf(stderr,"error: circuit reload failed.\n"); - }; + } +#endif (*(SPfrontEnd->OUTendPlot))(plot); return(converged); } diff --git a/src/spicelib/analysis/dctran.c b/src/spicelib/analysis/dctran.c index ff99a21b7..f44f6e133 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -110,7 +110,17 @@ DCtran(CKTcircuit *ckt, *(ckt->CKTbreaks)=0; *(ckt->CKTbreaks+1)=ckt->CKTfinalTime; ckt->CKTbreakSize=2; + +#ifdef XSPICE +/* gtri - begin - wbk - 12/19/90 - Modify setting of CKTminBreak */ +/* if(ckt->CKTminBreak==0) ckt->CKTminBreak=ckt->CKTmaxStep*5e-5; */ + /* Set to 10 times delmin for ATESSE 1 compatibity */ + if(ckt->CKTminBreak==0) ckt->CKTminBreak = 10.0 * ckt->CKTdelmin; +/* gtri - end - wbk - 12/19/90 - Modify setting of CKTminBreak */ +#else if(ckt->CKTminBreak==0) ckt->CKTminBreak=ckt->CKTmaxStep*5e-5; +#endif + #ifdef XSPICE /* gtri - add - wbk - 12/19/90 - Add IPC stuff and set anal_init and anal_type */ @@ -507,6 +517,15 @@ resume: #endif ckt->CKTdelta = MIN(ckt->CKTdelta,ckt->CKTmaxStep); +#ifdef XSPICE +/* gtri - begin - wbk - Cut integration order if first timepoint after breakpoint */ + if(ckt->CKTtime == g_mif_info.breakpoint.last) + ckt->CKTorder = 1; +/* gtri - end - wbk - Cut integration order if first timepoint after breakpoint */ + +#endif + + /* are we at a breakpoint, or indistinguishably close? */ if ((ckt->CKTtime == *(ckt->CKTbreaks)) || (*(ckt->CKTbreaks) - (ckt->CKTtime) <= ckt->CKTdelmin)) { @@ -536,6 +555,43 @@ resume: #endif } +#ifdef XSPICE + } + +/* gtri - begin - wbk - Add Breakpoint stuff */ + + if(ckt->CKTtime + ckt->CKTdelta >= g_mif_info.breakpoint.current) { + /* If next time > temporary breakpoint, force it to the breakpoint */ + /* And mark that timestep was set by temporary breakpoint */ + ckt->CKTsaveDelta = ckt->CKTdelta; + ckt->CKTdelta = g_mif_info.breakpoint.current - ckt->CKTtime; + g_mif_info.breakpoint.last = ckt->CKTtime + ckt->CKTdelta; + } + else { + /* Else, mark that timestep was not set by temporary breakpoint */ + g_mif_info.breakpoint.last = 1.0e30; + } + +/* gtri - end - wbk - Add Breakpoint stuff */ + +/* gtri - begin - wbk - Modify Breakpoint stuff */ + /* Throw out any permanent breakpoint times <= current time */ + while(1) { + if(*(ckt->CKTbreaks) <= (ckt->CKTtime + ckt->CKTminBreak)) + CKTclrBreak(ckt); + else + break; + } + /* Force the breakpoint if appropriate */ + if((ckt->CKTtime + ckt->CKTdelta) > *(ckt->CKTbreaks)) { + ckt->CKTbreak = 1; + ckt->CKTsaveDelta = ckt->CKTdelta; + ckt->CKTdelta = *(ckt->CKTbreaks) - ckt->CKTtime; + } + +/* gtri - end - wbk - Modify Breakpoint stuff */ +#else /* !XSPICE */ + /* don't want to get below delmin for no reason */ ckt->CKTdelta = MAX(ckt->CKTdelta, ckt->CKTdelmin*2.0); } @@ -557,6 +613,9 @@ resume: #ifdef PARALLEL_ARCH DGOP_( &type, &(ckt->CKTdelta), &length, "min" ); #endif /* PARALLEL_ARCH */ + +#endif /* XSPICE */ + #ifdef XSPICE /* gtri - begin - wbk - Do event solution */ @@ -707,6 +766,24 @@ resume: ckt->CKTmode = (ckt->CKTmode&MODEUIC)|MODETRAN | MODEINITTRAN; } ckt->CKTorder = 1; + +#ifdef XSPICE +/* gtri - begin - wbk - Add Breakpoint stuff */ + + /* Force backup if temporary breakpoint is < current time */ + } else if(g_mif_info.breakpoint.current < ckt->CKTtime) { + ckt->CKTsaveDelta = ckt->CKTdelta; + ckt->CKTtime -= ckt->CKTdelta; + ckt->CKTdelta = g_mif_info.breakpoint.current - ckt->CKTtime; + g_mif_info.breakpoint.last = ckt->CKTtime + ckt->CKTdelta; + if(firsttime) { + ckt->CKTmode = (ckt->CKTmode&MODEUIC)|MODETRAN | MODEINITTRAN; + } + ckt->CKTorder = 1; + +/* gtri - end - wbk - Add Breakpoint stuff */ +#endif + } else { if (firsttime) { #ifdef WANT_SENSE2 diff --git a/src/spicelib/analysis/dctrcurv.c b/src/spicelib/analysis/dctrcurv.c index 5133a2153..9e075c6ea 100644 --- a/src/spicelib/analysis/dctrcurv.c +++ b/src/spicelib/analysis/dctrcurv.c @@ -14,6 +14,14 @@ Modified: 1999 Paolo Nenzi #include "const.h" #include "sperror.h" +#ifdef XSPICE +/* gtri - add - wbk - 12/19/90 - Add headers */ +#include "mif.h" +#include "evtproto.h" +#include "ipctiein.h" +/* gtri - end - wbk */ +#endif + #include extern SPICEdev **DEVices; @@ -151,7 +159,21 @@ DCtrCurv(CKTcircuit *ckt, int restart) found:; } - + +#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_DCTRCURVE; + + /* 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 + i--; /* PN: This seems to do nothing ??? */ error = CKTnames(ckt,&numNames,&nameList); @@ -292,6 +314,11 @@ resume: ckt->CKTstate0 = temp; /* do operation */ +#ifdef XSPICE +/* gtri - begin - wbk - Do EVTop if event instances exist */ + if(ckt->evt->counts.num_insts == 0) { + /* If no event-driven instances, do what SPICE normally does */ +#endif converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); if(converged != 0) { converged = CKTop(ckt, @@ -302,6 +329,59 @@ resume: return(converged); } } +#ifdef XSPICE + } + else { + /* else do new algorithm */ + + /* first get the current step in the analysis */ + if(cv->TRCVvType[0] == vcode) { + g_mif_info.circuit.evt_step = ((VSRCinstance *)(cv->TRCVvElt[i])) + ->VSRCdcValue ; + } else if(cv->TRCVvType[0] == icode) { + g_mif_info.circuit.evt_step = ((ISRCinstance *)(cv->TRCVvElt[i])) + ->ISRCdcValue ; + } else if(cv->TRCVvType[0] == rcode) { + g_mif_info.circuit.evt_step = ((RESinstance*)(cv->TRCVvElt[i]->GENmodPtr)) + ->RESresist; + } else if(cv->TRCVvType[0] == TEMP_CODE) { + g_mif_info.circuit.evt_step = ckt->CKTtemp - CONSTCtoK; + } + + /* if first time through, call EVTop immediately and save event results */ + if(firstTime) { + converged = EVTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, + ckt->CKTdcMaxIter, + MIF_TRUE); + EVTdump(ckt, IPC_ANAL_DCOP, g_mif_info.circuit.evt_step); + EVTop_save(ckt, MIF_FALSE, g_mif_info.circuit.evt_step); + if(converged != 0) + return(converged); + } + /* else, call NIiter first with mode = MODEINITPRED */ + /* to attempt quick analog solution. Then call all hybrids and call */ + /* EVTop only if event outputs have changed, or if non-converged */ + else { + converged = NIiter(ckt,ckt->CKTdcTrcvMaxIter); + EVTcall_hybrids(ckt); + if((converged != 0) || (ckt->evt->queue.output.num_changed != 0)) { + converged = EVTop(ckt, + (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, + (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, + ckt->CKTdcMaxIter, + MIF_FALSE); + EVTdump(ckt, IPC_ANAL_DCTRCURVE, g_mif_info.circuit.evt_step); + EVTop_save(ckt, MIF_FALSE, g_mif_info.circuit.evt_step); + if(converged != 0) + return(converged); + } + } + } +/* gtri - end - wbk - Do EVTop if event instances exist */ +#endif + ckt->CKTmode = (ckt->CKTmode&MODEUIC) | MODEDCTRANCURVE | MODEINITPRED ; if(cv->TRCVvType[0] == vcode) { ckt->CKTtime = ((VSRCinstance *)(cv->TRCVvElt[i])) @@ -318,6 +398,22 @@ resume: { ckt->CKTtime = ckt->CKTtemp - CONSTCtoK ; } + +#ifdef XSPICE +/* gtri - add - wbk - 12/19/90 - Add IPC stuff */ + + /* If first time through, call CKTdump to output Operating Point info */ + /* for Mspice compatibility */ + + if(g_ipc.enabled && firstTime) { + ipc_send_dcop_prefix(); + CKTdump(ckt,(double) 0,plot); + ipc_send_dcop_suffix(); + } + +/* gtri - end - wbk */ +#endif + #ifdef WANT_SENSE2 /* if(!ckt->CKTsenInfo) printf("sensitivity structure does not exist\n"); @@ -355,8 +451,22 @@ resume: } #endif +#ifdef XSPICE +/* gtri - modify - wbk - 12/19/90 - Send IPC delimiters */ + + if(g_ipc.enabled) + ipc_send_data_prefix(ckt->CKTtime); +#endif CKTdump(ckt,ckt->CKTtime,plot); + +#ifdef XSPICE + if(g_ipc.enabled) + ipc_send_data_suffix(); + +/* gtri - end - wbk */ +#endif + if(firstTime) { firstTime=0; bcopy((char *)ckt->CKTstate0,(char *)ckt->CKTstate1,