diff --git a/src/include/ngspice/devdefs.h b/src/include/ngspice/devdefs.h index c91598f54..f86390dbb 100644 --- a/src/include/ngspice/devdefs.h +++ b/src/include/ngspice/devdefs.h @@ -28,10 +28,21 @@ double limitJunctionVoltage( double, double, int * ); double limitVbe( double, double, int * ); double limitVce( double, double, int * ); 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; diff --git a/src/spicelib/devices/bsim3v32/b3v32.c b/src/spicelib/devices/bsim3v32/b3v32.c index 5881eaa1c..d6f766822 100644 --- a/src/spicelib/devices/bsim3v32/b3v32.c +++ b/src/spicelib/devices/bsim3v32/b3v32.c @@ -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"), diff --git a/src/spicelib/devices/bsim3v32/b3v32ask.c b/src/spicelib/devices/bsim3v32/b3v32ask.c index 3eb7b1730..7d405a936 100644 --- a/src/spicelib/devices/bsim3v32/b3v32ask.c +++ b/src/spicelib/devices/bsim3v32/b3v32ask.c @@ -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); diff --git a/src/spicelib/devices/bsim3v32/b3v32check.c b/src/spicelib/devices/bsim3v32/b3v32check.c index f297934dc..86f4fabd0 100644 --- a/src/spicelib/devices/bsim3v32/b3v32check.c +++ b/src/spicelib/devices/bsim3v32/b3v32check.c @@ -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) @@ -197,6 +197,12 @@ 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", diff --git a/src/spicelib/devices/bsim3v32/b3v32ld.c b/src/spicelib/devices/bsim3v32/b3v32ld.c index 69b212937..ab1f62fee 100644 --- a/src/spicelib/devices/bsim3v32/b3v32ld.c +++ b/src/spicelib/devices/bsim3v32/b3v32ld.c @@ -351,21 +351,40 @@ for (; model != NULL; model = model->BSIM3v32nextModel) + here->BSIM3v32sourcePerimeter * model->BSIM3v32jctSidewallTempSatCurDensity; } + if ((here->BSIM3v32drainArea <= 0.0) && (here->BSIM3v32drainPerimeter <= 0.0)) + { DrainSatCurrent = 1.0e-14; + } + else + { DrainSatCurrent = here->BSIM3v32drainArea + * model->BSIM3v32jctTempSatCurDensity + + here->BSIM3v32drainPerimeter + * model->BSIM3v32jctSidewallTempSatCurDensity; + } } 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; + if ( + 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 + ) == 0) printf("load IDsat: %g ISsat: %g\n",DrainSatCurrent,SourceSatCurrent); } if (SourceSatCurrent <= 0.0) { here->BSIM3v32gbs = ckt->CKTgmin; @@ -408,34 +427,6 @@ for (; model != NULL; model = model->BSIM3v32nextModel) } } - /* acm model */ - if (model->BSIM3v32acmMod == 0) - { - if ((here->BSIM3v32drainArea <= 0.0) && (here->BSIM3v32drainPerimeter <= 0.0)) - { DrainSatCurrent = 1.0e-14; - } - else - { DrainSatCurrent = here->BSIM3v32drainArea - * model->BSIM3v32jctTempSatCurDensity - + here->BSIM3v32drainPerimeter - * model->BSIM3v32jctSidewallTempSatCurDensity; - } - } - else - { - 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; - } if (DrainSatCurrent <= 0.0) { here->BSIM3v32gbd = ckt->CKTgmin; here->BSIM3v32cbd = here->BSIM3v32gbd * vbd; @@ -2460,80 +2451,112 @@ finished: along gate side */ - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - czbd = model->BSIM3v32unitAreaTempJctCap * here->BSIM3v32drainArea; /*bug fix */ - czbs = model->BSIM3v32unitAreaTempJctCap * here->BSIM3v32sourceArea; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - czbd = model->BSIM3v32unitAreaJctCap * here->BSIM3v32drainArea; - czbs = model->BSIM3v32unitAreaJctCap * here->BSIM3v32sourceArea; - } + if (model->BSIM3v32acmMod == 0) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + czbd = model->BSIM3v32unitAreaTempJctCap * here->BSIM3v32drainArea; /*bug fix */ + czbs = model->BSIM3v32unitAreaTempJctCap * here->BSIM3v32sourceArea; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + czbd = model->BSIM3v32unitAreaJctCap * here->BSIM3v32drainArea; + czbs = model->BSIM3v32unitAreaJctCap * here->BSIM3v32sourceArea; + } + + if (here->BSIM3v32drainPerimeter < pParam->BSIM3v32weff) + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + czbdswg = model->BSIM3v32unitLengthGateSidewallTempJctCap + * here->BSIM3v32drainPerimeter; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + czbdswg = model->BSIM3v32unitLengthGateSidewallJctCap + * here->BSIM3v32drainPerimeter; + } + czbdsw = 0.0; + } + else + { + czbdsw = model->BSIM3v32unitLengthSidewallTempJctCap + * (here->BSIM3v32drainPerimeter - pParam->BSIM3v32weff); + czbdswg = model->BSIM3v32unitLengthGateSidewallTempJctCap + * pParam->BSIM3v32weff; + } + if (here->BSIM3v32sourcePerimeter < pParam->BSIM3v32weff) + { + czbssw = 0.0; + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + czbsswg = model->BSIM3v32unitLengthGateSidewallTempJctCap + * here->BSIM3v32sourcePerimeter; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + czbsswg = model->BSIM3v32unitLengthGateSidewallJctCap + * here->BSIM3v32sourcePerimeter; + } + } + else + { + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + czbssw = model->BSIM3v32unitLengthSidewallTempJctCap + * (here->BSIM3v32sourcePerimeter - pParam->BSIM3v32weff); + czbsswg = model->BSIM3v32unitLengthGateSidewallTempJctCap + * pParam->BSIM3v32weff; + break; + case BSIM3v32V322: + case BSIM3v32V32: + default: + czbssw = model->BSIM3v32unitLengthSidewallJctCap + * (here->BSIM3v32sourcePerimeter - pParam->BSIM3v32weff); + czbsswg = model->BSIM3v32unitLengthGateSidewallJctCap + * pParam->BSIM3v32weff; + } + } - if (here->BSIM3v32drainPerimeter < pParam->BSIM3v32weff) - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - czbdswg = model->BSIM3v32unitLengthGateSidewallTempJctCap - * here->BSIM3v32drainPerimeter; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - czbdswg = model->BSIM3v32unitLengthGateSidewallJctCap - * here->BSIM3v32drainPerimeter; - } - czbdsw = 0.0; - } - else - { - czbdsw = model->BSIM3v32unitLengthSidewallTempJctCap - * (here->BSIM3v32drainPerimeter - pParam->BSIM3v32weff); - czbdswg = model->BSIM3v32unitLengthGateSidewallTempJctCap - * pParam->BSIM3v32weff; - } - if (here->BSIM3v32sourcePerimeter < pParam->BSIM3v32weff) - { - czbssw = 0.0; - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - czbsswg = model->BSIM3v32unitLengthGateSidewallTempJctCap - * here->BSIM3v32sourcePerimeter; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - czbsswg = model->BSIM3v32unitLengthGateSidewallJctCap - * here->BSIM3v32sourcePerimeter; - } - } - else - { - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - czbssw = model->BSIM3v32unitLengthSidewallTempJctCap - * (here->BSIM3v32sourcePerimeter - pParam->BSIM3v32weff); - czbsswg = model->BSIM3v32unitLengthGateSidewallTempJctCap - * pParam->BSIM3v32weff; - break; - case BSIM3v32V322: - case BSIM3v32V32: - default: - czbssw = model->BSIM3v32unitLengthSidewallJctCap - * (here->BSIM3v32sourcePerimeter - pParam->BSIM3v32weff); - czbsswg = model->BSIM3v32unitLengthGateSidewallJctCap - * pParam->BSIM3v32weff; - } + } else { + if( + 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 + ) == 0) printf("load Cda: %g Cdsw: %g Cdswg: %g Csa: %g Cssw: %g Csswg %g\n",czbd,czbdsw,czbdswg,czbs,czbssw,czbsswg); } MJ = model->BSIM3v32bulkJctBotGradingCoeff; diff --git a/src/spicelib/devices/bsim3v32/b3v32mask.c b/src/spicelib/devices/bsim3v32/b3v32mask.c index d031ce718..bf66890a0 100644 --- a/src/spicelib/devices/bsim3v32/b3v32mask.c +++ b/src/spicelib/devices/bsim3v32/b3v32mask.c @@ -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 : diff --git a/src/spicelib/devices/bsim3v32/b3v32mpar.c b/src/spicelib/devices/bsim3v32/b3v32mpar.c index 6ca123156..46cd00364 100644 --- a/src/spicelib/devices/bsim3v32/b3v32mpar.c +++ b/src/spicelib/devices/bsim3v32/b3v32mpar.c @@ -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 : diff --git a/src/spicelib/devices/bsim3v32/b3v32par.c b/src/spicelib/devices/bsim3v32/b3v32par.c index 5ff8a05a8..425eb4489 100644 --- a/src/spicelib/devices/bsim3v32/b3v32par.c +++ b/src/spicelib/devices/bsim3v32/b3v32par.c @@ -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; diff --git a/src/spicelib/devices/bsim3v32/b3v32set.c b/src/spicelib/devices/bsim3v32/b3v32set.c index df50109ca..52e8acd0a 100644 --- a/src/spicelib/devices/bsim3v32/b3v32set.c +++ b/src/spicelib/devices/bsim3v32/b3v32set.c @@ -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; @@ -995,14 +1001,14 @@ IFuid tmpName; { here->BSIM3v32sNodePrime = here->BSIM3v32sNode; } - /* internal charge node */ + /* internal charge node */ if (here->BSIM3v32nqsMod) { if(here->BSIM3v32qNode == 0) - { error = CKTmkVolt(ckt,&tmp,here->BSIM3v32name,"charge"); - if(error) return(error); - here->BSIM3v32qNode = tmp->number; - } + { error = CKTmkVolt(ckt,&tmp,here->BSIM3v32name,"charge"); + if(error) return(error); + here->BSIM3v32qNode = tmp->number; + } } else { here->BSIM3v32qNode = 0; diff --git a/src/spicelib/devices/bsim3v32/b3v32temp.c b/src/spicelib/devices/bsim3v32/b3v32temp.c index d8fb780e1..96b5493fe 100644 --- a/src/spicelib/devices/bsim3v32/b3v32temp.c +++ b/src/spicelib/devices/bsim3v32/b3v32temp.c @@ -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 @@ -876,36 +877,37 @@ 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 - * here->BSIM3v32drainSquares; - here->BSIM3v32sourceConductance = model->BSIM3v32sheetResistance - * here->BSIM3v32sourceSquares; + here->BSIM3v32drainConductance = model->BSIM3v32sheetResistance + * here->BSIM3v32drainSquares; + 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; - } + if ( + 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) + ) == 0 ) printf("temp RD: %g RS: %g\n",here->BSIM3v32drainConductance,here->BSIM3v32sourceConductance); } if (here->BSIM3v32drainConductance > 0.0) here->BSIM3v32drainConductance = 1.0 @@ -935,23 +937,6 @@ int Size_Not_Found; + here->BSIM3v32sourcePerimeter * model->BSIM3v32jctSidewallTempSatCurDensity; } - if ((SourceSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) - { here->BSIM3v32vjsm = Nvtm * log(model->BSIM3v32ijth - / SourceSatCurrent + 1.0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - here->BSIM3v32IsEvjsm = - SourceSatCurrent * exp(here->BSIM3v32vjsm / Nvtm); - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } - } if ((here->BSIM3v32drainArea <= 0.0) && (here->BSIM3v32drainPerimeter <= 0.0)) @@ -963,85 +948,67 @@ int Size_Not_Found; + here->BSIM3v32drainPerimeter * model->BSIM3v32jctSidewallTempSatCurDensity; } - if ((DrainSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) - { here->BSIM3v32vjdm = Nvtm * log(model->BSIM3v32ijth - / DrainSatCurrent + 1.0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - here->BSIM3v32IsEvjdm = - DrainSatCurrent * exp(here->BSIM3v32vjdm / Nvtm); - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } - } } - 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; - if ((SourceSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) - { here->BSIM3v32vjsm = Nvtm * log(model->BSIM3v32ijth - / SourceSatCurrent + 1.0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - here->BSIM3v32IsEvjsm = - SourceSatCurrent * exp(here->BSIM3v32vjsm / Nvtm); - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } - } + if ( + 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 + ) == 0) printf("temp IDsat: %g ISsat: %g\n",DrainSatCurrent,SourceSatCurrent); - 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; - if ((DrainSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) - { here->BSIM3v32vjdm = Nvtm * log(model->BSIM3v32ijth - / DrainSatCurrent + 1.0); - /* Added revision dependent code */ - switch (model->BSIM3v32intVersion) { - case BSIM3v32V324: - case BSIM3v32V323: - case BSIM3v32V322: - here->BSIM3v32IsEvjdm = - DrainSatCurrent * exp(here->BSIM3v32vjdm / Nvtm); - break; - case BSIM3v32V32: - default: - /* Do nothing */ - break; - } - } + } + if ((SourceSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) + { here->BSIM3v32vjsm = Nvtm * log(model->BSIM3v32ijth + / SourceSatCurrent + 1.0); + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + here->BSIM3v32IsEvjsm = + SourceSatCurrent * exp(here->BSIM3v32vjsm / Nvtm); + break; + case BSIM3v32V32: + default: + /* Do nothing */ + break; + } + } + + if ((DrainSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0)) + { here->BSIM3v32vjdm = Nvtm * log(model->BSIM3v32ijth + / DrainSatCurrent + 1.0); + /* Added revision dependent code */ + switch (model->BSIM3v32intVersion) { + case BSIM3v32V324: + case BSIM3v32V323: + case BSIM3v32V322: + here->BSIM3v32IsEvjdm = + DrainSatCurrent * exp(here->BSIM3v32vjdm / Nvtm); + break; + case BSIM3v32V32: + default: + /* Do nothing */ + break; + } } } } diff --git a/src/spicelib/devices/bsim3v32/bsim3v32def.h b/src/spicelib/devices/bsim3v32/bsim3v32def.h index 188f2bfe4..8428f4413 100644 --- a/src/spicelib/devices/bsim3v32/bsim3v32def.h +++ b/src/spicelib/devices/bsim3v32/bsim3v32def.h @@ -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,10 +1754,9 @@ 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 - #define BSIM3v32_MOD_HDIF 711 #define BSIM3v32_MOD_LDIF 712 #define BSIM3v32_MOD_LD 713 @@ -1761,6 +1764,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 diff --git a/src/spicelib/devices/devsup.c b/src/spicelib/devices/devsup.c index edd1abeda..8d6d4c517 100644 --- a/src/spicelib/devices/devsup.c +++ b/src/spicelib/devices/devsup.c @@ -147,6 +147,379 @@ 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