| /**CFile**************************************************************** |
| |
| FileName [resSat.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Resynthesis package.] |
| |
| Synopsis [Interface with the SAT solver.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - January 15, 2007.] |
| |
| Revision [$Id: resSat.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "base/abc/abc.h" |
| #include "resInt.h" |
| #include "aig/hop/hop.h" |
| #include "sat/bsat/satSolver.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| extern int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl ); |
| extern int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl ); |
| extern int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Loads AIG into the SAT solver for checking resubstitution.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins ) |
| { |
| void * pCnf = NULL; |
| sat_solver * pSat; |
| Vec_Ptr_t * vNodes; |
| Abc_Obj_t * pObj; |
| int i, nNodes, status; |
| |
| // make sure fanins contain POs of the AIG |
| pObj = (Abc_Obj_t *)Vec_PtrEntry( vFanins, 0 ); |
| assert( pObj->pNtk == pAig && Abc_ObjIsPo(pObj) ); |
| |
| // collect reachable nodes |
| vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize ); |
| |
| // assign unique numbers to each node |
| nNodes = 0; |
| Abc_AigConst1(pAig)->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; |
| Abc_NtkForEachPi( pAig, pObj, i ) |
| pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; |
| Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) // useful POs |
| pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; |
| |
| // start the solver |
| pSat = sat_solver_new(); |
| sat_solver_store_alloc( pSat ); |
| |
| // add clause for the constant node |
| Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)Abc_AigConst1(pAig)->pCopy, 0 ); |
| // add clauses for AND gates |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| Res_SatAddAnd( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, |
| (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); |
| Vec_PtrFree( vNodes ); |
| // add clauses for POs |
| Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) |
| Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, |
| (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); |
| // add trivial clauses |
| pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 0); |
| Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // care-set |
| pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 1); |
| Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // on-set |
| |
| // bookmark the clauses of A |
| sat_solver_store_mark_clauses_a( pSat ); |
| |
| // duplicate the clauses |
| pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 1); |
| Sat_SolverDoubleClauses( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy ); |
| // add the equality constraints |
| Vec_PtrForEachEntryStart( Abc_Obj_t *, vFanins, pObj, i, 2 ) |
| Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, ((int)(ABC_PTRUINT_T)pObj->pCopy) + nNodes, 0 ); |
| |
| // bookmark the roots |
| sat_solver_store_mark_roots( pSat ); |
| |
| // solve the problem |
| status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); |
| if ( status == l_False ) |
| { |
| pCnf = sat_solver_store_release( pSat ); |
| // printf( "unsat\n" ); |
| } |
| else if ( status == l_True ) |
| { |
| // printf( "sat\n" ); |
| } |
| else |
| { |
| // printf( "undef\n" ); |
| } |
| sat_solver_delete( pSat ); |
| return pCnf; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Loads AIG into the SAT solver for constrained simulation.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void * Res_SatSimulateConstr( Abc_Ntk_t * pAig, int fOnSet ) |
| { |
| sat_solver * pSat; |
| Vec_Ptr_t * vFanins; |
| Vec_Ptr_t * vNodes; |
| Abc_Obj_t * pObj; |
| int i, nNodes; |
| |
| // start the array |
| vFanins = Vec_PtrAlloc( 2 ); |
| pObj = Abc_NtkPo( pAig, 0 ); |
| Vec_PtrPush( vFanins, pObj ); |
| pObj = Abc_NtkPo( pAig, 1 ); |
| Vec_PtrPush( vFanins, pObj ); |
| |
| // collect reachable nodes |
| vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize ); |
| |
| // assign unique numbers to each node |
| nNodes = 0; |
| Abc_AigConst1(pAig)->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; |
| Abc_NtkForEachPi( pAig, pObj, i ) |
| pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; |
| Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) // useful POs |
| pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; |
| |
| // start the solver |
| pSat = sat_solver_new(); |
| |
| // add clause for the constant node |
| Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)Abc_AigConst1(pAig)->pCopy, 0 ); |
| // add clauses for AND gates |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| Res_SatAddAnd( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, |
| (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); |
| Vec_PtrFree( vNodes ); |
| // add clauses for the first PO |
| pObj = Abc_NtkPo( pAig, 0 ); |
| Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, |
| (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); |
| // add clauses for the second PO |
| pObj = Abc_NtkPo( pAig, 1 ); |
| Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, |
| (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); |
| |
| // add trivial clauses |
| pObj = Abc_NtkPo( pAig, 0 ); |
| Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // care-set |
| |
| pObj = Abc_NtkPo( pAig, 1 ); |
| Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, !fOnSet ); // on-set |
| |
| Vec_PtrFree( vFanins ); |
| return pSat; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Loads AIG into the SAT solver for constrained simulation.] |
| |
| Description [Returns 1 if the required number of patterns are found. |
| Returns 0 if the solver ran out of time or proved a constant. |
| In the latter, case one of the flags, fConst0 or fConst1, are set to 1.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Res_SatSimulate( Res_Sim_t * p, int nPatsLimit, int fOnSet ) |
| { |
| Vec_Int_t * vLits; |
| Vec_Ptr_t * vPats; |
| sat_solver * pSat; |
| int RetValue = -1; // Suppress "might be used uninitialized" |
| int i, k, value, status, Lit, Var, iPat; |
| abctime clk = Abc_Clock(); |
| |
| //printf( "Looking for %s: ", fOnSet? "onset " : "offset" ); |
| |
| // decide what problem should be solved |
| Lit = toLitCond( (int)(ABC_PTRUINT_T)Abc_NtkPo(p->pAig,1)->pCopy, !fOnSet ); |
| if ( fOnSet ) |
| { |
| iPat = p->nPats1; |
| vPats = p->vPats1; |
| } |
| else |
| { |
| iPat = p->nPats0; |
| vPats = p->vPats0; |
| } |
| assert( iPat < nPatsLimit ); |
| |
| // derive the SAT solver |
| pSat = (sat_solver *)Res_SatSimulateConstr( p->pAig, fOnSet ); |
| pSat->fSkipSimplify = 1; |
| status = sat_solver_simplify( pSat ); |
| if ( status == 0 ) |
| { |
| if ( iPat == 0 ) |
| { |
| // if ( fOnSet ) |
| // p->fConst0 = 1; |
| // else |
| // p->fConst1 = 1; |
| RetValue = 0; |
| } |
| goto finish; |
| } |
| |
| // enumerate through the SAT assignments |
| RetValue = 1; |
| vLits = Vec_IntAlloc( 32 ); |
| for ( k = iPat; k < nPatsLimit; k++ ) |
| { |
| // solve with the assumption |
| // status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); |
| status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); |
| if ( status == l_False ) |
| { |
| //printf( "Const %d\n", !fOnSet ); |
| if ( k == 0 ) |
| { |
| if ( fOnSet ) |
| p->fConst0 = 1; |
| else |
| p->fConst1 = 1; |
| RetValue = 0; |
| } |
| break; |
| } |
| else if ( status == l_True ) |
| { |
| // save the pattern |
| Vec_IntClear( vLits ); |
| for ( i = 0; i < p->nTruePis; i++ ) |
| { |
| Var = (int)(ABC_PTRUINT_T)Abc_NtkPi(p->pAig,i)->pCopy; |
| // value = (int)(pSat->model.ptr[Var] == l_True); |
| value = sat_solver_var_value(pSat, Var); |
| if ( value ) |
| Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vPats, i), k ); |
| Lit = toLitCond( Var, value ); |
| Vec_IntPush( vLits, Lit ); |
| // printf( "%d", value ); |
| } |
| // printf( "\n" ); |
| |
| status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); |
| if ( status == 0 ) |
| { |
| k++; |
| RetValue = 1; |
| break; |
| } |
| } |
| else |
| { |
| //printf( "Undecided\n" ); |
| if ( k == 0 ) |
| RetValue = 0; |
| else |
| RetValue = 1; |
| break; |
| } |
| } |
| Vec_IntFree( vLits ); |
| //printf( "Found %d patterns\n", k - iPat ); |
| |
| // set the new number of patterns |
| if ( fOnSet ) |
| p->nPats1 = k; |
| else |
| p->nPats0 = k; |
| |
| finish: |
| |
| sat_solver_delete( pSat ); |
| p->timeSat += Abc_Clock() - clk; |
| return RetValue; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Asserts equality of the variable to a constant.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl ) |
| { |
| lit Lit = toLitCond( iVar, fCompl ); |
| if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) ) |
| return 0; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Asserts equality of two variables.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl ) |
| { |
| lit Lits[2]; |
| |
| Lits[0] = toLitCond( iVar0, 0 ); |
| Lits[1] = toLitCond( iVar1, !fCompl ); |
| if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) |
| return 0; |
| |
| Lits[0] = toLitCond( iVar0, 1 ); |
| Lits[1] = toLitCond( iVar1, fCompl ); |
| if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) |
| return 0; |
| |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds constraints for the two-input AND-gate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) |
| { |
| lit Lits[3]; |
| |
| Lits[0] = toLitCond( iVar, 1 ); |
| Lits[1] = toLitCond( iVar0, fCompl0 ); |
| if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) |
| return 0; |
| |
| Lits[0] = toLitCond( iVar, 1 ); |
| Lits[1] = toLitCond( iVar1, fCompl1 ); |
| if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) |
| return 0; |
| |
| Lits[0] = toLitCond( iVar, 0 ); |
| Lits[1] = toLitCond( iVar0, !fCompl0 ); |
| Lits[2] = toLitCond( iVar1, !fCompl1 ); |
| if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) |
| return 0; |
| |
| return 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |