abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddCheck.c
Go to the documentation of this file.
1 /**CFile***********************************************************************
2 
3  FileName [cuddCheck.c]
4 
5  PackageName [cudd]
6 
7  Synopsis [Functions to check consistency of data structures.]
8 
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>
24  ]
25 
26  SeeAlso []
27 
28  Author [Fabio Somenzi]
29 
30  Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
31 
32  All rights reserved.
33 
34  Redistribution and use in source and binary forms, with or without
35  modification, are permitted provided that the following conditions
36  are met:
37 
38  Redistributions of source code must retain the above copyright
39  notice, this list of conditions and the following disclaimer.
40 
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.
44 
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.
48 
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.]
61 
62 ******************************************************************************/
63 
64 #include "misc/util/util_hack.h"
65 #include "cuddInt.h"
66 
68 
69 
70 
71 /*---------------------------------------------------------------------------*/
72 /* Constant declarations */
73 /*---------------------------------------------------------------------------*/
74 
75 
76 /*---------------------------------------------------------------------------*/
77 /* Stucture declarations */
78 /*---------------------------------------------------------------------------*/
79 
80 
81 /*---------------------------------------------------------------------------*/
82 /* Type declarations */
83 /*---------------------------------------------------------------------------*/
84 
85 
86 /*---------------------------------------------------------------------------*/
87 /* Variable declarations */
88 /*---------------------------------------------------------------------------*/
89 
90 #ifndef lint
91 static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.35 2009/03/08 02:49:01 fabio Exp $";
92 #endif
93 
94 /*---------------------------------------------------------------------------*/
95 /* Macro declarations */
96 /*---------------------------------------------------------------------------*/
97 
98 
99 /**AutomaticStart*************************************************************/
100 
101 /*---------------------------------------------------------------------------*/
102 /* Static function prototypes */
103 /*---------------------------------------------------------------------------*/
104 
105 static void debugFindParent (DdManager *table, DdNode *node);
106 #if 0
107 static void debugCheckParent (DdManager *table, DdNode *node);
108 #endif
109 
110 /**AutomaticEnd***************************************************************/
111 
112 
113 /*---------------------------------------------------------------------------*/
114 /* Definition of exported functions */
115 /*---------------------------------------------------------------------------*/
116 
117 
118 /**Function********************************************************************
119 
120  Synopsis [Checks for inconsistencies in the DD heap.]
121 
122  Description [Checks for inconsistencies in the DD heap:
123  <ul>
124  <li> node has illegal index
125  <li> live node has dead children
126  <li> node has illegal Then or Else pointers
127  <li> BDD/ADD node has identical children
128  <li> ZDD node has zero then child
129  <li> wrong number of total nodes
130  <li> wrong number of dead nodes
131  <li> ref count error at node
132  </ul>
133  Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is
134  not enough memory; 1 otherwise.]
135 
136  SideEffects [None]
137 
138  SeeAlso [Cudd_CheckKeys]
139 
140 ******************************************************************************/
141 int
143  DdManager * table)
144 {
145  unsigned int i;
146  int j,count;
147  int slots;
148  DdNodePtr *nodelist;
149  DdNode *f;
150  DdNode *sentinel = &(table->sentinel);
151  st__table *edgeTable; /* stores internal ref count for each node */
152  st__generator *gen;
153  int flag = 0;
154  int totalNode;
155  int deadNode;
156  int index;
157 
158 
159  edgeTable = st__init_table( st__ptrcmp, st__ptrhash);
160  if (edgeTable == NULL) return(CUDD_OUT_OF_MEM);
161 
162  /* Check the BDD/ADD subtables. */
163  for (i = 0; i < (unsigned) table->size; i++) {
164  index = table->invperm[i];
165  if (i != (unsigned) table->perm[index]) {
166  (void) fprintf(table->err,
167  "Permutation corrupted: invperm[%u] = %d\t perm[%d] = %d\n",
168  i, index, index, table->perm[index]);
169  }
170  nodelist = table->subtables[i].nodelist;
171  slots = table->subtables[i].slots;
172 
173  totalNode = 0;
174  deadNode = 0;
175  for (j = 0; j < slots; j++) { /* for each subtable slot */
176  f = nodelist[j];
177  while (f != sentinel) {
178  totalNode++;
179  if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
180  if ((int) f->index != index) {
181  (void) fprintf(table->err,
182  "Error: node has illegal index\n");
183  cuddPrintNode(f,table->err);
184  flag = 1;
185  }
186  if ((unsigned) cuddI(table,cuddT(f)->index) <= i ||
187  (unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index)
188  <= i) {
189  (void) fprintf(table->err,
190  "Error: node has illegal children\n");
191  cuddPrintNode(f,table->err);
192  flag = 1;
193  }
194  if (Cudd_Regular(cuddT(f)) != cuddT(f)) {
195  (void) fprintf(table->err,
196  "Error: node has illegal form\n");
197  cuddPrintNode(f,table->err);
198  flag = 1;
199  }
200  if (cuddT(f) == cuddE(f)) {
201  (void) fprintf(table->err,
202  "Error: node has identical children\n");
203  cuddPrintNode(f,table->err);
204  flag = 1;
205  }
206  if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) {
207  (void) fprintf(table->err,
208  "Error: live node has dead children\n");
209  cuddPrintNode(f,table->err);
210  flag =1;
211  }
212  /* Increment the internal reference count for the
213  ** then child of the current node.
214  */
215  if ( st__lookup_int(edgeTable,(char *)cuddT(f),&count)) {
216  count++;
217  } else {
218  count = 1;
219  }
220  if ( st__insert(edgeTable,(char *)cuddT(f),
221  (char *)(long)count) == st__OUT_OF_MEM) {
222  st__free_table(edgeTable);
223  return(CUDD_OUT_OF_MEM);
224  }
225 
226  /* Increment the internal reference count for the
227  ** else child of the current node.
228  */
229  if ( st__lookup_int(edgeTable,(char *)Cudd_Regular(cuddE(f)),
230  &count)) {
231  count++;
232  } else {
233  count = 1;
234  }
235  if ( st__insert(edgeTable,(char *)Cudd_Regular(cuddE(f)),
236  (char *)(long)count) == st__OUT_OF_MEM) {
237  st__free_table(edgeTable);
238  return(CUDD_OUT_OF_MEM);
239  }
240  } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
241  deadNode++;
242 #if 0
243  debugCheckParent(table,f);
244 #endif
245  } else {
246  fprintf(table->err,
247  "Error: node has illegal Then or Else pointers\n");
248  cuddPrintNode(f,table->err);
249  flag = 1;
250  }
251 
252  f = f->next;
253  } /* for each element of the collision list */
254  } /* for each subtable slot */
255 
256  if ((unsigned) totalNode != table->subtables[i].keys) {
257  fprintf(table->err,"Error: wrong number of total nodes\n");
258  flag = 1;
259  }
260  if ((unsigned) deadNode != table->subtables[i].dead) {
261  fprintf(table->err,"Error: wrong number of dead nodes\n");
262  flag = 1;
263  }
264  } /* for each BDD/ADD subtable */
265 
266  /* Check the ZDD subtables. */
267  for (i = 0; i < (unsigned) table->sizeZ; i++) {
268  index = table->invpermZ[i];
269  if (i != (unsigned) table->permZ[index]) {
270  (void) fprintf(table->err,
271  "Permutation corrupted: invpermZ[%u] = %d\t permZ[%d] = %d in ZDD\n",
272  i, index, index, table->permZ[index]);
273  }
274  nodelist = table->subtableZ[i].nodelist;
275  slots = table->subtableZ[i].slots;
276 
277  totalNode = 0;
278  deadNode = 0;
279  for (j = 0; j < slots; j++) { /* for each subtable slot */
280  f = nodelist[j];
281  while (f != NULL) {
282  totalNode++;
283  if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
284  if ((int) f->index != index) {
285  (void) fprintf(table->err,
286  "Error: ZDD node has illegal index\n");
287  cuddPrintNode(f,table->err);
288  flag = 1;
289  }
290  if (Cudd_IsComplement(cuddT(f)) ||
291  Cudd_IsComplement(cuddE(f))) {
292  (void) fprintf(table->err,
293  "Error: ZDD node has complemented children\n");
294  cuddPrintNode(f,table->err);
295  flag = 1;
296  }
297  if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i ||
298  (unsigned) cuddIZ(table,cuddE(f)->index) <= i) {
299  (void) fprintf(table->err,
300  "Error: ZDD node has illegal children\n");
301  cuddPrintNode(f,table->err);
302  cuddPrintNode(cuddT(f),table->err);
303  cuddPrintNode(cuddE(f),table->err);
304  flag = 1;
305  }
306  if (cuddT(f) == DD_ZERO(table)) {
307  (void) fprintf(table->err,
308  "Error: ZDD node has zero then child\n");
309  cuddPrintNode(f,table->err);
310  flag = 1;
311  }
312  if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) {
313  (void) fprintf(table->err,
314  "Error: ZDD live node has dead children\n");
315  cuddPrintNode(f,table->err);
316  flag =1;
317  }
318  /* Increment the internal reference count for the
319  ** then child of the current node.
320  */
321  if ( st__lookup_int(edgeTable,(char *)cuddT(f),&count)) {
322  count++;
323  } else {
324  count = 1;
325  }
326  if ( st__insert(edgeTable,(char *)cuddT(f),
327  (char *)(long)count) == st__OUT_OF_MEM) {
328  st__free_table(edgeTable);
329  return(CUDD_OUT_OF_MEM);
330  }
331 
332  /* Increment the internal reference count for the
333  ** else child of the current node.
334  */
335  if ( st__lookup_int(edgeTable,(char *)cuddE(f),&count)) {
336  count++;
337  } else {
338  count = 1;
339  }
340  if ( st__insert(edgeTable,(char *)cuddE(f),
341  (char *)(long)count) == st__OUT_OF_MEM) {
342  st__free_table(edgeTable);
343  table->errorCode = CUDD_MEMORY_OUT;
344  return(CUDD_OUT_OF_MEM);
345  }
346  } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
347  deadNode++;
348 #if 0
349  debugCheckParent(table,f);
350 #endif
351  } else {
352  fprintf(table->err,
353  "Error: ZDD node has illegal Then or Else pointers\n");
354  cuddPrintNode(f,table->err);
355  flag = 1;
356  }
357 
358  f = f->next;
359  } /* for each element of the collision list */
360  } /* for each subtable slot */
361 
362  if ((unsigned) totalNode != table->subtableZ[i].keys) {
363  fprintf(table->err,
364  "Error: wrong number of total nodes in ZDD\n");
365  flag = 1;
366  }
367  if ((unsigned) deadNode != table->subtableZ[i].dead) {
368  fprintf(table->err,
369  "Error: wrong number of dead nodes in ZDD\n");
370  flag = 1;
371  }
372  } /* for each ZDD subtable */
373 
374  /* Check the constant table. */
375  nodelist = table->constants.nodelist;
376  slots = table->constants.slots;
377 
378  totalNode = 0;
379  deadNode = 0;
380  for (j = 0; j < slots; j++) {
381  f = nodelist[j];
382  while (f != NULL) {
383  totalNode++;
384  if (f->ref != 0) {
385  if (f->index != CUDD_CONST_INDEX) {
386  fprintf(table->err,"Error: node has illegal index\n");
387 #if SIZEOF_VOID_P == 8
388  fprintf(table->err,
389  " node 0x%lx, id = %u, ref = %u, value = %g\n",
390  (ptruint)f,f->index,f->ref,cuddV(f));
391 #else
392  fprintf(table->err,
393  " node 0x%x, id = %hu, ref = %hu, value = %g\n",
394  (ptruint)f,f->index,f->ref,cuddV(f));
395 #endif
396  flag = 1;
397  }
398  } else {
399  deadNode++;
400  }
401  f = f->next;
402  }
403  }
404  if ((unsigned) totalNode != table->constants.keys) {
405  (void) fprintf(table->err,
406  "Error: wrong number of total nodes in constants\n");
407  flag = 1;
408  }
409  if ((unsigned) deadNode != table->constants.dead) {
410  (void) fprintf(table->err,
411  "Error: wrong number of dead nodes in constants\n");
412  flag = 1;
413  }
414  gen = st__init_gen(edgeTable);
415  while ( st__gen(gen, (const char **)&f, (char **)&count)) {
416  if (count > (int)(f->ref) && f->ref != DD_MAXREF) {
417 #if SIZEOF_VOID_P == 8
418  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));
419 #else
420  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));
421 #endif
422  debugFindParent(table,f);
423  flag = 1;
424  }
425  }
426  st__free_gen(gen);
427  st__free_table(edgeTable);
428 
429  return (flag);
430 
431 } /* end of Cudd_DebugCheck */
432 
433 
434 /**Function********************************************************************
435 
436  Synopsis [Checks for several conditions that should not occur.]
437 
438  Description [Checks for the following conditions:
439  <ul>
440  <li>Wrong sizes of subtables.
441  <li>Wrong number of keys found in unique subtable.
442  <li>Wrong number of dead found in unique subtable.
443  <li>Wrong number of keys found in the constant table
444  <li>Wrong number of dead found in the constant table
445  <li>Wrong number of total slots found
446  <li>Wrong number of maximum keys found
447  <li>Wrong number of total dead found
448  </ul>
449  Reports the average length of non-empty lists. Returns the number of
450  subtables for which the number of keys is wrong.]
451 
452  SideEffects [None]
453 
454  SeeAlso [Cudd_DebugCheck]
455 
456 ******************************************************************************/
457 int
459  DdManager * table)
460 {
461  int size;
462  int i,j;
463  DdNodePtr *nodelist;
464  DdNode *node;
465  DdNode *sentinel = &(table->sentinel);
466  DdSubtable *subtable;
467  int keys;
468  int dead;
469  int count = 0;
470  int totalKeys = 0;
471  int totalSlots = 0;
472  int totalDead = 0;
473  int nonEmpty = 0;
474  unsigned int slots;
475  int logSlots;
476  int shift;
477 
478  size = table->size;
479 
480  for (i = 0; i < size; i++) {
481  subtable = &(table->subtables[i]);
482  nodelist = subtable->nodelist;
483  keys = subtable->keys;
484  dead = subtable->dead;
485  totalKeys += keys;
486  slots = subtable->slots;
487  shift = subtable->shift;
488  logSlots = sizeof(int) * 8 - shift;
489  if (((slots >> logSlots) << logSlots) != slots) {
490  (void) fprintf(table->err,
491  "Unique table %d is not the right power of 2\n", i);
492  (void) fprintf(table->err,
493  " slots = %u shift = %d\n", slots, shift);
494  }
495  totalSlots += slots;
496  totalDead += dead;
497  for (j = 0; (unsigned) j < slots; j++) {
498  node = nodelist[j];
499  if (node != sentinel) {
500  nonEmpty++;
501  }
502  while (node != sentinel) {
503  keys--;
504  if (node->ref == 0) {
505  dead--;
506  }
507  node = node->next;
508  }
509  }
510  if (keys != 0) {
511  (void) fprintf(table->err, "Wrong number of keys found \
512 in unique table %d (difference=%d)\n", i, keys);
513  count++;
514  }
515  if (dead != 0) {
516  (void) fprintf(table->err, "Wrong number of dead found \
517 in unique table no. %d (difference=%d)\n", i, dead);
518  }
519  } /* for each BDD/ADD subtable */
520 
521  /* Check the ZDD subtables. */
522  size = table->sizeZ;
523 
524  for (i = 0; i < size; i++) {
525  subtable = &(table->subtableZ[i]);
526  nodelist = subtable->nodelist;
527  keys = subtable->keys;
528  dead = subtable->dead;
529  totalKeys += keys;
530  totalSlots += subtable->slots;
531  totalDead += dead;
532  for (j = 0; (unsigned) j < subtable->slots; j++) {
533  node = nodelist[j];
534  if (node != NULL) {
535  nonEmpty++;
536  }
537  while (node != NULL) {
538  keys--;
539  if (node->ref == 0) {
540  dead--;
541  }
542  node = node->next;
543  }
544  }
545  if (keys != 0) {
546  (void) fprintf(table->err, "Wrong number of keys found \
547 in ZDD unique table no. %d (difference=%d)\n", i, keys);
548  count++;
549  }
550  if (dead != 0) {
551  (void) fprintf(table->err, "Wrong number of dead found \
552 in ZDD unique table no. %d (difference=%d)\n", i, dead);
553  }
554  } /* for each ZDD subtable */
555 
556  /* Check the constant table. */
557  subtable = &(table->constants);
558  nodelist = subtable->nodelist;
559  keys = subtable->keys;
560  dead = subtable->dead;
561  totalKeys += keys;
562  totalSlots += subtable->slots;
563  totalDead += dead;
564  for (j = 0; (unsigned) j < subtable->slots; j++) {
565  node = nodelist[j];
566  if (node != NULL) {
567  nonEmpty++;
568  }
569  while (node != NULL) {
570  keys--;
571  if (node->ref == 0) {
572  dead--;
573  }
574  node = node->next;
575  }
576  }
577  if (keys != 0) {
578  (void) fprintf(table->err, "Wrong number of keys found \
579 in the constant table (difference=%d)\n", keys);
580  count++;
581  }
582  if (dead != 0) {
583  (void) fprintf(table->err, "Wrong number of dead found \
584 in the constant table (difference=%d)\n", dead);
585  }
586  if ((unsigned) totalKeys != table->keys + table->keysZ) {
587  (void) fprintf(table->err, "Wrong number of total keys found \
588 (difference=%d)\n", (int) (totalKeys-table->keys));
589  }
590  if ((unsigned) totalSlots != table->slots) {
591  (void) fprintf(table->err, "Wrong number of total slots found \
592 (difference=%d)\n", (int) (totalSlots-table->slots));
593  }
594  if (table->minDead != (unsigned) (table->gcFrac * table->slots)) {
595  (void) fprintf(table->err, "Wrong number of minimum dead found \
596 (%u vs. %u)\n", table->minDead,
597  (unsigned) (table->gcFrac * (double) table->slots));
598  }
599  if ((unsigned) totalDead != table->dead + table->deadZ) {
600  (void) fprintf(table->err, "Wrong number of total dead found \
601 (difference=%d)\n", (int) (totalDead-table->dead));
602  }
603  (void)printf("Average length of non-empty lists = %g\n",
604  (double) table->keys / (double) nonEmpty);
605 
606  return(count);
607 
608 } /* end of Cudd_CheckKeys */
609 
610 
611 /*---------------------------------------------------------------------------*/
612 /* Definition of internal functions */
613 /*---------------------------------------------------------------------------*/
614 
615 
616 /**Function********************************************************************
617 
618  Synopsis [Prints information about the heap.]
619 
620  Description [Prints to the manager's stdout the number of live nodes for each
621  level of the DD heap that contains at least one live node. It also
622  prints a summary containing:
623  <ul>
624  <li> total number of tables;
625  <li> number of tables with live nodes;
626  <li> table with the largest number of live nodes;
627  <li> number of nodes in that table.
628  </ul>
629  If more than one table contains the maximum number of live nodes,
630  only the one of lowest index is reported. Returns 1 in case of success
631  and 0 otherwise.]
632 
633  SideEffects [None]
634 
635  SeeAlso []
636 
637 ******************************************************************************/
638 int
640  DdManager * dd)
641 {
642  int ntables = dd->size;
643  DdSubtable *subtables = dd->subtables;
644  int i, /* loop index */
645  nodes, /* live nodes in i-th layer */
646  retval, /* return value of fprintf */
647  largest = -1, /* index of the table with most live nodes */
648  maxnodes = -1, /* maximum number of live nodes in a table */
649  nonempty = 0; /* number of tables with live nodes */
650 
651  /* Print header. */
652 #if SIZEOF_VOID_P == 8
653  retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n",
654  (ptruint) dd);
655 #else
656  retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n",
657  (ptruint) dd);
658 #endif
659  if (retval == EOF) return 0;
660 
661  /* Print number of live nodes for each nonempty table. */
662  for (i=0; i<ntables; i++) {
663  nodes = subtables[i].keys - subtables[i].dead;
664  if (nodes) {
665  nonempty++;
666  retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes);
667  if (retval == EOF) return 0;
668  if (nodes > maxnodes) {
669  maxnodes = nodes;
670  largest = i;
671  }
672  }
673  }
674 
675  nodes = dd->constants.keys - dd->constants.dead;
676  if (nodes) {
677  nonempty++;
678  retval = fprintf(dd->out,"const: %5d nodes\n", nodes);
679  if (retval == EOF) return 0;
680  if (nodes > maxnodes) {
681  maxnodes = nodes;
682  largest = CUDD_CONST_INDEX;
683  }
684  }
685 
686  /* Print summary. */
687  retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ",
688  ntables+1, nonempty, largest);
689  if (retval == EOF) return 0;
690  retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes);
691  if (retval == EOF) return 0;
692 
693  return(1);
694 
695 } /* end of cuddHeapProfile */
696 
697 
698 /**Function********************************************************************
699 
700  Synopsis [Prints out information on a node.]
701 
702  Description [Prints out information on a node.]
703 
704  SideEffects [None]
705 
706  SeeAlso []
707 
708 ******************************************************************************/
709 void
711  DdNode * f,
712  FILE *fp)
713 {
714  f = Cudd_Regular(f);
715 #if SIZEOF_VOID_P == 8
716  (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));
717 #else
718  (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));
719 #endif
720 
721 } /* end of cuddPrintNode */
722 
723 
724 
725 /**Function********************************************************************
726 
727  Synopsis [Prints the variable groups as a parenthesized list.]
728 
729  Description [Prints the variable groups as a parenthesized list.
730  For each group the level range that it represents is printed. After
731  each group, the group's flags are printed, preceded by a `|'. For
732  each flag (except MTR_TERMINAL) a character is printed.
733  <ul>
734  <li>F: MTR_FIXED
735  <li>N: MTR_NEWNODE
736  <li>S: MTR_SOFT
737  </ul>
738  The second argument, silent, if different from 0, causes
739  Cudd_PrintVarGroups to only check the syntax of the group tree.]
740 
741  SideEffects [None]
742 
743  SeeAlso []
744 
745 ******************************************************************************/
746 void
748  DdManager * dd /* manager */,
749  MtrNode * root /* root of the group tree */,
750  int zdd /* 0: BDD; 1: ZDD */,
751  int silent /* flag to check tree syntax only */)
752 {
753  MtrNode *node;
754  int level;
755 
756  assert(root != NULL);
757  assert(root->younger == NULL || root->younger->elder == root);
758  assert(root->elder == NULL || root->elder->younger == root);
759  if (zdd) {
760  level = dd->permZ[root->index];
761  } else {
762  level = dd->perm[root->index];
763  }
764  if (!silent) (void) printf("(%d",level);
765  if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
766  if (!silent) (void) printf(",");
767  } else {
768  node = root->child;
769  while (node != NULL) {
770  assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
771  assert(node->parent == root);
772  cuddPrintVarGroups(dd,node,zdd,silent);
773  node = node->younger;
774  }
775  }
776  if (!silent) {
777  (void) printf("%d", (int) (level + root->size - 1));
778  if (root->flags != MTR_DEFAULT) {
779  (void) printf("|");
780  if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
781  if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
782  if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
783  }
784  (void) printf(")");
785  if (root->parent == NULL) (void) printf("\n");
786  }
787  assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
788  return;
789 
790 } /* end of cuddPrintVarGroups */
791 
792 
793 /*---------------------------------------------------------------------------*/
794 /* Definition of static functions */
795 /*---------------------------------------------------------------------------*/
796 
797 
798 /**Function********************************************************************
799 
800  Synopsis [Searches the subtables above node for its parents.]
801 
802  Description []
803 
804  SideEffects [None]
805 
806  SeeAlso []
807 
808 ******************************************************************************/
809 static void
811  DdManager * table,
812  DdNode * node)
813 {
814  int i,j;
815  int slots;
816  DdNodePtr *nodelist;
817  DdNode *f;
818 
819  for (i = 0; i < cuddI(table,node->index); i++) {
820  nodelist = table->subtables[i].nodelist;
821  slots = table->subtables[i].slots;
822 
823  for (j=0;j<slots;j++) {
824  f = nodelist[j];
825  while (f != NULL) {
826  if (cuddT(f) == node || Cudd_Regular(cuddE(f)) == node) {
827 #if SIZEOF_VOID_P == 8
828  (void) fprintf(table->out,"parent is at 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",
829  (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
830 #else
831  (void) fprintf(table->out,"parent is at 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",
832  (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
833 #endif
834  }
835  f = f->next;
836  }
837  }
838  }
839 
840 } /* end of debugFindParent */
841 
842 
843 #if 0
844 /**Function********************************************************************
845 
846  Synopsis [Reports an error if a (dead) node has a non-dead parent.]
847 
848  Description [Searches all the subtables above node. Very expensive.
849  The same check is now implemented more efficiently in ddDebugCheck.]
850 
851  SideEffects [None]
852 
853  SeeAlso [debugFindParent]
854 
855 ******************************************************************************/
856 static void
857 debugCheckParent(
858  DdManager * table,
859  DdNode * node)
860 {
861  int i,j;
862  int slots;
863  DdNode **nodelist,*f;
864 
865  for (i = 0; i < cuddI(table,node->index); i++) {
866  nodelist = table->subtables[i].nodelist;
867  slots = table->subtables[i].slots;
868 
869  for (j=0;j<slots;j++) {
870  f = nodelist[j];
871  while (f != NULL) {
872  if ((Cudd_Regular(cuddE(f)) == node || cuddT(f) == node) && f->ref != 0) {
873  (void) fprintf(table->err,
874  "error with zero ref count\n");
875  (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));
876  (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));
877  }
878  f = f->next;
879  }
880  }
881  }
882 }
883 #endif
884 
885 
887 
int Cudd_CheckKeys(DdManager *table)
Definition: cuddCheck.c:458
DdHalfWord ref
Definition: cudd.h:280
#define DD_MAXREF
Definition: cuddInt.h:100
#define MTR_TERMINAL
Definition: mtr.h:100
void st__free_table(st__table *table)
Definition: st.c:81
unsigned int keys
Definition: cuddInt.h:330
MtrHalfWord flags
Definition: mtr.h:132
#define CUDD_OUT_OF_MEM
Definition: cudd.h:95
void cuddPrintVarGroups(DdManager *dd, MtrNode *root, int zdd, int silent)
Definition: cuddCheck.c:747
#define cuddIZ(dd, index)
Definition: cuddInt.h:704
Definition: cudd.h:278
unsigned int deadZ
Definition: cuddInt.h:372
MtrHalfWord size
Definition: mtr.h:134
int * invpermZ
Definition: cuddInt.h:389
void st__free_gen(st__generator *gen)
Definition: st.c:556
int st__insert(st__table *table, const char *key, char *value)
Definition: st.c:171
static void debugFindParent(DdManager *table, DdNode *node)
Definition: cuddCheck.c:810
int size
Definition: cuddInt.h:361
double gcFrac
Definition: cuddInt.h:375
unsigned int slots
Definition: cuddInt.h:368
#define Cudd_Regular(node)
Definition: cudd.h:397
int cuddHeapProfile(DdManager *dd)
Definition: cuddCheck.c:639
int st__ptrcmp(const char *, const char *)
Definition: st.c:480
FILE * err
Definition: cuddInt.h:442
#define MTR_FIXED
Definition: mtr.h:102
int st__lookup_int(st__table *table, char *key, int *value)
Definition: st.c:134
DdSubtable * subtables
Definition: cuddInt.h:365
int * permZ
Definition: cuddInt.h:387
struct MtrNode * parent
Definition: mtr.h:136
int Cudd_DebugCheck(DdManager *table)
Definition: cuddCheck.c:142
#define MTR_DEFAULT
Definition: mtr.h:99
struct MtrNode * elder
Definition: mtr.h:138
#define MTR_TEST(node, flag)
Definition: mtr.h:155
#define cuddV(node)
Definition: cuddInt.h:668
ABC_PTRUINT_T ptruint
Definition: cuddInt.h:261
struct MtrNode * younger
Definition: mtr.h:139
st__table * st__init_table(st__compare_func_type compare, st__hash_func_type hash)
Definition: st.c:72
unsigned int dead
Definition: cuddInt.h:371
#define Cudd_IsComplement(node)
Definition: cudd.h:425
DdNode sentinel
Definition: cuddInt.h:344
void cuddPrintNode(DdNode *f, FILE *fp)
Definition: cuddCheck.c:710
MtrHalfWord index
Definition: mtr.h:135
unsigned int keys
Definition: cuddInt.h:369
unsigned int dead
Definition: cuddInt.h:332
FILE * out
Definition: cuddInt.h:441
Definition: st.h:52
DdNode * next
Definition: cudd.h:281
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
#define MTR_NEWNODE
Definition: mtr.h:103
#define CUDD_CONST_INDEX
Definition: cudd.h:117
DdNode ** nodelist
Definition: cuddInt.h:327
static int size
Definition: cuddSign.c:86
MtrHalfWord low
Definition: mtr.h:133
#define cuddT(node)
Definition: cuddInt.h:636
st__generator * st__init_gen(st__table *table)
Definition: st.c:486
Definition: mtr.h:131
#define st__OUT_OF_MEM
Definition: st.h:113
static int largest(void)
Definition: cuddGenetic.c:624
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
#define cuddI(dd, index)
Definition: cuddInt.h:686
int sizeZ
Definition: cuddInt.h:362
DdHalfWord index
Definition: cudd.h:279
unsigned int slots
Definition: cuddInt.h:329
#define cuddE(node)
Definition: cuddInt.h:652
#define assert(ex)
Definition: util_old.h:213
int * invperm
Definition: cuddInt.h:388
DdSubtable constants
Definition: cuddInt.h:367
int shift
Definition: cuddInt.h:328
unsigned int keysZ
Definition: cuddInt.h:370
struct MtrNode * child
Definition: mtr.h:137
int * perm
Definition: cuddInt.h:386
static ABC_NAMESPACE_IMPL_START char rcsid[] DD_UNUSED
Definition: cuddCheck.c:91
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
int st__ptrhash(const char *, int)
Definition: st.c:468
unsigned int minDead
Definition: cuddInt.h:374
int st__gen(st__generator *gen, const char **key_p, char **value_p)
Definition: st.c:502
#define MTR_SOFT
Definition: mtr.h:101
DdSubtable * subtableZ
Definition: cuddInt.h:366
#define DD_ZERO(dd)
Definition: cuddInt.h:927