From 7b2bd10b64ca9fe129ef0f0eaa8f6d075e952e05 Mon Sep 17 00:00:00 2001 From: dwarning Date: Thu, 16 May 2013 22:22:51 +0200 Subject: [PATCH] devices/bsim3v32: apply Area Calculation Method (ACM) to the bsim3v3.2.4 model --- src/include/ngspice/devdefs.h | 14 + src/spicelib/devices/bsim3v32/b3v32.c | 3 + src/spicelib/devices/bsim3v32/b3v32ask.c | 3 + src/spicelib/devices/bsim3v32/b3v32check.c | 9 +- src/spicelib/devices/bsim3v32/b3v32ld.c | 79 ++-- src/spicelib/devices/bsim3v32/b3v32mask.c | 8 +- src/spicelib/devices/bsim3v32/b3v32mpar.c | 8 + src/spicelib/devices/bsim3v32/b3v32par.c | 4 + src/spicelib/devices/bsim3v32/b3v32set.c | 8 +- src/spicelib/devices/bsim3v32/b3v32temp.c | 99 +++--- src/spicelib/devices/bsim3v32/bsim3v32def.h | 31 +- src/spicelib/devices/devsup.c | 376 ++++++++++++++++++++ 12 files changed, 553 insertions(+), 89 deletions(-) diff --git a/src/include/ngspice/devdefs.h b/src/include/ngspice/devdefs.h index c91598f54..9fa518dfb 100644 --- a/src/include/ngspice/devdefs.h +++ b/src/include/ngspice/devdefs.h @@ -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; 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..b0d3aa4f5 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) @@ -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); diff --git a/src/spicelib/devices/bsim3v32/b3v32ld.c b/src/spicelib/devices/bsim3v32/b3v32ld.c index 0cbb046b7..e62b6f946 100644 --- a/src/spicelib/devices/bsim3v32/b3v32ld.c +++ b/src/spicelib/devices/bsim3v32/b3v32ld.c @@ -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; diff --git a/src/spicelib/devices/bsim3v32/b3v32mask.c b/src/spicelib/devices/bsim3v32/b3v32mask.c index d031ce718..8d632a2ac 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..a27dfc66f 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; diff --git a/src/spicelib/devices/bsim3v32/b3v32temp.c b/src/spicelib/devices/bsim3v32/b3v32temp.c index e110ab3bc..7ee10059f 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 @@ -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)) diff --git a/src/spicelib/devices/bsim3v32/bsim3v32def.h b/src/spicelib/devices/bsim3v32/bsim3v32def.h index 188f2bfe4..faf96f106 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,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 diff --git a/src/spicelib/devices/devsup.c b/src/spicelib/devices/devsup.c index edd1abeda..6249344b4 100644 --- a/src/spicelib/devices/devsup.c +++ b/src/spicelib/devices/devsup.c @@ -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