1 /****************************************************************************/
3 /* Chaine de CAO & VLSI AVERTEC */
5 /* Produit : STM Version 1.00 */
6 /* Fichier : stm_pwl.c */
8 /* (c) copyright 2000 AVERTEC */
9 /* Tous droits reserves */
11 /* Auteur(s) : Gilles Augustins */
13 /****************************************************************************/
15 /****************************************************************************/
17 /****************************************************************************/
21 /****************************************************************************/
23 /****************************************************************************/
25 /* Transforme une structure stm_pwl en un ensemble de tangentes hyperbolique
26 le tableau pwth doit contenir (n-1) éléments.
27 Renvoie 1 si OK, 0 si un pb est survenu.
28 ntanh contient au retour le nb d'éléments dans pwth.
31 int stm_pwl_to_tanh( stm_pwl
*pwl
,
40 double v1
, v2
, t1
, t2
;
53 for( i
=0 ; i
<n
; i
++) {
55 t1
= pwl
->TAB
[ 2*i
+0 ] ;
56 v1
= pwl
->TAB
[ 2*i
+1 ] ;
57 t2
= pwl
->TAB
[ 2*i
+2 ] ;
58 v2
= pwl
->TAB
[ 2*i
+3 ] ;
60 if( v1
< vm
|| fabs((v2
-v1
)/v1
) < 1.0e-6 )
63 if( v1
> 0.99*vdd
|| v2
> 0.99*vdd
) {
68 k1
= atanh( (v1
-vt
)/(vdd
-vt
) );
69 k2
= atanh( (v2
-vt
)/(vdd
-vt
) );
71 dt
= ( t2
*k1
- t1
*k2
) / (k1
-k2
) ;
72 f
= ( t1
-t2
) / ( k1
-k2
);
78 pwth
[*ntanh
].DT
= dt
-dt0
;
79 pwth
[*ntanh
].T
= t2
-pwth
[*ntanh
].DT
;
86 pwth
[(*ntanh
)-1].T
= FLT_MAX
;
91 void stm_pwl_debug_pwl_q( double vt
,
101 stm_pwth tabthin
[32] ;
104 double imax
, an
, bn
, u
, f
;
112 sprintf( name
, "%s_q.dat", filename
);
114 if( !stm_pwl_to_tanh( pwlin
, vt
, vdd
, tabthin
, &nthin
, fin
) ) {
115 printf( "error in stm_pwl_to_tanh()\n" );
119 ptf
= fopen( name
, "w" );
123 imax
= params
->DP
[STM_IMAX
];
124 an
= params
->DP
[STM_AN
];
125 bn
= params
->DP
[STM_BN
];
126 stm_modscm_dual_cal_UF( imax
, an
, bn
, (vdd
-vt
), 0.0, fin
, &u
, &f
);
128 for( t
=0.0 ; t
<=tp
; t
=t
+0.1 ) {
132 for( i
=0 ; i
<nthin
&& tabthin
[i
].T
+tabthin
[i
].DT
< t
; i
++) {
134 q
= q
+ stm_get_q( imax
, tabthin
[i
].T
, tabthin
[i
].F
, bn
, u
)
135 - ( i
>0 ? stm_get_q( imax
, tabthin
[i
-1].T
+tabthin
[i
-1].DT
-tabthin
[i
].DT
, tabthin
[i
].F
, bn
, u
) : 0.0 );
138 q
= q
+ stm_get_q( imax
, t
- tabthin
[i
].DT
, tabthin
[i
].F
, bn
, u
)
139 - ( i
>0 ? stm_get_q( imax
, tabthin
[i
-1].T
+tabthin
[i
-1].DT
-tabthin
[i
].DT
, tabthin
[i
].F
, bn
, u
) : 0.0 );
141 fprintf( ptf
, "%g %g %g\n", t
, q
, stm_get_q( imax
, t
, fin
, bn
, u
) );
147 void stm_pwl_debug_pwl_to_tanh( stm_pwl
*pwl
,
161 char filenamepwldat
[256] ;
162 char filenametanhdat
[256] ;
163 char filenamemccdat
[256] ;
164 char filenamegpl
[256] ;
169 stm_pwth tabth
[32], tabthin
[32];
175 double tref_th
, tref_pw
, tabs
=100.0, dt_th
=0.0, trefthout
;
177 stm_dual_param_timing paramtimingpwl
;
178 stm_dual_param_timing paramtimingtanh
;
182 env
= getenv( "DEBUG_PWL_TE" );
189 sprintf( filenamepwldat
, "%s_pwl.dat", filename
);
190 sprintf( filenametanhdat
, "%s_tanh.dat", filename
);
193 sprintf( filenamemccdat
, "%s_mcc.dat", filename
);
195 sprintf( filenamegpl
, "%s.gpl", filename
);
197 filepwldat
= fopen( filenamepwldat
, "w" );
199 printf( "can't open file %s for writting\n", filenamepwldat
);
203 filetanhdat
= fopen( filenametanhdat
, "w" );
205 printf( "can't open file %s for writting\n", filenametanhdat
);
210 filemccdat
= fopen( filenamemccdat
, "w" );
212 printf( "can't open file %s for writting\n", filenamemccdat
);
217 filegpl
= fopen( filenamegpl
, "w" );
219 printf( "can't open file %s for writting\n", filenamegpl
);
223 if( !stm_pwl_to_tanh( pwl
, vt
, vdd
, tabth
, &nth
, fold
) ||
224 !stm_pwl_to_tanh( pwlin
, vt
, vdd
, tabthin
, &nthin
, fin
) ) {
225 printf( "error in stm_pwl_to_tanh()\n" );
226 fclose( filetanhdat
) ;
227 fclose( filepwldat
) ;
232 tref_th
= tabs
- stm_get_t(vdd
/2.0, vt
, 0.0, vdd
, fin
) ;
233 dt_th
= stm_get_t(vt
, vt
, 0.0, vdd
, fin
) ;
234 tref_pw
= tabs
- stm_get_t_pwth(vdd
-vt
, vt
, vdd
/2.0, tabthin
) ;
236 trefthout
= stm_modscm_dual_calculduts_threshold( params
,
242 - stm_get_t_pwth(vdd
-vt
, vt
, vdd
/2.0, tabth
) ;
244 for( i
=0 ; i
<pwl
->N
; i
++ ) {
246 fprintf( filepwldat
, "%g %g\n", (pwl
->TAB
[2*i
]+tref_pw
)*1e-12, pwl
->TAB
[2*i
+1] );
248 fprintf( filepwldat
, "%g %g\n", vdd
- (pwl
->TAB
[2*i
]+tref_pw
)*1e-12, pwl
->TAB
[2*i
+1] );
249 tmax
= 2.0*pwl
->TAB
[2*i
]+tref_pw
;
252 for( t
=0.0 ; t
<=tmax
; t
++ ) {
253 fprintf( filetanhdat
, "%g ", t
*1e-12 );
256 fprintf( filetanhdat
, "%g ", stm_get_v_pwth( t
-trefthout
, vt
, vdd
, STM_UP
, tabth
) );
258 fprintf( filetanhdat
, "%g ", vdd
-stm_get_v_pwth( t
-trefthout
, vt
, vdd
, STM_UP
, tabth
) );
261 fprintf( filetanhdat
, "%g ", stm_get_v( t
-tref_pw
-tp
, vt
, 0.0, vdd
, fold
) );
263 fprintf( filetanhdat
, "%g ", vdd
-stm_get_v( t
-tref_pw
-tp
, vt
, 0.0, vdd
, fold
) );
266 fprintf( filetanhdat
, "%g ", stm_get_v_pwth( t
-tref_pw
, vt
, vdd
, STM_UP
, tabthin
) );
268 fprintf( filetanhdat
, "%g ", vdd
-stm_get_v_pwth( t
-tref_pw
, vt
, vdd
, STM_UP
, tabthin
) );
271 fprintf( filetanhdat
, "%g\n", stm_get_v( t
-tref_th
, vt
, 0.0, vdd
, fin
) );
273 fprintf( filetanhdat
, "%g\n", vdd
-stm_get_v( t
-tref_th
, vt
, 0.0, vdd
, fin
) );
277 stm_modscm_dual_fill_param( params
, fin
, pwlin
, NULL
, load
, ¶mtimingpwl
);
278 stm_modscm_dual_fill_param( params
, fin
, NULL
, NULL
, load
, ¶mtimingtanh
);
280 for( v
=0.01*vdd
; v
<=0.99*vdd
; v
=v
+0.01*vdd
) {
281 tspwl
= stm_modscm_dual_calts_with_param_timing( ¶mtimingpwl
, v
);
282 tstanh
= stm_modscm_dual_calts_with_param_timing( ¶mtimingtanh
, v
);
284 fprintf( filemccdat
, "%g %g %g\n", ( tspwl
+ tref_pw
) * 1e-12,
285 ( tstanh
+ tref_th
+ dt_th
) * 1e-12,
286 eventout
=='U' ? v
: vdd
-v
292 "set key bottom right\n"
296 "plot [0:%g] '%s' title \"pwl\" with linespoints, '%s' using 1:2 title \"pwtanh\" with lines, '%s' using 1:3 title \"old tanh\" with lines, '%s' using 1:3 title \"mcc (in=pwl)\" with lines, '%s' using 2:3 title \"mcc (in=th)\" with lines, '%s' using 1:5 title \"input old tanh\" with lines, '%s' using 1:4 title \"input pwl\" with lines\n",
308 "plot [0:%g] '%s' title \"pwl\" with linespoints, '%s' using 1:2 title \"pwtanh\" with lines, '%s' using 1:3 title \"old tanh\" with lines\n",
314 fprintf( filegpl
, "pause -1\n" );
317 fclose( filepwldat
);
318 fclose( filetanhdat
);
320 fclose( filemccdat
);
323 int stm_get_v_pwth_fn( stm_pwth_fn
*args
, double t
, double *v
)
325 *v
= stm_get_v_pwth( t
,
334 /* Renvoie la tension à l'instant t */
335 double stm_get_v_pwth (float t
, float vt
, float vdd
, char sens
, stm_pwth
*pwth
)
343 v
= vt
+ (vdd
-vt
)*t
/pwth
[0].F
;
349 while( pwth
[i
].DT
+ pwth
[i
].T
< t
)
352 v
= vt
+ (vdd
-vt
)*tanh( (t
- pwth
[i
].DT
) / pwth
[i
].F
) ;
356 if( sens
== STM_DN
) {
363 /* Renvoie l'instant t où le signal passe à v */
364 double stm_get_t_pwth (float vddin
, float vt
, float seuil
, stm_pwth
*pwth
)
366 double vemax
, tmax
, dt
, f
;
371 te
= pwth
[0].F
*(seuil
-vt
)/vddin
;
379 vemax
= vt
+ vddin
*tanh(tmax
/f
);
380 if( vemax
< seuil
) {
384 while( vemax
< seuil
);
386 te
= stm_modscm_dual_calte( vddin
, vt
, seuil
, f
) + dt
;
392 void stm_plot_pwth( stm_pwth
*pwth
, char *filename
, float t0
, float vddin
, float vt
, float vth
, char sens
)
401 ptf
= mbkfopen( filename
, NULL
, "w" ) ;
403 printf( "can't open file \"%s\" for writting\n", filename
) ;
407 te
= stm_get_t_pwth( vddin
, vt
, vth
, pwth
);
410 for( v
=0.02*vddin
; v
<=0.98*(vddin
+vt
) ; v
=v
+vddin
/100 ) {
411 t
= stm_get_t_pwth( vddin
, vt
, v
, pwth
);
412 if( tolower(sens
)=='d' || tolower(sens
)=='f' )
416 fprintf( ptf
, "%g %g\n", (t
+dt
)*1e-12, vr
);