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