blob: 88e94156ec75ac5b53d99ecfae2bd6202c39507f [file] [log] [blame]
/**CFile****************************************************************
FileName [giaSim.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Fast sequential simulator.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "misc/util/utilTruth.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static inline unsigned * Gia_SimData( Gia_ManSim_t * p, int i ) { return p->pDataSim + i * p->nWords; }
static inline unsigned * Gia_SimDataCi( Gia_ManSim_t * p, int i ) { return p->pDataSimCis + i * p->nWords; }
static inline unsigned * Gia_SimDataCo( Gia_ManSim_t * p, int i ) { return p->pDataSimCos + i * p->nWords; }
unsigned * Gia_SimDataExt( Gia_ManSim_t * p, int i ) { return Gia_SimData(p, i); }
unsigned * Gia_SimDataCiExt( Gia_ManSim_t * p, int i ) { return Gia_SimDataCi(p, i); }
unsigned * Gia_SimDataCoExt( Gia_ManSim_t * p, int i ) { return Gia_SimDataCo(p, i); }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSimCollect_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vVec )
{
Vec_IntPush( vVec, Gia_ObjToLit(pGia, pObj) );
if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) )
return;
assert( Gia_ObjIsAnd(pObj) );
Gia_ManSimCollect_rec( pGia, Gia_ObjChild0(pObj), vVec );
Gia_ManSimCollect_rec( pGia, Gia_ObjChild1(pObj), vVec );
}
/**Function*************************************************************
Synopsis [Derives signal implications.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSimCollect( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vVec )
{
Vec_IntClear( vVec );
Gia_ManSimCollect_rec( pGia, pObj, vVec );
Vec_IntUniqify( vVec );
}
/**Function*************************************************************
Synopsis [Finds signals, which reset flops to have constant values.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManSimDeriveResets( Gia_Man_t * pGia )
{
int nImpLimit = 5;
Vec_Int_t * vResult;
Vec_Int_t * vCountLits, * vSuperGate;
Gia_Obj_t * pObj;
int i, k, Lit, Count;
int Counter0 = 0, Counter1 = 0;
int CounterPi0 = 0, CounterPi1 = 0;
abctime clk = Abc_Clock();
// create reset counters for each literal
vCountLits = Vec_IntStart( 2 * Gia_ManObjNum(pGia) );
// collect implications for each flop input driver
vSuperGate = Vec_IntAlloc( 1000 );
Gia_ManForEachRi( pGia, pObj, i )
{
if ( Gia_ObjFaninId0p(pGia, pObj) == 0 )
continue;
Vec_IntAddToEntry( vCountLits, Gia_ObjToLit(pGia, Gia_ObjChild0(pObj)), 1 );
Gia_ManSimCollect( pGia, Gia_ObjFanin0(pObj), vSuperGate );
Vec_IntForEachEntry( vSuperGate, Lit, k )
Vec_IntAddToEntry( vCountLits, Lit, 1 );
}
Vec_IntFree( vSuperGate );
// label signals whose counter if more than the limit
vResult = Vec_IntStartFull( Gia_ManObjNum(pGia) );
Vec_IntForEachEntry( vCountLits, Count, Lit )
{
if ( Count < nImpLimit )
continue;
pObj = Gia_ManObj( pGia, Abc_Lit2Var(Lit) );
if ( Abc_LitIsCompl(Lit) ) // const 0
{
// Ssm_ObjSetLogic0( pObj );
Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 0 );
CounterPi0 += Gia_ObjIsPi(pGia, pObj);
Counter0++;
}
else
{
// Ssm_ObjSetLogic1( pObj );
Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 1 );
CounterPi1 += Gia_ObjIsPi(pGia, pObj);
Counter1++;
}
// if ( Gia_ObjIsPi(pGia, pObj) )
// printf( "%d ", Count );
}
// printf( "\n" );
Vec_IntFree( vCountLits );
printf( "Logic0 = %d (%d). Logic1 = %d (%d). ", Counter0, CounterPi0, Counter1, CounterPi1 );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
return vResult;
}
/**Function*************************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSimSetDefaultParams( Gia_ParSim_t * p )
{
memset( p, 0, sizeof(Gia_ParSim_t) );
// user-controlled parameters
p->nWords = 8; // the number of machine words
p->nIters = 32; // the number of timeframes
p->RandSeed = 0; // the seed to generate random numbers
p->TimeLimit = 60; // time limit in seconds
p->fCheckMiter = 0; // check if miter outputs are non-zero
p->fVerbose = 0; // enables verbose output
p->iOutFail = -1; // index of the failed output
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSimDelete( Gia_ManSim_t * p )
{
Vec_IntFreeP( &p->vConsts );
Vec_IntFreeP( &p->vCis2Ids );
Gia_ManStopP( &p->pAig );
ABC_FREE( p->pDataSim );
ABC_FREE( p->pDataSimCis );
ABC_FREE( p->pDataSimCos );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Creates fast simulation manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_ManSim_t * Gia_ManSimCreate( Gia_Man_t * pAig, Gia_ParSim_t * pPars )
{
Gia_ManSim_t * p;
int Entry, i;
p = ABC_ALLOC( Gia_ManSim_t, 1 );
memset( p, 0, sizeof(Gia_ManSim_t) );
// look for reset signals
if ( pPars->fVerbose )
p->vConsts = Gia_ManSimDeriveResets( pAig );
// derive the frontier
p->pAig = Gia_ManFront( pAig );
p->pPars = pPars;
p->nWords = pPars->nWords;
p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->pAig->nFront );
p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * Gia_ManCiNum(p->pAig) );
p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * Gia_ManCoNum(p->pAig) );
if ( !p->pDataSim || !p->pDataSimCis || !p->pDataSimCos )
{
Abc_Print( 1, "Simulator could not allocate %.2f GB for simulation info.\n",
4.0 * p->nWords * (p->pAig->nFront + Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig)) / (1<<30) );
Gia_ManSimDelete( p );
return NULL;
}
p->vCis2Ids = Vec_IntAlloc( Gia_ManCiNum(p->pAig) );
Vec_IntForEachEntry( pAig->vCis, Entry, i )
Vec_IntPush( p->vCis2Ids, i ); // do we need p->vCis2Ids?
if ( pPars->fVerbose )
Abc_Print( 1, "AIG = %7.2f MB. Front mem = %7.2f MB. Other mem = %7.2f MB.\n",
12.0*Gia_ManObjNum(p->pAig)/(1<<20),
4.0*p->nWords*p->pAig->nFront/(1<<20),
4.0*p->nWords*(Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig))/(1<<20) );
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimInfoRandom( Gia_ManSim_t * p, unsigned * pInfo )
{
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = Gia_ManRandom( 0 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimInfoZero( Gia_ManSim_t * p, unsigned * pInfo )
{
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = 0;
}
/**Function*************************************************************
Synopsis [Returns index of the first pattern that failed.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Gia_ManSimInfoIsZero( Gia_ManSim_t * p, unsigned * pInfo )
{
int w;
for ( w = 0; w < p->nWords; w++ )
if ( pInfo[w] )
return 32*w + Gia_WordFindFirstBit( pInfo[w] );
return -1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimInfoOne( Gia_ManSim_t * p, unsigned * pInfo )
{
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = ~0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimInfoCopy( Gia_ManSim_t * p, unsigned * pInfo, unsigned * pInfo0 )
{
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimulateCi( Gia_ManSim_t * p, Gia_Obj_t * pObj, int iCi )
{
unsigned * pInfo = Gia_SimData( p, Gia_ObjValue(pObj) );
unsigned * pInfo0 = Gia_SimDataCi( p, iCi );
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimulateCo( Gia_ManSim_t * p, int iCo, Gia_Obj_t * pObj )
{
unsigned * pInfo = Gia_SimDataCo( p, iCo );
unsigned * pInfo0 = Gia_SimData( p, Gia_ObjDiff0(pObj) );
int w;
if ( Gia_ObjFaninC0(pObj) )
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = ~pInfo0[w];
else
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_ManSimulateNode( Gia_ManSim_t * p, Gia_Obj_t * pObj )
{
unsigned * pInfo = Gia_SimData( p, Gia_ObjValue(pObj) );
unsigned * pInfo0 = Gia_SimData( p, Gia_ObjDiff0(pObj) );
unsigned * pInfo1 = Gia_SimData( p, Gia_ObjDiff1(pObj) );
int w;
if ( Gia_ObjFaninC0(pObj) )
{
if ( Gia_ObjFaninC1(pObj) )
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
else
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = ~pInfo0[w] & pInfo1[w];
}
else
{
if ( Gia_ObjFaninC1(pObj) )
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w] & ~pInfo1[w];
else
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w] & pInfo1[w];
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSimInfoInit( Gia_ManSim_t * p )
{
int iPioNum, i;
Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
{
if ( iPioNum < Gia_ManPiNum(p->pAig) )
Gia_ManSimInfoRandom( p, Gia_SimDataCi(p, i) );
else
Gia_ManSimInfoZero( p, Gia_SimDataCi(p, i) );
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSimInfoTransfer( Gia_ManSim_t * p )
{
int iPioNum, i;
Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
{
if ( iPioNum < Gia_ManPiNum(p->pAig) )
Gia_ManSimInfoRandom( p, Gia_SimDataCi(p, i) );
else
Gia_ManSimInfoCopy( p, Gia_SimDataCi(p, i), Gia_SimDataCo(p, Gia_ManPoNum(p->pAig)+iPioNum-Gia_ManPiNum(p->pAig)) );
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManSimulateRound( Gia_ManSim_t * p )
{
Gia_Obj_t * pObj;
int i, iCis = 0, iCos = 0;
assert( p->pAig->nFront > 0 );
assert( Gia_ManConst0(p->pAig)->Value == 0 );
Gia_ManSimInfoZero( p, Gia_SimData(p, 0) );
Gia_ManForEachObj1( p->pAig, pObj, i )
{
if ( Gia_ObjIsAndOrConst0(pObj) )
{
assert( Gia_ObjValue(pObj) < p->pAig->nFront );
Gia_ManSimulateNode( p, pObj );
}
else if ( Gia_ObjIsCo(pObj) )
{
assert( Gia_ObjValue(pObj) == GIA_NONE );
Gia_ManSimulateCo( p, iCos++, pObj );
}
else // if ( Gia_ObjIsCi(pObj) )
{
assert( Gia_ObjValue(pObj) < p->pAig->nFront );
Gia_ManSimulateCi( p, pObj, iCis++ );
}
}
assert( Gia_ManCiNum(p->pAig) == iCis );
assert( Gia_ManCoNum(p->pAig) == iCos );
}
/**Function*************************************************************
Synopsis [Returns index of the PO and pattern that failed it.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Gia_ManCheckPos( Gia_ManSim_t * p, int * piPo, int * piPat )
{
int i, iPat;
for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ )
{
iPat = Gia_ManSimInfoIsZero( p, Gia_SimDataCo(p, i) );
if ( iPat >= 0 )
{
*piPo = i;
*piPat = iPat;
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Returns the counter-example.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Gia_ManGenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids )
{
Abc_Cex_t * p;
unsigned * pData;
int f, i, w, iPioId, Counter;
p = Abc_CexAlloc( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), iFrame+1 );
p->iFrame = iFrame;
p->iPo = iOut;
// fill in the binary data
Counter = p->nRegs;
pData = ABC_ALLOC( unsigned, nWords );
for ( f = 0; f <= iFrame; f++, Counter += p->nPis )
for ( i = 0; i < Gia_ManPiNum(pAig); i++ )
{
iPioId = Vec_IntEntry( vCis2Ids, i );
if ( iPioId >= p->nPis )
continue;
for ( w = nWords-1; w >= 0; w-- )
pData[w] = Gia_ManRandom( 0 );
if ( Abc_InfoHasBit( pData, iPat ) )
Abc_InfoSetBit( p->pData, Counter + iPioId );
}
ABC_FREE( pData );
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManResetRandom( Gia_ParSim_t * pPars )
{
int i;
Gia_ManRandom( 1 );
for ( i = 0; i < pPars->RandSeed; i++ )
Gia_ManRandom( 0 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManSimSimulate( Gia_Man_t * pAig, Gia_ParSim_t * pPars )
{
extern int Gia_ManSimSimulateEquiv( Gia_Man_t * pAig, Gia_ParSim_t * pPars );
Gia_ManSim_t * p;
abctime clkTotal = Abc_Clock();
int i, iOut, iPat, RetValue = 0;
abctime nTimeToStop = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
if ( pAig->pReprs && pAig->pNexts )
return Gia_ManSimSimulateEquiv( pAig, pPars );
ABC_FREE( pAig->pCexSeq );
p = Gia_ManSimCreate( pAig, pPars );
Gia_ManResetRandom( pPars );
Gia_ManSimInfoInit( p );
for ( i = 0; i < pPars->nIters; i++ )
{
Gia_ManSimulateRound( p );
if ( pPars->fVerbose )
{
Abc_Print( 1, "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit );
Abc_Print( 1, "Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC );
}
if ( pPars->fCheckMiter && Gia_ManCheckPos( p, &iOut, &iPat ) )
{
Gia_ManResetRandom( pPars );
pPars->iOutFail = iOut;
pAig->pCexSeq = Gia_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids );
Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", iOut, pAig->pName, i );
if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) )
{
// Abc_Print( 1, "\n" );
Abc_Print( 1, "\nGenerated counter-example is INVALID. " );
// Abc_Print( 1, "\n" );
}
else
{
// Abc_Print( 1, "\n" );
// if ( pPars->fVerbose )
// Abc_Print( 1, "\nGenerated counter-example is verified correctly. " );
// Abc_Print( 1, "\n" );
}
RetValue = 1;
break;
}
if ( Abc_Clock() > nTimeToStop )
{
i++;
break;
}
if ( i < pPars->nIters - 1 )
Gia_ManSimInfoTransfer( p );
}
Gia_ManSimDelete( p );
if ( pAig->pCexSeq == NULL )
Abc_Print( 1, "No bug detected after simulating %d frames with %d words. ", i, pPars->nWords );
Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
return RetValue;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManSimReadFile( char * pFileIn )
{
int c;
Vec_Int_t * vPat;
FILE * pFile = fopen( pFileIn, "rb" );
if ( pFile == NULL )
{
printf( "Cannot open input file.\n" );
return NULL;
}
vPat = Vec_IntAlloc( 1000 );
while ( (c = fgetc(pFile)) != EOF )
if ( c == '0' || c == '1' )
Vec_IntPush( vPat, c - '0' );
fclose( pFile );
return vPat;
}
int Gia_ManSimWriteFile( char * pFileOut, Vec_Int_t * vPat, int nOuts )
{
int c, i;
FILE * pFile = fopen( pFileOut, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open output file.\n" );
return 0;
}
assert( Vec_IntSize(vPat) % nOuts == 0 );
Vec_IntForEachEntry( vPat, c, i )
{
fputc( '0' + c, pFile );
if ( i % nOuts == nOuts - 1 )
fputc( '\n', pFile );
}
fclose( pFile );
return 1;
}
Vec_Int_t * Gia_ManSimSimulateOne( Gia_Man_t * p, Vec_Int_t * vPat )
{
Vec_Int_t * vPatOut;
Gia_Obj_t * pObj, * pObjRo;
int i, k, f;
assert( Vec_IntSize(vPat) % Gia_ManPiNum(p) == 0 );
Gia_ManConst0(p)->fMark1 = 0;
Gia_ManForEachRo( p, pObj, i )
pObj->fMark1 = 0;
vPatOut = Vec_IntAlloc( 1000 );
for ( k = f = 0; f < Vec_IntSize(vPat) / Gia_ManPiNum(p); f++ )
{
Gia_ManForEachPi( p, pObj, i )
pObj->fMark1 = Vec_IntEntry( vPat, k++ );
Gia_ManForEachAnd( p, pObj, i )
pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj));
Gia_ManForEachCo( p, pObj, i )
pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj));
Gia_ManForEachPo( p, pObj, i )
Vec_IntPush( vPatOut, pObj->fMark1 );
Gia_ManForEachRiRo( p, pObj, pObjRo, i )
pObjRo->fMark1 = pObj->fMark1;
}
assert( k == Vec_IntSize(vPat) );
Gia_ManForEachObj( p, pObj, i )
pObj->fMark1 = 0;
return vPatOut;
}
void Gia_ManSimSimulatePattern( Gia_Man_t * p, char * pFileIn, char * pFileOut )
{
Vec_Int_t * vPat, * vPatOut;
vPat = Gia_ManSimReadFile( pFileIn );
if ( vPat == NULL )
return;
if ( Vec_IntSize(vPat) % Gia_ManPiNum(p) )
{
printf( "The number of 0s and 1s in the input file (%d) does not evenly divide by the number of primary inputs (%d).\n",
Vec_IntSize(vPat), Gia_ManPiNum(p) );
Vec_IntFree( vPat );
return;
}
vPatOut = Gia_ManSimSimulateOne( p, vPat );
if ( Gia_ManSimWriteFile( pFileOut, vPatOut, Gia_ManPoNum(p) ) )
printf( "Output patterns are written into file \"%s\".\n", pFileOut );
Vec_IntFree( vPat );
Vec_IntFree( vPatOut );
}
/**Function*************************************************************
Synopsis [Bit-parallel simulation during AIG construction.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline word * Gia_ManBuiltInDataPi( Gia_Man_t * p, int iCiId )
{
return Vec_WrdEntryP( p->vSimsPi, p->nSimWords * iCiId );
}
static inline word * Gia_ManBuiltInData( Gia_Man_t * p, int iObj )
{
return Vec_WrdEntryP( p->vSims, p->nSimWords * iObj );
}
static inline void Gia_ManBuiltInDataPrint( Gia_Man_t * p, int iObj )
{
// printf( "Obj %6d : ", iObj ); Extra_PrintBinary( stdout, Gia_ManBuiltInData(p, iObj), p->nSimWords * 64 ); printf( "\n" );
}
void Gia_ManBuiltInSimStart( Gia_Man_t * p, int nWords, int nObjs )
{
int i, k;
assert( !p->fBuiltInSim );
assert( Gia_ManAndNum(p) == 0 );
p->fBuiltInSim = 1;
p->iPatsPi = 0;
p->iPastPiMax = 0;
p->nSimWords = nWords;
p->nSimWordsMax = 8;
Gia_ManRandomW( 1 );
// init PI care info
p->vSimsPi = Vec_WrdAlloc( p->nSimWords * Gia_ManCiNum(p) );
Vec_WrdFill( p->vSimsPi, p->nSimWords * Gia_ManCiNum(p), 0 );
// init object sim info
p->vSims = Vec_WrdAlloc( p->nSimWords * nObjs );
Vec_WrdFill( p->vSims, p->nSimWords, 0 );
for ( i = 0; i < Gia_ManCiNum(p); i++ )
for ( k = 0; k < p->nSimWords; k++ )
Vec_WrdPush( p->vSims, Gia_ManRandomW(0) );
}
void Gia_ManBuiltInSimPerformInt( Gia_Man_t * p, int iObj )
{
Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int w;
word * pInfo = Gia_ManBuiltInData( p, iObj );
word * pInfo0 = Gia_ManBuiltInData( p, Gia_ObjFaninId0(pObj, iObj) );
word * pInfo1 = Gia_ManBuiltInData( p, Gia_ObjFaninId1(pObj, iObj) );
assert( p->fBuiltInSim || p->fIncrSim );
if ( Gia_ObjFaninC0(pObj) )
{
if ( Gia_ObjFaninC1(pObj) )
for ( w = 0; w < p->nSimWords; w++ )
pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
else
for ( w = 0; w < p->nSimWords; w++ )
pInfo[w] = ~pInfo0[w] & pInfo1[w];
}
else
{
if ( Gia_ObjFaninC1(pObj) )
for ( w = 0; w < p->nSimWords; w++ )
pInfo[w] = pInfo0[w] & ~pInfo1[w];
else
for ( w = 0; w < p->nSimWords; w++ )
pInfo[w] = pInfo0[w] & pInfo1[w];
}
assert( Vec_WrdSize(p->vSims) == Gia_ManObjNum(p) * p->nSimWords );
}
void Gia_ManBuiltInSimPerform( Gia_Man_t * p, int iObj )
{
int w;
for ( w = 0; w < p->nSimWords; w++ )
Vec_WrdPush( p->vSims, 0 );
Gia_ManBuiltInSimPerformInt( p, iObj );
}
void Gia_ManBuiltInSimResimulateCone_rec( Gia_Man_t * p, int iObj )
{
Gia_Obj_t * pObj;
if ( Gia_ObjIsTravIdCurrentId(p, iObj) )
return;
Gia_ObjSetTravIdCurrentId(p, iObj);
pObj = Gia_ManObj( p, iObj );
if ( Gia_ObjIsCi(pObj) )
return;
assert( Gia_ObjIsAnd(pObj) );
Gia_ManBuiltInSimResimulateCone_rec( p, Gia_ObjFaninId0(pObj, iObj) );
Gia_ManBuiltInSimResimulateCone_rec( p, Gia_ObjFaninId1(pObj, iObj) );
Gia_ManBuiltInSimPerformInt( p, iObj );
}
void Gia_ManBuiltInSimResimulateCone( Gia_Man_t * p, int iLit0, int iLit1 )
{
Gia_ManIncrementTravId( p );
Gia_ManBuiltInSimResimulateCone_rec( p, Abc_Lit2Var(iLit0) );
Gia_ManBuiltInSimResimulateCone_rec( p, Abc_Lit2Var(iLit1) );
}
void Gia_ManBuiltInSimResimulate( Gia_Man_t * p )
{
Gia_Obj_t * pObj; int iObj;
Gia_ManForEachAnd( p, pObj, iObj )
Gia_ManBuiltInSimPerformInt( p, iObj );
}
int Gia_ManBuiltInSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 )
{
word * pInfo0 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit0) );
word * pInfo1 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit1) ); int w;
assert( p->fBuiltInSim || p->fIncrSim );
// printf( "%d %d\n", Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1) );
// Extra_PrintBinary( stdout, pInfo0, 64*p->nSimWords ); printf( "\n" );
// Extra_PrintBinary( stdout, pInfo1, 64*p->nSimWords ); printf( "\n" );
// printf( "\n" );
if ( Abc_LitIsCompl(iLit0) )
{
if ( Abc_LitIsCompl(iLit1) )
{
for ( w = 0; w < p->nSimWords; w++ )
if ( ~pInfo0[w] & ~pInfo1[w] )
return 1;
}
else
{
for ( w = 0; w < p->nSimWords; w++ )
if ( ~pInfo0[w] & pInfo1[w] )
return 1;
}
}
else
{
if ( Abc_LitIsCompl(iLit1) )
{
for ( w = 0; w < p->nSimWords; w++ )
if ( pInfo0[w] & ~pInfo1[w] )
return 1;
}
else
{
for ( w = 0; w < p->nSimWords; w++ )
if ( pInfo0[w] & pInfo1[w] )
return 1;
}
}
return 0;
}
int Gia_ManBuiltInSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 )
{
word * pInfo0 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit0) );
word * pInfo1 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit1) ); int w;
assert( p->fBuiltInSim || p->fIncrSim );
// printf( "%d %d\n", Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1) );
// Extra_PrintBinary( stdout, pInfo0, 64*p->nSimWords ); printf( "\n" );
// Extra_PrintBinary( stdout, pInfo1, 64*p->nSimWords ); printf( "\n" );
// printf( "\n" );
if ( Abc_LitIsCompl(iLit0) )
{
if ( Abc_LitIsCompl(iLit1) )
{
for ( w = 0; w < p->nSimWords; w++ )
if ( ~pInfo0[w] != ~pInfo1[w] )
return 0;
}
else
{
for ( w = 0; w < p->nSimWords; w++ )
if ( ~pInfo0[w] != pInfo1[w] )
return 0;
}
}
else
{
if ( Abc_LitIsCompl(iLit1) )
{
for ( w = 0; w < p->nSimWords; w++ )
if ( pInfo0[w] != ~pInfo1[w] )
return 0;
}
else
{
for ( w = 0; w < p->nSimWords; w++ )
if ( pInfo0[w] != pInfo1[w] )
return 0;
}
}
return 1;
}
int Gia_ManBuiltInSimPack( Gia_Man_t * p, Vec_Int_t * vPat )
{
int i, k, iLit;
assert( Vec_IntSize(vPat) > 0 );
//printf( "%d ", Vec_IntSize(vPat) );
for ( i = 0; i < p->iPatsPi; i++ )
{
Vec_IntForEachEntry( vPat, iLit, k )
if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), i) &&
Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), i) == Abc_LitIsCompl(iLit) )
break;
if ( k == Vec_IntSize(vPat) )
return i; // success
}
return -1; // failure
}
// adds PI pattern to storage; the pattern comes in terms of CiIds
int Gia_ManBuiltInSimAddPat( Gia_Man_t * p, Vec_Int_t * vPat )
{
int Period = 0xF;
int fOverflow = p->iPatsPi == 64 * p->nSimWords && p->nSimWords == p->nSimWordsMax;
int k, iLit, iPat = Gia_ManBuiltInSimPack( p, vPat );
if ( iPat == -1 )
{
if ( fOverflow )
{
if ( (p->iPastPiMax & Period) == 0 )
Gia_ManBuiltInSimResimulate( p );
iPat = p->iPastPiMax;
//if ( p->iPastPiMax == 64 * p->nSimWordsMax - 1 )
// printf( "Completed the cycle.\n" );
p->iPastPiMax = p->iPastPiMax == 64 * p->nSimWordsMax - 1 ? 0 : p->iPastPiMax + 1;
}
else
{
if ( p->iPatsPi && (p->iPatsPi & Period) == 0 )
Gia_ManBuiltInSimResimulate( p );
if ( p->iPatsPi == 64 * p->nSimWords )
{
Vec_Wrd_t * vTemp = Vec_WrdAlloc( 2 * Vec_WrdSize(p->vSims) );
word Data; int w, Count = 0, iObj = 0;
Vec_WrdForEachEntry( p->vSims, Data, w )
{
Vec_WrdPush( vTemp, Data );
if ( ++Count == p->nSimWords )
{
Gia_Obj_t * pObj = Gia_ManObj(p, iObj++);
if ( Gia_ObjIsCi(pObj) )
Vec_WrdPush( vTemp, Gia_ManRandomW(0) ); // Vec_WrdPush( vTemp, 0 );
else if ( Gia_ObjIsAnd(pObj) )
Vec_WrdPush( vTemp, pObj->fPhase ? ~(word)0 : 0 );
else
Vec_WrdPush( vTemp, 0 );
Count = 0;
}
}
assert( iObj == Gia_ManObjNum(p) );
Vec_WrdFree( p->vSims );
p->vSims = vTemp;
vTemp = Vec_WrdAlloc( 2 * Vec_WrdSize(p->vSimsPi) );
Count = 0;
Vec_WrdForEachEntry( p->vSimsPi, Data, w )
{
Vec_WrdPush( vTemp, Data );
if ( ++Count == p->nSimWords )
{
Vec_WrdPush( vTemp, 0 );
Count = 0;
}
}
Vec_WrdFree( p->vSimsPi );
p->vSimsPi = vTemp;
// update the word count
p->nSimWords++;
assert( Vec_WrdSize(p->vSims) == p->nSimWords * Gia_ManObjNum(p) );
assert( Vec_WrdSize(p->vSimsPi) == p->nSimWords * Gia_ManCiNum(p) );
//printf( "Resizing to %d words.\n", p->nSimWords );
}
iPat = p->iPatsPi++;
}
}
assert( iPat >= 0 && iPat < p->iPatsPi );
// add literals
if ( fOverflow )
{
int iVar;
Vec_IntForEachEntry( &p->vSuppVars, iVar, k )
if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, iVar), iPat) )
Abc_TtXorBit(Gia_ManBuiltInDataPi(p, iVar), iPat);
Vec_IntForEachEntry( vPat, iLit, k )
{
if ( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) == Abc_LitIsCompl(iLit) )
Abc_TtXorBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat);
Abc_TtXorBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat);
}
}
else
{
Vec_IntForEachEntry( vPat, iLit, k )
{
if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat) )
assert( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) != Abc_LitIsCompl(iLit) );
else
{
if ( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) == Abc_LitIsCompl(iLit) )
Abc_TtXorBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat);
Abc_TtXorBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat);
}
}
}
return 1;
}
/**Function*************************************************************
Synopsis [Finds a satisfying assignment.]
Description [Returns 1 if a sat assignment is found; 0 otherwise.]
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManObjCheckSat_rec( Gia_Man_t * p, int iLit, Vec_Int_t * vObjs )
{
int iObj = Abc_Lit2Var(iLit);
Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
if ( pObj->fMark0 )
return pObj->fMark1 == (unsigned)Abc_LitIsCompl(iLit);
pObj->fMark0 = 1;
pObj->fMark1 = Abc_LitIsCompl(iLit);
Vec_IntPush( vObjs, iObj );
if ( Gia_ObjIsAnd(pObj) )
{
if ( pObj->fMark1 == 0 ) // node value is 1
{
if ( !Gia_ManObjCheckSat_rec( p, Gia_ObjFaninLit0(pObj, iObj), vObjs ) ) return 0;
if ( !Gia_ManObjCheckSat_rec( p, Gia_ObjFaninLit1(pObj, iObj), vObjs ) ) return 0;
}
else
{
if ( !Gia_ManObjCheckSat_rec( p, Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)), vObjs ) ) return 0;
}
}
return 1;
}
int Gia_ManObjCheckOverlap1( Gia_Man_t * p, int iLit0, int iLit1, Vec_Int_t * vObjs )
{
Gia_Obj_t * pObj;
int i, Res0, Res1 = 0;
// Gia_ManForEachObj( p, pObj, i )
// assert( pObj->fMark0 == 0 && pObj->fMark1 == 0 );
Vec_IntClear( vObjs );
Res0 = Gia_ManObjCheckSat_rec( p, iLit0, vObjs );
if ( Res0 )
Res1 = Gia_ManObjCheckSat_rec( p, iLit1, vObjs );
Gia_ManForEachObjVec( vObjs, p, pObj, i )
pObj->fMark0 = pObj->fMark1 = 0;
return Res0 && Res1;
}
int Gia_ManObjCheckOverlap( Gia_Man_t * p, int iLit0, int iLit1, Vec_Int_t * vObjs )
{
if ( Gia_ManObjCheckOverlap1( p, iLit0, iLit1, vObjs ) )
return 1;
return Gia_ManObjCheckOverlap1( p, iLit1, iLit0, vObjs );
}
/**Function*************************************************************
Synopsis [Bit-parallel simulation during AIG construction.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManIncrSimUpdate( Gia_Man_t * p )
{
int i, k;
// extend timestamp info
assert( Vec_IntSize(p->vTimeStamps) <= Gia_ManObjNum(p) );
Vec_IntFillExtra( p->vTimeStamps, Gia_ManObjNum(p), 0 );
// extend simulation info
assert( Vec_WrdSize(p->vSims) <= Gia_ManObjNum(p) * p->nSimWords );
Vec_WrdFillExtra( p->vSims, Gia_ManObjNum(p) * p->nSimWords, 0 );
// extend PI info
assert( p->iNextPi <= Gia_ManCiNum(p) );
for ( i = p->iNextPi; i < Gia_ManCiNum(p); i++ )
{
word * pSims = Gia_ManBuiltInData( p, Gia_ManCiIdToId(p, i) );
for ( k = 0; k < p->nSimWords; k++ )
pSims[k] = Gia_ManRandomW(0);
}
p->iNextPi = Gia_ManCiNum(p);
}
void Gia_ManIncrSimStart( Gia_Man_t * p, int nWords, int nObjs )
{
assert( !p->fIncrSim );
p->fIncrSim = 1;
p->iPatsPi = 0;
p->nSimWords = nWords;
// init time stamps
p->iTimeStamp = 1;
p->vTimeStamps = Vec_IntAlloc( p->nSimWords );
// init object sim info
p->iNextPi = 0;
p->vSims = Vec_WrdAlloc( p->nSimWords * nObjs );
Gia_ManRandomW( 1 );
}
void Gia_ManIncrSimStop( Gia_Man_t * p )
{
assert( p->fIncrSim );
p->fIncrSim = 0;
p->iPatsPi = 0;
p->nSimWords = 0;
p->iTimeStamp = 1;
Vec_IntFreeP( &p->vTimeStamps );
Vec_WrdFreeP( &p->vSims );
}
void Gia_ManIncrSimSet( Gia_Man_t * p, Vec_Int_t * vObjLits )
{
int i, iLit;
assert( Vec_IntSize(vObjLits) > 0 );
p->iTimeStamp++;
Vec_IntForEachEntry( vObjLits, iLit, i )
{
word * pSims = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit) );
if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(iLit))) )
continue;
//assert( Vec_IntEntry(p->vTimeStamps, Abc_Lit2Var(iLit)) == p->iTimeStamp-1 );
Vec_IntWriteEntry(p->vTimeStamps, Abc_Lit2Var(iLit), p->iTimeStamp);
if ( Abc_TtGetBit(pSims, p->iPatsPi) == Abc_LitIsCompl(iLit) )
Abc_TtXorBit(pSims, p->iPatsPi);
}
p->iPatsPi = (p->iPatsPi == p->nSimWords * 64 - 1) ? 0 : p->iPatsPi + 1;
}
void Gia_ManIncrSimCone_rec( Gia_Man_t * p, int iObj )
{
Gia_Obj_t * pObj = Gia_ManObj( p, iObj );
if ( Gia_ObjIsCi(pObj) )
return;
if ( Vec_IntEntry(p->vTimeStamps, iObj) == p->iTimeStamp )
return;
assert( Vec_IntEntry(p->vTimeStamps, iObj) < p->iTimeStamp );
Vec_IntWriteEntry( p->vTimeStamps, iObj, p->iTimeStamp );
assert( Gia_ObjIsAnd(pObj) );
Gia_ManIncrSimCone_rec( p, Gia_ObjFaninId0(pObj, iObj) );
Gia_ManIncrSimCone_rec( p, Gia_ObjFaninId1(pObj, iObj) );
Gia_ManBuiltInSimPerformInt( p, iObj );
}
int Gia_ManIncrSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 )
{
assert( iLit0 > 1 && iLit1 > 1 );
Gia_ManIncrSimUpdate( p );
Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit0) );
Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit1) );
// return 0; // disable
return Gia_ManBuiltInSimCheckOver( p, iLit0, iLit1 );
}
int Gia_ManIncrSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 )
{
assert( iLit0 > 1 && iLit1 > 1 );
Gia_ManIncrSimUpdate( p );
Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit0) );
Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit1) );
// return 1; // disable
return Gia_ManBuiltInSimCheckEqual( p, iLit0, iLit1 );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END