devices/bsim3v32: apply Area Calculation Method (ACM) to the bsim3v3.2.4 model

This commit is contained in:
dwarning 2013-05-16 22:22:51 +02:00 committed by rlar
parent 959ee9cfbb
commit 7b2bd10b64
12 changed files with 553 additions and 89 deletions

View File

@ -32,6 +32,20 @@ double limitVgb( double, double, int * );
/* Area Calculation Method (ACM) for MOS models (devsup.c) */
int
ACM_SourceDrainResistances(int, double, double, double, double, double,
double, double, int, double, double, double,
int, double, double, double, double *, double *);
int
ACM_saturationCurrents(int, int, int, double, double, double, double, double,
double, int, double, int, double, int, double, int,
double, double *, double *);
int
ACM_junctionCapacitances(int, int, int, double, double, double, double, int,
double, int, double, int, double, int, double,
double, double, double, double *, double *,
double *, double *, double *, double *);
typedef struct SPICEdev {
IFdevice DEVpublic;

View File

@ -26,6 +26,7 @@ IOP( "nrd", BSIM3v32_NRD, IF_REAL , "Number of squares in drain"),
IOP( "nrs", BSIM3v32_NRS, IF_REAL , "Number of squares in source"),
IOP( "off", BSIM3v32_OFF, IF_FLAG , "Device is initially off"),
IOP( "nqsmod", BSIM3v32_NQSMOD, IF_INTEGER, "Non-quasi-static model selector"),
IOP( "geo", BSIM3v32_GEO, IF_INTEGER, "ACM model drain/source connection"),
IOP( "delvto", BSIM3v32_DELVTO, IF_REAL , "Zero bias threshold voltage variation"),
IOP( "mulu0", BSIM3v32_MULU0, IF_REAL , "Low field mobility multiplier"),
IP( "ic", BSIM3v32_IC, IF_REALVEC , "Vector of DS,GS,BS initial voltages"),
@ -66,6 +67,7 @@ IOP( "capmod", BSIM3v32_MOD_CAPMOD, IF_INTEGER, "Capacitance model selector"),
IOP( "mobmod", BSIM3v32_MOD_MOBMOD, IF_INTEGER, "Mobility model selector"),
IOP( "noimod", BSIM3v32_MOD_NOIMOD, IF_INTEGER, "Noise model selector"),
IOP( "acm", BSIM3v32_MOD_ACMMOD, IF_INTEGER, "Area calculation method selector"),
IOP( "calcacm", BSIM3v32_MOD_CALCACM, IF_INTEGER, "Area calculation method ACM=12"),
IOP( "paramchk", BSIM3v32_MOD_PARAMCHK, IF_INTEGER, "Model parameter checking selector"),
IOP( "binunit", BSIM3v32_MOD_BINUNIT, IF_INTEGER, "Bin unit selector"),
IOP( "version", BSIM3v32_MOD_VERSION, IF_STRING, " parameter for model version"),
@ -220,6 +222,7 @@ IOP( "rd", BSIM3v32_MOD_RD, IF_REAL, "ACM Parameter: Resistance of LDD drain sid
IOP( "rs", BSIM3v32_MOD_RS, IF_REAL, "ACM Parameter: Resistance of LDD source side"),
IOP( "rdc", BSIM3v32_MOD_RDC, IF_REAL, "ACM Parameter: Resistance contact drain side"),
IOP( "rsc", BSIM3v32_MOD_RSC, IF_REAL, "ACM Parameter: Resistance contact source side"),
IOP( "wmlt", BSIM3v32_MOD_WMLT, IF_REAL, "ACM Parameter: Width shrink factor"),
IOP( "alpha0", BSIM3v32_MOD_ALPHA0, IF_REAL, "substrate current model parameter"),
IOP( "alpha1", BSIM3v32_MOD_ALPHA1, IF_REAL, "substrate current model parameter"),

View File

@ -59,6 +59,9 @@ BSIM3v32instance *here = (BSIM3v32instance*)inst;
case BSIM3v32_NQSMOD:
value->iValue = here->BSIM3v32nqsMod;
return(OK);
case BSIM3v32_GEO:
value->iValue = here->BSIM3v32geo;
return(OK);
case BSIM3v32_DELVTO:
value->rValue = here->BSIM3v32delvto;
return(OK);

View File

@ -178,7 +178,7 @@ FILE *fplog;
printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM3v32pscbe2);
}
/* acm model */
/* ACM model */
if (model->BSIM3v32acmMod == 0) {
if (model->BSIM3v32unitLengthSidewallJctCap > 0.0 ||
model->BSIM3v32unitLengthGateSidewallJctCap > 0.0)
@ -198,6 +198,13 @@ FILE *fplog;
}
}
if ((model->BSIM3v32calcacm > 0) && (model->BSIM3v32acmMod != 12))
{ fprintf(fplog, "Warning: CALCACM = %d is wrong. Set back to 0.\n",
model->BSIM3v32calcacm);
printf("Warning: CALCACM = %d is wrong. Set back to 0.\n", model->BSIM3v32calcacm);
model->BSIM3v32calcacm = 0;
}
if (pParam->BSIM3v32noff < 0.1)
{ fprintf(fplog, "Warning: Noff = %g is too small.\n",
pParam->BSIM3v32noff);

View File

@ -363,30 +363,29 @@ for (; model != NULL; model = model->BSIM3v32nextModel)
}
else
{
SourceSatCurrent = 0.0;
if (!here->BSIM3v32sourceAreaGiven)
{
here->BSIM3v32sourceArea = 2.0 * model->BSIM3v32hdif * pParam->BSIM3v32weff;
}
SourceSatCurrent = here->BSIM3v32sourceArea * model->BSIM3v32jctTempSatCurDensity;
if (!here->BSIM3v32sourcePerimeterGiven)
{
here->BSIM3v32sourcePerimeter = 4.0 * model->BSIM3v32hdif + 2.0 * pParam->BSIM3v32weff;
}
SourceSatCurrent = SourceSatCurrent + here->BSIM3v32sourcePerimeter * model->BSIM3v32jctSidewallTempSatCurDensity;
if (SourceSatCurrent <= 0.0) SourceSatCurrent = 1.0e-14;
DrainSatCurrent = 0.0;
if (!here->BSIM3v32drainAreaGiven)
{
here->BSIM3v32drainArea = 2.0 * model->BSIM3v32hdif * pParam->BSIM3v32weff;
}
DrainSatCurrent = here->BSIM3v32drainArea * model->BSIM3v32jctTempSatCurDensity;
if (!here->BSIM3v32drainPerimeterGiven)
{
here->BSIM3v32drainPerimeter = 4.0 * model->BSIM3v32hdif + 2.0 * pParam->BSIM3v32weff;
}
DrainSatCurrent = DrainSatCurrent + here->BSIM3v32drainPerimeter * model->BSIM3v32jctSidewallTempSatCurDensity;
if (DrainSatCurrent <= 0.0) DrainSatCurrent = 1.0e-14;
error = ACM_saturationCurrents(
model->BSIM3v32acmMod,
model->BSIM3v32calcacm,
here->BSIM3v32geo,
model->BSIM3v32hdif,
model->BSIM3v32wmlt,
here->BSIM3v32w,
model->BSIM3v32xw,
model->BSIM3v32jctTempSatCurDensity,
model->BSIM3v32jctSidewallTempSatCurDensity,
here->BSIM3v32drainAreaGiven,
here->BSIM3v32drainArea,
here->BSIM3v32drainPerimeterGiven,
here->BSIM3v32drainPerimeter,
here->BSIM3v32sourceAreaGiven,
here->BSIM3v32sourceArea,
here->BSIM3v32sourcePerimeterGiven,
here->BSIM3v32sourcePerimeter,
&DrainSatCurrent,
&SourceSatCurrent
);
if (error)
return(error);
}
if (SourceSatCurrent <= 0.0)
{ here->BSIM3v32gbs = ckt->CKTgmin;
@ -2453,6 +2452,8 @@ finished:
along gate side
*/
if (model->BSIM3v32acmMod == 0)
{
/* Added revision dependent code */
switch (model->BSIM3v32intVersion) {
case BSIM3v32V324:
@ -2528,6 +2529,36 @@ finished:
* pParam->BSIM3v32weff;
}
}
} else {
error = ACM_junctionCapacitances(
model->BSIM3v32acmMod,
model->BSIM3v32calcacm,
here->BSIM3v32geo,
model->BSIM3v32hdif,
model->BSIM3v32wmlt,
here->BSIM3v32w,
model->BSIM3v32xw,
here->BSIM3v32drainAreaGiven,
here->BSIM3v32drainArea,
here->BSIM3v32drainPerimeterGiven,
here->BSIM3v32drainPerimeter,
here->BSIM3v32sourceAreaGiven,
here->BSIM3v32sourceArea,
here->BSIM3v32sourcePerimeterGiven,
here->BSIM3v32sourcePerimeter,
model->BSIM3v32unitAreaTempJctCap,
model->BSIM3v32unitLengthSidewallTempJctCap,
model->BSIM3v32unitLengthGateSidewallJctCap,
&czbd,
&czbdsw,
&czbdswg,
&czbs,
&czbssw,
&czbsswg
);
if (error)
return(error);
}
MJ = model->BSIM3v32bulkJctBotGradingCoeff;
MJSW = model->BSIM3v32bulkJctSideGradingCoeff;

