⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mobil.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
字号:
/**********Copyright 1991 Regents of the University of California.  All rights reserved.Author:	1992 David A. Gates, U. C. Berkeley CAD Group**********/#include <math.h>#include "numglobs.h"#include "numconst.h"#include "numenum.h"#include "nummacs.h"#include "material.h"void MOBdefaults( info, carrier, type, concmodel, fieldmodel )MaterialInfo *info;int carrier, type, concmodel, fieldmodel;{  switch (concmodel) {    case CT:       info->concModel = CT;      if (carrier == ELEC) {	info->muMax[ELEC][type] = CT_MUMAX_N;	info->muMin[ELEC][type] = CT_MUMIN_N;	info->ntRef[ELEC][type] = CT_NTREF_N;	info->ntExp[ELEC][type] = CT_NTEXP_N;      } else {	info->muMax[HOLE][type] = CT_MUMAX_P;	info->muMin[HOLE][type] = CT_MUMIN_P;	info->ntRef[HOLE][type] = CT_NTREF_P;	info->ntExp[HOLE][type] = CT_NTEXP_P;      }      break;    case AR:       info->concModel = AR;      if (carrier == ELEC) {	info->muMax[ELEC][type] = AR_MUMAX_N;	info->muMin[ELEC][type] = AR_MUMIN_N;	info->ntRef[ELEC][type] = AR_NTREF_N;	info->ntExp[ELEC][type] = AR_NTEXP_N;      } else {	info->muMax[HOLE][type] = AR_MUMAX_P;	info->muMin[HOLE][type] = AR_MUMIN_P;	info->ntRef[HOLE][type] = AR_NTREF_P;	info->ntExp[HOLE][type] = AR_NTEXP_P;      }      break;    case UF:       info->concModel = UF;      if (carrier == ELEC) {	info->muMax[ELEC][type] = UF_MUMAX_N;	info->muMin[ELEC][type] = UF_MUMIN_N;	info->ntRef[ELEC][type] = UF_NTREF_N;	info->ntExp[ELEC][type] = UF_NTEXP_N;      } else {	info->muMax[HOLE][type] = UF_MUMAX_P;	info->muMin[HOLE][type] = UF_MUMIN_P;	info->ntRef[HOLE][type] = UF_NTREF_P;	info->ntExp[HOLE][type] = UF_NTEXP_P;      }      break;    case GA:      info->concModel = GA;      if (carrier == ELEC) {	info->muMax[ELEC][type] = GA_MUMAX_N;	info->muMin[ELEC][type] = GA_MUMIN_N;	info->ntRef[ELEC][type] = GA_NTREF_N;	info->ntExp[ELEC][type] = GA_NTEXP_N;      } else {	info->muMax[HOLE][type] = GA_MUMAX_P;	info->muMin[HOLE][type] = GA_MUMIN_P;	info->ntRef[HOLE][type] = GA_NTREF_P;	info->ntExp[HOLE][type] = GA_NTEXP_P;      }      break;    case SG:    default:      info->concModel = SG;      if (carrier == ELEC) {	info->muMax[ELEC][type] = SG_MUMAX_N;	info->muMin[ELEC][type] = SG_MUMIN_N;	info->ntRef[ELEC][type] = SG_NTREF_N;	info->ntExp[ELEC][type] = SG_NTEXP_N;      } else {	info->muMax[HOLE][type] = SG_MUMAX_P;	info->muMin[HOLE][type] = SG_MUMIN_P;	info->ntRef[HOLE][type] = SG_NTREF_P;	info->ntExp[HOLE][type] = SG_NTEXP_P;      }      break;  }  if (type == MAJOR) {    switch (fieldmodel) {      case CT: 	info->fieldModel = CT;	if (carrier == ELEC) {	  info->vSat[ELEC] = CT_VSAT_N;	} else {	  info->vSat[HOLE] = CT_VSAT_P;	}	break;      case AR:       case UF:	info->fieldModel = AR;	if (carrier == ELEC) {	  info->vSat[ELEC] = AR_VSAT_N;	} else {	  info->vSat[HOLE] = AR_VSAT_P;	}	break;      case GA:	info->fieldModel = GA;	if (carrier == ELEC) {	  info->vSat[ELEC] = GA_VSAT_N;	  info->vWarm[ELEC] = GA_VWARM_N;	} else {	  info->vSat[HOLE] = GA_VSAT_P;	  info->vWarm[HOLE] = GA_VWARM_P;	}	break;      case SG:      default:	info->fieldModel = SG;	if (carrier == ELEC) {	  info->vSat[ELEC] = SG_VSAT_N;	  info->vWarm[ELEC] = SG_VWARM_N;	} else {	  info->vSat[HOLE] = SG_VSAT_P;	  info->vWarm[HOLE] = SG_VWARM_P;	}	break;    }  }}MOBtempDep (info, temp)MaterialInfo *info;double  temp;{  double  relTemp = temp / 300.0;  double  factor, muMin, muMax, mu0;  /* Modify if necessary. */  if (TempDepMobility)  {  /* Do concentration dependence parameters */    muMin = info->muMin[ELEC][MAJOR];    mu0 = info->muMax[ELEC][MAJOR] - muMin;    factor = pow(relTemp, TD_EXPMUMIN_N);    muMin *= factor;    factor = pow(relTemp, TD_EXPMUMAX_N);    mu0 *= factor;    info->muMin[ELEC][MAJOR] = muMin;    info->muMax[ELEC][MAJOR] = mu0 + muMin;    factor = pow(relTemp, TD_EXPNTREF_N);    info->ntRef[ELEC][MAJOR] *= factor;    factor = pow(relTemp, TD_EXPNTEXP_N);    info->ntExp[ELEC][MAJOR] *= factor;    muMin = info->muMin[ELEC][MINOR];    mu0 = info->muMax[ELEC][MINOR] - muMin;    factor = pow(relTemp, TD_EXPMUMIN_N);    muMin *= factor;    factor = pow(relTemp, TD_EXPMUMAX_N);    mu0 *= factor;    info->muMin[ELEC][MINOR] = muMin;    info->muMax[ELEC][MINOR] = mu0 + muMin;    factor = pow(relTemp, TD_EXPNTREF_N);    info->ntRef[ELEC][MINOR] *= factor;    factor = pow(relTemp, TD_EXPNTEXP_N);    info->ntExp[ELEC][MINOR] *= factor;    muMin = info->muMin[HOLE][MAJOR];    mu0 = info->muMax[HOLE][MAJOR] - muMin;    factor = pow(relTemp, TD_EXPMUMIN_P);    muMin *= factor;    factor = pow(relTemp, TD_EXPMUMAX_P);    mu0 *= factor;    info->muMin[HOLE][MAJOR] = muMin;    info->muMax[HOLE][MAJOR] = mu0 + muMin;    factor = pow(relTemp, TD_EXPNTREF_P);    info->ntRef[HOLE][MAJOR] *= factor;    factor = pow(relTemp, TD_EXPNTEXP_P);    info->ntExp[HOLE][MAJOR] *= factor;    muMin = info->muMin[HOLE][MINOR];    mu0 = info->muMax[HOLE][MINOR] - muMin;    factor = pow(relTemp, TD_EXPMUMIN_P);    muMin *= factor;    factor = pow(relTemp, TD_EXPMUMAX_P);    mu0 *= factor;    info->muMin[HOLE][MINOR] = muMin;    info->muMax[HOLE][MINOR] = mu0 + muMin;    factor = pow(relTemp, TD_EXPNTREF_P);    info->ntRef[HOLE][MINOR] *= factor;    factor = pow(relTemp, TD_EXPNTEXP_P);    info->ntExp[HOLE][MINOR] *= factor;    /* Modify field dependence parameters */    /* Assume warm carrier reference velocity has same temperature dep. */    factor = sqrt( tanh( TD_TREFVS_N / Temp ) );    info->vSat[ELEC] *= factor;    info->vWarm[ELEC] *= factor;    factor = sqrt( tanh( TD_TREFVS_P / Temp ) );    info->vSat[HOLE] *= factor;    info->vWarm[HOLE] *= factor;  }}MOBconcDep (info, conc, pMun, pMup)MaterialInfo *info;double  conc;double *pMun;double *pMup;{  double  s;  /* We have to check sign of conc even when concentration dependence   * is not used because it affects whether carriers are majority or   * minority carriers. Ideally, the minority/majority carrier models   * should agree at 0.0 concentration, but often they'll be inconsistent.   */  if (conc >= 0.0)  {				/* N type */    if (ConcDepMobility)    {      switch (info->concModel)      {	case CT: 	case AR: 	case UF: 	case GA:	  *pMun = info->muMin[ELEC][MAJOR] +	    (info->muMax[ELEC][MAJOR] - info->muMin[ELEC][MAJOR]) /	    (1.0 + pow(conc / info->ntRef[ELEC][MAJOR],		info->ntExp[ELEC][MAJOR]));	  *pMup = info->muMin[HOLE][MINOR] +	    (info->muMax[HOLE][MINOR] - info->muMin[HOLE][MINOR]) /	    (1.0 + pow(conc / info->ntRef[HOLE][MINOR],		info->ntExp[HOLE][MINOR]));	  break;	case SG: 	default: 	  s = info->muMax[ELEC][MAJOR] / info->muMin[ELEC][MAJOR];	  s = pow(s, 1.0 / info->ntExp[ELEC][MAJOR]) - 1;	  *pMun = info->muMax[ELEC][MAJOR] /	    pow(1.0 + conc / (conc / s + info->ntRef[ELEC][MAJOR]),	      info->ntExp[ELEC][MAJOR]);	  s = info->muMax[HOLE][MINOR] / info->muMin[HOLE][MINOR];	  s = pow(s, 1.0 / info->ntExp[HOLE][MINOR]) - 1;	  *pMup = info->muMax[HOLE][MINOR] /	    pow(1.0 + conc / (conc / s + info->ntRef[HOLE][MINOR]),	      info->ntExp[HOLE][MINOR]);	  break;      }    }    else    {      *pMun = info->muMax[ELEC][MAJOR];      *pMup = info->muMax[HOLE][MINOR];    }  }  else  {				/* P type */    if (ConcDepMobility)    {      conc = -conc;		/* Take absolute value. */      switch (info->concModel)      {	case CT: 	case AR: 	case UF: 	case GA:	  *pMun = info->muMin[ELEC][MINOR] +	    (info->muMax[ELEC][MINOR] - info->muMin[ELEC][MINOR]) /	    (1.0 + pow(conc / info->ntRef[ELEC][MINOR],		info->ntExp[ELEC][MINOR]));	  *pMup = info->muMin[HOLE][MAJOR] +	    (info->muMax[HOLE][MAJOR] - info->muMin[HOLE][MAJOR]) /	    (1.0 + pow(conc / info->ntRef[HOLE][MAJOR],		info->ntExp[HOLE][MAJOR]));	  break;	case SG: 	default: 	  s = info->muMax[ELEC][MINOR] / info->muMin[ELEC][MINOR];	  s = pow(s, 1.0 / info->ntExp[ELEC][MINOR]) - 1;	  *pMun = info->muMax[ELEC][MINOR] /	    pow(1.0 + conc / (conc / s + info->ntRef[ELEC][MINOR]),	      info->ntExp[ELEC][MINOR]);	  s = info->muMax[HOLE][MAJOR] / info->muMin[HOLE][MAJOR];	  s = pow(s, 1.0 / info->ntExp[HOLE][MAJOR]) - 1;	  *pMup = info->muMax[HOLE][MAJOR] /	    pow(1.0 + conc / (conc / s + info->ntRef[HOLE][MAJOR]),	      info->ntExp[HOLE][MAJOR]);	  break;      }    }    else    {      *pMun = info->muMax[ELEC][MINOR];      *pMup = info->muMax[HOLE][MAJOR];    }  }  return;}MOBfieldDep (info, carrier, field, pMu, pDMu)MaterialInfo *info;int   carrier;double  field;double *pMu;double *pDMu;{  double  eLateral, mu;  double  sgnL;  double  temp1, temp2, temp3, temp4, temp5, temp6;  double  dMuDEl;		/* Lateral Field Derivative */  /* Quick check to make sure we really belong here. */  if (!FieldDepMobility)    return;  sgnL = SGN (field);  eLateral = ABS (field);  mu = *pMu;			/* Grab temp. and conc.-dep. mobility */  if (carrier == ELEC)  {    switch (info->fieldModel)    {      case CT:       case AR:       case UF: 	temp1 = mu / info->vSat[ELEC];	temp2 = temp1 * eLateral;	temp3 = 1.0 / (1.0 + temp2 * temp2);	mu *= sqrt(temp3);	dMuDEl = -sgnL * mu * temp3 * temp2 * temp1;	break;      case GA:	temp1 = info->vSat[ELEC] / info->vWarm[ELEC]; /* Vsat / Vwarm */	temp2 = mu / info->vWarm[ELEC];	temp3 = temp2 * eLateral; /* Vdrift / Vwarm */	temp4 = temp3 * temp3 * temp3;	temp5 = 1.0 + temp1 * temp4;	temp6 = 1.0 / (1.0 + temp3 * temp4);	mu *= temp5 * temp6;	dMuDEl = - sgnL * mu * temp2 *	    (4.0 * temp4 * temp6 - 3.0 * temp1 * temp3 * temp3 / temp5 ); 	/*	dMuDEl = 0.0; 	    */	break;      case SG:       default: 	temp1 = mu / info->vSat[ELEC];	temp2 = temp1 * eLateral;/* Vdrift / Vsat */	temp3 = mu / info->vWarm[ELEC];	temp4 = temp3 * eLateral;/* Vdrift / Vwarm */	temp5 = temp4 / (temp4 + SG_FIT_N);	temp6 = 1.0 / (1.0 + temp4 * temp5 + temp2 * temp2);	mu *= sqrt(temp6);	dMuDEl = -sgnL * 0.5 * mu * temp6 *	  (temp5 * (2.0 - temp5) * temp3 + (2.0 * temp2 * temp1));	break;    }  }  else  {				/* Hole Mobility */    switch (info->fieldModel)    {      case CT:       case AR:       case UF: 	temp1 = mu / info->vSat[HOLE];	temp2 = temp1 * eLateral;	temp3 = 1.0 / (1.0 + temp2);	mu *= temp3;	dMuDEl = -sgnL * mu * temp3 * temp1;	break;      case GA:	temp1 = info->vSat[HOLE] / info->vWarm[HOLE]; /* Vsat / Vwarm */	temp2 = mu / info->vWarm[HOLE];	temp3 = temp2 * eLateral; /* Vdrift / Vwarm */	temp4 = temp3 * temp3 * temp3;	temp5 = 1.0 + temp1 * temp4;	temp6 = 1.0 / (1.0 + temp3 * temp4);	mu *= temp5 * temp6;	dMuDEl = - sgnL * mu * temp2 *	    (4.0 * temp4 * temp6 - 3.0 * temp1 * temp3 * temp3 / temp5 ); 	/*	dMuDEl = 0.0;	    */	break;      case SG:       default: 	temp1 = mu / info->vSat[HOLE];	temp2 = temp1 * eLateral;/* Vdrift / Vsat */	temp3 = mu / info->vWarm[HOLE];	temp4 = temp3 * eLateral;/* Vdrift / Vwarm */	temp5 = temp4 / (temp4 + SG_FIT_P);	temp6 = 1.0 / (1.0 + temp4 * temp5 + temp2 * temp2);	mu *= sqrt(temp6);	dMuDEl = -sgnL * 0.5 * mu * temp6 *	  (temp5 * (2.0 - temp5) * temp3 + (2.0 * temp2 * temp1));	break;    }  }  *pMu = mu;  *pDMu = dMuDEl;  return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -