| /**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 |
| |