View File

@ -43,6 +43,9 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
case BSIM3v32_MOD_ACMMOD:
value->iValue = model->BSIM3v32acmMod;
return(OK);
case BSIM3v32_MOD_CALCACM:
value->iValue = model->BSIM3v32calcacm;
return(OK);
case BSIM3v32_MOD_VERSION :
value->sValue = model->BSIM3v32version;
return(OK);
@ -334,7 +337,7 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
value->rValue = model->BSIM3v32tpbswg;
return(OK);
/* acm model */
/* ACM model */
case BSIM3v32_MOD_HDIF:
value->rValue = model->BSIM3v32hdif;
return(OK);
@ -356,6 +359,9 @@ BSIM3v32mAsk (CKTcircuit *ckt, GENmodel *inst, int which, IFvalue *value)
case BSIM3v32_MOD_RSC:
value->rValue = model->BSIM3v32rsc;
return(OK);
case BSIM3v32_MOD_WMLT:
value->rValue = model->BSIM3v32wmlt;
return(OK);
/* Length dependence */
case BSIM3v32_MOD_LCDSC :

View File

@ -41,6 +41,10 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod)
mod->BSIM3v32acmMod = value->iValue;
mod->BSIM3v32acmModGiven = TRUE;
break;
case BSIM3v32_MOD_CALCACM:
mod->BSIM3v32calcacm = value->iValue;
mod->BSIM3v32calcacmGiven = TRUE;
break;
case BSIM3v32_MOD_NOIMOD :
mod->BSIM3v32noiMod = value->iValue;
mod->BSIM3v32noiModGiven = TRUE;
@ -465,6 +469,10 @@ BSIM3v32mParam(int param, IFvalue *value, GENmodel *inMod)
mod->BSIM3v32rsc = value->rValue;
mod->BSIM3v32rscGiven = TRUE;
break;
case BSIM3v32_MOD_WMLT:
mod->BSIM3v32wmlt = value->rValue;
mod->BSIM3v32wmltGiven = TRUE;
break;
/* Length dependence */
case BSIM3v32_MOD_LCDSC :

