blob: b6b892a97848b34ba3a5e752cca4764fa63ad174 [file] [log] [blame]
/**CFile****************************************************************
FileName [resWin.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resynthesis package.]
Synopsis [Windowing algorithm.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - January 15, 2007.]
Revision [$Id: resWin.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "resInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates the window.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Res_Win_t * Res_WinAlloc()
{
Res_Win_t * p;
// start the manager
p = ABC_ALLOC( Res_Win_t, 1 );
memset( p, 0, sizeof(Res_Win_t) );
// set internal parameters
p->nFanoutLimit = 10;
p->nLevTfiMinus = 3;
// allocate storage
p->vRoots = Vec_PtrAlloc( 256 );
p->vLeaves = Vec_PtrAlloc( 256 );
p->vBranches = Vec_PtrAlloc( 256 );
p->vNodes = Vec_PtrAlloc( 256 );
p->vDivs = Vec_PtrAlloc( 256 );
p->vMatrix = Vec_VecStart( 128 );
return p;
}
/**Function*************************************************************
Synopsis [Frees the window.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_WinFree( Res_Win_t * p )
{
Vec_PtrFree( p->vRoots );
Vec_PtrFree( p->vLeaves );
Vec_PtrFree( p->vBranches );
Vec_PtrFree( p->vNodes );
Vec_PtrFree( p->vDivs );
Vec_VecFree( p->vMatrix );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Collect the limited TFI cone of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Res_WinCollectLeavesAndNodes( Res_Win_t * p )
{
Vec_Ptr_t * vFront;
Abc_Obj_t * pObj, * pTemp;
int i, k, m;
assert( p->nWinTfiMax > 0 );
assert( Vec_VecSize(p->vMatrix) > p->nWinTfiMax );
// start matrix with the node
Vec_VecClear( p->vMatrix );
Vec_VecPush( p->vMatrix, 0, p->pNode );
Abc_NtkIncrementTravId( p->pNode->pNtk );
Abc_NodeSetTravIdCurrent( p->pNode );
// collect the leaves (nodes pTemp such that "p->pNode->Level - pTemp->Level > p->nWinTfiMax")
Vec_PtrClear( p->vLeaves );
Vec_VecForEachLevelStartStop( p->vMatrix, vFront, i, 0, p->nWinTfiMax+1 )
{
Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pObj, k )
{
Abc_ObjForEachFanin( pObj, pTemp, m )
{
if ( Abc_NodeIsTravIdCurrent( pTemp ) )
continue;
Abc_NodeSetTravIdCurrent( pTemp );
if ( Abc_ObjIsCi(pTemp) || (int)(p->pNode->Level - pTemp->Level) > p->nWinTfiMax )
Vec_PtrPush( p->vLeaves, pTemp );
else
Vec_VecPush( p->vMatrix, p->pNode->Level - pTemp->Level, pTemp );
}
}
}
if ( Vec_PtrSize(p->vLeaves) == 0 )
return 0;
// collect the nodes in the reverse order
Vec_PtrClear( p->vNodes );
Vec_VecForEachLevelReverseStartStop( p->vMatrix, vFront, i, p->nWinTfiMax+1, 0 )
{
Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pObj, k )
Vec_PtrPush( p->vNodes, pObj );
Vec_PtrClear( vFront );
}
// get the lowest leaf level
p->nLevLeafMin = ABC_INFINITY;
Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, k )
p->nLevLeafMin = Abc_MinInt( p->nLevLeafMin, (int)pObj->Level );
// set minimum traversal level
p->nLevTravMin = Abc_MaxInt( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin );
assert( p->nLevTravMin >= 0 );
return 1;
}
/**Function*************************************************************
Synopsis [Returns 1 if the node should be a root.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Res_WinComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit )
{
Abc_Obj_t * pFanout;
int i;
// the node is the root if one of the following is true:
// (1) the node has more than fanouts than the limit
if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit )
return 1;
// (2) the node has CO fanouts
// (3) the node has fanouts above the cutoff level
Abc_ObjForEachFanout( pNode, pFanout, i )
if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Recursively collects the root candidates.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_WinComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots )
{
Abc_Obj_t * pFanout;
int i;
assert( Abc_ObjIsNode(pNode) );
if ( Abc_NodeIsTravIdCurrent(pNode) )
return;
Abc_NodeSetTravIdCurrent( pNode );
// check if the node should be the root
if ( Res_WinComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) )
Vec_PtrPush( vRoots, pNode );
else // if not, explore its fanouts
Abc_ObjForEachFanout( pNode, pFanout, i )
Res_WinComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots );
}
/**Function*************************************************************
Synopsis [Recursively collects the root candidates.]
Description [Returns 1 if the only root is this node.]
SideEffects []
SeeAlso []
***********************************************************************/
int Res_WinComputeRoots( Res_Win_t * p )
{
Vec_PtrClear( p->vRoots );
Abc_NtkIncrementTravId( p->pNode->pNtk );
Res_WinComputeRoots_rec( p->pNode, p->pNode->Level + p->nWinTfoMax, p->nFanoutLimit, p->vRoots );
assert( Vec_PtrSize(p->vRoots) > 0 );
if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Marks the paths from the roots to the leaves.]
Description [Returns 1 if the the node can reach a leaf.]
SideEffects []
SeeAlso []
***********************************************************************/
int Res_WinMarkPaths_rec( Abc_Obj_t * pNode, Abc_Obj_t * pPivot, int nLevelMin )
{
Abc_Obj_t * pFanin;
int i, RetValue;
// skip visited nodes
if ( Abc_NodeIsTravIdCurrent(pNode) )
return 1;
if ( Abc_NodeIsTravIdPrevious(pNode) )
return 0;
// assume that the node does not have access to the leaves
Abc_NodeSetTravIdPrevious( pNode );
// skip nodes below the given level
if ( pNode == pPivot || (int)pNode->Level <= nLevelMin )
return 0;
assert( Abc_ObjIsNode(pNode) );
// check if the fanins have access to the leaves
RetValue = 0;
Abc_ObjForEachFanin( pNode, pFanin, i )
RetValue |= Res_WinMarkPaths_rec( pFanin, pPivot, nLevelMin );
// relabel the node if it has access to the leaves
if ( RetValue )
Abc_NodeSetTravIdCurrent( pNode );
return RetValue;
}
/**Function*************************************************************
Synopsis [Marks the paths from the roots to the leaves.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_WinMarkPaths( Res_Win_t * p )
{
Abc_Obj_t * pObj;
int i;
// mark the leaves
Abc_NtkIncrementTravId( p->pNode->pNtk );
Abc_NtkIncrementTravId( p->pNode->pNtk );
Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
Abc_NodeSetTravIdCurrent( pObj );
// traverse from the roots and mark the nodes that can reach leaves
// the nodes that do not reach leaves have previous trav ID
// the nodes that reach leaves have current trav ID
Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
Res_WinMarkPaths_rec( pObj, p->pNode, p->nLevTravMin );
}
/**Function*************************************************************
Synopsis [Recursively collects the roots.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_WinFinalizeRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots )
{
Abc_Obj_t * pFanout;
int i;
assert( Abc_ObjIsNode(pObj) );
assert( Abc_NodeIsTravIdCurrent(pObj) );
// check if the node has all fanouts marked
Abc_ObjForEachFanout( pObj, pFanout, i )
if ( !Abc_NodeIsTravIdCurrent(pFanout) )
break;
// if some of the fanouts are unmarked, add the node to the roots
if ( i < Abc_ObjFanoutNum(pObj) )
Vec_PtrPushUnique( vRoots, pObj );
else // otherwise, call recursively
Abc_ObjForEachFanout( pObj, pFanout, i )
Res_WinFinalizeRoots_rec( pFanout, vRoots );
}
/**Function*************************************************************
Synopsis [Finalizes the roots of the window.]
Description [Roots of the window are the nodes that have at least
one fanout that it not in the TFO of the leaves.]
SideEffects []
SeeAlso []
***********************************************************************/
int Res_WinFinalizeRoots( Res_Win_t * p )
{
assert( !Abc_NodeIsTravIdCurrent(p->pNode) );
// mark the node with the old traversal ID
Abc_NodeSetTravIdCurrent( p->pNode );
// recollect the roots
Vec_PtrClear( p->vRoots );
Res_WinFinalizeRoots_rec( p->pNode, p->vRoots );
assert( Vec_PtrSize(p->vRoots) > 0 );
if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Recursively adds missing nodes and leaves.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_WinAddMissing_rec( Res_Win_t * p, Abc_Obj_t * pObj, int nLevTravMin )
{
Abc_Obj_t * pFanin;
int i;
// skip the already collected leaves, nodes, and branches
if ( Abc_NodeIsTravIdCurrent(pObj) )
return;
// if this is not an internal node - make it a new branch
if ( !Abc_NodeIsTravIdPrevious(pObj) )
{
assert( Vec_PtrFind(p->vLeaves, pObj) == -1 );
Abc_NodeSetTravIdCurrent( pObj );
Vec_PtrPush( p->vBranches, pObj );
return;
}
assert( Abc_ObjIsNode(pObj) ); // if this is a CI, then the window is incorrect!
Abc_NodeSetTravIdCurrent( pObj );
// visit the fanins of the node
Abc_ObjForEachFanin( pObj, pFanin, i )
Res_WinAddMissing_rec( p, pFanin, nLevTravMin );
// collect the node
Vec_PtrPush( p->vNodes, pObj );
}
/**Function*************************************************************
Synopsis [Adds to the window nodes and leaves in the TFI of the roots.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_WinAddMissing( Res_Win_t * p )
{
Abc_Obj_t * pObj;
int i;
// mark the leaves
Abc_NtkIncrementTravId( p->pNode->pNtk );
Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i )
Abc_NodeSetTravIdCurrent( pObj );
// mark the already collected nodes
Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i )
Abc_NodeSetTravIdCurrent( pObj );
// explore from the roots
Vec_PtrClear( p->vBranches );
Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
Res_WinAddMissing_rec( p, pObj, p->nLevTravMin );
}
/**Function*************************************************************
Synopsis [Returns 1 if the window is trivial (without TFO).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Res_WinIsTrivial( Res_Win_t * p )
{
return Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode;
}
/**Function*************************************************************
Synopsis [Computes the window.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p )
{
assert( Abc_ObjIsNode(pNode) );
assert( nWinTfiMax > 0 && nWinTfiMax < 10 );
assert( nWinTfoMax >= 0 && nWinTfoMax < 10 );
// initialize the window
p->pNode = pNode;
p->nWinTfiMax = nWinTfiMax;
p->nWinTfoMax = nWinTfoMax;
Vec_PtrClear( p->vBranches );
Vec_PtrClear( p->vDivs );
Vec_PtrClear( p->vRoots );
Vec_PtrPush( p->vRoots, pNode );
// compute the leaves
if ( !Res_WinCollectLeavesAndNodes( p ) )
return 0;
// compute the candidate roots
if ( p->nWinTfoMax > 0 && Res_WinComputeRoots(p) )
{
// mark the paths from the roots to the leaves
Res_WinMarkPaths( p );
// refine the roots and add branches and missing nodes
if ( Res_WinFinalizeRoots( p ) )
Res_WinAddMissing( p );
}
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END