emergency commit
[cl-cudd.git] / distr / cudd / cuddCheck.c
blob74eed40762ba800230b681e9cb448b09bf42c680
1 /**CFile***********************************************************************
3 FileName [cuddCheck.c]
5 PackageName [cudd]
7 Synopsis [Functions to check consistency of data structures.]
9 Description [External procedures included in this module:
10 <ul>
11 <li> Cudd_DebugCheck()
12 <li> Cudd_CheckKeys()
13 </ul>
14 Internal procedures included in this module:
15 <ul>
16 <li> cuddHeapProfile()
17 <li> cuddPrintNode()
18 <li> cuddPrintVarGroups()
19 </ul>
20 Static procedures included in this module:
21 <ul>
22 <li> debugFindParent()
23 </ul>
26 SeeAlso []
28 Author [Fabio Somenzi]
30 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
32 All rights reserved.
34 Redistribution and use in source and binary forms, with or without
35 modification, are permitted provided that the following conditions
36 are met:
38 Redistributions of source code must retain the above copyright
39 notice, this list of conditions and the following disclaimer.
41 Redistributions in binary form must reproduce the above copyright
42 notice, this list of conditions and the following disclaimer in the
43 documentation and/or other materials provided with the distribution.
45 Neither the name of the University of Colorado nor the names of its
46 contributors may be used to endorse or promote products derived from
47 this software without specific prior written permission.
49 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
52 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
53 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
54 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
55 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
57 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
59 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 POSSIBILITY OF SUCH DAMAGE.]
62 ******************************************************************************/
64 #include "util.h"
65 #include "cuddInt.h"
67 /*---------------------------------------------------------------------------*/
68 /* Constant declarations */
69 /*---------------------------------------------------------------------------*/
72 /*---------------------------------------------------------------------------*/
73 /* Stucture declarations */
74 /*---------------------------------------------------------------------------*/
77 /*---------------------------------------------------------------------------*/
78 /* Type declarations */
79 /*---------------------------------------------------------------------------*/
82 /*---------------------------------------------------------------------------*/
83 /* Variable declarations */
84 /*---------------------------------------------------------------------------*/
86 #ifndef lint
87 static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.35 2009/03/08 02:49:01 fabio Exp $";
88 #endif
90 /*---------------------------------------------------------------------------*/
91 /* Macro declarations */
92 /*---------------------------------------------------------------------------*/
95 /**AutomaticStart*************************************************************/
97 /*---------------------------------------------------------------------------*/
98 /* Static function prototypes */
99 /*---------------------------------------------------------------------------*/
101 static void debugFindParent (DdManager *table, DdNode *node);
102 #if 0
103 static void debugCheckParent (DdManager *table, DdNode *node);
104 #endif
106 /**AutomaticEnd***************************************************************/
109 /*---------------------------------------------------------------------------*/
110 /* Definition of exported functions */
111 /*---------------------------------------------------------------------------*/
114 /**Function********************************************************************
116 Synopsis [Checks for inconsistencies in the DD heap.]
118 Description [Checks for inconsistencies in the DD heap:
119 <ul>
120 <li> node has illegal index
121 <li> live node has dead children
122 <li> node has illegal Then or Else pointers
123 <li> BDD/ADD node has identical children
124 <li> ZDD node has zero then child
125 <li> wrong number of total nodes
126 <li> wrong number of dead nodes
127 <li> ref count error at node
128 </ul>
129 Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is
130 not enough memory; 1 otherwise.]
132 SideEffects [None]
134 SeeAlso [Cudd_CheckKeys]
136 ******************************************************************************/
138 Cudd_DebugCheck(
139 DdManager * table)
141 unsigned int i;
142 int j,count;
143 int slots;
144 DdNodePtr *nodelist;
145 DdNode *f;
146 DdNode *sentinel = &(table->sentinel);
147 st_table *edgeTable; /* stores internal ref count for each node */
148 st_generator *gen;
149 int flag = 0;
150 int totalNode;
151 int deadNode;
152 int index;
155 edgeTable = st_init_table(st_ptrcmp,st_ptrhash);
156 if (edgeTable == NULL) return(CUDD_OUT_OF_MEM);
158 /* Check the BDD/ADD subtables. */
159 for (i = 0; i < (unsigned) table->size; i++) {
160 index = table->invperm[i];
161 if (i != (unsigned) table->perm[index]) {
162 (void) fprintf(table->err,
163 "Permutation corrupted: invperm[%u] = %d\t perm[%d] = %d\n",
164 i, index, index, table->perm[index]);
166 nodelist = table->subtables[i].nodelist;
167 slots = table->subtables[i].slots;
169 totalNode = 0;
170 deadNode = 0;
171 for (j = 0; j < slots; j++) { /* for each subtable slot */
172 f = nodelist[j];
173 while (f != sentinel) {
174 totalNode++;
175 if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
176 if ((int) f->index != index) {
177 (void) fprintf(table->err,
178 "Error: node has illegal index\n");
179 cuddPrintNode(f,table->err);
180 flag = 1;
182 if ((unsigned) cuddI(table,cuddT(f)->index) <= i ||
183 (unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index)
184 <= i) {
185 (void) fprintf(table->err,
186 "Error: node has illegal children\n");
187 cuddPrintNode(f,table->err);
188 flag = 1;
190 if (Cudd_Regular(cuddT(f)) != cuddT(f)) {
191 (void) fprintf(table->err,
192 "Error: node has illegal form\n");
193 cuddPrintNode(f,table->err);
194 flag = 1;
196 if (cuddT(f) == cuddE(f)) {
197 (void) fprintf(table->err,
198 "Error: node has identical children\n");
199 cuddPrintNode(f,table->err);
200 flag = 1;
202 if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) {
203 (void) fprintf(table->err,
204 "Error: live node has dead children\n");
205 cuddPrintNode(f,table->err);
206 flag =1;
208 /* Increment the internal reference count for the
209 ** then child of the current node.
211 if (st_lookup_int(edgeTable,(char *)cuddT(f),&count)) {
212 count++;
213 } else {
214 count = 1;
216 if (st_insert(edgeTable,(char *)cuddT(f),
217 (char *)(long)count) == ST_OUT_OF_MEM) {
218 st_free_table(edgeTable);
219 return(CUDD_OUT_OF_MEM);
222 /* Increment the internal reference count for the
223 ** else child of the current node.
225 if (st_lookup_int(edgeTable,(char *)Cudd_Regular(cuddE(f)),
226 &count)) {
227 count++;
228 } else {
229 count = 1;
231 if (st_insert(edgeTable,(char *)Cudd_Regular(cuddE(f)),
232 (char *)(long)count) == ST_OUT_OF_MEM) {
233 st_free_table(edgeTable);
234 return(CUDD_OUT_OF_MEM);
236 } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
237 deadNode++;
238 #if 0
239 debugCheckParent(table,f);
240 #endif
241 } else {
242 fprintf(table->err,
243 "Error: node has illegal Then or Else pointers\n");
244 cuddPrintNode(f,table->err);
245 flag = 1;
248 f = f->next;
249 } /* for each element of the collision list */
250 } /* for each subtable slot */
252 if ((unsigned) totalNode != table->subtables[i].keys) {
253 fprintf(table->err,"Error: wrong number of total nodes\n");
254 flag = 1;
256 if ((unsigned) deadNode != table->subtables[i].dead) {
257 fprintf(table->err,"Error: wrong number of dead nodes\n");
258 flag = 1;
260 } /* for each BDD/ADD subtable */
262 /* Check the ZDD subtables. */
263 for (i = 0; i < (unsigned) table->sizeZ; i++) {
264 index = table->invpermZ[i];
265 if (i != (unsigned) table->permZ[index]) {
266 (void) fprintf(table->err,
267 "Permutation corrupted: invpermZ[%u] = %d\t permZ[%d] = %d in ZDD\n",
268 i, index, index, table->permZ[index]);
270 nodelist = table->subtableZ[i].nodelist;
271 slots = table->subtableZ[i].slots;
273 totalNode = 0;
274 deadNode = 0;
275 for (j = 0; j < slots; j++) { /* for each subtable slot */
276 f = nodelist[j];
277 while (f != NULL) {
278 totalNode++;
279 if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
280 if ((int) f->index != index) {
281 (void) fprintf(table->err,
282 "Error: ZDD node has illegal index\n");
283 cuddPrintNode(f,table->err);
284 flag = 1;
286 if (Cudd_IsComplement(cuddT(f)) ||
287 Cudd_IsComplement(cuddE(f))) {
288 (void) fprintf(table->err,
289 "Error: ZDD node has complemented children\n");
290 cuddPrintNode(f,table->err);
291 flag = 1;
293 if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i ||
294 (unsigned) cuddIZ(table,cuddE(f)->index) <= i) {
295 (void) fprintf(table->err,
296 "Error: ZDD node has illegal children\n");
297 cuddPrintNode(f,table->err);
298 cuddPrintNode(cuddT(f),table->err);
299 cuddPrintNode(cuddE(f),table->err);
300 flag = 1;
302 if (cuddT(f) == DD_ZERO(table)) {
303 (void) fprintf(table->err,
304 "Error: ZDD node has zero then child\n");
305 cuddPrintNode(f,table->err);
306 flag = 1;
308 if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) {
309 (void) fprintf(table->err,
310 "Error: ZDD live node has dead children\n");
311 cuddPrintNode(f,table->err);
312 flag =1;
314 /* Increment the internal reference count for the
315 ** then child of the current node.
317 if (st_lookup_int(edgeTable,(char *)cuddT(f),&count)) {
318 count++;
319 } else {
320 count = 1;
322 if (st_insert(edgeTable,(char *)cuddT(f),
323 (char *)(long)count) == ST_OUT_OF_MEM) {
324 st_free_table(edgeTable);
325 return(CUDD_OUT_OF_MEM);
328 /* Increment the internal reference count for the
329 ** else child of the current node.
331 if (st_lookup_int(edgeTable,(char *)cuddE(f),&count)) {
332 count++;
333 } else {
334 count = 1;
336 if (st_insert(edgeTable,(char *)cuddE(f),
337 (char *)(long)count) == ST_OUT_OF_MEM) {
338 st_free_table(edgeTable);
339 table->errorCode = CUDD_MEMORY_OUT;
340 return(CUDD_OUT_OF_MEM);
342 } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
343 deadNode++;
344 #if 0
345 debugCheckParent(table,f);
346 #endif
347 } else {
348 fprintf(table->err,
349 "Error: ZDD node has illegal Then or Else pointers\n");
350 cuddPrintNode(f,table->err);
351 flag = 1;
354 f = f->next;
355 } /* for each element of the collision list */
356 } /* for each subtable slot */
358 if ((unsigned) totalNode != table->subtableZ[i].keys) {
359 fprintf(table->err,
360 "Error: wrong number of total nodes in ZDD\n");
361 flag = 1;
363 if ((unsigned) deadNode != table->subtableZ[i].dead) {
364 fprintf(table->err,
365 "Error: wrong number of dead nodes in ZDD\n");
366 flag = 1;
368 } /* for each ZDD subtable */
370 /* Check the constant table. */
371 nodelist = table->constants.nodelist;
372 slots = table->constants.slots;
374 totalNode = 0;
375 deadNode = 0;
376 for (j = 0; j < slots; j++) {
377 f = nodelist[j];
378 while (f != NULL) {
379 totalNode++;
380 if (f->ref != 0) {
381 if (f->index != CUDD_CONST_INDEX) {
382 fprintf(table->err,"Error: node has illegal index\n");
383 #if SIZEOF_VOID_P == 8
384 fprintf(table->err,
385 " node 0x%lx, id = %u, ref = %u, value = %g\n",
386 (ptruint)f,f->index,f->ref,cuddV(f));
387 #else
388 fprintf(table->err,
389 " node 0x%x, id = %hu, ref = %hu, value = %g\n",
390 (ptruint)f,f->index,f->ref,cuddV(f));
391 #endif
392 flag = 1;
394 } else {
395 deadNode++;
397 f = f->next;
400 if ((unsigned) totalNode != table->constants.keys) {
401 (void) fprintf(table->err,
402 "Error: wrong number of total nodes in constants\n");
403 flag = 1;
405 if ((unsigned) deadNode != table->constants.dead) {
406 (void) fprintf(table->err,
407 "Error: wrong number of dead nodes in constants\n");
408 flag = 1;
410 gen = st_init_gen(edgeTable);
411 while (st_gen(gen, &f, &count)) {
412 if (count > (int)(f->ref) && f->ref != DD_MAXREF) {
413 #if SIZEOF_VOID_P == 8
414 fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
415 #else
416 fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
417 #endif
418 debugFindParent(table,f);
419 flag = 1;
422 st_free_gen(gen);
423 st_free_table(edgeTable);
425 return (flag);
427 } /* end of Cudd_DebugCheck */
430 /**Function********************************************************************
432 Synopsis [Checks for several conditions that should not occur.]
434 Description [Checks for the following conditions:
435 <ul>
436 <li>Wrong sizes of subtables.
437 <li>Wrong number of keys found in unique subtable.
438 <li>Wrong number of dead found in unique subtable.
439 <li>Wrong number of keys found in the constant table
440 <li>Wrong number of dead found in the constant table
441 <li>Wrong number of total slots found
442 <li>Wrong number of maximum keys found
443 <li>Wrong number of total dead found
444 </ul>
445 Reports the average length of non-empty lists. Returns the number of
446 subtables for which the number of keys is wrong.]
448 SideEffects [None]
450 SeeAlso [Cudd_DebugCheck]
452 ******************************************************************************/
454 Cudd_CheckKeys(
455 DdManager * table)
457 int size;
458 int i,j;
459 DdNodePtr *nodelist;
460 DdNode *node;
461 DdNode *sentinel = &(table->sentinel);
462 DdSubtable *subtable;
463 int keys;
464 int dead;
465 int count = 0;
466 int totalKeys = 0;
467 int totalSlots = 0;
468 int totalDead = 0;
469 int nonEmpty = 0;
470 unsigned int slots;
471 int logSlots;
472 int shift;
474 size = table->size;
476 for (i = 0; i < size; i++) {
477 subtable = &(table->subtables[i]);
478 nodelist = subtable->nodelist;
479 keys = subtable->keys;
480 dead = subtable->dead;
481 totalKeys += keys;
482 slots = subtable->slots;
483 shift = subtable->shift;
484 logSlots = sizeof(int) * 8 - shift;
485 if (((slots >> logSlots) << logSlots) != slots) {
486 (void) fprintf(table->err,
487 "Unique table %d is not the right power of 2\n", i);
488 (void) fprintf(table->err,
489 " slots = %u shift = %d\n", slots, shift);
491 totalSlots += slots;
492 totalDead += dead;
493 for (j = 0; (unsigned) j < slots; j++) {
494 node = nodelist[j];
495 if (node != sentinel) {
496 nonEmpty++;
498 while (node != sentinel) {
499 keys--;
500 if (node->ref == 0) {
501 dead--;
503 node = node->next;
506 if (keys != 0) {
507 (void) fprintf(table->err, "Wrong number of keys found \
508 in unique table %d (difference=%d)\n", i, keys);
509 count++;
511 if (dead != 0) {
512 (void) fprintf(table->err, "Wrong number of dead found \
513 in unique table no. %d (difference=%d)\n", i, dead);
515 } /* for each BDD/ADD subtable */
517 /* Check the ZDD subtables. */
518 size = table->sizeZ;
520 for (i = 0; i < size; i++) {
521 subtable = &(table->subtableZ[i]);
522 nodelist = subtable->nodelist;
523 keys = subtable->keys;
524 dead = subtable->dead;
525 totalKeys += keys;
526 totalSlots += subtable->slots;
527 totalDead += dead;
528 for (j = 0; (unsigned) j < subtable->slots; j++) {
529 node = nodelist[j];
530 if (node != NULL) {
531 nonEmpty++;
533 while (node != NULL) {
534 keys--;
535 if (node->ref == 0) {
536 dead--;
538 node = node->next;
541 if (keys != 0) {
542 (void) fprintf(table->err, "Wrong number of keys found \
543 in ZDD unique table no. %d (difference=%d)\n", i, keys);
544 count++;
546 if (dead != 0) {
547 (void) fprintf(table->err, "Wrong number of dead found \
548 in ZDD unique table no. %d (difference=%d)\n", i, dead);
550 } /* for each ZDD subtable */
552 /* Check the constant table. */
553 subtable = &(table->constants);
554 nodelist = subtable->nodelist;
555 keys = subtable->keys;
556 dead = subtable->dead;
557 totalKeys += keys;
558 totalSlots += subtable->slots;
559 totalDead += dead;
560 for (j = 0; (unsigned) j < subtable->slots; j++) {
561 node = nodelist[j];
562 if (node != NULL) {
563 nonEmpty++;
565 while (node != NULL) {
566 keys--;
567 if (node->ref == 0) {
568 dead--;
570 node = node->next;
573 if (keys != 0) {
574 (void) fprintf(table->err, "Wrong number of keys found \
575 in the constant table (difference=%d)\n", keys);
576 count++;
578 if (dead != 0) {
579 (void) fprintf(table->err, "Wrong number of dead found \
580 in the constant table (difference=%d)\n", dead);
582 if ((unsigned) totalKeys != table->keys + table->keysZ) {
583 (void) fprintf(table->err, "Wrong number of total keys found \
584 (difference=%d)\n", (int) (totalKeys-table->keys));
586 if ((unsigned) totalSlots != table->slots) {
587 (void) fprintf(table->err, "Wrong number of total slots found \
588 (difference=%d)\n", (int) (totalSlots-table->slots));
590 if (table->minDead != (unsigned) (table->gcFrac * table->slots)) {
591 (void) fprintf(table->err, "Wrong number of minimum dead found \
592 (%u vs. %u)\n", table->minDead,
593 (unsigned) (table->gcFrac * (double) table->slots));
595 if ((unsigned) totalDead != table->dead + table->deadZ) {
596 (void) fprintf(table->err, "Wrong number of total dead found \
597 (difference=%d)\n", (int) (totalDead-table->dead));
599 (void)printf("Average length of non-empty lists = %g\n",
600 (double) table->keys / (double) nonEmpty);
602 return(count);
604 } /* end of Cudd_CheckKeys */
607 /*---------------------------------------------------------------------------*/
608 /* Definition of internal functions */
609 /*---------------------------------------------------------------------------*/
612 /**Function********************************************************************
614 Synopsis [Prints information about the heap.]
616 Description [Prints to the manager's stdout the number of live nodes for each
617 level of the DD heap that contains at least one live node. It also
618 prints a summary containing:
619 <ul>
620 <li> total number of tables;
621 <li> number of tables with live nodes;
622 <li> table with the largest number of live nodes;
623 <li> number of nodes in that table.
624 </ul>
625 If more than one table contains the maximum number of live nodes,
626 only the one of lowest index is reported. Returns 1 in case of success
627 and 0 otherwise.]
629 SideEffects [None]
631 SeeAlso []
633 ******************************************************************************/
635 cuddHeapProfile(
636 DdManager * dd)
638 int ntables = dd->size;
639 DdSubtable *subtables = dd->subtables;
640 int i, /* loop index */
641 nodes, /* live nodes in i-th layer */
642 retval, /* return value of fprintf */
643 largest = -1, /* index of the table with most live nodes */
644 maxnodes = -1, /* maximum number of live nodes in a table */
645 nonempty = 0; /* number of tables with live nodes */
647 /* Print header. */
648 #if SIZEOF_VOID_P == 8
649 retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n",
650 (ptruint) dd);
651 #else
652 retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n",
653 (ptruint) dd);
654 #endif
655 if (retval == EOF) return 0;
657 /* Print number of live nodes for each nonempty table. */
658 for (i=0; i<ntables; i++) {
659 nodes = subtables[i].keys - subtables[i].dead;
660 if (nodes) {
661 nonempty++;
662 retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes);
663 if (retval == EOF) return 0;
664 if (nodes > maxnodes) {
665 maxnodes = nodes;
666 largest = i;
671 nodes = dd->constants.keys - dd->constants.dead;
672 if (nodes) {
673 nonempty++;
674 retval = fprintf(dd->out,"const: %5d nodes\n", nodes);
675 if (retval == EOF) return 0;
676 if (nodes > maxnodes) {
677 maxnodes = nodes;
678 largest = CUDD_CONST_INDEX;
682 /* Print summary. */
683 retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ",
684 ntables+1, nonempty, largest);
685 if (retval == EOF) return 0;
686 retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes);
687 if (retval == EOF) return 0;
689 return(1);
691 } /* end of cuddHeapProfile */
694 /**Function********************************************************************
696 Synopsis [Prints out information on a node.]
698 Description [Prints out information on a node.]
700 SideEffects [None]
702 SeeAlso []
704 ******************************************************************************/
705 void
706 cuddPrintNode(
707 DdNode * f,
708 FILE *fp)
710 f = Cudd_Regular(f);
711 #if SIZEOF_VOID_P == 8
712 (void) fprintf(fp," node 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
713 #else
714 (void) fprintf(fp," node 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
715 #endif
717 } /* end of cuddPrintNode */
721 /**Function********************************************************************
723 Synopsis [Prints the variable groups as a parenthesized list.]
725 Description [Prints the variable groups as a parenthesized list.
726 For each group the level range that it represents is printed. After
727 each group, the group's flags are printed, preceded by a `|'. For
728 each flag (except MTR_TERMINAL) a character is printed.
729 <ul>
730 <li>F: MTR_FIXED
731 <li>N: MTR_NEWNODE
732 <li>S: MTR_SOFT
733 </ul>
734 The second argument, silent, if different from 0, causes
735 Cudd_PrintVarGroups to only check the syntax of the group tree.]
737 SideEffects [None]
739 SeeAlso []
741 ******************************************************************************/
742 void
743 cuddPrintVarGroups(
744 DdManager * dd /* manager */,
745 MtrNode * root /* root of the group tree */,
746 int zdd /* 0: BDD; 1: ZDD */,
747 int silent /* flag to check tree syntax only */)
749 MtrNode *node;
750 int level;
752 assert(root != NULL);
753 assert(root->younger == NULL || root->younger->elder == root);
754 assert(root->elder == NULL || root->elder->younger == root);
755 if (zdd) {
756 level = dd->permZ[root->index];
757 } else {
758 level = dd->perm[root->index];
760 if (!silent) (void) printf("(%d",level);
761 if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
762 if (!silent) (void) printf(",");
763 } else {
764 node = root->child;
765 while (node != NULL) {
766 assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
767 assert(node->parent == root);
768 cuddPrintVarGroups(dd,node,zdd,silent);
769 node = node->younger;
772 if (!silent) {
773 (void) printf("%d", (int) (level + root->size - 1));
774 if (root->flags != MTR_DEFAULT) {
775 (void) printf("|");
776 if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
777 if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
778 if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
780 (void) printf(")");
781 if (root->parent == NULL) (void) printf("\n");
783 assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
784 return;
786 } /* end of cuddPrintVarGroups */
789 /*---------------------------------------------------------------------------*/
790 /* Definition of static functions */
791 /*---------------------------------------------------------------------------*/
794 /**Function********************************************************************
796 Synopsis [Searches the subtables above node for its parents.]
798 Description []
800 SideEffects [None]
802 SeeAlso []
804 ******************************************************************************/
805 static void
806 debugFindParent(
807 DdManager * table,
808 DdNode * node)
810 int i,j;
811 int slots;
812 DdNodePtr *nodelist;
813 DdNode *f;
815 for (i = 0; i < cuddI(table,node->index); i++) {
816 nodelist = table->subtables[i].nodelist;
817 slots = table->subtables[i].slots;
819 for (j=0;j<slots;j++) {
820 f = nodelist[j];
821 while (f != NULL) {
822 if (cuddT(f) == node || Cudd_Regular(cuddE(f)) == node) {
823 #if SIZEOF_VOID_P == 8
824 (void) fprintf(table->out,"parent is at 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",
825 (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
826 #else
827 (void) fprintf(table->out,"parent is at 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",
828 (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
829 #endif
831 f = f->next;
836 } /* end of debugFindParent */
839 #if 0
840 /**Function********************************************************************
842 Synopsis [Reports an error if a (dead) node has a non-dead parent.]
844 Description [Searches all the subtables above node. Very expensive.
845 The same check is now implemented more efficiently in ddDebugCheck.]
847 SideEffects [None]
849 SeeAlso [debugFindParent]
851 ******************************************************************************/
852 static void
853 debugCheckParent(
854 DdManager * table,
855 DdNode * node)
857 int i,j;
858 int slots;
859 DdNode **nodelist,*f;
861 for (i = 0; i < cuddI(table,node->index); i++) {
862 nodelist = table->subtables[i].nodelist;
863 slots = table->subtables[i].slots;
865 for (j=0;j<slots;j++) {
866 f = nodelist[j];
867 while (f != NULL) {
868 if ((Cudd_Regular(cuddE(f)) == node || cuddT(f) == node) && f->ref != 0) {
869 (void) fprintf(table->err,
870 "error with zero ref count\n");
871 (void) fprintf(table->err,"parent is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f));
872 (void) fprintf(table->err,"child is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node));
874 f = f->next;
879 #endif