/**CFile**************************************************************** FileName [giaCCof.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Backward reachability using circuit cofactoring.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaCCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Ccf_Man_t_ Ccf_Man_t; // manager struct Ccf_Man_t_ { // user data Gia_Man_t * pGia; // single-output AIG manager int nFrameMax; // maximum number of frames int nConfMax; // maximum number of conflicts int nTimeMax; // maximum runtime in seconds int fVerbose; // verbose flag // internal data void * pUnr; // unrolling manager Gia_Man_t * pFrames; // unrolled timeframes Vec_Int_t * vCopies; // copy pointers of the AIG sat_solver * pSat; // SAT solver }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ccf_Man_t * Ccf_ManStart( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose ) { static Gia_ParFra_t Pars, * pPars = &Pars; Ccf_Man_t * p; assert( nFrameMax > 0 ); p = ABC_CALLOC( Ccf_Man_t, 1 ); p->pGia = pGia; p->nFrameMax = nFrameMax; p->nConfMax = nConfMax; p->nTimeMax = nTimeMax; p->fVerbose = fVerbose; // create unrolling manager memset( pPars, 0, sizeof(Gia_ParFra_t) ); pPars->fVerbose = fVerbose; pPars->nFrames = nFrameMax; pPars->fSaveLastLit = 1; p->pUnr = Gia_ManUnrollStart( pGia, pPars ); p->vCopies = Vec_IntAlloc( 1000 ); // internal data p->pSat = sat_solver_new(); // sat_solver_setnvars( p->pSat, 10000 ); return p; } /**Function************************************************************* Synopsis [Delete manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ccf_ManStop( Ccf_Man_t * p ) { Vec_IntFree( p->vCopies ); Gia_ManUnrollStop( p->pUnr ); sat_solver_delete( p->pSat ); Gia_ManStopP( &p->pFrames ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Extends the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCofExtendSolver( Ccf_Man_t * p ) { Gia_Obj_t * pObj; int i; // add SAT clauses for ( i = sat_solver_nvars(p->pSat); i < Gia_ManObjNum(p->pFrames); i++ ) { pObj = Gia_ManObj( p->pFrames, i ); if ( Gia_ObjIsAnd(pObj) ) sat_solver_add_and( p->pSat, i, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } sat_solver_setnvars( p->pSat, Gia_ManObjNum(p->pFrames) ); } static inline int Gia_Obj0Copy( Vec_Int_t * vCopies, int Fan0, int fCompl0 ) { return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan0), fCompl0 ); } static inline int Gia_Obj1Copy( Vec_Int_t * vCopies, int Fan1, int fCompl1 ) { return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan1), fCompl1 ); } /**Function************************************************************* Synopsis [Cofactor the circuit w.r.t. the given assignment.] Description [Assumes that the solver has just returned SAT.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCofOneDerive_rec( Ccf_Man_t * p, int Id ) { Gia_Obj_t * pObj; int Res; if ( Vec_IntEntry(p->vCopies, Id) != -1 ) return; pObj = Gia_ManObj(p->pFrames, Id); assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); if ( Gia_ObjIsAnd(pObj) ) { int fCompl0 = Gia_ObjFaninC0(pObj); int fCompl1 = Gia_ObjFaninC1(pObj); int Fan0 = Gia_ObjFaninId0p(p->pFrames, pObj); int Fan1 = Gia_ObjFaninId1p(p->pFrames, pObj); Gia_ManCofOneDerive_rec( p, Fan0 ); Gia_ManCofOneDerive_rec( p, Fan1 ); Res = Gia_ManHashAnd( p->pFrames, Gia_Obj0Copy(p->vCopies, Fan0, fCompl0), Gia_Obj1Copy(p->vCopies, Fan1, fCompl1) ); } else if ( Gia_ObjCioId(pObj) >= Gia_ManRegNum(p->pGia) ) // PI Res = sat_solver_var_value( p->pSat, Id ); else Res = Abc_Var2Lit( Id, 0 ); Vec_IntWriteEntry( p->vCopies, Id, Res ); } /**Function************************************************************* Synopsis [Cofactor the circuit w.r.t. the given assignment.] Description [Assumes that the solver has just returned SAT.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCofOneDerive( Ccf_Man_t * p, int LitProp ) { int LitOut; // derive the cofactor of the property node Vec_IntFill( p->vCopies, Gia_ManObjNum(p->pFrames), -1 ); Gia_ManCofOneDerive_rec( p, Abc_Lit2Var(LitProp) ); LitOut = Vec_IntEntry( p->vCopies, Abc_Lit2Var(LitProp) ); LitOut = Abc_LitNotCond( LitOut, Abc_LitIsCompl(LitProp) ); // add new PO for the cofactor Gia_ManAppendCo( p->pFrames, LitOut ); // add SAT clauses Gia_ManCofExtendSolver( p ); // return negative literal of the cofactor return Abc_LitNot(LitOut); } /**Function************************************************************* Synopsis [Enumerates backward reachable states.] Description [Return -1 if resource limit is reached. Returns 1 if computation converged (there is no more reachable states). Returns 0 if no more states to enumerate.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCofGetReachable( Ccf_Man_t * p, int Lit ) { int ObjPrev = 0, ConfPrev = 0; int Count = 0, LitOut, RetValue; abctime clk; // try solving for the first time and quit if converged RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 ); if ( RetValue == l_False ) return 1; // iterate circuit cofactoring while ( RetValue == l_True ) { clk = Abc_Clock(); // derive cofactor LitOut = Gia_ManCofOneDerive( p, Lit ); // add the blocking clause RetValue = sat_solver_addclause( p->pSat, &LitOut, &LitOut + 1 ); assert( RetValue ); // try solving again RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 ); // derive cofactors if ( p->fVerbose ) { printf( "%3d : AIG =%7d Conf =%7d. ", Count++, Gia_ManObjNum(p->pFrames) - ObjPrev, sat_solver_nconflicts(p->pSat) - ConfPrev ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); ObjPrev = Gia_ManObjNum(p->pFrames); ConfPrev = sat_solver_nconflicts(p->pSat); } } if ( RetValue == l_Undef ) return -1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCofTest( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose ) { Gia_Man_t * pNew; Ccf_Man_t * p; Gia_Obj_t * pObj; int f, i, Lit, RetValue = -1, fFailed = 0; abctime nTimeToStop = Abc_Clock() + nTimeMax * CLOCKS_PER_SEC; abctime clk = Abc_Clock(); assert( Gia_ManPoNum(pGia) == 1 ); // create reachability manager p = Ccf_ManStart( pGia, nFrameMax, nConfMax, nTimeMax, fVerbose ); // set runtime limit if ( nTimeMax ) sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); // perform backward image computation for ( f = 0; f < nFrameMax; f++ ) { if ( fVerbose ) printf( "ITER %3d :\n", f ); // add to the mapping of nodes p->pFrames = (Gia_Man_t *)Gia_ManUnrollAdd( p->pUnr, f+1 ); // add SAT clauses Gia_ManCofExtendSolver( p ); // return output literal Lit = Gia_ManUnrollLastLit( p->pUnr ); // derives cofactors of the property literal till all states are blocked RetValue = Gia_ManCofGetReachable( p, Lit ); if ( RetValue ) break; // check the property output Gia_ManSetPhase( p->pFrames ); Gia_ManForEachPo( p->pFrames, pObj, i ) if ( pObj->fPhase ) { printf( "Property failed in frame %d.\n", f ); fFailed = 1; break; } if ( i < Gia_ManPoNum(p->pFrames) ) break; } // report the result if ( nTimeToStop && Abc_Clock() > nTimeToStop ) printf( "Runtime limit (%d sec) is reached after %d frames. ", nTimeMax, f ); else if ( f == nFrameMax ) printf( "Completed %d frames without converging. ", f ); else if ( RetValue == 1 ) printf( "Backward reachability converged after %d iterations. ", f-1 ); else if ( RetValue == -1 ) printf( "Conflict limit or timeout is reached after %d frames. ", f-1 ); Abc_PrintTime( 1, "Runtime", Abc_Clock() - clk ); if ( !fFailed && RetValue == 1 ) printf( "Property holds.\n" ); else if ( !fFailed ) printf( "Property is undecided.\n" ); // get the resulting AIG manager Gia_ManHashStop( p->pFrames ); pNew = p->pFrames; p->pFrames = NULL; Ccf_ManStop( p ); // cleanup // if ( fVerbose ) // Gia_ManPrintStats( pNew, 0 ); pNew = Gia_ManCleanup( pGia = pNew ); Gia_ManStop( pGia ); // if ( fVerbose ) // Gia_ManPrintStats( pNew, 0 ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END