1 /****************************************************************************/
3 /* Chaine de CAO & VLSI Alliance */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_graph.c */
8 /* (c) copyright 1994 Laboratoire MASI equipe CAO & VLSI */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
12 /* Auteur(s) : Anthony LESTER le : 20/06/1994 */
14 /* Modifie par : le : ../../.... */
15 /* Modifie par : le : ../../.... */
16 /* Modifie par : le : ../../.... */
18 /****************************************************************************/
20 #include "yag_headers.h"
28 #define GR_NOPRIMVAR 1
30 #define GRAPH_PACKET 4
31 #define NODE_PACKET 20
33 static graph
*EMPTY_GRAPH
= NULL
;
34 static graph
*ALLOC_GRAPH
= NULL
;
36 static gnode_list
*EMPTY_NODE
= NULL
;
38 static graph
*CUR_GRAPH
;
39 static short CUR_TREE
;
40 static cone_list
*CUR_ROOT
;
42 static chain_list
*VAR_LIST
;
45 //static int incomplete;
48 static int total_son_arcs
;
49 static int visited_son_arcs
;
51 static int add_constraints
;
53 #define convergence(node) (node->NUMSONS >= 2 || (node->NUMSONS == 1 && node->DEPTH == 0))
54 #define mark_treebit(node) (node->TREEBIT |= (1 << CUR_TREE))
55 #define unmark_treebit(node) (node->TREEBIT ^= (1 << CUR_TREE))
56 #define in_other_tree(node) (((node->TREEBIT & ~(1 << CUR_TREE)) != 0) ? TRUE : FALSE)
57 #define check_complete(ptgraph) (ptgraph->ROOTNODES == NULL ? TRUE : (ptgraph->ROOTNODES->TYPE & HOLENODE) == 0)
59 static gnode_list
*build(edge_list
*ptedge
, int depth
, int *ptrescode
, int invonly
, int force
);
60 static void update_depth(gnode_list
*ptnode
, int depth
);
61 static void check_memsym_constraint(cone_list
*ptcone
, graph
*ptgraph
);
62 static gnode_list
*add_node(void *object
, long type
, short deep
);
63 static void extra_constraints(gnode_list
*ptnode
, graph
*ptgraph
);
64 static void number_sons(gnode_list
*ptnode
);
65 static void traverse(gnode_list
*ptnode
);
66 static void unmark(gnode_list
*ptnode
);
67 static void count_sons(gnode_list
*ptnode
);
68 static void pick_prims(gnode_list
*ptnode
);
69 static chain_list
*add_primvar(chain_list
*list
, gnode_list
*ptnode
);
70 static void reduce(graph
*ptgraph
, gnode_list
*ptnode
);
71 static void prop_search(gnode_list
*ptnode
);
73 /****************************************************************************
74 * function yagBuildGraph(); *
75 ****************************************************************************/
78 yagBuildGraph(edge_list
*ptedgelist
, cone_list
*rootcone
, int force
)
88 if ((rootcone
&& rootcone
->TYPE
& YAG_HASDUAL
) != 0) save_hasdual
= TRUE
;
89 else save_hasdual
= FALSE
;
90 if (rootcone
) rootcone
->TYPE
&= ~YAG_HASDUAL
;
92 CUR_GRAPH
= yagNewGraph();
96 if (rootcone
&& (rootcone
->TYPE
& YAG_STOP
) == YAG_STOP
) stopcone
= TRUE
;
97 else stopcone
= FALSE
;
99 /* create root nodes separately in order to */
100 /* detect reconvergence onto a root */
102 for (ptedge
= ptedgelist
; ptedge
!= NULL
; ptedge
= ptedge
->NEXT
) {
103 if ((ptedge
->TYPE
& CNS_BLEEDER
) == CNS_BLEEDER
) continue;
104 CUR_TREE
= CUR_GRAPH
->WIDTH
;
105 if ((ptedge
->TYPE
& CNS_EXT
) == CNS_EXT
) {
106 ptcon
= ptedge
->UEDGE
.LOCON
;
107 ptnode
= add_node(ptcon
, ROOT_NODE
|EXT
, 0);
108 if (getptype(ptcon
->USER
, YAG_CONSTRAINT_PTYPE
) != NULL
) {
109 ptnode
->TYPE
|= CONSTRAINT_NODE
;
113 ptcone
= ptedge
->UEDGE
.CONE
;
114 ptnode
= add_node(ptcone
, ROOT_NODE
|CONE_TYPE
, 0);
115 if ((ptcone
->TYPE
& YAG_CONSTRAINT
) == YAG_CONSTRAINT
) {
116 ptnode
->TYPE
|= CONSTRAINT_NODE
;
118 if ((ptcone
->TYPE
& CNS_MEMSYM
) != 0) check_memsym_constraint(ptcone
, CUR_GRAPH
);
120 CUR_GRAPH
->ROOTNODES
= addptype(CUR_GRAPH
->ROOTNODES
, 0, ptnode
);
124 for (ptedge
= ptedgelist
; ptedge
!= NULL
; ptedge
= ptedge
->NEXT
) {
125 if ((ptedge
->TYPE
& CNS_BLEEDER
) == CNS_BLEEDER
) continue;
126 CUR_TREE
= CUR_GRAPH
->WIDTH
;
127 ptnode
= build(ptedge
, 0, &rescode
, TRUE
, force
);
129 if (rootcone
&& save_hasdual
) rootcone
->TYPE
|= YAG_HASDUAL
;
133 /****************************************************************************
134 * function yagRootGraph(); *
135 ****************************************************************************/
138 yagRootGraph(graph
*ptgraph
, cone_list
*ptcone
)
144 ptnode
= add_node(ptcone
, CONE_TYPE
|ROOT_NODE
, 0);
146 for (ptlist
= ptgraph
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
147 ptnode
->FATHERS
= addchain(ptnode
->FATHERS
, ptlist
->DATA
);
148 ((gnode_list
*)ptlist
->DATA
)->TYPE
&= ~ROOT_NODE
;
150 freeptype(ptgraph
->ROOTNODES
);
151 ptgraph
->ROOTNODES
= addptype(NULL
, 0, ptnode
);
156 /****************************************************************************
157 * function build(); *
158 ****************************************************************************/
161 build(edge_list
*ptedge
, int depth
, int *ptrescode
, int invonly
, int force
)
166 gnode_list
*ptinnode
;
168 edge_list
*inputlist
;
175 *ptrescode
= GR_NOERR
;
178 if ((ptedge
->TYPE
& CNS_EXT
) == CNS_EXT
) {
179 ptcon
= ptedge
->UEDGE
.LOCON
;
180 ptnode
= (gnode_list
*)gethtitem(CUR_GRAPH
->HASHTAB
, ptcon
);
181 if (ptnode
!= (gnode_list
*)EMPTYHT
) {
182 if (depth
> ptnode
->DEPTH
) ptnode
->DEPTH
= depth
;
185 ptnode
= add_node(ptcon
, EXT
, depth
);
186 /* check for a constraint */
187 if (getptype(ptcon
->USER
, YAG_CONSTRAINT_PTYPE
) != NULL
) {
188 ptnode
->TYPE
|= CONSTRAINT_NODE
;
196 ptcone
= ptedge
->UEDGE
.CONE
;
200 if ((ptcone
->TYPE
& YAG_VISITED
) != 0) {
201 *ptrescode
= GR_LOOP
;
204 ptcone
->TYPE
|= YAG_VISITED
;
206 nodetype
= CONE_TYPE
;
207 if ((ptcone
->TYPE
& CNS_POWER
) == CNS_POWER
) nodetype
|= CONSTBIT
;
208 if ((ptcone
->TYPE
& YAG_FORCEPRIM
) == YAG_FORCEPRIM
) nodetype
|= FORCEPRIM_NODE
;
210 /* check depth limit */
213 if (depth
>= YAG_CONTEXT
->YAG_DEPTH
* 2) tostop
= TRUE
;
216 if (depth
>= (YAG_CONTEXT
->YAG_DEPTH
<9?9:YAG_CONTEXT
->YAG_DEPTH
) * 2) tostop
= TRUE
;
219 /* set depth to zero if reconverging */
220 /* onto a rootnode */
221 ptnode
= (gnode_list
*)gethtitem(CUR_GRAPH
->HASHTAB
, ptcone
);
222 if (ptnode
!= (gnode_list
*)EMPTYHT
) {
223 if (ptnode
->DEPTH
== 0) depth
= 0;
226 /* check stop conditions */
227 if (!force
|| depth
!= 0) {
228 tostop
= ((ptcone
->TYPE
& (CNS_POWER
|CNS_LATCH
|CNS_MEMSYM
|CNS_RS
|YAG_CONSTRAINT
|YAG_STOP
)) != 0);
229 tostop
= (tostop
|| ((ptcone
->TYPE
& CNS_CONFLICT
) != 0 && (ptcone
->TYPE
& YAG_HASDUAL
) == 0 && (ptcone
->TECTYPE
& YAG_RESCONF
) == 0));
230 if ((ptcone
->TYPE
& CNS_EXT
) != 0) tostop
= (tostop
|| !yagIsOutput(ptcone
));
231 if (!YAG_CONTEXT
->YAG_PROP_HZ
) tostop
= (tostop
|| ((ptcone
->TYPE
& CNS_TRI
) != 0));
235 /* check for hole for graph completeness */
236 hole
= !tostop
&& ((ptcone
->TYPE
& YAG_PARTIAL
) != 0 && (ptcone
->TECTYPE
& CNS_DUAL_CMOS
) == 0);
238 if ((!tostop
&& !hole
) || (force
&& depth
== 0)) {
240 if (ptnode
!= (gnode_list
*)EMPTYHT
) {
242 /* return if reconverging onto a loop cut */
243 if ((ptnode
->TYPE
& LOOP_NODE
) != 0) {
244 ptcone
->TYPE
&= ~YAG_VISITED
;
248 /* return if reconverging onto */
249 /* a node of greater depth */
251 if (ptnode
->DEPTH
>= depth
) {
252 ptcone
->TYPE
&= ~YAG_VISITED
;
255 else update_depth(ptnode
, depth
);
258 else ptnode
= add_node(ptcone
, nodetype
, depth
);
260 addfathers
= (ptnode
->FATHERS
== NULL
);
264 //if ((ptcone->TYPE & CNS_CONFLICT) != 0 && (ptcone->TYPE & YAG_HASDUAL) != 0) {
265 if ((ptcone
->TYPE
& YAG_HASDUAL
) != 0 && (!force
|| depth
!= 0)) {
266 inputlist
= (edge_list
*)getptype(ptcone
->USER
, YAG_DUALINPUTS_PTYPE
)->DATA
;
268 else inputlist
= ptcone
->INCONE
;
270 if (!(inputlist
&& (inputlist
->NEXT
== NULL
))) invonly
=0;
272 for (input
= inputlist
; input
!= NULL
; input
= input
->NEXT
) {
274 if ((input
->TYPE
& CNS_BLEEDER
) == CNS_BLEEDER
) continue;
275 ptinnode
= build(input
, depth
+1, ptrescode
, invonly
, force
);
276 if (ptinnode
!= NULL
) {
278 ptnode
->FATHERS
= addchain(ptnode
->FATHERS
, ptinnode
);
281 else if (*ptrescode
== GR_LOOP
) {
282 if (!force
|| depth
!= 0) {
283 if (ptnode
->FATHERS
!= NULL
) {
284 freechain(ptnode
->FATHERS
);
285 ptnode
->FATHERS
= NULL
;
287 ptnode
->TYPE
|= LOOP_NODE
;
292 if (((*ptrescode
) & GR_STOP
) == 0) stop
= FALSE
;
296 ptnode
= (gnode_list
*)gethtitem(CUR_GRAPH
->HASHTAB
, ptcone
);
297 if (ptnode
!= (gnode_list
*)EMPTYHT
) {
298 if (ptnode
->DEPTH
!= 0) {
299 if (depth
> ptnode
->DEPTH
) ptnode
->DEPTH
= depth
;
303 ptnode
= add_node((void *)ptcone
, nodetype
, depth
);
305 if (tostop
|| hole
) stop
= TRUE
;
307 /* check for a contraint */
308 if ((ptcone
->TYPE
& YAG_CONSTRAINT
) == YAG_CONSTRAINT
) {
309 ptnode
->TYPE
|= CONSTRAINT_NODE
;
311 if ((ptcone
->TYPE
& CNS_MEMSYM
) != 0) check_memsym_constraint(ptcone
, CUR_GRAPH
);
313 ptcone
->TYPE
&= ~YAG_VISITED
;
314 if (ptcone
== CUR_ROOT
) hole
= FALSE
;
317 if (hole
&& !tostop
) {
318 ptnode
->TYPE
|= HOLENODE
;
321 ptnode
->TYPE
|= STOPNODE
;
322 *ptrescode
|= GR_STOP
;
329 update_depth(gnode_list
*ptnode
, int depth
)
333 /* reconverging onto a root */
334 if (ptnode
->DEPTH
== 0) return;
336 if (depth
> ptnode
->DEPTH
) {
337 ptnode
->DEPTH
= depth
;
339 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
340 update_depth((gnode_list
*)ptchain
->DATA
, depth
+1);
346 check_memsym_constraint(cone_list
*ptcone
, graph
*ptgraph
)
348 cone_list
*ptloopcone
;
349 gnode_list
*ptnode
, *ptloopnode
;
352 if ((ptcone
->TYPE
& CNS_MEMSYM
) != CNS_MEMSYM
) return;
353 if ((ptnode
= (gnode_list
*)gethtitem(CUR_GRAPH
->HASHTAB
, ptcone
)) == (gnode_list
*)EMPTYHT
) return;
354 if ((ptuser
= getptype(ptcone
->USER
, YAG_MEMORY_PTYPE
)) != NULL
) {
355 ptloopcone
= (cone_list
*)ptuser
->DATA
;
356 if ((ptloopnode
= (gnode_list
*)gethtitem(CUR_GRAPH
->HASHTAB
, ptloopcone
)) != (gnode_list
*)EMPTYHT
) {
357 ptnode
->TYPE
|= MEMSYM_NODE
;
358 ptloopnode
->TYPE
|= MEMSYM_NODE
;
363 /****************************************************************************
364 * function add_node(); *
365 ****************************************************************************/
368 add_node(void *object
, long type
, short deep
)
374 if (EMPTY_NODE
== NULL
) {
375 ptnode
= (gnode_list
*)mbkalloc(NODE_PACKET
* sizeof(gnode_list
));
377 for (i
=1; i
<NODE_PACKET
; i
++) {
378 ptnode
->NEXT
= ptnode
+ 1;
384 EMPTY_NODE
= EMPTY_NODE
->NEXT
;
385 ptnode
->NEXT
= CUR_GRAPH
->HEADNODE
;
386 CUR_GRAPH
->HEADNODE
= ptnode
;
388 ptnode
->OBJECT
.PTR
= object
;
389 ptnode
->VISITED
= FALSE
;
391 ptnode
->DEPTH
= deep
;
392 if (local
) ptnode
->TREEBIT
= 1 << CUR_TREE
;
393 else ptnode
->TREEBIT
= 0;
396 ptnode
->FATHERS
= NULL
;
398 addhtitem(CUR_GRAPH
->HASHTAB
, object
, (long)ptnode
);
400 if ((type
& CONE_TYPE
) == CONE_TYPE
) name
= ((cone_list
*)object
)->NAME
;
401 else name
= ((locon_list
*)object
)->NAME
;
402 addhtitem(CUR_GRAPH
->NAMEHASHTAB
, name
, (long)ptnode
);
407 /****************************************************************************
408 * function yagNewGraph(); *
409 ****************************************************************************/
417 if (EMPTY_GRAPH
== NULL
) {
418 ptgraph
= (graph
*)mbkalloc(GRAPH_PACKET
* sizeof(graph
));
419 EMPTY_GRAPH
= ptgraph
;
420 for (i
=1; i
<GRAPH_PACKET
; i
++) {
421 ptgraph
->NEXT
= ptgraph
+ 1;
424 ptgraph
->NEXT
= NULL
;
426 ptgraph
= EMPTY_GRAPH
;
427 EMPTY_GRAPH
= EMPTY_GRAPH
->NEXT
;
428 ptgraph
->NEXT
= ALLOC_GRAPH
;
429 ALLOC_GRAPH
= ptgraph
;
431 ptgraph
->ROOTNODES
= NULL
;
432 ptgraph
->PRIMVARS
= NULL
;
433 ptgraph
->HEADNODE
= NULL
;
434 ptgraph
->HASHTAB
= addht(40);
435 ptgraph
->NAMEHASHTAB
= addht(40);
436 ptgraph
->CONSTRAINTS
= NULL
;
437 ptgraph
->EXTRA_CONSTRAINTS
= NULL
;
438 ptgraph
->COMPLETE
= FALSE
;
444 /****************************************************************************
445 * function yagFreeGraph(); *
446 ****************************************************************************/
449 yagFreeGraph(graph
*ptgraph
)
451 gnode_list
*ptnode
, *ptlastnode
= NULL
;
454 if (ptgraph
== NULL
) yagBug(DBG_NULL_PTR
, "yagFreeGraph", NULL
, NULL
, 0);
456 delht(ptgraph
->HASHTAB
);
457 delht(ptgraph
->NAMEHASHTAB
);
459 for (ptnode
= ptgraph
->HEADNODE
; ptnode
!= NULL
; ptnode
= ptnode
->NEXT
) {
460 freechain(ptnode
->FATHERS
);
461 freechain(ptnode
->SONS
);
464 if (ptlastnode
!= NULL
) {
465 ptlastnode
->NEXT
= EMPTY_NODE
;
466 EMPTY_NODE
= ptgraph
->HEADNODE
;
467 freeptype(ptgraph
->ROOTNODES
);
468 freechain(ptgraph
->PRIMVARS
);
469 freeptype(ptgraph
->CONSTRAINTS
);
470 for (ptptype
= ptgraph
->EXTRA_CONSTRAINTS
; ptptype
; ptptype
= ptptype
->NEXT
) {
471 freechain((chain_list
*)ptptype
->TYPE
);
472 freeExpr((chain_list
*)ptptype
->DATA
);
474 freeptype(ptgraph
->EXTRA_CONSTRAINTS
);
477 ALLOC_GRAPH
= ptgraph
->NEXT
;
478 ptgraph
->NEXT
= EMPTY_GRAPH
;
479 EMPTY_GRAPH
= ptgraph
;
482 /****************************************************************************
483 * function yagTraverseGraph(); *
484 ****************************************************************************/
487 yagAddExtraConstraints(graph
*ptgraph
)
491 for (ptlist
= ptgraph
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
492 extra_constraints((gnode_list
*)ptlist
->DATA
, ptgraph
);
494 for (ptlist
= ptgraph
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
495 unmark((gnode_list
*)ptlist
->DATA
);
500 extra_constraints(gnode_list
*ptnode
, graph
*ptgraph
)
504 cone_list
*ptcone
, *ptinvcone
;
505 gnode_list
*ptinvnode
;
507 chain_list
*tempexpr
;
509 if (ptnode
->VISITED
) return;
510 ptnode
->VISITED
= TRUE
;
512 if ((ptnode
->TYPE
& EXT
) == 0) {
513 ptcone
= ptnode
->OBJECT
.CONE
;
514 if ((ptuser
= getptype(ptcone
->USER
, CNS_INVCONE
)) != NULL
) {
515 for (ptchain
= (chain_list
*)ptuser
->DATA
; ptchain
; ptchain
= ptchain
->NEXT
) {
516 ptinvcone
= (cone_list
*)ptchain
->DATA
;
517 support
= addchain(NULL
, ptcone
->NAME
);
518 support
= addchain(support
, ptinvcone
->NAME
);
519 tempexpr
= createExpr(OR
);
520 addQExpr(tempexpr
, createAtom(ptcone
->NAME
));
521 addQExpr(tempexpr
, createAtom(ptinvcone
->NAME
));
522 ptgraph
->CONSTRAINTS
= addptype(ptgraph
->CONSTRAINTS
, (long)support
, (void *)tempexpr
);
523 ptgraph
->EXTRA_CONSTRAINTS
= addptype(ptgraph
->EXTRA_CONSTRAINTS
, (long)support
, (void *)tempexpr
);
524 tempexpr
= createExpr(AND
);
525 addQExpr(tempexpr
, createAtom(ptcone
->NAME
));
526 addQExpr(tempexpr
, createAtom(ptinvcone
->NAME
));
527 tempexpr
= notExpr(tempexpr
);
528 ptgraph
->CONSTRAINTS
= addptype(ptgraph
->CONSTRAINTS
, (long)support
, (void *)tempexpr
);
529 ptgraph
->EXTRA_CONSTRAINTS
= addptype(ptgraph
->EXTRA_CONSTRAINTS
, (long)yagCopyChainList(support
), (void *)tempexpr
);
532 if (((ptnode
->TYPE
& MEMSYM_NODE
) == MEMSYM_NODE
) && (ptuser
= getptype(ptcone
->USER
, YAG_MEMORY_PTYPE
)) != NULL
) {
533 ptinvcone
= (cone_list
*)ptuser
->DATA
;
534 ptinvnode
= (gnode_list
*)gethtitem(CUR_GRAPH
->HASHTAB
, ptinvcone
);
535 if (ptinvnode
!= (gnode_list
*)EMPTYHT
) {
536 ptinvnode
->VISITED
= TRUE
;
537 support
= addchain(NULL
, ptcone
->NAME
);
538 support
= addchain(support
, ptinvcone
->NAME
);
539 tempexpr
= createExpr(OR
);
540 addQExpr(tempexpr
, createAtom(ptcone
->NAME
));
541 addQExpr(tempexpr
, createAtom(ptinvcone
->NAME
));
542 ptgraph
->CONSTRAINTS
= addptype(ptgraph
->CONSTRAINTS
, (long)support
, (void *)tempexpr
);
543 ptgraph
->EXTRA_CONSTRAINTS
= addptype(ptgraph
->EXTRA_CONSTRAINTS
, (long)support
, (void *)tempexpr
);
544 tempexpr
= createExpr(AND
);
545 addQExpr(tempexpr
, createAtom(ptcone
->NAME
));
546 addQExpr(tempexpr
, createAtom(ptinvcone
->NAME
));
547 tempexpr
= notExpr(tempexpr
);
548 ptgraph
->CONSTRAINTS
= addptype(ptgraph
->CONSTRAINTS
, (long)support
, (void *)tempexpr
);
549 ptgraph
->EXTRA_CONSTRAINTS
= addptype(ptgraph
->EXTRA_CONSTRAINTS
, (long)yagCopyChainList(support
), (void *)tempexpr
);
553 if ((ptnode
->TYPE
& PRIMNODE
) == 0) {
554 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
555 extra_constraints((gnode_list
*)ptchain
->DATA
, ptgraph
);
560 /****************************************************************************
561 * function yagTraverseGraph(); *
562 ****************************************************************************/
565 yagTraverseGraph(graph
*ptgraph
)
570 for (ptlist
= ptgraph
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
571 number_sons((gnode_list
*)ptlist
->DATA
);
573 for (ptlist
= ptgraph
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
574 unmark((gnode_list
*)ptlist
->DATA
);
577 for (ptlist
= ptgraph
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
578 traverse((gnode_list
*)ptlist
->DATA
);
582 for (ptlist
= ptgraph
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
583 pick_prims((gnode_list
*)ptlist
->DATA
);
585 for (ptlist
= ptgraph
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
586 unmark((gnode_list
*)ptlist
->DATA
);
588 ptgraph
->COMPLETE
= (numholes
< 1);
589 ptgraph
->PRIMVARS
= VAR_LIST
;
593 number_sons(gnode_list
*ptnode
)
596 gnode_list
*ptfather
;
597 int outdepth
= FALSE
;
598 int forceprim
= FALSE
;
601 if (ptnode
->VISITED
) return;
602 ptnode
->VISITED
= TRUE
;
604 if (ptnode
->DEPTH
>= YAG_CONTEXT
->YAG_DEPTH
) {
605 if (ptnode
->FATHERS
!= NULL
) {
606 freechain(ptnode
->FATHERS
);
607 ptnode
->FATHERS
= NULL
;
612 if ((ptnode
->TYPE
& HOLENODE
) != 0) {
616 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
617 ptfather
= (gnode_list
*)ptchain
->DATA
;
618 if (ptfather
->DEPTH
> YAG_CONTEXT
->YAG_DEPTH
) outdepth
= TRUE
;
619 if ((ptfather
->TYPE
& FORCEPRIM_NODE
) != 0) forceprim
= TRUE
;
621 if (outdepth
&& !forceprim
) {
622 freechain(ptnode
->FATHERS
);
623 ptnode
->FATHERS
= NULL
;
627 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
628 number_sons((gnode_list
*)ptchain
->DATA
);
633 traverse(gnode_list
*ptnode
)
637 if ((ptnode
->TYPE
& TRAVERSED
) != 0) return;
638 ptnode
->TYPE
|= TRAVERSED
;
640 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
641 traverse((gnode_list
*)ptchain
->DATA
);
645 visited_son_arcs
= 0;
647 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
648 count_sons((gnode_list
*)ptchain
->DATA
);
650 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
651 unmark((gnode_list
*)ptchain
->DATA
);
654 if (total_son_arcs
== visited_son_arcs
) ptnode
->TYPE
|= PRIMNODE
;
658 unmark(gnode_list
*ptnode
)
662 if (ptnode
->VISITED
== FALSE
) return;
663 ptnode
->VISITED
= FALSE
;
665 if ((ptnode
->TYPE
& PRIMNODE
) != 0) return;
667 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
668 unmark((gnode_list
*)ptchain
->DATA
);
673 count_sons(gnode_list
*ptnode
)
679 if (ptnode
->VISITED
) return;
680 ptnode
->VISITED
= TRUE
;
682 total_son_arcs
+= ptnode
->NUMSONS
;
684 /* add additional dependancy to constrained node to force it PRIM */
685 if ((ptnode
->TYPE
& (CONSTBIT
|CONSTRAINT_NODE
|FORCEPRIM_NODE
|MEMSYM_NODE
)) != 0) total_son_arcs
++;
687 if ((ptnode
->TYPE
& PRIMNODE
) == 0) {
688 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
689 count_sons((gnode_list
*)ptchain
->DATA
);
695 pick_prims(gnode_list
*ptnode
)
699 if (ptnode
->VISITED
) return;
700 ptnode
->VISITED
= TRUE
;
702 if ((ptnode
->TYPE
& CONSTRAINT_NODE
) != 0) {
703 if ((ptnode
->TYPE
& EXT
) != 0) yagTagConstraint(ptnode
->OBJECT
.LOCON
->NAME
);
704 else yagTagConstraint(ptnode
->OBJECT
.CONE
->NAME
);
707 if ((ptnode
->TYPE
& PRIMNODE
) != 0) {
708 VAR_LIST
= add_primvar(VAR_LIST
, ptnode
);
711 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
712 pick_prims((gnode_list
*)ptchain
->DATA
);
717 /****************************************************************************
718 * miscellaneous utility functions *
719 ****************************************************************************/
721 /*--------------------------------------------------*
722 | Add a node to the main list of primary variables |
723 *--------------------------------------------------*/
726 add_primvar(chain_list
*list
, gnode_list
*ptnode
)
728 return addchain(list
, ptnode
);
731 /*----------------------------------------------*
732 | Return the node pointer to the named father |
733 | of the given node |
734 *-----------------------------------------------*/
737 yagGetNodeFather(gnode_list
*ptnode
, char *name
)
740 gnode_list
*ptfather
;
743 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
744 ptfather
= (gnode_list
*)ptchain
->DATA
;
745 if ((ptfather
->TYPE
& EXT
) != 0) {
746 nodename
= ptfather
->OBJECT
.LOCON
->NAME
;
749 nodename
= ptfather
->OBJECT
.CONE
->NAME
;
751 if (nodename
== name
) break;
753 if (ptchain
== NULL
) {
754 yagBug(DBG_NO_FATHER
, "yagGetNodeFather", name
, ptnode
->OBJECT
.CONE
->NAME
, 0);
757 else return ptfather
;
760 /****************************************************************************
761 * function yagExtendSupportRoot(); *
762 ****************************************************************************/
763 /*------------------------------------------*
764 | Extend the support graph root of a given |
765 | graph by the given object |
766 *-------------------------------------------*/
769 yagExtendSupportRoot(graph
*ptgraph
, cone_list
*ptcone
, long roottype
)
776 CUR_TREE
= ptgraph
->WIDTH
;
780 ptnode
= (gnode_list
*)gethtitem(ptgraph
->HASHTAB
, ptcone
);
781 if (ptnode
== (gnode_list
*)EMPTYHT
) {
782 ptnode
= add_node(ptcone
, CONE_TYPE
, 0);
785 else mark_treebit(ptnode
);
787 ptgraph
->ROOTNODES
= addptype(ptgraph
->ROOTNODES
, roottype
, ptnode
);
789 for (ptroot
= ptgraph
->ROOTNODES
; ptroot
; ptroot
= ptroot
->NEXT
) {
790 ((gnode_list
*)ptroot
->DATA
)->TYPE
|= ptroot
->TYPE
;
798 /****************************************************************************
799 * function yagExtendSupportGraph(); *
800 ****************************************************************************/
801 /*------------------------------------------*
802 | Update the given graph given a node and |
803 | its newly obtained father list |
804 *-------------------------------------------*/
807 yagExtendSupportGraph(graph
*ptgraph
, gnode_list
*ptnode
, chain_list
*ptfatherlist
)
811 gnode_list
*ptfather
;
813 CUR_TREE
= ptgraph
->WIDTH
- 1;
816 for (ptchain
= ptfatherlist
; ptchain
; ptchain
= ptchain
->NEXT
) {
817 ptcone
= ((gnode_list
*)ptchain
->DATA
)->OBJECT
.CONE
;
819 ptfather
= (gnode_list
*)gethtitem(ptgraph
->HASHTAB
, ptcone
);
820 if (ptfather
== (gnode_list
*)EMPTYHT
) {
821 ptfather
= add_node(ptcone
, CONE_TYPE
, 0);
824 ptfather
->SONS
= addchain(ptfather
->SONS
, ptnode
);
825 ptnode
->FATHERS
= addchain(ptnode
->FATHERS
, ptfather
);
829 /****************************************************************************
830 * function yagReduceSupportGraph(); *
831 ****************************************************************************/
832 /*------------------------------------------*
833 | Reduce the given graph by removing the |
834 | most recently added root node |
835 *-------------------------------------------*/
838 yagReduceSupportGraph(graph
*ptgraph
)
843 CUR_TREE
= ptgraph
->WIDTH
- 1;
845 if (ptgraph
== NULL
) yagBug(DBG_NULL_PTR
, "yagReduceSupportGraph", NULL
, NULL
, 0);
847 for (ptroot
= ptgraph
->ROOTNODES
; ptroot
; ptroot
= ptroot
->NEXT
) {
848 ((gnode_list
*)ptroot
->DATA
)->TYPE
&= ~(TN_NODE
|TP_NODE
);
851 ptnode
= (gnode_list
*)ptgraph
->ROOTNODES
->DATA
;
852 reduce(ptgraph
, ptnode
);
853 ptroot
= ptgraph
->ROOTNODES
;
854 ptgraph
->ROOTNODES
= ptgraph
->ROOTNODES
->NEXT
;
858 ptgraph
->COMPLETE
= check_complete(ptgraph
);
862 reduce(graph
*ptgraph
, gnode_list
*ptnode
)
865 gnode_list
*ptfather
;
867 unmark_treebit(ptnode
);
868 if (in_other_tree(ptnode
)) return;
870 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
871 ptfather
= (gnode_list
*)ptchain
->DATA
;
872 ptfather
->SONS
= yagRmvChain(ptfather
->SONS
, ptnode
);
874 if (ptfather
->NUMSONS
== 0) {
875 ptfather
->TYPE
|= DELETED_NODE
;
876 delhtitem(ptgraph
->HASHTAB
, ptfather
->OBJECT
.PTR
);
880 freechain(ptnode
->FATHERS
);
881 ptnode
->FATHERS
= NULL
;
883 /* beware : node may be its own father hence already treated */
884 if ((ptnode
->TYPE
& DELETED_NODE
) == 0 && ptnode
->NUMSONS
== 0) {
885 ptnode
->TYPE
|= DELETED_NODE
;
886 delhtitem(ptgraph
->HASHTAB
, ptnode
->OBJECT
.PTR
);
890 /****************************************************************************
891 * function yagGetPrimVars(); *
892 ****************************************************************************/
893 /*---------------------------------------------*
894 | Return list of primary variables which |
895 | influence a given node |
896 *---------------------------------------------*/
899 yagGetPrimVars(graph
*ptgraph
, gnode_list
*ptnode
)
902 gnode_list
*ptprimnode
;
907 add_constraints
= FALSE
;
910 if (add_constraints
) {
911 for (ptchain
= ptgraph
->PRIMVARS
; ptchain
; ptchain
= ptchain
->NEXT
) {
912 ptprimnode
= (gnode_list
*)ptchain
->DATA
;
913 if ((ptprimnode
->TYPE
& CONSTRAINT_NODE
) != 0 && !ptprimnode
->VISITED
) {
914 VAR_LIST
= addchain(VAR_LIST
, ptprimnode
);
924 yagGetJustPrimVars(graph
*ptgraph
, gnode_list
*ptnode
)
935 prop_search(gnode_list
*ptnode
)
939 if (ptnode
->VISITED
) return;
940 ptnode
->VISITED
= TRUE
;
941 if ((ptnode
->TYPE
& PRIMNODE
) != 0) {
942 if ((ptnode
->TYPE
& CONSTRAINT_NODE
) != 0) add_constraints
= TRUE
;
943 VAR_LIST
= addchain(VAR_LIST
, ptnode
);
947 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
948 prop_search((gnode_list
*)ptchain
->DATA
);
953 static chain_list
*RESCHAIN
;
956 isNonPrimaryUsed(gnode_list
*ptnode
)
959 gnode_list
*ptinnode
;
963 ptnode
->VISITED
= TRUE
;
964 if ((ptnode
->TYPE
& PRIMNODE
) != 0) return;
966 RESCHAIN
= addchain(RESCHAIN
, ptnode
);
968 for (ptchain
= ptnode
->FATHERS
; ptchain
; ptchain
= ptchain
->NEXT
) {
969 ptinnode
= (gnode_list
*) ptchain
->DATA
;
970 isNonPrimaryUsed(ptinnode
);
975 yagGetNonPrimaryUsedNodes(graph
*ptgraph
)
982 for (ptroots
= ptgraph
->ROOTNODES
; ptroots
; ptroots
= ptroots
->NEXT
) {
983 ptnode
= (gnode_list
*) ptroots
->DATA
;
984 isNonPrimaryUsed(ptnode
);
986 for (ptroots
= ptgraph
->ROOTNODES
; ptroots
; ptroots
= ptroots
->NEXT
) {
987 ptnode
= (gnode_list
*) ptroots
->DATA
;