mirror of https://github.com/YosysHQ/abc.git
770 lines
25 KiB
C
770 lines
25 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [abcReconv.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Network and node package.]
|
|
|
|
Synopsis [Computation of reconvergence-driven cuts.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: abcReconv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "base/abc/abc.h"
|
|
#include "misc/extra/extraBdd.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
struct Abc_ManCut_t_
|
|
{
|
|
// user specified parameters
|
|
int nNodeSizeMax; // the limit on the size of the supernode
|
|
int nConeSizeMax; // the limit on the size of the containing cone
|
|
int nNodeFanStop; // the limit on the size of the supernode
|
|
int nConeFanStop; // the limit on the size of the containing cone
|
|
// internal parameters
|
|
Vec_Ptr_t * vNodeLeaves; // fanins of the collapsed node (the cut)
|
|
Vec_Ptr_t * vConeLeaves; // fanins of the containing cone
|
|
Vec_Ptr_t * vVisited; // the visited nodes
|
|
Vec_Vec_t * vLevels; // the data structure to compute TFO nodes
|
|
Vec_Ptr_t * vNodesTfo; // the nodes in the TFO of the cut
|
|
};
|
|
|
|
static int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit );
|
|
static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit );
|
|
static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Unmarks the TFI cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Abc_NodesMark( Vec_Ptr_t * vVisited )
|
|
{
|
|
Abc_Obj_t * pNode;
|
|
int i;
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
|
|
pNode->fMarkA = 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Unmarks the TFI cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited )
|
|
{
|
|
Abc_Obj_t * pNode;
|
|
int i;
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
|
|
pNode->fMarkA = 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Unmarks the TFI cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited )
|
|
{
|
|
Abc_Obj_t * pNode;
|
|
int i;
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
|
|
pNode->fMarkB = 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Evaluate the cost of removing the node from the set of leaves.]
|
|
|
|
Description [Returns the number of new leaves that will be brought in.
|
|
Returns large number if the node cannot be removed from the set of leaves.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit )
|
|
{
|
|
int Cost;
|
|
// make sure the node is in the construction zone
|
|
assert( pNode->fMarkB == 1 );
|
|
// cannot expand over the PI node
|
|
if ( Abc_ObjIsCi(pNode) )
|
|
return 999;
|
|
// get the cost of the cone
|
|
Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB);
|
|
// always accept if the number of leaves does not increase
|
|
if ( Cost < 2 )
|
|
return Cost;
|
|
// skip nodes with many fanouts
|
|
if ( Abc_ObjFanoutNum(pNode) > nFaninLimit )
|
|
return 999;
|
|
// return the number of nodes that will be on the leaves if this node is removed
|
|
return Cost;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Evaluate the cost of removing the node from the set of leaves.]
|
|
|
|
Description [Returns the number of new leaves that will be brought in.
|
|
Returns large number if the node cannot be removed from the set of leaves.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit,
|
|
Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 )
|
|
{
|
|
Abc_Obj_t * pFanin0, * pFanin1, * pTemp;
|
|
Abc_Obj_t * pGrand, * pGrandToAdd;
|
|
// make sure the node is in the construction zone
|
|
assert( pNode->fMarkB == 1 );
|
|
// cannot expand over the PI node
|
|
if ( Abc_ObjIsCi(pNode) )
|
|
return 999;
|
|
// skip nodes with many fanouts
|
|
// if ( Abc_ObjFanoutNum(pNode) > nFaninLimit )
|
|
// return 999;
|
|
// get the children
|
|
pFanin0 = Abc_ObjFanin0(pNode);
|
|
pFanin1 = Abc_ObjFanin1(pNode);
|
|
assert( !pFanin0->fMarkB && !pFanin1->fMarkB );
|
|
// count the number of unique grandchildren that will be included
|
|
// return infinite cost if this number if more than 1
|
|
if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) )
|
|
return 999;
|
|
// consider the special case when a non-CI fanin can be dropped
|
|
if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB )
|
|
{
|
|
*ppLeafToAdd = pFanin1;
|
|
*pNodeToMark1 = pFanin0;
|
|
*pNodeToMark2 = NULL;
|
|
return 1;
|
|
}
|
|
if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB )
|
|
{
|
|
*ppLeafToAdd = pFanin0;
|
|
*pNodeToMark1 = pFanin1;
|
|
*pNodeToMark2 = NULL;
|
|
return 1;
|
|
}
|
|
|
|
// make the first node CI if any
|
|
if ( Abc_ObjIsCi(pFanin1) )
|
|
pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp;
|
|
// consider the first node
|
|
pGrandToAdd = NULL;
|
|
if ( Abc_ObjIsCi(pFanin0) )
|
|
{
|
|
*pNodeToMark1 = NULL;
|
|
pGrandToAdd = pFanin0;
|
|
}
|
|
else
|
|
{
|
|
*pNodeToMark1 = pFanin0;
|
|
pGrand = Abc_ObjFanin0(pFanin0);
|
|
if ( !pGrand->fMarkB )
|
|
{
|
|
if ( pGrandToAdd && pGrandToAdd != pGrand )
|
|
return 999;
|
|
pGrandToAdd = pGrand;
|
|
}
|
|
pGrand = Abc_ObjFanin1(pFanin0);
|
|
if ( !pGrand->fMarkB )
|
|
{
|
|
if ( pGrandToAdd && pGrandToAdd != pGrand )
|
|
return 999;
|
|
pGrandToAdd = pGrand;
|
|
}
|
|
}
|
|
// consider the second node
|
|
*pNodeToMark2 = pFanin1;
|
|
pGrand = Abc_ObjFanin0(pFanin1);
|
|
if ( !pGrand->fMarkB )
|
|
{
|
|
if ( pGrandToAdd && pGrandToAdd != pGrand )
|
|
return 999;
|
|
pGrandToAdd = pGrand;
|
|
}
|
|
pGrand = Abc_ObjFanin1(pFanin1);
|
|
if ( !pGrand->fMarkB )
|
|
{
|
|
if ( pGrandToAdd && pGrandToAdd != pGrand )
|
|
return 999;
|
|
pGrandToAdd = pGrand;
|
|
}
|
|
assert( pGrandToAdd != NULL );
|
|
*ppLeafToAdd = pGrandToAdd;
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Finds a fanin-limited, reconvergence-driven cut for the node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, int fContain )
|
|
{
|
|
Abc_Obj_t * pNode;
|
|
int i;
|
|
|
|
assert( !Abc_ObjIsComplement(pRoot) );
|
|
assert( Abc_ObjIsNode(pRoot) );
|
|
|
|
// start the visited nodes and mark them
|
|
Vec_PtrClear( p->vVisited );
|
|
Vec_PtrPush( p->vVisited, pRoot );
|
|
Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) );
|
|
Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) );
|
|
pRoot->fMarkB = 1;
|
|
Abc_ObjFanin0(pRoot)->fMarkB = 1;
|
|
Abc_ObjFanin1(pRoot)->fMarkB = 1;
|
|
|
|
// start the cut
|
|
Vec_PtrClear( p->vNodeLeaves );
|
|
Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) );
|
|
Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) );
|
|
|
|
// compute the cut
|
|
while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) );
|
|
assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax );
|
|
|
|
// return if containing cut is not requested
|
|
if ( !fContain )
|
|
{
|
|
// unmark both fMarkA and fMarkB in tbe TFI
|
|
Abc_NodesUnmarkB( p->vVisited );
|
|
return p->vNodeLeaves;
|
|
}
|
|
|
|
//printf( "\n\n\n" );
|
|
// compute the containing cut
|
|
assert( p->nNodeSizeMax < p->nConeSizeMax );
|
|
// copy the current boundary
|
|
Vec_PtrClear( p->vConeLeaves );
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodeLeaves, pNode, i )
|
|
Vec_PtrPush( p->vConeLeaves, pNode );
|
|
// compute the containing cut
|
|
while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) );
|
|
assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax );
|
|
// unmark TFI using fMarkA and fMarkB
|
|
Abc_NodesUnmarkB( p->vVisited );
|
|
return p->vNodeLeaves;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.]
|
|
|
|
Description [This procedure looks at the current leaves and tries to change
|
|
one leaf at a time in such a way that the cut grows as little as possible.
|
|
In evaluating the fanins, this procedure looks only at their immediate
|
|
predecessors (this is why it is called a one-level construction procedure).]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit )
|
|
{
|
|
Abc_Obj_t * pNode, * pFaninBest, * pNext;
|
|
int CostBest, CostCur, i;
|
|
// find the best fanin
|
|
CostBest = 100;
|
|
pFaninBest = NULL;
|
|
//printf( "Evaluating fanins of the cut:\n" );
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
|
|
{
|
|
CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit );
|
|
//printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur );
|
|
// if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level
|
|
if ( CostBest > CostCur ||
|
|
(CostBest == CostCur && pNode->Level > pFaninBest->Level) )
|
|
{
|
|
CostBest = CostCur;
|
|
pFaninBest = pNode;
|
|
}
|
|
if ( CostBest == 0 )
|
|
break;
|
|
}
|
|
if ( pFaninBest == NULL )
|
|
return 0;
|
|
// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit );
|
|
|
|
assert( CostBest < 3 );
|
|
if ( vLeaves->nSize - 1 + CostBest > nSizeLimit )
|
|
return 0;
|
|
// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit );
|
|
|
|
assert( Abc_ObjIsNode(pFaninBest) );
|
|
// remove the node from the array
|
|
Vec_PtrRemove( vLeaves, pFaninBest );
|
|
//printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) );
|
|
|
|
// add the left child to the fanins
|
|
pNext = Abc_ObjFanin0(pFaninBest);
|
|
if ( !pNext->fMarkB )
|
|
{
|
|
//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) );
|
|
pNext->fMarkB = 1;
|
|
Vec_PtrPush( vLeaves, pNext );
|
|
Vec_PtrPush( vVisited, pNext );
|
|
}
|
|
// add the right child to the fanins
|
|
pNext = Abc_ObjFanin1(pFaninBest);
|
|
if ( !pNext->fMarkB )
|
|
{
|
|
//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) );
|
|
pNext->fMarkB = 1;
|
|
Vec_PtrPush( vLeaves, pNext );
|
|
Vec_PtrPush( vVisited, pNext );
|
|
}
|
|
assert( vLeaves->nSize <= nSizeLimit );
|
|
// keep doing this
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.]
|
|
|
|
Description [This procedure looks at the current leaves and tries to change
|
|
one leaf at a time in such a way that the cut grows as little as possible.
|
|
In evaluating the fanins, this procedure looks across two levels of fanins
|
|
(this is why it is called a two-level construction procedure).]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit )
|
|
{
|
|
Abc_Obj_t * pNode = NULL, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2;
|
|
int CostCur = 0, i;
|
|
// find the best fanin
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
|
|
{
|
|
CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 );
|
|
if ( CostCur < 2 )
|
|
break;
|
|
}
|
|
if ( CostCur > 2 )
|
|
return 0;
|
|
// remove the node from the array
|
|
Vec_PtrRemove( vLeaves, pNode );
|
|
// add the node to the leaves
|
|
if ( pLeafToAdd )
|
|
{
|
|
assert( !pLeafToAdd->fMarkB );
|
|
pLeafToAdd->fMarkB = 1;
|
|
Vec_PtrPush( vLeaves, pLeafToAdd );
|
|
Vec_PtrPush( vVisited, pLeafToAdd );
|
|
}
|
|
// mark the other nodes
|
|
if ( pNodeToMark1 )
|
|
{
|
|
assert( !pNodeToMark1->fMarkB );
|
|
pNodeToMark1->fMarkB = 1;
|
|
Vec_PtrPush( vVisited, pNodeToMark1 );
|
|
}
|
|
if ( pNodeToMark2 )
|
|
{
|
|
assert( !pNodeToMark2->fMarkB );
|
|
pNodeToMark2->fMarkB = 1;
|
|
Vec_PtrPush( vVisited, pNodeToMark2 );
|
|
}
|
|
// keep doing this
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Get the nodes contained in the cut.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins )
|
|
{
|
|
Abc_Obj_t * pTemp;
|
|
int i;
|
|
// mark the fanins of the cone
|
|
Abc_NodesMark( vLeaves );
|
|
// collect the nodes in the DFS order
|
|
Vec_PtrClear( vVisited );
|
|
// add the fanins
|
|
if ( fIncludeFanins )
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pTemp, i )
|
|
Vec_PtrPush( vVisited, pTemp );
|
|
// add other nodes
|
|
for ( i = 0; i < nRoots; i++ )
|
|
Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited );
|
|
// unmark both sets
|
|
Abc_NodesUnmark( vLeaves );
|
|
Abc_NodesUnmark( vVisited );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Marks the TFI cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
|
|
{
|
|
if ( pNode->fMarkA == 1 )
|
|
return;
|
|
// visit transitive fanin
|
|
if ( Abc_ObjIsNode(pNode) )
|
|
{
|
|
Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited );
|
|
Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited );
|
|
}
|
|
assert( pNode->fMarkA == 0 );
|
|
pNode->fMarkA = 1;
|
|
Vec_PtrPush( vVisited, pNode );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns BDD representing the logic function of the cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited )
|
|
{
|
|
Abc_Obj_t * pNode;
|
|
DdNode * bFunc0, * bFunc1, * bFunc = NULL;
|
|
int i;
|
|
// get the nodes in the cut without fanins in the DFS order
|
|
Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 );
|
|
// set the elementary BDDs
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
|
|
pNode->pCopy = (Abc_Obj_t *)pbVars[i];
|
|
// compute the BDDs for the collected nodes
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
|
|
{
|
|
assert( !Abc_ObjIsPi(pNode) );
|
|
bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) );
|
|
bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) );
|
|
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
|
|
pNode->pCopy = (Abc_Obj_t *)bFunc;
|
|
}
|
|
assert(bFunc);
|
|
Cudd_Ref( bFunc );
|
|
// dereference the intermediate ones
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
|
|
Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
|
|
Cudd_Deref( bFunc );
|
|
return bFunc;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns BDD representing the transition relation of the cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited )
|
|
{
|
|
DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult;
|
|
Abc_Obj_t * pNode;
|
|
int i;
|
|
// get the nodes in the cut without fanins in the DFS order
|
|
Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 );
|
|
// set the elementary BDDs
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
|
|
pNode->pCopy = (Abc_Obj_t *)pbVarsX[i];
|
|
// compute the BDDs for the collected nodes
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
|
|
{
|
|
bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) );
|
|
bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) );
|
|
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
|
|
pNode->pCopy = (Abc_Obj_t *)bFunc;
|
|
}
|
|
// compute the transition relation of the cone
|
|
bTrans = b1; Cudd_Ref( bTrans );
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pNode, i )
|
|
{
|
|
bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] ); Cudd_Ref( bFunc );
|
|
bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc ); Cudd_Ref( bTrans );
|
|
Cudd_RecursiveDeref( dd, bTemp );
|
|
Cudd_RecursiveDeref( dd, bFunc );
|
|
}
|
|
// dereference the intermediate ones
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
|
|
Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
|
|
// compute don't-cares
|
|
bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize ); Cudd_Ref( bCube );
|
|
bResult = Cudd_bddExistAbstract( dd, bTrans, bCube ); Cudd_Ref( bResult );
|
|
bResult = Cudd_Not( bResult );
|
|
Cudd_RecursiveDeref( dd, bCube );
|
|
Cudd_RecursiveDeref( dd, bTrans );
|
|
Cudd_Deref( bResult );
|
|
return bResult;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Starts the resynthesis manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop )
|
|
{
|
|
Abc_ManCut_t * p;
|
|
p = ABC_ALLOC( Abc_ManCut_t, 1 );
|
|
memset( p, 0, sizeof(Abc_ManCut_t) );
|
|
p->vNodeLeaves = Vec_PtrAlloc( 100 );
|
|
p->vConeLeaves = Vec_PtrAlloc( 100 );
|
|
p->vVisited = Vec_PtrAlloc( 100 );
|
|
p->vLevels = Vec_VecAlloc( 100 );
|
|
p->vNodesTfo = Vec_PtrAlloc( 100 );
|
|
p->nNodeSizeMax = nNodeSizeMax;
|
|
p->nConeSizeMax = nConeSizeMax;
|
|
p->nNodeFanStop = nNodeFanStop;
|
|
p->nConeFanStop = nConeFanStop;
|
|
return p;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Stops the resynthesis manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NtkManCutStop( Abc_ManCut_t * p )
|
|
{
|
|
Vec_PtrFree( p->vNodeLeaves );
|
|
Vec_PtrFree( p->vConeLeaves );
|
|
Vec_PtrFree( p->vVisited );
|
|
Vec_VecFree( p->vLevels );
|
|
Vec_PtrFree( p->vNodesTfo );
|
|
ABC_FREE( p );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the leaves of the cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p )
|
|
{
|
|
return p->vConeLeaves;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the leaves of the cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p )
|
|
{
|
|
return p->vNodeLeaves;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the leaves of the cone.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p )
|
|
{
|
|
return p->vVisited;
|
|
}
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects the TFO of the cut in the topological order.]
|
|
|
|
Description [TFO of the cut is defined as a set of nodes, for which the cut
|
|
is a cut, that is, every path from the collected nodes to the CIs goes through
|
|
a node in the cut. The nodes are collected if their level does not exceed
|
|
the given number (LevelMax). The nodes are returned in the topological order.
|
|
If the root node is given, its MFFC is marked, so that the collected nodes
|
|
do not contain any nodes in the MFFC.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax )
|
|
{
|
|
Abc_Ntk_t * pNtk = pRoot->pNtk;
|
|
Vec_Ptr_t * vVec;
|
|
Abc_Obj_t * pNode, * pFanout;
|
|
int i, k, v, LevelMin;
|
|
assert( Abc_NtkIsStrash(pNtk) );
|
|
|
|
// assuming that the structure is clean
|
|
Vec_VecForEachLevel( p->vLevels, vVec, i )
|
|
assert( vVec->nSize == 0 );
|
|
|
|
// put fanins into the structure while labeling them
|
|
Abc_NtkIncrementTravId( pNtk );
|
|
LevelMin = -1;
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
|
|
{
|
|
if ( pNode->Level > (unsigned)LevelMax )
|
|
continue;
|
|
Abc_NodeSetTravIdCurrent( pNode );
|
|
Vec_VecPush( p->vLevels, pNode->Level, pNode );
|
|
if ( LevelMin < (int)pNode->Level )
|
|
LevelMin = pNode->Level;
|
|
}
|
|
assert( LevelMin >= 0 );
|
|
|
|
// mark MFFC
|
|
if ( pRoot )
|
|
Abc_NodeMffcLabelAig( pRoot );
|
|
|
|
// go through the levels up
|
|
Vec_PtrClear( p->vNodesTfo );
|
|
Vec_VecForEachEntryStart( Abc_Obj_t *, p->vLevels, pNode, i, k, LevelMin )
|
|
{
|
|
if ( i > LevelMax )
|
|
break;
|
|
// if the node is not marked, it is not a fanin
|
|
if ( !Abc_NodeIsTravIdCurrent(pNode) )
|
|
{
|
|
// check if it belongs to the TFO
|
|
if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) ||
|
|
!Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) )
|
|
continue;
|
|
// save the node in the TFO and label it
|
|
Vec_PtrPush( p->vNodesTfo, pNode );
|
|
Abc_NodeSetTravIdCurrent( pNode );
|
|
}
|
|
// go through the fanouts and add them to the structure if they meet the conditions
|
|
Abc_ObjForEachFanout( pNode, pFanout, v )
|
|
{
|
|
// skip if fanout is a CO or its level exceeds
|
|
if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax )
|
|
continue;
|
|
// skip if it is already added or if it is in MFFC
|
|
if ( Abc_NodeIsTravIdCurrent(pFanout) )
|
|
continue;
|
|
// add it to the structure but do not mark it (until tested later)
|
|
Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout );
|
|
}
|
|
}
|
|
|
|
// clear the levelized structure
|
|
Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin )
|
|
{
|
|
if ( i > LevelMax )
|
|
break;
|
|
Vec_PtrClear( vVec );
|
|
}
|
|
return p->vNodesTfo;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|