/**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 //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Gia_IsoMan_t_ Gia_IsoMan_t; struct Gia_IsoMan_t_ { Gia_Man_t * pGia; int nObjs; int nUniques; // collected info Vec_Int_t * vLevels; Vec_Int_t * vFin0Levs; Vec_Int_t * vFin1Levs; Vec_Int_t * vFinSig; Vec_Int_t * vFoutPos; Vec_Int_t * vFoutNeg; // sorting structures Vec_Int_t * vMap; Vec_Int_t * vSeens; Vec_Int_t * vCounts; Vec_Int_t * vResult; // fanout representation Vec_Int_t * vFanout; Vec_Int_t * vFanout2; // class representation Vec_Int_t * vItems; Vec_Int_t * vUniques; Vec_Int_t * vClass; Vec_Int_t * vClass2; Vec_Int_t * vClassNew; Vec_Int_t * vLevelLim; // temporary storage Vec_Ptr_t * vRoots; Vec_Int_t * vUsed; Vec_Int_t * vRefs; // results Vec_Ptr_t * vResults; Vec_Int_t * vPermCis; Vec_Int_t * vPermCos; }; static inline int * Gia_IsoFanoutVec( Vec_Int_t * p, int Id ) { return Vec_IntEntryP( p, Vec_IntEntry(p, Id) ); } //////////////////////////////////////////////////////////////////////// /// 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 ); // collected info p->vLevels = Vec_IntAlloc( p->nObjs ); p->vFin0Levs = Vec_IntAlloc( p->nObjs ); p->vFin1Levs = Vec_IntAlloc( p->nObjs ); p->vFinSig = Vec_IntAlloc( p->nObjs ); p->vFoutPos = Vec_IntAlloc( p->nObjs ); p->vFoutNeg = Vec_IntAlloc( p->nObjs ); // sorting structures p->vMap = Vec_IntStartFull( 2*p->nObjs ); p->vSeens = Vec_IntAlloc( p->nObjs ); p->vCounts = Vec_IntAlloc( p->nObjs ); p->vResult = Vec_IntAlloc( p->nObjs ); // class representation p->vItems = Vec_IntAlloc( p->nObjs ); p->vUniques = Vec_IntAlloc( p->nObjs ); p->vClass = Vec_IntAlloc( p->nObjs/2 ); p->vClass2 = Vec_IntAlloc( p->nObjs/2 ); p->vClassNew = Vec_IntAlloc( p->nObjs/2 ); p->vLevelLim = Vec_IntAlloc( 1000 ); // fanout representation p->vFanout = Vec_IntAlloc( 6 * p->nObjs ); p->vFanout2 = Vec_IntAlloc( 0 ); // temporary storage p->vRoots = Vec_PtrAlloc( 1000 ); p->vUsed = Vec_IntAlloc( p->nObjs ); p->vRefs = Vec_IntAlloc( p->nObjs ); // results p->vResults = Vec_PtrAlloc( Gia_ManPoNum(pGia) ); p->vPermCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vPermCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); return p; } void Gia_IsoManStop( Gia_IsoMan_t * p ) { // collected info Vec_IntFree( p->vLevels ); Vec_IntFree( p->vFin0Levs ); Vec_IntFree( p->vFin1Levs ); Vec_IntFree( p->vFinSig ); Vec_IntFree( p->vFoutPos ); Vec_IntFree( p->vFoutNeg ); // sorting structures Vec_IntFree( p->vMap ); Vec_IntFree( p->vSeens ); Vec_IntFree( p->vCounts ); Vec_IntFree( p->vResult ); // class representation Vec_IntFree( p->vItems ); Vec_IntFree( p->vUniques ); Vec_IntFree( p->vClass ); Vec_IntFree( p->vClass2 ); Vec_IntFree( p->vClassNew ); Vec_IntFree( p->vLevelLim ); // fanout representation Vec_IntFree( p->vFanout ); Vec_IntFree( p->vFanout2 ); // temporary storage Vec_IntFree( p->vRefs ); Vec_IntFree( p->vUsed ); Vec_PtrFree( p->vRoots ); // results // Vec_PtrFree( p->vResults ); Vec_IntFree( p->vPermCis ); Vec_IntFree( p->vPermCos ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collect the nodes used for the given PO.] Description [Includes Const0, CI and AND nodes, no COs.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoCleanUsed( Gia_Man_t * p, Vec_Int_t * vUsed ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObjVec( vUsed, p, pObj, i ) pObj->Value = 0; } void Gia_IsoCollectUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vUsed, Vec_Ptr_t * vRoots ) { if ( pObj->Value ) return; if ( Gia_ObjIsAnd(pObj) ) { Gia_IsoCollectUsed_rec( p, Gia_ObjFanin0(pObj), vUsed, vRoots ); Gia_IsoCollectUsed_rec( p, Gia_ObjFanin1(pObj), vUsed, vRoots ); } else if ( Gia_ObjIsRo(p, pObj) ) Vec_PtrPush( vRoots, Gia_ObjRoToRi(p, pObj) ); else if ( !Gia_ObjIsPi(p, pObj) ) assert( 0 ); pObj->Value = Vec_IntSize( vUsed ); Vec_IntPush( vUsed, Gia_ObjId(p, pObj) ); } void Gia_IsoCollectUsed( Gia_Man_t * p, int iPo, Vec_Int_t * vUsed, Vec_Ptr_t * vRoots ) { Gia_Obj_t * pObj; int i; assert( iPo >= 0 && iPo < Gia_ManPoNum(p) ); Vec_PtrClear( vRoots ); Vec_PtrPush( vRoots, Gia_ManPo(p, iPo) ); // collect used nodes Vec_IntClear( vUsed ); Vec_IntPush( vUsed, 0 ); Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) Gia_IsoCollectUsed_rec( p, Gia_ObjFanin0(pObj), vUsed, vRoots ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoCreateFanout( Gia_Man_t * p, Vec_Int_t * vUsed, Vec_Int_t * vRefs, Vec_Int_t * vFanout ) { // Value of GIA objects points to the index in Used // vUsed includes only CIs and ANDs Gia_Obj_t * pObj, * pObjRi; int * pOff, * pOff0, * pOff1; int i, nOffset, Counter = 0; // count references Vec_IntFill( vRefs, Vec_IntSize(vUsed), 0 ); Gia_ManForEachObjVec( vUsed, p, pObj, i ) { if ( !i ) continue; if ( Gia_ObjIsAnd(pObj) ) { Vec_IntAddToEntry( vRefs, Gia_ObjFanin0(pObj)->Value, 1 ); Vec_IntAddToEntry( vRefs, Gia_ObjFanin1(pObj)->Value, 1 ); Counter += 2; } else if ( Gia_ObjIsRo(p, pObj) ) { pObj = Gia_ObjRoToRi(p, pObj); Vec_IntAddToEntry( vRefs, Gia_ObjFanin0(pObj)->Value, 1 ); Counter += 1; } else if ( !Gia_ObjIsPi(p, pObj) ) assert( 0 ); } // create fanout nOffset = Vec_IntSize(vUsed); Vec_IntGrowResize( vFanout, 2 * Vec_IntSize(vUsed) + 2 * Counter ); Gia_ManForEachObjVec( vUsed, p, pObj, i ) { Vec_IntWriteEntry( vFanout, i, nOffset ); Vec_IntWriteEntry( vFanout, nOffset, 0 ); nOffset += 1 + Vec_IntEntry(vRefs, pObj->Value); if ( Gia_ObjIsAnd(pObj) ) nOffset += 2; else if ( Gia_ObjIsRo(p, pObj) ) nOffset += 1; } assert( nOffset == 2 * Vec_IntSize(vUsed) + 2 * Counter ); // load fanout Gia_ManForEachObjVec( vUsed, p, pObj, i ) { pOff = Vec_IntEntryP( vFanout, Vec_IntEntry(vFanout, pObj->Value) ); if ( Gia_ObjIsAnd(pObj) ) { pOff0 = Gia_IsoFanoutVec( vFanout, Gia_ObjFanin0(pObj)->Value ); pOff1 = Gia_IsoFanoutVec( vFanout, Gia_ObjFanin1(pObj)->Value ); pOff[1+(*pOff)++] = Abc_Var2Lit( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); pOff[1+(*pOff)++] = Abc_Var2Lit( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); pOff0[1+(*pOff0)++] = Abc_Var2Lit( pObj->Value, Gia_ObjFaninC0(pObj) ); pOff1[1+(*pOff1)++] = Abc_Var2Lit( pObj->Value, Gia_ObjFaninC1(pObj) ); } else if ( Gia_ObjIsRo(p, pObj) ) { pObjRi = Gia_ObjRoToRi(p, pObj); pOff0 = Gia_IsoFanoutVec( vFanout, Gia_ObjFanin0(pObjRi)->Value ); pOff[1+(*pOff)++] = Abc_Var2Lit( Gia_ObjFanin0(pObjRi)->Value, Gia_ObjFaninC0(pObjRi) ); pOff0[1+(*pOff0)++] = Abc_Var2Lit( pObj->Value, Gia_ObjFaninC0(pObjRi) ); } } // verify Gia_ManForEachObjVec( vUsed, p, pObj, i ) { nOffset = *Gia_IsoFanoutVec( vFanout, pObj->Value ); if ( Gia_ObjIsAnd(pObj) ) nOffset -= 2; else if ( Gia_ObjIsRo(p, pObj) ) nOffset -= 1; assert( nOffset == Vec_IntEntry(vRefs, pObj->Value) ); } } /**Function************************************************************* Synopsis [Add fanouts of a new singleton object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_IsoAddSingletonFanouts( Gia_IsoMan_t * p, int Item, int Unique ) { int i, * pFan, * pFan2; pFan = Gia_IsoFanoutVec( p->vFanout, Item ); for ( i = 0; i < pFan[0]; i++ ) { if ( Vec_IntEntry( p->vUniques, Abc_Lit2Var(pFan[1+i]) ) >= 0 ) continue; pFan2 = Gia_IsoFanoutVec( p->vFanout2, Abc_Lit2Var(pFan[1+i]) ); pFan2[1+(*pFan2)++] = Abc_Var2Lit( Unique, Abc_LitIsCompl(pFan[1+i]) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoCreateFanout2( Gia_IsoMan_t * p ) { int i, Entry, nOffset, nFanouts = 0, nLeftover = 0; assert( Vec_IntSize(p->vFanout2) == 0 ); // count the number of fanouts and objects remaining Vec_IntForEachEntry( p->vUniques, Entry, i ) { if ( Entry >= 0 ) continue; nLeftover++; nFanouts += *Gia_IsoFanoutVec(p->vFanout, i); } assert( nLeftover + p->nUniques == Vec_IntSize(p->vUsed) ); // assign the fanouts nOffset = Vec_IntSize(p->vUsed); Vec_IntGrowResize( p->vFanout2, Vec_IntSize(p->vUsed) + 2 * nLeftover + nFanouts ); Vec_IntForEachEntry( p->vUniques, Entry, i ) { if ( Entry >= 0 ) continue; Vec_IntWriteEntry( p->vFanout2, i, nOffset ); Vec_IntWriteEntry( p->vFanout2, nOffset, 0 ); nOffset += 2 + *Gia_IsoFanoutVec(p->vFanout, i); } assert( nOffset == Vec_IntSize(p->vUsed) + 2 * nLeftover + nFanouts ); // add currently available items Vec_IntForEachEntry( p->vUniques, Entry, i ) { if ( Entry == -1 ) continue; Gia_IsoAddSingletonFanouts( p, i, Entry ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoCreateSigs( Gia_IsoMan_t * p ) { Gia_Obj_t * pObj, * pObjRi; int i, Lev0, Lev1, Lev; Vec_IntClear( p->vLevels ); Vec_IntClear( p->vFin0Levs ); Vec_IntClear( p->vFin1Levs ); Vec_IntClear( p->vFinSig ); Vec_IntFill( p->vFoutPos, Vec_IntSize(p->vUsed), 0 ); Vec_IntFill( p->vFoutNeg, Vec_IntSize(p->vUsed), 0 ); Gia_ManForEachObjVec( p->vUsed, p->pGia, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { Lev0 = Vec_IntEntry( p->vLevels, Gia_ObjFanin0(pObj)->Value ); Lev1 = Vec_IntEntry( p->vLevels, Gia_ObjFanin1(pObj)->Value ); Lev = 1 + Abc_MaxInt( Lev0, Lev1 ); Vec_IntPush( p->vLevels, Lev ); if ( Gia_ObjFaninC0(pObj) < Gia_ObjFaninC1(pObj) || (Gia_ObjFaninC0(pObj) == Gia_ObjFaninC1(pObj) && Lev0 < Lev1) ) { Vec_IntPush( p->vFin0Levs, Lev-Lev0 ); Vec_IntPush( p->vFin1Levs, Lev-Lev1 ); } else { Vec_IntPush( p->vFin0Levs, Lev-Lev1 ); Vec_IntPush( p->vFin1Levs, Lev-Lev0 ); } if ( Gia_ObjIsMuxType(pObj) ) // uniqify MUX/XOR Vec_IntPush( p->vFinSig, 3 ); else Vec_IntPush( p->vFinSig, Gia_ObjFaninC0(pObj) + Gia_ObjFaninC1(pObj) ); Vec_IntAddToEntry( Gia_ObjFaninC0(pObj) ? p->vFoutNeg : p->vFoutPos, Gia_ObjFanin0(pObj)->Value, 1 ); Vec_IntAddToEntry( Gia_ObjFaninC1(pObj) ? p->vFoutNeg : p->vFoutPos, Gia_ObjFanin1(pObj)->Value, 1 ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { pObjRi = Gia_ObjRoToRi(p->pGia, pObj); Vec_IntPush( p->vLevels, 0 ); Vec_IntPush( p->vFin0Levs, 1 ); // not ready yet! Vec_IntPush( p->vFin1Levs, 0 ); Vec_IntPush( p->vFinSig, Gia_ObjFaninC0(pObjRi) ); Vec_IntAddToEntry( Gia_ObjFaninC0(pObjRi) ? p->vFoutNeg : p->vFoutPos, Gia_ObjFanin0(pObjRi)->Value, 1 ); } else if ( Gia_ObjIsPi(p->pGia, pObj) ) { Vec_IntPush( p->vLevels, 0 ); Vec_IntPush( p->vFin0Levs, 0 ); Vec_IntPush( p->vFin1Levs, 0 ); Vec_IntPush( p->vFinSig, 4 ); } else if ( Gia_ObjIsConst0(pObj) ) { Vec_IntPush( p->vLevels, 0 ); Vec_IntPush( p->vFin0Levs, 0 ); Vec_IntPush( p->vFin1Levs, 0 ); Vec_IntPush( p->vFinSig, 5 ); } else assert( 0 ); } assert( Vec_IntSize( p->vLevels ) == Vec_IntSize(p->vUsed) ); assert( Vec_IntSize( p->vFin0Levs ) == Vec_IntSize(p->vUsed) ); assert( Vec_IntSize( p->vFin1Levs ) == Vec_IntSize(p->vUsed) ); assert( Vec_IntSize( p->vFinSig ) == Vec_IntSize(p->vUsed) ); // prepare items Vec_IntClear( p->vItems ); for ( i = 0; i < Vec_IntSize(p->vUsed); i++ ) Vec_IntPush( p->vItems, i ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoSortStats( Vec_Int_t * vItems, Vec_Int_t * vCosts, Vec_Int_t * vMap, Vec_Int_t * vSeens, Vec_Int_t * vCounts, Vec_Int_t * vResult ) { int i, Entry, Place; // assumes vCosts are between 0 and Vec_IntSize(vMap) // assumes vMap is clean and leaves it clean // Vec_IntForEachEntry( vMap, Entry, i ) // assert( Entry == -1 ); // printf( "vItems: " ); // Vec_IntPrint( vItems ); // printf( "vCosts: " ); // Vec_IntPrint( vCosts ); // collect places Vec_IntClear( vSeens ); Vec_IntClear( vCounts ); Vec_IntForEachEntry( vItems, Entry, i ) { Entry = Vec_IntEntry(vCosts, Entry); Place = Vec_IntEntry(vMap, Entry); if ( Place == -1 ) { Vec_IntWriteEntry( vMap, Entry, Vec_IntSize(vSeens) ); Vec_IntPush( vSeens, Entry ); Vec_IntPush( vCounts, 1 ); } else Vec_IntAddToEntry( vCounts, Place, 1 ); } // sort places Vec_IntSort( vSeens, 0 ); // printf( "vCounts: " ); // Vec_IntPrint( vCounts ); // printf( "vSeens: " ); // Vec_IntPrint( vSeens ); // create the final array Vec_IntClear( vResult ); Vec_IntForEachEntry( vSeens, Entry, i ) { Place = Vec_IntEntry( vMap, Entry ); Vec_IntPush( vResult, Entry ); Vec_IntPush( vResult, Vec_IntEntry(vCounts, Place) ); } // clean map Vec_IntForEachEntry( vSeens, Entry, i ) Vec_IntWriteEntry( vMap, Entry, -1 ); // printf( "vResult: " ); // Vec_IntPrint( vResult ); // printf( "(%d)", Vec_IntSize(vResult)/2 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_IsoCreateStats( Gia_IsoMan_t * p, int iPo ) { Vec_Int_t * vStats = Vec_IntAlloc( 1000 ); Gia_IsoCollectUsed( p->pGia, iPo, p->vUsed, p->vRoots ); Gia_IsoSortStats( p->vItems, p->vLevels, p->vMap, p->vSeens, p->vCounts, p->vResult ); Vec_IntAppend( vStats, p->vResult ); Gia_IsoSortStats( p->vItems, p->vFin0Levs, p->vMap, p->vSeens, p->vCounts, p->vResult ); Vec_IntAppend( vStats, p->vResult ); Gia_IsoSortStats( p->vItems, p->vFin1Levs, p->vMap, p->vSeens, p->vCounts, p->vResult ); Vec_IntAppend( vStats, p->vResult ); Gia_IsoSortStats( p->vItems, p->vFoutPos, p->vMap, p->vSeens, p->vCounts, p->vResult ); Vec_IntAppend( vStats, p->vResult ); Gia_IsoSortStats( p->vItems, p->vFoutNeg, p->vMap, p->vSeens, p->vCounts, p->vResult ); Vec_IntAppend( vStats, p->vResult ); Gia_IsoSortStats( p->vItems, p->vFinSig, p->vMap, p->vSeens, p->vCounts, p->vResult ); Vec_IntAppend( vStats, p->vResult ); Gia_IsoCleanUsed( p->pGia, p->vUsed ); return vStats; } /**Function************************************************************* Synopsis [Sorting an array of entries.] Description [This procedure can have the following outcomes: - There is no refinement (the class remains unchanged). - There is complete refinement (all elements became singletons) - There is partial refinement (some new classes and some singletons) The permutes set of items if returned in vItems.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoSortVec( Vec_Int_t * vItems, Vec_Int_t * vCosts, Vec_Int_t * vMap, Vec_Int_t * vSeens, Vec_Int_t * vCounts, Vec_Int_t * vResult, Vec_Int_t * vClassNew ) { int i, Entry, Entry0, Place, Counter; // assumes vCosts are between 0 and Vec_IntSize(vMap) // assumes vMap is clean and leaves it clean assert( Vec_IntSize(vItems) > 1 ); // prepare return values Vec_IntClear( vClassNew ); // collect places Vec_IntClear( vSeens ); Vec_IntClear( vCounts ); Vec_IntForEachEntry( vItems, Entry0, i ) { Entry = Vec_IntEntry(vCosts, Entry0); Place = Vec_IntEntry(vMap, Entry); if ( Place == -1 ) { Vec_IntWriteEntry( vMap, Entry, Vec_IntSize(vSeens) ); Vec_IntPush( vSeens, Entry ); Vec_IntPush( vCounts, 1 ); } else Vec_IntAddToEntry( vCounts, Place, 1 ); } // check if refinement is happening if ( Vec_IntSize(vSeens) == 1 ) // there is no refinement { Vec_IntPush( vClassNew, 0 ); Vec_IntPush( vClassNew, Vec_IntSize(vItems) ); // no need to change vItems } else // complete or partial refinement { // sort places Vec_IntSort( vSeens, 0 ); // set the map to point to the place in the final array Counter = 0; Vec_IntForEachEntry( vSeens, Entry, i ) { Place = Vec_IntEntry( vMap, Entry ); Vec_IntWriteEntry( vMap, Entry, Counter ); Vec_IntPush( vClassNew, Counter ); Vec_IntPush( vClassNew, Vec_IntEntry( vCounts, Place ) ); assert( Vec_IntEntry( vCounts, Place ) > 0 ); Counter += Vec_IntEntry( vCounts, Place ); } assert( Counter == Vec_IntSize(vItems) ); // fill the result Vec_IntGrowResize( vResult, Vec_IntSize(vItems) ); Vec_IntFill( vResult, Vec_IntSize(vItems), -1 ); // verify Vec_IntForEachEntry( vItems, Entry0, i ) { Entry = Vec_IntEntry(vCosts, Entry0); Place = Vec_IntAddToEntry( vMap, Entry, 1 ) - 1; Vec_IntWriteEntry( vResult, Place, Entry0 ); } Vec_IntForEachEntry( vResult, Entry, i ) // verify assert( Entry >= 0 ); assert( Vec_IntSize(vItems) == Vec_IntSize(vResult) ); memmove( Vec_IntArray(vItems), Vec_IntArray(vResult), sizeof(int) * Vec_IntSize(vResult) ); } // clean map Vec_IntForEachEntry( vSeens, Entry, i ) Vec_IntWriteEntry( vMap, Entry, -1 ); } /**Function************************************************************* Synopsis [Introduces a new singleton object.] Description [Updates current equivalence classes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoAddSingleton( Gia_IsoMan_t * p, int Item ) { // assign unique number assert( Vec_IntEntry( p->vUniques, Item ) == -1 ); Vec_IntWriteEntry( p->vUniques, Item, p->nUniques++ ); if ( Vec_IntSize(p->vFanout2) == 0 ) return; // create fanouts Gia_IsoAddSingletonFanouts( p, Item, p->nUniques-1 ); } /**Function************************************************************* Synopsis [Updates current equivalence classes.]] Description [ SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_IsoRefine( Gia_IsoMan_t * p, Vec_Int_t * vParam ) { Vec_Int_t vThis, * pTemp; int i, k, Begin, nSize, Begin2, nSize2, Counter = 0; assert( Vec_IntSize(p->vClass) > 0 ); assert( Vec_IntSize(p->vClass) % 2 == 0 ); Vec_IntClear( p->vClass2 ); Vec_IntForEachEntryDouble( p->vClass, Begin, nSize, i ) { vThis.nSize = vThis.nCap = nSize; vThis.pArray = Vec_IntArray(p->vItems) + Begin; Gia_IsoSortVec( &vThis, vParam, p->vMap, p->vSeens, p->vCounts, p->vResult, p->vClassNew ); Vec_IntForEachEntryDouble( p->vClassNew, Begin2, nSize2, k ) { if ( nSize2 == 1 ) { Gia_IsoAddSingleton( p, Vec_IntEntry(p->vItems, Begin+Begin2) ); Counter++; continue; } Vec_IntPush( p->vClass2, Begin+Begin2 ); Vec_IntPush( p->vClass2, nSize2 ); } } // update classes pTemp = p->vClass2; p->vClass2 = p->vClass; p->vClass = pTemp; // remember beginning of each level if ( vParam == p->vLevels ) { Vec_IntClear( p->vLevelLim ); Vec_IntForEachEntryDouble( p->vClass, Begin, nSize, i ) { assert( nSize > 0 ); assert( Vec_IntEntry(p->vLevels, Vec_IntEntry(p->vItems, Begin)) == i ); Vec_IntPush( p->vLevelLim, Begin ); } Vec_IntPush( p->vLevelLim, Vec_IntSize(p->vItems) ); } return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_IsoAssignUniqueToLastLevel( Gia_IsoMan_t * p ) { int i, Begin, End, Item, Level, Counter = 0; assert( Vec_IntSize( p->vClass ) > 0 ); // get the last unrefined class Begin = Vec_IntEntry( p->vClass, Vec_IntSize(p->vClass)-2 ); // get the last unrefined class Item = Vec_IntEntry( p->vItems, Begin ); // get the level of this class Level = Vec_IntEntry( p->vLevels, Item ); // get the first entry on this level Begin = Vec_IntEntry( p->vLevelLim, Level ); End = Vec_IntEntry( p->vLevelLim, Level+1 ); // assign all unassigned items on this level Vec_IntForEachEntryStartStop( p->vItems, Item, i, Begin, End ) if ( Vec_IntEntry( p->vUniques, Item ) == -1 ) { Gia_IsoAddSingleton( p, Item ); Counter++; } return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoPrint( Gia_IsoMan_t * p, int Iter, int nSingles, int Time ) { printf( "Iter %3d : ", Iter ); printf( "Classes =%7d. ", Vec_IntSize(p->vClass)/2 ); printf( "Uniques =%7d. ", p->nUniques ); printf( "Singles =%7d. ", nSingles ); Abc_PrintTime( 1, "Time", Time ); } /**Function************************************************************* Synopsis [Compares two objects by their ID.] 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( Gia_ObjIsTerm(pObj1) && Gia_ObjIsTerm(pObj2) ); return pObj1->Value - pObj2->Value; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoCreateUniques( Gia_IsoMan_t * p, int iPo ) { Vec_Int_t * vArray[6] = { p->vLevels, p->vFin0Levs, p->vFin1Levs, p->vFoutPos, p->vFoutNeg, p->vFinSig }; int i, nSingles, clk = clock(); Gia_IsoCollectUsed( p->pGia, iPo, p->vUsed, p->vRoots ); Vec_IntClear( p->vFanout2 ); // prepare uniques p->nUniques = 0; Vec_IntFill( p->vUniques, Vec_IntSize(p->vUsed), -1 ); Gia_IsoAddSingleton( p, 0 ); // prepare classes Vec_IntClear( p->vClass ); Vec_IntPush( p->vClass, 1 ); Vec_IntPush( p->vClass, Vec_IntSize(p->vUsed) ); // perform refinement Gia_IsoPrint( p, 0, 0, clock() - clk ); for ( i = 0; i < 6; i++ ) { nSingles = Gia_IsoRefine( p, vArray[i] ); Gia_IsoPrint( p, i+1, nSingles, clock() - clk ); } // derive fanouts Gia_IsoCreateFanout( p->pGia, p->vUsed, p->vRefs, p->vFanout ); Gia_IsoCreateFanout2( p ); // perform refinement for ( i = 6; p->nUniques < Vec_IntSize(p->vUsed); i++ ) { nSingles = Gia_IsoRefine( p, NULL ); Gia_IsoPrint( p, i+1, nSingles, clock() - clk ); if ( nSingles == 0 ) { nSingles = Gia_IsoAssignUniqueToLastLevel( p ); Gia_IsoPrint( p, i+1, nSingles, clock() - clk ); } } // finished refinement Gia_IsoCleanUsed( p->pGia, p->vUsed ); } /**Function************************************************************* Synopsis [Returns canonical permutation of the inputs.] Description [Assumes that each CI/AND object has its unique number set.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFindIsoPermCis( Gia_Man_t * p, Vec_Ptr_t * vTemp, Vec_Int_t * vRes ) { Gia_Obj_t * pObj; int i; Vec_IntClear( vRes ); // 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( vRes, Gia_ObjCioId(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( vRes, Gia_ObjCioId(pObj) ); } /**Function************************************************************* Synopsis [Find the canonical permutation of the COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFindIsoPermCos( Gia_Man_t * p, Vec_Int_t * vPermCis, Vec_Ptr_t * vTemp, Vec_Int_t * vRes ) { Gia_Obj_t * pObj; int i, Entry, Diff; assert( Vec_IntSize(vPermCis) == Gia_ManCiNum(p) ); Vec_IntClear( vRes ); if ( Gia_ManPoNum(p) == 1 ) Vec_IntPush( vRes, 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( vRes, Gia_ObjCioId(pObj) ); } // add flop outputs Diff = Gia_ManPoNum(p) - Gia_ManPiNum(p); Vec_IntForEachEntryStart( vPermCis, Entry, i, Gia_ManPiNum(p) ) Vec_IntPush( vRes, Entry + Diff ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupCanonical( Gia_Man_t * p, Vec_Int_t * vUsed, Vec_Int_t * vUniques ) { return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_IsoCompareVecStr( Vec_Str_t ** p1, Vec_Str_t ** p2 ) { return Vec_StrCompareVec( *p1, *p2 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoTest( Gia_Man_t * pGia ) { int fVerbose = 0; Vec_Ptr_t * vResults; Vec_Int_t * vStats; Gia_IsoMan_t * p; int i, clk = clock(); Gia_ManCleanValue( pGia ); p = Gia_IsoManStart( pGia ); for ( i = 0; i < Gia_ManPoNum(pGia); i++ ) { if ( i % 100 == 0 ) printf( "Finished %5d\r", i ); vStats = Gia_IsoCreateStats( p, i ); Vec_PtrPush( p->vResults, vStats ); if ( fVerbose ) printf( "%d ", Vec_IntSize(vStats)/2 ); } if ( fVerbose ) printf( " \n" ); vResults = p->vResults; p->vResults = NULL; Gia_IsoManStop( p ); // return vResults; Vec_VecFree( (Vec_Vec_t *)vResults ); Abc_PrintTime( 1, "Time", clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_IsoFilterPos( Gia_Man_t * pGia, int fVerbose ) { int fVeryVerbose = 0; Gia_IsoMan_t * p; Gia_Man_t * pTemp; Vec_Ptr_t * vBuffers, * vClasses; Vec_Int_t * vLevel, * vRemain; Vec_Str_t * vStr, * vPrev; int i, nUnique = 0, clk = clock(); int clkAig = 0, clkIso = 0, clk2; // start the manager Gia_ManCleanValue( pGia ); p = Gia_IsoManStart( pGia ); // derive AIG for each PO vBuffers = Vec_PtrAlloc( Gia_ManPoNum(pGia) ); for ( i = 0; i < Gia_ManPoNum(pGia); i++ ) { if ( i % 100 == 0 ) printf( "%6d finished...\r", i ); clk2 = clock(); pTemp = Gia_ManDupCanonical( pGia, p->vUsed, p->vUniques ); clkIso += clock() - clk2; clk2 = clock(); vStr = Gia_WriteAigerIntoMemoryStr( pTemp ); clkAig += clock() - clk2; Vec_PtrPush( vBuffers, vStr ); Gia_ManStop( pTemp ); // remember the output number in nCap (attention: hack!) vStr->nCap = i; } // stop the manager Gia_IsoManStop( p ); // s_Counter = 0; if ( fVerbose ) { Abc_PrintTime( 1, "Isomorph time", clkIso ); Abc_PrintTime( 1, "AIGER time", clkAig ); } // sort the infos clk = clock(); Vec_PtrSort( vBuffers, (int (*)(void))Gia_IsoCompareVecStr ); // create classes clk = clock(); vClasses = Vec_PtrAlloc( Gia_ManPoNum(pGia) ); // start the first class Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) ); vPrev = (Vec_Str_t *)Vec_PtrEntry( vBuffers, 0 ); Vec_IntPush( vLevel, vPrev->nCap ); // consider other classes Vec_PtrForEachEntryStart( Vec_Str_t *, vBuffers, vStr, i, 1 ) { if ( Vec_StrCompareVec(vPrev, vStr) ) Vec_PtrPush( vClasses, Vec_IntAlloc(4) ); vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses ); Vec_IntPush( vLevel, vStr->nCap ); vPrev = vStr; } Vec_VecFree( (Vec_Vec_t *)vBuffers ); if ( fVerbose ) Abc_PrintTime( 1, "Sorting time", 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", Gia_ManPoNum(pGia), Vec_PtrSize(vClasses) ); if ( fVerbose ) { 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 ); } // collect the first ones vRemain = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) ); // derive the resulting AIG pTemp = Gia_ManDupCones( pGia, Vec_IntArray(vRemain), Vec_IntSize(vRemain) ); Vec_IntFree( vRemain ); // return (Vec_Vec_t *)vClasses; Vec_VecFree( (Vec_Vec_t *)vClasses ); // printf( "The number of all checks %d. Complex checks %d.\n", nPos*(nPos-1)/2, s_Counter ); return pTemp; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END