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,