blob: b5b94cb5136de8e19abd11aa414d6806c025f755 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaEra.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Explicit reachability analysis.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaEra.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "misc/mem/mem.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// explicit state representation
typedef struct Gia_ObjEra_t_ Gia_ObjEra_t;
struct Gia_ObjEra_t_
{
int Num; // ID of this state
int Cond; // input condition
int iPrev; // previous state
int iNext; // next state in the hash table
unsigned pData[0]; // state bits
};
// explicit state reachability
typedef struct Gia_ManEra_t_ Gia_ManEra_t;
struct Gia_ManEra_t_
{
Gia_Man_t * pAig; // user's AIG manager
int nWordsSim; // 2^(PInum)
int nWordsDat; // Abc_BitWordNum
unsigned * pDataSim; // simulation data
Mem_Fixed_t * pMemory; // memory manager
Vec_Ptr_t * vStates; // reached states
Gia_ObjEra_t * pStateNew; // temporary state
int iCurState; // the current state
Vec_Int_t * vBugTrace; // the sequence of transitions
Vec_Int_t * vStgDump; // STG written into a file
// hash table for states
int nBins;
unsigned * pBins;
};
static inline unsigned * Gia_ManEraData( Gia_ManEra_t * p, int i ) { return p->pDataSim + i * p->nWordsSim; }
static inline Gia_ObjEra_t * Gia_ManEraState( Gia_ManEra_t * p, int i ) { return (Gia_ObjEra_t *)Vec_PtrEntry(p->vStates, i); }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates reachability manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_ManEra_t * Gia_ManEraCreate( Gia_Man_t * pAig )
{
Vec_Ptr_t * vTruths;
Gia_ManEra_t * p;
unsigned * pTruth, * pSimInfo;
int i;
p = ABC_CALLOC( Gia_ManEra_t, 1 );
p->pAig = pAig;
p->nWordsSim = Abc_TruthWordNum( Gia_ManPiNum(pAig) );
p->nWordsDat = Abc_BitWordNum( Gia_ManRegNum(pAig) );
p->pDataSim = ABC_ALLOC( unsigned, p->nWordsSim*Gia_ManObjNum(pAig) );
p->pMemory = Mem_FixedStart( sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat );
p->vStates = Vec_PtrAlloc( 100000 );
p->nBins = Abc_PrimeCudd( 100000 );
p->pBins = ABC_CALLOC( unsigned, p->nBins );
Vec_PtrPush( p->vStates, NULL );
// assign primary input values
vTruths = Vec_PtrAllocTruthTables( Gia_ManPiNum(pAig) );
Vec_PtrForEachEntry( unsigned *, vTruths, pTruth, i )
{
pSimInfo = Gia_ManEraData( p, Gia_ObjId(pAig, Gia_ManPi(pAig, i)) );
memcpy( pSimInfo, pTruth, sizeof(unsigned) * p->nWordsSim );
}
Vec_PtrFree( vTruths );
// assign constant zero node
pSimInfo = Gia_ManEraData( p, 0 );
memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim );
p->vStgDump = Vec_IntAlloc( 1000 );
return p;
}
/**Function*************************************************************
Synopsis [Deletes reachability manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManEraFree( Gia_ManEra_t * p )
{
Mem_FixedStop( p->pMemory, 0 );
Vec_IntFree( p->vStgDump );
Vec_PtrFree( p->vStates );
if ( p->vBugTrace ) Vec_IntFree( p->vBugTrace );
ABC_FREE( p->pDataSim );
ABC_FREE( p->pBins );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Creates new state.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_ObjEra_t * Gia_ManEraCreateState( Gia_ManEra_t * p )
{
Gia_ObjEra_t * pNew;
pNew = (Gia_ObjEra_t *)Mem_FixedEntryFetch( p->pMemory );
pNew->Num = Vec_PtrSize( p->vStates );
pNew->iPrev = 0;
Vec_PtrPush( p->vStates, pNew );
return pNew;
}
/**Function*************************************************************
Synopsis [Computes hash value of the node using its simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManEraStateHash( unsigned * pState, int nWordsSim, int nTableSize )
{
static int s_FPrimes[128] = {
1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
};
unsigned uHash;
int i;
uHash = 0;
for ( i = 0; i < nWordsSim; i++ )
uHash ^= pState[i] * s_FPrimes[i & 0x7F];
return uHash % nTableSize;
}
/**Function*************************************************************
Synopsis [Returns the place of this state in the table or NULL if it exists.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline unsigned * Gia_ManEraHashFind( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int * pStateNum )
{
Gia_ObjEra_t * pThis;
unsigned * pPlace = p->pBins + Gia_ManEraStateHash( pState->pData, p->nWordsDat, p->nBins );
for ( pThis = (*pPlace)? Gia_ManEraState(p, *pPlace) : NULL; pThis;
pPlace = (unsigned *)&pThis->iNext, pThis = (*pPlace)? Gia_ManEraState(p, *pPlace) : NULL )
if ( !memcmp( pState->pData, pThis->pData, sizeof(unsigned) * p->nWordsDat ) )
{
if ( pStateNum )
*pStateNum = pThis->Num;
return NULL;
}
if ( pStateNum )
*pStateNum = -1;
return pPlace;
}
/**Function*************************************************************
Synopsis [Resizes the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManEraHashResize( Gia_ManEra_t * p )
{
Gia_ObjEra_t * pThis;
unsigned * pBinsOld, * piPlace;
int nBinsOld, iNext, Counter, i;
assert( p->pBins != NULL );
// replace the table
pBinsOld = p->pBins;
nBinsOld = p->nBins;
p->nBins = Abc_PrimeCudd( 3 * p->nBins );
p->pBins = ABC_CALLOC( unsigned, p->nBins );
// rehash the entries from the old table
Counter = 0;
for ( i = 0; i < nBinsOld; i++ )
for ( pThis = (pBinsOld[i]? Gia_ManEraState(p, pBinsOld[i]) : NULL),
iNext = (pThis? pThis->iNext : 0);
pThis; pThis = (iNext? Gia_ManEraState(p, iNext) : NULL),
iNext = (pThis? pThis->iNext : 0) )
{
assert( pThis->Num );
pThis->iNext = 0;
piPlace = Gia_ManEraHashFind( p, pThis, NULL );
assert( *piPlace == 0 ); // should not be there
*piPlace = pThis->Num;
Counter++;
}
assert( Counter == Vec_PtrSize( p->vStates ) - 1 );
ABC_FREE( pBinsOld );
}
/**Function*************************************************************
Synopsis [Initialize register output to the given state.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManInsertState( Gia_ManEra_t * p, Gia_ObjEra_t * pState )
{
Gia_Obj_t * pObj;
unsigned * pSimInfo;
int i;
Gia_ManForEachRo( p->pAig, pObj, i )
{
pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) );
if ( Abc_InfoHasBit(pState->pData, i) )
memset( pSimInfo, 0xff, sizeof(unsigned) * p->nWordsSim );
else
memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim );
}
}
/**Function*************************************************************
Synopsis [Returns -1 if outputs are not asserted.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Gia_ManOutputAsserted( Gia_ManEra_t * p, Gia_Obj_t * pObj )
{
unsigned * pInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) );
int w;
for ( w = 0; w < p->nWordsSim; w++ )
if ( pInfo[w] )
return 32*w + Gia_WordFindFirstBit( pInfo[w] );
return -1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimulateCo( Gia_ManEra_t * p, Gia_Obj_t * pObj )
{
int Id = Gia_ObjId(p->pAig, pObj);
unsigned * pInfo = Gia_ManEraData( p, Id );
unsigned * pInfo0 = Gia_ManEraData( p, Gia_ObjFaninId0(pObj, Id) );
int w;
if ( Gia_ObjFaninC0(pObj) )
for ( w = p->nWordsSim-1; w >= 0; w-- )
pInfo[w] = ~pInfo0[w];
else
for ( w = p->nWordsSim-1; w >= 0; w-- )
pInfo[w] = pInfo0[w];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimulateNode( Gia_ManEra_t * p, Gia_Obj_t * pObj )
{
int Id = Gia_ObjId(p->pAig, pObj);
unsigned * pInfo = Gia_ManEraData( p, Id );
unsigned * pInfo0 = Gia_ManEraData( p, Gia_ObjFaninId0(pObj, Id) );
unsigned * pInfo1 = Gia_ManEraData( p, Gia_ObjFaninId1(pObj, Id) );
int w;
if ( Gia_ObjFaninC0(pObj) )
{
if ( Gia_ObjFaninC1(pObj) )
for ( w = p->nWordsSim-1; w >= 0; w-- )
pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
else
for ( w = p->nWordsSim-1; w >= 0; w-- )
pInfo[w] = ~pInfo0[w] & pInfo1[w];
}
else
{
if ( Gia_ObjFaninC1(pObj) )
for ( w = p->nWordsSim-1; w >= 0; w-- )
pInfo[w] = pInfo0[w] & ~pInfo1[w];
else
for ( w = p->nWordsSim-1; w >= 0; w-- )
pInfo[w] = pInfo0[w] & pInfo1[w];
}
}
/**Function*************************************************************
Synopsis [Performs one iteration of reachability analysis.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPerformOneIter( Gia_ManEra_t * p )
{
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObj1( p->pAig, pObj, i )
{
if ( Gia_ObjIsAnd(pObj) )
Gia_ManSimulateNode( p, pObj );
else if ( Gia_ObjIsCo(pObj) )
Gia_ManSimulateCo( p, pObj );
}
}
/**Function*************************************************************
Synopsis [Performs one iteration of reachability analysis.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManCollectBugTrace( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int iCond )
{
Vec_Int_t * vTrace;
vTrace = Vec_IntAlloc( 10 );
Vec_IntPush( vTrace, iCond );
for ( ; pState; pState = pState->iPrev ? Gia_ManEraState(p, pState->iPrev) : NULL )
Vec_IntPush( vTrace, pState->Cond );
Vec_IntReverseOrder( vTrace );
return vTrace;
}
/**Function*************************************************************
Synopsis [Counts the depth of state transitions leading ot this state.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManCountDepth( Gia_ManEra_t * p )
{
Gia_ObjEra_t * pState;
int Counter = 0;
pState = (Gia_ObjEra_t *)Vec_PtrEntryLast( p->vStates );
if ( pState->iPrev == 0 && Vec_PtrSize(p->vStates) > 3 )
pState = (Gia_ObjEra_t *)Vec_PtrEntry( p->vStates, Vec_PtrSize(p->vStates) - 2 );
for ( ; pState; pState = pState->iPrev ? Gia_ManEraState(p, pState->iPrev) : NULL )
Counter++;
return Counter;
}
/**Function*************************************************************
Synopsis [Analized reached states.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManAnalyzeResult( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int fMiter, int fStgDump )
{
Gia_Obj_t * pObj;
unsigned * pSimInfo, * piPlace, uOutput = 0;
int i, k, iCond, nMints, iNextState;
// check if the miter is asserted
if ( fMiter )
{
Gia_ManForEachPo( p->pAig, pObj, i )
{
iCond = Gia_ManOutputAsserted( p, pObj );
if ( iCond >= 0 )
{
p->vBugTrace = Gia_ManCollectBugTrace( p, pState, iCond );
return 1;
}
}
}
// collect reached states
nMints = (1 << Gia_ManPiNum(p->pAig));
for ( k = 0; k < nMints; k++ )
{
if ( p->pStateNew == NULL )
p->pStateNew = Gia_ManEraCreateState( p );
p->pStateNew->pData[p->nWordsDat-1] = 0;
Gia_ManForEachRi( p->pAig, pObj, i )
{
pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) );
if ( Abc_InfoHasBit(p->pStateNew->pData, i) != Abc_InfoHasBit(pSimInfo, k) )
Abc_InfoXorBit( p->pStateNew->pData, i );
}
if ( fStgDump )
{
uOutput = 0;
Gia_ManForEachPo( p->pAig, pObj, i )
{
pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) );
if ( Abc_InfoHasBit(pSimInfo, k) && i < 32 )
Abc_InfoXorBit( &uOutput, i );
}
}
piPlace = Gia_ManEraHashFind( p, p->pStateNew, &iNextState );
if ( fStgDump ) Vec_IntPush( p->vStgDump, k );
if ( fStgDump ) Vec_IntPush( p->vStgDump, pState->Num );
if ( piPlace == NULL )
{
if ( fStgDump ) Vec_IntPush( p->vStgDump, iNextState );
if ( fStgDump ) Vec_IntPush( p->vStgDump, uOutput );
continue;
}
if ( fStgDump ) Vec_IntPush( p->vStgDump, p->pStateNew->Num );
if ( fStgDump ) Vec_IntPush( p->vStgDump, uOutput );
//printf( "Inserting %d ", Vec_PtrSize(p->vStates) );
//Extra_PrintBinary( stdout, p->pStateNew->pData, Gia_ManRegNum(p->pAig) ); printf( "\n" );
assert( *piPlace == 0 );
*piPlace = p->pStateNew->Num;
p->pStateNew->Cond = k;
p->pStateNew->iPrev = pState->Num;
p->pStateNew->iNext = 0;
p->pStateNew = NULL;
// expand hash table if needed
if ( Vec_PtrSize(p->vStates) > 2 * p->nBins )
Gia_ManEraHashResize( p );
}
return 0;
}
/**Function*************************************************************
Synopsis [Resizes the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManCollectReachable( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fDumpFile, int fVerbose )
{
Gia_ManEra_t * p;
Gia_ObjEra_t * pState;
int Hash;
abctime clk = Abc_Clock();
int RetValue = 1;
assert( Gia_ManPiNum(pAig) <= 12 );
assert( Gia_ManRegNum(pAig) > 0 );
p = Gia_ManEraCreate( pAig );
// create init state
pState = Gia_ManEraCreateState( p );
pState->Cond = 0;
pState->iPrev = 0;
pState->iNext = 0;
memset( pState->pData, 0, sizeof(unsigned) * p->nWordsDat );
Hash = Gia_ManEraStateHash(pState->pData, p->nWordsDat, p->nBins);
p->pBins[ Hash ] = pState->Num;
// process reachable states
while ( p->iCurState < Vec_PtrSize( p->vStates ) - 1 )
{
if ( Vec_PtrSize(p->vStates) >= nStatesMax )
{
printf( "Reached the limit on states traversed (%d). ", nStatesMax );
RetValue = -1;
break;
}
pState = Gia_ManEraState( p, ++p->iCurState );
if ( p->iCurState > 1 && pState->iPrev == 0 )
continue;
//printf( "Extracting %d ", p->iCurState );
//Extra_PrintBinary( stdout, p->pStateNew->pData, Gia_ManRegNum(p->pAig) ); printf( "\n" );
Gia_ManInsertState( p, pState );
Gia_ManPerformOneIter( p );
if ( Gia_ManAnalyzeResult( p, pState, fMiter, fDumpFile ) && fMiter )
{
RetValue = 0;
printf( "Miter failed in state %d after %d transitions. ",
p->iCurState, Vec_IntSize(p->vBugTrace)-1 );
break;
}
if ( fVerbose && p->iCurState % 5000 == 0 )
{
printf( "States =%10d. Reached =%10d. R = %5.3f. Depth =%6d. Mem =%9.2f MB. ",
p->iCurState, Vec_PtrSize(p->vStates), 1.0*p->iCurState/Vec_PtrSize(p->vStates), Gia_ManCountDepth(p),
(1.0/(1<<20))*(1.0*Vec_PtrSize(p->vStates)*(sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat) +
1.0*p->nBins*sizeof(unsigned) + 1.0*p->vStates->nCap * sizeof(void*)) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
}
printf( "Reachability analysis traversed %d states with depth %d. ", p->iCurState-1, Gia_ManCountDepth(p) );
ABC_PRT( "Time", Abc_Clock() - clk );
if ( fDumpFile )
{
char * pFileName = "test.stg";
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
printf( "Cannot open file \"%s\" for writing.\n", pFileName );
else
{
Gia_ManStgPrint( pFile, p->vStgDump, Gia_ManPiNum(pAig), Gia_ManPoNum(pAig), p->iCurState-1 );
fclose( pFile );
printf( "Extracted STG was written into file \"%s\".\n", pFileName );
}
}
Gia_ManEraFree( p );
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END