/**Function******************************************************************** Synopsis [Rearranges a set of variables in the BDD B.] Description [Rearranges a set of variables in the BDD B. The size of the set is given by n. This procedure is intended for the `randomization' of the priority functions. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_PrioritySelect] ******************************************************************************/ DdNode * Cudd_bddAdjPermuteX( DdManager * dd, DdNode * B, DdNode ** x, int n) { DdNode *swapped; int i, j, k; int *permut; permut = ALLOC(int,dd->size); if (permut == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < dd->size; i++) permut[i] = i; for (i = 0; i < n-2; i += 3) { j = x[i]->index; k = x[i+1]->index; permut[j] = k; permut[k] = j; } swapped = Cudd_bddPermute(dd,B,permut); FREE(permut); return(swapped); } /* end of Cudd_bddAdjPermuteX */
/**Function******************************************************************** Synopsis [Swaps two sets of variables of the same size (x and y) in the BDD f.] Description [Swaps two sets of variables of the same size (x and y) in the BDD f. The size is given by n. The two sets of variables are assumed to be disjoint. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] ******************************************************************************/ DdNode * Cudd_bddSwapVariables( DdManager * dd, DdNode * f, DdNode ** x, DdNode ** y, int n) { DdNode *swapped; int i, j, k; int *permut; permut = ALLOC(int,dd->size); if (permut == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < dd->size; i++) permut[i] = i; for (i = 0; i < n; i++) { j = x[i]->index; k = y[i]->index; permut[j] = k; permut[k] = j; } swapped = Cudd_bddPermute(dd,f,permut); FREE(permut); return(swapped); } /* end of Cudd_bddSwapVariables */
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) { DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; int i; int fAllBuffs = 1; static int Permute[MAXINPUTS]; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->Type == DT_PRIME ); // transform the function of this block to depend on inputs // corresponding to the formal inputs // first, substitute those inputs that have some blocks associated with them // second, remap the inputs to the top of the manager (then, it is easy to output them) // start the function bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); // go over all primary inputs for ( i = 0; i < pNode->nDecs; i++ ) if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer { bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); Cudd_RecursiveDeref( dd, bCube0 ); bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); Cudd_RecursiveDeref( dd, bCube1 ); Cudd_RecursiveDeref( dd, bNewFunc ); // use the variable in the i-th level of the manager // bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); // use the first variale in the support of the component bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); } if ( fRemap ) { // remap the function to the top of the manager // remap the function to the first variables of the manager for ( i = 0; i < pNode->nDecs; i++ ) // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; Permute[ pNode->pDecs[i]->S->index ] = i; bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bNewFunc ); return bNewFunc; }
DdNode* compute_EX(DdManager* m, pos* postab, DdNode* R, DdNode* p) { DdNode* tmp; /* rename variables */ int perm[2*(postab->num_procs*postab->pc_size+postab->num_vars)]; int i, j, k; for (i=0; i<postab->num_vars; i++) { perm[i] = i+postab->num_vars; perm[i+postab->num_vars] = i; } for (j=0; j<postab->num_procs; j++) { for (k=0; k<postab->pc_size; k++) { perm[postab->num_vars+i] = postab->pc_[j][k]; perm[postab->num_vars+postab->num_procs*postab->pc_size+i++] = postab->pc[j][k]; } } p = Cudd_bddPermute(m, p, perm); /* construct cube of next state variables */ DdNode* cube = Cudd_ReadOne(m); for (i=0; i<postab->num_vars; i++) { tmp = Cudd_bddAnd(m, cube, Cudd_bddIthVar(m, postab->num_vars+i)); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, cube); cube = tmp; } for (i=0; i<postab->num_procs*postab->pc_size; i++) { tmp = Cudd_bddAnd(m, cube, Cudd_bddIthVar(m, 2*postab->num_vars+postab->num_procs*postab->pc_size+i)); Cudd_Ref(tmp); Cudd_RecursiveDeref(m, cube); cube = tmp; } DdNode* EX_p = Cudd_bddAndAbstract(m, R, p, cube); Cudd_Ref(EX_p); Cudd_RecursiveDeref(m, p); Cudd_RecursiveDeref(m, cube); return EX_p; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure is similar to Cudd_ShuffleHeap() and Cudd_bddPermute().] Description [The first argument is the REO manager. The 2nd/3d arguments are the function and its CUDD manager. The last argument is the permutation to be implemented. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use (that is, the size of CUDD manager and the size of REO manager).] SideEffects [Note that the resulting BDD is not referenced.] SeeAlso [] ***********************************************************************/ DdNode * reoShuffle( reo_man * p, DdManager * dd, DdNode * bFunc, int * pPerm, int * pPermInv ) { DdNode * bFuncRes = NULL; int i, k, v; if ( Cudd_IsConstant(bFunc) ) return bFunc; // set the initial parameters p->dd = dd; p->nSupp = Cudd_SupportSize( dd, bFunc ); p->nTops = 1; // p->nNodesBeg = Cudd_DagSize( bFunc ); // set the starting permutation for ( i = 0; i < p->nSupp; i++ ) { p->pOrderInt[i] = i; p->pMapToPlanes[ dd->invperm[i] ] = i; p->pMapToDdVarsFinal[i] = dd->invperm[i]; } // 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 p->pTops[0] = reoTransferNodesToUnits_rec( p, bFunc ); // assert( p->nNodesBeg == p->nNodesCur ); // reorder one variable at a time for ( i = 0; i < p->nSupp; i++ ) { if ( p->pOrderInt[i] == pPerm[i] ) continue; // find where is variable number pPerm[i] for ( k = i + 1; k < p->nSupp; k++ ) if ( pPerm[i] == p->pOrderInt[k] ) break; if ( k == p->nSupp ) { printf( "reoShuffle() Error: Cannot find a variable.\n" ); goto finish; } // move the variable up for ( v = k - 1; v >= i; v-- ) { reoReorderSwapAdjacentVars( p, v, 1 ); // check if the number of nodes is not too large if ( p->nNodesCur > 10000 ) { printf( "reoShuffle() Error: BDD size is too large.\n" ); goto finish; } } assert( p->pOrderInt[i] == pPerm[i] ); } // set the initial parameters p->nRefNodes = 0; p->nNodesCur = 0; p->Signature++; // transfer the BDDs from REO's internal data structure to CUDD bFuncRes = reoTransferUnitsToNodes_rec( p, p->pTops[0] ); Cudd_Ref( bFuncRes ); // 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 // assert( reoRecursiveDeref( p->pTops[0] ) ); // assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); // perform verification if ( p->fVerify ) { DdNode * bFuncPerm; bFuncPerm = Cudd_bddPermute( dd, bFunc, pPermInv ); Cudd_Ref( bFuncPerm ); if ( bFuncPerm != bFuncRes ) { printf( "REO: Internal verification has failed!\n" ); fflush( stdout ); } Cudd_RecursiveDeref( dd, bFuncPerm ); } // recycle the data structure for ( i = 0; i <= p->nSupp; i++ ) reoUnitsRecycleUnitList( p, p->pPlanes + i ); finish : if ( bFuncRes ) Cudd_Deref( bFuncRes ); return bFuncRes; }
/**Function************************************************************* Synopsis [Reorders the DD using REO and CUDD.] Description [This function can be used to test the performance of the reordering package.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ShuffleTest( reo_man * pReo, DdManager * dd, DdNode * Func ) { // extern int runtime1, runtime2; DdNode * Temp, * bRemap; int nSuppSize, OffSet, Num, i; clock_t clk; int pOrder[1000], pOrderInv[1000]; assert( dd->size < 1000 ); srand( 0x12341234 ); nSuppSize = Cudd_SupportSize( dd, Func ); if ( nSuppSize < 2 ) return; for ( i = 0; i < nSuppSize; i++ ) pOrder[i] = i; for ( i = 0; i < 120; i++ ) { OffSet = rand() % (nSuppSize - 1); Num = pOrder[OffSet]; pOrder[OffSet] = pOrder[OffSet+1]; pOrder[OffSet+1] = Num; } for ( i = 0; i < nSuppSize; i++ ) pOrderInv[pOrder[i]] = i; /* printf( "Permutation: " ); for ( i = 0; i < nSuppSize; i++ ) printf( "%d ", pOrder[i] ); printf( "\n" ); printf( "Inverse permutation: " ); for ( i = 0; i < nSuppSize; i++ ) printf( "%d ", pOrderInv[i] ); printf( "\n" ); */ // create permutation // Extra_ReorderSetVerification( pReo, 1 ); bRemap = Extra_bddRemapUp( dd, Func ); Cudd_Ref( bRemap ); clk = clock(); Temp = reoShuffle( pReo, dd, bRemap, pOrder, pOrderInv ); Cudd_Ref( Temp ); //runtime1 += clock() - clk; //printf( "Initial = %d. Final = %d.\n", Cudd_DagSize(bRemap), Cudd_DagSize(Temp) ); { DdNode * bFuncPerm; clk = clock(); bFuncPerm = Cudd_bddPermute( dd, bRemap, pOrderInv ); Cudd_Ref( bFuncPerm ); //runtime2 += clock() - clk; if ( bFuncPerm != Temp ) { printf( "REO: Internal verification has failed!\n" ); fflush( stdout ); } Cudd_RecursiveDeref( dd, bFuncPerm ); } Cudd_RecursiveDeref( dd, Temp ); Cudd_RecursiveDeref( dd, bRemap ); }
ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /* LinearSpace(f) = Space(f,f) Space(f,g) { if ( f = const ) { if ( f = g ) return 1; else return 0; } if ( g = const ) return 0; return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx'); } Equations(s) = Pos(s) + Neg(s); Pos(s) { if ( s = 0 ) return 1; if ( s = 1 ) return 0; if ( sx'= 0 ) return Pos(sx) + x; if ( sx = 0 ) return Pos(sx'); return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)]; } Neg(s) { if ( s = 0 ) return 1; if ( s = 1 ) return 0; if ( sx'= 0 ) return Neg(sx); if ( sx = 0 ) return Neg(sx') + x; return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)]; } SpaceP(A) { if ( A = 0 ) return 1; if ( A = 1 ) return 1; return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax); } SpaceN(A) { if ( A = 0 ) return 1; if ( A = 1 ) return 0; return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax); } LinInd(A) { if ( A = const ) return 1; if ( !LinInd(Ax') ) return 0; if ( !LinInd(Ax) ) return 0; if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0; if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0; return 1; } LinSumOdd(A) { if ( A = 0 ) return 0; // Odd0 ---e-- Odd1 if ( A = 1 ) return 1; // \ o Odd0 = LinSumOdd(Ax'); // x is absent // \ Even0 = LinSumEven(Ax'); // x is absent // / o Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1 Even1 = LinSumEven(Ax); // x is absent return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)]; } LinSumEven(A) { if ( A = 0 ) return 0; if ( A = 1 ) return 0; Odd0 = LinSumOdd(Ax'); // x is absent Even0 = LinSumEven(Ax'); // x is absent Odd1 = LinSumOdd(Ax); // x is present Even1 = LinSumEven(Ax); // x is absent return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)]; } */ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ) { int * pSupport; int * pPermute; int * pPermuteBack; DdNode ** pCompose; DdNode * bCube, * bTemp; DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift; int nSupp, Counter; int i, lev; // get the support pSupport = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) ); Extra_SupportArray( dd, bFunc, pSupport ); nSupp = 0; for ( i = 0; i < dd->size; i++ ) if ( pSupport[i] ) nSupp++; // make sure the manager has enough variables if ( 2*nSupp > dd->size ) { printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" ); fflush( stdout ); ABC_FREE( pSupport ); return NULL; } // create the permutation arrays pPermute = ABC_ALLOC( int, dd->size ); pPermuteBack = ABC_ALLOC( int, dd->size ); pCompose = ABC_ALLOC( DdNode *, dd->size ); for ( i = 0; i < dd->size; i++ ) { pPermute[i] = i; pPermuteBack[i] = i; pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] ); } // remap the function in such a way that the variables are interleaved Counter = 0; bCube = b1; Cudd_Ref( bCube ); for ( lev = 0; lev < dd->size; lev++ ) if ( pSupport[ dd->invperm[lev] ] ) { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter; pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter]; // var from level 2*Counter+1 should go back to the place of this var pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev]; // the permutation should be defined in such a way that variable // on level 2*Counter is replaced by an EXOR of itself and var on the next level Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] ); pCompose[ dd->invperm[2*Counter] ] = Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] ); Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] ); // add this variable to the cube bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); // increment the counter Counter ++; } // permute the functions bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 ); // compose to gate the function depending on both vars bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 ); // gate the vector space // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] ) bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift ); bSpaceShift = Cudd_Not( bSpaceShift ); // permute the space back into the original mapping bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace ); Cudd_RecursiveDeref( dd, bFunc1 ); Cudd_RecursiveDeref( dd, bFunc2 ); Cudd_RecursiveDeref( dd, bSpaceShift ); Cudd_RecursiveDeref( dd, bCube ); for ( i = 0; i < dd->size; i++ ) Cudd_RecursiveDeref( dd, pCompose[i] ); ABC_FREE( pPermute ); ABC_FREE( pPermuteBack ); ABC_FREE( pCompose ); ABC_FREE( pSupport ); Cudd_Deref( bSpace ); return bSpace; }
/**Function************************************************************* Synopsis [Returns the local function of the DSD node. ] Description [The local function is computed using the global function of the node and the global functions of the formal inputs. The resulting local function is mapped using the topmost N variables of the manager. The number of variables N is equal to the number of formal inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) { int * pForm2Var; // the mapping of each formal input into its first var int * pVar2Form; // the mapping of each var into its formal inputs int i, iVar, iLev, * pPermute; DdNode ** pbCube0, ** pbCube1; DdNode * bFunc, * bRes, * bTemp; st_table * pCache; pPermute = ALLOC( int, dd->size ); pVar2Form = ALLOC( int, dd->size ); pForm2Var = ALLOC( int, dd->size ); pbCube0 = ALLOC( DdNode *, dd->size ); pbCube1 = ALLOC( DdNode *, dd->size ); // remap the global function in such a way that // the support variables of each formal input are adjacent iLev = 0; for ( i = 0; i < pNode->nDecs; i++ ) { pForm2Var[i] = dd->invperm[i]; for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) ) { iVar = dd->invperm[iLev]; pPermute[bTemp->index] = iVar; pVar2Form[iVar] = i; iLev++; } // collect the cubes representing each assignment pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( pbCube0[i] ); pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( pbCube1[i] ); } // remap the function bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc ); // remap the cube for ( i = 0; i < pNode->nDecs; i++ ) { pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] ); Cudd_RecursiveDeref( dd, bTemp ); pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] ); Cudd_RecursiveDeref( dd, bTemp ); } // remap the function pCache = st_init_table(st_ptrcmp,st_ptrhash); bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes ); st_free_table( pCache ); Cudd_RecursiveDeref( dd, bFunc ); for ( i = 0; i < pNode->nDecs; i++ ) { Cudd_RecursiveDeref( dd, pbCube0[i] ); Cudd_RecursiveDeref( dd, pbCube1[i] ); } /* //////////// // permute the function once again // in such a way that i-th var stood for i-th formal input for ( i = 0; i < dd->size; i++ ) pPermute[i] = -1; for ( i = 0; i < pNode->nDecs; i++ ) pPermute[dd->invperm[i]] = i; bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); //////////// */ FREE(pPermute); FREE(pVar2Form); FREE(pForm2Var); FREE(pbCube0); FREE(pbCube1); Cudd_Deref( bRes ); return bRes; }