|
|
|
@ -16,8 +16,8 @@ Modified by Dietmar Warning 2003 and Paolo Nenzi 2003 |
|
|
|
|
|
|
|
int |
|
|
|
DIOload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
/* actually load the current resistance value into the |
|
|
|
* sparse matrix previously provided |
|
|
|
/* actually load the current resistance value into the |
|
|
|
* sparse matrix previously provided |
|
|
|
*/ |
|
|
|
{ |
|
|
|
DIOmodel *model = (DIOmodel*)inModel; |
|
|
|
@ -64,13 +64,13 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
/* loop through all the instances of the model */ |
|
|
|
for (here = model->DIOinstances; here != NULL ; |
|
|
|
here=here->DIOnextInstance) { |
|
|
|
if (here->DIOowner != ARCHme) continue; |
|
|
|
if (here->DIOowner != ARCHme) continue; |
|
|
|
|
|
|
|
/* |
|
|
|
* this routine loads diodes for dc and transient analyses. |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(ckt->CKTsenInfo){ |
|
|
|
if((ckt->CKTsenInfo->SENstatus == PERTURBATION) |
|
|
|
&& (here->DIOsenPertFlag == OFF))continue; |
|
|
|
@ -85,8 +85,8 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
gspr=here->DIOtConductance*here->DIOarea*here->DIOm; |
|
|
|
vt = CONSTKoverQ * here->DIOtemp; |
|
|
|
vte=model->DIOemissionCoeff * vt; |
|
|
|
/* |
|
|
|
* initialization |
|
|
|
/* |
|
|
|
* initialization |
|
|
|
*/ |
|
|
|
|
|
|
|
if(SenCond){ |
|
|
|
@ -113,7 +113,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
vd= *(ckt->CKTstate0 + here->DIOvoltage); |
|
|
|
} else if (ckt->CKTmode & MODEINITTRAN) { |
|
|
|
vd= *(ckt->CKTstate1 + here->DIOvoltage); |
|
|
|
} else if ( (ckt->CKTmode & MODEINITJCT) && |
|
|
|
} else if ( (ckt->CKTmode & MODEINITJCT) && |
|
|
|
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC) ) { |
|
|
|
vd=here->DIOinitCond; |
|
|
|
} else if ( (ckt->CKTmode & MODEINITJCT) && here->DIOoff) { |
|
|
|
@ -125,12 +125,12 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
} else { |
|
|
|
#ifndef PREDICTOR |
|
|
|
if (ckt->CKTmode & MODEINITPRED) { |
|
|
|
*(ckt->CKTstate0 + here->DIOvoltage) = |
|
|
|
*(ckt->CKTstate0 + here->DIOvoltage) = |
|
|
|
*(ckt->CKTstate1 + here->DIOvoltage); |
|
|
|
vd = DEVpred(ckt,here->DIOvoltage); |
|
|
|
*(ckt->CKTstate0 + here->DIOcurrent) = |
|
|
|
*(ckt->CKTstate0 + here->DIOcurrent) = |
|
|
|
*(ckt->CKTstate1 + here->DIOcurrent); |
|
|
|
*(ckt->CKTstate0 + here->DIOconduct) = |
|
|
|
*(ckt->CKTstate0 + here->DIOconduct) = |
|
|
|
*(ckt->CKTstate1 + here->DIOconduct); |
|
|
|
} else { |
|
|
|
#endif /* PREDICTOR */ |
|
|
|
@ -140,12 +140,12 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
} |
|
|
|
#endif /* PREDICTOR */ |
|
|
|
delvd=vd- *(ckt->CKTstate0 + here->DIOvoltage); |
|
|
|
cdhat= *(ckt->CKTstate0 + here->DIOcurrent) + |
|
|
|
cdhat= *(ckt->CKTstate0 + here->DIOcurrent) + |
|
|
|
*(ckt->CKTstate0 + here->DIOconduct) * delvd; |
|
|
|
/* |
|
|
|
/* |
|
|
|
* bypass if solution has not changed |
|
|
|
*/ |
|
|
|
#ifndef NOBYPASS |
|
|
|
#ifndef NOBYPASS |
|
|
|
if ((!(ckt->CKTmode & MODEINITPRED)) && (ckt->CKTbypass)) { |
|
|
|
tol=ckt->CKTvoltTol + ckt->CKTreltol* |
|
|
|
MAX(fabs(vd),fabs(*(ckt->CKTstate0 +here->DIOvoltage))); |
|
|
|
@ -166,7 +166,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
/* |
|
|
|
* limit new junction voltage |
|
|
|
*/ |
|
|
|
if ( (model->DIObreakdownVoltageGiven) && |
|
|
|
if ( (model->DIObreakdownVoltageGiven) && |
|
|
|
(vd < MIN(0,-here->DIOtBrkdwnV+10*vte))) { |
|
|
|
vdtemp = -(vd+here->DIOtBrkdwnV); |
|
|
|
vdtemp = DEVpnjlim(vdtemp, |
|
|
|
@ -183,58 +183,58 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt) |
|
|
|
* compute dc current and derivitives |
|
|
|
*/ |
|
|
|
next1: if (vd >= -3*vte) { /* forward */ |
|
|
|
|
|
|
|
evd = exp(vd/vte); |
|
|
|
|
|
|
|
evd = exp(vd/vte); |
|
|
|
cd = csat*(evd-1) + ckt->CKTgmin*vd; |
|
|
|
gd = csat*evd/vte + ckt->CKTgmin; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( (model->DIOforwardKneeCurrentGiven) && (model->DIOforwardKneeCurrent > 0.0) && (cd > 1.0e-18) ) { |
|
|
|
gd = gd-ckt->CKTgmin; |
|
|
|
cd = cd-ckt->CKTgmin*vd; |
|
|
|
ikf_area_m = model->DIOforwardKneeCurrent*here->DIOarea*here->DIOm; |
|
|
|
sqrt_ikf = sqrt(cd/ikf_area_m); |
|
|
|
gd = ((1+sqrt_ikf)*gd - cd*gd/(2*sqrt_ikf*ikf_area_m))/(1+2*sqrt_ikf+cd/ikf_area_m)+ckt->CKTgmin; |
|
|
|
cd = cd/(1+sqrt_ikf)+ckt->CKTgmin*vd; |
|
|
|
gd = gd-ckt->CKTgmin; |
|
|
|
cd = cd-ckt->CKTgmin*vd; |
|
|
|
ikf_area_m = model->DIOforwardKneeCurrent*here->DIOarea*here->DIOm; |
|
|
|
sqrt_ikf = sqrt(cd/ikf_area_m); |
|
|
|
gd = ((1+sqrt_ikf)*gd - cd*gd/(2*sqrt_ikf*ikf_area_m))/(1+2*sqrt_ikf+cd/ikf_area_m)+ckt->CKTgmin; |
|
|
|
cd = cd/(1+sqrt_ikf)+ckt->CKTgmin*vd; |
|
|
|
} |
|
|
|
|
|
|
|
} else if((!(model->DIObreakdownVoltageGiven)) || /* reverse*/ |
|
|
|
|
|
|
|
} else if((!(model->DIObreakdownVoltageGiven)) || /* reverse */ |
|
|
|
vd >= -here->DIOtBrkdwnV) { |
|
|
|
|
|
|
|
arg=3*vte/(vd*CONSTe); |
|
|
|
|
|
|
|
arg = 3*vte/(vd*CONSTe); |
|
|
|
arg = arg * arg * arg; |
|
|
|
cd = -csat*(1+arg) + ckt->CKTgmin*vd ; |
|
|
|
gd = csat*3*arg/vd + ckt->CKTgmin; |
|
|
|
|
|
|
|
if( (model->DIOreverseKneeCurrentGiven) && (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { |
|
|
|
gd = gd-ckt->CKTgmin; |
|
|
|
cd = cd-ckt->CKTgmin*vd; |
|
|
|
ikr_area_m = model->DIOreverseKneeCurrent*here->DIOarea*here->DIOm; |
|
|
|
sqrt_ikr = sqrt(cd/(-ikr_area_m)); |
|
|
|
gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m)+ckt->CKTgmin; |
|
|
|
cd = cd/(1+sqrt_ikr)+ckt->CKTgmin*vd; |
|
|
|
|
|
|
|
if( (model->DIOreverseKneeCurrentGiven) && (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { |
|
|
|
gd = gd-ckt->CKTgmin; |
|
|
|
cd = cd-ckt->CKTgmin*vd; |
|
|
|
ikr_area_m = model->DIOreverseKneeCurrent*here->DIOarea*here->DIOm; |
|
|
|
sqrt_ikr = sqrt(cd/(-ikr_area_m)); |
|
|
|
gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m)+ckt->CKTgmin; |
|
|
|
cd = cd/(1+sqrt_ikr)+ckt->CKTgmin*vd; |
|
|
|
} |
|
|
|
|
|
|
|
} else { /* breakdown */ |
|
|
|
evrev=exp(-(here->DIOtBrkdwnV+vd)/vte); |
|
|
|
|
|
|
|
} else { /* breakdown */ |
|
|
|
|
|
|
|
evrev = exp(-(here->DIOtBrkdwnV+vd)/vte); |
|
|
|
cd = -csat*evrev + ckt->CKTgmin*vd; |
|
|
|
gd = csat*evrev/vte + ckt->CKTgmin; |
|
|
|
|
|
|
|
if( (model->DIOreverseKneeCurrentGiven) && (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { |
|
|
|
gd = gd-ckt->CKTgmin; |
|
|
|
cd = cd-ckt->CKTgmin*vd; |
|
|
|
ikr_area_m = model->DIOreverseKneeCurrent*here->DIOarea*here->DIOm; |
|
|
|
sqrt_ikr = sqrt(cd/(-ikr_area_m)); |
|
|
|
gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m); |
|
|
|
cd = cd/(1+sqrt_ikr); |
|
|
|
|
|
|
|
if( (model->DIOreverseKneeCurrentGiven) && (model->DIOreverseKneeCurrent > 0.0) && (cd < -1.0e-18) ) { |
|
|
|
gd = gd-ckt->CKTgmin; |
|
|
|
cd = cd-ckt->CKTgmin*vd; |
|
|
|
ikr_area_m = model->DIOreverseKneeCurrent*here->DIOarea*here->DIOm; |
|
|
|
sqrt_ikr = sqrt(cd/(-ikr_area_m)); |
|
|
|
gd = ((1+sqrt_ikr)*gd + cd*gd/(2*sqrt_ikr*ikr_area_m))/(1+2*sqrt_ikr - cd/ikr_area_m); |
|
|
|
cd = cd/(1+sqrt_ikr); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) || |
|
|
|
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) { |
|
|
|
/* |
|
|
|
* charge storage elements |
|
|
|
*/ |
|
|
|
if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) || |
|
|
|
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) { |
|
|
|
/* |
|
|
|
* charge storage elements |
|
|
|
*/ |
|
|
|
czero=here->DIOtJctCap*here->DIOarea*here->DIOm; |
|
|
|
czeroSW=here->DIOtJctSWCap*here->DIOpj*here->DIOm; |
|
|
|
if (vd < here->DIOtDepCap){ |
|
|
|
@ -242,7 +242,7 @@ next1: if (vd >= -3*vte) { /* forward */ |
|
|
|
argSW=1-vd/here->DIOtJctSWPot; |
|
|
|
sarg=exp(-here->DIOtGradingCoeff*log(arg)); |
|
|
|
sargSW=exp(-model->DIOgradingSWCoeff*log(argSW)); |
|
|
|
*(ckt->CKTstate0 + here->DIOcapCharge) = |
|
|
|
*(ckt->CKTstate0 + here->DIOcapCharge) = |
|
|
|
here->DIOtTransitTime*cd+ |
|
|
|
here->DIOtJctPot*czero*(1-arg*sarg)/(1-here->DIOtGradingCoeff)+ |
|
|
|
here->DIOtJctSWPot*czeroSW*(1-argSW*sargSW)/(1-model->DIOgradingSWCoeff); |
|
|
|
@ -250,7 +250,7 @@ next1: if (vd >= -3*vte) { /* forward */ |
|
|
|
} else { |
|
|
|
czof2=czero/here->DIOtF2; |
|
|
|
czof2SW=czeroSW/here->DIOtF2SW; |
|
|
|
*(ckt->CKTstate0 + here->DIOcapCharge) = |
|
|
|
*(ckt->CKTstate0 + here->DIOcapCharge) = |
|
|
|
here->DIOtTransitTime*cd+czero*here->DIOtF1+ |
|
|
|
czof2*(here->DIOtF3*(vd-here->DIOtDepCap)+(here->DIOtGradingCoeff/(here->DIOtJctPot+here->DIOtJctPot))*(vd*vd-here->DIOtDepCap*here->DIOtDepCap))+ |
|
|
|
czof2SW*(here->DIOtF3SW*(vd-here->DIOtDepCap)+(model->DIOgradingSWCoeff/(here->DIOtJctSWPot+here->DIOtJctSWPot))*(vd*vd-here->DIOtDepCap*here->DIOtDepCap)); |
|
|
|
@ -258,12 +258,12 @@ next1: if (vd >= -3*vte) { /* forward */ |
|
|
|
czof2*(here->DIOtF3+here->DIOtGradingCoeff*vd/here->DIOtJctPot)+ |
|
|
|
czof2SW*(here->DIOtF3SW+model->DIOgradingSWCoeff*vd/here->DIOtJctSWPot); |
|
|
|
} |
|
|
|
here->DIOcap = capd; |
|
|
|
here->DIOcap = capd; |
|
|
|
|
|
|
|
/* |
|
|
|
* store small-signal parameters |
|
|
|
*/ |
|
|
|
if( (!(ckt->CKTmode & MODETRANOP)) || |
|
|
|
if( (!(ckt->CKTmode & MODETRANOP)) || |
|
|
|
(!(ckt->CKTmode & MODEUIC)) ) { |
|
|
|
if (ckt->CKTmode & MODEINITSMSIG){ |
|
|
|
*(ckt->CKTstate0 + here->DIOcapCurrent) = capd; |
|
|
|
@ -295,7 +295,7 @@ next1: if (vd >= -3*vte) { /* forward */ |
|
|
|
} |
|
|
|
|
|
|
|
if (ckt->CKTmode & MODEINITTRAN) { |
|
|
|
*(ckt->CKTstate1 + here->DIOcapCharge) = |
|
|
|
*(ckt->CKTstate1 + here->DIOcapCharge) = |
|
|
|
*(ckt->CKTstate0 + here->DIOcapCharge); |
|
|
|
} |
|
|
|
error = NIintegrate(ckt,&geq,&ceq,capd,here->DIOcapCharge); |
|
|
|
@ -303,7 +303,7 @@ next1: if (vd >= -3*vte) { /* forward */ |
|
|
|
gd=gd+geq; |
|
|
|
cd=cd+*(ckt->CKTstate0 + here->DIOcapCurrent); |
|
|
|
if (ckt->CKTmode & MODEINITTRAN) { |
|
|
|
*(ckt->CKTstate1 + here->DIOcapCurrent) = |
|
|
|
*(ckt->CKTstate1 + here->DIOcapCurrent) = |
|
|
|
*(ckt->CKTstate0 + here->DIOcapCurrent); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -317,7 +317,7 @@ next1: if (vd >= -3*vte) { /* forward */ |
|
|
|
if ( (!(ckt->CKTmode & MODEINITFIX)) || (!(here->DIOoff)) ) { |
|
|
|
if (Check == 1) { |
|
|
|
ckt->CKTnoncon++; |
|
|
|
ckt->CKTtroubleElt = (GENinstance *) here; |
|
|
|
ckt->CKTtroubleElt = (GENinstance *) here; |
|
|
|
} |
|
|
|
} |
|
|
|
next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd; |
|
|
|
|