blob: 9c80b27817084e01f186c06c0b97ad678ce10d48 [file] [log] [blame]
/**CFile****************************************************************
FileName [bmcCexTools.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [SAT-based bounded model checking.]
Synopsis [CEX analysis and optimization toolbox.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: bmcCexTools.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bmc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static inline word Bmc_CexBitMask( int iBit ) { assert( iBit < 64 ); return ~(((word)1) << iBit); }
static inline void Bmc_CexCopySim( Vec_Wrd_t * vSims, int iObjTo, int iObjFrom ) { Vec_WrdWriteEntry( vSims, iObjTo, iObjFrom ); }
static inline void Bmc_CexAndSim( Vec_Wrd_t * vSims, int iObjTo, int i, int j ) { Vec_WrdWriteEntry( vSims, iObjTo, Vec_WrdEntry(vSims, i) & Vec_WrdEntry(vSims, j) ); }
static inline void Bmc_CexOrSim( Vec_Wrd_t * vSims, int iObjTo, int i, int j ) { Vec_WrdWriteEntry( vSims, iObjTo, Vec_WrdEntry(vSims, i) | Vec_WrdEntry(vSims, j) ); }
static inline int Bmc_CexSim( Vec_Wrd_t * vSims, int iObj, int i ) { return (Vec_WrdEntry(vSims, iObj) >> i) & 1; }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bmc_CexBitCount( Abc_Cex_t * p, int nInputs )
{
int k, Counter = 0, Counter2 = 0;
if ( p == NULL )
{
printf( "The counter example is NULL.\n" );
return -1;
}
for ( k = 0; k < p->nBits; k++ )
{
Counter += Abc_InfoHasBit(p->pData, k);
if ( (k - p->nRegs) % p->nPis < nInputs )
Counter2 += Abc_InfoHasBit(p->pData, k);
}
return Counter2;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bmc_CexDumpStats( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare, Abc_Cex_t * pCexEss, Abc_Cex_t * pCexMin, abctime clk )
{
int nInputs = Gia_ManPiNum(p);
int nBitsTotal = (pCex->iFrame + 1) * nInputs;
int nBitsCare = Bmc_CexBitCount(pCexCare, nInputs);
int nBitsDC = nBitsTotal - nBitsCare;
int nBitsEss = Bmc_CexBitCount(pCexEss, nInputs);
int nBitsOpt = nBitsCare - nBitsEss;
int nBitsMin = Bmc_CexBitCount(pCexMin, nInputs);
FILE * pTable = fopen( "cex/stats.txt", "a+" );
fprintf( pTable, "%s ", p->pName );
fprintf( pTable, "%d ", nInputs );
fprintf( pTable, "%d ", Gia_ManRegNum(p) );
fprintf( pTable, "%d ", pCex->iFrame + 1 );
fprintf( pTable, "%d ", nBitsTotal );
fprintf( pTable, "%.2f ", 100.0 * nBitsDC / nBitsTotal );
fprintf( pTable, "%.2f ", 100.0 * nBitsOpt / nBitsTotal );
fprintf( pTable, "%.2f ", 100.0 * nBitsEss / nBitsTotal );
fprintf( pTable, "%.2f ", 100.0 * nBitsMin / nBitsTotal );
fprintf( pTable, "%.2f ", 1.0*clk/(CLOCKS_PER_SEC) );
fprintf( pTable, "\n" );
fclose( pTable );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bmc_CexDumpAogStats( Gia_Man_t * p, abctime clk )
{
FILE * pTable = fopen( "cex/aig_stats.txt", "a+" );
fprintf( pTable, "%s ", p->pName );
fprintf( pTable, "%d ", Gia_ManPiNum(p) );
fprintf( pTable, "%d ", Gia_ManAndNum(p) );
fprintf( pTable, "%d ", Gia_ManLevelNum(p) );
fprintf( pTable, "%.2f ", 1.0*clk/(CLOCKS_PER_SEC) );
fprintf( pTable, "\n" );
fclose( pTable );
}
/**Function*************************************************************
Synopsis [Performs initialized unrolling till the last frame.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Bmc_CexPerformUnrolling( Gia_Man_t * p, Abc_Cex_t * pCex )
{
Gia_Man_t * pNew, * pTemp;
Gia_Obj_t * pObj, * pObjRo, * pObjRi;
int i, k;
assert( Gia_ManRegNum(p) > 0 );
pNew = Gia_ManStart( (pCex->iFrame + 1) * Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManConst0(p)->Value = 0;
Gia_ManForEachRi( p, pObj, k )
pObj->Value = 0;
Gia_ManHashAlloc( pNew );
for ( i = 0; i <= pCex->iFrame; i++ )
{
Gia_ManForEachPi( p, pObj, k )
pObj->Value = Gia_ManAppendCi( pNew );
Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
pObjRo->Value = pObjRi->Value;
Gia_ManForEachAnd( p, pObj, k )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachCo( p, pObj, k )
pObj->Value = Gia_ObjFanin0Copy(pObj);
}
Gia_ManHashStop( pNew );
pObj = Gia_ManPo(p, pCex->iPo);
Gia_ManAppendCo( pNew, pObj->Value );
// cleanup
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
return pNew;
}
void Bmc_CexPerformUnrollingTest( Gia_Man_t * p, Abc_Cex_t * pCex )
{
Gia_Man_t * pNew;
abctime clk = Abc_Clock();
pNew = Bmc_CexPerformUnrolling( p, pCex );
Gia_ManPrintStats( pNew, NULL );
Gia_AigerWrite( pNew, "unroll.aig", 0, 0 );
//Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk );
Gia_ManStop( pNew );
printf( "CE-induced network is written into file \"unroll.aig\".\n" );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
/**Function*************************************************************
Synopsis [Computes CE-induced network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Bmc_CexBuildNetwork( Gia_Man_t * p, Abc_Cex_t * pCex )
{
Gia_Man_t * pNew, * pTemp;
Gia_Obj_t * pObj, * pObjRo, * pObjRi;
int fCompl0, fCompl1;
int i, k, iBit = pCex->nRegs;
// start the manager
pNew = Gia_ManStart( 1000 );
pNew->pName = Abc_UtilStrsav( "unate" );
// set const0
Gia_ManConst0(p)->fMark0 = 0;
Gia_ManConst0(p)->fMark1 = 1;
Gia_ManConst0(p)->Value = ~0;
// set init state
Gia_ManForEachRi( p, pObj, k )
{
pObj->fMark0 = 0;
pObj->fMark1 = 1;
pObj->Value = ~0;
}
Gia_ManHashAlloc( pNew );
for ( i = 0; i <= pCex->iFrame; i++ )
{
// primary inputs
Gia_ManForEachPi( p, pObj, k )
{
pObj->fMark0 = Abc_InfoHasBit( pCex->pData, iBit++ );
pObj->fMark1 = 0;
pObj->Value = Gia_ManAppendCi(pNew);
}
// transfer
Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
{
pObjRo->fMark0 = pObjRi->fMark0;
pObjRo->fMark1 = pObjRi->fMark1;
pObjRo->Value = pObjRi->Value;
}
// internal nodes
Gia_ManForEachAnd( p, pObj, k )
{
fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
pObj->fMark0 = fCompl0 & fCompl1;
if ( pObj->fMark0 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
else if ( !fCompl0 && !fCompl1 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
else if ( !fCompl0 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
else if ( !fCompl1 )
pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
else assert( 0 );
pObj->Value = ~0;
if ( pObj->fMark1 )
continue;
if ( pObj->fMark0 )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
else if ( !fCompl0 && !fCompl1 )
pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value );
else if ( !fCompl0 )
pObj->Value = Gia_ObjFanin0(pObj)->Value;
else if ( !fCompl1 )
pObj->Value = Gia_ObjFanin1(pObj)->Value;
else assert( 0 );
assert( pObj->Value > 0 );
}
// combinational outputs
Gia_ManForEachCo( p, pObj, k )
{
pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
pObj->Value = Gia_ObjFanin0(pObj)->Value;
}
}
Gia_ManHashStop( pNew );
assert( iBit == pCex->nBits );
// create primary output
pObj = Gia_ManPo(p, pCex->iPo);
assert( pObj->fMark0 == 1 );
assert( pObj->fMark1 == 0 );
assert( pObj->Value > 0 );
Gia_ManAppendCo( pNew, pObj->Value );
// cleanup
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
return pNew;
}
void Bmc_CexBuildNetworkTest( Gia_Man_t * p, Abc_Cex_t * pCex )
{
Gia_Man_t * pNew;
abctime clk = Abc_Clock();
pNew = Bmc_CexBuildNetwork( p, pCex );
Gia_ManPrintStats( pNew, NULL );
Gia_AigerWrite( pNew, "unate.aig", 0, 0 );
//Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk );
Gia_ManStop( pNew );
printf( "CE-induced network is written into file \"unate.aig\".\n" );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
/**Function*************************************************************
Synopsis [Prints one counter-example.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bmc_CexPrint( Abc_Cex_t * pCex, int nRealPis, int fVerbose )
{
int i, k, Count, iBit = pCex->nRegs;
Abc_CexPrintStatsInputs( pCex, nRealPis );
if ( !fVerbose )
return;
for ( i = 0; i <= pCex->iFrame; i++ )
{
Count = 0;
printf( "%3d : ", i );
for ( k = 0; k < nRealPis; k++ )
{
Count += Abc_InfoHasBit(pCex->pData, iBit);
printf( "%d", Abc_InfoHasBit(pCex->pData, iBit++) );
}
printf( " %3d ", Count );
Count = 0;
for ( ; k < pCex->nPis; k++ )
{
Count += Abc_InfoHasBit(pCex->pData, iBit);
printf( "%d", Abc_InfoHasBit(pCex->pData, iBit++) );
}
printf( " %3d\n", Count );
}
assert( iBit == pCex->nBits );
}
/**Function*************************************************************
Synopsis [Verifies the care set of the counter-example.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare )
{
Gia_Obj_t * pObj;
int i, k;
// assert( pCex->nRegs > 0 );
// assert( pCexCare->nRegs == 0 );
Gia_ObjTerSimSet0( Gia_ManConst0(p) );
Gia_ManForEachRi( p, pObj, k )
Gia_ObjTerSimSet0( pObj );
for ( i = 0; i <= pCex->iFrame; i++ )
{
Gia_ManForEachPi( p, pObj, k )
{
if ( !Abc_InfoHasBit( pCexCare->pData, pCexCare->nRegs + i * pCexCare->nPis + k ) )
Gia_ObjTerSimSetX( pObj );
else if ( Abc_InfoHasBit( pCex->pData, pCex->nRegs + i * pCex->nPis + k ) )
Gia_ObjTerSimSet1( pObj );
else
Gia_ObjTerSimSet0( pObj );
}
Gia_ManForEachRo( p, pObj, k )
Gia_ObjTerSimRo( p, pObj );
Gia_ManForEachAnd( p, pObj, k )
Gia_ObjTerSimAnd( pObj );
Gia_ManForEachCo( p, pObj, k )
Gia_ObjTerSimCo( pObj );
}
pObj = Gia_ManPo( p, pCex->iPo );
return Gia_ObjTerSimGet1(pObj);
}
/**Function*************************************************************
Synopsis [Computes internal states of the CEX.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Bmc_CexInnerStates( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t ** ppCexImpl, int fVerbose )
{
Abc_Cex_t * pNew, * pNew2;
Gia_Obj_t * pObj, * pObjRo, * pObjRi;
int fCompl0, fCompl1;
int i, k, iBit = 0;
assert( pCex->nRegs > 0 );
// start the counter-example
pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCex->iFrame + 1 );
pNew->iFrame = pCex->iFrame;
pNew->iPo = pCex->iPo;
// start the counter-example
pNew2 = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCex->iFrame + 1 );
pNew2->iFrame = pCex->iFrame;
pNew2->iPo = pCex->iPo;
// set initial state
Gia_ManCleanMark01(p);
// set const0
Gia_ManConst0(p)->fMark0 = 0;
Gia_ManConst0(p)->fMark1 = 1;
// set init state
Gia_ManForEachRi( p, pObjRi, k )
{
pObjRi->fMark0 = 0;
pObjRi->fMark1 = 1;
}
iBit = pCex->nRegs;
for ( i = 0; i <= pCex->iFrame; i++ )
{
Gia_ManForEachPi( p, pObj, k )
pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++);
Gia_ManForEachRiRo( p, pObjRi, pObjRo, k )
{
pObjRo->fMark0 = pObjRi->fMark0;
pObjRo->fMark1 = pObjRi->fMark1;
}
Gia_ManForEachCi( p, pObj, k )
{
if ( pObj->fMark0 )
Abc_InfoSetBit( pNew->pData, pNew->nPis * i + k );
if ( pObj->fMark1 )
Abc_InfoSetBit( pNew2->pData, pNew2->nPis * i + k );
}
Gia_ManForEachAnd( p, pObj, k )
{
fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
pObj->fMark0 = fCompl0 & fCompl1;
if ( pObj->fMark0 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
else if ( !fCompl0 && !fCompl1 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
else if ( !fCompl0 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
else if ( !fCompl1 )
pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
else assert( 0 );
}
Gia_ManForEachCo( p, pObj, k )
{
pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
}
/*
// print input/state/output
printf( "%3d : ", i );
Gia_ManForEachPi( p, pObj, k )
printf( "%d", pObj->fMark0 );
printf( " " );
Gia_ManForEachRo( p, pObj, k )
printf( "%d", pObj->fMark0 );
printf( " " );
Gia_ManForEachPo( p, pObj, k )
printf( "%d", pObj->fMark0 );
printf( "\n" );
*/
}
assert( iBit == pCex->nBits );
assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 );
printf( "Inner states: " );
Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose );
printf( "Implications: " );
Bmc_CexPrint( pNew2, Gia_ManPiNum(p), fVerbose );
if ( ppCexImpl )
*ppCexImpl = pNew2;
else
Abc_CexFree( pNew2 );
return pNew;
}
/**Function*************************************************************
Synopsis [Computes care bits of the CEX.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bmc_CexCareBits_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
int fCompl0, fCompl1;
if ( Gia_ObjIsConst0(pObj) )
return;
if ( pObj->fMark1 )
return;
pObj->fMark1 = 1;
if ( Gia_ObjIsCi(pObj) )
return;
assert( Gia_ObjIsAnd(pObj) );
fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
if ( pObj->fMark0 )
{
assert( fCompl0 == 1 && fCompl1 == 1 );
Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) );
Bmc_CexCareBits_rec( p, Gia_ObjFanin1(pObj) );
}
else
{
assert( fCompl0 == 0 || fCompl1 == 0 );
if ( fCompl0 == 0 )
Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) );
if ( fCompl1 == 0 )
Bmc_CexCareBits_rec( p, Gia_ObjFanin1(pObj) );
}
}
void Bmc_CexCareBits2_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
int fCompl0, fCompl1;
if ( Gia_ObjIsConst0(pObj) )
return;
if ( pObj->fMark1 )
return;
pObj->fMark1 = 1;
if ( Gia_ObjIsCi(pObj) )
return;
assert( Gia_ObjIsAnd(pObj) );
fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
if ( pObj->fMark0 )
{
assert( fCompl0 == 1 && fCompl1 == 1 );
Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) );
Bmc_CexCareBits2_rec( p, Gia_ObjFanin1(pObj) );
}
else
{
assert( fCompl0 == 0 || fCompl1 == 0 );
if ( fCompl0 == 0 )
Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) );
/**/
else
/**/
if ( fCompl1 == 0 )
Bmc_CexCareBits2_rec( p, Gia_ObjFanin1(pObj) );
}
}
Abc_Cex_t * Bmc_CexCareBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexImpl, Abc_Cex_t * pCexEss, int fFindAll, int fVerbose )
{
Abc_Cex_t * pNew;
Gia_Obj_t * pObj;
int fCompl0, fCompl1;
int i, k, iBit;
assert( pCexState->nRegs == 0 );
// start the counter-example
pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 );
pNew->iFrame = pCexState->iFrame;
pNew->iPo = pCexState->iPo;
// set initial state
Gia_ManCleanMark01(p);
// set const0
Gia_ManConst0(p)->fMark0 = 0;
Gia_ManConst0(p)->fMark1 = 1;
for ( i = pCexState->iFrame; i >= 0; i-- )
{
// set correct values
iBit = pCexState->nPis * i;
Gia_ManForEachCi( p, pObj, k )
{
pObj->fMark0 = Abc_InfoHasBit(pCexState->pData, iBit+k);
pObj->fMark1 = 0;
if ( pCexImpl )
pObj->fMark1 |= Abc_InfoHasBit(pCexImpl->pData, iBit+k);
if ( pCexEss )
pObj->fMark1 |= Abc_InfoHasBit(pCexEss->pData, iBit+k);
}
Gia_ManForEachAnd( p, pObj, k )
{
fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
pObj->fMark0 = fCompl0 & fCompl1;
if ( pObj->fMark0 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
else if ( !fCompl0 && !fCompl1 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
else if ( !fCompl0 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
else if ( !fCompl1 )
pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
else assert( 0 );
}
Gia_ManForEachCo( p, pObj, k )
pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
// move values from COs to CIs
if ( i == pCexState->iFrame )
{
assert( Gia_ManPo(p, pCexState->iPo)->fMark0 == 1 );
if ( fFindAll )
Bmc_CexCareBits_rec( p, Gia_ObjFanin0(Gia_ManPo(p, pCexState->iPo)) );
else
Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(Gia_ManPo(p, pCexState->iPo)) );
}
else
{
Gia_ManForEachRi( p, pObj, k )
if ( Abc_InfoHasBit(pNew->pData, pNew->nPis * (i+1) + Gia_ManPiNum(p) + k) )
{
if ( fFindAll )
Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) );
else
Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) );
}
}
// save the results
Gia_ManForEachCi( p, pObj, k )
if ( pObj->fMark1 )
{
pObj->fMark1 = 0;
if ( pCexImpl == NULL || !Abc_InfoHasBit(pCexImpl->pData, pNew->nPis * i + k) )
Abc_InfoSetBit(pNew->pData, pNew->nPis * i + k);
}
}
if ( pCexEss )
printf( "Minimized: " );
else
printf( "Care bits: " );
Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose );
return pNew;
}
/**Function*************************************************************
Synopsis [Simulates one bit to check whether it is essential.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Bmc_CexEssentialBitOne( Gia_Man_t * p, Abc_Cex_t * pCexState, int iBit, Abc_Cex_t * pCexPrev, int * pfEqual )
{
Abc_Cex_t * pNew;
Gia_Obj_t * pObj;
int i, k, fCompl0, fCompl1;
assert( pCexState->nRegs == 0 );
assert( iBit < pCexState->nBits );
if ( pfEqual )
*pfEqual = 0;
// start the counter-example
pNew = Abc_CexAllocFull( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 );
pNew->iFrame = pCexState->iFrame;
pNew->iPo = pCexState->iPo;
// clean bit
Abc_InfoXorBit( pNew->pData, iBit );
// simulate the remaining frames
Gia_ManConst0(p)->fMark0 = 0;
Gia_ManConst0(p)->fMark1 = 1;
for ( i = iBit / pCexState->nPis; i <= pCexState->iFrame; i++ )
{
Gia_ManForEachCi( p, pObj, k )
{
pObj->fMark0 = Abc_InfoHasBit( pCexState->pData, i * pCexState->nPis + k );
pObj->fMark1 = Abc_InfoHasBit( pNew->pData, i * pCexState->nPis + k );
}
Gia_ManForEachAnd( p, pObj, k )
{
fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj);
pObj->fMark0 = fCompl0 & fCompl1;
if ( pObj->fMark0 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1;
else if ( !fCompl0 && !fCompl1 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1;
else if ( !fCompl0 )
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
else if ( !fCompl1 )
pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1;
else assert( 0 );
}
Gia_ManForEachCo( p, pObj, k )
{
pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj);
pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1;
}
if ( i < pCexState->iFrame )
{
int fChanges = 0;
int fEqual = (pCexPrev != NULL);
int iBitShift = (i + 1) * pCexState->nPis + Gia_ManPiNum(p);
Gia_ManForEachRi( p, pObj, k )
{
if ( fEqual && pCexPrev && (int)pObj->fMark1 != Abc_InfoHasBit(pCexPrev->pData, iBitShift + k) )
fEqual = 0;
if ( !pObj->fMark1 )
{
fChanges = 1;
Abc_InfoXorBit( pNew->pData, iBitShift + k );
}
}
if ( !fChanges || fEqual )
{
if ( pfEqual )
*pfEqual = fEqual;
Abc_CexFree( pNew );
return NULL;
}
}
/*
if ( i == 20 )
{
printf( "Frame %d : ", i );
Gia_ManForEachRi( p, pObj, k )
printf( "%d", pObj->fMark1 );
printf( "\n" );
}
*/
}
return pNew;
}
void Bmc_CexEssentialBitTest( Gia_Man_t * p, Abc_Cex_t * pCexState )
{
Abc_Cex_t * pNew;
int b;
for ( b = 0; b < pCexState->nBits; b++ )
{
if ( b % 100 )
continue;
pNew = Bmc_CexEssentialBitOne( p, pCexState, b, NULL, NULL );
Bmc_CexPrint( pNew, Gia_ManPiNum(p), 0 );
if ( Gia_ManPo(p, pCexState->iPo)->fMark1 )
printf( "Not essential\n" );
else
printf( "Essential\n" );
Abc_CexFree( pNew );
}
}
/**Function*************************************************************
Synopsis [Computes essential bits of the CEX.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Bmc_CexEssentialBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexCare, int fVerbose )
{
Abc_Cex_t * pNew, * pTemp, * pPrev = NULL;
int b, fEqual = 0, fPrevStatus = 0;
// abctime clk = Abc_Clock();
assert( pCexState->nBits == pCexCare->nBits );
// start the counter-example
pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 );
pNew->iFrame = pCexState->iFrame;
pNew->iPo = pCexState->iPo;
// iterate through care-bits
for ( b = 0; b < pCexState->nBits; b++ )
{
// skip don't-care bits
if ( !Abc_InfoHasBit(pCexCare->pData, b) )
continue;
// skip state bits
if ( b % pCexCare->nPis >= Gia_ManPiNum(p) )
{
Abc_InfoSetBit( pNew->pData, b );
continue;
}
// check if this is an essential bit
pTemp = Bmc_CexEssentialBitOne( p, pCexState, b, pPrev, &fEqual );
// pTemp = Bmc_CexEssentialBitOne( p, pCexState, b, NULL, &fEqual );
if ( pTemp == NULL )
{
if ( fEqual && fPrevStatus )
Abc_InfoSetBit( pNew->pData, b );
continue;
}
// Bmc_CexPrint( pTemp, Gia_ManPiNum(p), fVerbose );
Abc_CexFree( pPrev );
pPrev = pTemp;
// record essential bit
fPrevStatus = !Gia_ManPo(p, pCexState->iPo)->fMark1;
if ( !Gia_ManPo(p, pCexState->iPo)->fMark1 )
Abc_InfoSetBit( pNew->pData, b );
}
Abc_CexFreeP( &pPrev );
// Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
printf( "Essentials: " );
Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose );
return pNew;
}
/**Function*************************************************************
Synopsis [Computes essential bits of the CEX.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose )
{
abctime clk = Abc_Clock();
Abc_Cex_t * pCexImpl = NULL;
Abc_Cex_t * pCexStates = Bmc_CexInnerStates( p, pCex, &pCexImpl, fVerbose );
Abc_Cex_t * pCexCare = Bmc_CexCareBits( p, pCexStates, pCexImpl, NULL, 1, fVerbose );
Abc_Cex_t * pCexEss, * pCexMin;
if ( !Bmc_CexVerify( p, pCex, pCexCare ) )
printf( "Counter-example care-set verification has failed.\n" );
pCexEss = Bmc_CexEssentialBits( p, pCexStates, pCexCare, fVerbose );
pCexMin = Bmc_CexCareBits( p, pCexStates, pCexImpl, pCexEss, 0, fVerbose );
if ( !Bmc_CexVerify( p, pCex, pCexMin ) )
printf( "Counter-example min-set verification has failed.\n" );
// Bmc_CexDumpStats( p, pCex, pCexCare, pCexEss, pCexMin, Abc_Clock() - clk );
Abc_CexFreeP( &pCexStates );
Abc_CexFreeP( &pCexImpl );
Abc_CexFreeP( &pCexCare );
Abc_CexFreeP( &pCexEss );
Abc_CexFreeP( &pCexMin );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
// Bmc_CexBuildNetworkTest( p, pCex );
// Bmc_CexPerformUnrollingTest( p, pCex );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END