text: /**CFile****************************************************************
  
    FileName    [fraSec.c]
  
    SystemName  [ABC: Logic synthesis and verification system.]
  
    PackageName [New FRAIG package.]
  
    Synopsis    [Performs SEC based on seq sweeping.]
  
    Author      [Alan Mishchenko]
    
    Affiliation [UC Berkeley]
  
    Date        [Ver. 1.0. Started - June 30, 2007.]
  
    Revision    [$Id: fraSec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
  
  ***********************************************************************/
  
  #include "fra.h"
  #include "aig/ioa/ioa.h"
  #include "proof/int/int.h"
  #include "proof/ssw/ssw.h"
  #include "aig/saig/saig.h"
  #include "bdd/bbr/bbr.h"
  #include "proof/pdr/pdr.h"
  
  ABC_NAMESPACE_IMPL_START
  
  
  ////////////////////////////////////////////////////////////////////////
  ///                        DECLARATIONS                              ///
  ////////////////////////////////////////////////////////////////////////
  
  ////////////////////////////////////////////////////////////////////////
  ///                     FUNCTION DEFINITIONS                         ///
  ////////////////////////////////////////////////////////////////////////
  
  /**Function*************************************************************
  
    Synopsis    []
  
    Description []
                 
    SideEffects []
  
    SeeAlso     []
  
  ***********************************************************************/
  void Fra_SecSetDefaultParams( Fra_Sec_t * p )
  {
      memset( p, 0, sizeof(Fra_Sec_t) );
      p->fTryComb          =       1;  // try CEC call as a preprocessing step
      p->fTryBmc           =       1;  // try BMC call as a preprocessing step 
      p->nFramesMax        =       4;  // the max number of frames used for induction
      p->nBTLimit          =    1000;  // conflict limit at a node during induction 
      p->nBTLimitGlobal    = 5000000;  // global conflict limit during induction
      p->nBTLimitInter     =   10000;  // conflict limit during interpolation
      p->nBddVarsMax       =     150;  // the limit on the number of registers in BDD reachability
      p->nBddMax           =   50000;  // the limit on the number of BDD nodes 
      p->nBddIterMax       = 1000000;  // the limit on the number of BDD iterations
      p->fPhaseAbstract    =       0;  // enables phase abstraction
      p->fRetimeFirst      =       1;  // enables most-forward retiming at the beginning
      p->fRetimeRegs       =       1;  // enables min-register retiming at the beginning
      p->fFraiging         =       1;  // enables fraiging at the beginning
      p->fInduction        =       1;  // enables the use of induction (signal correspondence)
      p->fInterpolation    =       1;  // enables interpolation
      p->fInterSeparate    =       0;  // enables interpolation for each outputs separately
      p->fReachability     =       1;  // enables BDD based reachability
      p->fReorderImage     =       1;  // enables variable reordering during image computation
      p->fStopOnFirstFail  =       1;  // enables stopping after first output of a miter has failed to prove
      p->fUseNewProver     =       0;  // enables new prover
      p->fUsePdr           =       1;  // enables PDR
      p->nPdrTimeout       =      60;  // enabled PDR timeout
      p->fSilent           =       0;  // disables all output
      p->fVerbose          =       0;  // enables verbose reporting of statistics
      p->fVeryVerbose      =       0;  // enables very verbose reporting  
      p->TimeLimit         =       0;  // enables the timeout
      // internal parameters
      p->fReportSolution   =       0;  // enables specialized format for reporting solution
  }
  
  /**Function*************************************************************
  
    Synopsis    []
  
    Description []
                 
    SideEffects []
  
    SeeAlso     []
  
  ***********************************************************************/
  int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult )
  {
      Ssw_Pars_t Pars2, * pPars2 = &Pars2;
      Fra_Ssw_t Pars, * pPars = &Pars;
      Fra_Sml_t * pSml;
      Aig_Man_t * pNew, * pTemp;
      int nFrames, RetValue, nIter;
      abctime clk, clkTotal = Abc_Clock();
      int TimeOut = 0;
      int fLatchCorr = 0;
      float TimeLeft = 0.0;
      pParSec->nSMnumber = -1;
  
      // try the miter before solving
      pNew = Aig_ManDupSimple( p );
      RetValue = Fra_FraigMiterStatus( pNew );
      if ( RetValue >= 0 )
          goto finish;
  
      // prepare parameters
      memset( pPars, 0, sizeof(Fra_Ssw_t) );
      pPars->fLatchCorr  = fLatchCorr;
      pPars->fVerbose = pParSec->fVeryVerbose;
      if ( pParSec->fVerbose )
      {
          printf( "Original miter:       Latches = %5d. Nodes = %6d.\n", 
              Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
      }
  //Aig_ManDumpBlif( pNew, "after.blif", NULL, NULL );
  
      // perform sequential cleanup
  clk = Abc_Clock();
      if ( pNew->nRegs )
      pNew = Aig_ManReduceLaches( pNew, 0 );
      if ( pNew->nRegs )
      pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 );
      if ( pParSec->fVerbose )
      {
          printf( "Sequential cleanup:   Latches = %5d. Nodes = %6d. ", 
              Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
      }
      RetValue = Fra_FraigMiterStatus( pNew );
      if ( RetValue >= 0 )
          goto finish;
  
      // perform phase abstraction
  clk = Abc_Clock();
      if ( pParSec->fPhaseAbstract )
      {
          extern Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose );
          pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); 
          pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); 
          pNew = Saig_ManPhaseAbstractAuto( pTemp = pNew, 0 );
          Aig_ManStop( pTemp );
          if ( pParSec->fVerbose )
          {
              printf( "Phase abstraction:    Latches = %5d. Nodes = %6d. ", 
                  Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
          }
      }
  
      // perform forward retiming
      if ( pParSec->fRetimeFirst && pNew->nRegs )
      {
  clk = Abc_Clock();
  //    pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
      pNew = Saig_ManRetimeForward( pTemp = pNew, 100, 0 );
      Aig_ManStop( pTemp );
      if ( pParSec->fVerbose )
      {
          printf( "Forward retiming:     Latches = %5d. Nodes = %6d. ", 
              Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
      }
      }
       
      // run latch correspondence
  clk = Abc_Clock();
      if ( pNew->nRegs )
      {
      pNew = Aig_ManDupOrdered( pTemp = pNew );
  //    pNew = Aig_ManDupDfs( pTemp = pNew );
      Aig_ManStop( pTemp );
  /*
      if ( RetValue == -1 && pParSec->TimeLimit )
      {
          TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
          TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
          if ( TimeLeft == 0.0 )
          {
              if ( !pParSec->fSilent )
                  printf( "Runtime limit exceeded.\n" );
              RetValue = -1;
              TimeOut = 1;
              goto finish;
          }
      }
  */
  
  //    pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 1000, 1, pParSec->fVeryVerbose, &nIter, TimeLeft );
  //Aig_ManDumpBlif( pNew, "ex.blif", NULL, NULL );
      Ssw_ManSetDefaultParamsLcorr( pPars2 );
      pNew = Ssw_LatchCorrespondence( pTemp = pNew, pPars2 );
      nIter = pPars2->nIters;
  
      // prepare parameters for scorr
      Ssw_ManSetDefaultParams( pPars2 );
  
      if ( pTemp->pSeqModel )
      {
          if ( !Saig_ManVerifyCex( pTemp, pTemp->pSeqModel ) )
              printf( "Fra_FraigSec(): Counter-example verification has FAILED.\n" );
          if ( Saig_ManPiNum(p) != Saig_ManPiNum(pTemp) )
              printf( "The counter-example is invalid because of phase abstraction.\n" );
          else
          {
          ABC_FREE( p->pSeqModel );
          p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) );
          ABC_FREE( pTemp->pSeqModel );
          }
      }
      if ( pNew == NULL )
      {
          if ( p->pSeqModel )
          {
              RetValue = 0;
              if ( !pParSec->fSilent )
              {
                  printf( "Networks are NOT EQUIVALENT after simulation.   " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
              }
              if ( pParSec->fReportSolution && !pParSec->fRecursive )
              {
              printf( "SOLUTION: FAIL       " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
              }
              Aig_ManStop( pTemp );
              return RetValue;
          }
          pNew = pTemp;
          RetValue = -1;
          TimeOut = 1;
          goto finish;
      }
      Aig_ManStop( pTemp );
  
      if ( pParSec->fVerbose )
      {
          printf( "Latch-corr (I=%3d):   Latches = %5d. Nodes = %6d. ", 
              nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
      }
      }
  /*
      if ( RetValue == -1 && pParSec->TimeLimit )
      {
          TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
          TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
          if ( TimeLeft == 0.0 )
          {
              if ( !pParSec->fSilent )
                  printf( "Runtime limit exceeded.\n" );
              RetValue = -1;
              TimeOut = 1;
              goto finish;
          }
      }
  */
      // perform fraiging
      if ( pParSec->fFraiging )
      {
  clk = Abc_Clock();
      pNew = Fra_FraigEquivence( pTemp = pNew, 100, 0 );
      Aig_ManStop( pTemp );
      if ( pParSec->fVerbose )
      {
          printf( "Fraiging:             Latches = %5d. Nodes = %6d. ", 
              Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
      }
      }
  
      if ( pNew->nRegs == 0 )
          RetValue = Fra_FraigCec( &pNew, 100000, 0 );
  
      RetValue = Fra_FraigMiterStatus( pNew );
      if ( RetValue >= 0 )
          goto finish;
  /*
      if ( RetValue == -1 && pParSec->TimeLimit )
      {
          TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
          TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
          if ( TimeLeft == 0.0 )
          {
              if ( !pParSec->fSilent )
                  printf( "Runtime limit exceeded.\n" );
              RetValue = -1;
              TimeOut = 1;
              goto finish;
          }
      }
  */
      // perform min-area retiming
      if ( pParSec->fRetimeRegs && pNew->nRegs )
      {
  //    extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
  clk = Abc_Clock();
      pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); 
      pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); 
  //        pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
      pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 );
      Aig_ManStop( pTemp );
      pNew = Aig_ManDupOrdered( pTemp = pNew );
      Aig_ManStop( pTemp );
      if ( pParSec->fVerbose )
      {
      printf( "Min-reg retiming:     Latches = %5d. Nodes = %6d. ", 
          Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
      }
      }
  
      // perform seq sweeping while increasing the number of frames
      RetValue = Fra_FraigMiterStatus( pNew );
      if ( RetValue == -1 && pParSec->fInduction )
      for ( nFrames = 1; nFrames <= pParSec->nFramesMax; nFrames *= 2 )
      {
  /*
          if ( RetValue == -1 && pParSec->TimeLimit )
          {
              TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
              TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
              if ( TimeLeft == 0.0 )
              {
                  if ( !pParSec->fSilent )
                      printf( "Runtime limit exceeded.\n" );
                  RetValue = -1;
                  TimeOut = 1;
                  goto finish;
              }
          }
  */ 
  
  clk = Abc_Clock();
          pPars->nFramesK = nFrames;
          pPars->TimeLimit = TimeLeft;
          pPars->fSilent = pParSec->fSilent;
  //        pNew = Fra_FraigInduction( pTemp = pNew, pPars );
  
          pPars2->nFramesK = nFrames;
          pPars2->nBTLimit = pParSec->nBTLimit;
          pPars2->nBTLimitGlobal = pParSec->nBTLimitGlobal;
  //        pPars2->nBTLimit = 1000 * nFrames;
  
          if ( RetValue == -1 && pPars2->nConflicts > pPars2->nBTLimitGlobal )
          {
              if ( !pParSec->fSilent )
                  printf( "Global conflict limit (%d) exceeded.\n", pPars2->nBTLimitGlobal );
              RetValue = -1;
              TimeOut = 1;
              goto finish;
          }
  
          Aig_ManSetRegNum( pNew, pNew->nRegs );
  //        pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 );
          if ( Aig_ManRegNum(pNew) > 0 )
              pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 );
          else
              pNew = Aig_ManDupSimpleDfs( pTemp = pNew );
  
          if ( pNew == NULL )
          {
              pNew = pTemp;
              RetValue = -1;
              TimeOut = 1;
              goto finish;
          }
  
  //        printf( "Total conflicts = %d.\n", pPars2->nConflicts );
  
          Aig_ManStop( pTemp );
          RetValue = Fra_FraigMiterStatus( pNew );
          if ( pParSec->fVerbose )
          { 
              printf( "K-step (K=%2d,I=%3d):  Latches = %5d. Nodes = %6d. ", 
                  nFrames, pPars2->nIters, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
          }
          if ( RetValue != -1 )
              break;
  
          // perform retiming
  //        if ( pParSec->fRetimeFirst && pNew->nRegs )
          if ( pNew->nRegs )
          {
  //        extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
  clk = Abc_Clock();
          pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); 
          pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); 
  //        pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
          pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 );
          Aig_ManStop( pTemp );
          pNew = Aig_ManDupOrdered( pTemp = pNew );
          Aig_ManStop( pTemp );
          if ( pParSec->fVerbose )
          {
              printf( "Min-reg retiming:     Latches = %5d. Nodes = %6d. ", 
                  Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
          }
          }  
  
          if ( pNew->nRegs )
              pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 );
  
          // perform rewriting
  clk = Abc_Clock();
          pNew = Aig_ManDupOrdered( pTemp = pNew );
          Aig_ManStop( pTemp );
  //        pNew = Dar_ManRewriteDefault( pTemp = pNew );
          pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 ); 
          Aig_ManStop( pTemp );
          if ( pParSec->fVerbose )
          {
              printf( "Rewriting:            Latches = %5d. Nodes = %6d. ", 
                  Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
          } 
  
          // perform sequential simulation
          if ( pNew->nRegs )
          {
  clk = Abc_Clock();
          pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000), 1  ); 
          if ( pParSec->fVerbose )
          {
              printf( "Seq simulation  :     Latches = %5d. Nodes = %6d. ", 
                  Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
  ABC_PRT( "Time", Abc_Clock() - clk );
          }
          if ( pSml->fNonConstOut )
          {
              pNew->pSeqModel = Fra_SmlGetCounterExample( pSml );
              // transfer to the original manager
              if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) )
                  printf( "The counter-example is invalid because of phase abstraction.\n" );
              else
              {
              ABC_FREE( p->pSeqModel );
              p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) );
              ABC_FREE( pNew->pSeqModel );
              }
  
              Fra_SmlStop( pSml );
              Aig_ManStop( pNew );
              RetValue = 0;
              if ( !pParSec->fSilent )
              {
                  printf( "Networks are NOT EQUIVALENT after simulation.   " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
              }
              if ( pParSec->fReportSolution && !pParSec->fRecursive )
              {
              printf( "SOLUTION: FAIL       " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
              }
              return RetValue;
          }
          Fra_SmlStop( pSml );
          }
      }
  
      // get the miter status
      RetValue = Fra_FraigMiterStatus( pNew );
  
      // try interplation
  clk = Abc_Clock();
      Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) );
      if ( pParSec->fInterpolation && RetValue == -1 && Aig_ManRegNum(pNew) > 0 )
      {
          Inter_ManParams_t Pars, * pPars = &Pars;
          int Depth;
          ABC_FREE( pNew->pSeqModel );
          Inter_ManSetDefaultParams( pPars );
  //        pPars->nBTLimit = 100;
          pPars->nBTLimit = pParSec->nBTLimitInter;
          pPars->fVerbose = pParSec->fVeryVerbose;
          if ( Saig_ManPoNum(pNew) == 1 )
          {
              RetValue = Inter_ManPerformInterpolation( pNew, pPars, &Depth );
          }
          else if ( pParSec->fInterSeparate )
          {
              Abc_Cex_t * pCex = NULL;
              Aig_Man_t * pTemp, * pAux;
              Aig_Obj_t * pObjPo;
              int i, Counter = 0;
              Saig_ManForEachPo( pNew, pObjPo, i )
              { 
                  if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pNew) )
                      continue;
                  if ( pPars->fVerbose )
                      printf( "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pNew) );
                  pTemp = Aig_ManDupOneOutput( pNew, i, 1 );
                  pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 );
                  Aig_ManStop( pAux );
                  if ( Saig_ManRegNum(pTemp) > 0 )
                  {
                      RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &Depth );
                      if ( pTemp->pSeqModel )
                      {
                          pCex = p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) );
                          pCex->iPo = i;
                          Aig_ManStop( pTemp );
                          break;
                      }
                      // if solved, remove the output
                      if ( RetValue == 1 )
                      {
                          Aig_ObjPatchFanin0( pNew, pObjPo, Aig_ManConst0(pNew) );
      //                    printf( "Output %3d : Solved ", i );
                      }
                      else
                      {
                          Counter++;
      //                    printf( "Output %3d : Undec  ", i );
                      }
                  }
                  else
                      Counter++;
  //                Aig_ManPrintStats( pTemp );
                  Aig_ManStop( pTemp );
                  printf( "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pNew) );
              }
              Aig_ManCleanup( pNew );
              if ( pCex == NULL )
              {
                  printf( "Interpolation left %d (out of %d) outputs unsolved              \n", Counter, Saig_ManPoNum(pNew) );
                  if ( Counter )
                      RetValue = -1;
              }
              pNew = Aig_ManDupUnsolvedOutputs( pTemp = pNew, 1 );
              Aig_ManStop( pTemp );
              pNew = Aig_ManScl( pTemp = pNew, 1, 1, 0, -1, -1, 0, 0 );
              Aig_ManStop( pTemp );
          }
          else
          {
              Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew );
              RetValue = Inter_ManPerformInterpolation( pNewOrpos, pPars, &Depth );
              if ( pNewOrpos->pSeqModel )
              {
                  Abc_Cex_t * pCex;
                  pCex = pNew->pSeqModel = pNewOrpos->pSeqModel; pNewOrpos->pSeqModel = NULL;
                  pCex->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel );
              }
              Aig_ManStop( pNewOrpos );
          }
  
          if ( pParSec->fVerbose )
          {
          if ( RetValue == 1 )
              printf( "Property proved using interpolation.  " );
          else if ( RetValue == 0 )
              printf( "Property DISPROVED in frame %d using interpolation.  ", Depth );
          else if ( RetValue == -1 )
              printf( "Property UNDECIDED after interpolation.  " );
          else
              assert( 0 ); 
  ABC_PRT( "Time", Abc_Clock() - clk );
          }
      }
  
      // try reachability analysis
      if ( pParSec->fReachability && RetValue == -1 && Aig_ManRegNum(pNew) > 0 && Aig_ManRegNum(pNew) < pParSec->nBddVarsMax )
      {
          Saig_ParBbr_t Pars, * pPars = &Pars;
          Bbr_ManSetDefaultParams( pPars );
          pPars->TimeLimit     = 0;
          pPars->nBddMax       = pParSec->nBddMax;
          pPars->nIterMax      = pParSec->nBddIterMax;
          pPars->fPartition    = 1;
          pPars->fReorder      = 1;
          pPars->fReorderImage = 1;
          pPars->fVerbose      = 0;
          pPars->fSilent       = pParSec->fSilent;
          pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); 
          pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); 
          RetValue = Aig_ManVerifyUsingBdds( pNew, pPars );
      }
  
      // try PDR
      if ( pParSec->fUsePdr && RetValue == -1 && Aig_ManRegNum(pNew) > 0 )
      {
          Pdr_Par_t Pars, * pPars = &Pars;
          Pdr_ManSetDefaultParams( pPars );
          pPars->nTimeOut = pParSec->nPdrTimeout;
          pPars->fVerbose = pParSec->fVerbose;
          if ( pParSec->fVerbose )
              printf( "Running property directed reachability...\n" );
          RetValue = Pdr_ManSolve( pNew, pPars );
          if ( pNew->pSeqModel )
              pNew->pSeqModel->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel );
      }
  
  finish:
      // report the miter
      if ( RetValue == 1 )
      {
          if ( !pParSec->fSilent )
          {
              printf( "Networks are equivalent.   " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
          }
          if ( pParSec->fReportSolution && !pParSec->fRecursive )
          {
          printf( "SOLUTION: PASS       " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
          }
      }
      else if ( RetValue == 0 )
      {
          if ( pNew->pSeqModel == NULL )
          {
              int i;
              // if the CEX is not derives, it is because tricial CEX should be assumed
              pNew->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pNew), pNew->nTruePis, 1 );
              // if the CEX does not work, we need to change PIs to 1 because 
              // the only way it can happen is when a PO is equal to a PI...
              if ( Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ) == -1 )
                  for ( i = 0; i < pNew->nTruePis; i++ )
                      Abc_InfoSetBit( pNew->pSeqModel->pData, i );
          }
          if ( !pParSec->fSilent )
          {
              printf( "Networks are NOT EQUIVALENT.   " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
          }
          if ( pParSec->fReportSolution && !pParSec->fRecursive )
          {
          printf( "SOLUTION: FAIL       " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
          }
      }
      else 
      {
          ///////////////////////////////////
          // save intermediate result
          extern void Abc_FrameSetSave1( void * pAig );
          Abc_FrameSetSave1( Aig_ManDupSimple(pNew) );
          ///////////////////////////////////
          if ( !pParSec->fSilent )
          {
              printf( "Networks are UNDECIDED.   " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
          }
          if ( pParSec->fReportSolution && !pParSec->fRecursive )
          {
          printf( "SOLUTION: UNDECIDED  " );
  ABC_PRT( "Time", Abc_Clock() - clkTotal );
          }
          if ( !TimeOut && !pParSec->fSilent )
          {
              static int Counter = 1;
              char pFileName[1000];
              pParSec->nSMnumber = Counter;
              sprintf( pFileName, "sm%02d.aig", Counter++ );
              Ioa_WriteAiger( pNew, pFileName, 0, 0 );
              printf( "The unsolved reduced miter is written into file \"%s\".\n", pFileName );
          }
      }
      if ( pNew->pSeqModel )
      {
          if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) )
              printf( "The counter-example is invalid because of phase abstraction.\n" );
          else
          {
          ABC_FREE( p->pSeqModel );
          p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) );
          ABC_FREE( pNew->pSeqModel );
          }
      }
      if ( ppResult != NULL )
          *ppResult = Aig_ManDupSimpleDfs( pNew );
      if ( pNew )
          Aig_ManStop( pNew );
      return RetValue;
  }
  
  ////////////////////////////////////////////////////////////////////////
  ///                       END OF FILE                                ///
  ////////////////////////////////////////////////////////////////////////
  
  
  ABC_NAMESPACE_IMPL_END
  
  