From 581376f1a4b69ab4f0eb5b076036fbd66a3c37fe Mon Sep 17 00:00:00 2001 From: dwarning Date: Tue, 27 Dec 2022 18:26:47 +0100 Subject: [PATCH] adaption trap tunnel currents for bsim3 --- src/spicelib/devices/bsim3/b3ld.c | 162 ++++++++++++++++++++------ src/spicelib/devices/bsim3/b3mask.c | 6 + src/spicelib/devices/bsim3/b3mpar.c | 9 ++ src/spicelib/devices/bsim3/b3temp.c | 65 ++++++----- src/spicelib/devices/bsim3/bsim3def.h | 24 ++-- 5 files changed, 192 insertions(+), 74 deletions(-) diff --git a/src/spicelib/devices/bsim3/b3ld.c b/src/spicelib/devices/bsim3/b3ld.c index 90351301b..dd86059af 100644 --- a/src/spicelib/devices/bsim3/b3ld.c +++ b/src/spicelib/devices/bsim3/b3ld.c @@ -31,6 +31,18 @@ #define DELTA_2 0.02 #define DELTA_3 0.02 #define DELTA_4 0.02 +#define DEXP(A,B,C) { \ + if (A > EXP_THRESHOLD) { \ + B = MAX_EXP*(1.0+(A)-EXP_THRESHOLD); \ + C = MAX_EXP; \ + } else if (A < -EXP_THRESHOLD) { \ + B = MIN_EXP; \ + C = 0; \ + } else { \ + B = exp(A); \ + C = B; \ + } \ + } #ifdef USE_OMP int BSIM3LoadOMP(BSIM3instance *here, CKTcircuit *ckt); @@ -480,43 +492,127 @@ for (; model != NULL; model = BSIM3nextModel(model)) } } - /* trap-assisted tunneling current enhancement */ - if ((model->BSIM3acmMod == 12) && (model->BSIM3bsim4diodeGiven)) - { - double t1 = 0.0; - if (model->BSIM3jtss > 0.0) - { - t1 = exp(-vbs/(model->BSIM3tNjts*model->BSIM3vtm)*(model->BSIM3vtss/(model->BSIM3vtss-vbs)))-1; - here->BSIM3cbs -= here->BSIM3sourceArea * model->BSIM3tJtss * t1; - } - if (model->BSIM3jtssws > 0.0) - { - t1 = exp(-vbs/(model->BSIM3tNjtssw*model->BSIM3vtm)*(model->BSIM3vtssws/(model->BSIM3vtssws-vbs)))-1; - here->BSIM3cbs -= here->BSIM3sourcePerimeter * model->BSIM3tJtssws * t1; - } - if (model->BSIM3jtsswgs > 0.0) - { - t1 = exp(-vbs/(model->BSIM3tNjtsswg*model->BSIM3vtm)*(model->BSIM3vtsswgs/(model->BSIM3vtsswgs-vbs)))-1; - here->BSIM3cbs -= pParam->BSIM3weff * model->BSIM3tJtsswgs * t1; - } + /* trap-assisted tunneling current enhancement */ + if ((model->BSIM3acmMod == 12) && (model->BSIM3bsim4diodeGiven)) + { + double dT4_dVb, dT5_dVb, dT6_dVb; + double Nvtmrss = model->BSIM3vtm * model->BSIM3njtstemp; + double Nvtmrsd = model->BSIM3vtm * model->BSIM3njtsdtemp; + double Nvtmrssws = model->BSIM3vtm * model->BSIM3njtsswtemp; + double Nvtmrsswd = model->BSIM3vtm * model->BSIM3njtsswdtemp; + double Nvtmrsswgs = model->BSIM3vtm * model->BSIM3njtsswgtemp; + double Nvtmrsswgd = model->BSIM3vtm * model->BSIM3njtsswgdtemp; - if (model->BSIM3jtsd > 0.0) - { - t1 = exp(-vbd/(model->BSIM3tNjtsd*model->BSIM3vtm)*(model->BSIM3vtsd/(model->BSIM3vtsd-vbd)))-1; - here->BSIM3cbd -= here->BSIM3drainArea * model->BSIM3tJtsd * t1; - } - if (model->BSIM3jtsswd > 0.0) - { - t1 = exp(-vbd/(model->BSIM3tNjtsswd*model->BSIM3vtm)*(model->BSIM3vtsswd/(model->BSIM3vtsswd-vbd)))-1; - here->BSIM3cbd -= here->BSIM3drainPerimeter * model->BSIM3tJtsswd * t1; - } - if (model->BSIM3jtsswgd > 0.0) - { - t1 = exp(-vbd/(model->BSIM3tNjtsswgd*model->BSIM3vtm)*(model->BSIM3vtsswgd/(model->BSIM3vtsswgd-vbd)))-1; - here->BSIM3cbd -= pParam->BSIM3weff * model->BSIM3tJtsswgd * t1; + if (model->BSIM3jtss > 0.0) + { + if ((model->BSIM3vtss - vbs) < (model->BSIM3vtss * 1e-3)) + { T9 = 1.0e3; + T0 = - vbs / Nvtmrss * T9; + DEXP(T0, T1, T10); + dT1_dVb = T10 / Nvtmrss * T9; + } else { + T9 = 1.0 / (model->BSIM3vtss - vbs); + T0 = -vbs / Nvtmrss * model->BSIM3vtss * T9; + dT0_dVb = model->BSIM3vtss / Nvtmrss * (T9 + vbs * T9 * T9) ; + DEXP(T0, T1, T10); + dT1_dVb = T10 * dT0_dVb; } + here->BSIM3gbs += here->BSIM3sourceArea * model->BSIM3jtsstemp * dT1_dVb; + here->BSIM3cbs -= here->BSIM3sourceArea * model->BSIM3jtsstemp * (T1 - 1.0); } + if (model->BSIM3jtssws > 0.0) + { + if ((model->BSIM3vtsd - vbd) < (model->BSIM3vtsd * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbd / Nvtmrsd * T9; + DEXP(T0, T2, T10); + dT2_dVb = T10 / Nvtmrsd * T9; + } else { + T9 = 1.0 / (model->BSIM3vtsd - vbd); + T0 = -vbd / Nvtmrsd * model->BSIM3vtsd * T9; + dT0_dVb = model->BSIM3vtsd / Nvtmrsd * (T9 + vbd * T9 * T9) ; + DEXP(T0, T2, T10); + dT2_dVb = T10 * dT0_dVb; + } + here->BSIM3gbs += here->BSIM3sourcePerimeter * model->BSIM3jtsswstemp * dT2_dVb; + here->BSIM3cbs -= here->BSIM3sourcePerimeter * model->BSIM3jtsswstemp * (T2 - 1.0); + } + + if (model->BSIM3jtsswgs > 0.0) + { + if ((model->BSIM3vtssws - vbs) < (model->BSIM3vtssws * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbs / Nvtmrssws * T9; + DEXP(T0, T3, T10); + dT3_dVb = T10 / Nvtmrssws * T9; + } else { + T9 = 1.0 / (model->BSIM3vtssws - vbs); + T0 = -vbs / Nvtmrssws * model->BSIM3vtssws * T9; + dT0_dVb = model->BSIM3vtssws / Nvtmrssws * (T9 + vbs * T9 * T9) ; + DEXP(T0, T3, T10); + dT3_dVb = T10 * dT0_dVb; + } + here->BSIM3gbs += pParam->BSIM3weff * model->BSIM3jtsswgstemp * dT3_dVb; + here->BSIM3cbs -= pParam->BSIM3weff * model->BSIM3jtsswgstemp * (T3 - 1.0); + } + + if (model->BSIM3jtsd > 0.0) + { + if ((model->BSIM3vtsswd - vbd) < (model->BSIM3vtsswd * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbd / Nvtmrsswd * T9; + DEXP(T0, T4, T10); + dT4_dVb = T10 / Nvtmrsswd * T9; + } else { + T9 = 1.0 / (model->BSIM3vtsswd - vbd); + T0 = -vbd / Nvtmrsswd * model->BSIM3vtsswd * T9; + dT0_dVb = model->BSIM3vtsswd / Nvtmrsswd * (T9 + vbd * T9 * T9) ; + DEXP(T0, T4, T10); + dT4_dVb = T10 * dT0_dVb; + } + here->BSIM3gbd += here->BSIM3drainArea * model->BSIM3jtsdtemp * dT4_dVb; + here->BSIM3cbd -= here->BSIM3drainArea * model->BSIM3jtsdtemp * (T4 - 1.0); + } + + if (model->BSIM3jtsswd > 0.0) + { + if ((model->BSIM3vtsswgs - vbs) < (model->BSIM3vtsswgs * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbs / Nvtmrsswgs * T9; + DEXP(T0, T5, T10); + dT5_dVb = T10 / Nvtmrsswgs * T9; + } else { + T9 = 1.0 / (model->BSIM3vtsswgs - vbs); + T0 = -vbs / Nvtmrsswgs * model->BSIM3vtsswgs * T9; + dT0_dVb = model->BSIM3vtsswgs / Nvtmrsswgs * (T9 + vbs * T9 * T9) ; + DEXP(T0, T5, T10); + dT5_dVb = T10 * dT0_dVb; + } + here->BSIM3gbd += here->BSIM3drainPerimeter * model->BSIM3jtsswdtemp * dT5_dVb; + here->BSIM3cbd -= here->BSIM3drainPerimeter * model->BSIM3jtsswdtemp * (T5 - 1.0); + } + + if (model->BSIM3jtsswgd > 0.0) + { + if ((model->BSIM3vtsswgd - vbd) < (model->BSIM3vtsswgd * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbd / Nvtmrsswgd * T9; + DEXP(T0, T6, T10); + dT6_dVb = T10 / Nvtmrsswgd * T9; + } else { + T9 = 1.0 / (model->BSIM3vtsswgd - vbd); + T0 = -vbd / Nvtmrsswgd * model->BSIM3vtsswgd * T9; + dT0_dVb = model->BSIM3vtsswgd / Nvtmrsswgd * (T9 + vbd * T9 * T9) ; + DEXP(T0, T6, T10); + dT6_dVb = T10 * dT0_dVb; + } + here->BSIM3gbd += pParam->BSIM3weff * model->BSIM3jtsswgdtemp * dT6_dVb; + here->BSIM3cbd -= pParam->BSIM3weff * model->BSIM3jtsswgdtemp * (T6 - 1.0); + } + + } + /* End of diode DC model */ if (vds >= 0.0) diff --git a/src/spicelib/devices/bsim3/b3mask.c b/src/spicelib/devices/bsim3/b3mask.c index 5f289d9f6..7a38315eb 100644 --- a/src/spicelib/devices/bsim3/b3mask.c +++ b/src/spicelib/devices/bsim3/b3mask.c @@ -1392,6 +1392,12 @@ IFvalue *value) case BSIM3_MOD_XTSSWD: value->rValue = model->BSIM3xtsswd; return(OK); + case BSIM3_MOD_XTSSWGS: + value->rValue = model->BSIM3xtsswgs; + return(OK); + case BSIM3_MOD_XTSSWGD: + value->rValue = model->BSIM3xtsswgd; + return(OK); case BSIM3_MOD_TNJTS: value->rValue = model->BSIM3tnjts; diff --git a/src/spicelib/devices/bsim3/b3mpar.c b/src/spicelib/devices/bsim3/b3mpar.c index 55acf896a..ccdce00a9 100644 --- a/src/spicelib/devices/bsim3/b3mpar.c +++ b/src/spicelib/devices/bsim3/b3mpar.c @@ -1861,6 +1861,15 @@ GENmodel *inMod) mod->BSIM3xtsswd = value->rValue; mod->BSIM3xtsswdGiven = TRUE; break; + case BSIM3_MOD_XTSSWGS: + mod->BSIM3xtsswgs = value->rValue; + mod->BSIM3xtsswgsGiven = TRUE; + break; + case BSIM3_MOD_XTSSWGD: + mod->BSIM3xtsswgd = value->rValue; + mod->BSIM3xtsswgdGiven = TRUE; + break; + case BSIM3_MOD_TNJTS: mod->BSIM3tnjts = value->rValue; mod->BSIM3tnjtsGiven = TRUE; diff --git a/src/spicelib/devices/bsim3/b3temp.c b/src/spicelib/devices/bsim3/b3temp.c index 8a93839e1..9093c69f9 100644 --- a/src/spicelib/devices/bsim3/b3temp.c +++ b/src/spicelib/devices/bsim3/b3temp.c @@ -28,6 +28,15 @@ #define MIN_EXP 1.713908431e-15 #define EXP_THRESHOLD 34.0 #define Charge_q 1.60219e-19 +#define DEXP(A,B) { \ + if (A > EXP_THRESHOLD) { \ + B = MAX_EXP*(1.0+(A)-EXP_THRESHOLD); \ + } else if (A < -EXP_THRESHOLD) { \ + B = MIN_EXP; \ + } else { \ + B = exp(A); \ + } \ + } /* ARGSUSED */ int @@ -38,7 +47,7 @@ CKTcircuit *ckt) BSIM3model *model = (BSIM3model*) inModel; BSIM3instance *here; struct bsim3SizeDependParam *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, T6, T7, T9, Ldrn, Wdrn; double delTemp, Temp, TRatio, Inv_L, Inv_W, Inv_LW, Vtm0, Tnom; double Nvtm, SourceSatCurrent, DrainSatCurrent; int Size_Not_Found, error; @@ -151,35 +160,33 @@ int Size_Not_Found, error; /* trap-assisted tunneling current enhancement */ if ((model->BSIM3acmMod == 12) && (model->BSIM3bsim4diodeGiven)) { - model->BSIM3tJtss = model->BSIM3jtss - * exp(model->BSIM3xtss * Eg0 / ((model->BSIM3vtm * TRatio) - 1)); + T0 = (TRatio - 1.0); + model->BSIM3njtstemp = model->BSIM3njts * (1.0 + model->BSIM3tnjts * T0); + model->BSIM3njtsdtemp = model->BSIM3njtsd * (1.0 + model->BSIM3tnjtsd * T0); + model->BSIM3njtsswtemp = model->BSIM3njtssw * (1.0 + model->BSIM3tnjtssw * T0); + model->BSIM3njtsswdtemp = model->BSIM3njtsswd * (1.0 + model->BSIM3tnjtsswd * T0); + model->BSIM3njtsswgtemp = model->BSIM3njtsswg * (1.0 + model->BSIM3tnjtsswg * T0); + model->BSIM3njtsswgdtemp = model->BSIM3njtsswgd * (1.0 + model->BSIM3tnjtsswgd * T0); + T7 = Eg0 / model->BSIM3vtm * T0; + T9 = model->BSIM3xtss * T7; + DEXP(T9, T1); + T9 = model->BSIM3xtsd * T7; + DEXP(T9, T2); + T9 = model->BSIM3xtssws * T7; + DEXP(T9, T3); + T9 = model->BSIM3xtsswd * T7; + DEXP(T9, T4); + T9 = model->BSIM3xtsswgs * T7; + DEXP(T9, T5); + T9 = model->BSIM3xtsswgd * T7; + DEXP(T9, T6); + model->BSIM3jtsstemp = T1 * model->BSIM3jtss; + model->BSIM3jtsdtemp = T2 * model->BSIM3jtsd; + model->BSIM3jtsswstemp = T3 * model->BSIM3jtssws; + model->BSIM3jtsswdtemp = T4 * model->BSIM3jtsswd; + model->BSIM3jtsswgstemp = T5 * model->BSIM3jtsswgs; + model->BSIM3jtsswgdtemp = T6 * model->BSIM3jtsswgd; - model->BSIM3tJtssws = model->BSIM3jtssws - * exp(model->BSIM3xtssws * Eg0 / ((model->BSIM3vtm * TRatio) - 1)); - - model->BSIM3tJtsswgs = model->BSIM3jtsswgs - * exp(model->BSIM3xtsswgs * Eg0 / ((model->BSIM3vtm * TRatio) - 1)); - - model->BSIM3tJtsd = model->BSIM3jtsd - * exp(model->BSIM3xtsd * Eg0 / ((model->BSIM3vtm * TRatio) - 1)); - - model->BSIM3tJtsswd = model->BSIM3jtsswd - * exp(model->BSIM3xtsswd * Eg0 / ((model->BSIM3vtm * TRatio) - 1)); - - model->BSIM3tJtsswgd = model->BSIM3jtsswgd - * exp(model->BSIM3xtsswgd * Eg0 / ((model->BSIM3vtm * TRatio) - 1)); - - model->BSIM3tNjts = model->BSIM3njts * (1 + model->BSIM3tnjts * (TRatio - 1)); - - model->BSIM3tNjtsd = model->BSIM3njtsd * (1 + model->BSIM3tnjtsd * (TRatio - 1)); - - model->BSIM3tNjtssw = model->BSIM3njtssw * (1 + model->BSIM3tnjtssw * (TRatio - 1)); - - model->BSIM3tNjtsswd = model->BSIM3njtsswd * (1 + model->BSIM3tnjtsswd * (TRatio - 1)); - - model->BSIM3tNjtsswg = model->BSIM3njtsswg * (1 + model->BSIM3tnjtsswg * (TRatio - 1)); - - model->BSIM3tNjtsswgd = model->BSIM3njtsswgd * (1 + model->BSIM3tnjtsswgd * (TRatio - 1)); } /* loop through all the instances of the model */ diff --git a/src/spicelib/devices/bsim3/bsim3def.h b/src/spicelib/devices/bsim3/bsim3def.h index 61030f76d..34403055e 100644 --- a/src/spicelib/devices/bsim3/bsim3def.h +++ b/src/spicelib/devices/bsim3/bsim3def.h @@ -918,18 +918,18 @@ typedef struct sBSIM3model double BSIM3tnjtsswd; double BSIM3tnjtsswgd; - double BSIM3tJtss; - double BSIM3tJtsd; - double BSIM3tJtssws; - double BSIM3tJtsswd; - double BSIM3tJtsswgs; - double BSIM3tJtsswgd; - double BSIM3tNjts; - double BSIM3tNjtssw; - double BSIM3tNjtsswg; - double BSIM3tNjtsd; - double BSIM3tNjtsswd; - double BSIM3tNjtsswgd; + double BSIM3njtstemp; + double BSIM3njtsswtemp; + double BSIM3njtsswgtemp; + double BSIM3njtsdtemp; + double BSIM3njtsswdtemp; + double BSIM3njtsswgdtemp; + double BSIM3jtsstemp; + double BSIM3jtsdtemp; + double BSIM3jtsswstemp; + double BSIM3jtsswdtemp; + double BSIM3jtsswgstemp; + double BSIM3jtsswgdtemp; struct bsim3SizeDependParam *pSizeDependParamKnot;