blob: 9e74d1be7094555c22a2c51a3ff92282d46972dc [file] [log] [blame]
/**CFile****************************************************************
FileName [aigSplit.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [AIG package.]
Synopsis [Splits the property output cone into a set of cofactor properties.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - April 28, 2007.]
Revision [$Id: aigSplit.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
***********************************************************************/
#include "aig.h"
#include "aig/saig/saig.h"
#ifdef ABC_USE_CUDD
#include "bdd/extrab/extraBdd.h"
#endif
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#ifdef ABC_USE_CUDD
/**Function*************************************************************
Synopsis [Converts the node to MUXes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Obj_t * Aig_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Aig_Man_t * pNew, st__table * tBdd2Node )
{
Aig_Obj_t * pNode, * pNode0, * pNode1, * pNodeC;
assert( !Cudd_IsComplement(bFunc) );
if ( st__lookup( tBdd2Node, (char *)bFunc, (char **)&pNode ) )
return pNode;
// solve for the children nodes
pNode0 = Aig_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNew, tBdd2Node );
pNode0 = Aig_NotCond( pNode0, Cudd_IsComplement(cuddE(bFunc)) );
pNode1 = Aig_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNew, tBdd2Node );
if ( ! st__lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeC ) )
assert( 0 );
// create the MUX node
pNode = Aig_Mux( pNew, pNodeC, pNode1, pNode0 );
st__insert( tBdd2Node, (char *)bFunc, (char *)pNode );
return pNode;
}
/**Function*************************************************************
Synopsis [Derives AIG for the BDDs of the cofactors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Aig_ManConvertBddsToAigs( Aig_Man_t * p, DdManager * dd, Vec_Ptr_t * vCofs )
{
DdNode * bFunc;
st__table * tBdd2Node;
Aig_Man_t * pNew;
Aig_Obj_t * pObj;
int i;
Aig_ManCleanData( p );
// generate AIG for BDD
pNew = Aig_ManStart( Aig_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
Aig_ManForEachCi( p, pObj, i )
pObj->pData = Aig_ObjCreateCi( pNew );
// create the table mapping BDD nodes into the ABC nodes
tBdd2Node = st__init_table( st__ptrcmp, st__ptrhash );
// add the constant and the elementary vars
st__insert( tBdd2Node, (char *)Cudd_ReadOne(dd), (char *)Aig_ManConst1(pNew) );
Aig_ManForEachCi( p, pObj, i )
st__insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pObj->pData );
// build primary outputs for the cofactors
Vec_PtrForEachEntry( DdNode *, vCofs, bFunc, i )
{
if ( bFunc == Cudd_ReadLogicZero(dd) )
continue;
pObj = Aig_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNew, tBdd2Node );
pObj = Aig_NotCond( pObj, Cudd_IsComplement(bFunc) );
Aig_ObjCreateCo( pNew, pObj );
}
st__free_table( tBdd2Node );
// duplicate the rest of the AIG
// add the POs
Aig_ManForEachCo( p, pObj, i )
{
if ( i == 0 )
continue;
Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) );
pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
}
Aig_ManCleanup( pNew );
Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
// check the resulting network
if ( !Aig_ManCheck(pNew) )
printf( "Aig_ManConvertBddsToAigs(): The check has failed.\n" );
return pNew;
}
/**Function*************************************************************
Synopsis [Returns the array of constraint candidates.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
DdNode * Aig_ManBuildPoBdd_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd )
{
DdNode * bBdd0, * bBdd1;
if ( pObj->pData != NULL )
return (DdNode *)pObj->pData;
assert( Aig_ObjIsNode(pObj) );
bBdd0 = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin0(pObj), dd );
bBdd1 = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin1(pObj), dd );
bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) );
bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) );
pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData );
return (DdNode *)pObj->pData;
}
/**Function*************************************************************
Synopsis [Derive BDDs for the cofactors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Aig_ManCofactorBdds( Aig_Man_t * p, Vec_Ptr_t * vSubset, DdManager * dd, DdNode * bFunc )
{
Vec_Ptr_t * vCofs;
DdNode * bCube, * bTemp, * bCof, ** pbVars;
int i;
vCofs = Vec_PtrAlloc( 100 );
pbVars = (DdNode **)Vec_PtrArray(vSubset);
for ( i = 0; i < (1 << Vec_PtrSize(vSubset)); i++ )
{
bCube = Extra_bddBitsToCube( dd, i, Vec_PtrSize(vSubset), pbVars, 1 ); Cudd_Ref( bCube );
bCof = Cudd_Cofactor( dd, bFunc, bCube ); Cudd_Ref( bCof );
bCof = Cudd_bddAnd( dd, bTemp = bCof, bCube ); Cudd_Ref( bCof );
Cudd_RecursiveDeref( dd, bTemp );
Cudd_RecursiveDeref( dd, bCube );
Vec_PtrPush( vCofs, bCof );
}
return vCofs;
}
/**Function*************************************************************
Synopsis [Construct BDDs for the primary output.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
DdManager * Aig_ManBuildPoBdd( Aig_Man_t * p, DdNode ** pbFunc )
{
DdManager * dd;
Aig_Obj_t * pObj;
int i;
assert( Saig_ManPoNum(p) == 1 );
Aig_ManCleanData( p );
dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
pObj = Aig_ManConst1(p);
pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData );
Aig_ManForEachCi( p, pObj, i )
{
pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData );
}
pObj = Aig_ManCo( p, 0 );
*pbFunc = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin0(pObj), dd ); Cudd_Ref( *pbFunc );
*pbFunc = Cudd_NotCond( *pbFunc, Aig_ObjFaninC0(pObj) );
Aig_ManForEachObj( p, pObj, i )
{
if ( pObj->pData )
Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
}
Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
return dd;
}
/**Function*************************************************************
Synopsis [Randomly selects a random subset of inputs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Aig_ManVecRandSubset( Vec_Ptr_t * vVec, int nVars )
{
Vec_Ptr_t * vRes;
void * pEntry;
unsigned Rand;
vRes = Vec_PtrDup(vVec);
while ( Vec_PtrSize(vRes) > nVars )
{
Rand = Aig_ManRandom( 0 );
pEntry = Vec_PtrEntry( vRes, Rand % Vec_PtrSize(vRes) );
Vec_PtrRemove( vRes, pEntry );
}
return vRes;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose )
{
Aig_Man_t * pRes;
Aig_Obj_t * pNode;
DdNode * bFunc;
DdManager * dd;
Vec_Ptr_t * vSupp, * vSubs, * vCofs;
int i;
abctime clk = Abc_Clock();
if ( Saig_ManPoNum(p) != 1 )
{
printf( "Currently works only for one primary output.\n" );
return NULL;
}
if ( nVars < 1 )
{
printf( "The number of cofactoring variables should be a positive number.\n" );
return NULL;
}
if ( nVars > 16 )
{
printf( "The number of cofactoring variables should be less than 17.\n" );
return NULL;
}
vSupp = Aig_Support( p, Aig_ObjFanin0(Aig_ManCo(p,0)) );
if ( Vec_PtrSize(vSupp) == 0 )
{
printf( "Property output function is a constant.\n" );
Vec_PtrFree( vSupp );
return NULL;
}
dd = Aig_ManBuildPoBdd( p, &bFunc ); // bFunc is referenced
if ( fVerbose )
printf( "Support =%5d. BDD size =%6d. ", Vec_PtrSize(vSupp), Cudd_DagSize(bFunc) );
vSubs = Aig_ManVecRandSubset( vSupp, nVars );
// replace nodes by their BDD variables
Vec_PtrForEachEntry( Aig_Obj_t *, vSubs, pNode, i )
Vec_PtrWriteEntry( vSubs, i, pNode->pData );
// derive cofactors and functions
vCofs = Aig_ManCofactorBdds( p, vSubs, dd, bFunc );
pRes = Aig_ManConvertBddsToAigs( p, dd, vCofs );
Vec_PtrFree( vSupp );
Vec_PtrFree( vSubs );
if ( fVerbose )
printf( "Created %d cofactors (out of %d). ", Saig_ManPoNum(pRes), Vec_PtrSize(vCofs) );
if ( fVerbose )
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
// dereference
Cudd_RecursiveDeref( dd, bFunc );
Vec_PtrForEachEntry( DdNode *, vCofs, bFunc, i )
Cudd_RecursiveDeref( dd, bFunc );
Vec_PtrFree( vCofs );
Extra_StopManager( dd );
return pRes;
}
#else
Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose )
{
return NULL;
}
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END