mirror of https://github.com/YosysHQ/abc.git
957 lines
30 KiB
C
957 lines
30 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [saigSimMv.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Sequential AIG package.]
|
|
|
|
Synopsis [Multi-valued simulation.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: saigSimMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "saig.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#define SAIG_DIFF_VALUES 8
|
|
#define SAIG_UNDEF_VALUE 0x1ffffffe //536870910
|
|
|
|
// old AIG
|
|
typedef struct Saig_MvObj_t_ Saig_MvObj_t;
|
|
struct Saig_MvObj_t_
|
|
{
|
|
int iFan0;
|
|
int iFan1;
|
|
unsigned Type : 3;
|
|
unsigned Value : 29;
|
|
};
|
|
|
|
// new AIG
|
|
typedef struct Saig_MvAnd_t_ Saig_MvAnd_t;
|
|
struct Saig_MvAnd_t_
|
|
{
|
|
int iFan0;
|
|
int iFan1;
|
|
int iNext;
|
|
};
|
|
|
|
// simulation manager
|
|
typedef struct Saig_MvMan_t_ Saig_MvMan_t;
|
|
struct Saig_MvMan_t_
|
|
{
|
|
// user data
|
|
Aig_Man_t * pAig; // original AIG
|
|
// parameters
|
|
int nStatesMax; // maximum number of states
|
|
int nLevelsMax; // maximum number of levels
|
|
int nValuesMax; // maximum number of values
|
|
int nFlops; // number of flops
|
|
// compacted AIG
|
|
Saig_MvObj_t * pAigOld; // AIG objects
|
|
Vec_Ptr_t * vFlops; // collected flops
|
|
Vec_Int_t * vXFlops; // flops that had at least one X-value
|
|
Vec_Ptr_t * vTired; // collected flops
|
|
unsigned * pTStates; // hash table for states
|
|
int nTStatesSize; // hash table size
|
|
Aig_MmFixed_t * pMemStates; // memory for states
|
|
Vec_Ptr_t * vStates; // reached states
|
|
int * pRegsUndef; // count the number of undef values
|
|
int ** pRegsValues; // write the first different values
|
|
int * nRegsValues; // count the number of different values
|
|
int nRUndefs; // the number of undef registers
|
|
int nRValues[SAIG_DIFF_VALUES+1]; // the number of registers with given values
|
|
// internal AIG
|
|
Saig_MvAnd_t * pAigNew; // AIG nodes
|
|
int nObjsAlloc; // the number of objects allocated
|
|
int nObjs; // the number of objects
|
|
int nPis; // the number of primary inputs
|
|
int * pTNodes; // hash table
|
|
int nTNodesSize; // hash table size
|
|
unsigned char * pLevels; // levels of AIG nodes
|
|
};
|
|
|
|
static inline int Saig_MvObjFaninC0( Saig_MvObj_t * pObj ) { return pObj->iFan0 & 1; }
|
|
static inline int Saig_MvObjFaninC1( Saig_MvObj_t * pObj ) { return pObj->iFan1 & 1; }
|
|
static inline int Saig_MvObjFanin0( Saig_MvObj_t * pObj ) { return pObj->iFan0 >> 1; }
|
|
static inline int Saig_MvObjFanin1( Saig_MvObj_t * pObj ) { return pObj->iFan1 >> 1; }
|
|
|
|
static inline int Saig_MvConst0() { return 1; }
|
|
static inline int Saig_MvConst1() { return 0; }
|
|
static inline int Saig_MvConst( int c ) { return !c; }
|
|
static inline int Saig_MvUndef() { return SAIG_UNDEF_VALUE; }
|
|
|
|
static inline int Saig_MvIsConst0( int iNode ) { return iNode == 1; }
|
|
static inline int Saig_MvIsConst1( int iNode ) { return iNode == 0; }
|
|
static inline int Saig_MvIsConst( int iNode ) { return iNode < 2; }
|
|
static inline int Saig_MvIsUndef( int iNode ) { return iNode == SAIG_UNDEF_VALUE; }
|
|
|
|
static inline int Saig_MvRegular( int iNode ) { return (iNode & ~01); }
|
|
static inline int Saig_MvNot( int iNode ) { return (iNode ^ 01); }
|
|
static inline int Saig_MvNotCond( int iNode, int c ) { return (iNode ^ (c)); }
|
|
static inline int Saig_MvIsComplement( int iNode ) { return (int)(iNode & 01); }
|
|
|
|
static inline int Saig_MvLit2Var( int iNode ) { return (iNode >> 1); }
|
|
static inline int Saig_MvVar2Lit( int iVar ) { return (iVar << 1); }
|
|
static inline int Saig_MvLev( Saig_MvMan_t * p, int iNode ) { return p->pLevels[iNode >> 1]; }
|
|
|
|
// iterator over compacted objects
|
|
#define Saig_MvManForEachObj( pAig, pEntry ) \
|
|
for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates reduced manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Saig_MvObj_t * Saig_ManCreateReducedAig( Aig_Man_t * p, Vec_Ptr_t ** pvFlops )
|
|
{
|
|
Saig_MvObj_t * pAig, * pEntry;
|
|
Aig_Obj_t * pObj;
|
|
int i;
|
|
*pvFlops = Vec_PtrAlloc( Aig_ManRegNum(p) );
|
|
pAig = ABC_CALLOC( Saig_MvObj_t, Aig_ManObjNumMax(p)+1 );
|
|
Aig_ManForEachObj( p, pObj, i )
|
|
{
|
|
pEntry = pAig + i;
|
|
pEntry->Type = pObj->Type;
|
|
if ( Aig_ObjIsCi(pObj) || i == 0 )
|
|
{
|
|
if ( Saig_ObjIsLo(p, pObj) )
|
|
{
|
|
pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1);
|
|
pEntry->iFan1 = -1;
|
|
Vec_PtrPush( *pvFlops, pEntry );
|
|
}
|
|
continue;
|
|
}
|
|
pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
|
|
if ( Aig_ObjIsCo(pObj) )
|
|
continue;
|
|
assert( Aig_ObjIsNode(pObj) );
|
|
pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj);
|
|
}
|
|
pEntry = pAig + Aig_ManObjNumMax(p);
|
|
pEntry->Type = AIG_OBJ_VOID;
|
|
return pAig;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates a new node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int Saig_MvCreateObj( Saig_MvMan_t * p, int iFan0, int iFan1 )
|
|
{
|
|
Saig_MvAnd_t * pNode;
|
|
if ( p->nObjs == p->nObjsAlloc )
|
|
{
|
|
p->pAigNew = ABC_REALLOC( Saig_MvAnd_t, p->pAigNew, 2*p->nObjsAlloc );
|
|
p->pLevels = ABC_REALLOC( unsigned char, p->pLevels, 2*p->nObjsAlloc );
|
|
p->nObjsAlloc *= 2;
|
|
}
|
|
pNode = p->pAigNew + p->nObjs;
|
|
pNode->iFan0 = iFan0;
|
|
pNode->iFan1 = iFan1;
|
|
pNode->iNext = 0;
|
|
if ( iFan0 || iFan1 )
|
|
p->pLevels[p->nObjs] = 1 + Abc_MaxInt( Saig_MvLev(p, iFan0), Saig_MvLev(p, iFan1) );
|
|
else
|
|
p->pLevels[p->nObjs] = 0, p->nPis++;
|
|
return p->nObjs++;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates multi-valued simulation manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Saig_MvMan_t * Saig_MvManStart( Aig_Man_t * pAig, int nFramesSatur )
|
|
{
|
|
Saig_MvMan_t * p;
|
|
int i;
|
|
assert( Aig_ManRegNum(pAig) > 0 );
|
|
p = (Saig_MvMan_t *)ABC_ALLOC( Saig_MvMan_t, 1 );
|
|
memset( p, 0, sizeof(Saig_MvMan_t) );
|
|
// set parameters
|
|
p->pAig = pAig;
|
|
p->nStatesMax = 2 * nFramesSatur + 100;
|
|
p->nLevelsMax = 4;
|
|
p->nValuesMax = SAIG_DIFF_VALUES;
|
|
p->nFlops = Aig_ManRegNum(pAig);
|
|
// compacted AIG
|
|
p->pAigOld = Saig_ManCreateReducedAig( pAig, &p->vFlops );
|
|
p->nTStatesSize = Abc_PrimeCudd( p->nStatesMax );
|
|
p->pTStates = ABC_CALLOC( unsigned, p->nTStatesSize );
|
|
p->pMemStates = Aig_MmFixedStart( sizeof(int) * (p->nFlops+1), p->nStatesMax );
|
|
p->vStates = Vec_PtrAlloc( p->nStatesMax );
|
|
Vec_PtrPush( p->vStates, NULL );
|
|
p->pRegsUndef = ABC_CALLOC( int, p->nFlops );
|
|
p->pRegsValues = ABC_ALLOC( int *, p->nFlops );
|
|
p->pRegsValues[0] = ABC_ALLOC( int, p->nValuesMax * p->nFlops );
|
|
for ( i = 1; i < p->nFlops; i++ )
|
|
p->pRegsValues[i] = p->pRegsValues[i-1] + p->nValuesMax;
|
|
p->nRegsValues = ABC_CALLOC( int, p->nFlops );
|
|
p->vTired = Vec_PtrAlloc( 100 );
|
|
// internal AIG
|
|
p->nObjsAlloc = 1000000;
|
|
p->pAigNew = ABC_ALLOC( Saig_MvAnd_t, p->nObjsAlloc );
|
|
p->nTNodesSize = Abc_PrimeCudd( p->nObjsAlloc / 3 );
|
|
p->pTNodes = ABC_CALLOC( int, p->nTNodesSize );
|
|
p->pLevels = ABC_ALLOC( unsigned char, p->nObjsAlloc );
|
|
Saig_MvCreateObj( p, 0, 0 );
|
|
return p;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Destroys multi-valued simulation manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_MvManStop( Saig_MvMan_t * p )
|
|
{
|
|
Aig_MmFixedStop( p->pMemStates, 0 );
|
|
Vec_PtrFree( p->vStates );
|
|
Vec_IntFreeP( &p->vXFlops );
|
|
Vec_PtrFree( p->vFlops );
|
|
Vec_PtrFree( p->vTired );
|
|
ABC_FREE( p->pRegsValues[0] );
|
|
ABC_FREE( p->pRegsValues );
|
|
ABC_FREE( p->nRegsValues );
|
|
ABC_FREE( p->pRegsUndef );
|
|
ABC_FREE( p->pAigOld );
|
|
ABC_FREE( p->pTStates );
|
|
ABC_FREE( p->pAigNew );
|
|
ABC_FREE( p->pTNodes );
|
|
ABC_FREE( p->pLevels );
|
|
ABC_FREE( p );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Hashing the node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int Saig_MvHash( int iFan0, int iFan1, int TableSize )
|
|
{
|
|
unsigned Key = 0;
|
|
assert( iFan0 < iFan1 );
|
|
Key ^= Saig_MvLit2Var(iFan0) * 7937;
|
|
Key ^= Saig_MvLit2Var(iFan1) * 2971;
|
|
Key ^= Saig_MvIsComplement(iFan0) * 911;
|
|
Key ^= Saig_MvIsComplement(iFan1) * 353;
|
|
return (int)(Key % TableSize);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the place where this node is stored (or should be stored).]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int * Saig_MvTableFind( Saig_MvMan_t * p, int iFan0, int iFan1 )
|
|
{
|
|
Saig_MvAnd_t * pEntry;
|
|
int * pPlace = p->pTNodes + Saig_MvHash( iFan0, iFan1, p->nTNodesSize );
|
|
for ( pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL; pEntry;
|
|
pPlace = &pEntry->iNext, pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL )
|
|
if ( pEntry->iFan0 == iFan0 && pEntry->iFan1 == iFan1 )
|
|
break;
|
|
return pPlace;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs an AND-operation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int Saig_MvAnd( Saig_MvMan_t * p, int iFan0, int iFan1, int fFirst )
|
|
{
|
|
if ( iFan0 == iFan1 )
|
|
return iFan0;
|
|
if ( iFan0 == Saig_MvNot(iFan1) )
|
|
return Saig_MvConst0();
|
|
if ( Saig_MvIsConst(iFan0) )
|
|
return Saig_MvIsConst1(iFan0) ? iFan1 : Saig_MvConst0();
|
|
if ( Saig_MvIsConst(iFan1) )
|
|
return Saig_MvIsConst1(iFan1) ? iFan0 : Saig_MvConst0();
|
|
if ( Saig_MvIsUndef(iFan0) || Saig_MvIsUndef(iFan1) )
|
|
return Saig_MvUndef();
|
|
// if ( Saig_MvLev(p, iFan0) >= p->nLevelsMax || Saig_MvLev(p, iFan1) >= p->nLevelsMax )
|
|
// return Saig_MvUndef();
|
|
|
|
// go undef after the first frame
|
|
if ( !fFirst )
|
|
return Saig_MvUndef();
|
|
|
|
if ( iFan0 > iFan1 )
|
|
{
|
|
int Temp = iFan0;
|
|
iFan0 = iFan1;
|
|
iFan1 = Temp;
|
|
}
|
|
{
|
|
int * pPlace;
|
|
pPlace = Saig_MvTableFind( p, iFan0, iFan1 );
|
|
if ( *pPlace == 0 )
|
|
{
|
|
if ( pPlace >= (int*)p->pAigNew && pPlace < (int*)(p->pAigNew + p->nObjsAlloc) )
|
|
{
|
|
int iPlace = pPlace - (int*)p->pAigNew;
|
|
int iNode = Saig_MvCreateObj( p, iFan0, iFan1 );
|
|
((int*)p->pAigNew)[iPlace] = iNode;
|
|
return Saig_MvVar2Lit( iNode );
|
|
}
|
|
else
|
|
*pPlace = Saig_MvCreateObj( p, iFan0, iFan1 );
|
|
}
|
|
return Saig_MvVar2Lit( *pPlace );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Propagates one edge.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int Saig_MvSimulateValue0( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj )
|
|
{
|
|
Saig_MvObj_t * pObj0 = pAig + Saig_MvObjFanin0(pObj);
|
|
if ( Saig_MvIsUndef( pObj0->Value ) )
|
|
return Saig_MvUndef();
|
|
return Saig_MvNotCond( pObj0->Value, Saig_MvObjFaninC0(pObj) );
|
|
}
|
|
static inline int Saig_MvSimulateValue1( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj )
|
|
{
|
|
Saig_MvObj_t * pObj1 = pAig + Saig_MvObjFanin1(pObj);
|
|
if ( Saig_MvIsUndef( pObj1->Value ) )
|
|
return Saig_MvUndef();
|
|
return Saig_MvNotCond( pObj1->Value, Saig_MvObjFaninC1(pObj) );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Prints MV state.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_MvPrintState( int Iter, Saig_MvMan_t * p )
|
|
{
|
|
Saig_MvObj_t * pEntry;
|
|
int i;
|
|
printf( "%3d : ", Iter );
|
|
Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
|
|
{
|
|
if ( pEntry->Value == SAIG_UNDEF_VALUE )
|
|
printf( " *" );
|
|
else
|
|
printf( "%5d", pEntry->Value );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs one iteration of simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_MvSimulateFrame( Saig_MvMan_t * p, int fFirst, int fVerbose )
|
|
{
|
|
Saig_MvObj_t * pEntry;
|
|
int i;
|
|
Saig_MvManForEachObj( p->pAigOld, pEntry )
|
|
{
|
|
if ( pEntry->Type == AIG_OBJ_AND )
|
|
{
|
|
pEntry->Value = Saig_MvAnd( p,
|
|
Saig_MvSimulateValue0(p->pAigOld, pEntry),
|
|
Saig_MvSimulateValue1(p->pAigOld, pEntry), fFirst );
|
|
}
|
|
else if ( pEntry->Type == AIG_OBJ_CO )
|
|
pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry);
|
|
else if ( pEntry->Type == AIG_OBJ_CI )
|
|
{
|
|
if ( pEntry->iFan1 == 0 ) // true PI
|
|
{
|
|
if ( fFirst )
|
|
pEntry->Value = Saig_MvVar2Lit( Saig_MvCreateObj( p, 0, 0 ) );
|
|
else
|
|
pEntry->Value = SAIG_UNDEF_VALUE;
|
|
}
|
|
// else if ( fFirst ) // register output
|
|
// pEntry->Value = Saig_MvConst0();
|
|
// else
|
|
// pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry);
|
|
}
|
|
else if ( pEntry->Type == AIG_OBJ_CONST1 )
|
|
pEntry->Value = Saig_MvConst1();
|
|
else if ( pEntry->Type != AIG_OBJ_NONE )
|
|
assert( 0 );
|
|
}
|
|
// transfer to registers
|
|
Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
|
|
pEntry->Value = Saig_MvSimulateValue0( p->pAigOld, pEntry );
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes hash value of the node using its simulation info.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_MvSimHash( unsigned * pState, int nFlops, int TableSize )
|
|
{
|
|
static int s_SPrimes[16] = {
|
|
1610612741,
|
|
805306457,
|
|
402653189,
|
|
201326611,
|
|
100663319,
|
|
50331653,
|
|
25165843,
|
|
12582917,
|
|
6291469,
|
|
3145739,
|
|
1572869,
|
|
786433,
|
|
393241,
|
|
196613,
|
|
98317,
|
|
49157
|
|
};
|
|
unsigned uHash = 0;
|
|
int i;
|
|
for ( i = 0; i < nFlops; i++ )
|
|
uHash ^= pState[i] * s_SPrimes[i & 0xF];
|
|
return (int)(uHash % TableSize);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the place where this state is stored (or should be stored).]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline unsigned * Saig_MvSimTableFind( Saig_MvMan_t * p, unsigned * pState )
|
|
{
|
|
unsigned * pEntry;
|
|
unsigned * pPlace = p->pTStates + Saig_MvSimHash( pState+1, p->nFlops, p->nTStatesSize );
|
|
for ( pEntry = (*pPlace)? (unsigned *)Vec_PtrEntry(p->vStates, *pPlace) : NULL; pEntry;
|
|
pPlace = pEntry, pEntry = (*pPlace)? (unsigned *)Vec_PtrEntry(p->vStates, *pPlace) : NULL )
|
|
if ( memcmp( pEntry+1, pState+1, sizeof(int)*p->nFlops ) == 0 )
|
|
break;
|
|
return pPlace;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Saves current state.]
|
|
|
|
Description [Returns -1 if there is no fixed point.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_MvSaveState( Saig_MvMan_t * p )
|
|
{
|
|
Saig_MvObj_t * pEntry;
|
|
unsigned * pState, * pPlace;
|
|
int i;
|
|
pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMemStates );
|
|
pState[0] = 0;
|
|
Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
|
|
pState[i+1] = pEntry->Value;
|
|
pPlace = Saig_MvSimTableFind( p, pState );
|
|
if ( *pPlace )
|
|
return *pPlace;
|
|
*pPlace = Vec_PtrSize( p->vStates );
|
|
Vec_PtrPush( p->vStates, pState );
|
|
return -1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs multi-valued simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Saig_MvManPostProcess( Saig_MvMan_t * p, int iState )
|
|
{
|
|
Saig_MvObj_t * pEntry;
|
|
unsigned * pState;
|
|
int i, k, j, nTotal = 0, iFlop;
|
|
Vec_Int_t * vUniques = Vec_IntAlloc( 100 );
|
|
Vec_Int_t * vCounter = Vec_IntAlloc( 100 );
|
|
// count registers that never became undef
|
|
Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
|
|
if ( p->pRegsUndef[i] == 0 )
|
|
nTotal++;
|
|
printf( "The number of registers that never became undef = %d. (Total = %d.)\n", nTotal, p->nFlops );
|
|
Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
|
|
{
|
|
if ( p->pRegsUndef[i] )
|
|
continue;
|
|
Vec_IntForEachEntry( vUniques, iFlop, k )
|
|
{
|
|
Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, j, 1 )
|
|
if ( pState[iFlop+1] != pState[i+1] )
|
|
break;
|
|
if ( j == Vec_PtrSize(p->vStates) )
|
|
{
|
|
Vec_IntAddToEntry( vCounter, k, 1 );
|
|
break;
|
|
}
|
|
}
|
|
if ( k == Vec_IntSize(vUniques) )
|
|
{
|
|
Vec_IntPush( vUniques, i );
|
|
Vec_IntPush( vCounter, 1 );
|
|
}
|
|
}
|
|
Vec_IntForEachEntry( vUniques, iFlop, i )
|
|
{
|
|
printf( "FLOP %5d : (%3d) ", iFlop, Vec_IntEntry(vCounter,i) );
|
|
/*
|
|
for ( k = 0; k < p->nRegsValues[iFlop]; k++ )
|
|
if ( p->pRegsValues[iFlop][k] == SAIG_UNDEF_VALUE )
|
|
printf( "* " );
|
|
else
|
|
printf( "%d ", p->pRegsValues[iFlop][k] );
|
|
printf( "\n" );
|
|
*/
|
|
Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, 1 )
|
|
{
|
|
if ( k == iState+1 )
|
|
printf( " # " );
|
|
if ( pState[iFlop+1] == SAIG_UNDEF_VALUE )
|
|
printf( "*" );
|
|
else
|
|
printf( "%d", pState[iFlop+1] );
|
|
}
|
|
printf( "\n" );
|
|
// if ( ++Counter == 10 )
|
|
// break;
|
|
}
|
|
|
|
Vec_IntFree( vUniques );
|
|
Vec_IntFree( vCounter );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs multi-valued simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Int_t * Saig_MvManFindXFlops( Saig_MvMan_t * p )
|
|
{
|
|
Vec_Int_t * vXFlops;
|
|
unsigned * pState;
|
|
int i, k;
|
|
vXFlops = Vec_IntStart( p->nFlops );
|
|
Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 )
|
|
{
|
|
for ( k = 0; k < p->nFlops; k++ )
|
|
if ( Saig_MvIsUndef(pState[k+1]) )
|
|
Vec_IntWriteEntry( vXFlops, k, 1 );
|
|
}
|
|
return vXFlops;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Checks if the flop is an oscilator.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_MvManCheckOscilator( Saig_MvMan_t * p, int iFlop )
|
|
{
|
|
Vec_Int_t * vValues;
|
|
unsigned * pState;
|
|
int k, Per, Entry;
|
|
// collect values of this flop
|
|
vValues = Vec_IntAlloc( 100 );
|
|
Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, 1 )
|
|
{
|
|
Vec_IntPush( vValues, pState[iFlop+1] );
|
|
//printf( "%d ", pState[iFlop+1] );
|
|
}
|
|
//printf( "\n" );
|
|
assert( Saig_MvIsConst0( Vec_IntEntry(vValues,0) ) );
|
|
// look for constants
|
|
for ( Per = 0; Per < Vec_IntSize(vValues)/2; Per++ )
|
|
{
|
|
// find the first non-const0
|
|
Vec_IntForEachEntryStart( vValues, Entry, Per, Per )
|
|
if ( !Saig_MvIsConst0(Entry) )
|
|
break;
|
|
if ( Per == Vec_IntSize(vValues) )
|
|
break;
|
|
// find the first const0
|
|
Vec_IntForEachEntryStart( vValues, Entry, Per, Per )
|
|
if ( Saig_MvIsConst0(Entry) )
|
|
break;
|
|
if ( Per == Vec_IntSize(vValues) )
|
|
break;
|
|
// try to determine period
|
|
assert( Saig_MvIsConst0( Vec_IntEntry(vValues,Per) ) );
|
|
for ( k = Per; k < Vec_IntSize(vValues); k++ )
|
|
if ( Vec_IntEntry(vValues, k-Per) != Vec_IntEntry(vValues, k) )
|
|
break;
|
|
if ( k < Vec_IntSize(vValues) )
|
|
continue;
|
|
Vec_IntFree( vValues );
|
|
//printf( "Period = %d\n", Per );
|
|
return Per;
|
|
}
|
|
Vec_IntFree( vValues );
|
|
return 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns const0 and binary flops.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Int_t * Saig_MvManFindConstBinaryFlops( Saig_MvMan_t * p, Vec_Int_t ** pvBinary )
|
|
{
|
|
unsigned * pState;
|
|
Vec_Int_t * vBinary, * vConst0;
|
|
int i, k, fConst0;
|
|
// detect constant flops
|
|
vConst0 = Vec_IntAlloc( p->nFlops );
|
|
vBinary = Vec_IntAlloc( p->nFlops );
|
|
for ( k = 0; k < p->nFlops; k++ )
|
|
{
|
|
// check if this flop is constant 0 in all states
|
|
fConst0 = 1;
|
|
Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 )
|
|
{
|
|
if ( !Saig_MvIsConst0(pState[k+1]) )
|
|
fConst0 = 0;
|
|
if ( Saig_MvIsUndef(pState[k+1]) )
|
|
break;
|
|
}
|
|
if ( i < Vec_PtrSize(p->vStates) )
|
|
continue;
|
|
// the flop is binary-valued
|
|
if ( fConst0 )
|
|
Vec_IntPush( vConst0, k );
|
|
else
|
|
Vec_IntPush( vBinary, k );
|
|
}
|
|
*pvBinary = vBinary;
|
|
return vConst0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Find oscilators.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Int_t * Saig_MvManFindOscilators( Saig_MvMan_t * p, Vec_Int_t ** pvConst0 )
|
|
{
|
|
Vec_Int_t * vBinary, * vOscils;
|
|
int Entry, i;
|
|
// detect constant flops
|
|
*pvConst0 = Saig_MvManFindConstBinaryFlops( p, &vBinary );
|
|
// check binary flops
|
|
vOscils = Vec_IntAlloc( 100 );
|
|
Vec_IntForEachEntry( vBinary, Entry, i )
|
|
if ( Saig_MvManCheckOscilator( p, Entry ) )
|
|
Vec_IntPush( vOscils, Entry );
|
|
Vec_IntFree( vBinary );
|
|
return vOscils;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Find constants and oscilators.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Int_t * Saig_MvManCreateNextSkip( Saig_MvMan_t * p )
|
|
{
|
|
Vec_Int_t * vConst0, * vOscils, * vXFlops;
|
|
int i, Entry;
|
|
vOscils = Saig_MvManFindOscilators( p, &vConst0 );
|
|
//printf( "Found %d constants and %d oscilators.\n", Vec_IntSize(vConst0), Vec_IntSize(vOscils) );
|
|
vXFlops = Vec_IntAlloc( p->nFlops );
|
|
Vec_IntFill( vXFlops, p->nFlops, 1 );
|
|
Vec_IntForEachEntry( vConst0, Entry, i )
|
|
Vec_IntWriteEntry( vXFlops, Entry, 0 );
|
|
Vec_IntForEachEntry( vOscils, Entry, i )
|
|
Vec_IntWriteEntry( vXFlops, Entry, 0 );
|
|
Vec_IntFree( vOscils );
|
|
Vec_IntFree( vConst0 );
|
|
return vXFlops;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Finds equivalent flops.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Saig_MvManDeriveMap( Saig_MvMan_t * p, int fVerbose )
|
|
{
|
|
Vec_Int_t * vConst0, * vBinValued;
|
|
Vec_Ptr_t * vMap = NULL;
|
|
Aig_Obj_t * pObj;
|
|
unsigned * pState;
|
|
int i, k, j, FlopK, FlopJ;
|
|
int Counter1 = 0, Counter2 = 0;
|
|
// prepare CI map
|
|
vMap = Vec_PtrAlloc( Aig_ManCiNum(p->pAig) );
|
|
Aig_ManForEachCi( p->pAig, pObj, i )
|
|
Vec_PtrPush( vMap, pObj );
|
|
// detect constant flops
|
|
vConst0 = Saig_MvManFindConstBinaryFlops( p, &vBinValued );
|
|
// set constants
|
|
Vec_IntForEachEntry( vConst0, FlopK, k )
|
|
{
|
|
Vec_PtrWriteEntry( vMap, Saig_ManPiNum(p->pAig) + FlopK, Aig_ManConst0(p->pAig) );
|
|
Counter1++;
|
|
}
|
|
Vec_IntFree( vConst0 );
|
|
|
|
// detect equivalent (non-ternary flops)
|
|
Vec_IntForEachEntry( vBinValued, FlopK, k )
|
|
if ( FlopK >= 0 )
|
|
Vec_IntForEachEntryStart( vBinValued, FlopJ, j, k+1 )
|
|
if ( FlopJ >= 0 )
|
|
{
|
|
// check if they are equal
|
|
Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 )
|
|
if ( pState[FlopK+1] != pState[FlopJ+1] )
|
|
break;
|
|
if ( i < Vec_PtrSize(p->vStates) )
|
|
continue;
|
|
// set the equivalence
|
|
Vec_PtrWriteEntry( vMap, Saig_ManPiNum(p->pAig) + FlopJ, Saig_ManLo(p->pAig, FlopK) );
|
|
Vec_IntWriteEntry( vBinValued, j, -1 );
|
|
Counter2++;
|
|
}
|
|
if ( fVerbose )
|
|
printf( "Detected %d const0 flops and %d pairs of equiv binary flops.\n", Counter1, Counter2 );
|
|
Vec_IntFree( vBinValued );
|
|
if ( Counter1 == 0 && Counter2 == 0 )
|
|
Vec_PtrFreeP( &vMap );
|
|
return vMap;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs multi-valued simulation.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Saig_MvManSimulate( Aig_Man_t * pAig, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose )
|
|
{
|
|
Vec_Ptr_t * vMap;
|
|
Saig_MvMan_t * p;
|
|
Saig_MvObj_t * pEntry;
|
|
int f, i, iState;
|
|
abctime clk = Abc_Clock();
|
|
assert( nFramesSymb >= 1 && nFramesSymb <= nFramesSatur );
|
|
|
|
// start manager
|
|
p = Saig_MvManStart( pAig, nFramesSatur );
|
|
if ( fVerbose )
|
|
ABC_PRT( "Constructing the problem", Abc_Clock() - clk );
|
|
|
|
// initialize registers
|
|
Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
|
|
pEntry->Value = Saig_MvConst0();
|
|
Saig_MvSaveState( p );
|
|
if ( fVeryVerbose )
|
|
Saig_MvPrintState( 0, p );
|
|
// simulate until convergence
|
|
clk = Abc_Clock();
|
|
for ( f = 0; ; f++ )
|
|
{
|
|
if ( f == nFramesSatur )
|
|
{
|
|
if ( fVerbose )
|
|
printf( "Beginning to saturate simulation after %d frames\n", f );
|
|
// find all flops that have at least one X value in the past and set them to X forever
|
|
p->vXFlops = Saig_MvManFindXFlops( p );
|
|
}
|
|
if ( f == 2 * nFramesSatur )
|
|
{
|
|
if ( fVerbose )
|
|
printf( "Aggressively saturating simulation after %d frames\n", f );
|
|
Vec_IntFree( p->vXFlops );
|
|
p->vXFlops = Saig_MvManCreateNextSkip( p );
|
|
}
|
|
// retire some flops
|
|
if ( p->vXFlops )
|
|
{
|
|
Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i )
|
|
if ( Vec_IntEntry( p->vXFlops, i ) )
|
|
pEntry->Value = SAIG_UNDEF_VALUE;
|
|
}
|
|
// simulate timeframe
|
|
Saig_MvSimulateFrame( p, (int)(f < nFramesSymb), fVerbose );
|
|
// save and print state
|
|
iState = Saig_MvSaveState( p );
|
|
if ( fVeryVerbose )
|
|
Saig_MvPrintState( f+1, p );
|
|
if ( iState >= 0 )
|
|
{
|
|
if ( fVerbose )
|
|
printf( "Converged after %d frames with lasso in state %d. Cycle = %d.\n", f+1, iState-1, f+2-iState );
|
|
// printf( "Total number of PIs = %d. AND nodes = %d.\n", p->nPis, p->nObjs - p->nPis );
|
|
break;
|
|
}
|
|
}
|
|
// printf( "Coverged after %d frames.\n", f );
|
|
if ( fVerbose )
|
|
ABC_PRT( "Multi-valued simulation", Abc_Clock() - clk );
|
|
// implement equivalences
|
|
// Saig_MvManPostProcess( p, iState-1 );
|
|
vMap = Saig_MvManDeriveMap( p, fVerbose );
|
|
Saig_MvManStop( p );
|
|
// return Aig_ManDupSimple( pAig );
|
|
return vMap;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|