/**Function************************************************************* Synopsis [Creates the canonical form of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_CanonPair_rec( Aig_Man_t * p, Aig_Obj_t * pGhost ) { Aig_Obj_t * pResult, * pLat0, * pLat1; int fCompl0, fCompl1; Aig_Type_t Type; assert( Aig_ObjIsNode(pGhost) ); // consider the case when the pair is canonical if ( !Aig_ObjIsLatch(Aig_ObjFanin0(pGhost)) || !Aig_ObjIsLatch(Aig_ObjFanin1(pGhost)) ) { if ( (pResult = Aig_TableLookup( p, pGhost )) ) return pResult; return Aig_ObjCreate( p, pGhost ); } /// remember the latches pLat0 = Aig_ObjFanin0(pGhost); pLat1 = Aig_ObjFanin1(pGhost); // remember type and compls Type = Aig_ObjType(pGhost); fCompl0 = Aig_ObjFaninC0(pGhost); fCompl1 = Aig_ObjFaninC1(pGhost); // call recursively pResult = Aig_Oper( p, Aig_NotCond(Aig_ObjChild0(pLat0), fCompl0), Aig_NotCond(Aig_ObjChild0(pLat1), fCompl1), Type ); // build latch on top of this return Aig_Latch( p, pResult, (Type == AIG_OBJ_AND)? fCompl0 & fCompl1 : fCompl0 ^ fCompl1 ); }
/**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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj->fMarkB ) return; pObj->fMarkB = 1; assert( Aig_ObjIsNode(pObj) ); Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); }
/**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 [Collects the support of depth-limited MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffcSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ) { int ConeSize1, ConeSize2; if ( vSupp ) Vec_PtrClear( vSupp ); if ( !Aig_ObjIsNode(pNode) ) { if ( Aig_ObjIsCi(pNode) && vSupp ) Vec_PtrPush( vSupp, pNode ); return 0; } assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); Aig_ManIncrementTravId( p ); ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin, NULL, NULL ); Aig_NodeMffcSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL ); ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); return ConeSize1; }
/**Function************************************************************* Synopsis [Labels the nodes in the MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode ) { int ConeSize1, ConeSize2; assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); Aig_ManIncrementTravId( p ); ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); return ConeSize1; }
/**Function************************************************************* Synopsis [Drive implications of the given node towards primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManSetAndDriveImplications_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int f, int fMax, Vec_Ptr_t * vSimInfo ) { Aig_Obj_t * pFanout; int k, iFanout = -1, Value0, Value1; int Value = Saig_ManSimInfo2Get( vSimInfo, pObj, f ); assert( !Saig_ManSimInfo2IsOld( Value ) ); Saig_ManSimInfo2Set( vSimInfo, pObj, f, Saig_ManSimInfo2SetOld(Value) ); if ( (Aig_ObjIsCo(pObj) && f == fMax) || Saig_ObjIsPo(p, pObj) ) return; if ( Saig_ObjIsLi( p, pObj ) ) { assert( f < fMax ); pFanout = Saig_ObjLiToLo(p, pObj); Value = Saig_ManSimInfo2Get( vSimInfo, pFanout, f+1 ); if ( !Saig_ManSimInfo2IsOld( Value ) ) Saig_ManSetAndDriveImplications_rec( p, pFanout, f+1, fMax, vSimInfo ); return; } assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ); Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) { Value = Saig_ManSimInfo2Get( vSimInfo, pFanout, f ); if ( Saig_ManSimInfo2IsOld( Value ) ) continue; if ( Aig_ObjIsCo(pFanout) ) { Saig_ManSetAndDriveImplications_rec( p, pFanout, f, fMax, vSimInfo ); continue; } assert( Aig_ObjIsNode(pFanout) ); Value0 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin0(pFanout), f ); Value1 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin1(pFanout), f ); if ( Aig_ObjFaninC0(pFanout) ) Value0 = Saig_ManSimInfo2Not( Value0 ); if ( Aig_ObjFaninC1(pFanout) ) Value1 = Saig_ManSimInfo2Not( Value1 ); if ( Value0 == SAIG_ZER_OLD || Value1 == SAIG_ZER_OLD || (Value0 == SAIG_ONE_OLD && Value1 == SAIG_ONE_OLD) ) Saig_ManSetAndDriveImplications_rec( p, pFanout, f, fMax, vSimInfo ); }
/**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 ); } }
/**Function************************************************************* Synopsis [Labels the nodes in the MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffcLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower ) { int ConeSize1, ConeSize2; assert( (pPower != NULL) == (p->vProbs != NULL) ); assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); Aig_ManIncrementTravId( p ); ConeSize1 = Aig_NodeDeref_rec( pNode, 0, pPower, p->vProbs? (float *)p->vProbs->pArray : NULL ); ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); return ConeSize1; }
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 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 [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 [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) { DdNode * bBdd0, * bBdd1; DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); if ( bFunc != NULL ) return bFunc; assert( Aig_ObjIsNode(pObj) ); bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); return bFunc; }
/**Function************************************************************* Synopsis [Performs one retiming step backward.] Description [Returns the pointer to node after retiming.] SideEffects [Remember to run Aig_ManSetCioIds() in advance.] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ManRetimeNodeBwd( Aig_Man_t * p, Aig_Obj_t * pObjLo ) { Aig_Obj_t * pFanin0, * pFanin1; Aig_Obj_t * pLo0New, * pLo1New; Aig_Obj_t * pLi0New, * pLi1New; Aig_Obj_t * pObj, * pObjNew, * pObjLi; int fCompl0, fCompl1; assert( Saig_ManRegNum(p) > 0 ); assert( Aig_ObjCioId(pObjLo) > 0 ); assert( Saig_ObjIsLo(p, pObjLo) ); // get the corresponding latch input pObjLi = Saig_ManLi( p, Aig_ObjCioId(pObjLo) - Saig_ManPiNum(p) ); // get the node pObj = Aig_ObjFanin0(pObjLi); if ( !Aig_ObjIsNode(pObj) ) return NULL; // get the fanins pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); // get the complemented attributes of the fanins fCompl0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFaninC0(pObjLi); fCompl1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFaninC0(pObjLi); // create latch inputs pLi0New = Aig_ObjCreateCo( p, Aig_NotCond(pFanin0, fCompl0) ); pLi0New->CioId = Aig_ManCoNum(p) - 1; pLi1New = Aig_ObjCreateCo( p, Aig_NotCond(pFanin1, fCompl1) ); pLi1New->CioId = Aig_ManCoNum(p) - 1; // create latch outputs pLo0New = Aig_ObjCreateCi(p); pLo0New->CioId = Aig_ManCiNum(p) - 1; pLo1New = Aig_ObjCreateCi(p); pLo1New->CioId = Aig_ManCiNum(p) - 1; pLo0New = Aig_NotCond( pLo0New, fCompl0 ); pLo1New = Aig_NotCond( pLo1New, fCompl1 ); p->nRegs += 2; // create node pObjNew = Aig_And( p, pLo0New, pLo1New ); // assert( pObjNew->fPhase == 0 ); return pObjNew; }
/**Function************************************************************* Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_NodeMffsSupp_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin, Vec_Ptr_t * vSupp, int fTopmost, Aig_Obj_t * pObjSkip ) { // skip visited nodes if ( Aig_ObjIsTravIdCurrent(p, pNode) ) return; Aig_ObjSetTravIdCurrent(p, pNode); // add to the new support nodes if ( !fTopmost && pNode != pObjSkip && (Aig_ObjIsPi(pNode) || pNode->nRefs > 0 || pNode->Level <= LevelMin) ) { if ( vSupp ) Vec_PtrPush( vSupp, pNode ); return; } assert( Aig_ObjIsNode(pNode) ); // recur on the children Aig_NodeMffsSupp_rec( p, Aig_ObjFanin0(pNode), LevelMin, vSupp, 0, pObjSkip ); Aig_NodeMffsSupp_rec( p, Aig_ObjFanin1(pNode), LevelMin, vSupp, 0, pObjSkip ); }
/**Function************************************************************* Synopsis [Labels the nodes in the MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ) { Aig_Obj_t * pObj; int i, ConeSize1, ConeSize2; assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( vLeaves, pObj, i ) pObj->nRefs++; ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); Vec_PtrForEachEntry( vLeaves, pObj, i ) pObj->nRefs--; assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); return ConeSize1; }
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 [Derives CNF for the mapping.] Description [The last argument shows the number of last outputs of the manager, which will not be converted into clauses but the new variables for which will be introduced.] SideEffects [] SeeAlso [] ***********************************************************************/ Cnf_Dat_t * Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs ) { Aig_Obj_t * pObj; Cnf_Dat_t * pCnf; Cnf_Cut_t * pCut; Vec_Int_t * vCover, * vSopTemp; int OutVar, PoVar, pVars[32], * pLits, ** pClas; unsigned uTruth; int i, k, nLiterals, nClauses, Cube, Number; // count the number of literals and clauses nLiterals = 1 + Aig_ManPoNum( p->pManAig ) + 3 * nOutputs; nClauses = 1 + Aig_ManPoNum( p->pManAig ) + nOutputs; Vec_PtrForEachEntry( vMapped, pObj, i ) { assert( Aig_ObjIsNode(pObj) ); pCut = Cnf_ObjBestCut( pObj ); // positive polarity of the cut if ( pCut->nFanins < 5 ) { uTruth = 0xFFFF & *Cnf_CutTruth(pCut); nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth]; assert( p->pSopSizes[uTruth] >= 0 ); nClauses += p->pSopSizes[uTruth]; } else { nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[1], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[1]); nClauses += Vec_IntSize(pCut->vIsop[1]); } // negative polarity of the cut if ( pCut->nFanins < 5 ) { uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut); nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth]; assert( p->pSopSizes[uTruth] >= 0 ); nClauses += p->pSopSizes[uTruth]; } else { nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[0], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[0]); nClauses += Vec_IntSize(pCut->vIsop[0]); } //printf( "%d ", nClauses-(1 + Aig_ManPoNum( p->pManAig )) ); }
/**Function************************************************************* Synopsis [Checks if node with the given attributes is in the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ) { Aig_Obj_t * pEntry; assert( !Aig_IsComplement(pGhost) ); assert( Aig_ObjIsNode(pGhost) ); assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) ); assert( Aig_ObjFanin0(pGhost)->Id < Aig_ObjFanin1(pGhost)->Id ); if ( p->pTable == NULL || !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost)) ) return NULL; for ( pEntry = p->pTable[Aig_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) { if ( Aig_ObjChild0(pEntry) == Aig_ObjChild0(pGhost) && Aig_ObjChild1(pEntry) == Aig_ObjChild1(pGhost) && Aig_ObjType(pEntry) == Aig_ObjType(pGhost) ) return pEntry; } return NULL; }
/**Function************************************************************* Synopsis [Expands the cut by adding the most closely related node.] Description [Returns 1 if the cut exists.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ) { Aig_Obj_t * pObj, * pLeafBest; int i, LevelMax, ConeSize1, ConeSize2, ConeCur1, ConeCur2, ConeBest; // dereference the current cut LevelMax = 0; Vec_PtrForEachEntry( vLeaves, pObj, i ) LevelMax = AIG_MAX( LevelMax, (int)pObj->Level ); if ( LevelMax == 0 ) return 0; // dereference the cut ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); // try expanding each node in the boundary ConeBest = AIG_INFINITY; pLeafBest = NULL; Vec_PtrForEachEntry( vLeaves, pObj, i ) { if ( (int)pObj->Level != LevelMax ) continue; ConeCur1 = Aig_NodeDeref_rec( pObj, 0 ); if ( ConeBest > ConeCur1 ) { ConeBest = ConeCur1; pLeafBest = pObj; } ConeCur2 = Aig_NodeRef_rec( pObj, 0 ); assert( ConeCur1 == ConeCur2 ); } assert( pLeafBest != NULL ); assert( Aig_ObjIsNode(pLeafBest) ); // deref the best leaf ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0 ); // collect the cut nodes Vec_PtrClear( vResult ); Aig_ManIncrementTravId( p ); Aig_NodeMffsSupp_rec( p, pNode, 0, vResult, 1, pLeafBest ); // ref the nodes ConeCur2 = Aig_NodeRef_rec( pLeafBest, 0 ); assert( ConeCur1 == ConeCur2 ); // ref the original node ConeSize2 = Aig_NodeRef_rec( pNode, 0 ); assert( ConeSize1 == ConeSize2 ); return 1; }
/**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFromAigChoices_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj == NULL || pObj->iData ) return; assert( Aig_ObjIsNode(pObj) ); Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) ); Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin1(pObj) ); Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjEquiv(p, pObj) ); pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); if ( Aig_ObjEquiv(p, pObj) ) { int iObjNew, iNextNew; iObjNew = Abc_Lit2Var(pObj->iData); iNextNew = Abc_Lit2Var(Aig_ObjEquiv(p, pObj)->iData); assert( iObjNew > iNextNew ); assert( Gia_ObjIsAnd(Gia_ManObj(pNew, iNextNew)) ); pNew->pSibls[iObjNew] = iNextNew; } }
/**Function************************************************************* Synopsis [Performs ternary simulation for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManExtendOneEval2( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame ) { int Value0, Value1, Value; Value0 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin0(pObj), iFrame ); if ( Aig_ObjFaninC0(pObj) ) Value0 = Saig_ManSimInfo2Not( Value0 ); if ( Aig_ObjIsCo(pObj) ) { Saig_ManSimInfo2Set( vSimInfo, pObj, iFrame, Value0 ); return Value0; } assert( Aig_ObjIsNode(pObj) ); Value1 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin1(pObj), iFrame ); if ( Aig_ObjFaninC1(pObj) ) Value1 = Saig_ManSimInfo2Not( Value1 ); Value = Saig_ManSimInfo2And( Value0, Value1 ); Saig_ManSimInfo2Set( vSimInfo, pObj, iFrame, Value ); return Value; }
/**Function************************************************************* Synopsis [Derives combinational miter of the two AIGs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFromAig_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pNext; if ( pObj->iData ) return; assert( Aig_ObjIsNode(pObj) ); Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin1(pObj) ); pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); if ( p->pEquivs && (pNext = Aig_ObjEquiv(p, pObj)) ) { int iObjNew, iNextNew; Gia_ManFromAig_rec( pNew, p, pNext ); iObjNew = Gia_Lit2Var(pObj->iData); iNextNew = Gia_Lit2Var(pNext->iData); if ( pNew->pNexts ) pNew->pNexts[iObjNew] = iNextNew; } }
/**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 [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; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Saig_ObjName( Aig_Man_t * p, Aig_Obj_t * pObj ) { static char Buffer[16]; if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) sprintf( Buffer, "n%0*d", Aig_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); else if ( Saig_ObjIsPi(p, pObj) ) sprintf( Buffer, "pi%0*d", Aig_Base10Log(Saig_ManPiNum(p)), Aig_ObjPioNum(pObj) ); else if ( Saig_ObjIsPo(p, pObj) ) sprintf( Buffer, "po%0*d", Aig_Base10Log(Saig_ManPoNum(p)), Aig_ObjPioNum(pObj) ); else if ( Saig_ObjIsLo(p, pObj) ) sprintf( Buffer, "lo%0*d", Aig_Base10Log(Saig_ManRegNum(p)), Aig_ObjPioNum(pObj) - Saig_ManPiNum(p) ); else if ( Saig_ObjIsLi(p, pObj) ) sprintf( Buffer, "li%0*d", Aig_Base10Log(Saig_ManRegNum(p)), Aig_ObjPioNum(pObj) - Saig_ManPoNum(p) ); else assert( 0 ); return Buffer; }
// pNtk->nLatches = Aig_ManRegNum(p); // pNtk->nTruePis = Nwk_ManCiNum(pNtk) - pNtk->nLatches; // pNtk->nTruePos = Nwk_ManCoNum(pNtk) - pNtk->nLatches; Aig_ManForEachObj( p, pObj, i ) { pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) continue; if ( Aig_ObjIsNode(pObj) ) { pCutBest = If_ObjCutBest( pIfObj ); nLeaves = If_CutLeaveNum( pCutBest ); ppLeaves = If_CutLeaves( pCutBest ); // create node pObjNew = Nwk_ManCreateNode( pNtk, nLeaves, pIfObj->nRefs ); for ( k = 0; k < nLeaves; k++ ) { pObjRepr = (Aig_Obj_t *)Vec_PtrEntry( vIfToAig, ppLeaves[k] ); Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)pObjRepr->pData ); } // get the functionality pObjNew->pFunc = Nwk_NodeIfToHop( pNtk->pManHop, pIfMan, pIfObj ); } else if ( Aig_ObjIsCi(pObj) ) pObjNew = Nwk_ManCreateCi( pNtk, pIfObj->nRefs ); else if ( Aig_ObjIsCo(pObj) ) { pObjNew = Nwk_ManCreateCo( pNtk ); pObjNew->fInvert = Aig_ObjFaninC0(pObj); Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); //printf( "%d ", pObjNew->Id ); } else if ( Aig_ObjIsConst1(pObj) ) { pObjNew = Nwk_ManCreateNode( pNtk, 0, pIfObj->nRefs ); pObjNew->pFunc = Hop_ManConst1( pNtk->pManHop ); } else assert( 0 ); pObj->pData = pObjNew; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds strashed nodes for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManSpeedupNode_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) return 1; if ( Aig_ObjIsPi(pNode) ) return 0; assert( Aig_ObjIsNode(pNode) ); Aig_ObjSetTravIdCurrent( pAig, pNode ); if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin0(pNode), vNodes ) ) return 0; if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin1(pNode), vNodes ) ) return 0; Vec_PtrPush( vNodes, pNode ); return 1; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) { extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Dar_Man_t * p; // Bar_Progress_t * pProgress; Dar_Cut_t * pCut; Aig_Obj_t * pObj, * pObjNew; int i, k, nNodesOld, nNodeBefore, nNodeAfter, Required; abctime clk = 0, clkStart; int Counter = 0; int nMffcSize;//, nMffcGains[MAX_VAL+1][MAX_VAL+1] = {{0}}; // prepare the library Dar_LibPrepare( pPars->nSubgMax ); // create rewriting manager p = Dar_ManStart( pAig, pPars ); if ( pPars->fPower ) pAig->vProbs = Saig_ManComputeSwitchProbs( pAig, 48, 16, 1 ); // remove dangling nodes Aig_ManCleanup( pAig ); // if updating levels is requested, start fanout and timing if ( p->pPars->fFanout ) Aig_ManFanoutStart( pAig ); if ( p->pPars->fUpdateLevel ) Aig_ManStartReverseLevels( pAig, 0 ); // set elementary cuts for the PIs // Dar_ManCutsStart( p ); // resynthesize each node once clkStart = Abc_Clock(); p->nNodesInit = Aig_ManNodeNum(pAig); nNodesOld = Vec_PtrSize( pAig->vObjs ); // pProgress = Bar_ProgressStart( stdout, nNodesOld ); Aig_ManForEachObj( pAig, pObj, i ) // pProgress = Bar_ProgressStart( stdout, 100 ); // Aig_ManOrderStart( pAig ); // Aig_ManForEachNodeInOrder( pAig, pObj ) { if ( pAig->Time2Quit && !(i & 256) && Abc_Clock() > pAig->Time2Quit ) break; // Bar_ProgressUpdate( pProgress, 100*pAig->nAndPrev/pAig->nAndTotal, NULL ); // Bar_ProgressUpdate( pProgress, i, NULL ); if ( !Aig_ObjIsNode(pObj) ) continue; if ( i > nNodesOld ) // if ( p->pPars->fUseZeros && i > nNodesOld ) break; if ( pPars->fRecycle && ++Counter % 50000 == 0 && Aig_DagSize(pObj) < Vec_PtrSize(p->vCutNodes)/100 ) { // printf( "Counter = %7d. Node = %7d. Dag = %5d. Vec = %5d.\n", // Counter, i, Aig_DagSize(pObj), Vec_PtrSize(p->vCutNodes) ); // fflush( stdout ); Dar_ManCutsRestart( p, pObj ); } // consider freeing the cuts // if ( (i & 0xFFF) == 0 && Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) > 100 ) // Dar_ManCutsStart( p ); // compute cuts for the node p->nNodesTried++; clk = Abc_Clock(); Dar_ObjSetCuts( pObj, NULL ); Dar_ObjComputeCuts_rec( p, pObj ); p->timeCuts += Abc_Clock() - clk; // check if there is a trivial cut Dar_ObjForEachCut( pObj, pCut, k ) if ( pCut->nLeaves == 0 || (pCut->nLeaves == 1 && pCut->pLeaves[0] != pObj->Id && Aig_ManObj(p->pAig, pCut->pLeaves[0])) ) break; if ( k < (int)pObj->nCuts ) { assert( pCut->nLeaves < 2 ); if ( pCut->nLeaves == 0 ) // replace by constant { assert( pCut->uTruth == 0 || pCut->uTruth == 0xFFFF ); pObjNew = Aig_NotCond( Aig_ManConst1(p->pAig), pCut->uTruth==0 ); } else { assert( pCut->uTruth == 0xAAAA || pCut->uTruth == 0x5555 ); pObjNew = Aig_NotCond( Aig_ManObj(p->pAig, pCut->pLeaves[0]), pCut->uTruth==0x5555 ); } // remove the old cuts Dar_ObjSetCuts( pObj, NULL ); // replace the node Aig_ObjReplace( pAig, pObj, pObjNew, p->pPars->fUpdateLevel ); continue; } // evaluate the cuts p->GainBest = -1; nMffcSize = -1; Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : ABC_INFINITY; Dar_ObjForEachCut( pObj, pCut, k ) { int nLeavesOld = pCut->nLeaves; if ( pCut->nLeaves == 3 ) pCut->pLeaves[pCut->nLeaves++] = 0; Dar_LibEval( p, pObj, pCut, Required, &nMffcSize ); pCut->nLeaves = nLeavesOld; } // check the best gain if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) { // Aig_ObjOrderAdvance( pAig ); continue; } // nMffcGains[p->GainBest < MAX_VAL ? p->GainBest : MAX_VAL][nMffcSize < MAX_VAL ? nMffcSize : MAX_VAL]++; // remove the old cuts Dar_ObjSetCuts( pObj, NULL ); // if we end up here, a rewriting step is accepted nNodeBefore = Aig_ManNodeNum( pAig ); pObjNew = Dar_LibBuildBest( p ); // pObjNew can be complemented! pObjNew = Aig_NotCond( pObjNew, Aig_ObjPhaseReal(pObjNew) ^ pObj->fPhase ); assert( (int)Aig_Regular(pObjNew)->Level <= Required ); // replace the node Aig_ObjReplace( pAig, pObj, pObjNew, p->pPars->fUpdateLevel ); // compare the gains nNodeAfter = Aig_ManNodeNum( pAig ); assert( p->GainBest <= nNodeBefore - nNodeAfter ); // count gains of this class p->ClassGains[p->ClassBest] += nNodeBefore - nNodeAfter; }