blob: c230787db823e1c21c209720cf6c7d1b4da12b27 [file] [log] [blame]
/**CFile****************************************************************
FileName [nwkDfs.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Logic network representation.]
Synopsis [DFS traversals.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: nwkDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "nwk.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Verifies that the objects are in a topo order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk )
{
Nwk_Obj_t * pObj, * pNext;
int i, k, iBox, iTerm1, nTerms;
Nwk_ManIncrementTravId( pNtk );
Nwk_ManForEachObj( pNtk, pObj, i )
{
if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) )
{
Nwk_ObjForEachFanin( pObj, pNext, k )
{
if ( !Nwk_ObjIsTravIdCurrent(pNext) )
{
printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id );
return 0;
}
}
}
else if ( Nwk_ObjIsCi(pObj) )
{
if ( pNtk->pManTime )
{
iBox = Tim_ManBoxForCi( pNtk->pManTime, pObj->PioId );
if ( iBox >= 0 ) // this is not a true PI
{
iTerm1 = Tim_ManBoxInputFirst( pNtk->pManTime, iBox );
nTerms = Tim_ManBoxInputNum( pNtk->pManTime, iBox );
for ( k = 0; k < nTerms; k++ )
{
pNext = Nwk_ManCo( pNtk, iTerm1 + k );
if ( !Nwk_ObjIsTravIdCurrent(pNext) )
{
printf( "Box %d has input %d that is not in a topological order.\n", iBox, pNext->Id );
return 0;
}
}
}
}
}
else
assert( 0 );
Nwk_ObjSetTravIdCurrent( pObj );
}
return 1;
}
/**Function*************************************************************
Synopsis [Computes the number of logic levels not counting PIs/POs.]
Description [Assumes that white boxes have unit level.]
SideEffects []
SeeAlso []
***********************************************************************/
int Nwk_ManLevelBackup( Nwk_Man_t * pNtk )
{
Tim_Man_t * pManTimeUnit;
Nwk_Obj_t * pObj, * pFanin;
int i, k, LevelMax, Level;
assert( Nwk_ManVerifyTopoOrder(pNtk) );
// clean the levels
Nwk_ManForEachObj( pNtk, pObj, i )
Nwk_ObjSetLevel( pObj, 0 );
// perform level computation
LevelMax = 0;
pManTimeUnit = pNtk->pManTime ? Tim_ManDup( pNtk->pManTime, 1 ) : NULL;
if ( pManTimeUnit )
Tim_ManIncrementTravId( pManTimeUnit );
Nwk_ManForEachObj( pNtk, pObj, i )
{
if ( Nwk_ObjIsCi(pObj) )
{
Level = pManTimeUnit? (int)Tim_ManGetCiArrival( pManTimeUnit, pObj->PioId ) : 0;
Nwk_ObjSetLevel( pObj, Level );
}
else if ( Nwk_ObjIsCo(pObj) )
{
Level = Nwk_ObjLevel( Nwk_ObjFanin0(pObj) );
if ( pManTimeUnit )
Tim_ManSetCoArrival( pManTimeUnit, pObj->PioId, (float)Level );
Nwk_ObjSetLevel( pObj, Level );
if ( LevelMax < Nwk_ObjLevel(pObj) )
LevelMax = Nwk_ObjLevel(pObj);
}
else if ( Nwk_ObjIsNode(pObj) )
{
Level = 0;
Nwk_ObjForEachFanin( pObj, pFanin, k )
if ( Level < Nwk_ObjLevel(pFanin) )
Level = Nwk_ObjLevel(pFanin);
Nwk_ObjSetLevel( pObj, Level + 1 );
}
else
assert( 0 );
}
// set the old timing manager
if ( pManTimeUnit )
Tim_ManStop( pManTimeUnit );
return LevelMax;
}
/**Function*************************************************************
Synopsis [Computes the number of logic levels not counting PIs/POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManLevel_rec( Nwk_Obj_t * pObj )
{
Tim_Man_t * pManTime = pObj->pMan->pManTime;
Nwk_Obj_t * pNext;
int i, iBox, iTerm1, nTerms, LevelMax = 0;
if ( Nwk_ObjIsTravIdCurrent( pObj ) )
return;
Nwk_ObjSetTravIdCurrent( pObj );
if ( Nwk_ObjIsCi(pObj) )
{
if ( pManTime )
{
iBox = Tim_ManBoxForCi( pManTime, pObj->PioId );
if ( iBox >= 0 ) // this is not a true PI
{
iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox );
nTerms = Tim_ManBoxInputNum( pManTime, iBox );
for ( i = 0; i < nTerms; i++ )
{
pNext = Nwk_ManCo(pObj->pMan, iTerm1 + i);
Nwk_ManLevel_rec( pNext );
if ( LevelMax < Nwk_ObjLevel(pNext) )
LevelMax = Nwk_ObjLevel(pNext);
}
LevelMax++;
}
}
}
else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) )
{
Nwk_ObjForEachFanin( pObj, pNext, i )
{
Nwk_ManLevel_rec( pNext );
if ( LevelMax < Nwk_ObjLevel(pNext) )
LevelMax = Nwk_ObjLevel(pNext);
}
if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0 )
LevelMax++;
}
else
assert( 0 );
Nwk_ObjSetLevel( pObj, LevelMax );
}
/**Function*************************************************************
Synopsis [Computes the number of logic levels not counting PIs/POs.]
Description [Does not assume that the objects are in a topo order.]
SideEffects []
SeeAlso []
***********************************************************************/
int Nwk_ManLevel( Nwk_Man_t * pNtk )
{
Nwk_Obj_t * pObj;
int i, LevelMax = 0;
Nwk_ManForEachObj( pNtk, pObj, i )
Nwk_ObjSetLevel( pObj, 0 );
Nwk_ManIncrementTravId( pNtk );
Nwk_ManForEachPo( pNtk, pObj, i )
{
Nwk_ManLevel_rec( pObj );
if ( LevelMax < Nwk_ObjLevel(pObj) )
LevelMax = Nwk_ObjLevel(pObj);
}
Nwk_ManForEachCi( pNtk, pObj, i )
{
Nwk_ManLevel_rec( pObj );
if ( LevelMax < Nwk_ObjLevel(pObj) )
LevelMax = Nwk_ObjLevel(pObj);
}
return LevelMax;
}
/**Function*************************************************************
Synopsis [Computes the number of logic levels not counting PIs/POs.]
Description [Does not assume that the objects are in a topo order.]
SideEffects []
SeeAlso []
***********************************************************************/
int Nwk_ManLevelMax( Nwk_Man_t * pNtk )
{
Nwk_Obj_t * pObj;
int i, LevelMax = 0;
Nwk_ManForEachPo( pNtk, pObj, i )
if ( LevelMax < Nwk_ObjLevel(pObj) )
LevelMax = Nwk_ObjLevel(pObj);
return LevelMax;
}
/**Function*************************************************************
Synopsis [Returns the array of objects in the AIG manager ordered by level.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Vec_t * Nwk_ManLevelize( Nwk_Man_t * pNtk )
{
Nwk_Obj_t * pObj;
Vec_Vec_t * vLevels;
int nLevels, i;
assert( Nwk_ManVerifyLevel(pNtk) );
nLevels = Nwk_ManLevelMax( pNtk );
vLevels = Vec_VecStart( nLevels + 1 );
Nwk_ManForEachNode( pNtk, pObj, i )
{
assert( Nwk_ObjLevel(pObj) <= nLevels );
Vec_VecPush( vLevels, Nwk_ObjLevel(pObj), pObj );
}
return vLevels;
}
/**Function*************************************************************
Synopsis [Performs DFS for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManDfs_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes )
{
Nwk_Obj_t * pNext;
int i;
if ( Nwk_ObjIsTravIdCurrent( pObj ) )
return;
Nwk_ObjSetTravIdCurrent( pObj );
Nwk_ObjForEachFanin( pObj, pNext, i )
Nwk_ManDfs_rec( pNext, vNodes );
Vec_PtrPush( vNodes, pObj );
}
/**Function*************************************************************
Synopsis [Returns the DFS ordered array of all objects except latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Nwk_ManDfs( Nwk_Man_t * pNtk )
{
Vec_Ptr_t * vNodes;
Nwk_Obj_t * pObj;
int i;
Nwk_ManIncrementTravId( pNtk );
vNodes = Vec_PtrAlloc( 100 );
Nwk_ManForEachObj( pNtk, pObj, i )
{
if ( Nwk_ObjIsCi(pObj) )
{
Nwk_ObjSetTravIdCurrent( pObj );
Vec_PtrPush( vNodes, pObj );
}
else if ( Nwk_ObjIsCo(pObj) )
Nwk_ManDfs_rec( pObj, vNodes );
}
return vNodes;
}
/**Function*************************************************************
Synopsis [Performs DFS for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManDfsNodes_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes )
{
Nwk_Obj_t * pNext;
int i;
if ( Nwk_ObjIsTravIdCurrent( pObj ) )
return;
Nwk_ObjSetTravIdCurrent( pObj );
if ( Nwk_ObjIsCi(pObj) )
return;
assert( Nwk_ObjIsNode(pObj) );
Nwk_ObjForEachFanin( pObj, pNext, i )
Nwk_ManDfsNodes_rec( pNext, vNodes );
Vec_PtrPush( vNodes, pObj );
}
/**Function*************************************************************
Synopsis [Returns the set of internal nodes rooted in the given nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes )
{
Vec_Ptr_t * vNodes;
int i;
// set the traversal ID
Nwk_ManIncrementTravId( pNtk );
// start the array of nodes
vNodes = Vec_PtrAlloc( 100 );
// go through the PO nodes and call for each of them
for ( i = 0; i < nNodes; i++ )
if ( Nwk_ObjIsCo(ppNodes[i]) )
Nwk_ManDfsNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes );
else
Nwk_ManDfsNodes_rec( ppNodes[i], vNodes );
return vNodes;
}
/**Function*************************************************************
Synopsis [Performs DFS for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManDfsReverse_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes )
{
Nwk_Obj_t * pNext;
int i, iBox, iTerm1, nTerms;
if ( Nwk_ObjIsTravIdCurrent( pObj ) )
return;
Nwk_ObjSetTravIdCurrent( pObj );
if ( Nwk_ObjIsCo(pObj) )
{
if ( pObj->pMan->pManTime )
{
iBox = Tim_ManBoxForCo( pObj->pMan->pManTime, pObj->PioId );
if ( iBox >= 0 ) // this is not a true PO
{
iTerm1 = Tim_ManBoxOutputFirst( pObj->pMan->pManTime, iBox );
nTerms = Tim_ManBoxOutputNum( pObj->pMan->pManTime, iBox );
for ( i = 0; i < nTerms; i++ )
{
pNext = Nwk_ManCi(pObj->pMan, iTerm1 + i);
Nwk_ManDfsReverse_rec( pNext, vNodes );
}
}
}
}
else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) )
{
Nwk_ObjForEachFanout( pObj, pNext, i )
Nwk_ManDfsReverse_rec( pNext, vNodes );
}
else
assert( 0 );
Vec_PtrPush( vNodes, pObj );
}
/**Function*************************************************************
Synopsis [Returns the DFS ordered array of all objects except latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Nwk_ManDfsReverse( Nwk_Man_t * pNtk )
{
Vec_Ptr_t * vNodes;
Nwk_Obj_t * pObj;
int i;
Nwk_ManIncrementTravId( pNtk );
vNodes = Vec_PtrAlloc( 100 );
Nwk_ManForEachPi( pNtk, pObj, i )
Nwk_ManDfsReverse_rec( pObj, vNodes );
// add nodes without fanins
Nwk_ManForEachNode( pNtk, pObj, i )
if ( Nwk_ObjFaninNum(pObj) == 0 && !Nwk_ObjIsTravIdCurrent(pObj) )
Vec_PtrPush( vNodes, pObj );
return vNodes;
}
/**Function*************************************************************
Synopsis [Performs DFS for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManSupportNodes_rec( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes )
{
Nwk_Obj_t * pFanin;
int i;
// if this node is already visited, skip
if ( Nwk_ObjIsTravIdCurrent( pNode ) )
return;
// mark the node as visited
Nwk_ObjSetTravIdCurrent( pNode );
// collect the CI
if ( Nwk_ObjIsCi(pNode) )
{
Vec_PtrPush( vNodes, pNode );
return;
}
assert( Nwk_ObjIsNode( pNode ) );
// visit the transitive fanin of the node
Nwk_ObjForEachFanin( pNode, pFanin, i )
Nwk_ManSupportNodes_rec( pFanin, vNodes );
}
/**Function*************************************************************
Synopsis [Returns the set of CI nodes in the support of the given nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes )
{
Vec_Ptr_t * vNodes;
int i;
// set the traversal ID
Nwk_ManIncrementTravId( pNtk );
// start the array of nodes
vNodes = Vec_PtrAlloc( 100 );
// go through the PO nodes and call for each of them
for ( i = 0; i < nNodes; i++ )
if ( Nwk_ObjIsCo(ppNodes[i]) )
Nwk_ManSupportNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes );
else
Nwk_ManSupportNodes_rec( ppNodes[i], vNodes );
return vNodes;
}
/**Function*************************************************************
Synopsis [Computes the sum total of supports of all outputs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ManSupportSum( Nwk_Man_t * pNtk )
{
Vec_Ptr_t * vSupp;
Nwk_Obj_t * pObj;
int i, nTotalSupps = 0;
Nwk_ManForEachCo( pNtk, pObj, i )
{
vSupp = Nwk_ManSupportNodes( pNtk, &pObj, 1 );
nTotalSupps += Vec_PtrSize( vSupp );
Vec_PtrFree( vSupp );
}
printf( "Total supports = %d.\n", nTotalSupps );
}
/**Function*************************************************************
Synopsis [Dereferences the node's MFFC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Nwk_ObjDeref_rec( Nwk_Obj_t * pNode )
{
Nwk_Obj_t * pFanin;
int i, Counter = 1;
if ( Nwk_ObjIsCi(pNode) )
return 0;
Nwk_ObjForEachFanin( pNode, pFanin, i )
{
assert( pFanin->nFanouts > 0 );
if ( --pFanin->nFanouts == 0 )
Counter += Nwk_ObjDeref_rec( pFanin );
}
return Counter;
}
/**Function*************************************************************
Synopsis [References the node's MFFC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Nwk_ObjRef_rec( Nwk_Obj_t * pNode )
{
Nwk_Obj_t * pFanin;
int i, Counter = 1;
if ( Nwk_ObjIsCi(pNode) )
return 0;
Nwk_ObjForEachFanin( pNode, pFanin, i )
{
if ( pFanin->nFanouts++ == 0 )
Counter += Nwk_ObjRef_rec( pFanin );
}
return Counter;
}
/**Function*************************************************************
Synopsis [Collects the internal and boundary nodes in the derefed MFFC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Nwk_ObjMffcLabel_rec( Nwk_Obj_t * pNode, int fTopmost )
{
Nwk_Obj_t * pFanin;
int i;
// add to the new support nodes
if ( !fTopmost && (Nwk_ObjIsCi(pNode) || pNode->nFanouts > 0) )
return;
// skip visited nodes
if ( Nwk_ObjIsTravIdCurrent(pNode) )
return;
Nwk_ObjSetTravIdCurrent(pNode);
// recur on the children
Nwk_ObjForEachFanin( pNode, pFanin, i )
Nwk_ObjMffcLabel_rec( pFanin, 0 );
// collect the internal node
// printf( "%d ", pNode->Id );
}
/**Function*************************************************************
Synopsis [Collects the internal nodes of the MFFC limited by cut.]
Description []
SideEffects [Increments the trav ID and marks visited nodes.]
SeeAlso []
***********************************************************************/
int Nwk_ObjMffcLabel( Nwk_Obj_t * pNode )
{
int Count1, Count2;
// dereference the node
Count1 = Nwk_ObjDeref_rec( pNode );
// collect the nodes inside the MFFC
Nwk_ManIncrementTravId( pNode->pMan );
Nwk_ObjMffcLabel_rec( pNode, 1 );
// reference it back
Count2 = Nwk_ObjRef_rec( pNode );
assert( Count1 == Count2 );
return Count1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END