Add optional switch for separate bottom and sidewall diode model - configuration is dependent from model parameter RSW
Further sidewall knee current parameter IKP is implemented.
This commit is contained in:
parent
f8d341b05a
commit
284d4308db
|
|
@ -55,6 +55,7 @@ IFparm DIOmPTable[] = { /* model parameters */
|
|||
IOPU( "tnom",DIO_MOD_TNOM,IF_REAL, "Parameter measurement temperature"),
|
||||
IOPUR("tref",DIO_MOD_TNOM,IF_REAL, "Parameter measurement temperature"),
|
||||
IOP( "rs", DIO_MOD_RS, IF_REAL, "Ohmic resistance"),
|
||||
IOP( "rsw", DIO_MOD_RSW, IF_REAL, "Ohmic resistance sidewall"),
|
||||
IOP( "trs", DIO_MOD_TRS, IF_REAL, "Ohmic resistance 1st order temp. coeff."),
|
||||
IOPR( "trs1", DIO_MOD_TRS, IF_REAL, "Ohmic resistance 1st order temp. coeff."),
|
||||
IOP( "trs2", DIO_MOD_TRS2, IF_REAL, "Ohmic resistance 2nd order temp. coeff."),
|
||||
|
|
@ -80,6 +81,7 @@ IFparm DIOmPTable[] = { /* model parameters */
|
|||
IOP( "ikf", DIO_MOD_IKF, IF_REAL, "Forward Knee current"),
|
||||
IOPR( "ik", DIO_MOD_IKF, IF_REAL, "Forward Knee current"),
|
||||
IOP( "ikr", DIO_MOD_IKR, IF_REAL, "Reverse Knee current"),
|
||||
IOP( "ikp", DIO_MOD_IKP, IF_REAL, "Forward Sw Knee current"),
|
||||
IOP( "nbv", DIO_MOD_NBV, IF_REAL, "Breakdown Emission Coefficient"),
|
||||
IOPR( "nz", DIO_MOD_NBV, IF_REAL, "Breakdown Emission Coefficient"),
|
||||
IOP("area", DIO_MOD_AREA, IF_REAL, "Area factor"),
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ int
|
|||
DIOacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
||||
{
|
||||
DIOmodel *model = (DIOmodel*)inModel;
|
||||
double gspr;
|
||||
double gspr, gsprsw;
|
||||
double geq;
|
||||
double xceq;
|
||||
DIOinstance *here;
|
||||
|
|
@ -42,6 +42,23 @@ DIOacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(here->DIOposPrimePosPtr ) -= gspr;
|
||||
*(here->DIOposPrimeNegPtr ) -= geq;
|
||||
*(here->DIOposPrimeNegPtr +1 ) -= xceq;
|
||||
if (model->DIOresistSWGiven) {
|
||||
gsprsw=here->DIOtConductanceSW;
|
||||
geq= *(ckt->CKTstate0 + here->DIOconductSW);
|
||||
xceq= *(ckt->CKTstate0 + here->DIOcapCurrentSW) * ckt->CKTomega;
|
||||
*(here->DIOposPosPtr) += gsprsw;
|
||||
*(here->DIOnegNegPtr) += geq;
|
||||
*(here->DIOnegNegPtr + 1) += xceq;
|
||||
*(here->DIOposSwPrimePosSwPrimePtr) += (geq + gsprsw);
|
||||
*(here->DIOposSwPrimePosSwPrimePtr + 1) += xceq;
|
||||
*(here->DIOposPosSwPrimePtr) -= gsprsw;
|
||||
*(here->DIOnegPosSwPrimePtr) -= geq;
|
||||
*(here->DIOnegPosSwPrimePtr + 1) -= xceq;
|
||||
*(here->DIOposSwPrimePosPtr) -= gsprsw;
|
||||
*(here->DIOposSwPrimeNegPtr) -= geq;
|
||||
*(here->DIOposSwPrimeNegPtr + 1) -= xceq;
|
||||
}
|
||||
|
||||
int selfheat = ((here->DIOtempNode > 0) && (here->DIOthermal) && (model->DIOrth0Given));
|
||||
if (selfheat) {
|
||||
double dIth_dVrs = here->DIOdIth_dVrs;
|
||||
|
|
@ -60,6 +77,19 @@ DIOacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
|||
|
||||
double xgcTt= *(ckt->CKTstate0 + here->DIOcqth) * ckt->CKTomega;
|
||||
(*(here->DIOtempTempPtr + 1) += xgcTt);
|
||||
|
||||
if (model->DIOresistSWGiven) {
|
||||
double dIth_dVrssw = here->DIOdIth_dVrs;
|
||||
double dIth_dVdioSw = here->DIOdIth_dVdio;
|
||||
double dIrssw_dT = here->DIOdIrs_dT;
|
||||
double dIdioSw_dT = *(ckt->CKTstate0 + here->DIOdIdio_dT);
|
||||
(*(here->DIOtempPosPtr) += -dIth_dVrssw);
|
||||
(*(here->DIOtempPosSwPrimePtr) += -dIth_dVdioSw + dIth_dVrssw);
|
||||
(*(here->DIOtempNegPtr) += dIth_dVdioSw);
|
||||
(*(here->DIOposTempPtr) += dIrssw_dT);
|
||||
(*(here->DIOposSwPrimeTempPtr) += dIdioSw_dT - dIrssw_dT);
|
||||
(*(here->DIOnegTempPtr) += -dIdioSw_dT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ DIObindCSC (GENmodel *inModel, CKTcircuit *ckt)
|
|||
CREATE_KLU_BINDING_TABLE(DIOposPosPtr, DIOposPosBinding, DIOposNode, DIOposNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOnegNegPtr, DIOnegNegBinding, DIOnegNode, DIOnegNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOposPrimePosPrimePtr, DIOposPrimePosPrimeBinding, DIOposPrimeNode, DIOposPrimeNode);
|
||||
/* separate sidewall */
|
||||
CREATE_KLU_BINDING_TABLE(DIOposPosSwPrimePtr,DIOposPosSwPrimeBinding,DIOposNode,DIOposSwPrimeNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOnegPosSwPrimePtr,DIOnegPosSwPrimeBinding,DIOnegNode,DIOposSwPrimeNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOposSwPrimePosPtr,DIOposSwPrimePosBinding,DIOposSwPrimeNode,DIOposNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOposSwPrimeNegPtr,DIOposSwPrimeNegBinding,DIOposSwPrimeNode,DIOnegNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOposSwPrimePosSwPrimePtr,DIOposSwPrimePosSwPrimeBinding,DIOposSwPrimeNode,DIOposSwPrimeNode);
|
||||
if ((here->DIOtempNode > 0) && (here->DIOthermal) && (model->DIOrth0Given)) {
|
||||
CREATE_KLU_BINDING_TABLE(DIOtempPosPtr, DIOtempPosBinding, DIOtempNode, DIOposNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOtempPosPrimePtr, DIOtempPosPrimeBinding, DIOtempNode, DIOposPrimeNode);
|
||||
|
|
@ -40,6 +46,9 @@ DIObindCSC (GENmodel *inModel, CKTcircuit *ckt)
|
|||
CREATE_KLU_BINDING_TABLE(DIOposTempPtr, DIOposTempBinding, DIOposNode, DIOtempNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOposPrimeTempPtr, DIOposPrimeTempBinding, DIOposPrimeNode, DIOtempNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOnegTempPtr, DIOnegTempBinding, DIOnegNode, DIOtempNode);
|
||||
/* separate sidewall */
|
||||
CREATE_KLU_BINDING_TABLE(DIOtempPosSwPrimePtr, DIOtempPosSwPrimeBinding, DIOtempNode, DIOposSwPrimeNode);
|
||||
CREATE_KLU_BINDING_TABLE(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -68,6 +77,12 @@ DIObindCSCComplex (GENmodel *inModel, CKTcircuit *ckt)
|
|||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposPosPtr, DIOposPosBinding, DIOposNode, DIOposNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOnegNegPtr, DIOnegNegBinding, DIOnegNode, DIOnegNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposPrimePosPrimePtr, DIOposPrimePosPrimeBinding, DIOposPrimeNode, DIOposPrimeNode);
|
||||
/* separate sidewall */
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposPosSwPrimePtr,DIOposPosSwPrimeBinding,DIOposNode,DIOposSwPrimeNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOnegPosSwPrimePtr,DIOnegPosSwPrimeBinding,DIOnegNode,DIOposSwPrimeNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposSwPrimePosPtr,DIOposSwPrimePosBinding,DIOposSwPrimeNode,DIOposNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposSwPrimeNegPtr,DIOposSwPrimeNegBinding,DIOposSwPrimeNode,DIOnegNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposSwPrimePosSwPrimePtr,DIOposSwPrimePosSwPrimeBinding,DIOposSwPrimeNode,DIOposSwPrimeNode);
|
||||
if ((here->DIOtempNode > 0) && (here->DIOthermal) && (model->DIOrth0Given)) {
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOtempPosPtr, DIOtempPosBinding, DIOtempNode, DIOposNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOtempPosPrimePtr, DIOtempPosPrimeBinding, DIOtempNode, DIOposPrimeNode);
|
||||
|
|
@ -76,6 +91,9 @@ DIObindCSCComplex (GENmodel *inModel, CKTcircuit *ckt)
|
|||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposTempPtr, DIOposTempBinding, DIOposNode, DIOtempNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposPrimeTempPtr, DIOposPrimeTempBinding, DIOposPrimeNode, DIOtempNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOnegTempPtr, DIOnegTempBinding, DIOnegNode, DIOtempNode);
|
||||
/* separate sidewall */
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOtempPosSwPrimePtr, DIOtempPosSwPrimeBinding, DIOtempNode, DIOposSwPrimeNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_COMPLEX(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -104,6 +122,12 @@ DIObindCSCComplexToReal (GENmodel *inModel, CKTcircuit *ckt)
|
|||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposPosPtr, DIOposPosBinding, DIOposNode, DIOposNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOnegNegPtr, DIOnegNegBinding, DIOnegNode, DIOnegNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposPrimePosPrimePtr, DIOposPrimePosPrimeBinding, DIOposPrimeNode, DIOposPrimeNode);
|
||||
/* separate sidewall */
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposPosSwPrimePtr,DIOposPosSwPrimeBinding,DIOposNode,DIOposSwPrimeNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOnegPosSwPrimePtr,DIOnegPosSwPrimeBinding,DIOnegNode,DIOposSwPrimeNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposSwPrimePosPtr,DIOposSwPrimePosBinding,DIOposSwPrimeNode,DIOposNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposSwPrimeNegPtr,DIOposSwPrimeNegBinding,DIOposSwPrimeNode,DIOnegNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposSwPrimePosSwPrimePtr,DIOposSwPrimePosSwPrimeBinding,DIOposSwPrimeNode,DIOposSwPrimeNode);
|
||||
if ((here->DIOtempNode > 0) && (here->DIOthermal) && (model->DIOrth0Given)) {
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOtempPosPtr, DIOtempPosBinding, DIOtempNode, DIOposNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOtempPosPrimePtr, DIOtempPosPrimeBinding, DIOtempNode, DIOposPrimeNode);
|
||||
|
|
@ -112,6 +136,9 @@ DIObindCSCComplexToReal (GENmodel *inModel, CKTcircuit *ckt)
|
|||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposTempPtr, DIOposTempBinding, DIOposNode, DIOtempNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposPrimeTempPtr, DIOposPrimeTempBinding, DIOposPrimeNode, DIOtempNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOnegTempPtr, DIOnegTempBinding, DIOnegNode, DIOtempNode);
|
||||
/* separate sidewall */
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOtempPosSwPrimePtr, DIOtempPosSwPrimeBinding, DIOtempNode, DIOposSwPrimeNode);
|
||||
CONVERT_KLU_BINDING_TABLE_TO_REAL(DIOposSwPrimeTempPtr, DIOposSwPrimeTempBinding, DIOposSwPrimeNode, DIOtempNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ DIOconvTest(GENmodel *inModel, CKTcircuit *ckt)
|
|||
{
|
||||
DIOmodel *model = (DIOmodel*)inModel;
|
||||
DIOinstance *here;
|
||||
double delvd,vd,cdhat,cd;
|
||||
double delvd,vd,cdhat,cd,vdsw,cdhatsw=0.0,cdsw=0.0;
|
||||
double tol;
|
||||
double delTemp, deldelTemp;
|
||||
/* loop through all the diode models */
|
||||
|
|
@ -46,11 +46,23 @@ DIOconvTest(GENmodel *inModel, CKTcircuit *ckt)
|
|||
deldelTemp = delTemp - *(ckt->CKTstate0 + here->DIOdeltemp);
|
||||
|
||||
cdhat= *(ckt->CKTstate0 + here->DIOcurrent) +
|
||||
*(ckt->CKTstate0 + here->DIOconduct) * delvd +
|
||||
*(ckt->CKTstate0 + here->DIOdIdio_dT) * deldelTemp;
|
||||
*(ckt->CKTstate0 + here->DIOconduct) * delvd +
|
||||
*(ckt->CKTstate0 + here->DIOdIdio_dT) * deldelTemp;
|
||||
|
||||
cd= *(ckt->CKTstate0 + here->DIOcurrent);
|
||||
|
||||
if (model->DIOresistSWGiven) {
|
||||
vdsw = *(ckt->CKTrhsOld+here->DIOposSwPrimeNode)-
|
||||
*(ckt->CKTrhsOld + here->DIOnegNode);
|
||||
|
||||
delvd=vdsw- *(ckt->CKTstate0 + here->DIOvoltageSW);
|
||||
|
||||
cdhatsw= *(ckt->CKTstate0 + here->DIOcurrentSW) +
|
||||
*(ckt->CKTstate0 + here->DIOconductSW) * delvd +
|
||||
*(ckt->CKTstate0 + here->DIOdIdioSW_dT) * deldelTemp;
|
||||
|
||||
cdsw= *(ckt->CKTstate0 + here->DIOcurrentSW);
|
||||
}
|
||||
/*
|
||||
* check convergence
|
||||
*/
|
||||
|
|
@ -61,6 +73,15 @@ DIOconvTest(GENmodel *inModel, CKTcircuit *ckt)
|
|||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
return(OK); /* don't need to check any more device */
|
||||
}
|
||||
if (model->DIOresistSWGiven) {
|
||||
tol=ckt->CKTreltol*
|
||||
MAX(fabs(cdhatsw),fabs(cdsw))+ckt->CKTabstol;
|
||||
if (fabs(cdhatsw-cdsw) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
return(OK); /* no reason to continue - we've failed... */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ enum {
|
|||
DIORSNOIZ = 0,
|
||||
DIOIDNOIZ,
|
||||
DIOFLNOIZ,
|
||||
DIORSSWNOIZ,
|
||||
DIOIDSWNOIZ,
|
||||
DIOFLSWNOIZ,
|
||||
DIOTOTNOIZ,
|
||||
/* finally, the number of noise sources */
|
||||
DIONSRCS
|
||||
|
|
@ -40,6 +43,7 @@ typedef struct sDIOinstance {
|
|||
const int DIOnegNode; /* number of negative node of diode */
|
||||
const int DIOtempNode; /* number of the temperature node of the diode */
|
||||
int DIOposPrimeNode; /* number of positive prime node of diode */
|
||||
int DIOposSwPrimeNode; /* number of positive prime node of diode sidewall */
|
||||
|
||||
double *DIOposPosPrimePtr; /* pointer to sparse matrix at
|
||||
* (positive,positive prime) */
|
||||
|
|
@ -55,6 +59,17 @@ typedef struct sDIOinstance {
|
|||
* (negative,negative) */
|
||||
double *DIOposPrimePosPrimePtr; /* pointer to sparse matrix at
|
||||
* (positive prime,positive prime) */
|
||||
/* separate sidewall */
|
||||
double *DIOposPosSwPrimePtr; /* pointer to sparse matrix at
|
||||
* (positive,positive prime sidewall) */
|
||||
double *DIOnegPosSwPrimePtr; /* pointer to sparse matrix at
|
||||
* (negative,positive prime sidewall) */
|
||||
double *DIOposSwPrimePosPtr; /* pointer to sparse matrix at
|
||||
* (positive prime sidewall,positive) */
|
||||
double *DIOposSwPrimeNegPtr; /* pointer to sparse matrix at
|
||||
* (positive prime sidewall,negative) */
|
||||
double *DIOposSwPrimePosSwPrimePtr; /* pointer to sparse matrix at
|
||||
* (positive prime sidewall,positive prime sidewall) */
|
||||
|
||||
/* self heating */
|
||||
double *DIOtempPosPtr;
|
||||
|
|
@ -64,8 +79,12 @@ typedef struct sDIOinstance {
|
|||
double *DIOposTempPtr;
|
||||
double *DIOposPrimeTempPtr;
|
||||
double *DIOnegTempPtr;
|
||||
/* separate sidewall */
|
||||
double *DIOtempPosSwPrimePtr;
|
||||
double *DIOposSwPrimeTempPtr;
|
||||
|
||||
double DIOcap; /* stores the diode capacitance */
|
||||
double DIOcapSW; /* stores the diode Sw capacitance */
|
||||
|
||||
double *DIOsens; /* stores the perturbed values of geq and ceq in ac
|
||||
sensitivity analyis */
|
||||
|
|
@ -114,6 +133,8 @@ typedef struct sDIOinstance {
|
|||
double DIOtGradingCoeff; /* temperature adjusted grading coefficient (MJ) */
|
||||
double DIOtConductance; /* temperature adjusted series conductance */
|
||||
double DIOtConductance_dT; /* temperature adjusted series conductance temperature derivative */
|
||||
double DIOtConductanceSW; /* temperature adjusted sw series conductance */
|
||||
double DIOtConductanceSW_dT; /* temperature adjusted sw series conductance temperature derivative */
|
||||
|
||||
double DIOtDepCap; /* temperature adjusted transition point in */
|
||||
/* the curve matching (Fc * Vj ) */
|
||||
|
|
@ -129,6 +150,7 @@ typedef struct sDIOinstance {
|
|||
double DIOtTunSatSWCur_dT; /* sidewall tunneling saturation current temperature derivative */
|
||||
|
||||
double DIOtVcrit; /* temperature adjusted V crit */
|
||||
double DIOtVcritSW; /* temperature adjusted V crit sidewall*/
|
||||
double DIOtF1; /* temperature adjusted f1 */
|
||||
double DIOtBrkdwnV; /* temperature adjusted breakdown voltage */
|
||||
|
||||
|
|
@ -139,17 +161,21 @@ typedef struct sDIOinstance {
|
|||
|
||||
double DIOforwardKneeCurrent; /* Forward Knee current */
|
||||
double DIOreverseKneeCurrent; /* Reverse Knee current */
|
||||
double DIOforwardSWKneeCurrent; /* Forward Sw Knee current */
|
||||
double DIOjunctionCap; /* geometry adjusted junction capacitance */
|
||||
double DIOjunctionSWCap; /* geometry adjusted junction sidewall capacitance */
|
||||
double DIOtRecSatCur; /* temperature adjusted recombination saturation current */
|
||||
double DIOtRecSatCur_dT; /* temperature adjusted recombination saturation current */
|
||||
|
||||
double DIOdIth_dVrs;
|
||||
double DIOdIth_dVrssw;
|
||||
double DIOdIth_dVdio;
|
||||
double DIOdIth_dT;
|
||||
double DIOgcTt;
|
||||
double DIOdIrs_dT;
|
||||
double DIOdIrssw_dT;
|
||||
double DIOdIdio_dT;
|
||||
double DIOdIdioSW_dT;
|
||||
|
||||
double DIOcmetal; /* parasitic metal overlap capacitance */
|
||||
double DIOcpoly; /* parasitic polysilicon overlap capacitance */
|
||||
|
|
@ -194,6 +220,12 @@ typedef struct sDIOinstance {
|
|||
BindElement *DIOposPosBinding ;
|
||||
BindElement *DIOnegNegBinding ;
|
||||
BindElement *DIOposPrimePosPrimeBinding ;
|
||||
/* separate sidewall */
|
||||
BindElement *DIOposPosSwPrimeBinding ;
|
||||
BindElement *DIOnegPosSwPrimeBinding ;
|
||||
BindElement *DIOposSwPrimePosBinding ;
|
||||
BindElement *DIOposSwPrimeNegBinding ;
|
||||
BindElement *DIOposSwPrimePosSwPrimeBinding ;
|
||||
/* self heating */
|
||||
BindElement *DIOtempPosBinding;
|
||||
BindElement *DIOtempPosPrimeBinding;
|
||||
|
|
@ -216,18 +248,24 @@ typedef struct sDIOinstance {
|
|||
#define DIOvoltage DIOstate
|
||||
#define DIOcurrent DIOstate+1
|
||||
#define DIOconduct DIOstate+2
|
||||
#define DIOcapCharge DIOstate+3
|
||||
#define DIOcapCurrent DIOstate+4
|
||||
#define DIOvoltageSW DIOstate+3
|
||||
#define DIOcurrentSW DIOstate+4
|
||||
#define DIOconductSW DIOstate+5
|
||||
#define DIOcapCharge DIOstate+6
|
||||
#define DIOcapCurrent DIOstate+7
|
||||
#define DIOcapChargeSW DIOstate+8
|
||||
#define DIOcapCurrentSW DIOstate+9
|
||||
|
||||
#define DIOqth DIOstate+5 /* thermal capacitor charge */
|
||||
#define DIOcqth DIOstate+6 /* thermal capacitor current */
|
||||
#define DIOqth DIOstate+10 /* thermal capacitor charge */
|
||||
#define DIOcqth DIOstate+11 /* thermal capacitor current */
|
||||
|
||||
#define DIOdeltemp DIOstate+7 /* thermal voltage over rth0 */
|
||||
#define DIOdIdio_dT DIOstate+8
|
||||
#define DIOdeltemp DIOstate+12 /* thermal voltage over rth0 */
|
||||
#define DIOdIdio_dT DIOstate+13
|
||||
#define DIOdIdioSW_dT DIOstate+14
|
||||
|
||||
#define DIOnumStates 9
|
||||
#define DIOnumStates 15
|
||||
|
||||
#define DIOsensxp DIOstate+9 /* charge sensitivities and their derivatives.
|
||||
#define DIOsensxp DIOstate+12 /* charge sensitivities and their derivatives.
|
||||
* +10 for the derivatives - pointer to the
|
||||
* beginning of the array */
|
||||
|
||||
|
|
@ -252,6 +290,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
|||
unsigned DIOresistGiven : 1;
|
||||
unsigned DIOresistTemp1Given : 1;
|
||||
unsigned DIOresistTemp2Given : 1;
|
||||
unsigned DIOresistSWGiven : 1;
|
||||
unsigned DIOemissionCoeffGiven : 1;
|
||||
unsigned DIOswEmissionCoeffGiven : 1;
|
||||
unsigned DIObrkdEmissionCoeffGiven : 1;
|
||||
|
|
@ -268,6 +307,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
|||
unsigned DIOgradingSWCoeffGiven : 1;
|
||||
unsigned DIOforwardKneeCurrentGiven : 1;
|
||||
unsigned DIOreverseKneeCurrentGiven : 1;
|
||||
unsigned DIOforwardSWKneeCurrentGiven : 1;
|
||||
|
||||
unsigned DIOtlevGiven : 1;
|
||||
unsigned DIOtlevcGiven : 1;
|
||||
|
|
@ -324,6 +364,8 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
|||
double DIOresistTemp1; /* series resistance 1st order temp. coeff. */
|
||||
double DIOresistTemp2; /* series resistance 2nd order temp. coeff. */
|
||||
double DIOconductance; /* conductance corresponding to ohmic R */
|
||||
double DIOresistSW; /* ohmic series resistance sidewall */
|
||||
double DIOconductanceSW; /* conductance corresponding to ohmic R */
|
||||
double DIOemissionCoeff; /* emission coefficient (N) */
|
||||
double DIOswEmissionCoeff; /* Sidewall emission coefficient (NS) */
|
||||
double DIObrkdEmissionCoeff; /* Breakdown emission coefficient (NBV) */
|
||||
|
|
@ -340,6 +382,7 @@ typedef struct sDIOmodel { /* model structure for a diode */
|
|||
double DIOgradingSWCoeff; /* Sidewall grading coefficient (mjsw) */
|
||||
double DIOforwardKneeCurrent; /* Forward Knee current (IKF) */
|
||||
double DIOreverseKneeCurrent; /* Reverse Knee current (IKR) */
|
||||
double DIOforwardSWKneeCurrent; /* Forward Sw Knee current (IKP) */
|
||||
|
||||
int DIOtlev; /* Diode temperature equation selector */
|
||||
int DIOtlevc; /* Diode temperature equation selector */
|
||||
|
|
@ -428,6 +471,7 @@ enum {
|
|||
DIO_MOD_LEVEL = 100,
|
||||
DIO_MOD_IS,
|
||||
DIO_MOD_RS,
|
||||
DIO_MOD_RSW,
|
||||
DIO_MOD_N,
|
||||
DIO_MOD_TT,
|
||||
DIO_MOD_CJO,
|
||||
|
|
@ -451,6 +495,7 @@ enum {
|
|||
DIO_MOD_MJSW,
|
||||
DIO_MOD_IKF,
|
||||
DIO_MOD_IKR,
|
||||
DIO_MOD_IKP,
|
||||
DIO_MOD_FCS,
|
||||
DIO_MOD_TTT1,
|
||||
DIO_MOD_TTT2,
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
DIOinstance *here;
|
||||
double arg;
|
||||
double argsw;
|
||||
double capd;
|
||||
double capd, capdsw=0.0;
|
||||
double cd, cdb, cdsw, cdb_dT, cdsw_dT;
|
||||
double cdeq;
|
||||
double cdhat;
|
||||
double cdhat, cdhatsw=0.0;
|
||||
double ceq;
|
||||
double csat; /* area-scaled saturation current */
|
||||
double csatsw; /* perimeter-scaled saturation current */
|
||||
|
|
@ -37,34 +37,33 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
double czeroSW;
|
||||
double czof2SW;
|
||||
double sargSW;
|
||||
double sqrt_ikr;
|
||||
double sqrt_ikf;
|
||||
double ikf_area_m;
|
||||
double ikr_area_m;
|
||||
double sqrt_ikx;
|
||||
|
||||
double delvd; /* change in diode voltage temporary */
|
||||
double delvd, delvdsw=0.0; /* change in diode voltage temporary */
|
||||
double evd;
|
||||
double evrev;
|
||||
double gd, gdb, gdsw, gen_fac, gen_fac_vd;
|
||||
double t1, evd_rec, cdb_rec, gdb_rec, cdb_rec_dT;
|
||||
double geq;
|
||||
double gspr; /* area-scaled conductance */
|
||||
double gsprsw; /* perim-scaled conductance */
|
||||
double sarg;
|
||||
#ifndef NOBYPASS
|
||||
double tol; /* temporary for tolerence calculations */
|
||||
#endif
|
||||
double vd; /* current diode voltage */
|
||||
double vd, vdsw=0.0; /* current diode voltage */
|
||||
double vdtemp;
|
||||
double vt; /* K t / Q */
|
||||
double vte, vtesw, vtetun, vtebrk;
|
||||
int Check_dio=0, Check_th;
|
||||
int Check_dio=0, Check_dio_sw=0, Check_th;
|
||||
int error;
|
||||
int SenCond=0; /* sensitivity condition */
|
||||
double diffcharge, deplcharge, deplchargeSW, diffcap, deplcap, deplcapSW;
|
||||
|
||||
double deldelTemp, delTemp, Temp;
|
||||
double ceqqth=0.0, Ith=0.0, gcTt=0.0, vrs=0.0;
|
||||
double ceqqth=0.0, Ith=0.0, gcTt=0.0, vrs=0.0, vrssw=0.0;
|
||||
double dIdio_dT, dIth_dVdio=0.0, dIrs_dT=0.0, dIth_dVrs=0.0, dIth_dT=0.0;
|
||||
double dIdioSw_dT=0.0, dIth_dVdioSw=0.0, dIth_dVrssw=0.0, dIrssw_dT=0.0;
|
||||
double argsw_dT, csat_dT, csatsw_dT;
|
||||
|
||||
/* loop through all the diode models */
|
||||
|
|
@ -101,8 +100,10 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
delTemp = 0.0;
|
||||
vt = CONSTKoverQ * here->DIOtemp;
|
||||
vte = model->DIOemissionCoeff * vt;
|
||||
vtesw = model->DIOswEmissionCoeff * vt;
|
||||
vtebrk = model->DIObrkdEmissionCoeff * vt;
|
||||
gspr = here->DIOtConductance;
|
||||
gsprsw = here->DIOtConductanceSW;
|
||||
/*
|
||||
* initialization
|
||||
*/
|
||||
|
|
@ -116,9 +117,11 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
if((ckt->CKTsenInfo->SENmode == TRANSEN)&&
|
||||
(ckt->CKTmode & MODEINITTRAN)) {
|
||||
vd = *(ckt->CKTstate1 + here->DIOvoltage);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate1 + here->DIOvoltageSW);
|
||||
delTemp = *(ckt->CKTstate1 + here->DIOdeltemp);
|
||||
} else{
|
||||
vd = *(ckt->CKTstate0 + here->DIOvoltage);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate0 + here->DIOvoltageSW);
|
||||
delTemp = *(ckt->CKTstate0 + here->DIOdeltemp);
|
||||
}
|
||||
|
||||
|
|
@ -128,24 +131,28 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
goto next1;
|
||||
}
|
||||
|
||||
Check_dio=1;
|
||||
Check_dio=1; Check_dio_sw=1;
|
||||
if(ckt->CKTmode & MODEINITSMSIG) {
|
||||
vd= *(ckt->CKTstate0 + here->DIOvoltage);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate0 + here->DIOvoltageSW);
|
||||
delTemp = *(ckt->CKTstate0 + here->DIOdeltemp);
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
vd= *(ckt->CKTstate1 + here->DIOvoltage);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTstate1 + here->DIOvoltageSW);
|
||||
delTemp = *(ckt->CKTstate1 + here->DIOdeltemp);
|
||||
} else if ( (ckt->CKTmode & MODEINITJCT) &&
|
||||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC) ) {
|
||||
vd=here->DIOinitCond;
|
||||
if (model->DIOresistSWGiven) vdsw = here->DIOinitCond;
|
||||
} else if ( (ckt->CKTmode & MODEINITJCT) && here->DIOoff) {
|
||||
vd=0;
|
||||
vd=vdsw=0;
|
||||
delTemp = 0.0;
|
||||
} else if ( ckt->CKTmode & MODEINITJCT) {
|
||||
vd=here->DIOtVcrit;
|
||||
vdsw=here->DIOtVcritSW;
|
||||
delTemp = 0.0;
|
||||
} else if ( ckt->CKTmode & MODEINITFIX && here->DIOoff) {
|
||||
vd=0;
|
||||
vd=vdsw=0;
|
||||
delTemp = 0.0;
|
||||
} else {
|
||||
#ifndef PREDICTOR
|
||||
|
|
@ -164,10 +171,17 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
*(ckt->CKTstate1 + here->DIOdIdio_dT);
|
||||
*(ckt->CKTstate0+here->DIOqth) =
|
||||
*(ckt->CKTstate1+here->DIOqth);
|
||||
if (model->DIOresistSWGiven) {
|
||||
vdsw = DEVpred(ckt,here->DIOvoltageSW);
|
||||
*(ckt->CKTstate0 + here->DIOdIdioSW_dT) =
|
||||
*(ckt->CKTstate1 + here->DIOdIdioSW_dT);
|
||||
}
|
||||
} else {
|
||||
#endif /* PREDICTOR */
|
||||
vd = *(ckt->CKTrhsOld+here->DIOposPrimeNode)-
|
||||
*(ckt->CKTrhsOld + here->DIOnegNode);
|
||||
if (model->DIOresistSWGiven) vdsw = *(ckt->CKTrhsOld+here->DIOposSwPrimeNode)-
|
||||
*(ckt->CKTrhsOld + here->DIOnegNode);
|
||||
if (selfheat)
|
||||
delTemp = *(ckt->CKTrhsOld + here->DIOtempNode);
|
||||
else
|
||||
|
|
@ -185,6 +199,11 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
cdhat= *(ckt->CKTstate0 + here->DIOcurrent) +
|
||||
*(ckt->CKTstate0 + here->DIOconduct) * delvd +
|
||||
*(ckt->CKTstate0 + here->DIOdIdio_dT) * deldelTemp;
|
||||
if (model->DIOresistSWGiven) {
|
||||
delvdsw=vdsw - *(ckt->CKTstate0 + here->DIOvoltageSW);
|
||||
cdhatsw = *(ckt->CKTstate0 + here->DIOconductSW) * delvdsw +
|
||||
*(ckt->CKTstate0 + here->DIOdIdioSW_dT) * deldelTemp;
|
||||
}
|
||||
/*
|
||||
* bypass if solution has not changed
|
||||
*/
|
||||
|
|
@ -192,7 +211,7 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
if ((!(ckt->CKTmode & MODEINITPRED)) && (ckt->CKTbypass)) {
|
||||
tol=ckt->CKTvoltTol + ckt->CKTreltol*
|
||||
MAX(fabs(vd),fabs(*(ckt->CKTstate0 +here->DIOvoltage)));
|
||||
if (fabs(delvd) < tol){
|
||||
if (fabs(delvd) < tol) {
|
||||
tol=ckt->CKTreltol* MAX(fabs(cdhat),
|
||||
fabs(*(ckt->CKTstate0 + here->DIOcurrent)))+
|
||||
ckt->CKTabstol;
|
||||
|
|
@ -202,12 +221,25 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
(fabs(deldelTemp) < (ckt->CKTreltol * MAX(fabs(delTemp),
|
||||
fabs(*(ckt->CKTstate0+here->DIOdeltemp)))+
|
||||
ckt->CKTvoltTol*1e4))) {
|
||||
vd= *(ckt->CKTstate0 + here->DIOvoltage);
|
||||
cd= *(ckt->CKTstate0 + here->DIOcurrent);
|
||||
gd= *(ckt->CKTstate0 + here->DIOconduct);
|
||||
delTemp = *(ckt->CKTstate0 + here->DIOdeltemp);
|
||||
dIdio_dT= *(ckt->CKTstate0 + here->DIOdIdio_dT);
|
||||
goto load;
|
||||
if ((!model->DIOresistSWGiven) || (fabs(delvdsw) < ckt->CKTvoltTol + ckt->CKTreltol *
|
||||
MAX(fabs(vdsw),fabs(*(ckt->CKTstate0+here->DIOvoltageSW))))) {
|
||||
if ((!model->DIOresistSWGiven) || (fabs(cdhatsw- *(ckt->CKTstate0 + here->DIOcurrentSW))
|
||||
< ckt->CKTreltol* MAX(fabs(cdhatsw),
|
||||
fabs(*(ckt->CKTstate0 + here->DIOcurrentSW)))+ckt->CKTabstol)) {
|
||||
vd= *(ckt->CKTstate0 + here->DIOvoltage);
|
||||
cd= *(ckt->CKTstate0 + here->DIOcurrent);
|
||||
gd= *(ckt->CKTstate0 + here->DIOconduct);
|
||||
delTemp = *(ckt->CKTstate0 + here->DIOdeltemp);
|
||||
dIdio_dT= *(ckt->CKTstate0 + here->DIOdIdio_dT);
|
||||
if (model->DIOresistSWGiven) {
|
||||
vdsw= *(ckt->CKTstate0 + here->DIOvoltageSW);
|
||||
cdsw= *(ckt->CKTstate0 + here->DIOcurrentSW);
|
||||
gdsw= *(ckt->CKTstate0 + here->DIOconductSW);
|
||||
dIdioSw_dT= *(ckt->CKTstate0 + here->DIOdIdioSW_dT);
|
||||
}
|
||||
goto load;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -228,6 +260,20 @@ DIOload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
vd = DEVpnjlim(vd,*(ckt->CKTstate0 + here->DIOvoltage),
|
||||
vte,here->DIOtVcrit,&Check_dio);
|
||||
}
|
||||
if (model->DIOresistSWGiven) {
|
||||
if ( (model->DIObreakdownVoltageGiven) &&
|
||||
(vdsw < MIN(0,-here->DIOtBrkdwnV+10*vtebrk))) {
|
||||
vdtemp = -(vdsw+here->DIOtBrkdwnV);
|
||||
vdtemp = DEVpnjlim(vdtemp,
|
||||
-(*(ckt->CKTstate0 + here->DIOvoltageSW) +
|
||||
here->DIOtBrkdwnV),vtebrk,
|
||||
here->DIOtVcritSW,&Check_dio_sw);
|
||||
vdsw = -(vdtemp+here->DIOtBrkdwnV);
|
||||
} else {
|
||||
vdsw = DEVpnjlim(vdsw,*(ckt->CKTstate0 + here->DIOvoltageSW),
|
||||
vtesw,here->DIOtVcritSW,&Check_dio_sw);
|
||||
}
|
||||
}
|
||||
if (selfheat)
|
||||
delTemp = DEVlimitlog(delTemp,
|
||||
*(ckt->CKTstate0 + here->DIOdeltemp), 100, &Check_th);
|
||||
|
|
@ -253,47 +299,45 @@ next1:
|
|||
csatsw = here->DIOtSatSWCur;
|
||||
csatsw_dT = here->DIOtSatSWCur_dT;
|
||||
gspr = here->DIOtConductance;
|
||||
gsprsw = here->DIOtConductanceSW;
|
||||
|
||||
if (model->DIOsatSWCurGiven) { /* sidewall current */
|
||||
if (model->DIOsatSWCurGiven) { /* sidewall current */
|
||||
double vds;
|
||||
if (model->DIOresistSWGiven)
|
||||
vds = vdsw; /* sidewall voltage used */
|
||||
else
|
||||
vds = vd; /* common voltage used */
|
||||
|
||||
if (model->DIOswEmissionCoeffGiven) { /* current with own characteristic */
|
||||
if (model->DIOswEmissionCoeffGiven) { /* with own characteristic */
|
||||
|
||||
vtesw = model->DIOswEmissionCoeff * vt;
|
||||
if (vds >= -3*vtesw) { /* forward */
|
||||
|
||||
if (vd >= -3*vtesw) { /* forward */
|
||||
|
||||
evd = exp(vd/vtesw);
|
||||
evd = exp(vds/vtesw);
|
||||
cdsw = csatsw*(evd-1);
|
||||
gdsw = csatsw*evd/vtesw;
|
||||
cdsw_dT = csatsw_dT * (evd - 1) - csatsw * vd * evd / (vtesw * Temp);
|
||||
cdsw_dT = csatsw_dT * (evd - 1) - csatsw * vds * evd / (vtesw * Temp);
|
||||
|
||||
} else if((!(model->DIObreakdownVoltageGiven)) ||
|
||||
vd >= -here->DIOtBrkdwnV) { /* reverse */
|
||||
} else if ((!(model->DIObreakdownVoltageGiven)) ||
|
||||
vds >= -here->DIOtBrkdwnV) { /* reverse */
|
||||
|
||||
argsw = 3*vtesw/(vd*CONSTe);
|
||||
argsw = 3*vtesw/(vds*CONSTe);
|
||||
argsw = argsw * argsw * argsw;
|
||||
argsw_dT = 3 * argsw / Temp;
|
||||
cdsw = -csatsw*(1+argsw);
|
||||
gdsw = csatsw*3*argsw/vd;
|
||||
gdsw = csatsw*3*argsw/vds;
|
||||
cdsw_dT = -csatsw_dT - (csatsw_dT*argsw + csatsw*argsw_dT);
|
||||
|
||||
} else { /* breakdown */
|
||||
} else if (!model->DIOresistSWGiven){ /* breakdown, but not for separate sidewall diode */
|
||||
double evrev_dT;
|
||||
|
||||
evrev = exp(-(here->DIOtBrkdwnV+vd)/vtebrk);
|
||||
evrev_dT = (here->DIOtBrkdwnV+vd)*evrev/(vtebrk*Temp);
|
||||
evrev = exp(-(here->DIOtBrkdwnV+vds)/vtebrk);
|
||||
evrev_dT = (here->DIOtBrkdwnV+vds)*evrev/(vtebrk*Temp);
|
||||
cdsw = -csatsw*evrev;
|
||||
gdsw = csatsw*evrev/vtebrk;
|
||||
cdsw_dT = -(csatsw_dT*evrev + csatsw*evrev_dT);
|
||||
|
||||
}
|
||||
|
||||
} else { /* merge saturation currents and use same characteristic as bottom diode */
|
||||
|
||||
csat = csat + csatsw;
|
||||
csat_dT = csat_dT + csatsw_dT;
|
||||
cdsw_dT = 0.0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -302,12 +346,17 @@ next1:
|
|||
* temperature dependent diode saturation current and derivative
|
||||
*/
|
||||
|
||||
if (vd >= -3*vte) { /* bottom current forward */
|
||||
|
||||
if (vd >= -3*vte) { /* bottom and sidewall current forward with common voltage */
|
||||
/* and with common characteristic */
|
||||
evd = exp(vd/vte);
|
||||
cdb = csat*(evd-1);
|
||||
gdb = csat*evd/vte;
|
||||
cdb_dT = csat_dT * (evd - 1) - csat * vd * evd / (vte * Temp);
|
||||
if ((model->DIOsatSWCurGiven)&&(!model->DIOswEmissionCoeffGiven)) {
|
||||
cdsw = csatsw*(evd-1);
|
||||
gdsw = csatsw*evd/vte;
|
||||
cdsw_dT = csatsw_dT * (evd - 1) - csatsw * vd * evd / (vte * Temp);
|
||||
}
|
||||
if (model->DIOrecSatCurGiven) { /* recombination current */
|
||||
double vterec = model->DIOrecEmissionCoeff*vt;
|
||||
evd_rec = exp(vd/(vterec));
|
||||
|
|
@ -326,7 +375,7 @@ next1:
|
|||
cdb_dT = cdb_dT + cdb_rec_dT*gen_fac;
|
||||
}
|
||||
|
||||
} else if((!(model->DIObreakdownVoltageGiven)) ||
|
||||
} else if ((!(model->DIObreakdownVoltageGiven)) ||
|
||||
vd >= -here->DIOtBrkdwnV) { /* reverse */
|
||||
|
||||
double darg_dT;
|
||||
|
|
@ -337,8 +386,14 @@ next1:
|
|||
cdb = -csat*(1+arg);
|
||||
gdb = csat*3*arg/vd;
|
||||
cdb_dT = -csat_dT - (csat_dT*arg + csat*darg_dT);
|
||||
if ((model->DIOsatSWCurGiven)&&(!model->DIOswEmissionCoeffGiven)) {
|
||||
cdsw = -csatsw*(1+arg);
|
||||
gdsw = csatsw*3*arg/vd;
|
||||
cdsw_dT = -csatsw_dT - (csatsw_dT*arg + csatsw*darg_dT);
|
||||
}
|
||||
|
||||
} else { /* breakdown */
|
||||
|
||||
double evrev_dT;
|
||||
|
||||
evrev = exp(-(here->DIOtBrkdwnV+vd)/vtebrk);
|
||||
|
|
@ -346,6 +401,15 @@ next1:
|
|||
cdb = -csat*evrev;
|
||||
gdb = csat*evrev/vtebrk;
|
||||
cdb_dT = -(csat_dT*evrev + csat*evrev_dT);
|
||||
if ((model->DIOsatSWCurGiven)
|
||||
&&(!model->DIOresistSWGiven) /* no breakdown for separate sidewall diode */
|
||||
&&(!model->DIOswEmissionCoeffGiven)) {
|
||||
evrev = exp(-(here->DIOtBrkdwnV+vdsw)/vtebrk);
|
||||
evrev_dT = (here->DIOtBrkdwnV+vdsw)*evrev/(vtebrk*Temp);
|
||||
cdsw = -csatsw*evrev;
|
||||
gdsw = csatsw*evrev/vtebrk;
|
||||
cdsw_dT = -(csatsw_dT*evrev + csatsw*evrev_dT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -373,36 +437,46 @@ next1:
|
|||
|
||||
}
|
||||
|
||||
cd = cdb + cdsw;
|
||||
gd = gdb + gdsw;
|
||||
dIdio_dT = cdb_dT + cdsw_dT;
|
||||
|
||||
if (vd >= -3*vte) { /* limit forward */
|
||||
|
||||
if( (model->DIOforwardKneeCurrentGiven) && (cd > 1.0e-18) ) {
|
||||
ikf_area_m = here->DIOforwardKneeCurrent;
|
||||
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 {
|
||||
gd = gd + ckt->CKTgmin;
|
||||
cd = cd + ckt->CKTgmin*vd;
|
||||
if ( (model->DIOforwardKneeCurrentGiven) && (cdb > 1.0e-18) ) {
|
||||
double ikf_area_m = here->DIOforwardKneeCurrent;
|
||||
sqrt_ikx = sqrt(cdb/ikf_area_m);
|
||||
gdb = ((1+sqrt_ikx)*gdb - cdb*gdb/(2*sqrt_ikx*ikf_area_m))/(1+2*sqrt_ikx + cdb/ikf_area_m);
|
||||
cdb = cdb/(1+sqrt_ikx);
|
||||
}
|
||||
|
||||
} else { /* limit reverse */
|
||||
|
||||
if( (model->DIOreverseKneeCurrentGiven) && (cd < -1.0e-18) ) {
|
||||
ikr_area_m = here->DIOreverseKneeCurrent;
|
||||
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 {
|
||||
gd = gd + ckt->CKTgmin;
|
||||
cd = cd + ckt->CKTgmin*vd;
|
||||
if ( (model->DIOreverseKneeCurrentGiven) && (cdb < -1.0e-18) ) {
|
||||
double ikr_area_m = here->DIOreverseKneeCurrent;
|
||||
sqrt_ikx = sqrt(cdb/(-ikr_area_m));
|
||||
gdb = ((1+sqrt_ikx)*gdb + cdb*gdb/(2*sqrt_ikx*ikr_area_m))/(1+2*sqrt_ikx - cdb/ikr_area_m);
|
||||
cdb = cdb/(1+sqrt_ikx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( (model->DIOforwardSWKneeCurrentGiven) && (cdsw > 1.0e-18) ) {
|
||||
double ikp_peri_m = here->DIOforwardSWKneeCurrent;
|
||||
sqrt_ikx = sqrt(cdsw/ikp_peri_m);
|
||||
gdsw = ((1+sqrt_ikx)*gdsw - cdsw*gdsw/(2*sqrt_ikx*ikp_peri_m))/(1+2*sqrt_ikx + cdsw/ikp_peri_m);
|
||||
cdsw = cdsw/(1+sqrt_ikx);
|
||||
}
|
||||
|
||||
if (!model->DIOresistSWGiven) {
|
||||
cd = cdb + cdsw + ckt->CKTgmin*vd;
|
||||
gd = gdb + gdsw + ckt->CKTgmin;
|
||||
dIdio_dT = cdb_dT + cdsw_dT;
|
||||
} else {
|
||||
cd = cdb + ckt->CKTgmin*vd;
|
||||
gd = gdb + ckt->CKTgmin;
|
||||
cdsw = cdsw + ckt->CKTgmin*vdsw;
|
||||
gdsw = gdsw + ckt->CKTgmin;
|
||||
dIdio_dT = cdb_dT;
|
||||
dIdioSw_dT = cdsw_dT;
|
||||
}
|
||||
|
||||
if ((ckt->CKTmode & (MODEDCTRANCURVE | MODETRAN | MODEAC | MODEINITSMSIG)) ||
|
||||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) {
|
||||
/*
|
||||
|
|
@ -421,28 +495,40 @@ next1:
|
|||
deplcap = czof2*(here->DIOtF3+here->DIOtGradingCoeff*vd/here->DIOtJctPot);
|
||||
}
|
||||
czeroSW=here->DIOtJctSWCap;
|
||||
if (vd < here->DIOtDepSWCap){
|
||||
argSW=1-vd/here->DIOtJctSWPot;
|
||||
double vdx;
|
||||
if (model->DIOresistSWGiven)
|
||||
vdx = vdsw;
|
||||
else
|
||||
vdx = vd;
|
||||
if (vdx < here->DIOtDepSWCap){
|
||||
argSW=1-vdx/here->DIOtJctSWPot;
|
||||
sargSW=exp(-model->DIOgradingSWCoeff*log(argSW));
|
||||
deplchargeSW = here->DIOtJctSWPot*czeroSW*(1-argSW*sargSW)/(1-model->DIOgradingSWCoeff);
|
||||
deplcapSW = czeroSW*sargSW;
|
||||
} else {
|
||||
czof2SW=czeroSW/here->DIOtF2SW;
|
||||
deplchargeSW = czeroSW*here->DIOtF1+czof2SW*(here->DIOtF3SW*(vd-here->DIOtDepSWCap)+
|
||||
(model->DIOgradingSWCoeff/(here->DIOtJctSWPot+here->DIOtJctSWPot))*(vd*vd-here->DIOtDepSWCap*here->DIOtDepSWCap));
|
||||
deplcapSW = czof2SW*(here->DIOtF3SW+model->DIOgradingSWCoeff*vd/here->DIOtJctSWPot);
|
||||
deplchargeSW = czeroSW*here->DIOtF1+czof2SW*(here->DIOtF3SW*(vdx-here->DIOtDepSWCap)+
|
||||
(model->DIOgradingSWCoeff/(here->DIOtJctSWPot+here->DIOtJctSWPot))*(vdx*vdx-here->DIOtDepSWCap*here->DIOtDepSWCap));
|
||||
deplcapSW = czof2SW*(here->DIOtF3SW+model->DIOgradingSWCoeff*vdx/here->DIOtJctSWPot);
|
||||
}
|
||||
|
||||
diffcharge = here->DIOtTransitTime*cd;
|
||||
*(ckt->CKTstate0 + here->DIOcapCharge) =
|
||||
diffcharge + deplcharge + deplchargeSW + (here->DIOcmetal + here->DIOcpoly)*vd;
|
||||
|
||||
diffcap = here->DIOtTransitTime*gd;
|
||||
|
||||
capd = diffcap + deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly;
|
||||
|
||||
here->DIOcap = capd;
|
||||
|
||||
if (!model->DIOresistSWGiven) {
|
||||
*(ckt->CKTstate0 + here->DIOcapCharge) =
|
||||
diffcharge + deplcharge + deplchargeSW + (here->DIOcmetal + here->DIOcpoly)*vd;
|
||||
capd = diffcap + deplcap + deplcapSW + here->DIOcmetal + here->DIOcpoly;
|
||||
here->DIOcap = capd;
|
||||
} else {
|
||||
*(ckt->CKTstate0 + here->DIOcapCharge) =
|
||||
diffcharge + deplcharge + (here->DIOcmetal + here->DIOcpoly)*vd;
|
||||
capd = diffcap + deplcap + here->DIOcmetal + here->DIOcpoly;
|
||||
here->DIOcap = capd;
|
||||
*(ckt->CKTstate0 + here->DIOcapChargeSW) =
|
||||
deplcapSW;
|
||||
capdsw = deplcapSW;
|
||||
here->DIOcapSW = capdsw;
|
||||
}
|
||||
/*
|
||||
* store small-signal parameters
|
||||
*/
|
||||
|
|
@ -450,11 +536,18 @@ next1:
|
|||
(!(ckt->CKTmode & MODEUIC)) ) {
|
||||
if (ckt->CKTmode & MODEINITSMSIG){
|
||||
*(ckt->CKTstate0 + here->DIOcapCurrent) = capd;
|
||||
|
||||
if (model->DIOresistSWGiven) {
|
||||
*(ckt->CKTstate0 + here->DIOcapCurrentSW) = capdsw;
|
||||
}
|
||||
if(SenCond){
|
||||
*(ckt->CKTstate0 + here->DIOcurrent) = cd;
|
||||
*(ckt->CKTstate0 + here->DIOconduct) = gd;
|
||||
*(ckt->CKTstate0 + here->DIOdIdio_dT) = dIdio_dT;
|
||||
if (model->DIOresistSWGiven) {
|
||||
*(ckt->CKTstate0 + here->DIOcurrentSW) = cdsw;
|
||||
*(ckt->CKTstate0 + here->DIOconductSW) = gdsw;
|
||||
*(ckt->CKTstate0 + here->DIOdIdioSW_dT) = dIdioSw_dT;
|
||||
}
|
||||
#ifdef SENSDEBUG
|
||||
printf("storing small signal parameters\n");
|
||||
printf("cd = %.7e,vd = %.7e\n",cd,vd);
|
||||
|
|
@ -469,6 +562,8 @@ next1:
|
|||
*/
|
||||
if(SenCond && (ckt->CKTsenInfo->SENmode == TRANSEN)){
|
||||
*(ckt->CKTstate0 + here->DIOcurrent) = cd;
|
||||
if (model->DIOresistSWGiven)
|
||||
*(ckt->CKTstate0 + here->DIOcurrentSW) = cdsw;
|
||||
#ifdef SENSDEBUG
|
||||
printf("storing parameters for transient sensitivity\n"
|
||||
);
|
||||
|
|
@ -481,21 +576,29 @@ next1:
|
|||
if (ckt->CKTmode & MODEINITTRAN) {
|
||||
*(ckt->CKTstate1 + here->DIOcapCharge) =
|
||||
*(ckt->CKTstate0 + here->DIOcapCharge);
|
||||
if (model->DIOresistSWGiven)
|
||||
*(ckt->CKTstate1 + here->DIOcapChargeSW) =
|
||||
*(ckt->CKTstate0 + here->DIOcapChargeSW);
|
||||
}
|
||||
error = NIintegrate(ckt,&geq,&ceq,capd,here->DIOcapCharge);
|
||||
if(error) return(error);
|
||||
gd=gd+geq;
|
||||
cd=cd+*(ckt->CKTstate0 + here->DIOcapCurrent);
|
||||
if (model->DIOresistSWGiven) {
|
||||
error = NIintegrate(ckt,&geq,&ceq,capdsw,here->DIOcapChargeSW);
|
||||
if(error) return(error);
|
||||
gdsw=gdsw+geq;
|
||||
cdsw=cdsw+*(ckt->CKTstate0 + here->DIOcapCurrentSW);
|
||||
}
|
||||
if (ckt->CKTmode & MODEINITTRAN) {
|
||||
*(ckt->CKTstate1 + here->DIOcapCurrent) =
|
||||
*(ckt->CKTstate0 + here->DIOcapCurrent);
|
||||
if (model->DIOresistSWGiven)
|
||||
*(ckt->CKTstate1 + here->DIOcapCurrentSW) =
|
||||
*(ckt->CKTstate0 + here->DIOcapCurrentSW);
|
||||
}
|
||||
if (selfheat)
|
||||
{
|
||||
if (ckt->CKTmode & MODEINITTRAN) {
|
||||
*(ckt->CKTstate1 + here->DIOqth) =
|
||||
*(ckt->CKTstate0 + here->DIOqth);
|
||||
}
|
||||
error = NIintegrate(ckt, &gcTt, &ceqqth, model->DIOcth0, here->DIOqth);
|
||||
if (error) return(error);
|
||||
if (ckt->CKTmode & MODEINITTRAN) {
|
||||
|
|
@ -512,9 +615,16 @@ next1:
|
|||
* check convergence
|
||||
*/
|
||||
if ( (!(ckt->CKTmode & MODEINITFIX)) || (!(here->DIOoff)) ) {
|
||||
if ((Check_th == 1) || (Check_dio == 1)) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
if (!model->DIOresistSWGiven) {
|
||||
if ((Check_th == 1) || (Check_dio == 1)) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
}
|
||||
} else {
|
||||
if ((Check_th == 1) || (Check_dio == 1) || (Check_dio_sw == 1)) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) here;
|
||||
}
|
||||
}
|
||||
}
|
||||
next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd;
|
||||
|
|
@ -522,7 +632,12 @@ next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd;
|
|||
*(ckt->CKTstate0 + here->DIOconduct) = gd;
|
||||
*(ckt->CKTstate0 + here->DIOdeltemp) = delTemp;
|
||||
*(ckt->CKTstate0 + here->DIOdIdio_dT) = dIdio_dT;
|
||||
|
||||
if (model->DIOresistSWGiven) {
|
||||
*(ckt->CKTstate0 + here->DIOvoltageSW) = vdsw;
|
||||
*(ckt->CKTstate0 + here->DIOcurrentSW) = cdsw;
|
||||
*(ckt->CKTstate0 + here->DIOconductSW) = gdsw;
|
||||
*(ckt->CKTstate0 + here->DIOdIdioSW_dT) = dIdioSw_dT;
|
||||
}
|
||||
if(SenCond) continue;
|
||||
|
||||
#ifndef NOBYPASS
|
||||
|
|
@ -531,20 +646,37 @@ next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd;
|
|||
if (selfheat) {
|
||||
double dIrs_dVrs, dIrs_dgspr, dIth_dIrs;
|
||||
vrs = *(ckt->CKTrhsOld + here->DIOposNode) - *(ckt->CKTrhsOld + here->DIOposPrimeNode);
|
||||
Ith = vd*cd + vrs*vrs*gspr; /* Diode dissipated power */
|
||||
dIrs_dVrs = gspr;
|
||||
dIrs_dgspr = vrs;
|
||||
dIrs_dT = dIrs_dgspr * here->DIOtConductance_dT;
|
||||
Ith = vd*cd + vrs*vrs*gspr; /* Diode dissipated power */
|
||||
dIth_dVrs = vrs*gspr;
|
||||
dIth_dIrs = vrs;
|
||||
dIth_dVrs = dIth_dVrs + dIth_dIrs*dIrs_dVrs;
|
||||
dIth_dT = dIth_dIrs*dIrs_dT + dIdio_dT*vd;
|
||||
dIth_dVdio = cd + vd*gd;
|
||||
here->DIOdIth_dVrs = dIth_dVrs;
|
||||
here->DIOdIth_dVdio = dIth_dVdio;
|
||||
here->DIOdIth_dT = dIth_dT;
|
||||
here->DIOgcTt = gcTt;
|
||||
here->DIOdIrs_dT = dIrs_dT;
|
||||
here->DIOdIth_dVdio = dIth_dVdio;
|
||||
here->DIOdIth_dT = dIth_dT;
|
||||
if (model->DIOresistSWGiven) {
|
||||
double dIrssw_dVrssw, dIrssw_dgsprsw, dIth_dIrssw;
|
||||
vrssw = *(ckt->CKTrhsOld + here->DIOposNode) - *(ckt->CKTrhsOld + here->DIOposSwPrimeNode);
|
||||
dIrssw_dVrssw = gsprsw;
|
||||
dIrssw_dgsprsw = vrssw;
|
||||
dIrssw_dT = dIrssw_dgsprsw * here->DIOtConductanceSW_dT;
|
||||
Ith = Ith + vdsw*cdsw + vrssw*vrssw*gsprsw; /* Diode dissipated power */
|
||||
dIth_dVrssw = vrssw*gsprsw;
|
||||
dIth_dIrssw = vrssw;
|
||||
dIth_dVrssw = dIth_dVrssw + dIth_dIrssw*dIrssw_dVrssw;
|
||||
dIth_dT = dIth_dT + dIth_dIrssw*dIrssw_dT + dIdioSw_dT*vdsw;
|
||||
dIth_dVdioSw = cdsw + vdsw*gdsw;
|
||||
here->DIOdIth_dVrssw = dIth_dVrssw;
|
||||
here->DIOdIth_dVdio = dIth_dVdioSw;
|
||||
here->DIOdIth_dT = dIth_dT;
|
||||
here->DIOdIrssw_dT = dIrssw_dT;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* load current vector
|
||||
|
|
@ -558,6 +690,17 @@ next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd;
|
|||
*(ckt->CKTrhs + here->DIOnegNode) += -dIdio_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->DIOtempNode) += Ith - dIth_dVdio*vd - dIth_dVrs*vrs - dIth_dT*delTemp - ceqqth;
|
||||
}
|
||||
if (model->DIOresistSWGiven) {
|
||||
cdeq=cdsw-gdsw*vdsw;
|
||||
*(ckt->CKTrhs + here->DIOnegNode) += cdeq;
|
||||
*(ckt->CKTrhs + here->DIOposSwPrimeNode) -= cdeq;
|
||||
if (selfheat) {
|
||||
*(ckt->CKTrhs + here->DIOposNode) += dIrssw_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->DIOposSwPrimeNode) += dIdioSw_dT*delTemp - dIrssw_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->DIOnegNode) += -dIdioSw_dT*delTemp;
|
||||
*(ckt->CKTrhs + here->DIOtempNode) += -dIth_dVdioSw*vdsw - dIth_dVrssw*vrssw;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* load matrix
|
||||
*/
|
||||
|
|
@ -577,6 +720,24 @@ next2: *(ckt->CKTstate0 + here->DIOvoltage) = vd;
|
|||
(*(here->DIOposPrimeTempPtr) += dIdio_dT - dIrs_dT);
|
||||
(*(here->DIOnegTempPtr) += -dIdio_dT);
|
||||
}
|
||||
if (model->DIOresistSWGiven) {
|
||||
*(here->DIOposPosPtr) += gsprsw;
|
||||
*(here->DIOnegNegPtr) += gdsw;
|
||||
*(here->DIOposSwPrimePosSwPrimePtr) += (gdsw + gsprsw);
|
||||
*(here->DIOposPosSwPrimePtr) -= gsprsw;
|
||||
*(here->DIOnegPosSwPrimePtr) -= gdsw;
|
||||
*(here->DIOposSwPrimePosPtr) -= gsprsw;
|
||||
*(here->DIOposSwPrimeNegPtr) -= gdsw;
|
||||
|
||||
if (selfheat) {
|
||||
(*(here->DIOtempPosPtr) += -dIth_dVrssw);
|
||||
(*(here->DIOtempPosSwPrimePtr) += -dIth_dVdioSw + dIth_dVrssw);
|
||||
(*(here->DIOtempNegPtr) += dIth_dVdioSw);
|
||||
(*(here->DIOposTempPtr) += dIrssw_dT);
|
||||
(*(here->DIOposSwPrimeTempPtr) += dIdioSw_dT - dIrssw_dT);
|
||||
(*(here->DIOnegTempPtr) += -dIdioSw_dT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value)
|
|||
case DIO_MOD_RS:
|
||||
value->rValue = model->DIOresist;
|
||||
return(OK);
|
||||
case DIO_MOD_RSW:
|
||||
value->rValue = model->DIOresistSW;
|
||||
return(OK);
|
||||
case DIO_MOD_TRS:
|
||||
value->rValue = model->DIOresistTemp1;
|
||||
return(OK);
|
||||
|
|
@ -93,6 +96,9 @@ DIOmAsk (CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value)
|
|||
case DIO_MOD_IKR:
|
||||
value->rValue = model->DIOreverseKneeCurrent;
|
||||
return(OK);
|
||||
case DIO_MOD_IKP:
|
||||
value->rValue = model->DIOforwardSWKneeCurrent;
|
||||
return(OK);
|
||||
case DIO_MOD_NBV:
|
||||
value->rValue = model->DIObrkdEmissionCoeff;
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->DIOresist = value->rValue;
|
||||
model->DIOresistGiven = TRUE;
|
||||
break;
|
||||
case DIO_MOD_RSW:
|
||||
model->DIOresistSW = value->rValue;
|
||||
model->DIOresistSWGiven = TRUE;
|
||||
break;
|
||||
case DIO_MOD_TRS:
|
||||
model->DIOresistTemp1 = value->rValue;
|
||||
model->DIOresistTemp1Given = TRUE;
|
||||
|
|
@ -108,6 +112,10 @@ DIOmParam(int param, IFvalue *value, GENmodel *inModel)
|
|||
model->DIOreverseKneeCurrent = value->rValue;
|
||||
model->DIOreverseKneeCurrentGiven = TRUE;
|
||||
break;
|
||||
case DIO_MOD_IKP:
|
||||
model->DIOforwardSWKneeCurrent = value->rValue;
|
||||
model->DIOforwardSWKneeCurrentGiven = TRUE;
|
||||
break;
|
||||
case DIO_MOD_NBV:
|
||||
model->DIObrkdEmissionCoeff = value->rValue;
|
||||
model->DIObrkdEmissionCoeffGiven = TRUE;
|
||||
|
|
|
|||
|
|
@ -41,10 +41,13 @@ DIOnoise(int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
|
|||
|
||||
static char *DIOnNames[DIONSRCS] = {
|
||||
/* Note that we have to keep the order
|
||||
consistent with thestrchr definitions in DIOdefs.h */
|
||||
consistent with the strchr definitions in DIOdefs.h */
|
||||
"_rs", /* noise due to rs */
|
||||
"_id", /* noise due to id */
|
||||
"_1overf", /* flicker (1/f) noise */
|
||||
"_rsw", /* noise due to rsw */
|
||||
"_idsw", /* noise due to id sw */
|
||||
"_1overfsw", /* flicker (1/f) noise sw */
|
||||
"" /* total diode noise */
|
||||
};
|
||||
|
||||
|
|
@ -108,10 +111,36 @@ DIOnoise(int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
|
|||
noizDens[DIOTOTNOIZ] = noizDens[DIORSNOIZ] +
|
||||
noizDens[DIOIDNOIZ] +
|
||||
noizDens[DIOFLNOIZ];
|
||||
|
||||
if (model->DIOresistSWGiven) {
|
||||
/* sidewall diode */
|
||||
NevalSrcInstanceTemp(&noizDens[DIORSSWNOIZ],&lnNdens[DIORSSWNOIZ],
|
||||
ckt, THERMNOISE, inst->DIOposSwPrimeNode, inst->DIOposNode,
|
||||
inst->DIOtConductanceSW, dtemp);
|
||||
|
||||
NevalSrc(&noizDens[DIOIDSWNOIZ],&lnNdens[DIOIDSWNOIZ],
|
||||
ckt, SHOTNOISE, inst->DIOposSwPrimeNode, inst->DIOnegNode,
|
||||
*(ckt->CKTstate0 + inst->DIOcurrentSW));
|
||||
|
||||
NevalSrc(&noizDens[DIOFLSWNOIZ], NULL, ckt,
|
||||
N_GAIN, inst->DIOposSwPrimeNode, inst->DIOnegNode,
|
||||
(double) 0.0);
|
||||
noizDens[DIOFLSWNOIZ] *= model->DIOfNcoef *
|
||||
exp(model->DIOfNexp *
|
||||
log(MAX(fabs(*(ckt->CKTstate0 + inst->DIOcurrentSW) / inst->DIOm), N_MINLOG))) /
|
||||
data->freq * inst->DIOm;
|
||||
lnNdens[DIOFLSWNOIZ] =
|
||||
log(MAX(noizDens[DIOFLSWNOIZ], N_MINLOG));
|
||||
|
||||
noizDens[DIOTOTNOIZ] += noizDens[DIORSSWNOIZ] +
|
||||
noizDens[DIOIDSWNOIZ] +
|
||||
noizDens[DIOFLSWNOIZ];
|
||||
}
|
||||
|
||||
lnNdens[DIOTOTNOIZ] =
|
||||
log(MAX(noizDens[DIOTOTNOIZ], N_MINLOG));
|
||||
|
||||
*OnDens += noizDens[DIOTOTNOIZ];
|
||||
*OnDens += noizDens[DIOTOTNOIZ];
|
||||
|
||||
if (data->delFreq == 0.0) {
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ int
|
|||
DIOpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
|
||||
{
|
||||
DIOmodel *model = (DIOmodel*)inModel;
|
||||
double gspr;
|
||||
double gspr, gsprsw;
|
||||
double geq;
|
||||
double xceq;
|
||||
DIOinstance *here;
|
||||
|
|
@ -43,6 +43,22 @@ DIOpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
|
|||
*(here->DIOposPrimePosPtr ) -= gspr;
|
||||
*(here->DIOposPrimeNegPtr ) -= geq + xceq * s->real;
|
||||
*(here->DIOposPrimeNegPtr +1 ) -= xceq * s->imag;
|
||||
if (model->DIOresistSWGiven) {
|
||||
gsprsw=here->DIOtConductanceSW;
|
||||
geq= *(ckt->CKTstate0 + here->DIOconductSW);
|
||||
xceq= *(ckt->CKTstate0 + here->DIOcapCurrentSW) * ckt->CKTomega;
|
||||
*(here->DIOposPosPtr) += gsprsw;
|
||||
*(here->DIOnegNegPtr) += geq + xceq * s->real;
|
||||
*(here->DIOnegNegPtr + 1) += xceq * s->imag;
|
||||
*(here->DIOposSwPrimePosSwPrimePtr) += geq + gsprsw + xceq * s->real;
|
||||
*(here->DIOposSwPrimePosSwPrimePtr + 1) += xceq * s->imag;
|
||||
*(here->DIOposPosSwPrimePtr) -= gsprsw;
|
||||
*(here->DIOnegPosSwPrimePtr) -= geq;
|
||||
*(here->DIOnegPosSwPrimePtr + 1) -= xceq;
|
||||
*(here->DIOposSwPrimePosPtr) -= gsprsw;
|
||||
*(here->DIOposSwPrimeNegPtr) -= geq + xceq * s->real;
|
||||
*(here->DIOposSwPrimeNegPtr + 1) -= xceq * s->imag;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,13 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
model->DIOmodName);
|
||||
}
|
||||
}
|
||||
if(model->DIOforwardSWKneeCurrentGiven) {
|
||||
if (model->DIOforwardSWKneeCurrent < ckt->CKTepsmin) {
|
||||
model->DIOforwardSWKneeCurrentGiven = FALSE;
|
||||
fprintf(stderr, "Warning: %s: IKP too small - model effect disabled!\n",
|
||||
model->DIOmodName);
|
||||
}
|
||||
}
|
||||
if(!model->DIObrkdEmissionCoeffGiven) {
|
||||
model->DIObrkdEmissionCoeff = model->DIOemissionCoeff;
|
||||
}
|
||||
|
|
@ -238,6 +245,24 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
} else {
|
||||
model->DIOconductance = 1/model->DIOresist;
|
||||
}
|
||||
if((!model->DIOresistSWGiven) || (model->DIOresistSW==0)) {
|
||||
if (newcompat.ps || newcompat.lt) {
|
||||
double rsdiode = 0.;
|
||||
/* to improve convergence (sometimes) */
|
||||
if (cp_getvar("diode_rser", CP_REAL, &rsdiode, 0) && rsdiode > 0) {
|
||||
model->DIOconductanceSW = 1./rsdiode;
|
||||
model->DIOresistSW = rsdiode;
|
||||
if (ft_ngdebug)
|
||||
fprintf(stderr, "Diode sidewall series resistance in model %s set to %e Ohm\n", model->gen.GENmodName, rsdiode);
|
||||
}
|
||||
else
|
||||
model->DIOconductanceSW = 0.0;
|
||||
}
|
||||
else
|
||||
model->DIOconductanceSW = 0.0;
|
||||
} else {
|
||||
model->DIOconductanceSW = 1/model->DIOresistSW;
|
||||
}
|
||||
|
||||
if (!model->DIOrth0Given) {
|
||||
model->DIOrth0 = 0;
|
||||
|
|
@ -329,6 +354,7 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
}
|
||||
here->DIOforwardKneeCurrent = model->DIOforwardKneeCurrent * here->DIOarea * here->DIOm;
|
||||
here->DIOreverseKneeCurrent = model->DIOreverseKneeCurrent * here->DIOarea * here->DIOm;
|
||||
here->DIOforwardSWKneeCurrent = model->DIOforwardSWKneeCurrent * here->DIOpj * here->DIOm;
|
||||
here->DIOjunctionCap = model->DIOjunctionCap * here->DIOarea * here->DIOm;
|
||||
here->DIOjunctionSWCap = model->DIOjunctionSWCap * here->DIOpj * here->DIOm;
|
||||
|
||||
|
|
@ -344,19 +370,41 @@ DIOsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
|||
|
||||
} else if(here->DIOposPrimeNode == 0) {
|
||||
|
||||
CKTnode *tmpNode;
|
||||
IFuid tmpName;
|
||||
CKTnode *tmpNode;
|
||||
IFuid tmpName;
|
||||
|
||||
error = CKTmkVolt(ckt,&tmp,here->DIOname,"internal");
|
||||
if(error) return(error);
|
||||
here->DIOposPrimeNode = tmp->number;
|
||||
if (ckt->CKTcopyNodesets) {
|
||||
if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) {
|
||||
if (tmpNode->nsGiven) {
|
||||
tmp->nodeset=tmpNode->nodeset;
|
||||
tmp->nsGiven=tmpNode->nsGiven;
|
||||
}
|
||||
}
|
||||
if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) {
|
||||
if (tmpNode->nsGiven) {
|
||||
tmp->nodeset=tmpNode->nodeset;
|
||||
tmp->nsGiven=tmpNode->nsGiven;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!model->DIOresistSWGiven) {
|
||||
|
||||
here->DIOposSwPrimeNode = here->DIOposPrimeNode;
|
||||
|
||||
} else if(here->DIOposSwPrimeNode == 0) {
|
||||
|
||||
CKTnode *tmpNode;
|
||||
IFuid tmpName;
|
||||
|
||||
error = CKTmkVolt(ckt,&tmp,here->DIOname,"internal_sw");
|
||||
if(error) return(error);
|
||||
here->DIOposSwPrimeNode = tmp->number;
|
||||
if (ckt->CKTcopyNodesets) {
|
||||
if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) {
|
||||
if (tmpNode->nsGiven) {
|
||||
tmp->nodeset=tmpNode->nodeset;
|
||||
tmp->nsGiven=tmpNode->nsGiven;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -375,6 +423,14 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
TSTALLOC(DIOposPosPtr,DIOposNode,DIOposNode);
|
||||
TSTALLOC(DIOnegNegPtr,DIOnegNode,DIOnegNode);
|
||||
TSTALLOC(DIOposPrimePosPrimePtr,DIOposPrimeNode,DIOposPrimeNode);
|
||||
if(model->DIOresistSWGiven) {
|
||||
/* separate sidewall */
|
||||
TSTALLOC(DIOposPosSwPrimePtr,DIOposNode,DIOposSwPrimeNode);
|
||||
TSTALLOC(DIOnegPosSwPrimePtr,DIOnegNode,DIOposSwPrimeNode);
|
||||
TSTALLOC(DIOposSwPrimePosPtr,DIOposSwPrimeNode,DIOposNode);
|
||||
TSTALLOC(DIOposSwPrimeNegPtr,DIOposSwPrimeNode,DIOnegNode);
|
||||
TSTALLOC(DIOposSwPrimePosSwPrimePtr,DIOposSwPrimeNode,DIOposSwPrimeNode);
|
||||
}
|
||||
|
||||
if (selfheat) {
|
||||
TSTALLOC(DIOtempPosPtr, DIOtempNode, DIOposNode);
|
||||
|
|
@ -384,6 +440,11 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
TSTALLOC(DIOposTempPtr, DIOposNode, DIOtempNode);
|
||||
TSTALLOC(DIOposPrimeTempPtr, DIOposPrimeNode, DIOtempNode);
|
||||
TSTALLOC(DIOnegTempPtr, DIOnegNode, DIOtempNode);
|
||||
if(model->DIOresistSWGiven) {
|
||||
/* separate sidewall */
|
||||
TSTALLOC(DIOtempPosSwPrimePtr, DIOtempNode, DIOposSwPrimeNode);
|
||||
TSTALLOC(DIOposSwPrimeTempPtr, DIOposSwPrimeNode, DIOtempNode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -410,6 +471,15 @@ DIOunsetup(
|
|||
&& here->DIOposPrimeNode != here->DIOposNode)
|
||||
CKTdltNNum(ckt, here->DIOposPrimeNode);
|
||||
here->DIOposPrimeNode = 0;
|
||||
|
||||
if(model->DIOresistSWGiven) {
|
||||
/* separate sidewall */
|
||||
if (here->DIOposSwPrimeNode > 0
|
||||
&& here->DIOposSwPrimeNode != here->DIOposNode)
|
||||
CKTdltNNum(ckt, here->DIOposSwPrimeNode);
|
||||
here->DIOposSwPrimeNode = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
|
|||
double dt;
|
||||
double factor;
|
||||
double tBreakdownVoltage;
|
||||
double totalSatCur;
|
||||
|
||||
double egfet1,arg1,fact1,pbfact1,pbo,gmaold,pboSW,gmaSWold;
|
||||
double fact2,pbfact,arg,egfet,gmanew,gmaSWnew;
|
||||
|
|
@ -196,9 +197,14 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
|
|||
here->DIOtDepSWCap=model->DIOdepletionSWcapCoeff*
|
||||
here->DIOtJctSWPot;
|
||||
/* and Vcrit */
|
||||
double totalSatCur = here->DIOtSatCur + here->DIOtSatSWCur;
|
||||
here->DIOtVcrit = vte * log(vte/(CONSTroot2*totalSatCur));
|
||||
|
||||
totalSatCur = here->DIOtSatCur + here->DIOtSatSWCur;
|
||||
if(model->DIOresistSWGiven) {
|
||||
here->DIOtVcrit = vte * log(vte/(CONSTroot2*here->DIOtSatCur));
|
||||
here->DIOtVcritSW = vts * log(vts/(CONSTroot2*here->DIOtSatSWCur));
|
||||
} else {
|
||||
here->DIOtVcrit = vte * log(vte/(CONSTroot2*totalSatCur));
|
||||
here->DIOtVcritSW = vts * log(vts/(CONSTroot2*here->DIOtSatSWCur));
|
||||
}
|
||||
/* and now to compute the breakdown voltage, again, using
|
||||
* temperature adjusted basic parameters */
|
||||
if (model->DIObreakdownVoltageGiven){
|
||||
|
|
@ -253,6 +259,14 @@ void DIOtempUpdate(DIOmodel *inModel, DIOinstance *here, double Temp, CKTcircuit
|
|||
here->DIOtConductance_dT = -model->DIOconductance * here->DIOarea * here->DIOm *
|
||||
(model->DIOresistTemp1 + model->DIOresistTemp2 * dt) / (factor*factor);
|
||||
}
|
||||
here->DIOtConductanceSW = model->DIOconductanceSW * here->DIOpj * here->DIOm;
|
||||
if(model->DIOresistSWGiven && model->DIOresistSW!=0.0) {
|
||||
factor = 1.0 + (model->DIOresistTemp1) * dt
|
||||
+ (model->DIOresistTemp2 * dt * dt);
|
||||
here->DIOtConductanceSW = model->DIOconductanceSW * here->DIOpj * here->DIOm / factor;
|
||||
here->DIOtConductanceSW_dT = -model->DIOconductanceSW * here->DIOpj * here->DIOm *
|
||||
(model->DIOresistTemp1 + model->DIOresistTemp2 * dt) / (factor*factor);
|
||||
}
|
||||
|
||||
here->DIOtF2=exp((1+here->DIOtGradingCoeff)*xfc);
|
||||
here->DIOtF3=1-model->DIOdepletionCapCoeff*
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ DIOtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep)
|
|||
for( ; model != NULL; model = DIOnextModel(model)) {
|
||||
for(here=DIOinstances(model);here!=NULL;here = DIOnextInstance(here)){
|
||||
CKTterr(here->DIOcapCharge,ckt,timeStep);
|
||||
if (model->DIOresistSWGiven) CKTterr(here->DIOcapChargeSW,ckt,timeStep);
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
|
|||
Loading…
Reference in New Issue