1/* $Id: d_mos7.model,v 26.132 2009/11/24 04:26:37 al Exp $ -*- C++ -*- 2 * Copyright (C) 2001 Albert Davis 3 * Author: Albert Davis <aldavis@gnu.org> 4 * 5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 * 02110-1301, USA. 21 *------------------------------------------------------------------ 22 * Berkeley BSIM3v3.1 model 23 * Derived from Spice3f4,Copyright 1990 Regents of the University of California 24 * Author: 1991 JianHui Huang and Min-Chie Jeng. 25 * Recoded for Gnucap model compiler, Al Davis, 2000 26 */ 27h_headers { 28#include "d_mos_base.h" 29} 30cc_headers { 31#include "l_compar.h" 32#include "l_denoise.h" 33} 34/*--------------------------------------------------------------------------*/ 35/* 36 from diode 37 no fc??? 38 double bulkJctPotential 39 "Source/drain junction built-in potential" 40 name=PB default=1.0; 41 double unitAreaJctCap 42 "Source/drain bottom junction capacitance per unit area" 43 name=CJ default=5.0E-4; 44 double bulkJctBotGradingCoeff 45 "Source/drain bottom junction capacitance grading coefficient" 46 name=MJ default=0.5; 47 double sidewallJctPotential 48 "Source/drain sw junction capacitance built in potential" 49 name=PBSW default=1.0; 50 double unitLengthSidewallJctCap 51 "Source/drain sw junction capacitance per unit periphery" 52 name=CJSW default=5.0E-10; 53 double bulkJctSideGradingCoeff 54 "Source/drain sw junction capacitance grading coefficient" 55 name=MJSW default=0.33; 56 double kf "Flicker noise coefficient" 57 name=KF default=0.0; 58 double af "Flicker noise exponent" 59 name=AF default=1.0; 60 61 from mos_base 62 no is??? 63 double jctSatCurDensity 64 "Source/drain junction reverse saturation current density" 65 name=JS default=1.0E-4; 66 double sheetResistance "Source-drain sheet resistance" 67 name=RSH default=0.0; 68 no rd??? 69 no rs??? 70 no cbd??? 71 no cbs??? 72 double cgso "Gate-source overlap capacitance per width" 73 "CGSO default=NA; 74 double cgdo "Gate-drain overlap capacitance per width" 75 name=CGDO default=NA; 76 double cgbo "Gate-bulk overlap capacitance per length" 77 name=CGBO default=NA; 78 */ 79model BUILT_IN_MOS7 { 80 level 7 81 public_keys { 82 nmos7 polarity=pN; 83 pmos7 polarity=pP; 84 } 85 dev_type BUILT_IN_MOS; 86 inherit BUILT_IN_MOS_BASE; 87 independent { 88 override { 89 double mjsw "" final_default=.33; 90 double pb "" final_default=1.0 quiet_min=0.1; 91 double pbsw "" final_default=pb quiet_min=0.1; 92 double cjo "" default=5.0E-4; 93 double cgdo "" final_default="(((dlc != NA) && (dlc > 0.0)) 94 ? dlc * cox - cgdl.nom() 95 : 0.6 * xj.nom() * cox)"; 96 double cgso "" final_default="(((dlc != NA) && (dlc > 0.0)) 97 ? dlc * cox - cgsl.nom() 98 : 0.6 * xj.nom() * cox)"; 99 double cgbo "" final_default="((dwc != NA) 100 ? 2.0 * dwc * cox 101 : 2.0 * Wint * cox)"; 102 /* assumes cg?? final_default is BEFORE d?c final_default */ 103 int cmodel "CMODEL" print_test="cmodel!=1" 104 calculate="((!cmodel)?1:cmodel)"; 105 bool needs_isub "" calculate="(alpha0.nom()!=0.)"; 106 int mos_level "back-annotate for diode" name=DIODElevel 107 print_test="mos_level != LEVEL" default=LEVEL; 108 } 109 raw_parameters { 110 int capMod "Capacitance model selector (0, 1, 2, other?)" 111 name=CAPMOD default=2; 112 int nqsMod "Non-quasi-static model selector (0, !0)" 113 name=NQSMOD default=0; 114 int mobMod "Mobility model selector (1,2,3,other?)" 115 name=MOBMOD default=1; 116 int noiMod "Noise model selector (not used)" 117 name=NOIMOD default=1; 118 int paramChk "Model parameter checking selector (not used)" 119 name=PARAMCHK default=0; 120 int binUnit "Bin unit selector (1, !1)" 121 name=BINUNIT default=1; 122 double version "parameter for model version (not used)" 123 name=VERSION default=3.1; 124 double tox "Gate oxide thickness in meters" 125 name=TOX default=150.0e-10; 126 127 double xpart "Channel charge partitioning" 128 name=XPART default=0.0; 129 130 double jctSidewallSatCurDensity 131 "Sidewall junction reverse saturation current density" 132 name=JSW default=0.0; 133 double mjswg 134 "Source/drain (gate side) sw junction capacitance grading coefficient" 135 name=MJSWG default=NA final_default=mjsw; 136 double pbswg 137 "Source/drain (gate side) sw junction capacitance built in potential" 138 name=PBSWG default=NA final_default=pbsw quiet_min=0.1; 139 double unitLengthGateSidewallJctCap 140 "Source/drain (gate side) sidewall junction capacitance per unit width" 141 name=CJSWG default=NA final_default=cjsw; 142 double jctEmissionCoeff 143 "Source/drain junction emission coefficient" 144 name=NJ default=1.0; 145 double jctTempExponent 146 "Junction current temperature exponent" 147 name=XTI default=3.0; 148 149 double Lint "Length reduction parameter" name=LINT default=0.0; 150 double Ll "Length reduction parameter" name=LL default=0.0; 151 double Lln "Length reduction parameter" name=LLN default=1.0; 152 double Lw "Length reduction parameter" name=LW default=0.0; 153 double Lwn "Length reduction parameter" name=LWN default=1.0; 154 double Lwl "Length reduction parameter" name=LWL default=0.0; 155 156 double Wint "Width reduction parameter" name=WINT default=0.0; 157 double Wl "Width reduction parameter" name=WL default=0.0; 158 double Wln "Width reduction parameter" name=WLN default=1.0; 159 double Ww "Width reduction parameter" name=WW default=0.0; 160 double Wwn "Width reduction parameter" name=WWN default=1.0; 161 double Wwl "Width reduction parameter" name=WWL default=0.0; 162 163 double dwc "Delta W for C-V model" 164 name=DWC default=NA final_default=Wint; 165 double dlc "Delta L for C-V model" 166 name=DLC default=NA final_default=Lint; 167 168 double noia "Flicker noise parameter, oxide trap density A" 169 name=NOIA default=NA final_default="(polarity==pN) ? 1e20 : 9.9e18"; 170 double noib "Flicker noise parameter, oxide trap density B" 171 name=NOIB default=NA final_default="(polarity==pN) ? 5e4 : 2.4e3"; 172 double noic "Flicker noise parameter, oxide trap density C" 173 name=NOIC default=NA final_default="(polarity==pN) ?-1.4e-12 :1.4e-12"; 174 double em "Flicker noise parameter V/m" 175 name=EM default=4.1e7; 176 double ef "Flicker noise frequency exponent" 177 name=EF default=1.0; 178 } 179 calculated_parameters { 180 double cox; 181 double factor1 "" calculate="sqrt(tox * P_EPS_SI / P_EPS_OX)"; 182 double vt_at_tnom "" calculate="tnom_k * P_K_Q"; 183 double ni "" calculate="(1.45e10 * (tnom_k / 300.15) 184 * sqrt(tnom_k / 300.15) 185 * exp(21.5565981 - egap / (2.0 * vt_at_tnom)))"; 186 } 187 code_pre { 188 //tox = std::max(tox, 1e-20); 189 cox = 3.453133e-11 / tox; 190 } 191 code_post { 192 if (npeak.has_good_value() && npeak.nom() > 1.0e20) { 193 npeak.set_nom(npeak.nom() * 1.0e-6); 194 } 195 if (ngate.has_good_value() && ngate.nom() > 1.0e23) { 196 ngate.set_nom(ngate.nom() * 1.0e-6); 197 } 198 } 199 } 200 size_dependent { 201 raw_parameters { 202 double cdsc "Drain/Source and channel coupling capacitance Q/V/m^2" 203 name=CDSC default=2.4e-4; 204 double cdscb "Body-bias dependence of cdsc Q/V/m^2" 205 name=CDSCB default=0.0; 206 double cdscd "Drain-bias dependence of cdsc Q/V/m^2" 207 name=CDSCD default=0.0; 208 double cit "Interface state capacitance Q/V/m^2" 209 name=CIT default=0.0; 210 double nfactor "Subthreshold swing Coefficient" 211 name=NFACTOR default=1; 212 double xj "Junction depth in meters" 213 name=XJ default=.15e-6; 214 double vsat "Saturation velocity at tnom m/s" 215 name=VSAT default=8.0e4; 216 double at "Temperature coefficient of vsat m/s" 217 name=AT default=3.3e4; 218 double a0 "Non-uniform depletion width effect coefficient." 219 name=A0 default=1.0; 220 double ags "Gate bias coefficient of Abulk." 221 name=AGS default=0.0; 222 double a1 "Non-saturation effect coefficient" 223 name=A1 default=0.0; 224 double a2 "Non-saturation effect coefficient" 225 name=A2 default=1.0; 226 double keta 227 "Body-bias coefficient of non-uniform depletion width effect. 1/v" 228 name=KETA default=-0.047; 229 double nsub "Substrate doping concentration 1/cm3" 230 name=NSUB default=6.0e16; 231 double npeak "Channel doping concentration 1/cm3" 232 name=NCH default=NA; 233 double ngate "Poly-gate doping concentration 1/cm3" 234 name=NGATE default=0.0; 235 double gamma1 "Vth body coefficient" 236 name=GAMMA1 default=NA; 237 double gamma2 "Vth body coefficient" 238 name=GAMMA2 default=NA; 239 double vbx "Vth transition body Voltage" 240 name=VBX default=NA; 241 double vbm "Maximum body voltage" 242 name=VBM default=-3.0; 243 244 double xt "Doping depth" 245 name=XT default=1.55e-7; 246 double k1 "Bulk effect coefficient 1" 247 name=K1 default=NA; 248 double kt1 "Temperature coefficient of Vth" 249 name=KT1 default=-0.11; 250 double kt1l "Temperature coefficient of Vth" 251 name=KT1L default=0.0; 252 double kt2 "Body-coefficient of kt1" 253 name=KT2 default=0.022; 254 double k2 "Bulk effect coefficient 2" 255 name=K2 default=NA; 256 double k3 "Narrow width effect coefficient" 257 name=K3 default=80.0; 258 double k3b "Body effect coefficient of k3" 259 name=K3B default=0.0; 260 double w0 "Narrow width effect parameter" 261 name=W0 default=2.5e-6; 262 double nlx "Lateral non-uniform doping effect" 263 name=NLX default=1.74e-7; 264 double dvt0 "Short channel effect coeff. 0" 265 name=DVT0 default=2.2; 266 double dvt1 "Short channel effect coeff. 1" 267 name=DVT1 default=0.53; 268 double dvt2 "Short channel effect coeff. 2 1/v" 269 name=DVT2 default=-0.032; 270 double dvt0w "Narrow Width coeff. 0" 271 name=DVT0W default=0.0; 272 double dvt1w "Narrow Width effect coeff. 1" 273 name=DVT1W default=5.3e6; 274 double dvt2w "Narrow Width effect coeff. 2" 275 name=DVT2W default=-0.032; 276 double drout "DIBL coefficient of output resistance" 277 name=DROUT default=0.56; 278 double dsub "DIBL coefficient in the subthreshold region" 279 name=DSUB default=NA final_default="drout"; 280 double vth0 "Threshold voltage" 281 name=VTH0 default=NA final_default=NA; 282 double ua1 "Temperature coefficient of ua m/v" 283 name=UA1 default=4.31e-9; 284 double ua "Linear gate dependence of mobility m/v" 285 name=UA default=2.25e-9; 286 double ub1 "Temperature coefficient of ub (m/V)**2" 287 name=UB1 default=-7.61e-18; 288 double ub "Quadratic gate dependence of mobility (m/V)**2" 289 name=UB default=5.87e-19; 290 double uc1 "Temperature coefficient of uc" 291 name=UC1 default=NA 292 final_default="((m->mobMod==3) ? -0.056 : -0.056e-9)"; 293 double uc "Body-bias dependence of mobility" 294 name=UC default=NA 295 final_default="((m->mobMod==3) ? -0.0465 : -0.0465e-9)"; 296 double u0 "Low-field mobility at Tnom" 297 name=U0 default=NA 298 final_default="((m->polarity == pN) ? 0.067 : 0.025)"; 299 double ute "Temperature coefficient of mobility" 300 name=UTE default=-1.5; 301 double voff "Threshold voltage offset" 302 name=VOFF default=-0.08; 303 304 double delta "Effective Vds parameter" 305 name=DELTA default=0.01; 306 double rdsw "Source-drain resistance per width" 307 name=RDSW default=0.0; 308 double prwg "Gate-bias effect on parasitic resistance" 309 name=PRWG default=0.0; 310 double prwb "Body-effect on parasitic resistance" 311 name=PRWB default=0.0; 312 double prt "Temperature coefficient of parasitic resistance" 313 name=PRT default=0.0; 314 double eta0 "Subthreshold region DIBL coefficient" 315 name=ETA0 default=0.08; 316 double etab "Subthreshold region DIBL coefficient 1/v" 317 name=ETAB default=-0.07; 318 double pclm "Channel length modulation Coefficient" 319 name=PCLM default=1.3; 320 double pdibl1 "Drain-induced barrier lowering coefficient" 321 name=PDIBLC1 default=.39; 322 double pdibl2 "Drain-induced barrier lowering coefficient" 323 name=PDIBLC2 default=0.0086; 324 double pdiblb "Body-effect on drain-induced barrier lowering 1/v" 325 name=PDIBLCB default=0.0; 326 double pscbe1 "Substrate current body-effect coefficient" 327 name=PSCBE1 default=4.24e8; 328 double pscbe2 "Substrate current body-effect coefficient" 329 name=PSCBE2 default=1.0e-5; 330 double pvag "Gate dependence of output resistance parameter" 331 name=PVAG default=0.0; 332 333 double wr "Width dependence of rds" 334 name=WR default=1.0; 335 double dwg "Width reduction parameter" 336 name=DWG default=0.0; 337 double dwb "Width reduction parameter" 338 name=DWB default=0.0; 339 double b0 "Abulk narrow width parameter" 340 name=B0 default=0.0; 341 double b1 "Abulk narrow width parameter" 342 name=B1 default=0.0; 343 344 double alpha0 "substrate current model parameter" 345 name=ALPHA0 default=0.0; 346 double beta0 "substrate current model parameter" 347 name=BETA0 default=30.0; 348 349 /* CV model */ 350 double elm "Non-quasi-static Elmore Constant Parameter" 351 name=ELM default=5.0; 352 double vfbcv "Flat Band Voltage parameter for capmod=0 only" 353 name=VFBCV default=-1.0; 354 double cgsl "New C-V model parameter" 355 name=CGSL default=0.0; 356 double cgdl "New C-V model parameter" 357 name=CGDL default=0.0; 358 double ckappa "New C-V model parameter" 359 name=CKAPPA default=0.6; 360 double cf "Fringe capacitance parameter" 361 name=CF default=NA 362 final_default="2.0 * P_EPS_OX / M_PI * log(1.0 + 0.4e-6 / m->tox)"; 363 double clc "Vdsat parameter for C-V model" 364 name=CLC default=0.1e-6; 365 double cle "Vdsat parameter for C-V model" 366 name=CLE default=0.6; 367 } 368 calculated_parameters { 369 double dl; 370 double dlc; 371 double dw; 372 double dwc; 373 374 double leff; /* BUG:: why not reuse from super */ 375 double weff; 376 double leffCV; 377 double weffCV; 378 379 double abulkCVfactor "" calculate="1.0 + pow((clc / leff), cle)"; 380 381 double cgso "" calculate="(m->cgso + cf) * weffCV"; 382 double cgdo "" calculate="(m->cgdo + cf) * weffCV"; 383 double cgbo "" calculate="m->cgbo * leffCV"; 384 385 double litl "" calculate="sqrt(3.0 * xj * m->tox)"; 386 } 387 code_pre { 388 { 389 double T0 = pow(c->l_in, m->Lln); 390 double T1 = pow(c->w_in, m->Lwn); 391 double tmp1 = m->Ll / T0 + m->Lw / T1 + m->Lwl / (T0 * T1); 392 dl = m->Lint + tmp1; 393 dlc = m->dlc + tmp1; 394 } 395 { 396 double T2 = pow(c->l_in, m->Wln); 397 double T3 = pow(c->w_in, m->Wwn); 398 double tmp2 = m->Wl / T2 + m->Ww / T3 + m->Wwl / (T2 * T3); 399 dw = m->Wint + tmp2; 400 dwc = m->dwc + tmp2; 401 } 402 403 leff = c->l_in - 2.0 * dl; 404 weff = c->w_in - 2.0 * dw; 405 leffCV = c->l_in - 2.0 * dlc; 406 weffCV = c->w_in - 2.0 * dwc; 407 cgate = m->cox * w_eff * l_eff; /* BUG:: not adjusted values?? */ 408 double L = leff; 409 double W = weff; 410 if (m->binUnit == 1) { 411 L /= MICRON2METER; 412 W /= MICRON2METER; 413 } 414 } 415 code_post { 416 if (u0 > 1.0) { 417 u0 /= 1.0e4; 418 } 419 if (m->npeak.nom() == NA) { 420 if (m->gamma1.nom() != NA) { 421 double T0 = gamma1 * m->cox; 422 npeak = 3.021E22 * T0 * T0; 423 }else{ 424 npeak = 1.7e17; 425 } 426 } 427 if (m->k1.nom() != NA && m->k2.nom() != NA) { 428 if (m->k1.nom() == NA) { 429 k1 = 0.53; 430 } 431 if (m->k2.nom() == NA) { 432 k2 = -0.0186; 433 } 434 }else{ 435 vbm = -std::abs(vbm); 436 if (m->gamma1.nom() == NA) { 437 gamma1 = 5.753e-12 * sqrt(npeak) / m->cox; 438 } 439 if (m->gamma2.nom() == NA) { 440 gamma2 = 5.753e-12 * sqrt(nsub) / m->cox; 441 } 442 } 443 } 444 } 445 temperature_dependent { 446 calculated_parameters { 447 double temp; 448 double tempratio "" calculate="temp / m->tnom_k"; 449 double tempratio_1 "" calculate="tempratio - 1"; 450 double vtm "vtm" calculate="temp * P_K_Q"; 451 double ua; 452 double ub; 453 double uc; 454 double u0temp; 455 double vsattemp; 456 double rds0; 457 double phi; 458 double sqrtPhi; 459 double phis3; 460 double Xdep0; 461 double vbi; 462 double cdep0; 463 double k1; 464 double k2; 465 double vbsc; 466 double vth0; 467 double vfb; 468 double theta0vb0; 469 double thetaRout; 470 } 471 code_pre { 472 temp = d->_sim->_temp_c + P_CELSIUS0; 473 double egap = 1.16 - 7.02e-4 * temp * temp / (temp + 1108.0); 474 } 475 code_post { 476 double jctTempSatCurDensity; 477 double jctSidewallTempSatCurDensity; 478 if (temp != m->tnom_k) { 479 double T0 = m->egap / m->vt_at_tnom - egap / vtm + m->jctTempExponent 480 * log(temp / m->tnom_k); 481 double T1 = exp(T0 / m->jctEmissionCoeff); 482 jctTempSatCurDensity = m->js * T1; 483 jctSidewallTempSatCurDensity = m->jctSidewallSatCurDensity * T1; 484 }else{ 485 jctTempSatCurDensity = m->js; 486 jctSidewallTempSatCurDensity = m->jctSidewallSatCurDensity; 487 } 488 if (jctTempSatCurDensity < 0.0) { 489 jctTempSatCurDensity = 0.0; 490 } 491 if (jctSidewallTempSatCurDensity < 0.0) { 492 jctSidewallTempSatCurDensity = 0.0; 493 } 494 { 495 double T0 = (tempratio - 1.0); 496 ua = s->ua + s->ua1 * T0; 497 ub = s->ub + s->ub1 * T0; 498 uc = s->uc + s->uc1 * T0; 499 u0temp = s->u0 * pow(tempratio, s->ute); 500 vsattemp = s->vsat - s->at * T0; 501 rds0 = (s->rdsw + s->prt * T0) / pow(s->weff * 1E6, s->wr); 502 } 503 phi = 2.0 * m->vt_at_tnom * log(s->npeak / m->ni); 504 sqrtPhi = sqrt(phi); 505 phis3 = sqrtPhi * phi; 506 Xdep0 = sqrt(2.0 * P_EPS_SI / (P_Q * s->npeak * 1.0e6)) * sqrtPhi; 507 vbi = m->vt_at_tnom * log(1.0e20 * s->npeak / (m->ni * m->ni)); 508 cdep0 = sqrt(P_Q * P_EPS_SI * s->npeak * 1.0e6 / 2.0 / phi); 509 510 if (m->k1.nom() != NA && m->k2.nom() != NA) { 511 k2 = s->k2; 512 k1 = s->k1; 513 }else{ 514 double vbx = (m->vbx.nom() == NA) 515 ? -std::abs(phi - 7.7348e-4 * s->npeak * s->xt * s->xt) 516 : -std::abs(s->vbx); 517 double T0 = s->gamma1 - s->gamma2; 518 double T1 = sqrt(phi - vbx) - sqrtPhi; 519 double T2 = sqrt(phi * (phi - s->vbm)) - phi; 520 k2 = T0 * T1 / (2.0 * T2 + s->vbm); 521 k1 = s->gamma2 - 2.0 * k2 * sqrt(phi - s->vbm); 522 } 523 if (k2 < 0.) { 524 double T0 = 0.5 * k1 / k2; 525 vbsc = to_range(-30.0, (0.9 * (phi - T0 * T0)), -3.0); 526 }else{ 527 vbsc = -30.0; 528 } 529 vbsc = std::min(vbsc, s->vbm); 530 if (s->vth0 == NA) { 531 vfb = -1.0; 532 vth0 = m->polarity * (vfb + phi + k1 * sqrtPhi); 533 }else{ 534 vth0 = s->vth0; 535 vfb = m->polarity * vth0 - phi - k1 * sqrtPhi; 536 } 537 trace3("", s->vth0, vth0, vfb); 538 { 539 double T1 = sqrt(P_EPS_SI / P_EPS_OX * m->tox * Xdep0); 540 double T0 = exp(-0.5 * s->dsub * s->leff / T1); 541 theta0vb0 = (T0 + 2.0 * T0 * T0); 542 543 T0 = exp(-0.5 * s->drout * s->leff / T1); 544 double T2 = (T0 + 2.0 * T0 * T0); 545 thetaRout = s->pdibl1 * T2 + s->pdibl2; 546 } 547 } 548 } 549 /*-----------------------------------------------------------------------*/ 550 tr_eval { 551 trace3("", d->vds, d->vgs, d->vbs); 552 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 553 const double EXP_THRESHOLD = 34.0; 554 const double MIN_EXP = 1.713908431e-15; 555 const double MAX_EXP = 5.834617425e14; 556 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 557 d->reverse_if_needed(); 558 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 559 double Vbseff, dVbseff_dVb; 560 { 561 double T0 = d->vbs - t->vbsc - 0.001; 562 double T1 = sqrt(T0 * T0 - 0.004 * t->vbsc); 563 trace3("", t->vbsc, T0, T1); 564 Vbseff = t->vbsc + 0.5 * (T0 + T1); 565 dVbseff_dVb = 0.5 * (1.0 + T0 / T1); 566 trace2("raw", Vbseff, dVbseff_dVb); 567 568 fixzero(&Vbseff, t->vbsc); 569 if (Vbseff < d->vbs) { // From Spice, to fix numeric problems 570 untested(); // inadequately. Above fixzero should do a 571 Vbseff = d->vbs; // better job, but I left this in case. 572 } 573 } 574 trace2("fixed", Vbseff, dVbseff_dVb); 575 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 576 double Phis, dPhis_dVb, sqrtPhis, dsqrtPhis_dVb; 577 if (Vbseff > 0.0) { 578 untested(); 579 d->sbfwd = true; 580 double T0 = t->phi / (t->phi + Vbseff); 581 Phis = t->phi * T0; 582 dPhis_dVb = -T0 * T0; 583 sqrtPhis = t->phis3 / (t->phi + 0.5 * Vbseff); 584 dsqrtPhis_dVb = -0.5 * sqrtPhis * sqrtPhis / t->phis3; 585 trace0("bs-fwd-bias"); 586 }else{ 587 d->sbfwd = false; 588 Phis = t->phi - Vbseff; 589 dPhis_dVb = -1.0; 590 sqrtPhis = sqrt(Phis); 591 dsqrtPhis_dVb = -0.5 / sqrtPhis; 592 trace0("bs-normal"); 593 } 594 trace4("", Phis, dPhis_dVb, sqrtPhis, dsqrtPhis_dVb); 595 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 596 double Xdep = t->Xdep0 * sqrtPhis / t->sqrtPhi; 597 double dXdep_dVb = (t->Xdep0 / t->sqrtPhi) * dsqrtPhis_dVb; 598 trace2("", Xdep, dXdep_dVb); 599 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 600 double Theta0, dTheta0_dVb; 601 { 602 double lt1, dlt1_dVb; 603 { 604 double T3 = sqrt(Xdep); 605 double T0 = s->dvt2 * Vbseff; 606 double T1, T2; 607 if (T0 >= - 0.5) { 608 T1 = 1.0 + T0; 609 T2 = s->dvt2; 610 trace4("", T0, T1, T2, T3); 611 }else{ 612 untested(); 613 /* Added to avoid any discontinuity problems caused by dvt2 */ 614 double T4 = 1.0 / (3.0 + 8.0 * T0); 615 T1 = (1.0 + 3.0 * T0) * T4; 616 T2 = s->dvt2 * T4 * T4; 617 trace4("dvd2 fix", T0, T1, T2, T3); 618 } 619 lt1 = m->factor1 * T3 * T1; 620 dlt1_dVb = m->factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2); 621 } 622 trace2("", lt1, dlt1_dVb); 623 624 double T0 = -0.5 * s->dvt1 * s->leff / lt1; 625 if (T0 > -EXP_THRESHOLD) { 626 double T1 = exp(T0); 627 Theta0 = T1 * (1.0 + 2.0 * T1); 628 double dT1_dVb = -T0 / lt1 * T1 * dlt1_dVb; 629 dTheta0_dVb = (1.0 + 4.0 * T1) * dT1_dVb; 630 trace2("T0 > -ET", Theta0, dTheta0_dVb); 631 }else{ 632 double T1 = MIN_EXP; 633 Theta0 = T1 * (1.0 + 2.0 * T1); 634 dTheta0_dVb = 0.0; 635 trace2("T0 < -ET", Theta0, dTheta0_dVb); 636 } 637 } 638 trace2("", Theta0, dTheta0_dVb); 639 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 640 double dVth_dVb, dVth_dVd; // d->von 641 { 642 double V0 = t->vbi - t->phi; 643 double T2, dT2_dVb; 644 { 645 double ltw, dltw_dVb; 646 { 647 double t3 = sqrt(Xdep); 648 double t0 = s->dvt2w * Vbseff; 649 double t1, t2; 650 if (t0 >= - 0.5) { 651 t1 = 1.0 + t0; 652 t2 = s->dvt2w; 653 }else{ 654 untested(); 655 /* Added to avoid any discontinuity problems caused by dvt2w */ 656 double t4 = 1.0 / (3.0 + 8.0 * t0); 657 t1 = (1.0 + 3.0 * t0) * t4; 658 t2 = s->dvt2w * t4 * t4; 659 } 660 trace4("", t0, t1, t2, t3); 661 ltw = m->factor1 * t3 * t1; 662 dltw_dVb = m->factor1 * (0.5 / t3 * t1 * dXdep_dVb + t3 * t2); 663 } 664 trace2("", ltw, dltw_dVb); 665 double T0 = -0.5 * s->dvt1w * s->weff * s->leff / ltw; 666 if (T0 > -EXP_THRESHOLD) { 667 double T1 = exp(T0); 668 T2 = T1 * (1.0 + 2.0 * T1); 669 double dT1_dVb = -T0 / ltw * T1 * dltw_dVb; 670 dT2_dVb = (1.0 + 4.0 * T1) * dT1_dVb; 671 }else{ 672 double T1 = MIN_EXP; 673 T2 = T1 * (1.0 + 2.0 * T1); 674 dT2_dVb = 0.0; 675 } 676 T0 = s->dvt0w * T2; 677 T2 = T0 * V0; 678 dT2_dVb = s->dvt0w * dT2_dVb * V0; 679 } 680 trace3("", V0, T2, dT2_dVb); 681 double T0 = sqrt(1.0 + s->nlx / s->leff); 682 double T1 = t->k1 * (T0 - 1.0) * t->sqrtPhi 683 + (s->kt1 + s->kt1l / s->leff + s->kt2 * Vbseff) * t->tempratio_1; 684 double tmp2 = m->tox * t->phi / (s->weff + s->w0); 685 686 double T3 = s->eta0 + s->etab * Vbseff; 687 trace4("", T0, T1, tmp2, T3); 688 double T4; 689 if (T3 < 1.0e-4) { 690 untested(); 691 /* avoid discontinuity problems caused by etab */ 692 double T9 = 1.0 / (3.0 - 2.0e4 * T3); 693 T3 = (2.0e-4 - T3) * T9; 694 T4 = T9 * T9; 695 trace3("", T9, T3, T4); 696 }else{ 697 T4 = 1.0; 698 trace1("", T4); 699 } 700 double thetavth = s->dvt0 * Theta0; 701 double Delt_vth = thetavth * V0; 702 double dDelt_vth_dVb = s->dvt0 * dTheta0_dVb * V0; 703 trace4("", thetavth, t->theta0vb0, Delt_vth, dDelt_vth_dVb); 704 double dDIBL_Sft_dVd = T3 * t->theta0vb0; 705 double DIBL_Sft = dDIBL_Sft_dVd * d->vds; 706 trace2("", dDIBL_Sft_dVd, DIBL_Sft); 707 708 trace4("", t->vth0, t->k1, sqrtPhis, t->sqrtPhi); 709 trace4("", t->k2, Vbseff, Delt_vth, T2); 710 trace4("", s->k3, s->k3b, Vbseff, tmp2); 711 trace2("", T1, DIBL_Sft); 712 double Vth = m->polarity * t->vth0 + t->k1 * (sqrtPhis - t->sqrtPhi) 713 - t->k2 * Vbseff - Delt_vth - T2 + (s->k3 + s->k3b * Vbseff) * tmp2 714 + T1 - DIBL_Sft; 715 d->von = Vth; 716 717 dVth_dVb = t->k1 * dsqrtPhis_dVb - t->k2 - dDelt_vth_dVb - dT2_dVb 718 + s->k3b * tmp2 - s->etab * d->vds * t->theta0vb0 * T4 719 + s->kt2 * t->tempratio_1; 720 dVth_dVd = -dDIBL_Sft_dVd; 721 } 722 trace3("", d->von, dVth_dVb, dVth_dVd); 723 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 724 /* Calculate n */ 725 double n, dn_dVb, dn_dVd; 726 { 727 double tmp2 = s->nfactor * P_EPS_SI / Xdep; 728 double tmp3 = s->cdsc + s->cdscb * Vbseff + s->cdscd * d->vds; 729 double tmp4 = (tmp2 + tmp3 * Theta0 + s->cit) / m->cox; 730 trace3("", tmp2, tmp3, tmp4); 731 if (tmp4 >= -0.5) { 732 n = 1.0 + tmp4; 733 dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb 734 + s->cdscb * Theta0) / m->cox; 735 dn_dVd = s->cdscd * Theta0 / m->cox; 736 trace3("n", n, dn_dVb, dn_dVd); 737 }else{ 738 /* avoid discontinuity problems caused by tmp4 */ 739 double T0 = 1.0 / (3.0 + 8.0 * tmp4); 740 n = (1.0 + 3.0 * tmp4) * T0; 741 T0 *= T0; 742 dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb 743 + s->cdscb * Theta0) / m->cox * T0; 744 dn_dVd = s->cdscd * Theta0 / m->cox * T0; 745 trace3("n disc", n, dn_dVb, dn_dVd); 746 } 747 } 748 trace3("", n, dn_dVb, dn_dVd); 749 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 750 /* Poly Gate Si Depletion Effect */ 751 double Vgs_eff, dVgs_eff_dVg; 752 { 753 double T0 = t->vfb + t->phi; 754 trace2("Poly", t->vfb, t->phi); 755 trace3("", s->ngate, d->vgs, T0); 756 if ((s->ngate > 1.e18) && (s->ngate < 1.e25) && (d->vgs > T0)) { 757 /* added to avoid the problem caused by ngate */ 758 double T1 = 1.0e6 * P_Q * P_EPS_SI * s->ngate / (m->cox * m->cox); 759 double T4 = sqrt(1.0 + 2.0 * (d->vgs - T0) / T1); 760 double T2 = T1 * (T4 - 1.0); 761 double T3 = 0.5 * T2 * T2 / T1; /* T3 = Vpoly */ 762 double T7 = 1.12 - T3 - 0.05; 763 double T6 = sqrt(T7 * T7 + 0.224); 764 double T5 = 1.12 - 0.5 * (T7 + T6); 765 Vgs_eff = d->vgs - T5; 766 dVgs_eff_dVg = 1.0 - (0.5 - 0.5 / T4) * (1.0 + T7 / T6); 767 trace2("><", Vgs_eff, dVgs_eff_dVg); 768 }else{ 769 Vgs_eff = d->vgs; 770 dVgs_eff_dVg = 1.0; 771 trace2("const", Vgs_eff, dVgs_eff_dVg); 772 } 773 } 774 trace2("", Vgs_eff, dVgs_eff_dVg); 775 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 776 /* Effective Vgst (Vgsteff) Calculation */ 777 double /*Vgsteff,*/ dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb, Vgst2Vtm; 778 double VgstNVt, ExpVgst; // d->vgst 779 { 780 double Vgst = Vgs_eff - d->von; 781 double T10 = 2.0 * n * t->vtm; 782 VgstNVt = Vgst / T10; 783 double ExpArg = (2.0 * s->voff - Vgst) / T10; 784 trace4("", Vgst, T10, VgstNVt, ExpArg); 785 786 /* MCJ: Very small Vgst */ 787 if (VgstNVt > EXP_THRESHOLD) { 788 d->vgst = Vgst; 789 dVgsteff_dVg = dVgs_eff_dVg; 790 dVgsteff_dVd = -dVth_dVd; 791 dVgsteff_dVb = -dVth_dVb; 792 ExpVgst = NOT_VALID; 793 trace4(">>", d->vgst, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb); 794 }else if (ExpArg > EXP_THRESHOLD) { 795 double T0 = (Vgst - s->voff) / (n * t->vtm); 796 ExpVgst = exp(T0); 797 d->vgst = t->vtm * t->cdep0 / m->cox * ExpVgst; 798 dVgsteff_dVg = d->vgst / (n * t->vtm); 799 dVgsteff_dVd = -dVgsteff_dVg * (dVth_dVd + T0 * t->vtm * dn_dVd); 800 dVgsteff_dVb = -dVgsteff_dVg * (dVth_dVb + T0 * t->vtm * dn_dVb); 801 dVgsteff_dVg *= dVgs_eff_dVg; 802 trace4(">", d->vgst, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb); 803 }else{ 804 ExpVgst = exp(VgstNVt); 805 double T1 = T10 * log(1.0 + ExpVgst); 806 double dT1_dVg = ExpVgst / (1.0 + ExpVgst); 807 double dT1_dVb = -dT1_dVg * (dVth_dVb + Vgst / n * dn_dVb) 808 + T1 / n * dn_dVb; 809 double dT1_dVd = -dT1_dVg * (dVth_dVd + Vgst / n * dn_dVd) 810 + T1 / n * dn_dVd; 811 812 double dT2_dVg = -m->cox / (t->vtm * t->cdep0) 813 * exp(ExpArg); 814 double T2 = 1.0 - T10 * dT2_dVg; 815 double dT2_dVd = -dT2_dVg * (dVth_dVd - 2.0 * t->vtm * ExpArg * dn_dVd) 816 + (T2 - 1.0) / n * dn_dVd; 817 double dT2_dVb = -dT2_dVg * (dVth_dVb - 2.0 * t->vtm * ExpArg * dn_dVb) 818 + (T2 - 1.0) / n * dn_dVb; 819 820 d->vgst = T1 / T2; 821 double T3 = T2 * T2; 822 dVgsteff_dVg = (T2 * dT1_dVg - T1 * dT2_dVg) / T3 * dVgs_eff_dVg; 823 dVgsteff_dVd = (T2 * dT1_dVd - T1 * dT2_dVd) / T3; 824 dVgsteff_dVb = (T2 * dT1_dVb - T1 * dT2_dVb) / T3; 825 trace4("<", d->vgst, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb); 826 } 827 Vgst2Vtm = d->vgst + 2.0 * t->vtm; 828 trace3("", d->vgst, t->vtm, Vgst2Vtm); 829 } 830 trace1("", d->vgst); 831 trace4("", dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb, Vgst2Vtm); 832 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 833 /* Calculate Effective Channel Geometry */ 834 double Weff, dWeff_dVg, dWeff_dVb; 835 { 836 double T9 = sqrtPhis - t->sqrtPhi; 837 Weff = s->weff - 2.0 * (s->dwg * d->vgst + s->dwb * T9); 838 dWeff_dVg = -2.0 * s->dwg; 839 dWeff_dVb = -2.0 * s->dwb * dsqrtPhis_dVb; 840 841 if (Weff < 2.0e-8) { 842 /* to avoid the discontinuity problem due to Weff*/ 843 double T0 = 1.0 / (6.0e-8 - 2.0 * Weff); 844 Weff = 2.0e-8 * (4.0e-8 - Weff) * T0; 845 T0 *= T0 * 4.0e-16; 846 dWeff_dVg *= T0; 847 dWeff_dVb *= T0; 848 trace3("Weff fix", Weff, dWeff_dVg, dWeff_dVb); 849 } 850 } 851 trace3("", Weff, dWeff_dVg, dWeff_dVb); 852 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 853 double Rds, dRds_dVg, dRds_dVb; 854 { 855 double T9 = sqrtPhis - t->sqrtPhi; 856 double T0 = s->prwg * d->vgst + s->prwb * T9; 857 if (T0 >= -0.9) { 858 Rds = t->rds0 * (1.0 + T0); 859 dRds_dVg = t->rds0 * s->prwg; 860 dRds_dVb = t->rds0 * s->prwb * dsqrtPhis_dVb; 861 }else{ 862 /* to avoid the discontinuity problem due to prwg and prwb*/ 863 double T1 = 1.0 / (17.0 + 20.0 * T0); 864 Rds = t->rds0 * (0.8 + T0) * T1; 865 T1 *= T1; 866 dRds_dVg = t->rds0 * s->prwg * T1; 867 dRds_dVb = t->rds0 * s->prwb * dsqrtPhis_dVb * T1; 868 trace3("Rds fix", T9, T0, T1); 869 trace3("Rds fix", Rds, dRds_dVg, dRds_dVb); 870 } 871 } 872 trace3("", Rds, dRds_dVg, dRds_dVb); 873 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 874 /* Calculate Abulk */ 875 double Abulk0, dAbulk0_dVb, dAbulk_dVg, Abulk, dAbulk_dVb; 876 { 877 double T1 = 0.5 * t->k1 / sqrtPhis; 878 double dT1_dVb = -T1 / sqrtPhis * dsqrtPhis_dVb; 879 880 double T9 = sqrt(s->xj * Xdep); 881 double tmp1 = s->leff + 2.0 * T9; 882 double T5 = s->leff / tmp1; 883 double tmp2 = s->a0 * T5; 884 double tmp3 = s->weff + s->b1; 885 double tmp4 = s->b0 / tmp3; 886 double T2 = tmp2 + tmp4; 887 double dT2_dVb = -T9 / tmp1 / Xdep * dXdep_dVb; 888 double T6 = T5 * T5; 889 double T7 = T5 * T6; 890 891 Abulk0 = 1.0 + T1 * T2; 892 dAbulk0_dVb = T1 * tmp2 * dT2_dVb + T2 * dT1_dVb; 893 894 double T8 = s->ags * s->a0 * T7; 895 dAbulk_dVg = -T1 * T8; 896 Abulk = Abulk0 + dAbulk_dVg * d->vgst; 897 dAbulk_dVb = dAbulk0_dVb - T8 * d->vgst * (dT1_dVb + 3.0 * T1 * dT2_dVb); 898 899 trace2("1", Abulk0, dAbulk0_dVb); 900 trace3("1", dAbulk_dVg, Abulk, dAbulk_dVb); 901 902 if (Abulk0 < 0.1) { 903 /* added to avoid the problems caused by Abulk0 */ 904 double t9 = 1.0 / (3.0 - 20.0 * Abulk0); 905 Abulk0 = (0.2 - Abulk0) * t9; 906 dAbulk0_dVb *= t9 * t9; 907 trace2("2", Abulk0, dAbulk0_dVb); 908 } 909 if (Abulk < 0.1) { 910 /* added to avoid the problems caused by Abulk */ 911 double t9 = 1.0 / (3.0 - 20.0 * Abulk); 912 Abulk = (0.2 - Abulk) * t9; 913 dAbulk_dVb *= t9 * t9; 914 trace3("2", dAbulk_dVg, Abulk, dAbulk_dVb); 915 } 916 917 double T0, dT0_dVb; 918 { 919 double t2 = s->keta * Vbseff; 920 if (t2 >= -0.9) { 921 T0 = 1.0 / (1.0 + t2); 922 dT0_dVb = -s->keta * T0 * T0; 923 trace3("", t2, T0, dT0_dVb); 924 }else{ 925 /* added to avoid the problems caused by Keta */ 926 double t1 = 1.0 / (0.8 + T2); 927 T0 = (17.0 + 20.0 * T2) * t1; 928 dT0_dVb = -s->keta * t1 * t1; 929 trace3("keta fix", T2, T0, dT0_dVb); 930 } 931 } 932 dAbulk_dVg *= T0; 933 dAbulk_dVb = dAbulk_dVb * T0 + Abulk * dT0_dVb; 934 dAbulk0_dVb = dAbulk0_dVb * T0 + Abulk0 * dT0_dVb; 935 Abulk *= T0; 936 Abulk0 *= T0; 937 } 938 trace2("", Abulk0, dAbulk0_dVb); 939 trace3("", dAbulk_dVg, Abulk, dAbulk_dVb); 940 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 941 /* Mobility calculation */ 942 double ueff, dueff_dVg, dueff_dVd, dueff_dVb; 943 { 944 double Denomi, dDenomi_dVg, dDenomi_dVd, dDenomi_dVb; 945 { 946 double T5; 947 if (m->mobMod == 1) { 948 double T0 = d->vgst + d->von + d->von; 949 double T2 = t->ua + t->uc * Vbseff; 950 double T3 = T0 / m->tox; 951 T5 = T3 * (T2 + t->ub * T3); 952 dDenomi_dVg = (T2 + 2.0 * t->ub * T3) / m->tox; 953 dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd; 954 dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + t->uc * T3; 955 }else if (m->mobMod == 2) { 956 T5 = d->vgst / m->tox 957 * (t->ua + t->uc * Vbseff + t->ub * d->vgst / m->tox); 958 dDenomi_dVg = (t->ua + t->uc * Vbseff + 2.0 * t->ub * d->vgst / m->tox) 959 / m->tox; 960 dDenomi_dVd = 0.0; 961 dDenomi_dVb = d->vgst * t->uc / m->tox; 962 }else{ 963 double T0 = d->vgst + d->von + d->von; 964 double T2 = 1.0 + t->uc * Vbseff; 965 double T3 = T0 / m->tox; 966 double T4 = T3 * (t->ua + t->ub * T3); 967 T5 = T4 * T2; 968 dDenomi_dVg = (t->ua + 2.0 * t->ub * T3) * T2 / m->tox; 969 dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd; 970 dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + t->uc * T4; 971 } 972 if (T5 >= -0.8) { 973 Denomi = 1.0 + T5; 974 }else{ 975 /* Added to avoid the discontinuity problem caused by ua and ub*/ 976 double t9 = 1.0 / (7.0 + 10.0 * T5); 977 Denomi = (0.6 + T5) * t9; 978 t9 *= t9; 979 dDenomi_dVg *= t9; 980 dDenomi_dVd *= t9; 981 dDenomi_dVb *= t9; 982 } 983 } 984 ueff = t->u0temp / Denomi; 985 double t9 = -ueff / Denomi; 986 dueff_dVg = t9 * dDenomi_dVg; 987 dueff_dVd = t9 * dDenomi_dVd; 988 dueff_dVb = t9 * dDenomi_dVb; 989 } 990 trace4("", ueff, dueff_dVg, dueff_dVd, dueff_dVb); 991 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 992 double Esat, EsatL, dEsatL_dVg, dEsatL_dVd, dEsatL_dVb; 993 { 994 Esat = 2.0 * t->vsattemp / ueff; 995 EsatL = Esat * s->leff; 996 double T0 = -EsatL /ueff; 997 dEsatL_dVg = T0 * dueff_dVg; 998 dEsatL_dVd = T0 * dueff_dVd; 999 dEsatL_dVb = T0 * dueff_dVb; 1000 } 1001 trace2("", Esat, EsatL); 1002 trace3("", dEsatL_dVg, dEsatL_dVd, dEsatL_dVb); 1003 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1004 double Vdsat, dVdsat_dVg, dVdsat_dVd, dVdsat_dVb; // d->vdsat 1005 double Vasat, dVasat_dVg, dVasat_dVb, dVasat_dVd; 1006 { 1007 double WVCoxRds; 1008 { 1009 double WVCox = Weff * t->vsattemp * m->cox; 1010 WVCoxRds = WVCox * Rds; 1011 } 1012 trace1("", WVCoxRds); 1013 1014 double Lambda, dLambda_dVg; 1015 { 1016 if (s->a1 == 0.0) { 1017 Lambda = s->a2; 1018 dLambda_dVg = 0.0; 1019 }else if (s->a1 > 0.0) { 1020 /* avoid discontinuity problem caused by s->a1 and s->a2 (Lambda) */ 1021 double T0 = 1.0 - s->a2; 1022 double T1 = T0 - s->a1 * d->vgst - 0.0001; 1023 double T2 = sqrt(T1 * T1 + 0.0004 * T0); 1024 Lambda = s->a2 + T0 - 0.5 * (T1 + T2); 1025 dLambda_dVg = 0.5 * s->a1 * (1.0 + T1 / T2); 1026 }else{ 1027 double T1 = s->a2 + s->a1 * d->vgst - 0.0001; 1028 double T2 = sqrt(T1 * T1 + 0.0004 * s->a2); 1029 Lambda = 0.5 * (T1 + T2); 1030 dLambda_dVg = 0.5 * s->a1 * (1.0 + T1 / T2); 1031 } 1032 } 1033 trace2("", Lambda, dLambda_dVg); 1034 1035 double tmp2, tmp3; 1036 if (Rds > 0) { 1037 tmp2 = dRds_dVg / Rds + dWeff_dVg / Weff; 1038 tmp3 = dRds_dVb / Rds + dWeff_dVb / Weff; 1039 }else{ 1040 tmp2 = dWeff_dVg / Weff; 1041 tmp3 = dWeff_dVb / Weff; 1042 } 1043 trace2("", tmp2, tmp3); 1044 1045 //double Vdsat, dVdsat_dVg, dVdsat_dVd, dVdsat_dVb; // d->vdsat 1046 double tmp1; 1047 { 1048 if ((Rds == 0.0) && (Lambda == 1.0)) { 1049 double T0 = 1.0 / (Abulk * EsatL + Vgst2Vtm); 1050 tmp1 = 0.0; 1051 double T1 = T0 * T0; 1052 double T2 = Vgst2Vtm * T0; 1053 double T3 = EsatL * Vgst2Vtm; 1054 Vdsat = T3 * T0; 1055 double dT0_dVg = -(Abulk * dEsatL_dVg + EsatL * dAbulk_dVg + 1.0)*T1; 1056 double dT0_dVd = -(Abulk * dEsatL_dVd) * T1; 1057 double dT0_dVb = -(Abulk * dEsatL_dVb + dAbulk_dVb * EsatL) * T1; 1058 dVdsat_dVg = T3 * dT0_dVg + T2 * dEsatL_dVg + EsatL * T0; 1059 dVdsat_dVd = T3 * dT0_dVd + T2 * dEsatL_dVd; 1060 dVdsat_dVb = T3 * dT0_dVb + T2 * dEsatL_dVb; 1061 }else{ 1062 tmp1 = dLambda_dVg / (Lambda * Lambda); 1063 double T9 = Abulk * WVCoxRds; 1064 double T8 = Abulk * T9; 1065 double T7 = Vgst2Vtm * T9; 1066 double T6 = Vgst2Vtm * WVCoxRds; 1067 double T0 = 2.0 * Abulk * (T9 - 1.0 + 1.0 / Lambda); 1068 double dT0_dVg = 2.0 * (T8 * tmp2 - Abulk * tmp1 1069 + (2.0 * T9 + 1.0 / Lambda - 1.0) * dAbulk_dVg); 1070 double dT0_dVb = 2.0 * (T8 * (2.0 / Abulk * dAbulk_dVb + tmp3) 1071 + (1.0 / Lambda - 1.0) * dAbulk_dVb); 1072 //double dT0_dVd = 0.0; 1073 1074 double T1 = Vgst2Vtm * (2.0 / Lambda - 1.0) + Abulk * EsatL + 3.0*T7; 1075 double dT1_dVg = (2.0 / Lambda - 1.0) - 2.0 * Vgst2Vtm * tmp1 1076 + Abulk * dEsatL_dVg + EsatL * dAbulk_dVg 1077 + 3.0 * (T9 + T7 * tmp2 + T6 * dAbulk_dVg); 1078 double dT1_dVb = Abulk * dEsatL_dVb + EsatL * dAbulk_dVb 1079 + 3.0 * (T6 * dAbulk_dVb + T7 * tmp3); 1080 double dT1_dVd = Abulk * dEsatL_dVd; 1081 1082 double T2 = Vgst2Vtm * (EsatL + 2.0 * T6); 1083 double dT2_dVg = EsatL + Vgst2Vtm * dEsatL_dVg 1084 + T6 * (4.0 + 2.0 * Vgst2Vtm * tmp2); 1085 double dT2_dVb = Vgst2Vtm * (dEsatL_dVb + 2.0 * T6 * tmp3); 1086 double dT2_dVd = Vgst2Vtm * dEsatL_dVd; 1087 1088 double T3 = sqrt(T1 * T1 - 2.0 * T0 * T2); 1089 Vdsat = (T1 - T3) / T0; 1090 dVdsat_dVg = (dT1_dVg - (T1 * dT1_dVg - dT0_dVg * T2 1091 - T0 * dT2_dVg) / T3 - Vdsat * dT0_dVg) / T0; 1092 dVdsat_dVb = (dT1_dVb - (T1 * dT1_dVb - dT0_dVb * T2 1093 - T0 * dT2_dVb) / T3 - Vdsat * dT0_dVb) / T0; 1094 dVdsat_dVd = (dT1_dVd - (T1 * dT1_dVd - T0 * dT2_dVd) / T3) / T0; 1095 } 1096 d->vdsat = Vdsat; 1097 d->saturated = (d->vds >= d->vdsat); 1098 } 1099 trace1("", tmp1); 1100 trace4("d->vdsat", Vdsat, dVdsat_dVg, dVdsat_dVd, dVdsat_dVb); 1101 1102 // double Vasat, dVasat_dVg, dVasat_dVb, dVasat_dVd; 1103 { 1104 double tmp4 = 1.0 - 0.5 * Abulk * Vdsat / Vgst2Vtm; 1105 double T9 = WVCoxRds * d->vgst; 1106 double T8 = T9 / Vgst2Vtm; 1107 double T0 = EsatL + Vdsat + 2.0 * T9 * tmp4; 1108 double T7 = 2.0 * WVCoxRds * tmp4; 1109 double dT0_dVg = dEsatL_dVg + dVdsat_dVg + T7 * (1.0 + tmp2 * d->vgst) 1110 - T8 * (Abulk * dVdsat_dVg - Abulk * Vdsat / Vgst2Vtm 1111 + Vdsat * dAbulk_dVg); 1112 double dT0_dVb = dEsatL_dVb + dVdsat_dVb + T7 * tmp3 * d->vgst 1113 - T8 * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb); 1114 double dT0_dVd = dEsatL_dVd + dVdsat_dVd - T8 * Abulk * dVdsat_dVd; 1115 T9 = WVCoxRds * Abulk; 1116 double T1 = 2.0 / Lambda - 1.0 + T9; 1117 double dT1_dVg = -2.0 * tmp1 + WVCoxRds * (Abulk * tmp2 + dAbulk_dVg); 1118 double dT1_dVb = dAbulk_dVb * WVCoxRds + T9 * tmp3; 1119 Vasat = T0 / T1; 1120 dVasat_dVg = (dT0_dVg - Vasat * dT1_dVg) / T1; 1121 dVasat_dVb = (dT0_dVb - Vasat * dT1_dVb) / T1; 1122 dVasat_dVd = dT0_dVd / T1; 1123 } 1124 trace4("", Vasat, dVasat_dVg, dVasat_dVb, dVasat_dVd); 1125 } 1126 trace1("", d->vdsat); 1127 trace4("", Vdsat, dVdsat_dVg, dVdsat_dVd, dVdsat_dVb); 1128 trace4("", Vasat, dVasat_dVg, dVasat_dVb, dVasat_dVd); 1129 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1130 /* Effective Vds (Vdseff) Calculation */ 1131 double Vdseff, diffVds, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb; 1132 { 1133 double T1 = Vdsat - d->vds - s->delta; 1134 double dT1_dVg = dVdsat_dVg; 1135 double dT1_dVd = dVdsat_dVd - 1.0; 1136 double dT1_dVb = dVdsat_dVb; 1137 trace4("", T1, dT1_dVg, dT1_dVd, dT1_dVb); 1138 1139 double T2 = sqrt(T1 * T1 + 4.0 * s->delta * Vdsat); 1140 double T0 = T1 / T2; 1141 double T3 = 2.0 * s->delta / T2; 1142 trace3("", T2, T0, T3); 1143 double dT2_dVg = T0 * dT1_dVg + T3 * dVdsat_dVg; 1144 double dT2_dVd = T0 * dT1_dVd + T3 * dVdsat_dVd; 1145 double dT2_dVb = T0 * dT1_dVb + T3 * dVdsat_dVb; 1146 trace3("", dT2_dVg, dT2_dVd, dT2_dVb); 1147 1148 Vdseff = Vdsat - 0.5 * (T1 + T2); 1149 dVdseff_dVg = dVdsat_dVg - 0.5 * (dT1_dVg + dT2_dVg); 1150 dVdseff_dVd = dVdsat_dVd - 0.5 * (dT1_dVd + dT2_dVd); 1151 dVdseff_dVb = dVdsat_dVb - 0.5 * (dT1_dVb + dT2_dVb); 1152 trace4("raw", Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb); 1153 1154 fixzero(&Vdseff, Vdsat); 1155 fixzero(&dVdseff_dVg, dVdsat_dVg); 1156 fixzero(&dVdseff_dVd, dVdsat_dVd); 1157 fixzero(&dVdseff_dVb, dVdsat_dVb); 1158 /* Added to eliminate non-zero Vdseff at Vds=0.0 */ 1159 if (d->vds == 0.0) { 1160 assert(Vdseff == 0.0); 1161 assert(dVdseff_dVg == 0.0); 1162 assert(dVdseff_dVb == 0.0); 1163 } 1164 if (Vdseff > d->vds) { // From Spice, to fix numeric problems. 1165 trace2("numeric problems", Vdseff, d->vds); 1166 Vdseff = d->vds; 1167 } 1168 trace4("fixed", Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb); 1169 1170 diffVds = d->vds - Vdseff; 1171 trace2("", Vdseff, diffVds); 1172 } 1173 trace2("", Vdseff, diffVds); 1174 trace3("", dVdseff_dVg, dVdseff_dVd, dVdseff_dVb); 1175 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1176 /* Calculate Ids */ 1177 double Idsa, dIdsa_dVg, dIdsa_dVd, dIdsa_dVb; 1178 { 1179 double Va, dVa_dVg, dVa_dVd, dVa_dVb; 1180 { 1181 double VACLM, dVACLM_dVg, dVACLM_dVb, dVACLM_dVd; 1182 if ((s->pclm > 0.0) && (diffVds > 1.0e-10)) { 1183 double T0 = 1.0 / (s->pclm * Abulk * s->litl); 1184 double dT0_dVb = -T0 / Abulk * dAbulk_dVb; 1185 double dT0_dVg = -T0 / Abulk * dAbulk_dVg; 1186 double T2 = d->vgst / EsatL; 1187 double T1 = s->leff * (Abulk + T2); 1188 double dT1_dVg = s->leff * ((1.0-T2*dEsatL_dVg)/EsatL + dAbulk_dVg); 1189 double dT1_dVb = s->leff * (dAbulk_dVb - T2 * dEsatL_dVb / EsatL); 1190 double dT1_dVd = -T2 * dEsatL_dVd / Esat; 1191 double T9 = T0 * T1; 1192 VACLM = T9 * diffVds; 1193 dVACLM_dVg = T0 * dT1_dVg * diffVds - T9 * dVdseff_dVg 1194 + T1 * diffVds * dT0_dVg; 1195 dVACLM_dVb = (dT0_dVb*T1 + T0*dT1_dVb) * diffVds - T9 * dVdseff_dVb; 1196 dVACLM_dVd = T0 * dT1_dVd * diffVds + T9 * (1.0 - dVdseff_dVd); 1197 }else{ 1198 VACLM = MAX_EXP; 1199 dVACLM_dVd = dVACLM_dVg = dVACLM_dVb = 0.0; 1200 } 1201 trace4("", VACLM, dVACLM_dVg, dVACLM_dVb, dVACLM_dVd); 1202 1203 double VADIBL, dVADIBL_dVg, dVADIBL_dVb, dVADIBL_dVd; 1204 if (t->thetaRout > 0.0) { 1205 double T8 = Abulk * Vdsat; 1206 double T0 = Vgst2Vtm * T8; 1207 double dT0_dVg = Vgst2Vtm * Abulk * dVdsat_dVg + T8 1208 + Vgst2Vtm * Vdsat * dAbulk_dVg; 1209 double dT0_dVb = Vgst2Vtm * (dAbulk_dVb*Vdsat + Abulk*dVdsat_dVb); 1210 double dT0_dVd = Vgst2Vtm * Abulk * dVdsat_dVd; 1211 double T1 = Vgst2Vtm + T8; 1212 double dT1_dVg = 1.0 + Abulk * dVdsat_dVg + Vdsat * dAbulk_dVg; 1213 double dT1_dVb = Abulk * dVdsat_dVb + dAbulk_dVb * Vdsat; 1214 double dT1_dVd = Abulk * dVdsat_dVd; 1215 double T9 = T1 * T1; 1216 double T2 = t->thetaRout; 1217 VADIBL = (Vgst2Vtm - T0 / T1) / T2; 1218 dVADIBL_dVg = (1.0 - dT0_dVg / T1 + T0 * dT1_dVg / T9) / T2; 1219 dVADIBL_dVb = (-dT0_dVb / T1 + T0 * dT1_dVb / T9) / T2; 1220 dVADIBL_dVd = (-dT0_dVd / T1 + T0 * dT1_dVd / T9) / T2; 1221 1222 double T7 = s->pdiblb * Vbseff; 1223 if (T7 >= -0.9) { 1224 double T3 = 1.0 / (1.0 + T7); 1225 VADIBL *= T3; 1226 dVADIBL_dVg *= T3; 1227 dVADIBL_dVb = (dVADIBL_dVb - VADIBL * s->pdiblb) * T3; 1228 dVADIBL_dVd *= T3; 1229 }else{ 1230 /* Added to avoid the discontinuity problem caused by pdiblcb */ 1231 double T4 = 1.0 / (0.8 + T7); 1232 double T3 = (17.0 + 20.0 * T7) * T4; 1233 dVADIBL_dVg *= T3; 1234 dVADIBL_dVb = dVADIBL_dVb * T3 - VADIBL * s->pdiblb * T4 * T4; 1235 dVADIBL_dVd *= T3; 1236 VADIBL *= T3; 1237 } 1238 }else{ 1239 VADIBL = MAX_EXP; 1240 dVADIBL_dVd = dVADIBL_dVg = dVADIBL_dVb = 0.0; 1241 } 1242 trace4("", VADIBL, dVADIBL_dVg, dVADIBL_dVb, dVADIBL_dVd); 1243 1244 double T8 = s->pvag / EsatL; 1245 double T9 = T8 * d->vgst; 1246 double T0, dT0_dVg, dT0_dVb, dT0_dVd; 1247 if (T9 > -0.9) { 1248 T0 = 1.0 + T9; 1249 dT0_dVg = T8 * (1.0 - d->vgst * dEsatL_dVg / EsatL); 1250 dT0_dVb = -T9 * dEsatL_dVb / EsatL; 1251 dT0_dVd = -T9 * dEsatL_dVd / EsatL; 1252 }else{ 1253 /* Added to avoid the discontinuity problems caused by pvag */ 1254 double T1 = 1.0 / (17.0 + 20.0 * T9); 1255 T0 = (0.8 + T9) * T1; 1256 T1 *= T1; 1257 dT0_dVg = T8 * (1.0 - d->vgst * dEsatL_dVg / EsatL) * T1; 1258 T9 *= T1 / EsatL; 1259 dT0_dVb = -T9 * dEsatL_dVb; 1260 dT0_dVd = -T9 * dEsatL_dVd; 1261 } 1262 double tmp1 = VACLM * VACLM; 1263 double tmp2 = VADIBL * VADIBL; 1264 double tmp3 = VACLM + VADIBL; 1265 1266 double T1 = VACLM * VADIBL / tmp3; 1267 tmp3 *= tmp3; 1268 double dT1_dVg = (tmp1 * dVADIBL_dVg + tmp2 * dVACLM_dVg) / tmp3; 1269 double dT1_dVd = (tmp1 * dVADIBL_dVd + tmp2 * dVACLM_dVd) / tmp3; 1270 double dT1_dVb = (tmp1 * dVADIBL_dVb + tmp2 * dVACLM_dVb) / tmp3; 1271 1272 Va = Vasat + T0 * T1; 1273 dVa_dVg = dVasat_dVg + T1 * dT0_dVg + T0 * dT1_dVg; 1274 dVa_dVd = dVasat_dVd + T1 * dT0_dVd + T0 * dT1_dVd; 1275 dVa_dVb = dVasat_dVb + T1 * dT0_dVb + T0 * dT1_dVb; 1276 } 1277 trace4("", Va, dVa_dVg, dVa_dVd, dVa_dVb); 1278 1279 double Idl, dIdl_dVg, dIdl_dVd, dIdl_dVb; 1280 { 1281 double gche, dgche_dVg, dgche_dVd, dgche_dVb; 1282 { 1283 double beta, dbeta_dVg, dbeta_dVd, dbeta_dVb; 1284 { 1285 double CoxWovL = m->cox * Weff / s->leff; 1286 beta = ueff * CoxWovL; 1287 dbeta_dVg = CoxWovL * dueff_dVg + beta * dWeff_dVg / Weff; 1288 dbeta_dVd = CoxWovL * dueff_dVd; 1289 dbeta_dVb = CoxWovL * dueff_dVb + beta * dWeff_dVb / Weff; 1290 } 1291 trace4("", beta, dbeta_dVg, dbeta_dVd, dbeta_dVb); 1292 1293 double fgche1, dfgche1_dVg, dfgche1_dVd, dfgche1_dVb; 1294 { 1295 double T0 = 1.0 - 0.5 * Abulk * Vdseff / Vgst2Vtm; 1296 double dT0_dVg = -0.5 * (Abulk * dVdseff_dVg 1297 - Abulk * Vdseff / Vgst2Vtm + Vdseff * dAbulk_dVg) / Vgst2Vtm; 1298 double dT0_dVd = -0.5 * Abulk * dVdseff_dVd / Vgst2Vtm; 1299 double dT0_dVb = -0.5 * (Abulk*dVdseff_dVb + dAbulk_dVb*Vdseff) 1300 / Vgst2Vtm; 1301 fgche1 = d->vgst * T0; 1302 dfgche1_dVg = d->vgst * dT0_dVg + T0; 1303 dfgche1_dVd = d->vgst * dT0_dVd; 1304 dfgche1_dVb = d->vgst * dT0_dVb; 1305 } 1306 trace4("", fgche1, dfgche1_dVg, dfgche1_dVd, dfgche1_dVb); 1307 1308 double fgche2, dfgche2_dVg, dfgche2_dVd, dfgche2_dVb; 1309 { 1310 double T9 = Vdseff / EsatL; 1311 fgche2 = 1.0 + T9; 1312 dfgche2_dVg = (dVdseff_dVg - T9 * dEsatL_dVg) / EsatL; 1313 dfgche2_dVd = (dVdseff_dVd - T9 * dEsatL_dVd) / EsatL; 1314 dfgche2_dVb = (dVdseff_dVb - T9 * dEsatL_dVb) / EsatL; 1315 } 1316 trace4("", fgche2, dfgche2_dVg, dfgche2_dVd, dfgche2_dVb); 1317 1318 gche = beta * fgche1 / fgche2; 1319 dgche_dVg = (beta * dfgche1_dVg + fgche1 * dbeta_dVg 1320 - gche * dfgche2_dVg) / fgche2; 1321 dgche_dVd = (beta * dfgche1_dVd + fgche1 * dbeta_dVd 1322 - gche * dfgche2_dVd) / fgche2; 1323 dgche_dVb = (beta * dfgche1_dVb + fgche1 * dbeta_dVb 1324 - gche * dfgche2_dVb) / fgche2; 1325 } 1326 trace4("", gche, dgche_dVg, dgche_dVd, dgche_dVb); 1327 1328 double T0 = 1.0 + gche * Rds; 1329 double T9 = Vdseff / T0; 1330 Idl = gche * T9; 1331 dIdl_dVg = (gche * dVdseff_dVg + T9 * dgche_dVg) / T0 1332 - Idl * gche / T0 * dRds_dVg; 1333 dIdl_dVd = (gche * dVdseff_dVd + T9 * dgche_dVd) / T0; 1334 dIdl_dVb = (gche*dVdseff_dVb + T9*dgche_dVb - Idl*dRds_dVb*gche) / T0; 1335 } 1336 trace4("", Idl, dIdl_dVg, dIdl_dVd, dIdl_dVb); 1337 1338 double T9 = diffVds / Va; 1339 double T0 = 1.0 + T9; 1340 Idsa = Idl * T0; 1341 dIdsa_dVg = T0 * dIdl_dVg - Idl * (dVdseff_dVg + T9 * dVa_dVg) / Va; 1342 dIdsa_dVd = T0 * dIdl_dVd + Idl * (1.0 - dVdseff_dVd - T9*dVa_dVd) / Va; 1343 dIdsa_dVb = T0 * dIdl_dVb - Idl * (dVdseff_dVb + T9 * dVa_dVb) / Va; 1344 } 1345 trace4("", Idsa, dIdsa_dVg, dIdsa_dVd, dIdsa_dVb); 1346 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1347 // d->ids, d->gds, d->gmf, d->gmbf 1348 { 1349 double VASCBE, dVASCBE_dVg, dVASCBE_dVd, dVASCBE_dVb; 1350 if (s->pscbe2 > 0.0) { 1351 if (diffVds > s->pscbe1 * s->litl / EXP_THRESHOLD) { 1352 double T0 = s->pscbe1 * s->litl / diffVds; 1353 VASCBE = s->leff * exp(T0) / s->pscbe2; 1354 double T1 = T0 * VASCBE / diffVds; 1355 dVASCBE_dVg = T1 * dVdseff_dVg; 1356 dVASCBE_dVd = -T1 * (1.0 - dVdseff_dVd); 1357 dVASCBE_dVb = T1 * dVdseff_dVb; 1358 }else{ 1359 VASCBE = MAX_EXP * s->leff/s->pscbe2; 1360 dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; 1361 } 1362 }else{ 1363 VASCBE = MAX_EXP; 1364 dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0; 1365 } 1366 double T9 = diffVds / VASCBE; 1367 double T0 = 1.0 + T9; 1368 double Ids = Idsa * T0; 1369 double Gm = T0*dIdsa_dVg - Idsa*(dVdseff_dVg + T9*dVASCBE_dVg) / VASCBE; 1370 double Gds = T0 * dIdsa_dVd 1371 + Idsa * (1.0 - dVdseff_dVd - T9 * dVASCBE_dVd) / VASCBE; 1372 double Gmb = T0 * dIdsa_dVb 1373 - Idsa * (dVdseff_dVb + T9 * dVASCBE_dVb) / VASCBE; 1374 trace3("", T0, dIdsa_dVb, (T0 * dIdsa_dVb)); 1375 trace4("", dVdseff_dVb, T9, dVASCBE_dVb, (dVdseff_dVb + T9*dVASCBE_dVb)); 1376 trace3("", Idsa, VASCBE, (Idsa*(dVdseff_dVb+T9*dVASCBE_dVb)/VASCBE)); 1377 1378 Gds += Gm * dVgsteff_dVd; 1379 Gmb += Gm * dVgsteff_dVb; 1380 Gm *= dVgsteff_dVg; 1381 Gmb *= dVbseff_dVb; 1382 trace4("", Ids, Gm, Gds, Gmb); 1383 trace0("========================="); 1384 1385 d->gds = Gds; 1386 if (d->reversed) { 1387 d->ids = -Ids; 1388 d->gmr = Gm; 1389 d->gmbr = Gmb; 1390 d->gmf = d->gmbf = 0; 1391 }else{ 1392 d->ids = Ids; 1393 d->gmf = Gm; 1394 d->gmbf = Gmb; 1395 d->gmr = d->gmbr = 0.; 1396 } 1397 } 1398 trace4("", d->ids, d->gds, d->gmf, d->gmbf); 1399 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1400 // d->isub, d->gbbs, d->gbgs, d->gbds 1401 { 1402 /* calculate substrate current Isub */ 1403 double Isub, Gbd, Gbb, Gbg; 1404 if ((s->alpha0 <= 0.0) || (s->beta0 <= 0.0)) { 1405 Isub = Gbd = Gbb = Gbg = 0.0; 1406 trace4("no-isub", Isub, Gbd, Gbb, Gbg); 1407 }else{ 1408 double T2 = s->alpha0 / s->leff; 1409 double T1, dT1_dVg, dT1_dVd, dT1_dVb; 1410 if (diffVds > s->beta0 / EXP_THRESHOLD) { 1411 double T0 = -s->beta0 / diffVds; 1412 T1 = T2 * diffVds * exp(T0); 1413 double T3 = T1 / diffVds * (T0 - 1.0); 1414 trace3("", T0, T2, T3); 1415 dT1_dVg = T3 * dVdseff_dVg; 1416 dT1_dVd = T3 * (dVdseff_dVd - 1.0); 1417 dT1_dVb = T3 * dVdseff_dVb; 1418 trace4("vds > ?", T1, dT1_dVg, dT1_dVd, dT1_dVb); 1419 }else{ 1420 double T3 = T2 * MIN_EXP; 1421 trace2("", T2, T3); 1422 T1 = T3 * diffVds; 1423 dT1_dVg = -T3 * dVdseff_dVg; 1424 dT1_dVd = T3 * (1.0 - dVdseff_dVd); 1425 dT1_dVb = -T3 * dVdseff_dVb; 1426 trace4("vds < ?", T1, dT1_dVg, dT1_dVd, dT1_dVb); 1427 } 1428 Isub = T1 * Idsa; 1429 Gbg = T1 * dIdsa_dVg + Idsa * dT1_dVg; 1430 Gbd = T1 * dIdsa_dVd + Idsa * dT1_dVd; 1431 Gbb = T1 * dIdsa_dVb + Idsa * dT1_dVb; 1432 trace4("raw", Isub, Gbd, Gbb, Gbg); 1433 1434 Gbd += Gbg * dVgsteff_dVd; 1435 Gbb += Gbg * dVgsteff_dVb; 1436 Gbg *= dVgsteff_dVg; 1437 Gbb *= dVbseff_dVb; /* bug fixing */ 1438 } 1439 trace4("", Isub, Gbd, Gbb, Gbg); 1440 if (d->reversed) { 1441 d->idb = Isub; 1442 d->gdbds = Gbd; 1443 d->gdbgs = Gbg; 1444 d->gdbbs = Gbb; 1445 d->isb = d->gsbsd = d->gsbgd = d->gsbbd = 0.; 1446 }else{ 1447 d->idb = d->gdbds = d->gdbgs = d->gdbbs = 0.; 1448 d->isb = Isub; 1449 d->gsbsd = Gbd; 1450 d->gsbgd = Gbg; 1451 d->gsbbd = Gbb; 1452 } 1453 //double d__csub = Isub - (Gbb * Vbseff + Gbd * d->vds + Gbg * d->vgs); 1454 } 1455 trace4("", d->isub, d->gbbs, d->gbgs, d->gbds); 1456 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1457 /* Calculate Qinv for Noise analysis */ 1458 { 1459 //double T1 = d->vgst * (1.0 - 0.5 * Abulk * Vdseff / Vgst2Vtm); 1460 //double d__qinv = -m->cox * Weff * s->leff * T1; 1461 } 1462 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1463 // ends line 2020 (finished) 1464 // d->qgate, d->qdrn, d->qbulk 1465 // d->cggb, d->cgsb, d->cgdb 1466 // d->cdgb, d->cdsb, d->cddb 1467 // d->cbgb, d->cbsb, d->cbdb 1468 { 1469 const bool ChargeComputationNeeded = true; 1470 trace2("", m->xpart, m->capMod); 1471 if ((m->xpart < 0) || (!ChargeComputationNeeded)) { 1472 d->qgate = d->qdrn = d->qbulk = 0.0; 1473 d->cggb = d->cgsb = d->cgdb = 0.0; 1474 d->cdgb = d->cdsb = d->cddb = 0.0; 1475 d->cbgb = d->cbsb = d->cbdb = 0.0; 1476 trace0("xpart < 0 || no charge computation"); 1477 }else if (m->capMod == 0) { 1478 // block ends 1710 this 1454 1479 trace0("begin capMod == 0 (mos7)"); 1480 if (Vbseff < 0.0) { // redefinition 1481 Vbseff = d->vbs; 1482 dVbseff_dVb = 1.0; 1483 }else{ 1484 Vbseff = t->phi - Phis; 1485 dVbseff_dVb = -dPhis_dVb; 1486 } 1487 trace1("old value replaced", dVth_dVb); 1488 double Vfb = s->vfbcv; // possible improper redefinition later 1489 double Vth = Vfb + t->phi + t->k1 * sqrtPhis; 1490 dVth_dVb = t->k1 * dsqrtPhis_dVb; // redefinition 1491 double Vgst = Vgs_eff - Vth; 1492 //double dVgst_dVb = -dVth_dVb; 1493 //double dVgst_dVg = dVgs_eff_dVg; 1494 double CoxWL = m->cox * s->weffCV * s->leffCV; 1495 double Arg1 = Vgs_eff - Vbseff - Vfb; 1496 trace3("", Vfb, Vth, dVth_dVb); 1497 trace3("", Vgst, CoxWL, Arg1); 1498 1499 // ends 1618 this 1328 1500 if (Arg1 <= 0.0) { 1501 trace0("Arg1 <= 0.0"); 1502 1503 d->qgate = CoxWL * Arg1; 1504 d->cggb = CoxWL * dVgs_eff_dVg; 1505 d->cgdb = 0.0; 1506 d->cgsb = CoxWL * (dVbseff_dVb - dVgs_eff_dVg); 1507 1508 d->qbulk = -d->qgate; 1509 d->cbgb = -CoxWL * dVgs_eff_dVg; 1510 d->cbdb = 0.0; 1511 d->cbsb = -d->cgsb; 1512 1513 d->qdrn = 0.0; 1514 d->cdgb = 0.0; 1515 d->cddb = 0.0; 1516 d->cdsb = 0.0; 1517 }else if (Vgst <= 0.0) { 1518 trace0("Vgst <= 0.0"); 1519 double T1 = 0.5 * t->k1; 1520 double T2 = sqrt(T1 * T1 + Arg1); 1521 double T0 = CoxWL * T1 / T2; 1522 1523 d->qgate = CoxWL * t->k1 * (T2 - T1); 1524 d->cggb = T0 * dVgs_eff_dVg; 1525 d->cgdb = 0.0; 1526 d->cgsb = T0 * (dVbseff_dVb - dVgs_eff_dVg); 1527 1528 d->qbulk = -d->qgate; 1529 d->cbgb = -d->cggb; 1530 d->cbdb = 0.0; 1531 d->cbsb = -d->cgsb; 1532 1533 d->qdrn = 0.0; 1534 d->cdgb = 0.0; 1535 d->cddb = 0.0; 1536 d->cdsb = 0.0; 1537 }else{ 1538 trace0("!(Arg1 <= 0.0 || Vgst <= 0.0)"); 1539 double One_Third_CoxWL = CoxWL / 3.0; 1540 double Two_Third_CoxWL = 2.0 * One_Third_CoxWL; 1541 // redefine Vdsat, dVdsat_dVg, dVdsat_dVb 1542 { 1543 double AbulkCV = Abulk0 * s->abulkCVfactor; 1544 double dAbulkCV_dVb = s->abulkCVfactor * dAbulk0_dVb; 1545 Vdsat = Vgst / AbulkCV; 1546 dVdsat_dVg = dVgs_eff_dVg / AbulkCV; 1547 dVdsat_dVb = - (Vdsat * dAbulkCV_dVb + dVth_dVb)/ AbulkCV; 1548 } 1549 if (m->xpart > 0.5) { 1550 /* 0/100 Charge petition model */ 1551 if (d->vds >= Vdsat) { 1552 /* saturation region */ 1553 double T1 = Vdsat / 3.0; 1554 double T2 = -One_Third_CoxWL * dVdsat_dVb; 1555 d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - T1); 1556 d->cggb = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg; 1557 d->cgsb = -(d->cggb + T2); 1558 d->cgdb = 0.0; 1559 1560 double T2a = -Two_Third_CoxWL * Vgst; 1561 double T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); 1562 d->qbulk = -(d->qgate + T2a); 1563 d->cbgb = -(d->cggb - Two_Third_CoxWL * dVgs_eff_dVg); 1564 d->cbsb = -(d->cbgb + T3); 1565 d->cbdb = 0.0; 1566 1567 d->qdrn = 0.0; 1568 d->cdgb = 0.0; 1569 d->cddb = 0.0; 1570 d->cdsb = 0.0; 1571 }else{ 1572 /* linear region */ 1573 double Alphaz = Vgst / Vdsat; 1574 double T1 = 2.0 * Vdsat - d->vds; 1575 double T2 = d->vds / (3.0 * T1); 1576 double T3 = T2 * d->vds; 1577 double T9 = 0.25 * CoxWL; 1578 double T4 = T9 * Alphaz; 1579 double T7 = 2.0 * d->vds - T1 - 3.0 * T3; 1580 double T8 = T3 - T1 - 2.0 * d->vds; 1581 d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - 0.5 * (d->vds-T3)); 1582 double T10 = T4 * T8; 1583 d->qdrn = T4 * T7; 1584 d->qbulk = -(d->qgate + d->qdrn + T10); 1585 1586 double T5 = T3 / T1; 1587 d->cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg; 1588 double T11 = -CoxWL * T5 * dVdsat_dVb; 1589 d->cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); 1590 d->cgsb = -(d->cggb + T11 + d->cgdb); 1591 1592 double T6 = 1.0 / Vdsat; 1593 double dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); 1594 double dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); 1595 T7 = T9 * T7; 1596 T8 = T9 * T8; 1597 T9 = 2.0 * T4 * (1.0 - 3.0 * T5); 1598 d->cdgb = (T7 * dAlphaz_dVg - T9 * dVdsat_dVg) * dVgs_eff_dVg; 1599 double T12 = T7 * dAlphaz_dVb - T9 * dVdsat_dVb; 1600 d->cddb = T4 * (3.0 - 6.0 * T2 - 3.0 * T5); 1601 d->cdsb = -(d->cdgb + T12 + d->cddb); 1602 1603 T9 = 2.0 * T4 * (1.0 + T5); 1604 T10 = (T8 * dAlphaz_dVg - T9 * dVdsat_dVg) * dVgs_eff_dVg; 1605 T11 = T8 * dAlphaz_dVb - T9 * dVdsat_dVb; 1606 T12 = T4 * (2.0 * T2 + T5 - 1.0); 1607 double T0 = -(T10 + T11 + T12); 1608 d->cbgb = -(d->cggb + d->cdgb + T10); 1609 d->cbdb = -(d->cgdb + d->cddb + T12); 1610 d->cbsb = -(d->cgsb + d->cdsb + T0); 1611 } 1612 }else if (m->xpart < 0.5) { 1613 /* 40/60 Charge petition model */ 1614 if (d->vds >= Vdsat) { 1615 /* saturation region */ 1616 double T1 = Vdsat / 3.0; 1617 d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - T1); 1618 double T2 = -Two_Third_CoxWL * Vgst; 1619 d->qbulk = -(d->qgate + T2); 1620 d->qdrn = 0.4 * T2; 1621 1622 d->cggb = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg; 1623 T2 = -One_Third_CoxWL * dVdsat_dVb; 1624 d->cgsb = -(d->cggb + T2); 1625 d->cgdb = 0.0; 1626 1627 double T3 = 0.4 * Two_Third_CoxWL; 1628 d->cdgb = -T3 * dVgs_eff_dVg; 1629 d->cddb = 0.0; 1630 double T4 = T3 * dVth_dVb; 1631 d->cdsb = -(T4 + d->cdgb); 1632 1633 d->cbgb = -(d->cggb - Two_Third_CoxWL * dVgs_eff_dVg); 1634 T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); 1635 d->cbsb = -(d->cbgb + T3); 1636 d->cbdb = 0.0; 1637 }else{ 1638 /* linear region */ 1639 double T1 = 2.0 * Vdsat - d->vds; 1640 double T2 = d->vds / (3.0 * T1); 1641 double T3 = T2 * d->vds; 1642 d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - 0.5 * (d->vds - T3)); 1643 double T5 = T3 / T1; 1644 d->cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg; 1645 double tmp = -CoxWL * T5 * dVdsat_dVb; 1646 d->cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); 1647 d->cgsb = -(d->cggb + d->cgdb + tmp); 1648 1649 double T6 = 1.0 / Vdsat; 1650 double Alphaz = T6 * Vgst; 1651 double dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); 1652 double dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); 1653 T6 = 8.0 * Vdsat * Vdsat - 6.0 * Vdsat * d->vds 1654 + 1.2 * d->vds * d->vds; 1655 double T8 = T2 / T1; 1656 double T7 = d->vds - T1 - T8 * T6; 1657 double T9 = 0.25 * CoxWL; 1658 double T4 = T9 * Alphaz; 1659 d->qdrn = T4 * T7; 1660 T7 *= T9; 1661 tmp = T8 / T1; 1662 double tmp1 = T4 * (2.0 - 4.0 * tmp * T6 1663 + T8 * (16.0 * Vdsat - 6.0 * d->vds)); 1664 d->cdgb = (T7 * dAlphaz_dVg - tmp1 * dVdsat_dVg) * dVgs_eff_dVg; 1665 double T10 = T7 * dAlphaz_dVb - tmp1 * dVdsat_dVb; 1666 d->cddb = T4 * (2.0 - (1.0 / (3.0 * T1 * T1) + 2.0 * tmp) * T6 1667 + T8 * (6.0 * Vdsat - 2.4 * d->vds)); 1668 d->cdsb = -(d->cdgb + T10 + d->cddb); 1669 1670 T7 = 2.0 * (T1 + T3); 1671 d->qbulk = -(d->qgate - T4 * T7); 1672 T7 *= T9; 1673 double T0 = 4.0 * T4 * (1.0 - T5); 1674 double T12 = (-T7 * dAlphaz_dVg - d->cdgb - T0 * dVdsat_dVg) 1675 * dVgs_eff_dVg; 1676 double T11 = -T7 * dAlphaz_dVb - T10 - T0 * dVdsat_dVb; 1677 T10 = -4.0 * T4 * (T2 - 0.5 + 0.5 * T5) - d->cddb; 1678 tmp = -(T10 + T11 + T12); 1679 d->cbgb = -(d->cggb + d->cdgb + T12); 1680 d->cbdb = -(d->cgdb + d->cddb + T11); 1681 d->cbsb = -(d->cgsb + d->cdsb + tmp); 1682 trace3("0,40/60,lin", T10, T11, T12); 1683 trace3("0,40/60,lin", d->cbgb, d->cbdb, d->cbsb); 1684 } 1685 }else{ 1686 /* 50/50 partitioning */ 1687 if (d->vds >= Vdsat) { 1688 /* saturation region */ 1689 double T1 = Vdsat / 3.0; 1690 d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - T1); 1691 double T2 = -Two_Third_CoxWL * Vgst; 1692 d->qbulk = -(d->qgate + T2); 1693 d->qdrn = 0.5 * T2; 1694 1695 T2 = -One_Third_CoxWL * dVdsat_dVb; 1696 d->cggb = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg; 1697 d->cgsb = -(d->cggb + T2); 1698 d->cgdb = 0.0; 1699 1700 double T4 = One_Third_CoxWL * dVth_dVb; 1701 d->cdgb = -One_Third_CoxWL * dVgs_eff_dVg; 1702 d->cddb = 0.0; 1703 d->cdsb = -(T4 + d->cdgb); 1704 1705 double T3 = -(T2 + Two_Third_CoxWL * dVth_dVb); 1706 d->cbgb = -(d->cggb - Two_Third_CoxWL * dVgs_eff_dVg); 1707 d->cbsb = -(d->cbgb + T3); 1708 d->cbdb = 0.0; 1709 }else{ 1710 /* linear region */ 1711 double T1 = 2.0 * Vdsat - d->vds; 1712 double T2 = d->vds / (3.0 * T1); 1713 double T3 = T2 * d->vds; 1714 double T5 = T3 / T1; 1715 double tmp = -CoxWL * T5 * dVdsat_dVb; 1716 d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - 0.5 * (d->vds-T3)); 1717 d->cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg; 1718 d->cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5); 1719 d->cgsb = -(d->cggb + d->cgdb + tmp); 1720 1721 double T6 = 1.0 / Vdsat; 1722 double Alphaz = T6 * Vgst; 1723 double dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg); 1724 double dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb); 1725 1726 double T9 = 0.25 * CoxWL; 1727 double T4 = T9 * Alphaz; 1728 double T7 = T1 + T3; 1729 d->qdrn = -T4 * T7; 1730 d->qbulk = - (d->qgate + d->qdrn + d->qdrn); 1731 1732 T7 *= T9; 1733 double T0 = T4 * (2.0 * T5 - 2.0); 1734 double T12 = T0 * dVdsat_dVb - T7 * dAlphaz_dVb; 1735 d->cdgb = (T0 * dVdsat_dVg - T7 * dAlphaz_dVg) * dVgs_eff_dVg; 1736 d->cddb = T4 * (1.0 - 2.0 * T2 - T5); 1737 d->cdsb = -(d->cdgb + T12 + d->cddb); 1738 1739 d->cbgb = -(d->cggb + 2.0 * d->cdgb); 1740 d->cbdb = -(d->cgdb + 2.0 * d->cddb); 1741 d->cbsb = -(d->cgsb + 2.0 * d->cdsb); 1742 } 1743 } 1744 } // begins 1328 this 1618 1745 trace0("end capMod == 0"); 1746 // end of else if (m->capMod == 0) line 1454 this 1709 1747 }else{ 1748 trace0("begin capMod != 0 (mos7)"); 1749 assert(m->capMod != 0); 1750 double qsrc; 1751 double VbseffCV, dVbseffCV_dVb; 1752 if (Vbseff < 0.0) { 1753 VbseffCV = Vbseff; 1754 dVbseffCV_dVb = 1.0; 1755 }else{ 1756 VbseffCV = t->phi - Phis; 1757 dVbseffCV_dVb = -dPhis_dVb; 1758 } 1759 trace2("", VbseffCV, dVbseffCV_dVb); 1760 1761 //double Vth = d->von; // possibly wrong value -- scope problem 1762 double Vfb = d->von - t->phi - t->k1 * sqrtPhis; 1763 double dVfb_dVb = 0.;//////dVth_dVb - t->k1 * dsqrtPhis_dVb; 1764 double dVfb_dVd = 0.;//////dVth_dVd; 1765 1766 //double Vgst = Vgs_eff - d->von; 1767 1768 //trace3("", d->vgst, Vgst, VgstNVt); 1769 trace2("", n, t->vtm); 1770 1771 double Vgsteff; 1772 { 1773 if ((VgstNVt > -EXP_THRESHOLD) && (VgstNVt < EXP_THRESHOLD)) { 1774 trace0("VgstNVt in range"); 1775 assert(ExpVgst != NOT_VALID); 1776 ExpVgst *= ExpVgst; 1777 ExpVgst = exp(VgstNVt); ////// test 1778 trace1("", ExpVgst); 1779 Vgsteff = n * t->vtm * log(1.0 + ExpVgst); 1780 dVgsteff_dVg = ExpVgst / (1.0 + ExpVgst); 1781 dVgsteff_dVd = -dVgsteff_dVg 1782 * (dVth_dVd + (Vgs_eff - d->von) / n * dn_dVd) 1783 + Vgsteff / n * dn_dVd; 1784 dVgsteff_dVb = -dVgsteff_dVg 1785 * (dVth_dVb + (Vgs_eff - d->von) / n * dn_dVb) 1786 + Vgsteff / n * dn_dVb; 1787 dVgsteff_dVg *= dVgs_eff_dVg; 1788 }else{ 1789 Vgsteff = d->vgst; 1790 } 1791 } 1792 trace4("", Vgsteff, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb); 1793 1794 double CoxWL = m->cox * s->weffCV * s->leffCV; 1795 // redundant?? 1796 1797 if (m->capMod == 1) { 1798 double Cgg, Cgd, Cgb; 1799 { 1800 double Arg1 = Vgs_eff - VbseffCV - Vfb - Vgsteff; 1801 if (Arg1 <= 0.0) { 1802 d->qgate = CoxWL * Arg1; 1803 Cgg = CoxWL * (dVgs_eff_dVg - dVgsteff_dVg); 1804 Cgd = -CoxWL * (dVfb_dVd + dVgsteff_dVd); 1805 Cgb = -CoxWL * (dVfb_dVb + dVbseffCV_dVb + dVgsteff_dVb); 1806 }else{ 1807 double T0 = 0.5 * t->k1; 1808 double T1 = sqrt(T0 * T0 + Arg1); 1809 double T2 = CoxWL * T0 / T1; 1810 d->qgate = CoxWL * t->k1 * (T1 - T0); 1811 Cgg = T2 * (dVgs_eff_dVg - dVgsteff_dVg); 1812 Cgd = -T2 * (dVfb_dVd + dVgsteff_dVd); 1813 Cgb = -T2 * (dVfb_dVb + dVbseffCV_dVb + dVgsteff_dVb); 1814 } 1815 } 1816 d->qbulk = -d->qgate; 1817 double Cbg = -Cgg; 1818 double Cbd = -Cgd; 1819 double Cbb = -Cgb; 1820 1821 double AbulkCV = Abulk0 * s->abulkCVfactor; 1822 double dAbulkCV_dVb = s->abulkCVfactor * dAbulk0_dVb; 1823 1824 double Csg, Csb, Csd; 1825 { 1826 double VdsatCV = Vgsteff / AbulkCV; 1827 if (VdsatCV < d->vds) { 1828 double One_Third_CoxWL = CoxWL / 3.0; 1829 double Two_Third_CoxWL = 2.0 * One_Third_CoxWL; 1830 double dVdsatCV_dVg = 1.0 / AbulkCV; 1831 double dVdsatCV_dVb = -VdsatCV * dAbulkCV_dVb / AbulkCV; 1832 { 1833 double T0 = Vgsteff - VdsatCV / 3.0; 1834 double dT0_dVg = 1.0 - dVdsatCV_dVg / 3.0; 1835 double dT0_dVb = -dVdsatCV_dVb / 3.0; 1836 d->qgate += CoxWL * T0; 1837 double Cgg1 = CoxWL * dT0_dVg; 1838 double Cgb1 = CoxWL * dT0_dVb + Cgg1 * dVgsteff_dVb; 1839 double Cgd1 = Cgg1 * dVgsteff_dVd; 1840 Cgg1 *= dVgsteff_dVg; 1841 Cgg += Cgg1; 1842 Cgb += Cgb1; 1843 Cgd += Cgd1; 1844 } 1845 { 1846 double T0 = VdsatCV - Vgsteff; 1847 double dT0_dVg = dVdsatCV_dVg - 1.0; 1848 double dT0_dVb = dVdsatCV_dVb; 1849 d->qbulk += One_Third_CoxWL * T0; 1850 double Cbg1 = One_Third_CoxWL * dT0_dVg; 1851 double Cbb1 = One_Third_CoxWL * dT0_dVb + Cbg1 * dVgsteff_dVb; 1852 double Cbd1 = Cbg1 * dVgsteff_dVd; 1853 Cbg1 *= dVgsteff_dVg; 1854 Cbg += Cbg1; 1855 Cbb += Cbb1; 1856 Cbd += Cbd1; 1857 } 1858 double T0; 1859 if (m->xpart > 0.5) { 1860 T0 = -Two_Third_CoxWL; 1861 }else if (m->xpart < 0.5) { 1862 T0 = -0.4 * CoxWL; 1863 }else{ 1864 T0 = -One_Third_CoxWL; 1865 } 1866 qsrc = T0 * Vgsteff; 1867 Csg = T0 * dVgsteff_dVg; 1868 Csb = T0 * dVgsteff_dVb; 1869 Csd = T0 * dVgsteff_dVd; 1870 Cgb *= dVbseff_dVb; 1871 Cbb *= dVbseff_dVb; 1872 Csb *= dVbseff_dVb; 1873 }else{ 1874 double T0 = AbulkCV * d->vds; 1875 double T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1.e-20); 1876 double Cgg1, Cgb1, Cgd1, Cbg1, Cbb1, Cbd1; 1877 { 1878 double T2 = d->vds / T1; 1879 double T3 = T0 * T2; 1880 double dT3_dVg = -12.0 * T2 * T2 * AbulkCV; 1881 double dT3_dVd = 6.0 * T0 * (4.0*Vgsteff - T0) / T1 / T1 - 0.5; 1882 double dT3_dVb = 12.0 * T2 * T2 * dAbulkCV_dVb * Vgsteff; 1883 1884 d->qgate += CoxWL * (Vgsteff - 0.5 * d->vds + T3); 1885 Cgg1 = CoxWL * (1.0 + dT3_dVg); 1886 Cgb1 = CoxWL * dT3_dVb + Cgg1 * dVgsteff_dVb; 1887 Cgd1 = CoxWL * dT3_dVd + Cgg1 * dVgsteff_dVd; 1888 Cgg1 *= dVgsteff_dVg; 1889 Cgg += Cgg1; 1890 Cgb += Cgb1; 1891 Cgd += Cgd1; 1892 1893 d->qbulk += CoxWL * (1.0 - AbulkCV) * (0.5 * d->vds - T3); 1894 Cbg1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVg); 1895 Cbb1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVb 1896 + (0.5 * d->vds - T3) * dAbulkCV_dVb) 1897 + Cbg1 * dVgsteff_dVb; 1898 Cbd1 = -CoxWL * (1.0 - AbulkCV) * dT3_dVd 1899 + Cbg1 * dVgsteff_dVd; 1900 Cbg1 *= dVgsteff_dVg; 1901 Cbg += Cbg1; 1902 Cbb += Cbb1; 1903 Cbd += Cbd1; 1904 } 1905 if (m->xpart > 0.5) { 1906 /* 0/100 Charge petition model */ 1907 T1 = T1 + T1; 1908 qsrc = -CoxWL * (0.5 * Vgsteff + 0.25 * T0 - T0 * T0 / T1); 1909 Csg = -CoxWL * (0.5 + 24.0 * T0 * d->vds / T1 / T1 * AbulkCV); 1910 Csb = -CoxWL * (0.25 * d->vds * dAbulkCV_dVb 1911 - 12.0 * T0 * d->vds / T1 / T1 * (4.0 * Vgsteff - T0) 1912 * dAbulkCV_dVb) + Csg * dVgsteff_dVb; 1913 Csd = -CoxWL * (0.25 * AbulkCV - 12.0 * AbulkCV * T0 1914 / T1 / T1 * (4.0 * Vgsteff - T0)) 1915 + Csg * dVgsteff_dVd; 1916 Csg *= dVgsteff_dVg; 1917 }else if (m->xpart < 0.5) { 1918 /* 40/60 Charge petition model */ 1919 T1 = T1 / 12.0; 1920 double T2 = 0.5 * CoxWL / (T1 * T1); 1921 double T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 1922 + Vgsteff * (Vgsteff - 4.0 * T0 / 3.0)) 1923 - 2.0 * T0 * T0 * T0 / 15.0; 1924 qsrc = -T2 * T3; 1925 double T4 = 4.0 / 3.0 * Vgsteff * (Vgsteff-T0) + 0.4 * T0 * T0; 1926 Csg = -2.0 * qsrc / T1 1927 - T2 * (Vgsteff * (3.0 * Vgsteff - 8.0 * T0 / 3.0) 1928 + 2.0 * T0 * T0 / 3.0); 1929 Csb = (qsrc / T1 * d->vds + T2 * T4 * d->vds) * dAbulkCV_dVb 1930 + Csg * dVgsteff_dVb; 1931 Csd = (qsrc / T1 + T2 * T4) * AbulkCV + Csg * dVgsteff_dVd; 1932 Csg *= dVgsteff_dVg; 1933 }else{ 1934 /* 50/50 Charge petition model */ 1935 qsrc = -0.5 * (d->qgate + d->qbulk); 1936 Csg = -0.5 * (Cgg1 + Cbg1); 1937 Csb = -0.5 * (Cgb1 + Cbb1); 1938 Csd = -0.5 * (Cgd1 + Cbd1); 1939 } 1940 Cgb *= dVbseff_dVb; 1941 Cbb *= dVbseff_dVb; 1942 Csb *= dVbseff_dVb; 1943 } 1944 } 1945 d->qdrn = -(d->qgate + d->qbulk + qsrc); 1946 d->cggb = Cgg; 1947 d->cgsb = -(Cgg + Cgd + Cgb); 1948 d->cgdb = Cgd; 1949 d->cdgb = -(Cgg + Cbg + Csg); 1950 d->cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + Csg + Csd + Csb); 1951 d->cddb = -(Cgd + Cbd + Csd); 1952 d->cbgb = Cbg; 1953 d->cbsb = -(Cbg + Cbd + Cbb); 1954 d->cbdb = Cbd; 1955 trace0("end capMod == 1"); 1956 }else if (m->capMod == 2) { 1957 trace0("begin capMod == 2"); 1958 double Qac0, dQac0_dVg, dQac0_dVd, dQac0_dVb; 1959 double Qsub0, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb; 1960 { 1961 double Vfbeff, dVfbeff_dVd, dVfbeff_dVg, dVfbeff_dVb; 1962 { 1963 const double DELTA_3 = 0.02; 1964 double V3 = Vfb - Vgs_eff + VbseffCV - DELTA_3; 1965 double T0, T2; 1966 if (Vfb <= 0.0) { 1967 T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * Vfb); 1968 T2 = -DELTA_3 / T0; 1969 }else{ 1970 T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * Vfb); 1971 T2 = DELTA_3 / T0; 1972 } 1973 double T1 = 0.5 * (1.0 + V3 / T0); 1974 Vfbeff = Vfb - 0.5 * (V3 + T0); 1975 dVfbeff_dVd = (1.0 - T1 - T2) * dVfb_dVd; 1976 dVfbeff_dVg = T1 * dVgs_eff_dVg; 1977 dVfbeff_dVb = (1.0 - T1 - T2) * dVfb_dVb - T1 * dVbseffCV_dVb; 1978 } 1979 trace3("", Vfbeff, dVfbeff_dVg, dVfbeff_dVb); 1980 trace1("", dVfbeff_dVd); 1981 1982 //double Qac0, dQac0_dVg, dQac0_dVd, dQac0_dVb; 1983 { 1984 Qac0 = CoxWL * (Vfbeff - Vfb); 1985 dQac0_dVg = CoxWL * dVfbeff_dVg; 1986 dQac0_dVd = CoxWL * (dVfbeff_dVd - dVfb_dVd); 1987 dQac0_dVb = CoxWL * (dVfbeff_dVb - dVfb_dVb); 1988 } 1989 1990 //double Qsub0, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb; 1991 { 1992 double T0 = 0.5 * t->k1; 1993 double T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff; 1994 double T1, T2; 1995 if (t->k1 == 0.0) { 1996 T1 = 0.0; 1997 T2 = 0.0; 1998 }else if (T3 < 0.0) { 1999 T1 = T0 + T3 / t->k1; 2000 T2 = CoxWL; 2001 }else{ 2002 T1 = sqrt(T0 * T0 + T3); 2003 T2 = CoxWL * T0 / T1; 2004 } 2005 Qsub0 = CoxWL * t->k1 * (T1 - T0); 2006 dQsub0_dVg = T2 * (dVgs_eff_dVg - dVfbeff_dVg - dVgsteff_dVg); 2007 dQsub0_dVd = -T2 * (dVfbeff_dVd + dVgsteff_dVd); 2008 dQsub0_dVb = -T2 * (dVfbeff_dVb +dVbseffCV_dVb +dVgsteff_dVb); 2009 } 2010 } 2011 trace3("", Qac0, dQac0_dVg, dQac0_dVb); 2012 trace1("", dQac0_dVd); 2013 trace4("", Qsub0, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb); 2014 2015 double AbulkCV = Abulk0 * s->abulkCVfactor; 2016 double dAbulkCV_dVb = s->abulkCVfactor * dAbulk0_dVb; 2017 trace2("", AbulkCV, dAbulkCV_dVb); 2018 2019 double VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb; 2020 { 2021 const double DELTA_4 = 0.02; 2022 double VdsatCV = Vgsteff / AbulkCV; 2023 double V4 = VdsatCV - d->vds - DELTA_4; 2024 double T0 = sqrt(V4 * V4 + 4.0 * DELTA_4 * VdsatCV); 2025 VdseffCV = VdsatCV - 0.5 * (V4 + T0); 2026 double T1 = 0.5 * (1.0 + V4 / T0); 2027 double T2 = DELTA_4 / T0; 2028 double T3 = (1.0 - T1 - T2) / AbulkCV; 2029 dVdseffCV_dVg = T3; 2030 dVdseffCV_dVd = T1; 2031 dVdseffCV_dVb = -T3 * VdsatCV * dAbulkCV_dVb; 2032 } 2033 trace4("", VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb); 2034 2035 double T0 = AbulkCV * VdseffCV; 2036 double T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1e-20); 2037 trace2("", T0, T1); 2038 2039 double Cgg1, Cgd1, Cgb1, Cbg1, Cbd1, Cbb1; 2040 // also 1st estimate of d->qgate, d->qbulk 2041 { 2042 double T2 = VdseffCV / T1; 2043 double T3 = T0 * T2; 2044 double T4 = (1.0 - 12.0 * T2 * T2 * AbulkCV); 2045 double T5 = (6.0 * T0 * (4.0 * Vgsteff - T0) / (T1 * T1) - 0.5); 2046 double T6 = 12.0 * T2 * T2 * Vgsteff; 2047 d->qgate = CoxWL * (Vgsteff - 0.5 * VdseffCV + T3); 2048 Cgg1 = CoxWL * (T4 + T5 * dVdseffCV_dVg); 2049 Cgd1 = CoxWL * T5 * dVdseffCV_dVd + Cgg1 * dVgsteff_dVd; 2050 Cgb1 = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) 2051 + Cgg1 * dVgsteff_dVb; 2052 Cgg1 *= dVgsteff_dVg; 2053 2054 double T7 = 1.0 - AbulkCV; 2055 d->qbulk = CoxWL * T7 * (0.5 * VdseffCV - T3); 2056 T4 = -T7 * (T4 - 1.0); 2057 T5 = -T7 * T5; 2058 T6 = -(T7 * T6 + (0.5 * VdseffCV - T3)); 2059 Cbg1 = CoxWL * (T4 + T5 * dVdseffCV_dVg); 2060 Cbd1 = CoxWL * T5 * dVdseffCV_dVd + Cbg1 * dVgsteff_dVd; 2061 Cbb1 = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) 2062 + Cbg1 * dVgsteff_dVb; 2063 Cbg1 *= dVgsteff_dVg; 2064 } 2065 trace3("", Cgg1, Cgd1, Cgb1); 2066 trace3("", Cbg1, Cbd1, Cbb1); 2067 trace2("2-1", d->qgate, d->qbulk); 2068 2069 double Csg, Csd, Csb; 2070 trace1("", m->xpart); 2071 if (m->xpart > 0.5) { 2072 trace0("0/100 Charge petition model"); 2073 T1 = T1 + T1; 2074 qsrc = -CoxWL * (0.5 * Vgsteff + 0.25 * T0 - T0 * T0 / T1); 2075 double T7 = (4.0 * Vgsteff - T0) / (T1 * T1); 2076 double T4 = -(0.5 + 24.0 * T0 * T0 / (T1 * T1)); 2077 double T5 = -(0.25 * AbulkCV - 12.0 * AbulkCV * T0 * T7); 2078 double T6 = -(0.25 * VdseffCV - 12.0 * T0 * VdseffCV * T7); 2079 Csg = CoxWL * (T4 + T5 * dVdseffCV_dVg); 2080 Csd = CoxWL * T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd; 2081 Csb = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) 2082 + Csg * dVgsteff_dVb; 2083 Csg *= dVgsteff_dVg; 2084 }else if (m->xpart < 0.5) { 2085 trace0("40/60 Charge petition model"); 2086 T1 = T1 / 12.0; 2087 double T2 = 0.5 * CoxWL / (T1 * T1); 2088 double T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff 2089 * (Vgsteff - 4.0 * T0 / 3.0)) 2090 - 2.0 * T0 * T0 * T0 / 15.0; 2091 qsrc = -T2 * T3; 2092 double T7 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) + 0.4 * T0 * T0; 2093 double T4 = -2.0 * qsrc / T1 2094 - T2 * (Vgsteff * (3.0 * Vgsteff - 8.0 * T0 / 3.0) 2095 + 2.0 * T0 * T0 / 3.0); 2096 double T5 = (qsrc / T1 + T2 * T7) * AbulkCV; 2097 double T6 = (qsrc / T1 * VdseffCV + T2 * T7 * VdseffCV); 2098 Csg = (T4 + T5 * dVdseffCV_dVg); 2099 Csd = T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd; 2100 Csb = (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb) 2101 + Csg * dVgsteff_dVb; 2102 Csg *= dVgsteff_dVg; 2103 }else{ 2104 trace0("50/50 Charge petition model"); 2105 qsrc = -0.5 * (d->qgate + d->qbulk); 2106 Csg = -0.5 * (Cgg1 + Cbg1); 2107 Csb = -0.5 * (Cgb1 + Cbb1); 2108 Csd = -0.5 * (Cgd1 + Cbd1); 2109 } 2110 trace4("", Csg, Csd, Csb, qsrc); 2111 2112 d->qgate += Qac0 + Qsub0; 2113 d->qbulk -= (Qac0 + Qsub0); 2114 d->qdrn = -(d->qgate + d->qbulk + qsrc); 2115 trace3("2-2", d->qgate, d->qbulk, d->qdrn); 2116 2117 double Cgg = dQac0_dVg + dQsub0_dVg + Cgg1; 2118 double Cgd = dQac0_dVd + dQsub0_dVd + Cgd1; 2119 double Cgb = dQac0_dVb + dQsub0_dVb + Cgb1; 2120 trace3("", Cgg, Cgd, Cgb); 2121 2122 double Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg; 2123 double Cbd = Cbd1 - dQac0_dVd - dQsub0_dVd; 2124 double Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb; 2125 trace3("", Cbg, Cbd, Cbb); 2126 2127 Cgb *= dVbseff_dVb; 2128 Cbb *= dVbseff_dVb; 2129 Csb *= dVbseff_dVb; 2130 trace3("adjusted", Cgb, Cbb, Csb); 2131 2132 d->cggb = Cgg; 2133 d->cgsb = -(Cgg + Cgd + Cgb); 2134 d->cgdb = Cgd; 2135 d->cdgb = -(Cgg + Cbg + Csg); 2136 d->cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + Csg + Csd + Csb); 2137 d->cddb = -(Cgd + Cbd + Csd); 2138 d->cbgb = Cbg; 2139 d->cbsb = -(Cbg + Cbd + Cbb); 2140 d->cbdb = Cbd; 2141 trace0("end capMod == 2"); 2142 }else{ 2143 error(bDANGER, "illegal capmod = %d\n", int(m->capMod)); 2144 d->qbulk = d->qgate = NOT_VALID; 2145 } 2146 2147 /* Non-quasi-static Model */ 2148 double tconst; 2149 if (m->nqsMod) { 2150 // d->gtau 2151 double qcheq = -d->qbulk - d->qgate; 2152 double T0 = s->leffCV * s->leffCV; 2153 tconst = t->u0temp * s->elm / CoxWL / T0; 2154 if (qcheq == 0.0) { 2155 tconst = 0.0; 2156 }else if (qcheq < 0.0) { 2157 tconst = -tconst; 2158 }else{ 2159 } 2160 double gtau_drift = std::abs(tconst * qcheq); 2161 double gtau_diff = 16.0 * t->u0temp * t->vtm / T0; 2162 d->gtau = gtau_drift + gtau_diff; 2163 d->cqgb = -(d->cggb + d->cbgb); 2164 d->cqdb = -(d->cgdb + d->cbdb); 2165 d->cqsb = -(d->cgsb + d->cbsb); 2166 d->cqbb = d->cggb +d->cgdb +d->cgsb +d->cbgb +d->cbdb +d->cbsb; 2167 2168 d->qbulk = d->qgate = d->qdrn = qsrc = 0.0; 2169 d->cggb = d->cgsb = d->cgdb = 0.0; 2170 d->cdgb = d->cdsb = d->cddb = 0.0; 2171 d->cbgb = d->cbsb = d->cbdb = 0.0; 2172#if 0 2173 *(ckt->CKTstate0 + d->qcheq) = qcheq; 2174 if (ckt->CKTmode & MODEINITTRAN) 2175 *(ckt->CKTstate1 + d->qcheq) = *(ckt->CKTstate0 + d->qcheq); 2176 error = NIintegrate(ckt, &geq, &ceq, 0.0, d->qcheq); 2177 if (error) return (error); 2178#endif 2179 }else{ 2180 d->gtau = 0.0; 2181 d->cqgb = d->cqdb = d->cqsb = d->cqbb = 0.0; 2182 } 2183 } 2184 } 2185 trace0("mos7"); 2186 trace3("", d->qgate, d->qdrn, d->qbulk); 2187 trace3("", d->cggb, d->cgsb, d->cgdb); 2188 trace3("", d->cdgb, d->cdsb, d->cddb); 2189 trace3("", d->cbgb, d->cbsb, d->cbdb); 2190 2191 trace2("", d->ids, d->gds); 2192 trace4("", d->gmf, d->gmr, d->gmbf, d->gmbr); 2193 trace4("", d->isub, d->gbbs, d->gbgs, d->gbds); 2194 trace4("", d->qgate, d->cggb, d->cgsb, d->cgdb); 2195 trace4("", d->qdrn, d->cdgb, d->cdsb, d->cddb); 2196 trace4("", d->qbulk, d->cbgb, d->cbsb, d->cbdb); 2197 trace1("", d->gtau); 2198 trace4("", d->cqgb, d->cqsb, d->cqdb, d->cqbb); 2199 trace1("", d->tconst); 2200 trace2("", d->cgb, d->qgb); 2201 trace2("", d->qgd, d->cgd); 2202 trace2("", d->qgs, d->cgs); 2203 trace3("", d->vgs, d->vds, d->vbs); 2204 trace3("", d->vdsat, d->vgst, d->von); 2205 } 2206} 2207/*--------------------------------------------------------------------------*/ 2208/*--------------------------------------------------------------------------*/ 2209