pa-62
This commit is contained in:
parent
a80f6e3e95
commit
3cdce8bef7
|
|
@ -25,6 +25,14 @@ Modified: 1999 Paolo Nenzi
|
||||||
#define TEMP_CODE 1023
|
#define TEMP_CODE 1023
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Enhancement-62: sweep type code for a generic instance-parameter sweep
|
||||||
|
(`.dc @inst[param] start stop step`), resolved through the device's own
|
||||||
|
DEVparam/DEVask interface -- works for any device type that exposes a
|
||||||
|
settable real instance parameter, including Verilog-A (OSDI) devices. */
|
||||||
|
#ifndef PARAM_CODE
|
||||||
|
#define PARAM_CODE 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int JOBtype;
|
int JOBtype;
|
||||||
JOB *JOBnextJob;
|
JOB *JOBnextJob;
|
||||||
|
|
@ -38,6 +46,11 @@ typedef struct {
|
||||||
IFuid TRCVvName[TRCVNESTLEVEL]; /* source being varied */
|
IFuid TRCVvName[TRCVNESTLEVEL]; /* source being varied */
|
||||||
GENinstance *TRCVvElt[TRCVNESTLEVEL]; /* pointer to source */
|
GENinstance *TRCVvElt[TRCVNESTLEVEL]; /* pointer to source */
|
||||||
int TRCVvType[TRCVNESTLEVEL]; /* type of element being varied */
|
int TRCVvType[TRCVNESTLEVEL]; /* type of element being varied */
|
||||||
|
int TRCVvParmId[TRCVNESTLEVEL]; /* Enhancement-62: IFparm id for a
|
||||||
|
* PARAM_CODE (@inst[param]) sweep */
|
||||||
|
double TRCVvNow[TRCVNESTLEVEL]; /* Enhancement-62: current value of a
|
||||||
|
* PARAM_CODE sweep (devices have no
|
||||||
|
* generic readback field to consult) */
|
||||||
int TRCVset[TRCVNESTLEVEL]; /* flag to indicate this nest level used */
|
int TRCVset[TRCVNESTLEVEL]; /* flag to indicate this nest level used */
|
||||||
int TRCVnestLevel; /* number of levels of nesting called for */
|
int TRCVnestLevel; /* number of levels of nesting called for */
|
||||||
int TRCVnestState; /* iteration state during pause */
|
int TRCVnestState; /* iteration state during pause */
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,22 @@ CKTdisto (CKTcircuit *ckt, int mode)
|
||||||
|
|
||||||
case D_SETUP:
|
case D_SETUP:
|
||||||
|
|
||||||
|
/* Enhancement-62: distortion analysis needs per-device Taylor
|
||||||
|
coefficients (DEVdisto); Verilog-A (OSDI) devices only expose
|
||||||
|
first derivatives through the OSDI ABI, so their
|
||||||
|
nonlinearities are invisible to .disto -- the analysis would
|
||||||
|
silently report ZERO distortion for them. Warn loudly instead
|
||||||
|
of returning quietly-wrong numbers. */
|
||||||
|
for (i=0;i<DEVmaxnum;i++) {
|
||||||
|
if ( DEVices[i] && !DEVices[i]->DEVdisto && ckt->CKThead[i]
|
||||||
|
&& DEVices[i]->DEVpublic.registry_entry ) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Warning: Verilog-A (OSDI) device type '%s' has no distortion model;\n"
|
||||||
|
" .disto results will NOT include its nonlinearities.\n",
|
||||||
|
DEVices[i]->DEVpublic.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0;i<DEVmaxnum;i++) {
|
for (i=0;i<DEVmaxnum;i++) {
|
||||||
if ( DEVices[i] && DEVices[i]->DEVdisto && ckt->CKThead[i] ) {
|
if ( DEVices[i] && DEVices[i]->DEVdisto && ckt->CKThead[i] ) {
|
||||||
error = DEVices[i]->DEVdisto (mode, ckt->CKThead[i], ckt);
|
error = DEVices[i]->DEVdisto (mode, ckt->CKThead[i], ckt);
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,75 @@ Modified: 1999 Paolo Nenzi
|
||||||
static double actval, actdiff;
|
static double actval, actdiff;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Enhancement-62: resolve a `@inst[param]` sweep variable to its instance,
|
||||||
|
device type, and (settable, real-valued) instance-parameter id, through
|
||||||
|
the generic DEVparam/DEVask tables. Returns OK on success. Instance
|
||||||
|
lookup walks every device type comparing names case-insensitively (the
|
||||||
|
sweep name is a raw token, not an interned IFuid, so the DEVnameHash
|
||||||
|
cannot be used). */
|
||||||
|
static int
|
||||||
|
DCTfindInstParam(CKTcircuit *ckt, const char *name, GENinstance **instOut,
|
||||||
|
int *typeOut, int *parmOut)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
char *lbrack, *rbrack, *parname;
|
||||||
|
GENmodel *model;
|
||||||
|
GENinstance *inst;
|
||||||
|
IFdevice *dev;
|
||||||
|
int type, k;
|
||||||
|
|
||||||
|
if (!name || name[0] != '@' || strlen(name) >= sizeof(buf))
|
||||||
|
return E_NODEV;
|
||||||
|
strcpy(buf, name + 1);
|
||||||
|
lbrack = strchr(buf, '[');
|
||||||
|
rbrack = lbrack ? strchr(lbrack, ']') : NULL;
|
||||||
|
if (!lbrack || !rbrack || rbrack <= lbrack + 1 || lbrack == buf)
|
||||||
|
return E_NODEV;
|
||||||
|
*lbrack = '\0';
|
||||||
|
*rbrack = '\0';
|
||||||
|
parname = lbrack + 1;
|
||||||
|
|
||||||
|
for (type = 0; type < DEVmaxnum; type++) {
|
||||||
|
if (!DEVices[type])
|
||||||
|
continue;
|
||||||
|
for (model = ckt->CKThead[type]; model; model = model->GENnextModel)
|
||||||
|
for (inst = model->GENinstances; inst; inst = inst->GENnextInstance)
|
||||||
|
if (inst->GENname && cieq(inst->GENname, buf)) {
|
||||||
|
dev = &DEVices[type]->DEVpublic;
|
||||||
|
for (k = 0; dev->instanceParms && k < *dev->numInstanceParms; k++) {
|
||||||
|
IFparm *prm = dev->instanceParms + k;
|
||||||
|
if ((prm->dataType & IF_SET)
|
||||||
|
&& (prm->dataType & IF_VARTYPES) == IF_REAL
|
||||||
|
&& cieq(prm->keyword, parname)) {
|
||||||
|
*instOut = inst;
|
||||||
|
*typeOut = type;
|
||||||
|
*parmOut = prm->id;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return E_BADPARM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return E_NODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enhancement-62: set the swept instance parameter to `val` and refresh the
|
||||||
|
device (DEVtemperature re-runs per-model/per-instance setup -- for OSDI
|
||||||
|
devices that is exactly the parameter-change path `alter` + a fresh
|
||||||
|
analysis would take). */
|
||||||
|
static void
|
||||||
|
DCTsetInstParam(CKTcircuit *ckt, TRCV *job, int i, double val)
|
||||||
|
{
|
||||||
|
IFvalue v;
|
||||||
|
int type = job->TRCVvElt[i]->GENmodPtr->GENmodType;
|
||||||
|
|
||||||
|
v.rValue = val;
|
||||||
|
DEVices[type]->DEVparam(job->TRCVvParmId[i], &v, job->TRCVvElt[i], NULL);
|
||||||
|
job->TRCVvNow[i] = val;
|
||||||
|
if (DEVices[type]->DEVtemperature)
|
||||||
|
DEVices[type]->DEVtemperature(ckt->CKThead[type], ckt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
DCtrCurv(CKTcircuit *ckt, int restart)
|
DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
|
|
@ -150,6 +219,27 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enhancement-62: `.dc @inst[param] start stop step` -- sweep any
|
||||||
|
settable real instance parameter of any device (incl. OSDI). */
|
||||||
|
if (job->TRCVvName[i] && job->TRCVvName[i][0] == '@') {
|
||||||
|
GENinstance *pinst;
|
||||||
|
int ptype, pid;
|
||||||
|
if (DCTfindInstParam(ckt, job->TRCVvName[i], &pinst, &ptype, &pid) == OK) {
|
||||||
|
IFvalue old_v;
|
||||||
|
job->TRCVvElt[i] = pinst;
|
||||||
|
job->TRCVvType[i] = PARAM_CODE;
|
||||||
|
job->TRCVvParmId[i] = pid;
|
||||||
|
if (DEVices[ptype]->DEVask
|
||||||
|
&& DEVices[ptype]->DEVask(ckt, pinst, pid, &old_v, NULL) == OK)
|
||||||
|
job->TRCVvSave[i] = old_v.rValue;
|
||||||
|
else
|
||||||
|
job->TRCVvSave[i] = job->TRCVvStart[i];
|
||||||
|
job->TRCVgSave[i] = 1;
|
||||||
|
DCTsetInstParam(ckt, job, i, job->TRCVvStart[i]);
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SPfrontEnd->IFerrorf (ERR_FATAL,
|
SPfrontEnd->IFerrorf (ERR_FATAL,
|
||||||
"DC Transfer Function: Voltage source, current source, or "
|
"DC Transfer Function: Voltage source, current source, or "
|
||||||
"resistor named \"%s\" is not in the circuit",
|
"resistor named \"%s\" is not in the circuit",
|
||||||
|
|
@ -185,6 +275,8 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "temp-sweep", UID_OTHER, NULL);
|
SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "temp-sweep", UID_OTHER, NULL);
|
||||||
else if (job->TRCVvType[0] == rcode)
|
else if (job->TRCVvType[0] == rcode)
|
||||||
SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "res-sweep", UID_OTHER, NULL);
|
SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "res-sweep", UID_OTHER, NULL);
|
||||||
|
else if (job->TRCVvType[0] == PARAM_CODE)
|
||||||
|
SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "param-sweep", UID_OTHER, NULL);
|
||||||
else
|
else
|
||||||
SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "?-sweep", UID_OTHER, NULL);
|
SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "?-sweep", UID_OTHER, NULL);
|
||||||
|
|
||||||
|
|
@ -261,6 +353,18 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
break;
|
break;
|
||||||
goto nextstep;
|
goto nextstep;
|
||||||
}
|
}
|
||||||
|
} else if (job->TRCVvType[i] == PARAM_CODE) { /* @inst[param] sweep */
|
||||||
|
if (SGN(job->TRCVvStep[i]) *
|
||||||
|
(job->TRCVvNow[i] - job->TRCVvStop[i]) >
|
||||||
|
DBL_EPSILON * 1e+03)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
firstTime = 1;
|
||||||
|
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT;
|
||||||
|
if (i > job->TRCVnestLevel)
|
||||||
|
break;
|
||||||
|
goto nextstep;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (--i >= 0)
|
while (--i >= 0)
|
||||||
|
|
@ -279,6 +383,8 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
job->TRCVvStart[i];
|
job->TRCVvStart[i];
|
||||||
RESupdate_conduct((RESinstance *)(job->TRCVvElt[i]), FALSE);
|
RESupdate_conduct((RESinstance *)(job->TRCVvElt[i]), FALSE);
|
||||||
DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt);
|
DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt);
|
||||||
|
} else if (job->TRCVvType[i] == PARAM_CODE) {
|
||||||
|
DCTsetInstParam(ckt, job, i, job->TRCVvStart[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rotate state vectors. */
|
/* Rotate state vectors. */
|
||||||
|
|
@ -331,6 +437,8 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
} else if (job->TRCVvType[0] == TEMP_CODE) {
|
} else if (job->TRCVvType[0] == TEMP_CODE) {
|
||||||
g_mif_info.circuit.evt_step =
|
g_mif_info.circuit.evt_step =
|
||||||
ckt->CKTtemp - CONSTCtoK;
|
ckt->CKTtemp - CONSTCtoK;
|
||||||
|
} else if (job->TRCVvType[0] == PARAM_CODE) {
|
||||||
|
g_mif_info.circuit.evt_step = job->TRCVvNow[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if first time through, call EVTop immediately and save event results */
|
/* if first time through, call EVTop immediately and save event results */
|
||||||
|
|
@ -374,6 +482,8 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
ckt->CKTtime = ((ISRCinstance *)(job->TRCVvElt[0]))->ISRCdcValue;
|
ckt->CKTtime = ((ISRCinstance *)(job->TRCVvElt[0]))->ISRCdcValue;
|
||||||
else if (job->TRCVvType[0] == rcode)
|
else if (job->TRCVvType[0] == rcode)
|
||||||
ckt->CKTtime = ((RESinstance *)(job->TRCVvElt[0]))->RESresist;
|
ckt->CKTtime = ((RESinstance *)(job->TRCVvElt[0]))->RESresist;
|
||||||
|
else if (job->TRCVvType[0] == PARAM_CODE)
|
||||||
|
ckt->CKTtime = job->TRCVvNow[0];
|
||||||
else if (job->TRCVvType[0] == TEMP_CODE)
|
else if (job->TRCVvType[0] == TEMP_CODE)
|
||||||
ckt->CKTtime = ckt->CKTtemp - CONSTCtoK;
|
ckt->CKTtime = ckt->CKTtemp - CONSTCtoK;
|
||||||
|
|
||||||
|
|
@ -450,6 +560,9 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
job->TRCVvStep[i];
|
job->TRCVvStep[i];
|
||||||
RESupdate_conduct((RESinstance *)(job->TRCVvElt[i]), FALSE);
|
RESupdate_conduct((RESinstance *)(job->TRCVvElt[i]), FALSE);
|
||||||
DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt);
|
DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt);
|
||||||
|
} else if (job->TRCVvType[i] == PARAM_CODE) { /* @inst[param] */
|
||||||
|
DCTsetInstParam(ckt, job, i,
|
||||||
|
job->TRCVvNow[i] + job->TRCVvStep[i]);
|
||||||
} else if (job->TRCVvType[i] == TEMP_CODE) { /* temperature */
|
} else if (job->TRCVvType[i] == TEMP_CODE) { /* temperature */
|
||||||
ckt->CKTtemp += job->TRCVvStep[i];
|
ckt->CKTtemp += job->TRCVvStep[i];
|
||||||
|
|
||||||
|
|
@ -500,6 +613,10 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
||||||
ckt->CKTtemp = job->TRCVvSave[i];
|
ckt->CKTtemp = job->TRCVvSave[i];
|
||||||
inp_evaluate_temper(ft_curckt);
|
inp_evaluate_temper(ft_curckt);
|
||||||
CKTtemp(ckt);
|
CKTtemp(ckt);
|
||||||
|
} else if (job->TRCVvType[i] == PARAM_CODE) {
|
||||||
|
/* value restored; the parameter stays marked "given" (the
|
||||||
|
generic DEVparam interface has no way to clear that) */
|
||||||
|
DCTsetInstParam(ckt, job, i, job->TRCVvSave[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPfrontEnd->OUTendPlot (plot);
|
SPfrontEnd->OUTendPlot (plot);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue