Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / tas / mcc / mcc_genspi.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI Alliance */
4 /* */
5 /* Produit : MCC Version 1 */
6 /* Fichier : mcc_genspi.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 <unistd.h>
17 #include "mcc_optim.h"
18 #include "mcc_util.h"
19 #include "mcc_genspi.h"
20 #include "mcc_drvelp.h"
21 #include "mcc_curv.h"
22 #include "mcc_fit.h"
23 #include "mcc_mod_util.h"
24 #include "mcc_mod_spice.h"
25 #include "mcc_debug.h"
26
27 char *MCC_TN_SUBCKT=NULL, *MCC_TP_SUBCKT=NULL;
28 lotrs_list *MCC_CURRENT_LOTRS=NULL;
29 char *MCC_CURRENT_SUBCKT=NULL;
30 int MCC_FLAG_FIT ;
31 long MCC_SPICEUD_FITA ;
32 long MCC_SPICEDU_FITA ;
33 long MCC_SPICEUD_FITCGNOCAPA ;
34 long MCC_SPICEDU_FITCGNOCAPA ;
35 long MCC_SPICEUD_FITCG ;
36 long MCC_SPICEDU_FITCG ;
37 long MCC_SPICEUD_FITDN ;
38 long MCC_SPICEDU_FITDN ;
39 long MCC_SPICEDU_FITDP ;
40 long MCC_SPICEUD_FITDP ;
41 long MCC_SPICEFUD_FITA ;
42 long MCC_SPICEFDU_FITA ;
43 long MCC_SPICEFUD_FITCG ;
44 long MCC_SPICEFDU_FITCG ;
45 long MCC_SPICEFUD_FITCGNOCAPA ;
46 long MCC_SPICEFDU_FITCGNOCAPA ;
47 long MCC_SPICEFUD_FITDN ;
48 long MCC_SPICEFDU_FITDN ;
49 long MCC_SPICEFDU_FITDP ;
50 long MCC_SPICEFUD_FITDP ;
51
52 double *MCC_IDNSAT ;
53 double *MCC_IDNRES ;
54 double *MCC_IDNVGS ;
55 double *MCC_IDPSAT ;
56 double *MCC_IDPRES ;
57 double *MCC_IDPVGS ;
58 double *MCC_VDDDEG ;
59 double *MCC_VSSDEG ;
60 double **MCC_FITS ;
61
62 char surf_string_n[1024];
63 char surf_string_p[1024];
64 elp_lotrs_param mcc_user_lotrsparam_n, mcc_user_lotrsparam_p;
65
66 void mcc_printf_instance_specific(FILE *file, elp_lotrs_param *lotrsparam_n)
67 {
68 int b3=0,b4=0;
69 b3 = 1;
70 b4 = ( MCC_SPICEMODELTYPE == MCC_BSIM4 ? 1 : 0 ) ;
71
72 if (b3 || b4) {
73 fprintf(file,"+");
74 if (lotrsparam_n->PARAM[elpDELVT0]!=0)
75 fprintf(file," delvto=%g", lotrsparam_n->PARAM[elpDELVT0]);
76 if (lotrsparam_n->PARAM[elpMULU0]!=1)
77 fprintf(file," mulu0=%g", lotrsparam_n->PARAM[elpMULU0]);
78 if ( lotrsparam_n->PARAM[elpSA] > ELPMINVALUE)
79 fprintf(file," sa=%g", lotrsparam_n->PARAM[elpSA]);
80 if ( lotrsparam_n->PARAM[elpSB] > ELPMINVALUE )
81 fprintf(file," sb=%g", lotrsparam_n->PARAM[elpSB]);
82 if ( lotrsparam_n->PARAM[elpSD] > ELPMINVALUE )
83 fprintf(file," sd=%g", lotrsparam_n->PARAM[elpSD]);
84 if ( lotrsparam_n->PARAM[elpNF] > ELPMINVALUE && lotrsparam_n->PARAM[elpNF]!=1)
85 fprintf(file," nf=%g", lotrsparam_n->PARAM[elpNF]);
86 if ( lotrsparam_n->PARAM[elpM] > ELPMINVALUE && lotrsparam_n->PARAM[elpM]!=1)
87 fprintf(file," m=%g", lotrsparam_n->PARAM[elpM]);
88 if ( lotrsparam_n->PARAM[elpNRS] > ELPMINVALUE)
89 fprintf(file," nrs=%g", lotrsparam_n->PARAM[elpNRS]);
90 if ( lotrsparam_n->PARAM[elpNRD] > ELPMINVALUE)
91 fprintf(file," nrd=%g", lotrsparam_n->PARAM[elpNRD]);
92 if ( lotrsparam_n->PARAM[elpSC] > ELPMINVALUE)
93 fprintf(file," sc=%g", lotrsparam_n->PARAM[elpSC]);
94 if ( lotrsparam_n->PARAM[elpSCA] > ELPMINVALUE)
95 fprintf(file," sca=%g", lotrsparam_n->PARAM[elpSCA]);
96 if ( lotrsparam_n->PARAM[elpSCB] > ELPMINVALUE)
97 fprintf(file," scb=%g", lotrsparam_n->PARAM[elpSCB]);
98 if ( lotrsparam_n->PARAM[elpSCC] > ELPMINVALUE)
99 fprintf(file," scc=%g", lotrsparam_n->PARAM[elpSCC]);
100 fprintf(file,"\n");
101 }
102 }
103
104 double mcc_calcul_isat(vgs,vbs,type_t)
105 double vgs;
106 double vbs;
107 int type_t;
108 {
109 double is ;
110 double vtn = MCC_VTN + MCC_KTN * vbs ;
111 double vtp = MCC_VTP + MCC_KTP * vbs ;
112
113 if(type_t == MCC_TRANS_N)
114 {
115 if(vgs <= vtn) return(0.0);
116 is = (MCC_AN*(vgs-vtn)*(vgs-vtn))/(1.0+MCC_BN*(vgs-vtn));
117 }
118 else
119 {
120 if(vgs <= vtp) return(0.0);
121 is = (MCC_AP*(vgs-vtp)*(vgs-vtp))/(1.0+MCC_BP*(vgs-vtp));
122 }
123
124 return(is);
125 }
126
127 double mcc_calcul_ures(vgs,vbs,type_t)
128 double vgs;
129 double vbs;
130 int type_t;
131 {
132 double i0;
133 double kres;
134 double ures;
135 double vtn = MCC_VTN + MCC_KTN * vbs ;
136 double vtp = MCC_VTP + MCC_KTP * vbs ;
137
138 if(type_t == MCC_TRANS_N)
139 {
140 if(vgs <= vtn) return(0.0);
141 i0 = mcc_calcul_isat(MCC_VDDmax,vbs,type_t) ;
142 kres = ((MCC_RNT*i0-(MCC_RNT*MCC_VDDmax)/MCC_RNS)/(1.0 - MCC_RNT/MCC_RNS))/(MCC_VDDmax-vtn);
143 ures = MCC_KRN*kres*(vgs-vtn) + kres*(1.0-MCC_KRN)*(MCC_VDDmax - vtn) ;
144 }
145 else
146 {
147 if(vgs <= vtp) return(0.0);
148 i0 = mcc_calcul_isat(MCC_VDDmax,vbs,type_t) ;
149 kres = ((MCC_RPT*i0-(MCC_RPT*MCC_VDDmax)/MCC_RPS)/(1.0 - MCC_RPT/MCC_RPS))/(MCC_VDDmax-vtp);
150 ures = MCC_KRP*kres*(vgs-vtp) + kres*(1.0-MCC_KRP)*(MCC_VDDmax - vtp) ;
151 }
152
153 return(ures);
154 }
155
156 double mcc_calcul_ires(vgs,vbs,type_t)
157 double vgs;
158 double vbs;
159 int type_t;
160 {
161 double ires ;
162 double vtn = MCC_VTN + MCC_KTN * vbs ;
163 double vtp = MCC_VTP + MCC_KTP * vbs ;
164
165 if(type_t == MCC_TRANS_N)
166 ires = (MCC_AN*(vgs-vtn)*(vgs-vtn))/(1.0+MCC_BN*(vgs-vtn)) - ((MCC_VDDmax - mcc_calcul_ures(vgs,vbs,type_t)) * (vgs - vtn)) / ((MCC_KSN * MCC_RNS * (MCC_VDDmax - vtn)) + (MCC_RNS * (1.0 - MCC_KSN) * (vgs-vtn))) ;
167 else
168 ires = (MCC_AP*(vgs-vtp)*(vgs-vtp))/(1.0+MCC_BP*(vgs-vtp)) - ((MCC_VDDmax - mcc_calcul_ures(vgs,vbs,type_t)) * (vgs - vtp)) / ((MCC_KSP * MCC_RPS * (MCC_VDDmax - vtp)) + (MCC_RPS * (1.0 - MCC_KSP) * (vgs-vtp))) ;
169
170 return(ires) ;
171 }
172
173 void mcc_trans_mcc_from_global( int type_t, mcc_trans_mcc *trs )
174 {
175 trs->VDD = MCC_VDDmax ;
176 trs->RD = 0.0 ;
177 trs->RS = 0.0 ;
178
179 if( type_t == MCC_TRANS_N ) {
180 trs->VG = MCC_VDDmax ;
181 trs->VB = 0.0 ;
182 trs->TRWIDTH = (long)(0.5+MCC_WNeff * ((double)SCALE_X)) ;
183 trs->TRLENGTH = (long)(0.5+MCC_LNeff * ((double)SCALE_X)) ;
184 trs->A = MCC_AN ;
185 trs->B = MCC_BN ;
186 trs->RNT = MCC_RNT ;
187 trs->RNS = MCC_RNS ;
188 trs->VT = MCC_VTN ;
189 trs->KVT = MCC_KTN ;
190 trs->VLIN = MCC_VDDmax * MCC_KRNT ;
191 trs->VSAT = MCC_VDDmax * MCC_KRNS ;
192 trs->KR = MCC_KRN ;
193 trs->KS = MCC_KSN ;
194 trs->TYPE = TRANSN ;
195 }
196 else {
197 trs->VG = 0.0 ;
198 trs->VB = MCC_VDDmax ;
199 trs->TRWIDTH = (long)(0.5+MCC_WPeff * ((double)SCALE_X)) ;
200 trs->TRLENGTH = (long)(0.5+MCC_LPeff * ((double)SCALE_X)) ;
201 trs->A = MCC_AP ;
202 trs->B = MCC_BP ;
203 trs->RNT = MCC_RPT ;
204 trs->RNS = MCC_RPS ;
205 trs->VT = MCC_VTP ;
206 trs->KVT = MCC_KTP ;
207 trs->VLIN = MCC_VDDmax * MCC_KRPT ;
208 trs->VSAT = MCC_VDDmax * MCC_KRPS ;
209 trs->KR = MCC_KRP ;
210 trs->KS = MCC_KSP ;
211 trs->TYPE = TRANSP ;
212 }
213 }
214
215 #define NEWMCCCURRENT
216
217 #ifdef NEWMCCCURRENT
218 double mcc_current(vgs,vds,vbs,type_t)
219 double vds ; /* valeur absolue */
220 double vgs ; /* valeur absolue */
221 double vbs ; /* valeur absolue */
222 int type_t ;
223 {
224 mcc_trans_mcc trs ;
225 float ids ;
226 float vs ;
227 float vd ;
228 float wl ;
229 float coef ;
230
231 mcc_trans_mcc_from_global( type_t, &trs );
232 trs.TRWIDTH = 1.0 ;
233 trs.TRLENGTH = 1.0 ;
234
235 if( type_t == MCC_TRANS_N ) {
236 wl = MCC_WNeff/MCC_LNeff ;
237 vbs = -vbs ;
238 coef = 1.0 ;
239 }
240 else {
241 wl = MCC_WPeff/MCC_LPeff ;
242 vgs = -vgs ;
243 vds = -vds ;
244 coef = -1.0 ;
245 }
246
247 vs = trs.VB - vbs ;
248 vd = vds + vs ;
249 trs.VG = vgs + vs ;
250
251 if( ! mcc_mcc_ids( &trs, vs, vd, &ids ) )
252 return 0.0 ;
253 return ids*wl*coef ;
254
255 }
256 #else
257 double mcc_current(vgs,vds,vbs,type_t)
258 double vds;
259 double vgs;
260 double vbs;
261 int type_t;
262 {
263 double aux;
264 double isat;
265 double ires;
266 double is;
267 double r;
268 double rsat;
269 double ures;
270 double vtn = MCC_VTN + MCC_KTN * vbs ;
271 double vtp = MCC_VTP + MCC_KTP * vbs ;
272 double factor = 1.0 ;
273 double vsat ;
274 double vlin ;
275 double rsatmin;
276
277 if(vds < 0.0)
278 {
279 vgs = vgs - vds ;
280 vbs = vbs - vds ;
281 vds = -vds ;
282 factor = -1.0 ;
283 }
284
285 if(type_t == MCC_TRANS_N)
286 {
287 if(vgs <= vtn) return(0.0);
288 isat = mcc_calcul_isat(vgs,vbs,type_t) ;
289
290 ures = mcc_calcul_ures(vgs,vbs,type_t) ;
291 ires = mcc_calcul_ires(vgs,vbs,type_t) ;
292 r = ures / ires ;
293
294 rsat = (MCC_VDDmax - ures)/(isat - ires) ;
295 rsatmin = MCC_VDDmax/isat ;
296
297 if( rsat > rsatmin && ures > 0.0 ) {
298 is = (MCC_VDDmax - vds)/rsat ;
299 is = isat - is ;
300
301 vsat = ((vgs-vtn)/(MCC_VDDmax-vtn))*(MCC_VDDmax * MCC_KRNS) ;
302 vlin = ((vgs-vtn)/(MCC_VDDmax-vtn))*(MCC_VDDmax * MCC_KRNT) ;
303
304 {
305 double ilin, isx, di, dv, a, b, iit, im, a1, b1, a2, b2, a3, b3, a4, b4 ;
306 double ures2, ires2, iit2, im2, csat, psat, plin ;
307
308 ilin = vlin/r ;
309 plin = 1.0/r ;
310
311 isx = isat-(MCC_VDDmax - vsat)/rsat ;
312 psat = 1.0/rsat ;
313 csat = isx-vsat*psat ;
314
315 di=isx-ilin ;
316 dv=(vsat-vlin) ;
317 a=di/dv ;
318 b=ilin-a*vlin ;
319
320 iit=a*ures+b ;
321 im=(ires-iit)/2.0+iit ;
322
323 a1=(im-ilin)/(ures-vlin) ;
324 b1=ilin-a1*vlin ;
325
326 a2=(isx-im)/(vsat-ures) ;
327 b2=isx-a2*vsat ;
328
329 ures2=(csat-b1)/(a1-psat) ;
330 ires2=psat*ures2+csat ;
331 iit2=a2*ures2+b2 ;
332 im2=(ires2-iit2)/2.0+iit2 ;
333
334 a3=(im2-im)/(ures2-ures) ;
335 b3=im2-a3*ures2 ;
336
337 a4=(isx-im2)/(vsat-ures2) ;
338 b4=isx-a4*vsat ;
339
340 if( vds < vlin )
341 aux = ( plin * vds ) * MCC_WNeff/MCC_LNeff ;
342 if( vds >= vlin && vds < ures )
343 aux = ( a1*vds + b1 ) * MCC_WNeff/MCC_LNeff ;
344 if( vds >= ures && vds < ures2 )
345 aux = ( a3*vds + b3 ) * MCC_WNeff/MCC_LNeff ;
346 if( vds >= ures2 && vds < vsat )
347 aux = ( a4*vds + b4 ) * MCC_WNeff/MCC_LNeff ;
348 if( vds >= vsat )
349 aux = ( psat*vds + csat ) * MCC_WNeff/MCC_LNeff ;
350
351 }
352 }
353 else {
354 aux = vds / rsatmin * MCC_WNeff/MCC_LNeff ;
355 }
356 }
357 else
358 {
359 if(vgs <= vtp) return(0.0);
360 isat = mcc_calcul_isat(vgs,vbs,type_t) ;
361
362 ures = mcc_calcul_ures(vgs,vbs,type_t) ;
363 ires = mcc_calcul_ires(vgs,vbs,type_t) ;
364 r = ures / ires ;
365
366 rsat = (MCC_VDDmax - ures)/(isat - ires) ;
367 rsatmin = MCC_VDDmax/isat ;
368
369 if( rsat > rsatmin && ures > 0.0 ) {
370 is = (MCC_VDDmax - vds)/rsat ;
371 is = isat - is ;
372
373 vsat = ((vgs-vtp)/(MCC_VDDmax-vtp))*(MCC_VDDmax * MCC_KRPS ) ;
374 vlin = ((vgs-vtp)/(MCC_VDDmax-vtp))*(MCC_VDDmax * MCC_KRPT ) ;
375
376 {
377 double ilin, isx, di, dv, a, b, iit, im, a1, b1, a2, b2, a3, b3, a4, b4 ;
378 double ures2, ires2, iit2, im2, csat, psat, plin ;
379
380 ilin = vlin/r ;
381 plin = 1.0/r ;
382
383 isx = isat-(MCC_VDDmax - vsat)/rsat ;
384 psat = 1.0/rsat ;
385 csat = isx-vsat*psat ;
386
387 di=isx-ilin ;
388 dv=(vsat-vlin) ;
389 a=di/dv ;
390 b=ilin-a*vlin ;
391
392 iit=a*ures+b ;
393 im=(ires-iit)/2.0+iit ;
394
395 a1=(im-ilin)/(ures-vlin) ;
396 b1=ilin-a1*vlin ;
397
398 a2=(isx-im)/(vsat-ures) ;
399 b2=isx-a2*vsat ;
400
401 ures2=(csat-b1)/(a1-psat) ;
402 ires2=psat*ures2+csat ;
403 iit2=a2*ures2+b2 ;
404 im2=(ires2-iit2)/2.0+iit2 ;
405
406 a3=(im2-im)/(ures2-ures) ;
407 b3=im2-a3*ures2 ;
408
409 a4=(isx-im2)/(vsat-ures2) ;
410 b4=isx-a4*vsat ;
411
412 if( vds < vlin )
413 aux = ( plin * vds ) * MCC_WPeff/MCC_LPeff ;
414 if( vds >= vlin && vds < ures )
415 aux = ( a1*vds + b1 ) * MCC_WPeff/MCC_LPeff ;
416 if( vds >= ures && vds < ures2 )
417 aux = ( a3*vds + b3 ) * MCC_WPeff/MCC_LPeff ;
418 if( vds >= ures2 && vds < vsat )
419 aux = ( a4*vds + b4 ) * MCC_WPeff/MCC_LPeff ;
420 if( vds >= vsat )
421 aux = ( psat*vds + csat ) * MCC_WPeff/MCC_LPeff ;
422
423 }
424 }
425 else {
426 aux = vds / rsatmin * MCC_WPeff/MCC_LPeff ;
427 }
428 }
429
430 return(aux*factor);
431 }
432 #endif
433
434 double mcc_spicecurrent(vgs,vds,vbs,type,lotrsparam)
435 double vgs ;
436 double vds ;
437 double vbs ;
438 int type ;
439 elp_lotrs_param *lotrsparam;
440 {
441 if(MCC_CALC_CUR == MCC_SIM_MODE)
442 return(mcc_spicesimcurrent(vgs,vds,vbs,type)) ;
443 else
444 return(mcc_spicecalccurrent(vgs,vds,vbs,type,lotrsparam)) ;
445 }
446
447 double mcc_spicecalccurrent(vgs,vds,vbs,type,lotrsparam)
448 double vgs ;
449 double vds ;
450 double vbs ;
451 int type ;
452 elp_lotrs_param *lotrsparam;
453 {
454 double gs ;
455 double ds ;
456 double bs ;
457 double w ;
458 double l ;
459 char *transname ;
460 int typet, corner ;
461 double factor = 1.0 ;
462
463 if(vds < 0.0)
464 {
465 vgs = vgs - vds ;
466 vbs = vbs - vds ;
467 vds = -vds ;
468 factor = -1.0 ;
469 }
470
471 if(type == MCC_TRANS_N)
472 {
473 typet = MCC_NMOS ;
474 corner = MCC_NCASE ;
475 transname = MCC_TNMODEL ;
476 ds = vds ;
477 gs = vgs ;
478 bs = vbs ;
479 w = MCC_WN ;
480 l = MCC_LN ;
481 }
482 else
483 {
484 typet = MCC_PMOS ;
485 corner = MCC_PCASE ;
486 transname = MCC_TPMODEL ;
487 ds = -vds ;
488 gs = -vgs ;
489 bs = vbs ;
490 w = MCC_WP ;
491 l = MCC_LP ;
492 }
493
494 return(factor * fabs(mcc_calcIDS(MCC_MODELFILE, transname,
495 typet, corner, bs, gs,
496 ds, l*1.0e-6, w*1.0e-6,MCC_TEMP,lotrsparam))) ;
497 }
498
499 static int mcc_optiom_resetsearch=1;
500 void mcc_optim_resetsearch_for_new_pwl()
501 {
502 mcc_optiom_resetsearch=1;
503 }
504 double mcc_spicesimcurrent(vgs,vds,vbs,type)
505 double vgs ;
506 double vds ;
507 double vbs ;
508 int type ;
509 {
510 double v, res ;
511 double *tab ;
512 int step ;
513 int stepmax, *curidx ;
514 mbk_pwl *mypwl;
515 static int MCC_OPTIM_IDNVGS_idx, MCC_OPTIM_IDNRES_idx, MCC_OPTIM_IDNSAT_idx;
516 static int MCC_OPTIM_IDPVGS_idx, MCC_OPTIM_IDPRES_idx, MCC_OPTIM_IDPSAT_idx;
517
518 #ifdef OPTIM5
519 if (MCC_OPTIM_MODE)
520 {
521 if (mcc_optiom_resetsearch)
522 {
523 MCC_OPTIM_IDNVGS_idx=MCC_OPTIM_IDNRES_idx=MCC_OPTIM_IDNSAT_idx=-1;
524 MCC_OPTIM_IDPVGS_idx=MCC_OPTIM_IDPRES_idx=MCC_OPTIM_IDPSAT_idx=-1;
525 mcc_optiom_resetsearch=0;
526 }
527 if((mcc_ftol(MCC_VGS * 1000.0) == mcc_ftol(vgs * 1000.0)) &&
528 (mcc_ftol(MCC_VDDmax * 1000.0) != mcc_ftol(vds * 1000.0)) &&
529 (mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0)))
530 {
531 v = vds ;
532 if(type == MCC_TRANS_N)
533 mypwl = MCC_OPTIM_IDNVGS, curidx=&MCC_OPTIM_IDNVGS_idx ;
534 else
535 mypwl = MCC_OPTIM_IDPVGS, curidx=&MCC_OPTIM_IDPVGS_idx ;
536 }
537 else if(vgs > vds)
538 {
539 v = vds ;
540 if(type == MCC_TRANS_N)
541 mypwl = MCC_OPTIM_IDNRES, curidx=&MCC_OPTIM_IDNRES_idx ;
542 else
543 mypwl = MCC_OPTIM_IDPRES, curidx=&MCC_OPTIM_IDPRES_idx ;
544 }
545 else
546 {
547 v = vgs ;
548 if(type == MCC_TRANS_N)
549 mypwl = MCC_OPTIM_IDNSAT, curidx=&MCC_OPTIM_IDNSAT_idx ;
550 else
551 mypwl = MCC_OPTIM_IDPSAT, curidx=&MCC_OPTIM_IDPSAT_idx ;
552 }
553 if (*curidx!=-1 && v<mypwl->DATA[ *curidx ].X0) *curidx=-1;
554 mbk_pwl_get_value_bytabindex (mypwl,v,&res,curidx);
555 if(type == MCC_TRANS_P) res=fabs(res);
556 return res;
557 }
558 else
559 #endif
560 {
561 if((mcc_ftol(MCC_VGS * 1000.0) == mcc_ftol(vgs * 1000.0)) &&
562 (mcc_ftol(MCC_VDDmax * 1000.0) != mcc_ftol(vds * 1000.0)) &&
563 (mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0)))
564 {
565 v = vds ;
566 if(type == MCC_TRANS_N)
567 tab = MCC_IDNVGS ;
568 else
569 tab = MCC_IDPVGS ;
570 }
571 else if(vgs > vds)
572 {
573 v = vds ;
574 if(type == MCC_TRANS_N)
575 tab = MCC_IDNRES ;
576 else
577 tab = MCC_IDPRES ;
578 }
579 else
580 {
581 v = vgs ;
582 if(type == MCC_TRANS_N)
583 tab = MCC_IDNSAT ;
584 else
585 tab = MCC_IDPSAT ;
586 }
587
588 step = mcc_ftoi((v) / (MCC_DC_STEP)) ;
589 stepmax = mcc_ftoi((MCC_VDDmax) / (MCC_DC_STEP)) ;
590
591 if(step > stepmax)
592 step = stepmax ;
593
594 return(tab[step]) ;
595 }
596 #ifndef __ALL__WARNING_
597 vbs = 0.0;
598 #endif
599 }
600
601 double mcc_spicevdeg(type,lotrsparam)
602 int type ;
603 elp_lotrs_param *lotrsparam;
604 {
605 double v ;
606
607 if(MCC_CALC_CUR == MCC_SIM_MODE)
608 {
609 if(type == MCC_TRANS_N)
610 {
611 v = MCC_VDDDEG[1] ;
612 if(v > (MCC_VDDmax - MCC_VTN))
613 v = MCC_VDDmax - MCC_VTN ;
614 if(v < (0.55*MCC_VDDmax))
615 v = 0.55*MCC_VDDmax;
616 }
617 else
618 {
619 v = MCC_VSSDEG[1] ;
620 if(v < MCC_VTP)
621 v = MCC_VTP ;
622 }
623 }
624 else
625 {
626 if(type == MCC_TRANS_N)
627 {
628 v = mcc_calcVDDDEG(MCC_MODELFILE, MCC_TNMODEL,
629 MCC_NMOS, MCC_NCASE, MCC_LN*1.0e-6, MCC_WN*1.0e-6,
630 MCC_VDDmax, MCC_TEMP, MCC_DC_STEP,lotrsparam) ;
631 if(v > (MCC_VDDmax - MCC_VTN))
632 v = (MCC_VDDmax - MCC_VTN)/ (1+MCC_KTN) ;
633 if(v < (0.55*MCC_VDDmax))
634 v = 0.55*MCC_VDDmax;
635 }
636 else
637 {
638 v = mcc_calcVSSDEG(MCC_MODELFILE, MCC_TPMODEL,
639 MCC_PMOS, MCC_PCASE, MCC_LP*1.0e-6, MCC_WP*1.0e-6,
640 MCC_VDDmax, MCC_TEMP, MCC_DC_STEP,lotrsparam) ;
641 if(v < MCC_VTP)
642 v = MCC_VTP/(1-MCC_KTP) ;
643 }
644
645 }
646 return(v) ;
647 }
648
649 double mcc_calcdiffmodelsat(double vmin,double vmax,int type,elp_lotrs_param *lotrsparam, double exitvalue, mcc_corner_info *info)
650 {
651 double var,vbs ;
652 double res = 0.0 ;
653 double imod ;
654 double ispice ;
655 double val ;
656 int cont = 0 ;
657
658 if ( MCC_OPTIM_MODE )
659 {
660 if( type == MCC_TRANS_N && MCC_OPTIM_IDNSAT )
661 return mcc_optim_calcdiffmodelsat (type,MCC_OPTIM_IDNSAT,exitvalue,info);
662 else if ( type == MCC_TRANS_P && MCC_OPTIM_IDPSAT )
663 return mcc_optim_calcdiffmodelsat (type,MCC_OPTIM_IDPSAT,exitvalue,info);
664 }
665 var = vmin + MCC_DC_STEP ;
666
667 if( lotrsparam->ISVBSSET )
668 vbs = lotrsparam->VBS ;
669 else
670 vbs = (type == MCC_TRANS_N) ? lotrsparam->VBULK : lotrsparam->VBULK-MCC_VDDmax;
671 while (var <= vmax )
672 {
673 imod = mcc_current(var,MCC_VDDmax,0.0,type) ;
674 ispice = mcc_spicecurrent(var,MCC_VDDmax,vbs,type,lotrsparam) ;
675 if(ispice == 0.0)
676 {
677 var += MCC_DC_STEP;
678 continue ;
679 }
680 val = (imod - ispice) * (imod - ispice) ;
681 if(val > 1.0)
682 {
683 var += MCC_DC_STEP;
684 continue ;
685 }
686 res += val ;
687 if (exitvalue>=0 && res>exitvalue) return res;
688 cont ++ ;
689 var += MCC_DC_STEP;
690 }
691
692 return(res
693 #ifndef OPTIM0
694 /(double)cont
695 #endif
696 ) ;
697 }
698
699 double mcc_calcul_vt_error( int type, elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p, double testvt, mcc_corner_info *info )
700 {
701 double v1 ;
702 double emin ;
703 double savevt ;
704 elp_lotrs_param *trs_param;
705
706 if( type == MCC_TRANS_N ) {
707 savevt = MCC_VTN ;
708 MCC_VTN = testvt ;
709 trs_param = lotrsparam_n ;
710 }
711 else {
712 savevt = MCC_VTP ;
713 MCC_VTP = testvt ;
714 trs_param = lotrsparam_p ;
715 }
716
717 if( MCC_NEW_CALC_ABR && MCC_OPTIM_MODE ) {
718 emin = mcc_get_best_abr_from_vt ( type, lotrsparam_n, lotrsparam_p, info ) ;
719 }
720 else {
721 v1 = (MCC_VDDmax-testvt)/2.0 + testvt ;
722 mcc_calcul_abr( type, v1, MCC_VDDmax, lotrsparam_n, lotrsparam_p ) ;
723 emin = mcc_calcdiffmodelsat( testvt, MCC_VDDmax, type, trs_param, -1,NULL ) ;
724 }
725
726 if( type == MCC_TRANS_N )
727 MCC_VTN = savevt ;
728 else
729 MCC_VTP = savevt ;
730
731 return emin ;
732 }
733
734 void mcc_calcul_vt_old( int type, elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p, mcc_corner_info *info )
735 {
736 double deltavt ;
737 double delta ;
738 double vmin ;
739 double vmax ;
740 double vhalf ;
741 double vhalf1 ;
742 double vhalf2 ;
743 double vstep ;
744 int cmin ;
745 int cmax ;
746 int chalf ;
747 double emin ;
748 double emax ;
749 double ehalf ;
750 double ehalf1 ;
751 double ehalf2 ;
752 char *env;
753 static FILE *vtfile=NULL;
754
755 if ( !MCC_CALC_VT )
756 return;
757 #if 0
758 if (!vtfile)
759 {
760 char *where=getenv("VTFILE");
761 if (where!=NULL)
762 {
763 vtfile=fopen(where, "a");
764 fprintf(vtfile,"***\n");
765 }
766 }
767 #endif
768 env = getenv( "MCC_DELTA_VT" ) ;
769 if ( env )
770 deltavt = atof ( env );
771 else
772 deltavt = 0.5;
773
774 if(type == MCC_TRANS_N) {
775 MCC_KSN = 1.0;
776 MCC_KRN = 1.0;
777 vmin = MCC_VTN * (1.0-deltavt) ;
778 vmax = MCC_VTN * (1.0+deltavt) ;
779 }
780 else {
781 if(type == MCC_TRANS_P) {
782 MCC_KSP = 1.0;
783 MCC_KRP = 1.0;
784 vmin = MCC_VTP * (1.0-deltavt) ;
785 vmax = MCC_VTP * (1.0+deltavt) ;
786 }
787 else {
788 MCC_KSN = 1.0;
789 MCC_KRN = 1.0;
790 MCC_KSP = 1.0;
791 MCC_KRP = 1.0;
792 }
793 }
794
795 if ( !mcc_check_param ( type) )
796 return;
797
798 if( V_BOOL_TAB[ __MCC_PRECISE_VT ].VALUE ) {
799 emin=1e10 ;
800 if(vmax > 0.9*MCC_VDDmax)
801 vmax = 0.9*MCC_VDDmax ;
802 if(vmin > 0.8*MCC_VDDmax)
803 vmin = 0.8*MCC_VDDmax ;
804 vstep = (vmax-vmin)/100.0 ;
805 for( vhalf = vmin ; vhalf <= vmax ; vhalf = vhalf+vstep ) {
806 ehalf = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vhalf, info );
807 if( ehalf < emin ) {
808 emin = ehalf ;
809 deltavt = vhalf ;
810 }
811 }
812 if( type == MCC_TRANS_P )
813 MCC_VTP = deltavt ;
814 else
815 MCC_VTN = deltavt ;
816 return ;
817 }
818
819 if( type == MCC_TRANS_N || type == MCC_TRANS_P ) {
820
821 if(vmax > MCC_VDDmax)
822 vmax = MCC_VDDmax ;
823
824 delta = (vmax-vmin)/1000.0 ;
825
826 vhalf = (vmin+vmax)/2.0 ;
827 cmin = 0 ;
828 cmax = 0 ;
829 chalf = 0 ;
830
831 do {
832
833 if( !cmin ) {
834 emin = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vmin, NULL );
835 cmin = 1 ;
836 }
837
838 if( !chalf ) {
839 ehalf = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vhalf, NULL );
840 chalf = 1 ;
841 }
842
843 if( !cmax ) {
844 emax = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vmax, NULL );
845 cmax = 1 ;
846 }
847
848 if( emin < ehalf && ehalf < emax ) {
849 vmax = vhalf ;
850 emax = ehalf ;
851 vhalf = (vmin+vmax)/2.0 ;
852 chalf = 0 ;
853 }
854 else {
855 if( emin > ehalf && ehalf > emax ) {
856 vmin = vhalf ;
857 emin = ehalf ;
858 vhalf = (vmin+vmax)/2.0 ;
859 chalf = 0 ;
860 }
861 else {
862
863 if( emin > ehalf && emax > ehalf ) {
864
865 vhalf1 = (vmin+vhalf)/2.0 ;
866 vhalf2 = (vmax+vhalf)/2.0 ;
867 ehalf1 = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vhalf1, NULL );
868 ehalf2 = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vhalf2, NULL );
869
870 if( ehalf1 < ehalf2 ) {
871 vmax = vhalf ;
872 emax = ehalf ;
873 vhalf = vhalf1 ;
874 ehalf = ehalf1 ;
875 }
876 else {
877 vmin = vhalf ;
878 emin = ehalf ;
879 vhalf = vhalf2 ;
880 ehalf = ehalf2 ;
881 }
882 }
883 else {
884 if( emin < emax ) {
885 vmax = vmin ;
886 emax = emin ;
887 vhalf = vmin ;
888 ehalf = emin ;
889 }
890 else {
891 vmin = vmax ;
892 emin = emax ;
893 vhalf = vmax ;
894 ehalf = emax ;
895 }
896 }
897 }
898 }
899 }
900 while( (vmax-vmin) > delta );
901
902 if( type == MCC_TRANS_N )
903 MCC_VTN = vhalf ;
904 else
905 MCC_VTP = vhalf ;
906
907 if (vtfile!=NULL)
908 {
909 double vt0=(type != MCC_TRANS_N)?MCC_VTP:MCC_VTN;
910 fprintf(vtfile, "%g %g\n",(vhalf-vt0)/vt0, ehalf);
911 }
912 }
913 }
914
915 void mcc_calcul_vt_new( int type, elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p )
916 {
917 double deltavt ;
918 double delta ;
919 double vmin ;
920 double vmax ;
921 double vhalf ;
922 int cmin ;
923 int cmax ;
924 int chalf ;
925 double emin ;
926 double emax ;
927 double ehalf ;
928 double ehalfp ;
929 double pente ;
930 double lmax ;
931 char *env;
932
933 if ( !MCC_CALC_VT )
934 return;
935
936 env = getenv("MCC_DELTA_VT") ;
937 if ( env )
938 deltavt = atof ( env );
939 else
940 deltavt = 0.5;
941
942 if(type == MCC_TRANS_N) {
943 MCC_KSN = 1.0;
944 MCC_KRN = 1.0;
945 vmin = MCC_VTN * (1.0-deltavt) ;
946 vmax = MCC_VTN * (1.0+deltavt) ;
947 lmax = MCC_VDDmax - (MCC_VDDmax-MCC_VTN)/10.0 ;
948 if( vmax > lmax )
949 vmax = lmax ;
950 }
951 else {
952 if(type == MCC_TRANS_P) {
953 MCC_KSP = 1.0;
954 MCC_KRP = 1.0;
955 vmin = MCC_VTP * (1.0-deltavt) ;
956 vmax = MCC_VTP * (1.0+deltavt) ;
957 lmax = MCC_VDDmax - (MCC_VDDmax-MCC_VTP)/10.0 ;
958 if( vmax > lmax )
959 vmax = lmax ;
960 }
961 else {
962 MCC_KSN = 1.0;
963 MCC_KRN = 1.0;
964 MCC_KSP = 1.0;
965 MCC_KRP = 1.0;
966 }
967 }
968
969 if ( !mcc_check_param ( type) )
970 return;
971
972 if( type == MCC_TRANS_N || type == MCC_TRANS_P ) {
973
974
975 cmin = 0 ;
976 cmax = 0 ;
977 chalf = 0 ;
978
979 /* check domain validy of mcc_calcul_vt_error() since allowing negative
980 capacitance may leads to forbiden values for vt */
981 delta = (vmax-vmin)/20.0 ;
982 do {
983 emax = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vmax, NULL );
984 if( emax > FLT_MAX/2.0 ) {
985 cmax = 0 ;
986 vmax = vmax - delta ;
987 if( vmax <= vmin )
988 break ;
989 }
990 else
991 cmax = 1 ;
992
993 }
994 while( !cmax );
995
996 if( !cmax ) {
997 printf( "can't find a valid solution for VT\n");
998 exit(1);
999 }
1000
1001 vhalf = (vmin+vmax)/2.0 ;
1002
1003 delta = (vmax-vmin)/1000.0 ;
1004
1005 do {
1006
1007 if( !cmin ) {
1008 emin = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vmin, NULL );
1009 cmin = 1 ;
1010 }
1011
1012 if( !chalf ) {
1013 ehalf = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vhalf, NULL );
1014 chalf = 1 ;
1015 }
1016
1017 if( !cmax ) {
1018 emax = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vmax, NULL );
1019 cmax = 1 ;
1020 }
1021
1022 if( emin > FLT_MAX/2.0 || ehalf > FLT_MAX/2.0 || emax > FLT_MAX/2.0 ) {
1023 printf( "validity domain for vt unconsistant\n" );
1024 exit(1);
1025 }
1026
1027 if( emin < ehalf && ehalf < emax ) {
1028 vmax = vhalf ;
1029 emax = ehalf ;
1030 vhalf = (vmin+vmax)/2.0 ;
1031 chalf = 0 ;
1032 }
1033 else {
1034 if( emin > ehalf && ehalf > emax ) {
1035 vmin = vhalf ;
1036 emin = ehalf ;
1037 vhalf = (vmin+vmax)/2.0 ;
1038 chalf = 0 ;
1039 }
1040 else {
1041
1042 if( emin > ehalf && emax > ehalf ) {
1043
1044 ehalfp = mcc_calcul_vt_error( type, lotrsparam_n,lotrsparam_p, vhalf+delta/2.0, NULL );
1045 pente = (ehalfp-ehalf)/(delta/2.0);
1046
1047 if( pente > 0.0 ) {
1048 vmax = vhalf ;
1049 emax = ehalf ;
1050 }
1051 else {
1052 vmin = vhalf ;
1053 emin = ehalf ;
1054 }
1055
1056 vhalf = (vmin+vmax)/2.0 ;
1057 chalf = 0 ;
1058
1059 }
1060 else {
1061 if( emin < emax ) {
1062 vmax = vmin ;
1063 emax = emin ;
1064 vhalf = vmin ;
1065 ehalf = emin ;
1066 }
1067 else {
1068 vmin = vmax ;
1069 emin = emax ;
1070 vhalf = vmax ;
1071 ehalf = emax ;
1072 }
1073 }
1074 }
1075 }
1076 }
1077 while( (vmax-vmin) > delta );
1078
1079 if( type == MCC_TRANS_N )
1080 MCC_VTN = vhalf ;
1081 else
1082 MCC_VTP = vhalf ;
1083 }
1084 }
1085
1086 int mcc_get_sat_parameter( double v1, double i1,
1087 double v2, double i2,
1088 double v3, double i3,
1089 double *a,
1090 double *b,
1091 double *vt
1092 )
1093 {
1094 double r1 ;
1095 double r2 ;
1096 double s1 ;
1097 double s2 ;
1098 double t1 ;
1099 double t2 ;
1100 double ta ;
1101 double tb ;
1102 double tc ;
1103 double delta ;
1104 double a1 ;
1105 double b1 ;
1106 double vt1 ;
1107 double a2 ;
1108 double b2 ;
1109 double vt2 ;
1110 double bmin ;
1111 int valid1 ;
1112 int valid2 ;
1113 int sol ;
1114 int found ;
1115
1116 r1 = i1*(v1-v3) ;
1117 r2 = i2*(v2-v3) ;
1118 s1 = 1.0-i1/i3 ;
1119 s2 = 1.0-i2/i3 ;
1120 t1 = i1*v3/i3 - v1 ;
1121 t2 = i2*v3/i3 - v2 ;
1122
1123 ta = s2*r1 - s1*r2 ;
1124 tb = v1*s1*r2 - t1*r2 - v2*s2*r1 + t2*r1 ;
1125 tc = v1*t1*r2 - v2*t2*r1 ;
1126
1127 delta = tb*tb - 4.0*ta*tc ;
1128
1129 if( delta >= 0.0 ) {
1130
1131 vt1 = ( -tb - sqrt( delta ) ) / ( 2.0*ta ) ;
1132 a1 = i1*(v1-v3)/( (v3-vt1)*(v1-vt1)*(i1*(v3-vt1)/i3-(v1-vt1))) ;
1133 b1 = a1*(v3-vt1)/i3-1.0/(v3-vt1) ;
1134
1135 vt2 = ( -tb + sqrt( delta ) ) / ( 2.0*ta ) ;
1136 a2 = i1*(v1-v3)/( (v3-vt2)*(v1-vt2)*(i1*(v3-vt2)/i3-(v1-vt2))) ;
1137 b2 = a2*(v3-vt2)/i3-1.0/(v3-vt1) ;
1138
1139 if( mcc_check_sat_param( a1, b1, vt1, MCC_VDDmax, 'T' ) && vt1 < v1 )
1140 valid1 = 1 ;
1141 else
1142 valid1 = 0 ;
1143
1144 if( mcc_check_sat_param( a2, b2, vt2, MCC_VDDmax, 'T' ) && vt2 < v1 )
1145 valid2 = 1 ;
1146 else
1147 valid2 = 0 ;
1148
1149 sol = 0 ;
1150 if( valid1 && valid2 ) {
1151 if( vt1 < vt2 )
1152 sol = 1 ;
1153 else
1154 sol = 2 ;
1155 }
1156 else {
1157 if( valid1 )
1158 sol = 1 ;
1159 if( valid2 )
1160 sol = 2 ;
1161 }
1162
1163 if( sol>0 ) {
1164 found = 1 ;
1165 if( sol==1 ) {
1166 *a = a1 ;
1167 *b = b1 ;
1168 *vt = vt1 ;
1169 }
1170 else {
1171 *a = a2 ;
1172 *b = b2 ;
1173 *vt = vt2 ;
1174 }
1175 }
1176 else
1177 found = 0 ;
1178 }
1179 else
1180 found = 0 ;
1181
1182 return found ;
1183 }
1184
1185 int mcc_get_iflex_isat( mbk_pwl *pwl, double *vgs, double *ids )
1186 {
1187 double amin ;
1188 int i ;
1189 int inflex ;
1190 int ret ;
1191
1192 amin = pwl->DATA[0].A ;
1193 inflex = 0 ;
1194
1195 for( i=1; i<pwl->N ; i++ ) {
1196 if( pwl->DATA[i].A < amin ) {
1197 inflex = 1 ;
1198 break ;
1199 }
1200 amin = pwl->DATA[i].A ;
1201 }
1202
1203 if( inflex ) {
1204 if( vgs )
1205 *vgs = pwl->DATA[i].X0 ;
1206 if( ids )
1207 *ids = pwl->DATA[i].A * pwl->DATA[i].X0 + pwl->DATA[i].B ;
1208 ret = 1 ;
1209 }
1210 else
1211 ret = 0 ;
1212
1213 return ret ;
1214 }
1215
1216 int mcc_check_sat_param( double a,
1217 double b,
1218 double vt,
1219 double vdd,
1220 char type /* 'B'=branch, 'T'=transistor */
1221 )
1222 {
1223 int allownegativeb ;
1224 double bmin ;
1225
1226 if( type == 'B' )
1227 allownegativeb = V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B_BRANCH ].VALUE ;
1228 else /* 'T' */
1229 allownegativeb = V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B ].VALUE ;
1230
1231 if( allownegativeb )
1232 bmin = -1.0/(vdd-vt);
1233 else
1234 bmin = 0.0 ;
1235
1236 if( vt > vdd ) return 0 ;
1237 if( vt < 0.0 ) return 0 ;
1238 if( b < bmin ) return 0 ;
1239 if( a < 0.0 ) return 0 ;
1240
1241 return 1 ;
1242 }
1243 void mcc_calcul_sat_parameter( int type, elp_lotrs_param *lotrsparam, mcc_corner_info *info )
1244 {
1245 double vs ;
1246 double vbs ;
1247 double *pt_a ;
1248 double *pt_b ;
1249 double *pt_vt ;
1250 double *tabvgs ;
1251 double ids ;
1252 double vgs ;
1253 double imax ;
1254 double vgsmax ;
1255 double *tabids ;
1256 double best_a ;
1257 double best_b ;
1258 double best_vt ;
1259 double error ;
1260 double minerror ;
1261 double pmin ;
1262 double pmax ;
1263 double wl ;
1264 double sgn ;
1265 double ids0 ;
1266 double ids1 ;
1267 double vgs0 ;
1268 double vgs1 ;
1269 int n ;
1270 int i ;
1271 int j ;
1272 int r ;
1273 int found ;
1274 int onemoretime ;
1275 mbk_pwl *spipwl ;
1276 static int fordebug ;
1277
1278 fordebug++ ;
1279
1280 if( type == MCC_TRANS_N ) {
1281 vs = 0.0 ;
1282 pt_a = &MCC_AN ;
1283 pt_b = &MCC_BN ;
1284 pt_vt = &MCC_VTN ;
1285 wl = (MCC_WN+MCC_DWN)/(MCC_LN+MCC_DLN) ;
1286 spipwl = MCC_OPTIM_IDNSAT ;
1287 sgn = 1.0 ;
1288 }
1289 else {
1290 vs = MCC_VDDmax ;
1291 pt_a = &MCC_AP ;
1292 pt_b = &MCC_BP ;
1293 pt_vt = &MCC_VTP ;
1294 wl = (MCC_WP+MCC_DWP)/(MCC_LP+MCC_DLP) ;
1295 spipwl = MCC_OPTIM_IDPSAT ;
1296 sgn = -1.0 ;
1297 }
1298
1299 if( lotrsparam->ISVBSSET )
1300 vbs = lotrsparam->VBS ;
1301 else
1302 vbs = lotrsparam->VBULK - vs ;
1303
1304 n = V_INT_TAB[ __MCC_SAT_N ].VALUE ;
1305
1306 tabvgs = (double*)alloca( sizeof(double)*(n-1) );
1307 tabids = (double*)alloca( sizeof(double)*(n-1) );
1308
1309 vgsmax = MCC_VDDmax ;
1310 mbk_pwl_get_value( spipwl, MCC_VDDmax, &imax );
1311 imax = sgn*imax ;
1312
1313 ids0 = imax*1.0/((double)n);
1314 ids1 = imax*2.0/((double)n);
1315
1316 do {
1317 mbk_pwl_get_inv_value( spipwl, sgn*ids0, &vgs );
1318 tabvgs[0] = vgs ;
1319 tabids[0] = mcc_spicecurrent( vgs, MCC_VDDmax, vbs, type, lotrsparam ) ;
1320 mbk_pwl_get_inv_value( spipwl, sgn*ids1, &vgs );
1321 tabvgs[1] = vgs ;
1322 tabids[1] = mcc_spicecurrent( vgs, MCC_VDDmax, vbs, type, lotrsparam ) ;
1323
1324 pmin = ( tabids[1] - tabids[0] ) / ( tabvgs[1] - tabvgs[0] ) ;
1325 pmax = ( imax - tabids[1] ) / ( vgsmax - tabvgs[1] ) ;
1326
1327 if( pmin > 0.95 * pmax ) {
1328 ids0 = ids0/2.0 ;
1329 ids1 = ids1/2.0 ;
1330 onemoretime = 1 ;
1331 }
1332 else
1333 onemoretime = 0 ;
1334 }
1335 while( onemoretime );
1336
1337
1338 for( i=3 ; i<n ; i++ ) {
1339
1340 //ids = (imax-ids1)*((double)(i-2))/((double)(n-2))+ids1;
1341 ids = (imax-tabids[1])*((double)(i-2))/((double)(n-2))+tabids[1];
1342
1343 mbk_pwl_get_inv_value( spipwl, sgn*ids, &vgs );
1344
1345 tabvgs[i-1] = vgs ;
1346 tabids[i-1] = mcc_spicecurrent( tabvgs[i-1], MCC_VDDmax, vbs, type, lotrsparam ) ;
1347 }
1348
1349 minerror = MAXFLOAT ;
1350
1351 found = 0 ;
1352 for( i=0 ; i<(n-2) ; i++ ) {
1353
1354 for( j=(i+1) ; j<(n-1) ; j++ ) {
1355
1356 r = mcc_get_sat_parameter( tabvgs[i], tabids[i]/wl,
1357 tabvgs[j], tabids[j]/wl,
1358 vgsmax, imax/wl,
1359 pt_a,
1360 pt_b,
1361 pt_vt
1362 ) ;
1363 if( !r )
1364 continue ;
1365
1366 error = mcc_calcdiffmodelsat( *pt_vt, MCC_VDDmax, type, lotrsparam, minerror, info ) ;
1367 if( error < minerror ) {
1368 best_a = *pt_a ;
1369 best_b = *pt_b ;
1370 best_vt = *pt_vt ;
1371 minerror = error ;
1372 found = 1 ;
1373 }
1374 }
1375 }
1376
1377 if( !found ) {
1378 printf( "can't find a valid set of parameter A, B, VT (fordebug=%d)\n", fordebug );
1379 exit(0);
1380 }
1381
1382 *pt_a = best_a ;
1383 *pt_b = best_b ;
1384 *pt_vt = best_vt ;
1385 }
1386
1387 void mcc_calcul_vt( int type, elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p, mcc_corner_info *info )
1388 {
1389 if( V_BOOL_TAB[ __MCC_CALCUL_VT_NEW].VALUE ) {
1390 if( type == MCC_TRANS_B ) {
1391 mcc_calcul_vt_new( MCC_TRANS_N, lotrsparam_n, lotrsparam_p );
1392 mcc_calcul_vt_new( MCC_TRANS_P, lotrsparam_n, lotrsparam_p );
1393 }
1394 else
1395 mcc_calcul_vt_new( type, lotrsparam_n, lotrsparam_p );
1396 }
1397 else {
1398 if( type == MCC_TRANS_B ) {
1399 mcc_calcul_vt_old( MCC_TRANS_N, lotrsparam_n, lotrsparam_p, info );
1400 mcc_calcul_vt_old( MCC_TRANS_P, lotrsparam_n, lotrsparam_p, info );
1401 }
1402 else
1403 mcc_calcul_vt_old( type, lotrsparam_n, lotrsparam_p, info );
1404 }
1405 }
1406
1407 double mcc_calcul_a(v1,v2,i1,i2,vt,l,w)
1408 double v1 ;
1409 double v2 ;
1410 double i1 ;
1411 double i2 ;
1412 double vt ;
1413 double l ;
1414 double w ;
1415 {
1416 double g1 ;
1417 double g2 ;
1418 double ct ;
1419 double ai1 ;
1420 double ai2 ;
1421 double res ;
1422
1423 g1 = fabs(v1 - vt);
1424 g2 = fabs(v2 - vt);
1425
1426 ai1 = fabs(i1) ;
1427 ai2 = fabs(i2) ;
1428
1429 ct= w/l ;
1430
1431 res = (ai1*ai2*(g2-g1))/(g1*g2*ct*((ai2*g1)-(ai1*g2))) ;
1432
1433 return(res);
1434 }
1435
1436 double mcc_calcul_b(v1,v2,i1,i2,vt,l,w)
1437 double v1 ;
1438 double v2 ;
1439 double i1 ;
1440 double i2 ;
1441 double vt ;
1442 double l ;
1443 double w ;
1444 {
1445 double g1 ;
1446 double g2 ;
1447 double ct ;
1448 double ai1 ;
1449 double ai2 ;
1450 double res ;
1451
1452 g1 = fabs(v1 - vt);
1453 g2 = fabs(v2 - vt);
1454
1455 ai1 = fabs(i1) ;
1456 ai2 = fabs(i2) ;
1457
1458 ct= w/l ;
1459
1460 res = ((ai2*g1*g1)-(ai1*g2*g2))/(g1*g2*((ai1*g2)-(ai2*g1))) ;
1461
1462 return(res);
1463 }
1464
1465 void mcc_calcul_ab(v1,v2,i1,i2,vt,l,w,a,b)
1466 double v1 ;
1467 double v2 ;
1468 double i1 ;
1469 double i2 ;
1470 double vt ;
1471 double l ;
1472 double w ;
1473 double *a ;
1474 double *b ;
1475 {
1476 double g1 ;
1477 double g2 ;
1478 double ct ;
1479 double ai1 ;
1480 double ai2 ;
1481
1482 g1 = v1 - vt;
1483 g2 = v2 - vt;
1484
1485 ai1 = i1 ;
1486 ai2 = i2 ;
1487
1488 ct= w/l ;
1489
1490 *a = (ai1*ai2*(g2-g1))/(g1*g2*ct*((ai2*g1)-(ai1*g2))) ;
1491 *b = ((ai2*g1*g1)-(ai1*g2*g2))/(g1*g2*((ai1*g2)-(ai2*g1))) ;
1492 }
1493
1494 double mcc_calcul_r(v,i,l,w)
1495 double v ;
1496 double i ;
1497 double l ;
1498 double w ;
1499 {
1500 double r ;
1501 double ct ;
1502
1503 ct = (w/l);
1504
1505 r = (v/i) * ct;
1506
1507 return(r);
1508 }
1509
1510 double mcc_calcul_rs(v1,i1,v2,i2,l,w)
1511 double v1 ;
1512 double v2 ;
1513 double i1 ;
1514 double i2 ;
1515 double l ;
1516 double w ;
1517 {
1518 double ct ;
1519
1520 ct = (w/l);
1521
1522 return(fabs((v2-v1)/(i2-i1))*ct);
1523 }
1524
1525 double mcc_calcul_k_error( int type,
1526 double vbs,
1527 int n,
1528 double *tabvgs,
1529 double *tabvsat,
1530 double *tabvmed,
1531 double *tabispisat,
1532 double *tabispimed
1533 )
1534 {
1535 int i ;
1536 double sumerror ;
1537 double error ;
1538 double imccsat ;
1539 double imccmed ;
1540
1541 sumerror = 0.0 ;
1542
1543 for( i=0 ; i<n ; i++ ) {
1544
1545 imccsat = mcc_current( tabvgs[i], tabvsat[i], vbs, type ) ;
1546 imccmed = mcc_current( tabvgs[i], tabvmed[i], vbs, type ) ;
1547
1548 error = (imccsat - tabispisat[i]) * (imccsat - tabispisat[i])
1549 + (imccmed - tabispimed[i]) * (imccmed - tabispimed[i]) ;
1550
1551 sumerror = sumerror + error ;
1552 }
1553
1554 return sumerror ;
1555 }
1556
1557 void mcc_calcul_k_new( int type, elp_lotrs_param *lotrsparam)
1558 {
1559 double vt ;
1560 double *ptkr ;
1561 double *ptks ;
1562 double vlin0 ;
1563 double vsat0 ;
1564 double rlin0 ;
1565 double rsat0 ;
1566 double vbs ;
1567 double vgs ;
1568 double ispimaxvdd ;
1569 double tabvgs[3] ;
1570 double ispimax[3] ;
1571 double ispimed[3] ;
1572 double ispisat[3] ;
1573 double ispilin[3] ;
1574 double vmed[3] ;
1575 double vsat[3] ;
1576 double vlin[3] ;
1577 double l, w ;
1578 double rsat ;
1579 double rlin ;
1580 double usat ;
1581 double kres ;
1582 double error ;
1583 double minerror ;
1584 double bestkr ;
1585 double bestks ;
1586 double vs ;
1587 int calc ;
1588 int n ;
1589
1590 if( type == MCC_TRANS_N ) {
1591 vt = MCC_VTN ;
1592 ptkr = &MCC_KRN ;
1593 ptks = &MCC_KSN ;
1594 vlin0 = MCC_VDDmax * MCC_KRNT ;
1595 vsat0 = MCC_VDDmax * MCC_KRNS ;
1596 l = MCC_LN+MCC_DLN ;
1597 w = MCC_WN+MCC_DWN ;
1598 rlin0 = MCC_RNT ;
1599 rsat0 = MCC_RNS ;
1600 vs = 0.0 ;
1601 }
1602 else {
1603 vt = MCC_VTP ;
1604 ptkr = &MCC_KRP ;
1605 ptks = &MCC_KSP ;
1606 vlin0 = MCC_VDDmax * MCC_KRPT ;
1607 vsat0 = MCC_VDDmax * MCC_KRPS ;
1608 l = MCC_LP+MCC_DLP ;
1609 w = MCC_WP+MCC_DWP ;
1610 rlin0 = MCC_RPT ;
1611 rsat0 = MCC_RPS ;
1612 vs = MCC_VDDmax ;
1613 }
1614
1615 calc = MCC_CALC_CUR ;
1616 if( MCC_VGS == MCC_VDDmax ) {
1617 *ptkr = 1.0 ;
1618 *ptks = 1.0 ;
1619 }
1620
1621 if( ( MCC_VGS <= 1.1*vt ) || ( MCC_CALC_ORG == MCC_CALC_MODE ) ) {
1622 if( MCC_CALC_ORG == MCC_SIM_MODE ) {
1623 *ptkr = 1.0 ;
1624 *ptks = 1.0 ;
1625 return ;
1626 }
1627 }
1628
1629 if( MCC_CALC_CUR == MCC_SIM_MODE )
1630 MCC_CALC_CUR = MCC_CALC_MODE ;
1631
1632 if( lotrsparam->ISVBSSET )
1633 vbs = lotrsparam->VBS ;
1634 else
1635 vbs = lotrsparam->VBULK - vs ;
1636
1637 tabvgs[0] = 0.25 * ( MCC_VDDmax-vt ) + vt ;
1638 tabvgs[1] = 0.50 * ( MCC_VDDmax-vt ) + vt ;
1639 tabvgs[2] = 0.75 * ( MCC_VDDmax-vt ) + vt ;
1640
1641 ispimaxvdd = mcc_calcul_isat( MCC_VDDmax, 0.0, type ) ;
1642
1643 for( n=0 ; n<=2 ; n++ ) {
1644
1645 vgs = tabvgs[n] ;
1646 vlin[n] = ( vgs - vt ) / ( MCC_VDDmax - vt ) * vlin0 ;
1647 vsat[n] = ( vgs - vt ) / ( MCC_VDDmax - vt ) * vsat0 ;
1648 vmed[n] = ( MCC_VDDmax - vsat[n] ) / 2.0 + vsat[n] ;
1649
1650 ispimax[n] = mcc_spicecurrent( vgs, MCC_VDDmax, vbs, type, lotrsparam ) ;
1651 ispisat[n] = mcc_spicecurrent( vgs, vsat[n], vbs, type, lotrsparam ) ;
1652 ispilin[n] = mcc_spicecurrent( vgs, vlin[n], vbs, type, lotrsparam ) ;
1653 ispimed[n] = mcc_spicecurrent( vgs, vmed[n], vbs, type, lotrsparam ) ;
1654 }
1655
1656 minerror = FLT_MAX ;
1657
1658 for( n=0 ; n<=2 ; n++ ) {
1659
1660 vgs = tabvgs[n] ;
1661
1662 rsat = mcc_calcul_rs( MCC_VDDmax, ispimax[n], vsat[n], ispisat[n], l, w ) ;
1663 rlin = mcc_calcul_r( vlin[n], ispilin[n], l, w ) ;
1664
1665 usat = ( rlin * (ispimax[n]*l/w) - rlin * MCC_VDDmax / rsat ) / (1.0 - rlin/rsat ) ;
1666 kres = ( ( rlin0*ispimaxvdd - ( rlin0 * MCC_VDDmax ) / rsat0 ) / ( 1.0 - rlin0/rsat0 )) / ( MCC_VDDmax - vt ) ;
1667
1668 *ptkr = ( kres * (MCC_VDDmax - vt) - usat) / (kres * ((MCC_VDDmax - vt) - (vgs - vt))) ;
1669 *ptks = ((vgs - vt) * (rsat - rsat0)) / (rsat0 * ((MCC_VDDmax - vt) - (vgs - vt))) ;
1670
1671 error = mcc_calcul_k_error( type, 0.0, 3, tabvgs, vsat, vmed, ispisat, ispimed ) ;
1672 if( error < minerror ) {
1673 minerror = error ;
1674 bestkr = *ptkr ;
1675 bestks = *ptks ;
1676 }
1677 }
1678
1679 *ptkr = bestkr ;
1680 *ptks = bestks ;
1681
1682 MCC_CALC_CUR = calc ;
1683 }
1684
1685 void mcc_calcul_k(type,lotrsparam)
1686 int type ;
1687 elp_lotrs_param *lotrsparam;
1688 {
1689 double il ;
1690 double rl ;
1691 double is ;
1692 double rs ;
1693 double vlin ;
1694 double vsat ;
1695 double usat ;
1696 double imax ;
1697 double kres ;
1698 double i0 ;
1699 double vbs ;
1700 double vgs ;
1701 int step ;
1702 int calc ;
1703
1704 if( V_BOOL_TAB[ __MCC_PRECISE_K ].VALUE ) {
1705 mcc_calcul_k_new( type, lotrsparam );
1706 return ;
1707 }
1708
1709 calc = MCC_CALC_CUR ;
1710
1711 if(type == MCC_TRANS_N)
1712 {
1713 if(MCC_VGS == MCC_VDDmax)
1714 {
1715 MCC_KRN = 1.0 ;
1716 MCC_KSN = 1.0 ;
1717 return ;
1718 }
1719 vgs = MCC_VGS ;
1720 if((MCC_VGS <= (MCC_VTN * 1.1)) || (MCC_CALC_ORG == MCC_CALC_MODE))
1721 {
1722 if(MCC_CALC_ORG == MCC_SIM_MODE)
1723 {
1724 MCC_KRN = 1.0 ;
1725 MCC_KSN = 1.0 ;
1726 return ;
1727 }
1728 MCC_VGS = MCC_VTN + (MCC_VDDmax-MCC_VTN) / 2.0 ;
1729 if(MCC_CALC_CUR == MCC_SIM_MODE)
1730 MCC_CALC_CUR = MCC_CALC_MODE ;
1731 }
1732 step = mcc_ftoi(((MCC_VGS-MCC_VTN)/(MCC_VDDmax-MCC_VTN))*(MCC_VDDmax * MCC_KRNT / MCC_DC_STEP)) ;
1733 vlin = step * MCC_DC_STEP ;
1734 step = mcc_ftoi(((MCC_VGS-MCC_VTN)/(MCC_VDDmax-MCC_VTN))*(MCC_VDDmax * MCC_KRNS ) / MCC_DC_STEP) ;
1735 vsat = step * MCC_DC_STEP ;
1736
1737 if( lotrsparam->ISVBSSET )
1738 vbs = lotrsparam->VBS ;
1739 else
1740 vbs = lotrsparam->VBULK ;
1741
1742 imax = mcc_spicecurrent(MCC_VGS,MCC_VDDmax,vbs,MCC_TRANS_N,lotrsparam) ;
1743 is = mcc_spicecurrent(MCC_VGS,vsat,vbs,MCC_TRANS_N,lotrsparam) ;
1744 rs = mcc_calcul_rs(MCC_VDDmax,imax,vsat,is,MCC_LN+MCC_DLN,MCC_WN+MCC_DWN) ;
1745 il = mcc_spicecurrent(MCC_VGS,vlin,vbs,MCC_TRANS_N,lotrsparam) ;
1746 rl = mcc_calcul_r(vlin,il,MCC_LN+MCC_DLN,MCC_WN+MCC_DWN) ;
1747 usat = (rl * (imax*(MCC_LN+MCC_DLN)/(MCC_WN+MCC_DWN)) - rl * MCC_VDDmax/rs) / (1.0 - rl/rs) ;
1748
1749 i0 = mcc_calcul_isat(MCC_VDDmax,0.0,type) ;
1750 kres = ((MCC_RNT*i0-(MCC_RNT*MCC_VDDmax)/MCC_RNS)/(1 - MCC_RNT/MCC_RNS))/(MCC_VDDmax-MCC_VTN);
1751 MCC_KRN = (kres * (MCC_VDDmax - MCC_VTN) - usat) / (kres * ((MCC_VDDmax - MCC_VTN) - (MCC_VGS - MCC_VTN))) ;
1752 MCC_KSN = ((MCC_VGS - MCC_VTN) * (rs - MCC_RNS)) / (MCC_RNS * ((MCC_VDDmax - MCC_VTN) - (MCC_VGS - MCC_VTN))) ;
1753 MCC_VGS = vgs ;
1754 MCC_CALC_CUR = calc ;
1755 if((MCC_KRN <= 0.0) || (MCC_KSN <= 0.0))
1756 {
1757 MCC_KRN = 1.0 ;
1758 MCC_KSN = 1.0 ;
1759 }
1760 }
1761 else
1762 {
1763 if(MCC_VGS == MCC_VDDmax)
1764 {
1765 MCC_KRP = 1.0 ;
1766 MCC_KSP = 1.0 ;
1767 return ;
1768 }
1769 vgs = MCC_VGS ;
1770 if((MCC_VGS <= (MCC_VTP * 1.1)) || (MCC_CALC_ORG == MCC_CALC_MODE))
1771 {
1772 if(MCC_CALC_ORG == MCC_SIM_MODE)
1773 {
1774 MCC_KRP = 1.0 ;
1775 MCC_KSP = 1.0 ;
1776 return ;
1777 }
1778 MCC_VGS = MCC_VTP + (MCC_VDDmax-MCC_VTP) / 2.0 ;
1779 if(MCC_CALC_CUR == MCC_SIM_MODE)
1780 MCC_CALC_CUR = MCC_CALC_MODE ;
1781 }
1782 step = mcc_ftoi(((MCC_VGS-MCC_VTP)/(MCC_VDDmax-MCC_VTP))*(MCC_VDDmax * MCC_KRPT / MCC_DC_STEP)) ;
1783 vlin = step * MCC_DC_STEP ;
1784 step = mcc_ftoi(((MCC_VGS-MCC_VTP)/(MCC_VDDmax-MCC_VTP))*(MCC_VDDmax * MCC_KRPS) / MCC_DC_STEP) ;
1785 vsat = step * MCC_DC_STEP ;
1786 if( lotrsparam->ISVBSSET )
1787 vbs = lotrsparam->VBS ;
1788 else
1789 vbs = lotrsparam->VBULK-MCC_VDDmax ;
1790 imax = mcc_spicecurrent(MCC_VGS,MCC_VDDmax,vbs,MCC_TRANS_P,lotrsparam) ;
1791 is = mcc_spicecurrent(MCC_VGS,vsat,vbs,MCC_TRANS_P,lotrsparam) ;
1792 rs = mcc_calcul_rs(MCC_VDDmax,imax,vsat,is,MCC_LP+MCC_DLP,MCC_WP+MCC_DWP) ;
1793 il = mcc_spicecurrent(MCC_VGS,vlin,vbs,MCC_TRANS_P,lotrsparam) ;
1794 rl = mcc_calcul_r(vlin,il,MCC_LP+MCC_DLP,MCC_WP+MCC_DWP) ;
1795 usat = (rl * (imax*(MCC_LP+MCC_DLP)/(MCC_WP+MCC_DWP)) - rl * MCC_VDDmax/rs) / (1.0 - rl/rs) ;
1796
1797 i0 = mcc_calcul_isat(MCC_VDDmax,0.0,type) ;
1798 kres = ((MCC_RPT*i0-(MCC_RPT*MCC_VDDmax)/MCC_RPS)/(1 - MCC_RPT/MCC_RPS))/(MCC_VDDmax-MCC_VTP);
1799
1800 MCC_KRP = (kres * (MCC_VDDmax - MCC_VTP) - usat) / (kres * ((MCC_VDDmax - MCC_VTP) - (MCC_VGS - MCC_VTP))) ;
1801 MCC_KSP = ((MCC_VGS - MCC_VTP) * (rs - MCC_RPS)) / (MCC_RPS * ((MCC_VDDmax - MCC_VTP) - (MCC_VGS - MCC_VTP))) ;
1802 MCC_VGS = vgs ;
1803 MCC_CALC_CUR = calc ;
1804 if((MCC_KRP <= 0.0) || (MCC_KSP <= 0.0))
1805 {
1806 MCC_KRP = 1.0 ;
1807 MCC_KSP = 1.0 ;
1808 }
1809 }
1810 }
1811
1812 float mcc_error_rst( mbk_pwl *spipwl, mcc_model *mccpwl, int nbmccpwl, int debug )
1813 {
1814 int nmcc ;
1815 int nspi ;
1816 float lastv ;
1817 float lastdeltai ;
1818 float maxspi ;
1819 float currentv ;
1820 float ispi ;
1821 float imcc ;
1822 float deltai ;
1823 float interror ;
1824 float error ;
1825 int move ;
1826
1827 nspi = 0 ;
1828 nmcc = 0 ;
1829
1830 lastv = 0.0 ;
1831 lastdeltai = 0.0 ;
1832 error = 0.0 ;
1833
1834 while( nspi < spipwl->N && nmcc < nbmccpwl ) {
1835
1836 if( nspi < spipwl->N -1 )
1837 maxspi = spipwl->DATA[nspi].X0 ;
1838 else
1839 maxspi = spipwl->X1 ;
1840
1841 if( maxspi < mccpwl[nmcc].VMAX ) {
1842 currentv = maxspi ;
1843 move = 1 ;
1844 }
1845 else {
1846 currentv = mccpwl[nmcc].VMAX ;
1847 move = 2 ;
1848 }
1849
1850 ispi = fabs( spipwl->DATA[nspi].A * currentv + spipwl->DATA[nspi].B ) ;
1851 imcc = fabs( mccpwl[nmcc].A * currentv + mccpwl[nmcc].B ) ;
1852 deltai = ispi - imcc ;
1853
1854 interror = ( currentv - lastv ) * ( deltai + lastdeltai ) / 2.0 ;
1855 error = error + fabs(interror) ;
1856
1857 if( debug ) {
1858 printf( "%g %g %g %g %g\n", currentv, ispi, imcc, interror, error );
1859 }
1860
1861 if( V_BOOL_TAB[ __AVT_BUG_RSAT ].VALUE )
1862 lastdeltai = ispi ;
1863 else
1864 lastdeltai = deltai ;
1865
1866 lastv = currentv ;
1867
1868 if( move==1 )
1869 nspi++ ;
1870 else
1871 nmcc++ ;
1872 }
1873
1874 return error ;
1875 }
1876
1877 void mcc_trs_corner( int type, elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p, mcc_corner_info *info )
1878 {
1879 stm_solver_maillon_list *brhead ;
1880 stm_solver_maillon_list *scan ;
1881 stm_solver_maillon *stmm[5] ;
1882 mcc_trans_spice trsspi[5] ;
1883 float ibranch ;
1884 float out ;
1885 int i ;
1886 int trs ;
1887 chain_list *chain ;
1888 lotrs_list lotrs[5] ;
1889 int n ;
1890 mccglobal *global ;
1891
1892 brhead = NULL ;
1893 n = V_INT_TAB[ __AVT_RST_N ].VALUE ;
1894
1895 if( type == MCC_TRANS_N )
1896 trs = 0 ;
1897 else
1898 trs = 1 ;
1899
1900 for( i=0 ; i<n ; i++ ) {
1901
1902 trsspi[i].MODELFILE = MCC_MODELFILE ;
1903 trsspi[i].MODELTYPE = mcc_getmodeltype (MCC_MODELFILE) ;
1904 trsspi[i].TRANSNAME = ( trs==0 ? MCC_TNMODEL : MCC_TPMODEL );
1905 trsspi[i].TRANSTYPE = ( trs==0 ? MCC_NMOS : MCC_PMOS );
1906 trsspi[i].TRANSCASE = ( trs==0 ? MCC_NCASE : MCC_PCASE );
1907 trsspi[i].TRLENGTH = ( trs==0 ? MCC_LN : MCC_LP ) * 1e-6 ;
1908 trsspi[i].TRWIDTH = ( trs==0 ? MCC_WN : MCC_WP ) * 1e-6 ;
1909 trsspi[i].AD = ( trs==0 ? MCC_ADN : MCC_ADP );
1910 trsspi[i].AS = ( trs==0 ? MCC_ASN : MCC_ASP );
1911 trsspi[i].PD = ( trs==0 ? MCC_PDN : MCC_PDP );
1912 trsspi[i].PS = ( trs==0 ? MCC_PSN : MCC_PSP );
1913 trsspi[i].VB = ( trs==0 ? lotrsparam_n->VBULK : lotrsparam_p->VBULK );
1914 trsspi[i].VG = ( trs==0 ? MCC_VDDmax : 0.0 );
1915 trsspi[i].PARAM = ( trs==0 ? lotrsparam_n : lotrsparam_p );
1916 trsspi[i].TEMP = MCC_TEMP ;
1917 trsspi[i].VDD = MCC_VDDmax ;
1918 trsspi[i].LOTRS = &(lotrs[i]) ;
1919 trsspi[i].RS = 0.0 ;
1920 trsspi[i].RD = 0.0 ;
1921
1922 lotrs[i].TRNAME = NULL;
1923 lotrs[i].LENGTH = (trs==0?MCC_LN:MCC_LP)*SCALE_X ;
1924 lotrs[i].WIDTH = (trs==0?MCC_WN:MCC_WP)*SCALE_X ;
1925 lotrs[i].TYPE = ( trs==0 ? TRANSN : TRANSP ) ;
1926 lotrs[i].USER = NULL;
1927 if (trsspi[i].PARAM->SUBCKTNAME!=NULL)
1928 lotrs[i].USER=addptype(lotrs[i].USER, TRANS_FIGURE, trsspi[i].PARAM->SUBCKTNAME);
1929 lotrs[i].BULK = NULL;
1930 lotrs[i].GRID = NULL;
1931 lotrs[i].SOURCE = NULL;
1932 lotrs[i].DRAIN = NULL;
1933 lotrs[i].NEXT = NULL;
1934 lotrs[i].PS = 0 ;
1935 lotrs[i].PD = 0 ;
1936 lotrs[i].XS = 0 ;
1937 lotrs[i].XD = 0 ;
1938 addlotrsmodel( &(lotrs[i]), trsspi[i].TRANSNAME ) ;
1939
1940 chain = addchain( NULL, &trsspi[i] );
1941
1942 stmm[i] = stm_solver_new_maillon();
1943
1944 stm_solver_add_model( stmm[i],
1945 (char(*)(void*,float,float,float*))mcc_spice_ids_list,
1946 (char(*)(void*,float,float,float*))mcc_spice_vds_list,
1947 chain,
1948 chain
1949 );
1950 freechain( chain );
1951
1952 brhead = stm_solver_maillon_addchain( brhead, stmm[i] );
1953 }
1954
1955 brhead = stm_solver_maillon_reverse( brhead );
1956
1957 for( scan = brhead ; scan->NEXT ; scan = scan->NEXT );
1958
1959 if( trs == 0 ) {
1960 scan->MAILLON->VS = 0.0 ;
1961 out = MCC_VDDmax ;
1962 }
1963 else {
1964 scan->MAILLON->VS = MCC_VDDmax ;
1965 out = 0.0 ;
1966 }
1967
1968 global = mcc_getglobal() ;
1969 stm_solver_i( brhead, out, &ibranch );
1970 mcc_setglobal( global );
1971
1972 info->vdsmin = fabs( stmm[n-1]->VD - stmm[n-1]->VS ) ;
1973 info->vgsmin = fabs( trsspi[0].VG - stmm[0]->VS );
1974
1975 for (i=0; i<n; i++) freeptype(trsspi[i].LOTRS->USER);
1976 stm_solver_maillon_freechain( brhead );
1977 }
1978
1979 void mcc_calcul_rst_better( int type, elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p, mcc_corner_info *infos )
1980 {
1981 double *kl, *ks, *rl, *rs ;
1982 mcc_trans_mcc trselp ;
1983 double vsat, vlin ;
1984 double isat, ilin ;
1985 double imax ;
1986 mbk_pwl *spipwl ;
1987 double l, w ;
1988 mcc_model mccpwl[10] ;
1989 int nbmccpwl ;
1990 int nsat ;
1991 int npwl ;
1992 float error ;
1993 float besterror ;
1994 int status ;
1995
1996 if( !MCC_OPTIM_MODE )
1997 return ;
1998
1999 if( type != MCC_TRANS_N && type != MCC_TRANS_P )
2000 return ;
2001
2002 if( type == MCC_TRANS_N ) {
2003
2004 kl = &MCC_KRNT ;
2005 ks = &MCC_KRNS ;
2006 rl = &MCC_RNT ;
2007 rs = &MCC_RNS ;
2008 spipwl = MCC_OPTIM_IDNRES ;
2009 l = MCC_LNeff ;
2010 w = MCC_WNeff ;
2011
2012 trselp.TYPE = TRANSN ;
2013 trselp.TRLENGTH = (long)(0.5+MCC_LNeff * ((double)SCALE_X)) ;
2014 trselp.TRWIDTH = (long)(0.5+MCC_WNeff * ((double)SCALE_X)) ;
2015 trselp.A = MCC_AN ;
2016 trselp.B = MCC_BN ;
2017 trselp.VT = MCC_VTN ;
2018 trselp.KVT = MCC_KTN ;
2019 trselp.VG = MCC_VDDmax ;
2020 trselp.VB = 0.0 ;
2021 }
2022 else {
2023 kl = &MCC_KRPT ;
2024 ks = &MCC_KRPS ;
2025 rl = &MCC_RPT ;
2026 rs = &MCC_RPS ;
2027 spipwl = MCC_OPTIM_IDPRES ;
2028 l = MCC_LPeff ;
2029 w = MCC_WPeff ;
2030
2031 trselp.TYPE = TRANSP ;
2032 trselp.TRLENGTH = (long)(0.5+MCC_LPeff * ((double)SCALE_X)) ;
2033 trselp.TRWIDTH = (long)(0.5+MCC_WPeff * ((double)SCALE_X)) ;
2034 trselp.A = MCC_AP ;
2035 trselp.B = MCC_BP ;
2036 trselp.VT = MCC_VTP ;
2037 trselp.KVT = MCC_KTP ;
2038 trselp.VG = 0 ;
2039 trselp.VB = MCC_VDDmax ;
2040 }
2041
2042 trselp.VDD = MCC_VDDmax ;
2043 trselp.KS = 1.0 ;
2044 trselp.KR = 1.0 ;
2045 trselp.RS = 0.0 ;
2046 trselp.RD = 0.0 ;
2047
2048 /*
2049 rlin and vlin
2050 */
2051
2052 vlin = infos->vdsmin ;
2053
2054 mbk_pwl_get_value( spipwl, vlin, &ilin ) ;
2055 if( ilin < 0.0 )
2056 ilin = -ilin ;
2057 *kl = vlin / MCC_VDDmax ;
2058 *rl = (w/l)*( vlin / ilin ) ;
2059
2060 trselp.VLIN = (*kl)*MCC_VDDmax ;
2061 trselp.RNT = (*rl) ;
2062
2063 /*
2064 rsat and vsat
2065 */
2066
2067 for( npwl = 0 ; npwl < spipwl->N && spipwl->DATA[npwl].X0 <= trselp.VLIN ; npwl++ ) ;
2068 imax = fabs( spipwl->DATA[spipwl->N-1].A * spipwl->X1 + spipwl->DATA[spipwl->N-1].B ) ;
2069 besterror = MAXFLOAT ;
2070
2071 for( nsat = npwl+1 ; nsat < spipwl->N ; nsat++ ) {
2072
2073 vsat = spipwl->DATA[nsat].X0 ;
2074 isat = fabs(spipwl->DATA[nsat].A * vsat + spipwl->DATA[nsat].B) ;
2075
2076 trselp.VSAT = vsat ;
2077 trselp.RNS = (w/l)*(MCC_VDDmax-vsat)/(imax-isat) ;
2078
2079 status = mcc_mcc_characteristic( &trselp, MCC_VDDmax, 0.0, mccpwl, &nbmccpwl, 10 ) ;
2080
2081 if( status ) {
2082
2083 error = mcc_error_rst( spipwl, mccpwl, nbmccpwl, 0 );
2084
2085 if( error < besterror ) {
2086 *rs = trselp.RNS ;
2087 *ks = trselp.VSAT / MCC_VDDmax;
2088 besterror = error ;
2089 }
2090 }
2091 }
2092 }
2093
2094 /*
2095 compute MCC_RNS, MCC_RNT, MCC_KRNS, MCC_KRNT
2096 MCC_OPTIM_MODE must be enabled.
2097 if MCC_OPTIM_MODE is not enabled :
2098 - no operation is performed on MCC_RNS and MCC_RNT : they are supposed to have been computed with mcc_calcul_abr().
2099 - MCC_KRNS and MCC_KRNT are set to 3/4 and 1/6.
2100 */
2101
2102 void mcc_calcul_rst( int type, elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p )
2103 {
2104 float vlinmax ;
2105 float defaultvlin ;
2106 float defaultvsat ;
2107 float vlin ;
2108 float vsat ;
2109 float vbs ;
2110 float imax ;
2111 float error ;
2112 float besterror ;
2113 float ilin ;
2114 float isat ;
2115 float bestrns ;
2116 float bestrnt ;
2117 float bestvlin ;
2118 float bestvsat ;
2119 float k ;
2120 int npwl ;
2121 int nsat ;
2122 int nbmccpwl ;
2123 mbk_pwl *spipwl ;
2124 mcc_trans_mcc trs ;
2125 mcc_model mccpwl[10];
2126 int status ;
2127
2128 if( type == MCC_TRANS_N || type == MCC_TRANS_B ) {
2129 MCC_KRNS = 3.0/4.0 ;
2130 MCC_KRNT = 1.0/6.0 ;
2131 }
2132 else {
2133 MCC_KRPS = 3.0/4.0 ;
2134 MCC_KRPT = 1.0/6.0 ;
2135 }
2136
2137 if( !MCC_OPTIM_MODE )
2138 return ;
2139
2140 if( type == MCC_TRANS_N || type == MCC_TRANS_B ) {
2141 vlinmax = MCC_VDDmax - MCC_VTN ;
2142 defaultvlin = MCC_VDDmax * MCC_KRNT ;
2143 defaultvsat = MCC_VDDmax * MCC_KRNS ;
2144 spipwl = MCC_OPTIM_IDNRES ;
2145 trs.TYPE = TRANSN ;
2146 trs.TRLENGTH = (long)(0.5+MCC_LNeff * ((double)SCALE_X)) ;
2147 trs.TRWIDTH = (long)(0.5+MCC_WNeff * ((double)SCALE_X)) ;
2148 trs.A = MCC_AN ;
2149 trs.B = MCC_BN ;
2150 trs.VT = MCC_VTN ;
2151 trs.KVT = MCC_KTN ;
2152 if( lotrsparam_n->ISVBSSET )
2153 vbs = lotrsparam_n->VBS ;
2154 else
2155 vbs = lotrsparam_n->VBULK;
2156 trs.VG = MCC_VDDmax ;
2157 trs.VB = 0.0 ;
2158 }
2159 else {
2160 vlinmax = MCC_VDDmax - MCC_VTP ;
2161 defaultvlin = MCC_VDDmax * MCC_KRPT ;
2162 defaultvsat = MCC_VDDmax * MCC_KRPS ;
2163 spipwl = MCC_OPTIM_IDPRES ;
2164 trs.TYPE = TRANSP ;
2165 trs.TRLENGTH = (long)(0.5+MCC_LPeff * ((double)SCALE_X)) ;
2166 trs.TRWIDTH = (long)(0.5+MCC_WPeff * ((double)SCALE_X)) ;
2167 trs.A = MCC_AP ;
2168 trs.B = MCC_BP ;
2169 trs.VT = MCC_VTP ;
2170 trs.KVT = MCC_KTP ;
2171 if( lotrsparam_p->ISVBSSET )
2172 vbs = lotrsparam_p->VBS ;
2173 else
2174 vbs = lotrsparam_p->VBULK - MCC_VDDmax;
2175 if( V_BOOL_TAB[ __AVT_BUG_RSAT ].VALUE ) {
2176 trs.VG = MCC_VDDmax ;
2177 trs.VB = 0.0 ;
2178 }
2179 else {
2180 trs.VG = 0 ;
2181 trs.VB = MCC_VDDmax ;
2182 }
2183 }
2184
2185 k = ((float)trs.TRWIDTH) / ((float)trs.TRLENGTH ) ;
2186 trs.VDD = MCC_VDDmax ;
2187 trs.KS = 1.0 ;
2188 trs.KR = 1.0 ;
2189 trs.RS = 0.0 ;
2190 trs.RD = 0.0 ;
2191
2192 /* Pour l'instant, on ne calcule ces valeurs que si le vt est supérieur à vdd/2.
2193 C'est parce lorsqu'on les calcules proprement, ça fait sortir certains bench
2194 d'infineon de [-4%:4%].
2195 */
2196
2197 if( ( V_BOOL_TAB[ __MCC_ACCURATE_RLIN_THRESHOLD ].VALUE && trs.VT > trs.VDD/2.0 ) ||
2198 ! V_BOOL_TAB[ __MCC_ACCURATE_RLIN_THRESHOLD ].VALUE ) {
2199 if( spipwl && spipwl->N > 1 ) {
2200
2201 imax = fabs( spipwl->DATA[spipwl->N-1].A * spipwl->X1 + spipwl->DATA[spipwl->N-1].B ) ;
2202
2203 besterror = MAXFLOAT ;
2204
2205 npwl = 1 ;
2206 while( npwl < spipwl->N && spipwl->DATA[npwl].X0 <= vlinmax ) {
2207
2208 vlin = spipwl->DATA[npwl].X0 ;
2209 ilin = fabs( spipwl->DATA[npwl].A*vlin + spipwl->DATA[npwl].B ) ;
2210
2211 trs.VLIN = vlin ;
2212 trs.RNT = k*vlin/ilin ;
2213
2214 for( nsat = npwl+1 ; nsat < spipwl->N ; nsat++ ) {
2215
2216 vsat = spipwl->DATA[nsat].X0 ;
2217 isat = fabs(spipwl->DATA[nsat].A * vsat + spipwl->DATA[nsat].B) ;
2218
2219 trs.VSAT = vsat ;
2220 trs.RNS = k*(MCC_VDDmax-vsat)/(imax-isat) ;
2221
2222 if( V_BOOL_TAB[ __AVT_BUG_RSAT ].VALUE )
2223 status = mcc_mcc_characteristic( &trs, MCC_VDDmax, vbs, mccpwl, &nbmccpwl, 10 ) ;
2224 else
2225 status = mcc_mcc_characteristic( &trs, MCC_VDDmax, 0.0, mccpwl, &nbmccpwl, 10 ) ;
2226
2227 if( status ) {
2228
2229 error = mcc_error_rst( spipwl, mccpwl, nbmccpwl, 0 );
2230
2231 if( error < besterror ) {
2232 bestrns = trs.RNS ;
2233 bestrnt = trs.RNT ;
2234 bestvlin = trs.VLIN ;
2235 bestvsat = trs.VSAT ;
2236 besterror = error ;
2237 }
2238 }
2239 }
2240
2241 npwl++ ;
2242 }
2243
2244 if( type == MCC_TRANS_N || type == MCC_TRANS_B ) {
2245 MCC_RNS = bestrns ;
2246 MCC_RNT = bestrnt ;
2247 MCC_KRNT = bestvlin / MCC_VDDmax ;
2248 MCC_KRNS = bestvsat / MCC_VDDmax ;
2249 }
2250 else {
2251 MCC_RPS = bestrns ;
2252 MCC_RPT = bestrnt ;
2253 MCC_KRPT = bestvlin / MCC_VDDmax ;
2254 MCC_KRPS = bestvsat / MCC_VDDmax ;
2255 }
2256 }
2257 }
2258 }
2259
2260 void mcc_calcul_abr(type,v1,v2,lotrsparam_n,lotrsparam_p)
2261 int type ;
2262 double v1;
2263 double v2;
2264 elp_lotrs_param *lotrsparam_n;
2265 elp_lotrs_param *lotrsparam_p;
2266 {
2267 double i1 ;
2268 double i2 ;
2269 double ir ;
2270 double irs ;
2271 double vr ;
2272 double vrs ;
2273 double vbs;
2274 int stepr ;
2275 int steprs ;
2276 int valid_param_n = 0,
2277 valid_param_p = 0;
2278 static int fordebug ;
2279
2280 fordebug++ ;
2281
2282 if((type == MCC_TRANS_N) || (type == MCC_TRANS_B)) {
2283 stepr = mcc_ftoi((MCC_VDDmax * MCC_KRNT) / ( MCC_DC_STEP)) ;
2284 steprs = mcc_ftoi((MCC_VDDmax * MCC_KRNS) / ( MCC_DC_STEP)) ;
2285 }
2286 else {
2287 stepr = mcc_ftoi((MCC_VDDmax * MCC_KRPT) / ( MCC_DC_STEP)) ;
2288 steprs = mcc_ftoi((MCC_VDDmax * MCC_KRPS) / ( MCC_DC_STEP)) ;
2289 }
2290
2291 vr = MCC_DC_STEP * stepr ;
2292 vrs = MCC_DC_STEP * steprs ;
2293
2294 if((type == MCC_TRANS_N) || (type == MCC_TRANS_B))
2295 {
2296 if ( v1 < 0.0 )
2297 v1 = (MCC_VDDmax-MCC_VTN)/2.0 + MCC_VTN;
2298 if ( v2 < 0.0 )
2299 v2 = MCC_VDDmax;
2300 if( lotrsparam_n->ISVBSSET )
2301 vbs = lotrsparam_n->VBS ;
2302 else
2303 vbs = lotrsparam_n->VBULK;
2304 i2 = mcc_spicecurrent(v2,MCC_VDDmax,vbs,MCC_TRANS_N,lotrsparam_n) ;
2305 ir = mcc_spicecurrent(MCC_VDDmax,vr,vbs,MCC_TRANS_N,lotrsparam_n) ;
2306 irs = mcc_spicecurrent(MCC_VDDmax,vrs,vbs,MCC_TRANS_N,lotrsparam_n) ;
2307 if( V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B ].VALUE ) {
2308 i1 = mcc_spicecurrent(v1,MCC_VDDmax,vbs,MCC_TRANS_N,lotrsparam_n) ;
2309 MCC_AN = mcc_calcul_a(v1,v2,i1,i2,MCC_VTN,MCC_LN+MCC_DLN,MCC_WN+MCC_DWN) ;
2310 MCC_BN = mcc_calcul_b(v1,v2,i1,i2,MCC_VTN,MCC_LN+MCC_DLN,MCC_WN+MCC_DWN) ;
2311 }
2312 else {
2313 // loop to satisfy B > 0.0
2314 while ( !valid_param_n && v1 < MCC_VDDmax )
2315 {
2316 i1 = mcc_spicecurrent(v1,MCC_VDDmax,vbs,MCC_TRANS_N,lotrsparam_n) ;
2317 MCC_AN = fabs(mcc_calcul_a(v1,v2,i1,i2,MCC_VTN,MCC_LN+MCC_DLN,MCC_WN+MCC_DWN)) ;
2318 if ( MCC_CALC_VT && !V_BOOL_TAB[ __MCC_TEST_B_NEG ].VALUE )
2319 valid_param_n = 1;
2320 else if ( (MCC_WNeff/MCC_LNeff)*MCC_AN*(v1-MCC_VTN)*(v1-MCC_VTN) > i1 )
2321 valid_param_n = 1;
2322 else
2323 v1 += MCC_VTN*0.05;
2324 }
2325 MCC_BN = fabs(mcc_calcul_b(v1,v2,i1,i2,MCC_VTN,MCC_LN+MCC_DLN,MCC_WN+MCC_DWN)) ;
2326 }
2327 MCC_RNT = mcc_calcul_r(vr,ir,MCC_LN+MCC_DLN,MCC_WN+MCC_DWN) ;
2328 MCC_RNS = mcc_calcul_rs(v2,i2,vrs,irs,MCC_LN+MCC_DLN,MCC_WN+MCC_DWN) ;
2329 }
2330
2331
2332 if((type == MCC_TRANS_P) || (type == MCC_TRANS_B))
2333 {
2334 if ( v1 < 0.0 )
2335 v1 = (MCC_VDDmax-MCC_VTP)/2.0 + MCC_VTP;
2336 if ( v2 < 0.0 )
2337 v2 = MCC_VDDmax;
2338 if( lotrsparam_p->ISVBSSET )
2339 vbs = lotrsparam_p->VBS ;
2340 else
2341 vbs = lotrsparam_p->VBULK - MCC_VDDmax;
2342 i2 = mcc_spicecurrent(v2,MCC_VDDmax,vbs,MCC_TRANS_P,lotrsparam_p) ;
2343 ir = mcc_spicecurrent(MCC_VDDmax,vr,vbs,MCC_TRANS_P,lotrsparam_p) ;
2344 irs = mcc_spicecurrent(MCC_VDDmax,vrs,vbs,MCC_TRANS_P,lotrsparam_p) ;
2345 if( V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B ].VALUE ) {
2346 i1 = mcc_spicecurrent(v1,MCC_VDDmax,vbs,MCC_TRANS_P,lotrsparam_p) ;
2347 MCC_AP = mcc_calcul_a(v1,v2,i1,i2,MCC_VTP,MCC_LP+MCC_DLP,MCC_WP+MCC_DWP) ;
2348 MCC_BP = mcc_calcul_b(v1,v2,i1,i2,MCC_VTP,MCC_LP+MCC_DLP,MCC_WP+MCC_DWP) ;
2349 }
2350 else {
2351 // loop to satisfy B > 0.0
2352 while ( !valid_param_p && v1 < MCC_VDDmax )
2353 {
2354 i1 = mcc_spicecurrent(v1,MCC_VDDmax,vbs,MCC_TRANS_P,lotrsparam_p) ;
2355 MCC_AP = fabs(mcc_calcul_a(v1,v2,i1,i2,MCC_VTP,MCC_LP+MCC_DLP,MCC_WP+MCC_DWP)) ;
2356 if ( MCC_CALC_VT && !V_BOOL_TAB[ __MCC_TEST_B_NEG ].VALUE )
2357 valid_param_p = 1;
2358 else if ( (MCC_WPeff/MCC_LPeff)*MCC_AP*(v1-MCC_VTP)*(v1-MCC_VTP) > i1 )
2359 valid_param_p = 1;
2360 else
2361 v1 += MCC_VTP*0.05;
2362 }
2363 MCC_BP = fabs(mcc_calcul_b(v1,v2,i1,i2,MCC_VTP,MCC_LP+MCC_DLP,MCC_WP+MCC_DWP)) ;
2364 }
2365 MCC_RPT = mcc_calcul_r(vr,ir,MCC_LP+MCC_DLP,MCC_WP+MCC_DWP) ;
2366 MCC_RPS = mcc_calcul_rs(v2,i2,vrs,irs,MCC_LP+MCC_DLP,MCC_WP+MCC_DWP) ;
2367 }
2368 }
2369
2370 void mcc_calcul_vti(type,lotrsparam_n,lotrsparam_p)
2371 int type ;
2372 elp_lotrs_param *lotrsparam_n;
2373 elp_lotrs_param *lotrsparam_p;
2374 {
2375 if((type == MCC_TRANS_N) || (type == MCC_TRANS_B))
2376 MCC_VTIN = mcc_calcVTI(MCC_MODELFILE, MCC_TNMODEL,
2377 MCC_NMOS, MCC_NCASE, MCC_LN*1.0e-6, MCC_WN*1.0e-6,
2378 MCC_VDDmax, MCC_TEMP, MCC_DC_STEP,lotrsparam_n) ;
2379 if((type == MCC_TRANS_P) || (type == MCC_TRANS_B))
2380 MCC_VTIP = mcc_calcVTI(MCC_MODELFILE, MCC_TPMODEL,
2381 MCC_PMOS, MCC_PCASE, MCC_LP*1.0e-6, MCC_WP*1.0e-6,
2382 MCC_VDDmax, MCC_TEMP, MCC_DC_STEP,lotrsparam_p) ;
2383
2384 }
2385
2386 void mcc_calcul_vdeg(type,lotrsparam_n,lotrsparam_p)
2387 int type ;
2388 elp_lotrs_param *lotrsparam_n;
2389 elp_lotrs_param *lotrsparam_p;
2390 {
2391 if((type == MCC_TRANS_N) || (type == MCC_TRANS_B))
2392 MCC_VDDdeg = mcc_spicevdeg(MCC_TRANS_N,lotrsparam_n) ;
2393 if((type == MCC_TRANS_P) || (type == MCC_TRANS_B))
2394 MCC_VSSdeg = mcc_spicevdeg(MCC_TRANS_P,lotrsparam_p) ;
2395 }
2396
2397 void mcc_calcul_raccess(type,lotrsparam_n,lotrsparam_p)
2398 int type ;
2399 elp_lotrs_param *lotrsparam_n;
2400 elp_lotrs_param *lotrsparam_p;
2401 {
2402 if((type == MCC_TRANS_N) || (type == MCC_TRANS_B))
2403 mcc_calcRACCESS( MCC_MODELFILE, MCC_TNMODEL, MCC_NMOS, MCC_NCASE, MCC_LN*1.0e-6, MCC_WN*1.0e-6, lotrsparam_n, &MCC_RACCNS, &MCC_RACCND );
2404 if((type == MCC_TRANS_P) || (type == MCC_TRANS_B))
2405 mcc_calcRACCESS( MCC_MODELFILE, MCC_TPMODEL, MCC_PMOS, MCC_PCASE, MCC_LP*1.0e-6, MCC_WP*1.0e-6, lotrsparam_p, &MCC_RACCPS, &MCC_RACCPD );
2406 }
2407
2408 void mcc_get_np_vgs(float *vgsn, float *vgsp)
2409 {
2410 *vgsn= MCC_VDDmax/2;
2411 *vgsp= MCC_VDDmax/2;
2412 /* *vgsn=(MCC_VDDmax-MCC_VTN)/2+MCC_VTN;
2413 *vgsp=(MCC_VDDmax-MCC_VTP)/2;
2414 */
2415 }
2416 void mcc_drvspitab(spifile,tab,nbx,nby,lotrsparam_n,lotrsparam_p)
2417 int spifile ;
2418 double **tab ;
2419 int nbx ;
2420 int nby ;
2421 elp_lotrs_param *lotrsparam_n;
2422 elp_lotrs_param *lotrsparam_p;
2423 {
2424 FILE *file ;
2425 char argv[1024][8] ;
2426 double step, val[8] ;
2427 double vbsn,vbsp;
2428 char *nomout ;
2429 char *pt ;
2430 int i, k ;
2431 int j ;
2432 float vgsn, vgsp, rn, rp;
2433
2434 i = 0 ;
2435 if( (spifile == MCC_PARAM) || (spifile == MCC_OPT_PARAM) || (spifile == MCC_CALC_PARAM))
2436 {
2437 strcpy(argv[i++],"vdnsat") ;
2438 strcpy(argv[i++],"vdnres") ;
2439
2440 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2441 strcpy(argv[i++],"vdnvgs") ;
2442
2443 strcpy(argv[i++],"vdpsat") ;
2444 strcpy(argv[i++],"vdpres") ;
2445
2446 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2447 strcpy(argv[i++],"vdpvgs") ;
2448
2449 strcpy(argv[i++],"vdddeg") ;
2450 strcpy(argv[i++],"vssdeg") ;
2451 }
2452 else
2453 {
2454 for(i = 0 ; i < nbx ; i++)
2455 sprintf(argv[i],"s%d",i) ;
2456 }
2457
2458 if ( spifile == MCC_OPT_PARAM )
2459 nomout = mbkstrdup (mcc_debug_prefix("param_opt.dat")) ;
2460 else if ( spifile == MCC_CALC_PARAM )
2461 {
2462 nomout = mbkstrdup (mcc_debug_prefix("param_calc.dat")) ;
2463 for (j=0; j<8; j++)
2464 {
2465 TRS_CURVS.I_BSIM[j]=mbkalloc(sizeof(double)*TRS_CURVS.nb);
2466 }
2467 }
2468 else {
2469 nomout = mbkalloc(strlen(mcc_debug_prefix(MCC_SPICEFILE[spifile])) + 1) ;
2470 strcpy(nomout,mcc_debug_prefix(MCC_SPICEFILE[spifile])) ;
2471 if((pt = strchr(nomout,(int)('.'))) != NULL)
2472 *pt = '\0' ;
2473 }
2474
2475 file = mbkfopen(nomout,"dat",WRITE_TEXT) ;
2476 avt_printExecInfo(file, "#", "", "");
2477
2478 if(file == NULL)
2479 {
2480 fprintf(stderr,"\nmcc error: can't open file %s.dat\n",nomout) ;
2481 EXIT(1);
2482 }
2483
2484 if( (spifile == MCC_PARAM) || (spifile == MCC_OPT_PARAM) || (spifile == MCC_CALC_PARAM))
2485 fprintf(file,"#volt ") ;
2486 else
2487 fprintf(file,"#time ") ;
2488
2489 for(i = 0 ; i < nbx ; i ++)
2490 {
2491 fprintf(file,"%s ",*(argv + i)) ;
2492 }
2493 fprintf(file,"\n") ;
2494
2495 step = 0.0 ;
2496
2497 if( lotrsparam_n->ISVBSSET )
2498 vbsn = lotrsparam_n->VBS ;
2499 else
2500 vbsn = lotrsparam_n->VBULK;
2501 if( lotrsparam_p->ISVBSSET )
2502 vbsp = lotrsparam_p->VBS ;
2503 else
2504 vbsp = lotrsparam_p->VBULK - MCC_VDDmax;
2505
2506 mcc_get_np_vgs(&vgsn, &vgsp);
2507 for(j = 0 ; j < nby ; j ++)
2508 {
2509 fprintf(file,"%.3e ",step) ;
2510 if( (spifile == MCC_PARAM) || (spifile == MCC_OPT_PARAM) || (spifile == MCC_CALC_PARAM))
2511 {
2512 MCC_VGS=vgsn;
2513 rn=mcc_spicecurrent(vgsn,step,vbsn,MCC_TRANS_N,lotrsparam_n);
2514 MCC_VGS=vgsp;
2515 rp=mcc_spicecurrent(vgsp,step,vbsp,MCC_TRANS_P,lotrsparam_p);
2516 fprintf(file,"%.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e ",
2517 val[0]=mcc_spicecurrent(step,MCC_VDDmax,vbsn,MCC_TRANS_N,lotrsparam_n),
2518 val[1]=mcc_spicecurrent(MCC_VDDmax,step,vbsn,MCC_TRANS_N,lotrsparam_n),
2519 val[2]=rn/*mcc_spicecurrent(vgsn,step,vbsn,MCC_TRANS_N,lotrsparam_n)*/,
2520 val[3]=mcc_spicecurrent(step,MCC_VDDmax,vbsp,MCC_TRANS_P,lotrsparam_p),
2521 val[4]=mcc_spicecurrent(MCC_VDDmax,step,vbsp,MCC_TRANS_P,lotrsparam_p),
2522 val[5]=rp/*mcc_spicecurrent(vgsp,step,vbsp,MCC_TRANS_P,lotrsparam_p)*/,
2523 val[6]=mcc_spicevdeg(MCC_TRANS_N,lotrsparam_n),
2524 val[7]=mcc_spicevdeg(MCC_TRANS_P,lotrsparam_p)) ;
2525 if ( spifile == MCC_CALC_PARAM && j<TRS_CURVS.nb)
2526 {
2527 for (k=0; k<8; k++)
2528 TRS_CURVS.I_BSIM[k][j]=val[k];
2529 }
2530 }
2531 else
2532 {
2533 for(i = 0 ; i < nbx ; i ++)
2534 {
2535 fprintf(file,"%.3e ",tab[i][j]) ;
2536 }
2537 }
2538 fprintf(file,"\n") ;
2539
2540 if( (spifile == MCC_PARAM) || (spifile == MCC_OPT_PARAM) || (spifile == MCC_CALC_PARAM))
2541 step += MCC_DC_STEP ;
2542 else
2543 step += (V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE) ;
2544 }
2545
2546 if(fclose(file) != 0)
2547 {
2548 fprintf(stderr,"\nmcc error: can't close file %s.dat\n",nomout) ;
2549 EXIT(1);
2550 }
2551
2552 mbkfree(nomout) ;
2553 }
2554
2555 void mcc_prsspifile(spifile,nbx,nby,tab)
2556 int spifile ;
2557 int nbx ;
2558 int nby ;
2559 double **tab ;
2560 {
2561 char *fileout ;
2562 char *argv[1024] ;
2563 char buf[64] ;
2564 double mccstep ;
2565 double limit ;
2566 int x, y ;
2567 int i ;
2568
2569 fileout = sim_getjoker(MCC_SPICEOUT,mcc_debug_prefix(MCC_SPICEFILE[spifile])) ;
2570
2571 if(spifile == MCC_PARAM)
2572 {
2573 i = 0 ;
2574 argv[i++] = mcc_initstr("vdnsat") ;
2575 argv[i++] = mcc_initstr("vdnres") ;
2576 if(nbx > 6)
2577 argv[i++] = mcc_initstr("vdnvgs") ;
2578 argv[i++] = mcc_initstr("vdpsat") ;
2579 argv[i++] = mcc_initstr("vdpres") ;
2580 if(nbx > 6)
2581 argv[i++] = mcc_initstr("vdpvgs") ;
2582 argv[i++] = mcc_initstr("vdddeg") ;
2583 argv[i++] = mcc_initstr("vssdeg") ;
2584 mccstep = MCC_DC_STEP ;
2585 limit = MCC_VDDmax ;
2586 }
2587 else
2588 {
2589 mccstep = (V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE) ;
2590 limit = (V_FLOAT_TAB[ __SIM_TIME ].VALUE) ;
2591 for(x = 0 ; x < nbx ; x++)
2592 {
2593 sprintf(buf,"s%d",x) ;
2594 argv[x] = mcc_initstr(buf) ;
2595 }
2596 }
2597
2598 sim_readspifiletab (fileout,argv,nbx,nby,tab,limit,mccstep) ;
2599 mbkfree(fileout) ;
2600 for(x = 0 ; x < nbx ; x++)
2601 {
2602 for(y = 0 ; y < nby ; y++)
2603 {
2604 tab[x][y] = fabs(tab[x][y]);
2605 }
2606 }
2607 for(x = 0 ; x < nbx ; x++)
2608 {
2609 mbkfree(argv[x]) ;
2610 }
2611 }
2612
2613 void mcc_addspidata(type,lotrsparam_n,lotrsparam_p)
2614 int type ;
2615 elp_lotrs_param *lotrsparam_n;
2616 elp_lotrs_param *lotrsparam_p;
2617 {
2618 double step,vbs ;
2619 double vdddeg ;
2620 double vssdeg ;
2621 int i ;
2622 int tabsize ;
2623
2624 tabsize = mcc_ftoi(MCC_VDDmax / MCC_DC_STEP) ;
2625 tabsize++ ;
2626
2627 if((type == MCC_TRANS_N) || (type == MCC_TRANS_B))
2628 {
2629 vdddeg = mcc_spicevdeg(MCC_TRANS_N,lotrsparam_n) ;
2630 step = 0.0 ;
2631 if( lotrsparam_n->ISVBSSET )
2632 vbs = lotrsparam_n->VBS ;
2633 else
2634 vbs = lotrsparam_n->VBULK;
2635 for(i = 0 ; i < tabsize ; i ++)
2636 {
2637 MCC_IDNSAT[i] = mcc_spicecurrent(step,MCC_VDDmax,vbs,MCC_TRANS_N,lotrsparam_n) ;
2638 MCC_IDNRES[i] = mcc_spicecurrent(MCC_VDDmax,step,vbs,MCC_TRANS_N,lotrsparam_n) ;
2639 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2640 {
2641 MCC_IDNVGS[i] = mcc_spicecurrent(MCC_VGS,step,vbs,MCC_TRANS_N,lotrsparam_n) ;
2642 }
2643 MCC_VDDDEG[i] = vdddeg ;
2644 step += MCC_DC_STEP ;
2645 }
2646 }
2647
2648 if((type == MCC_TRANS_P) || (type == MCC_TRANS_B))
2649 {
2650 vssdeg = mcc_spicevdeg(MCC_TRANS_P,lotrsparam_p) ;
2651 step = 0.0 ;
2652 if( lotrsparam_p->ISVBSSET )
2653 vbs = lotrsparam_p->VBS ;
2654 else
2655 vbs = lotrsparam_p->VBULK - MCC_VDDmax;
2656 for(i = 0 ; i < tabsize ; i ++)
2657 {
2658 MCC_IDPSAT[i] = mcc_spicecurrent(step,MCC_VDDmax,vbs,MCC_TRANS_P,lotrsparam_p) ;
2659 MCC_IDPRES[i] = mcc_spicecurrent(MCC_VDDmax,step,vbs,MCC_TRANS_P,lotrsparam_p) ;
2660 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2661 {
2662 MCC_IDPVGS[i] = mcc_spicecurrent(MCC_VGS,step,vbs,MCC_TRANS_P,lotrsparam_p) ;
2663 }
2664 MCC_VSSDEG[i] = vssdeg ;
2665 step += MCC_DC_STEP ;
2666 }
2667 }
2668 MCC_CALC_CUR = MCC_SIM_MODE ;
2669 }
2670
2671 void mcc_readspidata(fit,lotrsparam_n,lotrsparam_p)
2672 int fit ;
2673 elp_lotrs_param *lotrsparam_n;
2674 elp_lotrs_param *lotrsparam_p;
2675 {
2676 double totimeud ;
2677 double totimedu ;
2678 double beforeu ;
2679 double befored ;
2680 double seuil = MCC_VDDmax/2.0 ;
2681 double sfl = MCC_VDDmax*0.1 ;
2682 double sfh = MCC_VDDmax*0.9 ;
2683 double delay ;
2684 double slope ;
2685 double sloped ;
2686 double slopeu ;
2687 double last ;
2688 double *ptparam[8] ;
2689 int nbtimeud ;
2690 int nbtimedu ;
2691 int tabsize ;
2692 int i, k ;
2693 int f ;
2694 int type ;
2695 char oldMCC_CALC_ORG;
2696
2697 sim_set_result_file_extension('p', 1, &MCC_SPICEOUT);
2698
2699 MCC_FLAG_FIT = MCC_FIT_OK ;
2700
2701 tabsize = mcc_ftoi(MCC_VDDmax / MCC_DC_STEP) ;
2702 tabsize++ ;
2703
2704 mcc_allocspidata(MCC_TRANS_B) ;
2705
2706 i = 0 ;
2707 ptparam[i++] = MCC_IDNSAT ;
2708 ptparam[i++] = MCC_IDNRES ;
2709 // if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2710 ptparam[i++] = MCC_IDNVGS ;
2711 ptparam[i++] = MCC_IDPSAT ;
2712 ptparam[i++] = MCC_IDPRES ;
2713 // if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2714 ptparam[i++] = MCC_IDPVGS ;
2715 ptparam[i++] = MCC_VDDDEG ;
2716 ptparam[i++] = MCC_VSSDEG ;
2717
2718 if(MCC_CALC_CUR == MCC_SIM_MODE)
2719 {
2720 oldMCC_CALC_ORG=MCC_CALC_ORG;
2721 MCC_CALC_ORG = MCC_SIM_MODE ;
2722 mcc_prsspifile(MCC_PARAM,i,tabsize,ptparam) ;
2723 TRS_CURVS.nb=tabsize;
2724 for (k=0; k<i; k++)
2725 {
2726 TRS_CURVS.I_SIMU[k]=mbkalloc(sizeof(double)*tabsize);
2727 memcpy(TRS_CURVS.I_SIMU[k], ptparam[k], sizeof(double)*tabsize);
2728 }
2729 mcc_drvspitab(MCC_PARAM,ptparam,i,tabsize,lotrsparam_n,lotrsparam_p) ;
2730 MCC_CALC_CUR = MCC_CALC_MODE ;
2731 mcc_drvspitab(MCC_CALC_PARAM,ptparam,i,tabsize,lotrsparam_n,lotrsparam_p) ;
2732 MCC_CALC_CUR = MCC_SIM_MODE ;
2733 MCC_CALC_ORG=oldMCC_CALC_ORG;
2734 }
2735 else
2736 {
2737 if ( MCC_PLOT && !MCC_OPTIM_MODE )
2738 {
2739 mcc_addspidata(MCC_TRANS_B,lotrsparam_n,lotrsparam_p) ;
2740 mcc_drvspitab(MCC_PARAM,ptparam,i,tabsize,lotrsparam_n,lotrsparam_p) ;
2741 }
2742 if ( MCC_OPTIM_MODE )
2743 {
2744 mcc_optim_addspidata (MCC_TRANS_B,lotrsparam_n,lotrsparam_p) ;
2745 for (k=0; k<i; k++)
2746 {
2747 TRS_CURVS.I_OPTIM[k]=mbkalloc(sizeof(double)*tabsize);
2748 memcpy(TRS_CURVS.I_OPTIM[k], ptparam[k], sizeof(double)*tabsize);
2749 }
2750 if ( !MCC_PLOT )
2751 mcc_drvspitab(MCC_PARAM,ptparam,i,tabsize,lotrsparam_n,lotrsparam_p) ;
2752 else
2753 mcc_drvspitab(MCC_OPT_PARAM,ptparam,i,tabsize,lotrsparam_n,lotrsparam_p) ;
2754 }
2755 }
2756
2757 if(fit == 0)
2758 return ;
2759
2760 sim_set_result_file_extension('p', 0, &MCC_SPICEOUT);
2761
2762 tabsize = mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE / V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE) ;
2763 tabsize++ ;
2764
2765 MCC_FITS = (double **)mbkalloc((MCC_INSNUMB + 1) * sizeof(double *)) ;
2766
2767 for(i = 0 ; i <= MCC_INSNUMB ; i++)
2768 MCC_FITS[i] = (double *)mbkalloc(tabsize *sizeof(double)) ;
2769
2770 for(f = 0 ; f < MCC_SPICENB - 1 ; f++)
2771 {
2772 mcc_prsspifile(f,MCC_INSNUMB+1,tabsize,MCC_FITS) ;
2773 mcc_drvspitab(f,MCC_FITS,MCC_INSNUMB+1,tabsize,lotrsparam_n,lotrsparam_p) ;
2774 beforeu = -1.0 ;
2775 befored = -1.0 ;
2776 totimeud = 0.0 ;
2777 totimedu = 0.0 ;
2778 sloped = 0.0 ;
2779 slopeu = 0.0 ;
2780 nbtimeud = 0 ;
2781 nbtimedu = 0 ;
2782 type = 0 ;
2783 for(i = 3 ; i <= MCC_INSNUMB - 2 ; i++)
2784 {
2785 if(type == 0)
2786 last = befored ;
2787 else
2788 last = beforeu ;
2789
2790 delay = -1.0 ;
2791 slope = -1.0 ;
2792
2793 if(type == 1)
2794 {
2795 sfl = (MCC_VDDmax - MCC_VTP)/4.0 ;
2796 sfh = (MCC_VDDmax - MCC_VTP) ;
2797 }
2798 else
2799 {
2800 sfl = MCC_VTN ;
2801 sfh = (3.0*MCC_VDDmax + MCC_VTN)/4.0 ;
2802 }
2803
2804 last = sim_calcdelayslope(MCC_FITS[i],tabsize,2,seuil,sfl,sfh,last,
2805 &delay,&slope,&type,V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE*1e9,NULL,NULL) ;
2806
2807 if(type == 1)
2808 {
2809 if((delay > 0) && (slope > 0))
2810 {
2811 totimedu += delay ;
2812 nbtimedu++ ;
2813 slopeu += slope * 1000.0 ;
2814 }
2815 beforeu = last ;
2816 }
2817 else
2818 {
2819 if((delay > 0) && (slope > 0))
2820 {
2821 totimeud += delay ;
2822 nbtimeud++ ;
2823 sloped += slope * 1000.0 ;
2824 }
2825 befored = last ;
2826 }
2827 }
2828 if((nbtimeud != 0) && (nbtimedu != 0))
2829 {
2830 totimeud = totimeud * 1000.0 ;
2831 totimedu = totimedu * 1000.0 ;
2832 totimeud = (double)(totimeud/(double)nbtimeud) ;
2833 totimedu = (double)(totimedu/(double)nbtimedu) ;
2834 slopeu = (double)(slopeu/(double)nbtimedu) ;
2835 sloped = (double)(sloped/(double)nbtimeud) ;
2836 }
2837 else
2838 {
2839 beforeu = -1.0 ;
2840 befored = -1.0 ;
2841 totimeud = 0.0 ;
2842 totimedu = 0.0 ;
2843 sloped = 0.0 ;
2844 slopeu = 0.0 ;
2845 nbtimeud = 0 ;
2846 nbtimedu = 0 ;
2847 for(i = 1 ; i <= MCC_INSNUMB - 3 ; i++)
2848 {
2849 if(type == 0)
2850 last = befored ;
2851 else
2852 last = beforeu ;
2853
2854 delay = -1.0 ;
2855 slope = -1.0 ;
2856
2857 if(type == 1)
2858 {
2859 sfl = (MCC_VDDmax - MCC_VTP)/4.0 ;
2860 sfh = (MCC_VDDmax - MCC_VTP) ;
2861 }
2862 else
2863 {
2864 sfl = MCC_VTN ;
2865 sfh = (3.0*MCC_VDDmax + MCC_VTN)/4.0 ;
2866 }
2867
2868 last = sim_calcdelayslope(MCC_FITS[i],tabsize,2,seuil,sfl,sfh,last,
2869 &delay,&slope,&type,V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE*1e9,NULL,NULL) ;
2870 if(type == 1)
2871 {
2872 if((delay > 0) && (slope > 0))
2873 {
2874 totimedu += delay ;
2875 nbtimedu++ ;
2876 slopeu += slope * 1000.0 ;
2877 }
2878 beforeu = last ;
2879 }
2880 else
2881 {
2882 if((delay > 0) && (slope > 0))
2883 {
2884 totimeud += delay ;
2885 nbtimeud++ ;
2886 sloped += slope * 1000.0 ;
2887 }
2888 befored = last ;
2889 }
2890 }
2891 if((nbtimeud != 0) && (nbtimedu != 0))
2892 {
2893 totimeud = totimeud * 1000.0 ;
2894 totimedu = totimedu * 1000.0 ;
2895 totimeud = (double)(totimeud/(double)nbtimeud) ;
2896 totimedu = (double)(totimedu/(double)nbtimedu) ;
2897 slopeu = (double)(slopeu/(double)nbtimedu) ;
2898 sloped = (double)(sloped/(double)nbtimeud) ;
2899 }
2900 }
2901 switch(f)
2902 {
2903 case MCC_FIT_A : MCC_SPICEUD_FITA = (long)totimeud ;
2904 MCC_SPICEDU_FITA = (long)totimedu ;
2905 MCC_SPICEFUD_FITA = (long)sloped ;
2906 MCC_SPICEFDU_FITA = (long)slopeu ;
2907 if((MCC_SPICEUD_FITA == 0) ||
2908 (MCC_SPICEDU_FITA == 0))
2909 MCC_FLAG_FIT = MCC_FIT_KO ;
2910 break ;
2911 case MCC_FIT_CG_NOCAPA:
2912 MCC_SPICEUD_FITCGNOCAPA = (long)totimeud ;
2913 MCC_SPICEDU_FITCGNOCAPA = (long)totimedu ;
2914 MCC_SPICEFUD_FITCGNOCAPA = (long)sloped ;
2915 MCC_SPICEFDU_FITCGNOCAPA = (long)slopeu ;
2916 if((MCC_SPICEUD_FITCGNOCAPA == 0) ||
2917 (MCC_SPICEDU_FITCGNOCAPA == 0))
2918 MCC_FLAG_FIT = MCC_FIT_KO ;
2919 break ;
2920 case MCC_FIT_CG : MCC_SPICEUD_FITCG = (long)totimeud ;
2921 MCC_SPICEDU_FITCG = (long)totimedu ;
2922 MCC_SPICEFUD_FITCG = (long)sloped ;
2923 MCC_SPICEFDU_FITCG = (long)slopeu ;
2924 if((MCC_SPICEUD_FITCG == 0) ||
2925 (MCC_SPICEDU_FITCG == 0))
2926 MCC_FLAG_FIT = MCC_FIT_KO ;
2927 break ;
2928 case MCC_FIT_CDN : MCC_SPICEUD_FITDN = (long)totimeud ;
2929 MCC_SPICEDU_FITDN = (long)totimedu ;
2930 MCC_SPICEFUD_FITDN = (long)sloped ;
2931 MCC_SPICEFDU_FITDN = (long)slopeu ;
2932 if((MCC_SPICEUD_FITDN == 0) ||
2933 (MCC_SPICEDU_FITDN == 0))
2934 MCC_FLAG_FIT = MCC_FIT_KO ;
2935 break ;
2936 case MCC_FIT_CDP : MCC_SPICEUD_FITDP = (long)totimeud ;
2937 MCC_SPICEDU_FITDP = (long)totimedu ;
2938 MCC_SPICEFUD_FITDP = (long)sloped ;
2939 MCC_SPICEFDU_FITDP = (long)slopeu ;
2940 if((MCC_SPICEUD_FITDP == 0) ||
2941 (MCC_SPICEDU_FITDP == 0))
2942 MCC_FLAG_FIT = MCC_FIT_KO ;
2943 break ;
2944 }
2945 }
2946 sim_set_result_file_extension('p', 1, &MCC_SPICEOUT);
2947
2948 }
2949
2950 void mcc_allocspidata(type)
2951 int type ;
2952 {
2953 int tabsize ;
2954
2955 tabsize = mcc_ftoi(MCC_VDDmax / MCC_DC_STEP) ;
2956 tabsize++ ;
2957
2958 if((type == MCC_TRANS_N) || (type == MCC_TRANS_B))
2959 {
2960 MCC_IDNSAT = (double *)mbkalloc(tabsize * sizeof(double)) ;
2961 MCC_IDNRES = (double *)mbkalloc(tabsize * sizeof(double)) ;
2962 MCC_VDDDEG = (double *)mbkalloc(tabsize * sizeof(double)) ;
2963 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2964 MCC_IDNVGS = (double *)mbkalloc(tabsize * sizeof(double)) ;
2965 MCC_OPTIM_IDNSAT = NULL;
2966 MCC_OPTIM_IDNRES = NULL;
2967 MCC_OPTIM_IDNVGS = NULL;
2968 }
2969 if((type == MCC_TRANS_P) || (type == MCC_TRANS_B))
2970 {
2971 MCC_IDPSAT = (double *)mbkalloc(tabsize * sizeof(double)) ;
2972 MCC_IDPRES = (double *)mbkalloc(tabsize * sizeof(double)) ;
2973 MCC_VSSDEG = (double *)mbkalloc(tabsize * sizeof(double)) ;
2974 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2975 MCC_IDPVGS = (double *)mbkalloc(tabsize * sizeof(double)) ;
2976 MCC_OPTIM_IDPSAT = NULL;
2977 MCC_OPTIM_IDPRES = NULL;
2978 MCC_OPTIM_IDPVGS = NULL;
2979 }
2980 }
2981
2982 void mcc_freespidata(fit,type)
2983 int fit ;
2984 int type ;
2985 {
2986 int i ;
2987
2988 if(MCC_CALC_CUR == MCC_SIM_MODE)
2989 {
2990 if((type == MCC_TRANS_N) || (type == MCC_TRANS_B))
2991 {
2992 mbkfree(MCC_IDNSAT) ; MCC_IDNSAT=NULL;
2993 mbkfree(MCC_IDNRES) ;
2994 mbkfree(MCC_VDDDEG) ;
2995 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
2996 mbkfree(MCC_IDNVGS) ;
2997 if ( MCC_OPTIM_MODE )
2998 {
2999 mbk_pwl_free_pwl ( MCC_OPTIM_IDNSAT );
3000 MCC_OPTIM_IDNSAT = NULL;
3001 mbk_pwl_free_pwl ( MCC_OPTIM_IDNRES );
3002 MCC_OPTIM_IDNRES = NULL;
3003 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
3004 {
3005 mbk_pwl_free_pwl ( MCC_OPTIM_IDNVGS );
3006 MCC_OPTIM_IDNVGS = NULL;
3007 }
3008 }
3009 }
3010 if((type == MCC_TRANS_P) || (type == MCC_TRANS_B))
3011 {
3012 mbkfree(MCC_IDPSAT) ; MCC_IDPSAT=NULL;
3013 mbkfree(MCC_IDPRES) ;
3014 mbkfree(MCC_VSSDEG) ;
3015 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
3016 mbkfree(MCC_IDPVGS) ;
3017 if ( MCC_OPTIM_MODE )
3018 {
3019 mbk_pwl_free_pwl ( MCC_OPTIM_IDPSAT );
3020 MCC_OPTIM_IDPSAT = NULL;
3021 mbk_pwl_free_pwl ( MCC_OPTIM_IDPRES );
3022 MCC_OPTIM_IDPRES = NULL;
3023 if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
3024 {
3025 mbk_pwl_free_pwl ( MCC_OPTIM_IDPVGS );
3026 MCC_OPTIM_IDPVGS = NULL;
3027 }
3028 }
3029 }
3030 }
3031
3032 if(fit == 0)
3033 return ;
3034
3035 if ( MCC_FITS )
3036 {
3037 for(i = 0 ; i <= MCC_INSNUMB ; i++)
3038 mbkfree(MCC_FITS[i]) ;
3039
3040 mbkfree(MCC_FITS) ;
3041 }
3042 }
3043
3044 void mcc_runspice (int fit)
3045 {
3046 int i;
3047
3048 for (i = fit ? 0 : MCC_PARAM; i < MCC_SPICENB; i++)
3049 if((MCC_CALC_CUR == MCC_CALC_MODE) && (i == MCC_PARAM)) break;
3050 else sim_execspice(mcc_debug_prefix(MCC_SPICEFILE[i]), 0, MCC_SPICENAME, MCC_SPICESTRING, MCC_SPICESTDOUT);
3051 }
3052
3053 void mcc_genspicom(file,filename,lotrsparam_n,lotrsparam_p)
3054 FILE *file ;
3055 char *filename ;
3056 elp_lotrs_param *lotrsparam_n;
3057 elp_lotrs_param *lotrsparam_p;
3058 {
3059 char model[1024] ;
3060 char basename[1024] ;
3061 char *pt ;
3062 int i ;
3063 int issim ;
3064 char *subcktmodeln, *subcktmodelp ;
3065 char *modeln, *modelp ;
3066 char *mn, *mp ;
3067 char bufn[1024] ;
3068 char bufp[1024] ;
3069 int bs3 = 0 ;
3070 int bs4 = 0 ;
3071 float t;
3072
3073 // unused
3074 lotrsparam_n = NULL ;
3075 lotrsparam_p = NULL ;
3076
3077 bs3 = ( MCC_SPICEMODELTYPE == MCC_BSIM3V3 ? 1 : 0 ) ;
3078 bs4 = ( MCC_SPICEMODELTYPE == MCC_BSIM4 ? 1 : 0 ) ;
3079
3080 modeln = MCC_TNMODEL ;
3081 modelp = MCC_TPMODEL ;
3082 sprintf(bufn,"m") ;
3083 sprintf(bufp,"m") ;
3084
3085 strcpy(model,filename) ;
3086 pt = strchr(model,(int)('.')) ;
3087 if(pt != NULL)
3088 *pt = '\0' ;
3089 strcpy(basename,model) ;
3090 pt = strstr(model,"_sim") ;
3091 if(pt != NULL)
3092 {
3093 *pt = '\0' ;
3094 issim = 1 ;
3095 }
3096 else
3097 {
3098 issim = 0 ;
3099 }
3100
3101 fprintf(file,"****spice description of %s\n",filename);
3102 fprintf(file,"\n");
3103
3104 if(issim != 0)
3105 {
3106 if(MCC_SPICEOPTIONS != NULL) fprintf(file,".option %s\n",MCC_SPICEOPTIONS);
3107 if ( V_INT_TAB[__SIM_TOOL].VALUE == SIM_TOOL_NGSPICE )
3108 fprintf(file,".include %s\n",MCC_TECHFILE);
3109 else
3110 fprintf(file,".include \"%s\"\n",MCC_TECHFILE);
3111 fprintf(file,"\n");
3112 }
3113
3114 subcktmodeln = mcc_getsubckt( MCC_MODELFILE,
3115 MCC_TNMODEL,
3116 MCC_NMOS,
3117 MCC_NCASE,
3118 MCC_LN*1.0e-6,
3119 MCC_WN*1.0e-6
3120 ) ;
3121 subcktmodelp = mcc_getsubckt( MCC_MODELFILE,
3122 MCC_TPMODEL,
3123 MCC_PMOS,
3124 MCC_PCASE,
3125 MCC_LP*1.0e-6,
3126 MCC_WP*1.0e-6
3127 ) ;
3128
3129 if ((subcktmodeln != NULL) && (issim != 0))
3130 /*- le model est dans un subckt -*/
3131 {
3132 sprintf(bufn,"xm") ;
3133 modeln = subcktmodeln ;
3134 }
3135
3136 if ((subcktmodelp != NULL) && (issim != 0))
3137 /*- le model est dans un subckt -*/
3138 {
3139 sprintf(bufp,"xm") ;
3140 modelp = subcktmodelp ;
3141 }
3142
3143 mn = mbkstrdup(bufn) ;
3144 mp = mbkstrdup(bufp) ;
3145
3146 fprintf(file,".subckt inv in out vbn vbp vdd vss\n");
3147 fprintf(file,"%s1 out in vss vbn %s l=%gu w=%gu %s\n"
3148 ,mn,modeln,MCC_LN,MCC_WN,surf_string_n);
3149 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
3150 fprintf(file,"%s2 out in vdd vbp %s l=%gu w=%gu %s\n"
3151 ,mp,modelp,MCC_LP,MCC_WP,surf_string_p);
3152 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
3153 if(strstr(model,"fit_a") != NULL)
3154 {
3155 if(MCC_CAPA > 0.0)
3156 fprintf(file,"c1 out vss %gf\n",MCC_CAPA) ;
3157 }
3158 else if(strstr(model,"fit_cg") !=NULL || strstr(model,"fit_cg_nocapa") !=NULL)
3159 {
3160 for(i = 0 ; i < MCC_INVNUMB ; i++)
3161 {
3162 fprintf(file,"%sn%d out%d out ",mn,i,i) ;
3163 fprintf(file,"vss vbn %s l=%gu w=%gu %s\n"
3164 ,modeln,MCC_LN,MCC_WN,surf_string_n);
3165 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
3166 fprintf(file,"%sp%d out%d out ",mp,i,i) ;
3167 fprintf(file,"vdd vbp %s l=%gu w=%gu %s\n"
3168 ,modelp,MCC_LP,MCC_WP,surf_string_p);
3169 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
3170 if(strstr(model,"fit_cg_nocapa")==NULL && MCC_CAPA > 0.0)
3171 fprintf(file,"c%d out%d vss %gf\n",i,i,MCC_CAPA) ;
3172 }
3173 }
3174 else if(strstr(model,"fit_cdn") != NULL)
3175 {
3176 for(i = 0 ; i < MCC_TRANSNUMB ; i++)
3177 {
3178 fprintf(file,"%sn%d ",mn,i) ;
3179 fprintf(file,"out vss vss vbn %s l=%gu w=%gu %s\n"
3180 ,modeln,MCC_LN,MCC_WN,surf_string_n);
3181 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
3182 }
3183 }
3184 else if(strstr(model,"fit_cdp") !=NULL)
3185 {
3186 for(i = 0 ; i < MCC_TRANSNUMB ; i++)
3187 {
3188 fprintf(file,"%sp%d ",mp,i) ;
3189 fprintf(file,"out vdd vdd vbp %s l=%gu w=%gu %s\n"
3190 ,modelp,MCC_LP,MCC_WP,surf_string_p);
3191 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
3192 }
3193 }
3194 mbkfree(mn) ;
3195 mbkfree(mp) ;
3196
3197 fprintf(file,".ends inv\n");
3198
3199 fprintf(file,"\n") ;
3200
3201 fprintf(file,".subckt %s",model) ;
3202
3203 for(i = 0 ; i < MCC_INSNUMB + 1 ; i++)
3204 {
3205 fprintf(file," s%d",i) ;
3206 }
3207
3208 fprintf(file," vbn vbp vdd vss\n") ;
3209
3210 for(i = 0 ; i < MCC_INSNUMB ; i++)
3211 {
3212 fprintf(file,"xinv%d s%d s%d vbn vbp vdd vss inv\n",i,i,i+1) ;
3213 }
3214
3215 if ( !issim )
3216 {
3217 fprintf(file,"vbulkn vbn vss %g\n",(MCC_VBULKN > ELPMINVBULK) ? MCC_VBULKN : 0.0);
3218 fprintf(file,"vbulkp vbp vss %g\n",(MCC_VBULKP > ELPMINVBULK) ? MCC_VBULKP : MCC_VDDmax);
3219 }
3220
3221 fprintf(file,".ends %s\n",model) ;
3222
3223 if(issim != 0)
3224 {
3225 fprintf(file,"\n") ;
3226 fprintf(file,"x%s",model) ;
3227
3228 for(i = 0 ; i < MCC_INSNUMB + 1 ; i++)
3229 {
3230 fprintf(file," s%d",i) ;
3231 }
3232
3233 fprintf(file," vbn vbp vdd 0 %s\n",model);
3234 fprintf(file,"\n");
3235 fprintf(file,"valim vdd 0 %gV\n",MCC_VDDmax);
3236 fprintf(file,"vbulkn vbn 0 %gV\n",(MCC_VBULKN > ELPMINVBULK) ? MCC_VBULKN : 0.0);
3237 fprintf(file,"vbulkp vbp 0 %gV\n",(MCC_VBULKP > ELPMINVBULK) ? MCC_VBULKP : MCC_VDDmax);
3238 fprintf(file,"vin s0 0 pwl(\n");
3239 for(t = 0.0 ; t < (5*(float)MCC_SLOPE) ; t += ((float)MCC_SLOPE/10.0))
3240 fprintf(file,"+%.5fNS %.5fV\n",t/1000.0,(float)stm_get_v(t,0.2,0,MCC_VDDmax,MCC_SLOPE)) ;
3241 fprintf(file,"+)\n") ;
3242
3243 fprintf(file,".option tnom=%g\n", V_FLOAT_TAB[__SIM_TNOM].VALUE);
3244 fprintf(file,".temp %g\n",MCC_TEMP) ;
3245 fprintf(file,".tran %gn %gn\n",V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE*1e9,V_FLOAT_TAB[ __SIM_TIME ].VALUE*1e9) ;
3246 if ( V_BOOL_TAB[__SIM_USE_PRINT].VALUE )
3247 {
3248 for(i = 0 ; i < MCC_INSNUMB + 1 ; i++)
3249 fprintf(file,".print tran v(s%d)\n",i) ;
3250 }
3251 if ( V_BOOL_TAB[__SIM_USE_MEAS].VALUE )
3252 mcc_add_print_meas (file,filename);
3253 if ( V_INT_TAB[__SIM_TOOL].VALUE == SIM_TOOL_TITAN || V_INT_TAB[__SIM_TOOL].VALUE == SIM_TOOL_TITAN7)
3254 fprintf(file,".save %s\n",basename);
3255 fprintf(file,".end\n");
3256 }
3257 }
3258
3259 void mcc_genspi(fit,lotrsparam_n,lotrsparam_p)
3260 int fit ;
3261 elp_lotrs_param *lotrsparam_n;
3262 elp_lotrs_param *lotrsparam_p;
3263 {
3264 FILE *file ;
3265 int i ;
3266 char *subcktmodeln, *subcktmodelp ;
3267 char *modeln, *modelp, *name ;
3268 char *mn, *mp ;
3269 char bufn[1024] ;
3270 char bufp[1024], buf[1024] ;
3271 int bs3 = 0,
3272 bs4 = 0;
3273 float vgsn, vgsp;
3274
3275 bs3 = ( MCC_SPICEMODELTYPE == MCC_BSIM3V3 ? 1 : 0 ) ;
3276 bs4 = ( MCC_SPICEMODELTYPE == MCC_BSIM4 ? 1 : 0 ) ;
3277 modeln = MCC_TNMODEL ;
3278 modelp = MCC_TPMODEL ;
3279 sprintf(bufn,"m") ;
3280 sprintf(bufp,"m") ;
3281
3282 subcktmodeln = mcc_getsubckt( MCC_MODELFILE,
3283 MCC_TNMODEL,
3284 MCC_NMOS,
3285 MCC_NCASE,
3286 MCC_LN*1.0e-6,
3287 MCC_WN*1.0e-6
3288 ) ;
3289 subcktmodelp = mcc_getsubckt( MCC_MODELFILE,
3290 MCC_TPMODEL,
3291 MCC_PMOS,
3292 MCC_PCASE,
3293 MCC_LP*1.0e-6,
3294 MCC_WP*1.0e-6
3295 ) ;
3296
3297 if (subcktmodeln != NULL) /*- le model est dans un subckt -*/
3298 {
3299 sprintf(bufn,"xm") ;
3300 modeln = subcktmodeln ;
3301 }
3302
3303 if (subcktmodelp != NULL) /*- le model est dans un subckt -*/
3304 {
3305 sprintf(bufp,"xm") ;
3306 modelp = subcktmodelp ;
3307 }
3308 mn = mbkstrdup(bufn) ;
3309 mp = mbkstrdup(bufp) ;
3310
3311 if(MCC_CALC_CUR == MCC_SIM_MODE)
3312 {
3313 name=mcc_debug_prefix(MCC_SPICEFILE[MCC_PARAM]);
3314 file = mcc_fopen(name,"w") ;
3315 avt_printExecInfo(file, "*", "", "");
3316
3317 mcc_get_np_vgs(&vgsn, &vgsp);
3318
3319 fprintf(file,"* TAS PARAMETRISATION\n");
3320 fprintf(file,"\n");
3321 if(MCC_SPICEOPTIONS != NULL)
3322 fprintf(file,".option %s\n",MCC_SPICEOPTIONS);
3323 if (V_INT_TAB[__SIM_TOOL].VALUE==SIM_TOOL_HSPICE)
3324 fprintf(file,".option INGOLD=1\n");
3325 if (V_INT_TAB[__SIM_TOOL].VALUE==SIM_TOOL_NGSPICE)
3326 fprintf(file,".include %s\n",MCC_TECHFILE);
3327 else
3328 fprintf(file,".include \"%s\"\n",MCC_TECHFILE);
3329 fprintf(file,"\n");
3330
3331 fprintf(file,"%sn1 11 2 0 vbn %s l=%gu w=%gu %s\n",
3332 mn,modeln,MCC_LN,MCC_WN,surf_string_n);
3333 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
3334 fprintf(file,"%sn2 22 vdd 0 vbn %s l=%gu w=%gu %s\n",
3335 mn,modeln,MCC_LN,MCC_WN,surf_string_n);
3336 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
3337 // if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
3338 {
3339 fprintf(file,"%sn3 222 vgsn 0 vbn %s l=%gu w=%gu %s\n",
3340 mn,modeln,MCC_LN,MCC_WN,surf_string_n);
3341 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
3342 }
3343 fprintf(file,"%sp1 10 3 vdd vbp %s l=%gu w=%gu %s\n",
3344 mp,modelp,MCC_LP,MCC_WP,surf_string_p);
3345 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
3346 fprintf(file,"%sp2 33 0 vdd vbp %s l=%gu w=%gu %s\n",
3347 mp,modelp,MCC_LP,MCC_WP,surf_string_p);
3348 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
3349 // if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
3350 {
3351 fprintf(file,"%sp3 333 vgsp vdd vbp %s l=%gu w=%gu %s\n",
3352 mp,modelp,MCC_LP,MCC_WP,surf_string_p);
3353 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
3354 }
3355 fprintf(file,"\n");
3356 fprintf(file,"%spassn vdd vdd vdddeg vbn %s l=%gu w=%gu %s\n",
3357 mn,modeln,MCC_LN,MCC_WN,surf_string_n);
3358 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
3359 fprintf(file,"%spassp 0 0 vssdeg vbp %s l=%gu w=%gu %s\n",
3360 mp,modelp,MCC_LP,MCC_WP,surf_string_p);
3361 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
3362
3363 mbkfree(mn) ;
3364 mbkfree(mp) ;
3365 fprintf(file,"rvdddeg vdddeg 0 1e9\n");
3366 fprintf(file,"rvssdeg vssdeg vdd 1e9\n");
3367 fprintf(file,"\n");
3368 fprintf(file,"vddmax vdd 0 dc %gv\n",MCC_VDDmax);
3369 fprintf(file,"vbulkn vbn 0 %gv\n",(MCC_VBULKN > ELPMINVBULK) ? MCC_VBULKN : 0.0);
3370 fprintf(file,"vbulkp vbp 0 %gv\n",(MCC_VBULKP > ELPMINVBULK) ? MCC_VBULKP : MCC_VDDmax);
3371 // if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
3372 {
3373 fprintf(file,"vgsnmax vgsn 0 dc %gv\n",vgsn);
3374 fprintf(file,"vgspmax vdd vgsp dc %gv\n",vgsp);
3375 }
3376 fprintf(file,"var 2 0 dc 0\n");
3377 fprintf(file,"ep vdd 3 2 0 1\n");
3378 fprintf(file,"vdnsat vdd 11 dc 0\n");
3379 fprintf(file,"vdnres 2 22 dc 0\n");
3380 fprintf(file,"vdpsat 0 10 dc 0\n");
3381 fprintf(file,"vdpres 3 33 dc 0\n");
3382 // if(mcc_ftol(MCC_VGS * 1000.0) != mcc_ftol(MCC_VDDmax * 1000.0))
3383 {
3384 fprintf(file,"vdnvgs 2 222 dc 0\n");
3385 fprintf(file,"vdpvgs 3 333 dc 0\n");
3386 }
3387 fprintf(file,"\n");
3388 fprintf(file,".option tnom=%g\n", V_FLOAT_TAB[__SIM_TNOM].VALUE);
3389 fprintf(file,".temp %g\n",MCC_TEMP);
3390 fprintf(file,".dc var 0 %g %g\n",MCC_VDDmax,MCC_DC_STEP);
3391 fprintf(file,".print dc i(vdnsat)\n" );
3392 fprintf(file,".print dc i(vdnres)\n" );
3393 fprintf(file,".print dc i(vdnvgs)\n" );
3394 fprintf(file,".print dc i(vdpsat)\n" );
3395 fprintf(file,".print dc i(vdpres)\n" );
3396 fprintf(file,".print dc i(vdpvgs)\n" );
3397 fprintf(file,".print dc v(vdddeg)\n" );
3398 fprintf(file,".print dc v(vssdeg)\n" );
3399 fprintf(file,"\n");
3400 if ( V_INT_TAB[__SIM_TOOL].VALUE == SIM_TOOL_TITAN || V_INT_TAB[__SIM_TOOL].VALUE == SIM_TOOL_TITAN7)
3401 {
3402 char *c;
3403 strcpy(buf,name);
3404 if ((c=strrchr(buf,'.'))!=NULL) *c='\0';
3405 fprintf(file,".save %s\n", buf);
3406 }
3407 fprintf(file,".end\n");
3408
3409 mcc_fclose(file,name);
3410 }
3411
3412 if(fit == 0)
3413 return ;
3414 /*
3415 for(i = 0 ; i < MCC_TASNB ; i++)
3416 {
3417 name=mcc_debug_prefix(MCC_TASFILE[i]);
3418 file = mcc_fopen(name,"w");
3419 mcc_genspicom(file,name,lotrsparam_n,lotrsparam_p) ;
3420 mcc_fclose(file,name);
3421 }
3422 */
3423 for(i = 0 ; i < MCC_SPICENB - 1 ; i++)
3424 {
3425 name=mcc_debug_prefix(MCC_SPICEFILE[i]);
3426 file = mcc_fopen(name,"w");
3427 avt_printExecInfo(file, "*", "", "");
3428 mcc_genspicom(file,name,lotrsparam_n,lotrsparam_p) ;
3429 mcc_fclose(file,name);
3430 }
3431 }
3432
3433 void mcc_calcspicedelay(filename,namelist,start,vthr,vsthrl,vsthrh,tabres)
3434 char *filename ;
3435 chain_list *namelist ;
3436 double start ;
3437 double vthr ;
3438 double vsthrl ;
3439 double vsthrh ;
3440 double **tabres ;
3441 {
3442 chain_list *chain ;
3443 char *fileout ;
3444 int nbx ;
3445 int nby ;
3446 int i ;
3447 int j ;
3448 int type ;
3449 double **tab ;
3450 char *argv[1024] ;
3451 char *resfilename ;
3452 char *pt ;
3453 FILE *resfile;
3454 double total = 0.0;
3455
3456 nbx = 0 ;
3457 for(chain = namelist ; chain != NULL ; chain = chain->NEXT,nbx++)
3458 {
3459 argv[nbx] = (char*)chain->DATA ;
3460 }
3461
3462 nby = mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE / V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE) ;
3463 nby++ ;
3464
3465 tab = (double **)mbkalloc(nbx * sizeof(double *)) ;
3466
3467 for(i = 0 ; i < nbx ; i++)
3468 tab[i] = (double *)mbkalloc(nby *sizeof(double)) ;
3469
3470 sim_execspice(filename,0, MCC_SPICENAME, MCC_SPICESTRING, MCC_SPICESTDOUT) ;
3471 fileout = sim_getjoker(MCC_SPICEOUT,filename) ;
3472 sim_readspifiletab (fileout,argv,nbx,nby,tab,V_FLOAT_TAB[ __SIM_TIME ].VALUE,V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE) ;
3473
3474 resfilename = strdup(filename);
3475 pt = strchr(resfilename,'.');
3476 if (pt) *pt = '\0';
3477 if ((resfile = mbkfopen(resfilename,"dat",WRITE_TEXT)) != NULL )
3478 {
3479 avt_printExecInfo(resfile, "#", "", "");
3480 for(i = 0 , j = 0 ; i < nbx ; i++ , j+=2)
3481 {
3482 *tabres[j] = 0.0; //initialisation du delay
3483 *tabres[j+1] = 0.0; //initialisation du front
3484 start = sim_calcdelayslope(tab[i],nby,2,vthr,vsthrl,vsthrh,start,
3485 tabres[j],tabres[j+1],&type,V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE*1e9,NULL,NULL) ;
3486 //printf("==> tp( %s ) = %g pS\n",argv[i],start*1000.0);
3487 }
3488
3489 fprintf(resfile,"# Data extracted from %s\n\n",fileout);
3490
3491 for(i = 0 , j = 0 ; i < nbx ; i++ , j+=2)
3492 {
3493 total += *tabres[j];
3494 fprintf(resfile,"Signal %s :\n",argv[i]);
3495 fprintf(resfile,"------\n");
3496 fprintf(resfile,"* slope = %8g pS\n",*tabres[j+1]*1000.0);
3497 fprintf(resfile,"* delay = %8g pS\n",*tabres[j]*1000.0);
3498 fprintf(resfile,"* total delay = %8g pS\n",total*1000.0);
3499 fprintf(resfile,"\n");
3500 }
3501 }
3502 else
3503 {
3504 fprintf(stderr, "\nmcc error: can't open file %s.dat\n",resfilename);
3505 EXIT(1);
3506 }
3507
3508 fclose(resfile);
3509 mbkfree(resfilename) ;
3510 mbkfree(fileout) ;
3511 for(i = 0 ; i < nbx ; i++)
3512 mbkfree(tab[i]) ;
3513 mbkfree(tab) ;
3514 }
3515
3516 int mcc_modeltype_known ( int modeltype )
3517 {
3518 int res = 0;
3519
3520 switch ( modeltype ) {
3521 case MCC_BSIM3V3 :
3522 case MCC_BSIM4 :
3523 case MCC_MPSP :
3524 case MCC_MPSPB :
3525 case MCC_EXTMOD :
3526 res = 1;
3527 break;
3528 default : res = 0;
3529 break;
3530 }
3531 return res;
3532 }
3533
3534 void mcc_genparam(modelname,type,l,w,vdd,lotrs,lotrscase,lotrsparam)
3535 char *modelname ;
3536 int type ;
3537 double l ;
3538 double w ;
3539 double vdd ;
3540 int lotrscase;
3541 lotrs_list *lotrs;
3542 elp_lotrs_param *lotrsparam;
3543 {
3544 double vbs=0.0;
3545 double lscale = 0.0, wscale = 0.0 ;
3546 elp_lotrs_param *lotrsparam_n = NULL, *lotrsparam_p = NULL;
3547 //int lotrs_unused = 0;
3548 mcc_modellist *model = NULL;
3549 static int driveall = 1;
3550 alim_list *power;
3551 double Weffcj;
3552 long pd_s,xd_s,ps_s,xs_s;
3553 double v1,v2;
3554 float vsource;
3555 double vbulkn, vbulkp;
3556 char vbulkfixed=0;
3557 mcc_corner_info info;
3558 ptype_list *pt;
3559
3560
3561 mcc_update_technoparams (modelname,type,l,w,lotrs,lotrscase);
3562
3563 switch ( lotrscase ) {
3564 case MCC_BEST : MCC_VDDmax = MCC_VDD_BEST;
3565 MCC_TEMP = MCC_TEMP_BEST;
3566 break;
3567 case MCC_WORST : MCC_VDDmax = MCC_VDD_WORST;
3568 MCC_TEMP = MCC_TEMP_WORST;
3569 break;
3570 default : MCC_VDDmax = vdd;
3571 break;
3572 }
3573 MCC_VGS = MCC_VDDmax/2.0;
3574
3575 if(type == MCC_TRANS_N)
3576 {
3577 lscale = MCC_LN*1.0e-6 ;
3578 wscale = MCC_WN*1.0e-6 ;
3579 }
3580 else
3581 {
3582 lscale = MCC_LP*1.0e-6 ;
3583 wscale = MCC_WP*1.0e-6 ;
3584 }
3585
3586 MCC_CALC_CUR = MCC_CALC_MODE ;
3587
3588 if((model = mcc_getmodel(MCC_MODELFILE,modelname,type,lotrscase,
3589 lscale,wscale,1))) {
3590 model->USER = addptype(model->USER, MCC_MODEL_LOTRS, lotrs);
3591 if (mbk_istranscrypt(model->NAME)) avt_set_encrypted_mode(1);
3592 if ( avt_islog (1,LOGMCC )) {
3593 avt_log(LOGMCC,1,"Associated Model in technofile : ");
3594 avt_log(LOGMCC,1,"%s",model->NAME);
3595 avt_log(LOGMCC,1," %s\n",(type == MCC_TRANS_N) ? "NMOS":"PMOS");
3596 if ( model->SUBCKTNAME )
3597 avt_log(LOGMCC,1,"SubcktName : %s\n",model->SUBCKTNAME);
3598
3599 }
3600 if ( lotrsparam ) {
3601 if(type == MCC_TRANS_N) {
3602 lotrsparam_n = elp_lotrs_param_dup ( lotrsparam );
3603 if ( lotrsparam_n->VBULK < ELPMINVBULK )
3604 lotrsparam_n->VBULK = 0.0;
3605 lotrsparam_p = mcc_init_lotrsparam ();
3606 lotrsparam_p->VBULK = MCC_VDDmax;
3607 }
3608 else {
3609 lotrsparam_p = elp_lotrs_param_dup ( lotrsparam );
3610 if ( lotrsparam_p->VBULK < ELPMINVBULK || lotrscase != MCC_TYPICAL )
3611 lotrsparam_p->VBULK = MCC_VDDmax;
3612 lotrsparam_n = mcc_init_lotrsparam ();
3613 lotrsparam_n->VBULK = 0.0;
3614 }
3615 }
3616 else {
3617 lotrsparam_n = mcc_init_lotrsparam ();
3618 lotrsparam_p = mcc_init_lotrsparam ();
3619 lotrsparam_n->VBULK = 0.0;
3620 lotrsparam_p->VBULK = MCC_VDDmax;
3621 }
3622
3623 lotrsparam_p->SUBCKTNAME=NULL;
3624 lotrsparam_n->SUBCKTNAME=NULL;
3625
3626 if ( lotrs ) {
3627 if(type == MCC_TRANS_N) {
3628 if ( lotrs->SOURCE && getlosigalim (lotrs->SOURCE->SIG, &vsource))
3629 vbs = lotrsparam_n->VBULK - vsource;
3630 else if ( (power = cns_get_lotrs_multivoltage(lotrs))!=NULL) {
3631 vsource = power->VSSMIN;
3632 vbs = lotrsparam_n->VBULK - vsource;
3633 }
3634 else
3635 vbs = lotrsparam_n->VBULK;
3636 lotrsparam_n->VBS=vbs;
3637 lotrsparam_n->ISVBSSET=1;
3638 if ((pt=getptype(lotrs->USER, TRANS_FIGURE))!=NULL) lotrsparam_n->SUBCKTNAME=(char *)pt->DATA;
3639 }
3640 else {
3641 if ( lotrs->SOURCE && getlosigalim (lotrs->SOURCE->SIG, &vsource))
3642 vbs = lotrsparam_p->VBULK - vsource;
3643 else if ( cns_getlotrsalim (lotrs, 'M', &vsource))
3644 vbs = lotrsparam_p->VBULK - vsource;
3645 else
3646 vbs = lotrsparam_p->VBULK - MCC_VDDmax;
3647 lotrsparam_n->VBS=vbs;
3648 lotrsparam_n->ISVBSSET=1;
3649 if ((pt=getptype(lotrs->USER, TRANS_FIGURE))!=NULL) lotrsparam_p->SUBCKTNAME=(char *)pt->DATA;
3650 }
3651 }
3652 /*
3653 if ( (getptype (lotrs->USER,CNS_UNUSED)) ) {
3654 vbs = 0.0; // to avoid error while cheking vbs for an unused lotrs
3655 lotrs_unused = 1;
3656 }
3657 */
3658 avt_log(LOGMCC,1,"Automatic Characterization for temp=%g vdd=%g vbs=%g\n",MCC_TEMP,MCC_VDDmax,vbs);
3659 if ( mcc_check_vbs (model,l,w,vbs) == 0 ) {
3660
3661 vbulkfixed = 1 ;
3662 vbulkn = lotrsparam_n->VBULK ;
3663 vbulkp = lotrsparam_p->VBULK ;
3664
3665 lotrsparam_n->VBULK = 0.0 ;
3666 lotrsparam_p->VBULK = MCC_VDDmax ;
3667 lotrsparam_n->ISVBSSET = 0.0 ;
3668 lotrsparam_p->ISVBSSET = 0.0 ;
3669 avt_errmsg(MCC_ERRMSG, "001", AVT_WARNING);
3670 }
3671
3672 mcc_calcspiparam(type,lotrsparam_n,lotrsparam_p) ;
3673
3674 //if ( !lotrs_unused ) {
3675 if ( mcc_check_param (type) ) {
3676 if ((mcc_modeltype_known ( model->MODELTYPE ))) {
3677 mcc_allocspidata(type) ;
3678 if ( !MCC_OPTIM_MODE )
3679 mcc_addspidata(type,lotrsparam_n,lotrsparam_p) ;
3680 else
3681 mcc_optim_addspidata(type,lotrsparam_n,lotrsparam_p) ;
3682 mcc_trs_corner( type, lotrsparam_n, lotrsparam_p, &info );
3683 if( V_BOOL_TAB[ __MCC_NEW_IDS_SAT ].VALUE ) {
3684 switch( type ) {
3685 case MCC_TRANS_N :
3686 mcc_calcul_sat_parameter( MCC_TRANS_N, lotrsparam_n, &info );
3687 break ;
3688 case MCC_TRANS_P :
3689 mcc_calcul_sat_parameter( MCC_TRANS_P, lotrsparam_p, &info );
3690 break ;
3691 default :
3692 mcc_calcul_sat_parameter( MCC_TRANS_N, lotrsparam_n, &info );
3693 mcc_calcul_sat_parameter( MCC_TRANS_P, lotrsparam_p, &info );
3694 }
3695 }
3696 else {
3697 mcc_calcul_vt(type,lotrsparam_n,lotrsparam_p, &info) ;
3698 if ( type == MCC_TRANS_N )
3699 v1 = (MCC_VDDmax-MCC_VTN)/2.0 + MCC_VTN;
3700 else
3701 v1 = (MCC_VDDmax-MCC_VTP)/2.0 + MCC_VTP;
3702 v2 = MCC_VDDmax;
3703 if ( MCC_NEW_CALC_ABR && MCC_OPTIM_MODE )
3704 mcc_get_best_abr_from_vt ( type, lotrsparam_n,lotrsparam_p, &info );
3705 else
3706 mcc_calcul_abr(type,v1,v2,lotrsparam_n,lotrsparam_p) ;
3707 }
3708
3709 if( V_BOOL_TAB[__AVT_RST_BETTER].VALUE ) {
3710 mcc_calcul_rst_better(type,lotrsparam_n,lotrsparam_p, &info );
3711 }
3712 else {
3713 mcc_calcul_rst(type,lotrsparam_n,lotrsparam_p);
3714 }
3715
3716 mcc_calcul_k(type,(type == MCC_TRANS_N) ? lotrsparam_n:lotrsparam_p) ;
3717 mcc_calcul_vdeg(type,lotrsparam_n,lotrsparam_p) ;
3718 mcc_calcul_vti(type,lotrsparam_n,lotrsparam_p) ;
3719 mcc_calcul_raccess(type,lotrsparam_n,lotrsparam_p);
3720 mcc_freespidata(0,type) ;
3721 }
3722 }
3723 //}
3724
3725 mcc_cleanmodel( model );
3726
3727 if ( V_BOOL_TAB[__ELP_DRV_FILE].VALUE )
3728 driveall = (ELP_MODEL_LIST == NULL) ? MCC_DRV_ALL_MODEL : MCC_DRV_ONE_MODEL;
3729 else
3730 driveall = MCC_DONOT_DRV_MODEL;
3731
3732 if( vbulkfixed ) {
3733 lotrsparam_n->VBULK = vbulkn ;
3734 lotrsparam_p->VBULK = vbulkp ;
3735 }
3736 mcc_drvelp(MCC_PARAM, type,lotrsparam_n,lotrsparam_p,driveall) ;
3737
3738 if ( avt_islog (2,LOGMCC )) {
3739 // update area and perimeters
3740 elpLotrsGetShrinkDim(MCC_CURRENT_LOTRS,NULL,NULL,&xs_s,
3741 &xd_s,&ps_s,&pd_s,NULL,NULL, lotrscase);
3742 if ( type == MCC_TRANS_N ) {
3743 Weffcj = MCC_WN*MCC_XWN+MCC_DWCJN;
3744 MCC_ADN = ((double)xd_s*Weffcj)/((double)(100.0*SCALE_X*SCALE_X));
3745 MCC_ASN = ((double)xs_s*Weffcj)/((double)(100.0*SCALE_X*SCALE_X));
3746 MCC_PDN = (double)pd_s/(double)SCALE_X;
3747 MCC_PSN = (double)ps_s/(double)SCALE_X;
3748 mcc_DisplayInfos (MCC_MODELFILE, MCC_TNMODEL,
3749 MCC_NMOS, MCC_NCASE, MCC_LN*1.0e-6, MCC_WN*1.0e-6,
3750 MCC_TEMP, MCC_VDDmax/2.0, 0.0, MCC_VDDmax/2.0,
3751 MCC_VDDmax,lotrsparam_n);
3752 }
3753 else {
3754 Weffcj = MCC_WP*MCC_XWP+MCC_DWCJP;
3755 MCC_ADP = ((double)xd_s*Weffcj)/((double)(100.0*SCALE_X*SCALE_X));
3756 MCC_ASP = ((double)xs_s*Weffcj)/((double)(100.0*SCALE_X*SCALE_X));
3757 MCC_PDP = (double)pd_s/(double)SCALE_X;
3758 MCC_PSP = (double)ps_s/(double)SCALE_X;
3759 mcc_DisplayInfos (MCC_MODELFILE, MCC_TPMODEL,
3760 MCC_PMOS, MCC_PCASE, MCC_LP*1.0e-6, MCC_WP*1.0e-6,
3761 MCC_TEMP, MCC_VDDmax/2.0, 0.0, MCC_VDDmax/2.0,
3762 MCC_VDDmax,lotrsparam_p);
3763 }
3764 }
3765 elp_lotrs_param_free ( lotrsparam_n );
3766 elp_lotrs_param_free ( lotrsparam_p );
3767 }
3768 MCC_NCASE = MCC_TYPICAL;
3769 MCC_PCASE = MCC_TYPICAL;
3770 MCC_CURRENT_LOTRS = NULL;
3771 model->USER = delptype(model->USER, MCC_MODEL_LOTRS);
3772 avt_set_encrypted_mode(0);
3773 }
3774
3775 void mcc_setelpparam ( void )
3776 {
3777 elpGeneral[elpTEMP] = MCC_TEMP ;
3778 elpGeneral[elpSLOPE] = MCC_SLOPE ;
3779 elpGeneral[elpGVDDMAX] = MCC_VDDmax ;
3780 elpGeneral[elpGVDDBEST] = MCC_VDD_BEST ;
3781 elpGeneral[elpGVDDWORST] = MCC_VDD_WORST ;
3782 elpGeneral[elpGDTHR] = MCC_VTH ;
3783 elpGeneral[elpGSHTHR] = MCC_VTH_HIGH ;
3784 elpGeneral[elpGSLTHR] = MCC_VTH_LOW ;
3785 }
3786
3787 /****************************************************************************\
3788 * Function : mcc_get_best_abr_from_vt
3789 \****************************************************************************/
3790 double mcc_get_new_best_abr_from_vt ( int type,
3791 elp_lotrs_param *lotrsparam_n,
3792 elp_lotrs_param *lotrsparam_p,
3793 mcc_corner_info *info
3794 )
3795 {
3796 double vt ;
3797 double vstep ;
3798 double *pt_a ;
3799 double *pt_b ;
3800 double *pt_rs ;
3801 double *pt_rt ;
3802 double error ;
3803 double minerror ;
3804 double v ;
3805 double best_a ;
3806 double best_b ;
3807 double best_rs ;
3808 double best_rt ;
3809 mbk_pwl *pwl ;
3810
3811 if( type == MCC_TRANS_N ) {
3812 vt = MCC_VTN ;
3813 pwl = MCC_OPTIM_IDNSAT ;
3814 pt_a = & MCC_AN ;
3815 pt_b = & MCC_BN ;
3816 pt_rs = & MCC_RNS ;
3817 pt_rt = & MCC_RNT ;
3818 }
3819 else {
3820 vt = MCC_VTP ;
3821 pwl = MCC_OPTIM_IDPSAT ;
3822 pt_a = & MCC_AP ;
3823 pt_b = & MCC_BP ;
3824 pt_rs = & MCC_RPS ;
3825 pt_rt = & MCC_RPT ;
3826 }
3827
3828 vstep = (MCC_VDDmax - vt )/100.0 ;
3829 minerror = FLT_MAX ;
3830
3831 for( v = vt+vstep ; v < MCC_VDDmax ; v = v + vstep ) {
3832
3833 mcc_calcul_abr( type, v, MCC_VDDmax, lotrsparam_n, lotrsparam_p );
3834
3835 if( V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B ].VALUE ) {
3836 if( *pt_b <= -1.0/(MCC_VDDmax-vt) )
3837 error = FLT_MAX ;
3838 else
3839 error = mcc_calcdiffmodelsat( vt, MCC_VDDmax, type, lotrsparam_n, -1.0, info );
3840 }
3841 else
3842 error = mcc_calcdiffmodelsat( vt, MCC_VDDmax, type, lotrsparam_n, -1.0, info );
3843 if( error <= minerror ) {
3844 best_a = *pt_a ;
3845 best_b = *pt_b ;
3846 best_rs = *pt_rs ;
3847 best_rt = *pt_rt ;
3848 minerror = error;
3849 }
3850 }
3851
3852 *pt_a = best_a;
3853 *pt_b = best_b;
3854 *pt_rs = best_rs;
3855 *pt_rt = best_rt;
3856
3857 return minerror ;
3858 }
3859
3860 double mcc_get_best_abr_from_vt ( int type,
3861 elp_lotrs_param *lotrsparam_n,
3862 elp_lotrs_param *lotrsparam_p,
3863 mcc_corner_info *info
3864 )
3865 {
3866 double olderror = FLT_MAX , error = FLT_MAX ;
3867 double best_v1,nbpoints;
3868 double v1, v2 = MCC_VDDmax;
3869 double best_a,best_b,best_rs,best_rt;
3870 int i;
3871 int best_i;
3872 double exitvalue=-1, step=FLT_MAX, cnt=0;
3873
3874 if( V_BOOL_TAB[ __MCC_NEW_BEST_ABR ].VALUE )
3875 return mcc_get_new_best_abr_from_vt( type, lotrsparam_n, lotrsparam_p, info );
3876
3877 if (type == MCC_TRANS_N) {
3878 nbpoints = MCC_OPTIM_IDNSAT->N;
3879 for ( i = 0 ; i < nbpoints ; i++ ) {
3880 v1 = MCC_OPTIM_IDNSAT->DATA[i].X0;
3881 if( V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B ].VALUE ) {
3882 if( v1 < MCC_VTN )
3883 continue ;
3884 }
3885 #ifdef OPTIM2
3886 if( v1 <= MCC_VTN )
3887 continue ;
3888 #ifdef OPTIM3
3889 if (step==FLT_MAX)
3890 {
3891 if (nbpoints-i-1<OPTIM3) step=1;
3892 else step=OPTIM3/(nbpoints-i-1);
3893 }
3894 cnt+=step;
3895 if (cnt<1) continue;
3896 cnt--;
3897 #endif
3898 #endif
3899 mcc_calcul_abr(type,v1,v2,lotrsparam_n,lotrsparam_p) ;
3900 if( V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B ].VALUE ) {
3901 if( MCC_BN <= -1.0/(MCC_VDDmax-MCC_VTN) )
3902 error = FLT_MAX ;
3903 else
3904 error = mcc_calcdiffmodelsat(MCC_VTN,MCC_VDDmax,type,lotrsparam_n,exitvalue, info) ;
3905 }
3906 else
3907 error = mcc_calcdiffmodelsat(MCC_VTN,MCC_VDDmax,type,lotrsparam_n,exitvalue, info) ;
3908 if ( error <= olderror ) {
3909 best_a = MCC_AN;
3910 best_b = MCC_BN;
3911 best_rs = MCC_RNS;
3912 best_rt = MCC_RNT;
3913 best_v1 = v1;
3914 olderror = error;
3915 best_i = i ;
3916 #ifdef OPTIM1
3917 exitvalue=error;
3918 #endif
3919 }
3920 }
3921 MCC_AN = best_a;
3922 MCC_BN = best_b;
3923 MCC_RNS = best_rs;
3924 MCC_RNT = best_rt;
3925 }
3926 else {
3927 nbpoints = MCC_OPTIM_IDPSAT->N;
3928 for ( i = 0 ; i < nbpoints ; i++ ) {
3929 v1 = MCC_OPTIM_IDPSAT->DATA[i].X0;
3930 if( V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B ].VALUE ) {
3931 if( v1 < MCC_VTP )
3932 continue ;
3933 }
3934 #ifdef OPTIM2
3935 if( v1 <= MCC_VTP )
3936 continue ;
3937 #ifdef OPTIM3
3938 if (step==FLT_MAX)
3939 {
3940 if (nbpoints-i-1<OPTIM3) step=1;
3941 else step=OPTIM3/(nbpoints-i-1);
3942 }
3943 cnt+=step;
3944 if (cnt<1) continue;
3945 cnt--;
3946 #endif
3947 #endif
3948 mcc_calcul_abr(type,v1,v2,lotrsparam_n,lotrsparam_p) ;
3949 if( V_BOOL_TAB[ __MCC_ALLOW_NEGATIVE_B ].VALUE ) {
3950 if( MCC_BP <= -1.0/(MCC_VDDmax-MCC_VTP) )
3951 error = FLT_MAX ;
3952 else
3953 error = mcc_calcdiffmodelsat(MCC_VTP,MCC_VDDmax,type,lotrsparam_p,exitvalue, info) ;
3954 }
3955 else
3956 error = mcc_calcdiffmodelsat(MCC_VTP,MCC_VDDmax,type,lotrsparam_p,exitvalue, info) ;
3957 if ( error <= olderror ) {
3958 best_a = MCC_AP;
3959 best_b = MCC_BP;
3960 best_rs = MCC_RPS;
3961 best_rt = MCC_RPT;
3962 best_v1 = v1;
3963 olderror = error;
3964 #ifdef OPTIM1
3965 exitvalue=error;
3966 #endif
3967 }
3968 }
3969 MCC_AP = best_a;
3970 MCC_BP = best_b;
3971 MCC_RPS = best_rs;
3972 MCC_RPT = best_rt;
3973 }
3974 #ifndef BUGERROR
3975 return olderror;
3976 #else
3977 return error;
3978 #endif
3979 }
3980
3981
3982 void mcc_update_technoparams (char *modelname,int type, double l, double w,lotrs_list *lotrs,int lotrscase)
3983 {
3984 mcc_modellist *model=NULL;
3985 ptype_list *ptype;
3986
3987 // Si le fichier techno (spice) est le nom par defaut cad que l utilisateur
3988 // ne veut pas utiliser de fichier techno, et qu'il n existe pas de modele
3989 // mcc associe a un eventuel fichier techno inclus par une netlist spice
3990 // alors on ne genere aucun parametre.
3991 if ( !mcc_gettechno(MCC_MODELFILE) &&
3992 (avt_is_default_technoname(MCC_MODELFILE)) )
3993 return;
3994 if((l <= 0.0) || (w <= 0.0))
3995 {
3996 avt_errmsg(MCC_ERRMSG, "002", AVT_ERROR, modelname,mcc_ftol(l*1e03),mcc_ftol(w*1e03));
3997 return;
3998 }
3999
4000 mcc_init_globals ();
4001
4002 MCC_CURRENT_LOTRS = lotrs;
4003
4004 if ( avt_islog (1,LOGMCC ))
4005 {
4006 avt_log(LOGMCC,1,"-----------------------\n");
4007 if ( MCC_CURRENT_LOTRS->TRNAME )
4008 avt_log(LOGMCC,1,"TRNAME : %s ",MCC_CURRENT_LOTRS->TRNAME);
4009 if ( (ptype = getptype ( MCC_CURRENT_LOTRS->USER, TRANS_FIGURE )) )
4010 avt_log(LOGMCC,1," TRANS FIGURE : %s ", (char*)ptype->DATA);
4011 avt_log(LOGMCC,1,"(L=%gu, ",(double)MCC_CURRENT_LOTRS->LENGTH/(double)SCALE_X);
4012 avt_log(LOGMCC,1,"W=%gu)\n",(double)MCC_CURRENT_LOTRS->WIDTH /(double)SCALE_X);
4013 }
4014
4015 if(elpTechnoFile)
4016 {
4017 mbkfree(MCC_ELPFILE);
4018 MCC_ELPFILE = mbkstrdup(elpTechnoFile) ;
4019 }
4020
4021 if(type == MCC_TRANS_N)
4022 {
4023 if((l > 0.0) && (w > 0.0))
4024 {
4025 MCC_NCASE = lotrscase;
4026 MCC_LN = l ;
4027 MCC_WN = w ;
4028 if(MCC_TNMODEL != NULL)
4029 {
4030 if(strcmp(MCC_TNMODEL,modelname) != 0)
4031 {
4032 mbkfree(MCC_TNMODEL) ;
4033 MCC_TNMODEL = mcc_initstr(modelname) ;
4034 }
4035 }
4036 else
4037 {
4038 MCC_TNMODEL = mcc_initstr(modelname) ;
4039 }
4040 }
4041 else
4042 {
4043 MCC_LN = MCC_TECSIZE ;
4044 MCC_WN = MCC_TECSIZE*6.0 ;
4045 if ((model = mcc_getmodel(MCC_MODELFILE,NULL,type,MCC_NCASE,MCC_LN*1.0e-6,MCC_WN*1.0e-6,0)))
4046 MCC_TNMODEL = mbkstrdup(mcc_cutname (model->NAME));
4047 }
4048 }
4049 else
4050 {
4051 if((l > 0.0) && (w > 0.0))
4052 {
4053 MCC_PCASE = lotrscase;
4054 MCC_LP = l ;
4055 MCC_WP = w ;
4056 if(MCC_TPMODEL != NULL)
4057 {
4058 if(strcmp(MCC_TPMODEL,modelname) != 0)
4059 {
4060 mbkfree(MCC_TPMODEL) ;
4061 MCC_TPMODEL = mcc_initstr(modelname) ;
4062 }
4063 }
4064 else
4065 {
4066 MCC_TPMODEL = mcc_initstr(modelname) ;
4067 }
4068 }
4069 else
4070 {
4071 MCC_LP = MCC_TECSIZE ;
4072 MCC_WP = MCC_TECSIZE*12.0 ;
4073 if ((model = mcc_getmodel(MCC_MODELFILE,NULL,type,MCC_PCASE,MCC_LP*1.0e-6,MCC_WP*1.0e-6,0)))
4074 MCC_SPICEMODELTYPE = model->MODELTYPE;
4075 MCC_TPMODEL = mbkstrdup(mcc_cutname (model->NAME));
4076 }
4077 }
4078 }
4079
4080 /*****************************************************************************************\
4081 * FUNC mcc_calcIleakage_from_lotrs
4082 \*****************************************************************************************/
4083 double mcc_calcIleakage_from_lotrs (char *modelname,int type, double l, double w,
4084 lotrs_list *lotrs, int lotrscase,
4085 double vgs,double vds,double vbs,
4086 double AD,double PD,double AS, double PS,
4087 double *BLeak,double *DLeak,double *SLeak,
4088 elp_lotrs_param *lotrsparam)
4089 {
4090 double lscale,wscale;
4091 double Ileak = 0.0;
4092
4093 if ( lotrs ) {
4094 lscale = l*1.0e-6;
4095 wscale = w*1.0e-6;
4096
4097 Ileak = mcc_calcILeakage (MCC_MODELFILE, modelname,
4098 type, lotrscase,
4099 vbs, vds, vgs,
4100 lscale, wscale, MCC_TEMP,
4101 AD, PD, AS, PS,
4102 BLeak,DLeak,SLeak,
4103 lotrsparam);
4104 }
4105 if ( avt_islog (2,LOGMCC ))
4106 {
4107 avt_log(LOGMCC,2," ITotal leak = %g (vgs=%g,vds=%g,vbs=%g)\n",
4108 Ileak,vgs,vds,vbs);
4109 if ( BLeak )
4110 avt_log(LOGMCC,2," B leak = %g (vgs=%g,vds=%g,vbs=%g)\n",
4111 *BLeak,vgs,vds,vbs);
4112 if ( DLeak )
4113 avt_log(LOGMCC,2," D leak = %g (vgs=%g,vds=%g,vbs=%g)\n",
4114 *DLeak,vgs,vds,vbs);
4115 if ( SLeak )
4116 avt_log(LOGMCC,2," S leak = %g (vgs=%g,vds=%g,vbs=%g)\n",
4117 *SLeak,vgs,vds,vbs);
4118 }
4119 return Ileak;
4120 }
4121
4122
4123
4124
4125 void mcc_genspi_for_inverter_simulator(elp_lotrs_param *lotrsparam_n,elp_lotrs_param *lotrsparam_p)
4126 {
4127 FILE *file ;
4128 int i, j, k ;
4129 char *subcktmodeln, *subcktmodelp, *fileout ;
4130 char *modeln, *modelp, *name ;
4131 char *mn, *mp, *c, *dir ;
4132 char bufn[1024] ;
4133 char bufp[1024], buf[1024], tbuf[1024] ;
4134 int bs3 = 0, bs4 = 0, nbdata=2;
4135 char *argv[]={"i", "sig"};
4136 float vgsn, vgsp, slope, t, t_vdd_sur_2, val;
4137 double **tab;
4138 mcc_modellist *ptmodel ;
4139 int maxl[2];
4140
4141 bs3 = ( MCC_SPICEMODELTYPE == MCC_BSIM3V3 ? 1 : 0 ) ;
4142 bs4 = ( MCC_SPICEMODELTYPE == MCC_BSIM4 ? 1 : 0 ) ;
4143 modeln = MCC_TNMODEL ;
4144 modelp = MCC_TPMODEL ;
4145 sprintf(bufn,"m") ;
4146 sprintf(bufp,"m") ;
4147
4148 ptmodel = mcc_getmodel ( MCC_MODELFILE,
4149 MCC_TPMODEL,
4150 MCC_PMOS,
4151 MCC_PCASE,
4152 MCC_LP*1.0e-6,
4153 MCC_WP*1.0e-6, 0);
4154 subcktmodeln = mcc_getsubckt( MCC_MODELFILE,
4155 MCC_TNMODEL,
4156 MCC_NMOS,
4157 MCC_NCASE,
4158 MCC_LN*1.0e-6,
4159 MCC_WN*1.0e-6
4160 ) ;
4161 subcktmodelp = mcc_getsubckt( MCC_MODELFILE,
4162 MCC_TPMODEL,
4163 MCC_PMOS,
4164 MCC_PCASE,
4165 MCC_LP*1.0e-6,
4166 MCC_WP*1.0e-6
4167 ) ;
4168
4169 if (subcktmodeln != NULL) /*- le model est dans un subckt -*/
4170 {
4171 sprintf(bufn,"xm") ;
4172 modeln = subcktmodeln ;
4173 }
4174
4175 if (subcktmodelp != NULL) /*- le model est dans un subckt -*/
4176 {
4177 sprintf(bufp,"xm") ;
4178 modelp = subcktmodelp ;
4179 }
4180 mn = mbkstrdup(bufn) ;
4181 mp = mbkstrdup(bufp) ;
4182
4183 sim_set_result_file_extension('p', 0, &MCC_SPICEOUT);
4184
4185 strcpy(bufn, "");
4186
4187 for (i=0; i<2; i++)
4188 {
4189 name=mbkstrdup(mcc_debug_prefix(i==0?"inverter_rf.spi":"inverter_fr.spi"));
4190 strcpy(buf,name);
4191 if ((c=strrchr(buf,'.'))!=NULL) *c='\0';
4192
4193 file = mcc_fopen(name,"w") ;
4194 avt_printExecInfo(file, "*", "", "");
4195 mcc_get_np_vgs(&vgsn, &vgsp);
4196
4197 fprintf(file,"* TAS PARAMETRISATION\n");
4198 fprintf(file,"\n");
4199 if(MCC_SPICEOPTIONS != NULL)
4200 fprintf(file,".option %s\n",MCC_SPICEOPTIONS);
4201 if (V_INT_TAB[__SIM_TOOL].VALUE==SIM_TOOL_HSPICE)
4202 fprintf(file,".option INGOLD=1\n");
4203 if (V_INT_TAB[__SIM_TOOL].VALUE==SIM_TOOL_NGSPICE)
4204 fprintf(file,".include %s\n",MCC_TECHFILE);
4205 else
4206 fprintf(file,".include \"%s\"\n",MCC_TECHFILE);
4207 fprintf(file,"\n");
4208
4209 fprintf(file,".subckt %s i sig o\n", buf);
4210 fprintf(file,"%sin1 sig i 0 vbn %s l=%gu w=%gu %s\n",
4211 mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4212 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4213
4214 fprintf(file,"%sip1 sig i vdd vbp %s l=%gu w=%gu %s\n",
4215 mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4216 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4217
4218 fprintf(file,"%sin2 o sig 0 vbn %s l=%gu w=%gu %s\n",
4219 mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4220 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4221
4222 fprintf(file,"%sip2 o sig vdd vbp %s l=%gu w=%gu %s\n",
4223 mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4224 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4225 fprintf(file,"c1 o 0 %gf\n",MCC_CAPA) ;
4226
4227 fprintf(file,"vddmax vdd 0 dc %gv\n",MCC_VDDmax);
4228 fprintf(file,"vbulkn vbn 0 %gv\n",(lotrsparam_n->VBULK > ELPMINVBULK) ? lotrsparam_n->VBULK : 0.0);
4229 fprintf(file,"vbulkp vbp 0 %gv\n",(lotrsparam_p->VBULK > ELPMINVBULK) ? lotrsparam_p->VBULK : MCC_VDDmax);
4230 fprintf(file,".ends\n");
4231
4232 fprintf(file,"\nxinst i sig o %s\n", buf);
4233 fprintf(file,"\n");
4234 fprintf(file,".option tnom=%g\n", V_FLOAT_TAB[__SIM_TNOM].VALUE);
4235 fprintf(file,".temp %g\n",MCC_TEMP);
4236
4237 #define RANGELIMIT 0.005
4238
4239 slope=MCC_SLOPE;
4240 fprintf(file,"vinput i 0 PWL(\n") ;
4241 for(t = 0.0 ; t < V_FLOAT_TAB[ __SIM_TIME ].VALUE*1e9*1000; t += ((float)slope/10.0))
4242 {
4243 fprintf(file,"+%.5fNS %.5fV\n",t/1000.0,val=(float)mcc_tanh_slope_tas(t,i==0?MCC_VTN:MCC_VTP,i==0?0:MCC_VDDmax,i==0?MCC_VDDmax:0,(float)slope)) ;
4244 if ((i==0 && val>MCC_VDDmax*(1-RANGELIMIT)) || (i==1 && val<MCC_VDDmax*RANGELIMIT)) break;
4245 }
4246 fprintf(file,"+)\n") ;
4247
4248 fprintf(file,".tran %gn %gn\n",V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE*1e9,V_FLOAT_TAB[ __SIM_TIME ].VALUE*1e9) ;
4249
4250 fprintf(file,".print tran v(i)\n");
4251 fprintf(file,".print tran v(sig)\n");
4252 fprintf(file,"\n");
4253 if ( V_INT_TAB[__SIM_TOOL].VALUE == SIM_TOOL_TITAN || V_INT_TAB[__SIM_TOOL].VALUE == SIM_TOOL_TITAN7)
4254 fprintf(file,".save %s\n", buf);
4255
4256 fprintf(file,".end\n");
4257
4258 mcc_fclose(file,name);
4259
4260 sim_execspice(name,0,MCC_SPICENAME,MCC_SPICESTRING,MCC_SPICESTDOUT);
4261
4262 fileout = sim_getjoker(MCC_SPICEOUT,buf) ;
4263
4264 tab = (double **)mbkalloc(nbdata * sizeof(double *)) ;
4265 for(j = 0 ; j < nbdata ; j++)
4266 tab[j] = (double *)mbkalloc((mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE/V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE)+1) *sizeof(double)) ;
4267
4268 sim_readspifiletab (fileout,argv,nbdata,mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE/V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE)+1,tab,V_FLOAT_TAB[ __SIM_TIME ].VALUE,V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE) ;
4269
4270 if (i==0)
4271 {
4272 for (j=0; j<mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE/V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE)+1 && tab[0][j]<MCC_VDDmax/2; j++) ;
4273 for (k=0; k<mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE/V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE)+1 && tab[1][k]>MCC_VDDmax*RANGELIMIT; k++) ;
4274 }
4275 else
4276 {
4277 for (j=0; j<mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE/V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE)+1 && tab[0][j]>MCC_VDDmax/2; j++) ;
4278 for (k=0; k<mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE/V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE)+1 && tab[1][k]<MCC_VDDmax*(1-RANGELIMIT); k++) ;
4279 }
4280
4281 t_vdd_sur_2=(j-1)*V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE*1e9;
4282 t_vdd_sur_2+=((MCC_VDDmax/2-tab[0][j-1])/(tab[0][j]-tab[0][j-1]))*V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE*1e9;
4283
4284 if (i==0) sprintf(bufp," t0r=%g", t_vdd_sur_2*1e-9);
4285 else sprintf(bufp," t0f=%g", t_vdd_sur_2*1e-9);
4286 strcat(bufn, bufp);
4287 // printf("vdd/2: %g\n", t_vdd_sur_2);
4288
4289 sprintf(bufp,"%s.spice.dat", buf);
4290 file = mcc_fopen(bufp,"w") ;
4291 avt_printExecInfo(file, "#", "", "");
4292 fprintf(file,"#time\t\tv(i)\t\tv(sig)\n");
4293 TRS_CURVS.nbdyna = mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE/V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE)+1 ;
4294 for (j=0; j<2; j++)
4295 TRS_CURVS.SIMUINV[i][j]=(double *)mbkalloc(sizeof(double)*TRS_CURVS.nbdyna);
4296
4297 for (j=0; j<mcc_ftoi(V_FLOAT_TAB[ __SIM_TIME ].VALUE/V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE)+1; j++)
4298 {
4299 fprintf(file,"%10g\t%10g\t%10g\n", j*V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE, tab[0][j], tab[1][j]);
4300 TRS_CURVS.SIMUINV[i][0][j]=tab[0][j];
4301 TRS_CURVS.SIMUINV[i][1][j]=tab[1][j];
4302 }
4303 mcc_fclose(file,bufp);
4304 for(j = 0 ; j < nbdata ; j++)
4305 mbkfree(tab[j]) ;
4306 mbkfree(tab) ;
4307
4308
4309 if (i==0) dir="ud"; else dir="du";
4310 sprintf(bufp,"%s.plt", buf);
4311 file = mcc_fopen(bufp,"w") ;
4312 avt_printExecInfo(file, "#", "", "");
4313 fprintf(file,"set term %s\n", V_STR_TAB[__AVT_GNUPLOT_TERM].VALUE) ;
4314 if( i==0 )
4315 fprintf(file,"set key bottom left\n");
4316 else
4317 fprintf(file,"set key top left\n");
4318 fprintf(file,"set xlabel \"time\"\n") ;
4319 fprintf(file,"set ylabel \"V\"\n") ;
4320 fprintf(file,"set grid\n") ;
4321 fprintf(file,"set xrange [:%g]\n",k*V_FLOAT_TAB[ __SIM_TRAN_STEP ].VALUE) ;
4322 maxl[i]=k;
4323
4324 fprintf(file,"plot \"%s%s.dat\" using 1:2 title \"HiTas simulator with elp current : input\" with lines,\\\n", mcc_debug_prefix("inverter.tas."), dir);
4325 fprintf(file," \"%s%s.dat\" using 1:3 title \"HiTas simulator with elp current : output\" with lines,\\\n", mcc_debug_prefix("inverter.tas."), dir);
4326 fprintf(file," \"%s%s.dat\" using 1:2 title \"HiTas simulator with %s current : input\" with lines,\\\n", mcc_debug_prefix("inverter.mcc."), dir, mcc_getmccname( ptmodel ));
4327 fprintf(file," \"%s%s.dat\" using 1:3 title \"HiTas simulator with %s current : output\" with lines,\\\n", mcc_debug_prefix("inverter.mcc."), dir, mcc_getmccname( ptmodel ));
4328 fprintf(file," \"%s.%s.stm_ve.dat\" using 1:2 title \"HiTas analytical model\" with lines,\\\n", mcc_debug_prefix("inverter"), dir);
4329 fprintf(file," \"%s.%s.stm_vs.dat\" using 1:2 title \"HiTas analytical model\" with lines,\\\n", mcc_debug_prefix("inverter"), dir);
4330 fprintf(file," \"%s.spice.dat\" using 1:2 title \"External electrical simulator\" with lines,\\\n", buf);
4331 fprintf(file," \"%s.spice.dat\" using 1:3 title \"External electrical simulator\" with lines\n", buf);
4332 fprintf(file,"pause -1 'Hit CR to finish'\n") ;
4333
4334 mcc_fclose(file,bufp);
4335
4336 if (i!=1) mbkfree(name);
4337 }
4338 mbkfree(mn) ;
4339 mbkfree(mp) ;
4340
4341 mcc_bilan_capa_simulated_inverter(lotrsparam_n,lotrsparam_p, maxl);
4342
4343 sprintf(bufp,"S sig %s", mcc_debug_prefix("inverter"));
4344 avt_sethashvar("tasSimulateInverter", bufp);
4345 sprintf(bufp," tmax=%g", -1.0/*V_FLOAT_TAB[ __SIM_TIME ].VALUE*/);
4346 strcat(bufn, bufp);
4347 avt_sethashvar("tasSimulateInverterConfig", bufn);
4348 avt_sethashvar("tasDebugPwl", "sig");
4349 sprintf( tbuf, "top_%s", buf );
4350 c=strchr( tbuf,'.');
4351 if( c )
4352 *c='\0';
4353 if( getloadedlofig( tbuf ) )
4354 dellofig( tbuf );
4355 mcc_runtas_tcl(name,MCC_SLOPE,0,NULL,buf);
4356 sprintf(bufp,"T sig %s", mcc_debug_prefix("inverter"));
4357 avt_sethashvar("tasDebugPwl", NULL);
4358 avt_sethashvar("tasSimulateInverter", bufp);
4359 if( getloadedlofig( tbuf ) )
4360 dellofig( tbuf );
4361 mcc_runtas_tcl(name,MCC_SLOPE,0,NULL,buf);
4362 avt_sethashvar("tasSimulateInverter", NULL);
4363 avt_sethashvar("tasSimulateInverterConfig", NULL);
4364
4365
4366 // mcc_runtas_tcl(gate,slope,capa,buf1,NULL) ;
4367 mbkfree(name);
4368 }
4369
4370 void mcc_calcul_ibranch(elp_lotrs_param *lotrsparam_n,elp_lotrs_param *lotrsparam_p)
4371 {
4372 int i ;
4373
4374 mcc_calcul_ibranch_spice( lotrsparam_n, lotrsparam_p, TRS_CURVS.tabspin, TRS_CURVS.tabspip );
4375 for( i=1 ; i<=4 ; i++ ) {
4376 mcc_calcul_ibranch_mcc( lotrsparam_n, lotrsparam_p, &(TRS_CURVS.tabmccn[i-1]), &(TRS_CURVS.tabmccp[i-1]), i, 'm' );
4377 mcc_calcul_ibranch_mcc( lotrsparam_n, lotrsparam_p, &(TRS_CURVS.tabelpn[i-1]), &(TRS_CURVS.tabelpp[i-1]), i, 'e' );
4378 }
4379
4380 }
4381
4382 void mcc_calcul_ibranch_mcc( elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p, double *tabin, double *tabip, int n, char mode )
4383 {
4384 stm_solver_maillon_list *brhead ;
4385 stm_solver_maillon_list *scan ;
4386 stm_solver_maillon **stmm ;
4387 mcc_trans_mcc *trselp ;
4388 mcc_trans_spice *trsmcc ;
4389 float imax ;
4390 float out ;
4391 int i ;
4392 int trs ;
4393 chain_list *chain, *tofree=NULL ;
4394 lotrs_list *lotrs ;
4395
4396 stmm = alloca( sizeof( stm_solver_maillon* )*n ) ;
4397 if( mode == 'e' )
4398 trselp = alloca( sizeof( mcc_trans_mcc ) * n );
4399 else {
4400 trsmcc = alloca( sizeof( mcc_trans_spice ) * n );
4401 lotrs = alloca( sizeof( lotrs_list ) * n );
4402 }
4403
4404 for( trs=0 ; trs<2 ; trs++ ) {
4405 brhead = NULL ;
4406 for( i=1 ; i<=n ; i++ ) {
4407
4408 stmm[i-1] = stm_solver_new_maillon();
4409
4410 if( mode == 'e' ) {
4411
4412 if( trs==0 )
4413 mcc_trans_mcc_from_global( MCC_TRANS_N, &(trselp[i-1]) );
4414 else
4415 mcc_trans_mcc_from_global( MCC_TRANS_P, &(trselp[i-1]) );
4416
4417 chain = addchain( NULL, &trselp[i-1] );
4418 stm_solver_add_model( stmm[i-1],
4419 (char(*)(void*,float,float,float*))mcc_mcc_ids_list,
4420 (char(*)(void*,float,float,float*))mcc_mcc_vds_list,
4421 chain,
4422 chain
4423 );
4424 }
4425 else {
4426 trsmcc[i-1].MODELFILE = MCC_MODELFILE ;
4427 trsmcc[i-1].MODELTYPE = mcc_getmodeltype (MCC_MODELFILE) ;
4428 trsmcc[i-1].TRANSNAME = ( trs==0 ? MCC_TNMODEL : MCC_TPMODEL );
4429 trsmcc[i-1].TRANSTYPE = ( trs==0 ? MCC_NMOS : MCC_PMOS );
4430 trsmcc[i-1].TRANSCASE = ( trs==0 ? MCC_NCASE : MCC_PCASE );
4431 trsmcc[i-1].TRLENGTH = ( trs==0 ? MCC_LN : MCC_LP ) * 1e-6 ;
4432 trsmcc[i-1].TRWIDTH = ( trs==0 ? MCC_WN : MCC_WP ) * 1e-6 ;
4433 trsmcc[i-1].AD = ( trs==0 ? MCC_ADN : MCC_ADP );
4434 trsmcc[i-1].AS = ( trs==0 ? MCC_ASN : MCC_ASP );
4435 trsmcc[i-1].PD = ( trs==0 ? MCC_PDN : MCC_PDP );
4436 trsmcc[i-1].PS = ( trs==0 ? MCC_PSN : MCC_PSP );
4437 trsmcc[i-1].VB = ( trs==0 ? lotrsparam_n->VBULK : lotrsparam_p->VBULK );
4438 trsmcc[i-1].VG = ( trs==0 ? MCC_VDDmax : 0.0 );
4439 trsmcc[i-1].PARAM = ( trs==0 ? lotrsparam_n : lotrsparam_p );
4440 trsmcc[i-1].TEMP = MCC_TEMP ;
4441 trsmcc[i-1].VDD = MCC_VDDmax ;
4442 trsmcc[i-1].LOTRS = &(lotrs[i-1]) ;
4443 trsmcc[i-1].RS = 0.0 ;
4444 trsmcc[i-1].RD = 0.0 ;
4445
4446 lotrs[i-1].TRNAME = NULL;
4447 lotrs[i-1].LENGTH = (trs==0?MCC_LN:MCC_LP)*SCALE_X ;
4448 lotrs[i-1].WIDTH = (trs==0?MCC_WN:MCC_WP)*SCALE_X ;
4449 lotrs[i-1].TYPE = ( trs==0 ? TRANSN : TRANSP ) ;
4450 lotrs[i-1].USER = NULL;
4451 if (trsmcc[i-1].PARAM->SUBCKTNAME!=NULL)
4452 {
4453 lotrs[i-1].USER=addptype(lotrs[i-1].USER, TRANS_FIGURE, trsmcc[i-1].PARAM->SUBCKTNAME);
4454 tofree=addchain(tofree, lotrs[i-1].USER);
4455 }
4456 lotrs[i-1].BULK = NULL;
4457 lotrs[i-1].GRID = NULL;
4458 lotrs[i-1].SOURCE = NULL;
4459 lotrs[i-1].DRAIN= NULL;
4460 addlotrsmodel( &(lotrs[i-1]), trsmcc[i-1].TRANSNAME ) ;
4461
4462 chain = addchain( NULL, &trsmcc[i-1] );
4463 stm_solver_add_model( stmm[i-1],
4464 (char(*)(void*,float,float,float*))mcc_spice_ids_list,
4465 (char(*)(void*,float,float,float*))mcc_spice_vds_list,
4466 chain,
4467 chain
4468 );
4469 freechain( chain );
4470 }
4471
4472 brhead = stm_solver_maillon_addchain( brhead, stmm[i-1] );
4473 }
4474
4475 brhead = stm_solver_maillon_reverse( brhead );
4476
4477 for( scan = brhead ; scan->NEXT ; scan = scan->NEXT );
4478
4479 if( trs == 0 ) {
4480 scan->MAILLON->VS = 0.0 ;
4481 out = MCC_VDDmax ;
4482 }
4483 else {
4484 scan->MAILLON->VS = MCC_VDDmax ;
4485 out = 0.0 ;
4486 }
4487
4488 stm_solver_i( brhead, out, &imax );
4489 while (tofree!=NULL)
4490 {
4491 freeptype((ptype_list *)tofree->DATA);
4492 tofree=delchain(tofree, tofree);
4493 }
4494 stm_solver_maillon_freechain( brhead );
4495
4496 if( trs == 0 )
4497 *tabin = -imax*1e6 ;
4498 else
4499 *tabip = imax*1e6 ;
4500 }
4501
4502 MCC_CURRENT_LOTRS = NULL ;
4503 }
4504
4505 void mcc_calcul_ibranch_spice( elp_lotrs_param *lotrsparam_n, elp_lotrs_param *lotrsparam_p, double *tabin, double *tabip )
4506 {
4507 FILE *file ;
4508 int j ;
4509 char *subcktmodeln, *subcktmodelp, *fileout ;
4510 char *modeln, *modelp, *name ;
4511 char *mn, *mp, *c ;
4512 char bufn[1024] ;
4513 char bufp[1024], buf[1024] ;
4514 int bs3 = 0, bs4 = 0, nbdata=8;
4515 char *argv[]={"VN1","VN2","VN3","VN4", "VP1","VP2","VP3", "VP4"};
4516 float vgsn, vgsp ;
4517 double **tab;
4518 mcc_modellist *ptmodel ;
4519
4520 bs3 = ( MCC_SPICEMODELTYPE == MCC_BSIM3V3 ? 1 : 0 ) ;
4521 bs4 = ( MCC_SPICEMODELTYPE == MCC_BSIM4 ? 1 : 0 ) ;
4522 modeln = MCC_TNMODEL ;
4523 modelp = MCC_TPMODEL ;
4524 sprintf(bufn,"m") ;
4525 sprintf(bufp,"m") ;
4526
4527 ptmodel = mcc_getmodel ( MCC_MODELFILE,
4528 MCC_TPMODEL,
4529 MCC_PMOS,
4530 MCC_PCASE,
4531 MCC_LP*1.0e-6,
4532 MCC_WP*1.0e-6, 0);
4533 subcktmodeln = mcc_getsubckt( MCC_MODELFILE,
4534 MCC_TNMODEL,
4535 MCC_NMOS,
4536 MCC_NCASE,
4537 MCC_LN*1.0e-6,
4538 MCC_WN*1.0e-6
4539 ) ;
4540 subcktmodelp = mcc_getsubckt( MCC_MODELFILE,
4541 MCC_TPMODEL,
4542 MCC_PMOS,
4543 MCC_PCASE,
4544 MCC_LP*1.0e-6,
4545 MCC_WP*1.0e-6
4546 ) ;
4547
4548 if (subcktmodeln != NULL) /*- le model est dans un subckt -*/
4549 {
4550 sprintf(bufn,"xm") ;
4551 modeln = subcktmodeln ;
4552 }
4553
4554 if (subcktmodelp != NULL) /*- le model est dans un subckt -*/
4555 {
4556 sprintf(bufp,"xm") ;
4557 modelp = subcktmodelp ;
4558 }
4559 mn = mbkstrdup(bufn) ;
4560 mp = mbkstrdup(bufp) ;
4561
4562 sim_set_result_file_extension('p', 1, &MCC_SPICEOUT);
4563
4564 strcpy(bufn, "");
4565
4566 name=mbkstrdup(mcc_debug_prefix("ibranch.spi"));
4567 strcpy(buf,name);
4568 if ((c=strrchr(buf,'.'))!=NULL) *c='\0';
4569
4570 file = mcc_fopen(name,"w") ;
4571 avt_printExecInfo(file, "*", "", "");
4572 mcc_get_np_vgs(&vgsn, &vgsp);
4573
4574 fprintf(file,"* branch current measure\n" );
4575 fprintf(file,"\n");
4576 if(MCC_SPICEOPTIONS != NULL)
4577 fprintf(file,".option %s\n",MCC_SPICEOPTIONS);
4578 if (V_INT_TAB[__SIM_TOOL].VALUE==SIM_TOOL_HSPICE)
4579 fprintf(file,".option INGOLD=1\n");
4580 if(V_INT_TAB[__SIM_TOOL].VALUE==SIM_TOOL_NGSPICE)
4581 fprintf(file,".include %s\n",MCC_TECHFILE);
4582 else
4583 fprintf(file,".include \"%s\"\n",MCC_TECHFILE);
4584 fprintf(file,"\n");
4585
4586 fprintf(file,".subckt %s in out1 out2 out3 out4\n", buf);
4587
4588 fprintf(file,"%sn11 out1 in 0 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4589 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4590 fprintf(file,"%sp11 out1 in vdd vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4591 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4592
4593 fprintf(file,"%sn21 out2 in n21 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4594 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4595 fprintf(file,"%sn22 n21 in 0 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4596 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4597 fprintf(file,"%sp21 out2 in p21 vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4598 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4599 fprintf(file,"%sp22 p21 in vdd vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4600 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4601 fprintf(file,"rn21 n21 0 10Meg\n");
4602 fprintf(file,"rp21 p21 vdd 10Meg\n");
4603
4604 fprintf(file,"%sn31 out3 in n31 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4605 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4606 fprintf(file,"%sn32 n31 in n32 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4607 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4608 fprintf(file,"%sn33 n32 in 0 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4609 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4610 fprintf(file,"%sp31 out3 in p31 vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4611 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4612 fprintf(file,"%sp32 p31 in p32 vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4613 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4614 fprintf(file,"%sp33 p32 in vdd vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4615 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4616 fprintf(file,"rn31 n31 0 10Meg\n");
4617 fprintf(file,"rn32 n32 0 10Meg\n");
4618 fprintf(file,"rp31 p31 vdd 10Meg\n");
4619 fprintf(file,"rp32 p32 vdd 10Meg\n");
4620
4621 fprintf(file,"%sn41 out4 in n41 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4622 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4623 fprintf(file,"%sn42 n41 in n42 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4624 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4625 fprintf(file,"%sn43 n42 in n43 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4626 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4627 fprintf(file,"%sn44 n43 in 0 vbn %s l=%gu w=%gu %s\n", mn,modeln,MCC_LN,MCC_WN,surf_string_n);
4628 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_n);
4629 fprintf(file,"%sp41 out4 in p41 vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4630 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4631 fprintf(file,"%sp42 p41 in p42 vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4632 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4633 fprintf(file,"%sp43 p42 in p43 vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4634 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4635 fprintf(file,"%sp44 p43 in vdd vbp %s l=%gu w=%gu %s\n", mp,modelp,MCC_LP,MCC_WP,surf_string_p);
4636 mcc_printf_instance_specific(file, &mcc_user_lotrsparam_p);
4637 fprintf(file,"rn41 n41 0 10Meg\n");
4638 fprintf(file,"rn42 n42 0 10Meg\n");
4639 fprintf(file,"rn43 n43 0 10Meg\n");
4640 fprintf(file,"rp41 p41 vdd 10Meg\n");
4641 fprintf(file,"rp42 p42 vdd 10Meg\n");
4642 fprintf(file,"rp43 p43 vdd 10Meg\n");
4643
4644 fprintf(file,"vddmax vdd 0 dc %gv\n",MCC_VDDmax);
4645 fprintf(file,"vbulkn vbn 0 %gv\n",(lotrsparam_n->VBULK > ELPMINVBULK) ? lotrsparam_n->VBULK : 0.0);
4646 fprintf(file,"vbulkp vbp 0 %gv\n",(lotrsparam_p->VBULK > ELPMINVBULK) ? lotrsparam_p->VBULK : MCC_VDDmax);
4647 fprintf(file,".ends\n\n");
4648
4649 fprintf(file,"xinstn in outn1 outn2 outn3 outn4 %s\n", buf);
4650 fprintf(file,"xinstp in outp1 outp2 outp3 outp4 %s\n\n", buf);
4651 fprintf(file,".option tnom=%g\n", V_FLOAT_TAB[__SIM_TNOM].VALUE);
4652 fprintf(file,".temp %g\n\n",MCC_TEMP);
4653
4654 fprintf(file,"var in 0 dc %gv\n",MCC_VDDmax/2.0);
4655 fprintf(file,"vn1 outn1 0 dc %gv\n",MCC_VDDmax);
4656 fprintf(file,"vn2 outn2 0 dc %gv\n",MCC_VDDmax);
4657 fprintf(file,"vn3 outn3 0 dc %gv\n",MCC_VDDmax);
4658 fprintf(file,"vn4 outn4 0 dc %gv\n",MCC_VDDmax);
4659 fprintf(file,"vp1 outp1 0 dc %gv\n",0.0);
4660 fprintf(file,"vp2 outp2 0 dc %gv\n",0.0);
4661 fprintf(file,"vp3 outp3 0 dc %gv\n",0.0);
4662 fprintf(file,"vp4 outp4 0 dc %gv\n\n",0.0);
4663
4664 fprintf(file,".dc var %g %g %g\n\n", 0.0, MCC_VDDmax, MCC_VDDmax/10.0 );
4665
4666 fprintf(file,".print dc i(vn1)\n" );
4667 fprintf(file,".print dc i(vn2)\n" );
4668 fprintf(file,".print dc i(vn3)\n" );
4669 fprintf(file,".print dc i(vn4)\n" );
4670 fprintf(file,".print dc i(vp1)\n" );
4671 fprintf(file,".print dc i(vp2)\n" );
4672 fprintf(file,".print dc i(vp3)\n" );
4673 fprintf(file,".print dc i(vp4)\n" );
4674
4675 if ( V_INT_TAB[__SIM_TOOL].VALUE == SIM_TOOL_TITAN )
4676 fprintf(file,".save %s\n", buf);
4677
4678 fprintf(file,".end\n");
4679
4680 mcc_fclose(file,name);
4681
4682 sim_execspice(name,0,MCC_SPICENAME,MCC_SPICESTRING,MCC_SPICESTDOUT);
4683
4684 fileout = sim_getjoker(MCC_SPICEOUT,buf) ;
4685
4686 tab = (double **)mbkalloc(nbdata * sizeof(double *)) ;
4687 for(j = 0 ; j < nbdata ; j++)
4688 tab[j] = (double *)mbkalloc(11*sizeof(double)) ;
4689
4690 sim_readspifiletab( fileout, argv, nbdata, 11, tab, MCC_VDDmax, MCC_VDDmax/10.0) ;
4691
4692 tabin[0] = -tab[0][10]*1e6;
4693 tabin[1] = -tab[1][10]*1e6;
4694 tabin[2] = -tab[2][10]*1e6;
4695 tabin[3] = -tab[3][10]*1e6;
4696 tabip[0] = tab[4][0]*1e6;
4697 tabip[1] = tab[5][0]*1e6;
4698 tabip[2] = tab[6][0]*1e6;
4699 tabip[3] = tab[7][0]*1e6;
4700 }
4701
4702 char *mcc_check_subckt(char *nmos, char *pmos)
4703 {
4704 char *subcktmodeln, *subcktmodelp;
4705 mcc_modellist *ptmodeln,*ptmodelp;
4706 FILE *f;
4707 char *buf;
4708
4709 MCC_CURRENT_LOTRS=NULL;
4710 subcktmodeln = mcc_getsubckt( MCC_MODELFILE,
4711 MCC_TNMODEL,
4712 MCC_NMOS,
4713 MCC_NCASE,
4714 MCC_LN*1.0e-6,
4715 MCC_WN*1.0e-6
4716 ) ;
4717 subcktmodelp = mcc_getsubckt( MCC_MODELFILE,
4718 MCC_TPMODEL,
4719 MCC_PMOS,
4720 MCC_PCASE,
4721 MCC_LP*1.0e-6,
4722 MCC_WP*1.0e-6
4723 ) ;
4724 if (subcktmodeln || subcktmodelp)
4725 {
4726 buf=sensitive_namealloc(mcc_debug_prefix("no_param.techno"));
4727 f=mcc_fopen(buf, "w");
4728 avt_printExecInfo(f, "*", "", "");
4729 fprintf(f, "* generated technofile with all evaluated parameters\n\n");
4730
4731 ptmodeln = mcc_getmodel ( MCC_MODELFILE,
4732 MCC_TNMODEL,
4733 MCC_NMOS,
4734 MCC_NCASE,
4735 MCC_LN*1.0e-6,
4736 MCC_WN*1.0e-6, 0);
4737 fprintf(f, "*\n*\n* NMOS **********************\n*\n*\n\n");
4738 mcc_drive_dot_model(f, ptmodeln);
4739 ptmodelp = mcc_getmodel ( MCC_MODELFILE,
4740 MCC_TPMODEL,
4741 MCC_PMOS,
4742 MCC_PCASE,
4743 MCC_LP*1.0e-6,
4744 MCC_WP*1.0e-6, 0);
4745
4746 fprintf(f, "*\n*\n* PMOS **********************\n*\n*\n\n");
4747 mcc_drive_dot_model(f, ptmodelp);
4748 strcpy(nmos, ptmodeln->NAME);
4749 strcpy(pmos, ptmodelp->NAME);
4750 fclose(f);
4751 return buf;
4752 }
4753 return NULL;
4754 }
4755
4756 static void mcc_check_trs(lotrs_list *lt, elp_lotrs_param *lotrsparam_n, char *subname)
4757 {
4758 ptype_list *pt;
4759 optparam_list *ptopt;
4760 int disp;
4761 losig_list *sigs[4]={lt->SOURCE->SIG, lt->GRID->SIG, lt->DRAIN->SIG, lt->BULK->SIG};
4762 char *names[4]={"source", "gate", "drain", "bulk"};
4763 char *paramname;
4764 double value;
4765 if ((pt=getptype(lt->USER, OPT_PARAMS))!=NULL)
4766 {
4767 for (ptopt = (optparam_list *)pt->DATA; ptopt; ptopt = ptopt->NEXT)
4768 {
4769 disp=1;
4770 if (isknowntrsparam (ptopt->UNAME.STANDARD))
4771 {
4772 if (**(ptopt->UNAME.STANDARD) != '$') paramname=*(ptopt->UNAME.STANDARD);
4773 else continue;
4774 }
4775 else if (ptopt->TAG != '$')
4776 {
4777 paramname=ptopt->UNAME.SPECIAL;
4778 }
4779 else continue;
4780
4781 value=ptopt->UDATA.VALUE;
4782
4783 if (strcasecmp(paramname, "delvto")==0) lotrsparam_n->PARAM[elpDELVT0]=value;
4784 else if (strcasecmp(paramname, "mulu0")==0) lotrsparam_n->PARAM[elpMULU0]=value;
4785 else if (strcasecmp(paramname, "sa")==0) lotrsparam_n->PARAM[elpSA]=value;
4786 else if (strcasecmp(paramname, "sb")==0) lotrsparam_n->PARAM[elpSB]=value;
4787 else if (strcasecmp(paramname, "sd")==0) lotrsparam_n->PARAM[elpSD]=value;
4788 else if (strcasecmp(paramname, "nf")==0) lotrsparam_n->PARAM[elpNF]=value;
4789 else if (strcasecmp(paramname, "nrs")==0) lotrsparam_n->PARAM[elpNRS]=value;
4790 else if (strcasecmp(paramname, "nrd")==0) lotrsparam_n->PARAM[elpNRD]=value;
4791 else if (strcasecmp(paramname, "sc")==0) lotrsparam_n->PARAM[elpSC]=value;
4792 else if (strcasecmp(paramname, "sca")==0) lotrsparam_n->PARAM[elpSCA]=value;
4793 else if (strcasecmp(paramname, "scb")==0) lotrsparam_n->PARAM[elpSCB]=value;
4794 else if (strcasecmp(paramname, "scc")==0) lotrsparam_n->PARAM[elpSCC]=value;
4795 else if (strcasecmp(paramname, "m")==0)
4796 {
4797 if (mcc_ftoi(value)!=1)
4798 avt_errmsg(MCC_ERRMSG, "040", AVT_ERROR, mcc_ftoi(value));
4799 disp=0;
4800 }
4801 else disp=0;
4802 if (disp)
4803 {
4804 avt_errmsg(MCC_ERRMSG, "039", AVT_WARNING, paramname, value, subname);
4805 }
4806 }
4807 }
4808 for (disp=0; disp<4; disp++)
4809 {
4810 if (sigs[disp]->PRCN!=NULL && sigs[disp]->PRCN->PCTC!=NULL)
4811 avt_errmsg(MCC_ERRMSG, "041", AVT_WARNING, "capacitance", names[disp], subname);
4812 if (sigs[disp]->PRCN!=NULL && sigs[disp]->PRCN->PWIRE!=NULL)
4813 avt_errmsg(MCC_ERRMSG, "041", AVT_WARNING, "resistor", names[disp], subname);
4814 }
4815
4816 }
4817
4818 void mcc_check_techno_with_subckt(elp_lotrs_param *lotrsparam_n,elp_lotrs_param *lotrsparam_p, char *subcktmodeln, char *subcktmodelp)
4819 {
4820 char *modeln, *modelp ;
4821 char bufn[1024] ;
4822 char bufp[1024] ;
4823 FILE *f;
4824 lofig_list *lf;
4825 lotrs_list *lt;
4826
4827 modeln = MCC_TNMODEL ;
4828 modelp = MCC_TPMODEL ;
4829 sprintf(bufn,"m") ;
4830 sprintf(bufp,"m") ;
4831
4832 if (subcktmodeln != NULL || subcktmodelp != NULL)
4833 {
4834 if (subcktmodeln != NULL)
4835 {
4836 sprintf(bufn,"xm") ;
4837 modeln = subcktmodeln ;
4838 }
4839 if (subcktmodelp != NULL)
4840 {
4841 sprintf(bufp,"xm") ;
4842 modelp = subcktmodelp ;
4843 }
4844
4845 f=mcc_fopen("test.spi", "w");
4846 avt_printExecInfo(f, "*", "", "");
4847
4848 fprintf(f,"\n.subckt test in1 out1 vss in2 out2 vdd\n");
4849 fprintf(f,"%s1 out1 in1 vss vss %s l=%gu w=%gu %s\n"
4850 ,bufn,modeln,MCC_LN,MCC_WN,surf_string_n);
4851 mcc_printf_instance_specific(f, &mcc_user_lotrsparam_n);
4852 fprintf(f,"%s2 out2 in2 vdd vdd %s l=%gu w=%gu %s\n"
4853 ,bufp,modelp,MCC_LP,MCC_WP,surf_string_p);
4854 mcc_printf_instance_specific(f, &mcc_user_lotrsparam_p);
4855 fprintf(f,".ends\n");
4856 fclose(f);
4857
4858 parsespice("test.spi");
4859 if ((lf=getloadedlofig("test"))!=NULL)
4860 {
4861 rflattenlofig(lf, YES, NO);
4862 for (lt=lf->LOTRS; lt!=NULL; lt=lt->NEXT)
4863 {
4864 if (MLO_IS_TRANSN(lt->TYPE) && subcktmodeln!=NULL)
4865 mcc_check_trs(lt, lotrsparam_n, subcktmodeln);
4866 if (MLO_IS_TRANSP(lt->TYPE) && subcktmodelp!=NULL)
4867 mcc_check_trs(lt, lotrsparam_p, subcktmodelp);
4868 }
4869 dellofig("test");
4870 }
4871 unlink("test.spi");
4872 }
4873
4874 }
4875