Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / tas / mcc / mcc_genelp.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI Alliance */
4 /* */
5 /* Produit : MCC Version 1 */
6 /* Fichier : mcc_genelp.c */
7 /* */
8 /* (c) copyright 1991-1998 Laboratoire LIP6 equipe ASIM */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
11 /* */
12 /* Auteur(s) : Karim DIOURY */
13 /* */
14 /****************************************************************************/
15
16 #include "mcc.h"
17 #include "mcc_mod_util.h"
18 #include "mcc_util.h"
19 #include "mcc_genspi.h"
20 #include "mcc_debug.h"
21 #include "mcc_curv.h"
22
23 static int param_used=0;
24 static float ncurrent_vt=-1000, pcurrent_vt=-1000;
25
26 static struct
27 {
28 float l, w, as, ad, ps, pd;
29 } param[2];
30
31 void resetparam()
32 {
33 param[0].l=param[0].w=param[0].as=param[0].ad=param[0].ps=param[0].pd=0;
34 param[1].l=param[1].w=param[1].as=param[1].ad=param[1].ps=param[1].pd=0;
35 param_used=1;
36 }
37
38 char *mcc_getline (str)
39 char *str;
40 {
41 char prompt[1024];
42
43 sprintf (prompt, "%s : ", str);
44
45 if (MCC_BUF != NULL)
46 mbkfree(MCC_BUF);
47
48 fprintf (stdout, "\n");
49 MCC_BUF = readline (prompt);
50 if ((MCC_BUF != NULL) && (strcmp (MCC_BUF, "") != 0))
51 add_history (strdup (MCC_BUF));
52 else
53 return (NULL);
54
55 return (MCC_BUF);
56 }
57
58 int mcc_gettab (str, tab, size, old)
59 char *str;
60 char **tab;
61 int size;
62 int old;
63 {
64 char strx[1024];
65 char *pt;
66 int i;
67 int res = 0;
68
69 sprintf (strx, "%s [", str);
70 pt = strx + strlen (strx);
71
72 for (i = 0; i < size - 1; i++) {
73 sprintf (pt, "%s ", tab[i]);
74 pt = pt + strlen (pt);
75 }
76
77 sprintf (pt, "%s] [%s]", tab[i], tab[old]);
78
79 while (res != 1) {
80 pt = mcc_getline (strx);
81
82 if (pt == NULL) {
83 return (old);
84 }
85
86 for (i = 0; i < size; i++) {
87 if (strcasecmp (tab[i], pt) == 0)
88 return (i);
89 }
90
91 fprintf (stderr, "\nmcc error : bad string\n");
92 res = 0;
93 }
94
95 return (old);
96 }
97
98 int mcc_getint (str, min, max, old)
99 char *str;
100 int min;
101 int max;
102 int old;
103 {
104 int param = 0;
105 char *pt;
106 int res = 0;
107 char strx[1024];
108
109 sprintf (strx, "%s [%d:%d] [%d]", str, min, max, old);
110
111 while (res != 1) {
112 pt = mcc_getline (strx);
113
114 if (pt == NULL) {
115 return (old);
116 }
117
118 res = sscanf (pt, "%d", &param);
119
120
121 if ((param < min) || (param > max) || (res != 1)) {
122 fprintf (stderr, "\nmcc error : bad number\n");
123 res = 0;
124 }
125 }
126
127 return (param);
128 }
129
130 double mcc_getdouble (str, min, max, old)
131 char *str;
132 double min;
133 double max;
134 double old;
135 {
136 float param = 0.0;
137 double paramx;
138 char *pt;
139 int res = 0;
140 char strx[1024];
141
142 sprintf (strx, "%s [%g:%g] [%g]", str, min, max, old);
143
144 while (res != 1) {
145 pt = mcc_getline (strx);
146
147 if (pt == NULL) {
148 return (old);
149 }
150
151 res = sscanf (pt, "%f", &param);
152
153 paramx = (double)param;
154
155 if ((paramx < min) || (paramx > max) || (res != 1)) {
156 fprintf (stderr, "\nmcc error : bad number\n");
157 res = 0;
158 }
159 }
160
161 return (paramx);
162 }
163
164 char *mcc_getstr (str, old)
165 char *str;
166 char *old;
167 {
168 char word[1024];
169 int len = (1024 - 1);
170 char *pt;
171 char strx[1024];
172
173 if (old != NULL) {
174 sprintf (strx, "%s [%s]", str, old);
175 }
176 else {
177 sprintf (strx, "%s", str);
178 }
179
180 pt = NULL;
181
182 while (pt == NULL) {
183 pt = mcc_getline (strx);
184
185 if ((pt == NULL) && (old != NULL)) {
186 return (old);
187 }
188 else if (pt == NULL) {
189 fprintf (stderr, "\nmcc error : bad string\n");
190 continue;
191 }
192 }
193
194 strcpy (word, pt);
195
196 *(word + (len)) = '\0';
197
198 pt = strchr (word, (int)('\n'));
199
200 if (pt != NULL)
201 *pt = '\0';
202
203 mbkfree (old);
204 pt = (char *)mbkalloc (strlen (word) + 1);
205 strcpy (pt, word);
206
207 return (pt);
208 }
209
210 char *mcc_getword (str, old)
211 char *str;
212 char *old;
213 {
214 int res = 0;
215 char word[1024];
216 unsigned int len = (1024 - 1);
217 char *pt;
218 char strx[1024];
219
220 if (old != NULL) {
221 sprintf (strx, "%s [%s]", str, old);
222 }
223 else {
224 sprintf (strx, "%s", str);
225 }
226
227 while (res != 1) {
228 pt = mcc_getline (strx);
229
230 if ((pt == NULL) && (old != NULL)) {
231 return (old);
232 }
233 else if (pt == NULL) {
234 fprintf (stderr, "\nmcc error : bad string\n");
235 continue;
236 }
237
238 if (strlen (pt) > len) {
239 fprintf (stderr, "\nmcc error : string too long\n");
240 continue;
241 }
242
243 res = sscanf (pt, "%s", word);
244
245 if (res != 1) {
246 fprintf (stderr, "\nmcc error : bad string\n");
247 res = 0;
248 }
249 }
250
251 *(word + (len)) = '\0';
252 pt = strchr (word, (int)('\n'));
253
254 if (pt != NULL)
255 *pt = '\0';
256
257 pt = (char *)mbkalloc (strlen (word) + 1);
258 strcpy (pt, word);
259
260 mbkfree (old);
261
262 return (pt);
263 }
264
265 int mcc_genelp (int spice, int vt, double tec, int aut, int fit, mcc_modellist **modeln, mcc_modellist **modelp,elp_lotrs_param *lotrsparam_n,elp_lotrs_param *lotrsparam_p)
266 {
267 char *pt;
268 int res = 1;
269 long nlmax;
270 long nlmin;
271 long nwmax;
272 long nwmin;
273 long plmax;
274 long plmin;
275 long pwmax;
276 long pwmin;
277 int b3=0,b4=0;
278 int setwn=0, setwp=0;
279 mcc_corner_info infon, infop;
280
281
282 if ((MCC_MODE != MCC_FAST_MODE) && (MCC_MODE != MCC_NEXT_MODE)) {
283 mcc_prsparam (lotrsparam_n,lotrsparam_p);
284 while (1) {
285 pt = MCC_TECHFILE;
286 MCC_TECHFILE = mcc_getword ("Transistor model file name", MCC_TECHFILE);
287 if (pt != MCC_TECHFILE) {
288 if (MCC_MODELFILE != NULL)
289 mbkfree (MCC_MODELFILE);
290 MCC_MODELFILE = mcc_initstr (MCC_TECHFILE);
291 }
292 MCC_MODELFILE = mcc_getword ("model file name", MCC_MODELFILE);
293 if (mcc_gettechnofile (MCC_MODELFILE) != NULL)
294 break;
295 }
296
297 MCC_ELPFILE = mcc_getword ("elp file name", MCC_ELPFILE);
298 MCC_ELPVERSION = mcc_getword ("elp version", MCC_ELPVERSION);
299 MCC_TEMP = mcc_getdouble ("Electrical simulation temperature (in degree)", -273.15, 1000, MCC_TEMP);
300 }
301
302 MCC_SPICEMODELTYPE = mcc_getmodeltype (MCC_MODELFILE);
303
304 if (MCC_SPICEMODELTYPE == MCC_NOMODEL)
305 MCC_SPICEMODELTYPE = MCC_MOS2;
306
307 if ((MCC_MODE != MCC_FAST_MODE) && (MCC_MODE != MCC_NEXT_MODE)) {
308 pt = MCC_TNMODEL;
309 MCC_TNMODEL = mcc_getword ("N Transistor model name", MCC_TNMODEL);
310
311 pt = MCC_TPMODEL;
312 MCC_TPMODEL = mcc_getword ("P Transistor model name", MCC_TPMODEL);
313
314 b3 = ( MCC_SPICEMODELTYPE == MCC_BSIM3V3 ? 1 : 0 ) ;
315 b4 = ( MCC_SPICEMODELTYPE == MCC_BSIM4 ? 1 : 0 ) ;
316
317 MCC_SPICEMODELTYPE = mcc_gettab ("Model type", MCC_MOD_NAME, MCC_VALID_MOD, MCC_SPICEMODELTYPE);
318
319 MCC_SPICESTRING = mcc_getstr ("Spice string", MCC_SPICESTRING);
320 MCC_SPICENAME = mcc_getfisrtarg (MCC_SPICESTRING, MCC_SPICENAME);
321 MCC_SPICENAME = mcc_getword ("Spice tool name", MCC_SPICENAME);
322 MCC_SPICESTDOUT = mcc_getword ("Spice standard out file", MCC_SPICESTDOUT);
323 MCC_SPICEOUT = mcc_getword ("Spice out file", MCC_SPICEOUT);
324 MCC_TASNAME = mcc_getword ("Tas tool name", MCC_TASNAME);
325
326 mcc_drvparam (lotrsparam_n,lotrsparam_p);
327 }
328
329 if (aut == 1) {
330 *modeln = mcc_getnextmodel (MCC_MODELFILE, MCC_TNMODEL, MCC_NMOS, MCC_NCASE, *modeln);
331
332 *modelp = mcc_getnextmodel (MCC_MODELFILE, MCC_TPMODEL, MCC_PMOS, MCC_PCASE, *modelp);
333
334 if ((*modeln == NULL) && (*modelp == NULL))
335 return (0);
336
337 if (*modeln != NULL) {
338 nlmax = mcc_ftol (SCALE_X * mcc_getparam_quick(*modeln, __MCC_QUICK_LMAX) * 1e06);
339 nlmin = mcc_ftol (SCALE_X * mcc_getparam_quick(*modeln, __MCC_QUICK_LMIN) * 1e06);
340 nwmax = mcc_ftol (SCALE_X * mcc_getparam_quick(*modeln, __MCC_QUICK_WMAX) * 1e06);
341 nwmin = mcc_ftol (SCALE_X * mcc_getparam_quick(*modeln, __MCC_QUICK_WMIN) * 1e06);
342 }
343
344 if (*modelp != NULL) {
345 plmax = mcc_ftol (SCALE_X * mcc_getparam_quick(*modelp, __MCC_QUICK_LMAX) * 1e06);
346 plmin = mcc_ftol (SCALE_X * mcc_getparam_quick(*modelp, __MCC_QUICK_LMIN) * 1e06);
347 pwmax = mcc_ftol (SCALE_X * mcc_getparam_quick(*modelp, __MCC_QUICK_WMAX) * 1e06);
348 pwmin = mcc_ftol (SCALE_X * mcc_getparam_quick(*modelp, __MCC_QUICK_WMIN) * 1e06);
349 }
350
351 if (*modeln == NULL) {
352 nlmax = plmax;
353 nlmin = plmin;
354 nwmax = pwmax;
355 nwmin = pwmin;
356 }
357
358 if (*modelp == NULL) {
359 plmax = nlmax;
360 plmin = nlmin;
361 pwmax = nwmax;
362 pwmin = nwmin;
363 }
364
365 if (nlmin == 0)
366 nlmin = nlmax / (long)2;
367 if (plmin == 0)
368 plmin = plmax / (long)2;
369
370 if ((nwmax > ((long)1000 * nwmin)) || (nwmax == 0))
371 nwmax = nwmin * (long)10;
372
373 if ((pwmax > ((long)1000 * pwmin)) || (pwmax == 0))
374 pwmax = pwmin * (long)10;
375
376 MCC_LN = (double)nlmin / SCALE_X;
377 MCC_LP = (double)plmin / SCALE_X;
378 MCC_WN = ((double)nwmin + (double)nwmax) / (2.0 * SCALE_X);
379 MCC_WP = 2.0 * MCC_WN;
380
381 if (param_used)
382 {
383 if (param[0].l!=0) MCC_LN=param[0].l* 1e06;
384 if (param[1].l!=0) MCC_LP=param[1].l* 1e06;
385 if (param[0].w!=0) MCC_WN=param[0].w* 1e06, setwn=1;
386 if (param[1].w!=0) MCC_WP=param[1].w* 1e06, setwp=1;
387 }
388
389 if (!setwn && !setwp)
390 {
391 while ((pwmin > (long)(MCC_WP * SCALE_X)) || (pwmax <= (long)(MCC_WP * SCALE_X))) {
392 if (pwmin > (long)(MCC_WP * SCALE_X))
393 MCC_WN = MCC_WN * 11.0 / 10.0;
394 else
395 MCC_WN = MCC_WN * 9.0 / 10.0;
396
397 if (nwmin > (long)(MCC_WN * SCALE_X)) {
398 MCC_WN = (double)nwmin / (double)SCALE_X;
399 MCC_WP = (double)pwmax / (double)SCALE_X *0.95;
400 break;
401 }
402
403 if (nwmax <= (long)(MCC_WN * SCALE_X)) {
404 MCC_WN = (double)nwmax / (double)SCALE_X *0.95;
405 MCC_WP = (double)pwmin / (double)SCALE_X;
406 break;
407 }
408
409
410 MCC_WP = 2.0 * MCC_WN;
411 }
412 }
413 if (tec < 0.0)
414 MCC_DIF = MCC_LN * 2.0;
415 else
416 MCC_DIF = tec * 2.0;
417
418 if (tec > 0.0001) {
419 if (MCC_LN < 0.0001)
420 MCC_LN = tec;
421 if (MCC_WN < 0.0001)
422 MCC_WN = tec * 6.0;
423 if (MCC_LP < 0.0001)
424 MCC_LP = tec;
425 if (MCC_WP < 0.0001)
426 MCC_WP = tec * 12.0;
427 if (MCC_DIF < 0.0001)
428 MCC_DIF = tec * 2.0;
429 }
430
431 if (*modeln == NULL)
432 {
433 *modeln = mcc_getmodel (MCC_MODELFILE, MCC_TNMODEL, MCC_NMOS,
434 MCC_NCASE, MCC_LN * 1.0e-06, MCC_WN * 1.0e-06,0);
435 }
436
437 if (*modelp == NULL)
438 {
439 *modelp = mcc_getmodel (MCC_MODELFILE, MCC_TPMODEL, MCC_PMOS,
440 MCC_PCASE, MCC_LP * 1.0e-06, MCC_WP * 1.0e-06,0);
441 }
442
443 if (*modeln==NULL || *modelp==NULL) return res;
444
445 fprintf (stdout, "Transistor size for automatic model calculation:\n");
446 fprintf (stdout, "%s : LN=%g WN=%g %s : LP=%g WP=%g\n", (*modeln)->NAME,
447 MCC_LN, MCC_WN, (*modelp)->NAME, MCC_LP, MCC_WP);
448
449 mcc_drvparam (lotrsparam_n,lotrsparam_p);
450 }
451 else
452 {
453 if (*modeln == NULL)
454 {
455 *modeln = mcc_getmodel (MCC_MODELFILE, MCC_TNMODEL, MCC_NMOS,
456 MCC_NCASE, MCC_LN * 1.0e-06, MCC_WN * 1.0e-06,0);
457 }
458
459 if (*modelp == NULL)
460 {
461 *modelp = mcc_getmodel (MCC_MODELFILE, MCC_TPMODEL, MCC_PMOS,
462 MCC_PCASE, MCC_LP * 1.0e-06, MCC_WP * 1.0e-06,0);
463 }
464
465 if (*modeln==NULL || *modelp==NULL) return res;
466 mcc_drvparam (lotrsparam_n,lotrsparam_p);
467 }
468
469 lotrsparam_n->SUBCKTNAME=MCC_TN_SUBCKT;
470 lotrsparam_p->SUBCKTNAME=MCC_TP_SUBCKT;
471 memcpy(&mcc_user_lotrsparam_n, lotrsparam_n, sizeof(mcc_user_lotrsparam_n));
472 memcpy(&mcc_user_lotrsparam_p, lotrsparam_p, sizeof(mcc_user_lotrsparam_p));
473 mcc_check_techno_with_subckt(lotrsparam_n,lotrsparam_p, MCC_TN_SUBCKT, MCC_TP_SUBCKT);
474
475 if(MCC_OPTIM_MODE == 1){
476 MCC_DEBUG_INTERNAL = YES ;
477 mcc_spicecurrent( MCC_VDDmax, MCC_VDDmax, lotrsparam_n->VBULK, MCC_TRANS_N, lotrsparam_n );
478 mcc_spicecurrent( MCC_VDDmax, MCC_VDDmax, lotrsparam_p->VBULK-MCC_VDDmax, MCC_TRANS_P, lotrsparam_p );
479 MCC_DEBUG_INTERNAL = NO ;
480 }
481
482 if (MCC_MODE != MCC_FAST_MODE) {
483 mcc_prsparam (lotrsparam_n,lotrsparam_p);
484
485 tec = mcc_getdouble ("Technology size (in micro-meter)", 0.0, 100.0, (tec < 0.0) ? 0.0 : tec);
486
487 if (tec > 0.0001) {
488 MCC_TECSIZE = tec;
489 MCC_LN = tec;
490 MCC_WN = tec * 6.0;
491 MCC_LP = tec;
492 MCC_WP = tec * 12.0;
493 MCC_DIF = tec * 2.0;
494 }
495
496 MCC_LN = mcc_getdouble ("N MOS tansistor length size (in micro-meter)", 0.0, 100.00, MCC_LN);
497 MCC_WN = mcc_getdouble ("N MOS tansistor width size (in micro-meter)", 0.0, 1000.0, MCC_WN);
498 MCC_LP = mcc_getdouble ("P MOS tansistor length size (in micro-meter)", 0.0, 100.0, MCC_LP);
499 MCC_WP = mcc_getdouble ("P MOS tansistor width size (in micro-meter)", 0.0, 1000.0, MCC_WP);
500 MCC_VDDmax = mcc_getdouble ("Power supply (in Volt)", 0.1, 10.0, MCC_VDDmax);
501 MCC_VGS = MCC_VDDmax / 2.0 ;
502 if ( lotrsparam_n->VBULK < ELPMINVBULK )
503 lotrsparam_n->VBULK = 0.0;
504 if ( lotrsparam_p->VBULK < ELPMINVBULK )
505 lotrsparam_p->VBULK = MCC_VDDmax;
506 if ( b3 || b4 )
507 {
508 lotrsparam_n->PARAM[elpDELVT0] = mcc_getdouble ("N MOS transistor threshold voltage shrink (DELVT0)", -MCC_VTN/2.0, MCC_VTN/2.0, lotrsparam_n->PARAM[elpDELVT0]);
509 lotrsparam_n->PARAM[elpMULU0] = mcc_getdouble ("N MOS transistor mobility mult factor (U0)", 0.5, 1.5, lotrsparam_n->PARAM[elpMULU0]);
510 }
511 lotrsparam_n->VBULK = mcc_getdouble ("N MOS transistor bulk voltage (in Volt)", -MCC_VDDmax, MCC_VDDmax, lotrsparam_n->VBULK);
512 MCC_VBULKN = lotrsparam_n->VBULK;
513 if ( b3 || b4 )
514 {
515 lotrsparam_p->PARAM[elpDELVT0] = mcc_getdouble ("P MOS transistor threshold voltage shrink (DELVT0)", -MCC_VTP/2.0, MCC_VTP/2.0, lotrsparam_p->PARAM[elpDELVT0]);
516 lotrsparam_p->PARAM[elpMULU0] = mcc_getdouble ("P MOS transistor mobility mult factor (U0)", 0.5, 1.5, lotrsparam_p->PARAM[elpMULU0]);
517 }
518 lotrsparam_p->VBULK = mcc_getdouble ("P MOS transistor bulk voltage (in Volt)", -MCC_VDDmax, 2.0*MCC_VDDmax, lotrsparam_p->VBULK);
519 MCC_VBULKP = lotrsparam_p->VBULK;
520 MCC_DIF = mcc_getdouble ("Transistor diffusion width (in micro-meter)", 0.1, 100.0, MCC_DIF);
521
522 if (MCC_MODE == MCC_EXPERT_MODE) {
523 MCC_DC_STEP = mcc_getdouble ("Electrical simulation dc step", 0.00001, 0.100, MCC_DC_STEP);
524 MCC_INSNUMB = mcc_getint ("Number of instances to fit parametres", 10, 100, MCC_INSNUMB);
525 MCC_CAPA = mcc_getdouble ("Capacitance to fit curent parameters (in fF)", 10, 10000, MCC_CAPA);
526 MCC_INVNUMB = mcc_getint ("Number of inverters to fit gate capacitance", 1, 100, MCC_INVNUMB);
527 MCC_TRANSNUMB = mcc_getint ("Number of transistors to fit diffusion capacitance", 1, 100, MCC_TRANSNUMB);
528 }
529
530 mcc_drvparam (lotrsparam_n,lotrsparam_p);
531 }
532 else
533 {
534 if (param_used)
535 {
536 if (param[0].l!=0) MCC_LN=param[0].l* 1e06;
537 if (param[1].l!=0) MCC_LP=param[1].l* 1e06;
538 if (param[0].w!=0) MCC_WN=param[0].w* 1e06;
539 if (param[1].w!=0) MCC_WP=param[1].w* 1e06;
540 }
541 }
542 {
543 double kasn=MCC_WN*MCC_DIF, kadn=MCC_WN*MCC_DIF, kpsn=(2*MCC_DIF)+(2*MCC_WN), kpdn=(2*MCC_DIF)+(2*MCC_WN);
544 double kasp=MCC_WP*MCC_DIF, kadp=MCC_WP*MCC_DIF, kpsp=(2*MCC_DIF)+(2*MCC_WP), kpdp=(2*MCC_DIF)+(2*MCC_WP);
545 if (param_used)
546 {
547 if (param[0].as!=0) kasn=param[0].as* 1e12/SCALE_X;
548 if (param[0].ad!=0) kadn=param[0].ad* 1e12/SCALE_X;
549 if (param[0].ps!=0) kpsn=param[0].ps* 1e06/SCALE_X;
550 if (param[0].pd!=0) kpdn=param[0].pd* 1e06/SCALE_X;
551 if (param[1].as!=0) kasp=param[1].as* 1e12/SCALE_X;
552 if (param[1].ad!=0) kadp=param[1].ad* 1e12/SCALE_X;
553 if (param[1].ps!=0) kpsp=param[1].ps* 1e06/SCALE_X;
554 if (param[1].pd!=0) kpdp=param[1].pd* 1e06/SCALE_X;
555 }
556 sprintf(surf_string_n, "as=%gp ad=%gp ps=%gu pd=%gu", kasn, kadn, kpsn, kpdn);
557 sprintf(surf_string_p, "as=%gp ad=%gp ps=%gu pd=%gu", kasp, kadp, kpsp, kpdp);
558 }
559 if ( lotrsparam_n )
560 lotrsparam_n = mcc_lotrsparam_set ( lotrsparam_n,
561 lotrsparam_n->PARAM[elpDELVT0],
562 lotrsparam_n->PARAM[elpMULU0],
563 lotrsparam_n->PARAM[elpSA],
564 lotrsparam_n->PARAM[elpSB],
565 lotrsparam_n->PARAM[elpSD],
566 lotrsparam_n->PARAM[elpNF],
567 lotrsparam_n->PARAM[elpM],
568 lotrsparam_n->PARAM[elpNRS],
569 lotrsparam_n->PARAM[elpNRD],
570 lotrsparam_n->PARAM[elpSC],
571 lotrsparam_n->PARAM[elpSCA],
572 lotrsparam_n->PARAM[elpSCB],
573 lotrsparam_n->PARAM[elpSCC],
574 lotrsparam_n->VBULK );
575 if ( lotrsparam_p )
576 lotrsparam_p = mcc_lotrsparam_set ( lotrsparam_p,
577 lotrsparam_p->PARAM[elpDELVT0],
578 lotrsparam_p->PARAM[elpMULU0],
579 lotrsparam_p->PARAM[elpSA],
580 lotrsparam_p->PARAM[elpSB],
581 lotrsparam_p->PARAM[elpSD],
582 lotrsparam_p->PARAM[elpNF],
583 lotrsparam_p->PARAM[elpM],
584 lotrsparam_p->PARAM[elpNRS],
585 lotrsparam_p->PARAM[elpNRD],
586 lotrsparam_p->PARAM[elpSC],
587 lotrsparam_p->PARAM[elpSCA],
588 lotrsparam_p->PARAM[elpSCB],
589 lotrsparam_p->PARAM[elpSCC],
590 lotrsparam_p->VBULK );
591
592 lotrsparam_n->SUBCKTNAME=MCC_TN_SUBCKT;
593 lotrsparam_p->SUBCKTNAME=MCC_TP_SUBCKT;
594
595 if (MCC_VBULKP <= ELPMINVBULK) MCC_VBULKP=lotrsparam_p->VBULK;
596 if (MCC_VBULKN <= ELPMINVBULK) MCC_VBULKN=lotrsparam_n->VBULK;
597 if (MCC_VBULKP <= ELPMINVBULK) MCC_VBULKP=MCC_VDDmax;
598 if (MCC_VBULKN <= ELPMINVBULK) MCC_VBULKN=0;
599
600 mcc_calcspiparam (MCC_TRANS_B,lotrsparam_n,lotrsparam_p);
601
602 mcc_genspi (fit,lotrsparam_n,lotrsparam_p);
603
604 if (spice)
605 mcc_runspice (fit);
606
607 if ( avt_islog(2,LOGMCC) )
608 {
609 mcc_DisplayInfos (MCC_MODELFILE, MCC_TNMODEL,
610 MCC_NMOS, MCC_NCASE, MCC_LN*1.0e-6, MCC_WN*1.0e-6,
611 MCC_TEMP, MCC_VDDmax/2.0, 0.0, MCC_VDDmax/2.0,
612 MCC_VDDmax,lotrsparam_n);
613 mcc_DisplayInfos (MCC_MODELFILE, MCC_TPMODEL,
614 MCC_PMOS, MCC_PCASE, MCC_LP*1.0e-6, MCC_WP*1.0e-6,
615 MCC_TEMP, MCC_VDDmax/2.0, 0.0, MCC_VDDmax/2.0,
616 MCC_VDDmax,lotrsparam_p);
617 }
618
619
620 mcc_drvparam (lotrsparam_n,lotrsparam_p);
621
622 if ( V_BOOL_TAB[__SIM_USE_PRINT].VALUE )
623 mcc_readspidata (fit,lotrsparam_n,lotrsparam_p);
624 if ( V_BOOL_TAB[__SIM_USE_MEAS].VALUE )
625 mcc_optim_readspidata (fit,lotrsparam_n,lotrsparam_p);
626
627 if (MCC_MODE != MCC_FAST_MODE) {
628 mcc_prsparam (lotrsparam_n,lotrsparam_p);
629
630 MCC_TNMODELTYPE = mcc_getword ("N Transistor model type name", MCC_TNMODELTYPE);
631
632 MCC_NCASE = mcc_gettab ("N transistor corner", MCC_CASE_NAME, MCC_NB_CASE, MCC_NCASE);
633
634 MCC_TPMODELTYPE = mcc_getword ("P Transistor model type name", MCC_TPMODELTYPE);
635
636 MCC_PCASE = mcc_gettab ("P transistor corner", MCC_CASE_NAME, MCC_NB_CASE, MCC_PCASE);
637
638 if (MCC_SPICEMODELTYPE == MCC_OTHER)
639 MCC_SPICEMODELTYPE = MCC_NOMODELTYPE;
640
641 MCC_LNMIN = mcc_getdouble ("N Transistor minimum length", 0.0, 1.0e99, MCC_LNMIN);
642
643 MCC_LNMAX = mcc_getdouble ("N Transistor maximun length", 0.0, 1.0e99, MCC_LNMAX);
644
645 MCC_WNMIN = mcc_getdouble ("N Transistor minimum width", 0.0, 1.0e99, MCC_WNMIN);
646
647 MCC_WNMAX = mcc_getdouble ("N Transistor maximun width", 0.0, 1.0e99, MCC_WNMAX);
648
649 MCC_LPMIN = mcc_getdouble ("P Transistor minimum length", 0.0, 1.0e99, MCC_LPMIN);
650
651 MCC_LPMAX = mcc_getdouble ("P Transistor maximun length", 0.0, 1.0e99, MCC_LPMAX);
652
653 MCC_WPMIN = mcc_getdouble ("P Transistor minimum width", 0.0, 1.0e99, MCC_WPMIN);
654
655 MCC_WPMAX = mcc_getdouble ("P Transistor maximun width", 0.0, 1.0e99, MCC_WPMAX);
656
657 if (MCC_MODE == MCC_EXPERT_MODE) {
658 MCC_XWN = mcc_getdouble ("N Transistor width scale", 0.1, 1.0, MCC_XWN);
659 MCC_XLN = mcc_getdouble ("N Transistor length scale", 0.1, 1.0, MCC_XLN);
660 MCC_XWP = mcc_getdouble ("P Transistor width scale", 0.1, 1.0, MCC_XWP);
661 MCC_XLP = mcc_getdouble ("P Transistor length scale", 0.1, 1.0, MCC_XLP);
662 }
663
664 MCC_DWN = mcc_getdouble ("N transistor width shrink parameter (in micro-meter)", -100.0, 100.0, MCC_DWN);
665 MCC_DWCJN = mcc_getdouble ("N transistor effective width shrink parameter for capacitance (in micro-meter)",
666 -100.0, 100.0, MCC_DWCJN);
667 MCC_DLN = mcc_getdouble ("N transistor length shrink parameter (in micro-meter)", -100.0, 100.0, MCC_DLN);
668 MCC_DWP = mcc_getdouble ("P transistor width shrink parameter (in micro-meter)", -100.0, 100.0, MCC_DWP);
669 MCC_DWCJP = mcc_getdouble ("P transistor effective width shrink parameter for capacitance (in micro-meter)",
670 -100.0, 100.0, MCC_DWCJP);
671 MCC_DLP = mcc_getdouble ("P transistor length shrink parameter (in micro-meter)", -100.0, 100.0, MCC_DLP);
672
673 MCC_DWCN = mcc_getdouble ("N transistor active width shrink parameter (in micro-meter)",
674 -100.0, 100.0, MCC_DWCN);
675 MCC_DLCN = mcc_getdouble ("N transistor active length shrink parameter (in micro-meter)",
676 -100.0, 100.0, MCC_DLCN);
677 MCC_DWCP = mcc_getdouble ("P transistor active width shrink parameter (in micro-meter)",
678 -100.0, 100.0, MCC_DWCP);
679 MCC_DLCP = mcc_getdouble ("P transistor active length shrink parameter (in micro-meter)",
680 -100.0, 100.0, MCC_DLCP);
681 mcc_drvparam (lotrsparam_n,lotrsparam_p);
682 }
683
684 if (vt == 1) {
685 mcc_trs_corner( MCC_TRANS_N, lotrsparam_n, lotrsparam_p, &infon );
686 mcc_trs_corner( MCC_TRANS_P, lotrsparam_n, lotrsparam_p, &infop );
687 if( V_BOOL_TAB[ __MCC_NEW_IDS_SAT ].VALUE ) {
688 mcc_calcul_sat_parameter( MCC_TRANS_N, lotrsparam_n, &infon );
689 mcc_calcul_sat_parameter( MCC_TRANS_P, lotrsparam_p, &infop );
690 }
691 else {
692 mcc_calcul_vt (MCC_TRANS_N,lotrsparam_n,lotrsparam_p,&infon);
693 mcc_calcul_vt (MCC_TRANS_P,lotrsparam_n,lotrsparam_p,&infop);
694 }
695 }
696
697 if (MCC_MODE != MCC_FAST_MODE) {
698 MCC_VTN = mcc_getdouble ("N transistor threshold voltage (in volt)", 0.0, MCC_VDDmax, MCC_VTN);
699 MCC_VTP = mcc_getdouble ("P transistor threshold voltage (in volt)", 0.0, MCC_VDDmax, MCC_VTP);
700 }
701
702 if (vt==1)
703 {
704 if( !V_BOOL_TAB[ __MCC_NEW_IDS_SAT ].VALUE ) {
705 if ( MCC_NEW_CALC_ABR && MCC_OPTIM_MODE )
706 {
707 mcc_get_best_abr_from_vt ( MCC_TRANS_N, lotrsparam_n,lotrsparam_p,&infon );
708 mcc_get_best_abr_from_vt ( MCC_TRANS_P, lotrsparam_n,lotrsparam_p,&infop );
709 }
710 else {
711 mcc_calcul_abr (MCC_TRANS_N,-1.0,-1.0,lotrsparam_n,lotrsparam_p);
712 mcc_calcul_abr (MCC_TRANS_P,-1.0,-1.0,lotrsparam_n,lotrsparam_p);
713 }
714 }
715
716
717 if( V_BOOL_TAB[__AVT_RST_BETTER].VALUE ) {
718 mcc_calcul_rst_better(MCC_TRANS_N,lotrsparam_n,lotrsparam_p, &infon );
719 mcc_calcul_rst_better(MCC_TRANS_P,lotrsparam_n,lotrsparam_p, &infop );
720 }
721 else {
722 mcc_calcul_rst(MCC_TRANS_N,lotrsparam_n,lotrsparam_p);
723 mcc_calcul_rst(MCC_TRANS_P,lotrsparam_n,lotrsparam_p);
724 }
725 mcc_calcul_k (MCC_TRANS_N,lotrsparam_n);
726 mcc_calcul_k (MCC_TRANS_P,lotrsparam_p);
727 mcc_calcul_vdeg (MCC_TRANS_B,lotrsparam_n,lotrsparam_p);
728 mcc_calcul_vti (MCC_TRANS_B,lotrsparam_n,lotrsparam_p);
729 }
730 if(MCC_DEBUG_MODE > 0)
731 {
732 if(MCC_DEBUG_LEAK == 'Y')
733 mcc_calcul_leak (lotrsparam_n,lotrsparam_p) ;
734 if(MCC_DEBUG_RSAT == 'Y')
735 {
736 mcc_fill_current_for_rsat(lotrsparam_n,lotrsparam_p);
737 mcc_calcul_rsat(lotrsparam_n,lotrsparam_p) ;
738 }
739 if(MCC_DEBUG_RLIN == 'Y')
740 {
741 mcc_calcul_rlin(lotrsparam_n,lotrsparam_p) ;
742 }
743 if((MCC_DEBUG_RSAT == 'Y') && (MCC_DEBUG_RLIN == 'Y'))
744 mcc_calcul_vsat(lotrsparam_n,lotrsparam_p) ;
745 if(MCC_DEBUG_VTH == 'Y')
746 mcc_calcul_vth(lotrsparam_n,lotrsparam_p) ;
747 if(MCC_DEBUG_QINT == 'Y') {
748 mcc_calcul_qint (lotrsparam_n,lotrsparam_p, 'G' ) ;
749 mcc_calcul_qint (lotrsparam_n,lotrsparam_p, 'D' ) ;
750 mcc_check_capa( lotrsparam_n, lotrsparam_p ) ;
751 }
752 if(MCC_DEBUG_JCT_CAPA == 'Y')
753 {
754 mcc_calc_jct_capa (lotrsparam_n,lotrsparam_p) ;
755 }
756 if(MCC_DEBUG_INPUTCAPA == 'Y')
757 {
758 mcc_bilan_capa(lotrsparam_n,lotrsparam_p);
759 mcc_calc_coupling_capa(lotrsparam_n,lotrsparam_p);
760 }
761 if(MCC_DEBUG_CARAC == 'Y') {
762 mcc_calcul_trans(lotrsparam_n,lotrsparam_p) ;
763 mcc_calcul_rapisat_fqmulu0 (lotrsparam_n,lotrsparam_p);
764 }
765 if(MCC_DEBUG_CARACNEG == 'Y')
766 mcc_calcul_transneg(lotrsparam_n,lotrsparam_p) ;
767 if(MCC_DEBUG_DEG == 'Y')
768 mcc_calcul_deg(lotrsparam_n,lotrsparam_p) ;
769 }
770
771 mcc_drvparam (lotrsparam_n,lotrsparam_p);
772
773 if (vt==0 && MCC_CALC_CUR == MCC_SIM_MODE) {
774 ncurrent_vt = mcc_spicesimcurrent(MCC_VTN,MCC_VDDmax,0.0,MCC_TRANS_N) ;
775 pcurrent_vt = mcc_spicesimcurrent(MCC_VTP,MCC_VDDmax,0.0,MCC_TRANS_P) ;
776 }
777 mcc_freespidata (fit, MCC_TRANS_B);
778
779 if (MCC_MODE != MCC_FAST_MODE) {
780 mcc_prsparam (lotrsparam_n,lotrsparam_p);
781
782 MCC_CGSN = mcc_getdouble ("N tansistor gate capacitance (in pF/u2)", 0.0, 1.0, MCC_CGSN);
783 MCC_CGSP = mcc_getdouble ("P tansistor gate capacitance (in pF/u2)", 0.0, 1.0, MCC_CGSP);
784 MCC_CGDN = mcc_getdouble ("N tansistor gate/drain capacitance (in pF/u2)", 0.0, 1.0, MCC_CGDN);
785 MCC_CGDCN = mcc_getdouble ("N tansistor gate/drain conflict capacitance (in pF/u2)", 0.0, 1.0, MCC_CGDCN);
786 MCC_CGDP = mcc_getdouble ("P tansistor gate/drain capacitance (in pF/u2)", 0.0, 1.0, MCC_CGDP);
787 MCC_CGDCP = mcc_getdouble ("P tansistor gate/drain conflict capacitance (in pF/u2)", 0.0, 1.0, MCC_CGDCP);
788 MCC_CGPN = mcc_getdouble ("N tansistor gate diffusion capacitance (in pF/u)", 0.0, 1.0, MCC_CGPN);
789 MCC_CGPP = mcc_getdouble ("P tansistor gate diffusion capacitance (in pF/u)", 0.0, 1.0, MCC_CGPP);
790 MCC_CDSN = MCC_CSSN = mcc_getdouble ("Area N transistor diffusion capacitance (in pF/u2)", 0.0, 1.0, MCC_CDSN);
791 MCC_CDS_U_N = MCC_CDS_D_N = MCC_CDSN;
792 MCC_CDSP = MCC_CSSP = mcc_getdouble ("Area P transistor diffusion capacitance (in pF/u2)", 0.0, 1.0, MCC_CDSP);
793 MCC_CDS_U_P = MCC_CDS_D_P = MCC_CDSP;
794 MCC_CDPN = MCC_CSPN = mcc_getdouble ("Perimeter N transistor diffusion capacitance (in pF/u)",
795 0.0, 1.0, MCC_CDPN);
796 MCC_CDP_U_N = MCC_CDP_D_N = MCC_CDPN;
797 MCC_CDPP = MCC_CSPP = mcc_getdouble ("Perimeter P transistor diffusion capacitance (in pF/u)",
798 0.0, 1.0, MCC_CDPP);
799 MCC_CDP_U_P = MCC_CDP_D_P = MCC_CDPP;
800 MCC_CDWN = MCC_CSWN = mcc_getdouble ("Width N transistor diffusion capacitance (in pF/u)", 0.0, 1.0, MCC_CDWN);
801 MCC_CDW_U_N = MCC_CDW_D_N = MCC_CDWN;
802 MCC_CDWP = MCC_CSWP = mcc_getdouble ("Width P transistor diffusion capacitance (in pF/u)", 0.0, 1.0, MCC_CDWP);
803 MCC_CDW_U_P = MCC_CDW_D_P = MCC_CDWP;
804
805 if (MCC_MODE == MCC_EXPERT_MODE) {
806 MCC_ERROR = mcc_getdouble ("Max error to fit parameters (in %)", 0.1, 100.0, MCC_ERROR);
807 MCC_NBMAXLOOP = mcc_getint ("Maximun number of loop to fit parameters", 1, 100, MCC_NBMAXLOOP);
808 }
809
810 mcc_drvparam (lotrsparam_n,lotrsparam_p);
811 pt = mcc_initstr ("y");;
812 while (res) {
813 pt = mcc_getword ("Do you want to characterize other models y/n", pt);
814 if (strcmp (pt, "n") == 0) {
815 res = 0;
816 }
817 else if (strcmp (pt, "y") == 0) {
818 break;
819 }
820 }
821 mbkfree (pt);
822 }
823
824 if(vt && MCC_DEBUG_MODE > 0)
825 {
826 if(MCC_DEBUG_INPUTCAPA == 'Y')
827 {
828 /* mcc_cal_con_capa ( 'n', 's') ;
829 mcc_cal_con_capa ( 'n', 'g') ;
830 mcc_cal_con_capa ( 'n', 'd') ;
831 mcc_cal_con_capa ( 'p', 's') ;
832 mcc_cal_con_capa ( 'p', 'g') ;
833 mcc_cal_con_capa ( 'p', 'd') ;
834 */
835 }
836 }
837 return (res);
838 }
839
840
841 static void mcc_parse_instance_spec(char *str, elp_lotrs_param *lotrsparam_n, int idx)
842 {
843 eqt_ctx *ctx;
844 char *c, *var;
845 char buf[1024];
846 chain_list *cl=NULL, *ch;
847 int i=0, err;
848 double value;
849
850 if (str==NULL) return;
851
852 ctx=eqt_init(10);
853 eqt_add_spice_extension(ctx);
854
855 c=str;
856 while (*c!='\0')
857 {
858 if (*c!=' ')
859 {
860 if (*c=='=')
861 {
862 buf[i]='\0';
863 i=0;
864 if (strlen(buf)!=0) cl=addchain(cl,mbkstrdup(buf));
865 cl=addchain(cl,mbkstrdup("="));
866 }
867 else buf[i++]=*c;
868 }
869 else
870 {
871 buf[i]='\0';
872 i=0;
873 if (strlen(buf)!=0) cl=addchain(cl,mbkstrdup(buf));
874 }
875 c++;
876 }
877
878 buf[i]='\0';
879 if (strlen(buf)!=0) cl=addchain(cl,mbkstrdup(buf));
880
881 cl=ch=reverse(cl);
882 while (ch!=NULL)
883 {
884 if (ch->NEXT!=NULL && ch->NEXT->NEXT!=NULL && strcmp((char *)ch->NEXT->DATA,"=")==0)
885 {
886 var=(char *)ch->DATA;
887 value=eqt_eval (ctx, namealloc((char *)ch->NEXT->NEXT->DATA), EQTFAST);
888 if (eqt_resistrue (ctx))
889 {
890 err=0;
891 if (strcasecmp(var, "delvto")==0) lotrsparam_n->PARAM[elpDELVT0]=value;
892 else if (strcasecmp(var, "mulu0")==0) lotrsparam_n->PARAM[elpMULU0]=value;
893 else if (strcasecmp(var, "sa")==0) lotrsparam_n->PARAM[elpSA]=value;
894 else if (strcasecmp(var, "sb")==0) lotrsparam_n->PARAM[elpSB]=value;
895 else if (strcasecmp(var, "sd")==0) lotrsparam_n->PARAM[elpSD]=value;
896 else if (strcasecmp(var, "nf")==0) lotrsparam_n->PARAM[elpNF]=value;
897 // else if (strcasecmp(var, "m")==0) lotrsparam_n->PARAM[elpM]=value;
898 else if (strcasecmp(var, "nrs")==0) lotrsparam_n->PARAM[elpNRS]=value;
899 else if (strcasecmp(var, "nrd")==0) lotrsparam_n->PARAM[elpNRD]=value;
900 else if (strcasecmp(var, "sc")==0) lotrsparam_n->PARAM[elpSC]=value;
901 else if (strcasecmp(var, "sca")==0) lotrsparam_n->PARAM[elpSCA]=value;
902 else if (strcasecmp(var, "scb")==0) lotrsparam_n->PARAM[elpSCB]=value;
903 else if (strcasecmp(var, "scc")==0) lotrsparam_n->PARAM[elpSCC]=value;
904 else if (strcasecmp(var, "vbulk")==0) lotrsparam_n->VBULK=value;
905 else if (strcasecmp(var, "l")==0) param[idx].l=value;
906 else if (strcasecmp(var, "w")==0) param[idx].w=value;
907 else { avt_errmsg(MCC_ERRMSG, "036", AVT_ERROR, var); err=1; }
908 }
909 else
910 {
911 avt_errmsg(MCC_ERRMSG, "037", AVT_ERROR, (char *)ch->DATA, (char *)ch->NEXT->NEXT->DATA) ;
912 }
913 }
914 mbkfree(ch->DATA);
915 ch=delchain(ch, ch);
916 }
917 eqt_term(ctx);
918 }
919 void mcc_CheckTechno(char *label, char *tn, char *tp)
920 {
921 int aut=0, spice=1, fit=1, vt=1;
922 float tec=-1.0;
923 int res, save_ELP_LOAD_FILE_TYPE;
924 char buf[158];
925 int save_print, save_meas;
926 char *cn, *cp, *c, *search;
927 char *newtech;
928 char copytn[1024], copytp[1024];
929 char newtn[128], newtp[128];
930
931 elp_lotrs_param *lotrsparam_n = NULL;
932 elp_lotrs_param *lotrsparam_p = NULL;
933 mcc_modellist *modeln = NULL;
934 mcc_modellist *modelp = NULL;
935
936 strcpy(copytn, tn);
937 strcpy(copytp, tp);
938
939 sprintf(buf,"%s_techno_check.elp",label);
940
941 cp = MCC_ELPFILE = mbkstrdup(buf);
942 avt_sethashvar("avtSpiKeepCards", "all");
943 avt_sethashvar("avtSpiKeepNames", "all");
944 avt_sethashvar("avtElpTechnoName", MCC_ELPFILE);
945 avt_sethashvar("avtElpGenTechnoName", MCC_ELPFILE);
946 avt_sethashvar("avtElpDriveFile", "yes");
947 avt_sethashvar("avtLoadSpecifiedElpFile", "no");
948
949 elpenv() ;
950 save_ELP_LOAD_FILE_TYPE=ELP_LOAD_FILE_TYPE;
951
952 // mcc_initcalcparam(0);
953 mccenv ();
954 MCC_ELPFILE=cp;
955
956 resetparam();
957
958
959 //ELP_LOAD_FILE_TYPE = ELP_LOADELP_FILE;
960
961 MCC_DEBUG_MODE = 1 ;
962 MCC_DEBUG_GATE = NULL ;
963 MCC_DEBUG_INPUT = -1 ;
964 MCC_DEBUG_TRANS = -1 ;
965 MCC_DEBUG_SLOPE = 0 ;
966 MCC_DEBUG_CAPA = 0 ;
967 MCC_DEBUG_RSAT = 'N' ;
968 MCC_DEBUG_LEAK = 'N' ;
969 MCC_DEBUG_RLIN = 'N' ;
970 MCC_DEBUG_VTH = 'N' ;
971 MCC_DEBUG_QINT = 'N' ;
972 MCC_DEBUG_JCT_CAPA = 'N' ; // Junction capacitance => Cjbd, Cjbs...
973 MCC_DEBUG_INPUTCAPA = 'N' ;
974 MCC_DEBUG_CARAC = 'N' ;
975 MCC_DEBUG_CARACNEG = 'N' ;
976 MCC_DEBUG_DEG = 'N' ;
977 MCC_DEBUG_PASS_TRANS = 'X' ; // value can be 'N' or 'P'
978 MCC_DEBUG_SWITCH = 'X' ; // value can be 'N' or 'P'
979 MCC_DEBUG_BLEEDER = 'N' ;
980
981 memset(&TRS_CURVS, 0, sizeof(Icurvs));
982
983 if (getenv("MCC_FAST")!=NULL)
984 fit=0, MCC_DEBUG_MODE=0;
985
986 MCC_DEBUG_PREFIX=label;
987
988 elpLoadOnceElp();
989 MCC_TECHFILE = V_STR_TAB[__MCC_MODEL_FILE].VALUE;
990
991 MCC_MODE = MCC_FAST_MODE;
992
993 save_print=V_BOOL_TAB[__SIM_USE_PRINT].VALUE; V_BOOL_TAB[__SIM_USE_PRINT].VALUE=1;
994 save_meas=V_BOOL_TAB[__SIM_USE_MEAS].VALUE; V_BOOL_TAB[__SIM_USE_MEAS].VALUE=0;
995
996 if (V_FLOAT_TAB[__SIM_TECHNO_SIZE].SET)
997 {
998 tec=V_FLOAT_TAB[__SIM_TECHNO_SIZE].VALUE;
999 aut=0;
1000 MCC_LN = tec;
1001 MCC_WN = tec * 6.0;
1002 MCC_LP = tec;
1003 MCC_WP = tec * 12.0;
1004 MCC_DIF = tec * 2.0;
1005 }
1006 else aut=1;
1007
1008 MCC_VDDmax = V_FLOAT_TAB[__SIM_POWER_SUPPLY].VALUE;
1009 elpGeneral[elpGVDDMAX]=MCC_VDDmax;
1010 MCC_VGS = MCC_VDDmax / 2.0 ;
1011
1012 MCC_SLOPE = V_FLOAT_TAB[__SIM_INPUT_SLOPE].VALUE*1e12;
1013
1014 MCC_TEMP = V_FLOAT_TAB[__SIM_TEMP].VALUE;
1015
1016 cn=strchr(copytn, ' '); if (cn!=NULL) *cn='\0', cn++;
1017 cp=strchr(copytp, ' '); if (cp!=NULL) *cp='\0', cp++;
1018
1019 if ((search=strchr(copytn, '('))!=NULL)
1020 {
1021 cn = search;
1022 *cn='\0';
1023 cn++;
1024 if ((c=strchr(cn,')'))!=NULL) *c='\0';
1025 MCC_TN_SUBCKT=namealloc(cn);
1026 if (c != NULL) cn = c+1;
1027 }
1028
1029 if ((search=strchr(copytp, '('))!=NULL)
1030 {
1031 cp = search;
1032 *cp='\0';
1033 cp++;
1034 if ((c=strchr(cp,')'))!=NULL) *c='\0';
1035 MCC_TP_SUBCKT=namealloc(cp);
1036 if (c != NULL) cp = c+1;
1037 }
1038
1039 MCC_TNMODEL = mcc_initstr (copytn);
1040 MCC_TPMODEL = mcc_initstr (copytp);
1041
1042 MCC_OPTIM_MODE = 0 ;
1043 MCC_CALC_CUR = MCC_SIM_MODE;
1044
1045 lotrsparam_n = mcc_init_lotrsparam ();
1046 lotrsparam_p = mcc_init_lotrsparam ();
1047
1048 if ( lotrsparam_n->VBULK < ELPMINVBULK )
1049 lotrsparam_n->VBULK = 0.0;
1050 if ( lotrsparam_p->VBULK < ELPMINVBULK )
1051 lotrsparam_p->VBULK = MCC_VDDmax;
1052
1053 mcc_parse_instance_spec(cn, lotrsparam_n, 0);
1054 mcc_parse_instance_spec(cp, lotrsparam_p, 1);
1055
1056 res = mcc_genelp (spice, 0, tec, aut,
1057 fit, &modeln, &modelp,
1058 lotrsparam_n,lotrsparam_p);
1059
1060 if (modeln==NULL && modelp==NULL && aut==1)
1061 {
1062 if (modeln==NULL) avt_errmsg(MCC_ERRMSG, "027", AVT_ERROR, copytn) ;
1063 if (modelp==NULL) avt_errmsg(MCC_ERRMSG, "027", AVT_ERROR, copytp) ;
1064 }
1065 else
1066 {
1067 MCC_DEBUG_GATE = NULL ;
1068 MCC_DEBUG_RSAT = 'Y' ;
1069 MCC_DEBUG_LEAK = 'N' ;
1070 MCC_DEBUG_RLIN = 'Y' ;
1071 MCC_DEBUG_VTH = 'Y' ;
1072 MCC_DEBUG_QINT = 'Y' ;
1073 MCC_DEBUG_JCT_CAPA = 'Y' ; // Junction capacitance => Cjbd, Cjbs...
1074 MCC_DEBUG_INPUTCAPA = 'Y' ;
1075 MCC_DEBUG_CARAC = 'Y' ;
1076 MCC_DEBUG_CARACNEG = 'Y' ;
1077 MCC_DEBUG_DEG = 'Y' ;
1078 MCC_DEBUG_PASS_TRANS = 'X' ; // value can be 'N' or 'P'
1079 MCC_DEBUG_SWITCH = 'X' ; // value can be 'N' or 'P'
1080 MCC_DEBUG_BLEEDER = 'N' ;
1081
1082 MCC_PLOT=1;
1083 MCC_OPTIM_MODE = 1 ;
1084 MCC_CALC_CUR = MCC_CALC_MODE;
1085
1086 elp_lotrs_param_free ( lotrsparam_n );
1087 elp_lotrs_param_free ( lotrsparam_p );
1088 lotrsparam_n = mcc_init_lotrsparam ();
1089 lotrsparam_p = mcc_init_lotrsparam ();
1090
1091 modeln=modelp=NULL;
1092 if ( lotrsparam_n->VBULK < ELPMINVBULK )
1093 lotrsparam_n->VBULK = 0.0;
1094 if ( lotrsparam_p->VBULK < ELPMINVBULK )
1095 lotrsparam_p->VBULK = MCC_VDDmax;
1096
1097 mcc_parse_instance_spec(cn, lotrsparam_n, 0);
1098 mcc_parse_instance_spec(cp, lotrsparam_p, 1);
1099
1100 res = mcc_genelp (0, vt, tec, aut,
1101 0, &modeln, &modelp,
1102 lotrsparam_n,lotrsparam_p);
1103
1104 mcc_gencurv (MCC_PARAM,lotrsparam_n,lotrsparam_p);
1105 newtech=mcc_check_subckt(newtn, newtp);
1106
1107 if (fit)
1108 {
1109 mcc_calcul_ibranch(lotrsparam_n, lotrsparam_p) ;
1110 mcc_genspi_for_inverter_simulator(lotrsparam_n,lotrsparam_p);
1111 }
1112
1113 mcc_drvelp (MCC_PARAM, MCC_TRANS_B,lotrsparam_n,lotrsparam_p,MCC_DRV_ALL_MODEL);
1114 // mcc_gencurv (MCC_PARAM,lotrsparam_n,lotrsparam_p);
1115 mcc_printplot (MCC_PARAM, 1, ncurrent_vt, pcurrent_vt, modeln, modelp);
1116 if (fit && MCC_FLAG_FIT==MCC_FIT_OK)
1117 {
1118 mcc_fit (lotrsparam_n,lotrsparam_p,1);
1119 }
1120 else
1121 {
1122 mcc_gencurv (MCC_FIT,lotrsparam_n,lotrsparam_p);
1123 }
1124 // mcc_printplot (MCC_FIT, 0);
1125
1126 mcc_drive_summary(mcc_getmccname(modeln));
1127
1128 if(MCC_DEBUG_MODE > 1) mcc_genbench() ;
1129 if (newtech!=NULL)
1130 {
1131 printf("*\n*\n");
1132 printf("* The original technology file contains .subckt statement probably with\n"
1133 "* parameter evaluations. To ensure the correct evaluation of the parameters\n"
1134 "* a parameter-free technology file as been genereted :\n* \"%s\"\n"
1135 "* WARNING: THIS FILE CONTAINS SENSIBLE INFORMATION\n"
1136 "*\n*\n"
1137 , newtech
1138 );
1139 }
1140
1141 }
1142
1143 elp_lotrs_param_free ( lotrsparam_n );
1144 lotrsparam_n = NULL;
1145 elp_lotrs_param_free ( lotrsparam_p );
1146 lotrsparam_p = NULL;
1147 ELP_LOAD_FILE_TYPE=save_ELP_LOAD_FILE_TYPE;
1148 MCC_DEBUG_PREFIX="";
1149 V_BOOL_TAB[__SIM_USE_PRINT].VALUE=save_print;
1150 V_BOOL_TAB[__SIM_USE_MEAS].VALUE=save_meas;
1151 MCC_TN_SUBCKT=MCC_TP_SUBCKT=NULL;
1152
1153 if (newtech!=NULL)
1154 {
1155 sprintf(buf,"%s_no_param", label);
1156 printf("*\n"
1157 "* Consider re-runing the techno check API with the new techno file\n"
1158 "* setting: avt_config avtTechnologyName \"%s\"\n"
1159 "* using: avt_CheckTechno \"%s\" \"%s %s\" \"%s %s\"\n"
1160 "*\n\n"
1161 , newtech,buf,newtn, cn, newtp, cp
1162 );
1163 /*
1164 mcc_deltechnofile(MCC_MODELFILE);
1165 elpFreeModel();
1166
1167 oldtech=V_STR_TAB[__MCC_MODEL_FILE].VALUE;
1168 if (oldtech!=NULL) oldtech=sensitive_namealloc(oldtech);
1169 avt_sethashvar("avtTechnologyName", newtech);
1170 mcc_CheckTechno(buf, copytn, copytp);
1171 avt_sethashvar("avtTechnologyName", oldtech);
1172
1173 mcc_deltechnofile(MCC_MODELFILE);
1174 elpFreeModel();
1175
1176 printf("*\n*\n");
1177 printf("* WARNING: A parameter-free technology file as been genereted :\n"
1178 "* WARNING: \"%s\"\n"
1179 "* WARNING: THIS FILE CONTAINS SENSIBLE INFORMATION\n"
1180 "*\n*\n"
1181 , newtech
1182 );
1183 */
1184 }
1185 }
1186
1187 mcc_modifiedparam* mcc_setparamlist( mcc_modellist *model, chain_list *head, double value )
1188 {
1189 int n;
1190 chain_list *chain ;
1191 mcc_modifiedparam *param ;
1192
1193 for( n=0, chain=head ; chain ; chain=chain->NEXT, n++ );
1194 param = mbkalloc( sizeof( mcc_modifiedparam ) * (n+1) );
1195
1196 for( n=0, chain=head ; chain ; chain=chain->NEXT, n++ ) {
1197 param[n].LABEL = (char*)chain->DATA ;
1198 param[n].VALUE = mcc_getparam( model, param[n].LABEL );
1199 mcc_setparam( model, param[n].LABEL, value );
1200 }
1201 param[n].LABEL = NULL ;
1202 param[n].VALUE = -1 ;
1203
1204 return param ;
1205 }
1206
1207 void mcc_restoreparamlist( mcc_modellist *model, mcc_modifiedparam *param )
1208 {
1209 int n;
1210
1211 if( !param )
1212 return ;
1213
1214 n = 0;
1215 while( param[n].LABEL ) {
1216 mcc_setparam( model, param[n].LABEL, param[n].VALUE );
1217 n++ ;
1218 }
1219 mbkfree( param );
1220 }
1221
1222 void mcc_hacktechno( lofig_list *lofig, int whatjob )
1223 {
1224 lotrs_list *lotrs ;
1225 char *modelname ;
1226 float l, w ;
1227 char lotrstype ;
1228 mcc_modellist *model ;
1229 ht *drivedmodel ;
1230 FILE *file ;
1231 chain_list *headparam ;
1232 mcc_modifiedparam *keepvalue0 ;
1233 mcc_modifiedparam *keepvalue1 ;
1234
1235 drivedmodel = addht(2);
1236 file = mbkfopen( "techno_hack", "spi", "w" );
1237 fprintf( file, "* hacked model without capacitance\n" );
1238
1239 for( lotrs = lofig->LOTRS ; lotrs ; lotrs = lotrs->NEXT ) {
1240
1241 modelname = getlotrsmodel( lotrs ) ;
1242 lotrstype = MLO_IS_TRANSN(lotrs->TYPE) ? elpNMOS : elpPMOS ;
1243 l = ((double)lotrs->LENGTH)/((double)SCALE_X)*1e-6;
1244 w = ((double)lotrs->WIDTH)/((double)SCALE_X)*1e-6;
1245
1246 model = mcc_getmodel( MCC_MODELFILE, modelname, lotrstype, MCC_TYPICAL, l, w, 1 );
1247
1248 if( gethtitem( drivedmodel, model )==EMPTYHT ) {
1249
1250 addhtitem( drivedmodel, model, 1 );
1251
1252 keepvalue0 = NULL ;
1253 keepvalue1 = NULL ;
1254
1255 if( whatjob == MCC_HACK_REMOVE_LOTRS_CAPA ) {
1256
1257 /* remove intrinsic current */
1258 headparam = NULL ;
1259 headparam = addchain( headparam, "XPART" );
1260 keepvalue0 = mcc_setparamlist( model, headparam, -1.0 );
1261 freechain( headparam );
1262
1263 headparam = NULL ;
1264 /* remove gate-source overlap capacitance (doc bsim430.pdf p 85) */
1265 headparam = addchain( headparam, "CGSO" );
1266 headparam = addchain( headparam, "CGSL" );
1267
1268 /* remove gate-drain overlap capacitance (doc bsim430.pdf p 85) */
1269 headparam = addchain( headparam, "CGDO" );
1270 headparam = addchain( headparam, "CGDL" );
1271
1272 /* remove fringing capacitance (doc bsim430.pdf p83) */
1273 headparam = addchain( headparam, "CF" );
1274
1275 /* remove source diode capacitance (doc bsim430.pdf p109) */
1276 headparam = addchain( headparam, "CJS" );
1277 headparam = addchain( headparam, "CJSWS" );
1278 headparam = addchain( headparam, "CJSWGS" );
1279
1280 /* remove drain diode capacitance (doc bsim430.pdf p 109) */
1281 headparam = addchain( headparam, "CJD" );
1282 headparam = addchain( headparam, "CJSWD" );
1283 headparam = addchain( headparam, "CJSWGD" );
1284
1285 /* remove common drain and source diode capacitance (doc bsim430.pdf p 125) */
1286 headparam = addchain( headparam, "TCJSW" );
1287
1288 keepvalue1 = mcc_setparamlist( model, headparam, 0.0 );
1289 freechain( headparam );
1290 }
1291
1292 mcc_drive_dot_model( file, model );
1293
1294 /* remet le modèle en sortant dans l'état où on l'a trouvé en entrant... */
1295 mcc_restoreparamlist( model, keepvalue0 );
1296 mcc_restoreparamlist( model, keepvalue1 );
1297 }
1298 }
1299
1300 delht( drivedmodel );
1301 fclose( file );
1302 }
1303
1304 void mccHackNetlist( lofig_list *lofig )
1305 {
1306 lofig_list *hackedlofig ;
1307 char buffer[1024] ;
1308 int hacknetlist ;
1309 int hacktechno ;
1310 int removeresi ;
1311 int found ;
1312 char *pt ;
1313
1314 hackedlofig = rduplofig( lofig );
1315
1316 sprintf( buffer, "%s_hack", lofig->NAME );
1317 hackedlofig->NAME = namealloc( buffer );
1318
1319 lofigchain( hackedlofig );
1320
1321 hacknetlist = ELP_HACK_NONE ;
1322 hacktechno = MCC_HACK_NONE ;
1323 removeresi = 0 ;
1324
1325 if( V_STR_TAB[ __AVT_HACK_NETLIST_CONFIG ].VALUE ) {
1326 strcpy( buffer, V_STR_TAB[ __AVT_HACK_NETLIST_CONFIG ].VALUE ) ;
1327
1328 pt = strtok( buffer, " " );
1329
1330 while( pt ) {
1331
1332 found = 0 ;
1333
1334 if( !strcasecmp( pt, "removeresistance" ) ) {
1335 removeresi = 1 ;
1336 found = 1 ;
1337 }
1338
1339 if( !strcasecmp( pt, "fixcapa" ) ) {
1340 if( hacknetlist != ELP_HACK_NONE )
1341 printf( "avtHackNetlistConfig : bad configuration\n" );
1342 hacknetlist = ELP_HACK_FIX_CAPA ;
1343 hacktechno = MCC_HACK_REMOVE_LOTRS_CAPA ;
1344 found = 1 ;
1345 }
1346
1347 if( !strcasecmp( pt, "fixcapatoground" ) ) {
1348 if( hacknetlist != ELP_HACK_NONE )
1349 printf( "avtHackNetlistConfig : bad configuration\n" );
1350 hacknetlist = ELP_HACK_FIX_CAPA_TO_GND ;
1351 hacktechno = MCC_HACK_REMOVE_LOTRS_CAPA ;
1352 found = 1 ;
1353 }
1354
1355 if( !strcasecmp( pt, "removecapa" ) ) {
1356 if( hacknetlist != ELP_HACK_NONE )
1357 printf( "avtHackNetlistConfig : bad configuration\n" );
1358 hacknetlist = ELP_HACK_NONE ;
1359 hacktechno = MCC_HACK_REMOVE_LOTRS_CAPA ;
1360 found = 1 ;
1361 }
1362
1363 pt = strtok( NULL, " " );
1364 }
1365 }
1366
1367 if( hacknetlist != ELP_HACK_NONE )
1368 elpHackNetlistCapa( hackedlofig, hacknetlist );
1369
1370 if( removeresi )
1371 elpHackNetlistResi( hackedlofig );
1372
1373 mcc_hacktechno( hackedlofig, hacktechno );
1374
1375 savelofig( hackedlofig );
1376 dellofig( hackedlofig->NAME );
1377 }