Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / tas / trc / trc_rcx.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI Alliance */
4 /* */
5 /* Produit : TRC Version 1.01 */
6 /* Fichier : trc_rcx.c */
7 /* */
8 /* (c) copyright 1997-1998 Laboratoire LIP6 equipe ASIM */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
11 /* */
12 /* Auteur(s) : Gregoire AVOT */
13 /* */
14 /****************************************************************************/
15
16 /* CVS informations :
17
18 Revision : $Revision: 1.182 $
19 Author : $Author: fabrice $
20 Date : $Date: 2008/03/20 16:23:04 $
21
22 */
23
24 #include "trc.h"
25 #include MCC_H
26
27 int RCX_CROSSTALK=RCX_NOCROSSTALK;
28 char RCX_FREEUNUSEDCTC='Y';
29 char RCX_USECACHE='Y';
30 char RCX_FASTMODE=1;
31
32 /* Valeur du produit RC sur un signal en dessous duquel on considère qu'il n'y
33 a pas de délais RC à prendre en compte. */
34 RCXFLOAT RCX_MINRCSIGNAL=1.0;
35
36 /* Valeur relative entre 0 et 1 de la part de capacité de couplage sur un signal
37 en dessous de laquelle on considère que le signal n'est pas sujet au couplage */
38 RCXFLOAT RCX_MINRELCTKSIGNAL=0.05;
39
40 /* Filtrage des capacités de couplage : valeur relative entre 0 et 1 de la part
41 des capacités à négliger */
42 RCXFLOAT RCX_MINRELCTKFILTER=0.05;
43
44 /* Paramètres de la fonction rcx_rcnload() lorsque l'argument flag vaut
45 RCX_BESTLOAD.
46
47 RCX_CAPALOAD_MAXRC : Temps (en pico secondes) en dessous duquel le produit
48 de la somme des résistances x somme des capacités doit être inférieur pour
49 qu'on prenne systématiquement une charge purement capacitive.
50
51 RCX_MAXDELTALOAD : Ecart maximum autorisé entre la cellule en pi et la
52 capacité pure lorsque le générateur de courant est constant (valeur sans
53 influence).
54 */
55 RCXFLOAT RCX_CAPALOAD_MAXRC = 5.0;
56 RCXFLOAT RCX_MAXDELTALOAD = 1.0;
57
58 char RCX_CTK_MODEL = RCX_MILLER_NOMINAL ;
59 char RCX_CTK_NOISE = RCX_NOISE_FINE ;
60 char RCX_CTK_SLOPE_NOISE = RCX_SLOPE_CTK ;
61 char RCX_CTK_SLOPE_MILLER = RCX_SLOPE_NOMINAL ;
62 char RCX_CTK_SLOPE_DELAY = RCX_SLOPE_DELAY_CTK ;
63
64 double RCX_SLOPE_UNSHRINK = 0.6 ;
65
66 /* Prend en compte les fronts améliorés pour l'effet miller */
67 #define RCX_CORREC_MILLER
68
69 /*******************************************************************************
70 * *
71 * rcx_state() *
72 * Renvoie un nombre caracterisant l'etat de la vue RCX. L'argument peut etre *
73 * NULL. *
74 * *
75 * -1 Pas de vue RCX (ptrcx = NULL) *
76 * 0 Vue RCX vierge *
77 * 1 Vue RCX normale *
78 * 2 Vue RCX non extraite (RCXNODELAY seul) *
79 * L'argument where permet de savoir si il s'agit d'une vue interne ou externe. *
80 * 1=vue interne *
81 * 2=vue externe *
82 * autre=pas de verification *
83 *******************************************************************************/
84
85 // where :
86 #define RCX_STATE_NOCHECK 0
87 #define RCX_STATE_LOINS 1
88 #define RCX_STATE_LOFIG 2
89
90 // code retour :
91 #define RCX_STATE_NORCX -1
92 #define RCX_STATE_EMPTY 0
93 #define RCX_STATE_TYPED 1
94
95 int rcx_state( ptrcx, where )
96 rcx_list *ptrcx;
97 int where;
98 {
99 if( !ptrcx )
100 return(RCX_STATE_NORCX);
101
102 if( !GETFLAG( ptrcx->FLAG, MODELRCN ) )
103 {
104 if( where == RCX_STATE_LOINS ) // Dans une instance, on a forcement une
105 rcx_error( 21, NULL, AVT_ERROR ); // vue RCN.
106
107 return(RCX_STATE_EMPTY);
108 }
109
110 if( GETFLAG( ptrcx->FLAG, MODELRCN ) )
111 {
112 if( where == RCX_STATE_LOFIG && !ptrcx->VIEW )
113 rcx_error( 22, NULL, AVT_ERROR );
114 if( where == RCX_STATE_LOINS && ( !ptrcx->VIEW || !ptrcx->RCXEXTERNAL ) )
115 rcx_error( 23, NULL, AVT_ERROR );
116 return(RCX_STATE_TYPED);
117 }
118
119 rcx_error( 24, NULL, AVT_FATAL );
120
121 /* never reached */
122 return( 1 );
123 }
124
125 /*******************************************************************************
126 * *
127 * merge_ext() *
128 * Ajoute un connecteur dans la vue RCX d'un losig d'une lofig, en regroupant *
129 * ses connecteurs sans faire de boucles. *
130 * *
131 *******************************************************************************/
132
133 void merge_ext( file, ptsig, ptcon, iscache, keeponenode )
134 rcxfile *file;
135 losig_list *ptsig;
136 locon_list *ptcon;
137 char iscache;
138 char keeponenode;
139 {
140 chain_list *chemin;
141 num_list *sn;
142 rcx_list *ptrcx;
143 char buffer[1024];
144 int verif;
145
146 verif = 1;
147
148 if( chkloop( ptsig ) != 0 )
149 verif = 0;
150
151 if( ptcon->PNODE && keeponenode == YES )
152 {
153 /* On ne garde que le premier noeud. */
154 for( sn = ptcon->PNODE->NEXT ; sn ; sn = sn->NEXT )
155 {
156 if( verif )
157 {
158 chemin = getway( ptsig, ptcon->PNODE->DATA, sn->DATA );
159 if( !chemin ) {
160 rcx_drive_wire( file,
161 rcx_get_new_num_node( ptsig,
162 ptcon->PNODE->DATA,
163 RCX_LOFIG,
164 YES
165 ),
166 rcx_get_new_num_node( ptsig,
167 sn->DATA,
168 RCX_LOFIG,
169 YES
170 ),
171 0.0,
172 0.0
173 );
174 if( !iscache )
175 addlowire( ptsig,
176 0,
177 0.0,
178 0.0,
179 ptcon->PNODE->DATA,
180 sn->DATA
181 );
182 }
183 freechain( chemin );
184 }
185 }
186 while( ptcon->PNODE->NEXT )
187 delloconnode( ptcon, ptcon->PNODE->NEXT->DATA );
188
189 }
190
191 ptrcx = getrcx( ptsig );
192 ptrcx->RCXINTERNAL = addchain( ptrcx->RCXINTERNAL, ptcon );
193
194 if( ptcon->TYPE == 'I' ) {
195 sprintf( buffer,
196 "%s%c%s",
197 rcx_getinsname( (loins_list*)(ptcon->ROOT) ), SEPAR,
198 getloconrcxname( ptcon )
199 );
200 addloconrcxname( ptcon, buffer );
201 }
202 }
203
204 void set_ext_rcn( ptsig )
205 losig_list *ptsig;
206 {
207 rcx_list *ptrcx;
208
209 ptrcx = getrcx( ptsig );
210
211 #ifdef RCX_CHECK
212 if( rcx_state( ptrcx, RCX_STATE_LOFIG ) != RCX_STATE_EMPTY || !ptsig->PRCN )
213 rcx_error( 25, ptsig, AVT_WARNING );
214 #endif
215
216 ptrcx->VIEW = ptsig->PRCN;
217 SETFLAG( ptrcx->FLAG, MODELRCN );
218 }
219
220 void rcx_addbellow( losig_list *ptsig, char *sigpointed )
221 {
222 ptsig->USER = addptype( ptsig->USER, RCX_BELLOW, sigpointed );
223 }
224
225 losig_list* rcx_addsigbellow( lofig_list *ptfig, char *sigpointed )
226 {
227 int maxidx = 0;
228 losig_list *losig;
229 char buffer[1024];
230
231 for( losig = ptfig->LOSIG ; losig ; losig = losig->NEXT )
232 if( losig->INDEX > maxidx )
233 maxidx = losig->INDEX ;
234
235 maxidx++;
236
237 sprintf( buffer, "rcx_bellow_%d", maxidx );
238
239 losig = addlosig( ptfig,
240 ++maxidx,
241 addchain( NULL, namealloc( buffer ) ),
242 INTERNAL
243 );
244
245 losig->USER = addptype( losig->USER, RCX_BELLOW, sigpointed );
246 losig->USER = addptype( losig->USER, LOFIGCHAIN, NULL );
247
248 return( losig );
249 }
250
251 /******************************************************************************\
252 Transfert la vue rcx d'une loins dans la vue externe.
253 \******************************************************************************/
254
255 void rcx_copyrcx( lofig_list *lofig,
256 losig_list *sigext,
257 loins_list *loins,
258 losig_list *sigint )
259 {
260
261 rcx_list *rcxext;
262 rcx_list *rcxint;
263 locon_list *loconint;
264 num_list *headnum;
265 num_list *scannum;
266 ptype_list *pt;
267 chain_list *scanchain;
268
269 rcxext = getrcx( sigext );
270 rcxint = getrcx( sigint );
271
272 /* On deplace les locon de la vue interne vers la vue externe :
273 * il suffit juste de les enlever du lofigchain du signal
274 * interne */
275
276
277 for( scanchain = rcxint->RCXINTERNAL ;
278 scanchain ;
279 scanchain=scanchain->NEXT
280 )
281 {
282 loconint = (locon_list*)(scanchain->DATA);
283
284 headnum = NULL ;
285
286 // On commence par calculer les noeuds du locon avant de toucher
287 // à autre chose.
288 rcx_trsfnodelocon( loconint, RCX_LOINS );
289
290 while(loconint->PNODE)
291 {
292 headnum = addnum( headnum, loconint->PNODE->DATA );
293 delloconnode( loconint, loconint->PNODE->DATA );
294 }
295
296 loconint->SIG = sigext ;
297 loconint->ROOT = NULL;
298 rcxext->RCXINTERNAL = addchain( rcxext->RCXINTERNAL, loconint );
299
300 pt = getptype( sigext->USER, LOFIGCHAIN );
301 pt->DATA = addchain( ((chain_list*)(pt->DATA)),
302 loconint
303 );
304
305 pt = getptype( loconint->USER, RCXNAME );
306 if( pt )
307 loconint->USER = delptype( loconint->USER, RCXNAME );
308
309 for( scannum = headnum ; scannum ; scannum = scannum->NEXT )
310 {
311 if( !scannum->DATA )
312 rcx_error( 26, sigint, AVT_ERROR );
313 else
314 setloconnode( loconint, scannum->DATA );
315 }
316
317 freenum( headnum );
318
319 // On transfert la capacité associée au locon ( a cause des allocations
320 // par tat ).
321
322 rcx_transfert_capa_from_instance_to_figure( loins, lofig, loconint );
323 }
324
325 // On ne touche plus à ces connecteurs.
326 freechain( rcxint->RCXINTERNAL );
327 rcxint->RCXINTERNAL = NULL;
328
329 }
330
331 /******************************************************************************\
332 rcx_dump_loins() :
333 - Drive les RC
334 - Crée les BELLOW dans la lofig.
335
336 Drive les éléments RC d'un signal d'une instance dans le fichier. Crée des
337 signaux BELLOW dans la lofig pour les agresseurs internes à la loins. Ils sont
338 accessibles par le ptype RCX_COPIED mis dans les losigs typés UNRESOLVED de
339 l'instance.
340 \******************************************************************************/
341 void rcx_dump_loins( rcxfile *file,
342 lofig_list *lofig,
343 loins_list *loins,
344 losig_list *losig
345 )
346 {
347 lowire_list *wire;
348 losig_list *pseudovssins;
349 losig_list *pseudovssinsni;
350 chain_list *scanchain;
351 loctc_list *loctc;
352 int node;
353 losig_list *sigagr;
354 int nodeagr;
355 ptype_list *pt;
356 losig_list *sigbellow;
357 rcx_list *rcxint;
358 losig_list *sigext;
359 rcx_list *rcxext;
360 losig_list *sigagrext;
361
362 rcxint = getrcx( losig );
363 sigext = rcx_get_out_ins_sig( losig );
364 rcxext = getrcx( sigext );
365
366 if( !GETFLAG( rcxext->FLAG, RCXNOWIRE ) ) {
367 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
368 rcx_drive_wire( file,
369 rcx_get_new_num_node( losig, wire->NODE1, RCX_LOINS, YES ),
370 rcx_get_new_num_node( losig, wire->NODE2, RCX_LOINS, YES ),
371 wire->RESI,
372 wire->CAPA
373 );
374 }
375
376 pseudovssins = getrcxpseudovss( loins->USER );
377 pseudovssinsni = rcx_loinsgetvssni( loins );
378
379 for( scanchain = losig->PRCN->PCTC ;
380 scanchain ;
381 scanchain = scanchain->NEXT )
382 {
383
384 loctc = (loctc_list*)scanchain->DATA;
385 node = rcn_ctcnode( loctc, losig );
386 sigagr = rcn_ctcothersig( loctc, losig );
387 nodeagr = rcn_ctcothernode( loctc, losig );
388
389 if( sigagr == pseudovssins )
390 rcx_drive_ground_capa( file,
391 rcx_get_new_num_node( losig, node, RCX_LOINS, YES ),
392 loctc->CAPA
393 );
394
395 if( sigagr == pseudovssinsni )
396 rcx_drive_ctcni_capa( file,
397 rcx_get_new_num_node( losig, node, RCX_LOINS, YES ),
398 loctc->CAPA
399 );
400
401 if( sigagr != pseudovssins && sigagr != pseudovssinsni ) {
402
403 if( getptype( sigagr->USER, RCX_UNRESOLVEDSIG ) ) {
404 // L'agresseur n'a pas été lu, il correspond à un signal interne.
405 pt = getptype( sigagr->USER, RCX_COPIED );
406
407 if( !pt ) {
408 sigbellow = rcx_addsigbellow( lofig,
409 concatname( rcx_getinsname( loins ),
410 rcx_getsigname( sigagr )
411 )
412 );
413 sigagr->USER = addptype( sigagr->USER, RCX_COPIED, sigbellow );
414 addlorcnet( sigbellow );
415 }
416 else
417 sigbellow = (losig_list*)(pt->DATA);
418
419 rcx_drive_ctc_capa( file,
420 rcx_get_new_num_node( losig, node, RCX_LOINS, YES ),
421 loctc->CAPA,
422 rcx_getsigname( sigbellow ),
423 0
424 );
425 }
426 else {
427 // On teste le cas où il n'y a pas de vue RCX sur le signal externe.
428 /*
429 locon_agr = (locon_list*)getptype( sigagr->USER, RCX_LOCONINS )->DATA;
430 */
431 sigagrext = rcx_get_out_ins_sig( sigagr );
432 if( getrcx( sigagrext ) ) {
433 if( sigagrext != sigext ) {
434 rcx_drive_ctc_capa( file,
435 rcx_get_new_num_node( losig,
436 node,
437 RCX_LOINS,
438 YES
439 ),
440 loctc->CAPA,
441 rcx_getsigname( sigagrext ),
442 rcx_get_new_num_node( sigagr,
443 nodeagr,
444 RCX_LOINS,
445 YES
446 )
447 );
448 }
449 }
450 else {
451 if( tlc_islosigalim( sigagrext ) )
452 rcx_drive_ctcni_capa( file,
453 rcx_get_new_num_node( losig, node, RCX_LOINS, YES ),
454 loctc->CAPA
455 );
456 else
457 rcx_drive_ground_capa( file,
458 rcx_get_new_num_node( losig, node, RCX_LOINS, YES ),
459 loctc->CAPA
460 );
461
462 }
463 }
464 }
465 }
466 }
467
468
469 /******************************************************************************\
470 Crée les réseaux RC à plat en mémoire lorsqu'il n'y a pas de cache
471 \******************************************************************************/
472 void rcn_flatnet( lofig_list *lofig )
473 {
474 losig_list *vss=NULL;
475 losig_list *vssni=NULL;
476 ptype_list *ptl;
477 losig_list *losig;
478 chain_list *chain;
479 locon_list *locon;
480 losig_list *sigint;
481 loins_list *loins;
482 lowire_list *wire;
483 loctc_list *ptctc;
484 chain_list *ctc;
485 rcx_list *rcx;
486 int n1, n2;
487
488 vss = rcx_getvss( lofig );
489 vssni = rcx_getvssni( lofig );
490
491 /* Il faut renuméroter tous les RC de la lofig avant d'y ajouter les éléments
492 RC des instances pour ne pas avoir de problèmes avec les CTC/
493 */
494
495 for( losig = lofig->LOSIG ; losig ; losig = losig->NEXT ) {
496
497 if( !losig->PRCN ) continue;
498
499 rcx = getrcx( losig );
500 if( !rcx ) continue;
501
502 freetable( losig );
503 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
504 rcn_changewirenodes( losig,
505 wire,
506 rcx_get_new_num_node( losig, wire->NODE1, RCX_LOFIG, NO ),
507 rcx_get_new_num_node( losig, wire->NODE2, RCX_LOFIG, NO )
508 );
509
510 for( ctc = losig->PRCN->PCTC ; ctc ; ctc = ctc->NEXT ) {
511
512 ptctc = (loctc_list*)ctc->DATA;
513
514 if( ptctc->SIG1 == losig )
515 n1 = rcx_get_new_num_node( losig, ptctc->NODE1, RCX_LOFIG, NO );
516 else
517 n1 = ptctc->NODE1;
518
519 if( ptctc->SIG2 == losig )
520 n2 = rcx_get_new_num_node( losig, ptctc->NODE2, RCX_LOFIG, NO );
521 else
522 n2 = ptctc->NODE2;
523
524 rcn_changectcnodes( ptctc, n1, n2 );
525 }
526 }
527
528 for( losig = lofig->LOSIG ; losig ; losig = losig->NEXT ) {
529
530 if( !losig->PRCN ) continue;
531
532 rcx = getrcx( losig );
533 if( !rcx ) continue;
534
535 ptl = getptype( losig->USER, LOFIGCHAIN );
536 if( ptl ) {
537 for( chain = (chain_list*)ptl->DATA ; chain ; chain = chain->NEXT ) {
538 locon = (locon_list*)chain->DATA;
539 if( !rcx_isvalidlocon( locon ) )
540 continue;
541 if( locon->TYPE == 'I' ) {
542 ptl = getptype( locon->USER, PTYPERCX );
543 if( ptl ) {
544 sigint = (losig_list*)ptl->DATA;
545 loins = (loins_list*)locon->ROOT;
546 rcx_mergercn( lofig, losig, loins, sigint, vss, vssni );
547 }
548 }
549 }
550 }
551 }
552
553 // Nettoyage des ctc
554
555 for( losig = lofig->LOSIG ; losig ; losig = losig->NEXT ) {
556 if( !losig->PRCN )
557 continue;
558 for( ctc = losig->PRCN->PCTC ; ctc ; ctc = ctc->NEXT ) {
559 ptctc = (loctc_list*)ctc->DATA;
560 if( getptype( ptctc->USER, RCX_COPIED ) )
561 ptctc->USER = delptype( ptctc->USER, RCX_COPIED );
562 }
563 ptl = getptype( losig->USER, LOFIGCHAIN );
564 if( ptl ) {
565 for( chain = (chain_list*)ptl->DATA ; chain ; chain = chain->NEXT ) {
566 locon = (locon_list*)chain->DATA;
567 if( !rcx_isvalidlocon( locon ) )
568 continue;
569 if( locon->TYPE == 'I' ) {
570 ptl = getptype( locon->USER, PTYPERCX );
571 if( ptl ) {
572 sigint = (losig_list*)ptl->DATA;
573 for( ctc = sigint->PRCN->PCTC ; ctc ; ctc = ctc->NEXT ) {
574 ptctc = (loctc_list*)ctc->DATA;
575 if( getptype( ptctc->USER, RCX_COPIED ) )
576 ptctc->USER = delptype( ptctc->USER, RCX_COPIED );
577 }
578 }
579 }
580 }
581 }
582 }
583 }
584
585 /******************************************************************************\
586 Drive les éléments RC d'un signal d'une lofig.
587 \******************************************************************************/
588 void rcx_dumpnet( rcxfile *file, losig_list *losig )
589 {
590 lowire_list *wire;
591 chain_list *scanchain;
592 loctc_list *loctc;
593 int node;
594 losig_list *sigagr;
595 int nodeagr;
596 rcx_list *rcxagr;
597 rcx_list *rcxint;
598
599 rcxint = getrcx( losig );
600 if( !GETFLAG( rcxint->FLAG, RCXNOWIRE ) ) {
601 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT ) {
602 rcx_drive_wire( file,
603 rcx_get_new_num_node( losig, wire->NODE1, RCX_LOFIG, YES ),
604 rcx_get_new_num_node( losig, wire->NODE2, RCX_LOFIG, YES ),
605 wire->RESI,
606 wire->CAPA
607 );
608 }
609 }
610
611 for( scanchain = losig->PRCN->PCTC ;
612 scanchain ;
613 scanchain = scanchain->NEXT )
614 {
615
616 loctc = (loctc_list*)scanchain->DATA;
617 node = rcn_ctcnode( loctc, losig );
618 sigagr = rcn_ctcothersig( loctc, losig );
619 nodeagr = rcn_ctcothernode( loctc, losig );
620
621 rcxagr = getrcx( sigagr );
622
623 if( !rcxagr && !rcx_isbellow( sigagr ) ) {
624 if( rcx_isnotinfluentagressor( losig, sigagr ) )
625 rcx_drive_ctcni_capa( file,
626 rcx_get_new_num_node( losig, node, RCX_LOFIG, YES ),
627 loctc->CAPA
628 );
629 else
630 rcx_drive_ground_capa( file,
631 rcx_get_new_num_node( losig, node, RCX_LOFIG, YES ),
632 loctc->CAPA
633 );
634 }
635 else
636 rcx_drive_ctc_capa( file,
637 rcx_get_new_num_node( losig, node, RCX_LOFIG, YES ),
638 loctc->CAPA,
639 rcx_getsigname( sigagr ),
640 rcx_get_new_num_node( sigagr, nodeagr, RCX_LOFIG, YES )
641 );
642 }
643 }
644
645 /******************************************************************************\
646 rcx_mergercn()
647 Réalise le merge d'un losig d'une instance sur un signal externe. Utilise les
648 BELLOW créés par rcx_dump_loins.
649 Les vrais capacités de couplage qui ont été copiées ont un ptype RCX_COPIED, il
650 ne faudra plus les copier.
651 \******************************************************************************/
652 void rcx_mergercn( lofig_list *lofig,
653 losig_list *sigext,
654 loins_list *scanloins,
655 losig_list *sigint,
656 losig_list *vss,
657 losig_list *vssni
658 )
659 {
660 losig_list *pseudovssins;
661 losig_list *pseudovssinsni;
662 lowire_list *wire;
663 chain_list *scanchain;
664 loctc_list *loctc;
665 int node;
666 int nodeagr;
667 losig_list *sigagr;
668 losig_list *sigagrext;
669 ptype_list *pt;
670 losig_list *sigbellow;
671 rcx_list *rcxext;
672
673 pseudovssins = getrcxpseudovss( scanloins->USER );
674 pseudovssinsni = rcx_loinsgetvssni( scanloins );
675
676 if( !sigint->PRCN ) return;
677
678 rcxext = getrcx( sigext );
679 for( wire = sigint->PRCN->PWIRE ; wire ; wire = wire->NEXT )
680 addlowire( sigext,
681 wire->FLAG,
682 wire->RESI,
683 wire->CAPA,
684 rcx_get_new_num_node( sigint, wire->NODE1, RCX_LOINS, NO ),
685 rcx_get_new_num_node( sigint, wire->NODE2, RCX_LOINS, NO )
686 );
687
688 for( scanchain = sigint->PRCN->PCTC ;
689 scanchain ;
690 scanchain = scanchain->NEXT )
691 {
692
693 loctc = (loctc_list*)scanchain->DATA;
694 node = rcn_ctcnode( loctc, sigint );
695 sigagr = rcn_ctcothersig( loctc, sigint );
696 nodeagr = rcn_ctcothernode( loctc, sigint );
697
698 if( sigagr == pseudovssins )
699 addloctc( sigext, rcx_get_new_num_node( sigint, node, RCX_LOINS, NO ),
700 vss, 0,
701 loctc->CAPA
702 );
703
704 if( sigagr == pseudovssinsni )
705 addloctc( sigext, rcx_get_new_num_node( sigint, node, RCX_LOINS, NO ),
706 vssni, 0,
707 loctc->CAPA
708 );
709
710 if( sigagr != pseudovssins &&
711 sigagr != pseudovssinsni &&
712 !getptype( loctc->USER, RCX_COPIED ) )
713 {
714
715 if( getptype( sigagr->USER, RCX_UNRESOLVEDSIG ) ) {
716 // L'agresseur n'a pas été lu, il correspond à un signal interne.
717 pt = getptype( sigagr->USER, RCX_COPIED );
718
719 if( !pt ) {
720 // ce cas n'arrive jamais. Il a été traité dans rcx_dump_loins()
721 rcx_error(27,sigagr, AVT_ERROR );
722 }
723 else {
724 sigbellow = (losig_list*)(pt->DATA);
725
726 addloctc( sigext, rcx_get_new_num_node( sigint, node, RCX_LOINS, NO ),
727 sigbellow, 0,
728 loctc->CAPA
729 );
730 }
731 }
732 else {
733 pt = getptype( loctc->USER, RCX_COPIED );
734 if( !pt ) {
735 loctc->USER = addptype( loctc->USER, RCX_COPIED, NULL );
736 /*
737 sigagrext = ((locon_list*)
738 (getptype( sigagr->USER, RCX_LOCONINS )->DATA ))->SIG;
739 */
740 sigagrext = rcx_get_out_ins_sig( sigagr );
741 if( getrcx( sigagrext ) ) {
742 if( sigext != sigagrext ) {
743 addloctc(
744 sigext,
745 rcx_get_new_num_node( sigint, node, RCX_LOINS, NO ),
746 sigagrext,
747 rcx_get_new_num_node( sigagr, nodeagr, RCX_LOINS, NO ),
748 loctc->CAPA
749 );
750 }
751 }
752 else {
753 // Cas où l'agresseur est un signal ordinaire qui est connecté en
754 // externe à vdd ou vss.
755 if( tlc_islosigalim( sigagrext ) )
756 addloctc( sigext,
757 rcx_get_new_num_node( sigint, node, RCX_LOINS, NO ),
758 vss,
759 0,
760 loctc->CAPA
761 );
762 else
763 addloctc( sigext,
764 rcx_get_new_num_node( sigint, node, RCX_LOINS, NO ),
765 vssni,
766 0,
767 loctc->CAPA
768 );
769
770 }
771 }
772 }
773 }
774 }
775
776 lofig=NULL; //unused parameter
777 }
778
779 /******************************************************************************\
780 rcx_trsfloinscapa()
781 Dans le cas où les résistance ne sont pas prise en compte, transfère la
782 capacité des connecteurs internes vers le connecteur externe.
783 sigint est un losig dans une instance.
784 \******************************************************************************/
785 void rcx_trsfloinscapa( lofig_list *lofig,
786 loins_list *loins,
787 losig_list *sigint )
788 {
789 rcx_list *rcxint;
790 locon_list *loconext;
791 locon_list *loconint;
792 chain_list *chain;
793
794 loconext = (locon_list*)( getptype( sigint->USER, RCX_LOCONINS )->DATA );
795 rcxint = getrcx( sigint );
796
797 for( chain = rcxint->RCXINTERNAL ; chain ; chain = chain->NEXT ) {
798 loconint = (locon_list*)(chain->DATA);
799 rcx_add_capa_from_instance_to_figure( loins, lofig, loconint, loconext );
800 }
801
802 if( rcxint->RCXEXTERNAL ) {
803 chain_list *cl;
804 for (cl=rcxint->RCXEXTERNAL; cl!=NULL; cl=cl->NEXT)
805 rcx_add_capa_from_instance_to_figure( loins,
806 lofig,
807 (locon_list *)cl->DATA,
808 loconext
809 );
810 }
811 }
812
813 /******************************************************************************\
814 rcx_buildrcxnowire();
815 Conserve le nombre minimum de locon sur une vue RCX si celle-ci est type nowire.
816 Stratégie :
817 Si le signal est externe, on ne conserve que le connecteur externe.
818 Si le signal est interne, on ne conserve que le connecteur qui a le meme nom que
819 le signal.
820 Si aucun connecteur ne correspond, on prend un connecteur et on lui colle le
821 nom du signal.
822 \******************************************************************************/
823 void rcx_buildrcxnowire( lofig_list *lofig, losig_list *losig )
824 {
825 rcx_list *rcx;
826 chain_list *chain;
827 RCXFLOAT c;
828 char *name;
829 locon_list *locon;
830 locon_list *goodlocon;
831
832 rcx = getrcx( losig );
833
834 if( !rcx->RCXEXTERNAL && !rcx->RCXINTERNAL )
835 return;
836
837 // On cherche le locon qui va rester.
838
839 goodlocon = NULL;
840 if( rcx->RCXEXTERNAL ) {
841 goodlocon = rcx->RCXEXTERNAL->DATA;
842 name = getloconrcxname( goodlocon );
843 }
844 if( !goodlocon ) {
845 name = rcx_getsigname( losig );
846 for( chain = rcx->RCXINTERNAL ; chain ; chain = chain->NEXT ) {
847 locon = (locon_list*)(chain->DATA);
848 if( getloconrcxname( locon ) == name ) {
849 goodlocon = locon;
850 break;
851 }
852 }
853 }
854 if( !goodlocon ) {
855 for( chain = rcx->RCXINTERNAL ; chain ; chain = chain->NEXT ) {
856 locon = (locon_list*)(chain->DATA);
857 if( locon->ROOT ) {
858 goodlocon = locon;
859 break;
860 }
861 }
862 }
863 if( !goodlocon )
864 goodlocon = (locon_list*)(rcx->RCXINTERNAL->DATA);
865
866 // On efface les autres.
867
868 c=0.0;
869 for( chain = rcx->RCXINTERNAL ; chain ; chain = chain->NEXT ) {
870 locon = (locon_list*)(chain->DATA);
871 if( locon == goodlocon )
872 continue;
873 rcx_add_capa_locon( lofig, goodlocon, locon );
874 rcx_freeloconcapa( lofig, NULL, locon );
875 if( !locon->ROOT ) {
876 // Libère les locons alloués par RCX
877 freenum( locon->PNODE ); locon->PNODE = NULL;
878 locon->SIG = NULL;
879 freercxlocon( locon );
880 }
881 }
882 freechain( rcx->RCXINTERNAL ); rcx->RCXINTERNAL = NULL;
883 if( !rcx->RCXEXTERNAL )
884 rcx->RCXINTERNAL = addchain( NULL, goodlocon );
885
886 if( getloconrcxname( goodlocon ) != name )
887 addloconrcxname( goodlocon, name );
888
889 }
890
891 /******************************************************************************\
892 buildrcx()
893 Met les vues RCX à plat. Fonctionne avec ou sans cache.
894 Dans la boucle des losigs, les réseaux RC ont leurs index de noeud d'origine.
895 Par contre, les connecteurs sont renumérotés au fur et à mesure qu'on les
896 rencontre.
897 \******************************************************************************/
898
899 void buildrcx( currentfig )
900 lofig_list *currentfig;
901 {
902 losig_list *sigext;
903 losig_list *sigint;
904 rcx_list *rcxext;
905 rcx_list *rcxint;
906 loins_list *scanloins;
907 locon_list *scanlocon;
908 ptype_list *pt;
909 char *name;
910 chain_list *chain;
911 chain_list *chainlosig;
912 rcxfile *file;
913 char fileacces;
914 MBK_OFFSET_MAX offset;
915 chain_list *headlosig;
916 char iscache;
917 char buffer[1024];
918 lowire_list *lw, *nlw;
919 int origcache;
920
921 if( (origcache=(rcn_getlofigcache( currentfig ))!=NULL) || V_BOOL_TAB[__TAS_ALWAYS_USE_CACHE].VALUE)
922 iscache = 1;
923 else
924 iscache = 0;
925
926 file = rcx_init_driver( currentfig, iscache );
927
928 if( iscache )
929 fileacces = mbk_getfileacces( file->FD );
930
931 headlosig = rcx_driver_sort_losig( currentfig );
932 rcx_build_new_num_node( currentfig );
933
934 for( chainlosig = headlosig ; chainlosig ; chainlosig = chainlosig->NEXT )
935 {
936 if( chainlosig->DATA == NULL ) {
937 rcx_end_external( file );
938 continue;
939 }
940
941 sigext = (losig_list*)chainlosig->DATA;
942 rcxext = getrcx( sigext );
943 if( !rcxext )
944 continue;
945
946 if( rcx_has_rc_timings( sigext ) )
947 SETFLAG( rcxext->FLAG, RCXIGNORE );
948
949 if( rcx_state( rcxext, RCX_STATE_LOFIG ) == RCX_STATE_EMPTY )
950 set_ext_rcn( sigext );
951
952 rcn_lock_signal( currentfig, sigext );
953
954 if( !rcx_iscrosstalk( currentfig, sigext, RCX_TEST_ONE ))
955 SETFLAG( rcxext->FLAG, RCXNOCTC );
956
957 if( setrcxmodel( currentfig, sigext, RCX_BEST ) == RCX_NORCTC &&
958 V_INT_TAB[__ELP_CAPA_LEVEL].VALUE == ELP_CAPA_LEVEL0 )
959 {
960 rcn_unlock_signal( currentfig, sigext );
961 continue;
962 }
963
964 rcx_repair_pnode( sigext );
965
966 rcx_drive_signal_header( file, sigext, rcxext );
967 if( iscache ) {
968 if( !mbkftell( file->FD, &offset ))
969 avt_errmsg( TRC_ERRMSG, "034", AVT_FATAL, file->FILENAME );
970
971 mbk_losig_setfilepos( currentfig,
972 sigext,
973 file->FD,
974 &offset,
975 RCX_FLAGTAB,
976 RCX_FLAGHEAP
977 );
978 }
979 rcx_drive_begin_net( file );
980
981 rcx_dumpnet( file, sigext );
982
983 for( chain = (chain_list*)getptype( sigext->USER, LOFIGCHAIN )->DATA ;
984 chain ;
985 chain = chain->NEXT
986 )
987 {
988 scanlocon = (locon_list*)chain->DATA;
989 if( !rcx_isvalidlocon( scanlocon ) )
990 continue;
991
992 {
993
994 if( scanlocon->TYPE == 'I' ) {
995 scanloins = (loins_list*)scanlocon->ROOT;
996 if( (pt = getptype(scanlocon->USER,PTYPERCX) ) ) {
997 sigint = (losig_list*)(pt->DATA);
998 rcxint = getrcx( sigint );
999 if (countchain(rcxint->RCXEXTERNAL)>1)
1000 avt_errmsg( TRC_ERRMSG, "053", AVT_FATAL, scanloins->FIGNAME);
1001 }
1002 else {
1003 sigint = NULL;
1004 rcxint = NULL;
1005 }
1006
1007 if( rcx_state( rcxint, RCX_STATE_LOINS ) == RCX_STATE_NORCX ) {
1008 merge_ext( file, sigext, scanlocon, iscache, YES );
1009 rcx_trsfnodelocon( scanlocon, RCX_LOFIG );
1010 }
1011 else {
1012 rcx_dump_loins( file, currentfig, scanloins, sigint );
1013 rcx_trsfdriver( currentfig, sigext, rcxext, sigint, rcxint );
1014 name = concatname( rcx_getinsname( scanloins ),
1015 rcx_getsigname( sigint )
1016 );
1017 rcx_addorigin( currentfig, sigext, name );
1018 if( !GETFLAG( rcxext->FLAG, RCXNOWIRE ) &&
1019 !GETFLAG( rcxint->FLAG, RCXNOWIRE ) )
1020 rcx_copyrcx( currentfig, sigext, scanloins, sigint );
1021 else {
1022 rcx_trsfloinscapa( currentfig, scanloins, sigint );
1023 merge_ext( file, sigext, scanlocon, iscache, NO );
1024 rcx_trsfnodelocon( scanlocon, RCX_LOFIG );
1025 }
1026 rcn_addcapa( sigext, rcn_getnetcapa( sigint ) );
1027 }
1028 }
1029
1030 if( scanlocon->TYPE == 'T' ) {
1031 merge_ext( file, sigext, scanlocon, iscache, YES );
1032 rcx_trsfnodelocon( scanlocon, RCX_LOFIG );
1033 }
1034
1035 if( scanlocon->TYPE == 'E' ) {
1036 rcx_trsfnodelocon( scanlocon, RCX_LOFIG );
1037 }
1038 }
1039 }
1040
1041 if( GETFLAG( rcxext->FLAG, RCXNOWIRE ) ) {
1042 rcx_buildrcxnowire( currentfig, sigext );
1043 }
1044
1045 rcx_drive_end_net( file );
1046 rcxprintlocon( file, rcxext );
1047 rcxprintorigin( file, sigext );
1048 rcx_drive_signal_end( file, sigext );
1049
1050 rcn_unlock_signal( currentfig, sigext );
1051 if( rcn_islock_signal( currentfig, sigext ) == YES )
1052 avt_errmsg( TRC_ERRMSG, "041", AVT_WARNING, rcx_getsigname( sigext ) );
1053 rcn_flush_signal( currentfig, sigext );
1054 }
1055
1056 freechain( headlosig );
1057
1058 if( !iscache )
1059 rcn_flatnet( currentfig );
1060
1061 rcx_clear_new_num_node( currentfig );
1062
1063 rcx_drive_end( file, currentfig );
1064
1065 // Vire le contenu des instances
1066 for( scanloins = currentfig->LOINS ; scanloins ; scanloins = scanloins->NEXT )
1067 rcx_cleanloins( scanloins );
1068
1069 // Création des tables de hash
1070 for( sigext = currentfig->LOSIG ; sigext ; sigext = sigext->NEXT )
1071 {
1072 chain_list *cl;
1073 if( tlc_islosigalim( sigext ) )
1074 continue;
1075
1076 /* Modif Grégoire le 19 Mai 2003. Grosse bidouille immonde.
1077 TAS récupère les vecteurs sous la forme toto[23] car c'est comme ca que
1078 Yagle crée les noms. Pb : MBK/RCX n'est pas informé de ce nommage. On le
1079 fait donc maintenant ici.
1080 */
1081 strcpy( buffer, rcx_getsigname( sigext ) );
1082 rcx_vect( buffer );
1083 rcx_addhtrcxsigbyname( NULL, currentfig, sigext, namealloc( buffer ) );
1084
1085 rcxext = getrcx( sigext );
1086 if( !rcxext ) continue;
1087
1088 for (chain=rcxext->RCXEXTERNAL; chain!=NULL; chain=chain->NEXT)
1089 rcx_addhtrcxcon( NULL, currentfig, (locon_list *)chain->DATA );
1090 for( chain = rcxext->RCXINTERNAL ; chain ; chain = chain->NEXT )
1091 rcx_addhtrcxcon( NULL, currentfig, (locon_list*)chain->DATA );
1092 }
1093
1094 for( scanloins = currentfig->LOINS ; scanloins ; scanloins = scanloins->NEXT )
1095 rcx_addhtrcxmod( currentfig,
1096 rcx_getinsname( scanloins ),
1097 scanloins->FIGNAME
1098 );
1099
1100 if( iscache ) {
1101 // Elimination de l'ancien cache
1102 rcn_disable_cache( currentfig );
1103 if (!origcache)
1104 {
1105 for( sigext = currentfig->LOSIG ; sigext ; sigext = sigext->NEXT )
1106 {
1107 if (sigext->PRCN)
1108 {
1109 for (lw=sigext->PRCN->PWIRE; lw!=NULL; lw=nlw)
1110 {
1111 nlw=lw->NEXT;
1112 freelowire( lw );
1113 }
1114 sigext->PRCN->PWIRE=NULL;
1115 while( sigext->PRCN->PCTC )
1116 delloctc( (loctc_list*)sigext->PRCN->PCTC->DATA );
1117 sigext->PRCN->PCTC=NULL;
1118 }
1119 }
1120 }
1121 // Met en route le nouveau cache
1122 rcx_reload( currentfig, fileacces );
1123 }
1124
1125 }
1126
1127 void rcx_exit( code )
1128 int code;
1129 {
1130 fflush( stdout );
1131 fprintf( stderr,
1132 "\n\n*** RCX : abnormal terminaison. Exit code %d ***\n\n",
1133 code
1134 );
1135 avt_log(LOGTRC,2, "Exit code %d\n", code );
1136 EXIT( 1 );
1137 }
1138
1139 /******************************************************************************\
1140 Mémorise et retrouve les agresseurs d'un signal.
1141 insname est le nom d'instance de la lofig.
1142 rcx_getagrlistfast() renvoie EMPTYHY si on a jamais traité ce signal dans
1143 l'instance insname.
1144 \******************************************************************************/
1145 chain_list* rcx_getagrlistfast( lofig_list *lofig,
1146 char *insname,
1147 losig_list *victime
1148 )
1149 {
1150 ptype_list *ptl;
1151 ht *htins;
1152 ht *htsig;
1153 chain_list *headagr;
1154 chain_list *scan;
1155 rcxparam *param;
1156 chain_list *chain;
1157 losig_list *losig;
1158
1159 // Récupère la table des instances de cette lofig.
1160 // Il s'agit des différents noms sous laquelle est instanciée cette lofig. Il
1161 // ne s'agit pas d'un table pour accéder rapidement à un LOINS de cette lofig.
1162 ptl = getptype( lofig->USER, RCX_HTAGR );
1163 if( !ptl ) return (chain_list*)EMPTYHT;
1164 htins=(ht*)ptl->DATA;
1165
1166 // Récupère la table des signaux.
1167 htsig = (ht*)gethtitem( htins, insname );
1168 if( htsig == (ht*)EMPTYHT || htsig == (ht*)DELETEHT )
1169 return (chain_list*)EMPTYHT;
1170
1171 // Récupère la liste des agresseurs.
1172 headagr = (chain_list*)gethtitem( htsig, victime );
1173 if( headagr == (chain_list*)EMPTYHT || headagr == (chain_list*)DELETEHT )
1174 return (chain_list*)EMPTYHT;
1175
1176 // Il ne reste plus qu'a placer les REALAGRESSOR.
1177 for( scan = headagr ; scan ; scan = scan->NEXT ) {
1178 param = (rcxparam*)scan->DATA;
1179 for( chain = param->SIGLOCAL ; chain ; chain = chain->NEXT ) {
1180 losig = (losig_list*)chain->DATA;
1181 losig->USER = addptype( losig->USER, RCX_REALAGRESSOR, param );
1182 }
1183 if( !getptype( param->SIGNAL->USER, RCX_REALAGRESSOR ) )
1184 param->SIGNAL->USER = addptype( param->SIGNAL->USER,
1185 RCX_REALAGRESSOR,
1186 param
1187 );
1188 }
1189
1190 return headagr;
1191 }
1192
1193 void rcx_setagrlistfast( lofig_list *lofig,
1194 char *insname,
1195 losig_list *victime,
1196 chain_list *headagr
1197 )
1198 {
1199 ptype_list *ptl;
1200 ht *htins;
1201 ht *htsig;
1202 #ifdef RCX_CHECK
1203 chain_list *oldagr;
1204 #endif
1205
1206 // Récupère la table des instances de cette lofig.
1207 // Il s'agit des différents noms sous laquelle est instanciée cette lofig. Il
1208 // ne s'agit pas d'un table pour accéder rapidement à un LOINS de cette lofig.
1209 ptl = getptype( lofig->USER, RCX_HTAGR );
1210 if( !ptl ) {
1211 lofig->USER = addptype( lofig->USER, RCX_HTAGR, addht(1) );
1212 ptl = lofig->USER;
1213 }
1214 htins=(ht*)ptl->DATA;
1215
1216 // Récupère la table des signaux.
1217 htsig=(ht*)gethtitem( htins, insname );
1218 if( htsig == (ht*)EMPTYHT || htsig == (ht*)DELETEHT ) {
1219 htsig = addht(10);
1220 addhtitem( htins, insname, (long)htsig );
1221 }
1222
1223
1224 // Récupère la liste des agresseurs.
1225 #ifdef RCX_CHECK
1226 oldagr = (chain_list*)gethtitem( htsig, victime );
1227 if( oldagr != (chain_list*)EMPTYHT && oldagr != (chain_list*)DELETEHT )
1228 rcx_error( 30, NULL, AVT_ERROR );
1229 #endif
1230 addhtitem( htsig, victime, (long)headagr );
1231 }
1232
1233 /******************************************************************************\
1234
1235 rcx_getagrlist()
1236 - Récupère une liste de rcxparam correspondant aux agresseurs possédant une vue
1237 rcx et n'étant pas marqué NI par la fonction rcx_checkcrosstalk().
1238 - Place dans chaque agresseur local un ptype RCX_REALAGRESSOR vers le rcxparam.
1239
1240 \******************************************************************************/
1241
1242 chain_list* rcx_getagrlist( lofig_list *lofig,
1243 losig_list *victime,
1244 char *insname,
1245 chain_list *chainfig
1246 )
1247 {
1248 rcx_list *rcx;
1249 chain_list *scanctc;
1250 loctc_list *ctc;
1251 losig_list *agresseur;
1252 losig_list *real;
1253 chain_list *headagr;
1254 chain_list *scanagr;
1255 rcxparam *param;
1256 char *defins;
1257 lofig_list *deffig;
1258 rcx_list *rcxagr;
1259 ptype_list *ptl;
1260
1261 if( RCX_FASTMODE ) {
1262 headagr = rcx_getagrlistfast( lofig, insname, victime );
1263 if( headagr != (chain_list*)EMPTYHT )
1264 return headagr;
1265 }
1266
1267 rcx = getrcx( victime );
1268 #ifdef RCX_CHECK
1269 if( rcx_state( rcx, RCX_STATE_LOFIG ) != RCX_STATE_TYPED )
1270 return NULL;
1271 if( !GETFLAG( rcx->FLAG, MODELRCN ) )
1272 rcx_error(31,NULL, AVT_ERROR);
1273
1274 #endif
1275
1276 headagr = NULL;
1277
1278 if( ! GETFLAG( rcx->FLAG, RCXCTCDONE ) ) {
1279 if( !rcx_iscrosstalk( lofig, victime, RCX_TEST_LIMIT ))
1280 SETFLAG( rcx->FLAG, RCXNOCTC );
1281 SETFLAG( rcx->FLAG, RCXCTCDONE );
1282 }
1283
1284 if( ! GETFLAG( rcx->FLAG, RCXNOCTC ) )
1285 {
1286 rcn_lock_signal( lofig, victime );
1287 rcx_checkcrosstalk( victime );
1288
1289 for( scanctc = victime->PRCN->PCTC ; scanctc ; scanctc = scanctc->NEXT ) {
1290
1291 ctc = (loctc_list*)scanctc->DATA;
1292 agresseur = rcn_ctcothersig( ctc, victime );
1293
1294 if( tlc_islosigalim( agresseur ) )
1295 continue;
1296
1297 if( rcx_isnotinfluentagressor( victime, agresseur ) )
1298 continue;
1299
1300 param = NULL;
1301 ptl = getptype( agresseur->USER, RCX_REALAGRESSOR );
1302 if( ptl )
1303 param = (rcxparam*)ptl->DATA;
1304 else {
1305 real = rcx_gethierlosig( agresseur,
1306 insname,
1307 chainfig,
1308 &defins,
1309 &deffig
1310 );
1311 if( real ) {
1312 if( real != agresseur )
1313 ptl = getptype( real->USER, RCX_REALAGRESSOR );
1314
1315 if( !ptl ) {
1316 rcxagr = getrcx( real );
1317 if( rcx_state( rcxagr, RCX_STATE_LOFIG ) == RCX_STATE_TYPED ) {
1318
1319 param = rcx_allocrcxparam();
1320 param->LOFIG = deffig;
1321 param->INSNAME = defins;
1322 param->SIGNAL = real;
1323 param->SIGLOCAL = addchain( NULL, agresseur );
1324
1325 agresseur->USER = addptype( agresseur->USER,
1326 RCX_REALAGRESSOR,
1327 param
1328 );
1329 if( real != agresseur )
1330 real->USER = addptype( real->USER,
1331 RCX_REALAGRESSOR,
1332 param
1333 );
1334 headagr = addchain( headagr, param );
1335
1336 }
1337 }
1338 else {
1339 param = (rcxparam*)ptl->DATA;
1340 param->SIGLOCAL = addchain( param->SIGLOCAL, agresseur );
1341 agresseur->USER = addptype( agresseur->USER,
1342 RCX_REALAGRESSOR,
1343 param
1344 );
1345 }
1346 }
1347 }
1348
1349 if( param )
1350 param->CC = param->CC + ctc->CAPA ;
1351 }
1352 rcn_unlock_signal( lofig, victime );
1353 }
1354
1355 for( scanagr = headagr ; scanagr ; scanagr = scanagr->NEXT ) {
1356 param = (rcxparam*)(scanagr->DATA);
1357 param->CCA = -1.0 ;
1358 }
1359
1360 if( RCX_FASTMODE )
1361 rcx_setagrlistfast( lofig, insname, victime, headagr );
1362
1363 return( headagr );
1364 }
1365
1366 rcxparam* rcx_allocrcxparam( void )
1367 {
1368 rcxparam *param;
1369 param = (rcxparam*)mbkalloc( sizeof( rcxparam ) );
1370 param->LOFIG = NULL;
1371 param->INSNAME = NULL;
1372 param->SIGNAL = NULL;
1373 param->FMINUP = 0.0;
1374 param->F0UP = 0.0;
1375 param->FMINDW = 0.0;
1376 param->F0DW = 0.0;
1377 param->CC = 0.0;
1378 param->CCA = 0.0;
1379 param->ACTIF = 0;
1380 param->USER = NULL;
1381 param->SIGLOCAL = NULL;
1382 return( param );
1383 }
1384
1385 void rcx_freeagrlist( lofig_list *lofig,
1386 losig_list *victime,
1387 chain_list *agresseurs
1388 )
1389 {
1390 chain_list *scan;
1391 chain_list *siglocal;
1392 rcxparam *param;
1393 losig_list *losig;
1394
1395 for( scan = agresseurs ; scan ; scan=scan->NEXT ) {
1396
1397 param = ((rcxparam*)(scan->DATA));
1398
1399 #ifdef RCX_CHECK
1400 if( param->USER ) {
1401 rcx_error(20,NULL, AVT_WARNING);
1402 }
1403 #endif
1404 for( siglocal = param->SIGLOCAL ; siglocal ; siglocal = siglocal->NEXT ) {
1405 losig = (losig_list*)siglocal->DATA;
1406 #ifdef RCX_CHECK
1407 if( !getptype( losig->USER, RCX_REALAGRESSOR ) )
1408 rcx_error(32,NULL, AVT_WARNING);
1409 #endif
1410 losig->USER = delptype( losig->USER, RCX_REALAGRESSOR );
1411 }
1412 if( getptype( param->SIGNAL->USER, RCX_REALAGRESSOR ) )
1413 param->SIGNAL->USER = delptype( param->SIGNAL->USER, RCX_REALAGRESSOR );
1414
1415 if( !RCX_FASTMODE ) {
1416 freechain( param->SIGLOCAL );
1417 mbkfree( param );
1418 }
1419 }
1420
1421 if( !RCX_FASTMODE )
1422 freechain( agresseurs );
1423
1424 lofig=NULL;
1425 victime=NULL;
1426 }
1427
1428 /******************************************************************************\
1429 Renvoie le front réel sans la contribution du signal.
1430 cc=0 -> FCC
1431 cc=cca -> F0
1432
1433 arguments :
1434
1435 cc : somme des capacité de couplage entre la paire de signaux.
1436 cca : somme des capacité de couplage sur le signal.
1437 fcc : front calculé avec les agresseurs actifs
1438 f0 : front sans agression.
1439
1440 Si cca vaut 0, le fcc est renvoyé.
1441 \******************************************************************************/
1442
1443 RCXFLOAT rcx_realslope( RCXFLOAT cc, RCXFLOAT cca, RCXFLOAT fcc, RCXFLOAT f0 )
1444 {
1445 RCXFLOAT f;
1446
1447 if( cca > 0.0 )
1448 f = ( f0 - fcc ) * ( cc - cca ) / cca + f0 ;
1449 else
1450 f = fcc ;
1451
1452 return f;
1453 }
1454
1455 /******************************************************************************\
1456 Calcule l'effet miller entre 2 fronts.
1457 type = RCX_SAME | RCX_OPPOSITE
1458 model = RCX_MILLER2C ( capa entre 0C 2C ) | RCX_MILLER4C ( capa entre -C et 4C )
1459 \******************************************************************************/
1460
1461 RCXFLOAT rcx_getmiller( RCXFLOAT fvic, RCXFLOAT fagr, char type, char model )
1462 {
1463 RCXFLOAT m=1.0;
1464
1465 if( type == RCX_SAME ) {
1466 if( model == RCX_MILLER2C ) {
1467 if( fvic < fagr )
1468 m = (fagr-fvic)/fagr;
1469 else
1470 m = 0.0;
1471 }
1472 else {
1473 if( fvic < 2.0 * fagr )
1474 m = (fagr-fvic)/fagr;
1475 else
1476 m = -1.0;
1477 }
1478 }
1479
1480 if( type == RCX_OPPOSITE ) {
1481 if( model == RCX_MILLER2C ) {
1482 if( fvic < fagr )
1483 m = (fvic+fagr)/fagr;
1484 else
1485 m = 2.0;
1486 }
1487 else {
1488 if( fvic < 2.0 * fagr )
1489 m = (fvic+fagr)/fagr;
1490 else
1491 m = 3.0;
1492 }
1493 }
1494
1495 return m;
1496 }
1497
1498 /******************************************************************************\
1499 Renvoie la valeur d'une capacité prenant en compte l'effet Miller. Les fronts
1500 sont corrigés pour ne pas être pris de façon trop pessimiste.
1501 type : RCX_MIN | RCX_MAX.
1502 \******************************************************************************/
1503
1504 RCXFLOAT rcx_capamiller( losig_list *victime,
1505 loctc_list *loctc,
1506 rcx_slope *slope,
1507 char type
1508 )
1509 {
1510 RCXFLOAT cc;
1511 losig_list *sigagr;
1512 ptype_list *ptl;
1513 rcxparam *param;
1514 RCXFLOAT famin;
1515 RCXFLOAT fvmax;
1516 RCXFLOAT m;
1517
1518 cc = loctc->CAPA ;
1519
1520 if( rcx_crosstalkactive( RCX_QUERY ) == RCX_NOCROSSTALK )
1521 return cc;
1522
1523 sigagr = (loctc->SIG1 == victime ? loctc->SIG2 : loctc->SIG1 );
1524
1525 ptl = getptype( sigagr->USER, RCX_REALAGRESSOR );
1526
1527 if( ptl ) {
1528
1529 param = (rcxparam*)ptl->DATA;
1530
1531 if( type == RCX_MIN && (param->ACTIF & RCX_AGRBEST) == RCX_AGRBEST ) {
1532
1533 switch( RCX_CTK_SLOPE_MILLER ) {
1534
1535 case RCX_SLOPE_NOMINAL :
1536
1537 fvmax = slope->F0MAX ;
1538 if( slope->SENS == TRC_SLOPE_UP )
1539 famin = param->F0UP;
1540 else
1541 famin = param->F0DW;
1542 break;
1543
1544 case RCX_SLOPE_CTK :
1545
1546 fvmax = slope->FCCMAX ;
1547 if( slope->SENS == TRC_SLOPE_UP )
1548 famin = param->FMINUP;
1549 else
1550 famin = param->FMINDW;
1551 break;
1552
1553 default :
1554 rcx_error( 33, victime, AVT_FATAL );
1555 }
1556
1557 switch( RCX_CTK_MODEL ) {
1558
1559 case RCX_MILLER_0C2C :
1560 m=0.0 ;
1561 break;
1562
1563 case RCX_MILLER_NC3C :
1564 m = rcx_getmiller( fvmax, famin, RCX_SAME, RCX_MILLER4C );
1565 break;
1566
1567 case RCX_MILLER_NOMINAL :
1568 m = rcx_getmiller( fvmax, famin, RCX_SAME, RCX_MILLER2C );
1569 break;
1570
1571 default :
1572 rcx_error( 34, victime, AVT_FATAL );
1573 }
1574
1575 cc = loctc->CAPA * m ;
1576 }
1577
1578 if( type == RCX_MAX && (param->ACTIF & RCX_AGRWORST) == RCX_AGRWORST ) {
1579
1580 switch( RCX_CTK_SLOPE_MILLER ) {
1581
1582 case RCX_SLOPE_NOMINAL :
1583
1584 fvmax = slope->F0MAX ;
1585 if( slope->SENS == TRC_SLOPE_UP )
1586 famin = param->F0DW;
1587 else
1588 famin = param->F0UP;
1589
1590 break;
1591
1592 case RCX_SLOPE_CTK :
1593
1594 fvmax = slope->FCCMAX ;
1595 if( slope->SENS == TRC_SLOPE_UP )
1596 famin = param->FMINDW;
1597 else
1598 famin = param->FMINUP;
1599
1600 break;
1601
1602 default :
1603 rcx_error(35,victime, AVT_FATAL);
1604 }
1605
1606 switch( RCX_CTK_MODEL ) {
1607
1608 case RCX_MILLER_0C2C :
1609 m=2.0 ;
1610 break;
1611
1612 case RCX_MILLER_NC3C :
1613 m = rcx_getmiller( fvmax, famin, RCX_OPPOSITE, RCX_MILLER4C );
1614 break;
1615
1616 case RCX_MILLER_NOMINAL :
1617 m = rcx_getmiller( fvmax, famin, RCX_OPPOSITE, RCX_MILLER2C );
1618 break;
1619
1620 default :
1621 rcx_error( 13, victime, AVT_FATAL );
1622 }
1623
1624 cc = loctc->CAPA * m ;
1625 }
1626
1627 }
1628
1629 else {
1630
1631 if( rcx_isnotinfluentagressor( victime, sigagr ) ) {
1632 switch( type ) {
1633 case RCX_MIN:
1634 cc = 0.0;
1635 break;
1636 case RCX_MAX:
1637 cc = 2.0 * loctc->CAPA;
1638 break;
1639 }
1640 }
1641 }
1642
1643 return( cc );
1644 }
1645
1646 /******************************************************************************\
1647 Flags entre deux signaux couplés.
1648 La fonction rcx_getflagcoupled() renvoie seulement les bits sélectionnés si flag
1649 est différent de 0, et la totalité des bits si flag vaut 0.
1650 \******************************************************************************/
1651
1652 void rcx_setflagcoupled( losig_list *victime, losig_list *agresseur, long flag )
1653 {
1654 long f;
1655
1656 f = rcn_getcoupledinformation( victime, agresseur, RCXLOSIGFLAG );
1657 rcn_setcoupledinformation( victime, agresseur, f|flag, RCXLOSIGFLAG );
1658 }
1659
1660 int rcx_getflagcoupled( losig_list *victime, losig_list *agresseur, long flag )
1661 {
1662 long f;
1663
1664 f = rcn_getcoupledinformation( victime, agresseur, RCXLOSIGFLAG );
1665 if( flag == 0 )
1666 return f;
1667 return f & flag;
1668 }
1669
1670 void rcx_clearflagcoupled( losig_list *victime,
1671 losig_list *agresseur,
1672 long flag
1673 )
1674 {
1675 long f;
1676 f = rcn_getcoupledinformation( victime, agresseur, RCXLOSIGFLAG );
1677 rcn_setcoupledinformation( victime, agresseur, f & ~flag, RCXLOSIGFLAG );
1678 }
1679
1680 void rcx_freeflagcoupled( losig_list *victime )
1681 {
1682 rcn_freecoupledinformation( victime, RCXLOSIGFLAG );
1683 }
1684
1685 /******************************************************************************\
1686 Impose que l'agresseur est à considérer comme non influent, c'est à dire qu'on
1687 le considère toujours actif pour ne pas l'avoir dans le stboverlapdev.
1688 \******************************************************************************/
1689
1690 int rcx_isnotinfluentagressor( losig_list *victime, losig_list *agresseur )
1691 {
1692 if( rcx_getflagcoupled( victime, agresseur, RCX_NI_LOSIG )== RCX_NI_LOSIG )
1693 return 1;
1694 if( getptype( agresseur->USER, RCX_VSSNI ) )
1695 return 1;
1696 return 0;
1697 }
1698
1699 void rcx_setnotinfluentagressor( losig_list *victime, losig_list *agresseur )
1700 {
1701 rcx_list *rcx;
1702
1703 rcx = getrcx( victime );
1704 if( !rcx || GETFLAG( rcx->FLAG, RCXNOCTC ) ) return;
1705
1706 rcx_setflagcoupled( victime, agresseur, RCX_NI_LOSIG );
1707 }
1708
1709 void rcx_clearnotinfluentagressor( losig_list *victime, losig_list *agresseur )
1710 {
1711 rcx_clearflagcoupled( victime, agresseur, RCX_NI_LOSIG );
1712 }
1713
1714 int rcx_iscrosstalkcapa( loctc_list *loctc, losig_list *losig )
1715 {
1716 rcx_list *rcx;
1717 losig_list *sigagr;
1718
1719 rcx = getrcx( losig );
1720 if( !rcx )
1721 return 1;
1722
1723 if( GETFLAG( rcx->FLAG, RCXNOCTC ) )
1724 // On considère que toutes les CTC sont des capacités à la masse.
1725 return 0;
1726
1727 sigagr = rcn_ctcothersig( loctc, losig );
1728
1729 if( getrcx( sigagr ) ) {
1730 return 1;
1731 }
1732
1733 if( rcx_isnotinfluentagressor( losig, sigagr ) ) {
1734 // Capa de couplage non significative, mais capa de couplage quand même...
1735 return 1;
1736 }
1737
1738 if( rcx_isbellow( sigagr ) ) {
1739 return 1;
1740 }
1741
1742 return 0;
1743 }
1744
1745 int rcx_crosstalkactive( int model )
1746 {
1747 if( model != RCX_QUERY )
1748 RCX_CROSSTALK = model;
1749 return RCX_CROSSTALK;
1750 }
1751
1752 void rcx_freewire( losig_list *losig )
1753 {
1754 rcx_list *rcx;
1755 rcx = getrcx( losig );
1756 SETFLAG( rcx->FLAG, RCXNOWIRE );
1757 freetable(losig);
1758 }
1759
1760 void rcx_freectc( losig_list *losig )
1761 {
1762 rcx_list *rcx;
1763 rcx = getrcx( losig );
1764 if( !rcx ) return;
1765 SETFLAG( rcx->FLAG, RCXNOCTC );
1766 }
1767
1768 int setrcxmodel( lofig_list *lofig, losig_list *losig, int request )
1769 {
1770 int hasdelayrc;
1771 int retval=RCX_ALL;
1772 ptype_list *ptl;
1773 locon_list *locon;
1774 chain_list *chain;
1775 rcx_list *rcx;
1776 float ccl, ccg, cm;
1777
1778
1779 if( !losig->PRCN )
1780 return( RCX_NORCTC );
1781
1782 if( rcx_isbellow( losig ) )
1783 return( RCX_NORCTC );
1784
1785 if( tlc_islosigalim( losig ) ) {
1786 return( RCX_NORCTC );
1787 }
1788
1789 rcx = getrcx( losig );
1790 if( !rcx ) return( RCX_NORCTC );
1791
1792 switch( request ) {
1793 case RCX_NOCTC :
1794 SETFLAG( rcx->FLAG, RCXNOCTC );
1795 break;
1796 case RCX_NOR :
1797 if( losig->TYPE!='E')
1798 SETFLAG( rcx->FLAG, RCXNOWIRE );
1799 break;
1800 case RCX_NORCTC :
1801 SETFLAG( rcx->FLAG, RCXNOWIRE );
1802 SETFLAG( rcx->FLAG, RCXNOCTC );
1803 break;
1804 case RCX_BEST :
1805 break;
1806 default :
1807 rcx_error( 36, losig, AVT_FATAL );
1808 }
1809
1810 hasdelayrc = rcx_isrcdelay( lofig, losig );
1811 if( !hasdelayrc ) rcx_freewire( losig );
1812
1813 if( GETFLAG( rcx->FLAG, RCXNOWIRE ) && GETFLAG( rcx->FLAG, RCXNOCTC ) )
1814 retval = RCX_NORCTC;
1815 if( !GETFLAG( rcx->FLAG, RCXNOWIRE ) && GETFLAG( rcx->FLAG, RCXNOCTC ) )
1816 retval = RCX_NOCTC;
1817 if( GETFLAG( rcx->FLAG, RCXNOWIRE ) && !GETFLAG( rcx->FLAG, RCXNOCTC ) )
1818 retval = RCX_NOR;
1819 if( !GETFLAG( rcx->FLAG, RCXNOWIRE ) && !GETFLAG( rcx->FLAG, RCXNOCTC ) )
1820 retval = RCX_ALL;
1821
1822 if( retval == RCX_NORCTC && V_INT_TAB[__ELP_CAPA_LEVEL].VALUE == ELP_CAPA_LEVEL0 ) {
1823 // On met seulement la capa à jour
1824 ptl = getptype( losig->USER, LOFIGCHAIN );
1825 if( ptl ) {
1826 for( chain = (chain_list*)ptl->DATA ; chain ; chain = chain->NEXT ) {
1827 locon = (locon_list*)chain->DATA;
1828 if( !rcx_isvalidlocon( locon ) )
1829 continue;
1830 rcx_getloinscapa( locon, &cm, &ccl, &ccg );
1831 rcn_addcapa( losig, cm + ccl );
1832 }
1833 }
1834 // Force le calcul de la capa de RCN
1835 rcn_getcapa( lofig, losig );
1836 delrcx( losig );
1837 }
1838
1839 return retval;
1840 }
1841
1842 char* rcx_isbellow( losig )
1843 losig_list *losig;
1844 {
1845 ptype_list *ptl;
1846 ptl = getptype( losig->USER, RCX_BELLOW );
1847 if( ptl )
1848 return (char*)ptl->DATA;
1849 return NULL;
1850 }
1851
1852 int rcx_isloop( ptrcx, losig )
1853 rcx_list *ptrcx;
1854 losig_list *losig;
1855 {
1856 int r ;
1857 lowire_list *wire ;
1858 lonode_list *ptnode ;
1859 ht *htpack ;
1860 chain_list *headpack ;
1861 chain_list *scanpack ;
1862 rcx_triangle *pack ;
1863
1864 if( GETFLAG( ptrcx->FLAG, RCXHASNOLOOP ) ) return 0;
1865 if( GETFLAG( ptrcx->FLAG, RCXHASLOOP ) ) return 1;
1866
1867 if( RCX_USING_AWEMATRIX == RCX_USING_AWEMATRIX_FORCE ) {
1868 /* Le 6/04/2005, il y a une boucle infinie chez Sony dans le
1869 parcours des rc : lorsqu'on est en mode force, on considère
1870 que tous les rc ont des boucles et il ne faut surtout pas
1871 passer par rcn_treetrip */
1872 SETFLAG( ptrcx->FLAG, RCXHASLOOP );
1873 return 1 ;
1874 }
1875
1876 avt_logenterfunction(LOGTRC,2, "rcx_isloop()");
1877
1878 clearallwireflag( losig, RCN_FLAG_PASS );
1879 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
1880 RCN_CLEARFLAG( wire->FLAG, RCXNODEINTR );
1881
1882 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT ) {
1883
1884 ptnode = getlonode( losig, wire->NODE1 ) ;
1885 if( RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_PASS ) )
1886 continue ;
1887
1888 r = rcn_treetrip( losig,
1889 ptnode,
1890 (int (*)(losig_list*,lonode_list*,lowire_list*,void*)) rcx_up_forloop,
1891 (int (*)(losig_list*,lonode_list*,chain_list*,ht*,void*))
1892 rcx_dw_forloop,
1893 (int (*)(losig_list*,lonode_list*,void*,void*)) rcx_up_pack_forloop,
1894 NULL,
1895 0
1896 );
1897
1898 if( r == RCNTREETRIPLOOP ) {
1899 SETFLAG( ptrcx->FLAG, RCXHASLOOP );
1900 break ;
1901 }
1902 }
1903
1904 if( !wire )
1905 SETFLAG( ptrcx->FLAG, RCXHASNOLOOP );
1906
1907 if( GETFLAG( ptrcx->FLAG, RCXHASNOLOOP ) ) {
1908 if ( avt_islog(2,LOGTRC) ) {
1909 avt_log(LOGTRC,2,"no loop found\n" );
1910 }
1911 avt_logexitfunction(LOGTRC,2);
1912 return 0;
1913 }
1914
1915 if( GETFLAG( ptrcx->FLAG, RCXHASLOOP ) ) {
1916 avt_log(LOGTRC,2,"loop found\n" );
1917 /* il faut effacer les triangles qui ont commencés à être construits */
1918 htpack = addht( 100 );
1919 headpack = NULL ;
1920 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT ) {
1921 pack = rcn_getpack( losig, wire );
1922 if( pack ) {
1923 if( gethtitem( htpack, pack ) == EMPTYHT ) {
1924 headpack = addchain( headpack, pack );
1925 addhtitem( htpack, pack, 1 );
1926 }
1927 }
1928 }
1929 for( scanpack = headpack ; scanpack ; scanpack = scanpack->NEXT ) {
1930 pack = (rcx_triangle*)scanpack->DATA ;
1931 rcx_cleantriangle_node( losig, NULL, pack );
1932 }
1933 freechain( headpack );
1934 delht( htpack ) ;
1935 }
1936
1937 avt_logexitfunction(LOGTRC,2);
1938 return 1 ;
1939 }
1940
1941 int rcx_dw_forloop( losig_list *losig,
1942 lonode_list *lonode,
1943 chain_list *chwire,
1944 ht *htpack,
1945 void *userdata
1946 )
1947 {
1948 chain_list *headht ;
1949 chain_list *scanht ;
1950 rcx_triangle *tr ;
1951 lowire_list *wire ;
1952
1953 headht = GetAllHTElems( htpack );
1954
1955 for( scanht = headht ; scanht ; scanht = scanht->NEXT ) {
1956 wire = (lowire_list*)((chain_list*)scanht->DATA)->DATA ;
1957 tr = (rcx_triangle*)rcn_getpack( losig, wire );
1958 rcx_cleantriangle_node( losig, lonode, tr );
1959 }
1960
1961 chwire = NULL ;
1962 userdata = NULL ;
1963
1964 freechain( headht );
1965 return 1 ;
1966 }
1967
1968 int rcx_up_pack_forloop( losig_list *losig,
1969 lonode_list *lonode,
1970 rcx_triangle *tr,
1971 void *userdata
1972 )
1973 {
1974 chain_list *chain ;
1975 lonode_list *tstnode ;
1976
1977 if( tr->n0 != lonode ) rcx_triangle_node( losig, tr->n0, NULL );
1978 if( tr->n1 != lonode ) rcx_triangle_node( losig, tr->n1, NULL );
1979 if( tr->n2 != lonode ) rcx_triangle_node( losig, tr->n2, NULL );
1980 for( chain = tr->REPORTED_IN ; chain ; chain = chain->NEXT ) {
1981 tstnode = (lonode_list*)chain->DATA ;
1982 if( tstnode != lonode ) rcx_triangle_node( losig, tstnode, NULL );
1983 }
1984 for( chain = tr->REPORTED_N1 ; chain ; chain = chain->NEXT ) {
1985 tstnode = (lonode_list*)chain->DATA ;
1986 if( tstnode != lonode ) rcx_triangle_node( losig, tstnode, NULL );
1987 }
1988 for( chain = tr->REPORTED_N2 ; chain ; chain = chain->NEXT ) {
1989 tstnode = (lonode_list*)chain->DATA ;
1990 if( tstnode != lonode ) rcx_triangle_node( losig, tstnode, NULL );
1991 }
1992
1993 userdata = NULL ;
1994 return 1 ;
1995 }
1996
1997 int rcx_up_forloop( losig_list *losig,
1998 lonode_list *lonode,
1999 lowire_list *lowire,
2000 void *userdata
2001 )
2002 {
2003 rcx_triangle_node( losig, lonode, lowire );
2004 userdata = NULL ;
2005 return 1 ;
2006 }
2007
2008 void rcx_env_error( char *msg, char *was )
2009 {
2010 avt_errmsg( TRC_ERRMSG, "016", AVT_FATAL, msg, was );
2011 }
2012
2013 void rcx_env( void )
2014 {
2015 char *str;
2016 char *ptend;
2017 RCXFLOAT value;
2018 unsigned long int size;
2019
2020 if( STM_DEFAULT_SMAXR >= 0.0 && STM_DEFAULT_SMINR >= 0.0 )
2021 RCX_SLOPE_UNSHRINK = STM_DEFAULT_SMAXR - STM_DEFAULT_SMINR ;
2022 else
2023 RCX_SLOPE_UNSHRINK = 0.6 ;
2024
2025 if( V_FLOAT_TAB[__RCX_MINRCSIGNAL].VALUE < 0.0 )
2026 rcx_env_error( "RCX_MINRCSIGNAL must be a positive RCXFLOATing number.",
2027 str
2028 );
2029 RCX_MINRCSIGNAL = V_FLOAT_TAB[__RCX_MINRCSIGNAL].VALUE;
2030
2031 if( V_FLOAT_TAB[__RCX_MINRELCTKSIGNAL].VALUE < 0.0 || V_FLOAT_TAB[__RCX_MINRELCTKSIGNAL].VALUE > 1.0 )
2032 rcx_env_error(
2033 "RCX_MINRELCTKSIGNAL must be a RCXFLOATing number between 0 and 1.",
2034 str
2035 );
2036 RCX_MINRELCTKSIGNAL = V_FLOAT_TAB[__RCX_MINRELCTKSIGNAL].VALUE;
2037
2038 if( V_FLOAT_TAB[__RCX_MINRELCTKFILTER].VALUE < 0.0 || V_FLOAT_TAB[__RCX_MINRELCTKFILTER].VALUE > 1.0 )
2039 rcx_env_error(
2040 "RCX_MINRELCTKFILTER must be a RCXFLOATing number between 0 and 1.",
2041 str
2042 );
2043 RCX_MINRELCTKFILTER = V_FLOAT_TAB[__RCX_MINRELCTKFILTER].VALUE ;
2044
2045 if( V_FLOAT_TAB[__RCX_CAPALOAD_MAXRC].VALUE < 0.0 )
2046 rcx_env_error(
2047 "RCX_CAPALOAD_MAXRC must be a positive RCXFLOATing number.",
2048 str
2049 );
2050 RCX_CAPALOAD_MAXRC = V_FLOAT_TAB[__RCX_CAPALOAD_MAXRC].VALUE ;
2051
2052 if( V_FLOAT_TAB[__RCX_MAXDELTALOAD].VALUE < 0.0 )
2053 rcx_env_error( "RCX_MAXDELTALOAD must be a positive RCXFLOATing number.",
2054 str
2055 );
2056 RCX_MAXDELTALOAD = V_FLOAT_TAB[__RCX_MAXDELTALOAD].VALUE ;
2057
2058 str = getenv("RCX_FREEUNUSEDCTC");
2059 if( str ) {
2060 if( strcmp( str, "yes" ) == 0 )
2061 RCX_FREEUNUSEDCTC = 'Y';
2062 else {
2063 if( strcmp( str, "no" ) == 0 )
2064 RCX_FREEUNUSEDCTC = 'N';
2065 else
2066 rcx_env_error( "Allowed value for RCX_FREEUNUSEDCTC is 'yes' or 'no'.",
2067 str
2068 );
2069 }
2070 }
2071
2072 str = getenv("RCX_USECACHE");
2073 if( str ) {
2074 if( strcmp( str, "yes" ) == 0 )
2075 RCX_USECACHE = 'Y';
2076 else {
2077 if( strcmp( str, "no" ) == 0 )
2078 RCX_USECACHE = 'N';
2079 else
2080 rcx_env_error( "Allowed value for RCX_USECACHE is 'yes' or 'no'.",
2081 str
2082 );
2083 }
2084 }
2085
2086 RCX_USE_MATRIX_LOAD = V_BOOL_TAB[__RCX_USE_MATRIX_LOAD].VALUE?'Y':'N';
2087
2088 str = V_STR_TAB[__RCX_CTK_MODEL].VALUE;
2089 if( str ) {
2090 RCX_CTK_MODEL = 0;
2091 if( !strcmp( str, "MILLER_0C2C" ) )
2092 RCX_CTK_MODEL = RCX_MILLER_0C2C ;
2093 if( !strcmp( str, "MILLER_NC3C" ) )
2094 RCX_CTK_MODEL = RCX_MILLER_NC3C ;
2095 if( !strcmp( str, "MILLER_NOMINAL" ) )
2096 RCX_CTK_MODEL = RCX_MILLER_NOMINAL ;
2097 if( !RCX_CTK_MODEL )
2098 rcx_env_error(
2099 "Allowed value for RCX_CTK_MODEL : MILLER_0C2C | MILLER_NOMINAL | MILLER_NC3C.",
2100 str
2101 );
2102 }
2103
2104 str = V_STR_TAB[__RCX_CTK_NOISE].VALUE;
2105 if( str ) {
2106 RCX_CTK_NOISE = 0;
2107 if( !strcmp( str, "NOISE_NEVER" ) )
2108 RCX_CTK_NOISE = RCX_NOISE_NEVER ;
2109 if( !strcmp( str, "NOISE_ALWAYS" ) )
2110 RCX_CTK_NOISE = RCX_NOISE_ALWAYS ;
2111 if( !strcmp( str, "NOISE_IFSTRONG" ) )
2112 RCX_CTK_NOISE = RCX_NOISE_IFSTRONG ;
2113 if( !strcmp( str, "NOISE_CUSTOM" ) )
2114 RCX_CTK_NOISE = RCX_NOISE_CUSTOM ;
2115 if( !strcmp( str, "NOISE_FINE" ) )
2116 RCX_CTK_NOISE = RCX_NOISE_FINE ;
2117 if( !RCX_CTK_NOISE )
2118 rcx_env_error( "Allowed value for RCX_CTK_NOISE : NOISE_NEVER | NOISE_ALWAYS | NOISE_IFSTRONG | NOISE_CUSTOM | NOISE_FINE.\n",
2119 str
2120 );
2121 }
2122
2123 RCX_FASTMODE = V_BOOL_TAB[__RCX_FASTMODE].VALUE;
2124
2125 str = getenv("RCX_AWESTRAIGHT");
2126 if( str ) {
2127 if( strcmp( str, "yes" ) == 0 )
2128 RCX_AWESTRAIGHT = 1;
2129 else {
2130 if( strcmp( str, "no" ) == 0 )
2131 RCX_AWESTRAIGHT = 0;
2132 else
2133 rcx_env_error( "Allowed value for RCX_AWESTRAIGHT is 'yes' or 'no'.",
2134 str
2135 );
2136 }
2137 }
2138
2139 str = getenv("RCX_STEPTANH");
2140 if( str ) {
2141 if( strcmp( str, "yes" ) == 0 )
2142 RCX_STEPTANH = 1;
2143 else {
2144 if( strcmp( str, "no" ) == 0 )
2145 RCX_STEPTANH = 0;
2146 else
2147 rcx_env_error( "Allowed value for STEPTANH is 'yes' or 'no'.", str );
2148 }
2149 }
2150
2151 str = V_STR_TAB[__RCX_CTK_SLOPE_NOISE].VALUE;
2152 if( str ) {
2153 RCX_CTK_SLOPE_NOISE = RCX_SLOPE_NONE ;
2154 if( strcmp( str, "SLOPE_CTK" ) == 0 )
2155 RCX_CTK_SLOPE_NOISE = RCX_SLOPE_CTK ;
2156 if( strcmp( str, "SLOPE_NOMINAL" ) == 0 )
2157 RCX_CTK_SLOPE_NOISE = RCX_SLOPE_NOMINAL ;
2158 if( strcmp( str, "SLOPE_REAL" ) == 0 )
2159 RCX_CTK_SLOPE_NOISE = RCX_SLOPE_REAL ;
2160 if( RCX_CTK_SLOPE_NOISE == RCX_SLOPE_NONE )
2161 rcx_env_error( "Allowed value for RCX_CTK_SLOPE_NOISE is SLOPE_CTK | SLOPE_NOMINAL | SLOPE_REAL\n",
2162 str
2163 );
2164 }
2165
2166 str = getenv("RCX_CTK_SLOPE_MILLER");
2167 if( str ) {
2168 RCX_CTK_SLOPE_MILLER = RCX_SLOPE_NONE ;
2169 if( strcmp( str, "SLOPE_CTK" ) == 0 )
2170 RCX_CTK_SLOPE_MILLER = RCX_SLOPE_CTK ;
2171 if( strcmp( str, "SLOPE_NOMINAL" ) == 0 )
2172 RCX_CTK_SLOPE_MILLER = RCX_SLOPE_NOMINAL ;
2173 if( RCX_CTK_SLOPE_MILLER == RCX_SLOPE_NONE )
2174 rcx_env_error(
2175 "Allowed value for RCX_CTK_SLOPE_MILLER is SLOPE_CTK | SLOPE_NOMINAL\n",
2176 str
2177 );
2178 }
2179
2180 str = V_STR_TAB[__RCX_CTK_SLOPE_DELAY].VALUE;
2181 if( str ) {
2182 RCX_CTK_SLOPE_DELAY = RCX_SLOPE_DELAY_NONE;
2183 if( strcmp( str, "SLOPE_DELAY_CTK" ) == 0 )
2184 RCX_CTK_SLOPE_DELAY = RCX_SLOPE_DELAY_CTK ;
2185 if( strcmp( str, "SLOPE_DELAY_ENHANCED" ) == 0 )
2186 RCX_CTK_SLOPE_DELAY = RCX_SLOPE_DELAY_ENHANCED ;
2187 if( RCX_CTK_SLOPE_DELAY == RCX_SLOPE_DELAY_NONE )
2188 rcx_env_error( "Allowed value for RCX_CTK_SLOPE_DELAY is SLOPE_DELAY_CTK | SLOPE_DELAY_ENHANCED\n",
2189 str
2190 );
2191 }
2192
2193 str = V_STR_TAB[__RCX_USING_AWEMATRIX].VALUE;
2194 if( str ) {
2195 RCX_USING_AWEMATRIX=0;
2196 if( strcmp( str, "never" )==0 ) RCX_USING_AWEMATRIX = RCX_USING_AWEMATRIX_NEVER ;
2197 if( strcmp( str, "always" )==0 ) RCX_USING_AWEMATRIX = RCX_USING_AWEMATRIX_ALWAYS ;
2198 if( strcmp( str, "ifneed" )==0 ) RCX_USING_AWEMATRIX = RCX_USING_AWEMATRIX_IFNEED ;
2199 if( strcmp( str, "force" )==0 ) RCX_USING_AWEMATRIX = RCX_USING_AWEMATRIX_FORCE ;
2200 if( !RCX_USING_AWEMATRIX ) {
2201 rcx_env_error( "Allowed value for RCX_USING_AWEMATRIX is never | always | ifneed | force\n", str );
2202 }
2203 }
2204
2205 str = getenv("RCX_AWE_FAST_MODE") ;
2206 if( str ) {
2207 if( strcmp( str, "yes" ) == 0 )
2208 AWE_FAST_MODE = 'Y';
2209 else {
2210 if( strcmp( str, "no" ) == 0 )
2211 AWE_FAST_MODE = 'N';
2212 else
2213 rcx_env_error( "Allowed value for AWE_FAST_MODE is 'yes' or 'no'.", str );
2214 }
2215 }
2216
2217 str = V_STR_TAB[__RCX_DELAY_CACHE].VALUE;
2218 if( str ) {
2219 size = strtoul( str, &ptend, 10 );
2220
2221 if( *ptend != '\0' ) {
2222 if( strcasecmp( ptend, "kb" )==0 )
2223 size = size * 1024;
2224 else {
2225 if( strcasecmp( ptend, "mb" )==0 )
2226 size = size * 1048576;
2227 else {
2228 if( strcasecmp( ptend, "gb" )==0 )
2229 size = size * 1073741824;
2230 else {
2231 avt_errmsg( RCN_ERRMSG, "002", AVT_FATAL );
2232 }
2233 }
2234 }
2235 }
2236 rcx_init_delay_cache( size );
2237 }
2238 else
2239 rcx_init_delay_cache( 10*1024*1024 );
2240
2241 str = getenv( "RCX_AWE_ONE_PNODE" );
2242 if( str ) {
2243 RCX_AWE_ONE_PNODE = 0;
2244 if( strcmp( str, "yes" )==0 ) RCX_AWE_ONE_PNODE='Y' ;
2245 if( strcmp( str, "no" )==0 ) RCX_AWE_ONE_PNODE='N' ;
2246 if( !RCX_AWE_ONE_PNODE )
2247 rcx_env_error( "Allowed value for RCX_AWE_ONE_PNODE is yes or no\n", str );
2248 switch( RCX_AWE_ONE_PNODE ) {
2249 case 'Y' : printf( "yes\n" ); break ;
2250 case 'N' : printf( "no\n" ); break ;
2251 }
2252 }
2253
2254 str = getenv( "RCX_AWE_MIN_RESI" );
2255 if( str ) {
2256 AWE_MIN_RESI_VALUE = atof( str );
2257 if( AWE_MIN_RESI_VALUE <= 1.0e-6 ) {
2258 rcx_env_error( "Argument for RCX_AWE_MIN_RESI must be a floating number greater than 1.0e-6\n", str );
2259 }
2260 }
2261
2262 str = getenv( "RCX_PLOT_AWE" );
2263 if( str )
2264 RCX_PLOT_AWE = namealloc(str);
2265
2266 if( mcc_use_multicorner() ) {
2267
2268 switch( V_INT_TAB[__ELP_CAPA_LEVEL].VALUE ) {
2269
2270 case ELP_CAPA_LEVEL0 :
2271 RCX_CAPA_NOM_MIN = 0 ;
2272 RCX_CAPA_NOM_MAX = 1 ;
2273 RCX_CAPA_NOMF_MIN = 2 ;
2274 RCX_CAPA_NOMF_MAX = 3 ;
2275 RCX_NB_CAPA_L0 = 4 ;
2276 break ;
2277
2278 case ELP_CAPA_LEVEL1 :
2279 RCX_CAPA_UP_NOM_MIN = 0 ;
2280 RCX_CAPA_UP_NOM_MAX = 1 ;
2281 RCX_CAPA_DW_NOM_MIN = 2 ;
2282 RCX_CAPA_DW_NOM_MAX = 3 ;
2283 RCX_CAPA_UP_NOMF_MIN = 4 ;
2284 RCX_CAPA_UP_NOMF_MAX = 5 ;
2285 RCX_CAPA_DW_NOMF_MIN = 6 ;
2286 RCX_CAPA_DW_NOMF_MAX = 7 ;
2287 RCX_NB_CAPA_L1 = 8 ;
2288 break ;
2289
2290 case ELP_CAPA_LEVEL2 :
2291 RCX_CAPA_UP_MIN = 0 ;
2292 RCX_CAPA_UP_NOM_MIN = 1 ;
2293 RCX_CAPA_UP_NOM_MAX = 2 ;
2294 RCX_CAPA_UP_MAX = 3 ;
2295 RCX_CAPA_DW_MIN = 4 ;
2296 RCX_CAPA_DW_NOM_MIN = 5 ;
2297 RCX_CAPA_DW_NOM_MAX = 6 ;
2298 RCX_CAPA_DW_MAX = 7 ;
2299 RCX_CAPA_UP_NOMF_MIN = 8 ;
2300 RCX_CAPA_UP_NOMF_MAX = 9 ;
2301 RCX_CAPA_DW_NOMF_MIN = 10 ;
2302 RCX_CAPA_DW_NOMF_MAX = 11 ;
2303 RCX_NB_CAPA_L2 = 12 ;
2304 break ;
2305 }
2306 }
2307 else {
2308
2309 switch( V_INT_TAB[__ELP_CAPA_LEVEL].VALUE ) {
2310
2311 case ELP_CAPA_LEVEL0 :
2312 RCX_CAPA_NOM_MIN = 0 ;
2313 RCX_CAPA_NOM_MAX = 0 ;
2314 RCX_CAPA_NOMF_MIN = 1 ;
2315 RCX_CAPA_NOMF_MAX = 1 ;
2316 RCX_NB_CAPA_L0 = 2 ;
2317 break ;
2318
2319 case ELP_CAPA_LEVEL1 :
2320 RCX_CAPA_UP_NOM_MIN = 0 ;
2321 RCX_CAPA_UP_NOM_MAX = 0 ;
2322 RCX_CAPA_DW_NOM_MIN = 1 ;
2323 RCX_CAPA_DW_NOM_MAX = 1 ;
2324 RCX_CAPA_UP_NOMF_MIN = 2 ;
2325 RCX_CAPA_UP_NOMF_MAX = 2 ;
2326 RCX_CAPA_DW_NOMF_MIN = 3 ;
2327 RCX_CAPA_DW_NOMF_MAX = 3 ;
2328 RCX_NB_CAPA_L1 = 4 ;
2329 break ;
2330
2331 case ELP_CAPA_LEVEL2 :
2332 RCX_CAPA_UP_MIN = 0 ;
2333 RCX_CAPA_UP_NOM_MIN = 1 ;
2334 RCX_CAPA_UP_NOM_MAX = 1 ;
2335 RCX_CAPA_UP_MAX = 2 ;
2336 RCX_CAPA_DW_MIN = 3 ;
2337 RCX_CAPA_DW_NOM_MIN = 4 ;
2338 RCX_CAPA_DW_NOM_MAX = 4 ;
2339 RCX_CAPA_DW_MAX = 5 ;
2340 RCX_CAPA_UP_NOMF_MIN = 6 ;
2341 RCX_CAPA_UP_NOMF_MAX = 6 ;
2342 RCX_CAPA_DW_NOMF_MIN = 7 ;
2343 RCX_CAPA_DW_NOMF_MAX = 7 ;
2344 RCX_NB_CAPA_L2 = 8 ;
2345 break ;
2346 }
2347 }
2348 }
2349
2350 void rcx_setlosigbreakloop( losig_list *losig )
2351 {
2352 rcx_list *ptrcx;
2353
2354 ptrcx = getrcx( losig );
2355 if( !ptrcx ) {
2356 return;
2357 }
2358
2359 SETFLAG( ptrcx->FLAG, RCXBREAKLOOP );
2360 }
2361
2362 int rcx_islosigbreakloop( losig_list *losig )
2363 {
2364 rcx_list *ptrcx;
2365
2366 ptrcx = getrcx( losig );
2367
2368 if( !ptrcx ) {
2369 return 0;
2370 }
2371
2372 if( GETFLAG( ptrcx->FLAG, RCXBREAKLOOP ) )
2373 return 1;
2374 return 0;
2375 }
2376
2377
2378 /******************************************************************************\
2379 Fonction qui répare les locon de la lofig qui ont leur PNODE à 0.
2380
2381 Hypothèses :
2382
2383 - Le signal doit être présent en mémoire.
2384 - On a pas le droit de modifier des PNODE existant car ils ont peut être été
2385 référencés par d'autres signaux via la fonction rcx_get_new_num_node().
2386
2387 \******************************************************************************/
2388 void rcx_repair_pnode( losig_list *losig )
2389 {
2390 ptype_list *ptl;
2391 rcx_list *rcx;
2392 chain_list *chain;
2393 locon_list *locon;
2394 losig_list *sigint;
2395 rcx_list *rcxint;
2396 num_list *scan;
2397 int goodnode;
2398
2399 ptl = getptype( losig->USER, LOFIGCHAIN );
2400 if( !ptl ) return;
2401
2402 goodnode = -1;
2403 for( chain = (chain_list*)ptl->DATA ; chain ; chain = chain->NEXT ) {
2404 locon = (locon_list*)chain->DATA;
2405 if( !rcx_isvalidlocon( locon ) )
2406 continue;
2407 if( locon->PNODE ) {
2408 goodnode = locon->PNODE->DATA;
2409 break;
2410 }
2411 }
2412
2413 rcx = getrcx( losig );
2414
2415 if( goodnode == -1 ) // aucun locon n'a de PNODE.
2416 goodnode = losig->PRCN->NBNODE;
2417
2418 // Idée de bug : ca n'arrivera jamais, mais que ce passe t'il si il y
2419 // a des résistances...
2420
2421 for( chain = (chain_list*)ptl->DATA ; chain ; chain = chain->NEXT ) {
2422
2423 locon = (locon_list*)chain->DATA;
2424
2425 if( !locon->PNODE ) {
2426 chain_list *cl;
2427 ptl = getptype( locon->USER, PTYPERCX );
2428 if( ptl ) {
2429 sigint = (losig_list*)ptl->DATA;
2430 rcxint = getrcx( sigint );
2431 for (cl=rcxint->RCXEXTERNAL; cl!=NULL; cl=cl->NEXT)
2432 for( scan = ((locon_list *)cl->DATA)->PNODE ; scan ; scan = scan->NEXT ) {
2433 setloconnode( locon, goodnode );
2434 }
2435 }
2436 else {
2437 setloconnode( locon, goodnode );
2438 }
2439 }
2440 }
2441 }
2442
2443 /******************************************************************************\
2444
2445 Fonctions utilisées dans buildrcx pour déterminer le numéro d'un noeud d'un
2446 signal.
2447 Hypothèse :
2448 - On ne connait pas le NBNODE sur les signaux de la lofig (si on a jamais eu
2449 de refresh sur le signal).
2450 - On connait le NBNODE sur les signaux des instances.
2451
2452 \******************************************************************************/
2453
2454 int rcx_get_new_num_node( losig_list *losig,
2455 int node,
2456 char where,
2457 char withnowire )
2458 {
2459 int base ;
2460 int base_ext ;
2461 int newnode;
2462 rcx_list *rcxint ;
2463 rcx_list *ptrcx_ext ;
2464 locon_list *locon_ext ;
2465 num_list *num_int, *num_ext ;
2466 chain_list *cl;
2467
2468 base = rcx_get_node_base( losig );
2469
2470 switch( where ) {
2471 case RCX_LOINS :
2472
2473 rcxint = getrcx( losig );
2474 locon_ext = (locon_list*)getptype( losig->USER, RCX_LOCONINS )->DATA ;
2475 ptrcx_ext = getrcx( locon_ext->SIG );
2476
2477 // Cas où le connecteur externe ne contient pas de pnode
2478 if( !locon_ext->PNODE ) {
2479 if( withnowire==YES && GETFLAG( ptrcx_ext->FLAG, RCXNOWIRE ) ) {
2480 base_ext = 1;
2481 }
2482 else {
2483 base_ext = rcx_get_node_base( locon_ext->SIG ) +
2484 locon_ext->SIG->PRCN->NBNODE ;
2485 }
2486
2487 for (cl=rcxint->RCXEXTERNAL; cl!=NULL; cl=cl->NEXT)
2488 for( num_int = ((locon_list *)cl->DATA)->PNODE ;
2489 num_int ;
2490 num_int = num_int->NEXT )
2491 setloconnode( locon_ext, base_ext );
2492 }
2493
2494 if( withnowire==YES && GETFLAG( ptrcx_ext->FLAG, RCXNOWIRE ) )
2495 newnode = 1;
2496 else {
2497 if( withnowire==YES && GETFLAG( rcxint->FLAG, RCXNOWIRE ) ) {
2498 newnode = rcx_get_new_num_node( locon_ext->SIG,
2499 locon_ext->PNODE->DATA,
2500 RCX_LOFIG,
2501 withnowire
2502 );
2503 }
2504 else {
2505 for (cl=rcxint->RCXEXTERNAL; cl!=NULL; cl=cl->NEXT)
2506 for( num_int = ((locon_list *)cl->DATA)->PNODE,
2507 num_ext = locon_ext->PNODE ;
2508 num_int ;
2509 num_int = num_int->NEXT, num_ext = num_ext->NEXT )
2510 if( num_int->DATA == node )
2511 break;
2512
2513 if( num_int )
2514 newnode = rcx_get_new_num_node( locon_ext->SIG,
2515 num_ext->DATA,
2516 RCX_LOFIG,
2517 withnowire
2518 );
2519 else
2520 newnode = node + base;
2521 }
2522 }
2523 break;
2524
2525 case RCX_LOFIG :
2526 ptrcx_ext = getrcx( losig );
2527 if( withnowire==YES && GETFLAG( ptrcx_ext->FLAG, RCXNOWIRE ) )
2528 newnode = 1;
2529 else
2530 newnode = node + base;
2531 break;
2532 }
2533
2534 return newnode;
2535 }
2536
2537 // Créé les infos pour les signaux qui auront des noeuds renumérotés.
2538
2539 void rcx_build_new_num_node( lofig_list *lofig )
2540 {
2541 losig_list *sigext, *sigint ;
2542 ptype_list *ptl ;
2543 int n ;
2544 chain_list *chain ;
2545 locon_list *locon ;
2546
2547 for( sigext = lofig->LOSIG ; sigext ; sigext = sigext->NEXT ) {
2548
2549 n = 0;
2550
2551 ptl = getptype( sigext->USER, LOFIGCHAIN );
2552
2553 if( ptl ) {
2554
2555 for( chain = (chain_list*)ptl->DATA ; chain ; chain = chain->NEXT ) {
2556
2557 locon = (locon_list*)chain->DATA ;
2558 if( !rcx_isvalidlocon( locon ) )
2559 continue;
2560
2561 if( locon->TYPE == 'I' ) {
2562
2563 ptl = getptype( locon->USER, PTYPERCX ) ;
2564 if( ptl ) {
2565
2566 sigint = (losig_list*)(ptl->DATA) ;
2567 if (rcx_set_node_base( sigint, n ))
2568 n = n + sigint->PRCN->NBNODE ;
2569 }
2570 }
2571 }
2572 }
2573 rcx_set_node_base( sigext, n );
2574 }
2575 }
2576
2577 // Libère les infos pour les signaux qui auront des noeuds renumérotés.
2578
2579 void rcx_clear_new_num_node( lofig_list *lofig )
2580 {
2581 losig_list *sigext, *sigint ;
2582 ptype_list *ptl ;
2583 chain_list *chain ;
2584 locon_list *locon ;
2585
2586 for( sigext = lofig->LOSIG ; sigext ; sigext = sigext->NEXT ) {
2587
2588 ptl = getptype( sigext->USER, LOFIGCHAIN );
2589
2590 if( ptl ) {
2591
2592 for( chain = (chain_list*)ptl->DATA ; chain ; chain = chain->NEXT ) {
2593
2594 locon = (locon_list*)chain->DATA ;
2595 if( !rcx_isvalidlocon( locon ) )
2596 continue;
2597
2598 if( locon->TYPE == 'I' ) {
2599
2600 ptl = getptype( locon->USER, PTYPERCX ) ;
2601 if( ptl ) {
2602
2603 sigint = (losig_list*)(ptl->DATA) ;
2604 rcx_clear_node_base( sigint ) ;
2605 }
2606 }
2607 }
2608 }
2609 rcx_clear_node_base( sigext ) ;
2610 }
2611 }
2612
2613 // Le losig est interne à une loins. Récupère le nom du signal à l'extérieur de
2614 // la loins.
2615 losig_list* rcx_get_out_ins_sig( losig_list *losig )
2616 {
2617 locon_list *locon_ext;
2618 losig_list *sig_ext;
2619
2620 locon_ext = (locon_list*)getptype( losig->USER, RCX_LOCONINS )->DATA ;
2621 sig_ext = locon_ext->SIG;
2622
2623 return sig_ext;
2624 }
2625
2626 int rcx_get_node_base( losig_list *losig )
2627 {
2628 ptype_list *ptl;
2629 ptl = getptype( losig->USER, RCX_NODE_BASE );
2630 if( !ptl ) return 0;
2631 return (int)(long)ptl->DATA;
2632 }
2633
2634 int rcx_set_node_base( losig_list *losig, int index )
2635 {
2636 ptype_list *ptl;
2637 ptl = getptype( losig->USER, RCX_NODE_BASE );
2638 if( ptl ) {
2639 if (countchain(getrcx(losig)->RCXEXTERNAL)>1) return 0;
2640 rcx_error( 12, losig, AVT_ERROR );
2641 losig->USER = delptype( losig->USER, RCX_NODE_BASE );
2642 }
2643 losig->USER = addptype( losig->USER, RCX_NODE_BASE, (void*)(long)index );
2644 return 1;
2645 }
2646
2647 void rcx_clear_node_base( losig_list *losig )
2648 {
2649 ptype_list *ptl;
2650 ptl = getptype( losig->USER, RCX_NODE_BASE );
2651 if( ptl )
2652 losig->USER = delptype( losig->USER, RCX_NODE_BASE );
2653 }
2654
2655 /******************************************************************************\
2656 Transfert au niveau supérieur les informations sur les drivers.
2657 Si au niveau supérieur il y a deja des informations de driver (cas multi driver
2658 due à la hiérarchie), alors on en prend aucune en compte. Pour indiquer ce cas,
2659 on utilise le flag MULTIDRIVER dans la vue RCX externe.
2660 \******************************************************************************/
2661 void rcx_trsfdriver( lofig_list *currentfig, losig_list *sigext, rcx_list *rcxext, losig_list *sigint, rcx_list *rcxint )
2662 {
2663 num_list *headnodeup ;
2664 num_list *headnodedw ;
2665 num_list *node ;
2666
2667 if( GETFLAG( rcxext->FLAG, RCXMLTDRIVER ) )
2668 return ;
2669
2670 if( ( rcxext->DRIVERSUP || rcxext->DRIVERSDW ) &&
2671 ( rcxint->DRIVERSUP || rcxint->DRIVERSDW ) ) {
2672 rcx_cleardriver( sigext );
2673 SETFLAG( rcxext->FLAG, RCXMLTDRIVER );
2674 }
2675
2676 headnodeup = NULL ;
2677 headnodedw = NULL ;
2678
2679 if( rcxint->DRIVERSUP ) {
2680 for( node = rcxint->DRIVERSUP->PNODE ; node ; node = node->NEXT )
2681 headnodeup = addnum( headnodeup, rcx_get_new_num_node( sigint, node->DATA, RCX_LOINS, YES ) ) ;
2682 }
2683
2684 if( rcxint->DRIVERSDW ) {
2685 for( node = rcxint->DRIVERSDW->PNODE ; node ; node = node->NEXT )
2686 headnodedw = addnum( headnodedw, rcx_get_new_num_node( sigint, node->DATA, RCX_LOINS, YES ) ) ;
2687 }
2688
2689 rcx_setdriver( sigext, headnodeup, headnodedw );
2690 currentfig = NULL ;
2691 }
2692
2693 /******************************************************************************\
2694 Calcule les nouveaux PNODE d'un locon.
2695 \******************************************************************************/
2696 void rcx_trsfnodelocon( locon_list *locon, char where )
2697 {
2698 num_list *headup ;
2699 num_list *headdn ;
2700 num_list *scannum;
2701 for( scannum = locon->PNODE ; scannum ; scannum = scannum->NEXT ) {
2702 scannum->DATA = rcx_get_new_num_node( locon->SIG,
2703 scannum->DATA,
2704 where,
2705 NO
2706 );
2707 }
2708
2709 headup = rcx_getnodebytransition( locon, TRC_SLOPE_UP ) ;
2710 if( headup && locon->PNODE != headup ) {
2711 for( scannum = headup ; scannum ; scannum = scannum->NEXT )
2712 scannum->DATA = rcx_get_new_num_node( locon->SIG,
2713 scannum->DATA,
2714 where,
2715 NO
2716 );
2717 }
2718 headdn = rcx_getnodebytransition( locon, TRC_SLOPE_DOWN ) ;
2719 if( headdn && locon->PNODE != headdn ) {
2720 for( scannum = headdn ; scannum ; scannum = scannum->NEXT )
2721 scannum->DATA = rcx_get_new_num_node( locon->SIG,
2722 scannum->DATA,
2723 where,
2724 NO
2725 );
2726 }
2727 }
2728
2729 /******************************************************************************\
2730 Création d'une vue RCX sur une lofig, qui peut contenir des instances ou des
2731 transistors.
2732 \******************************************************************************/
2733
2734 void rcx_create( currentfig )
2735 lofig_list *currentfig;
2736 {
2737 loins_list *scanins;
2738
2739 // Ajoute une vue RCX sur tous les losigs.
2740 rcx_addsignal( currentfig );
2741
2742 // Récupère les informations correspondant aux instances.
2743 for( scanins = currentfig->LOINS ; scanins ; scanins=scanins->NEXT )
2744 rcxparse( scanins, NULL, scanins->FIGNAME, NULL );
2745
2746 // Ajoute des noms de connecteur sur les locons des transistors.
2747 rcx_name_locon_trs( currentfig );
2748
2749 // Ajoute les connecteurs externes de la lofig dans le champs EXTERNAL des
2750 // vues RCX.
2751 rcx_addfigcon( currentfig );
2752
2753 // Sélectionne les signaux à sauvegarder dans le fichier RCX.
2754 rcx_set_lofig_savesig( currentfig );
2755 }
2756
2757 void rcx_name_locon_trs( lofig_list *currentfig )
2758 {
2759 losig_list *scansig;
2760 locon_list *locon ;
2761 ptype_list *ptype ;
2762 chain_list *chain ;
2763
2764 for( scansig = currentfig->LOSIG ; scansig ; scansig = scansig->NEXT ) {
2765
2766 if(tlc_islosigalim(scansig))
2767 continue ;
2768
2769 if((ptype = getptype(scansig->USER,LOFIGCHAIN)) != NULL) {
2770
2771 for( chain = (chain_list *)ptype->DATA ; chain ; chain = chain->NEXT ) {
2772 locon = (locon_list *)chain->DATA ;
2773 if( !rcx_isvalidlocon( locon ) )
2774 continue;
2775 if(locon->TYPE == 'T')
2776 givetransloconrcxname(locon) ;
2777 }
2778 }
2779 }
2780 givetransloconrcxname(NULL) ;
2781 }
2782
2783 void rcx_addsignal( lofig_list *fig )
2784 {
2785 losig_list *scansig;
2786
2787 for( scansig = fig->LOSIG ; scansig ; scansig = scansig->NEXT )
2788 {
2789 if(( scansig->PRCN == NULL ) || tlc_islosigalim(scansig))
2790 continue ;
2791
2792 rcx_alloc( scansig );
2793 }
2794 }
2795
2796 void rcx_set_lofig_savesig( lofig_list *fig )
2797 {
2798 losig_list *scanlosig;
2799 rcx_list *rcxview;
2800 for( scanlosig = fig->LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT ) {
2801 rcxview = getrcx( scanlosig );
2802 if( rcxview ) {
2803 SETFLAG( rcxview->FLAG, SAVESIG );
2804 }
2805 }
2806 }
2807
2808 void rcx_addfigcon( lofig_list *fig )
2809 {
2810 locon_list *scanlocon;
2811 losig_list *sig;
2812 rcx_list *rcxview;
2813
2814 for(scanlocon=fig->LOCON;scanlocon;scanlocon=scanlocon->NEXT)
2815 {
2816 sig=scanlocon->SIG;
2817 rcxview = getrcx( sig );
2818
2819 if( rcxview == NULL)
2820 continue;
2821
2822 if( rcx_isvalidlocon( scanlocon ) )
2823 rcxview->RCXEXTERNAL=addchain(rcxview->RCXEXTERNAL, scanlocon);
2824 }
2825 }
2826
2827 char rcx_isvalidlocon( locon_list *locon )
2828 {
2829 char r;
2830
2831 switch( locon->TYPE ) {
2832 case 'I':
2833 case 'E':
2834 case 'T':
2835 r=1;
2836 break;
2837 default:
2838 r=0;
2839 break;
2840 }
2841
2842 return r;
2843 }
2844
2845 int rcx_calc_cca_param( rcxparam *param )
2846 {
2847 if( param->CCA < 0.0 ) {
2848 param->CCA = rcx_getsigcapa( param->LOFIG,
2849 param->SIGNAL,
2850 RCX_SIGCAPA_CTK,
2851 RCX_SIGCAPA_LOCAL|RCX_SIGCAPA_GLOBAL,
2852 RCX_SIGCAPA_NORM,
2853 NULL,
2854 0,
2855 TRC_HALF
2856 );
2857 return 1;
2858 }
2859 return 0;
2860 }
2861
2862 int rcx_calc_cca( rcx_slope *slope, losig_list *victime )
2863 {
2864 if( slope->CCA < 0.0 ) {
2865 slope->CCA = rcx_getsigcapa( NULL,
2866 victime,
2867 RCX_SIGCAPA_CTK,
2868 RCX_SIGCAPA_LOCAL|RCX_SIGCAPA_GLOBAL,
2869 RCX_SIGCAPA_NORM,
2870 NULL,
2871 0,
2872 TRC_HALF
2873 );
2874 return 1 ;
2875 }
2876 return 0;
2877 }
2878
2879 void rcx_cleardriver( losig_list *losig )
2880 {
2881 rcx_list *rcx ;
2882
2883 rcx = getrcx( losig );
2884
2885 if( rcx ) {
2886
2887 if( rcx->DRIVERSUP ) {
2888 freercxlocon( rcx->DRIVERSUP );
2889 rcx->DRIVERSUP = NULL ;
2890 }
2891
2892 if( rcx->DRIVERSDW ) {
2893 freercxlocon( rcx->DRIVERSDW );
2894 rcx->DRIVERSDW = NULL ;
2895 }
2896 }
2897 }
2898
2899 void rcx_setdriver( losig_list *losig, num_list *driversup, num_list *driversdw )
2900 {
2901 rcx_list *rcx ;
2902
2903 rcx = getrcx( losig );
2904
2905 if( rcx ) {
2906 if( driversup ) {
2907 if( !rcx->DRIVERSUP ) {
2908 rcx->DRIVERSUP = addrcxlocon();
2909 rcx->DRIVERSUP->NAME = "multi-driver-up" ;
2910 rcx->DRIVERSUP->SIG = losig ;
2911 }
2912 if( rcx->DRIVERSUP->PNODE )
2913 freenum( rcx->DRIVERSUP->PNODE );
2914 rcx->DRIVERSUP->PNODE = driversup ;
2915 }
2916 if( driversdw ) {
2917 if( !rcx->DRIVERSDW ) {
2918 rcx->DRIVERSDW = addrcxlocon();
2919 rcx->DRIVERSDW->NAME = "multi-driver-down" ;
2920 rcx->DRIVERSDW->SIG = losig ;
2921 }
2922 if( rcx->DRIVERSDW->PNODE )
2923 freenum( rcx->DRIVERSDW->PNODE );
2924 rcx->DRIVERSDW->PNODE = driversdw ;
2925 }
2926 }
2927 else {
2928 freenum( driversup );
2929 freenum( driversdw );
2930 }
2931 }