/**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