blob: 204d303340fa4e6ab2c4afc856690de5b241bef0 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaUtil.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Various utilities.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "base/main/mainInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define NUMBER1 3716960521u
#define NUMBER2 2174103536u
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates a sequence or random numbers.]
Description []
SideEffects []
SeeAlso [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx]
***********************************************************************/
unsigned Gia_ManRandom( int fReset )
{
static unsigned int m_z = NUMBER1;
static unsigned int m_w = NUMBER2;
if ( fReset )
{
m_z = NUMBER1;
m_w = NUMBER2;
}
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}
word Gia_ManRandomW( int fReset )
{
return ((word)Gia_ManRandom(fReset) << 32) | ((word)Gia_ManRandom(fReset) << 0);
}
/**Function*************************************************************
Synopsis [Creates random info for the primary inputs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop )
{
unsigned * pInfo;
int i, w;
Vec_PtrForEachEntryStart( unsigned *, vInfo, pInfo, i, iInputStart )
for ( w = iWordStart; w < iWordStop; w++ )
pInfo[w] = Gia_ManRandom(0);
}
/**Function*************************************************************
Synopsis [Returns the time stamp.]
Description [The file should be closed.]
SideEffects []
SeeAlso []
***********************************************************************/
char * Gia_TimeStamp()
{
static char Buffer[100];
char * TimeStamp;
time_t ltime;
// get the current time
time( &ltime );
TimeStamp = asctime( localtime( &ltime ) );
TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
strcpy( Buffer, TimeStamp );
return Buffer;
}
/**Function*************************************************************
Synopsis [Returns the composite name of the file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix )
{
static char Buffer[1000];
char * pDot;
strcpy( Buffer, pBase );
if ( (pDot = strrchr( Buffer, '.' )) )
*pDot = 0;
strcat( Buffer, pSuffix );
if ( (pDot = strrchr( Buffer, '\\' )) || (pDot = strrchr( Buffer, '/' )) )
return pDot+1;
return Buffer;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManIncrementTravId( Gia_Man_t * p )
{
if ( p->pTravIds == NULL )
{
p->nTravIdsAlloc = Gia_ManObjNum(p) + 100;
p->pTravIds = ABC_CALLOC( int, p->nTravIdsAlloc );
p->nTravIds = 0;
}
while ( p->nTravIdsAlloc < Gia_ManObjNum(p) )
{
p->nTravIdsAlloc *= 2;
p->pTravIds = ABC_REALLOC( int, p->pTravIds, p->nTravIdsAlloc );
memset( p->pTravIds + p->nTravIdsAlloc/2, 0, sizeof(int) * p->nTravIdsAlloc/2 );
}
p->nTravIds++;
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCleanMark01( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
pObj->fMark0 = pObj->fMark1 = 0;
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSetMark0( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
pObj->fMark0 = 1;
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCleanMark0( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
pObj->fMark0 = 0;
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCheckMark0( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
assert( pObj->fMark0 == 0 );
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSetMark1( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
pObj->fMark1 = 1;
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCleanMark1( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
pObj->fMark1 = 0;
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCheckMark1( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
assert( pObj->fMark1 == 0 );
}
/**Function*************************************************************
Synopsis [Cleans the value.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCleanValue( Gia_Man_t * p )
{
int i;
for ( i = 0; i < p->nObjs; i++ )
p->pObjs[i].Value = 0;
}
/**Function*************************************************************
Synopsis [Cleans the value.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManFillValue( Gia_Man_t * p )
{
int i;
for ( i = 0; i < p->nObjs; i++ )
p->pObjs[i].Value = ~0;
}
/**Function*************************************************************
Synopsis [Sets the phase of one object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ObjSetPhase( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( Gia_ObjIsAnd(pObj) )
{
int fPhase0 = Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj);
int fPhase1 = Gia_ObjPhase(Gia_ObjFanin1(pObj)) ^ Gia_ObjFaninC1(pObj);
if ( Gia_ObjIsMux(p, pObj) )
{
int fPhase2 = Gia_ObjPhase(Gia_ObjFanin2(p, pObj)) ^ Gia_ObjFaninC2(p, pObj);
pObj->fPhase = (fPhase2 && fPhase1) || (!fPhase2 && fPhase0);
}
else if ( Gia_ObjIsXor(pObj) )
pObj->fPhase = fPhase0 ^ fPhase1;
else
pObj->fPhase = fPhase0 & fPhase1;
}
else if ( Gia_ObjIsCo(pObj) )
pObj->fPhase = (Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj));
else
pObj->fPhase = 0;
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSetPhase( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
Gia_ObjSetPhase( p, pObj );
}
void Gia_ManSetPhasePattern( Gia_Man_t * p, Vec_Int_t * vCiValues )
{
Gia_Obj_t * pObj;
int i;
assert( Gia_ManCiNum(p) == Vec_IntSize(vCiValues) );
Gia_ManForEachObj( p, pObj, i )
if ( Gia_ObjIsCi(pObj) )
pObj->fPhase = Vec_IntEntry( vCiValues, Gia_ObjCioId(pObj) );
else
Gia_ObjSetPhase( p, pObj );
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSetPhase1( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachCi( p, pObj, i )
pObj->fPhase = 1;
Gia_ManForEachObj( p, pObj, i )
if ( !Gia_ObjIsCi(pObj) )
Gia_ObjSetPhase( p, pObj );
}
/**Function*************************************************************
Synopsis [Sets phases of the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCleanPhase( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
pObj->fPhase = 0;
}
/**Function*************************************************************
Synopsis [Returns the number of COs whose value is 1.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManCheckCoPhase( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, Counter = 0;
Gia_ManForEachCo( p, pObj, i )
Counter += pObj->fPhase;
return Counter;
}
/**Function*************************************************************
Synopsis [Prepares copies for the model.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCleanLevels( Gia_Man_t * p, int Size )
{
if ( p->vLevels == NULL )
p->vLevels = Vec_IntAlloc( Size );
Vec_IntFill( p->vLevels, Size, 0 );
}
/**Function*************************************************************
Synopsis [Prepares copies for the model.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCleanTruth( Gia_Man_t * p )
{
if ( p->vTruths == NULL )
p->vTruths = Vec_IntAlloc( Gia_ManObjNum(p) );
Vec_IntFill( p->vTruths, Gia_ManObjNum(p), -1 );
}
/**Function*************************************************************
Synopsis [Assigns levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManLevelNum( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
p->nLevels = 0;
Gia_ManForEachObj( p, pObj, i )
{
if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) )
Gia_ObjSetBufLevel( p, pObj );
else if ( Gia_ObjIsAnd(pObj) )
Gia_ObjSetGateLevel( p, pObj );
else if ( Gia_ObjIsCo(pObj) )
Gia_ObjSetCoLevel( p, pObj );
else
Gia_ObjSetLevel( p, pObj, 0 );
p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
}
return p->nLevels;
}
float Gia_ManLevelAve( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, Ave = 0;
assert( p->vLevels );
Gia_ManForEachCo( p, pObj, i )
Ave += Gia_ObjLevel(p, pObj);
return (float)Ave / Gia_ManCoNum(p);
}
/**Function*************************************************************
Synopsis [Assigns levels using CI level information.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManGetCiLevels( Gia_Man_t * p )
{
Vec_Int_t * vCiLevels;
Gia_Obj_t * pObj;
int i;
if ( p->vLevels == NULL )
return NULL;
vCiLevels = Vec_IntAlloc( Gia_ManCiNum(p) );
Gia_ManForEachCi( p, pObj, i )
Vec_IntPush( vCiLevels, Gia_ObjLevel(p, pObj) );
return vCiLevels;
}
int Gia_ManSetLevels( Gia_Man_t * p, Vec_Int_t * vCiLevels )
{
Gia_Obj_t * pObj;
int i;
if ( vCiLevels == NULL )
return Gia_ManLevelNum( p );
assert( Vec_IntSize(vCiLevels) == Gia_ManCiNum(p) );
Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
p->nLevels = 0;
Gia_ManForEachCi( p, pObj, i )
{
Gia_ObjSetLevel( p, pObj, Vec_IntEntry(vCiLevels, i) );
p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
}
Gia_ManForEachObj( p, pObj, i )
{
if ( Gia_ObjIsAnd(pObj) )
Gia_ObjSetGateLevel( p, pObj );
else if ( Gia_ObjIsCo(pObj) )
Gia_ObjSetCoLevel( p, pObj );
else continue;
p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) );
}
return p->nLevels;
}
/**Function*************************************************************
Synopsis [Compute reverse levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManReverseLevel( Gia_Man_t * p )
{
Vec_Int_t * vLevelRev;
Gia_Obj_t * pObj;
int i;
vLevelRev = Vec_IntStart( Gia_ManObjNum(p) );
Gia_ManForEachAndReverse( p, pObj, i )
{
int LevelR = Vec_IntEntry( vLevelRev, i );
if ( Gia_ObjIsMux(p, pObj) )
{
Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 2 );
Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 2 );
Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId2(p, i), LevelR + 2 );
}
else if ( Gia_ObjIsXor(pObj) )
{
Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 2 );
Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 2 );
}
else if ( Gia_ObjIsBuf(pObj) )
{
Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR );
}
else
{
Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 1 );
Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 1 );
}
}
return vLevelRev;
}
/**Function*************************************************************
Synopsis [Compute required levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManRequiredLevel( Gia_Man_t * p )
{
Vec_Int_t * vRequired;
Gia_Obj_t * pObj;
int i, LevelMax = 0;
vRequired = Gia_ManReverseLevel( p );
Gia_ManForEachCi( p, pObj, i )
LevelMax = Abc_MaxInt( LevelMax, Vec_IntEntry(vRequired, Gia_ObjId(p, pObj)) );
Gia_ManForEachObj( p, pObj, i )
Vec_IntWriteEntry( vRequired, i, LevelMax - Vec_IntEntry(vRequired, i) );
return vRequired;
}
/**Function*************************************************************
Synopsis [Compute slacks measured using the number of AIG levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManComputeSlacks( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, nLevels = Gia_ManLevelNum( p );
Vec_Int_t * vLevelR = Gia_ManReverseLevel( p );
Vec_Int_t * vSlacks = Vec_IntAlloc( Gia_ManObjNum(p) );
Gia_ManForEachObj( p, pObj, i )
Vec_IntPush( vSlacks, nLevels - Gia_ObjLevelId(p, i) - Vec_IntEntry(vLevelR, i) );
assert( Vec_IntSize(vSlacks) == Gia_ManObjNum(p) );
Vec_IntFree( vLevelR );
return vSlacks;
}
/**Function*************************************************************
Synopsis [Assigns levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCreateValueRefs( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
{
pObj->Value = 0;
if ( Gia_ObjIsAnd(pObj) )
{
Gia_ObjFanin0(pObj)->Value++;
Gia_ObjFanin1(pObj)->Value++;
}
else if ( Gia_ObjIsCo(pObj) )
Gia_ObjFanin0(pObj)->Value++;
}
}
/**Function*************************************************************
Synopsis [Assigns references.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCreateRefs( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
assert( p->pRefs == NULL );
p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManForEachObj( p, pObj, i )
{
if ( Gia_ObjIsAnd(pObj) )
{
Gia_ObjRefFanin0Inc( p, pObj );
Gia_ObjRefFanin1Inc( p, pObj );
if ( Gia_ObjIsMuxId(p, i) )
Gia_ObjRefFanin2Inc( p, pObj );
}
else if ( Gia_ObjIsCo(pObj) )
Gia_ObjRefFanin0Inc( p, pObj );
}
}
/**Function*************************************************************
Synopsis [Assigns references.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int * Gia_ManCreateMuxRefs( Gia_Man_t * p )
{
Gia_Obj_t * pObj, * pCtrl, * pFan0, * pFan1;
int i, * pMuxRefs;
pMuxRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
Gia_ManForEachObj( p, pObj, i )
{
if ( Gia_ObjRecognizeExor( pObj, &pFan0, &pFan1 ) )
continue;
if ( !Gia_ObjIsMuxType(pObj) )
continue;
pCtrl = Gia_ObjRecognizeMux( pObj, &pFan0, &pFan1 );
pMuxRefs[ Gia_ObjId(p, Gia_Regular(pCtrl)) ]++;
}
return pMuxRefs;
}
/**Function*************************************************************
Synopsis [Computes the maximum frontier size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManDfsForCrossCut_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
{
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return;
Gia_ObjSetTravIdCurrent(p, pObj);
if ( Gia_ObjIsCi(pObj) )
{
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
return;
}
if ( Gia_ObjIsCo(pObj) )
{
Gia_ObjFanin0(pObj)->Value++;
Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes );
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
return;
}
assert( Gia_ObjIsAnd(pObj) );
Gia_ObjFanin0(pObj)->Value++;
Gia_ObjFanin1(pObj)->Value++;
Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes );
Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin1(pObj), vNodes );
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
}
Vec_Int_t * Gia_ManDfsForCrossCut( Gia_Man_t * p, int fReverse )
{
Vec_Int_t * vNodes;
Gia_Obj_t * pObj;
int i;
Gia_ManCleanValue( p );
vNodes = Vec_IntAlloc( Gia_ManObjNum(p) );
Gia_ManIncrementTravId( p );
if ( fReverse )
{
Gia_ManForEachCoReverse( p, pObj, i )
if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
Gia_ManDfsForCrossCut_rec( p, pObj, vNodes );
}
else
{
Gia_ManForEachCo( p, pObj, i )
if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
Gia_ManDfsForCrossCut_rec( p, pObj, vNodes );
}
return vNodes;
}
int Gia_ManCrossCut( Gia_Man_t * p, int fReverse )
{
Vec_Int_t * vNodes;
Gia_Obj_t * pObj;
int i, nCutCur = 0, nCutMax = 0;
vNodes = Gia_ManDfsForCrossCut( p, fReverse );
Gia_ManForEachObjVec( vNodes, p, pObj, i )
{
if ( pObj->Value )
nCutCur++;
if ( nCutMax < nCutCur )
nCutMax = nCutCur;
if ( Gia_ObjIsAnd(pObj) )
{
if ( --Gia_ObjFanin0(pObj)->Value == 0 )
nCutCur--;
if ( --Gia_ObjFanin1(pObj)->Value == 0 )
nCutCur--;
}
else if ( Gia_ObjIsCo(pObj) )
{
if ( --Gia_ObjFanin0(pObj)->Value == 0 )
nCutCur--;
}
}
Vec_IntFree( vNodes );
Gia_ManForEachObj( p, pObj, i )
assert( pObj->Value == 0 );
return nCutMax;
}
/**Function*************************************************************
Synopsis [Collects PO Ids into one array.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManCollectPoIds( Gia_Man_t * p )
{
Vec_Int_t * vStart;
int Entry, i;
vStart = Vec_IntAlloc( Gia_ManPoNum(p) );
Vec_IntForEachEntryStop( p->vCos, Entry, i, Gia_ManPoNum(p) )
Vec_IntPush( vStart, Entry );
return vStart;
}
/**Function*************************************************************
Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ObjIsMuxType( Gia_Obj_t * pNode )
{
Gia_Obj_t * pNode0, * pNode1;
// check that the node is regular
assert( !Gia_IsComplement(pNode) );
// if the node is not AND, this is not MUX
if ( !Gia_ObjIsAnd(pNode) || Gia_ObjIsBuf(pNode) )
return 0;
// if the children are not complemented, this is not MUX
if ( !Gia_ObjFaninC0(pNode) || !Gia_ObjFaninC1(pNode) )
return 0;
// get children
pNode0 = Gia_ObjFanin0(pNode);
pNode1 = Gia_ObjFanin1(pNode);
// if the children are not ANDs, this is not MUX
if ( !Gia_ObjIsAnd(pNode0) || !Gia_ObjIsAnd(pNode1) )
return 0;
// otherwise the node is MUX iff it has a pair of equal grandchildren
return (Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1))) ||
(Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1))) ||
(Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1))) ||
(Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)));
}
/**Function*************************************************************
Synopsis [Recognizes what nodes are inputs of the EXOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** ppFan0, Gia_Obj_t ** ppFan1 )
{
Gia_Obj_t * p0, * p1;
assert( !Gia_IsComplement(pObj) );
if ( !Gia_ObjIsAnd(pObj) || Gia_ObjIsBuf(pObj) )
return 0;
assert( Gia_ObjIsAnd(pObj) );
p0 = Gia_ObjChild0(pObj);
p1 = Gia_ObjChild1(pObj);
if ( !Gia_IsComplement(p0) || !Gia_IsComplement(p1) )
return 0;
p0 = Gia_Regular(p0);
p1 = Gia_Regular(p1);
if ( !Gia_ObjIsAnd(p0) || !Gia_ObjIsAnd(p1) )
return 0;
if ( Gia_ObjFanin0(p0) != Gia_ObjFanin0(p1) || Gia_ObjFanin1(p0) != Gia_ObjFanin1(p1) )
return 0;
if ( Gia_ObjFaninC0(p0) == Gia_ObjFaninC0(p1) || Gia_ObjFaninC1(p0) == Gia_ObjFaninC1(p1) )
return 0;
if ( ppFan0 ) *ppFan0 = Gia_ObjChild0(p0);
if ( ppFan1 ) *ppFan1 = Gia_ObjChild1(p0);
return 1;
}
/**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 []
***********************************************************************/
Gia_Obj_t * Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE )
{
Gia_Obj_t * pNode0, * pNode1;
assert( !Gia_IsComplement(pNode) );
assert( Gia_ObjIsMuxType(pNode) );
// get children
pNode0 = Gia_ObjFanin0(pNode);
pNode1 = Gia_ObjFanin1(pNode);
// find the control variable
if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)) )
{
// if ( FrGia_IsComplement(pNode1->p2) )
if ( Gia_ObjFaninC1(pNode0) )
{ // pNode2->p2 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
*ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
return Gia_ObjChild1(pNode1);//pNode2->p2;
}
else
{ // pNode1->p2 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
*ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
return Gia_ObjChild1(pNode0);//pNode1->p2;
}
}
else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1)) )
{
// if ( FrGia_IsComplement(pNode1->p1) )
if ( Gia_ObjFaninC0(pNode0) )
{ // pNode2->p1 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
*ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
return Gia_ObjChild0(pNode1);//pNode2->p1;
}
else
{ // pNode1->p1 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
*ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
return Gia_ObjChild0(pNode0);//pNode1->p1;
}
}
else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1)) )
{
// if ( FrGia_IsComplement(pNode1->p1) )
if ( Gia_ObjFaninC0(pNode0) )
{ // pNode2->p2 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
*ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
return Gia_ObjChild1(pNode1);//pNode2->p2;
}
else
{ // pNode1->p1 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
*ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
return Gia_ObjChild0(pNode0);//pNode1->p1;
}
}
else if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1)) )
{
// if ( FrGia_IsComplement(pNode1->p2) )
if ( Gia_ObjFaninC1(pNode0) )
{ // pNode2->p1 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
*ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
return Gia_ObjChild0(pNode1);//pNode2->p1;
}
else
{ // pNode1->p2 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
*ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
return Gia_ObjChild1(pNode0);//pNode1->p2;
}
}
assert( 0 ); // this is not MUX
return NULL;
}
int Gia_ObjRecognizeMuxLits( Gia_Man_t * p, Gia_Obj_t * pNode, int * iLitT, int * iLitE )
{
Gia_Obj_t * pNodeT, * pNodeE;
Gia_Obj_t * pCtrl = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
assert( pCtrl != NULL );
*iLitT = Gia_Obj2Lit( p, pNodeT );
*iLitE = Gia_Obj2Lit( p, pNodeE );
return Gia_Obj2Lit( p, pCtrl );
}
/**Function*************************************************************
Synopsis [Dereferences the node's MFFC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_NodeDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode )
{
Gia_Obj_t * pFanin;
int Counter = 0;
if ( Gia_ObjIsCi(pNode) )
return 0;
assert( Gia_ObjIsAnd(pNode) );
pFanin = Gia_ObjFanin0(pNode);
assert( Gia_ObjRefNum(p, pFanin) > 0 );
if ( Gia_ObjRefDec(p, pFanin) == 0 )
Counter += Gia_NodeDeref_rec( p, pFanin );
pFanin = Gia_ObjFanin1(pNode);
assert( Gia_ObjRefNum(p, pFanin) > 0 );
if ( Gia_ObjRefDec(p, pFanin) == 0 )
Counter += Gia_NodeDeref_rec( p, pFanin );
return Counter + 1;
}
/**Function*************************************************************
Synopsis [References the node's MFFC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode )
{
Gia_Obj_t * pFanin;
int Counter = 0;
if ( Gia_ObjIsCi(pNode) )
return 0;
assert( Gia_ObjIsAnd(pNode) );
pFanin = Gia_ObjFanin0(pNode);
if ( Gia_ObjRefInc(p, pFanin) == 0 )
Counter += Gia_NodeRef_rec( p, pFanin );
pFanin = Gia_ObjFanin1(pNode);
if ( Gia_ObjRefInc(p, pFanin) == 0 )
Counter += Gia_NodeRef_rec( p, pFanin );
return Counter + 1;
}
/**Function*************************************************************
Synopsis [References the node's MFFC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManPoMffcSize( Gia_Man_t * p )
{
Gia_ManCreateRefs( p );
return Gia_NodeDeref_rec( p, Gia_ObjFanin0(Gia_ManPo(p, 0)) );
}
/**Function*************************************************************
Synopsis [Returns the number of internal nodes in the MFFC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode )
{
int ConeSize1, ConeSize2;
assert( !Gia_IsComplement(pNode) );
assert( Gia_ObjIsCand(pNode) );
ConeSize1 = Gia_NodeDeref_rec( p, pNode );
ConeSize2 = Gia_NodeRef_rec( p, pNode );
assert( ConeSize1 == ConeSize2 );
assert( ConeSize1 >= 0 );
return ConeSize1;
}
/**Function*************************************************************
Synopsis [Returns the number of internal nodes in the MFFC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_NodeCollect_rec( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp )
{
if ( Gia_ObjIsTravIdCurrent(p, pNode) )
return;
Gia_ObjSetTravIdCurrent(p, pNode);
if ( Gia_ObjRefNum(p, pNode) || Gia_ObjIsCi(pNode) )
{
Vec_IntPush( vSupp, Gia_ObjId(p, pNode) );
return;
}
assert( Gia_ObjIsAnd(pNode) );
Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp );
Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp );
}
int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp )
{
int ConeSize1, ConeSize2;
assert( !Gia_IsComplement(pNode) );
assert( Gia_ObjIsAnd(pNode) );
Vec_IntClear( vSupp );
Gia_ManIncrementTravId( p );
ConeSize1 = Gia_NodeDeref_rec( p, pNode );
Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp );
Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp );
ConeSize2 = Gia_NodeRef_rec( p, pNode );
assert( ConeSize1 == ConeSize2 );
assert( ConeSize1 >= 0 );
return ConeSize1;
}
/**Function*************************************************************
Synopsis [Returns 1 if AIG has dangling nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHasDangling( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, Counter = 0;
Gia_ManForEachObj( p, pObj, i )
{
pObj->fMark0 = 0;
if ( Gia_ObjIsCo(pObj) )
Gia_ObjFanin0(pObj)->fMark0 = 1;
else if ( Gia_ObjIsMux(p, pObj) )
{
Gia_ObjFanin0(pObj)->fMark0 = 1;
Gia_ObjFanin1(pObj)->fMark0 = 1;
Gia_ObjFanin2(p, pObj)->fMark0 = 1;
}
else if ( Gia_ObjIsAnd(pObj) )
{
Gia_ObjFanin0(pObj)->fMark0 = 1;
Gia_ObjFanin1(pObj)->fMark0 = 1;
}
}
Gia_ManForEachAnd( p, pObj, i )
Counter += !pObj->fMark0;
Gia_ManCleanMark0( p );
return Counter;
}
/**Function*************************************************************
Synopsis [Returns 1 if AIG has dangling nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManMarkDangling( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, Counter = 0;
Gia_ManForEachObj( p, pObj, i )
{
pObj->fMark0 = 0;
if ( Gia_ObjIsAnd(pObj) )
{
Gia_ObjFanin0(pObj)->fMark0 = 1;
Gia_ObjFanin1(pObj)->fMark0 = 1;
}
else if ( Gia_ObjIsCo(pObj) )
Gia_ObjFanin0(pObj)->fMark0 = 1;
}
Gia_ManForEachAnd( p, pObj, i )
Counter += !pObj->fMark0;
return Counter;
}
/**Function*************************************************************
Synopsis [Returns 1 if AIG has dangling nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManGetDangling( Gia_Man_t * p )
{
Vec_Int_t * vDangles;
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
{
pObj->fMark0 = 0;
if ( Gia_ObjIsAnd(pObj) )
{
Gia_ObjFanin0(pObj)->fMark0 = 1;
Gia_ObjFanin1(pObj)->fMark0 = 1;
}
else if ( Gia_ObjIsCo(pObj) )
Gia_ObjFanin0(pObj)->fMark0 = 1;
}
vDangles = Vec_IntAlloc( 100 );
Gia_ManForEachAnd( p, pObj, i )
if ( !pObj->fMark0 )
Vec_IntPush( vDangles, i );
Gia_ManCleanMark0( p );
return vDangles;
}
/**Function*************************************************************
Synopsis [Verbose printing of the AIG node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ObjPrint( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( pObj == NULL )
{
printf( "Object is NULL." );
return;
}
if ( Gia_IsComplement(pObj) )
{
printf( "Compl " );
pObj = Gia_Not(pObj);
}
assert( !Gia_IsComplement(pObj) );
printf( "Obj %4d : ", Gia_ObjId(p, pObj) );
if ( Gia_ObjIsConst0(pObj) )
printf( "constant 0" );
else if ( Gia_ObjIsPi(p, pObj) )
printf( "PI" );
else if ( Gia_ObjIsPo(p, pObj) )
printf( "PO( %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") );
else if ( Gia_ObjIsCi(pObj) )
printf( "RO( %4d%s )", Gia_ObjFaninId0p(p, Gia_ObjRoToRi(p, pObj)), (Gia_ObjFaninC0(Gia_ObjRoToRi(p, pObj))? "\'" : " ") );
else if ( Gia_ObjIsCo(pObj) )
printf( "RI( %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") );
// else if ( Gia_ObjIsBuf(pObj) )
// printf( "BUF( %d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") );
else if ( Gia_ObjIsXor(pObj) )
printf( "XOR( %4d%s, %4d%s )",
Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " "),
Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " ") );
else if ( Gia_ObjIsMuxId(p, Gia_ObjId(p, pObj)) )
printf( "MUX( %4d%s, %4d%s, %4d%s )",
Gia_ObjFaninId2p(p, pObj), (Gia_ObjFaninC2(p, pObj)? "\'" : " "),
Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " "),
Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") );
else
printf( "AND( %4d%s, %4d%s )",
Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " "),
Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " ") );
if ( p->pRefs )
printf( " (refs = %3d)", Gia_ObjRefNum(p, pObj) );
if ( pObj->fMark0 )
printf( " mark0" );
if ( pObj->fMark1 )
printf( " mark1" );
if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, Gia_ObjId(p, pObj)) )
{
int i, iFan;
printf( " Cut = { " );
Gia_LutForEachFanin( p, Gia_ObjId(p, pObj), iFan, i )
printf( "%d ", iFan );
printf( "}" );
}
if ( Gia_ManHasMapping2(p) && Gia_ObjIsLut2(p, Gia_ObjId(p, pObj)) )
{
int i, iFan;
printf( " Cut = { " );
Gia_LutForEachFanin2( p, Gia_ObjId(p, pObj), iFan, i )
printf( "%d ", iFan );
printf( "}" );
}
printf( "\n" );
/*
if ( p->pRefs )
{
Gia_Obj_t * pFanout;
int i;
int iFan = -1; // Suppress "might be used uninitialized"
printf( "\nFanouts:\n" );
Gia_ObjForEachFanout( p, pObj, pFanout, iFan, i )
{
printf( " " );
printf( "Node %4d : ", Gia_ObjId(pFanout) );
if ( Gia_ObjIsPo(pFanout) )
printf( "PO( %4d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " ") );
else if ( Gia_ObjIsBuf(pFanout) )
printf( "BUF( %d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " ") );
else
printf( "AND( %4d%s, %4d%s )",
Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " "),
Gia_ObjFanin1(pFanout)->Id, (Gia_ObjFaninC1(pFanout)? "\'" : " ") );
printf( "\n" );
}
return;
}
*/
}
void Gia_ManPrint( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
printf( "GIA manager has %d ANDs, %d XORs, %d MUXes.\n",
Gia_ManAndNum(p) - Gia_ManXorNum(p) - Gia_ManMuxNum(p), Gia_ManXorNum(p), Gia_ManMuxNum(p) );
Gia_ManForEachObj( p, pObj, i )
Gia_ObjPrint( p, pObj );
}
void Gia_ManPrintCo_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( Gia_ObjIsAnd(pObj) )
{
Gia_ManPrintCo_rec( p, Gia_ObjFanin0(pObj) );
Gia_ManPrintCo_rec( p, Gia_ObjFanin1(pObj) );
if ( Gia_ObjIsMux(p, pObj) )
Gia_ManPrintCo_rec( p, Gia_ObjFanin2(p, pObj) );
}
Gia_ObjPrint( p, pObj );
}
void Gia_ManPrintCo( Gia_Man_t * p, Gia_Obj_t * pObj )
{
assert( Gia_ObjIsCo(pObj) );
printf( "TFI cone of CO number %d:\n", Gia_ObjCioId(pObj) );
Gia_ManPrintCo_rec( p, Gia_ObjFanin0(pObj) );
Gia_ObjPrint( p, pObj );
}
void Gia_ManPrintCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
{
if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) >= 0 )
return;
assert( Gia_ObjIsAnd(pObj) );
Gia_ManPrintCollect_rec( p, Gia_ObjFanin0(pObj), vNodes );
Gia_ManPrintCollect_rec( p, Gia_ObjFanin1(pObj), vNodes );
if ( Gia_ObjIsMux(p, pObj) )
Gia_ManPrintCollect_rec( p, Gia_ObjFanin2(p, pObj), vNodes );
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
}
void Gia_ManPrintCone( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLeaves, int nLeaves, Vec_Int_t * vNodes )
{
int i;
Vec_IntClear( vNodes );
for ( i = 0; i < nLeaves; i++ )
Vec_IntPush( vNodes, pLeaves[i] );
Gia_ManPrintCollect_rec( p, pObj, vNodes );
printf( "GIA logic cone for node %d:\n", Gia_ObjId(p, pObj) );
Gia_ManForEachObjVec( vNodes, p, pObj, i )
Gia_ObjPrint( p, pObj );
}
void Gia_ManPrintConeMulti( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Int_t * vLeaves, Vec_Int_t * vNodes )
{
Gia_Obj_t * pObj;
int i;
Vec_IntClear( vNodes );
Vec_IntAppend( vNodes, vLeaves );
Gia_ManForEachObjVec( vObjs, p, pObj, i )
Gia_ManPrintCollect_rec( p, pObj, vNodes );
printf( "GIA logic cone for %d nodes:\n", Vec_IntSize(vObjs) );
Gia_ManForEachObjVec( vNodes, p, pObj, i )
Gia_ObjPrint( p, pObj );
}
void Gia_ManPrintCollect2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes )
{
if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) >= 0 )
return;
if ( Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj) )
Gia_ManPrintCollect2_rec( p, Gia_ObjFanin0(pObj), vNodes );
if ( Gia_ObjIsAnd(pObj) )
Gia_ManPrintCollect2_rec( p, Gia_ObjFanin1(pObj), vNodes );
if ( Gia_ObjIsMux(p, pObj) )
Gia_ManPrintCollect2_rec( p, Gia_ObjFanin2(p, pObj), vNodes );
Vec_IntPush( vNodes, Gia_ObjId(p, pObj) );
}
void Gia_ManPrintCone2( Gia_Man_t * p, Gia_Obj_t * pObj )
{
Vec_Int_t * vNodes;
int i;
vNodes = Vec_IntAlloc( 100 );
Gia_ManPrintCollect2_rec( p, pObj, vNodes );
printf( "GIA logic cone for node %d:\n", Gia_ObjId(p, pObj) );
Gia_ManForEachObjVec( vNodes, p, pObj, i )
Gia_ObjPrint( p, pObj );
Vec_IntFree( vNodes );
}
/**Function*************************************************************
Synopsis [Complements the constraint outputs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManInvertConstraints( Gia_Man_t * pAig )
{
Gia_Obj_t * pObj;
int i;
if ( Gia_ManConstrNum(pAig) == 0 )
return;
Gia_ManForEachPo( pAig, pObj, i )
if ( i >= Gia_ManPoNum(pAig) - Gia_ManConstrNum(pAig) )
Gia_ObjFlipFaninC0( pObj );
}
void Gia_ManInvertPos( Gia_Man_t * pAig )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachPo( pAig, pObj, i )
Gia_ObjFlipFaninC0( pObj );
}
/**Function*************************************************************
Synopsis [Testing the speedup due to grouping POs into batches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCollectObjs_rec( Gia_Man_t * p, int iObjId, Vec_Int_t * vObjs, int Limit )
{
Gia_Obj_t * pObj;
if ( Vec_IntSize(vObjs) == Limit )
return;
if ( Gia_ObjIsTravIdCurrentId(p, iObjId) )
return;
Gia_ObjSetTravIdCurrentId(p, iObjId);
pObj = Gia_ManObj( p, iObjId );
if ( Gia_ObjIsAnd(pObj) )
{
Gia_ManCollectObjs_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, Limit );
if ( Vec_IntSize(vObjs) == Limit )
return;
Gia_ManCollectObjs_rec( p, Gia_ObjFaninId1p(p, pObj), vObjs, Limit );
if ( Vec_IntSize(vObjs) == Limit )
return;
}
Vec_IntPush( vObjs, iObjId );
}
unsigned * Gia_ManComputePoTruthTables( Gia_Man_t * p, int nBytesMax )
{
int nVars = Gia_ManPiNum(p);
int nTruthWords = Abc_TruthWordNum( nVars );
int nTruths = nBytesMax / (sizeof(unsigned) * nTruthWords);
int nTotalNodes = 0, nRounds = 0;
Vec_Int_t * vObjs;
Gia_Obj_t * pObj;
abctime clk = Abc_Clock();
int i;
printf( "Var = %d. Words = %d. Truths = %d.\n", nVars, nTruthWords, nTruths );
vObjs = Vec_IntAlloc( nTruths );
Gia_ManIncrementTravId( p );
Gia_ManForEachPo( p, pObj, i )
{
Gia_ManCollectObjs_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, nTruths );
if ( Vec_IntSize(vObjs) == nTruths )
{
nRounds++;
// printf( "%d ", i );
nTotalNodes += Vec_IntSize( vObjs );
Vec_IntClear( vObjs );
Gia_ManIncrementTravId( p );
}
}
// printf( "\n" );
nTotalNodes += Vec_IntSize( vObjs );
Vec_IntFree( vObjs );
printf( "Rounds = %d. Objects = %d. Total = %d. ", nRounds, Gia_ManObjNum(p), nTotalNodes );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
return NULL;
}
/**Function*************************************************************
Synopsis [Returns 1 if the manager are structural identical.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 )
{
Gia_Obj_t * pObj1, * pObj2;
int i;
if ( Gia_ManObjNum(p1) != Gia_ManObjNum(p2) )
{
printf( "AIGs have different number of objects.\n" );
return 0;
}
Gia_ManCleanValue( p1 );
Gia_ManCleanValue( p2 );
Gia_ManForEachObj( p1, pObj1, i )
{
pObj2 = Gia_ManObj( p2, i );
if ( memcmp( pObj1, pObj2, sizeof(Gia_Obj_t) ) )
{
printf( "Objects %d are different.\n", i );
return 0;
}
if ( p1->pReprs && p2->pReprs )
{
if ( memcmp( &p1->pReprs[i], &p2->pReprs[i], sizeof(Gia_Rpr_t) ) )
{
printf( "Representatives of objects %d are different.\n", i );
return 0;
}
}
}
return 1;
}
/**Function*************************************************************
Synopsis [Marks nodes that appear as faninis of other nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManMarkFanoutDrivers( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
{
pObj->fMark0 = 0;
if ( Gia_ObjIsAnd(pObj) )
{
Gia_ObjFanin0(pObj)->fMark0 = 1;
Gia_ObjFanin1(pObj)->fMark0 = 1;
}
else if ( Gia_ObjIsCo(pObj) )
Gia_ObjFanin0(pObj)->fMark0 = 1;
}
}
/**Function*************************************************************
Synopsis [Swaps PO number 0 with PO number i.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSwapPos( Gia_Man_t * p, int i )
{
int Lit0, LitI;
assert( i >= 0 && i < Gia_ManPoNum(p) );
if ( i == 0 )
return;
Lit0 = Gia_ObjFaninLit0p( p, Gia_ManPo(p, 0) );
LitI = Gia_ObjFaninLit0p( p, Gia_ManPo(p, i) );
Gia_ManPatchCoDriver( p, 0, LitI );
Gia_ManPatchCoDriver( p, i, Lit0 );
}
/**Function*************************************************************
Synopsis [Save/load value from file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManSaveValue( Gia_Man_t * p )
{
Vec_Int_t * vValues;
Gia_Obj_t * pObj;
int i;
vValues = Vec_IntAlloc( Gia_ManObjNum(p) );
Gia_ManForEachObj( p, pObj, i )
Vec_IntPush( vValues, pObj->Value );
return vValues;
}
void Gia_ManLoadValue( Gia_Man_t * p, Vec_Int_t * vValues )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
pObj->Value = Vec_IntEntry(vValues, i);
}
/**Function*************************************************************
Synopsis [Returns the array containing the first fanout of each object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManFirstFanouts( Gia_Man_t * p )
{
Vec_Int_t * vFans = Vec_IntStart( Gia_ManObjNum(p) );
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj( p, pObj, i )
{
if ( Gia_ObjIsAnd(pObj) )
{
if ( Vec_IntEntry(vFans, Gia_ObjFaninId0p(p, pObj)) == 0 )
Vec_IntWriteEntry(vFans, Gia_ObjFaninId0p(p, pObj), i);
if ( Vec_IntEntry(vFans, Gia_ObjFaninId1p(p, pObj)) == 0 )
Vec_IntWriteEntry(vFans, Gia_ObjFaninId1p(p, pObj), i);
if ( Gia_ObjIsMuxId(p, i) && Vec_IntEntry(vFans, Gia_ObjFaninId2p(p, pObj)) == 0 )
Vec_IntWriteEntry(vFans, Gia_ObjFaninId2p(p, pObj), i);
}
else if ( Gia_ObjIsCo(pObj) )
{
if ( Vec_IntEntry(vFans, Gia_ObjFaninId0p(p, pObj)) == 0 )
Vec_IntWriteEntry(vFans, Gia_ObjFaninId0p(p, pObj), i);
}
}
return vFans;
}
/**Function*************************************************************
Synopsis [Returns 1 if AIG has choices.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHasChoices_very_old( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, Counter1 = 0, Counter2 = 0;
int nFailNoRepr = 0;
int nFailHaveRepr = 0;
int nChoiceNodes = 0;
int nChoices = 0;
if ( p->pReprs == NULL || p->pNexts == NULL )
return 0;
// check if there are any representatives
Gia_ManForEachObj( p, pObj, i )
{
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) )
{
// printf( "%d ", i );
Counter1++;
}
// if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) )
// Counter2++;
}
// printf( "\n" );
Gia_ManForEachObj( p, pObj, i )
{
// if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) )
// Counter1++;
if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) )
{
// printf( "%d ", i );
Counter2++;
}
}
// printf( "\n" );
if ( Counter1 == 0 )
{
printf( "Warning: AIG has repr data-strucure but not reprs.\n" );
return 0;
}
printf( "%d nodes have reprs.\n", Counter1 );
printf( "%d nodes have nexts.\n", Counter2 );
// check if there are any internal nodes without fanout
// make sure all nodes without fanout have representatives
// make sure all nodes with fanout have no representatives
ABC_FREE( p->pRefs );
Gia_ManCreateRefs( p );
Gia_ManForEachAnd( p, pObj, i )
{
if ( Gia_ObjRefNum(p, pObj) == 0 )
{
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) == NULL )
nFailNoRepr++;
else
nChoices++;
}
else
{
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) != NULL )
nFailHaveRepr++;
if ( Gia_ObjNextObj( p, Gia_ObjId(p, pObj) ) != NULL )
nChoiceNodes++;
}
if ( Gia_ObjReprObj( p, i ) )
assert( Gia_ObjRepr(p, i) < i );
}
if ( nChoices == 0 )
return 0;
if ( nFailNoRepr )
{
printf( "Gia_ManHasChoices_very_old(): Error: %d internal nodes have no fanout and no repr.\n", nFailNoRepr );
// return 0;
}
if ( nFailHaveRepr )
{
printf( "Gia_ManHasChoices_very_old(): Error: %d internal nodes have both fanout and repr.\n", nFailHaveRepr );
// return 0;
}
// printf( "Gia_ManHasChoices_very_old(): AIG has %d choice nodes with %d choices.\n", nChoiceNodes, nChoices );
return 1;
}
/**Function*************************************************************
Synopsis [Proving multi-output properties.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManGroupProve( Gia_Man_t * pInit, char * pCommLine, int nGroupSize, int fVerbose )
{
Abc_Frame_t * pAbc = Abc_FrameReadGlobalFrame();
Gia_Man_t * p = Gia_ManDup( pInit );
Gia_Man_t * pGroup;
Vec_Int_t * vOuts;
Vec_Int_t * vOutMap;
Vec_Ptr_t * vCexes;
int i, k, nGroupCur, nGroups;
abctime clk, timeComm = 0;
abctime timeStart = Abc_Clock();
// pre-conditions
assert( nGroupSize > 0 );
assert( pCommLine != NULL );
assert( p->nConstrs == 0 );
Abc_Print( 1, "RUNNING MultiProve: Group size = %d. Command line = \"%s\".\n", nGroupSize, pCommLine );
// create output map
vOuts = Vec_IntStartNatural( Gia_ManPoNum(p) );
vOutMap = Vec_IntAlloc( Gia_ManPoNum(p) );
vCexes = Vec_PtrAlloc( Gia_ManPoNum(p) );
nGroups = Gia_ManPoNum(p) / nGroupSize + (int)((Gia_ManPoNum(p) % nGroupSize) > 0);
for ( i = 0; i < nGroups; i++ )
{
// derive the group
nGroupCur = ((i + 1) * nGroupSize < Gia_ManPoNum(p)) ? nGroupSize : Gia_ManPoNum(p) - i * nGroupSize;
pGroup = Gia_ManDupCones( p, Vec_IntArray(vOuts) + i * nGroupSize, nGroupCur, 0 );
Abc_Print( 1, "GROUP %4d : %4d <= PoId < %4d : ", i, i * nGroupSize, i * nGroupSize + nGroupCur );
// set the current GIA
Abc_FrameUpdateGia( pAbc, pGroup );
// solve the group
clk = Abc_Clock();
Cmd_CommandExecute( pAbc, pCommLine );
timeComm += Abc_Clock() - clk;
// get the solution status
if ( nGroupSize == 1 )
{
Vec_IntPush( vOutMap, Abc_FrameReadProbStatus(pAbc) );
Vec_PtrPush( vCexes, Abc_FrameReadCex(pAbc) );
}
else // if ( nGroupSize > 1 )
{
Vec_Int_t * vStatusCur = Abc_FrameReadPoStatuses( pAbc );
Vec_Ptr_t * vCexesCur = Abc_FrameReadCexVec( pAbc );
assert( vStatusCur != NULL ); // only works for "bmc3" and "pdr"
// assert( vCexesCur != NULL );
for ( k = 0; k < nGroupCur; k++ )
{
Vec_IntPush( vOutMap, Vec_IntEntry(vStatusCur, k) );
Vec_PtrPush( vCexes, vCexesCur ? Vec_PtrEntry(vCexesCur, k) : NULL );
}
}
}
assert( Vec_PtrSize(vCexes) == Gia_ManPoNum(p) );
assert( Vec_IntSize(vOutMap) == Gia_ManPoNum(p) );
// set CEXes
if ( Vec_PtrCountZero(vCexes) < Vec_PtrSize(vCexes) )
Abc_FrameReplaceCexVec( pAbc, &vCexes );
else // there is no CEXes
Vec_PtrFree( vCexes );
// report the result
Abc_Print( 1, "SUMMARY: " );
Abc_Print( 1, "Properties = %6d. ", Gia_ManPoNum(p) );
Abc_Print( 1, "UNSAT = %6d. ", Vec_IntCountEntry(vOutMap, 1) );
Abc_Print( 1, "SAT = %6d. ", Vec_IntCountEntry(vOutMap, 0) );
Abc_Print( 1, "UNDEC = %6d. ", Vec_IntCountEntry(vOutMap, -1) );
Abc_Print( 1, "\n" );
Abc_PrintTime( 1, "Command time", timeComm );
Abc_PrintTime( 1, "Total time ", Abc_Clock() - timeStart );
// cleanup
Vec_IntFree( vOuts );
Gia_ManStop( p );
return vOutMap;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManPoXSim( Gia_Man_t * p, int nFrames, int fVerbose )
{
Vec_Int_t * vRes;
Gia_Obj_t * pObj;
int f, k, nLeft = Gia_ManPoNum(p);
vRes = Vec_IntAlloc( Gia_ManPoNum(p) );
Vec_IntFill( vRes, Gia_ManPoNum(p), nFrames );
Gia_ObjTerSimSet0( Gia_ManConst0(p) );
Gia_ManForEachRi( p, pObj, k )
Gia_ObjTerSimSet0( pObj );
for ( f = 0; f < nFrames; f++ )
{
Gia_ManForEachPi( p, pObj, k )
Gia_ObjTerSimSetX( pObj );
Gia_ManForEachRo( p, pObj, k )
Gia_ObjTerSimRo( p, pObj );
Gia_ManForEachAnd( p, pObj, k )
Gia_ObjTerSimAnd( pObj );
Gia_ManForEachCo( p, pObj, k )
Gia_ObjTerSimCo( pObj );
if ( fVerbose )
{
Gia_ManForEachPo( p, pObj, k )
Gia_ObjTerSimPrint( pObj );
printf( "\n" );
}
Gia_ManForEachPo( p, pObj, k )
if ( Vec_IntEntry(vRes, k) == nFrames && Gia_ObjTerSimGetX(pObj) )
Vec_IntWriteEntry(vRes, k, f), nLeft--;
if ( nLeft == 0 )
break;
}
if ( fVerbose )
{
if ( nLeft == 0 )
printf( "Simulation converged after %d frames.\n", f+1 );
else
printf( "Simulation terminated after %d frames.\n", nFrames );
}
// Vec_IntPrint( vRes );
return vRes;
}
#define MAX_LUT_SIZE 8
typedef struct Gia_MapLut_t_
{
int Type; // node type: PI=1, PO=2, LUT=3
int Out; // ID
int StartId; // -1
int nFans; // fanin count
float Delay; // 0.0
int pFans[MAX_LUT_SIZE]; // fanin IDs
unsigned pTruth[MAX_LUT_SIZE<6?1:(1<<(MAX_LUT_SIZE-5))]; // the truth table
} Gia_MapLut_t;
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_AigerWriteLut( Gia_Man_t * p, char * pFileName )
{
Gia_Obj_t * pObj;
int i, k, iFan, iLut = 0;
int LutSizeMax = Gia_ManLutSizeMax( p );
int nUints = Abc_TruthWordNum(LutSizeMax);
int nLuts = 1 + Gia_ManCiNum(p) + Gia_ManCoNum(p) + Gia_ManLutNum(p);
Gia_MapLut_t * pLuts = ABC_CALLOC( Gia_MapLut_t, nLuts );
Vec_Wrd_t * vTruths = Vec_WrdStart( Gia_ManObjNum(p) );
assert( LutSizeMax <= 6 );
// set obj numbers
// constant
pLuts->Type = 3;
memset( pLuts->pTruth, 0xFF, sizeof(unsigned) * nUints );
Gia_ManFillValue(p);
Gia_ManConst0(p)->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 );
iLut++;
// inputs
Gia_ManForEachCi( p, pObj, i )
{
pLuts[iLut].Type = 1;
memset( pLuts[iLut].pTruth, 0xAA, sizeof(unsigned) * nUints );
pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 );
iLut++;
}
// nodes
Gia_ManForEachObj( p, pObj, i )
if ( i && Gia_ObjIsLut(p, i) )
{
pLuts[iLut].Type = 3;
Gia_LutForEachFanin( p, i, iFan, k )
pLuts[iLut].pFans[k] = Gia_ManObj(p, iFan)->Value;
pLuts[iLut].nFans = k;
*(word *)pLuts[iLut].pTruth = Gia_LutComputeTruth6(p, i, vTruths);
pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 );
iLut++;
}
// outputs
Gia_ManForEachCo( p, pObj, i )
{
pLuts[iLut].Type = 2;
pLuts[iLut].pFans[0] = Gia_ObjFanin0(pObj)->Value;
if ( Gia_ObjFaninC0(pObj) ^ Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
memset( pLuts[iLut].pTruth, 0x55, sizeof(unsigned) * nUints );
else
memset( pLuts[iLut].pTruth, 0xAA, sizeof(unsigned) * nUints );
pLuts[iLut].nFans = 1;
pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 );
iLut++;
}
assert( iLut == nLuts );
// dump into a file
{
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
printf( "Cannot open file \"%s\" for writing.\n", pFileName );
else
{
int nSize1 = nLuts * sizeof(Gia_MapLut_t);
int nSize2 = fwrite( pLuts, 1, nSize1, pFile );
assert( nSize1 == nSize2 );
printf( "Successfully dumped %d bytes of binary data.\n", nSize1 );
}
fclose( pFile );
}
ABC_FREE( pLuts );
Vec_WrdFree( vTruths );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_DumpLutSizeDistrib( Gia_Man_t * p, char * pFileName )
{
FILE * pTable = fopen( pFileName, "a+" );
int i, Counts[10] = {0};
Gia_ManForEachLut( p, i )
if ( Gia_ObjLutSize(p, i) > 0 && Gia_ObjLutSize(p, i) < 10 )
Counts[ Gia_ObjLutSize(p, i) ]++;
fprintf( pTable, "%s", p->pName );
for ( i = 1; i < 10; i++ )
fprintf( pTable, " %d", Counts[i] );
fprintf( pTable, "\n" );
fclose( pTable );
}
/**Function*************************************************************
Synopsis [Check if two logic cones have overlap.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCheckSuppMark_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( pObj->fMark0 )
return;
pObj->fMark0 = 1;
if ( Gia_ObjIsCi(pObj) )
return;
Gia_ManCheckSuppMark_rec( p, Gia_ObjFanin0(pObj) );
Gia_ManCheckSuppMark_rec( p, Gia_ObjFanin1(pObj) );
}
void Gia_ManCheckSuppUnmark_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( !pObj->fMark0 )
return;
pObj->fMark0 = 0;
if ( Gia_ObjIsCi(pObj) )
return;
Gia_ManCheckSuppUnmark_rec( p, Gia_ObjFanin0(pObj) );
Gia_ManCheckSuppUnmark_rec( p, Gia_ObjFanin1(pObj) );
}
int Gia_ManCheckSupp_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( pObj->fMark0 )
return 1;
if ( Gia_ObjIsCi(pObj) )
return 0;
if ( Gia_ManCheckSupp_rec( p, Gia_ObjFanin0(pObj) ) )
return 1;
return Gia_ManCheckSupp_rec( p, Gia_ObjFanin1(pObj) );
}
int Gia_ManCheckSuppOverlap( Gia_Man_t * p, int iNode1, int iNode2 )
{
int Result;
if ( iNode1 == 0 || iNode2 == 0 )
return 0;
Gia_ManCheckSuppMark_rec( p, Gia_ManObj(p, iNode1) );
Result = Gia_ManCheckSupp_rec( p, Gia_ManObj(p, iNode2) );
Gia_ManCheckSuppUnmark_rec( p, Gia_ManObj(p, iNode1) );
return Result;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END