Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / tas / trc / trc_awe.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI AVERTEC */
4 /* */
5 /* Produit : RCX - AWE support. */
6 /* Fichier : trc_awe.c */
7 /* */
8 /* (c) copyright 2000 AVERTEC */
9 /* Tous droits reserves */
10 /* */
11 /* Auteur(s) : Grégoire Avot */
12 /* */
13 /****************************************************************************/
14
15 /* CVS informations :
16
17 Revision : $Revision: 1.107 $
18 Author : $Author: fabrice $
19 Date : $Date: 2008/03/27 15:16:20 $
20
21 */
22
23 //#define AWEDEBUG
24 #define AWE_NORMALISE
25
26 #include "trc.h"
27
28 /******************************************************************************\
29 * Code *
30 \******************************************************************************/
31
32 int AWECACHE;
33 awetabnode_list *AWEHEADTABNODE = NULL ; // Allocation par bloc
34 char RCX_AWESTRAIGHT=0;
35 char RCX_STEPTANH=0;
36 #ifdef AWEDEBUG
37 int awestatcallinfo=0;
38 int awestatcallmoment=0;
39 int awestatcallfilter=0;
40 int awestatnbheapinfo=0;
41 #endif
42 char RCX_USING_AWEMATRIX=RCX_USING_AWEMATRIX_IFNEED;
43 char RCX_AWE_ONE_PNODE='N';
44
45 losig_list *AWE_DEBUG_NET ;
46 locon_list *AWE_DEBUG_DRIVER ;
47 locon_list *AWE_DEBUG_RECEIVER ;
48 char *RCX_PLOT_AWE=NULL;
49 char *AWE_DUMP_NETNAME ;
50 char AWE_DUMP_SLOPE ;
51 char AWE_FAST_MODE='N';
52 int AWE_MAX_ITER=1000;
53
54 awetabnode* aweallocnodes( void )
55 {
56 awetabnode_list *pt;
57 int i;
58
59 if( AWEHEADTABNODE == NULL ) {
60 AWEHEADTABNODE = (awetabnode_list*)(mbkalloc( sizeof( awetabnode_list ) * AWESIZETABNODE ) );
61 pt = AWEHEADTABNODE ;
62 for( i=1 ; i < AWESIZETABNODE ; i++ ) {
63 pt->NEXT = pt+1;
64 pt++;
65 }
66 pt->NEXT = NULL;
67 }
68
69 pt = AWEHEADTABNODE;
70 AWEHEADTABNODE = AWEHEADTABNODE->NEXT;
71
72 /* initialisation des moments et de la capacité */
73 for( i=0 ; i < AWE_MAX_MOMENT ; i++ )
74 pt->TABNODE.MOMENT[i] = 0.0 ;
75 pt->TABNODE.SUMMOMENTCAPA = 0.0;
76
77 return((awetabnode*)pt);
78 }
79
80 void aweunallocnodes( awetabnode *tofree )
81 {
82 awetabnode_list *pt;
83
84 pt = (awetabnode_list*)(tofree);
85
86 pt->NEXT = AWEHEADTABNODE;
87 AWEHEADTABNODE = pt;
88 }
89
90 int awe_dw_forbuildnodes( losig_list *losig,
91 lonode_list *lonode,
92 chain_list *chwire,
93 ht *htpack,
94 awetreetrip *data
95 )
96 {
97 chain_list *headht ;
98 rcx_triangle *tr ;
99 awetabnode *tabnode;
100 awetabnode *ltabnode;
101 lonode_list *ptnode ;
102 chain_list *chain ;
103 chain_list *chrep ;
104 RCXFLOAT c ;
105 lowire_list *wire ;
106 int inode ;
107 ptype_list *ptl ;
108
109 if( !data->reset ) {
110 tabnode = aweallocnodes();
111 if( getptype( lonode->USER, AWENODE ) ) {
112 awe_error( 0, AVT_INTERNAL );
113 }
114 lonode->USER = addptype( lonode->USER, AWENODE, tabnode );
115 }
116 else {
117 ptl = getptype( lonode->USER, AWENODE );
118 if( !ptl ) {
119 awe_error( 1, AVT_INTERNAL );
120 }
121 tabnode = (awetabnode*)ptl->DATA ;
122 }
123
124 c = rcx_getnodecapa( losig,
125 lonode,
126 data->extcapa,
127 data->slope,
128 data->type,
129 TRC_HALF,
130 data->coefctc
131 );
132 tabnode->CAPA = c ;
133 tabnode->SUMMOMENTCAPA = c ;
134
135 for( chain = chwire ; chain ; chain = chain->NEXT ) {
136 wire = (lowire_list*)chain->DATA ;
137 inode = (wire->NODE1 == lonode->INDEX ? wire->NODE2 : wire->NODE1 );
138 ptnode = getlonode( losig, inode );
139 ltabnode = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA;
140 tabnode->SUMMOMENTCAPA = tabnode->SUMMOMENTCAPA + ltabnode->SUMMOMENTCAPA ;
141 }
142
143 headht = GetAllHTElems( htpack );
144
145 for( chain = headht ; chain ; chain = chain->NEXT ) {
146 wire = (lowire_list*)((chain_list*)chain->DATA)->DATA ;
147 tr = (rcx_triangle*)rcn_getpack( losig, wire ) ;
148
149 ltabnode = (awetabnode*)getptype( tr->n1->USER, AWENODE )->DATA;
150 tabnode->SUMMOMENTCAPA = tabnode->SUMMOMENTCAPA + ltabnode->SUMMOMENTCAPA ;
151
152 ltabnode = (awetabnode*)getptype( tr->n2->USER, AWENODE )->DATA;
153 tabnode->SUMMOMENTCAPA = tabnode->SUMMOMENTCAPA + ltabnode->SUMMOMENTCAPA ;
154
155 for( chrep = tr->REPORTED_IN ; chrep ; chrep = chrep->NEXT ) {
156 ptnode = (lonode_list*)chrep->DATA ;
157 ltabnode = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA;
158 tabnode->SUMMOMENTCAPA = tabnode->SUMMOMENTCAPA + ltabnode->SUMMOMENTCAPA;
159 }
160
161 for( chrep = tr->REPORTED_N1 ; chrep ; chrep = chrep->NEXT ) {
162 ptnode = (lonode_list*)chrep->DATA ;
163 ltabnode = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA;
164 tabnode->SUMMOMENTCAPA = tabnode->SUMMOMENTCAPA + ltabnode->SUMMOMENTCAPA;
165 }
166
167 for( chrep = tr->REPORTED_N2 ; chrep ; chrep = chrep->NEXT ) {
168 ptnode = (lonode_list*)chrep->DATA ;
169 ltabnode = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA;
170 tabnode->SUMMOMENTCAPA = tabnode->SUMMOMENTCAPA + ltabnode->SUMMOMENTCAPA;
171 }
172 }
173
174 freechain( headht );
175
176 return 1 ;
177 }
178
179 void awebuildnodes( losig_list *losig,
180 lonode_list *node,
181 RCXFLOAT extcapa,
182 rcx_slope *slopemiller,
183 char type,
184 RCXFLOAT coefctc,
185 char reset
186 )
187 {
188 awetreetrip infos ;
189 lowire_list *wire ;
190
191 infos.extcapa = extcapa ;
192 infos.slope = slopemiller ;
193 infos.type = type ;
194 infos.coefctc = coefctc ;
195 infos.reset = reset ;
196
197 avt_logenterfunction(LOGTRC,2, "awebuildnodes()" );
198
199 clearallwireflag( losig, RCN_FLAG_PASS );
200 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
201 RCN_CLEARFLAG( wire->FLAG, RCXNODEINTR );
202
203 rcn_treetrip( losig,
204 node,
205 NULL,
206 (int (*)(losig_list*,lonode_list*,chain_list*,ht*,void*))awe_dw_forbuildnodes,
207 NULL,
208 &infos,
209 0
210 );
211 avt_logexitfunction(LOGTRC,2);
212 }
213
214 int awe_up_formoment( losig_list *losig,
215 lonode_list *lonode,
216 lowire_list *lowire,
217 aweinfmmt *info
218 )
219 {
220 awetabnode *moment;
221 awetabnode *prevmoment;
222 int inode ;
223 lonode_list *prevnode ;
224
225 if( lowire ) {
226 inode = (lowire->NODE1 == lonode->INDEX ) ? lowire->NODE2 : lowire->NODE1 ;
227 prevnode = getlonode( losig, inode );
228
229 moment = (awetabnode*)getptype( lonode->USER, AWENODE )->DATA ;
230 prevmoment = (awetabnode*)getptype( prevnode->USER, AWENODE )->DATA ;
231
232 moment->MOMENT[info->ordre-1] = prevmoment->MOMENT[info->ordre-1] -
233 rcn_get_resi_para( lowire ) / info->k * moment->SUMMOMENTCAPA ;
234 }
235 return 1 ;
236 }
237
238 int awe_dw_formoment( losig_list *losig,
239 lonode_list *lonode,
240 chain_list *chwire,
241 ht *htpack,
242 aweinfmmt *info
243 )
244 {
245 awetabnode *moment ;
246 RCXFLOAT smc = 0.0 ;
247 chain_list *chain ;
248 chain_list *headht ;
249 rcx_triangle *tr ;
250 awetabnode *ltabnode ;
251 lowire_list *wire ;
252 int inode ;
253 lonode_list *ptnode ;
254 chain_list *chrep ;
255
256 moment = (awetabnode*)getptype( lonode->USER, AWENODE )->DATA ;
257
258 for( chain = chwire ; chain ; chain = chain->NEXT ) {
259
260 wire = (lowire_list*)chain->DATA ;
261
262 inode = (wire->NODE1 == lonode->INDEX ) ? wire->NODE2 : wire->NODE1 ;
263 ptnode = getlonode( losig, inode );
264
265 ltabnode = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA ;
266
267 smc = smc + ltabnode->SUMMOMENTCAPA ;
268 }
269
270 headht = GetAllHTElems( htpack );
271
272 for( chain = headht ; chain ; chain = chain->NEXT ) {
273 wire = (lowire_list*)((chain_list*)chain->DATA)->DATA ;
274 tr = (rcx_triangle*)rcn_getpack( losig, wire ) ;
275
276 ltabnode = (awetabnode*)getptype( tr->n1->USER, AWENODE )->DATA;
277 smc = smc + ltabnode->SUMMOMENTCAPA ;
278
279 ltabnode = (awetabnode*)getptype( tr->n2->USER, AWENODE )->DATA;
280 smc = smc + ltabnode->SUMMOMENTCAPA ;
281
282 for( chrep = tr->REPORTED_IN ; chrep ; chrep = chrep->NEXT ) {
283 ptnode = (lonode_list*)chrep->DATA ;
284 ltabnode = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA;
285 smc = smc + ltabnode->SUMMOMENTCAPA ;
286 }
287
288 for( chrep = tr->REPORTED_N1 ; chrep ; chrep = chrep->NEXT ) {
289 ptnode = (lonode_list*)chrep->DATA ;
290 ltabnode = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA;
291 smc = smc + ltabnode->SUMMOMENTCAPA ;
292 }
293
294 for( chrep = tr->REPORTED_N2 ; chrep ; chrep = chrep->NEXT ) {
295 ptnode = (lonode_list*)chrep->DATA ;
296 ltabnode = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA;
297 smc = smc + ltabnode->SUMMOMENTCAPA ;
298 }
299 }
300
301 smc = smc + moment->CAPA * moment->MOMENT[info->ordre-1];
302
303 moment->SUMMOMENTCAPA = smc ;
304
305 freechain( headht );
306
307 return 1 ;
308 }
309
310 int awe_packup_formoment( losig_list *losig,
311 lonode_list *lonode,
312 rcx_triangle *tr,
313 aweinfmmt *info
314 )
315 {
316 awetabnode *moment ;
317 awetabnode *repmoment ;
318 awetabnode *mmtn1 ;
319 awetabnode *mmtn2 ;
320 RCXFLOAT immt ;
321 RCXFLOAT mmc1 ;
322 RCXFLOAT mmc2 ;
323 chain_list *chain ;
324 lonode_list *ptnode ;
325
326 moment = (awetabnode*)getptype( lonode->USER, AWENODE )->DATA ;
327
328 for( chain = tr->REPORTED_IN ; chain ; chain = chain->NEXT ) {
329
330 ptnode = (lonode_list*)chain->DATA ;
331
332 repmoment = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA ;
333 repmoment->MOMENT[info->ordre-1] = moment->MOMENT[info->ordre-1] ;
334 }
335
336 mmtn1 = (awetabnode*)getptype( tr->n1->USER, AWENODE )->DATA ;
337 mmtn2 = (awetabnode*)getptype( tr->n2->USER, AWENODE )->DATA ;
338
339 mmc1 = mmtn1->SUMMOMENTCAPA ;
340 mmc2 = mmtn2->SUMMOMENTCAPA ;
341
342 for( chain = tr->REPORTED_N1 ; chain ; chain = chain->NEXT ) {
343 ptnode = (lonode_list*)chain->DATA ;
344 repmoment = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA ;
345 mmc1 = mmc1 + repmoment->SUMMOMENTCAPA ;
346 }
347 for( chain = tr->REPORTED_N2 ; chain ; chain = chain->NEXT ) {
348 ptnode = (lonode_list*)chain->DATA ;
349 repmoment = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA ;
350 mmc2 = mmc2 + repmoment->SUMMOMENTCAPA ;
351 }
352
353 immt = moment->MOMENT[info->ordre-1] - tr->Z0 / info->k * ( mmc1 + mmc2 ) ;
354
355 mmtn1->MOMENT[info->ordre-1] = immt - tr->Z1 / info->k * mmc1 ;
356 mmtn2->MOMENT[info->ordre-1] = immt - tr->Z2 / info->k * mmc2 ;
357
358 for( chain = tr->REPORTED_N1 ; chain ; chain = chain->NEXT ) {
359
360 ptnode = (lonode_list*)chain->DATA ;
361
362 repmoment = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA ;
363 repmoment->MOMENT[info->ordre-1] = mmtn1->MOMENT[info->ordre-1] ;
364 }
365
366 for( chain = tr->REPORTED_N2 ; chain ; chain = chain->NEXT ) {
367
368 ptnode = (lonode_list*)chain->DATA ;
369
370 repmoment = (awetabnode*)getptype( ptnode->USER, AWENODE )->DATA ;
371 repmoment->MOMENT[info->ordre-1] = mmtn2->MOMENT[info->ordre-1] ;
372 }
373
374 losig = NULL ;
375 return 1 ;
376 }
377
378 void awemoment( losig_list *losig,
379 lonode_list *node,
380 int ordre,
381 RCXFLOAT k,
382 RCXFLOAT extcapa
383 )
384 {
385 aweinfmmt infos ;
386 lowire_list *wire;
387
388 avt_logenterfunction(LOGTRC,2, "awemoment()" );
389
390 infos.ordre = ordre ;
391 infos.extcapa = extcapa ;
392 infos.k = k ;
393
394 clearallwireflag( losig, RCN_FLAG_PASS );
395 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
396 RCN_CLEARFLAG( wire->FLAG, RCXNODEINTR );
397
398 rcn_treetrip( losig,
399 node,
400 (int (*)(losig_list*,lonode_list*,lowire_list*,void*))awe_up_formoment,
401 (int (*)(losig_list*,lonode_list*,chain_list*,ht*,void*))awe_dw_formoment,
402 (int (*)(losig_list*,lonode_list*,void*,void*))awe_packup_formoment,
403 &infos,
404 0
405 );
406 avt_logexitfunction(LOGTRC,2);
407 }
408
409 int awe_dw_forcleannodes( losig_list *losig,
410 lonode_list *lonode,
411 chain_list *chwire,
412 ht *htpack,
413 void *userdata
414 )
415 {
416 ptype_list *ptl ;
417 ptl = getptype( lonode->USER, AWENODE );
418 if( !ptl ) {
419 awe_error( 2, AVT_INTERNAL );
420 }
421 aweunallocnodes( (awetabnode*) ptl->DATA );
422 lonode->USER = delptype( lonode->USER, AWENODE );
423
424 userdata = NULL ;
425 chwire = NULL ;
426 htpack = NULL ;
427 losig = NULL ;
428
429 return 1 ;
430 }
431
432 void awecleannodes( losig_list *losig,
433 lonode_list *node
434 )
435 {
436 lowire_list *wire ;
437
438 clearallwireflag( losig, RCN_FLAG_PASS );
439 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
440 RCN_CLEARFLAG( wire->FLAG, RCXNODEINTR );
441
442 rcn_treetrip( losig, node, NULL, awe_dw_forcleannodes, NULL, NULL, 0 );
443 }
444
445 RCXFLOAT awedelay( aweinfo_list *awe,
446 RCXFLOAT inputslope,
447 RCXFLOAT vmax,
448 RCXFLOAT vt,
449 RCXFLOAT v,
450 RCXFLOAT vsat,
451 RCXFLOAT rl,
452 RCXFLOAT r,
453 RCXFLOAT c1,
454 RCXFLOAT c2,
455 mbk_pwl *pwl
456 )
457 {
458 RCXFLOAT a, b;
459 RCXFLOAT ts, t;
460 double te ;
461 mbk_pwl *lines;
462 mbk_pwl *tanhpwl;
463 mbk_laplace *laplace;
464 static int fordebug=0;
465 int status;
466
467 avt_logenterfunction(LOGTRC,2, "awedelay()" );
468
469 fordebug++;
470
471 if( awe->FLAG == AWE_NODELAY ) {
472 avt_log(LOGTRC,2, "no delay\n" );
473 avt_logexitfunction(LOGTRC,2);
474 return( 0.0 );
475 }
476
477 t = 0.0 ;
478
479 if( RCX_AWESTRAIGHT ) {
480 avt_log(LOGTRC,2,"old algorithm : rcx_awestraight\n");
481 awe_tanh_to_straight( inputslope, vmax, vt, &a, &b );
482 ts = aweinstant_straight( awe, v, vmax, a, b );
483 te = ( v - b ) / a ;
484 t = ts - te ;
485 }
486 else {
487 if( pwl ) {
488 avt_log(LOGTRC,2,"using input pwl\n");
489 lines = pwl ;
490 tanhpwl = NULL ;
491 }
492 else {
493 avt_log(LOGTRC,2,"building pwl from hyperbolic tangent\n");
494 tanhpwl = awe_tanh_to_pwl( inputslope, vmax, vt, vsat, rl, r, c1, c2 );
495 lines = tanhpwl ;
496 }
497
498 if( lines ) {
499 laplace = awe_pwl_to_laplace( lines, awe );
500 if( laplace ) {
501 ts = aweinstant_pwl( awe, v, vmax, laplace, &status );
502 if( status ) {
503 avt_log(LOGTRC,2,"find ts=%g\n", ts );
504 if( mbk_pwl_get_inv_value( lines, v, &te ) ) {
505 t = ts - te ;
506 if( t<0.0 ) { /* possible car les solutions trouvées pour
507 ts et te sont approximatives. */
508 if( -t / ts > 0.01 ) {
509 /* on considère que si t représente plus de 1% de ts, c'est
510 qu'il y a un problème d'évaluation de awe */
511 avt_errmsg( TRC_ERRMSG, "001", AVT_WARNING,
512 rcx_getsigname( AWE_DEBUG_NET ) );
513 }
514
515 }
516 }
517 else {
518 t = ts ;
519 avt_errmsg( TRC_ERRMSG, "042", AVT_WARNING,
520 rcx_getsigname( AWE_DEBUG_NET ) );
521 }
522 }
523 else {
524 avt_log(LOGTRC,2,"can't determine output transition time\n");
525 avt_errmsg( TRC_ERRMSG, "043", AVT_WARNING, rcx_getsigname( AWE_DEBUG_NET ) );
526 }
527 mbk_free_laplace( laplace );
528 }
529 else {
530 avt_log(LOGTRC,2,"Laplace transfrom not found\n");
531 avt_errmsg( TRC_ERRMSG, "044", AVT_WARNING, rcx_getsigname( AWE_DEBUG_NET ) );
532 }
533 mbk_pwl_free_pwl( tanhpwl );
534 }
535 else {
536 avt_log(LOGTRC,2, "no pwl\n" );
537 avt_errmsg( TRC_ERRMSG, "044", AVT_WARNING, rcx_getsigname( AWE_DEBUG_NET ) );
538 }
539 }
540
541 if( t < 0.0 ) {
542 t = 0.0 ;
543 }
544
545 avt_logexitfunction(LOGTRC,2);
546 return t ;
547
548 }
549
550 RCXFLOAT aweslope( aweinfo_list *awe,
551 RCXFLOAT vmax,
552 mbk_pwl **pwlout,
553 rcx_slope *slope,
554 char type,
555 double coefctc
556 )
557 {
558 RCXFLOAT t1, t2, v1, v2 ;
559 RCXFLOAT a, b, f ;
560 mbk_pwl *tanhpwl;
561 mbk_pwl *lines;
562 mbk_laplace *laplace;
563 static int fordebug=0;
564 awefilter datapwltanh;
565 int status ;
566 double capa, capaf, tp2, t20, tp ;
567 RCXFLOAT inputslope ;
568 RCXFLOAT vt ;
569 RCXFLOAT v ;
570 RCXFLOAT vsat ;
571 RCXFLOAT rl ;
572 RCXFLOAT r ;
573 RCXFLOAT c1 ;
574 RCXFLOAT c2 ;
575 mbk_pwl *pwlin ;
576 rcx_slope_param *sparam ;
577 lonode_list *node;
578 chain_list *headlocon;
579
580 if( type == RCX_MAX )
581 sparam = &(slope->MAX) ;
582 else
583 sparam = &(slope->MIN) ;
584
585 inputslope = sparam->slope ;
586 vt = sparam->vt ;
587 v = sparam->vth ;
588 vsat = sparam->vsat ;
589 rl = sparam->rlin ;
590 r = sparam->r ;
591 c1 = sparam->c1 ;
592 c2 = sparam->c2 ;
593 pwlin = sparam->pwl ;
594
595 avt_logenterfunction(LOGTRC,2, "aweslope()" );
596
597 fordebug++;
598
599 if( pwlout )
600 *pwlout = NULL ;
601
602 if( awe->FLAG == AWE_NODELAY ) {
603 avt_log(LOGTRC,2, "call aweslope() with AWE_NODELAY filter.\n" );
604 avt_logexitfunction(LOGTRC,2);
605 return( inputslope );
606 }
607
608 // Le calcul s'effectue à partir de la tangente à la tension v, en prenant
609 // deux mesures de la tension séparée de 5%.
610
611 if( RCX_AWESTRAIGHT ) {
612
613 avt_log(LOGTRC,2, "old algorithm used : RCX_AWESTRAIGHT\n" );
614 awe_tanh_to_straight( inputslope, vmax, vt, &a, &b );
615
616 v1 = v;
617 t1 = aweinstant_straight( awe, v1, vmax, a, b );
618 if( t1 < 0.0 ) {
619 avt_log(LOGTRC,2, "error when computing t1\n" );
620 avt_logexitfunction(LOGTRC,2);
621 return( inputslope );
622 }
623
624 t2 = t1*0.95;
625 v2 = awevoltage_straight( awe, t2, vmax, a, b );
626 if( v2 < 0.0 ) {
627 avt_log(LOGTRC,2, "error when computing v2\n" );
628 avt_logexitfunction(LOGTRC,2);
629 return( inputslope );
630 }
631
632 // La dérivée
633 a=(v2-v1)/(t2-t1);
634
635 // Le front calculé à partir de la dérivée. Formule semblabe à celle
636 // décrite dans la thèse d'Amjad Hajjar pIII/9 (3-3-a et 3-3-b), généralisée
637 // à n'importe quelle tension de seuil.
638
639 f = (vmax-v)*(vmax+v-2.0*vt)/(a*(vmax-vt));
640 }
641 else {
642 if( pwlin ) {
643 avt_log(LOGTRC,2, "using input pwl\n" );
644 lines = pwlin ;
645 tanhpwl = NULL ;
646 }
647 else {
648 avt_log(LOGTRC,2, "building pwl from hyperbolic tangent\n" );
649 tanhpwl = awe_tanh_to_pwl( inputslope, vmax, vt, vsat, rl, r, c1, c2 );
650 lines = tanhpwl ;
651 }
652 if( !lines ) {
653 avt_log(LOGTRC,2, "no pwl\n" );
654 avt_logexitfunction(LOGTRC,2);
655 return inputslope;
656 }
657
658 laplace = awe_pwl_to_laplace( lines, awe );
659 if( !laplace ) {
660 mbk_pwl_free_pwl( tanhpwl );
661 avt_log(LOGTRC,2,"can't build Laplace transfom\n" );
662 avt_logexitfunction(LOGTRC,2);
663 return inputslope;
664 }
665
666 awe_tanh_point_measure( vt, vmax, inputslope, &t1, &v1, &t2, &v2 );
667
668 t1 = aweinstant_pwl( awe, v1, vmax, laplace, &status );
669 if( !status ) {
670 avt_errmsg( TRC_ERRMSG, "043", AVT_WARNING, rcx_getsigname( AWE_DEBUG_NET ) );
671 mbk_free_laplace( laplace );
672 mbk_pwl_free_pwl( tanhpwl );
673 avt_log(LOGTRC,2,"can't find t1\n");
674 avt_logexitfunction(LOGTRC,2);
675 return inputslope;
676 }
677
678 t2 = aweinstant_pwl( awe, v2, vmax, laplace, &status );
679 if( !status ) {
680 avt_errmsg( TRC_ERRMSG, "043", AVT_WARNING, rcx_getsigname( AWE_DEBUG_NET ) );
681 mbk_free_laplace( laplace );
682 mbk_pwl_free_pwl( tanhpwl );
683 avt_log(LOGTRC,2,"can't find t2\n");
684 avt_logexitfunction(LOGTRC,2);
685 return inputslope;
686 }
687
688 if( V_BOOL_TAB[ __TAS_USE_FINAL_CAPACITANCE ].VALUE ) {
689 node = getlonode( awe->LOCON_LOAD->SIG, awe->NODE_LOAD );
690 /* critère : un seul locon et une seul resistance, r>10k */
691 headlocon = getloconnode( node );
692 if( headlocon && !headlocon->NEXT ) {
693 if( node->WIRELIST && !node->WIRELIST->NEXT && ((lowire_list*)(node->WIRELIST->DATA))->RESI > 10000 ) {
694 if (mbk_pwl_get_inv_value( lines, v2, &t20 )) {
695 tp = t2-t20 ;
696 if( tp > 0.0 ) {
697 capa = rcx_getnodecapa( awe->LOCON_LOAD->SIG,
698 getlonode( awe->LOCON_LOAD->SIG, awe->NODE_LOAD ),
699 awe->EXTCAPA,
700 slope,
701 type,
702 TRC_HALF,
703 coefctc
704 );
705 capaf = rcx_getnodecapa( awe->LOCON_LOAD->SIG,
706 getlonode( awe->LOCON_LOAD->SIG, awe->NODE_LOAD ),
707 awe->EXTCAPA,
708 slope,
709 type,
710 TRC_END,
711 coefctc
712 );
713 tp2 = tp*capaf/capa ;
714 t2 = t20+tp2 ;
715 }
716 }
717 else {
718 avt_log(LOGTRC,2, "error when computing v2 crossing time\n" );
719 }
720 }
721 }
722 }
723
724 f = (t2-t1)/(atanh((v2-vt)/(vmax-vt)-atanh((v1-vt)/(vmax-vt))));
725
726 avt_log(LOGTRC,2, "slope computed : %g\n" ,f );
727
728 if( AWE_DUMP_NETNAME ) {
729 char name[1024];
730 sprintf( name, "rc_%s_%s", AWE_DUMP_NETNAME, AWE_DUMP_SLOPE==TRC_SLOPE_UP ? "up":"dw" );
731 awevoltage_pwl_plot( awe, 2.0*t2, lines, laplace, 1.0e-12, 0.0, vmax, name );
732 }
733
734 if( pwlout ) {
735 avt_log(LOGTRC,2,"build pwlout\n");
736 datapwltanh.LAPLACE = laplace ;
737 datapwltanh.AWE = awe ;
738 datapwltanh.VMAX = vmax ;
739 *pwlout = mbk_create_pwl_according_tanh( (char (*)(void*, float, float*))awe_get_time_for_pwl,
740 (void*)&datapwltanh,
741 vt ,
742 0.9*vmax
743 );
744 }
745
746 mbk_free_laplace( laplace );
747 mbk_pwl_free_pwl( tanhpwl );
748
749 if( f < inputslope ) {
750 avt_log(LOGTRC,2,"an error occured. try the simplest model for driver\n" );
751 lines = awe_tanh_to_pwl( inputslope, vmax, vt,
752 -1.0, -1.0, -1.0, -1.0, -1.0 );
753 if( !lines ) {
754 avt_logexitfunction(LOGTRC,2);
755 return inputslope;
756 }
757
758 laplace = awe_pwl_to_laplace( lines, awe );
759 if( !laplace ) {
760 mbk_pwl_free_pwl( lines );
761 avt_logexitfunction(LOGTRC,2);
762 return inputslope;
763 }
764
765 awe_tanh_point_measure( vt, vmax, inputslope, &t1, &v1, &t2, &v2 );
766
767 t1 = aweinstant_pwl( awe, v1, vmax, laplace, &status );
768 if( !status ) {
769 avt_errmsg( TRC_ERRMSG, "043", AVT_WARNING, rcx_getsigname( AWE_DEBUG_NET ) );
770 mbk_free_laplace( laplace );
771 mbk_pwl_free_pwl( lines );
772 avt_log(LOGTRC,2,"can't find t1\n");
773 avt_logexitfunction(LOGTRC,2);
774 return inputslope;
775 }
776
777 t2 = aweinstant_pwl( awe, v2, vmax, laplace, &status );
778 mbk_free_laplace( laplace );
779 mbk_pwl_free_pwl( lines );
780 if( !status ) {
781 avt_errmsg( TRC_ERRMSG, "043", AVT_WARNING, rcx_getsigname( AWE_DEBUG_NET ) );
782 avt_log(LOGTRC,2,"can't find t2\n");
783 avt_logexitfunction(LOGTRC,2);
784 return inputslope ;
785 }
786
787 f = (t2-t1)/(atanh((v2-vt)/(vmax-vt)-atanh((v1-vt)/(vmax-vt))));
788 avt_log(LOGTRC,2, "slope computed : %g\n" ,f );
789 }
790 }
791
792 avt_logexitfunction(LOGTRC,2);
793 return( f );
794 }
795
796 char awe_get_time_for_pwl( awefilter *filter, float v, float *t )
797 {
798 int status ;
799 *t = aweinstant_pwl( filter->AWE, v, filter->VMAX, filter->LAPLACE, &status );
800 return status;
801 }
802
803 void awe_tanh_point_measure( RCXFLOAT vt,
804 RCXFLOAT vmax,
805 RCXFLOAT f,
806 RCXFLOAT *t1,
807 RCXFLOAT *v1,
808 RCXFLOAT *t2,
809 RCXFLOAT *v2
810 )
811 {
812 *v1=vt;
813 *t1=0.0;
814
815 *v2=3.0*(vmax-vt)/4.0+vt;
816 *t2=f*atanh( (*v2-vt)/(vmax-vt) );
817 }
818
819 RCXFLOAT awe_pi_get_v20( RCXFLOAT tsat, RCXFLOAT inputslope, RCXFLOAT vmax, RCXFLOAT vt, RCXFLOAT r, RCXFLOAT c2 )
820 {
821 mbk_pwl *lines ;
822 RCXFLOAT v20 ;
823 RCXFLOAT tr ;
824 int i ;
825 mbk_laplace *laplace ;
826 RCXFLOAT a ;
827
828 v20 = -1.0 ;
829
830 lines = awe_tanh_to_pwl( inputslope, vmax, vt, -1.0, -1.0, -1.0, -1.0, -1.0 );
831
832 if( lines ) {
833
834 laplace = mbk_pwl_to_laplace( lines, sizeof( mbk_laplace_data ) );
835
836 if( laplace ) {
837
838 v20 = 0.0 ;
839
840 for( i = 0 ;
841 i < laplace->N && tsat > ((mbk_laplace_data*)laplace->DATA)[i].T ;
842 i++ )
843 {
844 tr = tsat - ((mbk_laplace_data*)laplace->DATA)[i].T ;
845 a = ((mbk_laplace_data*)laplace->DATA)[i].A ;
846 v20=v20+a*(tr-r*c2*(1.0-exp(-tr/(r*c2))));
847 }
848
849 mbk_free_laplace( laplace );
850 }
851 mbk_pwl_free_pwl( lines );
852 }
853
854 return v20 ;
855 }
856
857 /* Convertie une tangente hyperbolique en un ensemble de droites */
858 mbk_pwl* awe_tanh_to_pwl( RCXFLOAT inputslope,
859 RCXFLOAT vmax,
860 RCXFLOAT vt,
861 RCXFLOAT vsat,
862 RCXFLOAT rl,
863 RCXFLOAT r,
864 RCXFLOAT c1,
865 RCXFLOAT c2
866 )
867 {
868 mbk_pwl *lines ;
869 awe_tanh_data data ;
870 mbk_pwl_param *param;
871 RCXFLOAT t1, v1, t2, v2 ;
872 RCXFLOAT delta ;
873 RCXFLOAT v20 ;
874 RCXFLOAT tsat ;
875 double tmax ;
876 char piload ;
877 RCXFLOAT dxmin ;
878 RCXFLOAT sdmin ;
879 static int fordebug=0;
880
881 fordebug++;
882
883 data.F = inputslope ;
884 data.VT = vt ;
885 data.VMAX = vmax ;
886 data.A = ( vmax - vt ) / inputslope ;
887
888 data.TSAT = FLT_MAX ;
889
890 piload = 0 ;
891
892 if( vsat > 0.0 && rl>0.0 && r>0.0 && c1>0.0 && c2>0.0 ) {
893
894 delta = r*r*c2*c2 + rl*rl*(c1+c2)*(c1+c2) - 2*r*rl*c2*(c1-c2) ;
895 tsat = inputslope * atanh( ( vsat - vt ) / ( vmax - vt ) ) ;
896 v20 = awe_pi_get_v20( tsat, inputslope, vmax, vt, r, c2 );
897
898 if( delta > 0.0 && v20 > 0.0 ) {
899 piload = 1 ;
900 data.RLIN = rl ;
901 data.VSAT = vsat ;
902 data.TSAT = tsat ;
903 data.P1 = (-r*c2-rl*(c1+c2)-sqrt(delta))/(2.0*r*rl*c1*c2) ;
904 data.P2 = (-r*c2-rl*(c1+c2)+sqrt(delta))/(2.0*r*rl*c1*c2) ;
905 data.V20 = v20 ;
906 data.V10 = vsat ;
907 data.C1 = c1 ;
908 data.C2 = c2 ;
909 data.R = r ;
910 data.RL = rl ;
911 }
912 }
913
914 // Calcule l'instant td<0 de départ de la tanh en supposant qu'entre td et 0
915 // le front est une droite dont la pente vaut la dérivée de la tanh en t=0
916 if( RCX_STEPTANH )
917 data.TR = 0.0 ;
918 else
919 data.TR = - vt / data.A ;
920
921 tmax = awe_tanh_tmax( &data );
922
923 param = mbk_pwl_get_default_param( (char (*)(void*, double, double*))awe_tanh,
924 (void*) &data,
925 data.TR,
926 tmax
927 );
928
929 /* Demande une bonne modélisation de la partie correspondant à la tanh */
930 dxmin = data.F/5.0 ;
931 sdmin = data.F/100.0 ;
932 if( param->PARAM.DEFAULT.DELTAXMIN > dxmin )
933 param->PARAM.DEFAULT.DELTAXMIN = dxmin ;
934 if( param->PARAM.DEFAULT.SDERIVE > sdmin )
935 param->PARAM.DEFAULT.SDERIVE = sdmin ;
936 if( piload ) {
937 t1 = 0.7*r*c2 ;
938 if( t1 > 2.0*data.F )
939 mbk_pwl_add_param_point( param, t1 );
940 }
941
942 awe_tanh_point_measure( vt, vmax, inputslope, &t1, &v1, &t2, &v2 );
943 if( piload )
944 mbk_pwl_add_param_point( param, tsat );
945
946 if( !RCX_STEPTANH )
947 mbk_pwl_add_param_point( param, t1 );
948 mbk_pwl_add_param_point( param, t2 );
949
950 lines = mbk_pwl_create( (char (*)(void*, double, double*))awe_tanh,
951 (void*) &data,
952 data.TR,
953 tmax,
954 param
955 );
956
957 mbk_pwl_free_param( param );
958 return lines;
959
960 }
961
962 /* Renvoie l'instant à partir duquel le front est considéré comme terminé */
963 double awe_tanh_tmax( awe_tanh_data *data )
964 {
965 double t ;
966 double v ;
967 double vmax ;
968
969 t = data->F ;
970 vmax = 0.99 * data->VMAX ;
971
972 do {
973 t = 3.0 * t ;
974
975 if( !awe_tanh( data, t, &v ) )
976 return t;
977 }
978 while( v < vmax );
979
980 return t ;
981 }
982
983 /* Fonction locale de tangente hyperbolique */
984 char awe_tanh( awe_tanh_data *data, double t, double *v )
985 {
986 double r, c, vmin ;
987
988 if( t >= 0.0 )
989 if( t <= data->TSAT )
990 *v = data->VT + (data->VMAX - data->VT) * tanh( t/data->F );
991 else {
992
993 t = t - data->TSAT ;
994 /* pour eviter une diminution de la tension lorsqu'on passe du
995 générateur modélisé par une tension à une résistance linéaire */
996 r = data->R + data->RL ;
997 c = data->C1 + data->C2 ;
998 vmin = data->VMAX*(1.0-exp(-t/(r*c))) +
999 data->V10*exp(-t/(r*c)) ;
1000
1001 *v = ( data->C1*data->V10 + data->C2*data->V20 +
1002 data->VMAX*data->C2*data->R/data->RL )
1003 / ( data->R*data->C1*data->C2)
1004 * ( exp(data->P1*t) - exp(data->P2*t ))
1005 / (data->P1-data->P2) ;
1006 *v = *v + data->V10
1007 * ( data->P2*exp(data->P2*t) - data->P1*exp(data->P1*t) )
1008 / ( data->P2 - data->P1 ) ;
1009 *v = *v - data->VMAX / ( data->R * data->RL * data->C1 * data->C2 )
1010 * ( data->P1*exp(data->P2*t) - data->P2*exp(data->P1*t)
1011 + ( data->P2 - data->P1 ) )
1012 / ( data->P1 * data->P2 * ( data->P1 - data->P2 )) ;
1013 if( *v < vmin ) {
1014 *v = vmin ;
1015 }
1016 }
1017 else {
1018 if( t >= data->TR )
1019 *v = data->VT + t * data->A ;
1020 else
1021 *v = 0.0 ;
1022 }
1023 return 1;
1024 }
1025
1026 void plot_awe_tanh( awe_tanh_data *data, float t_unit, float tmax, char *name )
1027 {
1028 FILE *ptf ;
1029 double t, v ;
1030 ptf = mbkfopen( name, "dat", "w" );
1031 for( t=0.0 ; t<tmax ; t=t+0.01 ) {
1032 awe_tanh( data, t, &v );
1033 fprintf( ptf, "%g %g\n", t*t_unit, v );
1034 }
1035 fclose( ptf );
1036 }
1037
1038 /* Converti une tangente hyperbolique en une droite */
1039
1040 void awe_tanh_to_straight( RCXFLOAT inputslope,
1041 RCXFLOAT vmax,
1042 RCXFLOAT vt,
1043 RCXFLOAT *a,
1044 RCXFLOAT *b
1045 )
1046 {
1047 RCXFLOAT v1, v2, t1, t2;
1048
1049 v1 = 0.2*vmax ;
1050 v2 = 0.8*vmax ;
1051 t1 = INVTH( inputslope, vt, vmax, v1 );
1052 t2 = INVTH( inputslope, vt, vmax, v2 );
1053
1054 *a = (v1-v2)/(t1-t2);
1055 *b = v1-t1*(*a) ;
1056 }
1057
1058 void awevoltage_pwl_plot( aweinfo_list *awe,
1059 RCXFLOAT tmax,
1060 mbk_pwl *lines,
1061 mbk_laplace *laplace,
1062 float t_unit,
1063 float t_vth,
1064 float vmax,
1065 char *filename
1066 )
1067 {
1068 FILE *file;
1069 double ts;
1070 double t;
1071 double t0;
1072 double ve;
1073 double lve;
1074 double vs;
1075 double dt;
1076
1077 file = mbkfopen( filename, "dat", "w" );
1078 if( !file ) {
1079 printf( "Can't open file.\n" );
1080 return;
1081 }
1082
1083 ts = tmax/1000.0 ;
1084
1085 t0 = aweinstant_pwl( awe, vmax/2.0, vmax, laplace, NULL );
1086 dt = t_vth - t0 ;
1087
1088 lve=0.0;
1089 for( t=-lines->DATA[0].B/lines->DATA[0].A ; t<tmax ; t=t+ts ) {
1090 switch( mbk_pwl_get_value( lines, t, &ve ) ) {
1091 case MBK_PWL_FOUND :
1092 lve = ve ;
1093 break;
1094 case MBK_PWL_ERROR :
1095 case MBK_PWL_EXTPL :
1096 ve = lve ;
1097 break ;
1098 }
1099 vs = awevoltage_pwl( awe, t, laplace );
1100 if( AWE_DUMP_SLOPE == TRC_SLOPE_UP )
1101 fprintf( file, "%g %g %g\n", t*t_unit, ve, vs );
1102 else
1103 fprintf( file, "%g %g %g\n", t*t_unit, vmax-ve, vmax-vs );
1104 }
1105
1106 fclose( file );
1107 }
1108
1109 mbk_laplace* awe_pwl_to_laplace( mbk_pwl *lines, aweinfo_list *awe )
1110 {
1111 mbk_laplace *l;
1112 int i;
1113
1114 avt_logenterfunction(LOGTRC,2,"awe_pwl_to_laplace");
1115 if( awe->FLAG == AWE_MOMENT )
1116 awemomentfiltre( awe );
1117
1118 if( awe->FLAG != AWE_FILTER ) {
1119 avt_logexitfunction(LOGTRC,2);
1120 return( NULL );
1121 }
1122
1123 l = mbk_pwl_to_laplace( lines, sizeof( mbk_laplace_data ) );
1124
1125 // Normalise les pentes et les délais.
1126 for( i = 0 ; i < l->N ; i++ ) {
1127 ((mbk_laplace_data*)l->DATA)[i].A =
1128 ((mbk_laplace_data*)l->DATA)[i].A * awe->K ;
1129 ((mbk_laplace_data*)l->DATA)[i].T =
1130 ((mbk_laplace_data*)l->DATA)[i].T / awe->K ;
1131 }
1132 avt_logexitfunction(LOGTRC,2);
1133
1134 return l;
1135 }
1136
1137 RCXFLOAT awevoltage_fast( aweinfo_list *awe, double f )
1138 {
1139 double v ;
1140 double k ;
1141 double p ;
1142 double vmax ;
1143 double vtotal ;
1144 int l ;
1145 static int fordebug=0 ;
1146
1147 avt_logenterfunction(LOGTRC,2, "awevoltage_fast()" );
1148
1149 fordebug++;
1150
1151 if( AWE_FAST_MODE == 'N' ) {
1152 avt_log(LOGTRC,2, "AWE_FAST_MODE disable\n" );
1153 avt_logexitfunction(LOGTRC,2);
1154 return -1.0 ;
1155 }
1156
1157 if( awe->FLAG == AWE_NODELAY ) {
1158 avt_log(LOGTRC,2, "nodelay\n" );
1159 avt_logexitfunction(LOGTRC,2);
1160 return -1.0 ;
1161 }
1162
1163 if( awe->FLAG == AWE_MOMENT )
1164 awemomentfiltre( awe );
1165
1166 if( awe->FLAG != AWE_FILTER ) {
1167 avt_log(LOGTRC,2,"no filter\n");
1168 avt_logexitfunction(LOGTRC,2);
1169 return -1.0;
1170 }
1171
1172 vtotal = 0.0 ;
1173 vmax = 0.0 ;
1174
1175 v = 0.0 ;
1176
1177 for( l=0 ; l<awe->DATA.FILTER.ORDER ; l++ ) {
1178
1179 k = awe->DATA.FILTER.RESIDU[l] ;
1180 p = -awe->DATA.FILTER.POLE[l] ;
1181
1182 v = v + k/p/p ;
1183 }
1184 v = v * awe->K;
1185
1186 if( v > f/10.0 ) {
1187 avt_logexitfunction(LOGTRC,2);
1188 return -1 ;
1189 }
1190
1191 /* Une bonne approximation du temps de propagation du réseau RC est
1192 cet écart. */
1193
1194 avt_log(LOGTRC,2, "approx value : %g\n", v );
1195 avt_logexitfunction(LOGTRC,2);
1196 return v ;
1197
1198 }
1199
1200 RCXFLOAT awevoltage_pwl( aweinfo_list *awe,
1201 RCXFLOAT t,
1202 mbk_laplace *laplace
1203 )
1204 {
1205 int i, l ;
1206 double p, k, v, tr ;
1207
1208 t = t / awe->K ;
1209
1210 // Calcule la réponse temporelle.
1211
1212 v = 0.0 ;
1213 for( i = 0 ; i < laplace->N && t > ((mbk_laplace_data*)laplace->DATA)[i].T ; i++ ) {
1214
1215 tr = t - ((mbk_laplace_data*)laplace->DATA)[i].T ;
1216
1217 for( l=0 ; l<awe->DATA.FILTER.ORDER ; l++ ) {
1218
1219 k = awe->DATA.FILTER.RESIDU[l] ;
1220 p = awe->DATA.FILTER.POLE[l] ;
1221
1222 v = v + (((mbk_laplace_data*)laplace->DATA)[i].A) * k / p * ( -tr - 1.0/p + exp( tr*p )/p ) ;
1223
1224 if( i == 0 )
1225 v = v - laplace->B * k/p*( 1.0 - exp( tr*p ) ) ;
1226 }
1227 }
1228
1229 return v;
1230 }
1231
1232 RCXFLOAT aweinstant_pwl( aweinfo_list *awe,
1233 RCXFLOAT vf,
1234 RCXFLOAT vmax,
1235 mbk_laplace *laplace,
1236 int *status
1237 )
1238 {
1239 RCXFLOAT t1, t2, lt1, lt2, tp, v, v1, v2 ;
1240 int n;
1241 static int fordebug=0;
1242 fordebug++;
1243
1244 avt_logenterfunction(LOGTRC,2, "aweinstant_pwl()" );
1245 if( status ) *status = 0 ;
1246
1247 if( awe->FLAG == AWE_NODELAY )
1248 {
1249 avt_log(LOGTRC,2, "aweinstant_pwl() : call with AWE_NODELAY filter.\n" );
1250 avt_logexitfunction(LOGTRC,2);
1251 return( 0.0 );
1252 }
1253
1254 /* Calcul du tp par dichotomie */
1255 t1 = 0.0 ;
1256 t2 = 2*awe->K;
1257
1258 n = AWE_MAX_ITER ;
1259 do { // On vérifie que la solution recherchée est entre t1 et v2.
1260
1261 v = awevoltage_pwl( awe, t2, laplace );
1262
1263 if( v<vf ) {
1264 t1=t2;
1265 t2+=t2;
1266 }
1267
1268 n--;
1269 }
1270 while( v < vf && n );
1271
1272 if( !n ) {
1273 avt_log(LOGTRC,2, "aweinstant_pwl() : can't solve #1\n" );
1274 avt_logexitfunction(LOGTRC,2);
1275 return( 0.0 );
1276 }
1277
1278 v1 = awevoltage_pwl( awe, t1, laplace );
1279 v2 = v;
1280
1281 n = AWE_MAX_ITER ;
1282 do
1283 {
1284 // tp = (t2+t1)/2.0;
1285 tp = (t2-t1)/(v2-v1)*(vf-v1)+t1;
1286 lt1=t1;
1287 lt2=t2;
1288
1289 v = awevoltage_pwl( awe, tp, laplace );
1290
1291 if( v == vf ) { // ça arrive !
1292 t1 = tp;
1293 t2 = tp;
1294 v1 = v;
1295 v2 = v;
1296 } else {
1297 if( v > vf ) {
1298 t2 = tp;
1299 v2 = v;
1300 }
1301 else {
1302 t1 = tp;
1303 v1 = v;
1304 }
1305 }
1306
1307 n--;
1308 }
1309 while( fabs(v-vf)>vmax/1000.0 && n );
1310
1311 if( !n ) {
1312 avt_log(LOGTRC,2, "aweinstant_pwl() : can't solve #2\n" );
1313 avt_logexitfunction(LOGTRC,2);
1314 return( 0.0 );
1315 }
1316
1317 if( status ) *status = 1 ;
1318 avt_logexitfunction(LOGTRC,2);
1319 return( tp );
1320 }
1321
1322 /* Tension à l'instant T lorsque l'entrée est une droite v(t)=a.t+b
1323 jusqu'à vmax et constant après */
1324
1325 RCXFLOAT awevoltage_straight( aweinfo_list *awe,
1326 RCXFLOAT t,
1327 RCXFLOAT vmax,
1328 RCXFLOAT a,
1329 RCXFLOAT b
1330 )
1331 {
1332 int l;
1333 RCXFLOAT v, k, p, tm;
1334
1335 if( awe->FLAG == AWE_MOMENT )
1336 awemomentfiltre( awe );
1337
1338 if( awe->FLAG != AWE_FILTER )
1339 return( -1.0 );
1340
1341 a = a * awe->K ;
1342 t = t / awe->K ;
1343 v=0.0;
1344 tm = (vmax-b)/a ;
1345
1346 for( l=0 ; l<awe->DATA.FILTER.ORDER ; l++ ) {
1347
1348 k = awe->DATA.FILTER.RESIDU[l] ;
1349 p = awe->DATA.FILTER.POLE[l] ;
1350
1351 v = v + a*k*( -t/p - 1.0/p/p*(1.0-exp(p*t)) ) - b*k/p*(1.0-exp(p*t)) ;
1352 if( t > tm )
1353 v = v - (a*k*(-(t-tm)/p-1.0/p/p*(1.0-exp(p*(t-tm)))));
1354
1355 }
1356 return( v );
1357 }
1358
1359 /* Calcul par dichotomie l'instant de passage de la tension
1360 par vf. L'entrée est une droite */
1361
1362 RCXFLOAT aweinstant_straight( aweinfo_list *awe,
1363 RCXFLOAT vf,
1364 RCXFLOAT vmax,
1365 RCXFLOAT a,
1366 RCXFLOAT b
1367 )
1368 {
1369 RCXFLOAT t1, t2, lt1, lt2, tp, v, v1, v2 ;
1370
1371 if( awe->FLAG == AWE_NODELAY )
1372 {
1373 avt_log(LOGTRC,2, "awe : call aweinstant_straight() with AWE_NODELAY filter.\n"
1374 );
1375 return( -1.0 );
1376 }
1377
1378 /* Calcul du tp par dichotomie */
1379 t1 = 0.0 ;
1380 t2 = 2*awe->K;
1381
1382 do { // On vérifie que la solution recherchée est entre t1 et v2.
1383
1384 v = awevoltage_straight( awe, t2, vmax, a, b );
1385 if( v < 0.0 )
1386 return( -1.0 );
1387
1388 if( v<vf ) {
1389 t1=t2;
1390 t2+=t2;
1391 }
1392 }
1393 while( v < vf );
1394
1395 v1 = awevoltage_straight( awe, t1, vmax, a, b );
1396 v2 = v;
1397
1398 do
1399 {
1400 // tp = (t2+t1)/2.0;
1401 tp = (t2-t1)/(v2-v1)*(vf-v1)+t1;
1402 lt1=t1;
1403 lt2=t2;
1404
1405 v = awevoltage_straight( awe, tp, vmax, a, b );
1406 if( v < 0.0 )
1407 return( -1.0 );
1408
1409 if( v == vf ) { // ça arrive !
1410 t1 = tp;
1411 t2 = tp;
1412 v1 = v;
1413 v2 = v;
1414 } else {
1415 if( v > vf ) {
1416 t2 = tp;
1417 v2 = v;
1418 }
1419 else {
1420 t1 = tp;
1421 v1 = v;
1422 }
1423 }
1424 }
1425 while( fabs(v-vf)>vmax/1000.0 );
1426
1427 return( tp );
1428 }
1429
1430 /* Fonction utilisée pour normaliser les délais. Renvoie le plus grand moment de 1° ordre
1431 * sur le reseau ( ce nombre est <0 )
1432 */
1433 int awe_dw_formaxmoment( losig_list *losig,
1434 lonode_list *lonode,
1435 chain_list *chwire,
1436 ht *htpack,
1437 RCXFLOAT *ptmax
1438 )
1439 {
1440 ptype_list *ptl ;
1441 awetabnode *tabnode ;
1442 RCXFLOAT moment ;
1443
1444 ptl = getptype( lonode->USER, AWENODE );
1445 if( !ptl ) {
1446 awe_error( 3, AVT_INTERNAL );
1447 }
1448 tabnode = (awetabnode*)ptl->DATA ;
1449 moment = tabnode->MOMENT[0] ;
1450
1451 if( moment < *ptmax )
1452 *ptmax = moment ;
1453
1454 chwire = NULL ;
1455 htpack = NULL ;
1456 losig = NULL ;
1457
1458 return 1 ;
1459 }
1460
1461 RCXFLOAT awemaxmoment( losig_list *losig, lonode_list *node )
1462 {
1463 RCXFLOAT max ;
1464 lowire_list *wire ;
1465
1466 max = FLT_MAX ;
1467
1468 clearallwireflag( losig, RCN_FLAG_PASS );
1469 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
1470 RCN_CLEARFLAG( wire->FLAG, RCXNODEINTR );
1471
1472 rcn_treetrip( losig,
1473 node,
1474 NULL,
1475 (int (*)(losig_list*,lonode_list*,chain_list*,ht*,void*))awe_dw_formaxmoment,
1476 NULL,
1477 (void*)&max,
1478 0
1479 );
1480 return max ;
1481 }
1482
1483 // Renvoie le temps de propagation d'un réseau RC calculé avec AWE à l'ordre
1484 // 3. Comme le calcul des moments est assez long, on ne le fait qu'une fois pour toute
1485 // pour un émetteur donné, et les moments de tous les récepteurs sont mémorisés.
1486 // L'évaluation des poles et résidus étant également couteuse, on ne la fait
1487 // qu'a la demande.
1488 // Il faut qu'à tous les appels le réseau et extcapa soient identiques. Sinon, il faut appeler
1489 // avant la fonction awereset().
1490 // Renvoie 1 en cas de succès, 0 sinon.
1491
1492 int getawedelay( lofig_list *lofig, // La figure
1493 losig_list *losig, // Le signal
1494 locon_list *locon_emt, // L'emetteur
1495 locon_list *locon_rec, // Le recepteur
1496 rcx_slope *slopemiller, // Front d'entrée pour miller
1497 RCXFLOAT vmaxmax, // Tension max pour delai max
1498 RCXFLOAT vmaxmin, // Tension max pour delai min
1499 RCXFLOAT extcapa, // La capacité externe
1500 RCXFLOAT *dmax, // Le délai maximum calculé
1501 RCXFLOAT *dmin, // minimum
1502 RCXFLOAT *fmax, // Le front maximum calculé
1503 RCXFLOAT *fmin, // minimum
1504 mbk_pwl **pwloutmax,
1505 mbk_pwl **pwloutmin
1506 )
1507 {
1508 aweinfo_list *awe;
1509 RCXFLOAT v;
1510 RCXFLOAT d;
1511 RCXFLOAT groundcapa = -1e6 ;
1512 RCXFLOAT coefctc ;
1513 char flagmin=0, flagmax=0;
1514 int ctkactive;
1515 mbk_pwl *pwl;
1516 char computedfast ;
1517 chain_list *headawe;
1518 chain_list *scanawe;
1519
1520 avt_logenterfunction(LOGTRC,2,"getawedelay()");
1521 avt_log(LOGTRC,2, "vmaxmax=%g vmaxmin=%g\n", vmaxmax, vmaxmin );
1522
1523 if( pwloutmax )
1524 *pwloutmax = NULL ;
1525 if( pwloutmin )
1526 *pwloutmin = NULL ;
1527
1528 if( RCX_PLOT_AWE ) {
1529 if( rcx_getsigname( losig ) == RCX_PLOT_AWE ) {
1530 AWE_DUMP_NETNAME = RCX_PLOT_AWE ;
1531 AWE_DUMP_SLOPE = slopemiller->SENS ;
1532 }
1533 }
1534 else {
1535 AWE_DUMP_NETNAME = NULL ;
1536 }
1537
1538 AWE_DEBUG_NET = losig ;
1539 AWE_DEBUG_DRIVER = locon_emt ;
1540 AWE_DEBUG_RECEIVER = locon_rec ;
1541
1542 if( slopemiller->MIN.slope < 1.0 )
1543 slopemiller->MIN.slope = 1.0;
1544 if( slopemiller->MAX.slope < 1.0 )
1545 slopemiller->MAX.slope = 1.0;
1546
1547 ctkactive = rcx_crosstalkactive( RCX_QUERY );
1548
1549 if( fmin ) *fmin = -1.0 ;
1550 if( fmax ) *fmax = -1.0 ;
1551 if( dmin ) *dmin = -1.0 ;
1552 if( dmax ) *dmax = -1.0 ;
1553
1554
1555 if( fmin || dmin ) {
1556 avt_log(LOGTRC,2, "computing minimum delays\n" );
1557
1558 coefctc =
1559 rcx_getcoefctc( lofig, losig, slopemiller, RCX_MIN, extcapa, &groundcapa );
1560
1561 headawe = getaweinfo( losig,
1562 locon_rec,
1563 locon_emt,
1564 extcapa,
1565 slopemiller,
1566 RCX_MIN,
1567 coefctc
1568 );
1569
1570 for( scanawe = headawe ; scanawe ; scanawe = scanawe->NEXT ) {
1571 awe = (aweinfo_list*)scanawe->DATA ;
1572 if( awe->FLAG == AWE_NODELAY )
1573 continue ;
1574
1575 flagmin=1;
1576
1577 v = -1.0 ; // un nombre qui indique qu'on a pas de valeur calculée.
1578 computedfast = 'n' ;
1579
1580 if( dmin ) {
1581
1582 d = awevoltage_fast( awe, slopemiller->MIN.slope );
1583 computedfast = 'y' ;
1584
1585 if( d > 0.0 )
1586 v = d ;
1587 else
1588 v = awedelay( awe,
1589 slopemiller->MIN.slope,
1590 vmaxmin,
1591 slopemiller->MIN.vt,
1592 slopemiller->MIN.vth,
1593 slopemiller->MIN.vsat,
1594 slopemiller->MIN.rlin,
1595 slopemiller->MIN.r,
1596 slopemiller->MIN.c1,
1597 slopemiller->MIN.c2,
1598 slopemiller->MIN.pwl
1599 );
1600
1601 if( v >= 0.0 ) {
1602 if( *dmin < 0.0 || v < *dmin )
1603 *dmin = v;
1604 }
1605 }
1606
1607 v = -1.0 ;
1608
1609 if( fmin ) {
1610
1611 if( computedfast == 'n' )
1612 d = awevoltage_fast( awe, slopemiller->MIN.slope );
1613
1614 pwl = NULL ;
1615
1616 if( d > 0.0 ) {
1617 if( pwloutmin ) {
1618 if( slopemiller->MIN.pwl )
1619 pwl = mbk_pwl_duplicate( slopemiller->MIN.pwl );
1620 }
1621 v = slopemiller->MIN.slope ;
1622 }
1623 else
1624 v = aweslope( awe,
1625 vmaxmin,
1626 pwloutmin ? &pwl : NULL,
1627 slopemiller,
1628 RCX_MIN,
1629 coefctc
1630 );
1631
1632 if( v >= 0.0 ) {
1633 if( *fmin < 0.0 || v < *fmin ) {
1634 *fmin = v;
1635 if( pwloutmin ) {
1636 if( *pwloutmin ) mbk_pwl_free_pwl( *pwloutmin );
1637 *pwloutmin = pwl ;
1638 }
1639 }
1640 else
1641 mbk_pwl_free_pwl( pwl );
1642 }
1643 else {
1644 mbk_pwl_free_pwl( pwl );
1645 }
1646 }
1647 }
1648
1649 awefreeinfolist( headawe );
1650 // Pas de connexion entre les deux locons
1651 if( !flagmin ) {
1652 avt_log(LOGTRC,2, "can't compute delays for min\n" );
1653 if( fmin ) *fmin=slopemiller->MIN.slope;
1654 if( dmin ) *dmin=0.0;
1655 }
1656 }
1657
1658 if( dmax || fmax ) {
1659
1660 avt_log(LOGTRC,2, "computing maximum delays\n" );
1661
1662 /* récupere le delaycache */
1663
1664 coefctc =
1665 rcx_getcoefctc( lofig, losig, slopemiller, RCX_MAX, extcapa, &groundcapa );
1666
1667 headawe = getaweinfo( losig,
1668 locon_rec,
1669 locon_emt,
1670 extcapa,
1671 slopemiller,
1672 RCX_MAX,
1673 coefctc
1674 );
1675 for( scanawe = headawe ; scanawe ; scanawe = scanawe->NEXT ) {
1676 awe = (aweinfo_list*)scanawe->DATA ;
1677 if( awe->FLAG == AWE_NODELAY )
1678 continue ;
1679
1680 flagmax = 1;
1681
1682 v = -1.0 ; // un nombre qui indique qu'on a pas de valeur calculée.
1683 computedfast = 'n' ;
1684
1685 if( dmax ) {
1686
1687 d = awevoltage_fast( awe, slopemiller->MAX.slope );
1688 computedfast = 'y' ;
1689
1690 if( d > 0.0 )
1691 v = d ;
1692 else
1693 v = awedelay( awe,
1694 slopemiller->MAX.slope,
1695 vmaxmax,
1696 slopemiller->MAX.vt,
1697 slopemiller->MAX.vth,
1698 slopemiller->MAX.vsat,
1699 slopemiller->MAX.rlin,
1700 slopemiller->MAX.r,
1701 slopemiller->MAX.c1,
1702 slopemiller->MAX.c2,
1703 slopemiller->MAX.pwl
1704 );
1705
1706 if( v >= 0.0 ) {
1707 if( *dmax < 0.0 || v > *dmax )
1708 *dmax = v;
1709 }
1710 }
1711
1712 v = -1.0;
1713
1714 if( fmax ) {
1715
1716 if( computedfast == 'n' )
1717 d = awevoltage_fast( awe, slopemiller->MAX.slope );
1718
1719 pwl = NULL ;
1720 if( d > 0.0 ) {
1721 if( pwloutmax ) {
1722 if( slopemiller->MAX.pwl )
1723 pwl = mbk_pwl_duplicate( slopemiller->MAX.pwl );
1724 }
1725 v = slopemiller->MAX.slope ;
1726 }
1727 else
1728 v = aweslope( awe,
1729 vmaxmax,
1730 pwloutmax ? &pwl : NULL,
1731 slopemiller,
1732 RCX_MAX,
1733 coefctc
1734 );
1735
1736 if( v >= 0.0 ) {
1737 if( *fmax < 0.0 || v > *fmax ) {
1738 *fmax = v;
1739 if( pwloutmax ) {
1740 if( *pwloutmax ) mbk_pwl_free_pwl( *pwloutmax );
1741 *pwloutmax = pwl ;
1742 }
1743 }
1744 else
1745 mbk_pwl_free_pwl( pwl );
1746 }
1747 else {
1748 mbk_pwl_free_pwl( pwl );
1749 }
1750 }
1751 }
1752
1753 awefreeinfolist( headawe );
1754
1755 // Pas de connexion entre les deux locons
1756 if( !flagmax ) {
1757 avt_log(LOGTRC,2, "can't compute delays for max\n" );
1758 if( fmax ) *fmax=slopemiller->MAX.slope;
1759 if( dmax ) *dmax=0.0;
1760 }
1761 }
1762
1763 avt_logexitfunction(LOGTRC,2);
1764
1765 return(1);
1766 }
1767
1768 /******************************************************************************\
1769 Fonctions qui orientent le réseau RC.
1770 Il faut le faire pour chaque émetteur car les triangles supposent qu'on entre
1771 par le noeud n0.
1772 \******************************************************************************/
1773
1774 int awe_up_forcreatetriangle( losig_list *losig,
1775 lonode_list *lonode,
1776 lowire_list *lowire,
1777 void *userdata
1778 )
1779 {
1780 rcx_triangle_node( losig, lonode, lowire );
1781 userdata = NULL;
1782 return 1 ;
1783 }
1784
1785 int awe_packup_forcreatetriangle( losig_list *losig,
1786 lonode_list *lonode,
1787 rcx_triangle *tr,
1788 void *userdata
1789 )
1790 {
1791 chain_list *chain ;
1792 lonode_list *tstnode ;
1793
1794 if( tr->n0 != lonode ) rcx_triangle_node( losig, tr->n0, NULL );
1795 if( tr->n1 != lonode ) rcx_triangle_node( losig, tr->n1, NULL );
1796 if( tr->n2 != lonode ) rcx_triangle_node( losig, tr->n2, NULL );
1797 for( chain = tr->REPORTED_IN ; chain ; chain = chain->NEXT ) {
1798 tstnode = (lonode_list*)chain->DATA ;
1799 if( tstnode != lonode ) rcx_triangle_node( losig, tstnode, NULL );
1800 }
1801 for( chain = tr->REPORTED_N1 ; chain ; chain = chain->NEXT ) {
1802 tstnode = (lonode_list*)chain->DATA ;
1803 if( tstnode != lonode ) rcx_triangle_node( losig, tstnode, NULL );
1804 }
1805 for( chain = tr->REPORTED_N2 ; chain ; chain = chain->NEXT ) {
1806 tstnode = (lonode_list*)chain->DATA ;
1807 if( tstnode != lonode ) rcx_triangle_node( losig, tstnode, NULL );
1808 }
1809
1810 userdata = NULL;
1811 return 1 ;
1812 }
1813
1814 int awe_dw_forcleantriangle( losig_list *losig,
1815 lonode_list *lonode,
1816 chain_list *chwire,
1817 ht *htpack,
1818 void *userdata
1819 )
1820 {
1821 chain_list *headht, *chain ;
1822 rcx_triangle *tr ;
1823 lowire_list *wire ;
1824
1825 headht = GetAllHTElems( htpack );
1826
1827 for( chain = headht ; chain ; chain = chain->NEXT ) {
1828 wire = (lowire_list*)((chain_list*)chain->DATA)->DATA ;
1829 tr = (rcx_triangle*)rcn_getpack( losig, wire ) ;
1830 rcx_cleantriangle_node( losig, lonode, tr );
1831 }
1832
1833 freechain( headht );
1834 userdata = NULL;
1835 chwire = NULL;
1836 return 1 ;
1837 }
1838
1839
1840 void awe_create_triangle( losig_list *losig, lonode_list *driver )
1841 {
1842 lowire_list *wire ;
1843
1844 avt_logenterfunction(LOGTRC,2,"awe_create_triangle()");
1845 clearallwireflag( losig, RCN_FLAG_PASS );
1846 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
1847 RCN_CLEARFLAG( wire->FLAG, RCXNODEINTR );
1848
1849 rcn_treetrip( losig,
1850 driver,
1851 awe_up_forcreatetriangle,
1852 NULL,
1853 (int (*)(losig_list*,lonode_list*,void*,void*))
1854 awe_packup_forcreatetriangle,
1855 NULL,
1856 0
1857 );
1858 avt_logexitfunction(LOGTRC,2);
1859 }
1860
1861 void awe_clean_triangle( losig_list *losig, lonode_list *driver )
1862 {
1863 lowire_list *wire ;
1864
1865 clearallwireflag( losig, RCN_FLAG_PASS );
1866 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
1867 RCN_CLEARFLAG( wire->FLAG, RCXNODEINTR );
1868
1869 rcn_treetrip( losig,
1870 driver,
1871 NULL,
1872 awe_dw_forcleantriangle,
1873 NULL,
1874 NULL,
1875 0
1876 );
1877 }
1878
1879 /******************************************************************************\
1880 Fonction qui récupère les moments sur le réseau RC.
1881 \******************************************************************************/
1882 chain_list* getaweinfo( losig_list *losig,
1883 locon_list *load,
1884 locon_list *driver,
1885 RCXFLOAT extcapa,
1886 rcx_slope *slopemiller,
1887 char type,
1888 RCXFLOAT coefctc
1889 )
1890 {
1891 ptype_list *ptl ;
1892 rcx_list *rcx ;
1893 int isloop ;
1894 mbkcache *cache ;
1895 chain_list *head = NULL ;
1896 chain_list *list ;
1897 chain_list *removeextra = NULL ;
1898 aweinfo_list *awe ;
1899 unsigned long int sizeallocated=0;
1900 awecache *awetop ;
1901
1902 #ifdef AWEDEBUG
1903 awestatcallinfo++;
1904 #endif
1905
1906 avt_logenterfunction(LOGTRC,2,"getaweinfo()");
1907
1908 cache = rcx_get_delay_cache();
1909 if( cache ) {
1910 mbk_cache_refresh( cache, NULL, losig );
1911 mbk_cache_lock( cache, losig );
1912 awetop = rcx_get_cache_awe( losig,
1913 slopemiller->SENS,
1914 type,
1915 rcx_crosstalkactive( RCX_QUERY )
1916 );
1917
1918 if( awetop && awetop->HEAD ) {
1919 if( awetop->HT ) {
1920 list = (chain_list*)gethtitem( awetop->HT, load );
1921 if( list != (chain_list*)EMPTYHT && list != (chain_list*)DELETEHT ) {
1922 while( list ) {
1923 awe = (aweinfo_list*)list->DATA ;
1924 if( awe->LOCON_DRIVER == driver &&
1925 awe->EXTCAPA == extcapa )
1926 head = addchain( head, awe );
1927 list = list->NEXT ;
1928 }
1929 }
1930 }
1931 else {
1932 awe = awetop->HEAD ;
1933 while( awe ) {
1934 if( awe->LOCON_DRIVER == driver &&
1935 awe->LOCON_LOAD == load &&
1936 awe->EXTCAPA == extcapa )
1937 head = addchain( head, awe );
1938 awe = awe->NEXT ;
1939 }
1940 }
1941 }
1942
1943 if( head ) {
1944 avt_logexitfunction(LOGTRC,2);
1945 mbk_cache_unlock( cache, losig );
1946 return head;
1947 }
1948 }
1949
1950 // Il faut calculer tous les moments sur les récepteurs à partir de l'emetteur driver.
1951 if( !driver->PNODE ) {
1952 awe_error( 4, AVT_WARNING );
1953 avt_logexitfunction(LOGTRC,2);
1954 mbk_cache_unlock( cache, losig );
1955 return NULL ;
1956 }
1957
1958 rcx = getrcx( losig );
1959 if( rcx )
1960 isloop = rcx_isloop( rcx, losig );
1961 else
1962 isloop = 1 ;
1963
1964 if( ( RCX_USING_AWEMATRIX==RCX_USING_AWEMATRIX_ALWAYS ||
1965 RCX_USING_AWEMATRIX==RCX_USING_AWEMATRIX_FORCE ) ||
1966 ( RCX_USING_AWEMATRIX==RCX_USING_AWEMATRIX_IFNEED &&
1967 ( isloop ||
1968 rcx_is_multiple_pnode( losig, driver ) ) ) )
1969 build_awe_moment_with_loop( losig,
1970 driver,
1971 extcapa,
1972 slopemiller,
1973 type,
1974 coefctc
1975 );
1976 else
1977 build_awe_moment_without_loop( losig,
1978 driver,
1979 extcapa,
1980 slopemiller,
1981 type,
1982 coefctc
1983 );
1984
1985 ptl = getptype( losig->USER, AWEINFO );
1986
1987 if( ptl ) { // Cas des composantes connexes
1988
1989 for( awe = (aweinfo_list*)(ptl->DATA) ; awe ; awe = awe->NEXT ) {
1990 if( awe->LOCON_DRIVER == driver &&
1991 awe->LOCON_LOAD == load &&
1992 awe->EXTCAPA == extcapa )
1993 head = addchain( head, awe );
1994 else {
1995 if( !cache )
1996 removeextra = addchain( removeextra, awe );
1997 }
1998 }
1999
2000 if( cache ) {
2001 sizeallocated = rcx_add_cache_awe( losig,
2002 slopemiller->SENS,
2003 type,
2004 rcx_crosstalkactive( RCX_QUERY )
2005 );
2006 mbk_cache_update_size( cache, NULL, sizeallocated );
2007 // trccheckcachecoherence();
2008 }
2009 else {
2010 awefreeinfolist( removeextra );
2011 }
2012
2013 losig->USER = delptype( losig->USER, AWEINFO );
2014 }
2015
2016 if( cache )
2017 mbk_cache_unlock( cache, losig );
2018
2019 avt_logexitfunction(LOGTRC,2);
2020 return head ;
2021 }
2022
2023 /* return 1 if pnodes for locon 'driver' should be considered as mulptiple
2024 simultaneous driver, or 0 if they can be considers as equivalent. */
2025
2026 int rcx_is_multiple_pnode( losig_list *losig, locon_list *driver )
2027 {
2028 int n ;
2029 int valid ;
2030 num_list *pnode ;
2031 num_list *onode ;
2032 lonode_list *lonode ;
2033 ptype_list *ptl ;
2034 int resi ;
2035 RCXFLOAT capa ;
2036
2037 avt_logenterfunction(LOGTRC,2,"rcx_is_multiple_pnode()");
2038
2039 valid = 0 ;
2040
2041 if( !driver->PNODE ) {
2042 avt_log(LOGTRC,2, "no pnode found on locon %s\n", getloconrcxname( driver ) );
2043 avt_logexitfunction(LOGTRC,2);
2044 return 0;
2045 }
2046
2047 /* first test : check the number of pnode */
2048 n=0 ;
2049 for( pnode = driver->PNODE ; pnode ; pnode = pnode->NEXT )
2050 n++;
2051
2052 if( n > 3 ) {
2053 avt_log(LOGTRC,2, "more than 3 pnode found on locon %s\n", getloconrcxname( driver ) );
2054 avt_logexitfunction(LOGTRC,2);
2055 return 1 ;
2056 }
2057
2058 capa = rcx_getcapa( NULL, losig );
2059
2060 for( pnode = driver->PNODE ; pnode ; pnode = pnode->NEXT ) {
2061
2062 avt_log(LOGTRC,2,"computing from node %ld\n", pnode->DATA );
2063
2064 rcn_treetrip( losig,
2065 getlonode( losig, pnode->DATA ),
2066 rcx_imp_prop,
2067 NULL,
2068 NULL,
2069 NULL,
2070 5
2071 );
2072 for( onode = pnode->NEXT ; onode ; onode = onode->NEXT ) {
2073 lonode = getlonode( losig, onode->DATA );
2074 ptl = getptype( lonode->USER, AWESUMRESI );
2075 if( ptl ) {
2076 resi = ((long)ptl->DATA)/1000.0 ;
2077 if( resi * capa > 1.0 )
2078 break ;
2079 }
2080 else
2081 /* the number of wire between pnode and onode exceed the value of the
2082 last argument of rcn_treetrip */
2083 break ;
2084 }
2085
2086 if( onode )
2087 valid=1;
2088
2089 avt_log(LOGTRC,2, "cleanning\n" );
2090 rcn_treetrip( losig,
2091 getlonode( losig, pnode->DATA ),
2092 rcx_imp_clean,
2093 NULL,
2094 NULL,
2095 NULL,
2096 5
2097 );
2098
2099 if( valid )
2100 break;
2101 }
2102
2103 avt_logexitfunction(LOGTRC,2);
2104 return valid ;
2105 }
2106
2107 int rcx_imp_clean( losig_list *losig,
2108 lonode_list *lonode,
2109 lowire_list *lowire,
2110 void *data
2111 )
2112 {
2113 ptype_list *ptl ;
2114
2115 ptl = getptype( lonode->USER, AWESUMRESI );
2116 if( ptl ) {
2117 lonode->USER = delptype( lonode->USER, AWESUMRESI );
2118 }
2119
2120 losig=NULL;
2121 lowire=NULL;
2122 data=NULL;
2123 return 1 ;
2124 }
2125
2126 int rcx_imp_prop( losig_list *losig,
2127 lonode_list *lonode,
2128 lowire_list *lowire,
2129 void *data
2130 )
2131 {
2132 ptype_list *ptl ;
2133 int resi ;
2134 int ifrom ;
2135 lonode_list *pfrom ;
2136
2137 ptl = getptype( lonode->USER, AWESUMRESI );
2138 if( ptl ) {
2139 /* big problem : there is a loop not detected by rcn_treetrip */
2140 awe_error( 5, AVT_INTERNAL );
2141 }
2142 if( lowire ) {
2143 ifrom = (lowire->NODE1 == lonode->INDEX ? lowire->NODE2 : lowire->NODE1 );
2144 pfrom = getlonode( losig, ifrom );
2145 ptl = getptype( pfrom->USER, AWESUMRESI );
2146 if( ptl )
2147 resi = ((long)ptl->DATA);
2148 else
2149 resi = 0;
2150 resi = resi + ((int)(1000.0*lowire->RESI));
2151 lonode->USER = addptype( lonode->USER, AWESUMRESI, (void*)((long)resi) );
2152
2153 data=NULL;
2154 }
2155 return 1;
2156 }
2157
2158 void build_awe_moment_without_loop( losig_list *losig,
2159 locon_list *driver,
2160 RCXFLOAT extcapa,
2161 rcx_slope *slopemiller,
2162 char type,
2163 RCXFLOAT coefctc )
2164 {
2165 RCXFLOAT k;
2166 num_list *scan_driver;
2167 lonode_list *node_driver;
2168 int n;
2169
2170 avt_logenterfunction(LOGTRC,2,"build_awe_moment_without_loop()");
2171
2172 for( scan_driver = driver->PNODE ; scan_driver ; scan_driver = scan_driver->NEXT ) {
2173
2174 avt_log(LOGTRC,2, "from driver %d\n", scan_driver->DATA );
2175
2176 #ifdef AWEDEBUG
2177 // On ne compte que les vrais appels. Pas les récursifs.
2178 awestatcallmoment++;
2179 #endif
2180
2181 // Premiere étape, on reserve la mémoire pour les moments sur tous les noeuds du reseau RC.
2182
2183 node_driver = getlonode( losig, scan_driver->DATA );
2184
2185 awe_create_triangle( losig, node_driver );
2186
2187 awebuildnodes( losig,
2188 node_driver,
2189 extcapa,
2190 slopemiller,
2191 type,
2192 coefctc,
2193 0
2194 );
2195
2196 // Ensuite, on construit le premier moment : il sert à normaliser les résultats pour ne pas
2197 // avoir trop d'erreur d'arrondi dans les calculs.
2198
2199 #ifdef AWE_NORMALISE
2200 avt_log(LOGTRC,2,"normalisation\n");
2201 awemoment( losig, node_driver, 1, 1.0, extcapa );
2202 k = -awemaxmoment( losig, node_driver );
2203 awebuildnodes( losig,
2204 node_driver,
2205 extcapa,
2206 slopemiller,
2207 type,
2208 coefctc,
2209 1
2210 ); // Réinitialise les SUMMOMENTCAPA
2211 #else
2212 k = 1.0;
2213 #endif
2214
2215 if( k > 1e-6 ) {
2216 avt_log(LOGTRC,2,"building moment\n");
2217 // Enfin, on construit définitivement les moments.
2218 for( n=1;n<=AWE_MAX_MOMENT;n++)
2219 awemoment( losig, node_driver, n, k, extcapa );
2220
2221 // On les mémorise finalement dans les structures aweinfo.
2222 awebuildinfo( losig, driver, node_driver->INDEX, k, extcapa );
2223 }
2224 // Puis on efface ceux qui ne servent à rien.
2225 avt_log(LOGTRC,2,"cleanning\n");
2226 awecleannodes( losig, node_driver );
2227 awe_clean_triangle( losig, node_driver );
2228 }
2229
2230 avt_logexitfunction(LOGTRC,2);
2231 }
2232
2233 void awebuildinfo( losig_list *ptsig,
2234 locon_list *driver,
2235 long node_driver,
2236 RCXFLOAT k,
2237 RCXFLOAT extcapa
2238 )
2239 {
2240 chain_list *scanlocon ;
2241 num_list *scannode ;
2242 locon_list *load;
2243 awetabnode *tabnode;
2244 lonode_list *ptnode;
2245 ptype_list *ptl;
2246 double m[AWE_MAX_MOMENT];
2247 int i;
2248
2249 for( i=0 ; i<AWE_MAX_MOMENT ; i++ )
2250 m[i] = 0.0 ;
2251
2252 for( scanlocon = (chain_list*)(getptype( ptsig->USER, LOFIGCHAIN )->DATA ) ;
2253 scanlocon ;
2254 scanlocon = scanlocon->NEXT ) {
2255
2256 load = (locon_list*)(scanlocon->DATA);
2257 if( !rcx_isvalidlocon( load ) )
2258 continue;
2259
2260 if( load != driver ) {
2261
2262 for( scannode = load->PNODE ; scannode ; scannode = scannode->NEXT ) {
2263
2264 if( node_driver == scannode->DATA ) {
2265 aweaddnodeinfo( ptsig,
2266 driver,
2267 node_driver,
2268 load,
2269 scannode->DATA,
2270 m,
2271 k,
2272 extcapa
2273 );
2274 continue;
2275 }
2276
2277 ptnode = getlonode( ptsig, scannode->DATA );
2278
2279 // lorsqu'on a plusieurs composantes connexes, il est possible
2280 // de ne pas avoir de ptype construits.
2281 ptl = getptype( ptnode->USER, AWENODE );
2282 if( !ptl ) {
2283 aweaddnodeinfo( ptsig,
2284 driver,
2285 node_driver,
2286 load,
2287 scannode->DATA,
2288 m,
2289 k,
2290 extcapa
2291 );
2292 continue;
2293 }
2294
2295 tabnode = (awetabnode*)(ptl->DATA );
2296
2297 aweaddnodeinfo( ptsig,
2298 driver,
2299 node_driver,
2300 load,
2301 scannode->DATA,
2302 tabnode->MOMENT,
2303 k,
2304 extcapa
2305 );
2306 }
2307 }
2308 }
2309 }
2310
2311 aweinfo_list* awegetheapinfo( void )
2312 {
2313 aweinfo_list *pt=NULL;
2314
2315 pt = (aweinfo_list*)mbkalloc(sizeof( aweinfo_list ));
2316 return pt ;
2317 }
2318
2319 void awefreeinfo( aweinfo_list *awe )
2320 {
2321 mbkfree( awe );
2322 }
2323
2324 aweinfo_list* awegetnewinfo( void )
2325 {
2326 aweinfo_list *pt;
2327
2328 pt = awegetheapinfo();
2329 return pt;
2330 }
2331
2332 aweinfo_list* aweaddnodeinfo( losig_list *signal,
2333 locon_list *driver,
2334 long node_driver,
2335 locon_list *load,
2336 long node_load,
2337 RCXFLOAT *moment,
2338 RCXFLOAT k,
2339 RCXFLOAT extcapa
2340 )
2341 {
2342 aweinfo_list *pt;
2343 int i;
2344 ptype_list *ptl;
2345
2346 pt = awegetnewinfo( );
2347
2348 pt->LOCON_DRIVER = driver ;
2349 pt->NODE_DRIVER = node_driver ;
2350 pt->LOCON_LOAD = load ;
2351 pt->NODE_LOAD = node_load ;
2352 pt->K = k ;
2353 pt->EXTCAPA = extcapa ;
2354
2355 // Cas où tous les moments sont nuls : l'émetteur et le récepteur sont
2356 // sur le meme noeud.
2357
2358 for( i=0 ; i < AWE_MAX_MOMENT ; i++ ) {
2359 if( moment[i] != 0.0 )
2360 break;
2361 }
2362
2363 if( i==AWE_MAX_MOMENT ) {
2364 pt->FLAG = AWE_NODELAY ;
2365 } else {
2366 pt->FLAG = AWE_MOMENT ;
2367 }
2368
2369 for( i = 0 ; i < AWE_MAX_MOMENT ; i++ ) {
2370 pt->DATA.MOMENT[i] = moment[i];
2371 }
2372
2373 ptl = getptype( signal->USER, AWEINFO );
2374 if( !ptl ) {
2375 signal->USER = addptype( signal->USER, AWEINFO, NULL ) ;
2376 ptl = signal->USER ;
2377 }
2378
2379 pt->NEXT = (aweinfo_list*)(ptl->DATA );
2380 ptl->DATA = pt ;
2381
2382 return( pt );
2383 }
2384
2385 void awemomentfiltre( aweinfo_list *info )
2386 {
2387 matrice *a, *c, *alpha ;
2388 int l, m, k ;
2389 matrice *polea, *polec, *polex ;
2390 RCXFLOAT poles[AWE_MAX_ORDER], poly[AWE_MAX_ORDER+1];
2391 int ordre ;
2392
2393 avt_logenterfunction(LOGTRC,2,"awemomentfiltre()");
2394
2395 if( info->FLAG == AWE_NODELAY ) {
2396 avt_log(LOGTRC,2,"nodelay\n");
2397 avt_logexitfunction(LOGTRC,2);
2398 return;
2399 }
2400
2401 #ifdef AWEDEBUG
2402 awestatcallfilter++;
2403 #endif
2404
2405 ordre = AWE_MAX_ORDER+1;
2406
2407 do
2408 {
2409 ordre--;
2410 avt_log(LOGTRC,2,"order %d\n", ordre );
2411
2412 if( ordre == 0 ) {
2413 info->FLAG = (AWE_FLAGERROR | AWE_FLAGALLORDERFAILED );
2414
2415 avt_errmsg( TRC_ERRMSG, "002", AVT_WARNING,
2416 rcx_getsigname( AWE_DEBUG_NET ) );
2417 }
2418 else {
2419
2420 avt_log(LOGTRC,2, "building matrix\n");
2421 a = mat_create( ordre, ordre );
2422 alpha = mat_create( ordre, 1 );
2423 c = mat_create( ordre, 1 );
2424 polea = mat_create( ordre, ordre );
2425 polec = mat_create( ordre, 1 );
2426 polex = mat_create( ordre, 1 );
2427
2428 for( l = 0 ; l < ordre ; l++ )
2429 {
2430 for( m = 0, k=l ; m < ordre ; m++, k++ )
2431 MATELEM( a, l, m ) = ( (k==0) ? 1.0 : info->DATA.MOMENT[k-1] );
2432 }
2433
2434 for( l = 0 ; l < ordre ; l++ )
2435 MATELEM( c, l, 0 ) = -info->DATA.MOMENT[ordre+l-1];
2436
2437 // Détermination du dénominateur de la fonction de transfert
2438
2439 avt_log(LOGTRC,2,"finding denominator\n" );
2440
2441 if( !mat_solve( a, c, alpha ) ) {
2442 avt_log(LOGTRC,2, "singular matrix at order %d on signal %s.\n",
2443 ordre,
2444 rcx_getsigname( info->LOCON_DRIVER->SIG )
2445 );
2446 mat_free( a );
2447 mat_free( alpha );
2448 mat_free( c );
2449 mat_free( polea );
2450 mat_free( polec );
2451 mat_free( polex );
2452
2453 continue;
2454 }
2455
2456 // Vérifier qu'on a pas de nan :
2457 //
2458
2459 /* on recupère dans alpha le dénominateur de la fonction de transfert :
2460 * bn.s^n+...+b2.s^2+b1.s+1 -> (bn,...,b2,b1)
2461 */
2462
2463 for( l=0 ; l<ordre ; l++ )
2464 poly[l+1] = MATELEM(alpha, ordre-1-l, 0);
2465 poly[0]=1.0;
2466
2467 // On récupère les racines de ce polynome. Si on a pas pu les obtenir, on abandonne
2468 avt_log(LOGTRC,2,"finding root\n");
2469
2470 if( poly_findroot( poly, ordre, poles ) == 0 ) {
2471 avt_log(LOGTRC,2, "awe : can't find roots at order %d on signal %s.\n",
2472 ordre,
2473 rcx_getsigname( info->LOCON_DRIVER->SIG )
2474 );
2475 mat_free( a );
2476 mat_free( alpha );
2477 mat_free( c );
2478 mat_free( polea );
2479 mat_free( polec );
2480 mat_free( polex );
2481 continue;
2482 }
2483
2484 /* En principe, toutes les racines sont censées être négatives. On le vérifie
2485 */
2486 for( l = 0 ; l < ordre ; l++ )
2487 if( poles[l]>=0.0 ) {
2488 avt_log(LOGTRC,2, "awe : a positive root has been found at order %d on signal %s.\n",
2489 ordre,
2490 rcx_getsigname( info->LOCON_DRIVER->SIG )
2491 );
2492 break;
2493 }
2494 if( l<ordre ) {
2495 mat_free( a );
2496 mat_free( alpha );
2497 mat_free( c );
2498 mat_free( polea );
2499 mat_free( polec );
2500 mat_free( polex );
2501 continue;
2502 }
2503
2504 /* on détermine les résidus */
2505
2506 avt_log(LOGTRC,2,"find residues\n");
2507 for( l = 0 ; l < ordre ; l++ )
2508 for( m = 0 ; m < ordre ; m++ )
2509 MATELEM( polea, l, m ) = 1.0/pow(poles[m],l+1.0);
2510
2511 MATELEM( polec, 0, 0 ) = -1.0;
2512 for( l = 1 ; l < ordre ; l++ )
2513 MATELEM( polec, l, 0 ) = -info->DATA.MOMENT[l-1];
2514
2515 if( !mat_solve( polea, polec, polex ) ) {
2516 avt_log(LOGTRC,2, "awe : risidues matrix is singular at order %d on signal %s.\n",
2517 ordre,
2518 rcx_getsigname( info->LOCON_DRIVER->SIG )
2519 );
2520 mat_free( a );
2521 mat_free( alpha );
2522 mat_free( c );
2523 mat_free( polea );
2524 mat_free( polec );
2525 mat_free( polex );
2526 continue;
2527 }
2528
2529 // C'est fini : on range le tout.
2530
2531 avt_log(LOGTRC,2,"parameter determined\n");
2532 info->FLAG = AWE_FILTER ;
2533 for( l=0 ; l<ordre ; l++ ) {
2534 info->DATA.FILTER.POLE[l] = poles[l];
2535 info->DATA.FILTER.RESIDU[l] = MATELEM( polex, l, 0 ) ;
2536 }
2537 info->DATA.FILTER.ORDER = ordre;
2538
2539 mat_free( a );
2540 mat_free( alpha );
2541 mat_free( c );
2542 mat_free( polea );
2543 mat_free( polec );
2544 mat_free( polex );
2545 }
2546 }
2547 while( info->FLAG == AWE_MOMENT );
2548 avt_logexitfunction(LOGTRC,2);
2549 }
2550
2551 /******************************************************************************\
2552 Renvoie une liste de délais.
2553 \******************************************************************************/
2554
2555 awelist* getawedelaylist( lofig_list *lofig,
2556 losig_list *losig,
2557 locon_list *locon_emt,
2558 rcx_slope *slopemiller,
2559 RCXFLOAT extcapa
2560 )
2561 {
2562 chain_list *chain;
2563 locon_list *locon;
2564 int res;
2565 RCXFLOAT dmax, dmin, fmax, fmin;
2566 awelist *headlist=NULL;
2567
2568 for( chain = ((chain_list*)(getptype( losig->USER, LOFIGCHAIN )->DATA) ) ;
2569 chain ;
2570 chain = chain->NEXT
2571 ) {
2572
2573 locon = (locon_list*)chain->DATA;
2574 if( !rcx_isvalidlocon( locon ) )
2575 continue;
2576
2577 if( locon == locon_emt )
2578 continue;
2579
2580 res = getawedelay( lofig, losig, locon_emt, locon,
2581 slopemiller,
2582 slopemiller->MAX.vend,
2583 slopemiller->MIN.vend,
2584 extcapa,
2585 &dmax,
2586 &dmin,
2587 &fmax,
2588 &fmin,
2589 NULL,
2590 NULL
2591 );
2592
2593 if( res )
2594 headlist = addawelist( headlist, locon, dmax, dmin, fmax, fmin );
2595 }
2596
2597 return headlist;
2598 }
2599
2600 void freeawedelaylist( awelist *headlist )
2601 {
2602 awelist *next;
2603
2604 while( headlist ) {
2605 next = headlist->NEXT;
2606 mbkfree( headlist );
2607 headlist = next;
2608 }
2609 }
2610
2611 awelist *addawelist( awelist *head, locon_list *locon,
2612 RCXFLOAT dmax, RCXFLOAT dmin, RCXFLOAT fmax, RCXFLOAT fmin
2613 )
2614 {
2615 awelist *new;
2616
2617 new = mbkalloc( sizeof( awelist ) );
2618 new->LOCON = locon;
2619 new->DMAX = dmax;
2620 new->DMIN = dmin;
2621 new->FMAX = fmax;
2622 new->FMIN = fmin;
2623 new->NEXT = head;
2624
2625 return new;
2626 }
2627
2628 void awe_error( int subcode, int type )
2629 {
2630 avt_errmsg( TRC_ERRMSG, "000", type,
2631 subcode,
2632 rcx_getsigname( AWE_DEBUG_NET ),
2633 getloconrcxname( AWE_DEBUG_DRIVER ),
2634 getloconrcxname( AWE_DEBUG_RECEIVER )
2635 );
2636 }
2637
2638 void awefreeinfolist( chain_list *head )
2639 {
2640 mbkcache *cache ;
2641 chain_list *scan ;
2642
2643 cache = rcx_get_delay_cache();
2644
2645 if( !cache ) {
2646 for( scan = head ; scan ; scan = scan->NEXT ) {
2647 awefreeinfo( (aweinfo_list*)scan->DATA );
2648 }
2649 }
2650
2651 freechain( head );
2652 }
2653
2654 awecache* rcx_get_cache_awe( losig_list *losig,
2655 char transition,
2656 char type,
2657 char iscrosstalk
2658 )
2659 {
2660
2661 ptype_list *ptl ;
2662 long int ntype ;
2663 ptype_list *ptype ;
2664 awecache *awe ;
2665
2666 ptl = getptype( losig->USER, RCX_DELAYCACHE );
2667 if( !ptl ) {
2668 avt_errmsg( TRC_ERRMSG, "047", AVT_ERROR, rcx_getsigname( losig ) );
2669 return NULL ;
2670 }
2671
2672 ntype =
2673 rcx_cache_build_ptype( transition, type, iscrosstalk, RCX_MODEL_AWE );
2674
2675 for( ptype = (ptype_list*)ptl->DATA ; ptype ; ptype = ptype->NEXT ) {
2676
2677 if( ptype->TYPE == ntype ) {
2678 awe = (awecache*)ptype->DATA ;
2679 return awe ;
2680 }
2681 }
2682
2683 return NULL ;
2684 }
2685
2686 unsigned long int rcx_add_cache_awe( losig_list *losig,
2687 char transition,
2688 char type,
2689 char iscrosstalk
2690 )
2691 {
2692 unsigned long int size_allocated = 0 ;
2693 ptype_list *ptl ;
2694 long int ntype ;
2695 ptype_list *ptype ;
2696 aweinfo_list *head ;
2697 awecache *awetop ;
2698
2699 ptl = getptype( losig->USER, RCX_DELAYCACHE );
2700 if( !ptl ) {
2701 avt_errmsg( TRC_ERRMSG, "047", AVT_ERROR, rcx_getsigname( losig ) );
2702 return 0 ;
2703 }
2704
2705 ntype =
2706 rcx_cache_build_ptype( transition, type, iscrosstalk, RCX_MODEL_AWE );
2707
2708 for( ptype = (ptype_list*)ptl->DATA ; ptype ; ptype = ptype->NEXT ) {
2709
2710 if( ptype->TYPE == ntype )
2711 break ;
2712 }
2713
2714 if( !ptype ) {
2715
2716 awetop = mbkalloc( sizeof( awecache ) );
2717 awetop->HEAD = NULL ;
2718 awetop->HT = NULL ;
2719 awetop->NB = 0 ;
2720 size_allocated += sizeof( awecache );
2721
2722 ptl->DATA = addptype( (ptype_list*)ptl->DATA, ntype, awetop );
2723 size_allocated += sizeof( ptype_list );
2724
2725 }
2726 else {
2727 awetop = (awecache*)ptype->DATA ;
2728 }
2729
2730 ptl = getptype( losig->USER, AWEINFO );
2731 if( ptl ) {
2732
2733 head = (aweinfo_list*)ptl->DATA ;
2734
2735 if( head ) {
2736
2737 while( head->NEXT ) {
2738 size_allocated += sizeof( aweinfo_list );
2739 awetop->NB++ ;
2740 head = head->NEXT ;
2741 }
2742 size_allocated += sizeof( aweinfo_list );
2743 awetop->NB++ ;
2744
2745 size_allocated += rcx_awe_cache_update_ht( awetop,
2746 (aweinfo_list*)ptl->DATA
2747 );
2748
2749 head->NEXT = awetop->HEAD ;
2750 awetop->HEAD = (aweinfo_list*)ptl->DATA ;
2751 }
2752
2753 ptl->DATA = NULL ;
2754 }
2755 else {
2756 avt_errmsg( TRC_ERRMSG, "047", AVT_ERROR, rcx_getsigname( losig ) );
2757 }
2758
2759 return size_allocated ;
2760 }
2761
2762 unsigned long int rcx_awe_cache_update_ht( awecache *awetop,
2763 aweinfo_list *head
2764 )
2765 {
2766 aweinfo_list *scan ;
2767 unsigned long int size=0;
2768
2769 /* pas de prise en compte de la taille de la table de hash car sa taille
2770 peut varier */
2771 if( awetop->HT == NULL ) {
2772 if( awetop->NB > 30 ) {
2773 awetop->HT = addht(30);
2774 for( scan = awetop->HEAD ; scan ; scan = scan->NEXT ) {
2775 size += sizeof( chain_list );
2776 rcx_awe_cache_add_ht( awetop->HT, scan );
2777 }
2778 }
2779 }
2780 else {
2781 for( scan = head ; scan ; scan = scan->NEXT ) {
2782 size += sizeof( chain_list );
2783 rcx_awe_cache_add_ht( awetop->HT, scan );
2784 }
2785 }
2786
2787 return size ;
2788 }
2789
2790 void rcx_awe_cache_add_ht( ht *ht, aweinfo_list *aweinfo )
2791 {
2792 controlled_addhtitem( ht,
2793 aweinfo->LOCON_LOAD,
2794 (long(*)(int,long,void*))rcx_awe_cache_fn,
2795 (void*)aweinfo
2796 );
2797 }
2798
2799 long rcx_awe_cache_fn( int isnew, chain_list *head, aweinfo_list *awe )
2800 {
2801 if( isnew )
2802 return (long) addchain( NULL, awe );
2803 return (long) addchain( head, awe );
2804 }
2805
2806 unsigned long int rcx_cache_release_awe( awecache *awetop )
2807 {
2808 unsigned long int torelease = 0;
2809 aweinfo_list *next ;
2810 aweinfo_list *head ;
2811 chain_list *chainht ;
2812 chain_list *scanht ;
2813 chain_list *count ;
2814
2815 head = awetop->HEAD ;
2816 while( head ) {
2817 torelease += sizeof( aweinfo_list );
2818 next = head->NEXT ;
2819 awefreeinfo( head );
2820 head = next ;
2821 }
2822 if( awetop->HT ) {
2823 chainht = GetAllHTElems( awetop->HT );
2824 for( scanht = chainht ; scanht ; scanht = scanht->NEXT ) {
2825 for( count = (chain_list*)scanht->DATA ; count ; count = count->NEXT )
2826 torelease += sizeof( chain_list ) ;
2827 freechain( (chain_list*)scanht->DATA );
2828 }
2829 freechain( chainht );
2830 delht( awetop->HT );
2831 }
2832 mbkfree( awetop );
2833 torelease += sizeof( awecache );
2834
2835
2836 return torelease ;
2837 }