From 284d4308dbb2bbedce0883e10cf2e207c0f89a79 Mon Sep 17 00:00:00 2001 From: dwarning Date: Thu, 27 Nov 2025 16:21:31 +0100 Subject: [PATCH] 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. --- src/spicelib/devices/dio/dio.c | 2 + src/spicelib/devices/dio/dioacld.c | 32 ++- src/spicelib/devices/dio/diobindCSC.c | 27 +++ src/spicelib/devices/dio/dioconv.c | 27 ++- src/spicelib/devices/dio/diodefs.h | 61 ++++- src/spicelib/devices/dio/dioload.c | 337 +++++++++++++++++++------- src/spicelib/devices/dio/diomask.c | 6 + src/spicelib/devices/dio/diompar.c | 8 + src/spicelib/devices/dio/dionoise.c | 33 ++- src/spicelib/devices/dio/diopzld.c | 18 +- src/spicelib/devices/dio/diosetup.c | 86 ++++++- src/spicelib/devices/dio/diotemp.c | 20 +- src/spicelib/devices/dio/diotrunc.c | 1 + 13 files changed, 544 insertions(+), 114 deletions(-) diff --git a/src/spicelib/devices/dio/dio.c b/src/spicelib/devices/dio/dio.c index 3c4ff131c..8814c5a1a 100644 --- a/src/spicelib/devices/dio/dio.c +++ b/src/spicelib/devices/dio/dio.c @@ -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"), diff --git a/src/spicelib/devices/dio/dioacld.c b/src/spicelib/devices/dio/dioacld.c index d7e68c41b..62ad65efd 100644 --- a/src/spicelib/devices/dio/dioacld.c +++ b/src/spicelib/devices/dio/dioacld.c @@ -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); + } } } } diff --git a/src/spicelib/devices/dio/diobindCSC.c b/src/spicelib/devices/dio/diobindCSC.c index c33557307..a5df3db3d 100644 --- a/src/spicelib/devices/dio/diobindCSC.c +++ b/src/spicelib/devices/dio/diobindCSC.c @@ -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); } } } diff --git a/src/spicelib/devices/dio/dioconv.c b/src/spicelib/devices/dio/dioconv.c index ed1b0cea6..7e749576e 100644 --- a/src/spicelib/devices/dio/dioconv.c +++ b/src/spicelib/devices/dio/dioconv.c @@ -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); diff --git a/src/spicelib/devices/dio/diodefs.h b/src/spicelib/devices/dio/diodefs.h index 80f49a59d..836475538 100644 --- a/src/spicelib/devices/dio/diodefs.h +++ b/src/spicelib/devices/dio/diodefs.h @@ -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, diff --git a/src/spicelib/devices/dio/dioload.c b/src/spicelib/devices/dio/dioload.c index e8f1dd755..b8590c155 100644 --- a/src/spicelib/devices/dio/dioload.c +++ b/src/spicelib/devices/dio/dioload.c @@ -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); diff --git a/src/spicelib/devices/dio/diomask.c b/src/spicelib/devices/dio/diomask.c index dcbdfffc0..1f4e11ce5 100644 --- a/src/spicelib/devices/dio/diomask.c +++ b/src/spicelib/devices/dio/diomask.c @@ -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); diff --git a/src/spicelib/devices/dio/diompar.c b/src/spicelib/devices/dio/diompar.c index e68052eb0..498421160 100644 --- a/src/spicelib/devices/dio/diompar.c +++ b/src/spicelib/devices/dio/diompar.c @@ -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; diff --git a/src/spicelib/devices/dio/dionoise.c b/src/spicelib/devices/dio/dionoise.c index fc30d4132..de2ba3793 100644 --- a/src/spicelib/devices/dio/dionoise.c +++ b/src/spicelib/devices/dio/dionoise.c @@ -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) { diff --git a/src/spicelib/devices/dio/diopzld.c b/src/spicelib/devices/dio/diopzld.c index 8ec036031..44e13b84b 100644 --- a/src/spicelib/devices/dio/diopzld.c +++ b/src/spicelib/devices/dio/diopzld.c @@ -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); diff --git a/src/spicelib/devices/dio/diosetup.c b/src/spicelib/devices/dio/diosetup.c index 98ced6e01..0b40b1b49 100644 --- a/src/spicelib/devices/dio/diosetup.c +++ b/src/spicelib/devices/dio/diosetup.c @@ -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; diff --git a/src/spicelib/devices/dio/diotemp.c b/src/spicelib/devices/dio/diotemp.c index 30a47405b..d39b03de4 100644 --- a/src/spicelib/devices/dio/diotemp.c +++ b/src/spicelib/devices/dio/diotemp.c @@ -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* diff --git a/src/spicelib/devices/dio/diotrunc.c b/src/spicelib/devices/dio/diotrunc.c index 5c64086f9..b940528be 100644 --- a/src/spicelib/devices/dio/diotrunc.c +++ b/src/spicelib/devices/dio/diotrunc.c @@ -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);