blob: 24e5a74194a545019858c9f2ba613ab0b0acabcb [file] [log] [blame]
/**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