Fixed xspice extensions.

This commit is contained in:
pnenzi 2005-06-25 19:11:57 +00:00
parent 51988dfb80
commit b8dca1b4c2
8 changed files with 951 additions and 392 deletions

View File

@ -1,3 +1,26 @@
2005-06-25 Paolo Nenzi <p.nenzi@ieee.org>
* 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 <steven.borley@virgin.net>
* Changes supplied bt Hitoshi Tanaka to allow XSpice to compile using MinGW

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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;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);
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;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;
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;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;
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;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;
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);
};
} 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;i<DEVmaxnum;i++) {
if (((*DEVices[i]).DEVconvTest != NULL) && (ckt->CKThead[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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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 <devdefs.h>
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,