blob: c36fbef45e92f9f2a5b7a40646e1c5a94c9c98ed [file] [log] [blame]
/**CFile****************************************************************
FileName [dsdCheck.c]
PackageName [DSD: Disjoint-support decomposition package.]
Synopsis [Procedures to check the identity of root functions.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 8.0. Started - September 22, 2003.]
Revision [$Id: dsdCheck.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $]
***********************************************************************/
#include "dsdInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Dsd_Cache_t_ Dds_Cache_t;
typedef struct Dsd_Entry_t_ Dsd_Entry_t;
struct Dsd_Cache_t_
{
Dsd_Entry_t * pTable;
int nTableSize;
int nSuccess;
int nFailure;
};
struct Dsd_Entry_t_
{
DdNode * bX[5];
};
static Dds_Cache_t * pCache;
static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function********************************************************************
Synopsis [(Re)allocates the local cache.]
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Dsd_CheckCacheAllocate( int nEntries )
{
int nRequested;
pCache = ABC_ALLOC( Dds_Cache_t, 1 );
memset( pCache, 0, sizeof(Dds_Cache_t) );
// check what is the size of the current cache
nRequested = Abc_PrimeCudd( nEntries );
if ( pCache->nTableSize != nRequested )
{ // the current size is different
// deallocate the old, allocate the new
if ( pCache->nTableSize )
Dsd_CheckCacheDeallocate();
// allocate memory for the hash table
pCache->nTableSize = nRequested;
pCache->pTable = ABC_ALLOC( Dsd_Entry_t, nRequested );
}
// otherwise, there is no need to allocate, just clean
Dsd_CheckCacheClear();
// printf( "\nThe number of allocated cache entries = %d.\n\n", pCache->nTableSize );
}
/**Function********************************************************************
Synopsis [Deallocates the local cache.]
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Dsd_CheckCacheDeallocate()
{
ABC_FREE( pCache->pTable );
ABC_FREE( pCache );
}
/**Function********************************************************************
Synopsis [Clears the local cache.]
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Dsd_CheckCacheClear()
{
int i;
for ( i = 0; i < pCache->nTableSize; i++ )
pCache->pTable[0].bX[0] = NULL;
}
/**Function********************************************************************
Synopsis [Checks whether it is true that bF1(bC1=0) == bF2(bC2=0).]
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 )
{
int RetValue;
// pCache->nSuccess = 0;
// pCache->nFailure = 0;
RetValue = Dsd_CheckRootFunctionIdentity_rec(dd, bF1, bF2, bC1, bC2);
// printf( "Cache success = %d. Cache failure = %d.\n", pCache->nSuccess, pCache->nFailure );
return RetValue;
}
/**Function********************************************************************
Synopsis [Performs the recursive step of Dsd_CheckRootFunctionIdentity().]
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 )
{
unsigned HKey;
// if either bC1 or bC2 is zero, the test is true
// if ( bC1 == b0 || bC2 == b0 ) return 1;
assert( bC1 != b0 );
assert( bC2 != b0 );
// if both bC1 and bC2 are one - perform comparison
if ( bC1 == b1 && bC2 == b1 ) return (int)( bF1 == bF2 );
if ( bF1 == b0 )
return Cudd_bddLeq( dd, bC2, Cudd_Not(bF2) );
if ( bF1 == b1 )
return Cudd_bddLeq( dd, bC2, bF2 );
if ( bF2 == b0 )
return Cudd_bddLeq( dd, bC1, Cudd_Not(bF1) );
if ( bF2 == b1 )
return Cudd_bddLeq( dd, bC1, bF1 );
// otherwise, keep expanding
// check cache
// HKey = _Hash( ((unsigned)bF1), ((unsigned)bF2), ((unsigned)bC1), ((unsigned)bC2) );
HKey = hashKey4( bF1, bF2, bC1, bC2, pCache->nTableSize );
if ( pCache->pTable[HKey].bX[0] == bF1 &&
pCache->pTable[HKey].bX[1] == bF2 &&
pCache->pTable[HKey].bX[2] == bC1 &&
pCache->pTable[HKey].bX[3] == bC2 )
{
pCache->nSuccess++;
return (int)(ABC_PTRUINT_T)pCache->pTable[HKey].bX[4]; // the last bit records the result (yes/no)
}
else
{
// determine the top variables
int RetValue;
DdNode * bA[4] = { bF1, bF2, bC1, bC2 }; // arguments
DdNode * bAR[4] = { Cudd_Regular(bF1), Cudd_Regular(bF2), Cudd_Regular(bC1), Cudd_Regular(bC2) }; // regular arguments
int CurLevel[4] = { cuddI(dd,bAR[0]->index), cuddI(dd,bAR[1]->index), cuddI(dd,bAR[2]->index), cuddI(dd,bAR[3]->index) };
int TopLevel = CUDD_CONST_INDEX;
int i;
DdNode * bE[4], * bT[4];
DdNode * bF1next, * bF2next, * bC1next, * bC2next;
pCache->nFailure++;
// determine the top level
for ( i = 0; i < 4; i++ )
if ( TopLevel > CurLevel[i] )
TopLevel = CurLevel[i];
// compute the cofactors
for ( i = 0; i < 4; i++ )
if ( TopLevel == CurLevel[i] )
{
if ( bA[i] != bAR[i] ) // complemented
{
bE[i] = Cudd_Not(cuddE(bAR[i]));
bT[i] = Cudd_Not(cuddT(bAR[i]));
}
else
{
bE[i] = cuddE(bAR[i]);
bT[i] = cuddT(bAR[i]);
}
}
else
bE[i] = bT[i] = bA[i];
// solve subproblems
// three cases are possible
// (1) the top var belongs to both C1 and C2
// in this case, any cofactor of F1 and F2 will do,
// as long as the corresponding cofactor of C1 and C2 is not equal to 0
if ( TopLevel == CurLevel[2] && TopLevel == CurLevel[3] )
{
if ( bE[2] != b0 ) // C1
{
bF1next = bE[0];
bC1next = bE[2];
}
else
{
bF1next = bT[0];
bC1next = bT[2];
}
if ( bE[3] != b0 ) // C2
{
bF2next = bE[1];
bC2next = bE[3];
}
else
{
bF2next = bT[1];
bC2next = bT[3];
}
RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bF2next, bC1next, bC2next );
}
// (2) the top var belongs to either C1 or C2
// in this case normal splitting of cofactors
else if ( TopLevel == CurLevel[2] && TopLevel != CurLevel[3] )
{
if ( bE[2] != b0 ) // C1
{
bF1next = bE[0];
bC1next = bE[2];
}
else
{
bF1next = bT[0];
bC1next = bT[2];
}
// split around this variable
RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bE[1], bC1next, bE[3] );
if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test
RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bT[1], bC1next, bT[3] );
}
else if ( TopLevel != CurLevel[2] && TopLevel == CurLevel[3] )
{
if ( bE[3] != b0 ) // C2
{
bF2next = bE[1];
bC2next = bE[3];
}
else
{
bF2next = bT[1];
bC2next = bT[3];
}
// split around this variable
RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bF2next, bE[2], bC2next );
if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test
RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bF2next, bT[2], bC2next );
}
// (3) the top var does not belong to C1 and C2
// in this case normal splitting of cofactors
else // if ( TopLevel != CurLevel[2] && TopLevel != CurLevel[3] )
{
// split around this variable
RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bE[1], bE[2], bE[3] );
if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test
RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bT[1], bT[2], bT[3] );
}
// set cache
for ( i = 0; i < 4; i++ )
pCache->pTable[HKey].bX[i] = bA[i];
pCache->pTable[HKey].bX[4] = (DdNode*)(ABC_PTRUINT_T)RetValue;
return RetValue;
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END