/**CFile**************************************************************** FileName [bmcChain.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Implementation of chain BMC.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcChain.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "aig/gia/giaAig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the first failure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Bmc_ChainFailOneOutput( Gia_Man_t * p, int nFrameMax, int nConfMax, int fVerbose, int fVeryVerbose ) { int RetValue; Abc_Cex_t * pCex = NULL; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); Saig_ParBmc_t Pars, * pPars = &Pars; Saig_ParBmcSetDefaultParams( pPars ); pPars->nFramesMax = nFrameMax; pPars->nConfLimit = nConfMax; pPars->fVerbose = fVeryVerbose; RetValue = Saig_ManBmcScalable( pAig, pPars ); if ( RetValue == 0 ) // SAT { pCex = pAig->pSeqModel, pAig->pSeqModel = NULL; if ( fVeryVerbose ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.\n", pCex->iPo, p->pName, pCex->iFrame ); } else if ( fVeryVerbose ) Abc_Print( 1, "No output asserted in %d frames. Resource limit reached.\n", pPars->iFrame+2 ); Aig_ManStop( pAig ); return pCex; } /**Function************************************************************* Synopsis [Move GIA into the failing state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupWithInit( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) { pObj->Value = Gia_ManAppendCi( pNew ); pObj->Value = Abc_LitNotCond( pObj->Value, pObj->fMark0 ); } else if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ObjFanin0Copy(pObj); pObj->Value = Abc_LitNotCond( pObj->Value, pObj->fMark0 ); pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); } } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } Gia_Man_t * Gia_ManVerifyCexAndMove( Gia_Man_t * pGia, Abc_Cex_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; Gia_ManCleanMark0(pGia); Gia_ManForEachRo( pGia, pObj, i ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Gia_ManForEachPi( pGia, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); Gia_ManForEachAnd( pGia, pObj, k ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachCo( pGia, pObj, k ) pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); if ( i == p->iFrame ) break; Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, k ) pObjRo->fMark0 = pObjRi->fMark0; } assert( iBit == p->nBits ); RetValue = Gia_ManPo(pGia, p->iPo)->fMark0; assert( RetValue ); // set PI/PO values to zero and transfer RO values to RI Gia_ManForEachPi( pGia, pObj, k ) pObj->fMark0 = 0; Gia_ManForEachPo( pGia, pObj, k ) pObj->fMark0 = 0; Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, k ) pObjRi->fMark0 = pObjRo->fMark0; // duplicate assuming CI/CO marks are set correctly pNew = Gia_ManDupWithInit( pGia ); Gia_ManCleanMark0(pGia); return pNew; } /**Function************************************************************* Synopsis [Find what outputs fail in this state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupPosAndPropagateInit( Gia_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManHashAlloc( pNew ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsPi(p, pObj) ) pObj->Value = Gia_ManAppendCi( pNew ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = 0; else if ( Gia_ObjIsPo(p, pObj) ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManHashStop( pNew ); assert( Gia_ManPiNum(p) == Gia_ManPiNum(pNew) ); assert( Gia_ManPoNum(p) == Gia_ManPoNum(pNew) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } sat_solver * Gia_ManDeriveSatSolver( Gia_Man_t * p, Vec_Int_t * vSatIds ) { // extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); sat_solver * pSat; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); // Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); Cnf_Dat_t * pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); // save SAT vars for the primary inputs if ( vSatIds ) { Aig_Obj_t * pObj; int i; Vec_IntClear( vSatIds ); Aig_ManForEachCi( pAig, pObj, i ) Vec_IntPush( vSatIds, pCnf->pVarNums[ Aig_ObjId(pObj) ] ); assert( Vec_IntSize(vSatIds) == Gia_ManPiNum(p) ); } Aig_ManStop( pAig ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); Cnf_DataFree( pCnf ); assert( p->nRegs == 0 ); return pSat; } Vec_Int_t * Bmc_ChainFindFailedOutputs( Gia_Man_t * p, Vec_Ptr_t * vCexes ) { Vec_Int_t * vOutputs; Vec_Int_t * vSatIds; Gia_Man_t * pInit; Gia_Obj_t * pObj; sat_solver * pSat; int i, j, Lit, status = 0; // derive output logic cones pInit = Gia_ManDupPosAndPropagateInit( p ); // derive SAT solver and test vSatIds = Vec_IntAlloc( Gia_ManPiNum(p) ); pSat = Gia_ManDeriveSatSolver( pInit, vSatIds ); vOutputs = Vec_IntAlloc( 100 ); Gia_ManForEachPo( pInit, pObj, i ) { if ( Gia_ObjFaninLit0p(pInit, pObj) == 0 ) continue; Lit = Abc_Var2Lit( i+1, 0 ); status = sat_solver_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 ); if ( status == l_True ) { // save the index of solved output Vec_IntPush( vOutputs, i ); // create CEX for this output if ( vCexes ) { Abc_Cex_t * pCex = Abc_CexAlloc( Gia_ManRegNum(p), Gia_ManPiNum(p), 1 ); pCex->iFrame = 0; pCex->iPo = i; for ( j = 0; j < Gia_ManPiNum(p); j++ ) if ( sat_solver_var_value( pSat, Vec_IntEntry(vSatIds, j) ) ) Abc_InfoSetBit( pCex->pData, Gia_ManRegNum(p) + j ); Vec_PtrPush( vCexes, pCex ); } } } Gia_ManStop( pInit ); sat_solver_delete( pSat ); Vec_IntFree( vSatIds ); return vOutputs; } /**Function************************************************************* Synopsis [Cleanup AIG by removing COs replacing failed out by const0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ObjMakePoConst0( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); pObj->iDiff0 = Gia_ObjId( p, pObj ); pObj->fCompl0 = 0; } int Gia_ManCountNonConst0( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Count = 0; Gia_ManForEachPo( p, pObj, i ) Count += (Gia_ObjFaninLit0p(p, pObj) != 0); return Count; } Gia_Man_t * Bmc_ChainCleanup( Gia_Man_t * p, Vec_Int_t * vOutputs ) { int i, iOut; Vec_IntForEachEntry( vOutputs, iOut, i ) { Gia_Obj_t * pObj = Gia_ManPo( p, iOut ); assert( Gia_ObjFaninLit0p(p, pObj) != 0 ); Gia_ObjMakePoConst0( p, pObj ); assert( Gia_ObjFaninLit0p(p, pObj) == 0 ); } return Gia_ManCleanup( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_ChainTest( Gia_Man_t * p, int nFrameMax, int nConfMax, int fVerbose, int fVeryVerbose, Vec_Ptr_t ** pvCexes ) { int Iter, IterMax = 10000; Gia_Man_t * pTemp, * pNew = Gia_ManDup(p); Abc_Cex_t * pCex = NULL; Vec_Int_t * vOutputs; abctime clk2, clk = Abc_Clock(); abctime clkBmc = 0; abctime clkMov = 0; abctime clkSat = 0; abctime clkCln = 0; abctime clkSwp = 0; int DepthTotal = 0; if ( pvCexes ) *pvCexes = Vec_PtrAlloc( 1000 ); for ( Iter = 0; Iter < IterMax; Iter++ ) { if ( Gia_ManPoNum(pNew) == 0 ) { if ( fVerbose ) printf( "Finished all POs.\n" ); break; } // run BMC till the first failure clk2 = Abc_Clock(); pCex = Bmc_ChainFailOneOutput( pNew, nFrameMax, nConfMax, fVerbose, fVeryVerbose ); clkBmc += Abc_Clock() - clk2; if ( pCex == NULL ) { if ( fVerbose ) printf( "BMC could not detect a failed output in %d frames with %d conflicts.\n", nFrameMax, nConfMax ); break; } assert( !Iter || pCex->iFrame > 0 ); // move the AIG to the failure state clk2 = Abc_Clock(); pNew = Gia_ManVerifyCexAndMove( pTemp = pNew, pCex ); Gia_ManStop( pTemp ); DepthTotal += pCex->iFrame; clkMov += Abc_Clock() - clk2; // find outputs that fail in this state clk2 = Abc_Clock(); vOutputs = Bmc_ChainFindFailedOutputs( pNew, pvCexes ? *pvCexes : NULL ); assert( Vec_IntFind(vOutputs, pCex->iPo) >= 0 ); // save the counter-example if ( pvCexes ) Vec_PtrPush( *pvCexes, pCex ); else Abc_CexFree( pCex ); clkSat += Abc_Clock() - clk2; // remove them from the AIG clk2 = Abc_Clock(); pNew = Bmc_ChainCleanup( pTemp = pNew, vOutputs ); Gia_ManStop( pTemp ); clkCln += Abc_Clock() - clk2; // perform sequential cleanup clk2 = Abc_Clock(); // pNew = Gia_ManSeqStructSweep( pTemp = pNew, 0, 1, 0 ); // Gia_ManStop( pTemp ); clkSwp += Abc_Clock() - clk2; // printout if ( fVerbose ) { int nNonConst = Gia_ManCountNonConst0(pNew); printf( "Iter %4d : ", Iter+1 ); printf( "Depth =%5d ", DepthTotal ); printf( "FailPo =%5d ", Vec_IntSize(vOutputs) ); printf( "UndecPo =%5d ", nNonConst ); printf( "(%6.2f %%) ", 100.0 * nNonConst / Gia_ManPoNum(pNew) ); printf( "AIG =%8d ", Gia_ManAndNum(pNew) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } Vec_IntFree( vOutputs ); } printf( "Completed a CEX chain with %d segments, %d frames, and %d failed POs (out of %d). ", Iter, DepthTotal, Gia_ManPoNum(pNew) - Gia_ManCountNonConst0(pNew), Gia_ManPoNum(pNew) ); if ( fVerbose ) { Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Abc_PrintTimeP( 1, "BMC ", clkBmc, Abc_Clock() - clk ); Abc_PrintTimeP( 1, "Init ", clkMov, Abc_Clock() - clk ); Abc_PrintTimeP( 1, "SAT ", clkSat, Abc_Clock() - clk ); Abc_PrintTimeP( 1, "Clean", clkCln, Abc_Clock() - clk ); // Abc_PrintTimeP( 1, "Sweep", clkSwp, Abc_Clock() - clk ); } Gia_ManStop( pNew ); if ( pvCexes ) printf( "Total number of CEXes collected = %d.\n", Vec_PtrSize(*pvCexes) ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END