#include "util_hack.h"
#include "cuddInt.h"
Go to the source code of this file.
Functions | |
void | Cudd_Ref (DdNode *n) |
void | Cudd_RecursiveDeref (DdManager *table, DdNode *n) |
void | Cudd_IterDerefBdd (DdManager *table, DdNode *n) |
void | Cudd_DelayedDerefBdd (DdManager *table, DdNode *n) |
void | Cudd_RecursiveDerefZdd (DdManager *table, DdNode *n) |
void | Cudd_Deref (DdNode *node) |
int | Cudd_CheckZeroRef (DdManager *manager) |
void | cuddReclaim (DdManager *table, DdNode *n) |
void | cuddReclaimZdd (DdManager *table, DdNode *n) |
void | cuddShrinkDeathRow (DdManager *table) |
void | cuddClearDeathRow (DdManager *table) |
int | cuddIsInDeathRow (DdManager *dd, DdNode *f) |
int | cuddTimesInDeathRow (DdManager *dd, DdNode *f) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddRef.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" |
int Cudd_CheckZeroRef | ( | DdManager * | manager | ) |
Function********************************************************************
Synopsis [Checks the unique table for nodes with non-zero reference counts.]
Description [Checks the unique table for nodes with non-zero reference counts. It is normally called before Cudd_Quit to make sure that there are no memory leaks due to missing Cudd_RecursiveDeref's. Takes into account that reference counts may saturate and that the basic constants and the projection functions are referenced by the manager. Returns the number of nodes with non-zero reference count. (Except for the cases mentioned above.)]
SideEffects [None]
SeeAlso []
Definition at line 435 of file cuddRef.c.
00437 { 00438 int size; 00439 int i, j; 00440 int remain; /* the expected number of remaining references to one */ 00441 DdNodePtr *nodelist; 00442 DdNode *node; 00443 DdNode *sentinel = &(manager->sentinel); 00444 DdSubtable *subtable; 00445 int count = 0; 00446 int index; 00447 00448 #ifndef DD_NO_DEATH_ROW 00449 cuddClearDeathRow(manager); 00450 #endif 00451 00452 /* First look at the BDD/ADD subtables. */ 00453 remain = 1; /* reference from the manager */ 00454 size = manager->size; 00455 remain += 2 * size; /* reference from the BDD projection functions */ 00456 00457 for (i = 0; i < size; i++) { 00458 subtable = &(manager->subtables[i]); 00459 nodelist = subtable->nodelist; 00460 for (j = 0; (unsigned) j < subtable->slots; j++) { 00461 node = nodelist[j]; 00462 while (node != sentinel) { 00463 if (node->ref != 0 && node->ref != DD_MAXREF) { 00464 index = (int) node->index; 00465 if (node != manager->vars[index]) { 00466 count++; 00467 } else { 00468 if (node->ref != 1) { 00469 count++; 00470 } 00471 } 00472 } 00473 node = node->next; 00474 } 00475 } 00476 } 00477 00478 /* Then look at the ZDD subtables. */ 00479 size = manager->sizeZ; 00480 if (size) /* references from ZDD universe */ 00481 remain += 2; 00482 00483 for (i = 0; i < size; i++) { 00484 subtable = &(manager->subtableZ[i]); 00485 nodelist = subtable->nodelist; 00486 for (j = 0; (unsigned) j < subtable->slots; j++) { 00487 node = nodelist[j]; 00488 while (node != NULL) { 00489 if (node->ref != 0 && node->ref != DD_MAXREF) { 00490 index = (int) node->index; 00491 if (node == manager->univ[manager->permZ[index]]) { 00492 if (node->ref > 2) { 00493 count++; 00494 } 00495 } else { 00496 count++; 00497 } 00498 } 00499 node = node->next; 00500 } 00501 } 00502 } 00503 00504 /* Now examine the constant table. Plusinfinity, minusinfinity, and 00505 ** zero are referenced by the manager. One is referenced by the 00506 ** manager, by the ZDD universe, and by all projection functions. 00507 ** All other nodes should have no references. 00508 */ 00509 nodelist = manager->constants.nodelist; 00510 for (j = 0; (unsigned) j < manager->constants.slots; j++) { 00511 node = nodelist[j]; 00512 while (node != NULL) { 00513 if (node->ref != 0 && node->ref != DD_MAXREF) { 00514 if (node == manager->one) { 00515 if ((int) node->ref != remain) { 00516 count++; 00517 } 00518 } else if (node == manager->zero || 00519 node == manager->plusinfinity || 00520 node == manager->minusinfinity) { 00521 if (node->ref != 1) { 00522 count++; 00523 } 00524 } else { 00525 count++; 00526 } 00527 } 00528 node = node->next; 00529 } 00530 } 00531 return(count); 00532 00533 } /* end of Cudd_CheckZeroRef */
Function********************************************************************
Synopsis [Decreases the reference count of BDD node n.]
Description [Enqueues node n for later dereferencing. If the queue is full decreases the reference count of the oldest node N to make room for n. If N dies, recursively decreases the reference counts of its children. It is used to dispose of a BDD that is currently not needed, but may be useful again in the near future. The dereferencing proper is done as in Cudd_IterDerefBdd.]
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_IterDerefBdd]
Definition at line 243 of file cuddRef.c.
00246 { 00247 DdNode *N; 00248 int ord; 00249 DdNodePtr *stack; 00250 int SP; 00251 00252 unsigned int live = table->keys - table->dead; 00253 if (live > table->peakLiveNodes) { 00254 table->peakLiveNodes = live; 00255 } 00256 00257 n = Cudd_Regular(n); 00258 #ifdef DD_DEBUG 00259 assert(n->ref != 0); 00260 #endif 00261 00262 #ifdef DD_NO_DEATH_ROW 00263 N = n; 00264 #else 00265 if (cuddIsConstant(n) || n->ref > 1) { 00266 #ifdef DD_DEBUG 00267 assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table))); 00268 #endif 00269 cuddSatDec(n->ref); 00270 return; 00271 } 00272 00273 N = table->deathRow[table->nextDead]; 00274 00275 if (N != NULL) { 00276 #endif 00277 #ifdef DD_DEBUG 00278 assert(!Cudd_IsComplement(N)); 00279 #endif 00280 stack = table->stack; 00281 SP = 1; 00282 do { 00283 #ifdef DD_DEBUG 00284 assert(N->ref != 0); 00285 #endif 00286 if (N->ref == 1) { 00287 N->ref = 0; 00288 table->dead++; 00289 #ifdef DD_STATS 00290 table->nodesDropped++; 00291 #endif 00292 ord = table->perm[N->index]; 00293 stack[SP++] = Cudd_Regular(cuddE(N)); 00294 table->subtables[ord].dead++; 00295 N = cuddT(N); 00296 } else { 00297 cuddSatDec(N->ref); 00298 N = stack[--SP]; 00299 } 00300 } while (SP != 0); 00301 #ifndef DD_NO_DEATH_ROW 00302 } 00303 table->deathRow[table->nextDead] = n; 00304 00305 /* Udate insertion point. */ 00306 table->nextDead++; 00307 table->nextDead &= table->deadMask; 00308 #if 0 00309 if (table->nextDead == table->deathRowDepth) { 00310 if (table->deathRowDepth < table->looseUpTo / 2) { 00311 extern void (*MMoutOfMemory)(long); 00312 void (*saveHandler)(long) = MMoutOfMemory; 00313 DdNodePtr *newRow; 00314 MMoutOfMemory = Cudd_OutOfMem; 00315 newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth); 00316 MMoutOfMemory = saveHandler; 00317 if (newRow == NULL) { 00318 table->nextDead = 0; 00319 } else { 00320 int i; 00321 table->memused += table->deathRowDepth; 00322 i = table->deathRowDepth; 00323 table->deathRowDepth <<= 1; 00324 for (; i < table->deathRowDepth; i++) { 00325 newRow[i] = NULL; 00326 } 00327 table->deadMask = table->deathRowDepth - 1; 00328 table->deathRow = newRow; 00329 } 00330 } else { 00331 table->nextDead = 0; 00332 } 00333 } 00334 #endif 00335 #endif 00336 00337 } /* end of Cudd_DelayedDerefBdd */
void Cudd_Deref | ( | DdNode * | node | ) |
Function********************************************************************
Synopsis [Decreases the reference count of node.]
Description [Decreases the reference count of node. It is primarily used in recursive procedures to decrease the ref count of a result node before returning it. This accomplishes the goal of removing the protection applied by a previous Cudd_Ref.]
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref]
Definition at line 407 of file cuddRef.c.
00409 { 00410 node = Cudd_Regular(node); 00411 cuddSatDec(node->ref); 00412 00413 } /* end of Cudd_Deref */
Function********************************************************************
Synopsis [Decreases the reference count of BDD node n.]
Description [Decreases the reference count of node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a BDD that is no longer needed. It is more efficient than Cudd_RecursiveDeref, but it cannot be used on ADDs. The greater efficiency comes from being able to assume that no constant node will ever die as a result of a call to this procedure.]
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_DelayedDerefBdd]
Definition at line 186 of file cuddRef.c.
00189 { 00190 DdNode *N; 00191 int ord; 00192 DdNodePtr *stack = table->stack; 00193 int SP = 1; 00194 00195 unsigned int live = table->keys - table->dead; 00196 if (live > table->peakLiveNodes) { 00197 table->peakLiveNodes = live; 00198 } 00199 00200 N = Cudd_Regular(n); 00201 00202 do { 00203 #ifdef DD_DEBUG 00204 assert(N->ref != 0); 00205 #endif 00206 00207 if (N->ref == 1) { 00208 N->ref = 0; 00209 table->dead++; 00210 #ifdef DD_STATS 00211 table->nodesDropped++; 00212 #endif 00213 ord = table->perm[N->index]; 00214 stack[SP++] = Cudd_Regular(cuddE(N)); 00215 table->subtables[ord].dead++; 00216 N = cuddT(N); 00217 } else { 00218 cuddSatDec(N->ref); 00219 N = stack[--SP]; 00220 } 00221 } while (SP != 0); 00222 00223 } /* end of Cudd_IterDerefBdd */
Function********************************************************************
Synopsis [Decreases the reference count of node n.]
Description [Decreases the reference count of node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a DD that is no longer needed.]
SideEffects [None]
SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd]
Definition at line 123 of file cuddRef.c.
00126 { 00127 DdNode *N; 00128 int ord; 00129 DdNodePtr *stack = table->stack; 00130 int SP = 1; 00131 00132 unsigned int live = table->keys - table->dead; 00133 if (live > table->peakLiveNodes) { 00134 table->peakLiveNodes = live; 00135 } 00136 00137 N = Cudd_Regular(n); 00138 00139 do { 00140 #ifdef DD_DEBUG 00141 assert(N->ref != 0); 00142 #endif 00143 00144 if (N->ref == 1) { 00145 N->ref = 0; 00146 table->dead++; 00147 #ifdef DD_STATS 00148 table->nodesDropped++; 00149 #endif 00150 if (cuddIsConstant(N)) { 00151 table->constants.dead++; 00152 N = stack[--SP]; 00153 } else { 00154 ord = table->perm[N->index]; 00155 stack[SP++] = Cudd_Regular(cuddE(N)); 00156 table->subtables[ord].dead++; 00157 N = cuddT(N); 00158 } 00159 } else { 00160 cuddSatDec(N->ref); 00161 N = stack[--SP]; 00162 } 00163 } while (SP != 0); 00164 00165 } /* end of Cudd_RecursiveDeref */
Function********************************************************************
Synopsis [Decreases the reference count of ZDD node n.]
Description [Decreases the reference count of ZDD node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a ZDD that is no longer needed.]
SideEffects [None]
SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref]
Definition at line 354 of file cuddRef.c.
00357 { 00358 DdNode *N; 00359 int ord; 00360 DdNodePtr *stack = table->stack; 00361 int SP = 1; 00362 00363 N = n; 00364 00365 do { 00366 #ifdef DD_DEBUG 00367 assert(N->ref != 0); 00368 #endif 00369 00370 cuddSatDec(N->ref); 00371 00372 if (N->ref == 0) { 00373 table->deadZ++; 00374 #ifdef DD_STATS 00375 table->nodesDropped++; 00376 #endif 00377 #ifdef DD_DEBUG 00378 assert(!cuddIsConstant(N)); 00379 #endif 00380 ord = table->permZ[N->index]; 00381 stack[SP++] = cuddE(N); 00382 table->subtableZ[ord].dead++; 00383 N = cuddT(N); 00384 } else { 00385 N = stack[--SP]; 00386 } 00387 } while (SP != 0); 00388 00389 } /* end of Cudd_RecursiveDerefZdd */
void Cudd_Ref | ( | DdNode * | n | ) |
AutomaticStart AutomaticEnd Function********************************************************************
Synopsis [Increases the reference count of a node, if it is not saturated.]
Description []
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_Deref]
Definition at line 98 of file cuddRef.c.
00100 { 00101 00102 n = Cudd_Regular(n); 00103 00104 cuddSatInc(n->ref); 00105 00106 } /* end of Cudd_Ref */
void cuddClearDeathRow | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Clears the death row.]
Description []
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef cuddGarbageCollect]
Definition at line 695 of file cuddRef.c.
00697 { 00698 #ifndef DD_NO_DEATH_ROW 00699 int i; 00700 00701 for (i = 0; i < table->deathRowDepth; i++) { 00702 if (table->deathRow[i] == NULL) break; 00703 Cudd_IterDerefBdd(table,table->deathRow[i]); 00704 table->deathRow[i] = NULL; 00705 } 00706 #ifdef DD_DEBUG 00707 for (; i < table->deathRowDepth; i++) { 00708 assert(table->deathRow[i] == NULL); 00709 } 00710 #endif 00711 table->nextDead = 0; 00712 #endif 00713 00714 } /* end of cuddClearDeathRow */
Function********************************************************************
Synopsis [Checks whether a node is in the death row.]
Description [Checks whether a node is in the death row. Returns the position of the first occurrence if the node is present; -1 otherwise.]
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow]
Definition at line 731 of file cuddRef.c.
00734 { 00735 #ifndef DD_NO_DEATH_ROW 00736 int i; 00737 00738 for (i = 0; i < dd->deathRowDepth; i++) { 00739 if (f == dd->deathRow[i]) { 00740 return(i); 00741 } 00742 } 00743 #endif 00744 00745 return(-1); 00746 00747 } /* end of cuddIsInDeathRow */
Function********************************************************************
Synopsis [Brings children of a dead node back.]
Description []
SideEffects [None]
SeeAlso [cuddReclaimZdd]
Definition at line 553 of file cuddRef.c.
00556 { 00557 DdNode *N; 00558 int ord; 00559 DdNodePtr *stack = table->stack; 00560 int SP = 1; 00561 double initialDead = table->dead; 00562 00563 N = Cudd_Regular(n); 00564 00565 #ifdef DD_DEBUG 00566 assert(N->ref == 0); 00567 #endif 00568 00569 do { 00570 if (N->ref == 0) { 00571 N->ref = 1; 00572 table->dead--; 00573 if (cuddIsConstant(N)) { 00574 table->constants.dead--; 00575 N = stack[--SP]; 00576 } else { 00577 ord = table->perm[N->index]; 00578 stack[SP++] = Cudd_Regular(cuddE(N)); 00579 table->subtables[ord].dead--; 00580 N = cuddT(N); 00581 } 00582 } else { 00583 cuddSatInc(N->ref); 00584 N = stack[--SP]; 00585 } 00586 } while (SP != 0); 00587 00588 N = Cudd_Regular(n); 00589 cuddSatDec(N->ref); 00590 table->reclaimed += initialDead - table->dead; 00591 00592 } /* end of cuddReclaim */
Function********************************************************************
Synopsis [Brings children of a dead ZDD node back.]
Description []
SideEffects [None]
SeeAlso [cuddReclaim]
Definition at line 607 of file cuddRef.c.
00610 { 00611 DdNode *N; 00612 int ord; 00613 DdNodePtr *stack = table->stack; 00614 int SP = 1; 00615 00616 N = n; 00617 00618 #ifdef DD_DEBUG 00619 assert(N->ref == 0); 00620 #endif 00621 00622 do { 00623 cuddSatInc(N->ref); 00624 00625 if (N->ref == 1) { 00626 table->deadZ--; 00627 table->reclaimed++; 00628 #ifdef DD_DEBUG 00629 assert(!cuddIsConstant(N)); 00630 #endif 00631 ord = table->permZ[N->index]; 00632 stack[SP++] = cuddE(N); 00633 table->subtableZ[ord].dead--; 00634 N = cuddT(N); 00635 } else { 00636 N = stack[--SP]; 00637 } 00638 } while (SP != 0); 00639 00640 cuddSatDec(n->ref); 00641 00642 } /* end of cuddReclaimZdd */
void cuddShrinkDeathRow | ( | DdManager * | table | ) |
Function********************************************************************
Synopsis [Shrinks the death row.]
Description [Shrinks the death row by a factor of four.]
SideEffects [None]
SeeAlso [cuddClearDeathRow]
Definition at line 657 of file cuddRef.c.
00659 { 00660 #ifndef DD_NO_DEATH_ROW 00661 int i; 00662 00663 if (table->deathRowDepth > 3) { 00664 for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) { 00665 if (table->deathRow[i] == NULL) break; 00666 Cudd_IterDerefBdd(table,table->deathRow[i]); 00667 table->deathRow[i] = NULL; 00668 } 00669 table->deathRowDepth /= 4; 00670 table->deadMask = table->deathRowDepth - 2; 00671 if ((unsigned) table->nextDead > table->deadMask) { 00672 table->nextDead = 0; 00673 } 00674 table->deathRow = REALLOC(DdNodePtr, table->deathRow, 00675 table->deathRowDepth); 00676 } 00677 #endif 00678 00679 } /* end of cuddShrinkDeathRow */
Function********************************************************************
Synopsis [Counts how many times a node is in the death row.]
Description []
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow]
Definition at line 762 of file cuddRef.c.
00765 { 00766 int count = 0; 00767 #ifndef DD_NO_DEATH_ROW 00768 int i; 00769 00770 for (i = 0; i < dd->deathRowDepth; i++) { 00771 count += f == dd->deathRow[i]; 00772 } 00773 #endif 00774 00775 return(count); 00776 00777 } /* end of cuddTimesInDeathRow */
char rcsid [] DD_UNUSED = "$Id: cuddRef.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" [static] |
CFile***********************************************************************
FileName [cuddRef.c]
PackageName [cudd]
Synopsis [Functions that manipulate the reference counts.]
Description [External procedures included in this module:
Internal procedures included in this module:
]
SeeAlso []
Author [Fabio Somenzi]
Copyright [ This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]