| /**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 |
| |