/**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 [Converts the network from AIG to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MfsConvertHopToAig( Abc_Obj_t * pObjOld, Aig_Man_t * pMan ) { Hop_Man_t * pHopMan; Hop_Obj_t * pRoot; Abc_Obj_t * pFanin; int i; // get the local AIG pHopMan = (Hop_Man_t *)pObjOld->pNtk->pManFunc; pRoot = (Hop_Obj_t *)pObjOld->pData; // check the case of a constant if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) { pObjOld->pCopy = (Abc_Obj_t *)Aig_NotCond( Aig_ManConst1(pMan), Hop_IsComplement(pRoot) ); pObjOld->pNext = pObjOld->pCopy; return; } // assign the fanin nodes Abc_ObjForEachFanin( pObjOld, pFanin, i ) Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy; // construct the AIG Abc_MfsConvertHopToAig_rec( Hop_Regular(pRoot), pMan ); pObjOld->pCopy = (Abc_Obj_t *)Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); // assign the fanin nodes Abc_ObjForEachFanin( pObjOld, pFanin, i ) Hop_ManPi(pHopMan, i)->pData = pFanin->pNext; // construct the AIG Abc_MfsConvertHopToAig_rec( Hop_Regular(pRoot), pMan ); pObjOld->pNext = (Abc_Obj_t *)Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); }
/**Function************************************************************* Synopsis [Creates the canonical form of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Latch( Aig_Man_t * p, Aig_Obj_t * pObj, int fInitOne ) { Aig_Obj_t * pGhost, * pResult; pGhost = Aig_ObjCreateGhost( p, Aig_NotCond(pObj, fInitOne), NULL, AIG_OBJ_LATCH ); pResult = Aig_TableLookup( p, pGhost ); if ( pResult == NULL ) pResult = Aig_ObjCreate( p, pGhost ); return Aig_NotCond( pResult, fInitOne ); }
Kit_GraphForEachNode( pGraph, pNode, i ) { // get the children of this node pNode0 = Kit_GraphNode( pGraph, pNode->eEdge0.Node ); pNode1 = Kit_GraphNode( pGraph, pNode->eEdge1.Node ); // get the AIG nodes corresponding to the children pAnd0 = pNode0->pFunc; pAnd1 = pNode1->pFunc; if ( pAnd0 && pAnd1 ) { // if they are both present, find the resulting node pAnd0 = Aig_NotCond( pAnd0, pNode->eEdge0.fCompl ); pAnd1 = Aig_NotCond( pAnd1, pNode->eEdge1.fCompl ); pAnd = Aig_TableLookupTwo( pAig, pAnd0, pAnd1 ); // return -1 if the node is the same as the original root if ( Aig_Regular(pAnd) == pRoot ) return -1; } else pAnd = NULL; // count the number of added nodes if ( pAnd == NULL || Aig_ObjIsTravIdCurrent(pAig, Aig_Regular(pAnd)) ) { if ( ++Counter > NodeMax ) return -1; } // count the number of new levels LevelNew = 1 + AIG_MAX( pNode0->Level, pNode1->Level ); if ( pAnd ) { if ( Aig_Regular(pAnd) == Aig_ManConst1(pAig) ) LevelNew = 0; else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd0) ) LevelNew = (int)Aig_Regular(pAnd0)->Level; else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd1) ) LevelNew = (int)Aig_Regular(pAnd1)->Level; LevelOld = (int)Aig_Regular(pAnd)->Level; // assert( LevelNew == LevelOld ); } if ( LevelNew > LevelMax ) return -1; pNode->pFunc = pAnd; pNode->Level = LevelNew; /* printf( "Checking " ); Ref_ObjPrint( pAnd0 ); printf( " and " ); Ref_ObjPrint( pAnd1 ); printf( " Result " ); Ref_ObjPrint( pNode->pFunc ); printf( "\n" ); */ }
/**Function************************************************************* Synopsis [Transforms sequential AIG into dual-rail miter.] Description [Transforms sequential AIG into a miter encoding ternary problem formulated as follows "none of the POs has a ternary value". Interprets the first nDualPis as having ternary value. Sets flops to have ternary intial value when fDualFfs is set to 1.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupDual( Aig_Man_t * pAig, Vec_Int_t * vDcFlops, int nDualPis, int fDualFfs, int fMiterFfs, int fComplPo, int fCheckZero, int fCheckOne ) { Vec_Ptr_t * vCopies; Aig_Man_t * pAigNew; Aig_Obj_t * pObj, * pTemp0, * pTemp1, * pTemp2, * pTemp3, * pCare, * pMiter; int i; assert( Saig_ManPoNum(pAig) > 0 ); assert( nDualPis >= 0 && nDualPis <= Saig_ManPiNum(pAig) ); assert( vDcFlops == NULL || Vec_IntSize(vDcFlops) == Aig_ManRegNum(pAig) ); vCopies = Vec_PtrStart( 2*Aig_ManObjNum(pAig) ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Saig_ObjSetDual( vCopies, 0, 0, Aig_ManConst0(pAigNew) ); Saig_ObjSetDual( vCopies, 0, 1, Aig_ManConst1(pAigNew) ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) { if ( i < nDualPis ) { pTemp0 = Aig_ObjCreateCi( pAigNew ); pTemp1 = Aig_ObjCreateCi( pAigNew ); } else if ( i < Saig_ManPiNum(pAig) ) { pTemp1 = Aig_ObjCreateCi( pAigNew ); pTemp0 = Aig_Not( pTemp1 ); } else { pTemp0 = Aig_ObjCreateCi( pAigNew ); pTemp1 = Aig_ObjCreateCi( pAigNew ); if ( vDcFlops ) pTemp0 = Aig_NotCond( pTemp0, !Vec_IntEntry(vDcFlops, i-Saig_ManPiNum(pAig)) ); else pTemp0 = Aig_NotCond( pTemp0, !fDualFfs ); } Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 0, Aig_And(pAigNew, pTemp0, Aig_Not(pTemp1)) ); Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 1, Aig_And(pAigNew, pTemp1, Aig_Not(pTemp0)) ); } // create internal nodes Aig_ManForEachNode( pAig, pObj, i ) { Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); Saig_ObjDualFanin( pAigNew, vCopies, pObj, 1, &pTemp2, &pTemp3 ); Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 0, Aig_Or (pAigNew, pTemp0, pTemp2) ); Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 1, Aig_And(pAigNew, pTemp1, pTemp3) ); }
/**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 [Duplicates while ORing the POs of sequential circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManCreateEquivMiter( Aig_Man_t * pAig, Vec_Int_t * vPairs ) { Aig_Man_t * pAigNew; Aig_Obj_t * pObj, * pObj2, * pMiter; int i; if ( pAig->nConstrs > 0 ) { printf( "The AIG manager should have no constraints.\n" ); return NULL; } // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Aig_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachPi( pAig, pObj, i ) pObj->pData = Aig_ObjCreatePi( pAigNew ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create POs assert( Vec_IntSize(vPairs) % 2 == 0 ); Aig_ManForEachNodeVec( pAig, vPairs, pObj, i ) { pObj2 = Aig_ManObj( pAig, Vec_IntEntry(vPairs, ++i) ); pMiter = Aig_Exor( pAigNew, (Aig_Obj_t *)pObj->pData, (Aig_Obj_t *)pObj2->pData ); pMiter = Aig_NotCond( pMiter, pObj->fPhase ^ pObj2->fPhase ); Aig_ObjCreatePo( pAigNew, pMiter ); }
Aig_Obj_t *readLiveSignal_k( Aig_Man_t *pAig, int liveIndex_k ) { Aig_Obj_t *pObj; pObj = Aig_ManCo( pAig, liveIndex_k ); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); }
/**Function************************************************************* Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult ) { assert( s_pCuddMan != NULL ); if ( st_is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) ) return; pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) ); st_insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode ); }
/**Function************************************************************* Synopsis [Adds relevant constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Abc_NtkConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pMan ) { Aig_Obj_t * pObj0, * pObj1; if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) ) return (Aig_Obj_t *)pObj->pData; Aig_ObjSetTravIdCurrent( pCare, pObj ); if ( Aig_ObjIsPi(pObj) ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj0 = Abc_NtkConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pMan ); if ( pObj0 == NULL ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj1 = Abc_NtkConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pMan ); if ( pObj1 == NULL ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) ); pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pMan, pObj0, pObj1 )); }
/**Function************************************************************* Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Aig_Obj_t * Cudd2_GetArg( void * pArg ) { Aig_Obj_t * pNode; assert( s_pCuddMan != NULL ); if ( !st_lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) ) { printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" ); return NULL; } return Aig_NotCond( pNode, Aig_IsComplement(pArg) ); }
/**Function************************************************************* Synopsis [Returns 1 if the cone of the node overlaps with the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDeriveNewCone( Aig_Man_t * p, Vec_Ptr_t * vImplics, Aig_Obj_t * pNode ) { Aig_Obj_t * pTemp; int i; assert( !Aig_IsComplement(pNode) ); assert( !Aig_ObjIsConst1(pNode) ); Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vImplics, pTemp, i ) { Aig_ObjSetTravIdCurrent( p, Aig_Regular(pTemp) ); Aig_Regular(pTemp)->pData = Aig_NotCond( Aig_ManConst1(p), Aig_IsComplement(pTemp) ); }
Aig_Obj_t *readTargetPinSignal(Aig_Man_t *pAig, Abc_Ntk_t *pNtk) { Aig_Obj_t *pObj; int i; Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "0Liveness_" ) != NULL ) { //return Aig_ObjFanin0(pObj); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } } return NULL; }
Aig_Obj_t *readTargetPoutSignal(Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int nonFirstIteration) { Aig_Obj_t *pObj; int i; if( nonFirstIteration == 0 ) return NULL; else Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "kLiveness_" ) != NULL ) { //return Aig_ObjFanin0(pObj); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } } return NULL; }
/**Function************************************************************* Synopsis [Creates AIG for the window with constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Abc_NtkConstructAig( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Aig_Man_t * pMan; Abc_Obj_t * pFanin; Aig_Obj_t * pObjAig, * pPi, * pPo; Vec_Int_t * vOuts; int i, k, iOut; // start the new manager pMan = Aig_ManStart( 1000 ); // construct the root node's AIG cone pObjAig = Abc_NtkConstructAig_rec( p, pNode, pMan ); // assert( Aig_ManConst1(pMan) == pObjAig ); Aig_ObjCreatePo( pMan, pObjAig ); if ( p->pCare ) { // mark the care set Aig_ManIncrementTravId( p->pCare ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i ) { pPi = Aig_ManPi( p->pCare, (int)(ABC_PTRUINT_T)pFanin->pData ); Aig_ObjSetTravIdCurrent( p->pCare, pPi ); pPi->pData = pFanin->pCopy; } // construct the constraints Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i ) { vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vSuppsInv, (int)(ABC_PTRUINT_T)pFanin->pData ); Vec_IntForEachEntry( vOuts, iOut, k ) { pPo = Aig_ManPo( p->pCare, iOut ); if ( Aig_ObjIsTravIdCurrent( p->pCare, pPo ) ) continue; Aig_ObjSetTravIdCurrent( p->pCare, pPo ); if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) ) continue; pObjAig = Abc_NtkConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan ); if ( pObjAig == NULL ) continue; pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); Aig_ObjCreatePo( pMan, pObjAig ); } }
static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; }
/**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; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) { Dar_Man_t * p; ProgressBar * pProgress; Dar_Cut_t * pCut; Aig_Obj_t * pObj, * pObjNew; int i, k, nNodesOld, nNodeBefore, nNodeAfter, Required; int clk = 0, clkStart; // prepare the library Dar_LibPrepare( pPars->nSubgMax ); // create rewriting manager p = Dar_ManStart( pAig, pPars ); // 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 = clock(); p->nNodesInit = Aig_ManNodeNum(pAig); nNodesOld = Vec_PtrSize( pAig->vObjs ); pProgress = Extra_ProgressBarStart( stdout, nNodesOld ); Aig_ManForEachObj( pAig, pObj, i ) // pProgress = Extra_ProgressBarStart( stdout, 100 ); // Aig_ManOrderStart( pAig ); // Aig_ManForEachNodeInOrder( pAig, pObj ) { // Extra_ProgressBarUpdate( pProgress, 100*pAig->nAndPrev/pAig->nAndTotal, NULL ); Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( !Aig_ObjIsNode(pObj) ) continue; if ( i > nNodesOld ) break; // 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 = clock(); Dar_ObjComputeCuts_rec( p, pObj ); p->timeCuts += 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, 1, p->pPars->fUpdateLevel ); continue; } // evaluate the cuts p->GainBest = -1; Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : AIG_INFINITY; Dar_ObjForEachCut( pObj, pCut, k ) Dar_LibEval( p, pObj, pCut, Required ); // check the best gain if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) { // Aig_ObjOrderAdvance( pAig ); continue; } // 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, 1, 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; }
static inline Aig_Obj_t * Gia_ObjChild1Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Aig_NotCond( ppNodes[Gia_ObjFaninId1(pObj, Id)], Gia_ObjFaninC1(pObj) ); }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs one retiming step forward.] Description [Returns the pointer to the register output after retiming.] SideEffects [Remember to run Aig_ManSetCioIds() in advance.] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ManRetimeNodeFwd( Aig_Man_t * p, Aig_Obj_t * pObj, int fMakeBug ) { Aig_Obj_t * pFanin0, * pFanin1; Aig_Obj_t * pInput0, * pInput1; Aig_Obj_t * pObjNew, * pObjLi, * pObjLo; int fCompl; assert( Saig_ManRegNum(p) > 0 ); assert( Aig_ObjIsNode(pObj) ); // get the fanins pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); // skip of they are not primary inputs if ( !Aig_ObjIsCi(pFanin0) || !Aig_ObjIsCi(pFanin1) ) return NULL; // skip of they are not register outputs if ( !Saig_ObjIsLo(p, pFanin0) || !Saig_ObjIsLo(p, pFanin1) ) return NULL; assert( Aig_ObjCioId(pFanin0) > 0 ); assert( Aig_ObjCioId(pFanin1) > 0 ); // skip latch guns if ( !Aig_ObjIsTravIdCurrent(p, pFanin0) && !Aig_ObjIsTravIdCurrent(p, pFanin1) ) return NULL; // get the inputs of these registers pInput0 = Saig_ManLi( p, Aig_ObjCioId(pFanin0) - Saig_ManPiNum(p) ); pInput1 = Saig_ManLi( p, Aig_ObjCioId(pFanin1) - Saig_ManPiNum(p) ); pInput0 = Aig_ObjChild0( pInput0 ); pInput1 = Aig_ObjChild0( pInput1 ); pInput0 = Aig_NotCond( pInput0, Aig_ObjFaninC0(pObj) ); pInput1 = Aig_NotCond( pInput1, Aig_ObjFaninC1(pObj) ); // get the condition when the register should be complemetned fCompl = Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj); if ( fMakeBug ) { printf( "Introducing bug during retiming.\n" ); pInput1 = Aig_Not( pInput1 ); } // create new node pObjNew = Aig_And( p, pInput0, pInput1 ); // create new register input pObjLi = Aig_ObjCreateCo( p, Aig_NotCond(pObjNew, fCompl) ); pObjLi->CioId = Aig_ManCoNum(p) - 1; // create new register output pObjLo = Aig_ObjCreateCi( p ); pObjLo->CioId = Aig_ManCiNum(p) - 1; p->nRegs++; // make sure the register is retimable. Aig_ObjSetTravIdCurrent(p, pObjLo); //printf( "Reg = %4d. Reg = %4d. Compl = %d. Phase = %d.\n", // pFanin0->PioNum, pFanin1->PioNum, Aig_IsComplement(pObjNew), fCompl ); // return register output return Aig_NotCond( pObjLo, fCompl ); }