View File

@ -84,6 +84,10 @@ BSIM3v32param (int param, IFvalue *value, GENinstance *inst, IFvalue *select)
here->BSIM3v32nqsMod = value->iValue;
here->BSIM3v32nqsModGiven = TRUE;
break;
case BSIM3v32_GEO:
here->BSIM3v32geo = value->iValue;
here->BSIM3v32geoGiven = TRUE;
break;
case BSIM3v32_DELVTO:
here->BSIM3v32delvto = value->rValue;
here->BSIM3v32delvtoGiven = TRUE;

View File

@ -54,6 +54,8 @@ IFuid tmpName;
model->BSIM3v32capMod = 3;
if (!model->BSIM3v32acmModGiven)
model->BSIM3v32acmMod = 0;
if (!model->BSIM3v32calcacmGiven)
model->BSIM3v32calcacm = 0;
if (!model->BSIM3v32noiModGiven)
model->BSIM3v32noiMod = 1;
@ -259,7 +261,7 @@ IFuid tmpName;
if (!model->BSIM3v32tpbswgGiven)
model->BSIM3v32tpbswg = 0.0;
/* acm model */
/* ACM model */
if (!model->BSIM3v32hdifGiven)
model->BSIM3v32hdif = 0.0;
if (!model->BSIM3v32ldifGiven)
@ -274,6 +276,8 @@ IFuid tmpName;
model->BSIM3v32rdc = 0.0;
if (!model->BSIM3v32rscGiven)
model->BSIM3v32rsc = 0.0;
if (!model->BSIM3v32wmltGiven)
model->BSIM3v32wmlt = 1.0;
/* Length dependence */
if (!model->BSIM3v32lcdscGiven)
@ -939,6 +943,8 @@ IFuid tmpName;
here->BSIM3v32w = 5.0e-6;
if (!here->BSIM3v32nqsModGiven)
here->BSIM3v32nqsMod = 0;
if (!here->BSIM3v32geoGiven)
here->BSIM3v32geo = 0;
if (!here->BSIM3v32mGiven)
here->BSIM3v32m = 1;

View File

