Beispiel #1
0
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;
}
Beispiel #2
0
/**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] ]; 
		}
/**Function*************************************************************

  Synopsis    [Transfers the DD into the internal reordering data structure.]

  Description [It is important that the hash table is lossless.]

  SideEffects []

  SeeAlso     []

***********************************************************************/
reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F )
{
	DdManager * dd = p->dd;
	reo_unit * pUnit;
	int HKey, fComp;
	
	fComp = Cudd_IsComplement(F);
	F = Cudd_Regular(F);

	// check the hash-table
	if ( F->ref != 1 )
	{
		// search cache - use linear probing
		for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
			if ( p->HTable[HKey].Arg1 == (reo_unit *)F )
			{
				pUnit = p->HTable[HKey].Arg2;  
				assert( pUnit );
				// increment the edge counter
				pUnit->n++;
				return Unit_NotCond( pUnit, fComp );
			}
	}
	// the entry in not found in the cache
	
	// create a new entry
	pUnit         = reoUnitsGetNextUnit( p );
	pUnit->n      = 1;
	if ( cuddIsConstant(F) )
	{
		pUnit->lev    = REO_CONST_LEVEL;
		pUnit->pE     = (reo_unit*)((int)(cuddV(F)));
		pUnit->pT     = NULL;
		// check if the diagram that is being reordering has complement edges
		if ( F != dd->one )
			p->fThisIsAdd = 1;
		// insert the unit into the corresponding plane
		reoUnitsAddUnitToPlane( &(p->pPlanes[p->nSupp]), pUnit ); // increments the unit counter
	}
	else
	{
		pUnit->lev    = p->pMapToPlanes[F->index];
		pUnit->pE     = reoTransferNodesToUnits_rec( p, cuddE(F) );
		pUnit->pT     = reoTransferNodesToUnits_rec( p, cuddT(F) );
		// insert the unit into the corresponding plane
		reoUnitsAddUnitToPlane( &(p->pPlanes[pUnit->lev]), pUnit ); // increments the unit counter
	}

	// add to the hash table
	if ( F->ref != 1 )
	{
		// the next free entry is already found - it is pointed to by HKey
		// while we traversed the diagram, the hash entry to which HKey points,
		// might have been used. Make sure that its signature is different.
		for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
		p->HTable[HKey].Sign = p->Signature;
		p->HTable[HKey].Arg1 = (reo_unit *)F;
		p->HTable[HKey].Arg2 = pUnit;
	}

	// increment the counter of nodes
	p->nNodesCur++;
	return Unit_NotCond( pUnit, fComp );
}