/**CFile**************************************************************** FileName [giaSweeper.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Incremental SAT sweeper.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSweeper.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "base/main/main.h" #include "sat/bsat/satSolver.h" #include "proof/ssc/ssc.h" ABC_NAMESPACE_IMPL_START /* SAT sweeping/equivalence checking requires the following steps: - Creating probes These APIs should be called for all internal points in the logic, which may be used as - nodes representing conditions to be used as constraints - nodes representing functions to be equivalence checked - nodes representing functions needed by the user at the end of SAT sweeping Creating new probe using Gia_SweeperProbeCreate(): int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit ); Delete existing probe using Gia_SweeperProbeDelete(): int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId ); Update existing probe using Gia_SweeperProbeUpdate(): int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLit ); Comments: - a probe is identified by its 0-based ID, which is returned by above procedures - GIA literal of the probe is returned by int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId ) - Adding/removing conditions on the current path by calling Gia_SweeperCondPush() and Gia_SweeperCondPop() extern void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId ); extern void Gia_SweeperCondPop( Gia_Man_t * p ); - Performing equivalence checking by calling int Gia_SweeperCheckEquiv( Gia_Man_t * pGia, int Probe1, int Probe2 ) (resource limits, such as the number of conflicts, will be controllable by dedicated GIA APIs) - The resulting AIG to be returned to the user by calling Gia_SweeperExtractUserLogic() Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vOutNames ) */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Swp_Man_t_ Swp_Man_t; struct Swp_Man_t_ { Gia_Man_t * pGia; // GIA manager under construction int nConfMax; // conflict limit in seconds int nTimeOut; // runtime limit in seconds Vec_Int_t * vProbes; // probes Vec_Int_t * vCondProbes; // conditions as probes Vec_Int_t * vCondAssump; // conditions as SAT solver literals // equivalence checking sat_solver * pSat; // SAT solver Vec_Int_t * vId2Lit; // mapping of Obj IDs into SAT literal Vec_Int_t * vFront; // temporary frontier Vec_Int_t * vFanins; // temporary fanins Vec_Int_t * vCexSwp; // sweeper counter-example Vec_Int_t * vCexUser; // user-visible counter-example int nSatVars; // counter of SAT variables // statistics int nSatCalls; int nSatCallsSat; int nSatCallsUnsat; int nSatCallsUndec; int nSatProofs; abctime timeStart; abctime timeTotal; abctime timeCnf; abctime timeSat; abctime timeSatSat; abctime timeSatUnsat; abctime timeSatUndec; }; static inline int Swp_ManObj2Lit( Swp_Man_t * p, int Id ) { return Vec_IntGetEntry( p->vId2Lit, Id ); } static inline int Swp_ManLit2Lit( Swp_Man_t * p, int Lit ) { assert( Vec_IntEntry(p->vId2Lit, Abc_Lit2Var(Lit)) ); return Abc_Lit2LitL( Vec_IntArray(p->vId2Lit), Lit ); } static inline void Swp_ManSetObj2Lit( Swp_Man_t * p, int Id, int Lit ) { assert( Lit > 0 ); Vec_IntSetEntry( p->vId2Lit, Id, Lit ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creating/deleting the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Swp_Man_t * Swp_ManStart( Gia_Man_t * pGia ) { Swp_Man_t * p; int Lit; assert( pGia->pHTable != NULL ); pGia->pData = p = ABC_CALLOC( Swp_Man_t, 1 ); p->pGia = pGia; p->nConfMax = 1000; p->vProbes = Vec_IntAlloc( 100 ); p->vCondProbes = Vec_IntAlloc( 100 ); p->vCondAssump = Vec_IntAlloc( 100 ); p->vId2Lit = Vec_IntAlloc( 10000 ); p->vFront = Vec_IntAlloc( 100 ); p->vFanins = Vec_IntAlloc( 100 ); p->vCexSwp = Vec_IntAlloc( 100 ); p->pSat = sat_solver_new(); p->nSatVars = 1; sat_solver_setnvars( p->pSat, 1000 ); Swp_ManSetObj2Lit( p, 0, (Lit = Abc_Var2Lit(p->nSatVars++, 0)) ); Lit = Abc_LitNot(Lit); sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); p->timeStart = Abc_Clock(); return p; } static inline void Swp_ManStop( Gia_Man_t * pGia ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; sat_solver_delete( p->pSat ); Vec_IntFree( p->vFanins ); Vec_IntFree( p->vCexSwp ); Vec_IntFree( p->vId2Lit ); Vec_IntFree( p->vFront ); Vec_IntFree( p->vProbes ); Vec_IntFree( p->vCondProbes ); Vec_IntFree( p->vCondAssump ); ABC_FREE( p ); pGia->pData = NULL; } Gia_Man_t * Gia_SweeperStart( Gia_Man_t * pGia ) { if ( pGia == NULL ) pGia = Gia_ManStart( 10000 ); if ( pGia->pHTable == NULL ) Gia_ManHashStart( pGia ); // recompute fPhase and fMark1 to mark multiple fanout nodes if AIG is already defined!!! Swp_ManStart( pGia ); pGia->fSweeper = 1; return pGia; } void Gia_SweeperStop( Gia_Man_t * pGia ) { pGia->fSweeper = 0; Swp_ManStop( pGia ); Gia_ManHashStop( pGia ); // Gia_ManStop( pGia ); } int Gia_SweeperIsRunning( Gia_Man_t * pGia ) { return (pGia->pData != NULL); } double Gia_SweeperMemUsage( Gia_Man_t * pGia ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; double nMem = sizeof(Swp_Man_t); nMem += Vec_IntCap(p->vProbes); nMem += Vec_IntCap(p->vCondProbes); nMem += Vec_IntCap(p->vCondAssump); nMem += Vec_IntCap(p->vId2Lit); nMem += Vec_IntCap(p->vFront); nMem += Vec_IntCap(p->vFanins); nMem += Vec_IntCap(p->vCexSwp); return 4.0 * nMem; } void Gia_SweeperPrintStats( Gia_Man_t * pGia ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; double nMemSwp = Gia_SweeperMemUsage(pGia); double nMemGia = (double)Gia_ManObjNum(pGia)*(sizeof(Gia_Obj_t) + sizeof(int)); double nMemSat = sat_solver_memory(p->pSat); double nMemTot = nMemSwp + nMemGia + nMemSat; printf( "SAT sweeper statistics:\n" ); printf( "Memory usage:\n" ); ABC_PRMP( "Sweeper ", nMemSwp, nMemTot ); ABC_PRMP( "AIG manager ", nMemGia, nMemTot ); ABC_PRMP( "SAT solver ", nMemSat, nMemTot ); ABC_PRMP( "TOTAL ", nMemTot, nMemTot ); printf( "Runtime usage:\n" ); p->timeTotal = Abc_Clock() - p->timeStart; ABC_PRTP( "CNF construction", p->timeCnf, p->timeTotal ); ABC_PRTP( "SAT solving ", p->timeSat, p->timeTotal ); ABC_PRTP( " Sat ", p->timeSatSat, p->timeTotal ); ABC_PRTP( " Unsat ", p->timeSatUnsat, p->timeTotal ); ABC_PRTP( " Undecided ", p->timeSatUndec, p->timeTotal ); ABC_PRTP( "TOTAL RUNTIME ", p->timeTotal, p->timeTotal ); printf( "GIA: " ); Gia_ManPrintStats( pGia, NULL ); printf( "SAT calls = %d. Sat = %d. Unsat = %d. Undecided = %d. Proofs = %d.\n", p->nSatCalls, p->nSatCallsSat, p->nSatCallsUnsat, p->nSatCallsUndec, p->nSatProofs ); Sat_SolverPrintStats( stdout, p->pSat ); } /**Function************************************************************* Synopsis [Setting resource limits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SweeperSetConflictLimit( Gia_Man_t * p, int nConfMax ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; pSwp->nConfMax = nConfMax; } void Gia_SweeperSetRuntimeLimit( Gia_Man_t * p, int nSeconds ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; pSwp->nTimeOut = nSeconds; } Vec_Int_t * Gia_SweeperGetCex( Gia_Man_t * p ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; assert( pSwp->vCexUser == NULL || Vec_IntSize(pSwp->vCexUser) == Gia_ManPiNum(p) ); return pSwp->vCexUser; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // create new probe int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; int ProbeId = Vec_IntSize(pSwp->vProbes); assert( iLit >= 0 ); Vec_IntPush( pSwp->vProbes, iLit ); return ProbeId; } // delete existing probe int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); assert( iLit >= 0 ); Vec_IntWriteEntry(pSwp->vProbes, ProbeId, -1); return iLit; } // update existing probe int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLitNew ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); assert( iLit >= 0 ); Vec_IntWriteEntry(pSwp->vProbes, ProbeId, iLitNew); return iLit; } // returns literal associated with the probe int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); assert( iLit >= 0 ); return iLit; } /**Function************************************************************* Synopsis [This procedure returns indexes of all currently defined valid probes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_SweeperCollectValidProbeIds( Gia_Man_t * p ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; Vec_Int_t * vProbeIds = Vec_IntAlloc( 1000 ); int iLit, ProbeId; Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) { if ( iLit < 0 ) continue; Vec_IntPush( vProbeIds, ProbeId ); } return vProbeIds; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; Vec_IntPush( pSwp->vCondProbes, ProbeId ); } int Gia_SweeperCondPop( Gia_Man_t * p ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; return Vec_IntPop( pSwp->vCondProbes ); } Vec_Int_t * Gia_SweeperCondVector( Gia_Man_t * p ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; return pSwp->vCondProbes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManExtract_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjIds ) { if ( !Gia_ObjIsAnd(pObj) ) return; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); Gia_ManExtract_rec( p, Gia_ObjFanin0(pObj), vObjIds ); Gia_ManExtract_rec( p, Gia_ObjFanin1(pObj), vObjIds ); Vec_IntPush( vObjIds, Gia_ObjId(p, pObj) ); } Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vInNames, Vec_Ptr_t * vOutNames ) { Vec_Int_t * vObjIds, * vValues; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, ProbeId; assert( vInNames == NULL || Gia_ManPiNum(p) == Vec_PtrSize(vInNames) ); assert( vOutNames == NULL || Vec_IntSize(vProbeIds) == Vec_PtrSize(vOutNames) ); // create new Gia_ManIncrementTravId( p ); vObjIds = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( vProbeIds, ProbeId, i ) { pObj = Gia_Lit2Obj( p, Gia_SweeperProbeLit(p, ProbeId) ); Gia_ManExtract_rec( p, Gia_Regular(pObj), vObjIds ); } // create new manager pNew = Gia_ManStart( 1 + Gia_ManPiNum(p) + Vec_IntSize(vObjIds) + Vec_IntSize(vProbeIds) + 100 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create internal nodes Gia_ManHashStart( pNew ); vValues = Vec_IntAlloc( Vec_IntSize(vObjIds) ); Gia_ManForEachObjVec( vObjIds, p, pObj, i ) { Vec_IntPush( vValues, pObj->Value ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_ManHashStop( pNew ); // create outputs Vec_IntForEachEntry( vProbeIds, ProbeId, i ) { pObj = Gia_Lit2Obj( p, Gia_SweeperProbeLit(p, ProbeId) ); Gia_ManAppendCo( pNew, Gia_Regular(pObj)->Value ^ Gia_IsComplement(pObj) ); } // return the values back Gia_ManForEachPi( p, pObj, i ) pObj->Value = 0; Gia_ManForEachObjVec( vObjIds, p, pObj, i ) pObj->Value = Vec_IntEntry( vValues, i ); Vec_IntFree( vObjIds ); Vec_IntFree( vValues ); // duplicate if needed if ( Gia_ManHasDangling(pNew) ) { pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); } // copy names if present if ( vInNames ) pNew->vNamesIn = Vec_PtrDupStr( vInNames ); if ( vOutNames ) pNew->vNamesOut = Vec_PtrDupStr( vOutNames ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, char * pFileName ) { Gia_Man_t * pGiaOuts = Gia_SweeperExtractUserLogic( p, vProbeIds, NULL, NULL ); Vec_Int_t * vProbeConds = Gia_SweeperCondVector( p ); printf( "Dumping logic cones" ); if ( fDumpConds && Vec_IntSize(vProbeConds) > 0 ) { Gia_Man_t * pGiaCond = Gia_SweeperExtractUserLogic( p, vProbeConds, NULL, NULL ); Gia_ManDupAppendShare( pGiaOuts, pGiaCond ); pGiaOuts->nConstrs = Gia_ManPoNum(pGiaCond); Gia_ManHashStop( pGiaOuts ); Gia_ManStop( pGiaCond ); printf( " and conditions" ); } Gia_AigerWrite( pGiaOuts, pFileName, 0, 0 ); Gia_ManStop( pGiaOuts ); printf( " into file \"%s\".\n", pFileName ); } /**Function************************************************************* Synopsis [Sweeper cleanup.] Description [Returns new GIA with sweeper defined, which is the same as the original sweeper, with all the dangling logic removed and SAT solver restarted. The probe IDs are guaranteed to have the same logic functions as in the original manager.] SideEffects [The input manager is deleted inside this procedure.] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_SweeperCleanup( Gia_Man_t * p, char * pCommLime ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; Vec_Int_t * vObjIds; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit, ProbeId; // collect all internal nodes pointed to by currently-used probes Gia_ManIncrementTravId( p ); vObjIds = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) { if ( iLit < 0 ) continue; pObj = Gia_Lit2Obj( p, iLit ); Gia_ManExtract_rec( p, Gia_Regular(pObj), vObjIds ); } // create new manager pNew = Gia_ManStart( 1 + Gia_ManPiNum(p) + Vec_IntSize(vObjIds) + 100 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create internal nodes Gia_ManHashStart( pNew ); Gia_ManForEachObjVec( vObjIds, p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManHashStop( pNew ); // create outputs Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) { if ( iLit < 0 ) continue; pObj = Gia_Lit2Obj( p, iLit ); iLit = Gia_Regular(pObj)->Value ^ Gia_IsComplement(pObj); Vec_IntWriteEntry( pSwp->vProbes, ProbeId, iLit ); } Vec_IntFree( vObjIds ); // duplicate if needed if ( Gia_ManHasDangling(pNew) ) { pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); } // execute command line if ( pCommLime ) { // set pNew to be current GIA in ABC Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); // execute command line pCommLine using Abc_CmdCommandExecute() Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); // get pNew to be current GIA in ABC pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); } // restart the SAT solver Vec_IntClear( pSwp->vId2Lit ); sat_solver_delete( pSwp->pSat ); pSwp->pSat = sat_solver_new(); pSwp->nSatVars = 1; sat_solver_setnvars( pSwp->pSat, 1000 ); Swp_ManSetObj2Lit( pSwp, 0, (iLit = Abc_Var2Lit(pSwp->nSatVars++, 0)) ); iLit = Abc_LitNot(iLit); sat_solver_addclause( pSwp->pSat, &iLit, &iLit + 1 ); pSwp->timeStart = Abc_Clock(); // return the result pNew->pData = p->pData; p->pData = NULL; Gia_ManStop( p ); return pNew; } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManAddClausesMux( Swp_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 = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNode) ); LitI = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeI) ); LitT = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeT) ); LitE = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,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( Swp_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 = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNode) ); Vec_IntForEachEntry( vSuper, Lit, i ) { pLits[0] = Swp_ManLit2Lit( 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 Gia_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { // stop at complements, shared, PIs, and MUXes if ( Gia_IsComplement(pObj) || pObj->fMark1 || Gia_ObjIsCi(pObj) || Gia_ObjIsMuxType(pObj) ) { Vec_IntPushUnique( vSuper, Gia_Obj2Lit(p, pObj) ); return; } Gia_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Gia_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } static void Gia_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { assert( !Gia_IsComplement(pObj) ); assert( Gia_ObjIsAnd(pObj) ); Vec_IntClear( vSuper ); Gia_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Gia_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManObjAddToFrontier( Swp_Man_t * p, int Id, Vec_Int_t * vFront ) { Gia_Obj_t * pObj; if ( Id == 0 || Swp_ManObj2Lit(p, Id) ) return; pObj = Gia_ManObj( p->pGia, Id ); Swp_ManSetObj2Lit( p, Id, Abc_Var2Lit(p->nSatVars++, pObj->fPhase) ); sat_solver_setnvars( p->pSat, p->nSatVars + 100 ); if ( Gia_ObjIsAnd(pObj) ) Vec_IntPush( vFront, Id ); } static void Gia_ManCnfNodeAddToSolver( Swp_Man_t * p, int NodeId ) { Gia_Obj_t * pNode; int i, k, Id, Lit; abctime clk; // quit if CNF is ready if ( NodeId == 0 || Swp_ManObj2Lit(p, NodeId) ) return; clk = Abc_Clock(); // start the frontier Vec_IntClear( p->vFront ); Gia_ManObjAddToFrontier( p, NodeId, p->vFront ); // explore nodes in the frontier Gia_ManForEachObjVec( p->vFront, p->pGia, pNode, i ) { // create the supergate assert( Swp_ManObj2Lit(p, Gia_ObjId(p->pGia, pNode)) ); if ( Gia_ObjIsMuxType(pNode) ) { Vec_IntClear( p->vFanins ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pGia, Gia_ObjFanin0(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pGia, Gia_ObjFanin1(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pGia, Gia_ObjFanin0(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pGia, Gia_ObjFanin1(pNode) ) ); Vec_IntForEachEntry( p->vFanins, Id, k ) Gia_ManObjAddToFrontier( p, Id, p->vFront ); Gia_ManAddClausesMux( p, pNode ); } else { Gia_ManCollectSuper( p->pGia, pNode, p->vFanins ); Vec_IntForEachEntry( p->vFanins, Lit, k ) Gia_ManObjAddToFrontier( p, Abc_Lit2Var(Lit), p->vFront ); Gia_ManAddClausesSuper( p, pNode, p->vFanins ); } assert( Vec_IntSize(p->vFanins) > 1 ); } p->timeCnf += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Vec_Int_t * Gia_ManGetCex( Gia_Man_t * pGia, Vec_Int_t * vId2Lit, sat_solver * pSat, Vec_Int_t * vCex ) { Gia_Obj_t * pObj; int i, LitSat, Value; Vec_IntClear( vCex ); Gia_ManForEachPi( pGia, pObj, i ) { if ( Gia_ObjId(pGia, pObj) >= Vec_IntSize(vId2Lit) ) { Vec_IntPush( vCex, 2 ); continue; } LitSat = Vec_IntEntry( vId2Lit, Gia_ObjId(pGia, pObj) ); if ( LitSat == 0 ) { Vec_IntPush( vCex, 2 ); continue; } assert( LitSat > 0 ); Value = sat_solver_var_value(pSat, Abc_Lit2Var(LitSat)) ^ Abc_LitIsCompl(LitSat); Vec_IntPush( vCex, Value ); } return vCex; } /**Function************************************************************* Synopsis [Runs equivalence test for probes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SweeperCheckEquiv( Gia_Man_t * pGia, int Probe1, int Probe2 ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; int iLitOld, iLitNew, iLitAig, pLitsSat[2], RetValue, RetValue1, ProbeId, i; abctime clk; p->nSatCalls++; assert( p->pSat != NULL ); p->vCexUser = NULL; // get the literals iLitOld = Gia_SweeperProbeLit( pGia, Probe1 ); iLitNew = Gia_SweeperProbeLit( pGia, Probe2 ); // if the literals are identical, the probes are equivalent if ( iLitOld == iLitNew ) return 1; // if the literals are opposites, the probes are not equivalent if ( Abc_LitRegular(iLitOld) == Abc_LitRegular(iLitNew) ) { Vec_IntFill( p->vCexSwp, Gia_ManPiNum(pGia), 2 ); p->vCexUser = p->vCexSwp; return 0; } // order the literals if ( iLitOld < iLitNew ) ABC_SWAP( int, iLitOld, iLitNew ); assert( iLitOld > iLitNew ); // create logic cones and the array of assumptions Vec_IntClear( p->vCondAssump ); Vec_IntForEachEntry( p->vCondProbes, ProbeId, i ) { iLitAig = Gia_SweeperProbeLit( pGia, ProbeId ); Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitAig) ); Vec_IntPush( p->vCondAssump, Abc_LitNot(Swp_ManLit2Lit(p, iLitAig)) ); } Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitOld) ); Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitNew) ); sat_solver_compress( p->pSat ); // set the SAT literals pLitsSat[0] = Swp_ManLit2Lit( p, iLitOld ); pLitsSat[1] = Swp_ManLit2Lit( p, iLitNew ); // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 Vec_IntPush( p->vCondAssump, pLitsSat[0] ); Vec_IntPush( p->vCondAssump, Abc_LitNot(pLitsSat[1]) ); // set runtime limit for this call if ( p->nTimeOut ) sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); clk = Abc_Clock(); RetValue1 = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); Vec_IntShrink( p->vCondAssump, Vec_IntSize(p->vCondAssump) - 2 ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); assert( RetValue ); pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); p->timeSatUnsat += Abc_Clock() - clk; p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); p->timeSatSat += Abc_Clock() - clk; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatCallsUndec++; return -1; } // if the old node was constant 0, we already know the answer if ( Gia_ManIsConstLit(iLitNew) ) { p->nSatProofs++; return 1; } // solve under assumptions // A = 0; B = 1 OR A = 0; B = 0 Vec_IntPush( p->vCondAssump, Abc_LitNot(pLitsSat[0]) ); Vec_IntPush( p->vCondAssump, pLitsSat[1] ); clk = Abc_Clock(); RetValue1 = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); Vec_IntShrink( p->vCondAssump, Vec_IntSize(p->vCondAssump) - 2 ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); assert( RetValue ); pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); p->timeSatUnsat += Abc_Clock() - clk; p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); p->timeSatSat += Abc_Clock() - clk; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatCallsUndec++; return -1; } // return SAT proof p->nSatProofs++; return 1; } /**Function************************************************************* Synopsis [Returns 1 if the set of conditions is UNSAT (0 if SAT; -1 if undecided).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SweeperCondCheckUnsat( Gia_Man_t * pGia ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; int RetValue, ProbeId, iLitAig, i; abctime clk; assert( p->pSat != NULL ); p->nSatCalls++; p->vCexUser = NULL; // create logic cones and the array of assumptions Vec_IntClear( p->vCondAssump ); Vec_IntForEachEntry( p->vCondProbes, ProbeId, i ) { iLitAig = Gia_SweeperProbeLit( pGia, ProbeId ); Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitAig) ); Vec_IntPush( p->vCondAssump, Abc_LitNot(Swp_ManLit2Lit(p, iLitAig)) ); } sat_solver_compress( p->pSat ); // set runtime limit for this call if ( p->nTimeOut ) sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); clk = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); p->timeSat += Abc_Clock() - clk; if ( RetValue == l_False ) { assert( Vec_IntSize(p->vCondProbes) > 0 ); p->timeSatUnsat += Abc_Clock() - clk; p->nSatCallsUnsat++; p->nSatProofs++; return 1; } else if ( RetValue == l_True ) { p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); p->timeSatSat += Abc_Clock() - clk; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatCallsUndec++; return -1; } } /**Function************************************************************* Synopsis [Performs grafting from another manager.] Description [Returns the array of resulting literals in the destination manager.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_SweeperGraft( Gia_Man_t * pDst, Vec_Int_t * vProbes, Gia_Man_t * pSrc ) { Vec_Int_t * vOutLits; Gia_Obj_t * pObj; int i; assert( Gia_SweeperIsRunning(pDst) ); if ( vProbes ) assert( Vec_IntSize(vProbes) == Gia_ManPiNum(pSrc) ); else assert( Gia_ManPiNum(pDst) == Gia_ManPiNum(pSrc) ); Gia_ManForEachPi( pSrc, pObj, i ) pObj->Value = vProbes ? Gia_SweeperProbeLit(pDst, Vec_IntEntry(vProbes, i)) : Gia_Obj2Lit(pDst,Gia_ManPi(pDst, i)); Gia_ManForEachAnd( pSrc, pObj, i ) pObj->Value = Gia_ManHashAnd( pDst, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); vOutLits = Vec_IntAlloc( Gia_ManPoNum(pSrc) ); Gia_ManForEachPo( pSrc, pObj, i ) Vec_IntPush( vOutLits, Gia_ObjFanin0Copy(pObj) ); return vOutLits; } /**Function************************************************************* Synopsis [Performs conditional sweeping of the cone.] Description [Returns the result as a new GIA manager with as many inputs as the original manager and as many outputs as there are logic cones.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_SweeperSweep( Gia_Man_t * p, Vec_Int_t * vProbeOuts, int nWords, int nConfs, int fVerify, int fVerbose ) { Vec_Int_t * vProbeConds; Gia_Man_t * pGiaCond, * pGiaOuts, * pGiaRes; Ssc_Pars_t Pars, * pPars = &Pars; Ssc_ManSetDefaultParams( pPars ); pPars->nWords = nWords; pPars->nBTLimit = nConfs; pPars->fVerify = fVerify; pPars->fVerbose = fVerbose; // sweeper is running assert( Gia_SweeperIsRunning(p) ); // extract conditions and logic cones vProbeConds = Gia_SweeperCondVector( p ); pGiaCond = Gia_SweeperExtractUserLogic( p, vProbeConds, NULL, NULL ); pGiaOuts = Gia_SweeperExtractUserLogic( p, vProbeOuts, NULL, NULL ); Gia_ManSetPhase( pGiaOuts ); // if there is no conditions, define constant true constraint (constant 0 output) if ( Gia_ManPoNum(pGiaCond) == 0 ) Gia_ManAppendCo( pGiaCond, Gia_ManConst0Lit() ); // perform sweeping under constraints pGiaRes = Ssc_PerformSweeping( pGiaOuts, pGiaCond, pPars ); Gia_ManStop( pGiaCond ); Gia_ManStop( pGiaOuts ); return pGiaRes; } /**Function************************************************************* Synopsis [Procedure to perform conditional fraig sweeping on separate logic cones.] Description [The procedure takes GIA with the sweeper defined. The sweeper is assumed to have some conditions currently pushed, which will be used as constraints for fraig sweeping. The second argument (vProbes) contains the array of probe IDs pointing to the user's logic cones to be SAT swept. Finally, the optional command line (pCommLine) is an ABC command line to be applied to the resulting GIA after SAT sweeping before it is grafted back into the original GIA manager. The return value is the status (success/failure) and the array of original probes possibly pointing to the new literals in the original GIA manager, corresponding to the user's logic cones after sweeping, synthesis and grafting.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SweeperFraig( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int nWords, int nConfs, int fVerify, int fVerbose ) { Gia_Man_t * pNew; Vec_Int_t * vLits; int ProbeId, i; // sweeper is running assert( Gia_SweeperIsRunning(p) ); // sweep the logic pNew = Gia_SweeperSweep( p, vProbeIds, nWords, nConfs, fVerify, fVerbose ); if ( pNew == NULL ) return 0; // execute command line if ( pCommLime ) { // set pNew to be current GIA in ABC Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); // execute command line pCommLine using Abc_CmdCommandExecute() Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); // get pNew to be current GIA in ABC pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); } // return logic back into the main manager vLits = Gia_SweeperGraft( p, NULL, pNew ); Gia_ManStop( pNew ); // update the array of probes Vec_IntForEachEntry( vProbeIds, ProbeId, i ) Gia_SweeperProbeUpdate( p, ProbeId, Vec_IntEntry(vLits, i) ); Vec_IntFree( vLits ); return 1; } /**Function************************************************************* Synopsis [Executes given command line for the logic defined by the probes.] Description [ ] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SweeperRun( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int fVerbose ) { Gia_Man_t * pNew; Vec_Int_t * vLits; int ProbeId, i; // sweeper is running assert( Gia_SweeperIsRunning(p) ); // sweep the logic pNew = Gia_SweeperExtractUserLogic( p, vProbeIds, NULL, NULL ); // execute command line if ( pCommLime ) { if ( fVerbose ) printf( "GIA manager statistics before and after applying \"%s\":\n", pCommLime ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); // set pNew to be current GIA in ABC Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); // execute command line pCommLine using Abc_CmdCommandExecute() Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); // get pNew to be current GIA in ABC pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); } // return logic back into the main manager vLits = Gia_SweeperGraft( p, NULL, pNew ); Gia_ManStop( pNew ); // update the array of probes Vec_IntForEachEntry( vProbeIds, ProbeId, i ) Gia_SweeperProbeUpdate( p, ProbeId, Vec_IntEntry(vLits, i) ); Vec_IntFree( vLits ); return 1; } /**Function************************************************************* Synopsis [Sweeper sweeper test.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_SweeperFraigTest( Gia_Man_t * pInit, int nWords, int nConfs, int fVerbose ) { Gia_Man_t * p, * pGia; Gia_Obj_t * pObj; Vec_Int_t * vOuts; int i; // add one-hotness constraints p = Gia_ManDupOneHot( pInit ); // create sweeper Gia_SweeperStart( p ); // collect outputs and create conditions vOuts = Vec_IntAlloc( Gia_ManPoNum(p) ); Gia_ManForEachPo( p, pObj, i ) if ( i < Gia_ManPoNum(p) - p->nConstrs ) // this is the user's output Vec_IntPush( vOuts, Gia_SweeperProbeCreate( p, Gia_ObjFaninLit0p(p, pObj) ) ); else // this is a constraint Gia_SweeperCondPush( p, Gia_SweeperProbeCreate( p, Gia_ObjFaninLit0p(p, pObj) ) ); // perform the sweeping pGia = Gia_SweeperSweep( p, vOuts, nWords, nConfs, fVerbose, 0 ); // pGia = Gia_ManDup( p ); Vec_IntFree( vOuts ); // sop the sweeper Gia_SweeperStop( p ); Gia_ManStop( p ); return pGia; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END