/**CFile**************************************************************** FileName [darCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Core of the rewriting package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // iterator over the nodes in the topological order #define Aig_ManForEachNodeInOrder( p, pObj ) \ for ( assert(p->pOrderData), p->iPrev = 0, p->iNext = p->pOrderData[1]; \ p->iNext && (((pObj) = Aig_ManObj(p, p->iNext)), 1); \ p->iNext = p->pOrderData[2*p->iPrev+1] ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the structure with default assignment of parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ) { memset( pPars, 0, sizeof(Dar_RwrPar_t) ); pPars->nCutsMax = 8; // 8 pPars->nSubgMax = 5; // 5 is a "magic number" pPars->fFanout = 1; pPars->fUpdateLevel = 0; pPars->fUseZeros = 0; pPars->fPower = 0; pPars->fRecycle = 1; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } #define MAX_VAL 10 /**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; } // Aig_ManOrderStop( pAig ); /* printf( "Distribution of gain (row) by MFFC size (column) %s 0-costs:\n", p->pPars->fUseZeros? "with":"without" ); for ( k = 0; k <= MAX_VAL; k++ ) printf( "<%4d> ", k ); printf( "\n" ); for ( i = 0; i <= MAX_VAL; i++ ) { for ( k = 0; k <= MAX_VAL; k++ ) printf( "%6d ", nMffcGains[i][k] ); printf( "\n" ); } */ p->timeTotal = Abc_Clock() - clkStart; p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; // Bar_ProgressStop( pProgress ); Dar_ManCutsFree( p ); // put the nodes into the DFS order and reassign their IDs // Aig_NtkReassignIds( p ); // fix the levels // Aig_ManVerifyLevel( pAig ); if ( p->pPars->fFanout ) Aig_ManFanoutStop( pAig ); if ( p->pPars->fUpdateLevel ) { // Aig_ManVerifyReverseLevel( pAig ); Aig_ManStopReverseLevels( pAig ); } if ( pAig->vProbs ) { Vec_IntFree( pAig->vProbs ); pAig->vProbs = NULL; } // stop the rewriting manager Dar_ManStop( p ); Aig_ManCheckPhase( pAig ); // check if ( !Aig_ManCheck( pAig ) ) { printf( "Aig_ManRewrite: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Computes the total number of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ManCutCount( Aig_Man_t * pAig, int * pnCutsK ) { Dar_Cut_t * pCut; Aig_Obj_t * pObj; int i, k, nCuts = 0, nCutsK = 0; Aig_ManForEachNode( pAig, pObj, i ) Dar_ObjForEachCut( pObj, pCut, k ) { nCuts++; if ( pCut->nLeaves == 4 ) nCutsK++; } if ( pnCutsK ) *pnCutsK = nCutsK; return nCuts; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax, int fSkipTtMin, int fVerbose ) { Dar_Man_t * p; Dar_RwrPar_t Pars, * pPars = &Pars; Aig_Obj_t * pObj; Aig_MmFixed_t * pMemCuts; int i, nNodes; abctime clk = Abc_Clock(); // remove dangling nodes if ( (nNodes = Aig_ManCleanup( pAig )) ) { // printf( "Removing %d nodes.\n", nNodes ); } // create default parameters Dar_ManDefaultRwrParams( pPars ); pPars->nCutsMax = nCutsMax; // create rewriting manager p = Dar_ManStart( pAig, pPars ); // set elementary cuts for the PIs // Dar_ManCutsStart( p ); Aig_MmFixedRestart( p->pMemCuts ); Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); Aig_ManForEachCi( pAig, pObj, i ) Dar_ObjPrepareCuts( p, pObj ); // compute cuts for each nodes in the topological order Aig_ManForEachNode( pAig, pObj, i ) Dar_ObjComputeCuts( p, pObj, fSkipTtMin ); // print verbose stats if ( fVerbose ) { // Aig_Obj_t * pObj; int nCuts, nCutsK;//, i; nCuts = Dar_ManCutCount( pAig, &nCutsK ); printf( "Nodes = %6d. Total cuts = %6d. 4-input cuts = %6d.\n", Aig_ManObjNum(pAig), nCuts, nCutsK ); printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f MB ", (int)sizeof(Dar_Cut_t), (int)4, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); ABC_PRT( "Runtime", Abc_Clock() - clk ); /* Aig_ManForEachNode( pAig, pObj, i ) if ( i % 300 == 0 ) Dar_ObjCutPrint( pAig, pObj ); */ } // free the cuts pMemCuts = p->pMemCuts; p->pMemCuts = NULL; // Dar_ManCutsFree( p ); // stop the rewriting manager Dar_ManStop( p ); return pMemCuts; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END