/**CFile**************************************************************** FileName [cecSplit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Cofactoring for combinational miters.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecSplit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "aig/gia/gia.h" #include "aig/gia/giaAig.h" #include "sat/bmc/bmc.h" #include "proof/pdr/pdr.h" #include "proof/cec/cec.h" #include "proof/ssw/ssw.h" #include "proof/abs/abs.h" #ifdef ABC_USE_PTHREADS #if defined(_WIN32) && !defined(__MINGW32__) #include "../lib/pthread.h" #else #include #include #endif #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Ssw_RarSimulateGia( Gia_Man_t * p, Ssw_RarPars_t * pPars ); extern int Bmcg_ManPerform( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ); typedef struct Par_Share_t_ Par_Share_t; typedef struct Par_ThData_t_ Par_ThData_t; typedef struct Wlc_Ntk_t_ Wlc_Ntk_t; struct Cec_ScorrStop_t_; struct Cec_SproveTrace_t_; static int Cec_SProveCallback( void * pUser, int fSolved, unsigned Result ); static Gia_Man_t * Cec_GiaScorrOld( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare, struct Cec_ScorrStop_t_ * pStopOut ); static Gia_Man_t * Cec_GiaScorrNew( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare, struct Cec_ScorrStop_t_ * pStopOut ); static void Cec_GiaInitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * p, int nTimeOut, int nTimeOutU, Wlc_Ntk_t * pWlc, int fVerbose, pthread_t * WorkerThread, Par_Share_t * pShare, int * pEngines, int StageId, int NetId, struct Cec_SproveTrace_t_ * pTrace ); static void Cec_GiaStopThreads( Par_ThData_t * ThData, pthread_t * WorkerThread, int nWorkers ); static int Cec_GiaWaitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * p, int RetValue, int * pRetEngine ); extern int Ufar_ProveWithTimeout( Wlc_Ntk_t * pNtk, int nTimeOut, int fVerbose, int (*pFuncStop)(int), int RunId ); #ifndef ABC_USE_PTHREADS int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent, char * pReplayFile ) { return -1; } int Cec_GiaReplayReadParams( char * pFileName, int * pnProcs, int * pnTimeOut, int * pnTimeOut2, int * pnTimeOut3, int * pfUseUif ) { return 0; } int Cec_GiaReplayTest( Gia_Man_t * p, Wlc_Ntk_t * pWlc, char * pFileName, int fVerbose, int fVeryVerbose, int fSilent ) { return -1; } #else // pthreads are used #define PAR_THR_MAX 8 #define PAR_ENGINE_UFAR 6 #define PAR_ENGINE_SCORR1 7 #define PAR_ENGINE_SCORR2 8 #define PAR_ENGINE_GLA 9 #define SPROVE_STAGE_MAX 4 #define SPROVE_NET_ORIG 0 #define SPROVE_NET_SCNEW 1 #define SPROVE_NET_SCOLD 2 typedef struct Cec_SproveTrace_t_ Cec_SproveTrace_t; typedef struct Cec_SproveStage_t_ Cec_SproveStage_t; typedef struct Cec_SprovePlan_t_ Cec_SprovePlan_t; struct Par_Share_t_ { volatile int fSolved; volatile unsigned Result; volatile int iEngine; }; typedef struct Par_ThData_t_ { Gia_Man_t * p; int iEngine; int fWorking; int fStop; int nTimeOut; int Result; int fVerbose; int nTimeOutU; Wlc_Ntk_t * pWlc; int WorkerId; int StageId; int NetId; int StopReason; Par_Share_t * pShare; Cec_SproveTrace_t * pTrace; pthread_mutex_t Mutex; pthread_cond_t Cond; } Par_ThData_t; typedef struct Cec_ScorrStop_t_ { Par_Share_t * pShare; abctime TimeToStop; int fStoppedByCallback; int fStoppedByTimeout; } Cec_ScorrStop_t; struct Cec_SproveTrace_t_ { FILE * pFile; int fActive; abctime clkStart; pthread_mutex_t Mutex; }; struct Cec_SproveStage_t_ { int Id; int fGuardUnsolved; int GuardExistsNet; int GuardAndLimitNet; int GuardAndLimit; int fHasRound; int RoundNet; int RoundTimeout; int nRoundEngines; int RoundEngines[PAR_THR_MAX]; int fHasReduce; int ReduceType; int ReduceNetIn; int ReduceNetOut; int ReduceTimeout; }; struct Cec_SprovePlan_t_ { int nProcs; int nTimeOut; int nTimeOut2; int nTimeOut3; int fUseUif; int nStages; Cec_SproveStage_t Stages[SPROVE_STAGE_MAX]; }; static volatile Par_Share_t * g_pUfarShare = NULL; static volatile Par_Share_t * g_pGlaShare = NULL; static inline const char * Cec_SolveEngineName( int iEngine ) { if ( iEngine == 0 ) return "rar"; if ( iEngine == 1 ) return "bmc"; if ( iEngine == 2 ) return "pdr"; if ( iEngine == 3 ) return "bmc-g"; if ( iEngine == 4 ) return "pdr-t"; if ( iEngine == 5 ) return "bmcg"; if ( iEngine == PAR_ENGINE_UFAR ) return "ufar"; if ( iEngine == PAR_ENGINE_SCORR1 ) return "scnew"; if ( iEngine == PAR_ENGINE_SCORR2 ) return "scold"; if ( iEngine == PAR_ENGINE_GLA ) return "gla-q"; return "unknown"; } static inline void Cec_CopyGiaName( Gia_Man_t * pSrc, Gia_Man_t * pDst ) { char * pName = pSrc->pName ? pSrc->pName : pSrc->pSpec; if ( pName == NULL ) return; if ( pDst->pName == NULL ) pDst->pName = Abc_UtilStrsav( pName ); if ( pDst->pSpec == NULL ) pDst->pSpec = Abc_UtilStrsav( pName ); } static inline void Cec_CopyGiaNameToAig( Gia_Man_t * pGia, Aig_Man_t * pAig ) { char * pName = pGia->pName ? pGia->pName : pGia->pSpec; if ( pName == NULL ) return; if ( pAig->pName == NULL ) pAig->pName = Abc_UtilStrsav( pName ); if ( pAig->pSpec == NULL ) pAig->pSpec = Abc_UtilStrsav( pName ); } static int Cec_SProveStopUfar( int RunId ) { (void)RunId; return g_pUfarShare && g_pUfarShare->fSolved != 0; } static int Cec_SProveStopGla( int RunId ) { (void)RunId; return g_pGlaShare && g_pGlaShare->fSolved != 0; } static int Cec_ScorrStop( void * pUser ) { Cec_ScorrStop_t * p = (Cec_ScorrStop_t *)pUser; if ( p == NULL ) return 0; if ( p->pShare && p->pShare->fSolved ) { p->fStoppedByCallback = 1; return 1; } if ( p->TimeToStop && Abc_Clock() >= p->TimeToStop ) { p->fStoppedByTimeout = 1; return 1; } return 0; } static int Cec_SProveCallback( void * pUser, int fSolved, unsigned Result ) { Par_ThData_t * pThData = (Par_ThData_t *)pUser; Par_Share_t * pShare = pThData ? pThData->pShare : NULL; if ( pShare == NULL ) return 0; if ( fSolved ) { if ( pShare->fSolved == 0 ) { pShare->fSolved = 1; pShare->Result = Result; pShare->iEngine = pThData->iEngine; } return 0; } return pShare->fSolved != 0; } static inline const char * Cec_SproveNetName( int NetId ) { if ( NetId == SPROVE_NET_ORIG ) return "orig"; if ( NetId == SPROVE_NET_SCNEW ) return "scnew"; if ( NetId == SPROVE_NET_SCOLD ) return "scold"; return "unknown"; } static inline int Cec_SproveNetId( const char * pName ) { if ( !strcmp(pName, "orig") ) return SPROVE_NET_ORIG; if ( !strcmp(pName, "scnew") ) return SPROVE_NET_SCNEW; if ( !strcmp(pName, "scold") ) return SPROVE_NET_SCOLD; return -1; } static inline const char * Cec_SproveStopName( int StopReason ) { if ( StopReason == 1 ) return "self"; if ( StopReason == 2 ) return "callback"; if ( StopReason == 3 ) return "timeout"; if ( StopReason == 4 ) return "skip"; return "unknown"; } static inline const char * Cec_SproveResultName( int RetValue ) { if ( RetValue == 0 ) return "sat"; if ( RetValue == 1 ) return "unsat"; return "undecided"; } static inline unsigned long long Cec_SproveClockToMs( abctime Time ) { return (unsigned long long)(1000.0 * (double)Time / (double)CLOCKS_PER_SEC); } static int Cec_SproveFindValue( char * pLine, const char * pKey, char * pValue, int nValueSize ) { char * pBeg = strstr( pLine, pKey ); int i = 0; if ( pBeg == NULL ) return 0; pBeg += strlen(pKey); while ( *pBeg && *pBeg != ' ' && *pBeg != '\t' && *pBeg != '\r' && *pBeg != '\n' ) { if ( i < nValueSize - 1 ) pValue[i++] = *pBeg; pBeg++; } pValue[i] = 0; return i > 0; } static int Cec_SproveParseEngineName( const char * pName ) { int i; for ( i = 0; i <= PAR_ENGINE_GLA; i++ ) if ( !strcmp(pName, Cec_SolveEngineName(i)) ) return i; return -1; } static void Cec_SproveDeriveEngineList( int nProcs, int fUseUif, int * pEngines, int * pnEngines ) { int i, nEngines = nProcs + (fUseUif ? 1 : 0); assert( nEngines >= 1 && nEngines <= PAR_THR_MAX ); for ( i = 0; i < nEngines; i++ ) { if ( fUseUif && i == nEngines - 1 ) pEngines[i] = PAR_ENGINE_UFAR; else if ( !fUseUif && nEngines == 6 && i == 5 ) pEngines[i] = PAR_ENGINE_GLA; else pEngines[i] = i; } *pnEngines = nEngines; } static void Cec_SprovePlanDefault( Cec_SprovePlan_t * pPlan, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif ) { int nEngines; memset( pPlan, 0, sizeof(Cec_SprovePlan_t) ); { int i; for ( i = 0; i < SPROVE_STAGE_MAX; i++ ) pPlan->Stages[i].GuardExistsNet = pPlan->Stages[i].GuardAndLimitNet = -1; } pPlan->nProcs = nProcs; pPlan->nTimeOut = nTimeOut; pPlan->nTimeOut2 = nTimeOut2; pPlan->nTimeOut3 = nTimeOut3; pPlan->fUseUif = fUseUif; pPlan->nStages = 4; Cec_SproveDeriveEngineList( nProcs, fUseUif, pPlan->Stages[0].RoundEngines, &nEngines ); pPlan->Stages[0].Id = 1; pPlan->Stages[0].fHasRound = 1; pPlan->Stages[0].RoundNet = SPROVE_NET_ORIG; pPlan->Stages[0].RoundTimeout = nTimeOut; pPlan->Stages[0].nRoundEngines = nEngines; pPlan->Stages[0].fHasReduce = 1; pPlan->Stages[0].ReduceType = PAR_ENGINE_SCORR1; pPlan->Stages[0].ReduceNetIn = SPROVE_NET_ORIG; pPlan->Stages[0].ReduceNetOut = SPROVE_NET_SCNEW; pPlan->Stages[0].ReduceTimeout = nTimeOut; pPlan->Stages[1].Id = 2; pPlan->Stages[1].fGuardUnsolved = 1; pPlan->Stages[1].fHasRound = 1; pPlan->Stages[1].RoundNet = SPROVE_NET_SCNEW; pPlan->Stages[1].RoundTimeout = nTimeOut2; pPlan->Stages[1].nRoundEngines = nEngines; memcpy( pPlan->Stages[1].RoundEngines, pPlan->Stages[0].RoundEngines, sizeof(int) * nEngines ); pPlan->Stages[2].Id = 3; pPlan->Stages[2].fGuardUnsolved = 1; pPlan->Stages[2].GuardAndLimitNet = SPROVE_NET_SCNEW; pPlan->Stages[2].GuardAndLimit = 100000; pPlan->Stages[2].fHasReduce = 1; pPlan->Stages[2].ReduceType = PAR_ENGINE_SCORR2; pPlan->Stages[2].ReduceNetIn = SPROVE_NET_SCNEW; pPlan->Stages[2].ReduceNetOut = SPROVE_NET_SCOLD; pPlan->Stages[2].ReduceTimeout = nTimeOut3; pPlan->Stages[3].Id = 4; pPlan->Stages[3].fGuardUnsolved = 1; pPlan->Stages[3].GuardExistsNet = SPROVE_NET_SCOLD; pPlan->Stages[3].fHasRound = 1; pPlan->Stages[3].RoundNet = SPROVE_NET_SCOLD; pPlan->Stages[3].RoundTimeout = nTimeOut3; pPlan->Stages[3].nRoundEngines = nEngines; memcpy( pPlan->Stages[3].RoundEngines, pPlan->Stages[0].RoundEngines, sizeof(int) * nEngines ); } static void Cec_SproveTraceWrite( Cec_SproveTrace_t * pTrace, const char * pFormat, ... ) { va_list args; if ( pTrace == NULL || !pTrace->fActive || pTrace->pFile == NULL ) return; pthread_mutex_lock( &pTrace->Mutex ); va_start( args, pFormat ); vfprintf( pTrace->pFile, pFormat, args ); va_end( args ); fputc( '\n', pTrace->pFile ); fflush( pTrace->pFile ); pthread_mutex_unlock( &pTrace->Mutex ); } static abctime Cec_SproveTraceTime( Cec_SproveTrace_t * pTrace ) { return pTrace ? Abc_Clock() - pTrace->clkStart : 0; } static void Cec_SproveTraceOpen( Cec_SproveTrace_t * pTrace, Gia_Man_t * p, Cec_SprovePlan_t * pPlan, char * pReplayFile ) { int i, k; char * pProbName = p->pSpec ? p->pSpec : Gia_ManName(p); memset( pTrace, 0, sizeof(Cec_SproveTrace_t) ); if ( pReplayFile == NULL ) return; pTrace->pFile = fopen( pReplayFile, "wb" ); if ( pTrace->pFile == NULL ) return; pTrace->fActive = 1; pTrace->clkStart = Abc_Clock(); pthread_mutex_init( &pTrace->Mutex, NULL ); Cec_SproveTraceWrite( pTrace, "SPROVE_REPLAY 1" ); Cec_SproveTraceWrite( pTrace, "CASE %s", pProbName ? pProbName : "(none)" ); Cec_SproveTraceWrite( pTrace, "PARAMS P=%d T=%d U=%d W=%d UIF=%d", pPlan->nProcs, pPlan->nTimeOut, pPlan->nTimeOut2, pPlan->nTimeOut3, pPlan->fUseUif ); Cec_SproveTraceWrite( pTrace, "" ); Cec_SproveTraceWrite( pTrace, "PLAN_BEGIN" ); for ( i = 0; i < pPlan->nStages; i++ ) { Cec_SproveStage_t * pStage = &pPlan->Stages[i]; char Buffer[256]; Buffer[0] = 0; if ( pStage->fGuardUnsolved ) strcat( Buffer, "unsolved" ); if ( pStage->GuardExistsNet >= 0 ) sprintf( Buffer + strlen(Buffer), "%sexists(%s)", Buffer[0] ? "," : "", Cec_SproveNetName(pStage->GuardExistsNet) ); if ( pStage->GuardAndLimitNet >= 0 ) sprintf( Buffer + strlen(Buffer), "%sand_lt(%s,%d)", Buffer[0] ? "," : "", Cec_SproveNetName(pStage->GuardAndLimitNet), pStage->GuardAndLimit ); if ( !Buffer[0] ) strcpy( Buffer, "none" ); if ( pStage->fHasRound ) { char EngBuf[128]; EngBuf[0] = 0; for ( k = 0; k < pStage->nRoundEngines; k++ ) { if ( k > 0 ) strcat( EngBuf, "," ); strcat( EngBuf, Cec_SolveEngineName(pStage->RoundEngines[k]) ); } Cec_SproveTraceWrite( pTrace, "ROUND stage=%d guard=%s net=%s timeout=%d engines=%s", pStage->Id, Buffer, Cec_SproveNetName(pStage->RoundNet), pStage->RoundTimeout, EngBuf ); } if ( pStage->fHasReduce ) Cec_SproveTraceWrite( pTrace, "REDUCE stage=%d guard=%s name=%s in=%s out=%s timeout=%d stop=callback_or_timeout", pStage->Id, Buffer, Cec_SolveEngineName(pStage->ReduceType), Cec_SproveNetName(pStage->ReduceNetIn), Cec_SproveNetName(pStage->ReduceNetOut), pStage->ReduceTimeout ); } Cec_SproveTraceWrite( pTrace, "PLAN_END" ); Cec_SproveTraceWrite( pTrace, "" ); Cec_SproveTraceWrite( pTrace, "OBSERVED_BEGIN" ); Cec_SproveTraceWrite( pTrace, "CHECKPOINT net=orig regs=%d ands=%d pos=%d", Gia_ManRegNum(p), Gia_ManAndNum(p), Gia_ManPoNum(p) ); } static void Cec_SproveTraceClose( Cec_SproveTrace_t * pTrace ) { if ( pTrace == NULL || !pTrace->fActive ) return; Cec_SproveTraceWrite( pTrace, "OBSERVED_END" ); pthread_mutex_destroy( &pTrace->Mutex ); fclose( pTrace->pFile ); pTrace->pFile = NULL; pTrace->fActive = 0; } static int Cec_SproveReplayReadParamsInt( char * pFileName, Cec_SprovePlan_t * pPlan ) { char Buffer[1024], Value[256]; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) return 0; memset( pPlan, 0, sizeof(Cec_SprovePlan_t) ); { int i; for ( i = 0; i < SPROVE_STAGE_MAX; i++ ) pPlan->Stages[i].GuardExistsNet = pPlan->Stages[i].GuardAndLimitNet = -1; } while ( fgets( Buffer, sizeof(Buffer), pFile ) != NULL ) { if ( strncmp(Buffer, "PARAMS ", 7) == 0 ) { if ( !Cec_SproveFindValue(Buffer, "P=", Value, sizeof(Value)) ) break; pPlan->nProcs = atoi(Value); if ( !Cec_SproveFindValue(Buffer, "T=", Value, sizeof(Value)) ) break; pPlan->nTimeOut = atoi(Value); if ( !Cec_SproveFindValue(Buffer, "U=", Value, sizeof(Value)) ) break; pPlan->nTimeOut2 = atoi(Value); if ( !Cec_SproveFindValue(Buffer, "W=", Value, sizeof(Value)) ) break; pPlan->nTimeOut3 = atoi(Value); if ( !Cec_SproveFindValue(Buffer, "UIF=", Value, sizeof(Value)) ) break; pPlan->fUseUif = atoi(Value); fclose( pFile ); return 1; } } fclose( pFile ); return 0; } static int Cec_SproveReplayReadPlan( char * pFileName, Cec_SprovePlan_t * pPlan ) { char Buffer[1024], Value[256], Guard[256], Engines[256]; FILE * pFile; int fInPlan = 0; if ( !Cec_SproveReplayReadParamsInt( pFileName, pPlan ) ) return 0; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) return 0; while ( fgets( Buffer, sizeof(Buffer), pFile ) != NULL ) { Cec_SproveStage_t * pStage; int StageId; if ( strncmp(Buffer, "PLAN_BEGIN", 10) == 0 ) { fInPlan = 1; continue; } if ( strncmp(Buffer, "PLAN_END", 8) == 0 || strncmp(Buffer, "OBSERVED_BEGIN", 14) == 0 ) break; if ( !fInPlan ) continue; if ( strncmp(Buffer, "ROUND ", 6) == 0 ) { char * pTok; int nEngines = 0; if ( !Cec_SproveFindValue(Buffer, "stage=", Value, sizeof(Value)) ) continue; StageId = atoi(Value); if ( StageId < 1 || StageId > SPROVE_STAGE_MAX ) continue; pStage = &pPlan->Stages[StageId - 1]; if ( StageId > pPlan->nStages ) pPlan->nStages = StageId; memset( Guard, 0, sizeof(Guard) ); Cec_SproveFindValue(Buffer, "guard=", Guard, sizeof(Guard)); pStage->Id = StageId; pStage->fGuardUnsolved = strstr( Guard, "unsolved" ) != NULL; if ( strstr(Guard, "exists(") ) { sscanf( strstr(Guard, "exists("), "exists(%255[^)])", Value ); pStage->GuardExistsNet = Cec_SproveNetId( Value ); } if ( strstr(Guard, "and_lt(") ) { sscanf( strstr(Guard, "and_lt("), "and_lt(%255[^,],%d)", Value, &pStage->GuardAndLimit ); pStage->GuardAndLimitNet = Cec_SproveNetId( Value ); } if ( Cec_SproveFindValue(Buffer, "net=", Value, sizeof(Value)) ) pStage->RoundNet = Cec_SproveNetId( Value ); if ( Cec_SproveFindValue(Buffer, "timeout=", Value, sizeof(Value)) ) pStage->RoundTimeout = atoi(Value); if ( Cec_SproveFindValue(Buffer, "engines=", Engines, sizeof(Engines)) ) { pTok = strtok( Engines, "," ); while ( pTok && nEngines < PAR_THR_MAX ) { pStage->RoundEngines[nEngines++] = Cec_SproveParseEngineName( pTok ); pTok = strtok( NULL, "," ); } } pStage->fHasRound = 1; pStage->nRoundEngines = nEngines; } else if ( strncmp(Buffer, "REDUCE ", 7) == 0 ) { if ( !Cec_SproveFindValue(Buffer, "stage=", Value, sizeof(Value)) ) continue; StageId = atoi(Value); if ( StageId < 1 || StageId > SPROVE_STAGE_MAX ) continue; pStage = &pPlan->Stages[StageId - 1]; if ( StageId > pPlan->nStages ) pPlan->nStages = StageId; memset( Guard, 0, sizeof(Guard) ); Cec_SproveFindValue(Buffer, "guard=", Guard, sizeof(Guard)); pStage->Id = StageId; pStage->fGuardUnsolved = strstr( Guard, "unsolved" ) != NULL; if ( strstr(Guard, "exists(") ) { sscanf( strstr(Guard, "exists("), "exists(%255[^)])", Value ); pStage->GuardExistsNet = Cec_SproveNetId( Value ); } if ( strstr(Guard, "and_lt(") ) { sscanf( strstr(Guard, "and_lt("), "and_lt(%255[^,],%d)", Value, &pStage->GuardAndLimit ); pStage->GuardAndLimitNet = Cec_SproveNetId( Value ); } if ( Cec_SproveFindValue(Buffer, "name=", Value, sizeof(Value)) ) pStage->ReduceType = Cec_SproveParseEngineName( Value ); if ( Cec_SproveFindValue(Buffer, "in=", Value, sizeof(Value)) ) pStage->ReduceNetIn = Cec_SproveNetId( Value ); if ( Cec_SproveFindValue(Buffer, "out=", Value, sizeof(Value)) ) pStage->ReduceNetOut = Cec_SproveNetId( Value ); if ( Cec_SproveFindValue(Buffer, "timeout=", Value, sizeof(Value)) ) pStage->ReduceTimeout = atoi(Value); pStage->fHasReduce = 1; } } fclose( pFile ); return pPlan->nStages > 0; } static Gia_Man_t * Cec_SproveGetNet( int NetId, Gia_Man_t * pOrig, Gia_Man_t * pScorr, Gia_Man_t * pScorr2 ) { if ( NetId == SPROVE_NET_ORIG ) return pOrig; if ( NetId == SPROVE_NET_SCNEW ) return pScorr; if ( NetId == SPROVE_NET_SCOLD ) return pScorr2; return NULL; } static void Cec_SproveSetNet( int NetId, Gia_Man_t ** ppScorr, Gia_Man_t ** ppScorr2, Gia_Man_t * pNet ) { if ( NetId == SPROVE_NET_SCNEW ) { Gia_ManStopP( ppScorr ); *ppScorr = pNet; } else if ( NetId == SPROVE_NET_SCOLD ) { Gia_ManStopP( ppScorr2 ); *ppScorr2 = pNet; } else Gia_ManStop( pNet ); } static int Cec_SproveCheckGuard( Cec_SproveStage_t * pStage, int RetValue, Gia_Man_t * pOrig, Gia_Man_t * pScorr, Gia_Man_t * pScorr2 ) { Gia_Man_t * pNet; if ( pStage->fGuardUnsolved && RetValue != -1 ) return 0; if ( pStage->GuardExistsNet >= 0 && Cec_SproveGetNet( pStage->GuardExistsNet, pOrig, pScorr, pScorr2 ) == NULL ) return 0; if ( pStage->GuardAndLimitNet >= 0 ) { pNet = Cec_SproveGetNet( pStage->GuardAndLimitNet, pOrig, pScorr, pScorr2 ); if ( pNet == NULL || Gia_ManAndNum(pNet) >= pStage->GuardAndLimit ) return 0; } return 1; } static void Cec_SproveTraceCheckpoint( Cec_SproveTrace_t * pTrace, int NetId, Gia_Man_t * pNet ) { if ( pTrace == NULL || !pTrace->fActive || pNet == NULL ) return; Cec_SproveTraceWrite( pTrace, "CHECKPOINT net=%s regs=%d ands=%d pos=%d", Cec_SproveNetName(NetId), Gia_ManRegNum(pNet), Gia_ManAndNum(pNet), Gia_ManPoNum(pNet) ); } static Gia_Man_t * Cec_SproveRunReduce( Gia_Man_t * pInput, Cec_SproveStage_t * pStage, Par_Share_t * pShare, Cec_SproveTrace_t * pTrace, abctime * pClkUsed, int * pRetValue, int * pRetEngine ) { Cec_ScorrStop_t Stop; abctime clk = Abc_Clock(); Gia_Man_t * pOutput = NULL; int StopReason = 1; memset( &Stop, 0, sizeof(Stop) ); if ( pTrace && pTrace->fActive ) Cec_SproveTraceWrite( pTrace, "START kind=reduce stage=%d name=%s in=%s out=%s timeout=%d t=%llu", pStage->Id, Cec_SolveEngineName(pStage->ReduceType), Cec_SproveNetName(pStage->ReduceNetIn), Cec_SproveNetName(pStage->ReduceNetOut), pStage->ReduceTimeout, Cec_SproveClockToMs( Cec_SproveTraceTime(pTrace) ) ); if ( pStage->ReduceType == PAR_ENGINE_SCORR1 ) pOutput = Cec_GiaScorrNew( pInput, pStage->ReduceTimeout, pShare, &Stop ); else if ( pStage->ReduceType == PAR_ENGINE_SCORR2 ) pOutput = Cec_GiaScorrOld( pInput, pStage->ReduceTimeout, pShare, &Stop ); else assert( 0 ); if ( Gia_ManAndNum(pOutput) == 0 ) { pShare->fSolved = 1; pShare->Result = 1; pShare->iEngine = pStage->ReduceType; *pRetValue = 1; *pRetEngine = pStage->ReduceType; } if ( Stop.fStoppedByCallback ) StopReason = 2; else if ( Stop.fStoppedByTimeout ) StopReason = 3; if ( pClkUsed ) *pClkUsed = Abc_Clock() - clk; if ( pTrace && pTrace->fActive ) { Cec_SproveTraceWrite( pTrace, "STOP kind=reduce stage=%d name=%s in=%s out=%s result=%s stop=%s t=%llu elapsed=%llu", pStage->Id, Cec_SolveEngineName(pStage->ReduceType), Cec_SproveNetName(pStage->ReduceNetIn), Cec_SproveNetName(pStage->ReduceNetOut), *pRetEngine == pStage->ReduceType ? Cec_SproveResultName(*pRetValue) : "undecided", Cec_SproveStopName(StopReason), Cec_SproveClockToMs( Cec_SproveTraceTime(pTrace) ), Cec_SproveClockToMs( Abc_Clock() - clk ) ); Cec_SproveTraceCheckpoint( pTrace, pStage->ReduceNetOut, pOutput ); } return pOutput; } static int Cec_SproveExecutePlan( Gia_Man_t * p, Cec_SprovePlan_t * pPlan, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent, char * pReplayFile ) { abctime clkTotal = Abc_Clock(), clkStage = 0; Par_ThData_t ThData[PAR_THR_MAX]; pthread_t WorkerThread[PAR_THR_MAX]; Par_Share_t Share; Cec_SproveTrace_t Trace; Gia_Man_t * pScorr = NULL, * pScorr2 = NULL; int i, RetValue = -1, RetEngine = -1, fThreadsStarted = 0; (void)fVeryVerbose; memset( &Share, 0, sizeof(Par_Share_t) ); memset( &Trace, 0, sizeof(Cec_SproveTrace_t) ); memset( ThData, 0, sizeof(ThData) ); memset( WorkerThread, 0, sizeof(WorkerThread) ); Abc_CexFreeP( &p->pCexComb ); Abc_CexFreeP( &p->pCexSeq ); if ( !fSilent && fVerbose ) printf( "Solving verification problem with the following parameters:\n" ); if ( !fSilent && fVerbose ) printf( "Processes = %d TimeOut = %d sec Verbose = %d.\n", pPlan->nProcs, pPlan->nTimeOut, fVerbose ); fflush( stdout ); Cec_SproveTraceOpen( &Trace, p, pPlan, pReplayFile ); for ( i = 0; i < pPlan->nStages; i++ ) { Cec_SproveStage_t * pStage = &pPlan->Stages[i]; Gia_Man_t * pRoundNet = NULL, * pReduceNet = NULL, * pReduceOut = NULL; if ( !Cec_SproveCheckGuard( pStage, RetValue, p, pScorr, pScorr2 ) ) { Cec_SproveTraceWrite( &Trace, "SKIP stage=%d reason=guard", pStage->Id ); continue; } if ( pStage->fHasRound ) { pRoundNet = Cec_SproveGetNet( pStage->RoundNet, p, pScorr, pScorr2 ); if ( pRoundNet == NULL ) { Cec_SproveTraceWrite( &Trace, "SKIP stage=%d reason=missing_round_net", pStage->Id ); continue; } Cec_SproveTraceWrite( &Trace, "START kind=round stage=%d net=%s timeout=%d t=%llu", pStage->Id, Cec_SproveNetName(pStage->RoundNet), pStage->RoundTimeout, Cec_SproveClockToMs( Cec_SproveTraceTime(&Trace) ) ); Cec_GiaInitThreads( ThData, pStage->nRoundEngines, pRoundNet, pStage->RoundTimeout, pPlan->nTimeOut3, pWlc, fVerbose, fThreadsStarted ? NULL : WorkerThread, &Share, pStage->RoundEngines, pStage->Id, pStage->RoundNet, &Trace ); fThreadsStarted = 1; } if ( pStage->fHasReduce ) { pReduceNet = Cec_SproveGetNet( pStage->ReduceNetIn, p, pScorr, pScorr2 ); if ( pReduceNet == NULL ) Cec_SproveTraceWrite( &Trace, "SKIP stage=%d reason=missing_reduce_net", pStage->Id ); else { pReduceOut = Cec_SproveRunReduce( pReduceNet, pStage, &Share, &Trace, &clkStage, &RetValue, &RetEngine ); Cec_SproveSetNet( pStage->ReduceNetOut, &pScorr, &pScorr2, pReduceOut ); } } if ( pStage->fHasRound ) { RetValue = Cec_GiaWaitThreads( ThData, pStage->nRoundEngines, p, RetValue, &RetEngine ); Cec_SproveTraceWrite( &Trace, "STOP kind=round stage=%d net=%s result=%s winner=%s t=%llu", pStage->Id, Cec_SproveNetName(pStage->RoundNet), Cec_SproveResultName(RetValue), RetEngine >= 0 ? Cec_SolveEngineName(RetEngine) : "none", Cec_SproveClockToMs( Cec_SproveTraceTime(&Trace) ) ); } if ( pStage->fHasReduce && RetValue == -1 && !fSilent && fVerbose ) { Gia_Man_t * pAfter = Cec_SproveGetNet( pStage->ReduceNetOut, p, pScorr, pScorr2 ); if ( pAfter ) { printf( "Reduced the miter from %d to %d nodes. ", Gia_ManAndNum(Cec_SproveGetNet(pStage->ReduceNetIn, p, pScorr, pScorr2)), Gia_ManAndNum(pAfter) ); Abc_PrintTime( 1, "Time", clkStage ); } } } if ( fThreadsStarted ) Cec_GiaStopThreads( ThData, WorkerThread, pPlan->Stages[0].nRoundEngines > 0 ? pPlan->Stages[0].nRoundEngines : pPlan->nProcs + (pPlan->fUseUif ? 1 : 0) ); Gia_ManStopP( &pScorr2 ); Gia_ManStopP( &pScorr ); if ( !fSilent ) { char * pProbName = p->pSpec ? p->pSpec : Gia_ManName(p); if ( RetValue != -1 && RetEngine < 0 ) RetEngine = PAR_ENGINE_SCORR1; printf( "Problem \"%s\" is ", pProbName ? pProbName : "(none)" ); if ( RetValue == 0 ) printf( "SATISFIABLE (solved by %s).", Cec_SolveEngineName(RetEngine) ); else if ( RetValue == 1 ) printf( "UNSATISFIABLE (solved by %s).", Cec_SolveEngineName(RetEngine) ); else if ( RetValue == -1 ) printf( "UNDECIDED." ); else assert( 0 ); printf( " " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); fflush( stdout ); } Cec_SproveTraceWrite( &Trace, "FINAL result=%s winner=%s total=%llu", Cec_SproveResultName(RetValue), RetEngine >= 0 ? Cec_SolveEngineName(RetEngine) : "none", Cec_SproveClockToMs( Abc_Clock() - clkTotal ) ); Cec_SproveTraceClose( &Trace ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, int fVerbose, Par_ThData_t * pThData ) { abctime clk = Abc_Clock(); int RetValue = -1; if ( pThData && pThData->pTrace ) Cec_SproveTraceWrite( pThData->pTrace, "START kind=engine stage=%d net=%s engine=%s worker=%d timeout=%d t=%llu", pThData->StageId, Cec_SproveNetName(pThData->NetId), Cec_SolveEngineName(iEngine), pThData->WorkerId, nTimeOut, Cec_SproveClockToMs( Cec_SproveTraceTime(pThData->pTrace) ) ); if ( iEngine != PAR_ENGINE_UFAR && iEngine != PAR_ENGINE_GLA && Gia_ManRegNum(p) == 0 ) { if ( fVerbose ) printf( "Engine %d (%-5s) skipped because the current miter is combinational.\n", iEngine, Cec_SolveEngineName(iEngine) ); if ( pThData && pThData->pTrace ) Cec_SproveTraceWrite( pThData->pTrace, "STOP kind=engine stage=%d net=%s engine=%s worker=%d result=undecided stop=skip t=%llu", pThData->StageId, Cec_SproveNetName(pThData->NetId), Cec_SolveEngineName(iEngine), pThData->WorkerId, Cec_SproveClockToMs( Cec_SproveTraceTime(pThData->pTrace) ) ); return -1; } //abctime clkStop = nTimeOut * CLOCKS_PER_SEC + Abc_Clock(); if ( fVerbose ) printf( "Calling engine %d (%-5s) with timeout %d sec.\n", iEngine, Cec_SolveEngineName(iEngine), nTimeOut ); Abc_CexFreeP( &p->pCexSeq ); if ( iEngine == 0 ) { Ssw_RarPars_t Pars, * pPars = &Pars; Ssw_RarSetDefaultParams( pPars ); pPars->TimeOut = nTimeOut; pPars->fSilent = 1; if ( pThData && pThData->pShare ) { pPars->pFuncProgress = Cec_SProveCallback; pPars->pProgress = (void *)pThData; } RetValue = Ssw_RarSimulateGia( p, pPars ); } else if ( iEngine == 1 ) { Saig_ParBmc_t Pars, * pPars = &Pars; Saig_ParBmcSetDefaultParams( pPars ); pPars->nTimeOut = nTimeOut; pPars->fSilent = 1; if ( pThData && pThData->pShare ) { pPars->pFuncProgress = Cec_SProveCallback; pPars->pProgress = (void *)pThData; } Aig_Man_t * pAig = Gia_ManToAigSimple( p ); Cec_CopyGiaNameToAig( p, pAig ); RetValue = Saig_ManBmcScalable( pAig, pPars ); p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; Aig_ManStop( pAig ); } else if ( iEngine == 2 ) { Pdr_Par_t Pars, * pPars = &Pars; Pdr_ManSetDefaultParams( pPars ); pPars->nTimeOut = nTimeOut; pPars->fSilent = 1; if ( pThData && pThData->pShare ) { pPars->pFuncProgress = Cec_SProveCallback; pPars->pProgress = (void *)pThData; } Aig_Man_t * pAig = Gia_ManToAigSimple( p ); Cec_CopyGiaNameToAig( p, pAig ); RetValue = Pdr_ManSolve( pAig, pPars ); p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; Aig_ManStop( pAig ); } else if ( iEngine == 3 ) { Saig_ParBmc_t Pars, * pPars = &Pars; Saig_ParBmcSetDefaultParams( pPars ); pPars->fUseGlucose = 1; pPars->nTimeOut = nTimeOut; pPars->fSilent = 1; if ( pThData && pThData->pShare ) { pPars->pFuncProgress = Cec_SProveCallback; pPars->pProgress = (void *)pThData; } Aig_Man_t * pAig = Gia_ManToAigSimple( p ); Cec_CopyGiaNameToAig( p, pAig ); RetValue = Saig_ManBmcScalable( pAig, pPars ); p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; Aig_ManStop( pAig ); } else if ( iEngine == 4 ) { Pdr_Par_t Pars, * pPars = &Pars; Pdr_ManSetDefaultParams( pPars ); pPars->fUseAbs = 1; pPars->nTimeOut = nTimeOut; pPars->fSilent = 1; if ( pThData && pThData->pShare ) { pPars->pFuncProgress = Cec_SProveCallback; pPars->pProgress = (void *)pThData; } Aig_Man_t * pAig = Gia_ManToAigSimple( p ); Cec_CopyGiaNameToAig( p, pAig ); RetValue = Pdr_ManSolve( pAig, pPars ); p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; Aig_ManStop( pAig ); } else if ( iEngine == 5 ) { Bmc_AndPar_t Pars, * pPars = &Pars; memset( pPars, 0, sizeof(Bmc_AndPar_t) ); pPars->nProcs = 1; // the number of parallel solvers pPars->nFramesAdd = 1; // the number of additional frames pPars->fNotVerbose = 1; // silent pPars->nTimeOut = nTimeOut; // timeout in seconds if ( pThData && pThData->pShare ) { pPars->pFuncProgress = Cec_SProveCallback; pPars->pProgress = (void *)pThData; } RetValue = Bmcg_ManPerform( p, pPars ); } else if ( iEngine == PAR_ENGINE_UFAR ) { if ( pThData && pThData->pWlc ) { g_pUfarShare = pThData->pShare; RetValue = Ufar_ProveWithTimeout( pThData->pWlc, pThData->nTimeOutU, fVerbose, Cec_SProveStopUfar, 0 ); g_pUfarShare = NULL; } } else if ( iEngine == PAR_ENGINE_GLA ) { if ( Gia_ManPoNum(p) != 1 ) return -1; Abs_Par_t Pars, * pPars = &Pars; Abs_ParSetDefaults( pPars ); pPars->nTimeOut = nTimeOut; pPars->fCallProver = 1; // emulate "&gla -q" pPars->fVerbose = 0; pPars->fVeryVerbose = 0; pPars->RunId = 0; pPars->pFuncStop = Cec_SProveStopGla; g_pGlaShare = pThData ? pThData->pShare : NULL; RetValue = Gia_ManPerformGla( p, pPars ); g_pGlaShare = NULL; } else assert( 0 ); //while ( Abc_Clock() < clkStop ); if ( pThData && pThData->pShare && RetValue != -1 ) Cec_SProveCallback( (void *)pThData, 1, (unsigned)RetValue ); if ( pThData ) { if ( RetValue != -1 ) pThData->StopReason = 1; else if ( pThData->pShare && pThData->pShare->fSolved ) pThData->StopReason = 2; else pThData->StopReason = 3; } if ( pThData && pThData->pTrace ) Cec_SproveTraceWrite( pThData->pTrace, "STOP kind=engine stage=%d net=%s engine=%s worker=%d result=%s stop=%s t=%llu elapsed=%llu", pThData->StageId, Cec_SproveNetName(pThData->NetId), Cec_SolveEngineName(iEngine), pThData->WorkerId, Cec_SproveResultName(RetValue), Cec_SproveStopName(pThData->StopReason), Cec_SproveClockToMs( Cec_SproveTraceTime(pThData->pTrace) ), Cec_SproveClockToMs( Abc_Clock() - clk ) ); if ( fVerbose ) { printf( "Engine %d (%-5s) finished and %ssolved the problem. ", iEngine, Cec_SolveEngineName(iEngine), RetValue != -1 ? " " : "not " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return RetValue; } Gia_Man_t * Cec_GiaScorrOld( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare, Cec_ScorrStop_t * pStopOut ) { Cec_ScorrStop_t Stop; memset( &Stop, 0, sizeof(Stop) ); Stop.pShare = pShare; Stop.TimeToStop = nTimeOut > 0 ? (abctime)(Abc_Clock() + (abctime)nTimeOut * CLOCKS_PER_SEC) : 0; if ( Gia_ManRegNum(p) == 0 ) { if ( pStopOut ) *pStopOut = Stop; return Gia_ManDup( p ); } Ssw_Pars_t Pars, * pPars = &Pars; Ssw_ManSetDefaultParams( pPars ); pPars->pFunc = (void *)Cec_ScorrStop; pPars->pData = (void *)&Stop; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); Aig_Man_t * pAig2 = Ssw_SignalCorrespondence( pAig, pPars ); Gia_Man_t * pGia2 = Gia_ManFromAigSimple( pAig2 ); Aig_ManStop( pAig2 ); Aig_ManStop( pAig ); if ( pStopOut ) *pStopOut = Stop; return pGia2; } Gia_Man_t * Cec_GiaScorrNew( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare, Cec_ScorrStop_t * pStopOut ) { Cec_ScorrStop_t Stop; memset( &Stop, 0, sizeof(Stop) ); Stop.pShare = pShare; Stop.TimeToStop = nTimeOut > 0 ? (abctime)(Abc_Clock() + (abctime)nTimeOut * CLOCKS_PER_SEC) : 0; if ( Gia_ManRegNum(p) == 0 ) { if ( pStopOut ) *pStopOut = Stop; return Gia_ManDup( p ); } Cec_ParCor_t Pars, * pPars = &Pars; Cec_ManCorSetDefaultParams( pPars ); pPars->nBTLimit = 100; pPars->nLevelMax = 100; pPars->fVerbose = 0; pPars->fUseCSat = 1; pPars->pFunc = (void *)Cec_ScorrStop; pPars->pData = (void *)&Stop; p = Cec_ManLSCorrespondence( p, pPars ); if ( pStopOut ) *pStopOut = Stop; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Cec_GiaProveWorkerThread( void * pArg ) { Par_ThData_t * pThData = (Par_ThData_t *)pArg; int status, Result; status = pthread_mutex_lock( &pThData->Mutex ); assert( status == 0 ); while ( 1 ) { while ( !pThData->fWorking && !pThData->fStop ) { status = pthread_cond_wait( &pThData->Cond, &pThData->Mutex ); assert( status == 0 ); } if ( pThData->fStop ) break; status = pthread_mutex_unlock( &pThData->Mutex ); assert( status == 0 ); Result = Cec_GiaProveOne( pThData->p, pThData->iEngine, pThData->nTimeOut, pThData->fVerbose, pThData ); status = pthread_mutex_lock( &pThData->Mutex ); assert( status == 0 ); pThData->Result = Result; pThData->fWorking = 0; status = pthread_cond_broadcast( &pThData->Cond ); assert( status == 0 ); } status = pthread_mutex_unlock( &pThData->Mutex ); assert( status == 0 ); return NULL; } static void Cec_GiaStartThreads( Par_ThData_t * ThData, int nWorkers ) { int i, status; for ( i = 0; i < nWorkers; i++ ) { status = pthread_mutex_lock( &ThData[i].Mutex ); assert( status == 0 ); assert( !ThData[i].fStop ); assert( !ThData[i].fWorking ); ThData[i].fWorking = 1; status = pthread_cond_signal( &ThData[i].Cond ); assert( status == 0 ); status = pthread_mutex_unlock( &ThData[i].Mutex ); assert( status == 0 ); } } static void Cec_GiaInitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * p, int nTimeOut, int nTimeOutU, Wlc_Ntk_t * pWlc, int fVerbose, pthread_t * WorkerThread, Par_Share_t * pShare, int * pEngines, int StageId, int NetId, Cec_SproveTrace_t * pTrace ) { int i, status; assert( nWorkers <= PAR_THR_MAX ); for ( i = 0; i < nWorkers; i++ ) { if ( WorkerThread ) { ThData[i].p = Gia_ManDup( p ); Cec_CopyGiaName( p, ThData[i].p ); ThData[i].iEngine = pEngines[i]; ThData[i].fWorking = 0; ThData[i].fStop = 0; ThData[i].nTimeOut = nTimeOut; ThData[i].Result = -1; ThData[i].fVerbose = fVerbose; ThData[i].nTimeOutU= nTimeOutU; ThData[i].pWlc = pWlc; ThData[i].WorkerId = i; ThData[i].StageId = StageId; ThData[i].NetId = NetId; ThData[i].StopReason = 0; ThData[i].pShare = pShare; ThData[i].pTrace = pTrace; status = pthread_mutex_init( &ThData[i].Mutex, NULL ); assert( status == 0 ); status = pthread_cond_init( &ThData[i].Cond, NULL ); assert( status == 0 ); status = pthread_create( WorkerThread + i, NULL, Cec_GiaProveWorkerThread, (void *)(ThData + i) ); assert( status == 0 ); continue; } status = pthread_mutex_lock( &ThData[i].Mutex ); assert( status == 0 ); assert( !ThData[i].fStop ); assert( !ThData[i].fWorking ); Gia_ManStopP( &ThData[i].p ); ThData[i].p = Gia_ManDup( p ); Cec_CopyGiaName( p, ThData[i].p ); ThData[i].iEngine = pEngines[i]; ThData[i].nTimeOut = nTimeOut; ThData[i].Result = -1; ThData[i].fVerbose = fVerbose; ThData[i].nTimeOutU= nTimeOutU; ThData[i].pWlc = pWlc; ThData[i].WorkerId = i; ThData[i].StageId = StageId; ThData[i].NetId = NetId; ThData[i].StopReason = 0; ThData[i].pShare = pShare; ThData[i].pTrace = pTrace; status = pthread_mutex_unlock( &ThData[i].Mutex ); assert( status == 0 ); } Cec_GiaStartThreads( ThData, nWorkers ); } static void Cec_GiaStopThreads( Par_ThData_t * ThData, pthread_t * WorkerThread, int nWorkers ) { int i, status; for ( i = 0; i < nWorkers; i++ ) { status = pthread_mutex_lock( &ThData[i].Mutex ); assert( status == 0 ); ThData[i].fStop = 1; status = pthread_cond_signal( &ThData[i].Cond ); assert( status == 0 ); status = pthread_mutex_unlock( &ThData[i].Mutex ); assert( status == 0 ); } for ( i = 0; i < nWorkers; i++ ) { status = pthread_join( WorkerThread[i], NULL ); assert( status == 0 ); Gia_ManStopP( &ThData[i].p ); status = pthread_cond_destroy( &ThData[i].Cond ); assert( status == 0 ); status = pthread_mutex_destroy( &ThData[i].Mutex ); assert( status == 0 ); } } static int Cec_GiaWaitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * p, int RetValue, int * pRetEngine ) { int i, status, fWorking; for ( i = 0; i < nWorkers; i++ ) { status = pthread_mutex_lock( &ThData[i].Mutex ); assert( status == 0 ); fWorking = ThData[i].fWorking; if ( RetValue == -1 && !fWorking && ThData[i].Result != -1 ) { RetValue = ThData[i].Result; *pRetEngine = ThData[i].iEngine; if ( !p->pCexSeq && ThData[i].p->pCexSeq ) p->pCexSeq = Abc_CexDup( ThData[i].p->pCexSeq, -1 ); } status = pthread_mutex_unlock( &ThData[i].Mutex ); assert( status == 0 ); if ( fWorking ) i = -1; } return RetValue; } int Cec_GiaReplayReadParams( char * pFileName, int * pnProcs, int * pnTimeOut, int * pnTimeOut2, int * pnTimeOut3, int * pfUseUif ) { Cec_SprovePlan_t Plan; if ( !Cec_SproveReplayReadParamsInt( pFileName, &Plan ) ) return 0; if ( pnProcs ) *pnProcs = Plan.nProcs; if ( pnTimeOut ) *pnTimeOut = Plan.nTimeOut; if ( pnTimeOut2 ) *pnTimeOut2 = Plan.nTimeOut2; if ( pnTimeOut3 ) *pnTimeOut3 = Plan.nTimeOut3; if ( pfUseUif ) *pfUseUif = Plan.fUseUif; return 1; } int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent, char * pReplayFile ) { Cec_SprovePlan_t Plan; Cec_SprovePlanDefault( &Plan, nProcs, nTimeOut, nTimeOut2, nTimeOut3, fUseUif ); assert( nProcs >= 1 && nProcs <= 6 ); assert( nProcs + (fUseUif ? 1 : 0) <= PAR_THR_MAX ); return Cec_SproveExecutePlan( p, &Plan, pWlc, fVerbose, fVeryVerbose, fSilent, pReplayFile ); } int Cec_GiaReplayTest( Gia_Man_t * p, Wlc_Ntk_t * pWlc, char * pFileName, int fVerbose, int fVeryVerbose, int fSilent ) { Cec_SprovePlan_t Plan; if ( !Cec_SproveReplayReadPlan( pFileName, &Plan ) ) return -1; return Cec_SproveExecutePlan( p, &Plan, pWlc, fVerbose, fVeryVerbose, fSilent, NULL ); } #endif // pthreads are used //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END