Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / tas / stm / stm_simu.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI AVERTEC */
4 /* */
5 /* Produit : STM Version 1.00 */
6 /* Fichier : stm_noise.c */
7 /* */
8 /* (c) copyright 2000 AVERTEC */
9 /* Tous droits reserves */
10 /* */
11 /* Auteur(s) : Grégoire Avot */
12 /* */
13 /****************************************************************************/
14
15 /****************************************************************************/
16 /* includes */
17 /****************************************************************************/
18
19 #include "stm.h"
20
21 /****************************************************************************/
22 /* functions */
23 /****************************************************************************/
24
25 stm_simu_pi_load_parameter stm_simu_param_standard = {
26 /* DEFAULT_TIME_STEP */ 10.0 , // 10 FS
27 /* MIN_TIME_STEP */ 1.0 , // 1 FS
28 /* MAX_TIME_STEP */ 100.0 , // 100 Fs
29 /* MAX_DELTA_CURRENT */ 0.000100 , // 100uA
30 /* MIN_DELTA_CURRENT */ 0.000001 , // 1uA
31 /* MAX_DELTA_VOLTAGE */ 0.001000 , // 1000uV
32 /* MIN_DELTA_VOLTAGE */ 0.000010 , // 10uV
33 /* MAX_ITER */ 100000 ,
34 /* VARIABLE_STEP */ 1 ,
35 /* STAT_ITER */ 0 ,
36 /* STAT_CHANGE_STEP */ 0 ,
37 /* STAT_MIN_TIME_STEP */ 0.0 ,
38 /* STAT_MAX_TIME_STEP */ 0.0 ,
39 /* STAT_MIN_DELTA_VOLTAGE */ 0.0 ,
40 /* STAT_MAX_DELTA_VOLTAGE */ 0.0 ,
41 /* STAT_MIN_DELTA_CURRENT */ 0.0 ,
42 /* STAT_MAX_DELTA_CURRENT */ 0.0
43 };
44
45 /******************************************************************************\
46
47 \******************************************************************************/
48
49 /******************************************************************************\
50
51 Convention générateur :
52 transition UD : le courant décharge la sortie, il est négatif.
53 transition DU : le courant charge la sortie, il est positif
54
55 \******************************************************************************/
56
57 char stm_simu_mcc_ids( param_mcc_ids *param, float vgs, float vds, float *ids )
58 {
59 float a = param->A;
60 float b = param->B;
61 float vdd = param->VDD;
62 float rnt = param->RNT;
63 float rns = param->RNS;
64 float vt = param->VT;
65 char neg = param->NEG;
66 float imax = param->IMAX;
67 float kres;
68 float k;
69 float x;
70
71 float isat ;
72 float usat ;
73 float rlin ;
74 float ures ;
75 float ires ;
76 float rsat ;
77
78 /* Initialisation */
79 if( param->k == 0.0 ) {
80
81 k = imax * rnt / (vdd-vt );
82
83 x = ( imax * rnt - vdd*rnt/rns )/( 1.0 - rnt/rns );
84 kres = x/(vdd-vt);
85
86 param->k = k;
87 param->kres = kres;
88 }
89 else {
90 k = param->k;
91 kres = param->kres;
92 }
93
94 /* Calcul */
95 usat = k*(vgs-vt);
96 isat = a*(vgs-vt)*(vgs-vt) / ( 1.0 + b*(vgs-vt) );
97 rlin = usat/isat;
98
99 ures = kres*( vgs-vt );
100 ires = ures/rlin;
101 rsat = (vdd-ures) / (isat-ires);
102
103 if( vds > ures )
104 *ids = isat - (vdd-vds)/rsat;
105 else
106 *ids = vds/rlin;
107
108 if( neg )
109 *ids = -(*ids);
110
111 return 1;
112 }
113
114 /******************************************************************************\
115
116 \******************************************************************************/
117
118 char stm_simu_tanh( stm_simu_tanh_param *param, float t, float *v )
119 {
120 *v = stm_get_v( t, param->VT, param->VI, param->VF, param->F );
121 return 1;
122 }
123
124 /******************************************************************************\
125
126 Unités :
127 --------
128 Courant Ampère
129 Tension Volt
130 Capacité Femto-seconde
131 Temps Femto-seconde
132
133 Paramètres :
134 ------------
135 fn_is Pointeur sur fonction de calcul du courant dans la branche.
136 fn_ve Pointeur sur fonction de calcul de la tension d'entrée.
137 dat_is Données utilisées par fn_is.
138 dat_ve Données utilisées par fn_ve.
139 r, c1, c2 Charge de la branche.
140 vi Tension initiale de la sortie.
141 vth Tension de sortie à laquelle la simulation s'arrète.
142 ts, fs Pointeurs vers le temps et le front simulé lorsque la sortie
143 vaut vth. NULL autorisé.
144 param Configuration du simulateur. NULL autorisé.
145
146 Notes :
147 -------
148
149 Le front calculé correspond à la pente du signal, en V/fs. Il ne correspond
150 PAS au front défini par Amjad. Le passage de l'un à l'autre se fait avec la
151 relation 3-12-b page III/15 de la thèse.
152
153 \******************************************************************************/
154
155 char stm_simu_pi_load_ts( char (*fn_is)( void *dat_is,
156 float ve,
157 float vs,
158 float *is
159 ),
160 char (*fn_ve)( void *dat_ve, float t, float *v ),
161 void *dat_is,
162 void *dat_ve,
163 float r,
164 float c1,
165 float c2,
166 float vi,
167 float vth,
168 float *ts,
169 float *fs,
170 stm_simu_pi_load_parameter *param,
171 char *plotcurvename
172 )
173 {
174 double vx1, vx2, vx3, vx4, vx5;
175 double a, b;
176 double ti, tj;
177 double dt;
178 double v1i, v1j ;
179 double v2i, v2j ;
180 float ii, ij ;
181 double di;
182 double dv;
183 int needmodifyconst;
184 int i;
185 char ret=1;
186 float ve ;
187 char encore;
188 double t0;
189 FILE *ptf=NULL ;
190
191 /* Various initialisation */
192
193 if( plotcurvename ) {
194 ptf = mbkfopen( plotcurvename, "dat", WRITE_TEXT );
195 fprintf( ptf, "#time vin vout igate\n" );
196 }
197
198 if( !param ) param = &stm_simu_param_standard ;
199
200 param->STAT_ITER = 0.0 ;
201 param->STAT_CHANGE_STEP = 0.0;
202 param->STAT_MIN_TIME_STEP = 1.0e9;
203 param->STAT_MAX_TIME_STEP = -1.0e9;
204 param->STAT_MIN_DELTA_VOLTAGE = 1.0e9;
205 param->STAT_MAX_DELTA_VOLTAGE = -1.0e9;
206 param->STAT_MIN_DELTA_CURRENT = 1.0e9;
207 param->STAT_MAX_DELTA_CURRENT = -1.0e9;
208
209 ti = 0.0 ;
210 ii = 0.0 ;
211 dt = param->DEFAULT_TIME_STEP ;
212 b = r * c2;
213 v1i = vi ;
214 v2i = vi ;
215 needmodifyconst = 1;
216 t0 = 0.0 ;
217
218 do
219 {
220 tj = ti ;
221 ij = ii ;
222 v1j = v1i ;
223 v2j = v2i ;
224
225 /* Variable step */
226 do
227 {
228
229 if( needmodifyconst )
230 {
231 param->STAT_CHANGE_STEP++;
232 a = b + dt;
233 vx1 = 1.0/( c1 / dt + c2 / a );
234 vx2 = c1 / dt;
235 vx3 = ( c2 - b * c2 / a ) / dt;
236 vx4 = dt / a ;
237 vx5 = b / a ;
238 needmodifyconst = 0;
239 }
240
241 /* Le corp du simulateur */
242 ti = tj + dt ;
243 if( !fn_ve( dat_ve, ti-t0, &ve ) ) {
244 ret=0;
245 break;
246 }
247
248 for( i=3;i>0;i-- ) {
249 if( !fn_is( dat_is, ve, v1i, &ii ) ) {
250 ret=0;
251 break;
252 }
253 v1i = vx1 * ( ii + vx2 * v1j + vx3 * v2j ) ;
254 }
255 if( !ret )
256 break;
257
258 v2i = vx4 * v1i + vx5 * v2j ;
259 /* Fin du corp */
260
261 if( param->VARIABLE_STEP ) {
262 /* Vérification du step */
263 di = ii - ij ;
264 if( di < 0.0 )
265 di = -di ;
266
267 dv = v1i - v1j ;
268 if( dv < 0 )
269 dv = -dv ;
270
271 if( ( dv > param->MAX_DELTA_VOLTAGE ||
272 di > param->MAX_DELTA_CURRENT ) && dt > param->MIN_TIME_STEP )
273 {
274 dt = dt / 2.0 ;
275 needmodifyconst=1;
276 }
277 }
278 }
279 while( needmodifyconst );
280
281 if( !ret )
282 break;
283
284 if( param->VARIABLE_STEP ) {
285 /* Vérification du step */
286 if( ( di < param->MIN_DELTA_CURRENT &&
287 dv < param->MIN_DELTA_VOLTAGE ) && dt < param->MAX_TIME_STEP )
288 {
289 dt = dt * 1.2 ;
290 needmodifyconst=1;
291 }
292 }
293
294 di = ii - ij;
295 if( dv < param->STAT_MIN_DELTA_VOLTAGE ) param->STAT_MIN_DELTA_VOLTAGE = dv;
296 if( dv > param->STAT_MAX_DELTA_VOLTAGE ) param->STAT_MAX_DELTA_VOLTAGE = dv;
297 if( dt < param->STAT_MIN_TIME_STEP ) param->STAT_MIN_TIME_STEP = dt;
298 if( dt > param->STAT_MAX_TIME_STEP ) param->STAT_MAX_TIME_STEP = dt;
299 if( di < param->STAT_MIN_DELTA_CURRENT ) param->STAT_MIN_DELTA_CURRENT = di;
300 if( di > param->STAT_MAX_DELTA_CURRENT ) param->STAT_MAX_DELTA_CURRENT = di;
301
302 param->STAT_ITER++;
303
304 // test de sortie
305
306 if( ptf )
307 fprintf( ptf, "%g %g %g %g\n", ti, ve, v1i, ii );
308
309 encore = 1;
310 if( param->STAT_ITER > param->MAX_ITER )
311 encore = 0 ;
312 if( ( v1i > vth && v1j < vth ) || ( v1i < vth && v1j > vth ) )
313 encore = 0 ;
314 }
315 while( encore );
316
317 if( !ret || param->STAT_ITER >= param->MAX_ITER ) {
318 if(ts) *ts = 0.0;
319 if(fs) *fs = 0.0;
320 ret=0;
321 }
322 else {
323 if(ts) *ts = tj+(vth-v1j)/(v1i-v1j)*(ti-tj);
324 if(fs) *fs = fabs(v1i-v1j)/dt;
325 ret=1;
326 }
327
328 if( ptf )
329 fclose( ptf );
330 return ret;
331 }