1 /**** BSIM4.7.0 Released by Darsen Lu 04/08/2011 ****/
2 
3 /**********
4  * Copyright 2006 Regents of the University of California. All rights reserved.
5  * File: b4check.c of BSIM4.7.0.
6  * Author: 2000 Weidong Liu
7  * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu.
8  * Authors: 2006- Mohan Dunga, Ali Niknejad, Chenming Hu
9  * Authors: 2007- Mohan Dunga, Wenwei Yang, Ali Niknejad, Chenming Hu
10  * Project Director: Prof. Chenming Hu.
11  * Modified by Xuemei Xi, 04/06/2001.
12  * Modified by Xuemei Xi, 10/05/2001.
13  * Modified by Xuemei Xi, 11/15/2002.
14  * Modified by Xuemei Xi, 05/09/2003.
15  * Modified by Xuemei Xi, 03/04/2004.
16  * Modified by Xuemei Xi, 07/29/2005.
17  * Modified by Mohan Dunga, 12/13/2006
18  * Modified by Mohan Dunga, Wenwei Yang, 05/18/2007.
19  * Modified by  Wenwei Yang, 07/31/2008 .
20  * Modified by Tanvir Morshed, Darsen Lu 03/27/2011
21  * Modified by Holger Vogt, 12/27/2020.
22  **********/
23 
24 #include "ngspice/ngspice.h"
25 #include "ngspice/cktdefs.h"
26 #include "bsim4v7def.h"
27 #include "ngspice/trandefs.h"
28 #include "ngspice/const.h"
29 #include "ngspice/sperror.h"
30 #include "ngspice/devdefs.h"
31 #include "ngspice/suffix.h"
32 #include "ngspice/wordlist.h"
33 #include "ngspice/cpextern.h"
34 
35 
36 
37 /* Check for correctness of the BSIM4.7 parameters:
38    If parameter excursions are found, put the warning or error message into a wordlist.
39    Only then open a file bsim4v7.out and print the data into the file. */
40 int
BSIM4v7checkModel(BSIM4v7model * model,BSIM4v7instance * here,CKTcircuit * ckt)41 BSIM4v7checkModel(
42 BSIM4v7model *model,
43 BSIM4v7instance *here,
44 CKTcircuit *ckt)
45 {
46     struct bsim4SizeDependParam *pParam;
47     int Fatal_Flag = 0;
48     FILE *fplog;
49     wordlist* wl, *wlstart;
50 
51     pParam = here->pParam;
52 
53     if (cp_getvar("ng_nomodcheck", CP_BOOL, NULL, 0))
54         return(0);
55 
56     wl = wlstart = TMALLOC(wordlist, 1);
57     wl->wl_prev = NULL;
58     wl->wl_next = NULL;
59     wl->wl_word = tprintf("\nChecking parameters for BSIM 4.7 model %s\n", model->BSIM4v7modName);
60 
61     if ((here->BSIM4v7rgateMod == 2) || (here->BSIM4v7rgateMod == 3))
62     {   if ((here->BSIM4v7trnqsMod == 1) || (here->BSIM4v7acnqsMod == 1)) {
63             wl_append_word(&wl, &wl, tprintf("Warning: You've selected both Rg and charge deficit NQS; select one only.\n"));
64         }
65     }
66 
67     if (model->BSIM4v7toxe <= 0.0)
68     {
69          wl_append_word(&wl, &wl, tprintf("Fatal: Toxe = %g is not positive.\n",
70             model->BSIM4v7toxe));
71         Fatal_Flag = 1;
72     }
73 
74     if (model->BSIM4v7toxp <= 0.0)
75     {
76         wl_append_word(&wl, &wl, tprintf("Fatal: Toxp = %g is not positive.\n", model->BSIM4v7toxp));
77         Fatal_Flag = 1;
78     }
79 
80     if (model->BSIM4v7eot <= 0.0)
81     {
82         wl_append_word(&wl, &wl, tprintf("Fatal: EOT = %g is not positive.\n", model->BSIM4v7eot));
83         Fatal_Flag = 1;
84     }
85     if (model->BSIM4v7epsrgate < 0.0)
86     {
87         wl_append_word(&wl, &wl, tprintf("Fatal: Epsrgate = %g is not positive.\n", model->BSIM4v7epsrgate));
88         Fatal_Flag = 1;
89     }
90     if (model->BSIM4v7epsrsub < 0.0)
91     {
92         wl_append_word(&wl, &wl, tprintf("Fatal: Epsrsub = %g is not positive.\n", model->BSIM4v7epsrsub));
93         Fatal_Flag = 1;
94     }
95     if (model->BSIM4v7easub < 0.0)
96     {
97         wl_append_word(&wl, &wl, tprintf("Fatal: Easub = %g is not positive.\n", model->BSIM4v7easub));
98         Fatal_Flag = 1;
99     }
100     if (model->BSIM4v7ni0sub <= 0.0)
101     {
102         wl_append_word(&wl, &wl, tprintf("Fatal: Easub = %g is not positive.\n", model->BSIM4v7ni0sub));
103         Fatal_Flag = 1;
104     }
105 
106     if (model->BSIM4v7toxm <= 0.0)
107     {
108         wl_append_word(&wl, &wl, tprintf("Fatal: Toxm = %g is not positive.\n", model->BSIM4v7toxm));
109         Fatal_Flag = 1;
110     }
111     if (model->BSIM4v7toxref <= 0.0)
112     {
113         wl_append_word(&wl, &wl, tprintf("Fatal: Toxref = %g is not positive.\n", model->BSIM4v7toxref));
114         Fatal_Flag = 1;
115     }
116 
117     if (pParam->BSIM4v7lpe0 < -pParam->BSIM4v7leff)
118     {
119         wl_append_word(&wl, &wl, tprintf("Fatal: Lpe0 = %g is less than -Leff.\n",
120             pParam->BSIM4v7lpe0));
121         Fatal_Flag = 1;
122     }
123     if (model->BSIM4v7lintnoi > pParam->BSIM4v7leff / 2)
124     {
125         wl_append_word(&wl, &wl, tprintf("Fatal: Lintnoi = %g is too large - Leff for noise is negative.\n",
126             model->BSIM4v7lintnoi));
127         Fatal_Flag = 1;
128     }
129     if (pParam->BSIM4v7lpeb < -pParam->BSIM4v7leff)
130     {
131         wl_append_word(&wl, &wl, tprintf("Fatal: Lpeb = %g is less than -Leff.\n",
132             pParam->BSIM4v7lpeb));
133         Fatal_Flag = 1;
134     }
135     if (pParam->BSIM4v7ndep <= 0.0)
136     {
137         wl_append_word(&wl, &wl, tprintf("Fatal: Ndep = %g is not positive.\n",
138             pParam->BSIM4v7ndep));
139         Fatal_Flag = 1;
140     }
141     if (pParam->BSIM4v7phi <= 0.0)
142     {
143         wl_append_word(&wl, &wl, tprintf("Fatal: Phi = %g is not positive. Please check Phin and Ndep\n",
144             pParam->BSIM4v7phi));
145         wl_append_word(&wl, &wl, tprintf("	   Phin = %g  Ndep = %g \n",
146             pParam->BSIM4v7phin, pParam->BSIM4v7ndep));
147         Fatal_Flag = 1;
148     }
149     if (pParam->BSIM4v7nsub <= 0.0)
150     {
151         wl_append_word(&wl, &wl, tprintf("Fatal: Nsub = %g is not positive.\n",
152             pParam->BSIM4v7nsub));
153         Fatal_Flag = 1;
154     }
155     if (pParam->BSIM4v7ngate < 0.0)
156     {
157         wl_append_word(&wl, &wl, tprintf("Fatal: Ngate = %g Ngate is not positive.\n",
158             pParam->BSIM4v7ngate));
159         Fatal_Flag = 1;
160     }
161     if (pParam->BSIM4v7ngate > 1.e25)
162     {
163         wl_append_word(&wl, &wl, tprintf("Fatal: Ngate = %g Ngate is too high\n",
164             pParam->BSIM4v7ngate));
165         Fatal_Flag = 1;
166     }
167     if (pParam->BSIM4v7xj <= 0.0)
168     {
169         wl_append_word(&wl, &wl, tprintf("Fatal: Xj = %g is not positive.\n", pParam->BSIM4v7xj));
170         Fatal_Flag = 1;
171     }
172 
173     if (pParam->BSIM4v7dvt1 < 0.0)
174     {
175         wl_append_word(&wl, &wl, tprintf("Fatal: Dvt1 = %g is negative.\n", pParam->BSIM4v7dvt1));
176         Fatal_Flag = 1;
177     }
178 
179     if (pParam->BSIM4v7dvt1w < 0.0)
180     {
181         wl_append_word(&wl, &wl, tprintf("Fatal: Dvt1w = %g is negative.\n", pParam->BSIM4v7dvt1w));
182         Fatal_Flag = 1;
183     }
184 
185     if (pParam->BSIM4v7w0 == -pParam->BSIM4v7weff)
186     {
187         wl_append_word(&wl, &wl, tprintf("Fatal: (W0 + Weff) = 0 causing divided-by-zero.\n"));
188         Fatal_Flag = 1;
189     }
190 
191     if (pParam->BSIM4v7dsub < 0.0)
192     {
193         wl_append_word(&wl, &wl, tprintf("Fatal: Dsub = %g is negative.\n", pParam->BSIM4v7dsub));
194         Fatal_Flag = 1;
195     }
196     if (pParam->BSIM4v7b1 == -pParam->BSIM4v7weff)
197     {
198         wl_append_word(&wl, &wl, tprintf("Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"));
199         Fatal_Flag = 1;
200     }
201     if (here->BSIM4v7u0temp <= 0.0)
202     {
203         wl_append_word(&wl, &wl, tprintf("Fatal: u0 at current temperature = %g is not positive.\n",
204             here->BSIM4v7u0temp));
205         Fatal_Flag = 1;
206     }
207 
208     if (pParam->BSIM4v7delta < 0.0)
209     {
210         wl_append_word(&wl, &wl, tprintf("Fatal: Delta = %g is less than zero.\n", pParam->BSIM4v7delta));
211         Fatal_Flag = 1;
212     }
213 
214     if (here->BSIM4v7vsattemp <= 0.0)
215     {
216         wl_append_word(&wl, &wl, tprintf("Fatal: Vsat at current temperature = %g is not positive.\n",
217             here->BSIM4v7vsattemp));
218         Fatal_Flag = 1;
219     }
220 
221     if (pParam->BSIM4v7pclm <= 0.0)
222     {
223         wl_append_word(&wl, &wl, tprintf("Fatal: Pclm = %g is not positive.\n", pParam->BSIM4v7pclm));
224         Fatal_Flag = 1;
225     }
226 
227     if (pParam->BSIM4v7drout < 0.0)
228     {
229         wl_append_word(&wl, &wl, tprintf("Fatal: Drout = %g is negative.\n", pParam->BSIM4v7drout));
230         Fatal_Flag = 1;
231     }
232 
233     if (here->BSIM4v7m <= 0.0)
234     {
235         wl_append_word(&wl, &wl, tprintf("Fatal: multiplier = %g is not positive.\n", here->BSIM4v7m));
236         Fatal_Flag = 1;
237     }
238     if (here->BSIM4v7nf < 1.0)
239     {
240         wl_append_word(&wl, &wl, tprintf("Fatal: Number of finger = %g is smaller than one.\n", here->BSIM4v7nf));
241         Fatal_Flag = 1;
242     }
243 
244     if ((here->BSIM4v7sa > 0.0) && (here->BSIM4v7sb > 0.0) &&
245         ((here->BSIM4v7nf == 1.0) || ((here->BSIM4v7nf > 1.0) && (here->BSIM4v7sd > 0.0))))
246     {
247         if (model->BSIM4v7saref <= 0.0)
248         {
249             wl_append_word(&wl, &wl, tprintf("Fatal: SAref = %g is not positive.\n", model->BSIM4v7saref));
250             Fatal_Flag = 1;
251         }
252         if (model->BSIM4v7sbref <= 0.0)
253         {
254             wl_append_word(&wl, &wl, tprintf("Fatal: SBref = %g is not positive.\n", model->BSIM4v7sbref));
255             Fatal_Flag = 1;
256         }
257     }
258 
259     if ((here->BSIM4v7l + model->BSIM4v7xl) <= model->BSIM4v7xgl)
260     {
261         wl_append_word(&wl, &wl, tprintf("Fatal: The parameter xgl must be smaller than Ldrawn+XL.\n"));
262         Fatal_Flag = 1;
263     }
264     if (here->BSIM4v7ngcon < 1.0)
265     {
266         wl_append_word(&wl, &wl, tprintf("Fatal: The parameter ngcon cannot be smaller than one.\n"));
267         Fatal_Flag = 1;
268     }
269     if ((here->BSIM4v7ngcon != 1.0) && (here->BSIM4v7ngcon != 2.0))
270     {
271         here->BSIM4v7ngcon = 1.0;
272         wl_append_word(&wl, &wl, tprintf("Warning: Ngcon must be equal to one or two; reset to 1.0.\n"));
273     }
274 
275     if (model->BSIM4v7gbmin < 1.0e-20)
276     {
277         wl_append_word(&wl, &wl, tprintf("Warning: Gbmin = %g is too small.\n", model->BSIM4v7gbmin));
278     }
279 
280     /* Check saturation parameters */
281     if (pParam->BSIM4v7fprout < 0.0)
282     {
283         wl_append_word(&wl, &wl, tprintf("Fatal: fprout = %g is negative.\n", pParam->BSIM4v7fprout));
284         Fatal_Flag = 1;
285     }
286     if (pParam->BSIM4v7pdits < 0.0)
287     {
288         wl_append_word(&wl, &wl, tprintf("Fatal: pdits = %g is negative.\n", pParam->BSIM4v7pdits));
289         Fatal_Flag = 1;
290     }
291     if (model->BSIM4v7pditsl < 0.0)
292     {
293         wl_append_word(&wl, &wl, tprintf("Fatal: pditsl = %g is negative.\n", model->BSIM4v7pditsl));
294         Fatal_Flag = 1;
295     }
296 
297     /* Check gate current parameters */
298     if (model->BSIM4v7igbMod) {
299         if (pParam->BSIM4v7nigbinv <= 0.0)
300         {
301             wl_append_word(&wl, &wl, tprintf("Fatal: nigbinv = %g is non-positive.\n", pParam->BSIM4v7nigbinv));
302             Fatal_Flag = 1;
303         }
304         if (pParam->BSIM4v7nigbacc <= 0.0)
305         {
306             wl_append_word(&wl, &wl, tprintf("Fatal: nigbacc = %g is non-positive.\n", pParam->BSIM4v7nigbacc));
307             Fatal_Flag = 1;
308         }
309     }
310     if (model->BSIM4v7igcMod) {
311         if (pParam->BSIM4v7nigc <= 0.0)
312         {
313             wl_append_word(&wl, &wl, tprintf("Fatal: nigc = %g is non-positive.\n", pParam->BSIM4v7nigc));
314             Fatal_Flag = 1;
315         }
316         if (pParam->BSIM4v7poxedge <= 0.0)
317         {
318             wl_append_word(&wl, &wl, tprintf("Fatal: poxedge = %g is non-positive.\n", pParam->BSIM4v7poxedge));
319             Fatal_Flag = 1;
320         }
321         if (pParam->BSIM4v7pigcd <= 0.0)
322         {
323             wl_append_word(&wl, &wl, tprintf("Fatal: pigcd = %g is non-positive.\n", pParam->BSIM4v7pigcd));
324             Fatal_Flag = 1;
325         }
326     }
327 
328     /* Check capacitance parameters */
329     if (pParam->BSIM4v7clc < 0.0)
330     {
331         wl_append_word(&wl, &wl, tprintf("Fatal: Clc = %g is negative.\n", pParam->BSIM4v7clc));
332         Fatal_Flag = 1;
333     }
334 
335     /* Check overlap capacitance parameters */
336     if (pParam->BSIM4v7ckappas < 0.02)
337     {
338         wl_append_word(&wl, &wl, tprintf("Warning: ckappas = %g is too small.\n", pParam->BSIM4v7ckappas));
339         pParam->BSIM4v7ckappas = 0.02;
340     }
341     if (pParam->BSIM4v7ckappad < 0.02)
342     {
343         wl_append_word(&wl, &wl, tprintf("Warning: ckappad = %g is too small.\n", pParam->BSIM4v7ckappad));
344         pParam->BSIM4v7ckappad = 0.02;
345     }
346 
347     if (model->BSIM4v7vtss < 0.0)
348     {
349         wl_append_word(&wl, &wl, tprintf("Fatal: Vtss = %g is negative.\n",
350             model->BSIM4v7vtss));
351         Fatal_Flag = 1;
352     }
353     if (model->BSIM4v7vtsd < 0.0)
354     {
355         wl_append_word(&wl, &wl, tprintf("Fatal: Vtsd = %g is negative.\n",
356             model->BSIM4v7vtsd));
357         Fatal_Flag = 1;
358     }
359     if (model->BSIM4v7vtssws < 0.0)
360     {
361         wl_append_word(&wl, &wl, tprintf("Fatal: Vtssws = %g is negative.\n",
362             model->BSIM4v7vtssws));
363         Fatal_Flag = 1;
364     }
365     if (model->BSIM4v7vtsswd < 0.0)
366     {
367         wl_append_word(&wl, &wl, tprintf("Fatal: Vtsswd = %g is negative.\n",
368             model->BSIM4v7vtsswd));
369         Fatal_Flag = 1;
370     }
371     if (model->BSIM4v7vtsswgs < 0.0)
372     {
373         wl_append_word(&wl, &wl, tprintf("Fatal: Vtsswgs = %g is negative.\n",
374             model->BSIM4v7vtsswgs));
375         Fatal_Flag = 1;
376     }
377     if (model->BSIM4v7vtsswgd < 0.0)
378     {
379         wl_append_word(&wl, &wl, tprintf("Fatal: Vtsswgd = %g is negative.\n",
380             model->BSIM4v7vtsswgd));
381         Fatal_Flag = 1;
382     }
383 
384 
385     if (model->BSIM4v7paramChk == 1)
386     {
387         /* Check L and W parameters */
388         if (pParam->BSIM4v7leff <= 1.0e-9)
389         {
390             wl_append_word(&wl, &wl, tprintf("Warning: Leff = %g <= 1.0e-9. Recommended Leff >= 1e-8 \n",
391                 pParam->BSIM4v7leff));
392         }
393 
394         if (pParam->BSIM4v7leffCV <= 1.0e-9)
395         {
396             wl_append_word(&wl, &wl, tprintf("Warning: Leff for CV = %g <= 1.0e-9. Recommended LeffCV >=1e-8 \n",
397                 pParam->BSIM4v7leffCV));
398         }
399 
400         if (pParam->BSIM4v7weff <= 1.0e-9)
401         {
402             wl_append_word(&wl, &wl, tprintf("Warning: Weff = %g <= 1.0e-9. Recommended Weff >=1e-7 \n",
403                 pParam->BSIM4v7weff));
404         }
405 
406         if (pParam->BSIM4v7weffCV <= 1.0e-9)
407         {
408             wl_append_word(&wl, &wl, tprintf("Warning: Weff for CV = %g <= 1.0e-9. Recommended WeffCV >= 1e-7 \n",
409                 pParam->BSIM4v7weffCV));
410         }
411 
412         /* Check threshold voltage parameters */
413         if (model->BSIM4v7toxe < 1.0e-10)
414         {
415             wl_append_word(&wl, &wl, tprintf("Warning: Toxe = %g is less than 1A. Recommended Toxe >= 5A\n", model->BSIM4v7toxe));
416         }
417         if (model->BSIM4v7toxp < 1.0e-10)
418         {
419             wl_append_word(&wl, &wl, tprintf("Warning: Toxp = %g is less than 1A. Recommended Toxp >= 5A\n", model->BSIM4v7toxp));
420         }
421         if (model->BSIM4v7toxm < 1.0e-10)
422         {
423             wl_append_word(&wl, &wl, tprintf("Warning: Toxm = %g is less than 1A. Recommended Toxm >= 5A\n", model->BSIM4v7toxm));
424         }
425 
426         if (pParam->BSIM4v7ndep <= 1.0e12)
427         {
428             wl_append_word(&wl, &wl, tprintf("Warning: Ndep = %g may be too small.\n",
429                 pParam->BSIM4v7ndep));
430         }
431         else if (pParam->BSIM4v7ndep >= 1.0e21)
432         {
433             wl_append_word(&wl, &wl, tprintf("Warning: Ndep = %g may be too large.\n",
434                 pParam->BSIM4v7ndep));
435         }
436 
437         if (pParam->BSIM4v7nsub <= 1.0e14)
438         {
439             wl_append_word(&wl, &wl, tprintf("Warning: Nsub = %g may be too small.\n",
440                 pParam->BSIM4v7nsub));
441         }
442         else if (pParam->BSIM4v7nsub >= 1.0e21)
443         {
444             wl_append_word(&wl, &wl, tprintf("Warning: Nsub = %g may be too large.\n",
445                 pParam->BSIM4v7nsub));
446         }
447 
448         if ((pParam->BSIM4v7ngate > 0.0) &&
449             (pParam->BSIM4v7ngate <= 1.e18))
450         {
451             wl_append_word(&wl, &wl, tprintf("Warning: Ngate = %g is less than 1.E18cm^-3.\n",
452                 pParam->BSIM4v7ngate));
453         }
454 
455         if (pParam->BSIM4v7dvt0 < 0.0)
456         {
457             wl_append_word(&wl, &wl, tprintf("Warning: Dvt0 = %g is negative.\n", pParam->BSIM4v7dvt0));
458         }
459 
460         if (fabs(1.0e-8 / (pParam->BSIM4v7w0 + pParam->BSIM4v7weff)) > 10.0)
461         {
462             wl_append_word(&wl, &wl, tprintf("Warning: (W0 + Weff) may be too small.\n"));
463         }
464 
465         /* Check subthreshold parameters */
466         if (pParam->BSIM4v7nfactor < 0.0)
467         {
468             wl_append_word(&wl, &wl, tprintf("Warning: Nfactor = %g is negative.\n", pParam->BSIM4v7nfactor));
469         }
470         if (pParam->BSIM4v7cdsc < 0.0)
471         {
472             wl_append_word(&wl, &wl, tprintf("Warning: Cdsc = %g is negative.\n", pParam->BSIM4v7cdsc));
473         }
474         if (pParam->BSIM4v7cdscd < 0.0)
475         {
476             wl_append_word(&wl, &wl, tprintf("Warning: Cdscd = %g is negative.\n", pParam->BSIM4v7cdscd));
477         }
478         /* Check DIBL parameters */
479         if (here->BSIM4v7eta0 < 0.0)
480         {
481             wl_append_word(&wl, &wl, tprintf("Warning: Eta0 = %g is negative.\n", here->BSIM4v7eta0));
482         }
483 
484         /* Check Abulk parameters */
485         if (fabs(1.0e-8 / (pParam->BSIM4v7b1 + pParam->BSIM4v7weff)) > 10.0)
486         {
487             wl_append_word(&wl, &wl, tprintf("Warning: (B1 + Weff) may be too small.\n"));
488         }
489 
490 
491         /* Check Saturation parameters */
492         if (pParam->BSIM4v7a2 < 0.01)
493         {
494             wl_append_word(&wl, &wl, tprintf("Warning: A2 = %g is too small. Set to 0.01.\n",
495                 pParam->BSIM4v7a2));
496             pParam->BSIM4v7a2 = 0.01;
497         }
498         else if (pParam->BSIM4v7a2 > 1.0)
499         {
500             wl_append_word(&wl, &wl, tprintf("Warning: A2 = %g is larger than 1. A2 is set to 1 and A1 is set to 0.\n",
501                 pParam->BSIM4v7a2));
502             pParam->BSIM4v7a2 = 1.0;
503             pParam->BSIM4v7a1 = 0.0;
504         }
505 
506         if (pParam->BSIM4v7prwg < 0.0)
507         {
508             wl_append_word(&wl, &wl, tprintf("Warning: Prwg = %g is negative. Set to zero.\n",
509                 pParam->BSIM4v7prwg));
510             pParam->BSIM4v7prwg = 0.0;
511         }
512 
513         if (pParam->BSIM4v7rdsw < 0.0)
514         {
515             wl_append_word(&wl, &wl, tprintf("Warning: Rdsw = %g is negative. Set to zero.\n",
516                 pParam->BSIM4v7rdsw));
517             pParam->BSIM4v7rdsw = 0.0;
518             pParam->BSIM4v7rds0 = 0.0;
519         }
520 
521         if (pParam->BSIM4v7rds0 < 0.0)
522         {
523             wl_append_word(&wl, &wl, tprintf("Warning: Rds at current temperature = %g is negative. Set to zero.\n",
524                 pParam->BSIM4v7rds0));
525             pParam->BSIM4v7rds0 = 0.0;
526         }
527 
528         if (pParam->BSIM4v7rdswmin < 0.0)
529         {
530             wl_append_word(&wl, &wl, tprintf("Warning: Rdswmin at current temperature = %g is negative. Set to zero.\n",
531                 pParam->BSIM4v7rdswmin));
532             pParam->BSIM4v7rdswmin = 0.0;
533         }
534 
535         if (pParam->BSIM4v7pscbe2 <= 0.0)
536         {
537             wl_append_word(&wl, &wl, tprintf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM4v7pscbe2));
538         }
539 
540         if (pParam->BSIM4v7vsattemp < 1.0e3)
541         {
542             wl_append_word(&wl, &wl, tprintf("Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM4v7vsattemp));
543         }
544 
545         if ((model->BSIM4v7lambdaGiven) && (pParam->BSIM4v7lambda > 0.0))
546         {
547             if (pParam->BSIM4v7lambda > 1.0e-9)
548             {
549                 wl_append_word(&wl, &wl, tprintf("Warning: Lambda = %g may be too large.\n", pParam->BSIM4v7lambda));
550             }
551         }
552 
553         if ((model->BSIM4v7vtlGiven) && (pParam->BSIM4v7vtl > 0.0))
554         {
555             if (pParam->BSIM4v7vtl < 6.0e4)
556             {
557                 wl_append_word(&wl, &wl, tprintf("Warning: Thermal velocity vtl = %g may be too small.\n", pParam->BSIM4v7vtl));
558             }
559 
560             if (pParam->BSIM4v7xn < 3.0)
561             {
562                 wl_append_word(&wl, &wl, tprintf("Warning: back scattering coeff xn = %g is too small. Reset to 3.0 \n", pParam->BSIM4v7xn));
563                 pParam->BSIM4v7xn = 3.0;
564             }
565 
566             if (model->BSIM4v7lc < 0.0)
567             {
568                 wl_append_word(&wl, &wl, tprintf("Warning: back scattering coeff lc = %g is too small. Reset to 0.0\n", model->BSIM4v7lc));
569                 pParam->BSIM4v7lc = 0.0;
570             }
571         }
572 
573         if (pParam->BSIM4v7pdibl1 < 0.0)
574         {
575             wl_append_word(&wl, &wl, tprintf("Warning: Pdibl1 = %g is negative.\n", pParam->BSIM4v7pdibl1));
576         }
577     }
578 
579     if (pParam->BSIM4v7pdibl2 < 0.0)
580     {
581         wl_append_word(&wl, &wl, tprintf("Warning: Pdibl2 = %g is negative.\n", pParam->BSIM4v7pdibl2));
582     }
583 
584     /* Check stress effect parameters */
585     if ((here->BSIM4v7sa > 0.0) && (here->BSIM4v7sb > 0.0) &&
586         ((here->BSIM4v7nf == 1.0) || ((here->BSIM4v7nf > 1.0) && (here->BSIM4v7sd > 0.0))))
587     {
588         if (model->BSIM4v7lodk2 <= 0.0)
589         {
590             wl_append_word(&wl, &wl, tprintf("Warning: LODK2 = %g is not positive.\n", model->BSIM4v7lodk2));
591         }
592         if (model->BSIM4v7lodeta0 <= 0.0)
593         {
594             wl_append_word(&wl, &wl, tprintf("Warning: LODETA0 = %g is not positive.\n", model->BSIM4v7lodeta0));
595         }
596     }
597 
598     /* Check gate resistance parameters */
599     if (here->BSIM4v7rgateMod == 1)
600     {
601         if (model->BSIM4v7rshg <= 0.0)
602             wl_append_word(&wl, &wl, tprintf("Warning: rshg should be positive for rgateMod = 1.\n"));
603     }
604     else if (here->BSIM4v7rgateMod == 2)
605     {
606         if (model->BSIM4v7rshg <= 0.0)
607             wl_append_word(&wl, &wl, tprintf("Warning: rshg <= 0.0 for rgateMod = 2.\n"));
608         else if (pParam->BSIM4v7xrcrg1 <= 0.0)
609                 wl_append_word(&wl, &wl, tprintf("Warning: xrcrg1 <= 0.0 for rgateMod = 2.\n"));
610     }
611     if (here->BSIM4v7rgateMod == 3)
612     {
613         if (model->BSIM4v7rshg <= 0.0)
614             wl_append_word(&wl, &wl, tprintf("Warning: rshg should be positive for rgateMod = 3.\n"));
615         else if (pParam->BSIM4v7xrcrg1 <= 0.0)
616                 wl_append_word(&wl, &wl, tprintf("Warning: xrcrg1 should be positive for rgateMod = 3.\n"));
617     }
618 
619     /* Check capacitance parameters */
620     if (pParam->BSIM4v7noff < 0.1)
621     {
622         wl_append_word(&wl, &wl, tprintf("Warning: Noff = %g is too small.\n", pParam->BSIM4v7noff));
623     }
624 
625     if (pParam->BSIM4v7voffcv < -0.5)
626     {
627         wl_append_word(&wl, &wl, tprintf("Warning: Voffcv = %g is too small.\n", pParam->BSIM4v7voffcv));
628     }
629 
630     if (pParam->BSIM4v7moin < 5.0)
631     {
632         wl_append_word(&wl, &wl, tprintf("Warning: Moin = %g is too small.\n", pParam->BSIM4v7moin));
633     }
634     if (pParam->BSIM4v7moin > 25.0)
635     {
636         wl_append_word(&wl, &wl, tprintf("Warning: Moin = %g is too large.\n", pParam->BSIM4v7moin));
637     }
638     if (model->BSIM4v7capMod == 2) {
639         if (pParam->BSIM4v7acde < 0.1)
640         {
641             wl_append_word(&wl, &wl, tprintf("Warning: Acde = %g is too small.\n", pParam->BSIM4v7acde));
642         }
643         if (pParam->BSIM4v7acde > 1.6)
644         {
645             wl_append_word(&wl, &wl, tprintf("Warning: Acde = %g is too large.\n", pParam->BSIM4v7acde));
646         }
647     }
648 
649     /* Check overlap capacitance parameters */
650     if (model->BSIM4v7cgdo < 0.0)
651     {
652         wl_append_word(&wl, &wl, tprintf("Warning: cgdo = %g is negative. Set to zero.\n", model->BSIM4v7cgdo));
653         model->BSIM4v7cgdo = 0.0;
654     }
655     if (model->BSIM4v7cgso < 0.0)
656     {
657         wl_append_word(&wl, &wl, tprintf("Warning: cgso = %g is negative. Set to zero.\n", model->BSIM4v7cgso));
658         model->BSIM4v7cgso = 0.0;
659     }
660     if (model->BSIM4v7cgbo < 0.0)
661     {
662         wl_append_word(&wl, &wl, tprintf("Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM4v7cgbo));
663         model->BSIM4v7cgbo = 0.0;
664     }
665     /* v4.7 */
666     if (model->BSIM4v7tnoiMod == 1 || model->BSIM4v7tnoiMod == 2) {
667         if (model->BSIM4v7tnoia < 0.0)
668         {
669             wl_append_word(&wl, &wl, tprintf("Warning: tnoia = %g is negative. Set to zero.\n", model->BSIM4v7tnoia));
670             model->BSIM4v7tnoia = 0.0;
671         }
672         if (model->BSIM4v7tnoib < 0.0)
673         {
674             wl_append_word(&wl, &wl, tprintf("Warning: tnoib = %g is negative. Set to zero.\n", model->BSIM4v7tnoib));
675             model->BSIM4v7tnoib = 0.0;
676         }
677 
678         if (model->BSIM4v7rnoia < 0.0)
679         {
680             wl_append_word(&wl, &wl, tprintf("Warning: rnoia = %g is negative. Set to zero.\n", model->BSIM4v7rnoia));
681             model->BSIM4v7rnoia = 0.0;
682         }
683         if (model->BSIM4v7rnoib < 0.0)
684         {
685             wl_append_word(&wl, &wl, tprintf("Warning: rnoib = %g is negative. Set to zero.\n", model->BSIM4v7rnoib));
686             model->BSIM4v7rnoib = 0.0;
687         }
688     }
689 
690     /* v4.7 */
691     if (model->BSIM4v7tnoiMod == 2) {
692         if (model->BSIM4v7tnoic < 0.0) {
693             wl_append_word(&wl, &wl, tprintf("Warning: tnoic = %g is negative. Set to zero.\n", model->BSIM4v7tnoic));
694             model->BSIM4v7tnoic = 0.0;
695         }
696         if (model->BSIM4v7rnoic < 0.0) {
697             wl_append_word(&wl, &wl, tprintf("Warning: rnoic = %g is negative. Set to zero.\n", model->BSIM4v7rnoic));
698             model->BSIM4v7rnoic = 0.0;
699         }
700     }
701 
702     /* Limits of Njs and Njd modified in BSIM4v7.7 */
703     if (model->BSIM4v7SjctEmissionCoeff < 0.1) {
704         wl_append_word(&wl, &wl, tprintf("Warning: Njs = %g is less than 0.1. Setting Njs to 0.1.\n", model->BSIM4v7SjctEmissionCoeff));
705             model->BSIM4v7SjctEmissionCoeff = 0.1;
706     }
707     else if (model->BSIM4v7SjctEmissionCoeff < 0.7) {
708         wl_append_word(&wl, &wl, tprintf("Warning: Njs = %g is less than 0.7.\n", model->BSIM4v7SjctEmissionCoeff));
709     }
710     if (model->BSIM4v7DjctEmissionCoeff < 0.1)
711     {
712         wl_append_word(&wl, &wl, tprintf("Warning: Njd = %g is less than 0.1. Setting Njd to 0.1.\n", model->BSIM4v7DjctEmissionCoeff));
713         model->BSIM4v7DjctEmissionCoeff = 0.1;
714     }
715     else if (model->BSIM4v7DjctEmissionCoeff < 0.7) {
716         wl_append_word(&wl, &wl, tprintf("Warning: Njd = %g is less than 0.7.\n", model->BSIM4v7DjctEmissionCoeff));
717     }
718 
719     if (model->BSIM4v7njtsstemp < 0.0) {
720         wl_append_word(&wl, &wl, tprintf("Warning: Njts = %g is negative at temperature = %g.\n",
721                model->BSIM4v7njtsstemp, ckt->CKTtemp));
722     }
723     if (model->BSIM4v7njtsswstemp < 0.0) {
724         wl_append_word(&wl, &wl, tprintf("Warning: Njtssw = %g is negative at temperature = %g.\n",
725                 model->BSIM4v7njtsswstemp, ckt->CKTtemp));
726     }
727     if (model->BSIM4v7njtsswgstemp < 0.0) {
728         wl_append_word(&wl, &wl, tprintf("Warning: Njtsswg = %g is negative at temperature = %g.\n",
729                 model->BSIM4v7njtsswgstemp, ckt->CKTtemp));
730     }
731 
732     if (model->BSIM4v7njtsdGiven && model->BSIM4v7njtsdtemp < 0.0)
733     {
734         wl_append_word(&wl, &wl, tprintf("Warning: Njtsd = %g is negative at temperature = %g.\n",
735             model->BSIM4v7njtsdtemp, ckt->CKTtemp));
736     }
737     if (model->BSIM4v7njtsswdGiven && model->BSIM4v7njtsswdtemp < 0.0)
738     {
739         wl_append_word(&wl, &wl, tprintf("Warning: Njtsswd = %g is negative at temperature = %g.\n",
740             model->BSIM4v7njtsswdtemp, ckt->CKTtemp));
741     }
742     if (model->BSIM4v7njtsswgdGiven && model->BSIM4v7njtsswgdtemp < 0.0)
743     {
744         wl_append_word(&wl, &wl, tprintf("Warning: Njtsswgd = %g is negative at temperature = %g.\n",
745             model->BSIM4v7njtsswgdtemp, ckt->CKTtemp));
746     }
747 
748     if (model->BSIM4v7ntnoi < 0.0)
749     {
750         wl_append_word(&wl, &wl, tprintf("Warning: ntnoi = %g is negative. Set to zero.\n", model->BSIM4v7ntnoi));
751         model->BSIM4v7ntnoi = 0.0;
752     }
753 
754     /* diode model */
755     if (model->BSIM4v7SbulkJctBotGradingCoeff >= 0.99)
756     {
757         wl_append_word(&wl, &wl, tprintf("Warning: MJS = %g is too big. Set to 0.99.\n", model->BSIM4v7SbulkJctBotGradingCoeff));
758         model->BSIM4v7SbulkJctBotGradingCoeff = 0.99;
759     }
760     if (model->BSIM4v7SbulkJctSideGradingCoeff >= 0.99)
761     {
762         wl_append_word(&wl, &wl, tprintf("Warning: MJSWS = %g is too big. Set to 0.99.\n", model->BSIM4v7SbulkJctSideGradingCoeff));
763         model->BSIM4v7SbulkJctSideGradingCoeff = 0.99;
764     }
765     if (model->BSIM4v7SbulkJctGateSideGradingCoeff >= 0.99)
766     {
767         wl_append_word(&wl, &wl, tprintf("Warning: MJSWGS = %g is too big. Set to 0.99.\n", model->BSIM4v7SbulkJctGateSideGradingCoeff));
768         model->BSIM4v7SbulkJctGateSideGradingCoeff = 0.99;
769     }
770 
771     if (model->BSIM4v7DbulkJctBotGradingCoeff >= 0.99)
772     {
773         wl_append_word(&wl, &wl, tprintf("Warning: MJD = %g is too big. Set to 0.99.\n", model->BSIM4v7DbulkJctBotGradingCoeff));
774         model->BSIM4v7DbulkJctBotGradingCoeff = 0.99;
775     }
776     if (model->BSIM4v7DbulkJctSideGradingCoeff >= 0.99)
777     {
778         wl_append_word(&wl, &wl, tprintf("Warning: MJSWD = %g is too big. Set to 0.99.\n", model->BSIM4v7DbulkJctSideGradingCoeff));
779         model->BSIM4v7DbulkJctSideGradingCoeff = 0.99;
780     }
781     if (model->BSIM4v7DbulkJctGateSideGradingCoeff >= 0.99)
782     {
783         wl_append_word(&wl, &wl, tprintf("Warning: MJSWGD = %g is too big. Set to 0.99.\n", model->BSIM4v7DbulkJctGateSideGradingCoeff));
784         model->BSIM4v7DbulkJctGateSideGradingCoeff = 0.99;
785     }
786     if (model->BSIM4v7wpemod == 1)
787     {
788         if (model->BSIM4v7scref <= 0.0)
789         {
790             wl_append_word(&wl, &wl, tprintf("Warning: SCREF = %g is not positive. Set to 1e-6.\n", model->BSIM4v7scref));
791             model->BSIM4v7scref = 1e-6;
792         }
793         if (here->BSIM4v7sca < 0.0)
794         {
795             wl_append_word(&wl, &wl, tprintf("Warning: SCA = %g is negative. Set to 0.0.\n", here->BSIM4v7sca));
796             here->BSIM4v7sca = 0.0;
797         }
798         if (here->BSIM4v7scb < 0.0)
799         {
800             wl_append_word(&wl, &wl, tprintf("Warning: SCB = %g is negative. Set to 0.0.\n", here->BSIM4v7scb));
801             here->BSIM4v7scb = 0.0;
802         }
803         if (here->BSIM4v7scc < 0.0)
804         {
805             wl_append_word(&wl, &wl, tprintf("Warning: SCC = %g is negative. Set to 0.0.\n", here->BSIM4v7scc));
806             here->BSIM4v7scc = 0.0;
807         }
808         if (here->BSIM4v7sc < 0.0)
809         {
810             wl_append_word(&wl, &wl, tprintf("Warning: SC = %g is negative. Set to 0.0.\n", here->BSIM4v7sc));
811             here->BSIM4v7sc = 0.0;
812         }
813     }
814 
815     if (wlstart->wl_next) {
816         if ((fplog = fopen("bsim4v7.out", "w")) != NULL) {
817             while (wlstart) {
818                 fprintf(fplog, "%s", wlstart->wl_word);
819                 fprintf(stderr, "%s", wlstart->wl_word);
820                 wlstart = wlstart->wl_next;
821             }
822             fclose(fplog);
823         }
824         else {
825             while (wlstart) {
826                 fprintf(stderr, "%s", wlstart->wl_word);
827                 wlstart = wlstart->wl_next;
828             }
829         }
830     }
831 
832     wl_free(wlstart);
833 
834     if ((strcmp(model->BSIM4v7version, "4.7.0")) && (strncmp(model->BSIM4v7version, "4.70", 4)) && (strncmp(model->BSIM4v7version, "4.7", 3)))
835     {
836         printf("Warning: This model is BSIM4.7.0; you specified a wrong version number '%s'.\n", model->BSIM4v7version);
837     }
838 
839     return(Fatal_Flag);
840 }
841 
842