1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: 1988 Jaijeet S Roychowdhury
4 Modified: 2000 AlansFixes
5 **********/
6
7 #include "ngspice/ngspice.h"
8 #include "ngspice/distodef.h"
9 #include "ngspice/devdefs.h"
10 #include "ngspice/cktdefs.h"
11 #include "mos2defs.h"
12 #include "ngspice/trandefs.h"
13 #include "ngspice/const.h"
14 #include "ngspice/sperror.h"
15 #include "ngspice/suffix.h"
16
17 /* assuming silicon - make definition for epsilon of silicon */
18 #define EPSSIL (11.7 * 8.854214871e-12)
19
20 static double sig1[4] = {1.0, -1.0, 1.0, -1.0};
21 static double sig2[4] = {1.0, 1.0,-1.0, -1.0};
22
23 int
MOS2dSetup(GENmodel * inModel,CKTcircuit * ckt)24 MOS2dSetup(GENmodel *inModel, CKTcircuit *ckt)
25 /* actually load the current value into the
26 * sparse matrix previously provided
27 */
28 {
29 MOS2model *model = (MOS2model *)inModel;
30 MOS2instance *here;
31 double Beta;
32 double DrainSatCur;
33 double EffectiveLength;
34 double GateBulkOverlapCap;
35 double GateDrainOverlapCap;
36 double GateSourceOverlapCap;
37 double OxideCap;
38 double SourceSatCur;
39 double arg;
40 double cdrain;
41 double ebd;
42 double evbs;
43 double sarg;
44 double sargsw;
45 double vbd;
46 double vbs;
47 double vds;
48 double vdsat;
49 double vgb;
50 double vgd;
51 double vgs;
52 double von;
53 double vt; /* K * T / Q */
54 double lcapgs2;
55 double lcapgd2;
56 double lcapgb2;
57 double lcapgs3;
58 double lcapgd3;
59 double lcapgb3;
60 double lgbs, lgbs2, lgbs3;
61 double lgbd, lgbd2, lgbd3;
62 double vgst;
63 double lcapbs, lcapbs2, lcapbs3;
64 double lcapbd, lcapbd2, lcapbd3;
65 double gm2, gb2, gds2;
66 double gmb, gmds, gbds;
67 double gm3, gb3, gds3;
68 double gm2b, gm2ds, gmb2, gmds2, gbds2, gb2ds;
69 double gmbds;
70 Dderivs d_cdrain;
71 /*remove compiler warnings */
72 d_cdrain.value = 0.0;
73 d_cdrain.d1_p = 0.0;
74 d_cdrain.d1_q = 0.0;
75 d_cdrain.d1_r = 0.0;
76 d_cdrain.d2_p2 = 0.0;
77 d_cdrain.d2_q2 = 0.0;
78 d_cdrain.d2_r2 = 0.0;
79 d_cdrain.d2_pq = 0.0;
80 d_cdrain.d2_qr = 0.0;
81 d_cdrain.d2_pr = 0.0;
82 d_cdrain.d3_p3 = 0.0;
83 d_cdrain.d3_q3 = 0.0;
84 d_cdrain.d3_r3 = 0.0;
85 d_cdrain.d3_p2q = 0.0;
86 d_cdrain.d3_p2r = 0.0;
87 d_cdrain.d3_pq2 = 0.0;
88 d_cdrain.d3_q2r = 0.0;
89 d_cdrain.d3_pr2 = 0.0;
90 d_cdrain.d3_qr2 = 0.0;
91 d_cdrain.d3_pqr = 0.0;
92
93 /* loop through all the MOS2 device models */
94 for( ; model != NULL; model = MOS2nextModel(model)) {
95
96 /* loop through all the instances of the model */
97 for (here = MOS2instances(model); here != NULL ;
98 here=MOS2nextInstance(here)) {
99
100 vt = CONSTKoverQ * here->MOS2temp;
101
102 EffectiveLength=here->MOS2l - 2*model->MOS2latDiff;
103
104 if( (here->MOS2tSatCurDens == 0) ||
105 (here->MOS2drainArea == 0) ||
106 (here->MOS2sourceArea == 0)) {
107 DrainSatCur = here->MOS2m * here->MOS2tSatCur;
108 SourceSatCur = here->MOS2m * here->MOS2tSatCur;
109 } else {
110 DrainSatCur = here->MOS2tSatCurDens *
111 here->MOS2m * here->MOS2drainArea;
112 SourceSatCur = here->MOS2tSatCurDens *
113 here->MOS2m * here->MOS2sourceArea;
114 }
115 GateSourceOverlapCap = model->MOS2gateSourceOverlapCapFactor *
116 here->MOS2m * here->MOS2w;
117 GateDrainOverlapCap = model->MOS2gateDrainOverlapCapFactor *
118 here->MOS2m * here->MOS2w;
119 GateBulkOverlapCap = model->MOS2gateBulkOverlapCapFactor *
120 here->MOS2m * EffectiveLength;
121 Beta = here->MOS2tTransconductance * here->MOS2m *
122 here->MOS2w/EffectiveLength;
123 OxideCap = model->MOS2oxideCapFactor * EffectiveLength *
124 here->MOS2m * here->MOS2w;
125
126
127
128
129
130 /* general iteration */
131
132
133 vbs = model->MOS2type * (
134 *(ckt->CKTrhsOld+here->MOS2bNode) -
135 *(ckt->CKTrhsOld+here->MOS2sNodePrime));
136 vgs = model->MOS2type * (
137 *(ckt->CKTrhsOld+here->MOS2gNode) -
138 *(ckt->CKTrhsOld+here->MOS2sNodePrime));
139 vds = model->MOS2type * (
140 *(ckt->CKTrhsOld+here->MOS2dNodePrime) -
141 *(ckt->CKTrhsOld+here->MOS2sNodePrime));
142
143 /* now some common crunching for some more useful quantities */
144
145
146 vbd=vbs-vds;
147 vgd=vgs-vds;
148
149 /* now all the preliminaries are over - we can start doing the * real work
150 */
151
152 vgb = vgs - vbs;
153
154 /* bulk-source and bulk-drain doides here we just evaluate
155 * the ideal diode current and the correspoinding
156 * derivative (conductance). */
157 if(vbs <= 0) {
158 lgbs = SourceSatCur/vt;
159 lgbs += ckt->CKTgmin;
160 lgbs2 = lgbs3 = 0;
161 } else {
162 evbs = exp(MIN(MAX_EXP_ARG,vbs/vt));
163 lgbs = SourceSatCur*evbs/vt + ckt->CKTgmin;
164 lgbs2 = model->MOS2type *0.5 * (lgbs - ckt->CKTgmin)/vt;
165 lgbs3 = model->MOS2type *lgbs2/(vt*3);
166
167 }
168 if(vbd <= 0) {
169 lgbd = DrainSatCur/vt;
170 lgbd += ckt->CKTgmin;
171 lgbd2 = lgbd3 = 0;
172 } else {
173 ebd = exp(MIN(MAX_EXP_ARG,vbd/vt));
174 lgbd = DrainSatCur*ebd/vt +ckt->CKTgmin;
175 lgbd2 = model->MOS2type *0.5 * (lgbd - ckt->CKTgmin)/vt;
176 lgbd3 = model->MOS2type *lgbd2/(vt*3);
177 }
178
179 if(vds >= 0) {
180 /* normal mode */
181 here->MOS2mode = 1;
182 } else {
183 /* inverse mode */
184 here->MOS2mode = -1;
185 }
186 {
187 /* moseq2(vds,vbs,vgs,gm,gds,gmbs,qg,qc,qb,
188 * cggb,cgdb,cgsb,cbgb,cbdb,cbsb)
189 */
190 /* note: cgdb, cgsb, cbdb, cbsb never used */
191
192 /*
193 * this routine evaluates the drain current, its derivatives and * the charges associated with the gate, channel and bulk * for mosfets *
194 */
195
196 double arg1;
197 double sarg1;
198 double a4[4],b4[4],x4[8],poly4[8];
199 double beta1;
200 double sphi = 0.0; /* square root of phi */
201 double sphi3 = 0.0; /* square root of phi cubed */
202 double barg;
203 double factor;
204 double eta;
205 double vbin;
206 double argd = 0.0;
207 double args = 0.0;
208 double argss;
209 double argsd;
210 double argxs;
211 double argxd;
212 double gamasd;
213 double xwd;
214 double xws;
215 double gammad;
216 double cfs;
217 double cdonco;
218 double xn;
219 double argg = 0.0;
220 double sarg3;
221 double sbiarg;
222 double body;
223 double udenom;
224 double gammd2;
225 double argv;
226 double vgsx;
227 double ufact;
228 double ueff;
229 double a1;
230 double a3;
231 double a;
232 double b1;
233 double b3;
234 double b;
235 double c1;
236 double c;
237 double d1;
238 double fi;
239 double p0;
240 double p2;
241 double p3;
242 double p4;
243 double p;
244 double r3;
245 double r;
246 double ro;
247 double s2;
248 double s;
249 double v1;
250 double v2;
251 double xv;
252 double y3;
253 double delta4;
254 double xvalid = 0.0;
255 double bsarg = 0.0;
256 double bodys = 0.0;
257 double sargv;
258 double xlfact;
259 double xdv;
260 double xlv;
261 double xls;
262 double clfact;
263 double xleff;
264 double deltal;
265 double xwb;
266 double vdson;
267 double cdson;
268 double expg;
269 double xld;
270 double xlamda = model->MOS2lambda;
271 Dderivs d_xleff, d_delta1;
272 Dderivs d_xlfact;
273 Dderivs d_xlv, d_xls;
274 Dderivs d_bsarg, d_bodys, d_vdsat, d_sargv;
275 Dderivs d_delta4, d_a4[3], d_b4[3], d_x4[3], d_poly4[3];
276 Dderivs d_xvalid;
277 Dderivs d_ro, d_fi, d_y3, d_p3, d_p4, d_a3, d_b3;
278 Dderivs d_r3, d_s2, d_pee, d_p0, d_p2;
279 Dderivs d_b1, d_c1, d_d1, d_a, d_b, d_c, d_arr, d_s;
280 Dderivs d_xv, d_a1;
281 Dderivs d_v1, d_v2;
282 Dderivs d_argv,d_gammd2;
283 Dderivs d_ufact;
284 Dderivs d_udenom;
285 Dderivs d_sarg3, d_body;
286 Dderivs d_vgst;
287 Dderivs d_argg;
288 Dderivs d_cdonco,d_tmp,d_xn;
289 Dderivs d_dbargs,d_dbargd,d_dgddvb;
290 Dderivs d_dbxwd,d_dbxws;
291 Dderivs d_dsrgdb, d_dbrgdb;
292 Dderivs d_gamasd, d_gammad, d_args, d_argd;
293 Dderivs d_argxs, d_argxd;
294 Dderivs d_argss, d_argsd;
295 Dderivs d_xwd, d_xws;
296 Dderivs d_zero;
297 Dderivs d_vbin;
298 Dderivs d_barg;
299 Dderivs d_sarg;
300 Dderivs d_phiMinVbs;
301 Dderivs d_p, d_q, d_r;
302 Dderivs d_von, d_dummy, d_vgsx, d_arg, d_dumarg;
303 Dderivs d_ueff, d_beta1, d_clfact, d_xlamda,d_mos2gds;
304 Dderivs d_vdson, d_cdson, d_expg;
305 double dsrgdb, dbrgdb, dbxwd, dbxws, dbargs = 0.0, dbargd = 0.0;
306 double dgddvb;
307
308
309 /* from now on, p=vgs, q=vbs, r=vds */
310
311 /*
312 * 'local' variables - these switch d & s around appropriately
313 * so that we don't have to worry about vds < 0
314 */
315
316 double lvbs = here->MOS2mode==1?vbs:vbd;
317 double lvds = here->MOS2mode*vds;
318 double lvgs = here->MOS2mode==1?vgs:vgd;
319 double phiMinVbs = here->MOS2tPhi - lvbs;
320 double tmp; /* a temporary variable, not used for more than */
321 /* about 10 lines at a time */
322 int iknt;
323 int jknt;
324 int i;
325 int j;
326
327 /*
328 * compute some useful quantities
329 */
330 d_p.value = 0.0;
331 d_p.d1_p = 1.0;
332 d_p.d1_q = 0.0;
333 d_p.d1_r = 0.0;
334 d_p.d2_p2 = 0.0;
335 d_p.d2_q2 = 0.0;
336 d_p.d2_r2 = 0.0;
337 d_p.d2_pq = 0.0;
338 d_p.d2_qr = 0.0;
339 d_p.d2_pr = 0.0;
340 d_p.d3_p3 = 0.0;
341 d_p.d3_q3 = 0.0;
342 d_p.d3_r3 = 0.0;
343 d_p.d3_p2r = 0.0;
344 d_p.d3_p2q = 0.0;
345 d_p.d3_q2r = 0.0;
346 d_p.d3_pq2 = 0.0;
347 d_p.d3_pr2 = 0.0;
348 d_p.d3_qr2 = 0.0;
349 d_p.d3_pqr = 0.0;
350 EqualDeriv(&d_q,&d_p);
351 EqualDeriv(&d_r,&d_p);
352 EqualDeriv(&d_zero,&d_p);
353 d_q.d1_p = d_r.d1_p = d_zero.d1_p = 0.0;
354 d_q.d1_q = d_r.d1_r = 1.0;
355
356 EqualDeriv(&d_phiMinVbs,&d_q);
357 d_phiMinVbs.value = phiMinVbs;
358 d_phiMinVbs.d1_q = - d_phiMinVbs.d1_q;
359
360 if (lvbs <= 0.0) {
361 sarg1 = sqrt(phiMinVbs);
362 SqrtDeriv(&d_sarg, &d_phiMinVbs);
363 dsrgdb = -0.5/sarg1;
364 InvDeriv(&d_dsrgdb,&d_sarg);
365 TimesDeriv(&d_dsrgdb,&d_dsrgdb,-0.5);
366
367 } else {
368 sphi = sqrt(here->MOS2tPhi); /*const*/
369 sphi3 = here->MOS2tPhi*sphi; /*const*/
370 sarg1 = sphi/(1.0+0.5*lvbs/here->MOS2tPhi);
371 EqualDeriv(&d_sarg,&d_q); d_sarg.value = lvbs;
372 TimesDeriv(&d_sarg,&d_sarg,0.5/here->MOS2tPhi);
373 d_sarg.value += 1.0;
374 InvDeriv(&d_sarg,&d_sarg);
375 TimesDeriv(&d_sarg,&d_sarg,sphi);
376 dsrgdb = -0.5*sarg1*sarg1/sphi3;
377 MultDeriv(&d_dsrgdb,&d_sarg,&d_sarg);
378 TimesDeriv(&d_dsrgdb,&d_dsrgdb,-0.5/sphi3);
379 /* tmp = sarg/sphi3; */
380 }
381 if ((lvds-lvbs) >= 0) {
382 barg = sqrt(phiMinVbs+lvds);
383 EqualDeriv(&d_barg,&d_phiMinVbs);
384 d_barg.value += lvds; d_barg.d1_r += 1.0;
385 SqrtDeriv(&d_barg,&d_barg);
386 dbrgdb = -0.5/barg;
387 InvDeriv(&d_dbrgdb,&d_barg);
388 TimesDeriv(&d_dbrgdb,&d_dbrgdb,-0.5);
389 } else {
390 sphi = sqrt(here->MOS2tPhi); /* added by HT 050523 */
391 sphi3 = here->MOS2tPhi*sphi; /* added by HT 050523 */
392 barg = sphi/(1.0+0.5*(lvbs-lvds)/here->MOS2tPhi);
393 EqualDeriv(&d_barg,&d_q); d_barg.value = lvbs - lvds;
394 d_barg.d1_r -= 1.0;
395 TimesDeriv(&d_barg,&d_barg,0.5/here->MOS2tPhi);
396 d_barg.value += 1.0;
397 InvDeriv(&d_barg,&d_barg);
398 TimesDeriv(&d_barg,&d_barg,sphi);
399 dbrgdb = -0.5*barg*barg/sphi3;
400 MultDeriv(&d_dbrgdb,&d_barg,&d_barg);
401 TimesDeriv(&d_dbrgdb,&d_dbrgdb,-0.5/sphi3);
402 /* tmp = barg/sphi3; */
403 }
404 /*
405 * calculate threshold voltage (von)
406 * narrow-channel effect
407 */
408
409 /*XXX constant per device */
410 factor = 0.125*model->MOS2narrowFactor*2.0*M_PI*EPSSIL/
411 OxideCap*EffectiveLength;
412 /*XXX constant per device */
413 eta = 1.0+factor;
414 vbin = here->MOS2tVbi*model->MOS2type+factor*phiMinVbs;
415 /* mistake! fixed Dec 7 '89
416 TimesDeriv(&d_vbin,&d_phiMinVbs,here->MOS2tVbi*
417 model->MOS2type+factor);
418 */
419 TimesDeriv(&d_vbin,&d_phiMinVbs,factor);
420 d_vbin.value += here->MOS2tVbi*model->MOS2type;
421
422 if ((model->MOS2gamma > 0.0) ||
423 (model->MOS2substrateDoping > 0.0)) {
424 xwd = model->MOS2xd*barg;
425 xws = model->MOS2xd*sarg1;
426 TimesDeriv(&d_xwd,&d_barg,model->MOS2xd);
427 TimesDeriv(&d_xws,&d_sarg,model->MOS2xd);
428
429 /*
430 * short-channel effect with vds .ne. 0.0 */
431
432 argss = 0.0;
433 argsd = 0.0;
434 EqualDeriv(&d_argss,&d_zero);
435 EqualDeriv(&d_argsd,&d_zero);
436 if (model->MOS2junctionDepth > 0) {
437 tmp = 2.0/model->MOS2junctionDepth; /*const*/
438 argxs = 1.0+xws*tmp;
439 TimesDeriv(&d_argxs,&d_xws,tmp);
440 d_argxs.value += 1.0;
441 argxd = 1.0+xwd*tmp;
442 TimesDeriv(&d_argxd,&d_xwd,tmp);
443 d_argxd.value += 1.0;
444 args = sqrt(argxs);
445 SqrtDeriv(&d_args,&d_argxs);
446 argd = sqrt(argxd);
447 SqrtDeriv(&d_argd,&d_argxd);
448 tmp = .5*model->MOS2junctionDepth/EffectiveLength;
449 argss = tmp * (args-1.0);
450 TimesDeriv(&d_argss,&d_args,tmp);
451 d_argss.value -= tmp;
452 argsd = tmp * (argd-1.0);
453 TimesDeriv(&d_argsd,&d_argd,tmp);
454 d_argsd.value -= tmp;
455 }
456 gamasd = model->MOS2gamma*(1.0-argss-argsd);
457 PlusDeriv(&d_gamasd,&d_argss,&d_argsd);
458 d_gamasd.value -= 1.0;
459 TimesDeriv(&d_gamasd,&d_gamasd,-model->MOS2gamma);
460 dbxwd = model->MOS2xd*dbrgdb;
461 dbxws = model->MOS2xd*dsrgdb;
462 TimesDeriv(&d_dbxwd,&d_dbrgdb,model->MOS2xd);
463 TimesDeriv(&d_dbxws,&d_dsrgdb,model->MOS2xd);
464 if (model->MOS2junctionDepth > 0) {
465 tmp = 0.5/EffectiveLength;
466 dbargs = tmp*dbxws/args;
467 dbargd = tmp*dbxwd/argd;
468 DivDeriv(&d_dbargs,&d_dbxws,&d_args);
469 DivDeriv(&d_dbargd,&d_dbxwd,&d_argd);
470 TimesDeriv(&d_dbargs,&d_dbargs,tmp);
471 TimesDeriv(&d_dbargd,&d_dbargd,tmp);
472 }
473 dgddvb = -model->MOS2gamma*(dbargs+dbargd);
474 PlusDeriv(&d_dgddvb,&d_dbargs,&d_dbargd);
475 TimesDeriv(&d_dgddvb,&d_dgddvb,-model->MOS2gamma);
476 if (model->MOS2junctionDepth > 0) {
477 }
478 } else {
479 gamasd = model->MOS2gamma;
480 gammad = model->MOS2gamma;
481 EqualDeriv(&d_gamasd,&d_zero);
482 EqualDeriv(&d_gammad,&d_zero);
483 d_gamasd.value = d_gammad.value = model->MOS2gamma;
484 dgddvb = 0.0;
485 EqualDeriv(&d_dgddvb,&d_zero);
486 }
487 von = vbin+gamasd*sarg1;
488 MultDeriv(&d_von,&d_gamasd,&d_sarg);
489 PlusDeriv(&d_von,&d_von,&d_vbin);
490 /*
491 vth = von;
492 EqualDeriv(&d_vth,&d_von);
493 */
494 vdsat = 0.0;
495 EqualDeriv(&d_vdsat,&d_zero);
496 if (model->MOS2fastSurfaceStateDensity != 0.0 && OxideCap != 0.0) {
497 /* XXX constant per model */
498 cfs = CHARGE*model->MOS2fastSurfaceStateDensity*
499 1e4 /*(cm**2/m**2)*/;
500 cdonco = -(gamasd*dsrgdb + dgddvb*sarg1) + factor;
501 MultDeriv(&d_dummy,&d_dgddvb,&d_sarg);
502 MultDeriv(&d_cdonco,&d_gamasd,&d_dsrgdb);
503 PlusDeriv(&d_cdonco,&d_cdonco,&d_dummy);
504 TimesDeriv(&d_cdonco,&d_cdonco,-1.0);
505 d_cdonco.value += factor;
506 xn = 1.0+cfs/OxideCap*here->MOS2m*here->MOS2w*EffectiveLength+cdonco;
507 EqualDeriv(&d_xn,&d_cdonco);
508 d_xn.value = xn;
509 tmp = vt*xn;
510 TimesDeriv(&d_tmp,&d_xn,vt);
511 von = von+tmp;
512 PlusDeriv(&d_von,&d_von,&d_tmp);
513 argg = 1.0/tmp;
514 InvDeriv(&d_argg,&d_tmp);
515 vgst = lvgs-von;
516 TimesDeriv(&d_vgst,&d_von,-1.0);
517 PlusDeriv(&d_vgst,&d_vgst,&d_p);
518 d_vgst.value += lvgs;
519 } else {
520 vgst = lvgs-von;
521 TimesDeriv(&d_vgst,&d_von,-1.0);
522 PlusDeriv(&d_vgst,&d_vgst,&d_p);
523 d_vgst.value += lvgs;
524
525 if (lvgs <= von) {
526 /*
527 * cutoff region */
528 here->MOS2gds = 0.0; /* look at this later */
529 goto line1050;
530 }
531 }
532
533 /*
534 * compute some more useful quantities */
535
536 sarg3 = sarg1*sarg1*sarg1;
537 CubeDeriv(&d_sarg3,&d_sarg);
538 /* XXX constant per model */
539 sbiarg = sqrt(here->MOS2tBulkPot); /*const*/
540 gammad = gamasd;
541 EqualDeriv(&d_gammad,&d_gamasd);
542 body = barg*barg*barg-sarg3;
543 TimesDeriv(&d_body,&d_sarg3,-1.0);
544 CubeDeriv(&d_dummy,&d_barg);
545 PlusDeriv(&d_body,&d_body,&d_dummy);
546 if (model->MOS2fastSurfaceStateDensity == 0.0) goto line400;
547 if (OxideCap == 0.0) goto line410;
548 /*
549 * evaluate effective mobility and its derivatives */
550 line400:
551 if (OxideCap <= 0.0) goto line410;
552 udenom = vgst;
553 EqualDeriv(&d_udenom,&d_vgst);
554 tmp = model->MOS2critField * 100 /* cm/m */ * EPSSIL/
555 model->MOS2oxideCapFactor;
556 if (udenom <= tmp) goto line410;
557 ufact = exp(model->MOS2critFieldExp*log(tmp/udenom));
558 /* dummy = tmp/udenom */
559 InvDeriv(&d_dummy,&d_udenom);
560 TimesDeriv(&d_dummy,&d_dummy,tmp);
561 PowDeriv(&d_ufact,&d_dummy,model->MOS2critFieldExp);
562 ueff = model->MOS2surfaceMobility * 1e-4 /*(m**2/cm**2) */ *ufact;
563 TimesDeriv(&d_ueff,&d_ufact,model->MOS2surfaceMobility * 1e-4);
564 goto line500;
565 line410:
566 ufact = 0.0;
567 EqualDeriv(&d_ufact,&d_zero);
568 ueff = model->MOS2surfaceMobility * 1e-4 /*(m**2/cm**2) */ ;
569 EqualDeriv(&d_ueff,&d_zero);
570 d_ueff.value = ueff;
571
572 /*
573 * evaluate saturation voltage and its derivatives according to
574 * grove-frohman equation */
575 line500:
576 vgsx = lvgs;
577 EqualDeriv(&d_vgsx,&d_p); d_vgsx.value = lvgs;
578 gammad = gamasd/eta; /* eta is a constant */
579 TimesDeriv(&d_gammad,&d_gamasd,1/eta);
580 if (model->MOS2fastSurfaceStateDensity != 0 && OxideCap != 0) {
581 vgsx = MAX(lvgs,von);
582 /* mistake! fixed Dec 8 '89 if (vgsx < von) { } */
583 if (lvgs > von) {
584 EqualDeriv(&d_vgsx,&d_p);d_vgsx.value = lvgs;
585 } else {
586 EqualDeriv(&d_vgsx,&d_von);
587 }
588 }
589
590 if (gammad > 0) {
591 gammd2 = gammad*gammad;
592 MultDeriv(&d_gammd2,&d_gammad,&d_gammad);
593 argv = (vgsx-vbin)/eta+phiMinVbs;
594 TimesDeriv(&d_argv,&d_vbin,-1.0);
595 PlusDeriv(&d_argv,&d_vgsx,&d_vgsx);
596 TimesDeriv(&d_argv,&d_argv,1/eta);
597 PlusDeriv(&d_argv,&d_argv,&d_phiMinVbs);
598 if (argv <= 0.0) {
599 vdsat = 0.0;
600 EqualDeriv(&d_vdsat,&d_zero);
601 } else {
602 arg1 = sqrt(1.0+4.0*argv/gammd2);
603 DivDeriv(&d_arg,&d_argv,&d_gammd2);
604 TimesDeriv(&d_arg,&d_arg,4.0);d_arg.value += 1.0;
605 SqrtDeriv(&d_arg,&d_arg);
606 #if 0
607 dumarg= sqrt(gammd2*gammd2 +4*argv*gammd2);
608 TimesDeriv(&d_dumarg,&d_argv,4.0);
609 PlusDeriv(&d_dumarg,&d_dumarg,&d_gammd2);
610 MultDeriv(&d_dumarg,&d_dumarg,&d_gammd2);
611 SqrtDeriv(&d_dumarg,&d_dumarg);
612
613 vdsat = (vgsx-vbin)/eta+gammd2*(1.0-arg)/2.0;
614 /* distortion vdsat=(vgsx-vbin)/eta + (gammd2 - dumarg)/2.0
615 = argv - phiMinVbs + (gammd2 - dumarg)/2 */
616 #endif
617 TimesDeriv(&d_dummy,&d_dumarg,-1.0);
618 PlusDeriv(&d_dummy,&d_dummy,&d_gammd2);
619 TimesDeriv(&d_dummy,&d_dummy,0.5);
620 TimesDeriv(&d_vdsat,&d_phiMinVbs,-1.0);
621 PlusDeriv(&d_vdsat,&d_vdsat,&d_argv);
622 PlusDeriv(&d_vdsat,&d_dummy,&d_vdsat);
623 vdsat = MAX(vdsat,0.0);
624 if (vdsat < 0.0) {
625 EqualDeriv(&d_vdsat,&d_zero);
626 }
627 }
628 } else {
629 vdsat = (vgsx-vbin)/eta;
630 TimesDeriv(&d_vdsat,&d_vbin,-1.0);
631 PlusDeriv(&d_vdsat,&d_vgsx,&d_vdsat);
632 TimesDeriv(&d_vdsat,&d_vdsat,1/eta);
633 vdsat = MAX(vdsat,0.0);
634 if (vdsat < 0.0) {
635 EqualDeriv(&d_vdsat,&d_zero);
636 }
637 }
638 if (model->MOS2maxDriftVel > 0) {
639 /*
640 * evaluate saturation voltage and its derivatives
641 * according to baum's theory of scattering velocity
642 * saturation
643 */
644 gammd2 = gammad*gammad;
645 MultDeriv(&d_gammd2,&d_gammad,&d_gammad);
646 v1 = (vgsx-vbin)/eta+phiMinVbs;
647 TimesDeriv(&d_v1,&d_vbin,-1.0);
648 #if 0
649 /* mistake ! (fixed Dec 7 '89) thanks to Jean Hsu */
650 PlusDeriv(&d_v1,&d_vgsx,&d_vgsx);
651 #endif
652 PlusDeriv(&d_v1,&d_v1,&d_vgsx);
653 TimesDeriv(&d_v1,&d_v1,1/eta);
654 PlusDeriv(&d_v1,&d_v1,&d_phiMinVbs);
655 v2 = phiMinVbs;
656 EqualDeriv(&d_v2,&d_phiMinVbs);
657 xv = model->MOS2maxDriftVel*EffectiveLength/ueff;
658 InvDeriv(&d_xv,&d_ueff);
659 TimesDeriv(&d_xv,&d_xv,model->MOS2maxDriftVel*EffectiveLength);
660 a1 = gammad/0.75;
661 TimesDeriv(&d_a1,&d_gammad,4.0/3.0);
662 /* dummy1 = a1 */
663 b1 = -2.0*(v1+xv);
664 PlusDeriv(&d_b1,&d_v1,&d_xv);
665 TimesDeriv(&d_b1,&d_b1,-2.0);
666 /* dummy2 = b1 */
667 c1 = -2.0*gammad*xv;
668 MultDeriv(&d_c1,&d_gammad,&d_xv);
669 TimesDeriv(&d_c1,&d_c1,-2.0);
670 /* dummy3 = c1 */
671 d1 = 2.0*v1*(v2+xv)-v2*v2-4.0/3.0*gammad*sarg3;
672 MultDeriv(&d_d1,&d_gammad,&d_sarg3);
673 TimesDeriv(&d_d1,&d_d1,4.0/3.0);
674 MultDeriv(&d_dummy,&d_v2,&d_v2);
675 PlusDeriv(&d_d1,&d_d1,&d_dummy);
676 TimesDeriv(&d_d1,&d_d1,-1.0);
677 PlusDeriv(&d_dummy,&d_v2,&d_xv);
678 MultDeriv(&d_dummy,&d_dummy,&d_v1);
679 TimesDeriv(&d_dummy,&d_dummy,2.0);
680 PlusDeriv(&d_d1,&d_d1,&d_dummy);
681 a = -b1;
682 TimesDeriv(&d_a,&d_b1,-1.0);
683 b = a1*c1-4.0*d1;
684 TimesDeriv(&d_b,&d_d1,-4.0);
685 MultDeriv(&d_dummy,&d_a1,&d_c1);
686 /* mistake! - fixed Dec 8 '89
687 PlusDeriv(&d_d1,&d_d1,&d_dummy);
688 */
689 PlusDeriv(&d_b,&d_b,&d_dummy);
690 c = -d1*(a1*a1-4.0*b1)-c1*c1;
691 TimesDeriv(&d_dummy,&d_b1,-4.0);
692 MultDeriv(&d_c,&d_a1,&d_a1);
693 PlusDeriv(&d_dummy,&d_dummy,&d_c);
694 MultDeriv(&d_c,&d_dummy,&d_d1);
695 MultDeriv(&d_dummy,&d_c1,&d_c1);
696 PlusDeriv(&d_c,&d_c,&d_dummy);
697 TimesDeriv(&d_c,&d_c,-1.0);
698
699 r = -a*a/3.0+b;
700 MultDeriv(&d_arr,&d_a,&d_a);
701 TimesDeriv(&d_arr,&d_arr,-1.0/3.0);
702 PlusDeriv(&d_arr,&d_arr,&d_b);
703
704 s = 2.0*a*a*a/27.0-a*b/3.0+c;
705 CubeDeriv(&d_s,&d_a);
706 TimesDeriv(&d_s,&d_s,2.0/27.0);
707 PlusDeriv(&d_s,&d_s,&d_c);
708 MultDeriv(&d_dummy,&d_a,&d_b);
709 TimesDeriv(&d_dummy,&d_dummy,-1.0/3.0);
710 PlusDeriv(&d_s,&d_s,&d_dummy);
711
712 r3 = r*r*r;
713 CubeDeriv(&d_r3,&d_arr);
714
715 s2 = s*s;
716 MultDeriv(&d_s2,&d_s,&d_s);
717
718 p = s2/4.0+r3/27.0;
719 TimesDeriv(&d_dummy,&d_r3,1.0/27.0);
720 TimesDeriv(&d_pee,&d_s2,0.25);
721 PlusDeriv(&d_pee,&d_pee,&d_dummy);
722 p0 = fabs(p);
723 if (p < 0.0)
724 /* mistake! fixed Dec 8 '89
725 TimesDeriv(&d_pee,&d_pee, -1.0);
726 */
727 TimesDeriv(&d_p0,&d_pee, -1.0);
728 p2 = sqrt(p0);
729 SqrtDeriv(&d_p2,&d_p0);
730 if (p < 0) {
731 ro = sqrt(s2/4.0+p0);
732 ro = log(ro)/3.0;
733 ro = exp(ro);
734 /* the above is eqvt. to
735 ro = (s2/4.0 + p0)^1/6; */
736 TimesDeriv(&d_ro,&d_s2,0.25);
737 PlusDeriv(&d_ro,&d_ro,&d_p0);
738 PowDeriv(&d_ro,&d_ro,1.0/6.0);
739 fi = atan(-2.0*p2/s);
740 DivDeriv(&d_fi,&d_p2,&d_s);
741 TimesDeriv(&d_fi,&d_fi,-2.0);
742 AtanDeriv(&d_fi,&d_fi);
743 y3 = 2.0*ro*cos(fi/3.0)-a/3.0;
744 TimesDeriv(&d_dummy,&d_fi,1.0/3.0);
745 CosDeriv(&d_dummy,&d_dummy);
746 MultDeriv(&d_y3,&d_ro,&d_dummy);
747 TimesDeriv(&d_y3,&d_y3,2.0);
748 /* mistake! fixed Dec 8 '89
749 TimesDeriv(&d_dummy,&d_a,-3.0);
750 */
751 TimesDeriv(&d_dummy,&d_a,-1/3.0);
752 PlusDeriv(&d_y3,&d_y3,&d_dummy);
753 } else {
754 p3 = (-s/2.0+p2);
755 TimesDeriv(&d_p3,&d_s,-0.5);
756 PlusDeriv(&d_p3,&d_p3,&d_p2);
757 p3 = exp(log(fabs(p3))/3.0);
758 /* eqvt. to (fabs(p3)) ^ 1/3 */
759 if (p3 < 0.0)
760 TimesDeriv(&d_p3,&d_p3,-1.0);
761 PowDeriv(&d_p3,&d_p3,1.0/3.0);
762 p4 = (-s/2.0-p2);
763 TimesDeriv(&d_p4,&d_s,0.5);
764 PlusDeriv(&d_p4,&d_p4,&d_p2);
765 if (p4 < 0.0)
766 TimesDeriv(&d_p4,&d_p4,-1.0); /* this is fabs(p4) */
767 p4 = exp(log(fabs(p4))/3.0);
768 PowDeriv(&d_p4,&d_p4,1.0/3.0);
769
770 y3 = p3+p4-a/3.0;
771 TimesDeriv(&d_y3,&d_a,-1.0/3.0);
772 PlusDeriv(&d_y3,&d_y3,&d_p4);
773 PlusDeriv(&d_y3,&d_y3,&d_p3);
774 }
775 iknt = 0;
776 a3 = sqrt(a1*a1/4.0-b1+y3);
777 MultDeriv(&d_a3,&d_a1,&d_a1);
778 TimesDeriv(&d_a3,&d_a3,0.25);
779 PlusDeriv(&d_a3,&d_a3,&d_y3);
780 TimesDeriv(&d_dummy,&d_b1,-1.0);
781 PlusDeriv(&d_a3,&d_a3,&d_dummy);
782 SqrtDeriv(&d_a3,&d_a3);
783
784 b3 = sqrt(y3*y3/4.0-d1);
785 MultDeriv(&d_b3,&d_y3,&d_y3);
786 TimesDeriv(&d_b3,&d_b3,0.25);
787 TimesDeriv(&d_dummy,&d_d1,-1.0);
788 PlusDeriv(&d_b3,&d_b3,&d_dummy);
789 SqrtDeriv(&d_b3,&d_b3);
790
791 for(i = 1;i<=4;i++) {
792 a4[i-1] = a1/2.0+sig1[i-1]*a3;
793 TimesDeriv(&d_a4[i-1],&d_a1,0.5);
794 TimesDeriv(&d_dummy,&d_a3,sig1[i-1]);
795 PlusDeriv(&d_a4[i-1],&d_a4[i-1],&d_dummy);
796 b4[i-1] = y3/2.0+sig2[i-1]*b3;
797 TimesDeriv(&d_b4[i-1],&d_y3,0.5);
798 TimesDeriv(&d_dummy,&d_b3,sig2[i-1]);
799 PlusDeriv(&d_b4[i-1],&d_b4[i-1],&d_dummy);
800 delta4 = a4[i-1]*a4[i-1]/4.0-b4[i-1];
801 MultDeriv(&d_delta4,&d_a4[i-1],&d_a4[i-1]);
802 TimesDeriv(&d_delta4,&d_delta4,0.25);
803 TimesDeriv(&d_dummy,&d_b4[i-1],-1.0);
804 PlusDeriv(&d_delta4,&d_delta4,&d_dummy);
805
806 if (delta4 < 0) continue;
807 iknt = iknt+1;
808 tmp = sqrt(delta4);
809 SqrtDeriv(&d_tmp,&d_delta4);
810 x4[iknt-1] = -a4[i-1]/2.0+tmp;
811 TimesDeriv(&d_x4[iknt-1],&d_a4[i-1],-0.5);
812 PlusDeriv(&d_x4[iknt-1],&d_x4[iknt-1],&d_tmp);
813 iknt = iknt+1;
814 x4[iknt-1] = -a4[i-1]/2.0-tmp;
815 TimesDeriv(&d_x4[iknt-1],&d_a4[i-1],-0.5);
816 PlusDeriv(&d_x4[iknt-1],&d_x4[iknt-1],&d_tmp);
817 }
818 jknt = 0;
819 for(j = 1;j<=iknt;j++) {
820 if (x4[j-1] <= 0) continue;
821 /* XXX implement this sanely */
822 poly4[j-1] = x4[j-1]*x4[j-1]*x4[j-1]*x4[j-1]+a1*x4[j-1]*
823 x4[j-1]*x4[j-1];
824 CubeDeriv(&d_dummy,&d_x4[j-1]);
825 PlusDeriv(&d_poly4[j-1],&d_x4[j-1],&d_a1);
826 MultDeriv(&d_poly4[j-1],&d_poly4[j-1],&d_dummy);
827 poly4[j-1] = poly4[j-1]+b1*x4[j-1]*x4[j-1]+c1*x4[j-1]+d1;
828 PlusDeriv(&d_poly4[j-1],&d_poly4[j-1],&d_d1);
829 MultDeriv(&d_dummy,&d_b1,&d_x4[j-1]);
830 PlusDeriv(&d_dummy,&d_dummy,&d_c1);
831 MultDeriv(&d_dummy,&d_dummy,&d_x4[j-1]);
832 PlusDeriv(&d_poly4[j-1],&d_poly4[j-1],&d_dummy);
833 if (fabs(poly4[j-1]) > 1.0e-6) continue;
834 jknt = jknt+1;
835 if (jknt <= 1) {
836 xvalid = x4[j-1];
837 EqualDeriv(&d_xvalid,&d_x4[j-1]);
838 }
839 if (x4[j-1] > xvalid) continue;
840 xvalid = x4[j-1];
841 EqualDeriv(&d_xvalid,&d_x4[j-1]);
842 }
843 if (jknt > 0) {
844 vdsat = xvalid*xvalid-phiMinVbs;
845 MultDeriv(&d_vdsat,&d_xvalid,&d_xvalid);
846 TimesDeriv(&d_dummy,&d_phiMinVbs,-1.0);
847 PlusDeriv(&d_vdsat,&d_vdsat,&d_dummy);
848 }
849 }
850 /*
851 * evaluate effective channel length and its derivatives */
852 if (lvds != 0.0) {
853 gammad = gamasd;
854 EqualDeriv(&d_gammad,&d_gamasd);
855 if ((lvbs-vdsat) <= 0) {
856 bsarg = sqrt(vdsat+phiMinVbs);
857 PlusDeriv(&d_bsarg,&d_vdsat,&d_phiMinVbs);
858 SqrtDeriv(&d_bsarg,&d_bsarg);
859
860 } else {
861 bsarg = sphi/(1.0+0.5*(lvbs-vdsat)/here->MOS2tPhi);
862 TimesDeriv(&d_bsarg,&d_vdsat,-1.0);
863 d_bsarg.value += lvbs; d_bsarg.d1_r += 1.0;
864 TimesDeriv(&d_bsarg,&d_bsarg,0.5/here->MOS2tPhi);
865 d_bsarg.value += 1.0;
866 InvDeriv(&d_bsarg,&d_bsarg);
867 TimesDeriv(&d_bsarg,&d_bsarg,sphi);
868
869 }
870 bodys = bsarg*bsarg*bsarg-sarg3;
871 CubeDeriv(&d_bodys,&d_bsarg);
872 TimesDeriv(&d_dummy,&d_sarg3,-1.0);
873 PlusDeriv(&d_bodys,&d_bodys,&d_dummy);
874 if (model->MOS2maxDriftVel <= 0) {
875 if (model->MOS2substrateDoping == 0.0) goto line610;
876 if (xlamda > 0.0) goto line610;
877 argv = (lvds-vdsat)/4.0;
878 TimesDeriv(&d_argv,&d_vdsat,-1.0);
879 d_argv.value += lvds; d_argv.d1_r += 1.0;
880 TimesDeriv(&d_argv,&d_argv,0.25);
881
882 sargv = sqrt(1.0+argv*argv);
883 MultDeriv(&d_sargv,&d_argv,&d_argv);
884 d_sargv.value += 1.0;
885 SqrtDeriv(&d_sargv,&d_sargv);
886 arg1 = sqrt(argv+sargv);
887 PlusDeriv(&d_arg,&d_sargv,&d_argv);
888 SqrtDeriv(&d_arg,&d_arg);
889 xlfact = model->MOS2xd/(EffectiveLength*lvds);
890 EqualDeriv(&d_xlfact,&d_r); d_xlfact.value = lvds;
891 InvDeriv(&d_xlfact,&d_xlfact);
892 TimesDeriv(&d_xlfact,&d_xlfact,model->MOS2xd/EffectiveLength);
893 xlamda = xlfact*arg1;
894 MultDeriv(&d_xlamda,&d_xlfact,&d_arg);
895 } else {
896 argv = (vgsx-vbin)/eta-vdsat;
897 TimesDeriv(&d_argv,&d_vbin,-1.0);
898 PlusDeriv(&d_argv,&d_argv,&d_vgsx);
899 TimesDeriv(&d_argv,&d_argv,1/eta);
900 TimesDeriv(&d_dummy,&d_vdsat,-1.0);
901 PlusDeriv(&d_argv,&d_argv,&d_dummy);
902 xdv = model->MOS2xd/sqrt(model->MOS2channelCharge); /*const*/
903 xlv = model->MOS2maxDriftVel*xdv/(2.0*ueff);
904 InvDeriv(&d_xlv,&d_ueff);
905 TimesDeriv(&d_xlv,&d_xlv,model->MOS2maxDriftVel*xdv*0.5);
906 /* retained for historical interest
907 vqchan = argv-gammad*bsarg;
908 MultDeriv(&d_vqchan,&d_gammad,&d_bsarg);
909 TimesDeriv(&d_vqchan,&d_vqchan,-1);
910 PlusDeriv(&d_vqchan,&d_vqchan,&d_argv);
911 */
912 /* gammad = gamasd
913 vl = model->MOS2maxDriftVel*EffectiveLength;const*/
914 if (model->MOS2substrateDoping == 0.0) goto line610;
915 if (xlamda > 0.0) goto line610;
916 argv = lvds-vdsat;
917 TimesDeriv(&d_argv,&d_vdsat,-1.0);
918 d_argv.value += lvds;
919 d_argv.d1_r += 1.0;
920 if (argv < 0.0)
921 EqualDeriv(&d_argv,&d_zero);
922 argv = MAX(argv,0.0);
923 xls = sqrt(xlv*xlv+argv);
924 MultDeriv(&d_xls,&d_xlv,&d_xlv);
925 PlusDeriv(&d_xls,&d_xls,&d_argv);
926 SqrtDeriv(&d_xls,&d_xls);
927 /* dummy9 = xlv*xlv + argv */
928 xlfact = xdv/(EffectiveLength*lvds);
929 EqualDeriv(&d_xlfact,&d_r);
930 d_xlfact.value += lvds;
931 InvDeriv(&d_xlfact,&d_xlfact);
932 TimesDeriv(&d_xlfact,&d_xlfact,xdv/EffectiveLength);
933 xlamda = xlfact*(xls-xlv);
934 TimesDeriv(&d_xlamda,&d_xlv,-1.0);
935 PlusDeriv(&d_xlamda,&d_xlamda,&d_xls);
936 MultDeriv(&d_xlamda,&d_xlamda,&d_xlfact);
937
938 }
939 }
940 line610:
941
942 /*
943 * limit channel shortening at punch-through */
944 xwb = model->MOS2xd*sbiarg; /*const*/
945 xld = EffectiveLength-xwb; /*const*/
946 clfact = 1.0-xlamda*lvds;
947 EqualDeriv(&d_clfact,&d_r); d_clfact.value = lvds;
948 d_clfact.d1_r = -1;
949 MultDeriv(&d_clfact,&d_clfact,&d_xlamda);
950 d_clfact.value += 1.0;
951 xleff = EffectiveLength*clfact;
952 TimesDeriv(&d_xleff,&d_clfact,EffectiveLength);
953 deltal = xlamda*lvds*EffectiveLength;
954 EqualDeriv(&d_delta1,&d_r);
955 d_delta1.value = EffectiveLength*lvds;
956 d_delta1.d1_r = EffectiveLength;
957 MultDeriv(&d_delta1,&d_delta1,&d_xlamda);
958
959
960 if (model->MOS2substrateDoping == 0.0) xwb = 0.25e-6;
961 if (xleff < xwb) {
962 xleff = xwb/(1.0+(deltal-xld)/xwb);
963 EqualDeriv(&d_xleff,&d_delta1);d_xleff.value -= xld;
964 TimesDeriv(&d_xleff,&d_xleff,1/xwb);d_xleff.value += 1.0;
965 InvDeriv(&d_xleff,&d_xleff);
966 TimesDeriv(&d_xleff,&d_xleff,xwb);
967 clfact = xleff/EffectiveLength;
968 TimesDeriv(&d_clfact,&d_xleff,1/EffectiveLength);
969
970 /* dfact = xleff*xleff/(xwb*xwb); */
971 }
972 /*
973 * evaluate effective beta (effective kp)
974 */
975 beta1 = Beta*ufact/clfact;
976 DivDeriv(&d_beta1,&d_ufact,&d_clfact);
977 TimesDeriv(&d_beta1,&d_beta1,Beta);
978 /*
979 * test for mode of operation and branch appropriately */
980 gammad = gamasd;
981 EqualDeriv(&d_gammad,&d_gamasd);
982 if (lvds <= 1.0e-10) {
983 if (lvgs <= von) {
984 if ((model->MOS2fastSurfaceStateDensity == 0.0) ||
985 (OxideCap == 0.0)) {
986 here->MOS2gds = 0.0;
987 d_cdrain.d1_q = 0.0;
988 d_cdrain.d2_q2 = 0.0;
989 d_cdrain.d3_q3 = 0.0;
990 goto line1050;
991 }
992
993 here->MOS2gds = beta1*(von-vbin-gammad*sarg1)*exp(argg*
994 (lvgs-von));
995 MultDeriv(&d_dummy,&d_gammad,&d_sarg);
996 PlusDeriv(&d_dummy,&d_dummy,&d_vbin);
997 TimesDeriv(&d_dummy,&d_dummy,-1.0);
998 PlusDeriv(&d_dummy,&d_dummy,&d_von);
999 MultDeriv(&d_mos2gds,&d_beta1,&d_dummy);
1000 TimesDeriv(&d_dummy,&d_von,-1.0);
1001 PlusDeriv(&d_dummy,&d_dummy,&d_p);
1002 d_dummy.value += lvgs;
1003 MultDeriv(&d_dummy,&d_dummy,&d_argg);
1004 ExpDeriv(&d_dummy,&d_dummy);
1005 MultDeriv(&d_mos2gds,&d_mos2gds,&d_dummy);
1006 d_cdrain.d1_r = d_mos2gds.value;
1007 d_cdrain.d2_r2 = d_mos2gds.d1_r;
1008 d_cdrain.d3_r3 = d_mos2gds.d2_r2;
1009 /* dummy1 = von - vbin - gamasd*sarg */
1010 goto line1050;
1011 }
1012
1013
1014 here->MOS2gds = beta1*(lvgs-vbin-gammad*sarg1);
1015 MultDeriv(&d_mos2gds,&d_gammad,&d_sarg);
1016 PlusDeriv(&d_mos2gds,&d_mos2gds,&d_vbin);
1017 TimesDeriv(&d_mos2gds,&d_mos2gds,-1.0);
1018 MultDeriv(&d_mos2gds,&d_mos2gds,&d_beta1);
1019 d_cdrain.d1_r = d_mos2gds.value;
1020 d_cdrain.d2_r2 = d_mos2gds.d1_r;
1021 d_cdrain.d3_r3 = d_mos2gds.d2_r2;
1022
1023 goto line1050;
1024 }
1025
1026 if (lvgs > von) goto line900;
1027 /*
1028 * subthreshold region */
1029 if (vdsat <= 0) {
1030 here->MOS2gds = 0.0;
1031 d_cdrain.d1_r = 0.0;
1032 d_cdrain.d2_r2 = 0.0;
1033 d_cdrain.d3_r3 = 0.0;
1034 /* if (lvgs > vth) goto doneval; */
1035 goto line1050;
1036 }
1037 vdson = MIN(vdsat,lvds);
1038 if (vdsat <= lvds) {
1039 EqualDeriv(&d_vdson,&d_vdsat);
1040 } else {
1041 EqualDeriv(&d_vdson,&d_r);
1042 d_vdson.value = lvds;
1043 }
1044 if (lvds > vdsat) {
1045 barg = bsarg;
1046 EqualDeriv(&d_barg,&d_bsarg);
1047 body = bodys;
1048 EqualDeriv(&d_body,&d_bodys);
1049 }
1050 cdson = beta1*((von-vbin-eta*vdson*0.5)*vdson-gammad*body/1.5);
1051 MultDeriv(&d_dummy,&d_gammad,&d_body);
1052 TimesDeriv(&d_cdson,&d_dummy,-1/1.5);
1053 TimesDeriv(&d_dummy,&d_vdson,0.5*eta);
1054 PlusDeriv(&d_dummy,&d_dummy,&d_vbin);
1055 TimesDeriv(&d_dummy,&d_dummy,-1.0);
1056 PlusDeriv(&d_dummy,&d_dummy,&d_von);
1057 MultDeriv(&d_dummy,&d_dummy,&d_vdson);
1058 PlusDeriv(&d_dummy,&d_dummy,&d_cdson);
1059 MultDeriv(&d_cdson,&d_dummy,&d_beta1);
1060 expg = exp(argg*(lvgs-von));
1061 TimesDeriv(&d_expg,&d_von,-1.0);
1062 d_expg.value += lvgs;
1063 d_expg.d1_p += 1.0;
1064 MultDeriv(&d_expg,&d_expg,&d_argg);
1065 ExpDeriv(&d_expg,&d_expg);
1066
1067 cdrain = cdson*expg;
1068 MultDeriv(&d_cdrain,&d_cdson,&d_expg);
1069 /*
1070 gmw = cdrain*argg;
1071 here->MOS2gm = gmw;
1072 tmp = gmw*(lvgs-von)/xn;
1073 */
1074 goto doneval;
1075
1076 line900:
1077 if (lvds <= vdsat) {
1078 /*
1079 * linear region */
1080 cdrain = beta1*((lvgs-vbin-eta*lvds/2.0)*lvds-gammad*body/1.5);
1081 MultDeriv(&d_dummy,&d_gammad,&d_body);
1082 TimesDeriv(&d_dummy,&d_dummy,-1/1.5);
1083 EqualDeriv(&d_cdrain,&d_r);
1084 d_cdrain.value = eta*lvds*0.5;
1085 d_cdrain.d1_r = 0.5*eta;
1086 PlusDeriv(&d_cdrain,&d_cdrain,&d_vbin);
1087 TimesDeriv(&d_cdrain,&d_cdrain,-1.0);
1088 d_cdrain.value += lvgs;
1089 d_cdrain.d1_p += 1.0;
1090 EqualDeriv(&d_dummy,&d_r);
1091 d_dummy.value = lvds;
1092 MultDeriv(&d_cdrain,&d_cdrain,&d_dummy);
1093 MultDeriv(&d_dummy,&d_gammad,&d_body);
1094 TimesDeriv(&d_dummy,&d_dummy,-1/1.5);
1095 PlusDeriv(&d_cdrain,&d_cdrain,&d_dummy);
1096 MultDeriv(&d_cdrain,&d_cdrain,&d_beta1);
1097 } else {
1098 /*
1099 * saturation region */
1100 cdrain = beta1*((lvgs-vbin-eta*
1101 vdsat/2.0)*vdsat-gammad*bodys/1.5);
1102 TimesDeriv(&d_cdrain,&d_vdsat,0.5*eta);
1103 PlusDeriv(&d_cdrain,&d_cdrain,&d_vbin);
1104 TimesDeriv(&d_cdrain,&d_cdrain,-1.0);
1105 d_cdrain.value += lvgs;
1106 d_cdrain.d1_p += 1.0;
1107 MultDeriv(&d_cdrain,&d_cdrain,&d_vdsat);
1108 MultDeriv(&d_dummy,&d_gammad,&d_bodys);
1109 TimesDeriv(&d_dummy,&d_dummy,-1/1.5);
1110 PlusDeriv(&d_cdrain,&d_cdrain,&d_dummy);
1111 MultDeriv(&d_cdrain,&d_cdrain,&d_beta1);
1112 }
1113 /*
1114 * compute charges for "on" region */
1115 goto doneval;
1116 /*
1117 * finish special cases */
1118 line1050:
1119 cdrain = 0.0;
1120 here->MOS2gm = 0.0;
1121 here->MOS2gmbs = 0.0;
1122 d_cdrain.value = 0.0;
1123 d_cdrain.d1_p = 0.0;
1124 d_cdrain.d1_q = 0.0;
1125 d_cdrain.d2_p2 = 0.0;
1126 d_cdrain.d2_q2 = 0.0;
1127 d_cdrain.d2_pq = 0.0;
1128 d_cdrain.d2_qr = 0.0;
1129 d_cdrain.d2_pr = 0.0;
1130 d_cdrain.d3_p3 = 0.0;
1131 d_cdrain.d3_q3 = 0.0;
1132 d_cdrain.d3_p2r = 0.0;
1133 d_cdrain.d3_p2q = 0.0;
1134 d_cdrain.d3_q2r = 0.0;
1135 d_cdrain.d3_pq2 = 0.0;
1136 d_cdrain.d3_pr2 = 0.0;
1137 d_cdrain.d3_qr2 = 0.0;
1138 d_cdrain.d3_pqr = 0.0;
1139 }
1140
1141 /*
1142 * finished
1143 */
1144
1145 /*================HERE=================*/
1146 doneval:
1147 /*
1148 * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE
1149 */
1150 /*
1151 * now we do the hard part of the bulk-drain and bulk-source
1152 * diode - we evaluate the non-linear capacitance and
1153 * charge
1154 * the basic equations are not hard, but the implementation
1155 * is somewhat long in an attempt to avoid log/exponential
1156 * evaluations
1157 */
1158 /*
1159 * charge storage elements *
1160 *.. bulk-drain and bulk-source depletion capacitances
1161 */
1162 if (vbs < here->MOS2tDepCap){
1163 arg=1-vbs/here->MOS2tBulkPot;
1164 /*
1165 * the following block looks somewhat long and messy,
1166 * but since most users use the default grading
1167 * coefficients of .5, and sqrt is MUCH faster than an
1168 * exp(log()) we use this special case code to buy time.
1169 * (as much as 10% of total job time!)
1170 */
1171 if(model->MOS2bulkJctBotGradingCoeff ==
1172 model->MOS2bulkJctSideGradingCoeff) {
1173 if(model->MOS2bulkJctBotGradingCoeff == .5) {
1174 sarg = sargsw = 1/sqrt(arg);
1175 } else {
1176 sarg = sargsw =
1177 exp(-model->MOS2bulkJctBotGradingCoeff*
1178 log(arg));
1179 }
1180 } else {
1181 if(model->MOS2bulkJctBotGradingCoeff == .5) {
1182 sarg = 1/sqrt(arg);
1183 } else {
1184 sarg = exp(-model->MOS2bulkJctBotGradingCoeff*
1185 log(arg));
1186 }
1187 if(model->MOS2bulkJctSideGradingCoeff == .5) {
1188 sargsw = 1/sqrt(arg);
1189 } else {
1190 sargsw =exp(-model->MOS2bulkJctSideGradingCoeff*
1191 log(arg));
1192 }
1193 }
1194 lcapbs=here->MOS2Cbs*sarg+
1195 here->MOS2Cbssw*sargsw;
1196 lcapbs2 = model->MOS2type*0.5/here->MOS2tBulkPot*(
1197 here->MOS2Cbs*model->MOS2bulkJctBotGradingCoeff*
1198 sarg/arg + here->MOS2Cbssw*
1199 model->MOS2bulkJctSideGradingCoeff*sargsw/arg);
1200 lcapbs3 = here->MOS2Cbs*sarg*
1201 model->MOS2bulkJctBotGradingCoeff*
1202 (model->MOS2bulkJctBotGradingCoeff+1);
1203 lcapbs3 += here->MOS2Cbssw*sargsw*
1204 model->MOS2bulkJctSideGradingCoeff*
1205 (model->MOS2bulkJctSideGradingCoeff+1);
1206 lcapbs3 = lcapbs3/(6*here->MOS2tBulkPot*
1207 here->MOS2tBulkPot*arg*arg);
1208 } else {
1209 /* *(ckt->CKTstate0 + here->MOS2qbs)= here->MOS2f4s +
1210 vbs*(here->MOS2f2s+vbs*(here->MOS2f3s/2));*/
1211 lcapbs=here->MOS2f2s+here->MOS2f3s*vbs;
1212 lcapbs2 = 0.5*here->MOS2f3s;
1213 lcapbs3 = 0;
1214 }
1215 if (vbd < here->MOS2tDepCap) {
1216 arg=1-vbd/here->MOS2tBulkPot;
1217 /*
1218 * the following block looks somewhat long and messy,
1219 * but since most users use the default grading
1220 * coefficients of .5, and sqrt is MUCH faster than an
1221 * exp(log()) we use this special case code to buy time.
1222 * (as much as 10% of total job time!)
1223 */
1224 if(model->MOS2bulkJctBotGradingCoeff == .5 &&
1225 model->MOS2bulkJctSideGradingCoeff == .5) {
1226 sarg = sargsw = 1/sqrt(arg);
1227 } else {
1228 if(model->MOS2bulkJctBotGradingCoeff == .5) {
1229 sarg = 1/sqrt(arg);
1230 } else {
1231 sarg = exp(-model->MOS2bulkJctBotGradingCoeff*
1232 log(arg));
1233 }
1234 if(model->MOS2bulkJctSideGradingCoeff == .5) {
1235 sargsw = 1/sqrt(arg);
1236 } else {
1237 sargsw =exp(-model->MOS2bulkJctSideGradingCoeff*
1238 log(arg));
1239 }
1240 }
1241 lcapbd=here->MOS2Cbd*sarg+
1242 here->MOS2Cbdsw*sargsw;
1243 lcapbd2 = model->MOS2type*0.5/here->MOS2tBulkPot*(
1244 here->MOS2Cbd*model->MOS2bulkJctBotGradingCoeff*
1245 sarg/arg + here->MOS2Cbdsw*
1246 model->MOS2bulkJctSideGradingCoeff*sargsw/arg);
1247 lcapbd3 = here->MOS2Cbd*sarg*
1248 model->MOS2bulkJctBotGradingCoeff*
1249 (model->MOS2bulkJctBotGradingCoeff+1);
1250 lcapbd3 += here->MOS2Cbdsw*sargsw*
1251 model->MOS2bulkJctSideGradingCoeff*
1252 (model->MOS2bulkJctSideGradingCoeff+1);
1253 lcapbd3 = lcapbd3/(6*here->MOS2tBulkPot*
1254 here->MOS2tBulkPot*arg*arg);
1255 } else {
1256 lcapbd=here->MOS2f2d + vbd * here->MOS2f3d;
1257 lcapbd2=0.5*here->MOS2f3d;
1258 lcapbd3=0;
1259 }
1260 /*
1261 * meyer's capacitor model */
1262 /*
1263 * the meyer capacitance equations are in DEVqmeyer
1264 * these expressions are derived from those equations.
1265 * these expressions are incorrect; they assume just one
1266 * controlling variable for each charge storage element
1267 * while actually there are several; the MOS2 small
1268 * signal ac linear model is also wrong because it
1269 * ignores controlled capacitive elements. these can be
1270 * corrected (as can the linear ss ac model) if the
1271 * expressions for the charge are available
1272 */
1273
1274
1275 {
1276
1277
1278 double phi;
1279 double cox;
1280 double vddif;
1281 double vddif1;
1282 double vddif2;
1283 /* von, vgst and vdsat have already been adjusted for
1284 possible source-drain interchange */
1285
1286
1287
1288 phi = here->MOS2tPhi;
1289 cox = OxideCap;
1290 if (vgst <= -phi) {
1291 lcapgb2=lcapgb3=lcapgs2=lcapgs3=lcapgd2=lcapgd3=0;
1292 } else if (vgst <= -phi/2) {
1293 lcapgb2= -cox/(4*phi);
1294 lcapgb3=lcapgs2=lcapgs3=lcapgd2=lcapgd3=0;
1295 } else if (vgst <= 0) {
1296 lcapgb2= -cox/(4*phi);
1297 lcapgb3=lcapgs3=lcapgd2=lcapgd3=0;
1298 lcapgs2 = cox/(3*phi);
1299 } else { /* the MOS2modes are around because
1300 vds has not been adjusted */
1301 if (vdsat <= here->MOS2mode*vds) {
1302 lcapgb2=lcapgb3=lcapgs2=lcapgs3=lcapgd2=lcapgd3=0;
1303 } else {
1304 vddif = 2.0*vdsat-here->MOS2mode*vds;
1305 vddif1 = vdsat-here->MOS2mode*vds/*-1.0e-12*/;
1306 vddif2 = vddif*vddif;
1307 lcapgd2 = -vdsat*here->MOS2mode*vds*cox/(3*vddif*vddif2);
1308 lcapgd3 = - here->MOS2mode*vds*cox*(vddif - 6*vdsat)/(9*vddif2*vddif2);
1309 lcapgs2 = -vddif1*here->MOS2mode*vds*cox/(3*vddif*vddif2);
1310 lcapgs3 = - here->MOS2mode*vds*cox*(vddif - 6*vddif1)/(9*vddif2*vddif2);
1311 lcapgb2=lcapgb3=0;
1312 }
1313 }
1314 }
1315
1316 /* the b-s and b-d diodes need no processing ... */
1317 here->capbs2 = lcapbs2;
1318 here->capbs3 = lcapbs3;
1319 here->capbd2 = lcapbd2;
1320 here->capbd3 = lcapbd3;
1321 here->gbs2 = lgbs2;
1322 here->gbs3 = lgbs3;
1323 here->gbd2 = lgbd2;
1324 here->gbd3 = lgbd3;
1325 here->capgb2 = model->MOS2type*lcapgb2;
1326 here->capgb3 = lcapgb3;
1327 /*
1328 * process to get Taylor coefficients, taking into * account type and mode.
1329 */
1330 gm2 = d_cdrain.d2_p2;
1331 gb2 = d_cdrain.d2_q2;
1332 gds2 = d_cdrain.d2_r2;
1333 gmb = d_cdrain.d2_pq;
1334 gbds = d_cdrain.d2_qr;
1335 gmds = d_cdrain.d2_pr;
1336 gm3 = d_cdrain.d3_p3;
1337 gb3 = d_cdrain.d3_q3;
1338 gds3 = d_cdrain.d3_r3;
1339 gm2ds = d_cdrain.d3_p2r;
1340 gm2b = d_cdrain.d3_p2q;
1341 gb2ds = d_cdrain.d3_q2r;
1342 gmb2 = d_cdrain.d3_pq2;
1343 gmds2 = d_cdrain.d3_pr2;
1344 gbds2 = d_cdrain.d3_qr2;
1345 gmbds = d_cdrain.d3_pqr;
1346
1347 if (here->MOS2mode == 1)
1348 {
1349 /* normal mode - no source-drain interchange */
1350
1351 here->cdr_x2 = gm2;
1352 here->cdr_y2 = gb2;
1353 here->cdr_z2 = gds2;
1354 here->cdr_xy = gmb;
1355 here->cdr_yz = gbds;
1356 here->cdr_xz = gmds;
1357 here->cdr_x3 = gm3;
1358 here->cdr_y3 = gb3;
1359 here->cdr_z3 = gds3;
1360 here->cdr_x2z = gm2ds;
1361 here->cdr_x2y = gm2b;
1362 here->cdr_y2z = gb2ds;
1363 here->cdr_xy2 = gmb2;
1364 here->cdr_xz2 = gmds2;
1365 here->cdr_yz2 = gbds2;
1366 here->cdr_xyz = gmbds;
1367
1368 /* the gate caps have been divided and made into Taylor coeffs., but not adjusted for type */
1369
1370 here->capgs2 = model->MOS2type*lcapgs2;
1371 here->capgs3 = lcapgs3;
1372 here->capgd2 = model->MOS2type*lcapgd2;
1373 here->capgd3 = lcapgd3;
1374 } else {
1375 /*
1376 * inverse mode - source and drain interchanged */
1377 here->cdr_x2 = -gm2;
1378 here->cdr_y2 = -gb2;
1379 here->cdr_z2 = -(gm2 + gb2 + gds2 + 2*(gmb + gmds + gbds));
1380 here->cdr_xy = -gmb;
1381 here->cdr_yz = gmb + gb2 + gbds;
1382 here->cdr_xz = gm2 + gmb + gmds;
1383 here->cdr_x3 = -gm3;
1384 here->cdr_y3 = -gb3;
1385 here->cdr_z3 = gm3 + gb3 + gds3 +
1386 3*(gm2b + gm2ds + gmb2 + gb2ds + gmds2 + gbds2) + 6*gmbds ;
1387 here->cdr_x2z = gm3 + gm2b + gm2ds;
1388 here->cdr_x2y = -gm2b;
1389 here->cdr_y2z = gmb2 + gb3 + gb2ds;
1390 here->cdr_xy2 = -gmb2;
1391 here->cdr_xz2 = -(gm3 + 2*(gm2b + gm2ds + gmbds) +
1392 gmb2 + gmds2);
1393 here->cdr_yz2 = -(gb3 + 2*(gmb2 + gb2ds + gmbds) +
1394 gm2b + gbds2);
1395 here->cdr_xyz = gm2b + gmb2 + gmbds;
1396
1397 here->capgs2 = model->MOS2type*lcapgd2;
1398 here->capgs3 = lcapgd3;
1399
1400 here->capgd2 = model->MOS2type*lcapgs2;
1401 here->capgd3 = lcapgs3;
1402
1403 }
1404
1405 /* now to adjust for type and multiply by factors to convert to Taylor coeffs. */
1406
1407 here->cdr_x2 = 0.5*model->MOS2type*here->cdr_x2;
1408 here->cdr_y2 = 0.5*model->MOS2type*here->cdr_y2;
1409 here->cdr_z2 = 0.5*model->MOS2type*here->cdr_z2;
1410 here->cdr_xy = model->MOS2type*here->cdr_xy;
1411 here->cdr_yz = model->MOS2type*here->cdr_yz;
1412 here->cdr_xz = model->MOS2type*here->cdr_xz;
1413 here->cdr_x3 = here->cdr_x3/6.;
1414 here->cdr_y3 = here->cdr_y3/6.;
1415 here->cdr_z3 = here->cdr_z3/6.;
1416 here->cdr_x2z = 0.5*here->cdr_x2z;
1417 here->cdr_x2y = 0.5*here->cdr_x2y;
1418 here->cdr_y2z = 0.5*here->cdr_y2z;
1419 here->cdr_xy2 = 0.5*here->cdr_xy2;
1420 here->cdr_xz2 = 0.5*here->cdr_xz2;
1421 here->cdr_yz2 = 0.5*here->cdr_yz2;
1422
1423
1424 }
1425 }
1426 return(OK);
1427 }
1428