| /**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 |
| |