blob: d50bc40cfcdd455d431554a6b763e1b8ba74c84e [file] [log] [blame]
/**CFile****************************************************************
FileName [ifExpand.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [FPGA mapping based on priority cuts.]
Synopsis [Incremental improvement of current mapping.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 21, 2006.]
Revision [$Id: ifExpand.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
***********************************************************************/
#include "if.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void If_ManImproveExpand( If_Man_t * p, int nLimit );
static void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited );
static void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited );
static void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront );
static void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Improves current mapping using expand/Expand of one cut.]
Description [Assumes current mapping assigned and required times computed.]
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManImproveMapping( If_Man_t * p )
{
abctime clk;
clk = Abc_Clock();
If_ManImproveExpand( p, p->pPars->nLutSize );
If_ManComputeRequired( p );
if ( p->pPars->fVerbose )
{
Abc_Print( 1, "E: Del = %7.2f. Ar = %9.1f. Edge = %8d. ",
p->RequiredGlo, p->AreaGlo, p->nNets );
if ( p->dPower )
Abc_Print( 1, "Switch = %7.2f. ", p->dPower );
Abc_Print( 1, "Cut = %8d. ", p->nCutsMerged );
Abc_PrintTime( 1, "T", Abc_Clock() - clk );
}
}
/**Function*************************************************************
Synopsis [Performs area recovery for each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManImproveExpand( If_Man_t * p, int nLimit )
{
Vec_Ptr_t * vFront, * vFrontOld, * vVisited;
If_Obj_t * pObj;
int i;
vFront = Vec_PtrAlloc( nLimit );
vFrontOld = Vec_PtrAlloc( nLimit );
vVisited = Vec_PtrAlloc( 100 );
// iterate through all nodes in the topological order
If_ManForEachNode( p, pObj, i )
If_ManImproveNodeExpand( p, pObj, nLimit, vFront, vFrontOld, vVisited );
Vec_PtrFree( vFront );
Vec_PtrFree( vFrontOld );
Vec_PtrFree( vVisited );
}
/**Function*************************************************************
Synopsis [Counts the number of nodes with no external fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManImproveCutCost( If_Man_t * p, Vec_Ptr_t * vFront )
{
If_Obj_t * pFanin;
int i, Counter = 0;
Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
if ( pFanin->nRefs == 0 )
Counter++;
return Counter;
}
/**Function*************************************************************
Synopsis [Performs area recovery for each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited )
{
If_Obj_t * pFanin;
If_Cut_t * pCut;
int CostBef, CostAft, i;
float DelayOld, AreaBef, AreaAft;
pCut = If_ObjCutBest(pObj);
pCut->Delay = If_CutDelay( p, pObj, pCut );
assert( pCut->Delay <= pObj->Required + p->fEpsilon );
if ( pObj->nRefs == 0 )
return;
// get the delay
DelayOld = pCut->Delay;
// get the area
AreaBef = If_CutAreaRefed( p, pCut );
// if ( AreaBef == 1 )
// return;
// the cut is non-trivial
If_ManImproveNodePrepare( p, pObj, nLimit, vFront, vFrontOld, vVisited );
// iteratively modify the cut
If_CutAreaDeref( p, pCut );
CostBef = If_ManImproveCutCost( p, vFront );
If_ManImproveNodeFaninCompact( p, pObj, nLimit, vFront, vVisited );
CostAft = If_ManImproveCutCost( p, vFront );
If_CutAreaRef( p, pCut );
assert( CostBef >= CostAft );
// clean up
Vec_PtrForEachEntry( If_Obj_t *, vVisited, pFanin, i )
pFanin->fMark = 0;
// update the node
If_ManImproveNodeUpdate( p, pObj, vFront );
pCut->Delay = If_CutDelay( p, pObj, pCut );
// get the new area
AreaAft = If_CutAreaRefed( p, pCut );
if ( AreaAft > AreaBef || pCut->Delay > pObj->Required + p->fEpsilon )
{
If_ManImproveNodeUpdate( p, pObj, vFrontOld );
AreaAft = If_CutAreaRefed( p, pCut );
assert( AreaAft == AreaBef );
pCut->Delay = DelayOld;
}
}
/**Function*************************************************************
Synopsis [Performs area recovery for each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManImproveMark_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vVisited )
{
if ( pObj->fMark )
return;
assert( If_ObjIsAnd(pObj) );
If_ManImproveMark_rec( p, If_ObjFanin0(pObj), vVisited );
If_ManImproveMark_rec( p, If_ObjFanin1(pObj), vVisited );
Vec_PtrPush( vVisited, pObj );
pObj->fMark = 1;
}
/**Function*************************************************************
Synopsis [Prepares node mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited )
{
If_Cut_t * pCut;
If_Obj_t * pLeaf;
int i;
Vec_PtrClear( vFront );
Vec_PtrClear( vFrontOld );
Vec_PtrClear( vVisited );
// expand the cut downwards from the given place
pCut = If_ObjCutBest(pObj);
If_CutForEachLeaf( p, pCut, pLeaf, i )
{
Vec_PtrPush( vFront, pLeaf );
Vec_PtrPush( vFrontOld, pLeaf );
Vec_PtrPush( vVisited, pLeaf );
pLeaf->fMark = 1;
}
// mark the nodes in the cone
If_ManImproveMark_rec( p, pObj, vVisited );
}
/**Function*************************************************************
Synopsis [Updates the frontier.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront )
{
If_Cut_t * pCut;
If_Obj_t * pFanin;
int i;
pCut = If_ObjCutBest(pObj);
// deref node's cut
If_CutAreaDeref( p, pCut );
// update the node's cut
pCut->nLeaves = Vec_PtrSize(vFront);
Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
pCut->pLeaves[i] = pFanin->Id;
If_CutOrder( pCut );
pCut->uSign = If_ObjCutSignCompute(pCut);
// ref the new cut
If_CutAreaRef( p, pCut );
}
/**Function*************************************************************
Synopsis [Returns 1 if the number of fanins will grow.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManImproveNodeWillGrow( If_Man_t * p, If_Obj_t * pObj )
{
If_Obj_t * pFanin0, * pFanin1;
assert( If_ObjIsAnd(pObj) );
pFanin0 = If_ObjFanin0(pObj);
pFanin1 = If_ObjFanin1(pObj);
return !pFanin0->fMark && !pFanin1->fMark;
}
/**Function*************************************************************
Synopsis [Returns the increase in the number of fanins with no external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManImproveNodeFaninCost( If_Man_t * p, If_Obj_t * pObj )
{
int Counter = 0;
assert( If_ObjIsAnd(pObj) );
// check if the node has external refs
if ( pObj->nRefs == 0 )
Counter--;
// increment the number of fanins without external refs
if ( !If_ObjFanin0(pObj)->fMark && If_ObjFanin0(pObj)->nRefs == 0 )
Counter++;
// increment the number of fanins without external refs
if ( !If_ObjFanin1(pObj)->fMark && If_ObjFanin1(pObj)->nRefs == 0 )
Counter++;
return Counter;
}
/**Function*************************************************************
Synopsis [Updates the frontier.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManImproveNodeFaninUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
{
If_Obj_t * pFanin;
assert( If_ObjIsAnd(pObj) );
Vec_PtrRemove( vFront, pObj );
pFanin = If_ObjFanin0(pObj);
if ( !pFanin->fMark )
{
Vec_PtrPush( vFront, pFanin );
Vec_PtrPush( vVisited, pFanin );
pFanin->fMark = 1;
}
pFanin = If_ObjFanin1(pObj);
if ( !pFanin->fMark )
{
Vec_PtrPush( vFront, pFanin );
Vec_PtrPush( vVisited, pFanin );
pFanin->fMark = 1;
}
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManImproveNodeFaninCompact0( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
{
If_Obj_t * pFanin;
int i;
Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
{
if ( If_ObjIsCi(pFanin) )
continue;
if ( If_ManImproveNodeWillGrow(p, pFanin) )
continue;
if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 )
{
If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManImproveNodeFaninCompact1( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
{
If_Obj_t * pFanin;
int i;
Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
{
if ( If_ObjIsCi(pFanin) )
continue;
if ( If_ManImproveNodeFaninCost(p, pFanin) < 0 )
{
If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManImproveNodeFaninCompact2( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
{
If_Obj_t * pFanin;
int i;
Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i )
{
if ( If_ObjIsCi(pFanin) )
continue;
if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 )
{
If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited );
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_ManImproveNodeFaninCompact_int( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
{
if ( If_ManImproveNodeFaninCompact0(p, pObj, nLimit, vFront, vVisited) )
return 1;
if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact1(p, pObj, nLimit, vFront, vVisited) )
return 1;
// if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact2(p, pObj, nLimit, vFront, vVisited) )
// return 1;
assert( Vec_PtrSize(vFront) <= nLimit );
return 0;
}
/**Function*************************************************************
Synopsis [Compacts the number of external refs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited )
{
while ( If_ManImproveNodeFaninCompact_int( p, pObj, nLimit, vFront, vVisited ) );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END