/**Function************************************************************* Synopsis [Replaces node with a buffer fanin by a node without them.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_NodeFixBufferFanins( Aig_Man_t * p, Aig_Obj_t * pObj, int fNodesOnly, int fUpdateLevel ) { Aig_Obj_t * pFanReal0, * pFanReal1, * pResult; p->nBufFixes++; if ( Aig_ObjIsPo(pObj) ) { assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ); pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); assert( Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) == Aig_ObjPhaseReal(pFanReal0) ); Aig_ObjPatchFanin0( p, pObj, pFanReal0 ); return; } assert( Aig_ObjIsNode(pObj) ); assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) || Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ); // get the real fanins pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); pFanReal1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); // get the new node if ( Aig_ObjIsNode(pObj) ) pResult = Aig_Oper( p, pFanReal0, pFanReal1, Aig_ObjType(pObj) ); // else if ( Aig_ObjIsLatch(pObj) ) // pResult = Aig_Latch( p, pFanReal0, Aig_ObjInit(pObj) ); else assert( 0 ); // replace the node with buffer by the node without buffer Aig_ObjReplace( p, pObj, pResult, fNodesOnly, fUpdateLevel ); }
/**Function************************************************************* Synopsis [Replaces one object by another.] Description [The new object (pObjNew) should be used instead of the old object (pObjOld). If the new object is complemented or used, the buffer is added and the new object remains in the manager; otherwise, the new object is deleted.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fNodesOnly, int fUpdateLevel ) { Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew); // the object to be replaced cannot be complemented assert( !Aig_IsComplement(pObjOld) ); // the object to be replaced cannot be a terminal assert( !Aig_ObjIsPi(pObjOld) && !Aig_ObjIsPo(pObjOld) ); // the object to be used cannot be a buffer or a PO assert( !Aig_ObjIsBuf(pObjNewR) && !Aig_ObjIsPo(pObjNewR) ); // the object cannot be the same assert( pObjOld != pObjNewR ); // make sure object is not pointing to itself assert( pObjOld != Aig_ObjFanin0(pObjNewR) ); assert( pObjOld != Aig_ObjFanin1(pObjNewR) ); // recursively delete the old node - but leave the object there pObjNewR->nRefs++; Aig_ObjDelete_rec( p, pObjOld, 0 ); pObjNewR->nRefs--; // if the new object is complemented or already used, create a buffer p->nObjs[pObjOld->Type]--; if ( Aig_IsComplement(pObjNew) || Aig_ObjRefs(pObjNew) > 0 || (fNodesOnly && !Aig_ObjIsNode(pObjNew)) ) { pObjOld->Type = AIG_OBJ_BUF; Aig_ObjConnect( p, pObjOld, pObjNew, NULL ); p->nBufReplaces++; } else { Aig_Obj_t * pFanin0 = pObjNew->pFanin0; Aig_Obj_t * pFanin1 = pObjNew->pFanin1; int LevelOld = pObjOld->Level; pObjOld->Type = pObjNew->Type; Aig_ObjDisconnect( p, pObjNew ); Aig_ObjConnect( p, pObjOld, pFanin0, pFanin1 ); // delete the new object Aig_ObjDelete( p, pObjNew ); // update levels if ( p->pFanData ) { pObjOld->Level = LevelOld; Aig_ManUpdateLevel( p, pObjOld ); } if ( fUpdateLevel ) { Aig_ObjClearReverseLevel( p, pObjOld ); Aig_ManUpdateReverseLevel( p, pObjOld ); } } p->nObjs[pObjOld->Type]++; // store buffers if fanout is allocated if ( p->pFanData && Aig_ObjIsBuf(pObjOld) ) { Vec_PtrPush( p->vBufs, pObjOld ); p->nBufMax = AIG_MAX( p->nBufMax, Vec_PtrSize(p->vBufs) ); Aig_ManPropagateBuffers( p, fNodesOnly, fUpdateLevel ); } }
/**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDup( Aig_Man_t * p, int fOrdered ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Aig_UtilStrsav( p->pName ); pNew->nRegs = p->nRegs; pNew->nAsserts = p->nAsserts; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreatePi(pNew); // duplicate internal nodes if ( fOrdered ) { Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) pObj->pData = Aig_ObjChild0Copy(pObj); else if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } else {
/**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj->pData ) return pObj->pData; Aig_ManDup_rec( pNew, p, Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsBuf(pObj) ) return pObj->pData = Aig_ObjChild0Copy(pObj); Aig_ManDup_rec( pNew, p, Aig_ObjFanin1(pObj) ); return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); }
/**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsTerm(pObj) ); assert( Aig_ObjRefs(pObj) == 0 ); if ( p->pFanData && Aig_ObjIsBuf(pObj) ) Vec_PtrRemove( p->vBufs, pObj ); p->nObjs[pObj->Type]--; Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); Aig_ManRecycleMemory( p, pObj ); }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Dereferences the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs ) { float Power0 = 0.0, Power1 = 0.0; Aig_Obj_t * pFanin; int Counter = 0; if ( pProbs ) *pPower = 0.0; if ( Aig_ObjIsCi(pNode) ) return 0; // consider the first fanin pFanin = Aig_ObjFanin0(pNode); assert( pFanin->nRefs > 0 ); if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power0, pProbs ); if ( pProbs ) *pPower += Power0 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]); // skip the buffer if ( Aig_ObjIsBuf(pNode) ) return Counter; assert( Aig_ObjIsNode(pNode) ); // consider the second fanin pFanin = Aig_ObjFanin1(pNode); assert( pFanin->nRefs > 0 ); if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power1, pProbs ); if ( pProbs ) *pPower += Power1 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]); return Counter + 1; }
/**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( pObj == NULL ) return; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); Aig_ManDfs_rec( p, Aig_ObjFanin0(pObj), vNodes ); Aig_ManDfs_rec( p, Aig_ObjFanin1(pObj), vNodes ); assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection Aig_ObjSetTravIdCurrent(p, pObj); Vec_PtrPush( vNodes, pObj ); }
/**Function************************************************************* Synopsis [Collects internal nodes in the reverse DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDfsReverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Aig_Obj_t * pFanout; int iFanout, i; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) Aig_ManDfsReverse_rec( p, pFanout, vNodes ); assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection Aig_ObjSetTravIdCurrent(p, pObj); Vec_PtrPush( vNodes, pObj ); }
/**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ) { Aig_Obj_t * pFanin; int Counter = 0; if ( Aig_ObjIsPi(pNode) ) return 0; // consider the first fanin pFanin = Aig_ObjFanin0(pNode); if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeRef_rec( pFanin, LevelMin ); // skip the buffer if ( Aig_ObjIsBuf(pNode) ) return Counter; assert( Aig_ObjIsNode(pNode) ); // consider the second fanin pFanin = Aig_ObjFanin1(pNode); if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeRef_rec( pFanin, LevelMin ); return Counter + 1; }
/**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeRefLabel_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin ) { Aig_Obj_t * pFanin; int Counter = 0; if ( Aig_ObjIsPi(pNode) ) return 0; Aig_ObjSetTravIdCurrent( p, pNode ); // consider the first fanin pFanin = Aig_ObjFanin0(pNode); if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); if ( Aig_ObjIsBuf(pNode) ) return Counter; assert( Aig_ObjIsNode(pNode) ); // consider the second fanin pFanin = Aig_ObjFanin1(pNode); if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); return Counter + 1; }
/**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManPropagateBuffers( Aig_Man_t * p, int fNodesOnly, int fUpdateLevel ) { Aig_Obj_t * pObj; int nSteps; assert( p->pFanData ); for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) { // get the node with a buffer fanin for ( pObj = Vec_PtrEntryLast(p->vBufs); Aig_ObjIsBuf(pObj); pObj = Aig_ObjFanout0(p, pObj) ); // replace this node by a node without buffer Aig_NodeFixBufferFanins( p, pObj, fNodesOnly, fUpdateLevel ); // stop if a cycle occured if ( nSteps > 1000000 ) { printf( "Error: A cycle is encountered while propagating buffers.\n" ); break; } } return nSteps; }
/**Function************************************************************* Synopsis [Collects internal nodes in the reverse DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; Aig_ManIncrementTravId( p ); // mark POs Aig_ManForEachPo( p, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // if there are latches, mark them if ( Aig_ManLatchNum(p) > 0 ) Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsLatch(pObj) ) Aig_ObjSetTravIdCurrent( p, pObj ); // go through the nodes vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ) Aig_ManDfsReverse_rec( p, pObj, vNodes ); return vNodes; }