b3temp.c
来自「ngspice又一个电子CAD仿真软件代码.功能更全」· C语言 代码 · 共 1,044 行 · 第 1/3 页
C
1,044 行
/**** BSIM3v3.2.4, Released by Xuemei Xi 12/21/2001 ****//********** * Copyright 2001 Regents of the University of California. All rights reserved. * File: b3temp.c of BSIM3v3.2.4 * Author: 1995 Min-Chie Jeng and Mansun Chan. * Author: 1997-1999 Weidong Liu. * Author: 2001 Xuemei Xi * Modified by Paolo Nenzi 2002 and Dietmar Warning 2003 **********/#include "ngspice.h"#include "smpdefs.h"#include "cktdefs.h"#include "bsim3def.h"#include "const.h"#include "sperror.h"#include "suffix.h"#define Kb 1.3806226e-23#define KboQ 8.617087e-5 /* Kb / q where q = 1.60219e-19 */#define EPSOX 3.453133e-11#define EPSSI 1.03594e-10#define PI 3.141592654#define MAX_EXP 5.834617425e14#define MIN_EXP 1.713908431e-15#define EXP_THRESHOLD 34.0#define Charge_q 1.60219e-19/* ARGSUSED */intBSIM3temp (GENmodel *inModel, CKTcircuit *ckt){BSIM3model *model = (BSIM3model*) inModel;BSIM3instance *here;struct bsim3SizeDependParam *pSizeDependParamKnot, *pLastKnot, *pParam;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; /* loop through all the BSIM3 device models */ for (; model != NULL; model = model->BSIM3nextModel) { Temp = ckt->CKTtemp; if (model->BSIM3bulkJctPotential < 0.1) { model->BSIM3bulkJctPotential = 0.1; fprintf(stderr, "Given pb is less than 0.1. Pb is set to 0.1.\n"); } if (model->BSIM3sidewallJctPotential < 0.1) { model->BSIM3sidewallJctPotential = 0.1; fprintf(stderr, "Given pbsw is less than 0.1. Pbsw is set to 0.1.\n"); } if (model->BSIM3GatesidewallJctPotential < 0.1) { model->BSIM3GatesidewallJctPotential = 0.1; fprintf(stderr, "Given pbswg is less than 0.1. Pbswg is set to 0.1.\n"); } /* va: was memory leakage - free old node, (or better use again?) */ FREE(model->pSizeDependParamKnot); model->pSizeDependParamKnot = NULL; pLastKnot = NULL; Tnom = model->BSIM3tnom; TRatio = Temp / Tnom; model->BSIM3vcrit = CONSTvt0 * log(CONSTvt0 / (CONSTroot2 * 1.0e-14)); model->BSIM3factor1 = sqrt(EPSSI / EPSOX * model->BSIM3tox); Vtm0 = KboQ * Tnom; Eg0 = 1.16 - 7.02e-4 * Tnom * Tnom / (Tnom + 1108.0); ni = 1.45e10 * (Tnom / 300.15) * sqrt(Tnom / 300.15) * exp(21.5565981 - Eg0 / (2.0 * Vtm0)); model->BSIM3vtm = KboQ * Temp; Eg = 1.16 - 7.02e-4 * Temp * Temp / (Temp + 1108.0); if (Temp != Tnom) { T0 = Eg0 / Vtm0 - Eg / model->BSIM3vtm + model->BSIM3jctTempExponent * log(Temp / Tnom); T1 = exp(T0 / model->BSIM3jctEmissionCoeff); model->BSIM3jctTempSatCurDensity = model->BSIM3jctSatCurDensity * T1; model->BSIM3jctSidewallTempSatCurDensity = model->BSIM3jctSidewallSatCurDensity * T1; } else { model->BSIM3jctTempSatCurDensity = model->BSIM3jctSatCurDensity; model->BSIM3jctSidewallTempSatCurDensity = model->BSIM3jctSidewallSatCurDensity; } if (model->BSIM3jctTempSatCurDensity < 0.0) model->BSIM3jctTempSatCurDensity = 0.0; if (model->BSIM3jctSidewallTempSatCurDensity < 0.0) model->BSIM3jctSidewallTempSatCurDensity = 0.0; /* Temperature dependence of D/B and S/B diode capacitance begins */ delTemp = ckt->CKTtemp - model->BSIM3tnom; T0 = model->BSIM3tcj * delTemp; if (T0 >= -1.0) { /* Added revision dependent code */ switch (model->BSIM3intVersion) { case BSIM3V324: case BSIM3V323: model->BSIM3unitAreaTempJctCap = model->BSIM3unitAreaJctCap * (1.0 + T0); break; case BSIM3V322: case BSIM3V32: default: model->BSIM3unitAreaJctCap *= 1.0 + T0; } } else if (model->BSIM3unitAreaJctCap > 0.0) { /* Added revision dependent code */ switch (model->BSIM3intVersion) { case BSIM3V324: case BSIM3V323: model->BSIM3unitAreaTempJctCap = 0.0; break; case BSIM3V322: case BSIM3V32: default: model->BSIM3unitAreaJctCap = 0.0; } fprintf(stderr, "Temperature effect has caused cj to be negative. Cj is clamped to zero.\n"); } T0 = model->BSIM3tcjsw * delTemp; if (T0 >= -1.0) { /* Added revision dependent code */ switch (model->BSIM3intVersion) { case BSIM3V324: case BSIM3V323: model->BSIM3unitLengthSidewallTempJctCap = model->BSIM3unitLengthSidewallJctCap * (1.0 + T0); break; case BSIM3V322: case BSIM3V32: default: model->BSIM3unitLengthSidewallJctCap *= 1.0 + T0; } } else if (model->BSIM3unitLengthSidewallJctCap > 0.0) { /* Added revision dependent code */ switch (model->BSIM3intVersion) { case BSIM3V324: case BSIM3V323: model->BSIM3unitLengthSidewallTempJctCap = 0.0; break; case BSIM3V322: case BSIM3V32: default: model->BSIM3unitLengthSidewallJctCap = 0.0; } fprintf(stderr, "Temperature effect has caused cjsw to be negative. Cjsw is clamped to zero.\n"); } T0 = model->BSIM3tcjswg * delTemp; if (T0 >= -1.0) { /* Added revision dependent code */ switch (model->BSIM3intVersion) { case BSIM3V324: case BSIM3V323: model->BSIM3unitLengthGateSidewallTempJctCap = model->BSIM3unitLengthGateSidewallJctCap * (1.0 + T0); break; case BSIM3V322: case BSIM3V32: default: model->BSIM3unitLengthGateSidewallJctCap *= 1.0 + T0; } } else if (model->BSIM3unitLengthGateSidewallJctCap > 0.0) { /* Added revision dependent code */ switch (model->BSIM3intVersion) { case BSIM3V324: case BSIM3V323: model->BSIM3unitLengthGateSidewallTempJctCap = 0.0; break; case BSIM3V322: case BSIM3V32: default: model->BSIM3unitLengthGateSidewallJctCap = 0.0; } fprintf(stderr, "Temperature effect has caused cjswg to be negative. Cjswg is clamped to zero.\n"); } model->BSIM3PhiB = model->BSIM3bulkJctPotential - model->BSIM3tpb * delTemp; if (model->BSIM3PhiB < 0.01) { model->BSIM3PhiB = 0.01; fprintf(stderr, "Temperature effect has caused pb to be less than 0.01. Pb is clamped to 0.01.\n"); } model->BSIM3PhiBSW = model->BSIM3sidewallJctPotential - model->BSIM3tpbsw * delTemp; if (model->BSIM3PhiBSW <= 0.01) { model->BSIM3PhiBSW = 0.01; fprintf(stderr, "Temperature effect has caused pbsw to be less than 0.01. Pbsw is clamped to 0.01.\n"); } model->BSIM3PhiBSWG = model->BSIM3GatesidewallJctPotential - model->BSIM3tpbswg * delTemp; if (model->BSIM3PhiBSWG <= 0.01) { model->BSIM3PhiBSWG = 0.01; fprintf(stderr, "Temperature effect has caused pbswg to be less than 0.01. Pbswg is clamped to 0.01.\n"); } /* End of junction capacitance */ /* loop through all the instances of the model */ /* MCJ: Length and Width not initialized */ for (here = model->BSIM3instances; here != NULL; here = here->BSIM3nextInstance) { if (here->BSIM3owner != ARCHme) continue; pSizeDependParamKnot = model->pSizeDependParamKnot; Size_Not_Found = 1; while ((pSizeDependParamKnot != NULL) && Size_Not_Found) { if ((here->BSIM3l == pSizeDependParamKnot->Length) && (here->BSIM3w == pSizeDependParamKnot->Width)) { Size_Not_Found = 0; here->pParam = pSizeDependParamKnot; if (model->BSIM3intVersion > BSIM3V322) { pParam = here->pParam; /*bug-fix */ } } else { pLastKnot = pSizeDependParamKnot; pSizeDependParamKnot = pSizeDependParamKnot->pNext; } } if (Size_Not_Found) { pParam = (struct bsim3SizeDependParam *)malloc( sizeof(struct bsim3SizeDependParam)); if (pLastKnot == NULL) model->pSizeDependParamKnot = pParam; else pLastKnot->pNext = pParam; pParam->pNext = NULL; here->pParam = pParam; Ldrn = here->BSIM3l; Wdrn = here->BSIM3w; pParam->Length = Ldrn; pParam->Width = Wdrn; T0 = pow(Ldrn, model->BSIM3Lln); T1 = pow(Wdrn, model->BSIM3Lwn); tmp1 = model->BSIM3Ll / T0 + model->BSIM3Lw / T1 + model->BSIM3Lwl / (T0 * T1); pParam->BSIM3dl = model->BSIM3Lint + tmp1; tmp2 = model->BSIM3Llc / T0 + model->BSIM3Lwc / T1 + model->BSIM3Lwlc / (T0 * T1); pParam->BSIM3dlc = model->BSIM3dlc + tmp2; T2 = pow(Ldrn, model->BSIM3Wln); T3 = pow(Wdrn, model->BSIM3Wwn); tmp1 = model->BSIM3Wl / T2 + model->BSIM3Ww / T3 + model->BSIM3Wwl / (T2 * T3); pParam->BSIM3dw = model->BSIM3Wint + tmp1; tmp2 = model->BSIM3Wlc / T2 + model->BSIM3Wwc / T3 + model->BSIM3Wwlc / (T2 * T3); pParam->BSIM3dwc = model->BSIM3dwc + tmp2; pParam->BSIM3leff = here->BSIM3l + model->BSIM3xl - 2.0 * pParam->BSIM3dl; if (pParam->BSIM3leff <= 0.0) { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; (*(SPfrontEnd->IFerror))(ERR_FATAL, "BSIM3: mosfet %s, model %s: Effective channel length <= 0", namarray); return(E_BADPARM); } pParam->BSIM3weff = here->BSIM3w + model->BSIM3xw - 2.0 * pParam->BSIM3dw; if (pParam->BSIM3weff <= 0.0) { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; (*(SPfrontEnd->IFerror))(ERR_FATAL, "BSIM3: mosfet %s, model %s: Effective channel width <= 0", namarray); return(E_BADPARM); } pParam->BSIM3leffCV = here->BSIM3l + model->BSIM3xl - 2.0 * pParam->BSIM3dlc; if (pParam->BSIM3leffCV <= 0.0) { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; (*(SPfrontEnd->IFerror))(ERR_FATAL, "BSIM3: mosfet %s, model %s: Effective channel length for C-V <= 0", namarray); return(E_BADPARM); } pParam->BSIM3weffCV = here->BSIM3w + model->BSIM3xw - 2.0 * pParam->BSIM3dwc; if (pParam->BSIM3weffCV <= 0.0) { IFuid namarray[2]; namarray[0] = model->BSIM3modName; namarray[1] = here->BSIM3name; (*(SPfrontEnd->IFerror))(ERR_FATAL, "BSIM3: mosfet %s, model %s: Effective channel width for C-V <= 0", namarray); return(E_BADPARM); } if (model->BSIM3binUnit == 1) { Inv_L = 1.0e-6 / pParam->BSIM3leff; Inv_W = 1.0e-6 / pParam->BSIM3weff; Inv_LW = 1.0e-12 / (pParam->BSIM3leff * pParam->BSIM3weff); } else { Inv_L = 1.0 / pParam->BSIM3leff; Inv_W = 1.0 / pParam->BSIM3weff; Inv_LW = 1.0 / (pParam->BSIM3leff * pParam->BSIM3weff); } pParam->BSIM3cdsc = model->BSIM3cdsc + model->BSIM3lcdsc * Inv_L + model->BSIM3wcdsc * Inv_W + model->BSIM3pcdsc * Inv_LW; pParam->BSIM3cdscb = model->BSIM3cdscb + model->BSIM3lcdscb * Inv_L + model->BSIM3wcdscb * Inv_W + model->BSIM3pcdscb * Inv_LW; pParam->BSIM3cdscd = model->BSIM3cdscd + model->BSIM3lcdscd * Inv_L + model->BSIM3wcdscd * Inv_W + model->BSIM3pcdscd * Inv_LW; pParam->BSIM3cit = model->BSIM3cit + model->BSIM3lcit * Inv_L + model->BSIM3wcit * Inv_W + model->BSIM3pcit * Inv_LW; pParam->BSIM3nfactor = model->BSIM3nfactor + model->BSIM3lnfactor * Inv_L + model->BSIM3wnfactor * Inv_W + model->BSIM3pnfactor * Inv_LW; pParam->BSIM3xj = model->BSIM3xj
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?