@ -15,6 +15,7 @@
#include "bsim3v32def.h"
#include "ngspice/const.h"
#include "ngspice/sperror.h"
#include "ngspice/devdefs.h"
#include "ngspice/suffix.h"
#define Kb 1.3806226e-23
@ -37,7 +38,7 @@ struct bsim3v32SizeDependParam *pSizeDependParamKnot, *pLastKnot, *pParam=NULL;
double tmp, tmp1, tmp2, tmp3, Eg, Eg0, ni, T0, T1, T2, T3, T4, T5, Ldrn, Wdrn;
double delTemp, Temp, TRatio, Inv_L, Inv_W, Inv_LW, Vtm0, Tnom;
double Nvtm, SourceSatCurrent, DrainSatCurrent;
int Size_Not_Found;
int Size_Not_Found, error;
/* loop through all the BSIM3v32 device models */
for (; model != NULL; model = model->BSIM3v32nextModel)
@ -876,7 +877,7 @@ int Size_Not_Found;
* pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV * T0);
/* process source/drain series resistance */
/* acm model */
/* ACM model */
if (model->BSIM3v32acmMod == 0)
{
here->BSIM3v32drainConductance = model->BSIM3v32sheetResistance
@ -884,28 +885,30 @@ int Size_Not_Found;
here->BSIM3v32sourceConductance = model->BSIM3v32sheetResistance
* here->BSIM3v32sourceSquares;
}
else
else /* ACM > 0 */
{
if (here->BSIM3v32drainSquaresGiven)
{
here->BSIM3v32drainConductance = (model->BSIM3v32ld + model->BSIM3v32ldif)/(here->BSIM3v32w + model->BSIM3v32xw)*model->BSIM3v32rd
+ model->BSIM3v32sheetResistance * here->BSIM3v32drainSquares + model->BSIM3v32rdc;
}
else
{
here->BSIM3v32drainConductance = ((model->BSIM3v32ld + model->BSIM3v32ldif)*model->BSIM3v32rd
+ model->BSIM3v32hdif*model->BSIM3v32sheetResistance)/(here->BSIM3v32w + model->BSIM3v32xw) + model->BSIM3v32rdc;
}
if (here->BSIM3v32sourceSquaresGiven)
{
here->BSIM3v32sourceConductance = (model->BSIM3v32ld + model->BSIM3v32ldif)/(here->BSIM3v32w + model->BSIM3v32xw)*model->BSIM3v32rs
+ model->BSIM3v32sheetResistance * here->BSIM3v32sourceSquares + model->BSIM3v32rsc;
}
else
{
here->BSIM3v32sourceConductance = ((model->BSIM3v32ld + model->BSIM3v32ldif)*model->BSIM3v32rs
+ model->BSIM3v32hdif*model->BSIM3v32sheetResistance)/(here->BSIM3v32w + model->BSIM3v32xw) + model->BSIM3v32rsc;
}
error = ACM_SourceDrainResistances(
model->BSIM3v32acmMod,
model->BSIM3v32ld,
model->BSIM3v32ldif,
model->BSIM3v32hdif,
model->BSIM3v32wmlt,
here->BSIM3v32w,
model->BSIM3v32xw,
model->BSIM3v32sheetResistance,
here->BSIM3v32drainSquaresGiven,
model->BSIM3v32rd,
model->BSIM3v32rdc,
here->BSIM3v32drainSquares,
here->BSIM3v32sourceSquaresGiven,
model->BSIM3v32rs,
model->BSIM3v32rsc,
here->BSIM3v32sourceSquares,
&(here->BSIM3v32drainConductance),
&(here->BSIM3v32sourceConductance)
);
if (error)
return(error);
}
if (here->BSIM3v32drainConductance > 0.0)
here->BSIM3v32drainConductance = 1.0
@ -947,33 +950,31 @@ int Size_Not_Found;
* model->BSIM3v32jctSidewallTempSatCurDensity;
}
}
else
else /* ACM > 0 */
{
SourceSatCurrent = 0.0;
if (!here->BSIM3v32sourceAreaGiven)
{
here->BSIM3v32sourceArea = 2.0 * model->BSIM3v32hdif * pParam->BSIM3v32weff;
}
SourceSatCurrent = here->BSIM3v32sourceArea * model->BSIM3v32jctTempSatCurDensity;
if (!here->BSIM3v32sourcePerimeterGiven)
{
here->BSIM3v32sourcePerimeter = 4.0 * model->BSIM3v32hdif + 2.0 * pParam->BSIM3v32weff;
}
SourceSatCurrent = SourceSatCurrent + here->BSIM3v32sourcePerimeter * model->BSIM3v32jctSidewallTempSatCurDensity;
if (SourceSatCurrent <= 0.0) SourceSatCurrent = 1.0e-14;
DrainSatCurrent = 0.0;
if (!here->BSIM3v32drainAreaGiven)
{
here->BSIM3v32drainArea = 2.0 * model->BSIM3v32hdif * pParam->BSIM3v32weff;
}
DrainSatCurrent = here->BSIM3v32drainArea * model->BSIM3v32jctTempSatCurDensity;
if (!here->BSIM3v32drainPerimeterGiven)
{
here->BSIM3v32drainPerimeter = 4.0 * model->BSIM3v32hdif + 2.0 * pParam->BSIM3v32weff;
}
DrainSatCurrent = DrainSatCurrent + here->BSIM3v32drainPerimeter * model->BSIM3v32jctSidewallTempSatCurDensity;
if (DrainSatCurrent <= 0.0) DrainSatCurrent = 1.0e-14;
error = ACM_saturationCurrents(
model->BSIM3v32acmMod,
model->BSIM3v32calcacm,
here->BSIM3v32geo,
model->BSIM3v32hdif,
model->BSIM3v32wmlt,
here->BSIM3v32w,
model->BSIM3v32xw,
model->BSIM3v32jctTempSatCurDensity,
model->BSIM3v32jctSidewallTempSatCurDensity,
here->BSIM3v32drainAreaGiven,
here->BSIM3v32drainArea,
here->BSIM3v32drainPerimeterGiven,
here->BSIM3v32drainPerimeter,
here->BSIM3v32sourceAreaGiven,
here->BSIM3v32sourceArea,
here->BSIM3v32sourcePerimeterGiven,
here->BSIM3v32sourcePerimeter,
&DrainSatCurrent,
&SourceSatCurrent
);
if (error)
return(error);
}
if ((SourceSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0))

