/**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) { assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop ); // update node counters of the manager p->nObjs[pObj->Type]--; p->nDeleted++; // remove connections Ivy_ObjDisconnect( p, pObj ); // remove PIs/POs from the arrays if ( Ivy_ObjIsPi(pObj) ) Vec_PtrRemove( p->vPis, pObj ); else if ( Ivy_ObjIsPo(pObj) ) Vec_PtrRemove( p->vPos, pObj ); else if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) Vec_PtrRemove( p->vBufs, pObj ); // clean and recycle the entry if ( fFreeTop ) { // free the node Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); Ivy_ManRecycleMemory( p, pObj ); } else { int nRefsOld = pObj->nRefs; Ivy_Obj_t * pFanout = pObj->pFanout; Ivy_ObjClean( pObj ); pObj->pFanout = pFanout; pObj->nRefs = nRefsOld; } }
/**Function************************************************************* Synopsis [Connect the object to the fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL ); // remove connections if ( pObj->pFanin0 != NULL ) { Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj)); if ( p->fFanout ) Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj ); } if ( pObj->pFanin1 != NULL ) { Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj)); if ( p->fFanout ) Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj ); } assert( pObj->pNextFan0 == NULL ); assert( pObj->pNextFan1 == NULL ); assert( pObj->pPrevFan0 == NULL ); assert( pObj->pPrevFan1 == NULL ); // remove the node from the structural hash table Ivy_TableDelete( p, pObj ); // add the first fanin pObj->pFanin0 = NULL; pObj->pFanin1 = NULL; }
/**Function************************************************************* Synopsis [Performs algebraic balancing of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ) { Ivy_Man_t * pNew; Ivy_Obj_t * pObj, * pDriver; Vec_Vec_t * vStore; int i, NewNodeId; // clean the old manager Ivy_ManCleanTravId( p ); // create the new manager pNew = Ivy_ManStart(); // map the nodes Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) ); Ivy_ManForEachPi( p, pObj, i ) pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) ); // if HAIG is defined, trasfer the pointers to the PIs/latches // if ( p->pHaig ) // Ivy_ManHaigTrasfer( p, pNew ); // balance the AIG vStore = Vec_VecAlloc( 50 ); Ivy_ManForEachPo( p, pObj, i ) { pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) ); NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel ); NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) ); Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) ); }
// procedure to detect an EXOR gate static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 ) { if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) ) return 0; p0 = Ivy_Regular(p0); p1 = Ivy_Regular(p1); if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) ) return 0; if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) ) return 0; if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) ) return 0; *ppFan0 = Ivy_ObjChild0(p0); *ppFan1 = Ivy_ObjChild1(p0); return 1; }
/**Function************************************************************* Synopsis [Updates the table to point to the new node.] Description [If the old node (pObj) is in the table, updates the table to point to an object with different ID (ObjIdNew). The table should not contain an object with ObjIdNew (this is currently not checked).] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ) { int * pPlace; assert( !Ivy_IsComplement(pObj) ); if ( !Ivy_ObjIsHash(pObj) ) return; pPlace = Ivy_TableFind( p, pObj ); assert( *pPlace == pObj->Id ); // node should be in the table *pPlace = ObjIdNew; }
/**Function************************************************************* Synopsis [Deletes the MFFC of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) { Ivy_Obj_t * pFanin0, * pFanin1; assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_ObjIsNone(pObj) ); if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) ) return; pFanin0 = Ivy_ObjFanin0(pObj); pFanin1 = Ivy_ObjFanin1(pObj); Ivy_ObjDelete( p, pObj, fFreeTop ); if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 ) Ivy_ObjDelete_rec( p, pFanin0, 1 ); if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 ) Ivy_ObjDelete_rec( p, pFanin1, 1 ); }
/**Function************************************************************* Synopsis [Adds the node to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { int * pPlace; assert( !Ivy_IsComplement(pObj) ); if ( !Ivy_ObjIsHash(pObj) ) return; if ( (pObj->Id & 63) == 0 ) { if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) ) Ivy_TableResize( p ); } pPlace = Ivy_TableFind( p, pObj ); assert( *pPlace == 0 ); *pPlace = pObj->Id; }
/**Function************************************************************* Synopsis [Collects nodes in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) { Ivy_Obj_t * pTemp; int i; assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsNode(pObj) ); // mark the nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) Ivy_Regular(pTemp)->fMarkA = 1; assert( pObj->fMarkA == 0 ); // collect the cone Vec_PtrClear( vCone ); Ivy_ManCollectCone_rec( pObj, vCone ); // unmark the nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) Ivy_Regular(pTemp)->fMarkA = 0; }
/**Function************************************************************* Synopsis [Replaces the first fanin of the node by the new fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ) { Ivy_Obj_t * pFaninOld; assert( !Ivy_IsComplement(pObj) ); pFaninOld = Ivy_ObjFanin0(pObj); // decrement ref and remove fanout Ivy_ObjRefsDec( pFaninOld ); if ( p->fFanout ) Ivy_ObjDeleteFanout( p, pFaninOld, pObj ); // update the fanin pObj->pFanin0 = pFaninNew; // increment ref and add fanout Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) ); if ( p->fFanout ) Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj ); // get rid of old fanin if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 ) Ivy_ObjDelete_rec( p, pFaninOld, 1 ); }
/**Function************************************************************* Synopsis [Deletes the node from the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pEntry; int i, * pPlace; assert( !Ivy_IsComplement(pObj) ); if ( !Ivy_ObjIsHash(pObj) ) return; pPlace = Ivy_TableFind( p, pObj ); assert( *pPlace == pObj->Id ); // node should be in the table *pPlace = 0; // rehash the adjacent entries i = pPlace - p->pTable; for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) { pEntry = Ivy_ManObj( p, p->pTable[i] ); p->pTable[i] = 0; Ivy_TableInsert( p, pEntry ); } }
/**Function************************************************************* Synopsis [Checks if node with the given attributes is in the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pEntry; int i; assert( !Ivy_IsComplement(pObj) ); if ( !Ivy_ObjIsHash(pObj) ) return NULL; assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 ); assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) ); if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) ) return NULL; for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) { pEntry = Ivy_ManObj( p, p->pTable[i] ); if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) && Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) && Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) && Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) ) return pEntry; } return NULL; }
/**Function************************************************************* Synopsis [Connect the object to the fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ) { assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL ); // add the first fanin pObj->pFanin0 = pFan0; pObj->pFanin1 = pFan1; // increment references of the fanins and add their fanouts if ( Ivy_ObjFanin0(pObj) != NULL ) { Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) ); if ( p->fFanout ) Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); } if ( Ivy_ObjFanin1(pObj) != NULL ) { Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) ); if ( p->fFanout ) Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); } // add the node to the structural hash table Ivy_TableInsert( p, pObj ); }
/**Function************************************************************* Synopsis [Sets the final nodes to point to the original nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig ) { Abc_Obj_t * pObj; Ivy_Obj_t * pObjIvy, * pObjFraig; int i; pObj = Abc_AigConst1(pNtk); pObj->pCopy = Abc_AigConst1(pNtkAig); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = Abc_NtkCi(pNtkAig, i); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pCopy = Abc_NtkCo(pNtkAig, i); Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pCopy = Abc_NtkBox(pNtkAig, i); Abc_NtkForEachNode( pNtk, pObj, i ) { pObjIvy = (Ivy_Obj_t *)pObj->pCopy; if ( pObjIvy == NULL ) continue; pObjFraig = Ivy_ObjEquiv( pObjIvy ); if ( pObjFraig == NULL ) continue; pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId ); pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) ); }
/**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) { Ivy_Obj_t * pObj; assert( !Ivy_IsComplement(pGhost) ); assert( Ivy_ObjIsGhost(pGhost) ); assert( Ivy_TableLookup(p, pGhost) == NULL ); // get memory for the new object pObj = Ivy_ManFetchMemory( p ); assert( Ivy_ObjIsNone(pObj) ); pObj->Id = Vec_PtrSize(p->vObjs); Vec_PtrPush( p->vObjs, pObj ); // add basic info (fanins, compls, type, init) pObj->Type = pGhost->Type; pObj->Init = pGhost->Init; // add connections Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); // compute level if ( Ivy_ObjIsNode(pObj) ) pObj->Level = Ivy_ObjLevelNew(pObj); else if ( Ivy_ObjIsLatch(pObj) ) pObj->Level = 0; else if ( Ivy_ObjIsOneFanin(pObj) ) pObj->Level = Ivy_ObjFanin0(pObj)->Level; else if ( !Ivy_ObjIsPi(pObj) ) assert( 0 ); // create phase if ( Ivy_ObjIsNode(pObj) ) pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); else if ( Ivy_ObjIsOneFanin(pObj) ) pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); // set the fail TFO flag if ( Ivy_ObjIsNode(pObj) ) pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo; // mark the fanins in a special way if the node is EXOR if ( Ivy_ObjIsExor(pObj) ) { Ivy_ObjFanin0(pObj)->fExFan = 1; Ivy_ObjFanin1(pObj)->fExFan = 1; } // add PIs/POs to the arrays if ( Ivy_ObjIsPi(pObj) ) Vec_PtrPush( p->vPis, pObj ); else if ( Ivy_ObjIsPo(pObj) ) Vec_PtrPush( p->vPos, pObj ); // else if ( Ivy_ObjIsBuf(pObj) ) // Vec_PtrPush( p->vBufs, pObj ); if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id ) Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 ); // update node counters of the manager p->nObjs[Ivy_ObjType(pObj)]++; p->nCreated++; // printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " ); // Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL ); // printf( "\n" ); // if HAIG is defined, create a corresponding node if ( p->pHaig ) Ivy_ManHaigCreateObj( p, pObj ); return pObj; }
/**Function************************************************************* Synopsis [Replaces one object by another.] Description [Both objects are currently in the manager. 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.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ) { int nRefsOld;//, clk; // the object to be replaced cannot be complemented assert( !Ivy_IsComplement(pObjOld) ); // the object to be replaced cannot be a terminal assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) ); // the object to be used cannot be a PO or assert assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) ); // the object cannot be the same assert( pObjOld != Ivy_Regular(pObjNew) ); //printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id ); // if HAIG is defined, create the choice node if ( p->pHaig ) { // if ( pObjOld->Id == 31 ) // { // Ivy_ManShow( p, 0 ); // Ivy_ManShow( p->pHaig, 1 ); // } Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew ); } // if the new object is complemented or already used, add the buffer if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) ); assert( !Ivy_IsComplement(pObjNew) ); if ( fUpdateLevel ) { //clk = clock(); // if the new node's arrival time is different, recursively update arrival time of the fanouts if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level ) { assert( Ivy_ObjIsNode(pObjOld) ); pObjOld->Level = pObjNew->Level; Ivy_ObjUpdateLevel_rec( p, pObjOld ); } //p->time1 += clock() - clk; // if the new node's required time has changed, recursively update required time of the fanins //clk = clock(); if ( p->vRequired ) { int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id); if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) ) { Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew ); Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew ); } } //p->time2 += clock() - clk; } // delete the old object if ( fDeleteOld ) Ivy_ObjDelete_rec( p, pObjOld, fFreeTop ); // make sure object is not pointing to itself assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) ); assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) ); // make sure the old node has no fanin fanout pointers if ( p->fFanout ) { assert( pObjOld->pFanout != NULL ); assert( pObjNew->pFanout == NULL ); pObjNew->pFanout = pObjOld->pFanout; } // transfer the old object assert( Ivy_ObjRefs(pObjNew) == 0 ); nRefsOld = pObjOld->nRefs; Ivy_ObjOverwrite( pObjOld, pObjNew ); pObjOld->nRefs = nRefsOld; // patch the fanout of the fanins if ( p->fFanout ) { Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld ); if ( Ivy_ObjFanin1(pObjOld) ) Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld ); } // update the hash table Ivy_TableUpdate( p, pObjNew, pObjOld->Id ); // recycle the object that was taken over by pObjOld Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL ); Ivy_ManRecycleMemory( p, pObjNew ); // if the new node is the buffer propagate it if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) ) Vec_PtrPush( p->vBufs, pObjOld ); // Ivy_ManCheckFanouts( p ); // printf( "\n" ); /* if ( p->pHaig ) { int x; Ivy_ManShow( p, 0, NULL ); Ivy_ManShow( p->pHaig, 1, NULL ); x = 0; } */ // if ( Ivy_ManCheckFanoutNums(p) ) // { // int x = 0; // } }