1 /****************************************************************************/
3 /* Chaine de CAO & VLSI AVERTEC */
5 /* Produit : STM Version 1.00 */
6 /* Fichier : stm_modscm_eval.c */
8 /* (c) copyright 2000 AVERTEC */
9 /* Tous droits reserves */
11 /* Auteur(s) : Gilles Augustins */
13 /****************************************************************************/
15 /****************************************************************************/
17 /****************************************************************************/
21 double TESTIM
= -1.0 ;
23 /****************************************************************************/
25 /****************************************************************************/
26 float stm_modscm_dual_vf_input (dualparams
*params
)
28 double vddin
= (double)params
->DP
[STM_VDDIN
];
29 double vt
= (double)params
->DP
[STM_VT
];
30 return (float)(vddin
+ vt
);
33 float stm_modscm_dual_vdd_input (dualparams
*params
)
35 return params
->DP
[STM_VDDMAX
];
38 /*******************************************************************************/
39 /* sert au calcul de la prise en compte des maillons entre activelink et source*/
40 /*******************************************************************************/
42 void stm_modscm_dual_slopei(double k
, double B
, double U
, double IMAX
, double Fe
, double rsat
, double vdd
, double threshold
, double *imax
, double *Fs
)
45 delta
= k
* k
* B
* B
* U
* U
+ 4.0 * k
* (1.0 + B
* U
);
46 x
= (k
* B
* U
+ sqrt(delta
)) / 2.0 / (1.0 + B
* U
);
50 *imax
= IMAX
-(vdd
-threshold
)/rsat
;
55 /****************************************************************************/
57 double stm_modscm_dual_voltage_rc( double t
, double rbr
, double cbr
, double imax
, double Fs
)
62 v
= rbr
* rbr
* imax
* cbr
/ Fs
* ( 1.0 - exp( -t
/ (rbr
* cbr
)) - ( t
> Fs
? ( 1.0 - exp(-( t
- Fs
) / (rbr
* cbr
))) : 0.0 ) );
69 /****************************************************************************/
71 void stm_modscm_dual_modifslope(double vddin
, double vt
, double F
, double vdd
, double rbr
, double cbr
, double imax
, double Fs
, double *te
, double *Fm
)
77 // *te = F * atanh( ( vdd/2 - vt ) / vddin );
78 // Ve = vddin * tanh( *te / F) + vt + rbr * rbr * imax * cbr / Fs * ( 1.0 - exp(-(*te) / (rbr * cbr)) - (*te>Fs?(1.0 - exp(-(*te - Fs) / (rbr * cbr))):0.0));
80 /* Instant ou la tension d'entrée passe au millieu de son excursion : (vddin-vt)/2+vt */
82 Ve
= vddin
* tanh( *te
/ F
) + vt
+ stm_modscm_dual_voltage_rc( *te
, rbr
, cbr
, imax
, Fs
);
83 *Fm
= *te
/ atanh( (Ve
- vt
) / vddin
);
88 /****************************************************************************/
90 double stm_modscm_dual_get_ir( double t
,
115 /* Valeurs rapportées */
116 Vr
= Ur
* tanh( t
/ Fr
);
118 /* Valeurs réélles */
119 V
= vin
* tanh( t
/ F
) ;
120 b
= stm_modscm_dual_voltage_rc( t
, rbr
, cbr
, imax
, Fs
);
122 /* Valeur du bruit rapporté proportionnel à Vm / Vr */
128 /* Nouvelle tension d'entrée rapportée */
130 ir
= A
* Vr
* Vr
/ ( 1.0 + B
* Vr
);
132 i
= stm_modscm_dual_calc_i( imax
, ir
, A
, B
, rnt
, rns
, rni
, vint
, vdd
, vt
, vt
+V
+b
, vout
);
136 /****************************************************************************/
137 double stm_modscm_dual_get_ia( double t
,
158 V
= Ua
* tanh(t
/ Fa
);
159 ia
= A
* V
* V
/ (1.0 + B
* V
);
160 V
= vt
+ vin
* tanh( t
/fin
);
161 i
= stm_modscm_dual_calc_i( imax
, ia
, A
, B
, rnt
, rns
, rni
, vint
, vdd
, vt
, V
, vout
);
166 /****************************************************************************/
168 double stm_modscm_dual_get_k4Q( double A
,
193 if( rni
>0.0 && vint
> 0.0 )
200 ir
= stm_modscm_dual_get_ir( k
*Fs
, A
, B
, vin
, Fin
, Ur
, Fr
, rbr
, cbr
, imax
, Fs
, vdd
, rnt
, rns
, rni
, vint
, vt
, vout
);
201 ia
= stm_modscm_dual_get_ia( k
*Fs
, A
, B
, Ua
, Fa
, vin
, Fin
, imax
, vdd
, rnt
, rns
, rni
, vint
, vt
, vout
);
203 while ( fabs(ir
-ia
)/ir
> 0.01 );
208 /****************************************************************************/
210 double stm_modscm_dual_get_Q( double ts
,
247 if((ts
>= tm
) && (ts
< Fs
)) {
249 ia
= stm_modscm_dual_get_ia(ts
, A
, B
, Ua
, Fa
, vin
, Fin
, imax
, vdd
, rnt
, rns
, rni
, vint
, vt
, vout
) ;
250 ir
= stm_modscm_dual_get_ir(ts
, A
, B
, vin
, Fin
, Ur
, Fr
, rbr
, cbr
, imax
, Fs
, vdd
, rnt
, rns
, rni
, vint
, vt
, vout
) ;
251 Q
= 0.5 * (ts
- tm
) * ( ir
- ia
);
254 dt
= fout
* atanh((threshold
-vt
)/(vdd
-vt
)) ;
256 vout
= vdd
- ( vt
+ (vdd
-vt
)*tanh((Fs
-d
)/fout
) );
257 ia
= stm_modscm_dual_get_ia(Fs
, A
, B
, Ua
, Fa
, vin
, Fin
, imax
, vdd
, rnt
, rns
, rni
, vint
, vt
, vout
) ;
258 ir
= stm_modscm_dual_get_ir(Fs
, A
, B
, vin
, Fin
, Ur
, Fr
, rbr
, cbr
, imax
, Fs
, vdd
, rnt
, rns
, rni
, vint
, vt
, vout
) ;
259 s
= (k
* Fs
/ 2.0 - tm
/ 2.0) * ( ir
- ia
);
261 if((ts
>= Fs
) && (ts
< k
*Fs
)) {
263 ir
= stm_modscm_dual_get_ir(ts
, A
, B
, vin
, Fin
, Ur
, Fr
, rbr
, cbr
, imax
, Fs
, vdd
, rnt
, rns
, rni
, vint
, vt
, vout
) ;
264 ia
= stm_modscm_dual_get_ia(ts
, A
, B
, Ua
, Fa
, vin
, Fin
, imax
, vdd
, rnt
, rns
, rni
, vint
, vt
, vout
) ;
266 Q
= s
- 0.5 * (k
* Fs
- ts
) * ( ir
- ia
);
275 /****************************************************************************/
277 float stm_modscm_dual_cconf (dualparams
*params
, float slew
)
279 return params
->DP
[STM_CAPAI
] + (params
->DP
[STM_PCONF0
] + params
->DP
[STM_PCONF1
] * slew
)
280 * params
->DP
[STM_IRAP
];
283 /****************************************************************************/
285 float stm_modscm_dual_imax (dualparams
*params
)
287 return params
->DP
[STM_IMAX
];
290 /****************************************************************************/
292 float stm_modscm_dual_vth (dualparams
*params
)
294 return params
->DP
[STM_THRESHOLD
];
297 /****************************************************************************/
298 void stm_modscm_dual_cal_UF (double imax
,
308 *U
= (imax
* bn
+ sqrt (pow ((imax
* bn
), 2) + 4.0 * an
* imax
)) / (2.0 * an
);
310 *F
= fin
* *U
/ vddin
;
312 *F
*= (*U
- vx
) / *U
;
315 /****************************************************************************/
317 double stm_modscm_dual_calculduts (dualparams
*params
, float slew
, float load
, stm_pwl
*pwl
)
319 double threshold
= (double)params
->DP
[STM_THRESHOLD
];
321 ts
= stm_modscm_dual_calculduts_threshold( params
, slew
, load
, threshold
, pwl
);
326 /****************************************************************************/
328 char stm_modscm_dual_slew_for_pwl( paramforslewpwl
*param
, float v
, float *t
)
330 *t
= stm_modscm_dual_calts_with_param_timing( param
->DUALSCM
, v
);
334 /****************************************************************************/
335 float stm_modscm_dual_slew (dualparams
*params
, float slew
, stm_pwl
*pwl
, stm_pwl
**ptpwl
, float load
)
340 double s1old
, s1new
, s2old
, s2new
, seuil1
, seuil2
, ts1
, ts2
;
347 f
= stm_modscm_dual_slew_old( params
, slew
, load
);
350 vt
= (double)params
->DP
[STM_VT
];
351 vdd
= (double)params
->DP
[STM_VDDMAX
];
356 s2old
= 0.75 * (vdd
-vt
) + vt
;
359 if( s1old
> s1new
) seuil1
= s1old
; else seuil1
= s1new
;
360 if( s2old
> s2new
) seuil2
= s2old
; else seuil2
= s2new
;
362 ts1
= stm_modscm_dual_calculduts_threshold( params
, slew
, load
, seuil1
, pwl
);
363 ts2
= stm_modscm_dual_calculduts_threshold( params
, slew
, load
, seuil2
, pwl
);
365 f
= stm_thr2scm( ts2
-ts1
,
378 ts
= stm_modscm_dual_calculduts_threshold( params
, slew
, load
, vs
, pwl
);
379 tabpwl
[i
++] = ts
; tabpwl
[i
++]=vs
;
382 ts
= stm_modscm_dual_calculduts_threshold( params
, slew
, load
, vs
, pwl
);
383 tabpwl
[i
++] = ts
; tabpwl
[i
++]=vs
;
386 ts
= stm_modscm_dual_calculduts_threshold( params
, slew
, load
, vs
, pwl
);
387 tabpwl
[i
++] = ts
; tabpwl
[i
++]=vs
;
390 ts
= stm_modscm_dual_calculduts_threshold( params
, slew
, load
, vs
, pwl
);
391 tabpwl
[i
++] = ts
; tabpwl
[i
++]=vs
;
394 ts
= stm_modscm_dual_calculduts_threshold( params
, slew
, load
, vs
, pwl
);
395 tabpwl
[i
++] = ts
; tabpwl
[i
++]=vs
;
396 *ptpwl
= stm_pwl_create( tabpwl
, 5 );
400 static char printed=0;
404 vs = ((float)i)/((float)(n+1))*vdd ;
407 ts = stm_modscm_dual_calculduts_threshold( params, slew, load, vs, pwl );
413 printf( "---> %d points\n", j/2 );
416 *ptpwl = stm_pwl_create( tabpwl, j/2 );
424 float stm_modscm_dual_slew_old (dualparams
*params
, float slew
, float load
)
428 double pconf0
= (double)params
->DP
[STM_PCONF0
];
429 double pconf1
= (double)params
->DP
[STM_PCONF1
];
430 double capai
= (double)params
->DP
[STM_CAPAI
];
431 double irap
= (double)params
->DP
[STM_IRAP
];
432 double vddin
= (double)params
->DP
[STM_VDDIN
];
433 double vt
= (double)params
->DP
[STM_VT
];
434 double threshold
= (double)params
->DP
[STM_THRESHOLD
];
435 double imax
= (double)params
->DP
[STM_IMAX
];
436 double an
= (double)params
->DP
[STM_AN
];
437 double bn
= (double)params
->DP
[STM_BN
];
438 double delayrc
= (double)params
->DP
[STM_DRC
];
439 double rbr
= (double)params
->DP
[STM_RBR
];
440 double cbr
= (double)params
->DP
[STM_CBR
];
441 double rsat
= (double)params
->DP
[STM_RSAT
];
442 double rlin
= (double)params
->DP
[STM_RLIN
];
443 double vddmax
= (double)params
->DP
[STM_VDDMAX
];
446 double U
, F
, Ur
, Fr
, im
, Fs
, tm
, Fm
, k4Q
, t0
, Q
;
447 double ts1
, ts2
, seuil1
, seuil2
;
449 if( pconf1
*slew
< 10.0*load
)
450 pconf1
= 1.2 * pconf1
;
453 On n'appelle pas deux fois la fonction culcule du ts avec deux seuils
454 différents car on souhaite conserver la même caractéristique.
457 if((rbr
> 0.0) && (cbr
> 0.0)){
458 stm_modscm_dual_cal_UF (imax
, an
, bn
, vddin
, 0.0, (double)slew
, &Ur
, &Fr
);
459 stm_modscm_dual_slopei(0.7, bn
, Ur
, imax
, Fr
, rsat
, vddmax
, vddmax
, &im
, &Fs
);
460 stm_modscm_dual_modifslope( vddin
, vt
, slew
, vddmax
, rbr
, cbr
, im
, Fs
, &tm
, &Fm
);
465 stm_modscm_dual_cal_UF (imax
, an
, bn
, vddin
, 0.0, Fm
, &U
, &F
);
466 if((capai
> 0.00) && (capai
/(load
+ (pconf0
+ pconf1
* slew
) * irap
) > STM_OVERSHOOT
)){
467 deltat
= stm_modscm_dual_calts (imax
, an
, bn
, U
, threshold
, 0.0, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, slew
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
473 cconf
= pconf0
+ pconf1
* (slew
- deltat
);
476 capa0
= cconf
* irap
+ (double)load
;
477 t0
= stm_modscm_dual_calts (imax
, an
, bn
, U
, threshold
, capa0
, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, slew
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
479 if((rbr
> 0.0) && (cbr
> 0.0)){
480 fout
= stm_modscm_dual_calslew( imax
, an
, bn
, U
, vt
, vddmax
, capa
, slew
, F
, t0
);
481 k4Q
= stm_modscm_dual_get_k4Q( an
, bn
, vddin
, slew
, Ur
, Fr
, U
, F
, rbr
, cbr
, im
, Fs
, vddmax
, rsat
, rlin
, -1.0, -1.0, vt
);
482 Q
= stm_modscm_dual_get_Q( t0
, k4Q
, an
, bn
, vddin
, slew
, Ur
, Fr
, U
, F
, rbr
, cbr
, im
, Fs
, tm
, vddmax
, rsat
, rlin
, -1.0, -1.0, vt
, fout
, threshold
);
483 if( 2.0 * Q
/ vddmax
< capa
)
484 capa
-= 2.0 * Q
/ vddmax
;
488 if( STM_DEFAULT_SMINR > 0.0 && STM_DEFAULT_SMAXR < 1.0 ) {
489 seuil1 = STM_DEFAULT_SMINR*vddmax ;
490 seuil2 = STM_DEFAULT_SMAXR*vddmax ;
494 seuil2 = 0.75 * (vddmax-vt) + vt ;
498 seuil1
= 0.5*vddmax
;
499 seuil2
= 0.8*vddmax
;
502 double s1old
, s1new
, s2old
, s2new
;
507 s2old
= 0.75 * (vddmax
-vt
) + vt
;
510 if( s1old
> s1new
) seuil1
= s1old
; else seuil1
= s1new
;
511 if( s2old
> s2new
) seuil2
= s2old
; else seuil2
= s2new
;
516 ts1
= stm_modscm_dual_calts (imax
, an
, bn
, U
, seuil1
, capa
, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, slew
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
517 ts2
= stm_modscm_dual_calts (imax
, an
, bn
, U
, seuil2
, capa
, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, slew
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
520 ts1
= stm_modscm_dual_calts_rsat_full_range ( capai
, imax
, an
, bn
, U
, vt
, vddmax
, threshold
, seuil1
, rsat
, rlin
, capa
, slew
, F
, stm_modscm_dual_calte (vddin
, vt
, vt
, (double)slew
), t0
, vddin
, NULL
);
521 ts2
= stm_modscm_dual_calts_rsat_full_range ( capai
, imax
, an
, bn
, U
, vt
, vddmax
, threshold
, seuil2
, rsat
, rlin
, capa
, slew
, F
, stm_modscm_dual_calte (vddin
, vt
, vt
, (double)slew
), t0
, vddin
, NULL
);
524 return stm_thr2scm( ts2
-ts1
,
533 /****************************************************************************/
535 float stm_dv( float t
, mbk_pwl
*linetanh
, float rdriver
, float cin
, float capai
)
544 static char enable
='x' ;
546 if( V_BOOL_TAB
[ __STM_ENABLE_DV
].VALUE
)
554 t0
=linetanh
->DATA
[0].X0
;
558 for( n
= 0 ; n
< linetanh
->N
; n
++ ) {
560 if( n
==linetanh
->N
-1 )
561 tmax
= linetanh
->X1
;
563 tmax
= linetanh
->DATA
[n
+1].X0
;
569 if( n
>= linetanh
->N
)
570 n
= linetanh
->N
- 1 ;
573 k
= rdriver
* ( cin
+ capai
);
575 for( m
= 0 ; m
<= n
; m
++ ) {
576 a
= linetanh
->DATA
[m
].A
;
577 ta
= linetanh
->DATA
[m
].X0
;
578 dv
= dv
+ a
*(1.0-exp(-(t
-ta
)/k
)) ;
580 ta
= linetanh
->DATA
[m
+1].X0
;
581 dv
= dv
- a
*(1.0-exp(-(t
-ta
)/k
)) ;
584 dv
= dv
*rdriver
*capai
;
589 double stm_dv_old( double t
, double im
, double Fs
, double r
, double cl
, double cin
, double ci
)
595 k1
= r
*( cl
*cin
+ cl
*ci
+ cin
*ci
);
599 dv
= im
*r
*ci
/(Fs
*c1
)*(t
-k1
/c1
*(1.0-exp(-c1
*t
/k1
))) ;
601 dv
= im
*r
*ci
/(Fs
*c1
)*(t
-k1
/c1
*(1.0-exp(-c1
*t
/k1
))) -
602 im
*r
*ci
/(Fs
*c1
)*((t
-Fs
)-k1
/c1
*(1.0-exp(-c1
*(t
-Fs
)/k1
)));
607 /****************************************************************************/
608 void stm_estim_output( stm_dual_param_timing
*param
, double global_t
, double v
)
617 t0
= stm_modscm_dual_calts( param
->IMAX
,
639 param
->FOUT
= stm_modscm_dual_calslew( param
->IMAX
,
652 tst0
= stm_modscm_dual_calte( param
->VDDMAX
-param
->VT
, param
->VT
, param
->THRESHOLD
, param
->FOUT
) ;
653 tslocal_t
= stm_modscm_dual_calte( param
->VDDMAX
-param
->VT
, param
->VT
, v
, param
->FOUT
) ;
655 local_t
= dtlocal
+tslocal_t
;
656 dt
= global_t
- param
->DTPWL
- local_t
;
660 param
->T0
= t0
+ param
->DTPWL
;
663 void stm_modscm_dual_fill_param( dualparams
*params
,
668 stm_dual_param_timing
*paramtiming
673 double pconf0
= (double)params
->DP
[STM_PCONF0
];
674 double pconf1
= (double)params
->DP
[STM_PCONF1
];
675 double capai
= (double)params
->DP
[STM_CAPAI
];
676 double capao
= (double)params
->DP
[STM_CAPAO
];
677 double irap
= (double)params
->DP
[STM_IRAP
];
678 double vddin
= (double)params
->DP
[STM_VDDIN
];
679 double vt
= (double)params
->DP
[STM_VT
];
680 double threshold
= (double)params
->DP
[STM_THRESHOLD
];
681 double input_thr
= (double)params
->DP
[STM_INPUT_THR
];
682 double imax
= (double)params
->DP
[STM_IMAX
];
683 double an
= (double)params
->DP
[STM_AN
];
684 double bn
= (double)params
->DP
[STM_BN
];
685 double delayrc
= (double)params
->DP
[STM_DRC
];
686 double rbr
= (double)params
->DP
[STM_RBR
];
687 double cbr
= (double)params
->DP
[STM_CBR
];
688 double rsat
= (double)params
->DP
[STM_RSAT
];
689 double rlin
= (double)params
->DP
[STM_RLIN
];
690 double vddmax
= (double)params
->DP
[STM_VDDMAX
];
691 double rint
= (double)params
->DP
[STM_RINT
];
692 double vint
= (double)params
->DP
[STM_VINT
];
693 double chalf
= (double)params
->DP
[STM_CHALF
];
694 double rconf
= (double)params
->DP
[STM_RCONF
];
695 double kf
= (double)params
->DP
[STM_KF
];
696 double qinit0
= (double)params
->DP
[STM_QINIT
];
697 double vt0
= (double)params
->DP
[STM_VT0
];
698 double vt0c
= (double)params
->DP
[STM_VT0C
];
703 double U
, F
, Ur
, Fr
, im
, Fs
, tm
, Fm
, k4Q
, t0
, Q
, te
, ts
, koshoot
;
708 char newswitchmodel
;
714 stmtanhdata tanhdata
;
716 float lv
, dv
, tx
, tmin
, tminin
, tmax
, tmaxin
, tmaxout
, dt
, tminctk
;
717 static int fordebug
= 0 ;
718 mbk_pwl_param
*param
;
724 static char flag
='n';
731 capaie
[0] = params
->DP
[STM_CAPAI0
] ;
732 capaie
[1] = params
->DP
[STM_CAPAI1
] ;
733 capaie
[2] = params
->DP
[STM_CAPAI2
] ;
734 capaie
[3] = params
->DP
[STM_CAPAI3
] ;
735 if( capaie
[0] == capaie
[1] &&
736 capaie
[0] == capaie
[2] &&
737 capaie
[3] == capaie
[3] )
744 vcap
[1] = vddmax
/2.0 ;
747 qsort( vcap
, 3, sizeof(double), (int(*)(const void*,const void*))mbk_qsort_dbl_cmp
);
749 ctkmodel
= V_INT_TAB
[ __STM_CTK_MODEL
].VALUE
;
752 if( vint
> 0.0 && rint
> 0.0 )
757 if( newswitchmodel
&& ( vint
> 0.0 && rint
> 0.0 ) )
760 if( V_BOOL_TAB
[ __STM_NUMERICAL_INTEGRATION
].VALUE
) {
762 printf( "numerical integration forced !\n" );
771 if( rconf
> 0.0 && kf
> 0.0 && fin
> 1.0 ) {
773 icf0
= capaie
[0]*1e-15/(fin
*1e-12)*(vddmax
-vt
)*(1.0-exp(-tmax
*1e-12/(rconf
*(capaie
[0]+load
)*1e-15))) ;
774 if( V_BOOL_TAB
[ __STM_NEW_OVERSHOOT
].VALUE
) {
776 r
= (vddmax
-2*vt
)/vddmax
;
778 k
=V_FLOAT_TAB
[__STM_OVERSHOOT_K_LVT
].VALUE
;
780 k
=V_FLOAT_TAB
[__STM_OVERSHOOT_K_HVT
].VALUE
;
781 qinit
= -k
* (capai
*1e-3)/fin
*(vddmax
-vt
)*(tmax
+rconf
*(load
*1e-3)*(exp(-tmax
/(rconf
*load
*1e-3))-1.0));
784 Q
= -(pconf0
+load
)/1000.0*((-icf0
)*rconf
)-capaie
[0]/1000.0*vt
-qinit0
;
789 /* fin : front d'entrée réel original.
790 Fr : front d'entrée rapporté sans prendre en compte le cbr.
791 Ur : tension d'entrée rapporté sans prendre en compte le cbr.
792 Fs : instant où on considère que le courant atteint imax.
793 Fm : front d'entrée réel prenant en compte le cbr.
794 F : front d'entrée rapporté prenant en compte cbr.
795 U : tension d'entrée rapporté prenant en compte cbr.
796 t0 : estimation ts sortie en vdd/2
797 fout : estimation f sortie
801 capa
= load
+pconf0
+pconf1
*fin
;
803 if( !integnumeric
&& (rbr
> 0.0) && (cbr
> 0.0) ) {
804 stm_modscm_dual_cal_UF (imax
, an
, bn
, vddin
, 0.0, (double)fin
, &Ur
, &Fr
);
805 stm_modscm_dual_slopei(0.7, bn
, Ur
, imax
, Fr
, rsat
, vddmax
, vddmax
, &im
, &Fs
);
806 stm_modscm_dual_modifslope( vddin
, vt
, fin
, vddmax
, rbr
, cbr
, im
, Fs
, &tm
, &Fm
);
811 stm_modscm_dual_cal_UF (imax
, an
, bn
, vddin
, 0.0, Fm
, &U
, &F
);
812 t0
= stm_modscm_dual_calts (imax
, an
, bn
, U
, threshold
, capa
, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, fin
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
813 fout
= stm_modscm_dual_calslew( imax
, an
, bn
, U
, vt
, vddmax
, capa
, fin
, F
, t0
);
815 /* Prise en compte de la modification du front d'entree due au capai.
816 Pour l'instant, nous l'appliquons que les technos pour lesquelles le
817 vt est superieur à vdd/2 */
818 paramtiming
->NEWCTKMODEL
= 0 ;
819 paramtiming
->EVTIN
= '-' ;
820 paramtiming
->VIN
= -1.0 ;
823 if( ! V_BOOL_TAB
[ __AVT_CTK_ON_INPUT
].VALUE
|| integnumeric
==1 )
828 if( driver
->c
<= 0.0 ||
835 if( V_BOOL_TAB
[ __AVT_NEW_CTK_ON_INPUT
].VALUE
&& V_BOOL_TAB
[ __AVT_CTK_ON_INPUT
].VALUE
) {
836 paramtiming
->DRIVER
.c
= driver
->c
- capai
;
837 if( V_BOOL_TAB
[ __STM_RDRIVER_FROM_SLOPE
].VALUE
) {
838 if( V_BOOL_TAB
[ __AVT_BUG_RDRIVER
].VALUE
)
839 paramtiming
->DRIVER
.r
= 0.693*fin
/(driver
->c
/1000.0)/4.0 ;
841 paramtiming
->DRIVER
.r
= 0.693*fin
/(driver
->c
/1000.0) ;
844 paramtiming
->DRIVER
.r
= driver
->r
;
845 paramtiming
->DRIVER
.v
= driver
->v
;
846 paramtiming
->NEWCTKMODEL
= 1 ;
849 if( ! V_BOOL_TAB
[ __AVT_CTK_ON_INPUT
].VALUE
||
851 V_BOOL_TAB
[ __AVT_NEW_CTK_ON_INPUT
].VALUE
857 /* retire la capa de couplage comptée dans la capa d'entrée */
858 cin
= driver
->c
- capao
;
867 if( V_BOOL_TAB
[ __STM_RDRIVER_FROM_SLOPE
].VALUE
) {
868 /* resistance du driver du front d'entrée : modèle integrales à
870 if( V_BOOL_TAB
[ __AVT_BUG_RDRIVER
].VALUE
)
871 rdriver
= 0.693*fin
/(driver
->c
/1000.0)/4.0 ;
873 rdriver
= 0.693*fin
/(driver
->c
/1000.0) ;
876 rdriver
= driver
->r
;
881 /* calcul de l'écart entre le référentiel de l'entrée et de la sortie */
883 ts
= fout
*atanh( (threshold
-vt
)/(vddmax
-vt
));
885 ts
= fout
*(threshold
-vt
)/(vddmax
-vt
);
888 if( !integnumeric
&& ( (driver
&& driver
->r
> 0.0 && driver
->c
> 0.0 && cin
> 0.0 ) || usecapaie
) ) {
889 /* Calcule du dV de tensions sur l'entrée à partir de l'estimation du front de sortie :
890 Comme on ne connait pas la transformée de laplace de la tanh, on passe en pwl */
892 tanhdata
.VDD
= vddmax
;
896 /* calcul du dernier instant : quand les transitions atteignent 95% de leur valeurs finales */
897 tmaxout
= dt
+ fout
*atanh( (0.95*vddmax
-vt
)/(vddmax
-vt
) );
898 tmaxin
= fin
*atanh( (0.95*(vddin
+vt
)-vt
)/vddin
) ;
899 if( tmaxout
> tmaxin
)
904 /* calcul du premier instant */
905 tx
= -fout
*vt
/(vddmax
-vt
);
912 if( V_BOOL_TAB
[ __AVT_RDRIVER_UNDER_VSAT
].VALUE
&& driver
->v
> 0.0 ) {
913 vsat
= vddmax
-driver
->v
;
915 tminin
= fin
*atanh( ( vsat
- vt
)/vddin
);
924 param
= mbk_pwl_get_default_param( (char (*)(void*, double, double*))stmtanhfn
, (void*) &tanhdata
, tmin
, tmax
) ;
925 /* calcul des pwl : on impose le point vt */
926 mbk_pwl_add_param_point( param
, dt
);
928 linetanh
= mbk_pwl_create( (char (*)(void*, double, double*))stmtanhfn
, (void*) &tanhdata
, tmin
, tmax
, param
) ;
929 mbk_pwl_free_param( param
);
935 case 1 : /* méthode du pwl equivalent */
936 case 2 : /* méthode du pwl equivalent, limite haute */
937 case 3 : /* méthode du pwl equivalent, limite basse */
939 /* Determine le stm_pwl de l'entrée en retranchant les dv */
940 pwldv
= (stm_pwl
*)mbkalloc( sizeof(stm_pwl
));
941 pwldv
->TAB
= (float*)mbkalloc(sizeof(float)*2*V_INT_TAB
[ __STM_INPUT_NB_PWL
].VALUE
);
945 for( n
=0 ; n
<V_INT_TAB
[ __STM_INPUT_NB_PWL
].VALUE
; n
++ ) {
947 t
= ((float)n
)/((float)(V_INT_TAB
[ __STM_INPUT_NB_PWL
].VALUE
-1))*tmax
;
948 if( rdriver
>0.0 && t
>=tminctk
)
949 dv
= stm_dv( t
, linetanh
, rdriver
, cin
/1000.0, capao
/1000.0 );
952 v
= vt
+vddin
*tanh(t
/fin
) - dv
;
956 pwldv
->TAB
[2*nbdv
+0] = t
;
957 pwldv
->TAB
[2*nbdv
+1] = v
;
962 pwldv
->TAB
[2*nbdv
+0] = t
;
963 pwldv
->TAB
[2*nbdv
+1] = v
;
972 /* ecrasement du pwlin. a faire : calculer la forme de la tension
973 d'entrée en prenant en compte le dv */
978 case 4 : /* méthode du front equivalent */
983 for( n
=0 ; n
<V_INT_TAB
[ __STM_INPUT_NB_PWL
].VALUE
; n
++ ) {
984 t
= ((float)n
)/((float)(V_INT_TAB
[ __STM_INPUT_NB_PWL
].VALUE
-1))*tmax
;
986 dv
= stm_dv( t
, linetanh
, rdriver
, cin
/1000.0, capao
/1000.0 );
989 s
= s
+ (t
-lt
)*(dv
+ldv
)/2.0 ;
993 fin
= fin
+ s
/(vddin
*0.693);
997 mbk_pwl_free_pwl(linetanh
);
1001 /* transforme le pwl d'entrée proportionnellement au passage de
1002 vddin, fin -> U, F. */
1003 paramtiming
->NTHSHRK
= 0;
1005 pwlshrk
= stm_shrink_pwl( pwlin
, vddin
, fin
, U
, F
, vt
);
1006 if( !stm_pwl_to_tanh( pwlshrk
, vt
, U
+vt
, paramtiming
->PWTHSHRK
, ¶mtiming
->NTHSHRK
, F
) )
1007 paramtiming
->NTHSHRK
= 0;
1008 stm_pwl_destroy( pwlshrk
);
1011 stm_pwl_destroy( pwlin
);
1016 if( V_BOOL_TAB
[ __STM_QINIT_FOR_DT_CONF
].VALUE
&& icf0
>0.0 ) {
1017 /* calcule l'instant où la sortie vaut 0, après absorbtion de l'overshoot */
1018 strans
= stm_modscm_dual_calts (imax
, an
, bn
, U
, 0.0, 0.0, F
, 0.0, vt
, vddin
, capaie
[0], NULL
, NULL
, fin
, NULL
, 0, qinit
, 0.0, 0.0, NULL
);
1019 /* vérifie si cet instant est inférieur à l'instant où la branche conflictuelle se coupe */
1020 te
= stm_modscm_dual_calte (vddin
, vt
, vt0c
, (double)fin
);
1023 deltat
= stm_modscm_dual_calts_final( imax
, an
, bn
, U
, 0.0, 0.0, F
, vt
, vddin
, capaie
[0], fin
, 0.0, qinit
, strans
, icf0
, NULL
);
1027 if(V_BOOL_TAB
[__STM_QINIT_FOR_OVERSHOOT_CONF
].VALUE
)
1028 deltat
= stm_modscm_dual_calts (imax
, an
, bn
, U
, threshold
, 0.0, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, fin
, NULL
, 0, qinit
, 0.0, 0.0, NULL
);
1030 deltat
= stm_modscm_dual_calts (imax
, an
, bn
, U
, threshold
, 0.0, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, fin
, NULL
, 0, 0, 0.0, 0.0, NULL
);
1034 if( (capai
> 0.00) && (capai
/(load
+ (pconf0
+ pconf1
* fin
) * irap
) > STM_OVERSHOOT
) ) {
1035 te
= stm_modscm_dual_calte (vddin
, vt
, input_thr
, (double)fin
);
1036 koshoot
= ( deltat
/te
) * (deltat
/te
);
1042 if( newswitchmodel
) {
1044 cconf
= pconf0
+ irap
* pconf1
* fin
*( 1.0 - koshoot
) ;
1051 cconf
= pconf0
+ pconf1
* fin
*( 1.0 - koshoot
);
1054 capa0
= cconf
* irap
;
1057 if( capa0
+ load
< 0.0 )
1063 if( integnumeric
== 0 )
1064 t0
= stm_modscm_dual_calts (imax
, an
, bn
, U
, threshold
, capa0
+load
, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, fin
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
1066 if( integnumeric
== 0 && (rbr
> 0.0) && (cbr
> 0.0)){
1067 // Calcule de la charge supplémentaire due à l'overshoot
1068 fout
= stm_modscm_dual_calslew( imax
, an
, bn
, U
, vt
, vddmax
, capa
+load
, fin
, F
, t0
);
1069 k4Q
= stm_modscm_dual_get_k4Q( an
, bn
, vddin
, fin
, Ur
, Fr
, U
, F
, rbr
, cbr
, im
, Fs
, vddmax
, rsat
, rlin
, rint
, vint
, vt
);
1070 Q
= stm_modscm_dual_get_Q( t0
, k4Q
, an
, bn
, vddin
, fin
, Ur
, Fr
, U
, F
, rbr
, cbr
, im
, Fs
, tm
, vddmax
, vt
, rsat
, rlin
, rint
, vint
, fout
, threshold
);
1071 if( 2.0 * Q
/ vddmax
< (capa
+load
) )
1072 capa
-= 2.0 * Q
/ vddmax
;
1078 if( integnumeric
==0 && rsat
> 0.0 ) {
1079 rsatsep
= vddmax
/imax
;
1080 if( rsat
> rsatsep
&& rsatsep
> rlin
) {
1081 vsat
= vddmax
- ( imax
- vddmax
/ rsat
) * rlin
* rsat
/ ( rsat
- rlin
) ;
1082 if( vsat
< 0.0 || vsat
> vddmax
)
1085 fout
= stm_modscm_dual_calslew( imax
, an
, bn
, U
, vt
, vddmax
, capa
+load
, fin
, F
, t0
);
1091 paramtiming
->IMAX
= imax
;
1092 paramtiming
->AN
= an
;
1093 paramtiming
->BN
= bn
;
1094 paramtiming
->U
= U
;
1095 paramtiming
->CAPA
= capa
;
1096 paramtiming
->CAPA0
= capa0
;
1097 paramtiming
->CHALF
= chalf
;
1098 paramtiming
->F
= F
;
1099 paramtiming
->VT
= vt
;
1100 paramtiming
->VDDIN
= vddin
;
1101 paramtiming
->VDDMAX
= vddmax
;
1102 paramtiming
->CAPAI
= capai
;
1103 paramtiming
->FIN
= fin
;
1104 paramtiming
->VSAT
= vsat
;
1105 paramtiming
->VINT
= vint
;
1106 paramtiming
->RLIN
= rlin
;
1107 paramtiming
->RINT
= rint
;
1108 paramtiming
->RSAT
= rsat
;
1109 paramtiming
->FOUT
= fout
;
1110 paramtiming
->T0
= t0
;
1111 paramtiming
->TE
= stm_modscm_dual_calte (vddin
, vt
, vt
, fin
) ;
1112 paramtiming
->THRESHOLD
= threshold
;
1113 paramtiming
->RBR
= rbr
;
1114 paramtiming
->CBR
= cbr
;
1115 paramtiming
->QINIT
= qinit
;
1116 paramtiming
->INTEGNUMERIC
= integnumeric
;
1117 paramtiming
->DT
= deltat
;
1118 paramtiming
->QSAT_VE
= -1.0 ;
1119 paramtiming
->QSAT_TE
= -1.0 ;
1120 paramtiming
->QSAT_Q0
= -1.0 ;
1121 paramtiming
->DTPWL
= 0.0 ;
1122 for( n
=0 ; n
<4 ; n
++ )
1123 paramtiming
->CAPAIE
[n
] = capaie
[n
] ;
1124 for( n
=0 ; n
<3 ; n
++ )
1125 paramtiming
->VCAP
[n
] = vcap
[n
] ;
1127 if( ! V_BOOL_TAB
[ __STM_QSAT_ENHANCED
].VALUE
1128 && V_INT_TAB
[ __STM_QSAT_LEVEL
].VALUE
== 0 )
1129 paramtiming
->COMPAT30P3
= 1 ;
1131 paramtiming
->COMPAT30P3
= 0 ;
1132 paramtiming
->STRANS
= strans
;
1133 paramtiming
->ICF0
= icf0
;
1136 double stm_modscm_dual_get_qsat2( stm_dual_param_timing
*param
, double seuil
, double ceqrsat
)
1143 if( param
->THRESHOLD
> param
->VT
)
1144 tst
= param
->FOUT
* atanh( (param
->THRESHOLD
-param
->VT
)/(param
->VDDMAX
-param
->VT
) ) ;
1146 tst
= param
->FOUT
* (param
->THRESHOLD
-param
->VT
)/(param
->VDDMAX
-param
->VT
) ;
1148 dt
= (param
->T0
-param
->DTPWL
)-tst
; // Ecart entre le référentiel de l'entrée et de la sortie
1150 if( seuil
> param
->VT
)
1151 tout
= param
->FOUT
* atanh( (seuil
-param
->VT
)/(param
->VDDMAX
-param
->VT
) ) ;
1153 tout
= param
->FOUT
* (seuil
-param
->VT
)/(param
->VDDMAX
-param
->VT
) ;
1157 switch( V_INT_TAB
[ __STM_QSAT_LEVEL
].VALUE
) {
1159 qsat2
= ceqrsat
*seuil
/(tout
*tout
) ;
1162 qsat2
= ceqrsat
*seuil
/((tout
-param
->DT
)*(tout
-param
->DT
)) ;
1165 qsat2
= ceqrsat
*seuil
/tout
;
1174 void evalnewslope( double vt
,
1197 vin0
= vt
+ vddin
*tanh(t
/f
) ;
1199 /* compute minimal slope */
1200 // vinmin = lvin + (vin0-lvin)/100.0 ;
1202 dtm
= lt
-fm
*atanh((lvin
-vt
)/vddin
);
1203 vinmin
= vt
+vddin
*tanh((t
-dtm
)/fm
);
1205 *vin
= vin0
- dvin
;
1206 if( *vin
< vinmin
) {
1214 k1
= atanh((v1
-vt
)/vddin
);
1215 k2
= atanh((v2
-vt
)/vddin
);
1216 *dtnew
= (t2
*k1
-t1
*k2
)/(k1
-k2
);
1217 *fnew
= (t1
-t2
)/(k1
-k2
);
1220 /* résolution de q(t)=c.vs+ci.vi+qinit */
1221 double stm_modscm_dual_calts_newctk( stm_dual_param_timing
*param
,
1234 /* debug related variables */
1235 static int fordebug
=0 ;
1237 char* plotname
=NULL
;
1241 /* input crosstalk parameter */
1244 /* output slope parameter */
1250 /* interval parameter */
1264 /* input slope parameter */
1286 file
= mbkfopen( plotname
, "inout.dat", "w" );
1287 printf( "r = %g\n", param
->DRIVER
.r
);
1288 printf( "ci = %g\n", param
->DRIVER
.c
);
1289 printf( "cc = %g\n", param
->CAPAI
);
1295 capa
= param
->CAPA
+ capasup
;
1297 /* interval parameter */
1298 n
= V_INT_TAB
[ __STM_INPUT_NB_PWL
].VALUE
;
1303 /* output slope parameter */
1304 lvout
= (-1.0/capa
)*(param
->CAPAI
*param
->VT
+param
->QINIT
);
1306 pwlout
= mbk_pwl_alloc_pwl( 2*((int)(n
+0.5)) );
1309 /* input slope parameter */
1322 if( threshold
<= lvin
) {
1323 param
->TIN
= f
*(threshold
-param
->VT
)/param
->VDDIN
;
1334 kin
= ((double)nin
) / ((double)n
) ;
1335 kout
= ((double)nout
) / ((double)n
) ;
1337 /* working on interval [lt-t] */
1339 if( nin
== n
&& nout
== n
) {
1340 printf( "oups (fordebug=%d, threshold=%g)!\n", fordebug
, threshold
);
1346 vout
= kout
*param
->VDDMAX
;
1347 qorg
= stm_get_q( param
->IMAX
, lt
- dtr
, fr
, param
->BN
, param
->U
) ;
1348 tout
= stm_modscm_dual_calts_final( param
->IMAX
,
1360 param
->QINIT
+ dq
+ qorg
,
1370 vin
= param
->VT
+kin
*param
->VDDIN
;
1371 tin
= f
*atanh((vin
-param
->VT
)/param
->VDDIN
)+dt
;
1378 qt
= stm_get_q( param
->IMAX
, t
- dtr
, fr
, param
->BN
, param
->U
) ;
1379 qorg
= stm_get_q( param
->IMAX
, lt
- dtr
, fr
, param
->BN
, param
->U
) ;
1380 vout
= 1.0/(capa
/1000.0) * ( qt
- qorg
1381 - (param
->CAPAI
/1000.0) * (param
->VT
+param
->VDDIN
*tanh(t
/param
->FIN
))
1392 if( nin
< n
&& nout
< n
) {
1394 /* compute the input voltage variation caused by output voltage variation */
1395 pwlout
->DATA
[ pwlout
->N
].X0
= lt
;
1396 pwlout
->DATA
[ pwlout
->N
].A
= (vout
-lvout
)/(t
-lt
) ;
1397 pwlout
->DATA
[ pwlout
->N
].B
= vout
- pwlout
->DATA
[pwlout
->N
].A
* t
;
1401 dvin
= stm_dv( t
, pwlout
, param
->DRIVER
.r
, param
->DRIVER
.c
/1000.0, param
->CAPAI
/1000.0 ) ;
1402 dvinr
= dvin
*param
->U
/param
->VDDIN
;
1404 /* compute the new f and dt for input */
1405 evalnewslope( param
->VT
, param
->VDDIN
, lt
, lvin
, t
, f
, dvin
, &dtnew
, &fnew
, &vin
);
1408 /* compute the new fr and dtr for input */
1409 evalnewslope( param
->VT
, param
->U
, lt
, lvinr
, t
, fr
, dvinr
, &dtrnew
, &frnew
, &vinr
);
1411 /* compute charges at lt and t with frnew/dtrnew */
1412 qt
= stm_get_q( param
->IMAX
, t
- dtrnew
, frnew
, param
->BN
, param
->U
) ;
1413 qlt
= stm_get_q( param
->IMAX
, lt
- dtrnew
, frnew
, param
->BN
, param
->U
) ;
1415 /* compute vout and the (dis)charge for this interval */
1416 vout
= 1.0/(capa
/1000.0) * ( qt
1418 - (param
->CAPAI
/1000.0) * (param
->VT
+param
->VDDIN
*tanh(t
/param
->FIN
))
1434 if( vin
> threshold
&& !findin
) {
1435 param
->TIN
= dtnew
+ fnew
*atanh((threshold
-param
->VT
)/param
->VDDIN
);
1439 if( vout
> threshold
&& !findout
) {
1449 if( nin
< n
&& nout
< n
) {
1450 pwlout
->DATA
[ pwlout
->N
-1 ].A
= (vout
-lvout
)/(t
-lt
) ;
1451 pwlout
->DATA
[ pwlout
->N
-1 ].B
= vout
- pwlout
->DATA
[pwlout
->N
-1].A
* t
;
1454 /* prepare the next iteration : continue with FIN/F */
1457 dt
= t
- f
*atanh((vin
-param
->VT
)/param
->VDDIN
) ;
1459 //dtr = t - fr*atanh((vin*param->U/param->VDDIN-param->VT)/param->U) ;
1460 dtr
= t
- fr
*atanh((vinr
-param
->VT
)/param
->U
) ;
1470 vin0
= param
->VT
+ param
->U
*tanh(t
/param
->FIN
);
1471 dvpure
= dvpure
+ param
->CAPAI
/(param
->CAPAI
+param
->DRIVER
.c
)*(vout
-lvout
);
1472 fprintf( file
, "%g %g %g %g %g %g\n", t
, vin0
, vin
, vout
, dvin
, dvpure
);
1476 if( param
->EVTIN
== 'U' ) {
1477 fprintf( debug
->FIN
, "%g %g\n", (t
+debug
->DT
)*1e-12, vin
);
1478 fprintf( debug
->FOUT
, "%g %g\n", (t
+debug
->DT
)*1e-12, param
->VDDMAX
- vout
);
1481 fprintf( debug
->FIN
, "%g %g\n", (t
+debug
->DT
)*1e-12, param
->VDDMAX
- vin
);
1482 fprintf( debug
->FOUT
, "%g %g\n", (t
+debug
->DT
)*1e-12, vout
);
1486 dq
= dq
+ qlt
- qt
;
1492 if( findin
&& findout
)
1495 while( onemoretime
) ;
1498 qorg
= stm_get_q( param
->IMAX
, ltfinal
- dtrfinal
, frfinal
, param
->BN
, param
->U
) ;
1499 t
= stm_modscm_dual_calts_final( param
->IMAX
,
1511 param
->QINIT
+ dqfinal
+ qorg
,
1516 param
->VIN
= param
->VT
+ param
->VDDIN
*tanh((t
-dtfinal
)/ffinal
);
1519 param
->TIN
= dtfinal
+ ffinal
*atanh((threshold
-param
->VT
)/param
->VDDIN
);
1522 mbk_pwl_free_pwl( pwlout
);
1524 if( !finite( t
) || !finite( param
->TIN
) ) {
1525 printf( "delay calculation error !!! (fordebug=%d,iter=%d)\n", fordebug
,iter
);
1535 double stm_modscm_dual_calts_with_param_timing_classic( stm_dual_param_timing
*paramtiming
, double threshold
, stm_qsat_v
*qsatv
)
1539 double ceqrsat
=0.0 ;
1540 double ceqrsat0
=0.0 ;
1542 double localthreshold
;
1545 if( threshold
>= paramtiming
->VSAT
) {
1546 localthreshold
= paramtiming
->VSAT
;
1550 localthreshold
= threshold
;
1554 /* pour assurer la compatibilité avec ancien modèle, on maintient le bug
1555 où l'on calcul ceqrsat à threshold, sans le borner par vsat */
1556 if( paramtiming
->COMPAT30P3
/* && ! paramtiming->NEWCTKMODEL */ )
1557 stm_modscm_dual_calts_qsat( paramtiming
, threshold
, NULL
, &qsat
, &ceqrsat
, needceqrsat
? &ceqrsat0
: NULL
);
1559 stm_modscm_dual_calts_qsat( paramtiming
, localthreshold
, qsatv
, &qsat
, &ceqrsat
, needceqrsat
? &ceqrsat0
: NULL
);
1562 if( paramtiming
->NEWCTKMODEL
)
1563 tf
= stm_modscm_dual_calts_newctk( paramtiming
, localthreshold
, ceqrsat
, NULL
);
1565 TESTIM
= paramtiming
->T0
;
1566 tf
= stm_modscm_dual_calts( paramtiming
->IMAX
,
1571 paramtiming
->CAPA
+ceqrsat
,
1577 paramtiming
->CAPAIE
,
1580 paramtiming
->COMPAT30P3
? paramtiming
->PWTHSHRK
: NULL
,
1581 paramtiming
->COMPAT30P3
? paramtiming
->NTHSHRK
: 0,
1583 paramtiming
->STRANS
,
1589 if( threshold
> paramtiming
->VSAT
) {
1592 tf = tsat - paramtiming->RLIN * paramtiming->CAPA/1000.0 *
1593 log( 1.0 - ( threshold - paramtiming->VSAT ) / ( paramtiming->VDDMAX - paramtiming->VSAT ) );
1595 tf
= tsat
- paramtiming
->RLIN
* (paramtiming
->CAPA
+ceqrsat0
+paramtiming
->CAPAI
)/1000.0 *
1596 log( 1.0 - ( threshold
- paramtiming
->VSAT
) / ( paramtiming
->VDDMAX
- paramtiming
->VSAT
) );
1599 if( threshold
> 0.0 )
1600 paramtiming
->CEQRSAT
= ceqrsat
/1000.0 + stm_get_qsat(&qsat
,tf
)/threshold
;
1602 paramtiming
->CEQRSAT
= 0.0 ;
1607 double stm_compute_vout( stm_dual_param_timing
*param
, double *t
, double *vqsat
, stm_qsat_v
*qsat_enh
)
1616 static int fordebug
= 0 ;
1620 qsol
= stm_get_q( param
->IMAX
, (*t
- param
->DTPWL
), param
->F
, param
->BN
, param
->U
) - (param
->CAPAI
/1000.0)*( param
->VT
+ param
->VDDIN
*tanh(*t
/param
->FIN
) ) - param
->QINIT
;
1623 vmax
= qsol
/(param
->CAPA
/1000.0) ;
1624 if( vmax
> param
->VDDMAX
)
1625 vmax
= 0.999*param
->VDDMAX
;
1628 vmin
= -((param
->CAPAI
/1000.0)*param
->VT
+param
->QINIT
)/(param
->CAPA
/1000.0) ;
1631 vmin
= vmax
- param
->VDDMAX
/10.0 ;
1635 stm_modscm_dual_calts_qsat( param
, vmin
, qsat_enh
, &qsat
, &ceqrsat
, NULL
);
1636 qtot
= ( (param
->CAPA
/1000.0) + (ceqrsat
/1000.0) )*vmin
+ stm_get_qsat( &qsat
, *t
- param
->DTPWL
);
1638 vmin
= vmin
- param
->VDDMAX
/10.0 ;
1641 while( qtot
> qsol
);
1644 vout
= ( vmin
+ vmax
) / 2.0 ;
1646 stm_modscm_dual_calts_qsat( param
, vout
, qsat_enh
, &qsat
, &ceqrsat
, NULL
);
1647 qtot
= ( (param
->CAPA
/1000.0) + (ceqrsat
/1000.0) )*vout
+ stm_get_qsat( &qsat
, *t
- param
->DTPWL
);
1654 while( (vmax
-vmin
)>param
->VDDMAX
/1000.0 );
1656 vout
= ( vmin
+ vmax
) / 2.0 ;
1659 stm_modscm_dual_calts_qsat( param
, vout
, qsat_enh
, &qsat
, &ceqrsat
, NULL
);
1660 *vqsat
= vout
* ceqrsat
/1000.0 + stm_get_qsat( &qsat
, *t
- param
->DTPWL
) ;
1666 double stm_compute_vout_old( stm_dual_param_timing
*paramtiming
, double *t
, double *qsat
, stm_qsat_v
*qsat_enh
)
1674 vmin
= 0.1*paramtiming
->VDDMAX
;
1675 vmax
= paramtiming
->VSAT
;
1678 tmin
= stm_modscm_dual_calts_with_param_timing_classic( paramtiming
, vmin
, qsat_enh
) ;
1685 *qsat
= paramtiming
->CEQRSAT
* vout
;
1690 tmax
= stm_modscm_dual_calts_with_param_timing_classic( paramtiming
, vmax
, qsat_enh
) ;
1704 vout
= vmin
+ (*t
-tmin
)/(tmax
-tmin
)*(vmax
-vmin
) ;
1705 tx
= stm_modscm_dual_calts_with_param_timing_classic( paramtiming
, vout
, qsat_enh
) ;
1715 while( fabs(tx
-*t
) / *t
> 0.01 && iter
);
1718 avt_log( LOGDEBUG
, 1, "stm_compute_vout() : convergence failled\n" );
1723 *qsat
= paramtiming
->CEQRSAT
* vout
;
1730 void stm_modscm_dual_calts_qsat_v( stm_dual_param_timing
*paramtiming
, stm_qsat_v
*qsat
)
1732 qsat
->A
= 1.0/(paramtiming
->RSAT
*(paramtiming
->CAPA
/1000.0));
1733 qsat
->B
= (paramtiming
->IMAX
-paramtiming
->VDDMAX
/paramtiming
->RSAT
)/(paramtiming
->CAPA
/1000.0) ;
1734 qsat
->T0
= paramtiming
->QSAT_TE
-paramtiming
->DTPWL
+ (1.0/qsat
->A
)*log((paramtiming
->VDDMAX
+qsat
->B
/qsat
->A
-paramtiming
->QSAT_VE
)/(paramtiming
->VDDMAX
+qsat
->B
/qsat
->A
));
1735 qsat
->TS
= paramtiming
->QSAT_TE
-paramtiming
->DTPWL
;
1736 qsat
->QSAT0
= paramtiming
->QSAT_Q0
;
1739 /* Calcule le modèle de charge de saturation. Rempli la structure qsat suivant la configuration. Si le modèle ceqrsat est retenu,
1740 qsat est configuré de façon à renvoyer 0.
1741 si le pointeur ceqrsat0 est défini, il contiendra le ceqrsat intermédiaire utilisé pour configurer qsat */
1742 void stm_modscm_dual_calts_qsat( stm_dual_param_timing
*paramtiming
,
1755 qsat
->TSATMAX
= 0.0 ;
1760 if( threshold
>= paramtiming
->VDDMAX
) {
1761 avt_log( LOGDEBUG
, 1, "stm_modscm_dual_calts_qsat() : threshold exceed vdd. set to vdd\n" );
1762 threshold
= 0.999*paramtiming
->VDDMAX
;
1765 if( threshold
> 0.0 ) {
1768 qsat
->QSATV
= qsatv
;
1770 if( paramtiming
->COMPAT30P3
) {
1772 if( V_BOOL_TAB
[ __STM_CEQRSAT_NUMERIC
].VALUE
) {
1774 *ceqrsat
= stm_modscm_dual_ceqrsat_numeric( paramtiming
, threshold
);
1778 *ceqrsat
= stm_modscm_dual_ceqrsat( paramtiming
->IMAX
,
1780 paramtiming
->VDDMAX
,
1789 paramtiming
->THRESHOLD
,
1791 paramtiming
->T0
-paramtiming
->DTPWL
1795 *ceqrsat0
= *ceqrsat
;
1799 if( threshold
> 0.0 && paramtiming
->RSAT
&& ( !qsat
->QSATV
|| ceqrsat0
) ) {
1801 if( V_BOOL_TAB
[ __STM_CEQRSAT_NUMERIC
].VALUE
) {
1803 *ceqrsat
= stm_modscm_dual_ceqrsat_numeric( paramtiming
, threshold
);
1809 *ceqrsat
= stm_modscm_dual_ceqrsat( paramtiming
->IMAX
,
1811 paramtiming
->VDDMAX
,
1820 paramtiming
->THRESHOLD
,
1822 paramtiming
->T0
-paramtiming
->DTPWL
1827 *ceqrsat0
= *ceqrsat
;
1829 if( V_INT_TAB
[ __STM_QSAT_LEVEL
].VALUE
== 1 ||
1830 V_INT_TAB
[ __STM_QSAT_LEVEL
].VALUE
== 2 ||
1831 V_INT_TAB
[ __STM_QSAT_LEVEL
].VALUE
== 3 ) {
1833 qsat2
= stm_modscm_dual_get_qsat2( paramtiming
, threshold
, (*ceqrsat
)/1000.0 );
1847 qsat
->QSAT2
= qsat2
;
1848 qsat
->DT
= paramtiming
->DT
;
1849 qsat
->TSATMAX
= paramtiming
->IMAX
/(2.0*qsat2
);
1856 qsat
->QSATV
= NULL
;
1860 qsat
->IMAX
= paramtiming
->IMAX
;
1861 qsat
->C
= (paramtiming
->CAPA
+*ceqrsat
)/1000.0 ;
1862 qsat
->VDD
= paramtiming
->VDDMAX
;
1866 double stm_modscm_dual_calts_qbranch( stm_dual_param_timing
*param
, stm_qsat_v
*qsatv
, double vout
, double t
)
1874 q
= stm_get_q( param
->IMAX
, t
, param
->F
, param
->BN
, param
->U
);
1875 stm_modscm_dual_calts_qsat( param
, vout
, qsatv
, &qsat
, &ceqrsat
, NULL
);
1876 vqsat
= stm_get_qsat( &qsat
, t
) + ceqrsat
*vout
/1000.0 ;
1883 double stm_modscm_dual_calts_with_param_timing( stm_dual_param_timing
*paramtiming
, double threshold
)
1889 stm_qsat_v
*ptqsat
;
1892 static int fordebug
= 0 ;
1897 double backup_dtpwl
;
1898 double backup_qinit
;
1901 double localthreshold
;
1906 if( threshold
>= paramtiming
->VSAT
) {
1907 localthreshold
= paramtiming
->VSAT
;
1910 localthreshold
= threshold
;
1913 if( paramtiming
->NTHSHRK
&& !paramtiming
->COMPAT30P3
) {
1919 backup_f
= paramtiming
->F
;
1920 backup_dtpwl
= paramtiming
->DTPWL
;
1921 backup_qinit
= paramtiming
->QINIT
;
1923 for( i
=0 ; i
<paramtiming
->NTHSHRK
; i
++) {
1927 if( V_BOOL_TAB
[ __STM_QSAT_ENHANCED
].VALUE
)
1928 te
= paramtiming
->PWTHSHRK
[i
].F
* atanh( V_FLOAT_TAB
[ __STM_QSAT_RATIO
].VALUE
) + paramtiming
->PWTHSHRK
[i
].DT
;
1932 if( i
==paramtiming
->NTHSHRK
-1 )
1933 tiabs
= FLT_MAX
*0.9 ; /* to be sure to get a good comparison with te */
1935 tiabs
= paramtiming
->PWTHSHRK
[i
].T
+paramtiming
->PWTHSHRK
[i
].DT
;
1937 paramtiming
->F
= paramtiming
->PWTHSHRK
[i
].F
;
1938 paramtiming
->DTPWL
= paramtiming
->PWTHSHRK
[i
].DT
;
1940 stm_estim_output( paramtiming
, ltiabs
, lvout
);
1942 /* calcule de la charge initiale de l'intervalle courant. le modèle enhanced n'est activé
1943 que sur l'intervalle courant, pas avant */
1945 q
= q
- stm_modscm_dual_calts_qbranch( paramtiming
, NULL
, lvout
, paramtiming
->PWTHSHRK
[i
-1].T
+paramtiming
->PWTHSHRK
[i
-1].DT
-paramtiming
->PWTHSHRK
[i
].DT
) ;
1946 paramtiming
->QINIT
= backup_qinit
- q
;
1950 /* détermination de la tension de sortie à partir de laquelle on utilise le modèle enhanced */
1951 if( i
>0 && te
< paramtiming
->PWTHSHRK
[i
-1].T
+paramtiming
->PWTHSHRK
[i
-1].DT
)
1952 te
= paramtiming
->PWTHSHRK
[i
-1].T
+paramtiming
->PWTHSHRK
[i
-1].DT
;
1953 vout_enh
= stm_compute_vout( paramtiming
, &te
, &vqsat
, NULL
);
1955 if( localthreshold
< vout_enh
) {
1959 /* il faut calculer les paramètres enhanced avant le calcul de la charge initiale car ce modèle
1960 peut se déclencher avant l'intervalle courant */
1961 paramtiming
->QSAT_TE
= te
;
1962 paramtiming
->QSAT_VE
= vout_enh
;
1963 paramtiming
->QSAT_Q0
= vqsat
;
1964 stm_modscm_dual_calts_qsat_v( paramtiming
, &qsat
);
1967 /* détermination de la tension de sortie à la fin de l'intervalle courant */
1968 if( i
==paramtiming
->NTHSHRK
-1 )
1969 vout
= paramtiming
->VDDMAX
;
1971 vout
= stm_compute_vout( paramtiming
, &tiabs
, NULL
, ptqsat
);
1972 if( localthreshold
< vout
) {
1979 /* détermination de la tension de sortie à la fin de l'intervalle courant */
1980 if( i
==paramtiming
->NTHSHRK
-1 )
1981 vout
= paramtiming
->VDDMAX
;
1983 vout
= stm_compute_vout( paramtiming
, &tiabs
, NULL
, NULL
);
1984 if( localthreshold
< vout
) {
1989 if( i
==paramtiming
->NTHSHRK
-1 )
1990 avt_log( LOGDEBUG
, 1, "stm_modscm_dual_calts_with_param_timing() : last iteration\n" );
1992 q
= q
+ stm_modscm_dual_calts_qbranch( paramtiming
, ptqsat
, vout
, paramtiming
->PWTHSHRK
[i
].T
) ;
1997 paramtiming
->QINIT
= backup_qinit
- q
;
1998 tf
= stm_modscm_dual_calts_with_param_timing_classic( paramtiming
, threshold
, ptqsat
);
1999 tf
= tf
+ paramtiming
->PWTHSHRK
[i
].DT
;
2001 paramtiming
->F
= backup_f
;
2002 paramtiming
->DTPWL
= backup_dtpwl
;
2003 paramtiming
->QINIT
= backup_qinit
;
2008 if( V_BOOL_TAB
[ __STM_QSAT_ENHANCED
].VALUE
) {
2010 if( paramtiming
->QSAT_TE
< 0.0 ) {
2011 // instant when the input reach x% of vddin.
2012 te
= paramtiming
->FIN
* atanh( V_FLOAT_TAB
[ __STM_QSAT_RATIO
].VALUE
) ;
2013 vout_enh
= stm_compute_vout( paramtiming
, &te
, &vqsat
, NULL
);
2014 if( vout_enh
< paramtiming
->VSAT
) {
2015 paramtiming
->QSAT_TE
= te
;
2016 paramtiming
->QSAT_VE
= vout_enh
;
2017 paramtiming
->QSAT_Q0
= vqsat
;
2021 if( paramtiming
->QSAT_VE
> 0.0 && threshold
> paramtiming
->QSAT_VE
) {
2022 stm_modscm_dual_calts_qsat_v( paramtiming
, &qsat
);
2023 tf
= stm_modscm_dual_calts_with_param_timing_classic( paramtiming
, threshold
, &qsat
);
2029 tf
= stm_modscm_dual_calts_with_param_timing_classic( paramtiming
, threshold
, NULL
);
2035 /* Renvoie 0 pour le modèle enhanced. Le tsatmax n'est pas pris en compte. */
2036 double stm_get_qsat_derivative( stm_qsat
*qsat
, double t
)
2040 if( qsat
&& t
> 0.0 ) {
2046 switch( V_INT_TAB
[ __STM_QSAT_LEVEL
].VALUE
) {
2050 dq
= 2.0 * qsat
->QSAT2
* t
;
2064 inline double stm_get_qsat( stm_qsat
*qsat
, double t
)
2080 a
= qsat
->QSATV
->A
;
2081 b
= qsat
->QSATV
->B
;
2082 t0
= qsat
->QSATV
->T0
;
2083 ts
= qsat
->QSATV
->TS
;
2084 qsat0
= qsat
->QSATV
->QSAT0
;
2089 vf
= vdd
-(exp(-a
*(t
-t0
))*(vdd
+b
/a
)-b
/a
) ;
2090 vi
= vdd
-(exp(-a
*(ts
-t0
))*(vdd
+b
/a
)-b
/a
) ;
2091 q
= qsat
->IMAX
*(t
-ts
) - c
*(vf
-vi
) + qsat0
;
2098 switch( V_INT_TAB
[ __STM_QSAT_LEVEL
].VALUE
) {
2105 if( t
>qsat
->TSATMAX
)
2106 q
= qsat
->QSAT2
*qsat
->TSATMAX
*qsat
->TSATMAX
;
2108 q
= qsat
->QSAT2
*t
*t
;
2112 if( t
>qsat
->TSATMAX
)
2113 q
= qsat
->QSAT2
*(qsat
->TSATMAX
-qsat
->DT
)*(qsat
->TSATMAX
-qsat
->DT
) ;
2115 q
= qsat
->QSAT2
*(t
-qsat
->DT
)*(t
-qsat
->DT
) ;
2128 /****************************************************************************/
2130 double stm_modscm_dual_calculduts_threshold (dualparams
*params
, float slew
, float load
, double seuil
, stm_pwl
*pwl
)
2134 double pconf0
= (double)params
->DP
[STM_PCONF0
];
2135 double pconf1
= (double)params
->DP
[STM_PCONF1
];
2136 double capai
= (double)params
->DP
[STM_CAPAI
];
2137 double irap
= (double)params
->DP
[STM_IRAP
];
2138 double vddin
= (double)params
->DP
[STM_VDDIN
];
2139 double vt
= (double)params
->DP
[STM_VT
];
2140 double threshold
= (double)params
->DP
[STM_THRESHOLD
];
2141 double input_thr
= (double)params
->DP
[STM_INPUT_THR
];
2142 double imax
= (double)params
->DP
[STM_IMAX
];
2143 double an
= (double)params
->DP
[STM_AN
];
2144 double bn
= (double)params
->DP
[STM_BN
];
2145 double delayrc
= (double)params
->DP
[STM_DRC
];
2146 double rbr
= (double)params
->DP
[STM_RBR
];
2147 double cbr
= (double)params
->DP
[STM_CBR
];
2148 double rsat
= (double)params
->DP
[STM_RSAT
];
2149 double rlin
= (double)params
->DP
[STM_RLIN
];
2150 double rint
= (double)params
->DP
[STM_RINT
];
2151 double vint
= (double)params
->DP
[STM_VINT
];
2152 double vddmax
= (double)params
->DP
[STM_VDDMAX
];
2156 double U
, F
, Ur
, Fr
, im
, Fs
, tm
, Fm
, k4Q
, t0
, Q
, te
, koshoot
;
2158 /*double overshoot = (vt + (vddmax - vt) / 3.0)/vddmax ;*/
2160 if( pconf1
*slew
< 10.0*load
)
2161 pconf1
= 1.2 * pconf1
;
2163 if ((str
= avt_gethashvar ("STM_TRACE_MODE")))
2164 if (!strcmp (str
, "yes")) {
2165 fprintf (stdout
, "pconf0 = %f\n", pconf0
);
2166 fprintf (stdout
, "pconf1 = %f\n", pconf1
);
2167 fprintf (stdout
, "capai = %f\n", capai
);
2168 fprintf (stdout
, "irap = %f\n", irap
);
2169 fprintf (stdout
, "vddin = %f\n", vddin
);
2170 fprintf (stdout
, "vt = %f\n", vt
);
2171 fprintf (stdout
, "threshold = %f\n", threshold
);
2172 fprintf (stdout
, "imax = %f\n", imax
);
2173 fprintf (stdout
, "an = %f\n", an
);
2174 fprintf (stdout
, "bn = %f\n", bn
);
2175 fprintf (stdout
, "\n");
2179 /* slew : front d'entrée réel original.
2180 Fr : front d'entrée rapporté sans prendre en compte le cbr.
2181 Fs : instant où on considère que le courant atteint imax.
2182 Fm : front d'entrée réel prenant en compte le cbr.
2183 F : front d'entrée rapporté prenant en compte cbr.
2185 Les équations de courant instantané sont :
2187 Le courant avec prise en compte explicite de rbr, cbr :
2189 stm_modscm_dual_get_ir( t, A, B, Vin, Fin, Ur, Fr, rbr, cbr, imax, Fs) <--- eqt approchée
2191 Le courant équivalent :
2193 stm_modscm_dual_get_ia( t, A, B, Ua, Fa )
2197 /* A décommenter pour revenir à l'ancienne version */
2198 /* rbr=-1.0 ; cbr = -1.0 ; */
2200 if((rbr
> 0.0) && (cbr
> 0.0)){
2201 /* Determine une approximation du courant dans la branche complète. Cela revient
2202 à la méthode Amjad : an et bn sont les paramètres équivalent à la branche vers
2203 la source, et U et Fr sont les paramètres rapportés équivalent à la branche vers
2206 stm_modscm_dual_cal_UF (imax
, an
, bn
, vddin
, 0.0, (double)slew
, &Ur
, &Fr
);
2207 stm_modscm_dual_slopei(0.7, bn
, Ur
, imax
, Fr
, rsat
, vddmax
, vddmax
, &im
, &Fs
);
2209 /* Calcule la modification du front d'entrée. */
2210 stm_modscm_dual_modifslope( vddin
, vt
, slew
, vddmax
, rbr
, cbr
, im
, Fs
, &tm
, &Fm
);
2216 /* Calcule le front d'entrée rapporté. */
2217 stm_modscm_dual_cal_UF (imax
, an
, bn
, vddin
, 0.0, Fm
, &U
, &F
);
2220 if((capai
> 0.00) && (capai
/(load
+ (pconf0
+ pconf1
* slew
) * irap
) > STM_OVERSHOOT
)){
2221 deltat
= stm_modscm_dual_calts (imax
, an
, bn
, U
, threshold
, 0.0, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, slew
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
2222 te
= stm_modscm_dual_calte (vddin
, vt
, input_thr
, (double)slew
);
2223 koshoot
= ( deltat
/te
) * (deltat
/te
);
2229 cconf
= pconf0
+ pconf1
* slew
*( 1.0 - koshoot
);
2232 capa0
= cconf
* irap
+ (double)load
;
2233 t0
= stm_modscm_dual_calts (imax
, an
, bn
, U
, threshold
, capa0
, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, slew
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
2237 if((rbr
> 0.0) && (cbr
> 0.0)){
2238 // Calcule de la charge supplémentaire due à l'overshoot
2239 fout
= stm_modscm_dual_calslew( imax
, an
, bn
, U
, vt
, vddmax
, capa
, slew
, F
, t0
);
2240 k4Q
= stm_modscm_dual_get_k4Q( an
, bn
, vddin
, slew
, Ur
, Fr
, U
, F
, rbr
, cbr
, im
, Fs
, vddmax
, rsat
, rlin
, rint
, vint
, vt
);
2241 Q
= stm_modscm_dual_get_Q( t0
, k4Q
, an
, bn
, vddin
, slew
, Ur
, Fr
, U
, F
, rbr
, cbr
, im
, Fs
, tm
, vddmax
, vt
, rsat
, rlin
, rint
, vint
, fout
, threshold
);
2242 if( 2.0 * Q
/ vddmax
< capa
)
2243 capa
-= 2.0 * Q
/ vddmax
;
2246 ts
= stm_modscm_dual_calts (imax
, an
, bn
, U
, seuil
, capa
, F
, 0.0, vt
, vddin
, capai
, NULL
, NULL
, slew
, NULL
, 0, 0.0, 0.0, 0.0, NULL
);
2248 ts
= stm_modscm_dual_calts_rsat_full_range(capai
, imax
, an
, bn
, U
, vt
, vddmax
, threshold
, seuil
, rsat
, rlin
, capa
, slew
, F
, stm_modscm_dual_calte (vddin
, vt
, vt
, (double)slew
), t0
, vddin
, pwl
);
2254 /****************************************************************************/
2256 float stm_modscm_dual_slope (dualparams
*params
, float slew
, float load
)
2260 double pconf0
= (double)params
->DP
[STM_PCONF0
];
2261 double pconf1
= (double)params
->DP
[STM_PCONF1
];
2262 double capai
= (double)params
->DP
[STM_CAPAI
];
2263 double irap
= (double)params
->DP
[STM_IRAP
];
2264 double vddin
= (double)params
->DP
[STM_VDDIN
];
2265 double vt
= (double)params
->DP
[STM_VT
];
2266 double threshold
= (double)params
->DP
[STM_THRESHOLD
];
2267 double imax
= (double)params
->DP
[STM_IMAX
];
2268 double an
= (double)params
->DP
[STM_AN
];
2269 double bn
= (double)params
->DP
[STM_BN
];
2271 if( pconf1
*slew
< 10.0*load
)
2272 pconf1
= 1.2 * pconf1
;
2274 cconf
= pconf0
+ pconf1
* slew
;
2275 capa
= capai
+ cconf
* irap
;
2276 capa
+= (double)load
;
2278 return (float)stm_modscm_dual_calslope (imax
, an
, bn
, vddin
, vt
, threshold
, capa
, (double)slew
);
2281 /****************************************************************************/
2283 void stm_modscm_dual_timing( dualparams
*params
,
2296 stm_dual_param_timing paramtiming
;
2297 float threshold
= params
->DP
[STM_THRESHOLD
] ;
2298 float vddin
= params
->DP
[STM_VDDIN
] ;
2299 float vt
= params
->DP
[STM_VT
] ;
2300 float input_thr
= params
->DP
[STM_INPUT_THR
] ;
2301 float delayrc
= params
->DP
[STM_DRC
] ;
2302 float vdd
= params
->DP
[STM_VDDMAX
];
2303 stm_pwth pwthin
[10] ;
2317 paramforslewpwl parampwltanh
;
2319 static int fordebug
=0 ;
2336 load
= stm_modscm_dual_capaeq (params
, NULL
, fin
, r
, c1
, c2
, threshold
, modelname
);
2340 stm_modscm_dual_fill_param( params
, fin
, pwlin
, driver
, load
, ¶mtiming
) ;
2345 tabvout
[nbval
] = threshold
;
2356 s2old
= 0.75 * (vdd
-vt
) + vt
;
2359 if( s1old
> s1new
) seuil1
= s1old
; else seuil1
= s1new
;
2360 if( s2old
> s2new
) seuil2
= s2old
; else seuil2
= s2new
;
2362 if( V_BOOL_TAB
[ __STM_NEW_THRESHOLD
].VALUE
) {
2363 seuil1
= vdd
* STM_DEFAULT_SMINR
;
2364 seuil2
= vdd
* STM_DEFAULT_SMAXR
;
2367 indexslope1
= nbval
;
2368 tabvout
[nbval
] = seuil1
;
2370 indexslope2
= nbval
;
2371 tabvout
[nbval
] = seuil2
;
2376 capa
= paramtiming
.CAPA
;
2377 capa0
= paramtiming
.CAPA0
;
2379 if( paramtiming
.INTEGNUMERIC
) {
2380 paramtiming
.CAPA
= capa
+ load
;
2381 paramtiming
.CAPA0
= capa0
+ load
;
2382 stm_modscm_dual_calts_final_numeric( ¶mtiming
, tabvout
, tabt
, nbval
);
2385 if( V_BOOL_TAB
[ __AVT_NUMSOL_FOR_PILOAD
].VALUE
&& c2
>0 && r
>0.0 ) {
2386 stm_modscm_dual_calts_final_numeric_pi( ¶mtiming
, r
, c1
, c2
, tabvout
, tabt
, nbval
);
2389 for( i
=0 ; i
<nbval
; i
++ ) {
2390 if( r
> 0.0 && c2
> 0.0 ) {
2391 paramtiming
.CAPA
= capa
;
2392 load
= stm_modscm_dual_capaeq (params
, ¶mtiming
, fin
, r
, c1
, c2
, tabvout
[i
], modelname
);
2394 paramtiming
.CAPA
= capa
+ load
;
2395 paramtiming
.CAPA0
= capa0
+ load
;
2396 tabt
[i
] = stm_modscm_dual_calts_with_param_timing( ¶mtiming
, tabvout
[i
] ) ;
2397 if( paramtiming
.NEWCTKMODEL
)
2398 tabtin
[i
] = paramtiming
.TIN
;
2403 paramtiming
.CAPA
= capa
;
2404 paramtiming
.CAPA0
= capa0
;
2408 ts
= tabt
[ indextime
] ;
2412 if( stm_pwl_to_tanh( pwlin
, vt
, vddin
+vt
, pwthin
, &nthin
, fin
) )
2417 te
= stm_get_t_pwth( vddin
, vt
, input_thr
, ptthin
);
2419 if( paramtiming
.NEWCTKMODEL
)
2420 te
= tabtin
[ indextime
] ;
2422 te
= stm_modscm_dual_calte( vddin
, vt
, input_thr
, fin
);
2425 *delay
= ts
- te
+ delayrc
;
2431 *fout
= stm_modscm_dual_slew_old( params
, fin
, load
);
2435 ts1
= tabt
[ indexslope1
] ;
2436 ts2
= tabt
[ indexslope2
] ;
2438 if( ts2
-ts1
> 0.0 ) {
2439 *fout
= stm_thr2scm( ts2
-ts1
,
2450 parampwltanh
.DUALSCM
= ¶mtiming
;
2452 mbkpwlout
= mbk_create_pwl_according_tanh( (char (*)(void*, float, float*))stm_modscm_dual_slew_for_pwl
,
2453 (void*)¶mpwltanh
,
2455 *pwlout
= mbk_pwl_to_stm_pwl( mbkpwlout
);
2456 mbk_pwl_free_pwl( mbkpwlout
);
2466 /****************************************************************************/
2468 float stm_modscm_dual_delay (dualparams
*params
, float slew
, stm_pwl
*pwl
, float load
)
2470 double vddin
= (double)params
->DP
[STM_VDDIN
];
2471 double vt
= (double)params
->DP
[STM_VT
];
2472 double input_thr
= (double)params
->DP
[STM_INPUT_THR
];
2473 double delayrc
= (double)params
->DP
[STM_DRC
];
2480 if( stm_pwl_to_tanh( pwl
, vt
, vddin
+vt
, pwth
, &nth
, slew
) )
2481 te
= stm_get_t_pwth( vddin
, vt
, input_thr
, pwth
);
2483 te
= stm_modscm_dual_calte (vddin
, vt
, input_thr
, (double)slew
);
2486 te
= stm_modscm_dual_calte (vddin
, vt
, input_thr
, (double)slew
);
2488 ts
= stm_modscm_dual_calculduts (params
, slew
, load
, pwl
);
2490 return (float)(ts
- te
+ delayrc
);
2493 /****************************************************************************/
2495 double stm_modscm_dual_calte (double vddin
, double VT
, double seuil
, double fin
)
2500 te
= fin
* atanh((seuil
-VT
)/(vddin
)) ;
2502 te
= fin
* (seuil
-VT
)/(vddin
) ;
2507 /****************************************************************************/
2508 double stm_modscm_dual_calts_old (double imax
,
2538 /* calcul de la tension rapportée à partir de :
2545 if((U
<= 0.0)||(F
<= 0.0))
2551 /* Dans ce qui suit, on a un changement de variable t = t/F
2555 ( ln(2).b²u²-ln(1+b.u) )
2556 imax.( f.t - f.-------------------- )
2560 ( ln( 1 + -----.exp(-2t) ) )
2562 + f.imax.( ------------------------ + ( 1 + --- ).ln( 1+exp(-2t) ) )
2563 ( b²u² - b.u ( b.u ) )
2568 Solution initiale : on néglige la seconde ligne de l'expression
2570 ln(2).b²u²-ln(1+b.u) c.seuil
2571 t - -------------------- = -------
2579 z
= ((seuil
/ 1000.0) * c1
) / imax
;
2581 sf
= ((1.0 + bn1
) * LOG_2
) - (bn1
* bn1
* (log (0.5 * ((bn1
+ 1.0) / bn1
))) / (1.0 - bn1
));
2585 /* Puis on trouve par convergence :
2587 ln( 1 + -----.exp(-2t) )
2588 c.seuil ln(2).b²u²-ln(1+b.u) ( 1+b.u )
2589 t = ------- + -------------------- - ------------------------
2590 f.imax b²u²-b.u b²u² - b.u
2593 - ( 1 + --- ).ln( 1+exp(-2t) )
2601 b
= exp (- 2.0 * tt
);
2602 // ttt correspond aux trois termes avec les ln.
2603 ttt
= (1.0 + bn1
) * log (2.0 / (1.0 + b
))
2604 - ((bn1
* bn1
) / (1.0 - bn1
)) * log (1.0 + ((1.0 - bn1
) * (1.0 - b
) / (2.0 * bn1
)));
2607 while( (fabs((ltt
-tt
)/tt
) > STM_MCC_EPSILON
) && (i
< 20) );
2609 /* On défait le changement de variable */
2614 Qi
= imax
* (ti
- F
* (LOG_2
* BU2
- log(1.0 + BU
))/(BU2
- BU
))
2615 + F
* imax
* (1.0/(BU2
- BU
) * log(1.0 + (1.0 - BU
)/(1.0 + BU
) * exp(-2.0 * ti
/ F
))
2616 + (1.0 + 1.0/BU
) * log(1.0 + exp(-2.0 * ti
/ F
))) - c1
* seuil
/ 1000.0;
2620 tmin
= ti
- 0.1 * ti
;
2621 Qmin
= imax
* (tmin
- F
* (LOG_2
* BU2
- log(1.0 + BU
))/(BU2
- BU
))
2622 + F
* imax
* (1.0/(BU2
- BU
) * log(1.0 + (1.0 - BU
)/(1.0 + BU
) * exp(-2.0 * tmin
/ F
))
2623 + (1.0 + 1.0/BU
) * log(1.0 + exp(-2.0 * tmin
/ F
))) - c1
* seuil
/ 1000.0;
2627 tmax
= ti
+ 0.1 * ti
;
2628 Qmax
= imax
* (tmax
- F
* (LOG_2
* BU2
- log(1.0 + BU
))/(BU2
- BU
))
2629 + F
* imax
* (1.0/(BU2
- BU
) * log(1.0 + (1.0 - BU
)/(1.0 + BU
) * exp(-2.0 * tmax
/ F
))
2630 + (1.0 + 1.0/BU
) * log(1.0 + exp(-2.0 * tmax
/ F
))) - c1
* seuil
/ 1000.0;
2634 while((((Qmin
> 0.0) && (Qmax
> 0.0)) || ((Qmin
< 0.0) && (Qmax
< 0.0))) && (j
< 100)){
2636 Qmax
= imax
* (tmax
- F
* (LOG_2
* BU2
- log(1.0 + BU
))/(BU2
- BU
))
2637 + F
* imax
* (1.0/(BU2
- BU
) * log(1.0 + (1.0 - BU
)/(1.0 + BU
) * exp(-2.0 * tmax
/ F
))
2638 + (1.0 + 1.0/BU
) * log(1.0 + exp(-2.0 * tmax
/ F
))) - c1
* seuil
/ 1000.0;
2639 Qmin
= imax
* (tmin
- F
* (LOG_2
* BU2
- log(1.0 + BU
))/(BU2
- BU
))
2640 + F
* imax
* (1.0/(BU2
- BU
) * log(1.0 + (1.0 - BU
)/(1.0 + BU
) * exp(-2.0 * tmin
/ F
))
2641 + (1.0 + 1.0/BU
) * log(1.0 + exp(-2.0 * tmin
/ F
))) - c1
* seuil
/ 1000.0;
2642 if((Qmin
> 0.0) && (Qmax
> 0.0)){
2644 tmin
= tmin
- (tmax
- tmin
);
2646 }else if((Qmin
< 0.0) && (Qmax
< 0.0)){
2648 tmax
= tmax
+ (tmax
- tmin
);
2652 ti
= tmin
+ (tmax
- tmin
) / 2.0;
2653 while((tmax
- tmin
) > (1000.0 * STM_MCC_EPSILON
) && (j
< 100)){
2655 Qi
= imax
* (ti
- F
* (LOG_2
* BU2
- log(1.0 + BU
))/(BU2
- BU
))
2656 + F
* imax
* (1.0/(BU2
- BU
) * log(1.0 + (1.0 - BU
)/(1.0 + BU
) * exp(-2.0 * ti
/ F
))
2657 + (1.0 + 1.0/BU
) * log(1.0 + exp(-2.0 * ti
/ F
))) - c1
* seuil
/ 1000.0;
2660 ti
= tmin
+ (tmax
- tmin
) / 2.0;
2663 ti
= tmin
+ (tmax
- tmin
) / 2.0;
2668 ti
= (tmax
+ tmin
)/2.0;
2675 void stm_debug( char *fname
,
2700 file
= mbkfopen( fname
, NULL
, "w" ) ;
2702 printf( "can't open file %s\n", fname
) ;
2706 step
= (tmax
-tmin
)/1000.0 ;
2708 for( t
=tmin
; t
<=tmax
; t
=t
+step
) {
2709 q
= stm_get_q( imax
, t
, F
, BN
, U
);
2710 sol
= stm_get_qsat( qsat
, t
+dtin
) + (c
/1000.0)*threshold
+ qinit
+ ci
/1000.0 * (vt
+vddin
* tanh((t
+dtin
)/fin
));
2711 fprintf( file
, "%g %g %g %g %g\n", (t
+tref
)*1e-12, q
*1e-12, sol
*1e-12, (q
-stm_get_qsat(qsat
,t
+dtin
))*1e-12, stm_get_qsat(qsat
, t
+dtin
)*1e-12 );
2717 double stm_modscm_dual_calts (double imax
,
2741 double qcc
, qprev
, qinit
, q
, qsate
;
2746 static int fordebug
=0 ;
2754 ts
= stm_modscm_dual_calts_final( imax
, an
, bn
, U
, seuil
, c
, F
,
2755 vt
, vddin
, ci
, slew
, dt
, qinit0
, strans
, icf0
, qsat
);
2766 for( i
=0 ; i
<nth
-1 ; i
++) {
2768 q
= q
+ stm_get_q( imax
, pwth
[i
].T
, pwth
[i
].F
, bn
, U
)
2769 - ( i
>0 ? stm_get_q( imax
, pwth
[i
-1].T
+pwth
[i
-1].DT
-pwth
[i
].DT
, pwth
[i
].F
, bn
, U
) : 0.0 );
2771 vin
= vt
+ vddin
* tanh( (pwth
[i
].T
+pwth
[i
].DT
) / slew
);
2774 while( k
<3 && vin
> vcap
[k
] ) {
2776 qcapai
= qcapai
+ vcap
[k
-1]*(cie
[k
-1]-cie
[k
])/1000.0;
2781 if( strans
>0.0 && icf0
>0.0 ) {
2782 t
= pwth
[i
].T
+pwth
[i
].DT
;
2785 qconf
= -icf0
*(t
-t
*t
/(2.0*t
));
2787 qcc
= (capai
/1000.0) * vin
;
2788 qsate
= stm_get_qsat( qsat
, pwth
[i
].T
+pwth
[i
].DT
);
2790 vsmax
= (q
-qconf
-qcc
-qinit0
-qsate
-qcapai
)/(c
/1000.0);
2800 qprev
= qinit0
+ stm_get_q( imax
, pwth
[i
-1].T
+pwth
[i
-1].DT
-pwth
[i
].DT
, pwth
[i
].F
, bn
, U
) + qcapai
- qinit
;
2802 qprev
= qinit0
+ qinit
+ qcapai
;
2804 ts
= stm_modscm_dual_calts_final( imax
,
2822 ts
= ts
+ pwth
[i
].DT
;
2827 double stm_modscm_dual_calc_i( double imax
,
2849 if( rnt
> 0.0 && rns
> 0.0 ) {
2850 stm_modscm_dual_calc_rsat( imax
, isat
, a
, b
, rnt
, rns
, rni
, vint
, vdd
, vt
, vgs
, &rsat
, &rlin
, &rint
, &vsat
, &vlin
);
2858 i
= vlin
/rlin
+ (vds
-vlin
)/rint
;
2860 i
= isat
- (vdd
-vds
)/rsat
;
2865 i
= isat
- ( vdd
- vds
) / rsat
;
2876 void stm_plot_final_i( char *filename
, param_final_i
*p
)
2884 ptf
= fopen( filename
, "w" );
2886 perror( "can't open file " );
2890 u
= p
->VINR
- p
->VT
;
2891 isat
= p
->A
*u
*u
/ ( 1.0 + p
->B
*u
);
2892 save_vout
= p
->VOUT
;
2894 for( p
->VOUT
=0.0 ; p
->VOUT
<= p
->VDDOUT
; p
->VOUT
= p
->VOUT
+ p
->VDDOUT
/100.0 ) {
2895 ids
= stm_modscm_dual_calts_final_i( p
);
2896 fprintf( ptf
, "%g %g\n", p
->VOUT
, ids
);
2900 p
->VOUT
= save_vout
;
2903 double stm_modscm_dual_calts_final_i( param_final_i
*p
)
2910 u
= p
->VINR
- p
->VT
;
2911 isat
= p
->A
*u
*u
/ ( 1.0 + p
->B
*u
);
2913 vds
= p
->VDDOUT
- p
->VOUT
;
2915 i
= stm_modscm_dual_calc_i( p
->IMAX
, isat
, p
->A
, p
->B
, p
->RNT
, p
->RNS
, p
->RINT
, p
->VINT
, p
->VDDOUT
, p
->VT
, p
->VIN
, vds
);
2920 int stm_modscm_dual_calts_final_numeric_find_next_seuil( int index
, float *tabv
, int nbpoint
)
2928 seuil
= tabv
[index
] ;
2935 for( i
=0 ; i
<nbpoint
; i
++ ) {
2936 if( tabv
[i
] > seuil
) {
2937 if( tabv
[i
] < vmin
) {
2947 void stm_modscm_dual_calts_final_numeric_pi( stm_dual_param_timing
*paramtiming
,
2977 param_final_i param
;
2983 c1
= paramtiming
->CAPA
/1000.0 + cl1
/1000.0 ;
2985 ci
= paramtiming
->CAPAI
/1000.0 ;
2988 dt
= (c1
+c2
)*paramtiming
->VDDMAX
/paramtiming
->IMAX
/step
;
2990 k1
= 1.0/( c1
/dt
+ c2
/(dt
+r
*c2
) );
2992 v1
= 0.0 ; // to do : inclure valeur qinit et ci
2993 v2
= 0.0 ; // to do : inclure valeur qinit et ci
2998 param
.IMAX
= paramtiming
->IMAX
;
2999 param
.A
= paramtiming
->AN
;
3000 param
.B
= paramtiming
->BN
;
3001 param
.U
= paramtiming
->U
;
3002 param
.RNT
= paramtiming
->RLIN
;
3003 param
.RNS
= paramtiming
->RSAT
;
3004 param
.RINT
= paramtiming
->RINT
;
3005 param
.VINT
= paramtiming
->VINT
;
3006 param
.VT
= paramtiming
->VT
;
3007 param
.VDDOUT
= paramtiming
->VDDMAX
;
3008 param
.VIN
= paramtiming
->VT
;
3009 param
.VINR
= paramtiming
->VT
;
3012 index
= stm_modscm_dual_calts_final_numeric_find_next_seuil( index
, tabv
, nbpoint
);
3015 seuil
= tabv
[ index
] ;
3028 uin
= paramtiming
->VDDIN
* tanh( t
/ paramtiming
->FIN
) ;
3029 uinr
= paramtiming
->U
* tanh( t
/ paramtiming
->F
) ;
3032 param
.VIN
= paramtiming
->VT
+ uin
;
3033 param
.VINR
= paramtiming
->VT
+ uinr
;
3035 i
= stm_modscm_dual_calts_final_i( ¶m
);
3037 k0
= c1
*v10
/dt
+ c2
*v20
/(dt
+r
*c2
) + ci
*vi0
/dt
;
3038 v1
= k1
* ( i
- ci
*param
.VIN
/dt
+ k0
) ;
3039 v2
= v1
- r
*c2
*v1
/(dt
+r
*c2
) + r
*c2
*v20
/(dt
+r
*c2
) ;
3042 while( v1
< seuil
);
3043 ts
= ( t
-lt
)/( v1
-v10
)*( seuil
-v10
) + lt
;
3050 void stm_modscm_dual_calts_final_numeric( stm_dual_param_timing
*paramtiming
,
3083 param_final_i param
;
3088 q
= -paramtiming
->QINIT
;
3091 ci
= paramtiming
->CAPAI
/ 1000.0 ;
3092 c
= paramtiming
->CAPA
/ 1000.0 ;
3093 chalf
= paramtiming
->CHALF
/ 1000.0 ;
3097 dt
= ((c
+fabs(chalf
)) * paramtiming
->VDDMAX
/ (2.0 * paramtiming
->IMAX
) )/ step
;
3099 param
.IMAX
= paramtiming
->IMAX
;
3100 param
.A
= paramtiming
->AN
;
3101 param
.B
= paramtiming
->BN
;
3102 param
.U
= paramtiming
->U
;
3103 param
.RNT
= paramtiming
->RLIN
;
3104 param
.RNS
= paramtiming
->RSAT
;
3105 param
.RINT
= paramtiming
->RINT
;
3106 param
.VINT
= paramtiming
->VINT
;
3107 param
.VT
= paramtiming
->VT
;
3108 param
.VDDOUT
= paramtiming
->VDDMAX
;
3112 v
= ( q
- ci
* param
.VT
)/c
;
3121 index
= stm_modscm_dual_calts_final_numeric_find_next_seuil( index
, tabv
, nbpoint
);
3125 seuil
= tabv
[ index
] ;
3132 if( v
>= paramtiming
->VDDMAX
/2.0 && !half_set
) {
3149 uin
= paramtiming
->VDDIN
* tanh( t
/ paramtiming
->FIN
) ;
3150 uinr
= paramtiming
->U
* tanh( t
/ paramtiming
->F
) ;
3153 param
.VIN
= paramtiming
->VT
+ uin
;
3154 param
.VINR
= paramtiming
->VT
+ uinr
;
3156 i
= stm_modscm_dual_calts_final_i( ¶m
);
3158 if( paramtiming
->RBR
> 0.0 && paramtiming
->CBR
> 0.0 && t
> lt
) {
3160 vr
= i
*paramtiming
->RBR
;
3161 k
= 1.0/( 1.0/paramtiming
->RBR
+ (paramtiming
->CBR
/1000.0)/(t
-lt
) );
3162 vrc
= k
*( i
+ lvrc
* (paramtiming
->CBR
/1000.0)/(t
-lt
) );
3164 param
.VIN
= paramtiming
->VT
+ uin
+ dv
;
3165 param
.VINR
= paramtiming
->VT
+ uinr
+ dv
* uinr
/uin
;
3166 i
= stm_modscm_dual_calts_final_i( ¶m
);
3169 dq
= (i
+li
)*(t
-lt
)/2.0 ;
3172 if( v
< paramtiming
->VDDMAX
/2.0 ) {
3174 v
= ( q
- ci
* param
.VIN
)/c
;
3180 v
= v0
+ ( (q
-q0
) - ci
*(param
.VIN
-vin0
) )/(c
-chalf
);
3184 while( v
< seuil
&& iter
< 100*step
);
3186 ts
= ( t
-lt
)/( v
-lv
)*( seuil
-lv
) + lt
;
3191 while( index
>= 0 );
3194 /* valide la solution t pour q(t)-qsat(t) */
3196 int stm_modscm_dual_calts_valid( double imax
,
3211 if( !V_BOOL_TAB
[ __STM_CHECK_SOLUTION
].VALUE
|| checksol
==NO
)
3217 dq
= imax
*(1.0+bu
)*th
*th
/(1.0+bu
*th
);
3218 dqsat
= stm_get_qsat_derivative( qsat
, t
);
3220 if( dq
-dqsat
<= 0.0 )
3227 double stm_modscm_dual_calts_final (double imax
,
3250 double backup_tsatmax
;
3251 static int fordebug
= 0 ;
3255 if( V_BOOL_TAB
[ __STM_CHECK_SOLUTION
].VALUE
&& qsat
) {
3256 backup_tsatmax
= qsat
->TSATMAX
;
3257 qsat
->TSATMAX
= FLT_MAX
;
3260 status1
= stm_modscm_dual_calts_amjad( imax
, bn
, U
, seuil
, c
, F
, vt
, vddin
, ci
, slew
, dtin
, qinit
, qsat
, strans
, icf0
, &t
);
3262 if( status1
== CALTS_AMJAD_OK
) {
3263 if( ! stm_modscm_dual_calts_valid( imax
, bn
, U
, F
, dtin
, qsat
, t
, YES
) ) {
3264 status1
= CALTS_AMJAD_NC
;
3268 if( status1
== CALTS_AMJAD_NC
) {
3271 t
= (c
/1000.0*seuil
)/imax
;
3272 status2
= stm_modscm_dual_calts_dichotomie( imax
, bn
, U
, seuil
, c
, F
, vt
, vddin
, ci
, slew
, dtin
, qinit
, qsat
, strans
, icf0
, &t
, YES
) ;
3276 case CALTS_DICHO_NOSOL
:
3278 if( V_BOOL_TAB
[ __STM_CHECK_SOLUTION
].VALUE
&& qsat
) {
3279 avt_log( LOGDEBUG
, 1, "stm_modscm_dual_calts_final(%d) : no solution found -> fix tsatmax\n", fordebug
);
3281 status3
= stm_modscm_dual_calts_dichotomie( imax
, bn
, U
, seuil
, c
, F
, vt
, vddin
, ci
, slew
, dtin
, qinit
, qsat
, strans
, icf0
, &t
, NO
) ;
3282 if( status3
!= CALTS_DICHO_OK
) {
3283 avt_log( LOGDEBUG
, 1, " -> failed !\n" );
3288 avt_log( LOGDEBUG
, 1, "stm_modscm_dual_calts_final(%d) : no solution found -> very strange case !!!\n", fordebug
);
3292 case CALTS_DICHO_NC
:
3294 if( V_BOOL_TAB
[ __STM_CHECK_SOLUTION
].VALUE
&& qsat
) {
3295 avt_log( LOGDEBUG
, 1, "stm_modscm_dual_calts_final(%d) : no convergence -> fix tsatmax\n", fordebug
);
3297 status3
= stm_modscm_dual_calts_dichotomie( imax
, bn
, U
, seuil
, c
, F
, vt
, vddin
, ci
, slew
, dtin
, qinit
, qsat
, strans
, icf0
, &t
, NO
) ;
3298 if( status3
!= CALTS_DICHO_OK
) {
3299 avt_log( LOGDEBUG
, 1, " -> failed !\n" );
3304 avt_log( LOGDEBUG
, 1, "stm_modscm_dual_calts_final(%g) : no convergence -> very strange case !!!\n", fordebug
);
3309 if( V_BOOL_TAB
[ __STM_CHECK_SOLUTION
].VALUE
&& qsat
) {
3310 qsat
->TSATMAX
= backup_tsatmax
;
3314 /* if status2 == CALTS_DICHO_KO, revenir à modèle ceqrsat */
3318 int stm_modscm_dual_calts_amjad (double imax
,
3350 /* calcul de la tension rapportée à partir de :
3357 if((U
<= 0.0)||(F
<= 0.0))
3363 /* Dans ce qui suit, on a un changement de variable t = t/F
3367 ( ln(2).b²u²-ln(1+b.u) )
3368 imax.( f.t - f.-------------------- )
3372 ( ln( 1 + -----.exp(-2t) ) )
3374 + f.imax.( ------------------------ + ( 1 + --- ).ln( 1+exp(-2t) ) )
3375 ( b²u² - b.u ( b.u ) )
3377 = c.seuil + qsat2*t*t + ci * ( vt + vddin.th(t) ) + qinit + icf0*(t-t*t/(2*strans))
3380 Solution initiale : on néglige la seconde ligne de l'expression
3382 ln(2).b²u²-ln(1+b.u) c.seuil ci.vt qinit
3383 t - -------------------- = ------- + ------ + ------
3384 b²u²-b.u f.imax f.imax f.imax
3391 z
= (seuil
* c1
/1000.0 + vt
* ci
/1000.0 + qinit
) / imax
;
3393 sf
= ((1.0 + bn1
) * LOG_2
) - (bn1
* bn1
* (log (0.5 * ((bn1
+ 1.0) / bn1
))) / (1.0 - bn1
));
3396 if((TESTIM
> 0.0) && (TESTIM
> dtin
))
3397 tt
= (TESTIM
-dtin
)/F
;
3402 /* Puis on trouve par convergence :
3404 ln( 1 + -----.exp(-2t) )
3405 c.seuil ln(2).b²u²-ln(1+b.u) ( 1+b.u )
3406 t = ------- + -------------------- - ------------------------
3407 f.imax b²u²-b.u b²u² - b.u
3410 - ( 1 + --- ).ln( 1+exp(-2t) )
3415 /* pas sur que le critère de Lipschitz soit bon suite à l'introduction de qsat2 */
3419 b
= exp (- 2.0 * tt
);
3420 // ttt correspond aux trois termes avec les ln et le ci.
3421 ttt
= (1.0 + bn1
) * log (2.0 / (1.0 + b
))
3422 - ((bn1
* bn1
) / (1.0 - bn1
)) * log (1.0 + ((1.0 - bn1
) * (1.0 - b
) / (2.0 * bn1
)))
3423 + ci
/1000.0 * vddin
* tanh((tt
*F
+dtin
)/slew
)/F
/imax
+ stm_get_qsat(qsat
,tt
*F
)/F
/imax
;
3428 ttt
= ttt
- icf0
*(tin
-tin
*tin
/(2.0*strans
))/F
/imax
;
3432 while( (fabs((F
*ltt
-F
*tt
)/(F
*tt
+dtin
)) > STM_MCC_EPSILON
) && tt
< 10.0*tinit
&& (i
< 20) );
3434 /* On défait le changement de variable */
3437 if( i
>=20 || tt
>= 10.0*tinit
)
3438 ret
= CALTS_AMJAD_NC
;
3440 ret
= CALTS_AMJAD_OK
;
3445 inline double stm_modscm_dual_calts_dicho_q( double imax
,
3467 q
= imax
* (t
- f
* (LOG_2
))
3468 + f
* imax
* (2 * log(1.0 + exp(-2.0 * t
/ f
)));
3470 q
= imax
* (t
- f
* (LOG_2
* bu2
- log(1.0 + bu
))/(bu2
- bu
))
3471 + f
* imax
* (1.0/(bu2
- bu
) * log(1.0 + (1.0 - bu
)/(1.0 + bu
) * exp(-2.0 * t
/ f
))
3472 + (1.0 + 1.0/bu
) * log(1.0 + exp(-2.0 * t
/ f
)));
3474 q
+= - c
* seuil
/ 1000.0 - ci
/1000.0 * ( vt
+ vddin
* tanh((t
+dtin
)/fin
)) - qinit
- stm_get_qsat(qsat
,t
);
3476 if( strans
> 0.0 ) {
3480 q
= q
+ icf0
*(tin
-tin
*tin
/(2.0*strans
));
3486 /* une solution estimée doit être donnée dans *t */
3487 int stm_modscm_dual_calts_dichotomie( double imax
,
3513 int ret
= CALTS_DICHO_OK
;
3527 /* Etat initial : trouver qmin<0 valide et qmax>0 qui peut etre non valide */
3530 validmax
= stm_modscm_dual_calts_valid( imax
, bn
, U
, F
, dtin
, qsat
, tmax
, checksol
) ;
3532 Qmax
= stm_modscm_dual_calts_dicho_q( imax
, tmax
, F
, BU
, BU2
, c
, seuil
, ci
, vt
, vddin
, dtin
, fin
, qinit
, strans
, icf0
, qsat
) ;
3543 if( Qmax
< 0 && validmax
) {
3549 Qmax
= stm_modscm_dual_calts_dicho_q( imax
, tmax
, F
, BU
, BU2
, c
, seuil
, ci
, vt
, vddin
, dtin
, fin
, qinit
, strans
, icf0
, qsat
);
3550 validmax
= stm_modscm_dual_calts_valid( imax
, bn
, U
, F
, dtin
, qsat
, tmax
, checksol
) ;
3554 while( Qmax
< 0.0 && validmax
&& iter
);
3557 avt_log( LOGDEBUG
, 1, "stm_modscm_dual_calts_dichotomie() : no convergence\n" );
3558 ret
= CALTS_DICHO_NOSOL
;
3564 Qmin
= stm_modscm_dual_calts_dicho_q( imax
, tmin
, F
, BU
, BU2
, c
, seuil
, ci
, vt
, vddin
, dtin
, fin
, qinit
, strans
, icf0
, qsat
);
3571 Qmin
= stm_modscm_dual_calts_dicho_q( imax
, tmin
, F
, BU
, BU2
, c
, seuil
, ci
, vt
, vddin
, dtin
, fin
, qinit
, strans
, icf0
, qsat
);
3575 /* converge pour trouver qmax positif et valide */
3577 if( ret
== CALTS_DICHO_OK
&& !validmax
) {
3586 tm
= ( tvmin
+ tvmax
) / 2.0 ;
3587 validm
= stm_modscm_dual_calts_valid( imax
, bn
, U
, F
, dtin
, qsat
, tm
, checksol
) ;
3589 qm
= stm_modscm_dual_calts_dicho_q( imax
, tm
, F
, BU
, BU2
, c
, seuil
, ci
, vt
, vddin
, dtin
, fin
, qinit
, strans
, icf0
, qsat
);
3593 if( validm
&& qm
< 0.0 ) {
3604 while( !(validmin
&& validmax
) && iter
&& (tvmax
-tvmin
)>0.1 );
3610 if( !validmin
|| !validmax
)
3611 ret
= CALTS_DICHO_NOSOL
;
3614 /* dichotomie classique d'une fonction croissante à une seule racine, Qmin et Qmax sont valides */
3616 if( ret
== CALTS_DICHO_OK
) {
3622 tm
= ( tmin
+ tmax
)/2.0 ;
3623 qm
= stm_modscm_dual_calts_dicho_q( imax
, tm
, F
, BU
, BU2
, c
, seuil
, ci
, vt
, vddin
, dtin
, fin
, qinit
, strans
, icf0
, qsat
);
3632 while((tmax
- tmin
) > (1000.0 * STM_MCC_EPSILON
) && iter
);
3635 ret
= CALTS_DICHO_NC
;
3637 *t
= ( tmin
+ tmax
)/2.0 ;
3643 /****************************************************************************/
3646 Calcule rsat d'un transistor lorsqu'on a un VGS différent de VDD.
3647 Voir les explications dans mon classeur, chapitre rsat.
3650 void stm_modscm_dual_calc_rsat( double imax
,
3668 double x
, kres
, ures
, rsat
, rsatmin
, k
, rlin
, ires
;
3669 double vr
, ir
, gsep
, ire
, vre
;
3672 rsatmin
= vdd
/imax
;
3674 if( rsat_r
) *rsat_r
= -1.0 ;
3675 if( rlin_r
) *rlin_r
= -1.0 ;
3676 if( rint_r
) *rint_r
= -1.0 ;
3677 if( vsat_r
) *vsat_r
= -1.0 ;
3678 if( vlin_r
) *vlin_r
= -1.0 ;
3680 if( rni
< 0.0 && rnt
< rsatmin
&& rns
> rsatmin
) {
3682 rsatmin
= vdd
/isat
;
3684 k
= imax
*rnt
/ (vdd
-vt
) ;
3685 rlin
= k
* ( 1.0 + b
* (vgs
-vt
) ) / ( a
* (vgs
-vt
) ) ;
3687 if( rlin
> rsatmin
)
3690 x
= ( imax
*rnt
- vdd
*rnt
/rns
) / ( 1.0 - rnt
/rns
) ;
3691 kres
= x
/ ( vdd
- vt
) ;
3692 ures
= kres
* ( vgs
- vt
) ;
3693 ires
= ures
/ rlin
;
3694 rsat
= ( vdd
- ures
) / ( isat
- ires
) ;
3696 if( rsat
< rsatmin
)
3699 if( rsat_r
) *rsat_r
= rsat
;
3700 if( rlin_r
) *rlin_r
= rlin
;
3701 if( vsat_r
) *vsat_r
= ures
;
3707 /* calcul point 1 vgs=vdd : (vint;iint) */
3710 /* calcul point 2 vgs=vdd : (vr;ir) */
3711 vr
= ( imax
- iint
+ vint
/rni
- vdd
/rns
) * ( rns
* rni
) / ( rns
- rni
) ;
3712 ir
= imax
- (vdd
-vr
)/rns
;
3714 /* calcul point 2 vgs<>vdd : (vre;ire) */
3715 ire
= ir
*(vgs
-vt
)/(vdd
-vt
) ;
3716 if( ire
> 0.95*isat
)
3718 gsep
= ir
/(vdd
-vr
) ;
3719 vre
= vr
+ (ir
-ire
)/gsep
;
3721 /* calcul rlin vgs<>vdd */
3722 k
= ir
*rnt
/(vdd
-vt
);
3723 rlin
= k
*(vgs
-vt
)/ire
;
3725 /* calcul point 1 vgs<>vdd : (ures;ires) */
3726 kres
= vint
/(vdd
-vt
) ;
3727 ures
= kres
*(vgs
-vt
) ;
3730 /* calcul rsat et rint */
3731 rsat
= (vdd
-vre
)/(isat
-ire
) ;
3732 rint
= (vre
-ures
)/(ire
-ures
/rlin
) ;
3735 avt_log( LOGSTM
, 3, "warning : vr(%g)<vint(%g)\n", vr
, vint
);
3738 avt_log( LOGSTM
, 3, "warning : iint(%g)>ir(%g)\n", iint
, ir
);
3741 avt_log( LOGSTM
, 3, "warning : vre(%g)<ures(%g)\n", vre
, ures
);
3744 avt_log( LOGSTM
, 3, "warning : ire(%g)<ires(%g)\n", ire
, ires
);
3747 avt_log( LOGSTM
, 3, "warning : isat(%g)<ire(%g)\n", isat
, ire
);
3749 if( rsat_r
) *rsat_r
= rsat
;
3750 if( rlin_r
) *rlin_r
= rlin
;
3751 if( rint_r
) *rint_r
= rint
;
3752 if( vsat_r
) *vsat_r
= vre
;
3753 if( vlin_r
) *vlin_r
= ures
;
3756 if( rnt
> rsatmin
&& rns
< rsatmin
) {
3757 vr
= (imax
-vdd
/rns
)*(rns
*rnt
)/(rns
-rnt
) ;
3759 gsep
= ir
/(vdd
-vr
) ;
3760 ire
= ir
*(vgs
-vt
)/(vdd
-vt
) ;
3761 vre
= vr
+ (ir
-ire
)/gsep
;
3762 rsat
= (vdd
-vre
)/(isat
-ire
) ;
3764 if( rsat_r
) *rsat_r
= rsat
;
3765 if( rlin_r
) *rlin_r
= rlin
;
3766 if( vsat_r
) *vsat_r
= vre
;
3772 /****************************************************************************/
3775 Calcule le vgs du transistor lorsque la sortie commute.
3776 Pour l'instant, ne prend pas en compte le rbr/cbr.
3779 double stm_modscm_dual_calc_vin( double vddin
,
3787 vgs
= vddin
*tanh( ts
/slew
) + vt
;
3789 if( vgs
<=0.0 || vgs
>= vddin
+vt
)
3794 /****************************************************************************/
3796 double stm_modscm_dual_ceqrsat_numeric( stm_dual_param_timing
*param
, double seuil
)
3824 vddin
= param
->VDDIN
;
3826 qinit
= param
->QINIT
;
3831 imax
= param
->IMAX
;
3832 vdd
= param
->VDDMAX
;
3833 rlin
= param
->RLIN
;
3834 rsat
= param
->RSAT
;
3835 capai
= param
->CAPAI
/ 1000.0 ;
3836 capa
= param
->CAPA
/ 1000.0 ;
3837 dt
= param
->T0
/ 100.0 ;
3844 vin
= vt
+ vddin
* tanh( t
/fin
) ;
3845 q
= stm_get_q( imax
, t
, f
, b
, u
) ;
3846 vout
= ( q
- capai
*vin
- qinit
)/capa
;
3847 isat
= a
*(vin
-vt
)*(vin
-vt
)/(1.0+b
*(vin
-vt
));
3848 stm_modscm_dual_calc_rsat( imax
, isat
, a
, b
, rlin
, rsat
, -1.0, -1.0, vdd
, vt
, vin
, &rs
, NULL
, NULL
, NULL
, NULL
) ;
3853 qsat
= qsat
+ vout
/rs
;
3856 while( vout
< seuil
);
3858 ceqrsat
= qsat
*dt
/seuil
*1000.0 ;
3863 /****************************************************************************/
3866 Calcule une capacité equivalente à la charge perdue dans rsat lors d'une
3867 transition. La transition est modélisée par une tangente hyperbolique.
3869 vt, vmax, f : paramètres de la tangente hyperbolique de sortie.
3870 rsat : valeur de la résistance.
3871 seuil : tension où l'on réalise la mesure
3872 threshold : seuil logique de la porte : vdd/2
3873 te : instant de commutation de l'entrée minimum à partir duquel
3875 ts : instant de commutation de la sortie à threshold
3876 fout : estimation du front de sortie.
3878 retour : capacité equivalente.
3880 ATTENTION : cette fonction ne doit pas s'utiliser si on a un modèle de
3881 switch utilisant RINT.
3884 double stm_modscm_dual_ceqrsat( double imax
,
3885 double vt
, // output slope
3888 double vddin
, // input slope normalized
3899 double ta
, // Instant de début de la commutation.
3900 tb
, // Instant de fin de la commutation.
3901 qsat
, // Charge equivalente.
3902 ceq
, // Capacité equivalente.
3903 dt
, // Ecart entre les deux référentiels
3904 tee
, // Instant de commutation de la sortie
3908 double vgsa
, vgsb
, dve
;
3911 static int fordebug
= 0 ;
3916 if( seuil
> 0.97 * vmax
)
3917 seuil
= 0.97 * vmax
;
3921 t>=0 : v=vt+(vdd-vt)*tanh(t/f)
3922 t<0 : v=(vdd-vt)*t/f+vt
3925 ta
= -f
* vt
/ (vmax
-vt
);
3928 tb
= f
* atanh( (seuil
-vt
)/(vmax
-vt
) ) ;
3930 tb
= f
* (seuil
-vt
)/(vmax
-vt
) ;
3932 if( threshold
> vt
)
3933 tst
= f
* atanh( (threshold
-vt
)/(vmax
-vt
) ) ;
3935 tst
= f
* (threshold
-vt
)/(vmax
-vt
) ;
3937 // On vérifie si on est bien après l'entrée.
3938 dt
= ts
-tst
; // Ecart entre le référentiel de l'entrée et de la sortie
3939 tee
= dt
+ta
; // Début de commutation de la sortie dans le référentiel de l'entrée
3941 ta
= te
-dt
; // Début de commutation de la sortie
3948 vea
= vddin
- vddin
*tanh( (ta
+dt
)/fin
) ;
3949 veb
= vddin
- vddin
*tanh( (tb
+dt
)/fin
) ;
3954 for( i
=0; i
< n
; i
++ ) {
3956 vgsa
= vea
+ dve
*((float)i
) ;
3958 if( vgsa
< 0.01*vmax
) {
3960 /* lorsque vgsb devient très faible, le calcul de tsb est impossible (atanh(1)=inf).
3961 On considère dans ce cas qu'on est sur la dernière borne qui va jusqu'à tb */
3971 tsa
= fin
* atanh( (vddin
-vgsa
)/vddin
) - dt
;
3975 if( vgsb
< 0.01*vmax
) {
3976 /* lorsque vgsb devient très faible, le calcul de tsb est impossible (atanh(1)=inf).
3977 On considère dans ce cas qu'on est sur la dernière borne qui va jusqu'à tb */
3983 tsb
= fin
* atanh( (vddin
-vgsb
)/vddin
) - dt
;
3986 vgs
= (vddin
+vt
)-vgsb
;
3987 isat
= an
*(vgs
-vt
)*(vgs
-vt
)/(1.0+bn
*(vgs
-vt
));
3988 stm_modscm_dual_calc_rsat( imax
, isat
, an
, bn
, rlin
, rsat
, -1.0, -1.0, vmax
, vt
, vgs
, &rsatr
, NULL
, NULL
, NULL
, NULL
);
3995 qsat
= qsat
+ ( f
*(vmax
-vt
) * log(cosh(tsb
/f
)/cosh(tsa
/f
)) + vt
*(tsb
-tsa
) ) / rsatr
;
3998 ceq
= qsat
/ seuil
* 1000.0 ;
4006 /****************************************************************************/
4008 double stm_modscm_dual_calts_rsat_full_range (double capai
,
4042 if( stm_pwl_to_tanh( pwl
, VT
, vddin
+VT
, pwth
, &npwth
, fin
) )
4046 fout
= stm_modscm_dual_calslew( imax
, an
, bn
, U
, VT
, vddmax
, c
, fin
, F
, t0
);
4048 ceqrsat
= stm_modscm_dual_ceqrsat( imax
, VT
, vddmax
, fout
, U
, F
, rsat
, rlin
, an
, bn
, seuil
, threshold
, te
, t0
);
4049 capa
= c
+ ceqrsat
;
4051 rsatmin
= vddmax
/imax
;
4053 if( rsat
> rsatmin
&& rsatmin
> rlin
) {
4054 vsat
= vddmax
- ( imax
- vddmax
/ rsat
) * rlin
* rsat
/ ( rsat
- rlin
) ;
4056 tf
= stm_modscm_dual_calts( imax
, an
, bn
, U
, seuil
, capa
, F
, 0.0, VT
, vddin
, capai
, NULL
, NULL
, fin
, ptpwth
, npwth
, 0.0, 0.0, 0.0, NULL
);
4058 tsat
= stm_modscm_dual_calts( imax
, an
, bn
, U
, vsat
, capa
, F
, 0.0, VT
, vddin
, capai
, NULL
, NULL
, fin
, ptpwth
, npwth
, 0.0, 0.0, 0.0, NULL
);
4059 /* bonne relation, mise en commentaire en attendant que soit résulu le pb de modélisation des slopes
4060 qui rend certains bench d'ifx defectueux
4061 tf = tsat - rlin * c/1000.0 * log( 1.0 - ( seuil - vsat ) / ( vddmax - vsat ) );
4063 tf
= tsat
- rlin
* (capa
+capai
)/1000.0 * log( 1.0 - ( seuil
- vsat
) / ( vddmax
- vsat
) );
4067 tf
= stm_modscm_dual_calts( imax
, an
, bn
, U
, seuil
, capa
, F
, 0.0, VT
, vddin
, capai
, NULL
, NULL
, fin
, ptpwth
, npwth
, 0.0, 0.0, 0.0, NULL
);
4072 /****************************************************************************/
4074 double stm_modscm_dual_calslew (double imax
,
4091 /* pente en vdd/2 et front de sortie */
4092 pente
= imax
* ((1 + bn
* U
) * pow (tanh (ts
/ F
), 2)) / (c
* (1 + bn
* U
* tanh (ts
/ F
)));
4094 if( VT
< vddmax
/2.0 )
4095 fout
= ((3 * vddmax
- 4 * VT
) * vddmax
) / (4 * pente
* (vddmax
- VT
)) / 1000;
4097 fout
= (vddmax
-VT
)/pente
/1000.0 ;
4103 /****************************************************************************/
4105 long stm_modscm_dual_calslope (double imax
,
4130 /* calcul de la tension rapportée */
4131 U
= (imax
* bn
+ sqrt (pow ((imax
* bn
), 2) + 4 * an
* imax
)) / (2 * an
);
4133 /* calcul du front rapporté */
4134 F
= fin
* U
/ vddin
;
4140 /* calcul des deux premiers termes de l'équation de charge Qn(t) */
4141 z
= ((seuil
/ 1000) * c1
) / (F
* an1
* U
);
4142 tt
= (1.0 + bn1
) * z
;
4144 sf
= ((1.0 + bn1
) * LOG_2
) - (bn1
* bn1
* (log (0.5 * ((bn1
+ 1.0) / bn1
))) / (1.0 - bn1
));
4147 /* convergence du troisieme terme */
4152 b
= exp (-2.0 * tt
);
4153 ttt
= (1.0 + bn1
) * log (2.0 / (1.0 + b
))
4154 - ((bn1
* bn1
) / (1.0 - bn1
)) * log (1.0 + ((1.0 - bn1
) * (1.0 - b
) / (2.0 * bn1
)));
4155 tt
= (1.0 + bn1
) * z
+ ttt
;
4157 while( (fabs((ltt
-tt
)/tt
) > STM_MCC_EPSILON
) && (i
< 100) );
4159 k
= (seuil
- VT
) / vddin
;
4160 sf
= (tt
/ (rc
+ sf
)) * sf
;
4161 sf
-= 0.5 * log ((1.0 + k
) / (1.0 - k
)) ;
4162 slope
= (long)(1000.0 * sf
) ;
4167 /****************************************************************************/
4169 float stm_modscm_dual_capaeq ( dualparams
*dual
, stm_dual_param_timing
*paramtiming
, float slew
, float r
, float c1
, float c2
, float vth
, char *signame
)
4171 stm_param_isat param
;
4175 float localthreshold
;
4179 cconf
= stm_modscm_dual_cconf ( dual
, slew
);
4182 if( paramtiming
&& V_BOOL_TAB
[ __AVT_CEQRSAT_FOR_PILOAD
].VALUE
) {
4183 if( vth
>= paramtiming
->VSAT
)
4184 localthreshold
= paramtiming
->VSAT
;
4186 localthreshold
= vth
;
4187 stm_modscm_dual_calts_qsat( paramtiming
, localthreshold
, NULL
, &qsat
, &ceqrsat
, NULL
);
4190 if( paramtiming
&& V_BOOL_TAB
[ __STM_ENHANCED_CAPAEQ_FOR_PILOAD
].VALUE
) {
4191 param
.IMAX
= paramtiming
->IMAX
;
4192 param
.A
= paramtiming
->AN
;
4193 param
.B
= paramtiming
->BN
;
4194 param
.VT
= paramtiming
->VT
;
4195 param
.U
= paramtiming
->U
;
4196 param
.F
= paramtiming
->F
;
4197 param
.NTH
= paramtiming
->NTHSHRK
;
4198 param
.PWTH
= paramtiming
->PWTHSHRK
;
4199 cconf
= 2.0*paramtiming
->CAPAI
+ paramtiming
->CAPA
;
4203 param
.IMAX
= dual
->DP
[STM_IMAX
] ;
4204 param
.B
= dual
->DP
[STM_BN
] ;
4207 stm_modscm_dual_cal_UF( dual
->DP
[STM_IMAX
],
4210 dual
->DP
[STM_VDDIN
],
4220 capaadd
= cconf
+ ceqrsat
;
4221 if( paramtiming
&& vth
> dual
->DP
[STM_THRESHOLD
] && V_BOOL_TAB
[ __STM_PILOAD_SATURATION
].VALUE
)
4222 load
= stm_capaeq_fn( (char (*)(void*,double,double*)) stm_isat
, (void*) ¶m
, 10.0*slew
, r
, c1
+capaadd
, c2
, vth
, paramtiming
->VSAT
, paramtiming
->RLIN
, paramtiming
->VDDMAX
, signame
);
4224 load
= stm_capaeq_fn( (char (*)(void*,double,double*)) stm_isat
, (void*) ¶m
, 10.0*slew
, r
, c1
+capaadd
, c2
, vth
, -1.0, -1.0, -1.0, signame
);
4225 load
= load
- capaadd
;
4230 /****************************************************************************/
4232 char stm_isat( stm_param_isat
*param
, double t
, double *i
)
4240 uin
= stm_get_v_pwth( t
, param
->VT
, param
->U
+param
->VT
, STM_UP
, param
->PWTH
)-param
->VT
;
4241 *i
= param
->A
*uin
*uin
/(1.0+param
->B
*uin
);
4242 if( *i
> param
->IMAX
) {
4248 *i
= stm_get_ic_imax( t
, param
->U
, param
->IMAX
, param
->F
, param
->B
);
4254 /****************************************************************************/
4256 int stmtanhfn( stmtanhdata
*data
, double t
, double *v
)
4258 if( t
-data
->T0
>0.0 )
4259 *v
= data
->VT
+(data
->VDD
-data
->VT
)*tanh( (t
-data
->T0
)/data
->F
);
4261 *v
= (data
->VDD
-data
->VT
)*(t
-data
->T0
)/data
->F
+data
->VT
;
4269 void stm_plot_tanh( char *name
, float f
, float vt
, float vdd
, float t0
, float vth
, char sens
)
4278 ptf
= mbkfopen( name
, NULL
, "w" );
4280 printf( "can't open file for writing\n" );
4285 te
= f
* (vth
-vt
)/(vdd
-vt
);
4287 te
= f
* atanh((vth
-vt
)/(vdd
-vt
));
4293 if( sens
=='U' || sens
=='u' || sens
=='R' || sens
=='r' )
4297 fprintf( ptf
, "%g %g\n", (t
+dt
)*1e-12, v
);
4299 for( t
=0.0 ; t
<=3*f
; t
++ ) {
4300 vu
= vt
+(vdd
-vt
)*tanh(t
/f
);
4301 if( sens
=='U' || sens
=='u' || sens
=='R' || sens
=='r' )
4305 fprintf( ptf
, "%g %g\n", (t
+dt
)*1e-12, v
);