| /**CFile**************************************************************** |
| |
| FileName [bmcBmc.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [SAT-based bounded model checking.] |
| |
| Synopsis [Simple BMC package.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: bmcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "proof/fra/fra.h" |
| #include "sat/cnf/cnf.h" |
| #include "sat/bsat/satStore.h" |
| #include "sat/satoko/satoko.h" |
| #include "bmc.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Create timeframes of the manager for BMC.] |
| |
| Description [The resulting manager is combinational. POs correspond to \ |
| the property outputs in each time-frame.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Man_t * Saig_ManFramesBmc( Aig_Man_t * pAig, int nFrames ) |
| { |
| Aig_Man_t * pFrames; |
| Aig_Obj_t * pObj, * pObjLi, * pObjLo; |
| int i, f; |
| assert( Saig_ManRegNum(pAig) > 0 ); |
| pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); |
| // map the constant node |
| Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); |
| // create variables for register outputs |
| Saig_ManForEachLo( pAig, pObj, i ) |
| pObj->pData = Aig_ManConst0( pFrames ); |
| // add timeframes |
| for ( f = 0; f < nFrames; f++ ) |
| { |
| // create PI nodes for this frame |
| Saig_ManForEachPi( pAig, pObj, i ) |
| pObj->pData = Aig_ObjCreateCi( pFrames ); |
| // add internal nodes of this frame |
| Aig_ManForEachNode( pAig, pObj, i ) |
| pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| // create POs for this frame |
| Saig_ManForEachPo( pAig, pObj, i ) |
| Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); |
| if ( f == nFrames - 1 ) |
| break; |
| // save register inputs |
| Saig_ManForEachLi( pAig, pObj, i ) |
| pObj->pData = Aig_ObjChild0Copy(pObj); |
| // transfer to register outputs |
| Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) |
| pObjLo->pData = pObjLi->pData; |
| } |
| Aig_ManCleanup( pFrames ); |
| return pFrames; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns the number of internal nodes that are not counted yet.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Saig_ManFramesCount_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) |
| { |
| if ( !Aig_ObjIsNode(pObj) ) |
| return 0; |
| if ( Aig_ObjIsTravIdCurrent(p, pObj) ) |
| return 0; |
| Aig_ObjSetTravIdCurrent(p, pObj); |
| return 1 + Saig_ManFramesCount_rec( p, Aig_ObjFanin0(pObj) ) + |
| Saig_ManFramesCount_rec( p, Aig_ObjFanin1(pObj) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Create timeframes of the manager for BMC.] |
| |
| Description [The resulting manager is combinational. POs correspond to |
| the property outputs in each time-frame. |
| The unrolling is stopped as soon as the number of nodes in the frames |
| exceeds the given maximum size.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Man_t * Saig_ManFramesBmcLimit( Aig_Man_t * pAig, int nFrames, int nSizeMax ) |
| { |
| Aig_Man_t * pFrames; |
| Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjPo; |
| int i, f, Counter = 0; |
| assert( Saig_ManRegNum(pAig) > 0 ); |
| pFrames = Aig_ManStart( nSizeMax ); |
| Aig_ManIncrementTravId( pFrames ); |
| // map the constant node |
| Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); |
| // create variables for register outputs |
| Saig_ManForEachLo( pAig, pObj, i ) |
| pObj->pData = Aig_ManConst0( pFrames ); |
| // add timeframes |
| Counter = 0; |
| for ( f = 0; f < nFrames; f++ ) |
| { |
| // create PI nodes for this frame |
| Saig_ManForEachPi( pAig, pObj, i ) |
| pObj->pData = Aig_ObjCreateCi( pFrames ); |
| // add internal nodes of this frame |
| Aig_ManForEachNode( pAig, pObj, i ) |
| pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| // create POs for this frame |
| Saig_ManForEachPo( pAig, pObj, i ) |
| { |
| pObjPo = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); |
| Counter += Saig_ManFramesCount_rec( pFrames, Aig_ObjFanin0(pObjPo) ); |
| } |
| if ( Counter >= nSizeMax ) |
| { |
| Aig_ManCleanup( pFrames ); |
| return pFrames; |
| } |
| if ( f == nFrames - 1 ) |
| break; |
| // save register inputs |
| Saig_ManForEachLi( pAig, pObj, i ) |
| pObj->pData = Aig_ObjChild0Copy(pObj); |
| // transfer to register outputs |
| Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) |
| pObjLo->pData = pObjLi->pData; |
| } |
| Aig_ManCleanup( pFrames ); |
| return pFrames; |
| } |
| |
| ABC_NAMESPACE_IMPL_END |
| |
| #include "misc/util/utilMem.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns a counter-example.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int * Sat2_SolverGetModel( satoko_t * p, int * pVars, int nVars ) |
| { |
| int * pModel; |
| int i; |
| pModel = ABC_CALLOC( int, nVars+1 ); |
| for ( i = 0; i < nVars; i++ ) |
| pModel[i] = satoko_read_cex_varvalue(p, pVars[i]); |
| return pModel; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs BMC for the given AIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Saig_ManBmcSimple( Aig_Man_t * pAig, int nFrames, int nSizeMax, int nConfLimit, int fRewrite, int fVerbose, int * piFrame, int nCofFanLit, int fUseSatoko ) |
| { |
| extern Aig_Man_t * Gia_ManCofactorAig( Aig_Man_t * p, int nFrames, int nCofFanLit ); |
| sat_solver * pSat = NULL; |
| satoko_t * pSat2 = NULL; |
| Cnf_Dat_t * pCnf; |
| Aig_Man_t * pFrames, * pAigTemp; |
| Aig_Obj_t * pObj; |
| int status, Lit, i, RetValue = -1; |
| abctime clk; |
| |
| // derive the timeframes |
| clk = Abc_Clock(); |
| if ( nCofFanLit ) |
| { |
| pFrames = Gia_ManCofactorAig( pAig, nFrames, nCofFanLit ); |
| if ( pFrames == NULL ) |
| return -1; |
| } |
| else if ( nSizeMax > 0 ) |
| { |
| pFrames = Saig_ManFramesBmcLimit( pAig, nFrames, nSizeMax ); |
| nFrames = Aig_ManCoNum(pFrames) / Saig_ManPoNum(pAig) + ((Aig_ManCoNum(pFrames) % Saig_ManPoNum(pAig)) > 0); |
| } |
| else |
| pFrames = Saig_ManFramesBmc( pAig, nFrames ); |
| if ( piFrame ) |
| *piFrame = nFrames; |
| if ( fVerbose ) |
| { |
| printf( "Running \"bmc\". AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", |
| Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), |
| Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); |
| printf( "Time-frames (%d): PI/PO = %d/%d. Node = %6d. Lev = %5d. ", |
| nFrames, Aig_ManCiNum(pFrames), Aig_ManCoNum(pFrames), |
| Aig_ManNodeNum(pFrames), Aig_ManLevelNum(pFrames) ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| fflush( stdout ); |
| } |
| // rewrite the timeframes |
| if ( fRewrite ) |
| { |
| clk = Abc_Clock(); |
| // pFrames = Dar_ManBalance( pAigTemp = pFrames, 0 ); |
| pFrames = Dar_ManRwsat( pAigTemp = pFrames, 1, 0 ); |
| Aig_ManStop( pAigTemp ); |
| if ( fVerbose ) |
| { |
| printf( "Time-frames after rewriting: Node = %6d. Lev = %5d. ", |
| Aig_ManNodeNum(pFrames), Aig_ManLevelNum(pFrames) ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| fflush( stdout ); |
| } |
| } |
| // create the SAT solver |
| clk = Abc_Clock(); |
| pCnf = Cnf_Derive( pFrames, Aig_ManCoNum(pFrames) ); |
| //if ( s_fInterrupt ) |
| //return -1; |
| if ( fUseSatoko ) |
| { |
| satoko_opts_t opts; |
| satoko_default_opts(&opts); |
| opts.conf_limit = nConfLimit; |
| pSat2 = satoko_create(); |
| satoko_configure(pSat2, &opts); |
| satoko_setnvars(pSat2, pCnf->nVars); |
| for ( i = 0; i < pCnf->nClauses; i++ ) |
| if ( !satoko_add_clause( pSat2, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) |
| assert( 0 ); |
| } |
| else |
| { |
| pSat = sat_solver_new(); |
| sat_solver_setnvars( pSat, pCnf->nVars ); |
| for ( i = 0; i < pCnf->nClauses; i++ ) |
| if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) |
| assert( 0 ); |
| } |
| if ( fVerbose ) |
| { |
| printf( "CNF: Variables = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| fflush( stdout ); |
| } |
| status = pSat ? sat_solver_simplify(pSat) : 1; |
| if ( status == 0 ) |
| { |
| if ( fVerbose ) |
| { |
| printf( "The BMC problem is trivially UNSAT\n" ); |
| fflush( stdout ); |
| } |
| } |
| else |
| { |
| abctime clkPart = Abc_Clock(); |
| Aig_ManForEachCo( pFrames, pObj, i ) |
| { |
| Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); |
| if ( fVerbose ) |
| { |
| printf( "Solving output %2d of frame %3d ... \r", |
| i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) ); |
| } |
| clk = Abc_Clock(); |
| if ( pSat2 ) |
| status = satoko_solve_assumptions_limit( pSat2, &Lit, 1, nConfLimit ); |
| else |
| status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); |
| if ( fVerbose && (i % Saig_ManPoNum(pAig) == Saig_ManPoNum(pAig) - 1) ) |
| { |
| printf( "Solved %2d outputs of frame %3d. ", |
| Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) ); |
| printf( "Conf =%8.0f. Imp =%11.0f. ", |
| (double)(pSat ? pSat->stats.conflicts : satoko_conflictnum(pSat2)), |
| (double)(pSat ? pSat->stats.propagations : satoko_stats(pSat2)->n_propagations) ); |
| ABC_PRT( "T", Abc_Clock() - clkPart ); |
| clkPart = Abc_Clock(); |
| fflush( stdout ); |
| } |
| if ( status == l_False ) |
| { |
| /* |
| Lit = lit_neg( Lit ); |
| RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); |
| assert( RetValue ); |
| if ( pSat->qtail != pSat->qhead ) |
| { |
| RetValue = sat_solver_simplify(pSat); |
| assert( RetValue ); |
| } |
| */ |
| } |
| else if ( status == l_True ) |
| { |
| Vec_Int_t * vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames ); |
| int * pModel = pSat2 ? Sat2_SolverGetModel(pSat2, vCiIds->pArray, vCiIds->nSize) : Sat_SolverGetModel(pSat, vCiIds->pArray, vCiIds->nSize); |
| pModel[Aig_ManCiNum(pFrames)] = pObj->Id; |
| pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pFrames, pModel ); |
| ABC_FREE( pModel ); |
| Vec_IntFree( vCiIds ); |
| |
| if ( piFrame ) |
| *piFrame = i / Saig_ManPoNum(pAig); |
| RetValue = 0; |
| break; |
| } |
| else |
| { |
| if ( piFrame ) |
| *piFrame = i / Saig_ManPoNum(pAig); |
| RetValue = -1; |
| break; |
| } |
| } |
| } |
| if ( pSat ) sat_solver_delete( pSat ); |
| if ( pSat2 ) satoko_destroy( pSat2 ); |
| Cnf_DataFree( pCnf ); |
| Aig_ManStop( pFrames ); |
| return RetValue; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |