blob: 6378e4db0f53d1a6106a3e8b7ed914ac37a368e6 [file] [log] [blame]
/**CFile****************************************************************
FileName [aigIsoFast.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [AIG package.]
Synopsis [Graph isomorphism package.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - April 28, 2007.]
Revision [$Id: aigIsoFast.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
***********************************************************************/
#include "saig.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define AIG_ISO_NUM 16
typedef struct Iso_Dat_t_ Iso_Dat_t;
struct Iso_Dat_t_
{
unsigned nFiNeg : 3;
unsigned nFoNeg : 2;
unsigned nFoPos : 2;
unsigned Fi0Lev : 3;
unsigned Fi1Lev : 3;
unsigned Level : 3;
unsigned fVisit : 16;
};
typedef struct Iso_Dat2_t_ Iso_Dat2_t;
struct Iso_Dat2_t_
{
unsigned Data : 16;
};
typedef struct Iso_Sto_t_ Iso_Sto_t;
struct Iso_Sto_t_
{
Aig_Man_t * pAig; // user's AIG manager
int nObjs; // number of objects
Iso_Dat_t * pData; // data for each object
Vec_Int_t * vVisited; // visited nodes
Vec_Ptr_t * vRoots; // root nodes
Vec_Int_t * vPlaces; // places in the counter lists
int * pCounters; // counters
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Iso_Sto_t * Iso_StoStart( Aig_Man_t * pAig )
{
Iso_Sto_t * p;
p = ABC_CALLOC( Iso_Sto_t, 1 );
p->pAig = pAig;
p->nObjs = Aig_ManObjNumMax( pAig );
p->pData = ABC_CALLOC( Iso_Dat_t, p->nObjs );
p->vVisited = Vec_IntStart( 1000 );
p->vPlaces = Vec_IntStart( 1000 );
p->vRoots = Vec_PtrStart( 1000 );
p->pCounters = ABC_CALLOC( int, (1 << AIG_ISO_NUM) );
return p;
}
void Iso_StoStop( Iso_Sto_t * p )
{
Vec_IntFree( p->vPlaces );
Vec_IntFree( p->vVisited );
Vec_PtrFree( p->vRoots );
ABC_FREE( p->pCounters );
ABC_FREE( p->pData );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Collect statistics about one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Iso_StoCollectInfo_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fCompl, Vec_Int_t * vVisited, Iso_Dat_t * pData, Vec_Ptr_t * vRoots )
{
Iso_Dat_t * pThis = pData + Aig_ObjId(pObj);
assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) );
if ( pThis->fVisit )
{
if ( fCompl )
pThis->nFoNeg++;
else
pThis->nFoPos++;
return;
}
assert( *((int *)pThis) == 0 );
pThis->fVisit = 1;
if ( fCompl )
pThis->nFoNeg++;
else
pThis->nFoPos++;
pThis->Level = pObj->Level;
pThis->nFiNeg = Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj);
if ( Aig_ObjIsNode(pObj) )
{
if ( Aig_ObjFaninC0(pObj) < Aig_ObjFaninC1(pObj) || (Aig_ObjFaninC0(pObj) == Aig_ObjFaninC1(pObj) && Aig_ObjFanin0(pObj)->Level < Aig_ObjFanin1(pObj)->Level) )
{
pThis->Fi0Lev = pObj->Level - Aig_ObjFanin0(pObj)->Level;
pThis->Fi1Lev = pObj->Level - Aig_ObjFanin1(pObj)->Level;
}
else
{
pThis->Fi0Lev = pObj->Level - Aig_ObjFanin1(pObj)->Level;
pThis->Fi1Lev = pObj->Level - Aig_ObjFanin0(pObj)->Level;
}
Iso_StoCollectInfo_rec( p, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj), vVisited, pData, vRoots );
Iso_StoCollectInfo_rec( p, Aig_ObjFanin1(pObj), Aig_ObjFaninC1(pObj), vVisited, pData, vRoots );
}
else if ( Saig_ObjIsLo(p, pObj) )
{
pThis->Fi0Lev = 1;
pThis->Fi1Lev = 0;
Vec_PtrPush( vRoots, Saig_ObjLoToLi(p, pObj) );
}
else if ( Saig_ObjIsPi(p, pObj) )
{
pThis->Fi0Lev = 0;
pThis->Fi1Lev = 0;
}
else
assert( 0 );
assert( pThis->nFoNeg + pThis->nFoPos );
Vec_IntPush( vVisited, Aig_ObjId(pObj) );
}
//static abctime time_Trav = 0;
/**Function*************************************************************
Synopsis [Collect statistics about one output.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Iso_StoCollectInfo( Iso_Sto_t * p, Aig_Obj_t * pPo )
{
int fVerboseShow = 0;
Vec_Int_t * vInfo;
Iso_Dat2_t * pData2 = (Iso_Dat2_t *)p->pData;
Aig_Man_t * pAig = p->pAig;
Aig_Obj_t * pObj;
int i, Value, Entry, * pPerm;
// abctime clk = Abc_Clock();
assert( Aig_ObjIsCo(pPo) );
// collect initial POs
Vec_IntClear( p->vVisited );
Vec_PtrClear( p->vRoots );
Vec_PtrPush( p->vRoots, pPo );
// mark internal nodes
Vec_PtrForEachEntry( Aig_Obj_t *, p->vRoots, pObj, i )
if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
Iso_StoCollectInfo_rec( pAig, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj), p->vVisited, p->pData, p->vRoots );
// time_Trav += Abc_Clock() - clk;
// count how many times each data entry appears
Vec_IntClear( p->vPlaces );
Vec_IntForEachEntry( p->vVisited, Entry, i )
{
Value = pData2[Entry].Data;
// assert( Value > 0 );
if ( p->pCounters[Value]++ == 0 )
Vec_IntPush( p->vPlaces, Value );
// pData2[Entry].Data = 0;
*((int *)(p->pData + Entry)) = 0;
}
// collect non-trivial counters
Vec_IntClear( p->vVisited );
Vec_IntForEachEntry( p->vPlaces, Entry, i )
{
assert( p->pCounters[Entry] );
Vec_IntPush( p->vVisited, p->pCounters[Entry] );
p->pCounters[Entry] = 0;
}
// printf( "%d ", Vec_IntSize(p->vVisited) );
// sort the costs in the increasing order
pPerm = Abc_MergeSortCost( Vec_IntArray(p->vVisited), Vec_IntSize(p->vVisited) );
assert( Vec_IntEntry(p->vVisited, pPerm[0]) <= Vec_IntEntry(p->vVisited, pPerm[Vec_IntSize(p->vVisited)-1]) );
// create information
vInfo = Vec_IntAlloc( Vec_IntSize(p->vVisited) );
for ( i = Vec_IntSize(p->vVisited)-1; i >= 0; i-- )
{
Entry = Vec_IntEntry( p->vVisited, pPerm[i] );
Entry = (Entry << AIG_ISO_NUM) | Vec_IntEntry( p->vPlaces, pPerm[i] );
Vec_IntPush( vInfo, Entry );
}
ABC_FREE( pPerm );
// show the final result
if ( fVerboseShow )
Vec_IntForEachEntry( vInfo, Entry, i )
{
Iso_Dat2_t Data = { Entry & 0xFFFF };
Iso_Dat_t * pData = (Iso_Dat_t *)&Data;
printf( "%6d : ", i );
printf( "Freq =%6d ", Entry >> 16 );
printf( "FiNeg =%3d ", pData->nFiNeg );
printf( "FoNeg =%3d ", pData->nFoNeg );
printf( "FoPos =%3d ", pData->nFoPos );
printf( "Fi0L =%3d ", pData->Fi0Lev );
printf( "Fi1L =%3d ", pData->Fi1Lev );
printf( "Lev =%3d ", pData->Level );
printf( "\n" );
}
return vInfo;
}
/**Function*************************************************************
Synopsis [Takes multi-output sequential AIG.]
Description [Returns candidate equivalence classes of POs.]
SideEffects []
SeeAlso []
***********************************************************************/
int Iso_StoCompareVecInt( Vec_Int_t ** p1, Vec_Int_t ** p2 )
{
return Vec_IntCompareVec( *p1, *p2 );
}
/**Function*************************************************************
Synopsis [Takes multi-output sequential AIG.]
Description [Returns candidate equivalence classes of POs.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig )
{
Iso_Sto_t * pMan;
Aig_Obj_t * pObj;
Vec_Ptr_t * vClasses, * vInfos;
Vec_Int_t * vInfo, * vPrev, * vLevel;
int i, Number, nUnique = 0;
abctime clk = Abc_Clock();
// collect infos and remember their number
pMan = Iso_StoStart( pAig );
vInfos = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
Saig_ManForEachPo( pAig, pObj, i )
{
vInfo = Iso_StoCollectInfo(pMan, pObj);
Vec_IntPush( vInfo, i );
Vec_PtrPush( vInfos, vInfo );
}
Iso_StoStop( pMan );
Abc_PrintTime( 1, "Info computation time", Abc_Clock() - clk );
// sort the infos
clk = Abc_Clock();
Vec_PtrSort( vInfos, (int (*)(void))Iso_StoCompareVecInt );
// create classes
clk = Abc_Clock();
vClasses = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
// start the first class
Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) );
vPrev = (Vec_Int_t *)Vec_PtrEntry( vInfos, 0 );
Vec_IntPush( vLevel, Vec_IntPop(vPrev) );
// consider other classes
Vec_PtrForEachEntryStart( Vec_Int_t *, vInfos, vInfo, i, 1 )
{
Number = Vec_IntPop( vInfo );
if ( Vec_IntCompareVec(vPrev, vInfo) )
Vec_PtrPush( vClasses, Vec_IntAlloc(4) );
vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses );
Vec_IntPush( vLevel, Number );
vPrev = vInfo;
}
Vec_VecFree( (Vec_Vec_t *)vInfos );
Abc_PrintTime( 1, "Sorting time", Abc_Clock() - clk );
// Abc_PrintTime( 1, "Traversal time", time_Trav );
// report the results
// Vec_VecPrintInt( (Vec_Vec_t *)vClasses );
printf( "Devided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) );
Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i )
if ( Vec_IntSize(vLevel) > 1 )
printf( "%d ", Vec_IntSize(vLevel) );
else
nUnique++;
printf( " Unique = %d\n", nUnique );
// return (Vec_Vec_t *)vClasses;
Vec_VecFree( (Vec_Vec_t *)vClasses );
return NULL;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END