abcBridge-0.10.0.0: abc-build/src/base/abc/abcAig.c
/**CFile****************************************************************
FileName [abcAig.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Simple structural hashing package.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "abc.h"
ABC_NAMESPACE_IMPL_START
/*
AIG is an And-Inv Graph with structural hashing.
It is always structurally hashed. It means that at any time:
- for each AND gate, there are no other AND gates with the same children
- the constants are propagated
- there is no single-input nodes (inverters/buffers)
Additionally the following invariants are satisfied:
- there are no dangling nodes (the nodes without fanout)
- the level of each AND gate reflects the levels of this fanins
- the EXOR-status of each node is up-to-date
- the AND nodes are in the topological order
- the constant 1 node has always number 0 in the object list
The operations that are performed on AIGs:
- building new nodes (Abc_AigAnd)
- performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc)
- replacing one node by another (Abc_AigReplace)
- propagating constants (Abc_AigReplace)
When AIG is duplicated, the new graph is structurally hashed too.
If this repeated hashing leads to fewer nodes, it means the original
AIG was not strictly hashed (one of the conditions above is violated).
*/
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// the simple AIG manager
struct Abc_Aig_t_
{
Abc_Ntk_t * pNtkAig; // the AIG network
Abc_Obj_t * pConst1; // the constant 1 object (not a node!)
Abc_Obj_t ** pBins; // the table bins
int nBins; // the size of the table
int nEntries; // the total number of entries in the table
Vec_Ptr_t * vNodes; // the temporary array of nodes
Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced
Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement
Vec_Vec_t * vLevels; // the nodes to be updated
Vec_Vec_t * vLevelsR; // the nodes to be updated
Vec_Ptr_t * vAddedCells; // the added nodes
Vec_Ptr_t * vUpdatedNets; // the nodes whose fanouts have changed
int nStrash0;
int nStrash1;
int nStrash5;
int nStrash2;
};
// iterators through the entries in the linked lists of nodes
#define Abc_AigBinForEachEntry( pBin, pEnt ) \
for ( pEnt = pBin; \
pEnt; \
pEnt = pEnt->pNext )
#define Abc_AigBinForEachEntrySafe( pBin, pEnt, pEnt2 ) \
for ( pEnt = pBin, \
pEnt2 = pEnt? pEnt->pNext: NULL; \
pEnt; \
pEnt = pEnt2, \
pEnt2 = pEnt? pEnt->pNext: NULL )
// hash key for the structural hash table
//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; }
// hashing the node
static unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize )
{
unsigned Key = 0;
Key ^= Abc_ObjRegular(p0)->Id * 7937;
Key ^= Abc_ObjRegular(p1)->Id * 2971;
Key ^= Abc_ObjIsComplement(p0) * 911;
Key ^= Abc_ObjIsComplement(p1) * 353;
return Key % TableSize;
}
// structural hash table procedures
static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd );
static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis );
static void Abc_AigResize( Abc_Aig_t * pMan );
// incremental AIG procedures
static void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel );
static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan );
static void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan );
static void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode );
static void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates the local AIG manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
{
Abc_Aig_t * pMan;
// start the manager
pMan = ABC_ALLOC( Abc_Aig_t, 1 );
memset( pMan, 0, sizeof(Abc_Aig_t) );
// allocate the table
pMan->nBins = Abc_PrimeCudd( 10000 );
pMan->pBins = ABC_ALLOC( Abc_Obj_t *, pMan->nBins );
memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins );
pMan->vNodes = Vec_PtrAlloc( 100 );
pMan->vLevels = Vec_VecAlloc( 100 );
pMan->vLevelsR = Vec_VecAlloc( 100 );
pMan->vStackReplaceOld = Vec_PtrAlloc( 100 );
pMan->vStackReplaceNew = Vec_PtrAlloc( 100 );
// create the constant node
assert( pNtkAig->vObjs->nSize == 0 );
pMan->pConst1 = Abc_NtkCreateObj( pNtkAig, ABC_OBJ_NODE );
pMan->pConst1->Type = ABC_OBJ_CONST1;
pMan->pConst1->fPhase = 1;
pNtkAig->nObjCounts[ABC_OBJ_NODE]--;
// save the current network
pMan->pNtkAig = pNtkAig;
return pMan;
}
/**Function*************************************************************
Synopsis [Deallocates the local AIG manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigFree( Abc_Aig_t * pMan )
{
assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 );
assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 );
// free the table
if ( pMan->vAddedCells )
Vec_PtrFree( pMan->vAddedCells );
if ( pMan->vUpdatedNets )
Vec_PtrFree( pMan->vUpdatedNets );
Vec_VecFree( pMan->vLevels );
Vec_VecFree( pMan->vLevelsR );
Vec_PtrFree( pMan->vStackReplaceOld );
Vec_PtrFree( pMan->vStackReplaceNew );
Vec_PtrFree( pMan->vNodes );
ABC_FREE( pMan->pBins );
ABC_FREE( pMan );
}
/**Function*************************************************************
Synopsis [Returns the number of dangling nodes removed.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigCleanup( Abc_Aig_t * pMan )
{
Vec_Ptr_t * vDangles;
Abc_Obj_t * pAnd;
int i, nNodesOld;
// printf( "Strash0 = %d. Strash1 = %d. Strash100 = %d. StrashM = %d.\n",
// pMan->nStrash0, pMan->nStrash1, pMan->nStrash5, pMan->nStrash2 );
nNodesOld = pMan->nEntries;
// collect the AND nodes that do not fanout
vDangles = Vec_PtrAlloc( 100 );
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
if ( Abc_ObjFanoutNum(pAnd) == 0 )
Vec_PtrPush( vDangles, pAnd );
// process the dangling nodes and their MFFCs
Vec_PtrForEachEntry( Abc_Obj_t *, vDangles, pAnd, i )
Abc_AigDeleteNode( pMan, pAnd );
Vec_PtrFree( vDangles );
return nNodesOld - pMan->nEntries;
}
/**Function*************************************************************
Synopsis [Makes sure that every node in the table is in the network and vice versa.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigCheck( Abc_Aig_t * pMan )
{
Abc_Obj_t * pObj, * pAnd;
int i, nFanins, Counter;
Abc_NtkForEachNode( pMan->pNtkAig, pObj, i )
{
nFanins = Abc_ObjFaninNum(pObj);
if ( nFanins == 0 )
{
if ( !Abc_AigNodeIsConst(pObj) )
{
printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" );
return 0;
}
continue;
}
if ( nFanins == 1 )
{
printf( "Abc_AigCheck: The AIG has single input nodes.\n" );
return 0;
}
if ( nFanins > 2 )
{
printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" );
return 0;
}
if ( pObj->Level != 1 + (unsigned)Abc_MaxInt( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) )
printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) );
pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) );
if ( pAnd != pObj )
printf( "Abc_AigCheck: Node \"%s\" is not in the structural hashing table.\n", Abc_ObjName(pObj) );
}
// count the number of nodes in the table
Counter = 0;
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
Counter++;
if ( Counter != Abc_NtkNodeNum(pMan->pNtkAig) )
{
printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n" );
return 0;
}
// if the node is a choice node, nodes in its class should not have fanouts
Abc_NtkForEachNode( pMan->pNtkAig, pObj, i )
if ( Abc_AigNodeIsChoice(pObj) )
for ( pAnd = (Abc_Obj_t *)pObj->pData; pAnd; pAnd = (Abc_Obj_t *)pAnd->pData )
if ( Abc_ObjFanoutNum(pAnd) > 0 )
{
printf( "Abc_AigCheck: Representative %s", Abc_ObjName(pAnd) );
printf( " of choice node %s has %d fanouts.\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pAnd) );
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Computes the number of logic levels not counting PIs/POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigLevel( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
int i, LevelsMax;
assert( Abc_NtkIsStrash(pNtk) );
if ( pNtk->nBarBufs )
return Abc_NtkLevel( pNtk );
// perform the traversal
LevelsMax = 0;
Abc_NtkForEachCo( pNtk, pNode, i )
if ( LevelsMax < (int)Abc_ObjFanin0(pNode)->Level )
LevelsMax = (int)Abc_ObjFanin0(pNode)->Level;
return LevelsMax;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
Abc_Obj_t * pAnd;
unsigned Key;
// check if it is a good time for table resizing
if ( pMan->nEntries > 2 * pMan->nBins )
Abc_AigResize( pMan );
// order the arguments
if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
pAnd = p0, p0 = p1, p1 = pAnd;
// create the new node
pAnd = Abc_NtkCreateNode( pMan->pNtkAig );
Abc_ObjAddFanin( pAnd, p0 );
Abc_ObjAddFanin( pAnd, p1 );
// set the level of the new node
pAnd->Level = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
pAnd->fExor = Abc_NodeIsExorType(pAnd);
pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase);
// add the node to the corresponding linked list in the table
Key = Abc_HashKey2( p0, p1, pMan->nBins );
pAnd->pNext = pMan->pBins[Key];
pMan->pBins[Key] = pAnd;
pMan->nEntries++;
// create the cuts if defined
// if ( pAnd->pNtk->pManCut )
// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd );
pAnd->pCopy = NULL;
// add the node to the list of updated nodes
if ( pMan->vAddedCells )
Vec_PtrPush( pMan->vAddedCells, pAnd );
return pAnd;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd )
{
Abc_Obj_t * pTemp;
unsigned Key;
assert( !Abc_ObjIsComplement(pAnd) );
// order the arguments
if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
pTemp = p0, p0 = p1, p1 = pTemp;
// create the new node
Abc_ObjAddFanin( pAnd, p0 );
Abc_ObjAddFanin( pAnd, p1 );
// set the level of the new node
pAnd->Level = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
pAnd->fExor = Abc_NodeIsExorType(pAnd);
// add the node to the corresponding linked list in the table
Key = Abc_HashKey2( p0, p1, pMan->nBins );
pAnd->pNext = pMan->pBins[Key];
pMan->pBins[Key] = pAnd;
pMan->nEntries++;
// create the cuts if defined
// if ( pAnd->pNtk->pManCut )
// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd );
pAnd->pCopy = NULL;
// add the node to the list of updated nodes
// if ( pMan->vAddedCells )
// Vec_PtrPush( pMan->vAddedCells, pAnd );
return pAnd;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
Abc_Obj_t * pAnd, * pConst1;
unsigned Key;
assert( Abc_ObjRegular(p0)->pNtk->pManFunc == pMan );
assert( Abc_ObjRegular(p1)->pNtk->pManFunc == pMan );
// check for trivial cases
pConst1 = Abc_AigConst1(pMan->pNtkAig);
if ( p0 == p1 )
return p0;
if ( p0 == Abc_ObjNot(p1) )
return Abc_ObjNot(pConst1);
if ( Abc_ObjRegular(p0) == pConst1 )
{
if ( p0 == pConst1 )
return p1;
return Abc_ObjNot(pConst1);
}
if ( Abc_ObjRegular(p1) == pConst1 )
{
if ( p1 == pConst1 )
return p0;
return Abc_ObjNot(pConst1);
}
/*
{
int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) );
int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) );
if ( nFans0 == 0 || nFans1 == 0 )
pMan->nStrash0++;
else if ( nFans0 == 1 || nFans1 == 1 )
pMan->nStrash1++;
else if ( nFans0 <= 100 && nFans1 <= 100 )
pMan->nStrash5++;
else
pMan->nStrash2++;
}
*/
{
int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) );
int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) );
if ( nFans0 == 0 || nFans1 == 0 )
return NULL;
}
// order the arguments
if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
pAnd = p0, p0 = p1, p1 = pAnd;
// get the hash key for these two nodes
Key = Abc_HashKey2( p0, p1, pMan->nBins );
// find the matching node in the table
Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd )
if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) )
{
// assert( Abc_ObjFanoutNum(Abc_ObjRegular(p0)) && Abc_ObjFanoutNum(p1) );
return pAnd;
}
return NULL;
}
/**Function*************************************************************
Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType )
{
Abc_Obj_t * pNode1, * pNode2, * pNode;
// set the flag to zero
if ( pType ) *pType = 0;
// check the case of XOR(a,b) = OR(ab, a'b')'
if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) &&
(pNode2 = Abc_AigAndLookup(pMan, p0, p1)) )
{
pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
if ( pNode && pType ) *pType = 1;
return pNode;
}
// check the case of XOR(a,b) = OR(a'b, ab')
if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) &&
(pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) )
{
pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
return pNode? Abc_ObjNot(pNode) : NULL;
}
return NULL;
}
/**Function*************************************************************
Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType )
{
Abc_Obj_t * pNode1, * pNode2, * pNode;
// set the flag to zero
if ( pType ) *pType = 0;
// check the case of MUX(c,t,e) = OR(ct', c'e')'
if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) &&
(pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) )
{
pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
if ( pNode && pType ) *pType = 1;
return pNode;
}
// check the case of MUX(c,t,e) = OR(ct, c'e)
if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) &&
(pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) )
{
pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
return pNode? Abc_ObjNot(pNode) : NULL;
}
return NULL;
}
/**Function*************************************************************
Synopsis [Deletes an AIG node from the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis )
{
Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace;
unsigned Key;
assert( !Abc_ObjIsComplement(pThis) );
assert( Abc_ObjIsNode(pThis) );
assert( Abc_ObjFaninNum(pThis) == 2 );
assert( pMan->pNtkAig == pThis->pNtk );
// get the hash key for these two nodes
pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) );
pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) );
Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins );
// find the matching node in the table
ppPlace = pMan->pBins + Key;
Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd )
{
if ( pAnd != pThis )
{
ppPlace = &pAnd->pNext;
continue;
}
*ppPlace = pAnd->pNext;
break;
}
assert( pAnd == pThis );
pMan->nEntries--;
// delete the cuts if defined
if ( pThis->pNtk->pManCut )
Abc_NodeFreeCuts( pThis->pNtk->pManCut, pThis );
}
/**Function*************************************************************
Synopsis [Resizes the hash table of AIG nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigResize( Abc_Aig_t * pMan )
{
Abc_Obj_t ** pBinsNew;
Abc_Obj_t * pEnt, * pEnt2;
int nBinsNew, Counter, i;
abctime clk;
unsigned Key;
clk = Abc_Clock();
// get the new table size
nBinsNew = Abc_PrimeCudd( 3 * pMan->nBins );
// allocate a new array
pBinsNew = ABC_ALLOC( Abc_Obj_t *, nBinsNew );
memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew );
// rehash the entries from the old table
Counter = 0;
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 )
{
Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), nBinsNew );
pEnt->pNext = pBinsNew[Key];
pBinsNew[Key] = pEnt;
Counter++;
}
assert( Counter == pMan->nEntries );
// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew );
// ABC_PRT( "Time", Abc_Clock() - clk );
// replace the table and the parameters
ABC_FREE( pMan->pBins );
pMan->pBins = pBinsNew;
pMan->nBins = nBinsNew;
}
/**Function*************************************************************
Synopsis [Resizes the hash table of AIG nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigRehash( Abc_Aig_t * pMan )
{
Abc_Obj_t ** pBinsNew;
Abc_Obj_t * pEnt, * pEnt2;
int * pArray;
unsigned Key;
int Counter, Temp, i;
// allocate a new array
pBinsNew = ABC_ALLOC( Abc_Obj_t *, pMan->nBins );
memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * pMan->nBins );
// rehash the entries from the old table
Counter = 0;
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 )
{
// swap the fanins if needed
pArray = pEnt->vFanins.pArray;
if ( pArray[0] > pArray[1] )
{
Temp = pArray[0];
pArray[0] = pArray[1];
pArray[1] = Temp;
Temp = pEnt->fCompl0;
pEnt->fCompl0 = pEnt->fCompl1;
pEnt->fCompl1 = Temp;
}
// rehash the node
Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins );
pEnt->pNext = pBinsNew[Key];
pBinsNew[Key] = pEnt;
Counter++;
}
assert( Counter == pMan->nEntries );
// replace the table and the parameters
ABC_FREE( pMan->pBins );
pMan->pBins = pBinsNew;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk )
{
assert( Abc_NtkIsStrash(pNtk) );
return ((Abc_Aig_t *)pNtk->pManFunc)->pConst1;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
Abc_Obj_t * pAnd;
if ( (pAnd = Abc_AigAndLookup( pMan, p0, p1 )) )
return pAnd;
return Abc_AigAndCreate( pMan, p0, p1 );
}
/**Function*************************************************************
Synopsis [Implements Boolean OR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
return Abc_ObjNot( Abc_AigAnd( pMan, Abc_ObjNot(p0), Abc_ObjNot(p1) ) );
}
/**Function*************************************************************
Synopsis [Implements Boolean XOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
return Abc_AigOr( pMan, Abc_AigAnd(pMan, p0, Abc_ObjNot(p1)),
Abc_AigAnd(pMan, p1, Abc_ObjNot(p0)) );
}
/**Function*************************************************************
Synopsis [Implements Boolean XOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigMux( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * p1, Abc_Obj_t * p0 )
{
return Abc_AigOr( pMan, Abc_AigAnd(pMan, pC, p1), Abc_AigAnd(pMan, Abc_ObjNot(pC), p0) );
}
/**Function*************************************************************
Synopsis [Implements the miter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs )
{
Abc_Obj_t * pObj1, * pObj2;
if ( nObjs == 1 )
return ppObjs[0];
pObj1 = Abc_AigMiter_rec( pMan, ppObjs, nObjs/2 );
pObj2 = Abc_AigMiter_rec( pMan, ppObjs + nObjs/2, nObjs - nObjs/2 );
return Abc_AigOr( pMan, pObj1, pObj2 );
}
/**Function*************************************************************
Synopsis [Implements the miter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs, int fImplic )
{
int i;
if ( vPairs->nSize == 0 )
return Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) );
assert( vPairs->nSize % 2 == 0 );
// go through the cubes of the node's SOP
if ( fImplic )
{
for ( i = 0; i < vPairs->nSize; i += 2 )
vPairs->pArray[i/2] = Abc_AigAnd( pMan, (Abc_Obj_t *)vPairs->pArray[i], Abc_ObjNot((Abc_Obj_t *)vPairs->pArray[i+1]) );
}
else
{
for ( i = 0; i < vPairs->nSize; i += 2 )
vPairs->pArray[i/2] = Abc_AigXor( pMan, (Abc_Obj_t *)vPairs->pArray[i], (Abc_Obj_t *)vPairs->pArray[i+1] );
}
vPairs->nSize = vPairs->nSize/2;
return Abc_AigMiter_rec( pMan, (Abc_Obj_t **)vPairs->pArray, vPairs->nSize );
}
/**Function*************************************************************
Synopsis [Implements the miter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs )
{
Abc_Obj_t * pMiter, * pXor;
int i;
assert( vPairs->nSize % 2 == 0 );
// go through the cubes of the node's SOP
pMiter = Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) );
for ( i = 0; i < vPairs->nSize; i += 2 )
{
pXor = Abc_AigXor( pMan, (Abc_Obj_t *)vPairs->pArray[i], (Abc_Obj_t *)vPairs->pArray[i+1] );
pMiter = Abc_AigOr( pMan, pMiter, pXor );
}
return pMiter;
}
/**Function*************************************************************
Synopsis [Replaces one AIG node by the other.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel )
{
assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 );
assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 );
Vec_PtrPush( pMan->vStackReplaceOld, pOld );
Vec_PtrPush( pMan->vStackReplaceNew, pNew );
assert( !Abc_ObjIsComplement(pOld) );
// process the replacements
while ( Vec_PtrSize(pMan->vStackReplaceOld) )
{
pOld = (Abc_Obj_t *)Vec_PtrPop( pMan->vStackReplaceOld );
pNew = (Abc_Obj_t *)Vec_PtrPop( pMan->vStackReplaceNew );
Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel );
}
if ( fUpdateLevel )
{
Abc_AigUpdateLevel_int( pMan );
if ( pMan->pNtkAig->vLevelsR )
Abc_AigUpdateLevelR_int( pMan );
}
}
/**Function*************************************************************
Synopsis [Performs internal replacement step.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel )
{
Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout;
int k, v, iFanin;
// make sure the old node is regular and has fanouts
// (the new node can be complemented and can have fanouts)
assert( !Abc_ObjIsComplement(pOld) );
assert( Abc_ObjFanoutNum(pOld) > 0 );
// look at the fanouts of old node
Abc_NodeCollectFanouts( pOld, pMan->vNodes );
Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vNodes, pFanout, k )
{
if ( Abc_ObjIsCo(pFanout) )
{
Abc_ObjPatchFanin( pFanout, pOld, pNew );
continue;
}
// find the old node as a fanin of this fanout
iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id );
assert( iFanin == 0 || iFanin == 1 );
// get the new fanin
pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) );
assert( Abc_ObjRegular(pFanin1) != pFanout );
// get another fanin
pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 );
assert( Abc_ObjRegular(pFanin2) != pFanout );
// check if the node with these fanins exists
if ( (pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 )) )
{ // such node exists (it may be a constant)
// schedule replacement of the old fanout by the new fanout
Vec_PtrPush( pMan->vStackReplaceOld, pFanout );
Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew );
continue;
}
// such node does not exist - modify the old fanout node
// (this way the change will not propagate all the way to the COs)
assert( Abc_ObjRegular(pFanin1) != Abc_ObjRegular(pFanin2) );
// if the node is in the level structure, remove it
if ( pFanout->fMarkA )
Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout );
// if the node is in the level structure, remove it
if ( pFanout->fMarkB )
Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanout );
// remove the old fanout node from the structural hashing table
Abc_AigAndDelete( pMan, pFanout );
// remove the fanins of the old fanout
Abc_ObjRemoveFanins( pFanout );
// recreate the old fanout with new fanins and add it to the table
Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout );
assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) );
if ( fUpdateLevel )
{
// schedule the updated fanout for updating direct level
assert( pFanout->fMarkA == 0 );
pFanout->fMarkA = 1;
Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
// schedule the updated fanout for updating reverse level
if ( pMan->pNtkAig->vLevelsR )
{
assert( pFanout->fMarkB == 0 );
pFanout->fMarkB = 1;
Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanout), pFanout );
}
}
// the fanout has changed, update EXOR status of its fanouts
Abc_ObjForEachFanout( pFanout, pFanoutFanout, v )
if ( Abc_AigNodeIsAnd(pFanoutFanout) )
pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout);
}
// if the node has no fanouts left, remove its MFFC
if ( Abc_ObjFanoutNum(pOld) == 0 )
Abc_AigDeleteNode( pMan, pOld );
}
/**Function*************************************************************
Synopsis [Performs internal deletion step.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
{
Abc_Obj_t * pNode0, * pNode1, * pTemp;
int i, k;
// make sure the node is regular and dangling
assert( !Abc_ObjIsComplement(pNode) );
assert( Abc_ObjIsNode(pNode) );
assert( Abc_ObjFaninNum(pNode) == 2 );
assert( Abc_ObjFanoutNum(pNode) == 0 );
// when deleting an old node that is scheduled for replacement, remove it from the replacement queue
Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vStackReplaceOld, pTemp, i )
if ( pNode == pTemp )
{
// remove the entry from the replacement array
for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ )
{
pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1];
pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1];
}
pMan->vStackReplaceOld->nSize--;
pMan->vStackReplaceNew->nSize--;
}
// when deleting a new node that should replace another node, do not delete
Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vStackReplaceNew, pTemp, i )
if ( pNode == Abc_ObjRegular(pTemp) )
return;
// remember the node's fanins
pNode0 = Abc_ObjFanin0( pNode );
pNode1 = Abc_ObjFanin1( pNode );
// add the node to the list of updated nodes
if ( pMan->vUpdatedNets )
{
Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 );
Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 );
}
// remove the node from the table
Abc_AigAndDelete( pMan, pNode );
// if the node is in the level structure, remove it
if ( pNode->fMarkA )
Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode );
if ( pNode->fMarkB )
Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode );
// remove the node from the network
Abc_NtkDeleteObj( pNode );
// call recursively for the fanins
if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 )
Abc_AigDeleteNode( pMan, pNode0 );
if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 )
Abc_AigDeleteNode( pMan, pNode1 );
}
/**Function*************************************************************
Synopsis [Updates the level of the node after it has changed.]
Description [This procedure is based on the observation that
after the node's level has changed, the fanouts levels can change too,
but the new fanout levels are always larger than the node's level.
As a result, we can accumulate the nodes to be updated in the queue
and process them in the increasing order of levels.]
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan )
{
Abc_Obj_t * pNode, * pFanout;
Vec_Ptr_t * vVec;
int LevelNew, i, k, v;
// go through the nodes and update the level of their fanouts
Vec_VecForEachLevel( pMan->vLevels, vVec, i )
{
if ( Vec_PtrSize(vVec) == 0 )
continue;
Vec_PtrForEachEntry( Abc_Obj_t *, vVec, pNode, k )
{
if ( pNode == NULL )
continue;
assert( Abc_ObjIsNode(pNode) );
assert( (int)pNode->Level == i );
// clean the mark
assert( pNode->fMarkA == 1 );
pNode->fMarkA = 0;
// iterate through the fanouts
Abc_ObjForEachFanout( pNode, pFanout, v )
{
if ( Abc_ObjIsCo(pFanout) )
continue;
// get the new level of this fanout
LevelNew = 1 + Abc_MaxInt( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level );
assert( LevelNew > i );
if ( (int)pFanout->Level == LevelNew ) // no change
continue;
// if the fanout is present in the data structure, pull it out
if ( pFanout->fMarkA )
Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout );
// update the fanout level
pFanout->Level = LevelNew;
// add the fanout to the data structure to update its fanouts
assert( pFanout->fMarkA == 0 );
pFanout->fMarkA = 1;
Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
}
}
Vec_PtrClear( vVec );
}
}
/**Function*************************************************************
Synopsis [Updates the level of the node after it has changed.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan )
{
Abc_Obj_t * pNode, * pFanin, * pFanout;
Vec_Ptr_t * vVec;
int LevelNew, i, k, v, j;
// go through the nodes and update the level of their fanouts
Vec_VecForEachLevel( pMan->vLevelsR, vVec, i )
{
if ( Vec_PtrSize(vVec) == 0 )
continue;
Vec_PtrForEachEntry( Abc_Obj_t *, vVec, pNode, k )
{
if ( pNode == NULL )
continue;
assert( Abc_ObjIsNode(pNode) );
assert( Abc_ObjReverseLevel(pNode) == i );
// clean the mark
assert( pNode->fMarkB == 1 );
pNode->fMarkB = 0;
// iterate through the fanins
Abc_ObjForEachFanin( pNode, pFanin, v )
{
if ( Abc_ObjIsCi(pFanin) )
continue;
// get the new reverse level of this fanin
LevelNew = 0;
Abc_ObjForEachFanout( pFanin, pFanout, j )
if ( LevelNew < Abc_ObjReverseLevel(pFanout) )
LevelNew = Abc_ObjReverseLevel(pFanout);
LevelNew += 1;
assert( LevelNew > i );
if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change
continue;
// if the fanin is present in the data structure, pull it out
if ( pFanin->fMarkB )
Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin );
// update the reverse level
Abc_ObjSetReverseLevel( pFanin, LevelNew );
// add the fanin to the data structure to update its fanins
assert( pFanin->fMarkB == 0 );
pFanin->fMarkB = 1;
Vec_VecPush( pMan->vLevelsR, LevelNew, pFanin );
}
}
Vec_PtrClear( vVec );
}
}
/**Function*************************************************************
Synopsis [Removes the node from the level structure.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode )
{
Vec_Ptr_t * vVecTemp;
Abc_Obj_t * pTemp;
int m;
assert( pNode->fMarkA );
vVecTemp = Vec_VecEntry( vStruct, pNode->Level );
Vec_PtrForEachEntry( Abc_Obj_t *, vVecTemp, pTemp, m )
{
if ( pTemp != pNode )
continue;
Vec_PtrWriteEntry( vVecTemp, m, NULL );
break;
}
assert( m < Vec_PtrSize(vVecTemp) ); // found
pNode->fMarkA = 0;
}
/**Function*************************************************************
Synopsis [Removes the node from the level structure.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode )
{
Vec_Ptr_t * vVecTemp;
Abc_Obj_t * pTemp;
int m;
assert( pNode->fMarkB );
vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) );
Vec_PtrForEachEntry( Abc_Obj_t *, vVecTemp, pTemp, m )
{
if ( pTemp != pNode )
continue;
Vec_PtrWriteEntry( vVecTemp, m, NULL );
break;
}
assert( m < Vec_PtrSize(vVecTemp) ); // found
pNode->fMarkB = 0;
}
/**Function*************************************************************
Synopsis [Returns 1 if the node has at least one complemented fanout.]
Description [A fanout is complemented if the fanout's fanin edge pointing
to the given node is complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode )
{
Abc_Obj_t * pFanout;
int i, iFanin;
Abc_ObjForEachFanout( pNode, pFanout, i )
{
iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id );
assert( iFanin >= 0 );
if ( Abc_ObjFaninC( pFanout, iFanin ) )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis [Returns 1 if the node has at least one complemented fanout.]
Description [A fanout is complemented if the fanout's fanin edge pointing
to the given node is complemented. Only the fanouts with current TravId
are counted.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode )
{
Abc_Obj_t * pFanout;
int i, iFanin;
Abc_ObjForEachFanout( pNode, pFanout, i )
{
if ( !Abc_NodeIsTravIdCurrent(pFanout) )
continue;
iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id );
assert( iFanin >= 0 );
if ( Abc_ObjFaninC( pFanout, iFanin ) )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis [Prints the AIG node for debugging purposes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigPrintNode( Abc_Obj_t * pNode )
{
Abc_Obj_t * pNodeR = Abc_ObjRegular(pNode);
if ( Abc_ObjIsCi(pNodeR) )
{
printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" );
return;
}
if ( Abc_AigNodeIsConst(pNodeR) )
{
printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" );
return;
}
// print the node's function
printf( "%7s%s", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" );
printf( " = " );
printf( "%7s%s", Abc_ObjName(Abc_ObjFanin0(pNodeR)), Abc_ObjFaninC0(pNodeR)? "\'" : "" );
printf( " * " );
printf( "%7s%s", Abc_ObjName(Abc_ObjFanin1(pNodeR)), Abc_ObjFaninC1(pNodeR)? "\'" : "" );
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Check if the node has a combination loop of depth 1 or 2.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot )
{
Abc_Obj_t * pFanin0, * pFanin1;
Abc_Obj_t * pChild00, * pChild01;
Abc_Obj_t * pChild10, * pChild11;
if ( !Abc_AigNodeIsAnd(pNode) )
return 1;
pFanin0 = Abc_ObjFanin0(pNode);
pFanin1 = Abc_ObjFanin1(pNode);
if ( pRoot == pFanin0 || pRoot == pFanin1 )
return 0;
if ( Abc_ObjIsCi(pFanin0) )
{
pChild00 = NULL;
pChild01 = NULL;
}
else
{
pChild00 = Abc_ObjFanin0(pFanin0);
pChild01 = Abc_ObjFanin1(pFanin0);
if ( pRoot == pChild00 || pRoot == pChild01 )
return 0;
}
if ( Abc_ObjIsCi(pFanin1) )
{
pChild10 = NULL;
pChild11 = NULL;
}
else
{
pChild10 = Abc_ObjFanin0(pFanin1);
pChild11 = Abc_ObjFanin1(pFanin1);
if ( pRoot == pChild10 || pRoot == pChild11 )
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Resizes the hash table of AIG nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan )
{
Abc_Obj_t * pEnt;
int i;
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntry( pMan->pBins[i], pEnt )
{
if ( Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id > Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id )
{
// int i0 = Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id;
// int i1 = Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id;
printf( "Node %d has incorrect ordering of fanins.\n", pEnt->Id );
}
}
}
/**Function*************************************************************
Synopsis [Sets the correct phase of the nodes.]
Description [The AIG nodes should be in the DFS order.]
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
int i;
assert( Abc_NtkIsDfsOrdered(pNtk) );
Abc_AigConst1(pNtk)->fPhase = 1;
Abc_NtkForEachPi( pNtk, pObj, i )
pObj->fPhase = 0;
Abc_NtkForEachLatchOutput( pNtk, pObj, i )
pObj->fPhase = Abc_LatchIsInit1(pObj);
Abc_AigForEachAnd( pNtk, pObj, i )
pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fPhase ^ Abc_ObjFaninC1(pObj));
Abc_NtkForEachPo( pNtk, pObj, i )
pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj));
Abc_NtkForEachLatchInput( pNtk, pObj, i )
pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj));
}
/**Function*************************************************************
Synopsis [Start the update list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets )
{
assert( pMan->vAddedCells == NULL );
pMan->vAddedCells = Vec_PtrAlloc( 1000 );
pMan->vUpdatedNets = Vec_PtrAlloc( 1000 );
*pvUpdatedNets = pMan->vUpdatedNets;
return pMan->vAddedCells;
}
/**Function*************************************************************
Synopsis [Start the update list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigUpdateStop( Abc_Aig_t * pMan )
{
assert( pMan->vAddedCells != NULL );
Vec_PtrFree( pMan->vAddedCells );
Vec_PtrFree( pMan->vUpdatedNets );
pMan->vAddedCells = NULL;
pMan->vUpdatedNets = NULL;
}
/**Function*************************************************************
Synopsis [Start the update list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigUpdateReset( Abc_Aig_t * pMan )
{
assert( pMan->vAddedCells != NULL );
Vec_PtrClear( pMan->vAddedCells );
Vec_PtrClear( pMan->vUpdatedNets );
}
/**Function*************************************************************
Synopsis [Start the update list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigCountNext( Abc_Aig_t * pMan )
{
Abc_Obj_t * pAnd;
int i, Counter = 0, CounterTotal = 0;
// count how many nodes have pNext set
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
{
Counter += (pAnd->pNext != NULL);
CounterTotal++;
}
printf( "Counter = %d. Nodes = %d. Ave = %6.2f\n", Counter, CounterTotal, 1.0 * CounterTotal/pMan->nBins );
return Counter;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
void Abc_NtkHelloWorld( Abc_Ntk_t * pNtk )
{
printf( "Hello, World!\n" );
}
ABC_NAMESPACE_IMPL_END