diff options
Diffstat (limited to 'src/misc/extra/extraBddMisc.c')
-rw-r--r-- | src/misc/extra/extraBddMisc.c | 2342 |
1 files changed, 0 insertions, 2342 deletions
diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c deleted file mode 100644 index a2ba4036..00000000 --- a/src/misc/extra/extraBddMisc.c +++ /dev/null @@ -1,2342 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddMisc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [DD-based utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $] - -***********************************************************************/ - -#include "extraBdd.h" - -ABC_NAMESPACE_IMPL_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -// file "extraDdTransfer.c" -static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute ); -static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ); -static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) ); - -static DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); - -// file "cuddUtils.c" -static void ddSupportStep(DdNode *f, int *support); -static void ddClearFlag(DdNode *f); - -static DdNode* extraZddPrimes( DdManager *dd, DdNode* F ); - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] - - Description [Convert a {A,B}DD from a manager to another one. The orders of the - variables in the two managers may be different. Returns a - pointer to the {A,B}DD in the destination manager if successful; NULL - otherwise. The i-th entry in the array Permute tells what is the index - of the i-th variable from the old manager in the new manager.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ) -{ - DdNode * bRes; - do - { - ddDestination->reordered = 0; - bRes = extraTransferPermute( ddSource, ddDestination, f, Permute ); - } - while ( ddDestination->reordered == 1 ); - return ( bRes ); - -} /* end of Extra_TransferPermute */ - -/**Function******************************************************************** - - Synopsis [Transfers the BDD from one manager into another level by level.] - - Description [Transfers the BDD from one manager into another while - preserving the correspondence between variables level by level.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ) -{ - DdNode * bRes; - int * pPermute; - int nMin, nMax, i; - - nMin = ddMin(ddSource->size, ddDestination->size); - nMax = ddMax(ddSource->size, ddDestination->size); - pPermute = ABC_ALLOC( int, nMax ); - // set up the variable permutation - for ( i = 0; i < nMin; i++ ) - pPermute[ ddSource->invperm[i] ] = ddDestination->invperm[i]; - if ( ddSource->size > ddDestination->size ) - { - for ( ; i < nMax; i++ ) - pPermute[ ddSource->invperm[i] ] = -1; - } - bRes = Extra_TransferPermute( ddSource, ddDestination, f, pPermute ); - ABC_FREE( pPermute ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Remaps the function to depend on the topmost variables on the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddRemapUp( - DdManager * dd, - DdNode * bF ) -{ - int * pPermute; - DdNode * bSupp, * bTemp, * bRes; - int Counter; - - pPermute = ABC_ALLOC( int, dd->size ); - - // get support - bSupp = Cudd_Support( dd, bF ); Cudd_Ref( bSupp ); - - // create the variable map - // to remap the DD into the upper part of the manager - Counter = 0; - for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) - pPermute[bTemp->index] = dd->invperm[Counter++]; - - // transfer the BDD and remap it - bRes = Cudd_bddPermute( dd, bF, pPermute ); Cudd_Ref( bRes ); - - // remove support - Cudd_RecursiveDeref( dd, bSupp ); - - // return - Cudd_Deref( bRes ); - ABC_FREE( pPermute ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Moves the BDD by the given number of variables up or down.] - - Description [] - - SideEffects [] - - SeeAlso [Extra_bddShift] - -******************************************************************************/ -DdNode * Extra_bddMove( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int nVars) -{ - DdNode * res; - DdNode * bVars; - if ( nVars == 0 ) - return bF; - if ( Cudd_IsConstant(bF) ) - return bF; - assert( nVars <= dd->size ); - if ( nVars > 0 ) - bVars = dd->vars[nVars]; - else - bVars = Cudd_Not(dd->vars[-nVars]); - - do { - dd->reordered = 0; - res = extraBddMove( dd, bF, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_bddMove */ - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_StopManager( DdManager * dd ) -{ - int RetValue; - // check for remaining references in the package - RetValue = Cudd_CheckZeroRef( dd ); - if ( RetValue > 10 ) -// if ( RetValue ) - printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); -// Cudd_PrintInfo( dd, stdout ); - Cudd_Quit( dd ); -} - -/**Function******************************************************************** - - Synopsis [Outputs the BDD in a readable format.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void Extra_bddPrint( DdManager * dd, DdNode * F ) -{ - DdGen * Gen; - int * Cube; - CUDD_VALUE_TYPE Value; - int nVars = dd->size; - int fFirstCube = 1; - int i; - - if ( F == NULL ) - { - printf("NULL"); - return; - } - if ( F == b0 ) - { - printf("Constant 0"); - return; - } - if ( F == b1 ) - { - printf("Constant 1"); - return; - } - - Cudd_ForeachCube( dd, F, Gen, Cube, Value ) - { - if ( fFirstCube ) - fFirstCube = 0; - else -// Output << " + "; - printf( " + " ); - - for ( i = 0; i < nVars; i++ ) - if ( Cube[i] == 0 ) - printf( "[%d]'", i ); -// printf( "%c'", (char)('a'+i) ); - else if ( Cube[i] == 1 ) - printf( "[%d]", i ); -// printf( "%c", (char)('a'+i) ); - } - -// printf("\n"); -} - -/**Function******************************************************************** - - Synopsis [Outputs the BDD in a readable format.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void Extra_bddPrintSupport( DdManager * dd, DdNode * F ) -{ - DdNode * bSupp; - bSupp = Cudd_Support( dd, F ); Cudd_Ref( bSupp ); - Extra_bddPrint( dd, bSupp ); - Cudd_RecursiveDeref( dd, bSupp ); -} - -/**Function******************************************************************** - - Synopsis [Returns the size of the support.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ) -{ - int Counter = 0; - while ( bSupp != b1 ) - { - assert( !Cudd_IsComplement(bSupp) ); - assert( cuddE(bSupp) == b0 ); - - bSupp = cuddT(bSupp); - Counter++; - } - return Counter; -} - -/**Function******************************************************************** - - Synopsis [Returns 1 if the support contains the given BDD variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ) -{ - for( ; bS != b1; bS = cuddT(bS) ) - if ( bS->index == bVar->index ) - return 1; - return 0; -} - -/**Function******************************************************************** - - Synopsis [Returns 1 if two supports represented as BDD cubes are overlapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ) -{ - while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) - { - // if the top vars are the same, they intersect - if ( S1->index == S2->index ) - return 1; - // if the top vars are different, skip the one, which is higher - if ( dd->perm[S1->index] < dd->perm[S2->index] ) - S1 = cuddT(S1); - else - S2 = cuddT(S2); - } - return 0; -} - -/**Function******************************************************************** - - Synopsis [Returns the number of different vars in two supports.] - - Description [Counts the number of variables that appear in one support and - does not appear in other support. If the number exceeds DiffMax, returns DiffMax.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ) -{ - int Result = 0; - while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) - { - // if the top vars are the same, this var is the same - if ( S1->index == S2->index ) - { - S1 = cuddT(S1); - S2 = cuddT(S2); - continue; - } - // the top var is different - Result++; - - if ( Result >= DiffMax ) - return DiffMax; - - // if the top vars are different, skip the one, which is higher - if ( dd->perm[S1->index] < dd->perm[S2->index] ) - S1 = cuddT(S1); - else - S2 = cuddT(S2); - } - - // consider the remaining variables - if ( S1->index != CUDD_CONST_INDEX ) - Result += Extra_bddSuppSize(dd,S1); - else if ( S2->index != CUDD_CONST_INDEX ) - Result += Extra_bddSuppSize(dd,S2); - - if ( Result >= DiffMax ) - return DiffMax; - return Result; -} - - -/**Function******************************************************************** - - Synopsis [Checks the support containment.] - - Description [This function returns 1 if one support is contained in another. - In this case, bLarge (bSmall) is assigned to point to the larger (smaller) support. - If the supports are identical, return 0 and does not assign the supports!] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ) -{ - DdNode * bSL = bL; - DdNode * bSH = bH; - int fLcontainsH = 1; - int fHcontainsL = 1; - int TopVar; - - if ( bSL == bSH ) - return 0; - - while ( bSL != b1 || bSH != b1 ) - { - if ( bSL == b1 ) - { // Low component has no vars; High components has some vars - fLcontainsH = 0; - if ( fHcontainsL == 0 ) - return 0; - else - break; - } - - if ( bSH == b1 ) - { // similarly - fHcontainsL = 0; - if ( fLcontainsH == 0 ) - return 0; - else - break; - } - - // determine the topmost var of the supports by comparing their levels - if ( dd->perm[bSL->index] < dd->perm[bSH->index] ) - TopVar = bSL->index; - else - TopVar = bSH->index; - - if ( TopVar == bSL->index && TopVar == bSH->index ) - { // they are on the same level - // it does not tell us anything about their containment - // skip this var - bSL = cuddT(bSL); - bSH = cuddT(bSH); - } - else if ( TopVar == bSL->index ) // and TopVar != bSH->index - { // Low components is higher and contains more vars - // it is not possible that High component contains Low - fHcontainsL = 0; - // skip this var - bSL = cuddT(bSL); - } - else // if ( TopVar == bSH->index ) // and TopVar != bSL->index - { // similarly - fLcontainsH = 0; - // skip this var - bSH = cuddT(bSH); - } - - // check the stopping condition - if ( !fHcontainsL && !fLcontainsH ) - return 0; - } - // only one of them can be true at the same time - assert( !fHcontainsL || !fLcontainsH ); - if ( fHcontainsL ) - { - *bLarge = bH; - *bSmall = bL; - } - else // fLcontainsH - { - *bLarge = bL; - *bSmall = bH; - } - return 1; -} - - -/**Function******************************************************************** - - Synopsis [Finds variables on which the DD depends and returns them as am array.] - - Description [Finds the variables on which the DD depends. Returns an array - with entries set to 1 for those variables that belong to the support; - NULL otherwise. The array is allocated by the user and should have at least - as many entries as the maximum number of variables in BDD and ZDD parts of - the manager.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -int * -Extra_SupportArray( - DdManager * dd, /* manager */ - DdNode * f, /* DD whose support is sought */ - int * support ) /* array allocated by the user */ -{ - int i, size; - - /* Initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - for (i = 0; i < size; i++) - support[i] = 0; - - /* Compute support and clean up markers. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(Cudd_Regular(f)); - - return(support); - -} /* end of Extra_SupportArray */ - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a set of DDs depends.] - - Description [Finds the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns a BDD consisting of the product of the variables if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_ClassifySupport] - -******************************************************************************/ -int * -Extra_VectorSupportArray( - DdManager * dd, /* manager */ - DdNode ** F, /* array of DDs whose support is sought */ - int n, /* size of the array */ - int * support ) /* array allocated by the user */ -{ - int i, size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax( dd->size, dd->sizeZ ); - for ( i = 0; i < size; i++ ) - support[i] = 0; - - /* Compute support and clean up markers. */ - for ( i = 0; i < n; i++ ) - ddSupportStep( Cudd_Regular(F[i]), support ); - for ( i = 0; i < n; i++ ) - ddClearFlag( Cudd_Regular(F[i]) ); - - return support; -} - -/**Function******************************************************************** - - Synopsis [Find any cube belonging to the on-set of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ) -{ - char * s_Temp; - DdNode * bCube, * bTemp; - int v; - - // get the vector of variables in the cube - s_Temp = ABC_ALLOC( char, dd->size ); - Cudd_bddPickOneCube( dd, bF, s_Temp ); - - // start the cube - bCube = b1; Cudd_Ref( bCube ); - for ( v = 0; v < dd->size; v++ ) - if ( s_Temp[v] == 0 ) - { -// Cube &= !s_XVars[v]; - bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(dd->vars[v]) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - else if ( s_Temp[v] == 1 ) - { -// Cube &= s_XVars[v]; - bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[v] ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref(bCube); - ABC_FREE( s_Temp ); - return bCube; -} - -/**Function******************************************************************** - - Synopsis [Returns one cube contained in the given BDD.] - - Description [This function returns the cube with the smallest - bits-to-integer value.] - - SideEffects [] - -******************************************************************************/ -DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bFuncR, * bFunc0, * bFunc1; - DdNode * bRes0, * bRes1, * bRes; - - bFuncR = Cudd_Regular(bFunc); - if ( cuddIsConstant(bFuncR) ) - return bFunc; - - // cofactor - if ( Cudd_IsComplement(bFunc) ) - { - bFunc0 = Cudd_Not( cuddE(bFuncR) ); - bFunc1 = Cudd_Not( cuddT(bFuncR) ); - } - else - { - bFunc0 = cuddE(bFuncR); - bFunc1 = cuddT(bFuncR); - } - - // try to find the cube with the negative literal - bRes0 = Extra_bddGetOneCube( dd, bFunc0 ); Cudd_Ref( bRes0 ); - - if ( bRes0 != b0 ) - { - bRes = Cudd_bddAnd( dd, bRes0, Cudd_Not(dd->vars[bFuncR->index]) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - } - else - { - Cudd_RecursiveDeref( dd, bRes0 ); - // try to find the cube with the positive literal - bRes1 = Extra_bddGetOneCube( dd, bFunc1 ); Cudd_Ref( bRes1 ); - assert( bRes1 != b0 ); - bRes = Cudd_bddAnd( dd, bRes1, dd->vars[bFuncR->index] ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes1 ); - } - - Cudd_Deref( bRes ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) -{ - DdNode * bTemp, * bProd; - int i; - assert( iStart <= iStop ); - assert( iStart >= 0 && iStart <= dd->size ); - assert( iStop >= 0 && iStop <= dd->size ); - bProd = b1; Cudd_Ref( bProd ); - for ( i = iStart; i < iStop; i++ ) - { - bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bProd ); - return bProd; -} - -/**Function******************************************************************** - - Synopsis [Computes the cube of BDD variables corresponding to bits it the bit-code] - - Description [Returns a bdd composed of elementary bdds found in array BddVars[] such - that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1, - the most significant bit is encoded with the first bdd variable). If the variables - BddVars are not specified, takes the first CodeWidth variables of the manager] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ) -{ - int z; - DdNode * bTemp, * bVar, * bVarBdd, * bResult; - - bResult = b1; Cudd_Ref( bResult ); - for ( z = 0; z < CodeWidth; z++ ) - { - bVarBdd = (pbVars)? pbVars[z]: dd->vars[z]; - if ( fMsbFirst ) - bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 ); - else - bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 ); - bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bResult ); - - return bResult; -} /* end of Extra_bddBitsToCube */ - -/**Function******************************************************************** - - Synopsis [Finds the support as a negative polarity cube.] - - Description [Finds the variables on which a DD depends. Returns a BDD - consisting of the product of the variables in the negative polarity - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_VectorSupport Cudd_Support] - -******************************************************************************/ -DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ) -{ - int *support; - DdNode *res, *tmp, *var; - int i, j; - int size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax( dd->size, dd->sizeZ ); - support = ABC_ALLOC( int, size ); - if ( support == NULL ) - { - dd->errorCode = CUDD_MEMORY_OUT; - return ( NULL ); - } - for ( i = 0; i < size; i++ ) - { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - ddSupportStep( Cudd_Regular( f ), support ); - ddClearFlag( Cudd_Regular( f ) ); - - /* Transform support from array to cube. */ - do - { - dd->reordered = 0; - res = DD_ONE( dd ); - cuddRef( res ); - for ( j = size - 1; j >= 0; j-- ) - { /* for each level bottom-up */ - i = ( j >= dd->size ) ? j : dd->invperm[j]; - if ( support[i] == 1 ) - { - var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) ); - ////////////////////////////////////////////////////////////////// - var = Cudd_Not(var); - ////////////////////////////////////////////////////////////////// - cuddRef( var ); - tmp = cuddBddAndRecur( dd, res, var ); - if ( tmp == NULL ) - { - Cudd_RecursiveDeref( dd, res ); - Cudd_RecursiveDeref( dd, var ); - res = NULL; - break; - } - cuddRef( tmp ); - Cudd_RecursiveDeref( dd, res ); - Cudd_RecursiveDeref( dd, var ); - res = tmp; - } - } - } - while ( dd->reordered == 1 ); - - ABC_FREE( support ); - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - -} /* end of Extra_SupportNeg */ - -/**Function******************************************************************** - - Synopsis [Returns 1 if the BDD is the BDD of elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddIsVar( DdNode * bFunc ) -{ - bFunc = Cudd_Regular( bFunc ); - if ( cuddIsConstant(bFunc) ) - return 0; - return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) ); -} - -/**Function******************************************************************** - - Synopsis [Creates AND composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Creates OR composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Creates EXOR composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Computes the set of primes as a ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ) -{ - DdNode *res; - do { - dd->reordered = 0; - res = extraZddPrimes(dd, F); - if ( dd->reordered == 1 ) - printf("\nReordering in Extra_zddPrimes()\n"); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddPrimes */ - -/**Function******************************************************************** - - Synopsis [Permutes the variables of the array of BDDs.] - - Description [Given a permutation in array permut, creates a new BDD - with permuted variables. There should be an entry in array permut - for each variable in the manager. The i-th entry of permut holds the - index of the variable that is to substitute the i-th variable. - The DDs in the resulting array are already referenced.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] - -******************************************************************************/ -void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ) -{ - DdHashTable *table; - int i, k; - do - { - manager->reordered = 0; - table = cuddHashTableInit( manager, 1, 2 ); - - /* permute the output functions one-by-one */ - for ( i = 0; i < nNodes; i++ ) - { - bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut ); - if ( bNodesOut[i] == NULL ) - { - /* deref the array of the already computed outputs */ - for ( k = 0; k < i; k++ ) - Cudd_RecursiveDeref( manager, bNodesOut[k] ); - break; - } - cuddRef( bNodesOut[i] ); - } - /* Dispose of local cache. */ - cuddHashTableQuit( table ); - } - while ( manager->reordered == 1 ); -} /* end of Extra_bddPermuteArray */ - - -/**Function******************************************************************** - - Synopsis [Computes the positive polarty cube composed of the first vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) -{ - DdNode * bRes; - DdNode * bTemp; - int i; - - bRes = b1; Cudd_Ref( bRes ); - for ( i = 0; i < nVars; i++ ) - { - bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bRes ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Changes the polarity of vars listed in the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddChangePolarity( - DdManager * dd, /* the DD manager */ - DdNode * bFunc, - DdNode * bVars) -{ - DdNode *res; - do { - dd->reordered = 0; - res = extraBddChangePolarity( dd, bFunc, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_bddChangePolarity */ - - -/**Function************************************************************* - - Synopsis [Checks if the given variable belongs to the cube.] - - Description [Return -1 if the var does not appear in the cube. - Otherwise, returns polarity (0 or 1) of the var in the cube.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_bddVarIsInCube( DdNode * bCube, int iVar ) -{ - DdNode * bCube0, * bCube1; - while ( Cudd_Regular(bCube)->index != CUDD_CONST_INDEX ) - { - bCube0 = Cudd_NotCond( cuddE(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) ); - bCube1 = Cudd_NotCond( cuddT(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) ); - // make sure it is a cube - assert( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) || // bCube0 == 0 - (Cudd_IsComplement(bCube1) && Cudd_Regular(bCube1)->index == CUDD_CONST_INDEX) ); // bCube1 == 0 - // quit if it is the last one - if ( Cudd_Regular(bCube)->index == iVar ) - return (int)(Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX); - // get the next cube - if ( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) ) - bCube = bCube1; - else - bCube = bCube0; - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Computes the AND of two BDD with different orders.] - - Description [Derives the result of Boolean AND of bF and bG in ddF. - The array pPermute gives the mapping of variables of ddG into that of ddF.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ) -{ - DdHashTable * table; - DdNode * bRes; - do - { - ddF->reordered = 0; - table = cuddHashTableInit( ddF, 2, 256 ); - if (table == NULL) return NULL; - bRes = extraBddAndPermute( table, ddF, bF, ddG, bG, pPermute ); - if ( bRes ) cuddRef( bRes ); - cuddHashTableQuit( table ); - if ( bRes ) cuddDeref( bRes ); -//if ( ddF->reordered == 1 ) -//printf( "Reordering happened\n" ); - } - while ( ddF->reordered == 1 ); -//printf( "|F| =%6d |G| =%6d |H| =%6d |F|*|G| =%9d\n", -// Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes), -// Cudd_DagSize(bF) * Cudd_DagSize(bG) ); - return ( bRes ); -} - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddMove( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bDist) -{ - DdNode * bRes; - - if ( Cudd_IsConstant(bF) ) - return bF; - - if ( (bRes = cuddCacheLookup2(dd, extraBddMove, bF, bDist)) ) - return bRes; - else - { - DdNode * bRes0, * bRes1; - DdNode * bF0, * bF1; - DdNode * bFR = Cudd_Regular(bF); - int VarNew; - - if ( Cudd_IsComplement(bDist) ) - VarNew = bFR->index - Cudd_Not(bDist)->index; - else - VarNew = bFR->index + bDist->index; - assert( VarNew < dd->size ); - - // cofactor the functions - if ( bFR != bF ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - bRes0 = extraBddMove( dd, bF0, bDist ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - - bRes1 = extraBddMove( dd, bF1, bDist ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bRes1 ); - - /* only bRes0 and bRes1 are referenced at this point */ - bRes = cuddBddIteRecur( dd, dd->vars[VarNew], bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - return NULL; - } - cuddRef( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - - /* insert the result into cache */ - cuddCacheInsert2( dd, extraBddMove, bF, bDist, bRes ); - cuddDeref( bRes ); - return bRes; - } -} /* end of extraBddMove */ - - -/**Function******************************************************************** - - Synopsis [Finds three cofactors of the cover w.r.t. to the topmost variable.] - - Description [Finds three cofactors of the cover w.r.t. to the topmost variable. - Does not check the cover for being a constant. Assumes that ZDD variables encoding - positive and negative polarities are adjacent in the variable order. Is different - from cuddZddGetCofactors3() in that it does not compute the cofactors w.r.t. the - given variable but takes the cofactors with respent to the topmost variable. - This function is more efficient when used in recursive procedures because it does - not require referencing of the resulting cofactors (compare cuddZddProduct() - and extraZddPrimeProduct()).] - - SideEffects [None] - - SeeAlso [cuddZddGetCofactors3] - -******************************************************************************/ -void -extraDecomposeCover( - DdManager* dd, /* the manager */ - DdNode* zC, /* the cover */ - DdNode** zC0, /* the pointer to the negative var cofactor */ - DdNode** zC1, /* the pointer to the positive var cofactor */ - DdNode** zC2 ) /* the pointer to the cofactor without var */ -{ - if ( (zC->index & 1) == 0 ) - { /* the top variable is present in positive polarity and maybe in negative */ - - DdNode *Temp = cuddE( zC ); - *zC1 = cuddT( zC ); - if ( cuddIZ(dd,Temp->index) == cuddIZ(dd,zC->index) + 1 ) - { /* Temp is not a terminal node - * top var is present in negative polarity */ - *zC2 = cuddE( Temp ); - *zC0 = cuddT( Temp ); - } - else - { /* top var is not present in negative polarity */ - *zC2 = Temp; - *zC0 = dd->zero; - } - } - else - { /* the top variable is present only in negative */ - *zC1 = dd->zero; - *zC2 = cuddE( zC ); - *zC0 = cuddT( zC ); - } -} /* extraDecomposeCover */ - - - -/**Function******************************************************************** - - Synopsis [Counts the total number of cubes in the ISOPs of the functions.] - - Description [Returns -1 if the number of cubes exceeds the limit.] - - SideEffects [None] - - SeeAlso [Extra_TransferPermute] - -******************************************************************************/ -static DdNode * extraBddCountCubes( DdManager * dd, DdNode * L, DdNode * U, st__table *table, int * pnCubes, int Limit ) -{ - DdNode *one = DD_ONE(dd); - DdNode *zero = Cudd_Not(one); - int v, top_l, top_u; - DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; - DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; - DdNode *Isub0, *Isub1, *Id; - DdNode *x; - DdNode *term0, *term1, *sum; - DdNode *Lv, *Uv, *Lnv, *Unv; - DdNode *r; - int index; - int Count0 = 0, Count1 = 0, Count2 = 0; - - statLine(dd); - if (L == zero) - { - *pnCubes = 0; - return(zero); - } - if (U == one) - { - *pnCubes = 1; - return(one); - } - - /* Check cache */ - r = cuddCacheLookup2(dd, cuddBddIsop, L, U); - if (r) - { - int nCubes = 0; - if ( st__lookup( table, (char *)r, (char **)&nCubes ) ) - *pnCubes = nCubes; - else assert( 0 ); - return r; - } - - top_l = dd->perm[Cudd_Regular(L)->index]; - top_u = dd->perm[Cudd_Regular(U)->index]; - v = ddMin(top_l, top_u); - - /* Compute cofactors */ - if (top_l == v) { - index = Cudd_Regular(L)->index; - Lv = Cudd_T(L); - Lnv = Cudd_E(L); - if (Cudd_IsComplement(L)) { - Lv = Cudd_Not(Lv); - Lnv = Cudd_Not(Lnv); - } - } - else { - index = Cudd_Regular(U)->index; - Lv = Lnv = L; - } - - if (top_u == v) { - Uv = Cudd_T(U); - Unv = Cudd_E(U); - if (Cudd_IsComplement(U)) { - Uv = Cudd_Not(Uv); - Unv = Cudd_Not(Unv); - } - } - else { - Uv = Unv = U; - } - - Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); - if (Lsub0 == NULL) - return(NULL); - Cudd_Ref(Lsub0); - Usub0 = Unv; - Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); - if (Lsub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - return(NULL); - } - Cudd_Ref(Lsub1); - Usub1 = Uv; - - Isub0 = extraBddCountCubes(dd, Lsub0, Usub0, table, &Count0, Limit); - if (Isub0 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - return(NULL); - } - Cudd_Ref(Isub0); - Isub1 = extraBddCountCubes(dd, Lsub1, Usub1, table, &Count1, Limit); - if (Isub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - Cudd_RecursiveDeref(dd, Isub0); - return(NULL); - } - Cudd_Ref(Isub1); - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - - Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); - if (Lsuper0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - return(NULL); - } - Cudd_Ref(Lsuper0); - Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); - if (Lsuper1 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - return(NULL); - } - Cudd_Ref(Lsuper1); - Usuper0 = Unv; - Usuper1 = Uv; - - /* Ld = Lsuper0 + Lsuper1 */ - Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); - Ld = Cudd_NotCond(Ld, Ld != NULL); - if (Ld == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - return(NULL); - } - Cudd_Ref(Ld); - Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); - if (Ud == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - Cudd_RecursiveDeref(dd, Ld); - return(NULL); - } - Cudd_Ref(Ud); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - - Id = extraBddCountCubes(dd, Ld, Ud, table, &Count2, Limit); - if (Id == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - return(NULL); - } - Cudd_Ref(Id); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - - x = cuddUniqueInter(dd, index, one, zero); - if (x == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - return(NULL); - } - Cudd_Ref(x); - term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); - if (term0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - Cudd_Ref(term0); - Cudd_RecursiveDeref(dd, Isub0); - term1 = cuddBddAndRecur(dd, x, Isub1); - if (term1 == NULL) { - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, term0); - return(NULL); - } - Cudd_Ref(term1); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, Isub1); - /* sum = term0 + term1 */ - sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); - sum = Cudd_NotCond(sum, sum != NULL); - if (sum == NULL) { - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - return(NULL); - } - Cudd_Ref(sum); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - /* r = sum + Id */ - r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); - r = Cudd_NotCond(r, r != NULL); - if (r == NULL) { - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, sum); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDeref(dd, sum); - Cudd_RecursiveDeref(dd, Id); - - cuddCacheInsert2(dd, cuddBddIsop, L, U, r); - *pnCubes = Count0 + Count1 + Count2; - if ( st__add_direct( table, (char *)r, (char *)(ABC_PTRINT_T)*pnCubes ) == st__OUT_OF_MEM ) - { - Cudd_RecursiveDeref( dd, r ); - return NULL; - } - if ( *pnCubes > Limit ) - { - Cudd_RecursiveDeref( dd, r ); - return NULL; - } - //printf( "%d ", *pnCubes ); - Cudd_Deref(r); - return r; -} -int Extra_bddCountCubes( DdManager * dd, DdNode ** pFuncs, int nFuncs, int fMode, int nLimit, int * pGuide ) -{ - DdNode * pF0, * pF1; - int i, Count, Count0, Count1, CounterAll = 0; - st__table *table = st__init_table( st__ptrcmp, st__ptrhash ); - unsigned int saveLimit = dd->maxLive; - dd->maxLive = dd->keys - dd->dead + 1000000; // limit on intermediate BDD nodes - for ( i = 0; i < nFuncs; i++ ) - { - if ( !pFuncs[i] ) - continue; - pF1 = pF0 = NULL; - Count0 = Count1 = nLimit; - if ( fMode == -1 || fMode == 1 ) // both or pos - pF1 = extraBddCountCubes( dd, pFuncs[i], pFuncs[i], table, &Count1, nLimit ); - pFuncs[i] = Cudd_Not( pFuncs[i] ); - if ( fMode == -1 || fMode == 0 ) // both or neg - pF0 = extraBddCountCubes( dd, pFuncs[i], pFuncs[i], table, &Count0, Count1 ); - pFuncs[i] = Cudd_Not( pFuncs[i] ); - if ( !pF1 && !pF0 ) - break; - if ( !pF0 ) pGuide[i] = 1, Count = Count1; // use pos - else if ( !pF1 ) pGuide[i] = 0, Count = Count0; // use neg - else if ( Count1 <= Count0 ) pGuide[i] = 1, Count = Count1; // use pos - else pGuide[i] = 0, Count = Count0; // use neg - CounterAll += Count; - //printf( "Output %5d has %5d cubes (%d) (%5d and %5d)\n", nOuts++, Count, pGuide[i], Count1, Count0 ); - } - dd->maxLive = saveLimit; - st__free_table( table ); - return i == nFuncs ? CounterAll : -1; -} /* end of Extra_bddCountCubes */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Extra_TransferPermute] - -******************************************************************************/ -DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) -{ - DdNode *res; - st__table *table = NULL; - st__generator *gen = NULL; - DdNode *key, *value; - - table = st__init_table( st__ptrcmp, st__ptrhash ); - if ( table == NULL ) - goto failure; - res = extraTransferPermuteRecur( ddS, ddD, f, table, Permute ); - if ( res != NULL ) - cuddRef( res ); - - /* Dereference all elements in the table and dispose of the table. - ** This must be done also if res is NULL to avoid leaks in case of - ** reordering. */ - gen = st__init_gen( table ); - if ( gen == NULL ) - goto failure; - while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) ) - { - Cudd_RecursiveDeref( ddD, value ); - } - st__free_gen( gen ); - gen = NULL; - st__free_table( table ); - table = NULL; - - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - - failure: - if ( table != NULL ) - st__free_table( table ); - if ( gen != NULL ) - st__free_gen( gen ); - return ( NULL ); - -} /* end of extraTransferPermute */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Extra_TransferPermute.] - - Description [Performs the recursive step of Extra_TransferPermute. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [extraTransferPermute] - -******************************************************************************/ -static DdNode * -extraTransferPermuteRecur( - DdManager * ddS, - DdManager * ddD, - DdNode * f, - st__table * table, - int * Permute ) -{ - DdNode *ft, *fe, *t, *e, *var, *res; - DdNode *one, *zero; - int index; - int comple = 0; - - statLine( ddD ); - one = DD_ONE( ddD ); - comple = Cudd_IsComplement( f ); - - /* Trivial cases. */ - if ( Cudd_IsConstant( f ) ) - return ( Cudd_NotCond( one, comple ) ); - - - /* Make canonical to increase the utilization of the cache. */ - f = Cudd_NotCond( f, comple ); - /* Now f is a regular pointer to a non-constant node. */ - - /* Check the cache. */ - if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) ) - return ( Cudd_NotCond( res, comple ) ); - - if ( ddS->TimeStop && Abc_Clock() > ddS->TimeStop ) - return NULL; - if ( ddD->TimeStop && Abc_Clock() > ddD->TimeStop ) - return NULL; - - /* Recursive step. */ - if ( Permute ) - index = Permute[f->index]; - else - index = f->index; - - ft = cuddT( f ); - fe = cuddE( f ); - - t = extraTransferPermuteRecur( ddS, ddD, ft, table, Permute ); - if ( t == NULL ) - { - return ( NULL ); - } - cuddRef( t ); - - e = extraTransferPermuteRecur( ddS, ddD, fe, table, Permute ); - if ( e == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - return ( NULL ); - } - cuddRef( e ); - - zero = Cudd_Not(ddD->one); - var = cuddUniqueInter( ddD, index, one, zero ); - if ( var == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - res = cuddBddIteRecur( ddD, var, t, e ); - - if ( res == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - cuddRef( res ); - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - - if ( st__add_direct( table, ( char * ) f, ( char * ) res ) == - st__OUT_OF_MEM ) - { - Cudd_RecursiveDeref( ddD, res ); - return ( NULL ); - } - return ( Cudd_NotCond( res, comple ) ); - -} /* end of extraTransferPermuteRecur */ - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_Support.] - - Description [Performs the recursive step of Cudd_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 [ddClearFlag] - -******************************************************************************/ -static void -ddSupportStep( - DdNode * f, - int * support) -{ - if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { - return; - } - - support[f->index] = 1; - ddSupportStep(cuddT(f),support); - ddSupportStep(Cudd_Regular(cuddE(f)),support); - /* Mark as visited. */ - f->next = Cudd_Not(f->next); - return; - -} /* end of ddSupportStep */ - - -/**Function******************************************************************** - - Synopsis [Performs a DFS from f, clearing the LSB of the next - pointers.] - - Description [] - - SideEffects [None] - - SeeAlso [ddSupportStep ddDagInt] - -******************************************************************************/ -static void -ddClearFlag( - DdNode * f) -{ - if (!Cudd_IsComplement(f->next)) { - return; - } - /* Clear visited flag. */ - f->next = Cudd_Regular(f->next); - if (cuddIsConstant(f)) { - return; - } - ddClearFlag(cuddT(f)); - ddClearFlag(Cudd_Regular(cuddE(f))); - return; - -} /* end of ddClearFlag */ - - -/**Function******************************************************************** - - Synopsis [Composed three subcovers into one ZDD.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -extraComposeCover( - DdManager* dd, /* the manager */ - DdNode* zC0, /* the pointer to the negative var cofactor */ - DdNode* zC1, /* the pointer to the positive var cofactor */ - DdNode* zC2, /* the pointer to the cofactor without var */ - int TopVar) /* the index of the positive ZDD var */ -{ - DdNode * zRes, * zTemp; - /* compose with-neg-var and without-var using the neg ZDD var */ - zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 ); - if ( zTemp == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zC0); - Cudd_RecursiveDerefZdd(dd, zC1); - Cudd_RecursiveDerefZdd(dd, zC2); - return NULL; - } - cuddRef( zTemp ); - cuddDeref( zC0 ); - cuddDeref( zC2 ); - - /* compose with-pos-var and previous result using the pos ZDD var */ - zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zC1); - Cudd_RecursiveDerefZdd(dd, zTemp); - return NULL; - } - cuddDeref( zC1 ); - cuddDeref( zTemp ); - return zRes; -} /* extraComposeCover */ - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of prime computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode* extraZddPrimes( DdManager *dd, DdNode* F ) -{ - DdNode *zRes; - - if ( F == Cudd_Not( dd->one ) ) - return dd->zero; - if ( F == dd->one ) - return dd->one; - - /* check cache */ - zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F); - if (zRes) - return(zRes); - { - /* temporary variables */ - DdNode *bF01, *zP0, *zP1; - /* three components of the prime set */ - DdNode *zResE, *zResP, *zResN; - int fIsComp = Cudd_IsComplement( F ); - - /* find cofactors of F */ - DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp ); - DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp ); - - /* find the intersection of cofactors */ - bF01 = cuddBddAndRecur( dd, bF0, bF1 ); - if ( bF01 == NULL ) return NULL; - cuddRef( bF01 ); - - /* solve the problems for cofactors */ - zP0 = extraZddPrimes( dd, bF0 ); - if ( zP0 == NULL ) - { - Cudd_RecursiveDeref( dd, bF01 ); - return NULL; - } - cuddRef( zP0 ); - - zP1 = extraZddPrimes( dd, bF1 ); - if ( zP1 == NULL ) - { - Cudd_RecursiveDeref( dd, bF01 ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - return NULL; - } - cuddRef( zP1 ); - - /* check for local unateness */ - if ( bF01 == bF0 ) /* unate increasing */ - { - /* intersection is useless */ - cuddDeref( bF01 ); - /* the primes of intersection are the primes of F0 */ - zResE = zP0; - /* there are no primes with negative var */ - zResN = dd->zero; - cuddRef( zResN ); - /* primes with positive var are primes of F1 that are not primes of F01 */ - zResP = cuddZddDiff( dd, zP1, zP0 ); - if ( zResP == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResN ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResP ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - } - else if ( bF01 == bF1 ) /* unate decreasing */ - { - /* intersection is useless */ - cuddDeref( bF01 ); - /* the primes of intersection are the primes of F1 */ - zResE = zP1; - /* there are no primes with positive var */ - zResP = dd->zero; - cuddRef( zResP ); - /* primes with negative var are primes of F0 that are not primes of F01 */ - zResN = cuddZddDiff( dd, zP0, zP1 ); - if ( zResN == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResP ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - return NULL; - } - cuddRef( zResN ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - } - else /* not unate */ - { - /* primes without the top var are primes of F10 */ - zResE = extraZddPrimes( dd, bF01 ); - if ( zResE == NULL ) - { - Cudd_RecursiveDerefZdd( dd, bF01 ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResE ); - Cudd_RecursiveDeref( dd, bF01 ); - - /* primes with the negative top var are those of P0 that are not in F10 */ - zResN = cuddZddDiff( dd, zP0, zResE ); - if ( zResN == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResN ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - - /* primes with the positive top var are those of P1 that are not in F10 */ - zResP = cuddZddDiff( dd, zP1, zResE ); - if ( zResP == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResN ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResP ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - } - - zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index ); - if ( zRes == NULL ) return NULL; - - /* insert the result into cache */ - cuddCacheInsert1(dd, extraZddPrimes, F, zRes); - return zRes; - } -} /* end of extraZddPrimes */ - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddPermute.] - - Description [ Recursively puts the BDD in the order given in the array permut. - Checks for trivial cases to terminate recursion, then splits on the - children of this node. Once the solutions for the children are - obtained, it puts into the current position the node from the rest of - the BDD that should be here. Then returns this BDD. - The key here is that the node being visited is NOT put in its proper - place by this instance, but rather is switched when its proper position - is reached in the recursion tree.<p> - The DdNode * that is returned is the same BDD as passed in as node, - but in the new order.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] - -******************************************************************************/ -static DdNode * -cuddBddPermuteRecur( DdManager * manager /* DD manager */ , - DdHashTable * table /* computed table */ , - DdNode * node /* BDD to be reordered */ , - int *permut /* permutation array */ ) -{ - DdNode *N, *T, *E; - DdNode *res; - int index; - - statLine( manager ); - N = Cudd_Regular( node ); - - /* Check for terminal case of constant node. */ - if ( cuddIsConstant( N ) ) - { - return ( node ); - } - - /* If problem already solved, look up answer and return. */ - if ( N->ref != 1 && ( res = cuddHashTableLookup1( table, N ) ) != NULL ) - { - return ( Cudd_NotCond( res, N != node ) ); - } - - /* Split and recur on children of this node. */ - T = cuddBddPermuteRecur( manager, table, cuddT( N ), permut ); - if ( T == NULL ) - return ( NULL ); - cuddRef( T ); - E = cuddBddPermuteRecur( manager, table, cuddE( N ), permut ); - if ( E == NULL ) - { - Cudd_IterDerefBdd( manager, T ); - return ( NULL ); - } - cuddRef( E ); - - /* Move variable that should be in this position to this position - ** by retrieving the single var BDD for that variable, and calling - ** cuddBddIteRecur with the T and E we just created. - */ - index = permut[N->index]; - res = cuddBddIteRecur( manager, manager->vars[index], T, E ); - if ( res == NULL ) - { - Cudd_IterDerefBdd( manager, T ); - Cudd_IterDerefBdd( manager, E ); - return ( NULL ); - } - cuddRef( res ); - Cudd_IterDerefBdd( manager, T ); - Cudd_IterDerefBdd( manager, E ); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if ( N->ref != 1 ) - { - ptrint fanout = ( ptrint ) N->ref; - cuddSatDec( fanout ); - if ( !cuddHashTableInsert1( table, N, res, fanout ) ) - { - Cudd_IterDerefBdd( manager, res ); - return ( NULL ); - } - } - cuddDeref( res ); - return ( Cudd_NotCond( res, N != node ) ); - -} /* end of cuddBddPermuteRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddChangePolarity().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddChangePolarity( - DdManager * dd, /* the DD manager */ - DdNode * bFunc, - DdNode * bVars) -{ - DdNode * bRes; - - if ( bVars == b1 ) - return bFunc; - if ( Cudd_IsConstant(bFunc) ) - return bFunc; - - if ( (bRes = cuddCacheLookup2(dd, extraBddChangePolarity, bFunc, bVars)) ) - return bRes; - else - { - DdNode * bFR = Cudd_Regular(bFunc); - int LevelF = dd->perm[bFR->index]; - int LevelV = dd->perm[bVars->index]; - - if ( LevelV < LevelF ) - bRes = extraBddChangePolarity( dd, bFunc, cuddT(bVars) ); - else // if ( LevelF <= LevelV ) - { - DdNode * bRes0, * bRes1; - DdNode * bF0, * bF1; - DdNode * bVarsNext; - - // cofactor the functions - if ( bFR != bFunc ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - if ( LevelF == LevelV ) - bVarsNext = cuddT(bVars); - else - bVarsNext = bVars; - - bRes0 = extraBddChangePolarity( dd, bF0, bVarsNext ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - - bRes1 = extraBddChangePolarity( dd, bF1, bVarsNext ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bRes1 ); - - if ( LevelF == LevelV ) - { // swap the cofactors - DdNode * bTemp; - bTemp = bRes0; - bRes0 = bRes1; - bRes1 = bTemp; - } - - /* only aRes0 and aRes1 are referenced at this point */ - - /* consider the case when Res0 and Res1 are the same node */ - if ( bRes0 == bRes1 ) - bRes = bRes1; - /* consider the case when Res1 is complemented */ - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter(dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0)); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - } - - /* insert the result into cache */ - cuddCacheInsert2(dd, extraBddChangePolarity, bFunc, bVars, bRes); - return bRes; - } -} /* end of extraBddChangePolarity */ - - - -static int Counter = 0; - -/**Function************************************************************* - - Synopsis [Computes the AND of two BDD with different orders.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ) -{ - DdNode * bF0, * bF1, * bG0, * bG1, * bRes0, * bRes1, * bRes, * bVar; - int LevF, LevG, Lev; - - // if F == 0, return 0 - if ( bF == Cudd_Not(ddF->one) ) - return Cudd_Not(ddF->one); - // if G == 0, return 0 - if ( bG == Cudd_Not(ddG->one) ) - return Cudd_Not(ddF->one); - // if G == 1, return F - if ( bG == ddG->one ) - return bF; - // cannot use F == 1, because the var order of G has to be changed - - // check cache - if ( //(Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1) && - (bRes = cuddHashTableLookup2(table, bF, bG)) ) - return bRes; - Counter++; - - if ( ddF->TimeStop && Abc_Clock() > ddF->TimeStop ) - return NULL; - if ( ddG->TimeStop && Abc_Clock() > ddG->TimeStop ) - return NULL; - - // find the topmost variable in F and G using var order of F - LevF = cuddI( ddF, Cudd_Regular(bF)->index ); - LevG = cuddI( ddF, pPermute ? pPermute[Cudd_Regular(bG)->index] : Cudd_Regular(bG)->index ); - Lev = Abc_MinInt( LevF, LevG ); - assert( Lev < ddF->size ); - bVar = ddF->vars[ddF->invperm[Lev]]; - - // cofactor - bF0 = (Lev < LevF) ? bF : Cudd_NotCond( cuddE(Cudd_Regular(bF)), Cudd_IsComplement(bF) ); - bF1 = (Lev < LevF) ? bF : Cudd_NotCond( cuddT(Cudd_Regular(bF)), Cudd_IsComplement(bF) ); - bG0 = (Lev < LevG) ? bG : Cudd_NotCond( cuddE(Cudd_Regular(bG)), Cudd_IsComplement(bG) ); - bG1 = (Lev < LevG) ? bG : Cudd_NotCond( cuddT(Cudd_Regular(bG)), Cudd_IsComplement(bG) ); - - // call for cofactors - bRes0 = extraBddAndPermute( table, ddF, bF0, ddG, bG0, pPermute ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - // call for cofactors - bRes1 = extraBddAndPermute( table, ddF, bF1, ddG, bG1, pPermute ); - if ( bRes1 == NULL ) - { - Cudd_IterDerefBdd( ddF, bRes0 ); - return NULL; - } - cuddRef( bRes1 ); - - // compose the result - bRes = cuddBddIteRecur( ddF, bVar, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_IterDerefBdd( ddF, bRes0 ); - Cudd_IterDerefBdd( ddF, bRes1 ); - return NULL; - } - cuddRef( bRes ); - Cudd_IterDerefBdd( ddF, bRes0 ); - Cudd_IterDerefBdd( ddF, bRes1 ); - - // cache the result -// if ( Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1 ) - { - ptrint fanout = (ptrint)Cudd_Regular(bF)->ref * Cudd_Regular(bG)->ref; - cuddSatDec(fanout); - cuddHashTableInsert2( table, bF, bG, bRes, fanout ); - } - cuddDeref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [Testbench.] - - Description [This procedure takes BDD manager ddF and two BDDs - in this manager (bF and bG). It creates a new manager ddG, - transfers bG into it and then reorders it, resulting in bG2. - Then it tries to compute the product of bF and bG2 in ddF.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TestAndPerm( DdManager * ddF, DdNode * bF, DdNode * bG ) -{ - DdManager * ddG; - DdNode * bG2, * bRes1, * bRes2; - abctime clk; - // disable variable ordering in ddF - Cudd_AutodynDisable( ddF ); - - // create new BDD manager - ddG = Cudd_Init( ddF->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // transfer BDD into it - Cudd_ShuffleHeap( ddG, ddF->invperm ); - bG2 = Extra_TransferLevelByLevel( ddF, ddG, bG ); Cudd_Ref( bG2 ); - // reorder the new manager - Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); - - // compute the result -clk = Abc_Clock(); - bRes1 = Cudd_bddAnd( ddF, bF, bG ); Cudd_Ref( bRes1 ); -Abc_PrintTime( 1, "Runtime of Cudd_bddAnd ", Abc_Clock() - clk ); - - // compute the result -Counter = 0; -clk = Abc_Clock(); - bRes2 = Extra_bddAndPermute( ddF, bF, ddG, bG2, NULL ); Cudd_Ref( bRes2 ); -Abc_PrintTime( 1, "Runtime of new procedure", Abc_Clock() - clk ); -printf( "Recursive calls = %d\n", Counter ); -printf( "|F| =%6d |G| =%6d |H| =%6d |F|*|G| =%9d ", - Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes2), - Cudd_DagSize(bF) * Cudd_DagSize(bG) ); - - if ( bRes1 == bRes2 ) - printf( "Result verified.\n\n" ); - else - printf( "Result is incorrect.\n\n" ); - - Cudd_RecursiveDeref( ddF, bRes1 ); - Cudd_RecursiveDeref( ddF, bRes2 ); - // quit the new manager - Cudd_RecursiveDeref( ddG, bG2 ); - Extra_StopManager( ddG ); - - // re-enable variable ordering in ddF - Cudd_AutodynEnable( ddF, CUDD_REORDER_SYMM_SIFT ); -} - -/**Function************************************************************* - - Synopsis [Writes ZDD into a PLA file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_zddDumpPla( DdManager * dd, DdNode * F, int nVars, char * pFileName ) -{ - DdGen *gen; - char * pCube; - int * pPath, i; - FILE * pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - { - printf( "Cannot open file \"%s\" for writing.\n", pFileName ); - return; - } - fprintf( pFile, "# PLA file dumped by Extra_zddDumpPla() in ABC\n" ); - fprintf( pFile, ".i %d\n", nVars ); - fprintf( pFile, ".o 1\n" ); - pCube = ABC_CALLOC( char, dd->sizeZ ); - Cudd_zddForeachPath( dd, F, gen, pPath ) - { - for ( i = 0; i < nVars; i++ ) - pCube[i] = '-'; - for ( i = 0; i < nVars; i++ ) - if ( pPath[2*i] == 1 || pPath[2*i+1] == 1 ) - pCube[i] = '0' + (pPath[2*i] == 1); - fprintf( pFile, "%s 1\n", pCube ); - } - fprintf( pFile, ".e\n\n" ); - fclose( pFile ); - ABC_FREE( pCube ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - |