/**CFile**************************************************************** FileName [sscClass.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sweeping under constraints.] Synopsis [Equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: sscClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sscInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes hash key of the simuation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ssc_GiaSimHashKey( Gia_Man_t * p, int iObj, int nTableSize ) { static int s_Primes[16] = { 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; word * pSim = Gia_ObjSim( p, iObj ); unsigned uHash = 0; int i, nWords = Gia_ObjSimWords(p); if ( pSim[0] & 1 ) for ( i = 0; i < nWords; i++ ) uHash ^= ~pSim[i] * s_Primes[i & 0xf]; else for ( i = 0; i < nWords; i++ ) uHash ^= pSim[i] * s_Primes[i & 0xf]; return (int)(uHash % nTableSize); } /**Function************************************************************* Synopsis [Returns 1 if sim patterns are equal up to the complement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ssc_GiaSimIsConst0( Gia_Man_t * p, int iObj0 ) { int w, nWords = Gia_ObjSimWords(p); word * pSim = Gia_ObjSim( p, iObj0 ); if ( pSim[0] & 1 ) { for ( w = 0; w < nWords; w++ ) if ( ~pSim[w] ) return 0; } else { for ( w = 0; w < nWords; w++ ) if ( pSim[w] ) return 0; } return 1; } static inline int Ssc_GiaSimAreEqual( Gia_Man_t * p, int iObj0, int iObj1 ) { int w, nWords = Gia_ObjSimWords(p); word * pSim0 = Gia_ObjSim( p, iObj0 ); word * pSim1 = Gia_ObjSim( p, iObj1 ); if ( (pSim0[0] & 1) != (pSim1[0] & 1) ) { for ( w = 0; w < nWords; w++ ) if ( pSim0[w] != ~pSim1[w] ) return 0; } else { for ( w = 0; w < nWords; w++ ) if ( pSim0[w] != pSim1[w] ) return 0; } return 1; } static inline int Ssc_GiaSimAreEqualBit( Gia_Man_t * p, int iObj0, int iObj1 ) { Gia_Obj_t * pObj0 = Gia_ManObj( p, iObj0 ); Gia_Obj_t * pObj1 = Gia_ManObj( p, iObj1 ); return (pObj0->fPhase ^ pObj0->fMark0) == (pObj1->fPhase ^ pObj1->fMark0); } /**Function************************************************************* Synopsis [Refines one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_GiaSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass ) { int Repr = GIA_VOID, EntPrev = -1, Ent, i; assert( Vec_IntSize(vClass) > 0 ); Vec_IntForEachEntry( vClass, Ent, i ) { if ( i == 0 ) { Repr = Ent; Gia_ObjSetRepr( p, Ent, GIA_VOID ); EntPrev = Ent; } else { assert( Repr < Ent ); Gia_ObjSetRepr( p, Ent, Repr ); Gia_ObjSetNext( p, EntPrev, Ent ); EntPrev = Ent; } } Gia_ObjSetNext( p, EntPrev, 0 ); } /**Function************************************************************* Synopsis [Refines one equivalence class using individual bit-pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_GiaSimClassRefineOneBit( Gia_Man_t * p, int i ) { Gia_Obj_t * pObj; int Ent; assert( Gia_ObjIsHead( p, i ) ); Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Vec_IntPush( p->vClassOld, i ); pObj = Gia_ManObj(p, i); Gia_ClassForEachObj1( p, i, Ent ) { if ( Ssc_GiaSimAreEqualBit( p, i, Ent ) ) Vec_IntPush( p->vClassOld, Ent ); else Vec_IntPush( p->vClassNew, Ent ); } if ( Vec_IntSize( p->vClassNew ) == 0 ) return 0; Ssc_GiaSimClassCreate( p, p->vClassOld ); Ssc_GiaSimClassCreate( p, p->vClassNew ); return 1; } /**Function************************************************************* Synopsis [Refines one class using simulation patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_GiaSimClassRefineOne( Gia_Man_t * p, int i ) { Gia_Obj_t * pObj; int Ent; assert( Gia_ObjIsHead( p, i ) ); Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Vec_IntPush( p->vClassOld, i ); pObj = Gia_ManObj(p, i); Gia_ClassForEachObj1( p, i, Ent ) { if ( Ssc_GiaSimAreEqual( p, i, Ent ) ) Vec_IntPush( p->vClassOld, Ent ); else Vec_IntPush( p->vClassNew, Ent ); } if ( Vec_IntSize( p->vClassNew ) == 0 ) return 0; Ssc_GiaSimClassCreate( p, p->vClassOld ); Ssc_GiaSimClassCreate( p, p->vClassNew ); if ( Vec_IntSize(p->vClassNew) > 1 ) return 1 + Ssc_GiaSimClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); return 1; } void Ssc_GiaSimProcessRefined( Gia_Man_t * p, Vec_Int_t * vRefined ) { int * pTable, nTableSize, i, k, Key; if ( Vec_IntSize(vRefined) == 0 ) return; nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 3 ); pTable = ABC_CALLOC( int, nTableSize ); Vec_IntForEachEntry( vRefined, i, k ) { assert( !Ssc_GiaSimIsConst0( p, i ) ); Key = Ssc_GiaSimHashKey( p, i, nTableSize ); if ( pTable[Key] == 0 ) { assert( Gia_ObjRepr(p, i) == 0 ); assert( Gia_ObjNext(p, i) == 0 ); Gia_ObjSetRepr( p, i, GIA_VOID ); } else { Gia_ObjSetNext( p, pTable[Key], i ); Gia_ObjSetRepr( p, i, Gia_ObjRepr(p, pTable[Key]) ); if ( Gia_ObjRepr(p, i) == GIA_VOID ) Gia_ObjSetRepr( p, i, pTable[Key] ); assert( Gia_ObjRepr(p, i) > 0 ); } pTable[Key] = i; } Vec_IntForEachEntry( vRefined, i, k ) if ( Gia_ObjIsHead( p, i ) ) Ssc_GiaSimClassRefineOne( p, i ); ABC_FREE( pTable ); } /**Function************************************************************* Synopsis [Refines equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_GiaClassesInit( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; assert( p->pReprs == NULL ); p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); p->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) Gia_ObjSetRepr( p, i, Gia_ObjIsCand(pObj) ? 0 : GIA_VOID ); if ( p->vClassOld == NULL ) p->vClassOld = Vec_IntAlloc( 100 ); if ( p->vClassNew == NULL ) p->vClassNew = Vec_IntAlloc( 100 ); } int Ssc_GiaClassesRefine( Gia_Man_t * p ) { Vec_Int_t * vRefinedC; Gia_Obj_t * pObj; int i, Counter = 0; if ( p->pReprs != NULL ); vRefinedC = Vec_IntAlloc( 100 ); Gia_ManForEachCand( p, pObj, i ) if ( Gia_ObjIsTail(p, i) ) Counter += Ssc_GiaSimClassRefineOne( p, Gia_ObjRepr(p, i) ); else if ( Gia_ObjIsConst(p, i) && !Ssc_GiaSimIsConst0(p, i) ) Vec_IntPush( vRefinedC, i ); Ssc_GiaSimProcessRefined( p, vRefinedC ); Counter += Vec_IntSize( vRefinedC ); Vec_IntFree( vRefinedC ); return Counter; } /**Function************************************************************* Synopsis [Check if the pairs have been disproved.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_GiaClassesCheckPairs( Gia_Man_t * p, Vec_Int_t * vDisPairs ) { int i, iRepr, iObj, Result = 1; Vec_IntForEachEntryDouble( vDisPairs, iRepr, iObj, i ) if ( iRepr == Gia_ObjRepr(p, iObj) ) printf( "Pair (%d, %d) are still equivalent.\n", iRepr, iObj ), Result = 0; // if ( Result ) // printf( "Classes are refined correctly.\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END