blob: 59540cc2daf2627e549766186a9e4b89b081638e [file] [log] [blame]
/**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;
assert( 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