/**CFile**************************************************************** FileName [sscSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sweeping under constraints.] Synopsis [SAT procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: sscSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sscInt.h" #include "sat/cnf/cnf.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Ssc_ObjSatLit( Ssc_Man_t * p, int Lit ) { return Abc_Var2Lit( Ssc_ObjSatVar(p, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManAddClausesMux( Ssc_Man_t * p, Gia_Obj_t * pNode ) { Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], LitF, LitI, LitT, LitE, RetValue; assert( !Gia_IsComplement( pNode ) ); assert( Gia_ObjIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the Litiable numbers LitF = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNode) ); LitI = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNodeI) ); LitT = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNodeT) ); LitE = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNodeE) ); // f = ITE(i, t, e) // i' + t' + f // i' + t + f' // i + e' + f // i + e + f' // create four clauses pLits[0] = Abc_LitNotCond(LitI, 1); pLits[1] = Abc_LitNotCond(LitT, 1); pLits[2] = Abc_LitNotCond(LitF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = Abc_LitNotCond(LitI, 1); pLits[1] = Abc_LitNotCond(LitT, 0); pLits[2] = Abc_LitNotCond(LitF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = Abc_LitNotCond(LitI, 0); pLits[1] = Abc_LitNotCond(LitE, 1); pLits[2] = Abc_LitNotCond(LitF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = Abc_LitNotCond(LitI, 0); pLits[1] = Abc_LitNotCond(LitE, 0); pLits[2] = Abc_LitNotCond(LitF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); // two additional clauses // t' & e' -> f' // t & e -> f // t + e + f' // t' + e' + f if ( LitT == LitE ) { // assert( fCompT == !fCompE ); return; } pLits[0] = Abc_LitNotCond(LitT, 0); pLits[1] = Abc_LitNotCond(LitE, 0); pLits[2] = Abc_LitNotCond(LitF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = Abc_LitNotCond(LitT, 1); pLits[1] = Abc_LitNotCond(LitE, 1); pLits[2] = Abc_LitNotCond(LitF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManAddClausesSuper( Ssc_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSuper ) { int i, RetValue, Lit, LitNode, pLits[2]; assert( !Gia_IsComplement(pNode) ); assert( Gia_ObjIsAnd( pNode ) ); // suppose AND-gate is A & B = C // add !A => !C or A + !C // add !B => !C or B + !C LitNode = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNode) ); Vec_IntForEachEntry( vSuper, Lit, i ) { pLits[0] = Ssc_ObjSatLit( p, Lit ); pLits[1] = Abc_LitNot( LitNode ); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); // update literals Vec_IntWriteEntry( vSuper, i, Abc_LitNot(pLits[0]) ); } // add A & B => C or !A + !B + C Vec_IntPush( vSuper, LitNode ); RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vSuper), Vec_IntArray(vSuper) + Vec_IntSize(vSuper) ); assert( RetValue ); (void) RetValue; } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Ssc_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { // stop at complements, PIs, and MUXes if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || Gia_ObjIsMuxType(pObj) ) { Vec_IntPushUnique( vSuper, Gia_Obj2Lit(p, pObj) ); return; } Ssc_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Ssc_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } static void Ssc_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { assert( !Gia_IsComplement(pObj) ); assert( Gia_ObjIsAnd(pObj) ); Vec_IntClear( vSuper ); Ssc_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Ssc_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Ssc_ManCnfAddToFrontier( Ssc_Man_t * p, int Id, Vec_Int_t * vFront ) { Gia_Obj_t * pObj; assert( Id > 0 ); if ( Ssc_ObjSatVar(p, Id) ) return; pObj = Gia_ManObj( p->pFraig, Id ); Ssc_ObjSetSatVar( p, Id, p->nSatVars++ ); sat_solver_setnvars( p->pSat, p->nSatVars + 100 ); if ( Gia_ObjIsAnd(pObj) ) Vec_IntPush( vFront, Id ); } static void Ssc_ManCnfNodeAddToSolver( Ssc_Man_t * p, int NodeId ) { Gia_Obj_t * pNode; int i, k, Id, Lit; abctime clk; assert( NodeId > 0 ); // quit if CNF is ready if ( Ssc_ObjSatVar(p, NodeId) ) return; clk = Abc_Clock(); // start the frontier Vec_IntClear( p->vFront ); Ssc_ManCnfAddToFrontier( p, NodeId, p->vFront ); // explore nodes in the frontier Gia_ManForEachObjVec( p->vFront, p->pFraig, pNode, i ) { // create the supergate assert( Ssc_ObjSatVar(p, Gia_ObjId(p->pFraig, pNode)) ); if ( Gia_ObjIsMuxType(pNode) ) { Vec_IntClear( p->vFanins ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pFraig, Gia_ObjFanin0(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pFraig, Gia_ObjFanin1(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pFraig, Gia_ObjFanin0(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pFraig, Gia_ObjFanin1(pNode) ) ); Vec_IntForEachEntry( p->vFanins, Id, k ) Ssc_ManCnfAddToFrontier( p, Id, p->vFront ); Gia_ManAddClausesMux( p, pNode ); } else { Ssc_ManCollectSuper( p->pFraig, pNode, p->vFanins ); Vec_IntForEachEntry( p->vFanins, Lit, k ) Ssc_ManCnfAddToFrontier( p, Abc_Lit2Var(Lit), p->vFront ); Gia_ManAddClausesSuper( p, pNode, p->vFanins ); } assert( Vec_IntSize(p->vFanins) > 1 ); } p->timeCnfGen += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Starts the SAT solver for constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_ManStartSolver( Ssc_Man_t * p ) { Aig_Man_t * pMan = Gia_ManToAigSimple( p->pFraig ); Cnf_Dat_t * pDat = Cnf_Derive( pMan, 0 ); Gia_Obj_t * pObj; sat_solver * pSat; int i, status; assert( p->pSat == NULL && p->vId2Var == NULL ); assert( Aig_ManObjNumMax(pMan) == Gia_ManObjNum(p->pFraig) ); Aig_ManStop( pMan ); // save variable mapping p->nSatVarsPivot = p->nSatVars = pDat->nVars; p->vId2Var = Vec_IntStart( Gia_ManCandNum(p->pAig) + Gia_ManCandNum(p->pCare) + 10 ); // mapping of each node into its SAT var p->vVar2Id = Vec_IntStart( Gia_ManCandNum(p->pAig) + Gia_ManCandNum(p->pCare) + 10 ); // mapping of each SAT var into its node Ssc_ObjSetSatVar( p, 0, pDat->pVarNums[0] ); Gia_ManForEachCi( p->pFraig, pObj, i ) { int iObj = Gia_ObjId( p->pFraig, pObj ); Ssc_ObjSetSatVar( p, iObj, pDat->pVarNums[iObj] ); } //Cnf_DataWriteIntoFile( pDat, "dump.cnf", 1, NULL, NULL ); // start the SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, pDat->nVars + 1000 ); for ( i = 0; i < pDat->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pDat->pClauses[i], pDat->pClauses[i+1] ) ) { Cnf_DataFree( pDat ); sat_solver_delete( pSat ); return; } } Cnf_DataFree( pDat ); status = sat_solver_simplify( pSat ); if ( status == 0 ) { sat_solver_delete( pSat ); return; } p->pSat = pSat; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_ManCollectSatPattern( Ssc_Man_t * p, Vec_Int_t * vPattern ) { Gia_Obj_t * pObj; int i; Vec_IntClear( vPattern ); Gia_ManForEachCi( p->pFraig, pObj, i ) Vec_IntPush( vPattern, sat_solver_var_value(p->pSat, Ssc_ObjSatVar(p, Gia_ObjId(p->pFraig, pObj))) ); } Vec_Int_t * Ssc_ManFindPivotSat( Ssc_Man_t * p ) { Vec_Int_t * vInit; int status = sat_solver_solve( p->pSat, NULL, NULL, p->pPars->nBTLimit, 0, 0, 0 ); if ( status == l_False ) return (Vec_Int_t *)(ABC_PTRINT_T)1; if ( status == l_Undef ) return NULL; assert( status == l_True ); vInit = Vec_IntAlloc( Gia_ManCiNum(p->pFraig) ); Ssc_ManCollectSatPattern( p, vInit ); return vInit; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_ManCheckEquivalence( Ssc_Man_t * p, int iRepr, int iNode, int fCompl ) { int pLitsSat[2], RetValue; abctime clk; assert( iRepr != iNode ); if ( iRepr > iNode ) return l_Undef; assert( iRepr < iNode ); // if ( p->nTimeOut ) // sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); // create CNF if ( iRepr ) Ssc_ManCnfNodeAddToSolver( p, iRepr ); Ssc_ManCnfNodeAddToSolver( p, iNode ); sat_solver_compress( p->pSat ); // order the literals pLitsSat[0] = Abc_Var2Lit( Ssc_ObjSatVar(p, iRepr), 0 ); pLitsSat[1] = Abc_Var2Lit( Ssc_ObjSatVar(p, iNode), fCompl ^ (int)(iRepr > 0) ); // solve under assumptions // A = 1; B = 0 clk = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, pLitsSat, pLitsSat + 2, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) { pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); // compl pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); // compl RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); assert( RetValue ); p->timeSatUnsat += Abc_Clock() - clk; } else if ( RetValue == l_True ) { Ssc_ManCollectSatPattern( p, p->vPattern ); p->timeSatSat += Abc_Clock() - clk; return l_True; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; return l_Undef; } // if the old node was constant 0, we already know the answer if ( iRepr == 0 ) return l_False; // solve under assumptions // A = 0; B = 1 clk = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, pLitsSat, pLitsSat + 2, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) { pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); assert( RetValue ); p->timeSatUnsat += Abc_Clock() - clk; } else if ( RetValue == l_True ) { Ssc_ManCollectSatPattern( p, p->vPattern ); p->timeSatSat += Abc_Clock() - clk; return l_True; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; return l_Undef; } return l_False; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END