1 /****************************************************************************/
3 /* Chaine de CAO & VLSI Alliance */
5 /* Produit : MCC Version 1 */
6 /* Fichier : mcc_genspi.c */
8 /* (c) copyright 1991-1998 Laboratoire LIP6 equipe ASIM */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
12 /* Auteur(s) : Karim DIOURY */
14 /****************************************************************************/
17 #include "mcc_optim.h"
19 #include "mcc_genspi.h"
20 #include "mcc_drvelp.h"
23 #include "mcc_mod_util.h"
24 #include "mcc_mod_spice.h"
25 #include "mcc_debug.h"
27 char *MCC_TN_SUBCKT
=NULL
, *MCC_TP_SUBCKT
=NULL
;
28 lotrs_list
*MCC_CURRENT_LOTRS
=NULL
;
29 char *MCC_CURRENT_SUBCKT
=NULL
;
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
;
62 char surf_string_n
[1024];
63 char surf_string_p
[1024];
64 elp_lotrs_param mcc_user_lotrsparam_n
, mcc_user_lotrsparam_p
;
66 void mcc_printf_instance_specific(FILE *file
, elp_lotrs_param
*lotrsparam_n
)
70 b4
= ( MCC_SPICEMODELTYPE
== MCC_BSIM4
? 1 : 0 ) ;
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
]);
104 double mcc_calcul_isat(vgs
,vbs
,type_t
)
110 double vtn
= MCC_VTN
+ MCC_KTN
* vbs
;
111 double vtp
= MCC_VTP
+ MCC_KTP
* vbs
;
113 if(type_t
== MCC_TRANS_N
)
115 if(vgs
<= vtn
) return(0.0);
116 is
= (MCC_AN
*(vgs
-vtn
)*(vgs
-vtn
))/(1.0+MCC_BN
*(vgs
-vtn
));
120 if(vgs
<= vtp
) return(0.0);
121 is
= (MCC_AP
*(vgs
-vtp
)*(vgs
-vtp
))/(1.0+MCC_BP
*(vgs
-vtp
));
127 double mcc_calcul_ures(vgs
,vbs
,type_t
)
135 double vtn
= MCC_VTN
+ MCC_KTN
* vbs
;
136 double vtp
= MCC_VTP
+ MCC_KTP
* vbs
;
138 if(type_t
== MCC_TRANS_N
)
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
) ;
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
) ;
156 double mcc_calcul_ires(vgs
,vbs
,type_t
)
162 double vtn
= MCC_VTN
+ MCC_KTN
* vbs
;
163 double vtp
= MCC_VTP
+ MCC_KTP
* vbs
;
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
))) ;
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
))) ;
173 void mcc_trans_mcc_from_global( int type_t
, mcc_trans_mcc
*trs
)
175 trs
->VDD
= MCC_VDDmax
;
179 if( type_t
== MCC_TRANS_N
) {
180 trs
->VG
= MCC_VDDmax
;
182 trs
->TRWIDTH
= (long)(0.5+MCC_WNeff
* ((double)SCALE_X
)) ;
183 trs
->TRLENGTH
= (long)(0.5+MCC_LNeff
* ((double)SCALE_X
)) ;
190 trs
->VLIN
= MCC_VDDmax
* MCC_KRNT
;
191 trs
->VSAT
= MCC_VDDmax
* MCC_KRNS
;
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
)) ;
207 trs
->VLIN
= MCC_VDDmax
* MCC_KRPT
;
208 trs
->VSAT
= MCC_VDDmax
* MCC_KRPS
;
215 #define 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 */
231 mcc_trans_mcc_from_global( type_t
, &trs
);
235 if( type_t
== MCC_TRANS_N
) {
236 wl
= MCC_WNeff
/MCC_LNeff
;
241 wl
= MCC_WPeff
/MCC_LPeff
;
251 if( ! mcc_mcc_ids( &trs
, vs
, vd
, &ids
) )
257 double mcc_current(vgs
,vds
,vbs
,type_t
)
270 double vtn
= MCC_VTN
+ MCC_KTN
* vbs
;
271 double vtp
= MCC_VTP
+ MCC_KTP
* vbs
;
272 double factor
= 1.0 ;
285 if(type_t
== MCC_TRANS_N
)
287 if(vgs
<= vtn
) return(0.0);
288 isat
= mcc_calcul_isat(vgs
,vbs
,type_t
) ;
290 ures
= mcc_calcul_ures(vgs
,vbs
,type_t
) ;
291 ires
= mcc_calcul_ires(vgs
,vbs
,type_t
) ;
294 rsat
= (MCC_VDDmax
- ures
)/(isat
- ires
) ;
295 rsatmin
= MCC_VDDmax
/isat
;
297 if( rsat
> rsatmin
&& ures
> 0.0 ) {
298 is
= (MCC_VDDmax
- vds
)/rsat
;
301 vsat
= ((vgs
-vtn
)/(MCC_VDDmax
-vtn
))*(MCC_VDDmax
* MCC_KRNS
) ;
302 vlin
= ((vgs
-vtn
)/(MCC_VDDmax
-vtn
))*(MCC_VDDmax
* MCC_KRNT
) ;
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
;
311 isx
= isat
-(MCC_VDDmax
- vsat
)/rsat
;
313 csat
= isx
-vsat
*psat
;
321 im
=(ires
-iit
)/2.0+iit
;
323 a1
=(im
-ilin
)/(ures
-vlin
) ;
326 a2
=(isx
-im
)/(vsat
-ures
) ;
329 ures2
=(csat
-b1
)/(a1
-psat
) ;
330 ires2
=psat
*ures2
+csat
;
332 im2
=(ires2
-iit2
)/2.0+iit2
;
334 a3
=(im2
-im
)/(ures2
-ures
) ;
337 a4
=(isx
-im2
)/(vsat
-ures2
) ;
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
;
349 aux
= ( psat
*vds
+ csat
) * MCC_WNeff
/MCC_LNeff
;
354 aux
= vds
/ rsatmin
* MCC_WNeff
/MCC_LNeff
;
359 if(vgs
<= vtp
) return(0.0);
360 isat
= mcc_calcul_isat(vgs
,vbs
,type_t
) ;
362 ures
= mcc_calcul_ures(vgs
,vbs
,type_t
) ;
363 ires
= mcc_calcul_ires(vgs
,vbs
,type_t
) ;
366 rsat
= (MCC_VDDmax
- ures
)/(isat
- ires
) ;
367 rsatmin
= MCC_VDDmax
/isat
;
369 if( rsat
> rsatmin
&& ures
> 0.0 ) {
370 is
= (MCC_VDDmax
- vds
)/rsat
;
373 vsat
= ((vgs
-vtp
)/(MCC_VDDmax
-vtp
))*(MCC_VDDmax
* MCC_KRPS
) ;
374 vlin
= ((vgs
-vtp
)/(MCC_VDDmax
-vtp
))*(MCC_VDDmax
* MCC_KRPT
) ;
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
;
383 isx
= isat
-(MCC_VDDmax
- vsat
)/rsat
;
385 csat
= isx
-vsat
*psat
;
393 im
=(ires
-iit
)/2.0+iit
;
395 a1
=(im
-ilin
)/(ures
-vlin
) ;
398 a2
=(isx
-im
)/(vsat
-ures
) ;
401 ures2
=(csat
-b1
)/(a1
-psat
) ;
402 ires2
=psat
*ures2
+csat
;
404 im2
=(ires2
-iit2
)/2.0+iit2
;
406 a3
=(im2
-im
)/(ures2
-ures
) ;
409 a4
=(isx
-im2
)/(vsat
-ures2
) ;
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
;
421 aux
= ( psat
*vds
+ csat
) * MCC_WPeff
/MCC_LPeff
;
426 aux
= vds
/ rsatmin
* MCC_WPeff
/MCC_LPeff
;
434 double mcc_spicecurrent(vgs
,vds
,vbs
,type
,lotrsparam
)
439 elp_lotrs_param
*lotrsparam
;
441 if(MCC_CALC_CUR
== MCC_SIM_MODE
)
442 return(mcc_spicesimcurrent(vgs
,vds
,vbs
,type
)) ;
444 return(mcc_spicecalccurrent(vgs
,vds
,vbs
,type
,lotrsparam
)) ;
447 double mcc_spicecalccurrent(vgs
,vds
,vbs
,type
,lotrsparam
)
452 elp_lotrs_param
*lotrsparam
;
461 double factor
= 1.0 ;
471 if(type
== MCC_TRANS_N
)
475 transname
= MCC_TNMODEL
;
486 transname
= MCC_TPMODEL
;
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
))) ;
499 static int mcc_optiom_resetsearch
=1;
500 void mcc_optim_resetsearch_for_new_pwl()
502 mcc_optiom_resetsearch
=1;
504 double mcc_spicesimcurrent(vgs
,vds
,vbs
,type
)
513 int stepmax
, *curidx
;
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
;
521 if (mcc_optiom_resetsearch
)
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;
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)))
532 if(type
== MCC_TRANS_N
)
533 mypwl
= MCC_OPTIM_IDNVGS
, curidx
=&MCC_OPTIM_IDNVGS_idx
;
535 mypwl
= MCC_OPTIM_IDPVGS
, curidx
=&MCC_OPTIM_IDPVGS_idx
;
540 if(type
== MCC_TRANS_N
)
541 mypwl
= MCC_OPTIM_IDNRES
, curidx
=&MCC_OPTIM_IDNRES_idx
;
543 mypwl
= MCC_OPTIM_IDPRES
, curidx
=&MCC_OPTIM_IDPRES_idx
;
548 if(type
== MCC_TRANS_N
)
549 mypwl
= MCC_OPTIM_IDNSAT
, curidx
=&MCC_OPTIM_IDNSAT_idx
;
551 mypwl
= MCC_OPTIM_IDPSAT
, curidx
=&MCC_OPTIM_IDPSAT_idx
;
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
);
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)))
566 if(type
== MCC_TRANS_N
)
574 if(type
== MCC_TRANS_N
)
582 if(type
== MCC_TRANS_N
)
588 step
= mcc_ftoi((v
) / (MCC_DC_STEP
)) ;
589 stepmax
= mcc_ftoi((MCC_VDDmax
) / (MCC_DC_STEP
)) ;
596 #ifndef __ALL__WARNING_
601 double mcc_spicevdeg(type
,lotrsparam
)
603 elp_lotrs_param
*lotrsparam
;
607 if(MCC_CALC_CUR
== MCC_SIM_MODE
)
609 if(type
== MCC_TRANS_N
)
612 if(v
> (MCC_VDDmax
- MCC_VTN
))
613 v
= MCC_VDDmax
- MCC_VTN
;
614 if(v
< (0.55*MCC_VDDmax
))
626 if(type
== MCC_TRANS_N
)
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
))
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
) ;
642 v
= MCC_VTP
/(1-MCC_KTP
) ;
649 double mcc_calcdiffmodelsat(double vmin
,double vmax
,int type
,elp_lotrs_param
*lotrsparam
, double exitvalue
, mcc_corner_info
*info
)
658 if ( MCC_OPTIM_MODE
)
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
);
665 var
= vmin
+ MCC_DC_STEP
;
667 if( lotrsparam
->ISVBSSET
)
668 vbs
= lotrsparam
->VBS
;
670 vbs
= (type
== MCC_TRANS_N
) ? lotrsparam
->VBULK
: lotrsparam
->VBULK
-MCC_VDDmax
;
673 imod
= mcc_current(var
,MCC_VDDmax
,0.0,type
) ;
674 ispice
= mcc_spicecurrent(var
,MCC_VDDmax
,vbs
,type
,lotrsparam
) ;
680 val
= (imod
- ispice
) * (imod
- ispice
) ;
687 if (exitvalue
>=0 && res
>exitvalue
) return res
;
699 double mcc_calcul_vt_error( int type
, elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
, double testvt
, mcc_corner_info
*info
)
704 elp_lotrs_param
*trs_param
;
706 if( type
== MCC_TRANS_N
) {
709 trs_param
= lotrsparam_n
;
714 trs_param
= lotrsparam_p
;
717 if( MCC_NEW_CALC_ABR
&& MCC_OPTIM_MODE
) {
718 emin
= mcc_get_best_abr_from_vt ( type
, lotrsparam_n
, lotrsparam_p
, info
) ;
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
) ;
726 if( type
== MCC_TRANS_N
)
734 void mcc_calcul_vt_old( int type
, elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
, mcc_corner_info
*info
)
753 static FILE *vtfile
=NULL
;
760 char *where
=getenv("VTFILE");
763 vtfile
=fopen(where
, "a");
764 fprintf(vtfile
,"***\n");
768 env
= getenv( "MCC_DELTA_VT" ) ;
770 deltavt
= atof ( env
);
774 if(type
== MCC_TRANS_N
) {
777 vmin
= MCC_VTN
* (1.0-deltavt
) ;
778 vmax
= MCC_VTN
* (1.0+deltavt
) ;
781 if(type
== MCC_TRANS_P
) {
784 vmin
= MCC_VTP
* (1.0-deltavt
) ;
785 vmax
= MCC_VTP
* (1.0+deltavt
) ;
795 if ( !mcc_check_param ( type
) )
798 if( V_BOOL_TAB
[ __MCC_PRECISE_VT
].VALUE
) {
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
);
812 if( type
== MCC_TRANS_P
)
819 if( type
== MCC_TRANS_N
|| type
== MCC_TRANS_P
) {
821 if(vmax
> MCC_VDDmax
)
824 delta
= (vmax
-vmin
)/1000.0 ;
826 vhalf
= (vmin
+vmax
)/2.0 ;
834 emin
= mcc_calcul_vt_error( type
, lotrsparam_n
,lotrsparam_p
, vmin
, NULL
);
839 ehalf
= mcc_calcul_vt_error( type
, lotrsparam_n
,lotrsparam_p
, vhalf
, NULL
);
844 emax
= mcc_calcul_vt_error( type
, lotrsparam_n
,lotrsparam_p
, vmax
, NULL
);
848 if( emin
< ehalf
&& ehalf
< emax
) {
851 vhalf
= (vmin
+vmax
)/2.0 ;
855 if( emin
> ehalf
&& ehalf
> emax
) {
858 vhalf
= (vmin
+vmax
)/2.0 ;
863 if( emin
> ehalf
&& emax
> ehalf
) {
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
);
870 if( ehalf1
< ehalf2
) {
900 while( (vmax
-vmin
) > delta
);
902 if( type
== MCC_TRANS_N
)
909 double vt0
=(type
!= MCC_TRANS_N
)?MCC_VTP
:MCC_VTN
;
910 fprintf(vtfile
, "%g %g\n",(vhalf
-vt0
)/vt0
, ehalf
);
915 void mcc_calcul_vt_new( int type
, elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
)
936 env
= getenv("MCC_DELTA_VT") ;
938 deltavt
= atof ( env
);
942 if(type
== MCC_TRANS_N
) {
945 vmin
= MCC_VTN
* (1.0-deltavt
) ;
946 vmax
= MCC_VTN
* (1.0+deltavt
) ;
947 lmax
= MCC_VDDmax
- (MCC_VDDmax
-MCC_VTN
)/10.0 ;
952 if(type
== MCC_TRANS_P
) {
955 vmin
= MCC_VTP
* (1.0-deltavt
) ;
956 vmax
= MCC_VTP
* (1.0+deltavt
) ;
957 lmax
= MCC_VDDmax
- (MCC_VDDmax
-MCC_VTP
)/10.0 ;
969 if ( !mcc_check_param ( type
) )
972 if( type
== MCC_TRANS_N
|| type
== MCC_TRANS_P
) {
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 ;
983 emax
= mcc_calcul_vt_error( type
, lotrsparam_n
,lotrsparam_p
, vmax
, NULL
);
984 if( emax
> FLT_MAX
/2.0 ) {
986 vmax
= vmax
- delta
;
997 printf( "can't find a valid solution for VT\n");
1001 vhalf
= (vmin
+vmax
)/2.0 ;
1003 delta
= (vmax
-vmin
)/1000.0 ;
1008 emin
= mcc_calcul_vt_error( type
, lotrsparam_n
,lotrsparam_p
, vmin
, NULL
);
1013 ehalf
= mcc_calcul_vt_error( type
, lotrsparam_n
,lotrsparam_p
, vhalf
, NULL
);
1018 emax
= mcc_calcul_vt_error( type
, lotrsparam_n
,lotrsparam_p
, vmax
, NULL
);
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" );
1027 if( emin
< ehalf
&& ehalf
< emax
) {
1030 vhalf
= (vmin
+vmax
)/2.0 ;
1034 if( emin
> ehalf
&& ehalf
> emax
) {
1037 vhalf
= (vmin
+vmax
)/2.0 ;
1042 if( emin
> ehalf
&& emax
> ehalf
) {
1044 ehalfp
= mcc_calcul_vt_error( type
, lotrsparam_n
,lotrsparam_p
, vhalf
+delta
/2.0, NULL
);
1045 pente
= (ehalfp
-ehalf
)/(delta
/2.0);
1056 vhalf
= (vmin
+vmax
)/2.0 ;
1077 while( (vmax
-vmin
) > delta
);
1079 if( type
== MCC_TRANS_N
)
1086 int mcc_get_sat_parameter( double v1
, double i1
,
1087 double v2
, double i2
,
1088 double v3
, double i3
,
1120 t1
= i1
*v3
/i3
- v1
;
1121 t2
= i2
*v3
/i3
- v2
;
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
;
1127 delta
= tb
*tb
- 4.0*ta
*tc
;
1129 if( delta
>= 0.0 ) {
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
) ;
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
) ;
1139 if( mcc_check_sat_param( a1
, b1
, vt1
, MCC_VDDmax
, 'T' ) && vt1
< v1
)
1144 if( mcc_check_sat_param( a2
, b2
, vt2
, MCC_VDDmax
, 'T' ) && vt2
< v1
)
1150 if( valid1
&& valid2
) {
1185 int mcc_get_iflex_isat( mbk_pwl
*pwl
, double *vgs
, double *ids
)
1192 amin
= pwl
->DATA
[0].A
;
1195 for( i
=1; i
<pwl
->N
; i
++ ) {
1196 if( pwl
->DATA
[i
].A
< amin
) {
1200 amin
= pwl
->DATA
[i
].A
;
1205 *vgs
= pwl
->DATA
[i
].X0
;
1207 *ids
= pwl
->DATA
[i
].A
* pwl
->DATA
[i
].X0
+ pwl
->DATA
[i
].B
;
1216 int mcc_check_sat_param( double a
,
1220 char type
/* 'B'=branch, 'T'=transistor */
1223 int allownegativeb
;
1227 allownegativeb
= V_BOOL_TAB
[ __MCC_ALLOW_NEGATIVE_B_BRANCH
].VALUE
;
1229 allownegativeb
= V_BOOL_TAB
[ __MCC_ALLOW_NEGATIVE_B
].VALUE
;
1231 if( allownegativeb
)
1232 bmin
= -1.0/(vdd
-vt
);
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 ;
1243 void mcc_calcul_sat_parameter( int type
, elp_lotrs_param
*lotrsparam
, mcc_corner_info
*info
)
1276 static int fordebug
;
1280 if( type
== MCC_TRANS_N
) {
1285 wl
= (MCC_WN
+MCC_DWN
)/(MCC_LN
+MCC_DLN
) ;
1286 spipwl
= MCC_OPTIM_IDNSAT
;
1294 wl
= (MCC_WP
+MCC_DWP
)/(MCC_LP
+MCC_DLP
) ;
1295 spipwl
= MCC_OPTIM_IDPSAT
;
1299 if( lotrsparam
->ISVBSSET
)
1300 vbs
= lotrsparam
->VBS
;
1302 vbs
= lotrsparam
->VBULK
- vs
;
1304 n
= V_INT_TAB
[ __MCC_SAT_N
].VALUE
;
1306 tabvgs
= (double*)alloca( sizeof(double)*(n
-1) );
1307 tabids
= (double*)alloca( sizeof(double)*(n
-1) );
1309 vgsmax
= MCC_VDDmax
;
1310 mbk_pwl_get_value( spipwl
, MCC_VDDmax
, &imax
);
1313 ids0
= imax
*1.0/((double)n
);
1314 ids1
= imax
*2.0/((double)n
);
1317 mbk_pwl_get_inv_value( spipwl
, sgn
*ids0
, &vgs
);
1319 tabids
[0] = mcc_spicecurrent( vgs
, MCC_VDDmax
, vbs
, type
, lotrsparam
) ;
1320 mbk_pwl_get_inv_value( spipwl
, sgn
*ids1
, &vgs
);
1322 tabids
[1] = mcc_spicecurrent( vgs
, MCC_VDDmax
, vbs
, type
, lotrsparam
) ;
1324 pmin
= ( tabids
[1] - tabids
[0] ) / ( tabvgs
[1] - tabvgs
[0] ) ;
1325 pmax
= ( imax
- tabids
[1] ) / ( vgsmax
- tabvgs
[1] ) ;
1327 if( pmin
> 0.95 * pmax
) {
1335 while( onemoretime
);
1338 for( i
=3 ; i
<n
; i
++ ) {
1340 //ids = (imax-ids1)*((double)(i-2))/((double)(n-2))+ids1;
1341 ids
= (imax
-tabids
[1])*((double)(i
-2))/((double)(n
-2))+tabids
[1];
1343 mbk_pwl_get_inv_value( spipwl
, sgn
*ids
, &vgs
);
1346 tabids
[i
-1] = mcc_spicecurrent( tabvgs
[i
-1], MCC_VDDmax
, vbs
, type
, lotrsparam
) ;
1349 minerror
= MAXFLOAT
;
1352 for( i
=0 ; i
<(n
-2) ; i
++ ) {
1354 for( j
=(i
+1) ; j
<(n
-1) ; j
++ ) {
1356 r
= mcc_get_sat_parameter( tabvgs
[i
], tabids
[i
]/wl
,
1357 tabvgs
[j
], tabids
[j
]/wl
,
1366 error
= mcc_calcdiffmodelsat( *pt_vt
, MCC_VDDmax
, type
, lotrsparam
, minerror
, info
) ;
1367 if( error
< minerror
) {
1378 printf( "can't find a valid set of parameter A, B, VT (fordebug=%d)\n", fordebug
);
1387 void mcc_calcul_vt( int type
, elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
, mcc_corner_info
*info
)
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
);
1395 mcc_calcul_vt_new( type
, lotrsparam_n
, lotrsparam_p
);
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
);
1403 mcc_calcul_vt_old( type
, lotrsparam_n
, lotrsparam_p
, info
);
1407 double mcc_calcul_a(v1
,v2
,i1
,i2
,vt
,l
,w
)
1431 res
= (ai1
*ai2
*(g2
-g1
))/(g1
*g2
*ct
*((ai2
*g1
)-(ai1
*g2
))) ;
1436 double mcc_calcul_b(v1
,v2
,i1
,i2
,vt
,l
,w
)
1460 res
= ((ai2
*g1
*g1
)-(ai1
*g2
*g2
))/(g1
*g2
*((ai1
*g2
)-(ai2
*g1
))) ;
1465 void mcc_calcul_ab(v1
,v2
,i1
,i2
,vt
,l
,w
,a
,b
)
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
))) ;
1494 double mcc_calcul_r(v
,i
,l
,w
)
1510 double mcc_calcul_rs(v1
,i1
,v2
,i2
,l
,w
)
1522 return(fabs((v2
-v1
)/(i2
-i1
))*ct
);
1525 double mcc_calcul_k_error( int type
,
1543 for( i
=0 ; i
<n
; i
++ ) {
1545 imccsat
= mcc_current( tabvgs
[i
], tabvsat
[i
], vbs
, type
) ;
1546 imccmed
= mcc_current( tabvgs
[i
], tabvmed
[i
], vbs
, type
) ;
1548 error
= (imccsat
- tabispisat
[i
]) * (imccsat
- tabispisat
[i
])
1549 + (imccmed
- tabispimed
[i
]) * (imccmed
- tabispimed
[i
]) ;
1551 sumerror
= sumerror
+ error
;
1557 void mcc_calcul_k_new( int type
, elp_lotrs_param
*lotrsparam
)
1590 if( type
== MCC_TRANS_N
) {
1594 vlin0
= MCC_VDDmax
* MCC_KRNT
;
1595 vsat0
= MCC_VDDmax
* MCC_KRNS
;
1596 l
= MCC_LN
+MCC_DLN
;
1597 w
= MCC_WN
+MCC_DWN
;
1606 vlin0
= MCC_VDDmax
* MCC_KRPT
;
1607 vsat0
= MCC_VDDmax
* MCC_KRPS
;
1608 l
= MCC_LP
+MCC_DLP
;
1609 w
= MCC_WP
+MCC_DWP
;
1615 calc
= MCC_CALC_CUR
;
1616 if( MCC_VGS
== MCC_VDDmax
) {
1621 if( ( MCC_VGS
<= 1.1*vt
) || ( MCC_CALC_ORG
== MCC_CALC_MODE
) ) {
1622 if( MCC_CALC_ORG
== MCC_SIM_MODE
) {
1629 if( MCC_CALC_CUR
== MCC_SIM_MODE
)
1630 MCC_CALC_CUR
= MCC_CALC_MODE
;
1632 if( lotrsparam
->ISVBSSET
)
1633 vbs
= lotrsparam
->VBS
;
1635 vbs
= lotrsparam
->VBULK
- vs
;
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
;
1641 ispimaxvdd
= mcc_calcul_isat( MCC_VDDmax
, 0.0, type
) ;
1643 for( n
=0 ; n
<=2 ; 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
] ;
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
) ;
1656 minerror
= FLT_MAX
;
1658 for( n
=0 ; n
<=2 ; n
++ ) {
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
) ;
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
) ;
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
))) ;
1671 error
= mcc_calcul_k_error( type
, 0.0, 3, tabvgs
, vsat
, vmed
, ispisat
, ispimed
) ;
1672 if( error
< minerror
) {
1682 MCC_CALC_CUR
= calc
;
1685 void mcc_calcul_k(type
,lotrsparam
)
1687 elp_lotrs_param
*lotrsparam
;
1704 if( V_BOOL_TAB
[ __MCC_PRECISE_K
].VALUE
) {
1705 mcc_calcul_k_new( type
, lotrsparam
);
1709 calc
= MCC_CALC_CUR
;
1711 if(type
== MCC_TRANS_N
)
1713 if(MCC_VGS
== MCC_VDDmax
)
1720 if((MCC_VGS
<= (MCC_VTN
* 1.1)) || (MCC_CALC_ORG
== MCC_CALC_MODE
))
1722 if(MCC_CALC_ORG
== MCC_SIM_MODE
)
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
;
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
;
1737 if( lotrsparam
->ISVBSSET
)
1738 vbs
= lotrsparam
->VBS
;
1740 vbs
= lotrsparam
->VBULK
;
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
) ;
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
))) ;
1754 MCC_CALC_CUR
= calc
;
1755 if((MCC_KRN
<= 0.0) || (MCC_KSN
<= 0.0))
1763 if(MCC_VGS
== MCC_VDDmax
)
1770 if((MCC_VGS
<= (MCC_VTP
* 1.1)) || (MCC_CALC_ORG
== MCC_CALC_MODE
))
1772 if(MCC_CALC_ORG
== MCC_SIM_MODE
)
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
;
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
;
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
) ;
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
);
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
))) ;
1803 MCC_CALC_CUR
= calc
;
1804 if((MCC_KRP
<= 0.0) || (MCC_KSP
<= 0.0))
1812 float mcc_error_rst( mbk_pwl
*spipwl
, mcc_model
*mccpwl
, int nbmccpwl
, int debug
)
1834 while( nspi
< spipwl
->N
&& nmcc
< nbmccpwl
) {
1836 if( nspi
< spipwl
->N
-1 )
1837 maxspi
= spipwl
->DATA
[nspi
].X0
;
1839 maxspi
= spipwl
->X1
;
1841 if( maxspi
< mccpwl
[nmcc
].VMAX
) {
1846 currentv
= mccpwl
[nmcc
].VMAX
;
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
;
1854 interror
= ( currentv
- lastv
) * ( deltai
+ lastdeltai
) / 2.0 ;
1855 error
= error
+ fabs(interror
) ;
1858 printf( "%g %g %g %g %g\n", currentv
, ispi
, imcc
, interror
, error
);
1861 if( V_BOOL_TAB
[ __AVT_BUG_RSAT
].VALUE
)
1864 lastdeltai
= deltai
;
1877 void mcc_trs_corner( int type
, elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
, mcc_corner_info
*info
)
1879 stm_solver_maillon_list
*brhead
;
1880 stm_solver_maillon_list
*scan
;
1881 stm_solver_maillon
*stmm
[5] ;
1882 mcc_trans_spice trsspi
[5] ;
1888 lotrs_list lotrs
[5] ;
1893 n
= V_INT_TAB
[ __AVT_RST_N
].VALUE
;
1895 if( type
== MCC_TRANS_N
)
1900 for( i
=0 ; i
<n
; i
++ ) {
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 ;
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
;
1938 addlotrsmodel( &(lotrs
[i
]), trsspi
[i
].TRANSNAME
) ;
1940 chain
= addchain( NULL
, &trsspi
[i
] );
1942 stmm
[i
] = stm_solver_new_maillon();
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
,
1952 brhead
= stm_solver_maillon_addchain( brhead
, stmm
[i
] );
1955 brhead
= stm_solver_maillon_reverse( brhead
);
1957 for( scan
= brhead
; scan
->NEXT
; scan
= scan
->NEXT
);
1960 scan
->MAILLON
->VS
= 0.0 ;
1964 scan
->MAILLON
->VS
= MCC_VDDmax
;
1968 global
= mcc_getglobal() ;
1969 stm_solver_i( brhead
, out
, &ibranch
);
1970 mcc_setglobal( global
);
1972 info
->vdsmin
= fabs( stmm
[n
-1]->VD
- stmm
[n
-1]->VS
) ;
1973 info
->vgsmin
= fabs( trsspi
[0].VG
- stmm
[0]->VS
);
1975 for (i
=0; i
<n
; i
++) freeptype(trsspi
[i
].LOTRS
->USER
);
1976 stm_solver_maillon_freechain( brhead
);
1979 void mcc_calcul_rst_better( int type
, elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
, mcc_corner_info
*infos
)
1981 double *kl
, *ks
, *rl
, *rs
;
1982 mcc_trans_mcc trselp
;
1988 mcc_model mccpwl
[10] ;
1996 if( !MCC_OPTIM_MODE
)
1999 if( type
!= MCC_TRANS_N
&& type
!= MCC_TRANS_P
)
2002 if( type
== MCC_TRANS_N
) {
2008 spipwl
= MCC_OPTIM_IDNRES
;
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
)) ;
2017 trselp
.VT
= MCC_VTN
;
2018 trselp
.KVT
= MCC_KTN
;
2019 trselp
.VG
= MCC_VDDmax
;
2027 spipwl
= MCC_OPTIM_IDPRES
;
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
)) ;
2036 trselp
.VT
= MCC_VTP
;
2037 trselp
.KVT
= MCC_KTP
;
2039 trselp
.VB
= MCC_VDDmax
;
2042 trselp
.VDD
= MCC_VDDmax
;
2052 vlin
= infos
->vdsmin
;
2054 mbk_pwl_get_value( spipwl
, vlin
, &ilin
) ;
2057 *kl
= vlin
/ MCC_VDDmax
;
2058 *rl
= (w
/l
)*( vlin
/ ilin
) ;
2060 trselp
.VLIN
= (*kl
)*MCC_VDDmax
;
2061 trselp
.RNT
= (*rl
) ;
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
;
2071 for( nsat
= npwl
+1 ; nsat
< spipwl
->N
; nsat
++ ) {
2073 vsat
= spipwl
->DATA
[nsat
].X0
;
2074 isat
= fabs(spipwl
->DATA
[nsat
].A
* vsat
+ spipwl
->DATA
[nsat
].B
) ;
2076 trselp
.VSAT
= vsat
;
2077 trselp
.RNS
= (w
/l
)*(MCC_VDDmax
-vsat
)/(imax
-isat
) ;
2079 status
= mcc_mcc_characteristic( &trselp
, MCC_VDDmax
, 0.0, mccpwl
, &nbmccpwl
, 10 ) ;
2083 error
= mcc_error_rst( spipwl
, mccpwl
, nbmccpwl
, 0 );
2085 if( error
< besterror
) {
2087 *ks
= trselp
.VSAT
/ MCC_VDDmax
;
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.
2102 void mcc_calcul_rst( int type
, elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
)
2125 mcc_model mccpwl
[10];
2128 if( type
== MCC_TRANS_N
|| type
== MCC_TRANS_B
) {
2129 MCC_KRNS
= 3.0/4.0 ;
2130 MCC_KRNT
= 1.0/6.0 ;
2133 MCC_KRPS
= 3.0/4.0 ;
2134 MCC_KRPT
= 1.0/6.0 ;
2137 if( !MCC_OPTIM_MODE
)
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
;
2146 trs
.TRLENGTH
= (long)(0.5+MCC_LNeff
* ((double)SCALE_X
)) ;
2147 trs
.TRWIDTH
= (long)(0.5+MCC_WNeff
* ((double)SCALE_X
)) ;
2152 if( lotrsparam_n
->ISVBSSET
)
2153 vbs
= lotrsparam_n
->VBS
;
2155 vbs
= lotrsparam_n
->VBULK
;
2156 trs
.VG
= MCC_VDDmax
;
2160 vlinmax
= MCC_VDDmax
- MCC_VTP
;
2161 defaultvlin
= MCC_VDDmax
* MCC_KRPT
;
2162 defaultvsat
= MCC_VDDmax
* MCC_KRPS
;
2163 spipwl
= MCC_OPTIM_IDPRES
;
2165 trs
.TRLENGTH
= (long)(0.5+MCC_LPeff
* ((double)SCALE_X
)) ;
2166 trs
.TRWIDTH
= (long)(0.5+MCC_WPeff
* ((double)SCALE_X
)) ;
2171 if( lotrsparam_p
->ISVBSSET
)
2172 vbs
= lotrsparam_p
->VBS
;
2174 vbs
= lotrsparam_p
->VBULK
- MCC_VDDmax
;
2175 if( V_BOOL_TAB
[ __AVT_BUG_RSAT
].VALUE
) {
2176 trs
.VG
= MCC_VDDmax
;
2181 trs
.VB
= MCC_VDDmax
;
2185 k
= ((float)trs
.TRWIDTH
) / ((float)trs
.TRLENGTH
) ;
2186 trs
.VDD
= MCC_VDDmax
;
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%].
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 ) {
2201 imax
= fabs( spipwl
->DATA
[spipwl
->N
-1].A
* spipwl
->X1
+ spipwl
->DATA
[spipwl
->N
-1].B
) ;
2203 besterror
= MAXFLOAT
;
2206 while( npwl
< spipwl
->N
&& spipwl
->DATA
[npwl
].X0
<= vlinmax
) {
2208 vlin
= spipwl
->DATA
[npwl
].X0
;
2209 ilin
= fabs( spipwl
->DATA
[npwl
].A
*vlin
+ spipwl
->DATA
[npwl
].B
) ;
2212 trs
.RNT
= k
*vlin
/ilin
;
2214 for( nsat
= npwl
+1 ; nsat
< spipwl
->N
; nsat
++ ) {
2216 vsat
= spipwl
->DATA
[nsat
].X0
;
2217 isat
= fabs(spipwl
->DATA
[nsat
].A
* vsat
+ spipwl
->DATA
[nsat
].B
) ;
2220 trs
.RNS
= k
*(MCC_VDDmax
-vsat
)/(imax
-isat
) ;
2222 if( V_BOOL_TAB
[ __AVT_BUG_RSAT
].VALUE
)
2223 status
= mcc_mcc_characteristic( &trs
, MCC_VDDmax
, vbs
, mccpwl
, &nbmccpwl
, 10 ) ;
2225 status
= mcc_mcc_characteristic( &trs
, MCC_VDDmax
, 0.0, mccpwl
, &nbmccpwl
, 10 ) ;
2229 error
= mcc_error_rst( spipwl
, mccpwl
, nbmccpwl
, 0 );
2231 if( error
< besterror
) {
2234 bestvlin
= trs
.VLIN
;
2235 bestvsat
= trs
.VSAT
;
2244 if( type
== MCC_TRANS_N
|| type
== MCC_TRANS_B
) {
2247 MCC_KRNT
= bestvlin
/ MCC_VDDmax
;
2248 MCC_KRNS
= bestvsat
/ MCC_VDDmax
;
2253 MCC_KRPT
= bestvlin
/ MCC_VDDmax
;
2254 MCC_KRPS
= bestvsat
/ MCC_VDDmax
;
2260 void mcc_calcul_abr(type
,v1
,v2
,lotrsparam_n
,lotrsparam_p
)
2264 elp_lotrs_param
*lotrsparam_n
;
2265 elp_lotrs_param
*lotrsparam_p
;
2276 int valid_param_n
= 0,
2278 static int fordebug
;
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
)) ;
2287 stepr
= mcc_ftoi((MCC_VDDmax
* MCC_KRPT
) / ( MCC_DC_STEP
)) ;
2288 steprs
= mcc_ftoi((MCC_VDDmax
* MCC_KRPS
) / ( MCC_DC_STEP
)) ;
2291 vr
= MCC_DC_STEP
* stepr
;
2292 vrs
= MCC_DC_STEP
* steprs
;
2294 if((type
== MCC_TRANS_N
) || (type
== MCC_TRANS_B
))
2297 v1
= (MCC_VDDmax
-MCC_VTN
)/2.0 + MCC_VTN
;
2300 if( lotrsparam_n
->ISVBSSET
)
2301 vbs
= lotrsparam_n
->VBS
;
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
) ;
2313 // loop to satisfy B > 0.0
2314 while ( !valid_param_n
&& v1
< MCC_VDDmax
)
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
)
2320 else if ( (MCC_WNeff
/MCC_LNeff
)*MCC_AN
*(v1
-MCC_VTN
)*(v1
-MCC_VTN
) > i1
)
2325 MCC_BN
= fabs(mcc_calcul_b(v1
,v2
,i1
,i2
,MCC_VTN
,MCC_LN
+MCC_DLN
,MCC_WN
+MCC_DWN
)) ;
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
) ;
2332 if((type
== MCC_TRANS_P
) || (type
== MCC_TRANS_B
))
2335 v1
= (MCC_VDDmax
-MCC_VTP
)/2.0 + MCC_VTP
;
2338 if( lotrsparam_p
->ISVBSSET
)
2339 vbs
= lotrsparam_p
->VBS
;
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
) ;
2351 // loop to satisfy B > 0.0
2352 while ( !valid_param_p
&& v1
< MCC_VDDmax
)
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
)
2358 else if ( (MCC_WPeff
/MCC_LPeff
)*MCC_AP
*(v1
-MCC_VTP
)*(v1
-MCC_VTP
) > i1
)
2363 MCC_BP
= fabs(mcc_calcul_b(v1
,v2
,i1
,i2
,MCC_VTP
,MCC_LP
+MCC_DLP
,MCC_WP
+MCC_DWP
)) ;
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
) ;
2370 void mcc_calcul_vti(type
,lotrsparam_n
,lotrsparam_p
)
2372 elp_lotrs_param
*lotrsparam_n
;
2373 elp_lotrs_param
*lotrsparam_p
;
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
) ;
2386 void mcc_calcul_vdeg(type
,lotrsparam_n
,lotrsparam_p
)
2388 elp_lotrs_param
*lotrsparam_n
;
2389 elp_lotrs_param
*lotrsparam_p
;
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
) ;
2397 void mcc_calcul_raccess(type
,lotrsparam_n
,lotrsparam_p
)
2399 elp_lotrs_param
*lotrsparam_n
;
2400 elp_lotrs_param
*lotrsparam_p
;
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
);
2408 void mcc_get_np_vgs(float *vgsn
, float *vgsp
)
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;
2416 void mcc_drvspitab(spifile
,tab
,nbx
,nby
,lotrsparam_n
,lotrsparam_p
)
2421 elp_lotrs_param
*lotrsparam_n
;
2422 elp_lotrs_param
*lotrsparam_p
;
2425 char argv
[1024][8] ;
2426 double step
, val
[8] ;
2432 float vgsn
, vgsp
, rn
, rp
;
2435 if( (spifile
== MCC_PARAM
) || (spifile
== MCC_OPT_PARAM
) || (spifile
== MCC_CALC_PARAM
))
2437 strcpy(argv
[i
++],"vdnsat") ;
2438 strcpy(argv
[i
++],"vdnres") ;
2440 if(mcc_ftol(MCC_VGS
* 1000.0) != mcc_ftol(MCC_VDDmax
* 1000.0))
2441 strcpy(argv
[i
++],"vdnvgs") ;
2443 strcpy(argv
[i
++],"vdpsat") ;
2444 strcpy(argv
[i
++],"vdpres") ;
2446 if(mcc_ftol(MCC_VGS
* 1000.0) != mcc_ftol(MCC_VDDmax
* 1000.0))
2447 strcpy(argv
[i
++],"vdpvgs") ;
2449 strcpy(argv
[i
++],"vdddeg") ;
2450 strcpy(argv
[i
++],"vssdeg") ;
2454 for(i
= 0 ; i
< nbx
; i
++)
2455 sprintf(argv
[i
],"s%d",i
) ;
2458 if ( spifile
== MCC_OPT_PARAM
)
2459 nomout
= mbkstrdup (mcc_debug_prefix("param_opt.dat")) ;
2460 else if ( spifile
== MCC_CALC_PARAM
)
2462 nomout
= mbkstrdup (mcc_debug_prefix("param_calc.dat")) ;
2465 TRS_CURVS
.I_BSIM
[j
]=mbkalloc(sizeof(double)*TRS_CURVS
.nb
);
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
)
2475 file
= mbkfopen(nomout
,"dat",WRITE_TEXT
) ;
2476 avt_printExecInfo(file
, "#", "", "");
2480 fprintf(stderr
,"\nmcc error: can't open file %s.dat\n",nomout
) ;
2484 if( (spifile
== MCC_PARAM
) || (spifile
== MCC_OPT_PARAM
) || (spifile
== MCC_CALC_PARAM
))
2485 fprintf(file
,"#volt ") ;
2487 fprintf(file
,"#time ") ;
2489 for(i
= 0 ; i
< nbx
; i
++)
2491 fprintf(file
,"%s ",*(argv
+ i
)) ;
2493 fprintf(file
,"\n") ;
2497 if( lotrsparam_n
->ISVBSSET
)
2498 vbsn
= lotrsparam_n
->VBS
;
2500 vbsn
= lotrsparam_n
->VBULK
;
2501 if( lotrsparam_p
->ISVBSSET
)
2502 vbsp
= lotrsparam_p
->VBS
;
2504 vbsp
= lotrsparam_p
->VBULK
- MCC_VDDmax
;
2506 mcc_get_np_vgs(&vgsn
, &vgsp
);
2507 for(j
= 0 ; j
< nby
; j
++)
2509 fprintf(file
,"%.3e ",step
) ;
2510 if( (spifile
== MCC_PARAM
) || (spifile
== MCC_OPT_PARAM
) || (spifile
== MCC_CALC_PARAM
))
2513 rn
=mcc_spicecurrent(vgsn
,step
,vbsn
,MCC_TRANS_N
,lotrsparam_n
);
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
)
2528 TRS_CURVS
.I_BSIM
[k
][j
]=val
[k
];
2533 for(i
= 0 ; i
< nbx
; i
++)
2535 fprintf(file
,"%.3e ",tab
[i
][j
]) ;
2538 fprintf(file
,"\n") ;
2540 if( (spifile
== MCC_PARAM
) || (spifile
== MCC_OPT_PARAM
) || (spifile
== MCC_CALC_PARAM
))
2541 step
+= MCC_DC_STEP
;
2543 step
+= (V_FLOAT_TAB
[ __SIM_TRAN_STEP
].VALUE
) ;
2546 if(fclose(file
) != 0)
2548 fprintf(stderr
,"\nmcc error: can't close file %s.dat\n",nomout
) ;
2555 void mcc_prsspifile(spifile
,nbx
,nby
,tab
)
2569 fileout
= sim_getjoker(MCC_SPICEOUT
,mcc_debug_prefix(MCC_SPICEFILE
[spifile
])) ;
2571 if(spifile
== MCC_PARAM
)
2574 argv
[i
++] = mcc_initstr("vdnsat") ;
2575 argv
[i
++] = mcc_initstr("vdnres") ;
2577 argv
[i
++] = mcc_initstr("vdnvgs") ;
2578 argv
[i
++] = mcc_initstr("vdpsat") ;
2579 argv
[i
++] = mcc_initstr("vdpres") ;
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
;
2589 mccstep
= (V_FLOAT_TAB
[ __SIM_TRAN_STEP
].VALUE
) ;
2590 limit
= (V_FLOAT_TAB
[ __SIM_TIME
].VALUE
) ;
2591 for(x
= 0 ; x
< nbx
; x
++)
2593 sprintf(buf
,"s%d",x
) ;
2594 argv
[x
] = mcc_initstr(buf
) ;
2598 sim_readspifiletab (fileout
,argv
,nbx
,nby
,tab
,limit
,mccstep
) ;
2600 for(x
= 0 ; x
< nbx
; x
++)
2602 for(y
= 0 ; y
< nby
; y
++)
2604 tab
[x
][y
] = fabs(tab
[x
][y
]);
2607 for(x
= 0 ; x
< nbx
; x
++)
2613 void mcc_addspidata(type
,lotrsparam_n
,lotrsparam_p
)
2615 elp_lotrs_param
*lotrsparam_n
;
2616 elp_lotrs_param
*lotrsparam_p
;
2624 tabsize
= mcc_ftoi(MCC_VDDmax
/ MCC_DC_STEP
) ;
2627 if((type
== MCC_TRANS_N
) || (type
== MCC_TRANS_B
))
2629 vdddeg
= mcc_spicevdeg(MCC_TRANS_N
,lotrsparam_n
) ;
2631 if( lotrsparam_n
->ISVBSSET
)
2632 vbs
= lotrsparam_n
->VBS
;
2634 vbs
= lotrsparam_n
->VBULK
;
2635 for(i
= 0 ; i
< tabsize
; i
++)
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))
2641 MCC_IDNVGS
[i
] = mcc_spicecurrent(MCC_VGS
,step
,vbs
,MCC_TRANS_N
,lotrsparam_n
) ;
2643 MCC_VDDDEG
[i
] = vdddeg
;
2644 step
+= MCC_DC_STEP
;
2648 if((type
== MCC_TRANS_P
) || (type
== MCC_TRANS_B
))
2650 vssdeg
= mcc_spicevdeg(MCC_TRANS_P
,lotrsparam_p
) ;
2652 if( lotrsparam_p
->ISVBSSET
)
2653 vbs
= lotrsparam_p
->VBS
;
2655 vbs
= lotrsparam_p
->VBULK
- MCC_VDDmax
;
2656 for(i
= 0 ; i
< tabsize
; i
++)
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))
2662 MCC_IDPVGS
[i
] = mcc_spicecurrent(MCC_VGS
,step
,vbs
,MCC_TRANS_P
,lotrsparam_p
) ;
2664 MCC_VSSDEG
[i
] = vssdeg
;
2665 step
+= MCC_DC_STEP
;
2668 MCC_CALC_CUR
= MCC_SIM_MODE
;
2671 void mcc_readspidata(fit
,lotrsparam_n
,lotrsparam_p
)
2673 elp_lotrs_param
*lotrsparam_n
;
2674 elp_lotrs_param
*lotrsparam_p
;
2680 double seuil
= MCC_VDDmax
/2.0 ;
2681 double sfl
= MCC_VDDmax
*0.1 ;
2682 double sfh
= MCC_VDDmax
*0.9 ;
2688 double *ptparam
[8] ;
2695 char oldMCC_CALC_ORG
;
2697 sim_set_result_file_extension('p', 1, &MCC_SPICEOUT
);
2699 MCC_FLAG_FIT
= MCC_FIT_OK
;
2701 tabsize
= mcc_ftoi(MCC_VDDmax
/ MCC_DC_STEP
) ;
2704 mcc_allocspidata(MCC_TRANS_B
) ;
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
;
2718 if(MCC_CALC_CUR
== MCC_SIM_MODE
)
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
;
2726 TRS_CURVS
.I_SIMU
[k
]=mbkalloc(sizeof(double)*tabsize
);
2727 memcpy(TRS_CURVS
.I_SIMU
[k
], ptparam
[k
], sizeof(double)*tabsize
);
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
;
2737 if ( MCC_PLOT
&& !MCC_OPTIM_MODE
)
2739 mcc_addspidata(MCC_TRANS_B
,lotrsparam_n
,lotrsparam_p
) ;
2740 mcc_drvspitab(MCC_PARAM
,ptparam
,i
,tabsize
,lotrsparam_n
,lotrsparam_p
) ;
2742 if ( MCC_OPTIM_MODE
)
2744 mcc_optim_addspidata (MCC_TRANS_B
,lotrsparam_n
,lotrsparam_p
) ;
2747 TRS_CURVS
.I_OPTIM
[k
]=mbkalloc(sizeof(double)*tabsize
);
2748 memcpy(TRS_CURVS
.I_OPTIM
[k
], ptparam
[k
], sizeof(double)*tabsize
);
2751 mcc_drvspitab(MCC_PARAM
,ptparam
,i
,tabsize
,lotrsparam_n
,lotrsparam_p
) ;
2753 mcc_drvspitab(MCC_OPT_PARAM
,ptparam
,i
,tabsize
,lotrsparam_n
,lotrsparam_p
) ;
2760 sim_set_result_file_extension('p', 0, &MCC_SPICEOUT
);
2762 tabsize
= mcc_ftoi(V_FLOAT_TAB
[ __SIM_TIME
].VALUE
/ V_FLOAT_TAB
[ __SIM_TRAN_STEP
].VALUE
) ;
2765 MCC_FITS
= (double **)mbkalloc((MCC_INSNUMB
+ 1) * sizeof(double *)) ;
2767 for(i
= 0 ; i
<= MCC_INSNUMB
; i
++)
2768 MCC_FITS
[i
] = (double *)mbkalloc(tabsize
*sizeof(double)) ;
2770 for(f
= 0 ; f
< MCC_SPICENB
- 1 ; f
++)
2772 mcc_prsspifile(f
,MCC_INSNUMB
+1,tabsize
,MCC_FITS
) ;
2773 mcc_drvspitab(f
,MCC_FITS
,MCC_INSNUMB
+1,tabsize
,lotrsparam_n
,lotrsparam_p
) ;
2783 for(i
= 3 ; i
<= MCC_INSNUMB
- 2 ; i
++)
2795 sfl
= (MCC_VDDmax
- MCC_VTP
)/4.0 ;
2796 sfh
= (MCC_VDDmax
- MCC_VTP
) ;
2801 sfh
= (3.0*MCC_VDDmax
+ MCC_VTN
)/4.0 ;
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
) ;
2809 if((delay
> 0) && (slope
> 0))
2813 slopeu
+= slope
* 1000.0 ;
2819 if((delay
> 0) && (slope
> 0))
2823 sloped
+= slope
* 1000.0 ;
2828 if((nbtimeud
!= 0) && (nbtimedu
!= 0))
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
) ;
2847 for(i
= 1 ; i
<= MCC_INSNUMB
- 3 ; i
++)
2859 sfl
= (MCC_VDDmax
- MCC_VTP
)/4.0 ;
2860 sfh
= (MCC_VDDmax
- MCC_VTP
) ;
2865 sfh
= (3.0*MCC_VDDmax
+ MCC_VTN
)/4.0 ;
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
) ;
2872 if((delay
> 0) && (slope
> 0))
2876 slopeu
+= slope
* 1000.0 ;
2882 if((delay
> 0) && (slope
> 0))
2886 sloped
+= slope
* 1000.0 ;
2891 if((nbtimeud
!= 0) && (nbtimedu
!= 0))
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
) ;
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
;
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
;
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
;
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
;
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
;
2946 sim_set_result_file_extension('p', 1, &MCC_SPICEOUT
);
2950 void mcc_allocspidata(type
)
2955 tabsize
= mcc_ftoi(MCC_VDDmax
/ MCC_DC_STEP
) ;
2958 if((type
== MCC_TRANS_N
) || (type
== MCC_TRANS_B
))
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
;
2969 if((type
== MCC_TRANS_P
) || (type
== MCC_TRANS_B
))
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
;
2982 void mcc_freespidata(fit
,type
)
2988 if(MCC_CALC_CUR
== MCC_SIM_MODE
)
2990 if((type
== MCC_TRANS_N
) || (type
== MCC_TRANS_B
))
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
)
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))
3005 mbk_pwl_free_pwl ( MCC_OPTIM_IDNVGS
);
3006 MCC_OPTIM_IDNVGS
= NULL
;
3010 if((type
== MCC_TRANS_P
) || (type
== MCC_TRANS_B
))
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
)
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))
3025 mbk_pwl_free_pwl ( MCC_OPTIM_IDPVGS
);
3026 MCC_OPTIM_IDPVGS
= NULL
;
3037 for(i
= 0 ; i
<= MCC_INSNUMB
; i
++)
3038 mbkfree(MCC_FITS
[i
]) ;
3044 void mcc_runspice (int fit
)
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
);
3053 void mcc_genspicom(file
,filename
,lotrsparam_n
,lotrsparam_p
)
3056 elp_lotrs_param
*lotrsparam_n
;
3057 elp_lotrs_param
*lotrsparam_p
;
3060 char basename
[1024] ;
3064 char *subcktmodeln
, *subcktmodelp
;
3065 char *modeln
, *modelp
;
3074 lotrsparam_n
= NULL
;
3075 lotrsparam_p
= NULL
;
3077 bs3
= ( MCC_SPICEMODELTYPE
== MCC_BSIM3V3
? 1 : 0 ) ;
3078 bs4
= ( MCC_SPICEMODELTYPE
== MCC_BSIM4
? 1 : 0 ) ;
3080 modeln
= MCC_TNMODEL
;
3081 modelp
= MCC_TPMODEL
;
3085 strcpy(model
,filename
) ;
3086 pt
= strchr(model
,(int)('.')) ;
3089 strcpy(basename
,model
) ;
3090 pt
= strstr(model
,"_sim") ;
3101 fprintf(file
,"****spice description of %s\n",filename
);
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
);
3110 fprintf(file
,".include \"%s\"\n",MCC_TECHFILE
);
3114 subcktmodeln
= mcc_getsubckt( MCC_MODELFILE
,
3121 subcktmodelp
= mcc_getsubckt( MCC_MODELFILE
,
3129 if ((subcktmodeln
!= NULL
) && (issim
!= 0))
3130 /*- le model est dans un subckt -*/
3132 sprintf(bufn
,"xm") ;
3133 modeln
= subcktmodeln
;
3136 if ((subcktmodelp
!= NULL
) && (issim
!= 0))
3137 /*- le model est dans un subckt -*/
3139 sprintf(bufp
,"xm") ;
3140 modelp
= subcktmodelp
;
3143 mn
= mbkstrdup(bufn
) ;
3144 mp
= mbkstrdup(bufp
) ;
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
)
3156 fprintf(file
,"c1 out vss %gf\n",MCC_CAPA
) ;
3158 else if(strstr(model
,"fit_cg") !=NULL
|| strstr(model
,"fit_cg_nocapa") !=NULL
)
3160 for(i
= 0 ; i
< MCC_INVNUMB
; i
++)
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
) ;
3174 else if(strstr(model
,"fit_cdn") != NULL
)
3176 for(i
= 0 ; i
< MCC_TRANSNUMB
; i
++)
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
);
3184 else if(strstr(model
,"fit_cdp") !=NULL
)
3186 for(i
= 0 ; i
< MCC_TRANSNUMB
; i
++)
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
);
3197 fprintf(file
,".ends inv\n");
3199 fprintf(file
,"\n") ;
3201 fprintf(file
,".subckt %s",model
) ;
3203 for(i
= 0 ; i
< MCC_INSNUMB
+ 1 ; i
++)
3205 fprintf(file
," s%d",i
) ;
3208 fprintf(file
," vbn vbp vdd vss\n") ;
3210 for(i
= 0 ; i
< MCC_INSNUMB
; i
++)
3212 fprintf(file
,"xinv%d s%d s%d vbn vbp vdd vss inv\n",i
,i
,i
+1) ;
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
);
3221 fprintf(file
,".ends %s\n",model
) ;
3225 fprintf(file
,"\n") ;
3226 fprintf(file
,"x%s",model
) ;
3228 for(i
= 0 ; i
< MCC_INSNUMB
+ 1 ; i
++)
3230 fprintf(file
," s%d",i
) ;
3233 fprintf(file
," vbn vbp vdd 0 %s\n",model
);
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") ;
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
)
3248 for(i
= 0 ; i
< MCC_INSNUMB
+ 1 ; i
++)
3249 fprintf(file
,".print tran v(s%d)\n",i
) ;
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");
3259 void mcc_genspi(fit
,lotrsparam_n
,lotrsparam_p
)
3261 elp_lotrs_param
*lotrsparam_n
;
3262 elp_lotrs_param
*lotrsparam_p
;
3266 char *subcktmodeln
, *subcktmodelp
;
3267 char *modeln
, *modelp
, *name
;
3270 char bufp
[1024], buf
[1024] ;
3275 bs3
= ( MCC_SPICEMODELTYPE
== MCC_BSIM3V3
? 1 : 0 ) ;
3276 bs4
= ( MCC_SPICEMODELTYPE
== MCC_BSIM4
? 1 : 0 ) ;
3277 modeln
= MCC_TNMODEL
;
3278 modelp
= MCC_TPMODEL
;
3282 subcktmodeln
= mcc_getsubckt( MCC_MODELFILE
,
3289 subcktmodelp
= mcc_getsubckt( MCC_MODELFILE
,
3297 if (subcktmodeln
!= NULL
) /*- le model est dans un subckt -*/
3299 sprintf(bufn
,"xm") ;
3300 modeln
= subcktmodeln
;
3303 if (subcktmodelp
!= NULL
) /*- le model est dans un subckt -*/
3305 sprintf(bufp
,"xm") ;
3306 modelp
= subcktmodelp
;
3308 mn
= mbkstrdup(bufn
) ;
3309 mp
= mbkstrdup(bufp
) ;
3311 if(MCC_CALC_CUR
== MCC_SIM_MODE
)
3313 name
=mcc_debug_prefix(MCC_SPICEFILE
[MCC_PARAM
]);
3314 file
= mcc_fopen(name
,"w") ;
3315 avt_printExecInfo(file
, "*", "", "");
3317 mcc_get_np_vgs(&vgsn
, &vgsp
);
3319 fprintf(file
,"* TAS PARAMETRISATION\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
);
3328 fprintf(file
,".include \"%s\"\n",MCC_TECHFILE
);
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))
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
);
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))
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
);
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
);
3365 fprintf(file
,"rvdddeg vdddeg 0 1e9\n");
3366 fprintf(file
,"rvssdeg vssdeg vdd 1e9\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))
3373 fprintf(file
,"vgsnmax vgsn 0 dc %gv\n",vgsn
);
3374 fprintf(file
,"vgspmax vdd vgsp dc %gv\n",vgsp
);
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))
3384 fprintf(file
,"vdnvgs 2 222 dc 0\n");
3385 fprintf(file
,"vdpvgs 3 333 dc 0\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" );
3400 if ( V_INT_TAB
[__SIM_TOOL
].VALUE
== SIM_TOOL_TITAN
|| V_INT_TAB
[__SIM_TOOL
].VALUE
== SIM_TOOL_TITAN7
)
3404 if ((c
=strrchr(buf
,'.'))!=NULL
) *c
='\0';
3405 fprintf(file
,".save %s\n", buf
);
3407 fprintf(file
,".end\n");
3409 mcc_fclose(file
,name
);
3415 for(i = 0 ; i < MCC_TASNB ; i++)
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);
3423 for(i
= 0 ; i
< MCC_SPICENB
- 1 ; i
++)
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
);
3433 void mcc_calcspicedelay(filename
,namelist
,start
,vthr
,vsthrl
,vsthrh
,tabres
)
3435 chain_list
*namelist
;
3457 for(chain
= namelist
; chain
!= NULL
; chain
= chain
->NEXT
,nbx
++)
3459 argv
[nbx
] = (char*)chain
->DATA
;
3462 nby
= mcc_ftoi(V_FLOAT_TAB
[ __SIM_TIME
].VALUE
/ V_FLOAT_TAB
[ __SIM_TRAN_STEP
].VALUE
) ;
3465 tab
= (double **)mbkalloc(nbx
* sizeof(double *)) ;
3467 for(i
= 0 ; i
< nbx
; i
++)
3468 tab
[i
] = (double *)mbkalloc(nby
*sizeof(double)) ;
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
) ;
3474 resfilename
= strdup(filename
);
3475 pt
= strchr(resfilename
,'.');
3477 if ((resfile
= mbkfopen(resfilename
,"dat",WRITE_TEXT
)) != NULL
)
3479 avt_printExecInfo(resfile
, "#", "", "");
3480 for(i
= 0 , j
= 0 ; i
< nbx
; i
++ , j
+=2)
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);
3489 fprintf(resfile
,"# Data extracted from %s\n\n",fileout
);
3491 for(i
= 0 , j
= 0 ; i
< nbx
; i
++ , j
+=2)
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");
3504 fprintf(stderr
, "\nmcc error: can't open file %s.dat\n",resfilename
);
3509 mbkfree(resfilename
) ;
3511 for(i
= 0 ; i
< nbx
; i
++)
3516 int mcc_modeltype_known ( int modeltype
)
3520 switch ( modeltype
) {
3534 void mcc_genparam(modelname
,type
,l
,w
,vdd
,lotrs
,lotrscase
,lotrsparam
)
3542 elp_lotrs_param
*lotrsparam
;
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;
3552 long pd_s
,xd_s
,ps_s
,xs_s
;
3555 double vbulkn
, vbulkp
;
3557 mcc_corner_info info
;
3561 mcc_update_technoparams (modelname
,type
,l
,w
,lotrs
,lotrscase
);
3563 switch ( lotrscase
) {
3564 case MCC_BEST
: MCC_VDDmax
= MCC_VDD_BEST
;
3565 MCC_TEMP
= MCC_TEMP_BEST
;
3567 case MCC_WORST
: MCC_VDDmax
= MCC_VDD_WORST
;
3568 MCC_TEMP
= MCC_TEMP_WORST
;
3570 default : MCC_VDDmax
= vdd
;
3573 MCC_VGS
= MCC_VDDmax
/2.0;
3575 if(type
== MCC_TRANS_N
)
3577 lscale
= MCC_LN
*1.0e-6 ;
3578 wscale
= MCC_WN
*1.0e-6 ;
3582 lscale
= MCC_LP
*1.0e-6 ;
3583 wscale
= MCC_WP
*1.0e-6 ;
3586 MCC_CALC_CUR
= MCC_CALC_MODE
;
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
);
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
;
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;
3617 lotrsparam_n
= mcc_init_lotrsparam ();
3618 lotrsparam_p
= mcc_init_lotrsparam ();
3619 lotrsparam_n
->VBULK
= 0.0;
3620 lotrsparam_p
->VBULK
= MCC_VDDmax
;
3623 lotrsparam_p
->SUBCKTNAME
=NULL
;
3624 lotrsparam_n
->SUBCKTNAME
=NULL
;
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
;
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
;
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
;
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
;
3653 if ( (getptype (lotrs->USER,CNS_UNUSED)) ) {
3654 vbs = 0.0; // to avoid error while cheking vbs for an unused lotrs
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 ) {
3662 vbulkn
= lotrsparam_n
->VBULK
;
3663 vbulkp
= lotrsparam_p
->VBULK
;
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
);
3672 mcc_calcspiparam(type
,lotrsparam_n
,lotrsparam_p
) ;
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
) ;
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
) {
3686 mcc_calcul_sat_parameter( MCC_TRANS_N
, lotrsparam_n
, &info
);
3689 mcc_calcul_sat_parameter( MCC_TRANS_P
, lotrsparam_p
, &info
);
3692 mcc_calcul_sat_parameter( MCC_TRANS_N
, lotrsparam_n
, &info
);
3693 mcc_calcul_sat_parameter( MCC_TRANS_P
, lotrsparam_p
, &info
);
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
;
3701 v1
= (MCC_VDDmax
-MCC_VTP
)/2.0 + MCC_VTP
;
3703 if ( MCC_NEW_CALC_ABR
&& MCC_OPTIM_MODE
)
3704 mcc_get_best_abr_from_vt ( type
, lotrsparam_n
,lotrsparam_p
, &info
);
3706 mcc_calcul_abr(type
,v1
,v2
,lotrsparam_n
,lotrsparam_p
) ;
3709 if( V_BOOL_TAB
[__AVT_RST_BETTER
].VALUE
) {
3710 mcc_calcul_rst_better(type
,lotrsparam_n
,lotrsparam_p
, &info
);
3713 mcc_calcul_rst(type
,lotrsparam_n
,lotrsparam_p
);
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
) ;
3725 mcc_cleanmodel( model
);
3727 if ( V_BOOL_TAB
[__ELP_DRV_FILE
].VALUE
)
3728 driveall
= (ELP_MODEL_LIST
== NULL
) ? MCC_DRV_ALL_MODEL
: MCC_DRV_ONE_MODEL
;
3730 driveall
= MCC_DONOT_DRV_MODEL
;
3733 lotrsparam_n
->VBULK
= vbulkn
;
3734 lotrsparam_p
->VBULK
= vbulkp
;
3736 mcc_drvelp(MCC_PARAM
, type
,lotrsparam_n
,lotrsparam_p
,driveall
) ;
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
);
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
);
3765 elp_lotrs_param_free ( lotrsparam_n
);
3766 elp_lotrs_param_free ( lotrsparam_p
);
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);
3775 void mcc_setelpparam ( void )
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
;
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
3811 if( type
== MCC_TRANS_N
) {
3813 pwl
= MCC_OPTIM_IDNSAT
;
3821 pwl
= MCC_OPTIM_IDPSAT
;
3828 vstep
= (MCC_VDDmax
- vt
)/100.0 ;
3829 minerror
= FLT_MAX
;
3831 for( v
= vt
+vstep
; v
< MCC_VDDmax
; v
= v
+ vstep
) {
3833 mcc_calcul_abr( type
, v
, MCC_VDDmax
, lotrsparam_n
, lotrsparam_p
);
3835 if( V_BOOL_TAB
[ __MCC_ALLOW_NEGATIVE_B
].VALUE
) {
3836 if( *pt_b
<= -1.0/(MCC_VDDmax
-vt
) )
3839 error
= mcc_calcdiffmodelsat( vt
, MCC_VDDmax
, type
, lotrsparam_n
, -1.0, info
);
3842 error
= mcc_calcdiffmodelsat( vt
, MCC_VDDmax
, type
, lotrsparam_n
, -1.0, info
);
3843 if( error
<= minerror
) {
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
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
;
3872 double exitvalue
=-1, step
=FLT_MAX
, cnt
=0;
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
);
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
) {
3891 if (nbpoints
-i
-1<OPTIM3
) step
=1;
3892 else step
=OPTIM3
/(nbpoints
-i
-1);
3895 if (cnt
<1) continue;
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
) )
3904 error
= mcc_calcdiffmodelsat(MCC_VTN
,MCC_VDDmax
,type
,lotrsparam_n
,exitvalue
, info
) ;
3907 error
= mcc_calcdiffmodelsat(MCC_VTN
,MCC_VDDmax
,type
,lotrsparam_n
,exitvalue
, info
) ;
3908 if ( error
<= olderror
) {
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
) {
3940 if (nbpoints
-i
-1<OPTIM3
) step
=1;
3941 else step
=OPTIM3
/(nbpoints
-i
-1);
3944 if (cnt
<1) continue;
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
) )
3953 error
= mcc_calcdiffmodelsat(MCC_VTP
,MCC_VDDmax
,type
,lotrsparam_p
,exitvalue
, info
) ;
3956 error
= mcc_calcdiffmodelsat(MCC_VTP
,MCC_VDDmax
,type
,lotrsparam_p
,exitvalue
, info
) ;
3957 if ( error
<= olderror
) {
3982 void mcc_update_technoparams (char *modelname
,int type
, double l
, double w
,lotrs_list
*lotrs
,int lotrscase
)
3984 mcc_modellist
*model
=NULL
;
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
)) )
3994 if((l
<= 0.0) || (w
<= 0.0))
3996 avt_errmsg(MCC_ERRMSG
, "002", AVT_ERROR
, modelname
,mcc_ftol(l
*1e03
),mcc_ftol(w
*1e03
));
4000 mcc_init_globals ();
4002 MCC_CURRENT_LOTRS
= lotrs
;
4004 if ( avt_islog (1,LOGMCC
))
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
);
4017 mbkfree(MCC_ELPFILE
);
4018 MCC_ELPFILE
= mbkstrdup(elpTechnoFile
) ;
4021 if(type
== MCC_TRANS_N
)
4023 if((l
> 0.0) && (w
> 0.0))
4025 MCC_NCASE
= lotrscase
;
4028 if(MCC_TNMODEL
!= NULL
)
4030 if(strcmp(MCC_TNMODEL
,modelname
) != 0)
4032 mbkfree(MCC_TNMODEL
) ;
4033 MCC_TNMODEL
= mcc_initstr(modelname
) ;
4038 MCC_TNMODEL
= mcc_initstr(modelname
) ;
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
));
4051 if((l
> 0.0) && (w
> 0.0))
4053 MCC_PCASE
= lotrscase
;
4056 if(MCC_TPMODEL
!= NULL
)
4058 if(strcmp(MCC_TPMODEL
,modelname
) != 0)
4060 mbkfree(MCC_TPMODEL
) ;
4061 MCC_TPMODEL
= mcc_initstr(modelname
) ;
4066 MCC_TPMODEL
= mcc_initstr(modelname
) ;
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
));
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
)
4090 double lscale
,wscale
;
4097 Ileak
= mcc_calcILeakage (MCC_MODELFILE
, modelname
,
4100 lscale
, wscale
, MCC_TEMP
,
4105 if ( avt_islog (2,LOGMCC
))
4107 avt_log(LOGMCC
,2," ITotal leak = %g (vgs=%g,vds=%g,vbs=%g)\n",
4110 avt_log(LOGMCC
,2," B leak = %g (vgs=%g,vds=%g,vbs=%g)\n",
4111 *BLeak
,vgs
,vds
,vbs
);
4113 avt_log(LOGMCC
,2," D leak = %g (vgs=%g,vds=%g,vbs=%g)\n",
4114 *DLeak
,vgs
,vds
,vbs
);
4116 avt_log(LOGMCC
,2," S leak = %g (vgs=%g,vds=%g,vbs=%g)\n",
4117 *SLeak
,vgs
,vds
,vbs
);
4125 void mcc_genspi_for_inverter_simulator(elp_lotrs_param
*lotrsparam_n
,elp_lotrs_param
*lotrsparam_p
)
4129 char *subcktmodeln
, *subcktmodelp
, *fileout
;
4130 char *modeln
, *modelp
, *name
;
4131 char *mn
, *mp
, *c
, *dir
;
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
;
4138 mcc_modellist
*ptmodel
;
4141 bs3
= ( MCC_SPICEMODELTYPE
== MCC_BSIM3V3
? 1 : 0 ) ;
4142 bs4
= ( MCC_SPICEMODELTYPE
== MCC_BSIM4
? 1 : 0 ) ;
4143 modeln
= MCC_TNMODEL
;
4144 modelp
= MCC_TPMODEL
;
4148 ptmodel
= mcc_getmodel ( MCC_MODELFILE
,
4154 subcktmodeln
= mcc_getsubckt( MCC_MODELFILE
,
4161 subcktmodelp
= mcc_getsubckt( MCC_MODELFILE
,
4169 if (subcktmodeln
!= NULL
) /*- le model est dans un subckt -*/
4171 sprintf(bufn
,"xm") ;
4172 modeln
= subcktmodeln
;
4175 if (subcktmodelp
!= NULL
) /*- le model est dans un subckt -*/
4177 sprintf(bufp
,"xm") ;
4178 modelp
= subcktmodelp
;
4180 mn
= mbkstrdup(bufn
) ;
4181 mp
= mbkstrdup(bufp
) ;
4183 sim_set_result_file_extension('p', 0, &MCC_SPICEOUT
);
4189 name
=mbkstrdup(mcc_debug_prefix(i
==0?"inverter_rf.spi":"inverter_fr.spi"));
4191 if ((c
=strrchr(buf
,'.'))!=NULL
) *c
='\0';
4193 file
= mcc_fopen(name
,"w") ;
4194 avt_printExecInfo(file
, "*", "", "");
4195 mcc_get_np_vgs(&vgsn
, &vgsp
);
4197 fprintf(file
,"* TAS PARAMETRISATION\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
);
4206 fprintf(file
,".include \"%s\"\n",MCC_TECHFILE
);
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
);
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
);
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
);
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
) ;
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");
4232 fprintf(file
,"\nxinst i sig o %s\n", buf
);
4234 fprintf(file
,".option tnom=%g\n", V_FLOAT_TAB
[__SIM_TNOM
].VALUE
);
4235 fprintf(file
,".temp %g\n",MCC_TEMP
);
4237 #define RANGELIMIT 0.005
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))
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;
4246 fprintf(file
,"+)\n") ;
4248 fprintf(file
,".tran %gn %gn\n",V_FLOAT_TAB
[ __SIM_TRAN_STEP
].VALUE
*1e9
,V_FLOAT_TAB
[ __SIM_TIME
].VALUE
*1e9
) ;
4250 fprintf(file
,".print tran v(i)\n");
4251 fprintf(file
,".print tran v(sig)\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
);
4256 fprintf(file
,".end\n");
4258 mcc_fclose(file
,name
);
4260 sim_execspice(name
,0,MCC_SPICENAME
,MCC_SPICESTRING
,MCC_SPICESTDOUT
);
4262 fileout
= sim_getjoker(MCC_SPICEOUT
,buf
) ;
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)) ;
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
) ;
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
++) ;
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
++) ;
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
;
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);
4287 // printf("vdd/2: %g\n", t_vdd_sur_2);
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 ;
4295 TRS_CURVS
.SIMUINV
[i
][j
]=(double *)mbkalloc(sizeof(double)*TRS_CURVS
.nbdyna
);
4297 for (j
=0; j
<mcc_ftoi(V_FLOAT_TAB
[ __SIM_TIME
].VALUE
/V_FLOAT_TAB
[ __SIM_TRAN_STEP
].VALUE
)+1; j
++)
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
];
4303 mcc_fclose(file
,bufp
);
4304 for(j
= 0 ; j
< nbdata
; j
++)
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
) ;
4315 fprintf(file
,"set key bottom left\n");
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
) ;
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") ;
4334 mcc_fclose(file
,bufp
);
4336 if (i
!=1) mbkfree(name
);
4341 mcc_bilan_capa_simulated_inverter(lotrsparam_n
,lotrsparam_p
, maxl
);
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*/);
4347 avt_sethashvar("tasSimulateInverterConfig", bufn
);
4348 avt_sethashvar("tasDebugPwl", "sig");
4349 sprintf( tbuf
, "top_%s", buf
);
4350 c
=strchr( tbuf
,'.');
4353 if( getloadedlofig( 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
) )
4361 mcc_runtas_tcl(name
,MCC_SLOPE
,0,NULL
,buf
);
4362 avt_sethashvar("tasSimulateInverter", NULL
);
4363 avt_sethashvar("tasSimulateInverterConfig", NULL
);
4366 // mcc_runtas_tcl(gate,slope,capa,buf1,NULL) ;
4370 void mcc_calcul_ibranch(elp_lotrs_param
*lotrsparam_n
,elp_lotrs_param
*lotrsparam_p
)
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' );
4382 void mcc_calcul_ibranch_mcc( elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
, double *tabin
, double *tabip
, int n
, char mode
)
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
;
4393 chain_list
*chain
, *tofree
=NULL
;
4396 stmm
= alloca( sizeof( stm_solver_maillon
* )*n
) ;
4398 trselp
= alloca( sizeof( mcc_trans_mcc
) * n
);
4400 trsmcc
= alloca( sizeof( mcc_trans_spice
) * n
);
4401 lotrs
= alloca( sizeof( lotrs_list
) * n
);
4404 for( trs
=0 ; trs
<2 ; trs
++ ) {
4406 for( i
=1 ; i
<=n
; i
++ ) {
4408 stmm
[i
-1] = stm_solver_new_maillon();
4413 mcc_trans_mcc_from_global( MCC_TRANS_N
, &(trselp
[i
-1]) );
4415 mcc_trans_mcc_from_global( MCC_TRANS_P
, &(trselp
[i
-1]) );
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
,
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 ;
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
)
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
);
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
) ;
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
,
4472 brhead
= stm_solver_maillon_addchain( brhead
, stmm
[i
-1] );
4475 brhead
= stm_solver_maillon_reverse( brhead
);
4477 for( scan
= brhead
; scan
->NEXT
; scan
= scan
->NEXT
);
4480 scan
->MAILLON
->VS
= 0.0 ;
4484 scan
->MAILLON
->VS
= MCC_VDDmax
;
4488 stm_solver_i( brhead
, out
, &imax
);
4489 while (tofree
!=NULL
)
4491 freeptype((ptype_list
*)tofree
->DATA
);
4492 tofree
=delchain(tofree
, tofree
);
4494 stm_solver_maillon_freechain( brhead
);
4497 *tabin
= -imax
*1e6
;
4502 MCC_CURRENT_LOTRS
= NULL
;
4505 void mcc_calcul_ibranch_spice( elp_lotrs_param
*lotrsparam_n
, elp_lotrs_param
*lotrsparam_p
, double *tabin
, double *tabip
)
4509 char *subcktmodeln
, *subcktmodelp
, *fileout
;
4510 char *modeln
, *modelp
, *name
;
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"};
4518 mcc_modellist
*ptmodel
;
4520 bs3
= ( MCC_SPICEMODELTYPE
== MCC_BSIM3V3
? 1 : 0 ) ;
4521 bs4
= ( MCC_SPICEMODELTYPE
== MCC_BSIM4
? 1 : 0 ) ;
4522 modeln
= MCC_TNMODEL
;
4523 modelp
= MCC_TPMODEL
;
4527 ptmodel
= mcc_getmodel ( MCC_MODELFILE
,
4533 subcktmodeln
= mcc_getsubckt( MCC_MODELFILE
,
4540 subcktmodelp
= mcc_getsubckt( MCC_MODELFILE
,
4548 if (subcktmodeln
!= NULL
) /*- le model est dans un subckt -*/
4550 sprintf(bufn
,"xm") ;
4551 modeln
= subcktmodeln
;
4554 if (subcktmodelp
!= NULL
) /*- le model est dans un subckt -*/
4556 sprintf(bufp
,"xm") ;
4557 modelp
= subcktmodelp
;
4559 mn
= mbkstrdup(bufn
) ;
4560 mp
= mbkstrdup(bufp
) ;
4562 sim_set_result_file_extension('p', 1, &MCC_SPICEOUT
);
4566 name
=mbkstrdup(mcc_debug_prefix("ibranch.spi"));
4568 if ((c
=strrchr(buf
,'.'))!=NULL
) *c
='\0';
4570 file
= mcc_fopen(name
,"w") ;
4571 avt_printExecInfo(file
, "*", "", "");
4572 mcc_get_np_vgs(&vgsn
, &vgsp
);
4574 fprintf(file
,"* branch current measure\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
);
4583 fprintf(file
,".include \"%s\"\n",MCC_TECHFILE
);
4586 fprintf(file
,".subckt %s in out1 out2 out3 out4\n", buf
);
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
);
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");
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");
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");
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");
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
);
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);
4664 fprintf(file
,".dc var %g %g %g\n\n", 0.0, MCC_VDDmax
, MCC_VDDmax
/10.0 );
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" );
4675 if ( V_INT_TAB
[__SIM_TOOL
].VALUE
== SIM_TOOL_TITAN
)
4676 fprintf(file
,".save %s\n", buf
);
4678 fprintf(file
,".end\n");
4680 mcc_fclose(file
,name
);
4682 sim_execspice(name
,0,MCC_SPICENAME
,MCC_SPICESTRING
,MCC_SPICESTDOUT
);
4684 fileout
= sim_getjoker(MCC_SPICEOUT
,buf
) ;
4686 tab
= (double **)mbkalloc(nbdata
* sizeof(double *)) ;
4687 for(j
= 0 ; j
< nbdata
; j
++)
4688 tab
[j
] = (double *)mbkalloc(11*sizeof(double)) ;
4690 sim_readspifiletab( fileout
, argv
, nbdata
, 11, tab
, MCC_VDDmax
, MCC_VDDmax
/10.0) ;
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
;
4702 char *mcc_check_subckt(char *nmos
, char *pmos
)
4704 char *subcktmodeln
, *subcktmodelp
;
4705 mcc_modellist
*ptmodeln
,*ptmodelp
;
4709 MCC_CURRENT_LOTRS
=NULL
;
4710 subcktmodeln
= mcc_getsubckt( MCC_MODELFILE
,
4717 subcktmodelp
= mcc_getsubckt( MCC_MODELFILE
,
4724 if (subcktmodeln
|| subcktmodelp
)
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");
4731 ptmodeln
= mcc_getmodel ( MCC_MODELFILE
,
4737 fprintf(f
, "*\n*\n* NMOS **********************\n*\n*\n\n");
4738 mcc_drive_dot_model(f
, ptmodeln
);
4739 ptmodelp
= mcc_getmodel ( MCC_MODELFILE
,
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
);
4756 static void mcc_check_trs(lotrs_list
*lt
, elp_lotrs_param
*lotrsparam_n
, char *subname
)
4759 optparam_list
*ptopt
;
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"};
4765 if ((pt
=getptype(lt
->USER
, OPT_PARAMS
))!=NULL
)
4767 for (ptopt
= (optparam_list
*)pt
->DATA
; ptopt
; ptopt
= ptopt
->NEXT
)
4770 if (isknowntrsparam (ptopt
->UNAME
.STANDARD
))
4772 if (**(ptopt
->UNAME
.STANDARD
) != '$') paramname
=*(ptopt
->UNAME
.STANDARD
);
4775 else if (ptopt
->TAG
!= '$')
4777 paramname
=ptopt
->UNAME
.SPECIAL
;
4781 value
=ptopt
->UDATA
.VALUE
;
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)
4797 if (mcc_ftoi(value
)!=1)
4798 avt_errmsg(MCC_ERRMSG
, "040", AVT_ERROR
, mcc_ftoi(value
));
4804 avt_errmsg(MCC_ERRMSG
, "039", AVT_WARNING
, paramname
, value
, subname
);
4808 for (disp
=0; disp
<4; disp
++)
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
);
4818 void mcc_check_techno_with_subckt(elp_lotrs_param
*lotrsparam_n
,elp_lotrs_param
*lotrsparam_p
, char *subcktmodeln
, char *subcktmodelp
)
4820 char *modeln
, *modelp
;
4827 modeln
= MCC_TNMODEL
;
4828 modelp
= MCC_TPMODEL
;
4832 if (subcktmodeln
!= NULL
|| subcktmodelp
!= NULL
)
4834 if (subcktmodeln
!= NULL
)
4836 sprintf(bufn
,"xm") ;
4837 modeln
= subcktmodeln
;
4839 if (subcktmodelp
!= NULL
)
4841 sprintf(bufp
,"xm") ;
4842 modelp
= subcktmodelp
;
4845 f
=mcc_fopen("test.spi", "w");
4846 avt_printExecInfo(f
, "*", "", "");
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");
4858 parsespice("test.spi");
4859 if ((lf
=getloadedlofig("test"))!=NULL
)
4861 rflattenlofig(lf
, YES
, NO
);
4862 for (lt
=lf
->LOTRS
; lt
!=NULL
; lt
=lt
->NEXT
)
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
);