/**Function************************************************************* Synopsis [Initializes the reordering engine.] Description [The first argument is the max number of variables in the CUDD DD manager which will be used with the reordering engine (this number of should be the maximum of BDD and ZDD parts). The second argument is the maximum number of BDD nodes in the BDDs to be reordered. These limits are soft. Setting lower limits will later cause the reordering manager to resize internal data structures. However, setting the exact values will make reordering more efficient because resizing will be not necessary.] SideEffects [] SeeAlso [] ***********************************************************************/ reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ) { reo_man * p; // allocate and clean the data structure p = ALLOC( reo_man, 1 ); memset( p, 0, sizeof(reo_man) ); // resize the manager to meet user's needs reoResizeStructures( p, nDdVarsMax, nNodesMax, 100 ); // set the defaults p->fMinApl = 0; p->fMinWidth = 0; p->fRemapUp = 0; p->fVerbose = 0; p->fVerify = 0; p->nIters = 1; return p; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) { int Counter, i; // set the initial parameters p->dd = dd; p->pOrder = pOrder; p->nTops = nFuncs; // get the initial number of nodes p->nNodesBeg = Cudd_SharingSize( Funcs, nFuncs ); // resize the internal data structures of the manager if necessary reoResizeStructures( p, ddMax(dd->size,dd->sizeZ), p->nNodesBeg, nFuncs ); // compute the support p->pSupp = Extra_VectorSupportArray( dd, Funcs, nFuncs, p->pSupp ); // get the number of support variables p->nSupp = 0; for ( i = 0; i < dd->size; i++ ) p->nSupp += p->pSupp[i]; // if it is the constant function, no need to reorder if ( p->nSupp == 0 ) { for ( i = 0; i < nFuncs; i++ ) { FuncsRes[i] = Funcs[i]; Cudd_Ref( FuncsRes[i] ); } return; } // create the internal variable maps // go through variable levels in the manager Counter = 0; for ( i = 0; i < dd->size; i++ ) if ( p->pSupp[ dd->invperm[i] ] ) { p->pMapToPlanes[ dd->invperm[i] ] = Counter; p->pMapToDdVarsOrig[Counter] = dd->invperm[i]; if ( !p->fRemapUp ) p->pMapToDdVarsFinal[Counter] = dd->invperm[i]; else p->pMapToDdVarsFinal[Counter] = dd->invperm[Counter]; p->pOrderInt[Counter] = Counter; Counter++; } // set the initial parameters p->nUnitsUsed = 0; p->nNodesCur = 0; p->fThisIsAdd = 0; p->Signature++; // transfer the function from the CUDD package into REO"s internal data structure for ( i = 0; i < nFuncs; i++ ) p->pTops[i] = reoTransferNodesToUnits_rec( p, Funcs[i] ); assert( p->nNodesBeg == p->nNodesCur ); if ( !p->fThisIsAdd && p->fMinWidth ) { printf( "An important message from the REO reordering engine:\n" ); printf( "The BDD given to the engine for reordering contains complemented edges.\n" ); printf( "Currently, such BDDs cannot be reordered for the minimum width.\n" ); printf( "Therefore, minimization for the number of BDD nodes is performed.\n" ); fflush( stdout ); p->fMinApl = 0; p->fMinWidth = 0; } if ( p->fMinWidth ) reoProfileWidthStart(p); else if ( p->fMinApl ) reoProfileAplStart(p); else reoProfileNodesStart(p); if ( p->fVerbose ) { printf( "INITIAL: " ); if ( p->fMinWidth ) reoProfileWidthPrint(p); else if ( p->fMinApl ) reoProfileAplPrint(p); else reoProfileNodesPrint(p); } /////////////////////////////////////////////////////////////////// // performs the reordering p->nSwaps = 0; p->nNISwaps = 0; for ( i = 0; i < p->nIters; i++ ) { reoReorderSift( p ); // print statistics after each iteration if ( p->fVerbose ) { printf( "ITER #%d: ", i+1 ); if ( p->fMinWidth ) reoProfileWidthPrint(p); else if ( p->fMinApl ) reoProfileAplPrint(p); else reoProfileNodesPrint(p); } // if the cost function did not change, stop iterating if ( p->fMinWidth ) { p->nWidthEnd = p->nWidthCur; assert( p->nWidthEnd <= p->nWidthBeg ); if ( p->nWidthEnd == p->nWidthBeg ) break; } else if ( p->fMinApl ) { p->nAplEnd = p->nAplCur; assert( p->nAplEnd <= p->nAplBeg ); if ( p->nAplEnd == p->nAplBeg ) break; } else { p->nNodesEnd = p->nNodesCur; assert( p->nNodesEnd <= p->nNodesBeg ); if ( p->nNodesEnd == p->nNodesBeg ) break; } } assert( reoCheckLevels( p ) ); /////////////////////////////////////////////////////////////////// s_AplBefore = p->nAplBeg; s_AplAfter = p->nAplEnd; // set the initial parameters p->nRefNodes = 0; p->nNodesCur = 0; p->Signature++; // transfer the BDDs from REO's internal data structure to CUDD for ( i = 0; i < nFuncs; i++ ) { FuncsRes[i] = reoTransferUnitsToNodes_rec( p, p->pTops[i] ); Cudd_Ref( FuncsRes[i] ); } // undo the DDs referenced for storing in the cache for ( i = 0; i < p->nRefNodes; i++ ) Cudd_RecursiveDeref( dd, p->pRefNodes[i] ); // verify zero refs of the terminal nodes for ( i = 0; i < nFuncs; i++ ) { assert( reoRecursiveDeref( p->pTops[i] ) ); } assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); // prepare the variable map to return to the user if ( p->pOrder ) { // i is the current level in the planes data structure // p->pOrderInt[i] is the original level in the planes data structure // p->pMapToDdVarsOrig[i] is the variable, into which we remap when we construct the BDD from planes // p->pMapToDdVarsOrig[ p->pOrderInt[i] ] is the original BDD variable corresponding to this level // Therefore, p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ] // creates the permutation, which remaps the resulting BDD variable into the original BDD variable for ( i = 0; i < p->nSupp; i++ ) p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; } if ( p->fVerify ) { int fVerification; DdNode * FuncRemapped; int * pOrder; if ( p->pOrder == NULL ) { pOrder = ABC_ALLOC( int, p->nSupp ); for ( i = 0; i < p->nSupp; i++ ) pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; }