| /**CFile**************************************************************** |
| |
| FileName [darBalance.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [DAG-aware AIG rewriting.] |
| |
| Synopsis [Algebraic AIG balancing.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - April 28, 2007.] |
| |
| Revision [$Id: darBalance.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "darInt.h" |
| #include "misc/tim/tim.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //#define USE_LUTSIZE_BALANCE |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Uniqifies the node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dar_ObjCompareLits( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) |
| { |
| int Diff = Aig_ObjToLit(*pp1) - Aig_ObjToLit(*pp2); |
| if ( Diff < 0 ) |
| return -1; |
| if ( Diff > 0 ) |
| return 1; |
| return 0; |
| } |
| void Dar_BalanceUniqify( Aig_Obj_t * pObj, Vec_Ptr_t * vNodes, int fExor ) |
| { |
| Aig_Obj_t * pTemp, * pTempNext; |
| int i, k; |
| // sort the nodes by their literal |
| Vec_PtrSort( vNodes, (int (*)())Dar_ObjCompareLits ); |
| // remove duplicates |
| k = 0; |
| Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, i ) |
| { |
| if ( i + 1 == Vec_PtrSize(vNodes) ) |
| { |
| Vec_PtrWriteEntry( vNodes, k++, pTemp ); |
| break; |
| } |
| pTempNext = (Aig_Obj_t *)Vec_PtrEntry( vNodes, i+1 ); |
| if ( !fExor && pTemp == Aig_Not(pTempNext) ) // pos_lit & neg_lit = 0 |
| { |
| Vec_PtrClear( vNodes ); |
| return; |
| } |
| if ( pTemp != pTempNext ) // save if different |
| Vec_PtrWriteEntry( vNodes, k++, pTemp ); |
| else if ( fExor ) // in case of XOR, remove identical |
| i++; |
| } |
| Vec_PtrShrink( vNodes, k ); |
| if ( Vec_PtrSize(vNodes) < 2 ) |
| return; |
| // check that there is no duplicates |
| pTemp = (Aig_Obj_t *)Vec_PtrEntry( vNodes, 0 ); |
| Vec_PtrForEachEntryStart( Aig_Obj_t *, vNodes, pTempNext, i, 1 ) |
| { |
| assert( pTemp != pTempNext ); |
| pTemp = pTempNext; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the nodes of the supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) |
| { |
| if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) ) |
| Vec_PtrPush( vSuper, pObj ); |
| else |
| { |
| assert( !Aig_IsComplement(pObj) ); |
| assert( Aig_ObjIsNode(pObj) ); |
| // go through the branches |
| Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); |
| Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); |
| } |
| } |
| Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) |
| { |
| Vec_Ptr_t * vNodes; |
| assert( !Aig_IsComplement(pObj) ); |
| assert( Aig_ObjIsNode(pObj) ); |
| // extend the storage |
| if ( Vec_VecSize( vStore ) <= Level ) |
| Vec_VecPush( vStore, Level, 0 ); |
| // get the temporary array of nodes |
| vNodes = Vec_VecEntry( vStore, Level ); |
| Vec_PtrClear( vNodes ); |
| // collect the nodes in the implication supergate |
| Dar_BalanceCone_rec( pObj, pObj, vNodes ); |
| // remove duplicates |
| Dar_BalanceUniqify( pObj, vNodes, Aig_ObjIsExor(pObj) ); |
| return vNodes; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the nodes of the supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| /* |
| int Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) |
| { |
| int RetValue1, RetValue2, i; |
| // check if the node is visited |
| if ( Aig_Regular(pObj)->fMarkB ) |
| { |
| if ( Aig_ObjIsExor(pRoot) ) |
| { |
| assert( !Aig_IsComplement(pObj) ); |
| // check if the node occurs in the same polarity |
| Vec_PtrRemove( vSuper, pObj ); |
| Aig_Regular(pObj)->fMarkB = 0; |
| //printf( " Duplicated EXOR input!!! " ); |
| return 1; |
| } |
| else |
| { |
| // check if the node occurs in the same polarity |
| for ( i = 0; i < vSuper->nSize; i++ ) |
| if ( vSuper->pArray[i] == pObj ) |
| return 1; |
| // check if the node is present in the opposite polarity |
| for ( i = 0; i < vSuper->nSize; i++ ) |
| if ( vSuper->pArray[i] == Aig_Not(pObj) ) |
| return -1; |
| } |
| assert( 0 ); |
| return 0; |
| } |
| // if the new node is complemented or a PI, another gate begins |
| if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) ) |
| { |
| Vec_PtrPush( vSuper, pObj ); |
| Aig_Regular(pObj)->fMarkB = 1; |
| return 0; |
| } |
| assert( !Aig_IsComplement(pObj) ); |
| assert( Aig_ObjIsNode(pObj) ); |
| // go through the branches |
| RetValue1 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); |
| RetValue2 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); |
| if ( RetValue1 == -1 || RetValue2 == -1 ) |
| return -1; |
| // return 1 if at least one branch has a duplicate |
| return RetValue1 || RetValue2; |
| } |
| Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) |
| { |
| Vec_Ptr_t * vNodes; |
| int RetValue, i; |
| assert( !Aig_IsComplement(pObj) ); |
| // extend the storage |
| if ( Vec_VecSize( vStore ) <= Level ) |
| Vec_VecPush( vStore, Level, 0 ); |
| // get the temporary array of nodes |
| vNodes = Vec_VecEntry( vStore, Level ); |
| Vec_PtrClear( vNodes ); |
| // collect the nodes in the implication supergate |
| RetValue = Dar_BalanceCone_rec( pObj, pObj, vNodes ); |
| assert( RetValue != 0 || vNodes->nSize > 1 ); |
| // unmark the visited nodes |
| Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) |
| Aig_Regular(pObj)->fMarkB = 0; |
| // if we found the node and its complement in the same implication supergate, |
| // return empty set of nodes (meaning that we should use constant-0 node) |
| if ( RetValue == -1 ) |
| vNodes->nSize = 0; |
| return vNodes; |
| } |
| */ |
| |
| /**Function************************************************************* |
| |
| Synopsis [Finds the left bound on the next candidate to be paired.] |
| |
| Description [The nodes in the array are in the decreasing order of levels. |
| The last node in the array has the smallest level. By default it would be paired |
| with the next node on the left. However, it may be possible to pair it with some |
| other node on the left, in such a way that the new node is shared. This procedure |
| finds the index of the left-most node, which can be paired with the last node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper ) |
| { |
| Aig_Obj_t * pObjRight, * pObjLeft; |
| int Current; |
| // if two or less nodes, pair with the first |
| if ( Vec_PtrSize(vSuper) < 3 ) |
| return 0; |
| // set the pointer to the one before the last |
| Current = Vec_PtrSize(vSuper) - 2; |
| pObjRight = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current ); |
| // go through the nodes to the left of this one |
| for ( Current--; Current >= 0; Current-- ) |
| { |
| // get the next node on the left |
| pObjLeft = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current ); |
| // if the level of this node is different, quit the loop |
| if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) ) |
| break; |
| } |
| Current++; |
| // get the node, for which the equality holds |
| pObjLeft = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current ); |
| assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_Regular(pObjRight)) ); |
| return Current; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Moves closer to the end the node that is best for sharing.] |
| |
| Description [If there is no node with sharing, randomly chooses one of |
| the legal nodes.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) |
| { |
| Aig_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; |
| int RightBound, i; |
| // get the right bound |
| RightBound = Vec_PtrSize(vSuper) - 2; |
| assert( LeftBound <= RightBound ); |
| if ( LeftBound == RightBound ) |
| return; |
| // get the two last nodes |
| pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); |
| pObj2 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); |
| if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 || Aig_Regular(pObj1) == Aig_Regular(pObj2) ) |
| return; |
| // find the first node that can be shared |
| for ( i = RightBound; i >= LeftBound; i-- ) |
| { |
| pObj3 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, i ); |
| if ( Aig_Regular(pObj3) == p->pConst1 ) |
| { |
| Vec_PtrWriteEntry( vSuper, i, pObj2 ); |
| Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); |
| return; |
| } |
| if ( Aig_Regular(pObj1) == Aig_Regular(pObj3) ) |
| { |
| if ( pObj3 == pObj2 ) |
| return; |
| Vec_PtrWriteEntry( vSuper, i, pObj2 ); |
| Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); |
| return; |
| } |
| pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_OBJ_EXOR : AIG_OBJ_AND ); |
| if ( Aig_TableLookup( p, pGhost ) ) |
| { |
| if ( pObj3 == pObj2 ) |
| return; |
| Vec_PtrWriteEntry( vSuper, i, pObj2 ); |
| Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); |
| return; |
| } |
| } |
| /* |
| // we did not find the node to share, randomize choice |
| { |
| int Choice = Aig_ManRandom(0) % (RightBound - LeftBound + 1); |
| pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); |
| if ( pObj3 == pObj2 ) |
| return; |
| Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); |
| Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); |
| } |
| */ |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) |
| { |
| int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2)); |
| if ( Diff > 0 ) |
| return -1; |
| if ( Diff < 0 ) |
| return 1; |
| Diff = Aig_ObjId(Aig_Regular(*pp1)) - Aig_ObjId(Aig_Regular(*pp2)); |
| if ( Diff > 0 ) |
| return -1; |
| if ( Diff < 0 ) |
| return 1; |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Inserts a new node in the order by levels.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj, int fExor ) |
| { |
| Aig_Obj_t * pObj1, * pObj2; |
| int i; |
| if ( Vec_PtrPushUnique(vStore, pObj) ) |
| { |
| if ( fExor ) |
| Vec_PtrRemove(vStore, pObj); |
| return; |
| } |
| // find the p of the node |
| for ( i = vStore->nSize-1; i > 0; i-- ) |
| { |
| pObj1 = (Aig_Obj_t *)vStore->pArray[i ]; |
| pObj2 = (Aig_Obj_t *)vStore->pArray[i-1]; |
| if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) ) |
| break; |
| vStore->pArray[i ] = pObj2; |
| vStore->pArray[i-1] = pObj1; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Builds implication supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ) |
| { |
| Aig_Obj_t * pObj1, * pObj2; |
| int LeftBound; |
| assert( vSuper->nSize > 1 ); |
| // sort the new nodes by level in the decreasing order |
| Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); |
| // balance the nodes |
| while ( vSuper->nSize > 1 ) |
| { |
| // find the left bound on the node to be paired |
| LeftBound = (!fUpdateLevel)? 0 : Dar_BalanceFindLeft( vSuper ); |
| // find the node that can be shared (if no such node, randomize choice) |
| Dar_BalancePermute( p, vSuper, LeftBound, Type == AIG_OBJ_EXOR ); |
| // pull out the last two nodes |
| pObj1 = (Aig_Obj_t *)Vec_PtrPop(vSuper); |
| pObj2 = (Aig_Obj_t *)Vec_PtrPop(vSuper); |
| Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type), Type == AIG_OBJ_EXOR ); |
| } |
| return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns affective support size.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Aig_BaseSize( Aig_Man_t * p, Aig_Obj_t * pObj, int nLutSize ) |
| { |
| int nBaseSize; |
| pObj = Aig_Regular(pObj); |
| if ( Aig_ObjIsConst1(pObj) ) |
| return 0; |
| if ( Aig_ObjLevel(pObj) >= nLutSize ) |
| return 1; |
| nBaseSize = Aig_SupportSize( p, pObj ); |
| if ( nBaseSize >= nLutSize ) |
| return 1; |
| return nBaseSize; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Builds implication supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Obj_t * Dar_BalanceBuildSuperTop( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel, int nLutSize ) |
| { |
| Vec_Ptr_t * vSubset; |
| Aig_Obj_t * pObj; |
| int i, nBaseSizeAll, nBaseSize; |
| assert( vSuper->nSize > 1 ); |
| // sort the new nodes by level in the decreasing order |
| Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); |
| // add one LUT at a time |
| while ( Vec_PtrSize(vSuper) > 1 ) |
| { |
| // isolate the group of nodes with nLutSize inputs |
| nBaseSizeAll = 0; |
| vSubset = Vec_PtrAlloc( nLutSize ); |
| Vec_PtrForEachEntryReverse( Aig_Obj_t *, vSuper, pObj, i ) |
| { |
| nBaseSize = Aig_BaseSize( p, pObj, nLutSize ); |
| if ( nBaseSizeAll + nBaseSize > nLutSize && Vec_PtrSize(vSubset) > 1 ) |
| break; |
| nBaseSizeAll += nBaseSize; |
| Vec_PtrPush( vSubset, pObj ); |
| } |
| // remove them from vSuper |
| Vec_PtrShrink( vSuper, Vec_PtrSize(vSuper) - Vec_PtrSize(vSubset) ); |
| // create the new supergate |
| pObj = Dar_BalanceBuildSuper( p, vSubset, Type, fUpdateLevel ); |
| Vec_PtrFree( vSubset ); |
| // add the new output |
| Dar_BalancePushUniqueOrderByLevel( vSuper, pObj, Type == AIG_OBJ_EXOR ); |
| } |
| return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns the new node constructed.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) |
| { |
| Aig_Obj_t * pObjNew; |
| Vec_Ptr_t * vSuper; |
| int i; |
| assert( !Aig_IsComplement(pObjOld) ); |
| assert( !Aig_ObjIsBuf(pObjOld) ); |
| // return if the result is known |
| if ( pObjOld->pData ) |
| return (Aig_Obj_t *)pObjOld->pData; |
| assert( Aig_ObjIsNode(pObjOld) ); |
| // get the implication supergate |
| vSuper = Dar_BalanceCone( pObjOld, vStore, Level ); |
| // check if supergate contains two nodes in the opposite polarity |
| if ( vSuper->nSize == 0 ) |
| return (Aig_Obj_t *)(pObjOld->pData = Aig_ManConst0(pNew)); |
| // for each old node, derive the new well-balanced node |
| for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) |
| { |
| pObjNew = Dar_Balance_rec( pNew, Aig_Regular((Aig_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); |
| if ( pObjNew == NULL ) |
| return NULL; |
| vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement((Aig_Obj_t *)vSuper->pArray[i]) ); |
| } |
| // check for exactly one node |
| if ( vSuper->nSize == 1 ) |
| return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); |
| // build the supergate |
| #ifdef USE_LUTSIZE_BALANCE |
| pObjNew = Dar_BalanceBuildSuperTop( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel, 6 ); |
| #else |
| pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel ); |
| #endif |
| if ( pNew->Time2Quit && !(Aig_Regular(pObjNew)->Id & 255) && Abc_Clock() > pNew->Time2Quit ) |
| return NULL; |
| // make sure the balanced node is not assigned |
| // assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level ); |
| assert( pObjOld->pData == NULL ); |
| return (Aig_Obj_t *)(pObjOld->pData = pObjNew); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs algebraic balancing of the AIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ) |
| { |
| Aig_Man_t * pNew; |
| Aig_Obj_t * pObj, * pDriver, * pObjNew; |
| Vec_Vec_t * vStore; |
| int i; |
| assert( Aig_ManVerifyTopoOrder(p) ); |
| // create the new manager |
| pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); |
| pNew->pName = Abc_UtilStrsav( p->pName ); |
| pNew->pSpec = Abc_UtilStrsav( p->pSpec ); |
| pNew->nAsserts = p->nAsserts; |
| pNew->nConstrs = p->nConstrs; |
| pNew->nBarBufs = p->nBarBufs; |
| pNew->Time2Quit = p->Time2Quit; |
| if ( p->vFlopNums ) |
| pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); |
| // map the PI nodes |
| Aig_ManCleanData( p ); |
| Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); |
| vStore = Vec_VecAlloc( 50 ); |
| if ( p->pManTime != NULL ) |
| { |
| float arrTime; |
| Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime ); |
| Aig_ManSetCioIds( p ); |
| Aig_ManForEachObj( p, pObj, i ) |
| { |
| if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) |
| continue; |
| if ( Aig_ObjIsCi(pObj) ) |
| { |
| // copy the PI |
| pObjNew = Aig_ObjCreateCi(pNew); |
| pObj->pData = pObjNew; |
| // set the arrival time of the new PI |
| arrTime = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) ); |
| pObjNew->Level = (int)arrTime; |
| } |
| else if ( Aig_ObjIsCo(pObj) ) |
| { |
| // perform balancing |
| pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); |
| pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel ); |
| if ( pObjNew == NULL ) |
| { |
| Vec_VecFree( vStore ); |
| Aig_ManStop( pNew ); |
| return NULL; |
| } |
| pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) ); |
| // save arrival time of the output |
| arrTime = (float)Aig_Regular(pObjNew)->Level; |
| Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj), arrTime ); |
| // create PO |
| pObjNew = Aig_ObjCreateCo( pNew, pObjNew ); |
| } |
| else |
| assert( 0 ); |
| } |
| Aig_ManCleanCioIds( p ); |
| pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); |
| } |
| else |
| { |
| Aig_ManForEachCi( p, pObj, i ) |
| { |
| pObjNew = Aig_ObjCreateCi(pNew); |
| pObjNew->Level = pObj->Level; |
| pObj->pData = pObjNew; |
| } |
| if ( p->nBarBufs == 0 ) |
| { |
| Aig_ManForEachCo( p, pObj, i ) |
| { |
| pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); |
| pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel ); |
| if ( pObjNew == NULL ) |
| { |
| Vec_VecFree( vStore ); |
| Aig_ManStop( pNew ); |
| return NULL; |
| } |
| pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) ); |
| pObjNew = Aig_ObjCreateCo( pNew, pObjNew ); |
| } |
| } |
| else |
| { |
| Vec_Ptr_t * vLits = Vec_PtrStart( Aig_ManCoNum(p) ); |
| Aig_ManForEachCo( p, pObj, i ) |
| { |
| int k = i < p->nBarBufs ? Aig_ManCoNum(p) - p->nBarBufs + i : i - p->nBarBufs; |
| pObj = Aig_ManCo( p, k ); |
| pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); |
| pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel ); |
| if ( pObjNew == NULL ) |
| { |
| Vec_VecFree( vStore ); |
| Aig_ManStop( pNew ); |
| return NULL; |
| } |
| pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) ); |
| Vec_PtrWriteEntry( vLits, k, pObjNew ); |
| if ( i < p->nBarBufs ) |
| Aig_ManCi(pNew, Aig_ManCiNum(p) - p->nBarBufs + i)->Level = Aig_Regular(pObjNew)->Level; |
| } |
| Aig_ManForEachCo( p, pObj, i ) |
| Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vLits, i) ); |
| Vec_PtrFree(vLits); |
| } |
| } |
| Vec_VecFree( vStore ); |
| // remove dangling nodes |
| Aig_ManCleanup( pNew ); |
| Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); |
| // check the resulting AIG |
| if ( !Aig_ManCheck(pNew) ) |
| printf( "Dar_ManBalance(): The check has failed.\n" ); |
| return pNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reproduces script "compress2".] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose ) |
| { |
| Aig_Man_t * pAigXor, * pRes; |
| if ( fExor ) |
| { |
| pAigXor = Aig_ManDupExor( pAig ); |
| if ( fVerbose ) |
| Dar_BalancePrintStats( pAigXor ); |
| pRes = Dar_ManBalance( pAigXor, fUpdateLevel ); |
| Aig_ManStop( pAigXor ); |
| } |
| else |
| { |
| pRes = Dar_ManBalance( pAig, fUpdateLevel ); |
| } |
| return pRes; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Inserts a new node in the order by levels.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dar_BalancePrintStats( Aig_Man_t * p ) |
| { |
| Vec_Ptr_t * vSuper; |
| Aig_Obj_t * pObj, * pTemp; |
| int i, k; |
| if ( Aig_ManExorNum(p) == 0 ) |
| { |
| printf( "There is no EXOR gates.\n" ); |
| return; |
| } |
| Aig_ManForEachExor( p, pObj, i ) |
| { |
| Aig_ObjFanin0(pObj)->fMarkA = 1; |
| Aig_ObjFanin1(pObj)->fMarkA = 1; |
| assert( !Aig_ObjFaninC0(pObj) ); |
| assert( !Aig_ObjFaninC1(pObj) ); |
| } |
| vSuper = Vec_PtrAlloc( 1000 ); |
| Aig_ManForEachExor( p, pObj, i ) |
| { |
| if ( pObj->fMarkA && pObj->nRefs == 1 ) |
| continue; |
| Vec_PtrClear( vSuper ); |
| Dar_BalanceCone_rec( pObj, pObj, vSuper ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) |
| pTemp->fMarkB = 0; |
| if ( Vec_PtrSize(vSuper) < 3 ) |
| continue; |
| printf( " %d(", Vec_PtrSize(vSuper) ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) |
| printf( " %d", pTemp->Level ); |
| printf( " )" ); |
| } |
| Vec_PtrFree( vSuper ); |
| Aig_ManForEachObj( p, pObj, i ) |
| pObj->fMarkA = 0; |
| printf( "\n" ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |