blob: c8d4003a41e58463711abf772b7e70ab4a010e93 [file] [log] [blame]
/**CFile****************************************************************
FileName [ivyUtil.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [And-Inverter Graph package.]
Synopsis [Various procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - May 11, 2006.]
Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ivy.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Increments the current traversal ID of the network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManIncrementTravId( Ivy_Man_t * p )
{
if ( p->nTravIds >= (1<<30)-1 - 1000 )
Ivy_ManCleanTravId( p );
p->nTravIds++;
}
/**Function*************************************************************
Synopsis [Sets the DFS ordering of the nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManCleanTravId( Ivy_Man_t * p )
{
Ivy_Obj_t * pObj;
int i;
p->nTravIds = 1;
Ivy_ManForEachObj( p, pObj, i )
pObj->TravId = 0;
}
/**Function*************************************************************
Synopsis [Computes truth table of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes )
{
if ( pNode->fMarkA )
return;
pNode->fMarkA = 1;
assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) );
Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes );
Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes );
Vec_IntPush( vNodes, pNode->Id );
}
/**Function*************************************************************
Synopsis [Computes truth table of the cut.]
Description [Does not modify the array of leaves. Uses array vTruth to store
temporary truth tables. The returned pointer should be used immediately.]
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes )
{
int i, Leaf;
// collect and mark the leaves
Vec_IntClear( vNodes );
Vec_IntForEachEntry( vLeaves, Leaf, i )
{
Vec_IntPush( vNodes, Leaf );
Ivy_ManObj(p, Leaf)->fMarkA = 1;
}
// collect and mark the nodes
Ivy_ManCollectCut_rec( p, pRoot, vNodes );
// clean the nodes
Vec_IntForEachEntry( vNodes, Leaf, i )
Ivy_ManObj(p, Leaf)->fMarkA = 0;
}
/**Function*************************************************************
Synopsis [Returns the pointer to the truth table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth )
{
return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum;
}
/**Function*************************************************************
Synopsis [Computes truth table of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords )
{
unsigned * pTruth, * pTruth0, * pTruth1;
int i;
pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth );
pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth );
pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth );
if ( Ivy_ObjIsExor(pNode) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = pTruth0[i] ^ pTruth1[i];
else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = pTruth0[i] & pTruth1[i];
else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = pTruth0[i] & ~pTruth1[i];
else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = ~pTruth0[i] & pTruth1[i];
else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
}
/**Function*************************************************************
Synopsis [Computes truth table of the cut.]
Description [Does not modify the array of leaves. Uses array vTruth to store
temporary truth tables. The returned pointer should be used immediately.]
SideEffects []
SeeAlso []
***********************************************************************/
unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth )
{
static unsigned uTruths[8][8] = { // elementary truth tables
{ 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
{ 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
{ 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
{ 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
{ 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
{ 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
{ 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
{ 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
};
int i, Leaf;
// collect the cut
Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes );
// set the node numbers
Vec_IntForEachEntry( vNodes, Leaf, i )
Ivy_ManObj(p, Leaf)->TravId = i;
// alloc enough memory
Vec_IntClear( vTruth );
Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) );
// set the elementary truth tables
Vec_IntForEachEntry( vLeaves, Leaf, i )
memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) );
// compute truths for other nodes
Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) )
Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 );
return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth );
}
/**Function*************************************************************
Synopsis [Collect the latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p )
{
Vec_Int_t * vLatches;
Ivy_Obj_t * pObj;
int i;
vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) );
Ivy_ManForEachLatch( p, pObj, i )
Vec_IntPush( vLatches, pObj->Id );
return vLatches;
}
/**Function*************************************************************
Synopsis [Collect the latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManLevels( Ivy_Man_t * p )
{
Ivy_Obj_t * pObj;
int i, LevelMax = 0;
Ivy_ManForEachPo( p, pObj, i )
LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level );
return LevelMax;
}
/**Function*************************************************************
Synopsis [Collect the latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj )
{
if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) )
return pObj->Level;
if ( Ivy_ObjIsBuf(pObj) )
return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
assert( Ivy_ObjIsNode(pObj) );
Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) );
return pObj->Level = Ivy_ObjLevelNew( pObj );
}
/**Function*************************************************************
Synopsis [Collect the latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManResetLevels( Ivy_Man_t * p )
{
Ivy_Obj_t * pObj;
int i;
Ivy_ManForEachObj( p, pObj, i )
pObj->Level = 0;
Ivy_ManForEachCo( p, pObj, i )
Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) );
}
/**Function*************************************************************
Synopsis [References/references the node and returns MFFC size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel )
{
Ivy_Obj_t * pNode0, * pNode1;
int Counter;
// label visited nodes
if ( fLabel )
Ivy_ObjSetTravIdCurrent( p, pNode );
// skip the CI
if ( Ivy_ObjIsPi(pNode) )
return 0;
assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) );
// process the internal node
pNode0 = Ivy_ObjFanin0(pNode);
pNode1 = Ivy_ObjFanin1(pNode);
Counter = Ivy_ObjIsNode(pNode);
if ( fReference )
{
if ( pNode0->nRefs++ == 0 )
Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel );
if ( pNode1 && pNode1->nRefs++ == 0 )
Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel );
}
else
{
assert( pNode0->nRefs > 0 );
assert( pNode1 == NULL || pNode1->nRefs > 0 );
if ( --pNode0->nRefs == 0 )
Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel );
if ( pNode1 && --pNode1->nRefs == 0 )
Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel );
}
return Counter;
}
/**Function*************************************************************
Synopsis [Labels MFFC with the current label.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode )
{
int nConeSize1, nConeSize2;
assert( !Ivy_IsComplement( pNode ) );
assert( Ivy_ObjIsNode( pNode ) );
nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference
nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference
assert( nConeSize1 == nConeSize2 );
assert( nConeSize1 > 0 );
return nConeSize1;
}
/**Function*************************************************************
Synopsis [Recursively updates fanout levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj )
{
Ivy_Obj_t * pFanout;
Vec_Ptr_t * vFanouts;
int i, LevelNew;
assert( p->fFanout );
assert( Ivy_ObjIsNode(pObj) );
vFanouts = Vec_PtrAlloc( 10 );
Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
{
if ( Ivy_ObjIsCo(pFanout) )
{
// assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax );
continue;
}
LevelNew = Ivy_ObjLevelNew( pFanout );
if ( (int)pFanout->Level == LevelNew )
continue;
pFanout->Level = LevelNew;
Ivy_ObjUpdateLevel_rec( p, pFanout );
}
Vec_PtrFree( vFanouts );
}
/**Function*************************************************************
Synopsis [Compute the new required level.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj )
{
Ivy_Obj_t * pFanout;
Vec_Ptr_t * vFanouts;
int i, Required, LevelNew = 1000000;
assert( p->fFanout && p->vRequired );
vFanouts = Vec_PtrAlloc( 10 );
Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
{
Required = Vec_IntEntry(p->vRequired, pFanout->Id);
LevelNew = IVY_MIN( LevelNew, Required );
}
Vec_PtrFree( vFanouts );
return LevelNew - 1;
}
/**Function*************************************************************
Synopsis [Recursively updates fanout levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew )
{
Ivy_Obj_t * pFanin;
if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) )
return;
assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
// process the first fanin
pFanin = Ivy_ObjFanin0(pObj);
if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 )
{
Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 );
Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 );
}
if ( Ivy_ObjIsBuf(pObj) )
return;
// process the second fanin
pFanin = Ivy_ObjFanin1(pObj);
if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 )
{
Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 );
Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 );
}
}
/**Function*************************************************************
Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode )
{
Ivy_Obj_t * pNode0, * pNode1;
// check that the node is regular
assert( !Ivy_IsComplement(pNode) );
// if the node is not AND, this is not MUX
if ( !Ivy_ObjIsAnd(pNode) )
return 0;
// if the children are not complemented, this is not MUX
if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) )
return 0;
// get children
pNode0 = Ivy_ObjFanin0(pNode);
pNode1 = Ivy_ObjFanin1(pNode);
// if the children are not ANDs, this is not MUX
if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) )
return 0;
// otherwise the node is MUX iff it has a pair of equal grandchildren
return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) ||
(Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) ||
(Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) ||
(Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)));
}
/**Function*************************************************************
Synopsis [Recognizes what nodes are control and data inputs of a MUX.]
Description [If the node is a MUX, returns the control variable C.
Assigns nodes T and E to be the then and else variables of the MUX.
Node C is never complemented. Nodes T and E can be complemented.
This function also recognizes EXOR/NEXOR gates as MUXes.]
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE )
{
Ivy_Obj_t * pNode0, * pNode1;
assert( !Ivy_IsComplement(pNode) );
assert( Ivy_ObjIsMuxType(pNode) );
// get children
pNode0 = Ivy_ObjFanin0(pNode);
pNode1 = Ivy_ObjFanin1(pNode);
// find the control variable
// if ( pNode1->p1 == Fraig_Not(pNode2->p1) )
if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) )
{
// if ( Fraig_IsComplement(pNode1->p1) )
if ( Ivy_ObjFaninC0(pNode0) )
{ // pNode2->p1 is positive phase of C
*ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
*ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
return Ivy_ObjChild0(pNode1);//pNode2->p1;
}
else
{ // pNode1->p1 is positive phase of C
*ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
*ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
return Ivy_ObjChild0(pNode0);//pNode1->p1;
}
}
// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) )
else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) )
{
// if ( Fraig_IsComplement(pNode1->p1) )
if ( Ivy_ObjFaninC0(pNode0) )
{ // pNode2->p2 is positive phase of C
*ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
*ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
return Ivy_ObjChild1(pNode1);//pNode2->p2;
}
else
{ // pNode1->p1 is positive phase of C
*ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2);
*ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
return Ivy_ObjChild0(pNode0);//pNode1->p1;
}
}
// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) )
else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) )
{
// if ( Fraig_IsComplement(pNode1->p2) )
if ( Ivy_ObjFaninC1(pNode0) )
{ // pNode2->p1 is positive phase of C
*ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
*ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
return Ivy_ObjChild0(pNode1);//pNode2->p1;
}
else
{ // pNode1->p2 is positive phase of C
*ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
*ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2);
return Ivy_ObjChild1(pNode0);//pNode1->p2;
}
}
// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) )
else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) )
{
// if ( Fraig_IsComplement(pNode1->p2) )
if ( Ivy_ObjFaninC1(pNode0) )
{ // pNode2->p2 is positive phase of C
*ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
*ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
return Ivy_ObjChild1(pNode1);//pNode2->p2;
}
else
{ // pNode1->p2 is positive phase of C
*ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1);
*ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1);
return Ivy_ObjChild1(pNode0);//pNode1->p2;
}
}
assert( 0 ); // this is not MUX
return NULL;
}
/**Function*************************************************************
Synopsis [Returns the real fanin.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj )
{
Ivy_Obj_t * pFanin;
if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) )
return pObj;
pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) );
return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) );
}
/**Function*************************************************************
Synopsis [Prints node in HAIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig )
{
Ivy_Obj_t * pTemp;
int fShowFanouts = 0;
assert( !Ivy_IsComplement(pObj) );
printf( "Node %5d : ", Ivy_ObjId(pObj) );
if ( Ivy_ObjIsConst1(pObj) )
printf( "constant 1" );
else if ( Ivy_ObjIsPi(pObj) )
printf( "PI" );
else if ( Ivy_ObjIsPo(pObj) )
printf( "PO" );
else if ( Ivy_ObjIsLatch(pObj) )
printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
else if ( Ivy_ObjIsBuf(pObj) )
printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
else
printf( "AND( %5d%s, %5d%s )",
Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "),
Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") );
printf( " (refs = %3d)", Ivy_ObjRefs(pObj) );
if ( fShowFanouts )
{
Vec_Ptr_t * vFanouts;
Ivy_Obj_t * pFanout;
int i;
vFanouts = Vec_PtrAlloc( 10 );
printf( "\nFanouts:\n" );
Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i )
{
printf( " " );
printf( "Node %5d : ", Ivy_ObjId(pFanout) );
if ( Ivy_ObjIsPo(pFanout) )
printf( "PO" );
else if ( Ivy_ObjIsLatch(pFanout) )
printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") );
else if ( Ivy_ObjIsBuf(pFanout) )
printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") );
else
printf( "AND( %5d%s, %5d%s )",
Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "),
Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") );
printf( "\n" );
}
Vec_PtrFree( vFanouts );
return;
}
if ( !fHaig )
{
if ( pObj->pEquiv == NULL )
printf( " HAIG node not given" );
else
printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") );
return;
}
if ( pObj->pEquiv == NULL )
return;
// there are choices
if ( Ivy_ObjRefs(pObj) > 0 )
{
// print equivalence class
printf( " { %5d ", pObj->Id );
assert( !Ivy_IsComplement(pObj->pEquiv) );
for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) )
printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") );
printf( " }" );
return;
}
// this is a secondary node
for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) );
assert( Ivy_ObjRefs(pTemp) > 0 );
printf( " class of %d", pTemp->Id );
}
/**Function*************************************************************
Synopsis [Prints node in HAIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig )
{
Vec_Int_t * vNodes;
Ivy_Obj_t * pObj;
int i;
printf( "PIs: " );
Ivy_ManForEachPi( p, pObj, i )
printf( " %d", pObj->Id );
printf( "\n" );
printf( "POs: " );
Ivy_ManForEachPo( p, pObj, i )
printf( " %d", pObj->Id );
printf( "\n" );
printf( "Latches: " );
Ivy_ManForEachLatch( p, pObj, i )
printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") );
printf( "\n" );
vNodes = Ivy_ManDfsSeq( p, NULL );
Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" );
printf( "\n" );
Vec_IntFree( vNodes );
}
/**Function*************************************************************
Synopsis [Performs incremental rewriting of the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_CutTruthPrint2( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth )
{
int i;
printf( "Trying cut : {" );
for ( i = 0; i < pCut->nSize; i++ )
printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
printf( " } " );
Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" );
return 0;
}
/**Function*************************************************************
Synopsis [Performs incremental rewriting of the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth )
{
Vec_Ptr_t * vArray;
Ivy_Obj_t * pObj, * pFanout;
int nLatches = 0;
int nPresent = 0;
int i, k;
int fVerbose = 0;
if ( fVerbose )
printf( "Trying cut : {" );
for ( i = 0; i < pCut->nSize; i++ )
{
if ( fVerbose )
printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) );
nLatches += Ivy_LeafLat(pCut->pArray[i]);
}
if ( fVerbose )
printf( " } " );
if ( fVerbose )
printf( "Latches = %d. ", nLatches );
// check if there are latches on the fanout edges
vArray = Vec_PtrAlloc( 100 );
for ( i = 0; i < pCut->nSize; i++ )
{
pObj = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[i]) );
Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, k )
{
if ( Ivy_ObjIsLatch(pFanout) )
{
nPresent++;
break;
}
}
}
Vec_PtrSize( vArray );
if ( fVerbose )
{
printf( "Present = %d. ", nPresent );
if ( nLatches > nPresent )
printf( "Clauses = %d. ", 2*(nLatches - nPresent) );
printf( "\n" );
}
return ( nLatches > nPresent ) ? 2*(nLatches - nPresent) : 0;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END