View File

@ -67,6 +67,7 @@ typedef struct sBSIM3v32instance
int BSIM3v32off;
int BSIM3v32mode;
int BSIM3v32nqsMod;
int BSIM3v32geo;
/* OP point */
double BSIM3v32qinv;
@ -135,6 +136,7 @@ typedef struct sBSIM3v32instance
unsigned BSIM3v32icVDSGiven :1;
unsigned BSIM3v32icVGSGiven :1;
unsigned BSIM3v32nqsModGiven :1;
unsigned BSIM3v32geoGiven :1;
double *BSIM3v32DdPtr;
double *BSIM3v32GgPtr;
@ -361,6 +363,7 @@ typedef struct sBSIM3v32model
int BSIM3v32mobMod;
int BSIM3v32capMod;
int BSIM3v32acmMod;
int BSIM3v32calcacm;
int BSIM3v32noiMod;
int BSIM3v32binUnit;
int BSIM3v32paramChk;
@ -471,7 +474,9 @@ typedef struct sBSIM3v32model
double BSIM3v32tpbsw;
double BSIM3v32tpbswg;
/* acm model */
/* ACM model */
double BSIM3v32xl;
double BSIM3v32xw;
double BSIM3v32hdif;
double BSIM3v32ldif;
double BSIM3v32ld;
@ -479,6 +484,7 @@ typedef struct sBSIM3v32model
double BSIM3v32rs;
double BSIM3v32rdc;
double BSIM3v32rsc;
double BSIM3v32wmlt;
/* Length Dependence */
double BSIM3v32lcdsc;
@ -788,10 +794,6 @@ typedef struct sBSIM3v32model
double BSIM3v32Wmin;
double BSIM3v32Wmax;
/* acm model */
double BSIM3v32xl;
double BSIM3v32xw;
/* Pre-calculated constants */
/* MCJ: move to size-dependent param. */
double BSIM3v32vtm;
@ -826,6 +828,7 @@ typedef struct sBSIM3v32model
unsigned BSIM3v32binUnitGiven :1;
unsigned BSIM3v32capModGiven :1;
unsigned BSIM3v32acmModGiven :1;
unsigned BSIM3v32calcacmGiven :1;
unsigned BSIM3v32paramChkGiven :1;
unsigned BSIM3v32noiModGiven :1;
unsigned BSIM3v32typeGiven :1;
@ -927,7 +930,9 @@ typedef struct sBSIM3v32model
unsigned BSIM3v32tpbswGiven :1;
unsigned BSIM3v32tpbswgGiven :1;
/* acm model */
/* ACM model */
unsigned BSIM3v32xlGiven :1;
unsigned BSIM3v32xwGiven :1;
unsigned BSIM3v32hdifGiven :1;
unsigned BSIM3v32ldifGiven :1;
unsigned BSIM3v32ldGiven :1;
@ -935,6 +940,7 @@ typedef struct sBSIM3v32model
unsigned BSIM3v32rsGiven :1;
unsigned BSIM3v32rdcGiven :1;
unsigned BSIM3v32rscGiven :1;
unsigned BSIM3v32wmltGiven :1;
/* Length dependence */
unsigned BSIM3v32lcdscGiven :1;
@ -1251,10 +1257,6 @@ typedef struct sBSIM3v32model
unsigned BSIM3v32WminGiven :1;
unsigned BSIM3v32WmaxGiven :1;
/* acm model */
unsigned BSIM3v32xlGiven :1;
unsigned BSIM3v32xwGiven :1;
} BSIM3v32model;
@ -1282,10 +1284,12 @@ typedef struct sBSIM3v32model
#define BSIM3v32_M 15
#define BSIM3v32_DELVTO 16
#define BSIM3v32_MULU0 17
#define BSIM3v32_GEO 18
/* model parameters */
#define BSIM3v32_MOD_CAPMOD 101
#define BSIM3v32_MOD_ACMMOD 102
#define BSIM3v32_MOD_CAPMOD 100
#define BSIM3v32_MOD_ACMMOD 101
#define BSIM3v32_MOD_CALCACM 102
#define BSIM3v32_MOD_MOBMOD 103
#define BSIM3v32_MOD_NOIMOD 104
@ -1750,7 +1754,7 @@ typedef struct sBSIM3v32model
#define BSIM3v32_MOD_WWC 701
#define BSIM3v32_MOD_WWLC 702
/* acm parameters */
/* ACM parameters */
#define BSIM3v32_MOD_XL 703
#define BSIM3v32_MOD_XW 704
@ -1761,6 +1765,7 @@ typedef struct sBSIM3v32model
#define BSIM3v32_MOD_RS 715
#define BSIM3v32_MOD_RDC 716
#define BSIM3v32_MOD_RSC 717
#define BSIM3v32_MOD_WMLT 718
/* device questions */
#define BSIM3v32_DNODE 751

