/**Function************************************************************* Synopsis [Computes initial values of the new latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose ) { Vec_Int_t * vSolution; Abc_Ntk_t * pNtkMiter, * pNtkLogic; int RetValue; abctime clk; if ( pNtkCone == NULL ) return Vec_IntDup( vValues ); // convert the target network to AIG pNtkLogic = Abc_NtkDup( pNtkCone ); Abc_NtkToAig( pNtkLogic ); // get the miter pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues ); if ( fVerbose ) printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) ); // solve the miter clk = Abc_Clock(); RetValue = Abc_NtkMiterSat( pNtkMiter, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL ); if ( fVerbose ) { ABC_PRT( "SAT solving time", Abc_Clock() - clk ); } // analyze the result if ( RetValue == 1 ) printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" ); else if ( RetValue == -1 ) printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" ); else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) ) printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" ); // set the values of the latches vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) ); pNtkMiter->pModel = NULL; Abc_NtkDelete( pNtkMiter ); Abc_NtkDelete( pNtkLogic ); return vSolution; }
/**Function************************************************************* Synopsis [Verifies combinational equivalence by brute-force SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ) { extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); Abc_Ntk_t * pMiter; Abc_Ntk_t * pCnf; int RetValue; // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); printf( "Networks are equivalent after structural hashing.\n" ); return; } // convert the miter into a CNF pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); Abc_NtkDelete( pMiter ); if ( pCnf == NULL ) { printf( "Renoding for CNF has failed.\n" ); return; } // solve the CNF using the SAT solver RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL ); if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out).\n" ); else if ( RetValue == 0 ) printf( "Networks are NOT EQUIVALENT after SAT.\n" ); else printf( "Networks are equivalent after SAT.\n" ); if ( pCnf->pModel ) Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel ); FREE( pCnf->pModel ); Abc_NtkDelete( pCnf ); }
/**Function************************************************************* Synopsis [Solves the targets added by ABC_AddTarget().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) { Prove_Params_t * pParams = &mng->Params; int RetValue, i; // check if the target network is available if ( mng->pTarget == NULL ) { printf( "ABC_Solve: Target network is not derived by ABC_SolveInit().\n" ); return UNDETERMINED; } // try to prove the miter using a number of techniques if ( mng->mode ) RetValue = Abc_NtkMiterSat( mng->pTarget, (ABC_INT64_T)pParams->nMiteringLimitLast, (ABC_INT64_T)0, 0, NULL, NULL ); else // RetValue = Abc_NtkMiterProve( &mng->pTarget, pParams ); // old CEC engine RetValue = Abc_NtkIvyProve( &mng->pTarget, pParams ); // new CEC engine // analyze the result mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); if ( RetValue == -1 ) mng->pResult->status = UNDETERMINED; else if ( RetValue == 1 ) mng->pResult->status = UNSATISFIABLE; else if ( RetValue == 0 ) { mng->pResult->status = SATISFIABLE; // create the array of PI names and values for ( i = 0; i < mng->pResult->no_sig; i++ ) { mng->pResult->names[i] = Extra_UtilStrsav( ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)) ); mng->pResult->values[i] = mng->pTarget->pModel[i]; } ABC_FREE( mng->pTarget->pModel ); } else assert( 0 ); // delete the target Abc_NtkDelete( mng->pTarget ); mng->pTarget = NULL; // return the status return mng->pResult->status; }
/**Function************************************************************* Synopsis [Attempts to solve the miter using a number of tricks.] Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns a simplified version of the original network (or a constant 0 network). In case the network is not a constant zero and a SAT assignment is found, pNtk->pModel contains a satisfying assignment.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) { Prove_Params_t * pParams = pPars; Abc_Ntk_t * pNtk, * pNtkTemp; int RetValue, nIter, nSatFails, Counter, clk, timeStart = clock(); sint64 nSatConfs, nSatInspects, nInspectLimit; // get the starting network pNtk = *ppNtk; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 1 ); if ( pParams->fVerbose ) { printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); printf( "Mitering last = %d.\n", pParams->nMiteringLimitLast ); } // if SAT only, solve without iteration if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) { clk = clock(); RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL ); Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); *ppNtk = pNtk; return RetValue; } // check the current resource limits for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) { if ( pParams->fVerbose ) { printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); fflush( stdout ); } // try brute-force SAT clk = clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; RetValue = Abc_NtkMiterSat( pNtk, (sint64)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (sint64)nInspectLimit, 0, &nSatConfs, &nSatInspects ); Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); if ( RetValue >= 0 ) break; // add to the number of backtracks and inspects pParams->nTotalBacktracksMade += nSatConfs; pParams->nTotalInspectsMade += nSatInspects; // check if global resource limit is reached if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) { printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); *ppNtk = pNtk; return -1; } // try rewriting if ( pParams->fUseRewriting ) { clk = clock(); Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); // Counter = 1; while ( 1 ) { /* extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 ); Abc_NtkDelete( pNtkTemp ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; */ /* Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; */ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; } Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose ); } if ( pParams->fUseFraiging ) { // try FRAIGing clk = clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects ); Abc_NtkDelete( pNtkTemp ); Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose ); // printf( "NumFails = %d\n", nSatFails ); if ( RetValue >= 0 ) break; // add to the number of backtracks and inspects pParams->nTotalBacktracksMade += nSatConfs; pParams->nTotalInspectsMade += nSatInspects; // check if global resource limit is reached if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) { printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); *ppNtk = pNtk; return -1; } } } // try to prove it using brute force SAT if ( RetValue < 0 && pParams->fUseBdds ) { if ( pParams->fVerbose ) { printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); fflush( stdout ); } clk = clock(); pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); if ( pNtk ) { Abc_NtkDelete( pNtkTemp ); RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); } else pNtk = pNtkTemp; Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose ); } if ( RetValue < 0 ) { if ( pParams->fVerbose ) { printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); fflush( stdout ); } clk = clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)nInspectLimit, 0, NULL, NULL ); Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); } // assign the model if it was proved by rewriting (const 1 miter) if ( RetValue == 0 && pNtk->pModel == NULL ) { pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) ); memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) ); }
/**Function************************************************************* Synopsis [Solve the QBF problem EpAx[M(p,x)].] Description [The network should be a Boolean network where, the variables p go first, followed by variables x. The number of parameters is nPars. The number of iterations to try is nItersMax. The inputs to try are in vPiValues, and it will store the results if a model is found. The return value is 1 if the problem is false, 0 if the problem is true (and an assignment to p returned via vPiValeus), -1 if the iteration limit reached, and -2 if the sat solver times out. ] SideEffects [] SeeAlso [] ***********************************************************************/ int AbcBridge_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int nItersMax, Vec_Int_t* vPiValues) { Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp; int nIters, nInputs, RetValue, fFound = 0; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkIsComb(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 1 ); assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) ); // assert( Abc_NtkPiNum(pNtk)-nPars < 32 ); nInputs = Abc_NtkPiNum(pNtk) - nPars; assert(Vec_IntSize(vPiValues) == Abc_NtkPiNum(pNtk)); AbcBridge_NtkVectorClearPars( vPiValues, nPars ); pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues ); // iteratively solve for ( nIters = 0; nIters < nItersMax; nIters++ ) { // solve the synthesis instance // RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL ); RetValue = Abc_NtkDSat( pNtkSyn, (ABC_INT64_T)0, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 ); if ( RetValue == 0 ) AbcBridge_NtkModelToVector( pNtkSyn, vPiValues ); // Formula is unsat when forall variables replaced with concrete inputs, and // thus unsat in general. if ( RetValue == 1 ) { Abc_NtkDelete(pNtkSyn); return 1; // Return UNSAT } // Synthesis timed out. if (RetValue == -1) { Abc_NtkDelete(pNtkSyn); return -2; } // there is a counter-example // construct the verification instance AbcBridge_NtkVectorClearVars( pNtk, vPiValues, nPars ); pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues ); // complement the output Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 ); // solve the verification instance RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL ); if ( RetValue == 0 ) AbcBridge_NtkModelToVector( pNtkVer, vPiValues ); Abc_NtkDelete( pNtkVer ); if ( RetValue == 1 ) { Abc_NtkDelete( pNtkSyn ); return 0; // Return sat } // If verification timed out. if ( RetValue == -1 ) { Abc_NtkDelete(pNtkSyn); return -2; } // there is a counter-example // create a new synthesis network AbcBridge_NtkVectorClearPars( vPiValues, nPars ); pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues ); // add to the synthesis instance pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 ); Abc_NtkDelete( pNtkSyn2 ); Abc_NtkDelete( pNtkTemp ); } Abc_NtkDelete( pNtkSyn ); // Limit reached. return -1; }
/**Function************************************************************* Synopsis [Implements the given retiming on the sequential AIG.] Description [Returns 0 of initial state computation fails.] SideEffects [] SeeAlso [] ***********************************************************************/ int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int fVerbose ) { Seq_RetEdge_t RetEdge; stmm_table * tTable; stmm_generator * gen; Vec_Int_t * vValues; Abc_Ntk_t * pNtkProb, * pNtkMiter, * pNtkCnf; Abc_Obj_t * pNode, * pNodeNew; int * pModel, RetValue, i, clk; // return if the retiming is trivial if ( Vec_PtrSize(vMoves) == 0 ) return 1; // create the network for the initial state computation // start the table and the array of PO values pNtkProb = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); tTable = stmm_init_table( stmm_numcmp, stmm_numhash ); vValues = Vec_IntAlloc( 100 ); // perform the backward moves and build the network for initial state computation RetValue = 0; Vec_PtrForEachEntry( vMoves, pNode, i ) RetValue |= Abc_ObjRetimeBackward( pNode, pNtkProb, tTable, vValues ); // add the PIs corresponding to the white spots stmm_foreach_item( tTable, gen, (char **)&RetEdge, (char **)&pNodeNew ) Abc_ObjAddFanin( pNodeNew, Abc_NtkCreatePi(pNtkProb) ); // add the PI/PO names Abc_NtkAddDummyPiNames( pNtkProb ); Abc_NtkAddDummyPoNames( pNtkProb ); Abc_NtkAddDummyAssertNames( pNtkProb ); // make sure everything is okay with the network structure if ( !Abc_NtkDoCheck( pNtkProb ) ) { printf( "Seq_NtkImplementRetimingBackward: The internal network check has failed.\n" ); Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); Abc_NtkDelete( pNtkProb ); stmm_free_table( tTable ); Vec_IntFree( vValues ); return 0; } // check if conflict is found if ( RetValue ) { printf( "Seq_NtkImplementRetimingBackward: A top level conflict is detected. DC latch values are used.\n" ); Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); Abc_NtkDelete( pNtkProb ); stmm_free_table( tTable ); Vec_IntFree( vValues ); return 0; } // get the miter cone pNtkMiter = Abc_NtkCreateTarget( pNtkProb, pNtkProb->vCos, vValues ); Abc_NtkDelete( pNtkProb ); Vec_IntFree( vValues ); if ( fVerbose ) printf( "The number of ANDs in the AIG = %5d.\n", Abc_NtkNodeNum(pNtkMiter) ); // transform the miter into a logic network for efficient CNF construction // pNtkCnf = Abc_Ntk_Renode( pNtkMiter, 0, 100, 1, 0, 0 ); // Abc_NtkDelete( pNtkMiter ); pNtkCnf = pNtkMiter; // solve the miter clk = clock(); // RetValue = Abc_NtkMiterSat_OldAndRusty( pNtkCnf, 30, 0 ); RetValue = Abc_NtkMiterSat( pNtkCnf, (sint64)500000, (sint64)50000000, 0, 0, NULL, NULL ); if ( fVerbose ) if ( clock() - clk > 100 ) { PRT( "SAT solving time", clock() - clk ); } pModel = pNtkCnf->pModel; pNtkCnf->pModel = NULL; Abc_NtkDelete( pNtkCnf ); // analyze the result if ( RetValue == -1 || RetValue == 1 ) { Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); if ( RetValue == 1 ) printf( "Seq_NtkImplementRetimingBackward: The problem is unsatisfiable. DC latch values are used.\n" ); else printf( "Seq_NtkImplementRetimingBackward: The SAT problem timed out. DC latch values are used.\n" ); stmm_free_table( tTable ); return 0; } // set the values of the latches Abc_NtkRetimeSetInitialValues( pNtk, tTable, pModel ); stmm_free_table( tTable ); free( pModel ); return 1; }