Browse Source

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

pre-master-46
dwarning 13 years ago
committed by rlar
parent
commit
7b2bd10b64
  1. 14
      src/include/ngspice/devdefs.h
  2. 3
      src/spicelib/devices/bsim3v32/b3v32.c
  3. 3
      src/spicelib/devices/bsim3v32/b3v32ask.c
  4. 9
      src/spicelib/devices/bsim3v32/b3v32check.c
  5. 79
      src/spicelib/devices/bsim3v32/b3v32ld.c
  6. 8
      src/spicelib/devices/bsim3v32/b3v32mask.c
  7. 8
      src/spicelib/devices/bsim3v32/b3v32mpar.c
  8. 4
      src/spicelib/devices/bsim3v32/b3v32par.c
  9. 8
      src/spicelib/devices/bsim3v32/b3v32set.c
  10. 99
      src/spicelib/devices/bsim3v32/b3v32temp.c
  11. 31
      src/spicelib/devices/bsim3v32/bsim3v32def.h
  12. 376
      src/spicelib/devices/devsup.c

14
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 { typedef struct SPICEdev {
IFdevice DEVpublic; IFdevice DEVpublic;

3
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( "nrs", BSIM3v32_NRS, IF_REAL , "Number of squares in source"),
IOP( "off", BSIM3v32_OFF, IF_FLAG , "Device is initially off"), IOP( "off", BSIM3v32_OFF, IF_FLAG , "Device is initially off"),
IOP( "nqsmod", BSIM3v32_NQSMOD, IF_INTEGER, "Non-quasi-static model selector"), 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( "delvto", BSIM3v32_DELVTO, IF_REAL , "Zero bias threshold voltage variation"),
IOP( "mulu0", BSIM3v32_MULU0, IF_REAL , "Low field mobility multiplier"), IOP( "mulu0", BSIM3v32_MULU0, IF_REAL , "Low field mobility multiplier"),
IP( "ic", BSIM3v32_IC, IF_REALVEC , "Vector of DS,GS,BS initial voltages"), 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( "mobmod", BSIM3v32_MOD_MOBMOD, IF_INTEGER, "Mobility model selector"),
IOP( "noimod", BSIM3v32_MOD_NOIMOD, IF_INTEGER, "Noise model selector"), IOP( "noimod", BSIM3v32_MOD_NOIMOD, IF_INTEGER, "Noise model selector"),
IOP( "acm", BSIM3v32_MOD_ACMMOD, IF_INTEGER, "Area calculation method 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( "paramchk", BSIM3v32_MOD_PARAMCHK, IF_INTEGER, "Model parameter checking selector"),
IOP( "binunit", BSIM3v32_MOD_BINUNIT, IF_INTEGER, "Bin unit selector"), IOP( "binunit", BSIM3v32_MOD_BINUNIT, IF_INTEGER, "Bin unit selector"),
IOP( "version", BSIM3v32_MOD_VERSION, IF_STRING, " parameter for model version"), 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( "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( "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( "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( "alpha0", BSIM3v32_MOD_ALPHA0, IF_REAL, "substrate current model parameter"),
IOP( "alpha1", BSIM3v32_MOD_ALPHA1, IF_REAL, "substrate current model parameter"), IOP( "alpha1", BSIM3v32_MOD_ALPHA1, IF_REAL, "substrate current model parameter"),

3
src/spicelib/devices/bsim3v32/b3v32ask.c

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

9
src/spicelib/devices/bsim3v32/b3v32check.c

@ -178,7 +178,7 @@ FILE *fplog;
printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM3v32pscbe2); printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM3v32pscbe2);
} }
/* acm model */
/* ACM model */
if (model->BSIM3v32acmMod == 0) { if (model->BSIM3v32acmMod == 0) {
if (model->BSIM3v32unitLengthSidewallJctCap > 0.0 || if (model->BSIM3v32unitLengthSidewallJctCap > 0.0 ||
model->BSIM3v32unitLengthGateSidewallJctCap > 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) if (pParam->BSIM3v32noff < 0.1)
{ fprintf(fplog, "Warning: Noff = %g is too small.\n", { fprintf(fplog, "Warning: Noff = %g is too small.\n",
pParam->BSIM3v32noff); pParam->BSIM3v32noff);

79
src/spicelib/devices/bsim3v32/b3v32ld.c

@ -363,30 +363,29 @@ for (; model != NULL; model = model->BSIM3v32nextModel)
} }
else 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) if (SourceSatCurrent <= 0.0)
{ here->BSIM3v32gbs = ckt->CKTgmin; { here->BSIM3v32gbs = ckt->CKTgmin;
@ -2453,6 +2452,8 @@ finished:
along gate side along gate side
*/ */
if (model->BSIM3v32acmMod == 0)
{
/* Added revision dependent code */ /* Added revision dependent code */
switch (model->BSIM3v32intVersion) { switch (model->BSIM3v32intVersion) {
case BSIM3v32V324: case BSIM3v32V324:
@ -2528,6 +2529,36 @@ finished:
* pParam->BSIM3v32weff; * 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; MJ = model->BSIM3v32bulkJctBotGradingCoeff;
MJSW = model->BSIM3v32bulkJctSideGradingCoeff; MJSW = model->BSIM3v32bulkJctSideGradingCoeff;

8
src/spicelib/devices/bsim3v32/b3v32mask.c

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

8
src/spicelib/devices/bsim3v32/b3v32mpar.c

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

4
src/spicelib/devices/bsim3v32/b3v32par.c

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

8
src/spicelib/devices/bsim3v32/b3v32set.c

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

99
src/spicelib/devices/bsim3v32/b3v32temp.c

@ -15,6 +15,7 @@
#include "bsim3v32def.h" #include "bsim3v32def.h"
#include "ngspice/const.h" #include "ngspice/const.h"
#include "ngspice/sperror.h" #include "ngspice/sperror.h"
#include "ngspice/devdefs.h"
#include "ngspice/suffix.h" #include "ngspice/suffix.h"
#define Kb 1.3806226e-23 #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 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 delTemp, Temp, TRatio, Inv_L, Inv_W, Inv_LW, Vtm0, Tnom;
double Nvtm, SourceSatCurrent, DrainSatCurrent; double Nvtm, SourceSatCurrent, DrainSatCurrent;
int Size_Not_Found;
int Size_Not_Found, error;
/* loop through all the BSIM3v32 device models */ /* loop through all the BSIM3v32 device models */
for (; model != NULL; model = model->BSIM3v32nextModel) for (; model != NULL; model = model->BSIM3v32nextModel)
@ -876,7 +877,7 @@ int Size_Not_Found;
* pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV * T0); * pParam->BSIM3v32weffCV * pParam->BSIM3v32leffCV * T0);
/* process source/drain series resistance */ /* process source/drain series resistance */
/* acm model */
/* ACM model */
if (model->BSIM3v32acmMod == 0) if (model->BSIM3v32acmMod == 0)
{ {
here->BSIM3v32drainConductance = model->BSIM3v32sheetResistance here->BSIM3v32drainConductance = model->BSIM3v32sheetResistance
@ -884,28 +885,30 @@ int Size_Not_Found;
here->BSIM3v32sourceConductance = model->BSIM3v32sheetResistance here->BSIM3v32sourceConductance = model->BSIM3v32sheetResistance
* here->BSIM3v32sourceSquares; * 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) if (here->BSIM3v32drainConductance > 0.0)
here->BSIM3v32drainConductance = 1.0 here->BSIM3v32drainConductance = 1.0
@ -947,33 +950,31 @@ int Size_Not_Found;
* model->BSIM3v32jctSidewallTempSatCurDensity; * 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)) if ((SourceSatCurrent > 0.0) && (model->BSIM3v32ijth > 0.0))

31
src/spicelib/devices/bsim3v32/bsim3v32def.h

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

376
src/spicelib/devices/devsup.c

@ -147,6 +147,382 @@ DEVfetlim(double vnew, double vold, double vto)
return(vnew); 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 /* Compute the MOS overlap capacitances as functions of the device
* terminal voltages * terminal voltages

Loading…
Cancel
Save