/**CFile**************************************************************** FileName [mfsInter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Procedures for computing resub function by interpolation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds constraints for the two-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_MfsSatAddXor( sat_solver * pSat, int iVarA, int iVarB, int iVarC ) { lit Lits[3]; Lits[0] = toLitCond( iVarA, 1 ); Lits[1] = toLitCond( iVarB, 1 ); Lits[2] = toLitCond( iVarC, 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; Lits[0] = toLitCond( iVarA, 1 ); Lits[1] = toLitCond( iVarB, 0 ); Lits[2] = toLitCond( iVarC, 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; Lits[0] = toLitCond( iVarA, 0 ); Lits[1] = toLitCond( iVarB, 1 ); Lits[2] = toLitCond( iVarC, 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; Lits[0] = toLitCond( iVarA, 0 ); Lits[1] = toLitCond( iVarB, 0 ); Lits[2] = toLitCond( iVarC, 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Creates miter for checking resubsitution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Abc_MfsCreateSolverResub( Mfs_Man_t * p, int * pCands, int nCands, int fInvert ) { sat_solver * pSat; Aig_Obj_t * pObjPo; int Lits[2], status, iVar, i, c; // get the literal for the output of F pObjPo = Aig_ManCo( p->pAigWin, Aig_ManCoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) - 1 ); Lits[0] = toLitCond( p->pCnf->pVarNums[pObjPo->Id], fInvert ); // collect the outputs of the divisors Vec_IntClear( p->vProjVarsCnf ); Vec_PtrForEachEntryStart( Aig_Obj_t *, p->pAigWin->vCos, pObjPo, i, Aig_ManCoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) ) { assert( p->pCnf->pVarNums[pObjPo->Id] >= 0 ); Vec_IntPush( p->vProjVarsCnf, p->pCnf->pVarNums[pObjPo->Id] ); } assert( Vec_IntSize(p->vProjVarsCnf) == Vec_PtrSize(p->vDivs) ); // start the solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, 2 * p->pCnf->nVars + Vec_PtrSize(p->vDivs) ); if ( pCands ) sat_solver_store_alloc( pSat ); // load the first copy of the clauses for ( i = 0; i < p->pCnf->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) ) { sat_solver_delete( pSat ); return NULL; } } // add the clause for the first output of F if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) { sat_solver_delete( pSat ); return NULL; } // add one-hotness constraints if ( p->pPars->fOneHotness ) { p->pSat = pSat; if ( !Abc_NtkAddOneHotness( p ) ) return NULL; p->pSat = NULL; } // bookmark the clauses of A if ( pCands ) sat_solver_store_mark_clauses_a( pSat ); // transform the literals for ( i = 0; i < p->pCnf->nLiterals; i++ ) p->pCnf->pClauses[0][i] += 2 * p->pCnf->nVars; // load the second copy of the clauses for ( i = 0; i < p->pCnf->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) ) { sat_solver_delete( pSat ); return NULL; } } // add one-hotness constraints if ( p->pPars->fOneHotness ) { p->pSat = pSat; if ( !Abc_NtkAddOneHotness( p ) ) return NULL; p->pSat = NULL; } // transform the literals for ( i = 0; i < p->pCnf->nLiterals; i++ ) p->pCnf->pClauses[0][i] -= 2 * p->pCnf->nVars; // add the clause for the second output of F Lits[0] = 2 * p->pCnf->nVars + lit_neg( Lits[0] ); if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) { sat_solver_delete( pSat ); return NULL; } if ( pCands ) { // add relevant clauses for EXOR gates for ( c = 0; c < nCands; c++ ) { // get the variable number of this divisor i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; // get the corresponding SAT variable iVar = Vec_IntEntry( p->vProjVarsCnf, i ); // add the corresponding EXOR gate if ( !Abc_MfsSatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) ) { sat_solver_delete( pSat ); return NULL; } // add the corresponding clause if ( !sat_solver_addclause( pSat, pCands + c, pCands + c + 1 ) ) { sat_solver_delete( pSat ); return NULL; } } // bookmark the roots sat_solver_store_mark_roots( pSat ); } else { // add the clauses for the EXOR gates - and remember their outputs Vec_IntClear( p->vProjVarsSat ); Vec_IntForEachEntry( p->vProjVarsCnf, iVar, i ) { if ( !Abc_MfsSatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) ) { sat_solver_delete( pSat ); return NULL; } Vec_IntPush( p->vProjVarsSat, 2 * p->pCnf->nVars + i ); } assert( Vec_IntSize(p->vProjVarsCnf) == Vec_IntSize(p->vProjVarsSat) ); // simplify the solver status = sat_solver_simplify(pSat); if ( status == 0 ) { // printf( "Abc_MfsCreateSolverResub(): SAT solver construction has failed. Skipping node.\n" ); sat_solver_delete( pSat ); return NULL; } } return pSat; } /**Function************************************************************* Synopsis [Performs interpolation.] Description [Derives the new function of the node.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Abc_NtkMfsInterplateTruth( Mfs_Man_t * p, int * pCands, int nCands, int fInvert ) { sat_solver * pSat; Sto_Man_t * pCnf = NULL; unsigned * puTruth; int nFanins, status; int c, i, * pGloVars; // derive the SAT solver for interpolation pSat = Abc_MfsCreateSolverResub( p, pCands, nCands, fInvert ); // solve the problem status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status != l_False ) { p->nTimeOuts++; return NULL; } // get the learned clauses pCnf = (Sto_Man_t *)sat_solver_store_release( pSat ); sat_solver_delete( pSat ); // set the global variables pGloVars = Int_ManSetGlobalVars( p->pMan, nCands ); for ( c = 0; c < nCands; c++ ) { // get the variable number of this divisor i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; // get the corresponding SAT variable pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i ); } // derive the interpolant nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth ); Sto_ManFree( pCnf ); assert( nFanins == nCands ); return puTruth; } /**Function************************************************************* Synopsis [Performs interpolation.] Description [Derives the new function of the node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsInterplateEval( Mfs_Man_t * p, int * pCands, int nCands ) { unsigned * pTruth, uTruth0[2], uTruth1[2]; int nCounter; pTruth = Abc_NtkMfsInterplateTruth( p, pCands, nCands, 0 ); if ( nCands == 6 ) { uTruth1[0] = pTruth[0]; uTruth1[1] = pTruth[1]; } else { uTruth1[0] = pTruth[0]; uTruth1[1] = pTruth[0]; } pTruth = Abc_NtkMfsInterplateTruth( p, pCands, nCands, 1 ); if ( nCands == 6 ) { uTruth0[0] = ~pTruth[0]; uTruth0[1] = ~pTruth[1]; } else { uTruth0[0] = ~pTruth[0]; uTruth0[1] = ~pTruth[0]; } nCounter = Extra_WordCountOnes( uTruth0[0] ^ uTruth1[0] ); nCounter += Extra_WordCountOnes( uTruth0[1] ^ uTruth1[1] ); // printf( "%d ", nCounter ); return nCounter; } /**Function************************************************************* Synopsis [Performs interpolation.] Description [Derives the new function of the node.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_NtkMfsInterplate( Mfs_Man_t * p, int * pCands, int nCands ) { extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); int fDumpFile = 0; char FileName[32]; sat_solver * pSat; Sto_Man_t * pCnf = NULL; unsigned * puTruth; Kit_Graph_t * pGraph; Hop_Obj_t * pFunc; int nFanins, status; int c, i, * pGloVars; // abctime clk = Abc_Clock(); // p->nDcMints += Abc_NtkMfsInterplateEval( p, pCands, nCands ); // derive the SAT solver for interpolation pSat = Abc_MfsCreateSolverResub( p, pCands, nCands, 0 ); // dump CNF file (remember to uncomment two-lit clases in clause_create_new() in 'satSolver.c') if ( fDumpFile ) { static int Counter = 0; sprintf( FileName, "cnf\\pj1_if6_mfs%03d.cnf", Counter++ ); Sat_SolverWriteDimacs( pSat, FileName, NULL, NULL, 1 ); } // solve the problem status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( fDumpFile ) printf( "File %s has UNSAT problem with %d conflicts.\n", FileName, (int)pSat->stats.conflicts ); if ( status != l_False ) { p->nTimeOuts++; return NULL; } //printf( "%d\n", pSat->stats.conflicts ); // ABC_PRT( "S", Abc_Clock() - clk ); // get the learned clauses pCnf = (Sto_Man_t *)sat_solver_store_release( pSat ); sat_solver_delete( pSat ); // set the global variables pGloVars = Int_ManSetGlobalVars( p->pMan, nCands ); for ( c = 0; c < nCands; c++ ) { // get the variable number of this divisor i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; // get the corresponding SAT variable pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i ); } // derive the interpolant nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth ); Sto_ManFree( pCnf ); assert( nFanins == nCands ); // transform interpolant into AIG pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem ); pFunc = Kit_GraphToHop( (Hop_Man_t *)p->pNtk->pManFunc, pGraph ); Kit_GraphFree( pGraph ); return pFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END