blob: 0706382f8f47f48909890ec0a8b1126840af9dd3 [file] [log] [blame]
/**CFile****************************************************************
FileName [hopDfs.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Minimalistic And-Inverter Graph package.]
Synopsis [DFS traversal procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - May 11, 2006.]
Revision [$Id: hopDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "hop.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Collects internal nodes in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_ManDfs_rec( Hop_Obj_t * pObj, Vec_Ptr_t * vNodes )
{
assert( !Hop_IsComplement(pObj) );
if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
return;
Hop_ManDfs_rec( Hop_ObjFanin0(pObj), vNodes );
Hop_ManDfs_rec( Hop_ObjFanin1(pObj), vNodes );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA(pObj);
Vec_PtrPush( vNodes, pObj );
}
/**Function*************************************************************
Synopsis [Collects internal nodes in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p )
{
Vec_Ptr_t * vNodes;
Hop_Obj_t * pObj;
int i;
vNodes = Vec_PtrAlloc( Hop_ManNodeNum(p) );
Hop_ManForEachNode( p, pObj, i )
Hop_ManDfs_rec( pObj, vNodes );
Hop_ManForEachNode( p, pObj, i )
Hop_ObjClearMarkA(pObj);
return vNodes;
}
/**Function*************************************************************
Synopsis [Collects internal nodes in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode )
{
Vec_Ptr_t * vNodes;
Hop_Obj_t * pObj;
int i;
assert( !Hop_IsComplement(pNode) );
vNodes = Vec_PtrAlloc( 16 );
Hop_ManDfs_rec( pNode, vNodes );
Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
Hop_ObjClearMarkA(pObj);
return vNodes;
}
/**Function*************************************************************
Synopsis [Computes the max number of levels in the manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Hop_ManCountLevels( Hop_Man_t * p )
{
Vec_Ptr_t * vNodes;
Hop_Obj_t * pObj;
int i, LevelsMax, Level0, Level1;
// initialize the levels
Hop_ManConst1(p)->pData = NULL;
Hop_ManForEachPi( p, pObj, i )
pObj->pData = NULL;
// compute levels in a DFS order
vNodes = Hop_ManDfs( p );
Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
{
Level0 = (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData;
Level1 = (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData;
pObj->pData = (void *)(ABC_PTRUINT_T)(1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Level0, Level1));
}
Vec_PtrFree( vNodes );
// get levels of the POs
LevelsMax = 0;
Hop_ManForEachPo( p, pObj, i )
LevelsMax = Abc_MaxInt( LevelsMax, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData );
return LevelsMax;
}
/**Function*************************************************************
Synopsis [Creates correct reference counters at each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_ManCreateRefs( Hop_Man_t * p )
{
Hop_Obj_t * pObj;
int i;
if ( p->fRefCount )
return;
p->fRefCount = 1;
// clear refs
Hop_ObjClearRef( Hop_ManConst1(p) );
Hop_ManForEachPi( p, pObj, i )
Hop_ObjClearRef( pObj );
Hop_ManForEachNode( p, pObj, i )
Hop_ObjClearRef( pObj );
Hop_ManForEachPo( p, pObj, i )
Hop_ObjClearRef( pObj );
// set refs
Hop_ManForEachNode( p, pObj, i )
{
Hop_ObjRef( Hop_ObjFanin0(pObj) );
Hop_ObjRef( Hop_ObjFanin1(pObj) );
}
Hop_ManForEachPo( p, pObj, i )
Hop_ObjRef( Hop_ObjFanin0(pObj) );
}
/**Function*************************************************************
Synopsis [Counts the number of AIG nodes rooted at this cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_ConeMark_rec( Hop_Obj_t * pObj )
{
assert( !Hop_IsComplement(pObj) );
if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
return;
Hop_ConeMark_rec( Hop_ObjFanin0(pObj) );
Hop_ConeMark_rec( Hop_ObjFanin1(pObj) );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
}
/**Function*************************************************************
Synopsis [Counts the number of AIG nodes rooted at this cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_ConeCleanAndMark_rec( Hop_Obj_t * pObj )
{
assert( !Hop_IsComplement(pObj) );
if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
return;
Hop_ConeCleanAndMark_rec( Hop_ObjFanin0(pObj) );
Hop_ConeCleanAndMark_rec( Hop_ObjFanin1(pObj) );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
pObj->pData = NULL;
}
/**Function*************************************************************
Synopsis [Counts the number of AIG nodes rooted at this cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Hop_ConeCountAndMark_rec( Hop_Obj_t * pObj )
{
int Counter;
assert( !Hop_IsComplement(pObj) );
if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
return 0;
Counter = 1 + Hop_ConeCountAndMark_rec( Hop_ObjFanin0(pObj) ) +
Hop_ConeCountAndMark_rec( Hop_ObjFanin1(pObj) );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
return Counter;
}
/**Function*************************************************************
Synopsis [Counts the number of AIG nodes rooted at this cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_ConeUnmark_rec( Hop_Obj_t * pObj )
{
assert( !Hop_IsComplement(pObj) );
if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) )
return;
Hop_ConeUnmark_rec( Hop_ObjFanin0(pObj) );
Hop_ConeUnmark_rec( Hop_ObjFanin1(pObj) );
assert( Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjClearMarkA( pObj );
}
/**Function*************************************************************
Synopsis [Counts the number of AIG nodes rooted at this cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Hop_DagSize( Hop_Obj_t * pObj )
{
int Counter;
Counter = Hop_ConeCountAndMark_rec( Hop_Regular(pObj) );
Hop_ConeUnmark_rec( Hop_Regular(pObj) );
return Counter;
}
/**Function*************************************************************
Synopsis [Counts how many fanout the given node has.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Hop_ObjFanoutCount_rec( Hop_Obj_t * pObj, Hop_Obj_t * pPivot )
{
int Counter;
assert( !Hop_IsComplement(pObj) );
if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
return (int)(pObj == pPivot);
Counter = Hop_ObjFanoutCount_rec( Hop_ObjFanin0(pObj), pPivot ) +
Hop_ObjFanoutCount_rec( Hop_ObjFanin1(pObj), pPivot );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
return Counter;
}
int Hop_ObjFanoutCount( Hop_Obj_t * pObj, Hop_Obj_t * pPivot )
{
int Counter;
assert( !Hop_IsComplement(pPivot) );
Counter = Hop_ObjFanoutCount_rec( Hop_Regular(pObj), pPivot );
Hop_ConeUnmark_rec( Hop_Regular(pObj) );
return Counter;
}
/**Function*************************************************************
Synopsis [Transfers the AIG from one manager into another.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_Transfer_rec( Hop_Man_t * pDest, Hop_Obj_t * pObj )
{
assert( !Hop_IsComplement(pObj) );
if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
return;
Hop_Transfer_rec( pDest, Hop_ObjFanin0(pObj) );
Hop_Transfer_rec( pDest, Hop_ObjFanin1(pObj) );
pObj->pData = Hop_And( pDest, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
}
/**Function*************************************************************
Synopsis [Transfers the AIG from one manager into another.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pRoot, int nVars )
{
Hop_Obj_t * pObj;
int i;
// solve simple cases
if ( pSour == pDest )
return pRoot;
if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
return Hop_NotCond( Hop_ManConst1(pDest), Hop_IsComplement(pRoot) );
// set the PI mapping
Hop_ManForEachPi( pSour, pObj, i )
{
if ( i == nVars )
break;
pObj->pData = Hop_IthVar(pDest, i);
}
// transfer and set markings
Hop_Transfer_rec( pDest, Hop_Regular(pRoot) );
// clear the markings
Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
}
/**Function*************************************************************
Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_Compose_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFunc, Hop_Obj_t * pVar )
{
assert( !Hop_IsComplement(pObj) );
if ( Hop_ObjIsMarkA(pObj) )
return;
if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) )
{
pObj->pData = pObj == pVar ? pFunc : pObj;
return;
}
Hop_Compose_rec( p, Hop_ObjFanin0(pObj), pFunc, pVar );
Hop_Compose_rec( p, Hop_ObjFanin1(pObj), pFunc, pVar );
pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
}
/**Function*************************************************************
Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar )
{
// quit if the PI variable is not defined
if ( iVar >= Hop_ManPiNum(p) )
{
printf( "Hop_Compose(): The PI variable %d is not defined.\n", iVar );
return NULL;
}
// recursively perform composition
Hop_Compose_rec( p, Hop_Regular(pRoot), pFunc, Hop_ManPi(p, iVar) );
// clear the markings
Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
}
/**Function*************************************************************
Synopsis [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_Complement_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pVar )
{
assert( !Hop_IsComplement(pObj) );
if ( Hop_ObjIsMarkA(pObj) )
return;
if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) )
{
pObj->pData = pObj == pVar ? Hop_Not(pObj) : pObj;
return;
}
Hop_Complement_rec( p, Hop_ObjFanin0(pObj), pVar );
Hop_Complement_rec( p, Hop_ObjFanin1(pObj), pVar );
pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
}
/**Function*************************************************************
Synopsis [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Hop_Obj_t * Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar )
{
// quit if the PI variable is not defined
if ( iVar >= Hop_ManPiNum(p) )
{
printf( "Hop_Complement(): The PI variable %d is not defined.\n", iVar );
return NULL;
}
// recursively perform composition
Hop_Complement_rec( p, Hop_Regular(pRoot), Hop_ManPi(p, iVar) );
// clear the markings
Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
}
/**Function*************************************************************
Synopsis [Remaps the AIG (pRoot) to have the given support (uSupp).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_Remap_rec( Hop_Man_t * p, Hop_Obj_t * pObj )
{
assert( !Hop_IsComplement(pObj) );
if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
return;
Hop_Remap_rec( p, Hop_ObjFanin0(pObj) );
Hop_Remap_rec( p, Hop_ObjFanin1(pObj) );
pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
}
/**Function*************************************************************
Synopsis [Remaps the AIG (pRoot) to have the given support (uSupp).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Hop_Obj_t * Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars )
{
Hop_Obj_t * pObj;
int i, k;
// quit if the PI variable is not defined
if ( nVars > Hop_ManPiNum(p) )
{
printf( "Hop_Remap(): The number of variables (%d) is more than the manager size (%d).\n", nVars, Hop_ManPiNum(p) );
return NULL;
}
// return if constant
if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
return pRoot;
if ( uSupp == 0 )
return Hop_NotCond( Hop_ManConst0(p), Hop_ObjPhaseCompl(pRoot) );
// set the PI mapping
k = 0;
Hop_ManForEachPi( p, pObj, i )
{
if ( i == nVars )
break;
if ( uSupp & (1 << i) )
pObj->pData = Hop_IthVar(p, k++);
else
pObj->pData = Hop_ManConst0(p);
}
assert( k > 0 && k < nVars );
// recursively perform composition
Hop_Remap_rec( p, Hop_Regular(pRoot) );
// clear the markings
Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
}
/**Function*************************************************************
Synopsis [Permute the AIG according to the given permutation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Hop_Obj_t * Hop_Permute( Hop_Man_t * p, Hop_Obj_t * pRoot, int nRootVars, int * pPermute )
{
Hop_Obj_t * pObj;
int i;
// return if constant
if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) )
return pRoot;
// create mapping
Hop_ManForEachPi( p, pObj, i )
{
if ( i == nRootVars )
break;
assert( pPermute[i] >= 0 && pPermute[i] < Hop_ManPiNum(p) );
pObj->pData = Hop_IthVar( p, pPermute[i] );
}
// recursively perform composition
Hop_Remap_rec( p, Hop_Regular(pRoot) );
// clear the markings
Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END