| /**CFile**************************************************************** |
| |
| FileName [abcHaig.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Network and node package.] |
| |
| Synopsis [Implements history AIG for combinational rewriting.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: abcHaig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "base/abc/abc.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the nodes in the classes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * Abc_NtkHaigCollectMembers( Hop_Man_t * p ) |
| { |
| Vec_Ptr_t * vObjs; |
| Hop_Obj_t * pObj; |
| int i; |
| vObjs = Vec_PtrAlloc( 4098 ); |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| if ( pObj->pData == NULL ) |
| continue; |
| pObj->pData = Hop_ObjRepr( pObj ); |
| Vec_PtrPush( vObjs, pObj ); |
| } |
| return vObjs; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates classes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * Abc_NtkHaigCreateClasses( Vec_Ptr_t * vMembers ) |
| { |
| Vec_Ptr_t * vClasses; |
| Hop_Obj_t * pObj, * pRepr; |
| int i; |
| |
| // count classes |
| vClasses = Vec_PtrAlloc( 4098 ); |
| Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) |
| { |
| pRepr = (Hop_Obj_t *)pObj->pData; |
| assert( pRepr->pData == NULL ); |
| if ( pRepr->fMarkA == 0 ) // new |
| { |
| pRepr->fMarkA = 1; |
| Vec_PtrPush( vClasses, pRepr ); |
| } |
| } |
| |
| // set representatives as representatives |
| Vec_PtrForEachEntry( Hop_Obj_t *, vClasses, pObj, i ) |
| { |
| pObj->fMarkA = 0; |
| pObj->pData = pObj; |
| } |
| |
| // go through the members and update |
| Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) |
| { |
| pRepr = (Hop_Obj_t *)pObj->pData; |
| if ( ((Hop_Obj_t *)pRepr->pData)->Id > pObj->Id ) |
| pRepr->pData = pObj; |
| } |
| |
| // change representatives of the class |
| Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) |
| { |
| pRepr = (Hop_Obj_t *)pObj->pData; |
| pObj->pData = pRepr->pData; |
| assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); |
| } |
| |
| // update classes |
| Vec_PtrForEachEntry( Hop_Obj_t *, vClasses, pObj, i ) |
| { |
| pRepr = (Hop_Obj_t *)pObj->pData; |
| assert( pRepr->pData == pRepr ); |
| // pRepr->pData = NULL; |
| Vec_PtrWriteEntry( vClasses, i, pRepr ); |
| Vec_PtrPush( vMembers, pObj ); |
| } |
| |
| Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) |
| if ( pObj->pData == pObj ) |
| pObj->pData = NULL; |
| |
| /* |
| Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) |
| { |
| printf( "ObjId = %4d : ", pObj->Id ); |
| if ( pObj->pData == NULL ) |
| { |
| printf( "NULL" ); |
| } |
| else |
| { |
| printf( "%4d", ((Hop_Obj_t *)pObj->pData)->Id ); |
| assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); |
| } |
| printf( "\n" ); |
| } |
| */ |
| return vClasses; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Counts how many data members have non-trivial fanout.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkHaigCountFans( Hop_Man_t * p ) |
| { |
| Hop_Obj_t * pObj; |
| int i, Counter = 0; |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| if ( pObj->pData == NULL ) |
| continue; |
| if ( Hop_ObjRefs(pObj) > 0 ) |
| Counter++; |
| } |
| printf( "The number of class members with fanouts = %5d.\n", Counter ); |
| return Counter; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Hop_Obj_t * Hop_ObjReprHop( Hop_Obj_t * pObj ) |
| { |
| Hop_Obj_t * pRepr; |
| assert( pObj->pNext != NULL ); |
| if ( pObj->pData == NULL ) |
| return pObj->pNext; |
| pRepr = (Hop_Obj_t *)pObj->pData; |
| assert( pRepr->pData == pRepr ); |
| return Hop_NotCond( pRepr->pNext, pObj->fPhase ^ pRepr->fPhase ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Hop_Obj_t * Hop_ObjChild0Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin0(pObj)), Hop_ObjFaninC0(pObj) ); } |
| static inline Hop_Obj_t * Hop_ObjChild1Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin1(pObj)), Hop_ObjFaninC1(pObj) ); } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Stops history AIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Hop_Man_t * Abc_NtkHaigReconstruct( Hop_Man_t * p ) |
| { |
| Hop_Man_t * pNew; |
| Hop_Obj_t * pObj; |
| int i, Counter = 0; |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| pObj->pNext = NULL; |
| // start the HOP package |
| pNew = Hop_ManStart(); |
| pNew->vObjs = Vec_PtrAlloc( p->nCreated ); |
| Vec_PtrPush( pNew->vObjs, Hop_ManConst1(pNew) ); |
| // map the constant node |
| Hop_ManConst1(p)->pNext = Hop_ManConst1(pNew); |
| // map the CIs |
| Hop_ManForEachPi( p, pObj, i ) |
| pObj->pNext = Hop_ObjCreatePi(pNew); |
| // map the internal nodes |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| if ( !Hop_ObjIsNode(pObj) ) |
| continue; |
| pObj->pNext = Hop_And( pNew, Hop_ObjChild0Hop(pObj), Hop_ObjChild1Hop(pObj) ); |
| // assert( !Hop_IsComplement(pObj->pNext) ); |
| if ( Hop_ManConst1(pNew) == Hop_Regular(pObj->pNext) ) |
| Counter++; |
| if ( pObj->pData ) // member of the class |
| Hop_Regular(pObj->pNext)->pData = Hop_Regular(((Hop_Obj_t *)pObj->pData)->pNext); |
| } |
| // printf( " Counter = %d.\n", Counter ); |
| // transfer the POs |
| Hop_ManForEachPo( p, pObj, i ) |
| Hop_ObjCreatePo( pNew, Hop_ObjChild0Hop(pObj) ); |
| // check the new manager |
| if ( !Hop_ManCheck(pNew) ) |
| { |
| printf( "Abc_NtkHaigReconstruct: Check for History AIG has failed.\n" ); |
| Hop_ManStop(pNew); |
| return NULL; |
| } |
| return pNew; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if pOld is in the TFI of pNew.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkHaigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld ) |
| { |
| if ( pNode == NULL ) |
| return 0; |
| if ( pNode == pOld ) |
| return 1; |
| // check the trivial cases |
| if ( Abc_ObjIsCi(pNode) ) |
| return 0; |
| assert( Abc_ObjIsNode(pNode) ); |
| // if this node is already visited, skip |
| if ( Abc_NodeIsTravIdCurrent( pNode ) ) |
| return 0; |
| // mark the node as visited |
| Abc_NodeSetTravIdCurrent( pNode ); |
| // check the children |
| if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) ) |
| return 1; |
| if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) ) |
| return 1; |
| // check equivalent nodes |
| return Abc_NtkHaigCheckTfi_rec( (Abc_Obj_t *)pNode->pData, pOld ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if pOld is in the TFI of pNew.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkHaigCheckTfi( Abc_Ntk_t * pNtk, Abc_Obj_t * pOld, Abc_Obj_t * pNew ) |
| { |
| assert( !Abc_ObjIsComplement(pOld) ); |
| assert( !Abc_ObjIsComplement(pNew) ); |
| Abc_NtkIncrementTravId(pNtk); |
| return Abc_NtkHaigCheckTfi_rec( pNew, pOld ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Abc_Obj_t * Hop_ObjChild0Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin0(pObj)->pNext, Hop_ObjFaninC0(pObj) ); } |
| static inline Abc_Obj_t * Hop_ObjChild1Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin1(pObj)->pNext, Hop_ObjFaninC1(pObj) ); } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Stops history AIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p ) |
| { |
| Abc_Ntk_t * pNtkAig; |
| Abc_Obj_t * pObjOld, * pObjAbcThis, * pObjAbcRepr; |
| Hop_Obj_t * pObj; |
| int i; |
| assert( p->nCreated == Vec_PtrSize(p->vObjs) ); |
| |
| // start the new network |
| pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); |
| |
| // transfer new nodes to the PIs of HOP |
| Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig ); |
| Hop_ManForEachPi( p, pObj, i ) |
| pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i ); |
| |
| // construct new nodes |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| if ( !Hop_ObjIsNode(pObj) ) |
| continue; |
| pObj->pNext = (Hop_Obj_t *)Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); |
| assert( !Hop_IsComplement(pObj->pNext) ); |
| } |
| |
| // set the COs |
| Abc_NtkForEachCo( pNtk, pObjOld, i ) |
| Abc_ObjAddFanin( pObjOld->pCopy, Hop_ObjChild0Next(Hop_ManPo(p,i)) ); |
| |
| // construct choice nodes |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| // skip the node without choices |
| if ( pObj->pData == NULL ) |
| continue; |
| // skip the representative of the class |
| if ( pObj->pData == pObj ) |
| continue; |
| // do not create choices for constant 1 and PIs |
| if ( !Hop_ObjIsNode((Hop_Obj_t *)pObj->pData) ) |
| continue; |
| // get the corresponding new nodes |
| pObjAbcThis = (Abc_Obj_t *)pObj->pNext; |
| pObjAbcRepr = (Abc_Obj_t *)((Hop_Obj_t *)pObj->pData)->pNext; |
| // the new node cannot be already in the class |
| assert( pObjAbcThis->pData == NULL ); |
| // the new node cannot have fanouts |
| assert( Abc_ObjFanoutNum(pObjAbcThis) == 0 ); |
| // these should be different nodes |
| assert( pObjAbcRepr != pObjAbcThis ); |
| // do not create choices if there is a path from pObjAbcThis to pObjAbcRepr |
| if ( !Abc_NtkHaigCheckTfi( pNtkAig, pObjAbcRepr, pObjAbcThis ) ) |
| { |
| // find the last node in the class |
| while ( pObjAbcRepr->pData ) |
| pObjAbcRepr = (Abc_Obj_t *)pObjAbcRepr->pData; |
| // add the new node at the end of the list |
| pObjAbcRepr->pData = pObjAbcThis; |
| } |
| } |
| |
| // finish the new network |
| // Abc_NtkFinalize( pNtk, pNtkAig ); |
| // Abc_AigCleanup( pNtkAig->pManFunc ); |
| // check correctness of the network |
| if ( !Abc_NtkCheck( pNtkAig ) ) |
| { |
| printf( "Abc_NtkHaigUse: The network check has failed.\n" ); |
| Abc_NtkDelete( pNtkAig ); |
| return NULL; |
| } |
| return pNtkAig; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Resets representatives.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkHaigResetReprsOld( Hop_Man_t * pMan ) |
| { |
| Vec_Ptr_t * vMembers, * vClasses; |
| |
| // collect members of the classes and make them point to reprs |
| vMembers = Abc_NtkHaigCollectMembers( pMan ); |
| printf( "Collected %6d class members.\n", Vec_PtrSize(vMembers) ); |
| |
| // create classes |
| vClasses = Abc_NtkHaigCreateClasses( vMembers ); |
| printf( "Collected %6d classes. (Ave = %5.2f)\n", Vec_PtrSize(vClasses), |
| (float)(Vec_PtrSize(vMembers))/Vec_PtrSize(vClasses) ); |
| |
| Vec_PtrFree( vMembers ); |
| Vec_PtrFree( vClasses ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Resets representatives.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkHaigResetReprs( Hop_Man_t * p ) |
| { |
| Hop_Obj_t * pObj, * pRepr; |
| int i, nClasses, nMembers, nFanouts, nNormals; |
| // clear self-classes |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| // fix the strange situation of double-loop |
| pRepr = (Hop_Obj_t *)pObj->pData; |
| if ( pRepr && pRepr->pData == pObj ) |
| pRepr->pData = pRepr; |
| // remove self-loops |
| if ( pObj->pData == pObj ) |
| pObj->pData = NULL; |
| } |
| // set representatives |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| if ( pObj->pData == NULL ) |
| continue; |
| // get representative of the node |
| pRepr = Hop_ObjRepr( pObj ); |
| pRepr->pData = pRepr; |
| // set the representative |
| pObj->pData = pRepr; |
| } |
| // make each class point to the smallest topological order |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| if ( pObj->pData == NULL ) |
| continue; |
| pRepr = Hop_ObjRepr( pObj ); |
| if ( pRepr->Id > pObj->Id ) |
| { |
| pRepr->pData = pObj; |
| pObj->pData = pObj; |
| } |
| else |
| pObj->pData = pRepr; |
| } |
| // count classes, members, and fanouts - and verify |
| nMembers = nClasses = nFanouts = nNormals = 0; |
| Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) |
| { |
| if ( pObj->pData == NULL ) |
| continue; |
| // count members |
| nMembers++; |
| // count the classes and fanouts |
| if ( pObj->pData == pObj ) |
| nClasses++; |
| else if ( Hop_ObjRefs(pObj) > 0 ) |
| nFanouts++; |
| else |
| nNormals++; |
| // compare representatives |
| pRepr = Hop_ObjRepr( pObj ); |
| assert( pObj->pData == pRepr ); |
| assert( pRepr->Id <= pObj->Id ); |
| } |
| // printf( "Nodes = %7d. Member = %7d. Classes = %6d. Fanouts = %6d. Normals = %6d.\n", |
| // Hop_ManNodeNum(p), nMembers, nClasses, nFanouts, nNormals ); |
| return nFanouts; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Transform HOP manager into the one without loops.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) |
| { |
| Abc_Ntk_t * pNtkAig; |
| Hop_Man_t * pManTemp; |
| |
| // iteratively reconstruct the HOP manager to create choice nodes |
| while ( Abc_NtkHaigResetReprs( pMan ) ) |
| { |
| pMan = Abc_NtkHaigReconstruct( pManTemp = pMan ); |
| Hop_ManStop( pManTemp ); |
| } |
| |
| // traverse in the topological order and create new AIG |
| pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan ); |
| Hop_ManStop( pMan ); |
| return pNtkAig; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |