| /**CFile**************************************************************** |
| |
| FileName [darRefact.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [DAG-aware AIG rewriting.] |
| |
| Synopsis [Refactoring.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - April 28, 2007.] |
| |
| Revision [$Id: darRefact.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "darInt.h" |
| #include "bool/kit/kit.h" |
| |
| #include "bool/bdc/bdc.h" |
| #include "bool/bdc/bdcInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| // the refactoring manager |
| typedef struct Ref_Man_t_ Ref_Man_t; |
| struct Ref_Man_t_ |
| { |
| // input data |
| Dar_RefPar_t * pPars; // rewriting parameters |
| Aig_Man_t * pAig; // AIG manager |
| // computed cuts |
| Vec_Vec_t * vCuts; // the storage for cuts |
| // truth table and ISOP |
| Vec_Ptr_t * vTruthElem; // elementary truth tables |
| Vec_Ptr_t * vTruthStore; // storage for truth tables |
| Vec_Int_t * vMemory; // storage for ISOP |
| Vec_Ptr_t * vCutNodes; // storage for internal nodes of the cut |
| // various data members |
| Vec_Ptr_t * vLeavesBest; // the best set of leaves |
| Kit_Graph_t * pGraphBest; // the best factored form |
| int GainBest; // the best gain |
| int LevelBest; // the level of node with the best gain |
| // bi-decomposition |
| Bdc_Par_t DecPars; // decomposition parameters |
| Bdc_Man_t * pManDec; // decomposition manager |
| // node statistics |
| int nNodesInit; // the initial number of nodes |
| int nNodesTried; // the number of nodes tried |
| int nNodesBelow; // the number of nodes below the level limit |
| int nNodesExten; // the number of nodes with extended cut |
| int nCutsUsed; // the number of rewriting steps |
| int nCutsTried; // the number of cuts tries |
| // timing statistics |
| abctime timeCuts; |
| abctime timeEval; |
| abctime timeOther; |
| abctime timeTotal; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns the structure with default assignment of parameters.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars ) |
| { |
| memset( pPars, 0, sizeof(Dar_RefPar_t) ); |
| pPars->nMffcMin = 2; // the min MFFC size for which refactoring is used |
| pPars->nLeafMax = 12; // the max number of leaves of a cut |
| pPars->nCutsMax = 5; // the max number of cuts to consider |
| pPars->fUpdateLevel = 0; |
| pPars->fUseZeros = 0; |
| pPars->fVerbose = 0; |
| pPars->fVeryVerbose = 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts the rewriting manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ref_Man_t * Dar_ManRefStart( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) |
| { |
| Ref_Man_t * p; |
| // start the manager |
| p = ABC_ALLOC( Ref_Man_t, 1 ); |
| memset( p, 0, sizeof(Ref_Man_t) ); |
| p->pAig = pAig; |
| p->pPars = pPars; |
| // other data |
| p->vCuts = Vec_VecStart( pPars->nCutsMax ); |
| p->vTruthElem = Vec_PtrAllocTruthTables( pPars->nLeafMax ); |
| p->vTruthStore = Vec_PtrAllocSimInfo( 1024, Kit_TruthWordNum(pPars->nLeafMax) ); |
| p->vMemory = Vec_IntAlloc( 1 << 16 ); |
| p->vCutNodes = Vec_PtrAlloc( 256 ); |
| p->vLeavesBest = Vec_PtrAlloc( pPars->nLeafMax ); |
| // alloc bi-decomposition manager |
| p->DecPars.nVarsMax = pPars->nLeafMax; |
| p->DecPars.fVerbose = pPars->fVerbose; |
| p->DecPars.fVeryVerbose = 0; |
| // p->pManDec = Bdc_ManAlloc( &p->DecPars ); |
| return p; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints out the statistics of the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dar_ManRefPrintStats( Ref_Man_t * p ) |
| { |
| int Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig); |
| printf( "NodesBeg = %8d. NodesEnd = %8d. Gain = %6d. (%6.2f %%).\n", |
| p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit ); |
| printf( "Tried = %6d. Below = %5d. Extended = %5d. Used = %5d. Levels = %4d.\n", |
| p->nNodesTried, p->nNodesBelow, p->nNodesExten, p->nCutsUsed, Aig_ManLevels(p->pAig) ); |
| ABC_PRT( "Cuts ", p->timeCuts ); |
| ABC_PRT( "Eval ", p->timeEval ); |
| ABC_PRT( "Other ", p->timeOther ); |
| ABC_PRT( "TOTAL ", p->timeTotal ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Stops the rewriting manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Dar_ManRefStop( Ref_Man_t * p ) |
| { |
| if ( p->pManDec ) |
| Bdc_ManFree( p->pManDec ); |
| if ( p->pPars->fVerbose ) |
| Dar_ManRefPrintStats( p ); |
| Vec_VecFree( p->vCuts ); |
| Vec_PtrFree( p->vTruthElem ); |
| Vec_PtrFree( p->vTruthStore ); |
| Vec_PtrFree( p->vLeavesBest ); |
| Vec_IntFree( p->vMemory ); |
| Vec_PtrFree( p->vCutNodes ); |
| ABC_FREE( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ref_ObjComputeCuts( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Vec_t * vCuts ) |
| { |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ref_ObjPrint( Aig_Obj_t * pObj ) |
| { |
| printf( "%d", pObj? Aig_Regular(pObj)->Id : -1 ); |
| if ( pObj ) |
| printf( "(%d) ", Aig_IsComplement(pObj) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Counts the number of new nodes added when using this graph.] |
| |
| Description [AIG nodes for the fanins should be assigned to pNode->pFunc |
| of the leaves of the graph before calling this procedure. |
| Returns -1 if the number of nodes and levels exceeded the given limit or |
| the number of levels exceeded the maximum allowed level.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dar_RefactTryGraph( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph, int NodeMax, int LevelMax ) |
| { |
| Kit_Node_t * pNode, * pNode0, * pNode1; |
| Aig_Obj_t * pAnd, * pAnd0, * pAnd1; |
| int i, Counter, LevelNew, LevelOld; |
| // check for constant function or a literal |
| if ( Kit_GraphIsConst(pGraph) || Kit_GraphIsVar(pGraph) ) |
| return 0; |
| // set the levels of the leaves |
| Kit_GraphForEachLeaf( pGraph, pNode, i ) |
| { |
| pNode->pFunc = Vec_PtrEntry(vCut, i); |
| pNode->Level = Aig_Regular((Aig_Obj_t *)pNode->pFunc)->Level; |
| assert( Aig_Regular((Aig_Obj_t *)pNode->pFunc)->Level < (1<<24)-1 ); |
| } |
| //printf( "Trying:\n" ); |
| // compute the AIG size after adding the internal nodes |
| Counter = 0; |
| 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 = (Aig_Obj_t *)pNode0->pFunc; |
| pAnd1 = (Aig_Obj_t *)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 + Abc_MaxInt( 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" ); |
| */ |
| } |
| return Counter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Obj_t * Dar_RefactBuildGraph( Aig_Man_t * pAig, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph ) |
| { |
| Aig_Obj_t * pAnd0, * pAnd1; |
| Kit_Node_t * pNode = NULL; |
| int i; |
| // check for constant function |
| if ( Kit_GraphIsConst(pGraph) ) |
| return Aig_NotCond( Aig_ManConst1(pAig), Kit_GraphIsComplement(pGraph) ); |
| // set the leaves |
| Kit_GraphForEachLeaf( pGraph, pNode, i ) |
| pNode->pFunc = Vec_PtrEntry(vCut, i); |
| // check for a literal |
| if ( Kit_GraphIsVar(pGraph) ) |
| return Aig_NotCond( (Aig_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); |
| // build the AIG nodes corresponding to the AND gates of the graph |
| //printf( "Building (current number %d):\n", Aig_ManObjNumMax(pAig) ); |
| Kit_GraphForEachNode( pGraph, pNode, i ) |
| { |
| pAnd0 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); |
| pAnd1 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); |
| pNode->pFunc = Aig_And( pAig, pAnd0, pAnd1 ); |
| /* |
| printf( "Checking " ); |
| Ref_ObjPrint( pAnd0 ); |
| printf( " and " ); |
| Ref_ObjPrint( pAnd1 ); |
| printf( " Result " ); |
| Ref_ObjPrint( pNode->pFunc ); |
| printf( "\n" ); |
| */ |
| } |
| // complement the result if necessary |
| return Aig_NotCond( (Aig_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dar_ManRefactorTryCuts( Ref_Man_t * p, Aig_Obj_t * pObj, int nNodesSaved, int Required ) |
| { |
| Vec_Ptr_t * vCut; |
| Kit_Graph_t * pGraphCur; |
| int k, RetValue, GainCur, nNodesAdded; |
| unsigned * pTruth; |
| |
| p->GainBest = -1; |
| p->pGraphBest = NULL; |
| Vec_VecForEachLevel( p->vCuts, vCut, k ) |
| { |
| if ( Vec_PtrSize(vCut) == 0 ) |
| continue; |
| // if ( Vec_PtrSize(vCut) != 0 && Vec_PtrSize(Vec_VecEntry(p->vCuts, k+1)) != 0 ) |
| // continue; |
| |
| p->nCutsTried++; |
| // get the cut nodes |
| Aig_ObjCollectCut( pObj, vCut, p->vCutNodes ); |
| // get the truth table |
| pTruth = Aig_ManCutTruth( pObj, vCut, p->vCutNodes, p->vTruthElem, p->vTruthStore ); |
| if ( Kit_TruthIsConst0(pTruth, Vec_PtrSize(vCut)) ) |
| { |
| p->GainBest = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL ); |
| p->pGraphBest = Kit_GraphCreateConst0(); |
| Vec_PtrCopy( p->vLeavesBest, vCut ); |
| return p->GainBest; |
| } |
| if ( Kit_TruthIsConst1(pTruth, Vec_PtrSize(vCut)) ) |
| { |
| p->GainBest = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL ); |
| p->pGraphBest = Kit_GraphCreateConst1(); |
| Vec_PtrCopy( p->vLeavesBest, vCut ); |
| return p->GainBest; |
| } |
| |
| // try the positive phase |
| RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 ); |
| if ( RetValue > -1 ) |
| { |
| pGraphCur = Kit_SopFactor( p->vMemory, 0, Vec_PtrSize(vCut), p->vMemory ); |
| /* |
| { |
| int RetValue; |
| RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 ); |
| printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue ); |
| } |
| */ |
| nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required ); |
| if ( nNodesAdded > -1 ) |
| { |
| GainCur = nNodesSaved - nNodesAdded; |
| if ( p->GainBest < GainCur || (p->GainBest == GainCur && |
| (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) ) |
| { |
| p->GainBest = GainCur; |
| if ( p->pGraphBest ) |
| Kit_GraphFree( p->pGraphBest ); |
| p->pGraphBest = pGraphCur; |
| Vec_PtrCopy( p->vLeavesBest, vCut ); |
| } |
| else |
| Kit_GraphFree( pGraphCur ); |
| } |
| else |
| Kit_GraphFree( pGraphCur ); |
| } |
| // try negative phase |
| Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) ); |
| RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 ); |
| // Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) ); |
| if ( RetValue > -1 ) |
| { |
| pGraphCur = Kit_SopFactor( p->vMemory, 1, Vec_PtrSize(vCut), p->vMemory ); |
| /* |
| { |
| int RetValue; |
| RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 ); |
| printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue ); |
| } |
| */ |
| nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required ); |
| if ( nNodesAdded > -1 ) |
| { |
| GainCur = nNodesSaved - nNodesAdded; |
| if ( p->GainBest < GainCur || (p->GainBest == GainCur && |
| (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) ) |
| { |
| p->GainBest = GainCur; |
| if ( p->pGraphBest ) |
| Kit_GraphFree( p->pGraphBest ); |
| p->pGraphBest = pGraphCur; |
| Vec_PtrCopy( p->vLeavesBest, vCut ); |
| } |
| else |
| Kit_GraphFree( pGraphCur ); |
| } |
| else |
| Kit_GraphFree( pGraphCur ); |
| } |
| } |
| |
| return p->GainBest; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if a non-PI node has nLevelMin or below.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dar_ObjCutLevelAchieved( Vec_Ptr_t * vCut, int nLevelMin ) |
| { |
| Aig_Obj_t * pObj; |
| int i; |
| Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) |
| if ( !Aig_ObjIsCi(pObj) && (int)pObj->Level <= nLevelMin ) |
| return 1; |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) |
| { |
| // Bar_Progress_t * pProgress; |
| Ref_Man_t * p; |
| Vec_Ptr_t * vCut, * vCut2; |
| Aig_Obj_t * pObj, * pObjNew; |
| int nNodesOld, nNodeBefore, nNodeAfter, nNodesSaved, nNodesSaved2; |
| int i, Required, nLevelMin; |
| abctime clkStart, clk; |
| |
| // start the manager |
| p = Dar_ManRefStart( pAig, pPars ); |
| // remove dangling nodes |
| Aig_ManCleanup( pAig ); |
| // if updating levels is requested, start fanout and timing |
| Aig_ManFanoutStart( pAig ); |
| if ( p->pPars->fUpdateLevel ) |
| Aig_ManStartReverseLevels( pAig, 0 ); |
| |
| // resynthesize each node once |
| clkStart = Abc_Clock(); |
| vCut = Vec_VecEntry( p->vCuts, 0 ); |
| vCut2 = Vec_VecEntry( p->vCuts, 1 ); |
| p->nNodesInit = Aig_ManNodeNum(pAig); |
| nNodesOld = Vec_PtrSize( pAig->vObjs ); |
| // pProgress = Bar_ProgressStart( stdout, nNodesOld ); |
| Aig_ManForEachObj( pAig, pObj, i ) |
| { |
| // Bar_ProgressUpdate( pProgress, i, NULL ); |
| if ( !Aig_ObjIsNode(pObj) ) |
| continue; |
| if ( i > nNodesOld ) |
| break; |
| if ( pAig->Time2Quit && !(i & 256) && Abc_Clock() > pAig->Time2Quit ) |
| break; |
| Vec_VecClear( p->vCuts ); |
| |
| //printf( "\nConsidering node %d.\n", pObj->Id ); |
| // get the bounded MFFC size |
| clk = Abc_Clock(); |
| nLevelMin = Abc_MaxInt( 0, Aig_ObjLevel(pObj) - 10 ); |
| nNodesSaved = Aig_NodeMffcSupp( pAig, pObj, nLevelMin, vCut ); |
| if ( nNodesSaved < p->pPars->nMffcMin ) // too small to consider |
| { |
| p->timeCuts += Abc_Clock() - clk; |
| continue; |
| } |
| p->nNodesTried++; |
| if ( Vec_PtrSize(vCut) > p->pPars->nLeafMax ) // get one reconv-driven cut |
| { |
| Aig_ManFindCut( pObj, vCut, p->vCutNodes, p->pPars->nLeafMax, 50 ); |
| nNodesSaved = Aig_NodeMffcLabelCut( p->pAig, pObj, vCut ); |
| } |
| else if ( Vec_PtrSize(vCut) < p->pPars->nLeafMax - 2 && p->pPars->fExtend ) |
| { |
| if ( !Dar_ObjCutLevelAchieved(vCut, nLevelMin) ) |
| { |
| if ( Aig_NodeMffcExtendCut( pAig, pObj, vCut, vCut2 ) ) |
| { |
| nNodesSaved2 = Aig_NodeMffcLabelCut( p->pAig, pObj, vCut ); |
| assert( nNodesSaved2 == nNodesSaved ); |
| } |
| if ( Vec_PtrSize(vCut2) > p->pPars->nLeafMax ) |
| Vec_PtrClear(vCut2); |
| if ( Vec_PtrSize(vCut2) > 0 ) |
| { |
| p->nNodesExten++; |
| // printf( "%d(%d) ", Vec_PtrSize(vCut), Vec_PtrSize(vCut2) ); |
| } |
| } |
| else |
| p->nNodesBelow++; |
| } |
| p->timeCuts += Abc_Clock() - clk; |
| |
| // try the cuts |
| clk = Abc_Clock(); |
| Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : ABC_INFINITY; |
| Dar_ManRefactorTryCuts( p, pObj, nNodesSaved, Required ); |
| p->timeEval += Abc_Clock() - clk; |
| |
| // check the best gain |
| if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) |
| { |
| if ( p->pGraphBest ) |
| Kit_GraphFree( p->pGraphBest ); |
| continue; |
| } |
| //printf( "\n" ); |
| |
| // if we end up here, a rewriting step is accepted |
| nNodeBefore = Aig_ManNodeNum( pAig ); |
| pObjNew = Dar_RefactBuildGraph( pAig, p->vLeavesBest, p->pGraphBest ); |
| 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 ); |
| Kit_GraphFree( p->pGraphBest ); |
| p->nCutsUsed++; |
| // break; |
| } |
| p->timeTotal = Abc_Clock() - clkStart; |
| p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; |
| |
| // Bar_ProgressStop( pProgress ); |
| // put the nodes into the DFS order and reassign their IDs |
| // Aig_NtkReassignIds( p ); |
| // fix the levels |
| Aig_ManFanoutStop( pAig ); |
| if ( p->pPars->fUpdateLevel ) |
| Aig_ManStopReverseLevels( pAig ); |
| /* |
| Aig_ManForEachObj( p->pAig, pObj, i ) |
| if ( Aig_ObjIsNode(pObj) && Aig_ObjRefs(pObj) == 0 ) |
| { |
| printf( "Unreferenced " ); |
| Aig_ObjPrintVerbose( pObj, 0 ); |
| printf( "\n" ); |
| } |
| */ |
| // remove dangling nodes (they should not be here!) |
| Aig_ManCleanup( pAig ); |
| |
| // stop the rewriting manager |
| Dar_ManRefStop( p ); |
| // Aig_ManCheckPhase( pAig ); |
| if ( !Aig_ManCheck( pAig ) ) |
| { |
| printf( "Dar_ManRefactor: The network check has failed.\n" ); |
| return 0; |
| } |
| return 1; |
| |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |