| /**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 unsigned 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 |
| abctime timeStart; |
| abctime timeSim; |
| abctime timeRefine; |
| abctime timeSort; |
| abctime timeOther; |
| abctime 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, abctime Time ) |
| { |
| printf( "Iter %4d : ", Iter ); |
| printf( "Entries =%8d. ", p->nEntries ); |
| // printf( "Classes =%8d. ", Vec_IntSize(p->vClasses)/2 ); |
| printf( "Uniques =%8d. ", p->nUniques ); |
| 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; |
| abctime 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 = Abc_Clock(); |
| Abc_QuickSort3( p->pStoreW + iBegin, nSize, 0 ); |
| p->timeSort += Abc_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 = -1, 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; |
| abctime clk = Abc_Clock(), clkTotal = Abc_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 = Abc_Clock() - clk; |
| if ( fVerbose ) |
| Gia_IsoPrint( p, 0, Abc_Clock() - clkTotal ); |
| |
| // Gia_IsoRecognizeMuxes( pGia ); |
| |
| i = 0; |
| if ( fForward ) |
| { |
| for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 ) |
| { |
| clk = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; |
| clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; |
| if ( fVerbose ) |
| Gia_IsoPrint( p, i+1, Abc_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 = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; |
| clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; |
| if ( fVerbose ) |
| Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); |
| fRefinedAll |= fRefined; |
| } |
| for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 ) |
| { |
| clk = Abc_Clock(); Gia_IsoSimulateBack( p, i ); p->timeSim += Abc_Clock() - clk; |
| clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; |
| if ( fVerbose ) |
| Gia_IsoPrint( p, i+1, Abc_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 = Abc_Clock(); Gia_IsoSimulateBack( p, i ); p->timeSim += Abc_Clock() - clk; |
| clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; |
| if ( fVerbose ) |
| Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); |
| fRefinedAll |= fRefined; |
| } |
| for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 ) |
| { |
| clk = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; |
| clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; |
| if ( fVerbose ) |
| Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); |
| fRefinedAll |= fRefined; |
| // if ( fRefined ) |
| // printf( "Refinedment happened.\n" ); |
| } |
| } |
| } |
| |
| if ( fVerbose ) |
| Gia_IsoPrint( p, i+2, Abc_Clock() - clkTotal ); |
| } |
| // Gia_IsoPrintClasses( p ); |
| if ( fVerbose ) |
| { |
| p->timeTotal = Abc_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_Int_t ** pvPiPerm ) |
| { |
| 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) ); |
| // remember PI permutation |
| if ( pvPiPerm ) |
| { |
| *pvPiPerm = Vec_IntAlloc( Gia_ManPiNum(p) ); |
| Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) |
| Vec_IntPush( *pvPiPerm, Gia_ObjCioId(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_ManIsoCanonicize( Gia_Man_t * p, int fVerbose ) |
| { |
| Gia_Man_t * pRes = 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, NULL ); |
| // derive the new AIG |
| pRes = Gia_ManDupFromVecs( p, vCis, vAnds, vCos, Gia_ManRegNum(p) ); |
| // cleanup |
| Vec_IntFree( vCis ); |
| Vec_IntFree( vAnds ); |
| Vec_IntFree( vCos ); |
| return pRes; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Str_t * Gia_ManIsoFindString( Gia_Man_t * p, int iPo, int fVerbose, Vec_Int_t ** pvPiPerm ) |
| { |
| 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 ); |
| //Gia_ManPrint( pPart ); |
| assert( Gia_ManPoNum(pPart) == 1 ); |
| if ( Gia_ManCiNum(pPart) == 0 ) // const AIG |
| { |
| assert( Gia_ManPoNum(pPart) == 1 ); |
| assert( Gia_ManObjNum(pPart) == 2 ); |
| vStr = Gia_AigerWriteIntoMemoryStr( pPart ); |
| Gia_ManStop( pPart ); |
| if ( pvPiPerm ) |
| *pvPiPerm = Vec_IntAlloc( 0 ); |
| 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, pvPiPerm ); |
| //printf( "Internal: " ); |
| //Vec_IntPrint( vCis ); |
| // derive the AIGER string |
| vStr = Gia_AigerWriteIntoMemoryStrPart( 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 [] |
| |
| ***********************************************************************/ |
| int Vec_IntCountNonTrivial( Vec_Ptr_t * vEquivs, int * pnUsed ) |
| { |
| Vec_Int_t * vClass; |
| int i, nClasses = 0; |
| *pnUsed = 0; |
| Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vClass, i ) |
| { |
| if ( Vec_IntSize(vClass) < 2 ) |
| continue; |
| nClasses++; |
| (*pnUsed) += Vec_IntSize(vClass); |
| } |
| return nClasses; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Gia_ManIsoReduce( Gia_Man_t * pInit, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fDualOut, int fVerbose, int fVeryVerbose ) |
| { |
| 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, iPo, Counter; |
| int nClasses, nUsedPos; |
| abctime clk = Abc_Clock(); |
| if ( pvPosEquivs ) |
| *pvPosEquivs = NULL; |
| if ( pvPiPerms ) |
| *pvPiPerms = Vec_PtrStart( Gia_ManPoNum(pInit) ); |
| |
| 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; |
| } |
| nClasses = Vec_IntCountNonTrivial( vEquivs, &nUsedPos ); |
| printf( "Reduced %d outputs to %d candidate classes (%d outputs are in %d non-trivial classes). ", |
| Gia_ManPoNum(p), Vec_PtrSize(vEquivs), nUsedPos, nClasses ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| if ( fEstimate ) |
| { |
| Vec_VecFree( (Vec_Vec_t *)vEquivs ); |
| return Gia_ManDup(pInit); |
| } |
| |
| // 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; |
| } |
| |
| if ( fVerbose ) |
| { |
| iPo = Vec_IntEntry(vLevel, 0); |
| printf( "%6d %6d %6d : ", i, Vec_IntSize(vLevel), iPo ); |
| pPart = Gia_ManDupCones( p, &iPo, 1, 1 ); |
| Gia_ManPrintStats(pPart, NULL); |
| Gia_ManStop( pPart ); |
| } |
| |
| sStart = Vec_PtrSize( vEquivs2 ); |
| vStrings = Vec_PtrAlloc( 100 ); |
| Vec_IntForEachEntry( vLevel, iPo, k ) |
| { |
| if ( ++Counter % 100 == 0 ) |
| printf( "%6d finished...\r", Counter ); |
| assert( pvPiPerms == NULL || Vec_PtrArray(*pvPiPerms)[iPo] == NULL ); |
| vStr = Gia_ManIsoFindString( p, iPo, 0, pvPiPerms ? (Vec_Int_t **)Vec_PtrArray(*pvPiPerms) + iPo : NULL ); |
| |
| // printf( "Output %2d : ", iPo ); |
| // Vec_IntPrint( Vec_PtrArray(*pvPiPerms)[iPo] ); |
| |
| // 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, iPo ); |
| } |
| // if ( Vec_PtrSize(vEquivs2) - sStart > 1 ) |
| // printf( "Refined class %d into %d classes.\n", i, Vec_PtrSize(vEquivs2) - sStart ); |
| 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 |
| nClasses = Vec_IntCountNonTrivial( vEquivs, &nUsedPos ); |
| if ( !fDualOut ) |
| printf( "Reduced %d outputs to %d equivalence classes (%d outputs are in %d non-trivial classes). ", |
| Gia_ManPoNum(p), Vec_PtrSize(vEquivs), nUsedPos, nClasses ); |
| else |
| printf( "Reduced %d dual outputs to %d dual outputs. ", Gia_ManPoNum(p)/2, Gia_ManPoNum(pPart)/2 ); |
| Abc_PrintTime( 1, "Time", Abc_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_IsoTestOld( Gia_Man_t * p, int fVerbose ) |
| { |
| Vec_Ptr_t * vEquivs; |
| abctime clk = Abc_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", Abc_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 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Test remapping of CEXes for isomorphic POs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Gia_IsoTestGenPerm( int nPis ) |
| { |
| Vec_Int_t * vPerm; |
| int i, * pArray; |
| vPerm = Vec_IntStartNatural( nPis ); |
| pArray = Vec_IntArray( vPerm ); |
| for ( i = 0; i < nPis; i++ ) |
| { |
| int iNew = rand() % nPis; |
| ABC_SWAP( int, pArray[i], pArray[iNew] ); |
| } |
| return vPerm; |
| } |
| void Gia_IsoTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ) |
| { |
| Abc_Cex_t * pCexNew; |
| Vec_Int_t * vPiPerm; |
| Vec_Ptr_t * vPosEquivs, * vPisPerm; |
| Vec_Int_t * vPerm0, * vPerm1; |
| Gia_Man_t * pPerm, * pDouble, * pAig; |
| assert( Gia_ManPoNum(p) == 1 ); |
| assert( Gia_ManRegNum(p) > 0 ); |
| // generate random permutation of PIs |
| vPiPerm = Gia_IsoTestGenPerm( Gia_ManPiNum(p) ); |
| printf( "Considering random permutation of the primary inputs of the AIG:\n" ); |
| Vec_IntPrint( vPiPerm ); |
| // create AIG with two primary outputs (original and permuted) |
| pPerm = Gia_ManDupPerm( p, vPiPerm ); |
| pDouble = Gia_ManDupAppendNew( p, pPerm ); |
| //Gia_AigerWrite( pDouble, "test.aig", 0, 0 ); |
| |
| // analyze the two-output miter |
| pAig = Gia_ManIsoReduce( pDouble, &vPosEquivs, &vPisPerm, 0, 0, 0, 0 ); |
| Vec_VecFree( (Vec_Vec_t *)vPosEquivs ); |
| |
| // given CEX for output 0, derive CEX for output 1 |
| vPerm0 = (Vec_Int_t *)Vec_PtrEntry( vPisPerm, 0 ); |
| vPerm1 = (Vec_Int_t *)Vec_PtrEntry( vPisPerm, 1 ); |
| pCexNew = Abc_CexPermuteTwo( pCex, vPerm0, vPerm1 ); |
| Vec_VecFree( (Vec_Vec_t *)vPisPerm ); |
| |
| // check that original CEX and the resulting CEX is valid |
| if ( Gia_ManVerifyCex(p, pCex, 0) ) |
| printf( "CEX for the init AIG is valid.\n" ); |
| else |
| printf( "CEX for the init AIG is not valid.\n" ); |
| if ( Gia_ManVerifyCex(pPerm, pCexNew, 0) ) |
| printf( "CEX for the perm AIG is valid.\n" ); |
| else |
| printf( "CEX for the perm AIG is not valid.\n" ); |
| // delete |
| Gia_ManStop( pAig ); |
| Gia_ManStop( pDouble ); |
| Gia_ManStop( pPerm ); |
| Vec_IntFree( vPiPerm ); |
| Abc_CexFree( pCexNew ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |