/**CFile**************************************************************** FileName [sswCnf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Computation of CNF.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswCnf.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the SAT manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Sat_t * Ssw_SatStart( int fPolarFlip ) { Ssw_Sat_t * p; int Lit; p = ABC_ALLOC( Ssw_Sat_t, 1 ); memset( p, 0, sizeof(Ssw_Sat_t) ); p->pAig = NULL; p->fPolarFlip = fPolarFlip; p->vSatVars = Vec_IntStart( 10000 ); p->vFanins = Vec_PtrAlloc( 100 ); p->vUsedPis = Vec_PtrAlloc( 100 ); p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, 1000 ); // var 0 is not used // var 1 is reserved for const1 node - add the clause p->nSatVars = 1; Lit = toLit( p->nSatVars ); if ( fPolarFlip ) Lit = lit_neg( Lit ); sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); // Ssw_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ ); Vec_IntWriteEntry( p->vSatVars, 0, p->nSatVars++ ); return p; } /**Function************************************************************* Synopsis [Stop the SAT manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SatStop( Ssw_Sat_t * p ) { // Abc_Print( 1, "Recycling SAT solver with %d vars and %d restarts.\n", // p->pSat->size, p->pSat->stats.starts ); if ( p->pSat ) sat_solver_delete( p->pSat ); Vec_IntFree( p->vSatVars ); Vec_PtrFree( p->vFanins ); Vec_PtrFree( p->vUsedPis ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_AddClausesMux( Ssw_Sat_t * p, Aig_Obj_t * pNode ) { Aig_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; assert( !Aig_IsComplement( pNode ) ); assert( Aig_ObjIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the variable numbers VarF = Ssw_ObjSatNum(p,pNode); VarI = Ssw_ObjSatNum(p,pNodeI); VarT = Ssw_ObjSatNum(p,Aig_Regular(pNodeT)); VarE = Ssw_ObjSatNum(p,Aig_Regular(pNodeE)); // get the complementation flags fCompT = Aig_IsComplement(pNodeT); fCompE = Aig_IsComplement(pNodeE); // f = ITE(i, t, e) // i' + t' + f // i' + t + f' // i + e' + f // i + e + f' // create four clauses pLits[0] = toLitCond(VarI, 1); pLits[1] = toLitCond(VarT, 1^fCompT); pLits[2] = toLitCond(VarF, 0); if ( p->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = toLitCond(VarI, 1); pLits[1] = toLitCond(VarT, 0^fCompT); pLits[2] = toLitCond(VarF, 1); if ( p->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = toLitCond(VarI, 0); pLits[1] = toLitCond(VarE, 1^fCompE); pLits[2] = toLitCond(VarF, 0); if ( p->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = toLitCond(VarI, 0); pLits[1] = toLitCond(VarE, 0^fCompE); pLits[2] = toLitCond(VarF, 1); if ( p->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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 ( VarT == VarE ) { // assert( fCompT == !fCompE ); return; } pLits[0] = toLitCond(VarT, 0^fCompT); pLits[1] = toLitCond(VarE, 0^fCompE); pLits[2] = toLitCond(VarF, 1); if ( p->fPolarFlip ) { if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = toLitCond(VarT, 1^fCompT); pLits[1] = toLitCond(VarE, 1^fCompE); pLits[2] = toLitCond(VarF, 0); if ( p->fPolarFlip ) { if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_AddClausesSuper( Ssw_Sat_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper ) { Aig_Obj_t * pFanin; int * pLits, nLits, RetValue, i; assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode( pNode ) ); // create storage for literals nLits = Vec_PtrSize(vSuper) + 1; pLits = ABC_ALLOC( int, nLits ); // suppose AND-gate is A & B = C // add !A => !C or A + !C Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) { pLits[0] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); pLits[1] = toLitCond(Ssw_ObjSatNum(p,pNode), 1); if ( p->fPolarFlip ) { if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); } // add A & B => C or !A + !B + C Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) { pLits[i] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); if ( p->fPolarFlip ) { if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); } } pLits[nLits-1] = toLitCond(Ssw_ObjSatNum(p,pNode), 0); if ( p->fPolarFlip ) { if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); assert( RetValue ); ABC_FREE( pLits ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) { // if the new node is complemented or a PI, another gate begins if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || (!fFirst && Aig_ObjRefs(pObj) > 1) || (fUseMuxes && Aig_ObjIsMuxType(pObj)) ) { Vec_PtrPushUnique( vSuper, pObj ); return; } // pObj->fMarkA = 1; // go through the branches Ssw_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); Ssw_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) { assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCi(pObj) ); Vec_PtrClear( vSuper ); Ssw_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ObjAddToFrontier( Ssw_Sat_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) { assert( !Aig_IsComplement(pObj) ); if ( Ssw_ObjSatNum(p,pObj) ) return; assert( Ssw_ObjSatNum(p,pObj) == 0 ); if ( Aig_ObjIsConst1(pObj) ) return; // pObj->fMarkA = 1; // save PIs (used by register correspondence) if ( Aig_ObjIsCi(pObj) ) Vec_PtrPush( p->vUsedPis, pObj ); Ssw_ObjSetSatNum( p, pObj, p->nSatVars++ ); sat_solver_setnvars( p->pSat, 100 * (1 + p->nSatVars / 100) ); if ( Aig_ObjIsNode(pObj) ) Vec_PtrPush( vFrontier, pObj ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj ) { Vec_Ptr_t * vFrontier; Aig_Obj_t * pNode, * pFanin; int i, k, fUseMuxes = 1; // quit if CNF is ready if ( Ssw_ObjSatNum(p,pObj) ) return; // start the frontier vFrontier = Vec_PtrAlloc( 100 ); Ssw_ObjAddToFrontier( p, pObj, vFrontier ); // explore nodes in the frontier Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i ) { // create the supergate assert( Ssw_ObjSatNum(p,pNode) ); if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) { Vec_PtrClear( p->vFanins ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); Ssw_AddClausesMux( p, pNode ); } else { Ssw_CollectSuper( pNode, fUseMuxes, p->vFanins ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); Ssw_AddClausesSuper( p, pNode, p->vFanins ); } assert( Vec_PtrSize(p->vFanins) > 1 ); } Vec_PtrFree( vFrontier ); } /**Function************************************************************* Synopsis [Copy pattern from the solver into the internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObj ) { int Value0, Value1, nVarNum; assert( !Aig_IsComplement(pObj) ); nVarNum = Ssw_ObjSatNum( p, pObj ); if ( nVarNum > 0 ) return sat_solver_var_value( p->pSat, nVarNum ); // if ( pObj->fMarkA == 1 ) // return 0; if ( Aig_ObjIsCi(pObj) ) return 0; assert( Aig_ObjIsNode(pObj) ); Value0 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin0(pObj) ); Value0 ^= Aig_ObjFaninC0(pObj); Value1 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin1(pObj) ); Value1 ^= Aig_ObjFaninC1(pObj); return Value0 & Value1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END