| /**CFile**************************************************************** |
| |
| FileName [cloudCore.c] |
| |
| PackageName [Fast application-specific BDD package.] |
| |
| Synopsis [The package core.] |
| |
| Author [Alan Mishchenko <alanmi@ece.pdx.edu>] |
| |
| Affiliation [ECE Department. Portland State University, Portland, Oregon.] |
| |
| Date [Ver. 1.0. Started - June 10, 2002.] |
| |
| Revision [$Id: cloudCore.c,v 1.0 2002/06/10 03:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include <string.h> |
| #include "cloud.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| // the number of operators using cache |
| static int CacheOperNum = 4; |
| |
| // the ratio of cache size to the unique table size for each operator |
| static int CacheLogRatioDefault[4] = { |
| 2, // CLOUD_OPER_AND, |
| 8, // CLOUD_OPER_XOR, |
| 8, // CLOUD_OPER_BDIFF, |
| 8 // CLOUD_OPER_LEQ |
| }; |
| |
| // the ratio of cache size to the unique table size for each operator |
| static int CacheSize[4] = { |
| 2, // CLOUD_OPER_AND, |
| 2, // CLOUD_OPER_XOR, |
| 2, // CLOUD_OPER_BDIFF, |
| 2 // CLOUD_OPER_LEQ |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| // static functions |
| static CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ); |
| static void cloudCacheAllocate( CloudManager * dd, CloudOper oper ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Starts the cloud manager.] |
| |
| Description [The first arguments is the number of elementary variables used. |
| The second arguments is the number of bits of the unsigned integer used to |
| represent nodes in the unique table. If the second argument is 0, the package |
| assumes 23 to represent nodes, which is equivalent to 2^23 = 8,388,608 nodes.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| CloudManager * Cloud_Init( int nVars, int nBits ) |
| { |
| CloudManager * dd; |
| int i; |
| abctime clk1, clk2; |
| |
| assert( nVars <= 100000 ); |
| assert( nBits < 32 ); |
| |
| // assign the defaults |
| if ( nBits == 0 ) |
| nBits = CLOUD_NODE_BITS; |
| |
| // start the manager |
| dd = ABC_CALLOC( CloudManager, 1 ); |
| dd->nMemUsed += sizeof(CloudManager); |
| |
| // variables |
| dd->nVars = nVars; // the number of variables allocated |
| // bits |
| dd->bitsNode = nBits; // the number of bits used for the node |
| for ( i = 0; i < CacheOperNum; i++ ) |
| dd->bitsCache[i] = nBits - CacheLogRatioDefault[i]; |
| // shifts |
| dd->shiftUnique = 8*sizeof(unsigned) - (nBits + 1); // gets node index in the hash table |
| for ( i = 0; i < CacheOperNum; i++ ) |
| dd->shiftCache[i] = 8*sizeof(unsigned) - dd->bitsCache[i]; |
| // nodes |
| dd->nNodesAlloc = (1 << (nBits + 1)); // 2 ^ (nBits + 1) |
| dd->nNodesLimit = (1 << nBits); // 2 ^ nBits |
| |
| // unique table |
| clk1 = Abc_Clock(); |
| dd->tUnique = ABC_CALLOC( CloudNode, dd->nNodesAlloc ); |
| dd->nMemUsed += sizeof(CloudNode) * dd->nNodesAlloc; |
| clk2 = Abc_Clock(); |
| //ABC_PRT( "calloc() time", clk2 - clk1 ); |
| |
| // set up the constant node (the only node that is not in the hash table) |
| dd->nSignCur = 1; |
| dd->tUnique[0].s = dd->nSignCur; |
| dd->tUnique[0].v = CLOUD_CONST_INDEX; |
| dd->tUnique[0].e = NULL; |
| dd->tUnique[0].t = NULL; |
| dd->one = dd->tUnique; |
| dd->zero = Cloud_Not(dd->one); |
| dd->nNodesCur = 1; |
| |
| // special nodes |
| dd->pNodeStart = dd->tUnique + 1; |
| dd->pNodeEnd = dd->tUnique + dd->nNodesAlloc; |
| |
| // set up the elementary variables |
| dd->vars = ABC_ALLOC( CloudNode *, dd->nVars ); |
| dd->nMemUsed += sizeof(CloudNode *) * dd->nVars; |
| for ( i = 0; i < dd->nVars; i++ ) |
| dd->vars[i] = cloudMakeNode( dd, i, dd->one, dd->zero ); |
| |
| return dd; |
| }; |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Stops the cloud manager.] |
| |
| Description [The first arguments tells show many elementary variables are used. |
| The second arguments tells how many bits of the unsigned integer are used |
| to represent regular nodes in the unique table.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| void Cloud_Quit( CloudManager * dd ) |
| { |
| int i; |
| ABC_FREE( dd->ppNodes ); |
| ABC_FREE( dd->tUnique ); |
| ABC_FREE( dd->vars ); |
| for ( i = 0; i < 4; i++ ) |
| ABC_FREE( dd->tCaches[i] ); |
| ABC_FREE( dd ); |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Prepares the manager for another run.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| void Cloud_Restart( CloudManager * dd ) |
| { |
| int i; |
| assert( dd->one->s == dd->nSignCur ); |
| dd->nSignCur++; |
| dd->one->s++; |
| for ( i = 0; i < dd->nVars; i++ ) |
| dd->vars[i]->s++; |
| dd->nNodesCur = 1 + dd->nVars; |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [This optional function allocates operation cache of the given size.] |
| |
| Description [Cache for each operation is allocated independently when the first |
| operation of the given type is performed. The user can allocate cache of his/her |
| preferred size by calling Cloud_CacheAllocate before the first operation of the |
| given type is performed, but this call is optional. Argument "logratio" gives |
| the binary logarithm of the ratio of the size of the unique table to that of cache. |
| For example, if "logratio" is equal to 3, and the unique table will be 2^3=8 times |
| larger than cache; so, if unique table is 2^23 = 8,388,608 nodes, the cache size |
| will be 2^3=8 times smaller and equal to 2^20 = 1,048,576 entries.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int logratio ) |
| { |
| assert( logratio > 0 ); // cache cannot be larger than the unique table |
| assert( logratio < dd->bitsNode ); // cache cannot be smaller than 2 entries |
| |
| if ( logratio ) |
| { |
| dd->bitsCache[oper] = dd->bitsNode - logratio; |
| dd->shiftCache[oper] = 8*sizeof(unsigned) - dd->bitsCache[oper]; |
| } |
| cloudCacheAllocate( dd, oper ); |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Internal cache allocation.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| void cloudCacheAllocate( CloudManager * dd, CloudOper oper ) |
| { |
| int nCacheEntries = (1 << dd->bitsCache[oper]); |
| |
| if ( CacheSize[oper] == 1 ) |
| { |
| dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry1, nCacheEntries ); |
| dd->nMemUsed += sizeof(CloudCacheEntry1) * nCacheEntries; |
| } |
| else if ( CacheSize[oper] == 2 ) |
| { |
| dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry2, nCacheEntries ); |
| dd->nMemUsed += sizeof(CloudCacheEntry2) * nCacheEntries; |
| } |
| else if ( CacheSize[oper] == 3 ) |
| { |
| dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry3, nCacheEntries ); |
| dd->nMemUsed += sizeof(CloudCacheEntry3) * nCacheEntries; |
| } |
| } |
| |
| |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Returns or creates a new node] |
| |
| Description [Checks the unique table for the existance of the node. If the node is |
| present, returns the node. If the node is absent, creates a new node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ) |
| { |
| CloudNode * pRes; |
| CLOUD_ASSERT(t); |
| CLOUD_ASSERT(e); |
| assert( v < Cloud_V(t) && v < Cloud_V(e) ); // variable should be above in the order |
| if ( Cloud_IsComplement(t) ) |
| { |
| pRes = cloudMakeNode( dd, v, Cloud_Not(t), Cloud_Not(e) ); |
| if ( pRes != NULL ) |
| pRes = Cloud_Not(pRes); |
| } |
| else |
| pRes = cloudMakeNode( dd, v, t, e ); |
| return pRes; |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Returns or creates a new node] |
| |
| Description [Checks the unique table for the existance of the node. If the node is |
| present, returns the node. If the node is absent, creates a new node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ) |
| { |
| CloudNode * entryUnique; |
| |
| CLOUD_ASSERT(t); |
| CLOUD_ASSERT(e); |
| |
| assert( ((int)v) >= 0 && ((int)v) < dd->nVars ); // the variable must be in the range |
| assert( v < Cloud_V(t) && v < Cloud_V(e) ); // variable should be above in the order |
| assert( !Cloud_IsComplement(t) ); // the THEN edge must not be complemented |
| |
| // make sure we are not searching for the constant node |
| assert( t && e ); |
| |
| // get the unique entry |
| entryUnique = dd->tUnique + cloudHashCudd3(v, t, e, dd->shiftUnique); |
| while ( entryUnique->s == dd->nSignCur ) |
| { |
| // compare the node |
| if ( entryUnique->v == v && entryUnique->t == t && entryUnique->e == e ) |
| { // the node is found |
| dd->nUniqueHits++; |
| return entryUnique; // returns the node |
| } |
| // increment the hash value modulus the hash table size |
| if ( ++entryUnique - dd->tUnique == dd->nNodesAlloc ) |
| entryUnique = dd->tUnique + 1; |
| // increment the number of steps through the table |
| dd->nUniqueSteps++; |
| } |
| dd->nUniqueMisses++; |
| |
| // check if the new node can be created |
| if ( ++dd->nNodesCur == dd->nNodesLimit ) |
| { // initiate the restart |
| printf( "Cloud needs restart!\n" ); |
| // fflush( stdout ); |
| // exit(1); |
| return NULL; |
| } |
| // create the node |
| entryUnique->s = dd->nSignCur; |
| entryUnique->v = v; |
| entryUnique->t = t; |
| entryUnique->e = e; |
| return entryUnique; // returns the node |
| } |
| |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the AND or two BDDs] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| CloudNode * cloudBddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ) |
| { |
| CloudNode * F, * G, * r; |
| CloudCacheEntry2 * cacheEntry; |
| CloudNode * fv, * fnv, * gv, * gnv, * t, * e; |
| CloudVar var; |
| |
| assert( f <= g ); |
| |
| // terminal cases |
| F = Cloud_Regular(f); |
| G = Cloud_Regular(g); |
| if ( F == G ) |
| { |
| if ( f == g ) |
| return f; |
| else |
| return dd->zero; |
| } |
| if ( F == dd->one ) |
| { |
| if ( f == dd->one ) |
| return g; |
| else |
| return f; |
| } |
| |
| // check cache |
| cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashCudd2(f, g, dd->shiftCache[CLOUD_OPER_AND]); |
| // cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashBuddy2(f, g, dd->shiftCache[CLOUD_OPER_AND]); |
| r = cloudCacheLookup2( cacheEntry, dd->nSignCur, f, g ); |
| if ( r != NULL ) |
| { |
| dd->nCacheHits++; |
| return r; |
| } |
| dd->nCacheMisses++; |
| |
| |
| // compute cofactors |
| if ( cloudV(F) <= cloudV(G) ) |
| { |
| var = cloudV(F); |
| if ( Cloud_IsComplement(f) ) |
| { |
| fnv = Cloud_Not(cloudE(F)); |
| fv = Cloud_Not(cloudT(F)); |
| } |
| else |
| { |
| fnv = cloudE(F); |
| fv = cloudT(F); |
| } |
| } |
| else |
| { |
| var = cloudV(G); |
| fv = fnv = f; |
| } |
| |
| if ( cloudV(G) <= cloudV(F) ) |
| { |
| if ( Cloud_IsComplement(g) ) |
| { |
| gnv = Cloud_Not(cloudE(G)); |
| gv = Cloud_Not(cloudT(G)); |
| } |
| else |
| { |
| gnv = cloudE(G); |
| gv = cloudT(G); |
| } |
| } |
| else |
| { |
| gv = gnv = g; |
| } |
| |
| if ( fv <= gv ) |
| t = cloudBddAnd( dd, fv, gv ); |
| else |
| t = cloudBddAnd( dd, gv, fv ); |
| |
| if ( t == NULL ) |
| return NULL; |
| |
| if ( fnv <= gnv ) |
| e = cloudBddAnd( dd, fnv, gnv ); |
| else |
| e = cloudBddAnd( dd, gnv, fnv ); |
| |
| if ( e == NULL ) |
| return NULL; |
| |
| if ( t == e ) |
| r = t; |
| else |
| { |
| if ( Cloud_IsComplement(t) ) |
| { |
| r = cloudMakeNode( dd, var, Cloud_Not(t), Cloud_Not(e) ); |
| if ( r == NULL ) |
| return NULL; |
| r = Cloud_Not(r); |
| } |
| else |
| { |
| r = cloudMakeNode( dd, var, t, e ); |
| if ( r == NULL ) |
| return NULL; |
| } |
| } |
| cloudCacheInsert2( cacheEntry, dd->nSignCur, f, g, r ); |
| return r; |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the AND or two BDDs] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| static inline CloudNode * cloudBddAnd_gate( CloudManager * dd, CloudNode * f, CloudNode * g ) |
| { |
| if ( f <= g ) |
| return cloudBddAnd(dd,f,g); |
| else |
| return cloudBddAnd(dd,g,f); |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the AND or two BDDs] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ) |
| { |
| if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL ) |
| return NULL; |
| CLOUD_ASSERT(f); |
| CLOUD_ASSERT(g); |
| if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) |
| cloudCacheAllocate( dd, CLOUD_OPER_AND ); |
| return cloudBddAnd_gate( dd, f, g ); |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the OR or two BDDs] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g ) |
| { |
| CloudNode * res; |
| if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL ) |
| return NULL; |
| CLOUD_ASSERT(f); |
| CLOUD_ASSERT(g); |
| if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) |
| cloudCacheAllocate( dd, CLOUD_OPER_AND ); |
| res = cloudBddAnd_gate( dd, Cloud_Not(f), Cloud_Not(g) ); |
| res = Cloud_NotCond( res, res != NULL ); |
| return res; |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the XOR or two BDDs] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| CloudNode * Cloud_bddXor( CloudManager * dd, CloudNode * f, CloudNode * g ) |
| { |
| CloudNode * t0, * t1, * r; |
| if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL ) |
| return NULL; |
| CLOUD_ASSERT(f); |
| CLOUD_ASSERT(g); |
| if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) |
| cloudCacheAllocate( dd, CLOUD_OPER_AND ); |
| t0 = cloudBddAnd_gate( dd, f, Cloud_Not(g) ); |
| if ( t0 == NULL ) |
| return NULL; |
| t1 = cloudBddAnd_gate( dd, Cloud_Not(f), g ); |
| if ( t1 == NULL ) |
| return NULL; |
| r = Cloud_bddOr( dd, t0, t1 ); |
| return r; |
| } |
| |
| |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs a DFS from f, clearing the LSB of the next |
| pointers.] |
| |
| Description [] |
| |
| SideEffects [None] |
| |
| SeeAlso [cloudSupport cloudDagSize] |
| |
| ******************************************************************************/ |
| static void cloudClearMark( CloudManager * dd, CloudNode * n ) |
| { |
| if ( !cloudNodeIsMarked(n) ) |
| return; |
| // clear visited flag |
| cloudNodeUnmark(n); |
| if ( cloudIsConstant(n) ) |
| return; |
| cloudClearMark( dd, cloudT(n) ); |
| cloudClearMark( dd, Cloud_Regular(cloudE(n)) ); |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the recursive step of Cloud_Support.] |
| |
| Description [Performs the recursive step of Cloud_Support. Performs a |
| DFS from f. The support is accumulated in supp as a side effect. Uses |
| the LSB of the then pointer as visited flag.] |
| |
| SideEffects [None] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| static void cloudSupport( CloudManager * dd, CloudNode * n, int * support ) |
| { |
| if ( cloudIsConstant(n) || cloudNodeIsMarked(n) ) |
| return; |
| // set visited flag |
| cloudNodeMark(n); |
| support[cloudV(n)] = 1; |
| cloudSupport( dd, cloudT(n), support ); |
| cloudSupport( dd, Cloud_Regular(cloudE(n)), support ); |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Finds the variables on which a DD depends.] |
| |
| Description [Finds the variables on which a DD depends. |
| Returns a BDD consisting of the product of the variables if |
| successful; NULL otherwise.] |
| |
| SideEffects [None] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n ) |
| { |
| CloudNode * res; |
| int * support, i; |
| |
| CLOUD_ASSERT(n); |
| |
| // allocate and initialize support array for cloudSupport |
| support = ABC_CALLOC( int, dd->nVars ); |
| |
| // compute support and clean up markers |
| cloudSupport( dd, Cloud_Regular(n), support ); |
| cloudClearMark( dd, Cloud_Regular(n) ); |
| |
| // transform support from array to cube |
| res = dd->one; |
| for ( i = dd->nVars - 1; i >= 0; i-- ) // for each level bottom-up |
| if ( support[i] == 1 ) |
| { |
| res = Cloud_bddAnd( dd, res, dd->vars[i] ); |
| if ( res == NULL ) |
| break; |
| } |
| ABC_FREE( support ); |
| return res; |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Counts the variables on which a DD depends.] |
| |
| Description [Counts the variables on which a DD depends. |
| Returns the number of the variables if successful; Cloud_OUT_OF_MEM |
| otherwise.] |
| |
| SideEffects [None] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| int Cloud_SupportSize( CloudManager * dd, CloudNode * n ) |
| { |
| int * support, i, count; |
| |
| CLOUD_ASSERT(n); |
| |
| // allocate and initialize support array for cloudSupport |
| support = ABC_CALLOC( int, dd->nVars ); |
| |
| // compute support and clean up markers |
| cloudSupport( dd, Cloud_Regular(n), support ); |
| cloudClearMark( dd, Cloud_Regular(n) ); |
| |
| // count support variables |
| count = 0; |
| for ( i = 0; i < dd->nVars; i++ ) |
| { |
| if ( support[i] == 1 ) |
| count++; |
| } |
| |
| ABC_FREE( support ); |
| return count; |
| } |
| |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the recursive step of Cloud_DagSize.] |
| |
| Description [Performs the recursive step of Cloud_DagSize. Returns the |
| number of nodes in the graph rooted at n.] |
| |
| SideEffects [None] |
| |
| ******************************************************************************/ |
| static int cloudDagSize( CloudManager * dd, CloudNode * n ) |
| { |
| int tval, eval; |
| if ( cloudNodeIsMarked(n) ) |
| return 0; |
| // set visited flag |
| cloudNodeMark(n); |
| if ( cloudIsConstant(n) ) |
| return 1; |
| tval = cloudDagSize( dd, cloudT(n) ); |
| eval = cloudDagSize( dd, Cloud_Regular(cloudE(n)) ); |
| return tval + eval + 1; |
| |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Counts the number of nodes in a DD.] |
| |
| Description [Counts the number of nodes in a DD. Returns the number |
| of nodes in the graph rooted at node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| int Cloud_DagSize( CloudManager * dd, CloudNode * n ) |
| { |
| int res; |
| res = cloudDagSize( dd, Cloud_Regular( n ) ); |
| cloudClearMark( dd, Cloud_Regular( n ) ); |
| return res; |
| |
| } |
| |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the recursive step of Cloud_DagSize.] |
| |
| Description [Performs the recursive step of Cloud_DagSize. Returns the |
| number of nodes in the graph rooted at n.] |
| |
| SideEffects [None] |
| |
| ******************************************************************************/ |
| static int Cloud_DagCollect_rec( CloudManager * dd, CloudNode * n, int * pCounter ) |
| { |
| int tval, eval; |
| if ( cloudNodeIsMarked(n) ) |
| return 0; |
| // set visited flag |
| cloudNodeMark(n); |
| if ( cloudIsConstant(n) ) |
| { |
| dd->ppNodes[(*pCounter)++] = n; |
| return 1; |
| } |
| tval = Cloud_DagCollect_rec( dd, cloudT(n), pCounter ); |
| eval = Cloud_DagCollect_rec( dd, Cloud_Regular(cloudE(n)), pCounter ); |
| dd->ppNodes[(*pCounter)++] = n; |
| return tval + eval + 1; |
| |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Counts the number of nodes in a DD.] |
| |
| Description [Counts the number of nodes in a DD. Returns the number |
| of nodes in the graph rooted at node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| int Cloud_DagCollect( CloudManager * dd, CloudNode * n ) |
| { |
| int res, Counter = 0; |
| if ( dd->ppNodes == NULL ) |
| dd->ppNodes = ABC_ALLOC( CloudNode *, dd->nNodesLimit ); |
| res = Cloud_DagCollect_rec( dd, Cloud_Regular( n ), &Counter ); |
| cloudClearMark( dd, Cloud_Regular( n ) ); |
| assert( res == Counter ); |
| return res; |
| |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Counts the number of nodes in an array of DDs.] |
| |
| Description [Counts the number of nodes in a DD. Returns the number |
| of nodes in the graph rooted at node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| int Cloud_SharingSize( CloudManager * dd, CloudNode ** pn, int nn ) |
| { |
| int res, i; |
| res = 0; |
| for ( i = 0; i < nn; i++ ) |
| res += cloudDagSize( dd, Cloud_Regular( pn[i] ) ); |
| for ( i = 0; i < nn; i++ ) |
| cloudClearMark( dd, Cloud_Regular( pn[i] ) ); |
| return res; |
| } |
| |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Returns one cube contained in the given BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| ******************************************************************************/ |
| CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * bFunc ) |
| { |
| CloudNode * bFunc0, * bFunc1, * res; |
| |
| if ( Cloud_IsConstant(bFunc) ) |
| return bFunc; |
| |
| // cofactor |
| if ( Cloud_IsComplement(bFunc) ) |
| { |
| bFunc0 = Cloud_Not( cloudE(bFunc) ); |
| bFunc1 = Cloud_Not( cloudT(bFunc) ); |
| } |
| else |
| { |
| bFunc0 = cloudE(bFunc); |
| bFunc1 = cloudT(bFunc); |
| } |
| |
| // try to find the cube with the negative literal |
| res = Cloud_GetOneCube( dd, bFunc0 ); |
| if ( res == NULL ) |
| return NULL; |
| |
| if ( res != dd->zero ) |
| { |
| res = Cloud_bddAnd( dd, res, Cloud_Not(dd->vars[Cloud_V(bFunc)]) ); |
| } |
| else |
| { |
| // try to find the cube with the positive literal |
| res = Cloud_GetOneCube( dd, bFunc1 ); |
| if ( res == NULL ) |
| return NULL; |
| assert( res != dd->zero ); |
| res = Cloud_bddAnd( dd, res, dd->vars[Cloud_V(bFunc)] ); |
| } |
| return res; |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Prints the BDD as a set of disjoint cubes to the standard output.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| ******************************************************************************/ |
| void Cloud_bddPrint( CloudManager * dd, CloudNode * Func ) |
| { |
| CloudNode * Cube; |
| int fFirst = 1; |
| |
| if ( Func == dd->zero ) |
| printf( "Constant 0." ); |
| else if ( Func == dd->one ) |
| printf( "Constant 1." ); |
| else |
| { |
| while ( 1 ) |
| { |
| Cube = Cloud_GetOneCube( dd, Func ); |
| if ( Cube == NULL || Cube == dd->zero ) |
| break; |
| if ( fFirst ) fFirst = 0; |
| else printf( " + " ); |
| Cloud_bddPrintCube( dd, Cube ); |
| Func = Cloud_bddAnd( dd, Func, Cloud_Not(Cube) ); |
| } |
| } |
| printf( "\n" ); |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Prints one cube.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| ******************************************************************************/ |
| void Cloud_bddPrintCube( CloudManager * dd, CloudNode * bCube ) |
| { |
| CloudNode * bCube0, * bCube1; |
| |
| assert( !Cloud_IsConstant(bCube) ); |
| while ( 1 ) |
| { |
| // get the node structure |
| if ( Cloud_IsConstant(bCube) ) |
| break; |
| |
| // cofactor the cube |
| if ( Cloud_IsComplement(bCube) ) |
| { |
| bCube0 = Cloud_Not( cloudE(bCube) ); |
| bCube1 = Cloud_Not( cloudT(bCube) ); |
| } |
| else |
| { |
| bCube0 = cloudE(bCube); |
| bCube1 = cloudT(bCube); |
| } |
| |
| if ( bCube0 != dd->zero ) |
| { |
| assert( bCube1 == dd->zero ); |
| printf( "[%d]'", cloudV(bCube) ); |
| bCube = bCube0; |
| } |
| else |
| { |
| assert( bCube1 != dd->zero ); |
| printf( "[%d]", cloudV(bCube) ); |
| bCube = bCube1; |
| } |
| } |
| } |
| |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Prints info.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| void Cloud_PrintInfo( CloudManager * dd ) |
| { |
| if ( dd == NULL ) return; |
| printf( "The number of unique table nodes allocated = %12d.\n", dd->nNodesAlloc ); |
| printf( "The number of unique table nodes present = %12d.\n", dd->nNodesCur ); |
| printf( "The number of unique table hits = %12d.\n", dd->nUniqueHits ); |
| printf( "The number of unique table misses = %12d.\n", dd->nUniqueMisses ); |
| printf( "The number of unique table steps = %12d.\n", dd->nUniqueSteps ); |
| printf( "The number of cache hits = %12d.\n", dd->nCacheHits ); |
| printf( "The number of cache misses = %12d.\n", dd->nCacheMisses ); |
| printf( "The current signature = %12d.\n", dd->nSignCur ); |
| printf( "The total memory in use = %12d.\n", dd->nMemUsed ); |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Prints the state of the hash table.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| void Cloud_PrintHashTable( CloudManager * dd ) |
| { |
| int i; |
| |
| for ( i = 0; i < dd->nNodesAlloc; i++ ) |
| if ( dd->tUnique[i].v == CLOUD_CONST_INDEX ) |
| printf( "-" ); |
| else |
| printf( "+" ); |
| printf( "\n" ); |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| ABC_NAMESPACE_IMPL_END |
| |