mirror of https://github.com/YosysHQ/abc.git
1228 lines
40 KiB
C
1228 lines
40 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [giaIso.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Scalable AIG package.]
|
|
|
|
Synopsis [Graph isomorphism.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: giaIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "gia.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
#define ISO_MASK 0xFF
|
|
static int s_256Primes[ISO_MASK+1] =
|
|
{
|
|
0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55,
|
|
0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055,
|
|
0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120,
|
|
0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d,
|
|
0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035,
|
|
0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10,
|
|
0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6,
|
|
0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f,
|
|
0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43,
|
|
0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879,
|
|
0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba,
|
|
0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce,
|
|
0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d,
|
|
0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f,
|
|
0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb,
|
|
0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa,
|
|
0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4,
|
|
0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351,
|
|
0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09,
|
|
0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3,
|
|
0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79,
|
|
0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1,
|
|
0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74,
|
|
0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a,
|
|
0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a,
|
|
0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd,
|
|
0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c,
|
|
0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d,
|
|
0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328,
|
|
0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7,
|
|
0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0,
|
|
0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct Gia_IsoMan_t_ Gia_IsoMan_t;
|
|
struct Gia_IsoMan_t_
|
|
{
|
|
Gia_Man_t * pGia;
|
|
int nObjs;
|
|
int nUniques;
|
|
int nSingles;
|
|
int nEntries;
|
|
// internal data
|
|
int * pLevels;
|
|
int * pUniques;
|
|
word * pStoreW;
|
|
unsigned * pStoreU;
|
|
// equivalence classes
|
|
Vec_Int_t * vLevCounts;
|
|
Vec_Int_t * vClasses;
|
|
Vec_Int_t * vClasses2;
|
|
// statistics
|
|
clock_t timeStart;
|
|
clock_t timeSim;
|
|
clock_t timeRefine;
|
|
clock_t timeSort;
|
|
clock_t timeOther;
|
|
clock_t timeTotal;
|
|
};
|
|
|
|
static inline unsigned Gia_IsoGetValue( Gia_IsoMan_t * p, int i ) { return (unsigned)(p->pStoreW[i]); }
|
|
static inline unsigned Gia_IsoGetItem( Gia_IsoMan_t * p, int i ) { return (unsigned)(p->pStoreW[i] >> 32); }
|
|
|
|
static inline void Gia_IsoSetValue( Gia_IsoMan_t * p, int i, unsigned v ) { ((unsigned *)(p->pStoreW + i))[0] = v; }
|
|
static inline void Gia_IsoSetItem( Gia_IsoMan_t * p, int i, unsigned v ) { ((unsigned *)(p->pStoreW + i))[1] = v; }
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Gia_IsoMan_t * Gia_IsoManStart( Gia_Man_t * pGia )
|
|
{
|
|
Gia_IsoMan_t * p;
|
|
p = ABC_CALLOC( Gia_IsoMan_t, 1 );
|
|
p->pGia = pGia;
|
|
p->nObjs = Gia_ManObjNum( pGia );
|
|
p->nUniques = 1;
|
|
p->nEntries = p->nObjs;
|
|
// internal data
|
|
p->pLevels = ABC_CALLOC( int, p->nObjs );
|
|
p->pUniques = ABC_CALLOC( int, p->nObjs );
|
|
p->pStoreW = ABC_CALLOC( word, p->nObjs );
|
|
// class representation
|
|
p->vClasses = Vec_IntAlloc( p->nObjs/4 );
|
|
p->vClasses2 = Vec_IntAlloc( p->nObjs/4 );
|
|
return p;
|
|
}
|
|
void Gia_IsoManStop( Gia_IsoMan_t * p )
|
|
{
|
|
// class representation
|
|
Vec_IntFree( p->vClasses );
|
|
Vec_IntFree( p->vClasses2 );
|
|
// internal data
|
|
ABC_FREE( p->pLevels );
|
|
ABC_FREE( p->pUniques );
|
|
ABC_FREE( p->pStoreW );
|
|
ABC_FREE( p );
|
|
}
|
|
void Gia_IsoManTransferUnique( Gia_IsoMan_t * p )
|
|
{
|
|
Gia_Obj_t * pObj;
|
|
int i;
|
|
// copy unique numbers into the nodes
|
|
Gia_ManForEachObj( p->pGia, pObj, i )
|
|
pObj->Value = p->pUniques[i];
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_IsoPrintClasses( Gia_IsoMan_t * p )
|
|
{
|
|
int fVerbose = 0;
|
|
int i, k, iBegin, nSize;
|
|
printf( "The total of %d classes:\n", Vec_IntSize(p->vClasses)/2 );
|
|
Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
|
|
{
|
|
printf( "%5d : (%3d,%3d) ", i/2, iBegin, nSize );
|
|
if ( fVerbose )
|
|
{
|
|
printf( "{" );
|
|
for ( k = 0; k < nSize; k++ )
|
|
printf( " %3d,%08x", Gia_IsoGetItem(p, iBegin+k), Gia_IsoGetValue(p, iBegin+k) );
|
|
printf( " }" );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
}
|
|
void Gia_IsoPrint( Gia_IsoMan_t * p, int Iter, clock_t Time )
|
|
{
|
|
printf( "Iter %4d : ", Iter );
|
|
printf( "Entries =%8d. ", p->nEntries );
|
|
printf( "Classes =%8d. ", Vec_IntSize(p->vClasses)/2 );
|
|
printf( "Singles =%8d. ", p->nSingles );
|
|
printf( "%9.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC) );
|
|
printf( "\n" );
|
|
fflush( stdout );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_IsoPrepare( Gia_IsoMan_t * p )
|
|
{
|
|
Gia_Obj_t * pObj;
|
|
int * pLevBegins, * pLevSizes;
|
|
int i, iObj, MaxLev = 0;
|
|
// assign levels
|
|
p->pLevels[0] = 0;
|
|
Gia_ManForEachCi( p->pGia, pObj, i )
|
|
p->pLevels[Gia_ObjId(p->pGia, pObj)] = 0;
|
|
Gia_ManForEachAnd( p->pGia, pObj, i )
|
|
p->pLevels[i] = 1 + Abc_MaxInt( p->pLevels[Gia_ObjFaninId0(pObj, i)], p->pLevels[Gia_ObjFaninId1(pObj, i)] );
|
|
Gia_ManForEachCo( p->pGia, pObj, i )
|
|
{
|
|
iObj = Gia_ObjId(p->pGia, pObj);
|
|
p->pLevels[iObj] = 1 + p->pLevels[Gia_ObjFaninId0(pObj, iObj)]; // "1 +" is different!
|
|
MaxLev = Abc_MaxInt( MaxLev, p->pLevels[Gia_ObjId(p->pGia, pObj)] );
|
|
}
|
|
|
|
// count nodes on each level
|
|
pLevSizes = ABC_CALLOC( int, MaxLev+1 );
|
|
for ( i = 1; i < p->nObjs; i++ )
|
|
pLevSizes[p->pLevels[i]]++;
|
|
// start classes
|
|
Vec_IntClear( p->vClasses );
|
|
Vec_IntPush( p->vClasses, 0 );
|
|
Vec_IntPush( p->vClasses, 1 );
|
|
// find beginning of each level
|
|
pLevBegins = ABC_CALLOC( int, MaxLev+2 );
|
|
pLevBegins[0] = 1;
|
|
for ( i = 0; i <= MaxLev; i++ )
|
|
{
|
|
assert( pLevSizes[i] > 0 ); // we do not allow AIG with a const node and no PIs
|
|
Vec_IntPush( p->vClasses, pLevBegins[i] );
|
|
Vec_IntPush( p->vClasses, pLevSizes[i] );
|
|
pLevBegins[i+1] = pLevBegins[i] + pLevSizes[i];
|
|
}
|
|
assert( pLevBegins[MaxLev+1] == p->nObjs );
|
|
// put them into the structure
|
|
for ( i = 1; i < p->nObjs; i++ )
|
|
Gia_IsoSetItem( p, pLevBegins[p->pLevels[i]]++, i );
|
|
ABC_FREE( pLevBegins );
|
|
ABC_FREE( pLevSizes );
|
|
/*
|
|
// print the results
|
|
for ( i = 0; i < p->nObjs; i++ )
|
|
printf( "%3d : (%d,%d)\n", i, Gia_IsoGetItem(p, i), Gia_IsoGetValue(p, i) );
|
|
printf( "\n" );
|
|
*/
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_IsoAssignUnique( Gia_IsoMan_t * p )
|
|
{
|
|
int i, iBegin, nSize;
|
|
p->nSingles = 0;
|
|
Vec_IntClear( p->vClasses2 );
|
|
Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
|
|
{
|
|
if ( nSize == 1 )
|
|
{
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
|
|
p->nSingles++;
|
|
}
|
|
else
|
|
{
|
|
Vec_IntPush( p->vClasses2, iBegin );
|
|
Vec_IntPush( p->vClasses2, nSize );
|
|
}
|
|
}
|
|
ABC_SWAP( Vec_Int_t *, p->vClasses, p->vClasses2 );
|
|
p->nEntries -= p->nSingles;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Gia_IsoSort( Gia_IsoMan_t * p )
|
|
{
|
|
Gia_Obj_t * pObj, * pObj0;
|
|
int i, k, fSameValue, iBegin, iBeginOld, nSize, nSizeNew;
|
|
int fRefined = 0;
|
|
clock_t clk;
|
|
|
|
// go through the equiv classes
|
|
p->nSingles = 0;
|
|
Vec_IntClear( p->vClasses2 );
|
|
Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
|
|
{
|
|
assert( nSize > 1 );
|
|
fSameValue = 1;
|
|
pObj0 = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin) );
|
|
for ( k = 0; k < nSize; k++ )
|
|
{
|
|
pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) );
|
|
Gia_IsoSetValue( p, iBegin+k, pObj->Value );
|
|
if ( pObj->Value != pObj0->Value )
|
|
fSameValue = 0;
|
|
}
|
|
if ( fSameValue )
|
|
{
|
|
Vec_IntPush( p->vClasses2, iBegin );
|
|
Vec_IntPush( p->vClasses2, nSize );
|
|
continue;
|
|
}
|
|
fRefined = 1;
|
|
// sort objects
|
|
clk = clock();
|
|
Abc_QuickSort3( p->pStoreW + iBegin, nSize, 0 );
|
|
p->timeSort += clock() - clk;
|
|
// divide into new classes
|
|
iBeginOld = iBegin;
|
|
pObj0 = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin) );
|
|
for ( k = 1; k < nSize; k++ )
|
|
{
|
|
pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) );
|
|
if ( pObj0->Value == pObj->Value )
|
|
continue;
|
|
nSizeNew = iBegin + k - iBeginOld;
|
|
if ( nSizeNew == 1 )
|
|
{
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBeginOld)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBeginOld)] = p->nUniques++;
|
|
p->nSingles++;
|
|
}
|
|
else
|
|
{
|
|
Vec_IntPush( p->vClasses2, iBeginOld );
|
|
Vec_IntPush( p->vClasses2, nSizeNew );
|
|
}
|
|
iBeginOld = iBegin + k;
|
|
pObj0 = pObj;
|
|
}
|
|
// add the last one
|
|
nSizeNew = iBegin + k - iBeginOld;
|
|
if ( nSizeNew == 1 )
|
|
{
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBeginOld)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBeginOld)] = p->nUniques++;
|
|
p->nSingles++;
|
|
}
|
|
else
|
|
{
|
|
Vec_IntPush( p->vClasses2, iBeginOld );
|
|
Vec_IntPush( p->vClasses2, nSizeNew );
|
|
}
|
|
}
|
|
|
|
ABC_SWAP( Vec_Int_t *, p->vClasses, p->vClasses2 );
|
|
p->nEntries -= p->nSingles;
|
|
return fRefined;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Gia_IsoCollectCosClasses( Gia_IsoMan_t * p, int fVerbose )
|
|
{
|
|
Vec_Ptr_t * vGroups;
|
|
Vec_Int_t * vLevel;
|
|
Gia_Obj_t * pObj;
|
|
int i, k, iBegin, nSize;
|
|
// add singletons
|
|
vGroups = Vec_PtrAlloc( 1000 );
|
|
Gia_ManForEachPo( p->pGia, pObj, i )
|
|
if ( p->pUniques[Gia_ObjId(p->pGia, pObj)] > 0 )
|
|
{
|
|
vLevel = Vec_IntAlloc( 1 );
|
|
Vec_IntPush( vLevel, i );
|
|
Vec_PtrPush( vGroups, vLevel );
|
|
}
|
|
|
|
// add groups
|
|
Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
|
|
{
|
|
for ( k = 0; k < nSize; k++ )
|
|
{
|
|
pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) );
|
|
if ( Gia_ObjIsPo(p->pGia, pObj) )
|
|
break;
|
|
}
|
|
if ( k == nSize )
|
|
continue;
|
|
vLevel = Vec_IntAlloc( 8 );
|
|
for ( k = 0; k < nSize; k++ )
|
|
{
|
|
pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) );
|
|
if ( Gia_ObjIsPo(p->pGia, pObj) )
|
|
Vec_IntPush( vLevel, Gia_ObjCioId(pObj) );
|
|
}
|
|
Vec_PtrPush( vGroups, vLevel );
|
|
}
|
|
// canonicize order
|
|
Vec_PtrForEachEntry( Vec_Int_t *, vGroups, vLevel, i )
|
|
Vec_IntSort( vLevel, 0 );
|
|
Vec_VecSortByFirstInt( (Vec_Vec_t *)vGroups, 0 );
|
|
// Vec_VecFree( (Vec_Vec_t *)vGroups );
|
|
// return NULL;
|
|
return vGroups;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline unsigned Gia_IsoUpdateValue( int Value, int fCompl )
|
|
{
|
|
return (Value+1) * s_256Primes[Abc_Var2Lit(Value, fCompl) & ISO_MASK];
|
|
}
|
|
static inline unsigned Gia_IsoUpdate( Gia_IsoMan_t * p, int Iter, int iObj, int fCompl )
|
|
{
|
|
if ( Iter == 0 ) return Gia_IsoUpdateValue( p->pLevels[iObj], fCompl );
|
|
if ( p->pUniques[iObj] > 0 ) return Gia_IsoUpdateValue( p->pUniques[iObj], fCompl );
|
|
// if ( p->pUniques[iObj] > 0 ) return Gia_IsoUpdateValue( 11, fCompl );
|
|
return 0;
|
|
}
|
|
void Gia_IsoSimulate( Gia_IsoMan_t * p, int Iter )
|
|
{
|
|
Gia_Obj_t * pObj, * pObjF;
|
|
int i, iObj;
|
|
// initialize constant, inputs, and flops in the first frame
|
|
Gia_ManConst0(p->pGia)->Value += s_256Primes[ISO_MASK];
|
|
Gia_ManForEachPi( p->pGia, pObj, i )
|
|
pObj->Value += s_256Primes[ISO_MASK-1];
|
|
if ( Iter == 0 )
|
|
Gia_ManForEachRo( p->pGia, pObj, i )
|
|
pObj->Value += s_256Primes[ISO_MASK-2];
|
|
// simulate nodes
|
|
Gia_ManForEachAnd( p->pGia, pObj, i )
|
|
{
|
|
pObj->Value += Gia_ObjFanin0(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj));
|
|
pObj->Value += Gia_ObjFanin1(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC1(pObj));
|
|
}
|
|
// simulate COs
|
|
Gia_ManForEachCo( p->pGia, pObj, i )
|
|
{
|
|
iObj = Gia_ObjId(p->pGia, pObj);
|
|
pObj->Value += Gia_ObjFanin0(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId0(pObj, iObj), Gia_ObjFaninC0(pObj));
|
|
}
|
|
// transfer flop values
|
|
Gia_ManForEachRiRo( p->pGia, pObjF, pObj, i )
|
|
pObj->Value += pObjF->Value;
|
|
}
|
|
void Gia_IsoSimulateBack( Gia_IsoMan_t * p, int Iter )
|
|
{
|
|
Gia_Obj_t * pObj, * pObjF;
|
|
int i, iObj;
|
|
// simulate COs
|
|
Gia_ManForEachCo( p->pGia, pObj, i )
|
|
{
|
|
iObj = Gia_ObjId(p->pGia, pObj);
|
|
Gia_ObjFanin0(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, iObj, Gia_ObjFaninC0(pObj));
|
|
}
|
|
// simulate objects
|
|
Gia_ManForEachAndReverse( p->pGia, pObj, i )
|
|
{
|
|
Gia_ObjFanin0(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, i, Gia_ObjFaninC0(pObj));
|
|
Gia_ObjFanin1(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, i, Gia_ObjFaninC1(pObj));
|
|
}
|
|
// transfer flop values
|
|
Gia_ManForEachRiRo( p->pGia, pObjF, pObj, i )
|
|
pObjF->Value += pObj->Value;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_IsoAssignOneClass2( Gia_IsoMan_t * p )
|
|
{
|
|
int i, iBegin, nSize = -1;
|
|
// find two variable class
|
|
assert( Vec_IntSize(p->vClasses) > 0 );
|
|
Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
|
|
{
|
|
if ( nSize == 2 )
|
|
break;
|
|
}
|
|
assert( nSize > 1 );
|
|
|
|
if ( nSize == 2 )
|
|
{
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
|
|
p->nSingles++;
|
|
p->nEntries--;
|
|
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBegin+1)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBegin+1)] = p->nUniques++;
|
|
p->nSingles++;
|
|
p->nEntries--;
|
|
}
|
|
else
|
|
{
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
|
|
p->nSingles++;
|
|
p->nEntries--;
|
|
}
|
|
|
|
for ( ; i < Vec_IntSize(p->vClasses) - 2; i += 2 )
|
|
{
|
|
p->vClasses->pArray[i+0] = p->vClasses->pArray[i+2];
|
|
p->vClasses->pArray[i+1] = p->vClasses->pArray[i+3];
|
|
}
|
|
Vec_IntShrink( p->vClasses, Vec_IntSize(p->vClasses) - 2 );
|
|
|
|
printf( "Broke ties in class %d of size %d at level %d.\n", i/2, nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] );
|
|
}
|
|
|
|
void Gia_IsoAssignOneClass3( Gia_IsoMan_t * p )
|
|
{
|
|
int iBegin, nSize;
|
|
// find the last class
|
|
assert( Vec_IntSize(p->vClasses) > 0 );
|
|
iBegin = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 2 );
|
|
nSize = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 1 );
|
|
Vec_IntShrink( p->vClasses, Vec_IntSize(p->vClasses) - 2 );
|
|
|
|
// assign the class
|
|
assert( nSize > 1 );
|
|
if ( nSize == 2 )
|
|
{
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
|
|
p->nSingles++;
|
|
p->nEntries--;
|
|
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBegin+1)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBegin+1)] = p->nUniques++;
|
|
p->nSingles++;
|
|
p->nEntries--;
|
|
}
|
|
else
|
|
{
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++;
|
|
p->nSingles++;
|
|
p->nEntries--;
|
|
}
|
|
printf( "Broke ties in last class of size %d at level %d.\n", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] );
|
|
}
|
|
|
|
void Gia_IsoAssignOneClass( Gia_IsoMan_t * p, int fVerbose )
|
|
{
|
|
int i, k, iBegin0, iBegin, nSize, Shrink;
|
|
// find the classes with the highest level
|
|
assert( Vec_IntSize(p->vClasses) > 0 );
|
|
iBegin0 = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 2 );
|
|
for ( i = Vec_IntSize(p->vClasses) - 2; i >= 0; i -= 2 )
|
|
{
|
|
iBegin = Vec_IntEntry( p->vClasses, i );
|
|
if ( p->pLevels[Gia_IsoGetItem(p, iBegin)] != p->pLevels[Gia_IsoGetItem(p, iBegin0)] )
|
|
break;
|
|
}
|
|
i += 2;
|
|
assert( i >= 0 );
|
|
// assign all classes starting with this one
|
|
for ( Shrink = i; i < Vec_IntSize(p->vClasses); i += 2 )
|
|
{
|
|
iBegin = Vec_IntEntry( p->vClasses, i );
|
|
nSize = Vec_IntEntry( p->vClasses, i + 1 );
|
|
for ( k = 0; k < nSize; k++ )
|
|
{
|
|
assert( p->pUniques[Gia_IsoGetItem(p, iBegin+k)] == 0 );
|
|
p->pUniques[Gia_IsoGetItem(p, iBegin+k)] = p->nUniques++;
|
|
// Gia_ManObj(p->pGia, Gia_IsoGetItem(p, iBegin+k))->Value += s_256Primes[0]; /// new addition!!!
|
|
p->nSingles++;
|
|
p->nEntries--;
|
|
}
|
|
if ( fVerbose )
|
|
printf( "Broke ties in class of size %d at level %d.\n", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] );
|
|
}
|
|
Vec_IntShrink( p->vClasses, Shrink );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Report topmost equiv nodes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_IsoReportTopmost( Gia_IsoMan_t * p )
|
|
{
|
|
Gia_Obj_t * pObj;
|
|
int i, k, iBegin, nSize, Counter = 0;
|
|
// go through equivalence classes
|
|
Gia_ManIncrementTravId( p->pGia );
|
|
Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
|
|
{
|
|
// printf( "%d(%d) ", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] );
|
|
for ( k = 0; k < nSize; k++ )
|
|
{
|
|
pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p, iBegin+k) );
|
|
if ( Gia_ObjIsAnd(pObj) )
|
|
{
|
|
Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin0(pObj) );
|
|
Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin1(pObj) );
|
|
}
|
|
else if ( Gia_ObjIsRo(p->pGia, pObj) )
|
|
Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin0(Gia_ObjRoToRi(p->pGia, pObj)) );
|
|
}
|
|
}
|
|
// printf( "\n" );
|
|
|
|
// report non-labeled nodes
|
|
Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i )
|
|
{
|
|
for ( k = 0; k < nSize; k++ )
|
|
{
|
|
pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p, iBegin+k) );
|
|
if ( !Gia_ObjIsTravIdCurrent(p->pGia, pObj) )
|
|
{
|
|
printf( "%5d : ", ++Counter );
|
|
printf( "Obj %6d : Level = %4d. iBegin = %4d. Size = %4d.\n",
|
|
Gia_ObjId(p->pGia, pObj), p->pLevels[Gia_ObjId(p->pGia, pObj)], iBegin, nSize );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_IsoRecognizeMuxes( Gia_Man_t * pGia )
|
|
{
|
|
Gia_Obj_t * pObj, * pObjC, * pObj1, * pObj0;
|
|
int i;
|
|
Gia_ManForEachAnd( pGia, pObj, i )
|
|
{
|
|
if ( !Gia_ObjIsMuxType(pObj) )
|
|
continue;
|
|
pObjC = Gia_ObjRecognizeMux( pObj, &pObj1, &pObj0 );
|
|
if ( Gia_Regular(pObj0) == Gia_Regular(pObj1) )
|
|
{
|
|
// this is XOR
|
|
Gia_Regular(pObj)->Value += s_256Primes[233];
|
|
Gia_Regular(pObjC)->Value += s_256Primes[234];
|
|
Gia_Regular(pObj0)->Value += s_256Primes[234];
|
|
}
|
|
else
|
|
{
|
|
// this is MUX
|
|
Gia_Regular(pObj)->Value += s_256Primes[235];
|
|
Gia_Regular(pObjC)->Value += s_256Primes[236];
|
|
Gia_Regular(pObj0)->Value += s_256Primes[237];
|
|
Gia_Regular(pObj1)->Value += s_256Primes[237];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Gia_IsoDeriveEquivPos( Gia_Man_t * pGia, int fForward, int fVerbose )
|
|
{
|
|
int nIterMax = 10000;
|
|
int nFixedPoint = 1;
|
|
Gia_IsoMan_t * p;
|
|
Vec_Ptr_t * vEquivs = NULL;
|
|
int fRefined, fRefinedAll;
|
|
int i, c;
|
|
clock_t clk = clock(), clkTotal = clock();
|
|
assert( Gia_ManCiNum(pGia) > 0 );
|
|
assert( Gia_ManPoNum(pGia) > 0 );
|
|
|
|
Gia_ManCleanValue( pGia );
|
|
p = Gia_IsoManStart( pGia );
|
|
Gia_IsoPrepare( p );
|
|
Gia_IsoAssignUnique( p );
|
|
p->timeStart = clock() - clk;
|
|
if ( fVerbose )
|
|
Gia_IsoPrint( p, 0, clock() - clkTotal );
|
|
|
|
// Gia_IsoRecognizeMuxes( pGia );
|
|
|
|
i = 0;
|
|
if ( fForward )
|
|
{
|
|
for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 )
|
|
{
|
|
clk = clock(); Gia_IsoSimulate( p, i ); p->timeSim += clock() - clk;
|
|
clk = clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += clock() - clk;
|
|
if ( fVerbose )
|
|
Gia_IsoPrint( p, i+1, clock() - clkTotal );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while ( Vec_IntSize(p->vClasses) > 0 )
|
|
{
|
|
for ( fRefinedAll = 1; i < nIterMax && fRefinedAll; )
|
|
{
|
|
fRefinedAll = 0;
|
|
for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 )
|
|
{
|
|
clk = clock(); Gia_IsoSimulate( p, i ); p->timeSim += clock() - clk;
|
|
clk = clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += clock() - clk;
|
|
if ( fVerbose )
|
|
Gia_IsoPrint( p, i+1, clock() - clkTotal );
|
|
fRefinedAll |= fRefined;
|
|
}
|
|
for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 )
|
|
{
|
|
clk = clock(); Gia_IsoSimulateBack( p, i ); p->timeSim += clock() - clk;
|
|
clk = clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += clock() - clk;
|
|
if ( fVerbose )
|
|
Gia_IsoPrint( p, i+1, clock() - clkTotal );
|
|
fRefinedAll |= fRefined;
|
|
}
|
|
}
|
|
if ( !fRefinedAll )
|
|
break;
|
|
}
|
|
|
|
// Gia_IsoReportTopmost( p );
|
|
|
|
while ( Vec_IntSize(p->vClasses) > 0 )
|
|
{
|
|
Gia_IsoAssignOneClass( p, fVerbose );
|
|
for ( fRefinedAll = 1; i < nIterMax && fRefinedAll; )
|
|
{
|
|
fRefinedAll = 0;
|
|
for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 )
|
|
{
|
|
clk = clock(); Gia_IsoSimulateBack( p, i ); p->timeSim += clock() - clk;
|
|
clk = clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += clock() - clk;
|
|
if ( fVerbose )
|
|
Gia_IsoPrint( p, i+1, clock() - clkTotal );
|
|
fRefinedAll |= fRefined;
|
|
}
|
|
for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 )
|
|
{
|
|
clk = clock(); Gia_IsoSimulate( p, i ); p->timeSim += clock() - clk;
|
|
clk = clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += clock() - clk;
|
|
if ( fVerbose )
|
|
Gia_IsoPrint( p, i+1, clock() - clkTotal );
|
|
fRefinedAll |= fRefined;
|
|
// if ( fRefined )
|
|
// printf( "Refinedment happened.\n" );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fVerbose )
|
|
Gia_IsoPrint( p, i+2, clock() - clkTotal );
|
|
}
|
|
// Gia_IsoPrintClasses( p );
|
|
if ( fVerbose )
|
|
{
|
|
p->timeTotal = clock() - clkTotal;
|
|
p->timeOther = p->timeTotal - p->timeStart - p->timeSim - p->timeRefine;
|
|
ABC_PRTP( "Start ", p->timeStart, p->timeTotal );
|
|
ABC_PRTP( "Simulate ", p->timeSim, p->timeTotal );
|
|
ABC_PRTP( "Refine ", p->timeRefine-p->timeSort, p->timeTotal );
|
|
ABC_PRTP( "Sort ", p->timeSort, p->timeTotal );
|
|
ABC_PRTP( "Other ", p->timeOther, p->timeTotal );
|
|
ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
|
|
}
|
|
if ( Gia_ManPoNum(p->pGia) > 1 )
|
|
vEquivs = Gia_IsoCollectCosClasses( p, fVerbose );
|
|
Gia_IsoManTransferUnique( p );
|
|
Gia_IsoManStop( p );
|
|
return vEquivs;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Finds canonical ordering of CIs/COs/nodes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Gia_ObjCompareByValue( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 )
|
|
{
|
|
Gia_Obj_t * pObj1 = *pp1;
|
|
Gia_Obj_t * pObj2 = *pp2;
|
|
// assert( pObj1->Value != pObj2->Value );
|
|
return (int)pObj1->Value - (int)pObj2->Value;
|
|
}
|
|
void Gia_ManFindCaninicalOrder_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vAnds )
|
|
{
|
|
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
|
|
return;
|
|
Gia_ObjSetTravIdCurrent(p, pObj);
|
|
assert( Gia_ObjIsAnd(pObj) );
|
|
if ( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || !Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) )
|
|
{
|
|
Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds );
|
|
Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds );
|
|
}
|
|
else
|
|
{
|
|
assert( Gia_ObjFanin0(pObj)->Value != Gia_ObjFanin1(pObj)->Value );
|
|
if ( Gia_ObjFanin0(pObj)->Value < Gia_ObjFanin1(pObj)->Value )
|
|
{
|
|
Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds );
|
|
Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds );
|
|
}
|
|
else
|
|
{
|
|
Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds );
|
|
Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds );
|
|
}
|
|
}
|
|
Vec_IntPush( vAnds, Gia_ObjId(p, pObj) );
|
|
}
|
|
void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos )
|
|
{
|
|
Vec_Ptr_t * vTemp;
|
|
Gia_Obj_t * pObj;
|
|
int i;
|
|
|
|
vTemp = Vec_PtrAlloc( 1000 );
|
|
Vec_IntClear( vCis );
|
|
Vec_IntClear( vAnds );
|
|
Vec_IntClear( vCos );
|
|
|
|
// assign unique IDs to PIs
|
|
Vec_PtrClear( vTemp );
|
|
Gia_ManForEachPi( p, pObj, i )
|
|
Vec_PtrPush( vTemp, pObj );
|
|
Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue );
|
|
// create the result
|
|
Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i )
|
|
Vec_IntPush( vCis, Gia_ObjId(p, pObj) );
|
|
|
|
// assign unique IDs to POs
|
|
if ( Gia_ManPoNum(p) == 1 )
|
|
Vec_IntPush( vCos, Gia_ObjId(p, Gia_ManPo(p, 0)) );
|
|
else
|
|
{
|
|
Vec_PtrClear( vTemp );
|
|
Gia_ManForEachPo( p, pObj, i )
|
|
{
|
|
pObj->Value = Abc_Var2Lit( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) );
|
|
Vec_PtrPush( vTemp, pObj );
|
|
}
|
|
Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue );
|
|
Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i )
|
|
Vec_IntPush( vCos, Gia_ObjId(p, pObj) );
|
|
}
|
|
|
|
// assign unique IDs to ROs
|
|
Vec_PtrClear( vTemp );
|
|
Gia_ManForEachRo( p, pObj, i )
|
|
Vec_PtrPush( vTemp, pObj );
|
|
Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue );
|
|
// create the result
|
|
Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i )
|
|
{
|
|
Vec_IntPush( vCis, Gia_ObjId(p, pObj) );
|
|
Vec_IntPush( vCos, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
|
|
}
|
|
Vec_PtrFree( vTemp );
|
|
|
|
// assign unique IDs to internal nodes
|
|
Gia_ManIncrementTravId( p );
|
|
Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) );
|
|
Gia_ManForEachObjVec( vCis, p, pObj, i )
|
|
Gia_ObjSetTravIdCurrent( p, pObj );
|
|
Gia_ManForEachObjVec( vCos, p, pObj, i )
|
|
Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Gia_Man_t * Gia_ManDupFromVecs( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs )
|
|
{
|
|
Gia_Man_t * pNew;
|
|
Gia_Obj_t * pObj;
|
|
int i;
|
|
// start the new manager
|
|
pNew = Gia_ManStart( 5000 );
|
|
pNew->pName = Abc_UtilStrsav( p->pName );
|
|
// create constant
|
|
Gia_ManConst0(p)->Value = 0;
|
|
// create PIs
|
|
Gia_ManForEachObjVec( vCis, p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCi( pNew );
|
|
// create internal nodes
|
|
Gia_ManForEachObjVec( vAnds, p, pObj, i )
|
|
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
|
// create ROs
|
|
Gia_ManForEachObjVec( vCos, p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
|
Gia_ManSetRegNum( pNew, nRegs );
|
|
return pNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Gia_Man_t * Gia_ManIsoCanonicize( Gia_Man_t * p, int fVerbose )
|
|
{
|
|
Gia_Man_t * vResult = NULL;
|
|
Vec_Int_t * vCis, * vAnds, * vCos;
|
|
Vec_Ptr_t * vEquiv;
|
|
if ( Gia_ManCiNum(p) == 0 ) // const AIG
|
|
{
|
|
assert( Gia_ManPoNum(p) == 1 );
|
|
assert( Gia_ManObjNum(p) == 2 );
|
|
return Gia_ManDup(p);
|
|
}
|
|
// derive canonical values
|
|
vEquiv = Gia_IsoDeriveEquivPos( p, 0, fVerbose );
|
|
Vec_VecFreeP( (Vec_Vec_t **)&vEquiv );
|
|
// find canonical order of CIs/COs/nodes
|
|
// find canonical order
|
|
vCis = Vec_IntAlloc( Gia_ManCiNum(p) );
|
|
vAnds = Vec_IntAlloc( Gia_ManAndNum(p) );
|
|
vCos = Vec_IntAlloc( Gia_ManCoNum(p) );
|
|
Gia_ManFindCaninicalOrder( p, vCis, vAnds, vCos );
|
|
// derive the new AIG
|
|
vResult = Gia_ManDupFromVecs( p, vCis, vAnds, vCos, Gia_ManRegNum(p) );
|
|
// cleanup
|
|
Vec_IntFree( vCis );
|
|
Vec_IntFree( vAnds );
|
|
Vec_IntFree( vCos );
|
|
return vResult;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Str_t * Gia_ManIsoFindString( Gia_Man_t * p, int iPo, int fVerbose )
|
|
{
|
|
Gia_Man_t * pPart;
|
|
Vec_Ptr_t * vEquiv;
|
|
Vec_Int_t * vCis, * vAnds, * vCos;
|
|
Vec_Str_t * vStr;
|
|
// duplicate
|
|
pPart = Gia_ManDupCones( p, &iPo, 1, 1 );
|
|
assert( Gia_ManPoNum(pPart) == 1 );
|
|
if ( Gia_ManCiNum(pPart) == 0 ) // const AIG
|
|
{
|
|
assert( Gia_ManPoNum(pPart) == 1 );
|
|
assert( Gia_ManObjNum(pPart) == 2 );
|
|
vStr = Gia_WriteAigerIntoMemoryStr( pPart );
|
|
Gia_ManStop( pPart );
|
|
return vStr;
|
|
}
|
|
// derive canonical values
|
|
vEquiv = Gia_IsoDeriveEquivPos( pPart, 0, fVerbose );
|
|
Vec_VecFreeP( (Vec_Vec_t **)&vEquiv );
|
|
// find canonical order
|
|
vCis = Vec_IntAlloc( Gia_ManCiNum(pPart) );
|
|
vAnds = Vec_IntAlloc( Gia_ManAndNum(pPart) );
|
|
vCos = Vec_IntAlloc( Gia_ManCoNum(pPart) );
|
|
Gia_ManFindCaninicalOrder( pPart, vCis, vAnds, vCos );
|
|
// derive the AIGER string
|
|
vStr = Gia_WriteAigerIntoMemoryStrPart( pPart, vCis, vAnds, vCos, Gia_ManRegNum(pPart) );
|
|
// cleanup
|
|
Vec_IntFree( vCis );
|
|
Vec_IntFree( vAnds );
|
|
Vec_IntFree( vCos );
|
|
Gia_ManStop( pPart );
|
|
return vStr;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Gia_Man_t * Gia_ManIsoReduce( Gia_Man_t * pInit, Vec_Ptr_t ** pvPosEquivs, int fDualOut, int fVerbose )
|
|
{
|
|
int fVeryVerbose = 0;
|
|
Gia_Man_t * p, * pPart;
|
|
Vec_Ptr_t * vEquivs, * vEquivs2, * vStrings;
|
|
Vec_Int_t * vRemain, * vLevel, * vLevel2;
|
|
Vec_Str_t * vStr, * vStr2;
|
|
int i, k, s, sStart, Entry, Counter;
|
|
clock_t clk = clock();
|
|
if ( pvPosEquivs )
|
|
*pvPosEquivs = NULL;
|
|
|
|
if ( fDualOut )
|
|
{
|
|
assert( (Gia_ManPoNum(pInit) & 1) == 0 );
|
|
if ( Gia_ManPoNum(pInit) == 2 )
|
|
return Gia_ManDup(pInit);
|
|
p = Gia_ManTransformMiter( pInit );
|
|
p = Gia_ManSeqStructSweep( pPart = p, 1, 1, 0 );
|
|
Gia_ManStop( pPart );
|
|
}
|
|
else
|
|
{
|
|
if ( Gia_ManPoNum(pInit) == 1 )
|
|
return Gia_ManDup(pInit);
|
|
p = pInit;
|
|
}
|
|
|
|
// create preliminary equivalences
|
|
vEquivs = Gia_IsoDeriveEquivPos( p, 1, fVeryVerbose );
|
|
if ( vEquivs == NULL )
|
|
{
|
|
if ( fDualOut )
|
|
Gia_ManStop( p );
|
|
return NULL;
|
|
}
|
|
// printf( "Reduced %d outputs to %d outputs. ", Gia_ManPoNum(p), Vec_PtrSize(vEquivs) );
|
|
// Abc_PrintTime( 1, "Time", clock() - clk );
|
|
|
|
// perform refinement of equivalence classes
|
|
Counter = 0;
|
|
vEquivs2 = Vec_PtrAlloc( 100 );
|
|
Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vLevel, i )
|
|
{
|
|
if ( Vec_IntSize(vLevel) < 2 )
|
|
{
|
|
Vec_PtrPush( vEquivs2, Vec_IntDup(vLevel) );
|
|
for ( k = 0; k < Vec_IntSize(vLevel); k++ )
|
|
if ( ++Counter % 100 == 0 )
|
|
printf( "%6d finished...\r", Counter );
|
|
continue;
|
|
}
|
|
sStart = Vec_PtrSize( vEquivs2 );
|
|
vStrings = Vec_PtrAlloc( 100 );
|
|
Vec_IntForEachEntry( vLevel, Entry, k )
|
|
{
|
|
if ( ++Counter % 100 == 0 )
|
|
printf( "%6d finished...\r", Counter );
|
|
vStr = Gia_ManIsoFindString( p, Entry, 0 );
|
|
// check if this string already exists
|
|
Vec_PtrForEachEntry( Vec_Str_t *, vStrings, vStr2, s )
|
|
if ( Vec_StrCompareVec(vStr, vStr2) == 0 )
|
|
break;
|
|
if ( s == Vec_PtrSize(vStrings) )
|
|
{
|
|
Vec_PtrPush( vStrings, vStr );
|
|
Vec_PtrPush( vEquivs2, Vec_IntAlloc(8) );
|
|
}
|
|
else
|
|
Vec_StrFree( vStr );
|
|
// add this entry to the corresponding level
|
|
vLevel2 = (Vec_Int_t *)Vec_PtrEntry( vEquivs2, sStart + s );
|
|
Vec_IntPush( vLevel2, Entry );
|
|
}
|
|
Vec_VecFree( (Vec_Vec_t *)vStrings );
|
|
}
|
|
assert( Counter == Gia_ManPoNum(p) );
|
|
Vec_VecSortByFirstInt( (Vec_Vec_t *)vEquivs2, 0 );
|
|
Vec_VecFree( (Vec_Vec_t *)vEquivs );
|
|
vEquivs = vEquivs2;
|
|
|
|
// collect the first ones
|
|
vRemain = Vec_IntAlloc( 100 );
|
|
Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vLevel, i )
|
|
Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) );
|
|
|
|
if ( fDualOut )
|
|
{
|
|
Vec_Int_t * vTemp = Vec_IntAlloc( Vec_IntSize(vRemain) );
|
|
int i, Entry;
|
|
Vec_IntForEachEntry( vRemain, Entry, i )
|
|
{
|
|
// printf( "%d ", Entry );
|
|
Vec_IntPush( vTemp, 2*Entry );
|
|
Vec_IntPush( vTemp, 2*Entry+1 );
|
|
}
|
|
// printf( "\n" );
|
|
Vec_IntFree( vRemain );
|
|
vRemain = vTemp;
|
|
Gia_ManStop( p );
|
|
p = pInit;
|
|
}
|
|
|
|
|
|
// derive the resulting AIG
|
|
pPart = Gia_ManDupCones( p, Vec_IntArray(vRemain), Vec_IntSize(vRemain), 0 );
|
|
Vec_IntFree( vRemain );
|
|
// report the results
|
|
if ( !fDualOut )
|
|
printf( "Reduced %d outputs to %d outputs. ", Gia_ManPoNum(p), Gia_ManPoNum(pPart) );
|
|
else
|
|
printf( "Reduced %d dual outputs to %d dual outputs. ", Gia_ManPoNum(p)/2, Gia_ManPoNum(pPart)/2 );
|
|
Abc_PrintTime( 1, "Time", clock() - clk );
|
|
if ( fVerbose )
|
|
{
|
|
printf( "Nontrivial classes:\n" );
|
|
Vec_VecPrintInt( (Vec_Vec_t *)vEquivs, 1 );
|
|
}
|
|
if ( pvPosEquivs )
|
|
*pvPosEquivs = vEquivs;
|
|
else
|
|
Vec_VecFree( (Vec_Vec_t *)vEquivs );
|
|
// Gia_ManStopP( &pPart );
|
|
return pPart;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Gia_IsoTest( Gia_Man_t * p, int fVerbose )
|
|
{
|
|
Vec_Ptr_t * vEquivs;
|
|
clock_t clk = clock();
|
|
vEquivs = Gia_IsoDeriveEquivPos( p, 0, fVerbose );
|
|
printf( "Reduced %d outputs to %d. ", Gia_ManPoNum(p), vEquivs ? Vec_PtrSize(vEquivs) : 1 );
|
|
Abc_PrintTime( 1, "Time", clock() - clk );
|
|
if ( fVerbose && vEquivs && Gia_ManPoNum(p) != Vec_PtrSize(vEquivs) )
|
|
{
|
|
printf( "Nontrivial classes:\n" );
|
|
// Vec_VecPrintInt( (Vec_Vec_t *)vEquivs, 1 );
|
|
}
|
|
Vec_VecFreeP( (Vec_Vec_t **)&vEquivs );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|