View File

@ -147,6 +147,382 @@ DEVfetlim(double vnew, double vold, double vto)
return(vnew);
}
int
ACM_SourceDrainResistances(
int ACM,
double LD,
double LDIF,
double HDIF,
double WMLT,
double w,
double XW,
double RSH,
int drainSquaresGiven,
double RD,
double RDC,
double drainSquares,
int sourceSquaresGiven,
double RS,
double RSC,
double sourceSquares,
double *drainConductance,
double *sourceConductance
)
{
switch (ACM)
{
case 1:
case 11:
*drainConductance = (LD + LDIF)/(w * WMLT + XW)*RD + RSH*drainSquares + RDC;
*sourceConductance = (LD + LDIF)/(w * WMLT + XW)*RS + RSH*sourceSquares + RSC;
break;
case 2:
case 12:
case 3:
case 13:
if (drainSquaresGiven)
*drainConductance = (LD + LDIF)/(w * WMLT + XW)*RD + RSH*drainSquares + RDC;
else
*drainConductance = ((LD + LDIF)*RD + (HDIF * WMLT)*RSH)/(w * WMLT + XW) + RDC;
if (sourceSquaresGiven)
*sourceConductance = (LD + LDIF)/(w * WMLT + XW)*RS + RSH*sourceSquares + RSC;
else
*sourceConductance = ((LD + LDIF)*RS + (HDIF * WMLT)*RSH)/(w * WMLT + XW) + RSC;
break;
default:
break;
}
return 0;
}
/* Area Calculation Method (ACM) for MOS models */
int
ACM_saturationCurrents(
int ACM,
int CALCACM,
int GEO,
double HDIF,
double WMLT,
double w,
double XW,
double jctTempSatCurDensity,
double jctSidewallTempSatCurDensity,
int drainAreaGiven,
double drainArea,
int drainPerimeterGiven,
double drainPerimeter,
int sourceAreaGiven,
double sourceArea,
int sourcePerimeterGiven,
double sourcePerimeter,
double *DrainSatCurrent,
double *SourceSatCurrent
)
{
switch (ACM)
{
case 1:
case 11:
drainArea = (w * WMLT + XW) * WMLT;
drainPerimeter = (w * WMLT + XW);
*DrainSatCurrent = drainArea * jctTempSatCurDensity + drainPerimeter * jctSidewallTempSatCurDensity;
if (*DrainSatCurrent <= 0.0) *DrainSatCurrent = 1.0e-14;
sourceArea = (w * WMLT + XW) * WMLT;
sourcePerimeter = (w * WMLT + XW);
*SourceSatCurrent = sourceArea * jctTempSatCurDensity + sourcePerimeter * jctSidewallTempSatCurDensity;
if (*SourceSatCurrent <= 0.0) *SourceSatCurrent = 1.0e-14;
break;
case 2:
case 12:
if ((ACM == 2) || ((ACM == 12) && (CALCACM == 1))) {
if (!drainAreaGiven)
drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
drainArea = drainArea * WMLT * WMLT;
if (!drainPerimeterGiven)
drainPerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW);
else
drainPerimeter = drainPerimeter * WMLT;
}
*DrainSatCurrent = drainArea * jctTempSatCurDensity + drainPerimeter * jctSidewallTempSatCurDensity;
if (*DrainSatCurrent <= 0.0) *DrainSatCurrent = 1.0e-14;
if ((ACM == 2) || ((ACM == 12) && (CALCACM == 1))) {
if (!sourceAreaGiven)
sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
sourceArea = sourceArea * WMLT * WMLT;
if (!sourcePerimeterGiven)
sourcePerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW);
else
sourcePerimeter = sourcePerimeter * WMLT;
}
*SourceSatCurrent = sourceArea * jctTempSatCurDensity + sourcePerimeter * jctSidewallTempSatCurDensity;
if (*SourceSatCurrent <= 0.0) *SourceSatCurrent = 1.0e-14;
break;
case 3:
case 13:
if (!drainAreaGiven)
if ((GEO == 0) || (GEO == 2))
drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
drainArea = (HDIF * WMLT) * (w * WMLT + XW);
else
drainArea = drainArea * WMLT * WMLT;
if (!drainPerimeterGiven)
if ((GEO == 0) || (GEO == 2))
drainPerimeter = 4.0 * (HDIF * WMLT) + (w * WMLT + XW);
else
drainPerimeter = 2.0 * (HDIF * WMLT);
else
drainPerimeter = drainPerimeter * WMLT;
*DrainSatCurrent = drainArea * jctTempSatCurDensity + drainPerimeter * jctSidewallTempSatCurDensity;
if (*DrainSatCurrent <= 0.0) *DrainSatCurrent = 1.0e-14;
if (!sourceAreaGiven)
if ((GEO == 0) || (GEO == 1))
sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
sourceArea = (HDIF * WMLT) * (w * WMLT + XW);
else
sourceArea = sourceArea * WMLT * WMLT;
if (!sourcePerimeterGiven)
if ((GEO == 0) || (GEO == 1))
sourcePerimeter = 4.0 * (HDIF * WMLT) + (w * WMLT + XW);
else
sourcePerimeter = 2.0 * (HDIF * WMLT);
else
sourcePerimeter = sourcePerimeter * WMLT;
*SourceSatCurrent = sourceArea * jctTempSatCurDensity + sourcePerimeter * jctSidewallTempSatCurDensity;
if (*SourceSatCurrent <= 0.0) *SourceSatCurrent = 1.0e-14;
break;
default:
break;
}
return 0;
}
int
ACM_junctionCapacitances(
int ACM,
int CALCACM,
int GEO,
double HDIF,
double WMLT,
double w,
double XW,
int drainAreaGiven,
double drainArea,
int drainPerimeterGiven,
double drainPerimeter,
int sourceAreaGiven,
double sourceArea,
int sourcePerimeterGiven,
double sourcePerimeter,
double CJ,
double CJSW,
double CJGATE,
double *areaDrainBulkCapacitance,
double *periDrainBulkCapacitance,
double *gateDrainBulkCapacitance,
double *areaSourceBulkCapacitance,
double *periSourceBulkCapacitance,
double *gateSourceBulkCapacitance
)
{
switch (ACM)
{
case 1:
drainArea = (w * WMLT + XW) * WMLT;
drainPerimeter = (w * WMLT + XW);
*areaDrainBulkCapacitance = drainArea * CJ;
*periDrainBulkCapacitance = drainPerimeter * CJSW;
*gateDrainBulkCapacitance = 0.0;
sourceArea = (w * WMLT + XW) * WMLT;
sourcePerimeter = (w * WMLT + XW);
*areaSourceBulkCapacitance = sourceArea * CJ;
*periSourceBulkCapacitance = sourcePerimeter * CJSW;
*gateSourceBulkCapacitance = 0.0;
break;
case 2:
if (!drainAreaGiven)
drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
drainArea = drainArea * WMLT * WMLT;
if (!drainPerimeterGiven)
drainPerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW);
else
drainPerimeter = drainPerimeter * WMLT;
*areaDrainBulkCapacitance = drainArea * CJ;
if (drainPerimeter > (w * WMLT + XW)) {
*periDrainBulkCapacitance = (drainPerimeter - (w * WMLT + XW)) * CJSW;
*gateDrainBulkCapacitance = (w * WMLT + XW) * CJGATE;
} else {
*periDrainBulkCapacitance = drainPerimeter * CJGATE;
*gateDrainBulkCapacitance = 0.0;
}
if (!sourceAreaGiven)
sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
sourceArea = sourceArea * WMLT * WMLT;
if (!sourcePerimeterGiven)
sourcePerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW);
else
sourcePerimeter = sourcePerimeter * WMLT;
*areaSourceBulkCapacitance = sourceArea * CJ;
if (sourcePerimeter > (w * WMLT + XW)) {
*periSourceBulkCapacitance = (sourcePerimeter - (w * WMLT + XW)) * CJSW;
*gateSourceBulkCapacitance = (w * WMLT + XW) * CJGATE;
} else {
*periSourceBulkCapacitance = sourcePerimeter * CJGATE;
*gateSourceBulkCapacitance = 0.0;
}
break;
case 3:
if (!drainAreaGiven)
if ((GEO == 0) || (GEO == 2))
drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
drainArea = (HDIF * WMLT) * (w * WMLT + XW);
else
drainArea = drainArea * WMLT * WMLT;
if (!drainPerimeterGiven)
if ((GEO == 0) || (GEO == 2))
drainPerimeter = 4.0 * (HDIF * WMLT) + (w * WMLT + XW);
else
drainPerimeter = 2.0 * (HDIF * WMLT);
else
drainPerimeter = drainPerimeter * WMLT;
*areaDrainBulkCapacitance = drainArea * CJ;
*periDrainBulkCapacitance = drainPerimeter * CJSW ;
*gateDrainBulkCapacitance = (w * WMLT + XW) * CJGATE;
if (!sourceAreaGiven)
if ((GEO == 0) || (GEO == 1))
sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
sourceArea = (HDIF * WMLT) * (w * WMLT + XW);
else
sourceArea = sourceArea * WMLT * WMLT;
if (!sourcePerimeterGiven)
if ((GEO == 0) || (GEO == 1))
sourcePerimeter = 4.0 * (HDIF * WMLT) + (w * WMLT + XW);
else
sourcePerimeter = 2.0 * (HDIF * WMLT);
else
sourcePerimeter = sourcePerimeter * WMLT;
*areaSourceBulkCapacitance = sourceArea * CJ;
*periSourceBulkCapacitance = sourcePerimeter * CJSW;
*gateSourceBulkCapacitance = (w * WMLT + XW) * CJGATE;
break;
case 11:
drainArea = (w * WMLT + XW) * WMLT;
drainPerimeter = (w * WMLT + XW);
*areaDrainBulkCapacitance = drainArea * CJ;
*periDrainBulkCapacitance = drainPerimeter * CJSW;
*gateDrainBulkCapacitance = 0.0;
sourceArea = (w * WMLT + XW) * WMLT;
sourcePerimeter = (w * WMLT + XW);
*areaSourceBulkCapacitance = sourceArea * CJ;
*periSourceBulkCapacitance = sourcePerimeter * CJSW;
*gateSourceBulkCapacitance = 0.0;
break;
case 12:
if (CALCACM == 1) {
if (!drainAreaGiven)
drainArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
drainArea = drainArea * WMLT * WMLT;
if (!drainPerimeterGiven)
drainPerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW);
else
drainPerimeter = drainPerimeter * WMLT;
}
*areaDrainBulkCapacitance = drainArea * CJ;
if (drainPerimeter > (w * WMLT + XW)) {
*periDrainBulkCapacitance = (drainPerimeter - (w * WMLT + XW)) * CJSW;
*gateDrainBulkCapacitance = (w * WMLT + XW) * CJGATE;
} else {
*periDrainBulkCapacitance = 0.0;
*gateDrainBulkCapacitance = drainPerimeter * CJGATE;
}
if (CALCACM == 1) {
if (!sourceAreaGiven)
sourceArea = 2.0 * (HDIF * WMLT) * (w * WMLT + XW);
else
sourceArea = sourceArea * WMLT * WMLT;
if (!sourcePerimeterGiven)
sourcePerimeter = 4.0 * (HDIF * WMLT) + 2.0 * (w * WMLT + XW);
else
sourcePerimeter = sourcePerimeter * WMLT;
}
*areaSourceBulkCapacitance = sourceArea * CJ;
if (sourcePerimeter > (w * WMLT + XW)) {
*periSourceBulkCapacitance = (sourcePerimeter - (w * WMLT + XW)) * CJSW;
*gateSourceBulkCapacitance = (w * WMLT + XW) * CJGATE;
} else {
*periSourceBulkCapacitance = 0.0;
*gateSourceBulkCapacitance = sourcePerimeter * CJGATE;
}
break;
case 13:
drainArea = drainArea * WMLT * WMLT;
drainPerimeter = drainPerimeter * WMLT;
*areaDrainBulkCapacitance = drainArea * CJ;
if (drainPerimeter > (w * WMLT + XW)) {
*periDrainBulkCapacitance = (drainPerimeter - (w * WMLT + XW)) * CJSW;
*gateDrainBulkCapacitance = (w * WMLT + XW) * CJGATE;
} else {
*periDrainBulkCapacitance = 0.0;
*gateDrainBulkCapacitance = drainPerimeter * CJGATE;
}
sourceArea = sourceArea * WMLT * WMLT;
sourcePerimeter = sourcePerimeter * WMLT;
*areaSourceBulkCapacitance = sourceArea * CJ;
if (sourcePerimeter > (w * WMLT + XW)) {
*periSourceBulkCapacitance = (sourcePerimeter - (w * WMLT + XW)) * CJSW;
*gateSourceBulkCapacitance = (w * WMLT + XW) * CJGATE;
} else {
*periSourceBulkCapacitance = 0.0;
*gateSourceBulkCapacitance = sourcePerimeter * CJGATE;
}
break;
default:
break;
}
return 0;
}
/* Compute the MOS overlap capacitances as functions of the device
* terminal voltages