From c48e3c7ab43f7aac5b462b1a544d82e1be7cf9ea Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 29 Nov 2012 13:34:07 -0800 Subject: Counter-example analysis and optimization. --- src/sat/bmc/bmcCexTools.c | 590 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 590 insertions(+) create mode 100644 src/sat/bmc/bmcCexTools.c (limited to 'src/sat') diff --git a/src/sat/bmc/bmcCexTools.c b/src/sat/bmc/bmcCexTools.c new file mode 100644 index 00000000..0cbb0e9a --- /dev/null +++ b/src/sat/bmc/bmcCexTools.c @@ -0,0 +1,590 @@ +/**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 [Prints one counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs ) +{ + int i, k, Count, iBit = 0; + Abc_CexPrintStatsInputs( pCex, nInputs ); + return; + + for ( i = 0; i <= pCex->iFrame; i++ ) + { + Count = 0; + printf( "%3d : ", i ); + for ( k = 0; k < nInputs; 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, 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 ) +{ + 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 = Abc_InfoHasBit(pCex->pData, iBit++); + pObjRi->fMark1 = 1; + } + 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) ); + printf( "Implications: " ); + Bmc_CexPrint( pNew2, Gia_ManPiNum(p) ); + 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 ) +{ + 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 = 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 ( !Abc_InfoHasBit(pCexImpl->pData, pNew->nPis * i + k) ) + Abc_InfoSetBit(pNew->pData, pNew->nPis * i + k); + } + } + printf( "Care bits: " ); + Bmc_CexPrint( pNew, Gia_ManPiNum(p) ); + 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; + int iFrame = iBit / pCexState->nPis; + int iNumber = iBit % pCexState->nPis; + 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 = iFrame; 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) ); + + 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 ) +{ + Abc_Cex_t * pNew, * pTemp, * pPrev = NULL; + int b, fEqual = 0, fPrevStatus = 0; + clock_t clk = 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) ); + 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", clock() - clk ); + printf( "Essentials: " ); + Bmc_CexPrint( pNew, Gia_ManPiNum(p) ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [Computes essential bits of the CEX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex ) +{ + Abc_Cex_t * pCexImpl = NULL; + Abc_Cex_t * pCexStates = Bmc_CexInnerStates( p, pCex, &pCexImpl ); + Abc_Cex_t * pCexCare = Bmc_CexCareBits( p, pCexStates, pCexImpl, NULL, 1 ); + Abc_Cex_t * pCexEss, * pCexMin; + + if ( !Bmc_CexVerify( p, pCex, pCexCare ) ) + printf( "Counter-example care-set verification has failed.\n" ); + +// Bmc_CexEssentialBitTest( p, pCexStates ); + pCexEss = Bmc_CexEssentialBits( p, pCexStates, pCexCare ); + + pCexMin = Bmc_CexCareBits( p, pCexStates, pCexImpl, pCexEss, 0 ); + + if ( !Bmc_CexVerify( p, pCex, pCexMin ) ) + printf( "Counter-example care-set verification has failed.\n" ); + +// if ( !Bmc_CexVerify( p, pCex, pCexEss ) ) +// printf( "Counter-example care-set verification has failed.\n" ); + + Abc_CexFreeP( &pCexStates ); + Abc_CexFreeP( &pCexImpl ); + Abc_CexFreeP( &pCexCare ); + Abc_CexFreeP( &pCexEss ); + Abc_CexFreeP( &pCexMin ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + -- cgit v1.2.3