Ejemplo n.º 1
0
V3MPDRCube* const
V3VrfMPDR::recursiveBlockCube(V3MPDRCube* const badCube) {
   // Create a Queue for Blocking Cubes
   V3BucketList<V3MPDRCube*> badQueue(getPDRFrame());
   assert (badCube); badQueue.add(getPDRDepth(), badCube);
   // Block Cubes from the Queue
   V3MPDRTimedCube baseCube, generalizedCube;
   while (badQueue.pop(baseCube.first, baseCube.second)) {
      assert (baseCube.first < getPDRFrame());
      if (!baseCube.first) {
         // Clear All Cubes in badQueue before Return
         V3Set<const V3MPDRCube*>::Set traceCubes; traceCubes.clear();
         const V3MPDRCube* traceCube = baseCube.second;
         while (true) {
            traceCubes.insert(traceCube); if (_pdrBad == traceCube) break;
            traceCube = traceCube->getNextCube();
         }
         while (badQueue.pop(generalizedCube.first, generalizedCube.second)) {
            if (traceCubes.end() == traceCubes.find(generalizedCube.second)) delete generalizedCube.second;
         }
         return baseCube.second;  // A Cube cannot be blocked by R0 --> Cex
      }
      if (!isBlocked(baseCube)) {
         assert (!existInitial(baseCube.second->getState()));
         // Check Reachability : SAT (R ^ ~cube ^ T ^ cube')
         if (checkReachability(baseCube.first, baseCube.second->getState())) {  // SAT, Not Blocked Yet
            if (profileON()) _ternaryStat->start();
            generalizedCube.second = extractModel(baseCube.second, baseCube.first - 1);
            if (profileON()) _ternaryStat->end();
            badQueue.add(baseCube.first - 1, generalizedCube.second);  // This Cube should be blocked in previous frame
            badQueue.add(baseCube.first, baseCube.second);  // This Cube has not yet been blocked (postpone to future)
         }
         else {  // UNSAT, Blocked
            bool satGen = true;
            while (true) {
               if (profileON()) _generalStat->start();
               generalizedCube.first = baseCube.first;
               generalizedCube.second = new V3MPDRCube(*(baseCube.second));
               generalization(generalizedCube);  // Generalization
               if (profileON()) _generalStat->end();
               addBlockedCube(generalizedCube);  // Record this Cube that is bad and to be blocked
               // I found Niklas Een has modified the original IWLS paper and alter the line below
               // However, I suggest the alteration restricts PDR (i.e. fold-free) and does not help
               if (satGen && (baseCube.first < getPDRDepth()) && (generalizedCube.first < getPDRFrame()))
                  badQueue.add(baseCube.first + 1, baseCube.second);
               //if ((baseCube.first < getPDRDepth()) && (generalizedCube.first < getPDRDepth()))
               //   badQueue.add(generalizedCube.first + 1, baseCube.second);
               if (!isForwardSATGen() || getPDRDepth() <= generalizedCube.first) break;
               baseCube.second = forwardModel(generalizedCube.second); if (!baseCube.second) break;
               baseCube.first = baseCube.first + 1; satGen = false;
               if (checkReachability(baseCube.first, baseCube.second->getState())) break;
            }
         }
      }
      //else delete baseCube.second;
   }
   return 0;
}
Ejemplo n.º 2
0
void
V3VrfMPDR::recycleSolver() {
   // Initialize Solver
   assert (!_pdrActCount); initializeSolver();
   // Initialize Frames
   _pdrFrame[0]->setActivator(_pdrSvr->setImplyInit());
   for (uint32_t i = 1; i < _pdrFrame.size(); ++i) addFrameInfoToSolver(i);
   // Check Shared Invariants
   if (_sharedInv) {
      V3NetTable sharedInv; _sharedInv->getInv(sharedInv);
      for (uint32_t i = 0; i < sharedInv.size(); ++i) {
         V3MPDRCube* const inv = new V3MPDRCube(0); assert (inv);
         inv->setState(sharedInv[i]); addBlockedCube(make_pair(getPDRFrame(), inv));
      }
   }
   _pdrSvr->simplify();
}
Ejemplo n.º 3
0
V3SIPDRCube* const
V3SVrfIPDR::recursiveBlockCube2(V3SIPDRCube* const badCube) {
   //unfolding_depth
   uint32_t d = _decompDepth;
   //cerr << "_decompDepth : " << d << endl;
   if(heavy_debug) cerr << "\n\n\nrecursiveBlockCube2\n";
   // Create a Queue for Blocking Cubes
   V3BucketList<V3SIPDRCube*> badQueue(getPDRFrame());
   assert (badCube); badQueue.add(getPDRDepth(), badCube);

   vector<uint32_t> v;
   for (unsigned i = 0; i <= getPDRDepth(); ++i){
     v.push_back(0);
   }
   // Block Cubes from the Queue
   V3SIPDRTimedCube baseCube, generalizedCube;
   while (badQueue.pop(baseCube.first, baseCube.second)) {
      v[baseCube.first]++;
      if(heavy_debug){
         cerr << "\nPoped: baseCube frame: " << baseCube.first <<  ", cube: ";
         printState( baseCube.second->getState() );
      }
      assert (baseCube.first < getPDRFrame());
      if (!baseCube.first) {
         // Clear All Cubes in badQueue before Return
         V3Set<const V3SIPDRCube*>::Set traceCubes; traceCubes.clear();
         const V3SIPDRCube* traceCube = baseCube.second;
         while (true) {
            traceCubes.insert(traceCube); if (_pdrBad == traceCube) break;
            traceCube = traceCube->getNextCube();
         }
         while (badQueue.pop(generalizedCube.first, generalizedCube.second)) {
            if (traceCubes.end() == traceCubes.find(generalizedCube.second)) delete generalizedCube.second;
         }
         return baseCube.second;  // A Cube cannot be blocked by R0 --> Cex
      }
      if (!isBlocked(baseCube)) {
         assert (!existInitial2(baseCube.second->getState()));
         // Check Reachability : SAT (R ^ ~cube ^ T ^ cube')

         if( baseCube.first >= d && v[baseCube.first] > 10){
         //if( false ){
            if(checkReachability2(baseCube.first - d + 1, baseCube.second->getState(),false)){
               if(heavy_debug){
                  cerr << "SAT, generalizing... Frame before gen:" << baseCube.first << " Cube before gen:";
                  printState(baseCube.second->getState());
               }
               if (profileON()) _ternaryStat->start();
               generalizedCube.second = extractModel2(baseCube.first - d, baseCube.second);
               if (profileON()) _ternaryStat->end();
               if(heavy_debug){
                  cerr << "SAT, pushing to queue, Frame after gen:" << baseCube.first-d << " Cube after gen:";
                  printState(generalizedCube.second->getState());
               }
               badQueue.add(baseCube.first - d, generalizedCube.second);  // This Cube should be blocked in previous frame
               badQueue.add(baseCube.first, baseCube.second);  // This Cube has not yet been blocked (postpone to future)
               //cout << "WOW" << endl;
               continue;
            }
         }


         if (checkReachability(baseCube.first, baseCube.second->getState())) {  // SAT, Not Blocked Yet
            if(heavy_debug){
               cerr << "SAT, generalizing... Frame before gen:" << baseCube.first << " Cube before gen:";
               printState(baseCube.second->getState());
            }
            if (profileON()) _ternaryStat->start();
            generalizedCube.second = extractModel(baseCube.first - 1, baseCube.second);
            if (profileON()) _ternaryStat->end();
            if(heavy_debug){
               cerr << "SAT, pushing to queue, Frame after gen:" << baseCube.first-1 << " Cube after gen:";
               printState(generalizedCube.second->getState());
            }
            badQueue.add(baseCube.first - 1, generalizedCube.second);  // This Cube should be blocked in previous frame
            badQueue.add(baseCube.first, baseCube.second);  // This Cube has not yet been blocked (postpone to future)
         }
         else {  // UNSAT, Blocked
            if (profileON()) _generalStat->start();
            generalizedCube.first = baseCube.first;
            generalizedCube.second = new V3SIPDRCube(*(baseCube.second));
            generalization2(generalizedCube);  // Generalization
            if (profileON()) _generalStat->end();
            addBlockedCube(generalizedCube);  // Record this Cube that is bad and to be blocked
            if ((baseCube.first < getPDRDepth()) && (generalizedCube.first < getPDRFrame()))
               badQueue.add(baseCube.first + 1, baseCube.second);
         }
      }
   }
   return 0;
}
Ejemplo n.º 4
0
const bool
V3VrfMPDR::propagateCubes() {
   if (profileON()) _propagateStat->start();
   // Check Each Frame if some Cubes can be Further Propagated
   for (uint32_t i = 1; i < getPDRDepth(); ++i) {
      const V3MPDRCubeList& cubeList = _pdrFrame[i]->getCubeList();
#ifdef V3_MPDR_USE_PROPAGATE_BACKWARD
      // Backward Version  (Check from rbegin() to rend())
      uint32_t candidates = 1; V3MPDRCubeList::const_iterator it;
      while (candidates <= cubeList.size()) {
         it = cubeList.begin(); for (uint32_t j = candidates; j < cubeList.size(); ++j) ++it;
#else
      // Forward Version  (Check from begin() to end())
      V3MPDRCubeList::const_iterator it = cubeList.begin();
      while (it != cubeList.end()) {
#endif
         // Check if this cube can be pushed forward (closer to All Frame)
         if (!checkReachability(i + 1, (*it)->getState(), false)) {
            V3MPDRTimedCube cube = make_pair(i + 1, new V3MPDRCube(*(*it)));
            // Remove Cubes in the Next Frame that can be Subsumed by the cube
            removeFromProof(cube); _pdrFrame[i + 1]->removeSubsumed(cube.second);
            // Remove cubes in this frame that can be subsumed by the cube
            _pdrFrame[i]->removeSubsumed(cube.second, ++it);
            // Block this cube again at higher frames
            addBlockedCube(cube);
         }
         else {
            // Remove cubes in this frame that can be subsumed by the cube
            _pdrFrame[i]->removeSubsumed(*it, it);
#ifdef V3_MPDR_USE_PROPAGATE_BACKWARD
            // Backward Version  (Check from rbegin() to rend())
            ++candidates;
#else
            // Forward Version  (Check from begin() to end())
            ++it;
#endif
         }
      }
      // Check if Any Remaining Cubes in this Frame can be Subsumed
      _pdrFrame[i]->removeSelfSubsumed();
      /*
      // Debug : Check Real Containment
      for (uint32_t j = i + 1; j < _pdrFrame.size(); ++j) {
         it = _pdrFrame[j]->getCubeList().begin();
         while (it != _pdrFrame[j]->getCubeList().end()) {
            assert (!checkReachability(i, (*it)->getState()));
            ++it;
         }
      }
      */
      // Check Inductive Invariant
      if (!_pdrFrame[i]->getCubeList().size()) {
         if (profileON()) _propagateStat->end();
         return true;
      }
   }
   // Check if Any Remaining Cubes in the Latest Frame can be Subsumed
   _pdrFrame[getPDRDepth()]->removeSelfSubsumed(); //_pdrFrame[getPDRFrame()]->removeSelfSubsumed();
   /*
   // Debug : Check Real Containment
   for (uint32_t j = getPDRDepth() + 1; j < _pdrFrame.size(); ++j) {
      V3MPDRCubeList::const_iterator it = _pdrFrame[j]->getCubeList().begin();
      while (it != _pdrFrame[j]->getCubeList().end()) {
         assert (!checkReachability(getPDRDepth(), (*it)->getState()));
         ++it;
      }
   }
   */
   if (profileON()) _propagateStat->end();
   return false;
}
#else
const bool
V3VrfMPDR::propagateCubes() {
   if (profileON()) _propagateStat->start();
   // Check Each Frame if some Cubes can be Further Propagated
   for (uint32_t i = 1; i < getPDRDepth(); ++i) {
      const V3MPDRCubeList& cubeList = _pdrFrame[i]->getCubeList();
#ifdef V3_MPDR_USE_PROPAGATE_BACKWARD
      // Backward Version  (Check from rbegin() to rend())
      uint32_t candidates = 1; V3MPDRCubeList::const_iterator it;
      while (candidates <= cubeList.size()) {
         it = cubeList.begin(); for (uint32_t j = candidates; j < cubeList.size(); ++j) ++it;
#else
      // Forward Version  (Check from begin() to end())
      V3MPDRCubeList::const_iterator it = cubeList.begin();
      while (it != cubeList.end()) {
#endif
         // Check if this cube can be pushed forward (closer to All Frame)
         if (!checkReachability(i + 1, (*it)->getState(), false)) {
            V3MPDRTimedCube cube = make_pair(i + 1, new V3MPDRCube(*(*it)));
            // Block this cube again at higher frames
            removeFromProof(cube); addBlockedCube(cube);
            // Remove blocked cubes in lower frames that can be subsumed by the cube
            for (uint32_t j = 1; j < i; ++j) _pdrFrame[j]->removeSubsumed(cube.second);
            // Remove Cubes in this Frame that can be Subsumed by the cube
            _pdrFrame[i]->removeSubsumed(cube.second, ++it);
            // NOTE: Need not to recover iterator after subsumption (set.erase)
            //       the iterator it will point to the next candidate
         }
         else {
            // Remove blocked cubes in lower frames that can be subsumed by the cube
            for (uint32_t j = 1; j < i; ++j) _pdrFrame[j]->removeSubsumed(*it);
#ifdef V3_MPDR_USE_PROPAGATE_BACKWARD
            // Backward Version  (Check from rbegin() to rend())
            ++candidates;
#else
            // Forward Version  (Check from begin() to end())
            ++it;
#endif
         }
      }
      // Check if Any Remaining Cubes in this Frame can be Subsumed
      _pdrFrame[i]->removeSelfSubsumed();
      // Check Inductive Invariant
      for (uint32_t j = 1; j <= i; ++j) {
         if (!_pdrFrame[j]->getCubeList().size()) {
            if (profileON()) _propagateStat->end();
            return true;
         }
      }
   }
   // Check if Any Remaining Cubes in these Frames can be Subsumed
   _pdrFrame[getPDRDepth()]->removeSelfSubsumed(); _pdrFrame[getPDRFrame()]->removeSelfSubsumed();
   if (profileON()) _propagateStat->end();
   return false;
}
#endif

// PDR Auxiliary Functions
const bool
V3VrfMPDR::checkReachability(const uint32_t& frame, const V3NetVec& cubeState, const bool& extend) {
   assert (frame > 0); assert (frame <= getPDRFrame());
   // Check if Recycle is Triggered
   if (!_pdrActCount) recycleSolver();
   // Assume R
   _pdrSvr->assumeRelease(); assumeReachability((frame == getPDRFrame()) ? frame : frame - 1);
   // Assume cube'
   addCubeToSolver(cubeState, 1);
   for (uint32_t i = 0; i < cubeState.size(); ++i)
      _pdrSvr->assumeProperty(_pdrSvr->getFormula(_vrfNtk->getLatch(cubeState[i].id), 1), cubeState[i].cp);
   if (extend) {
      // Assume ~cube
      addCubeToSolver(cubeState, 0);
      V3SvrDataVec blockCube; blockCube.clear(); blockCube.reserve(cubeState.size()); size_t fId;
      for (uint32_t i = 0; i < cubeState.size(); ++i) {
         fId = _pdrSvr->getFormula(_vrfNtk->getLatch(cubeState[i].id), 0);
         blockCube.push_back(cubeState[i].cp ? fId : _pdrSvr->getNegFormula(fId));
      }
      _pdrSvrData = _pdrSvr->setImplyUnion(blockCube);
      assert (_pdrSvrData); _pdrSvr->assumeProperty(_pdrSvrData);
      // Check Reachability by SAT Calling
      if (profileON()) _solveStat->start();
      _pdrSvr->simplify();
      const bool result = _pdrSvr->assump_solve();
      if (profileON()) _solveStat->end();
      _pdrSvr->assertProperty(_pdrSvr->getNegFormula(_pdrSvrData));  // Invalidate ~cube in future solving
      --_pdrActCount; return result;
   }
   else {
      if (profileON()) _solveStat->start();
      _pdrSvr->simplify();
      const bool result = _pdrSvr->assump_solve();
      if (profileON()) _solveStat->end();
      return result;
   }
}

const bool
V3VrfMPDR::isBlocked(const V3MPDRTimedCube& timedCube) {
   // Check if cube has already been blocked by R (at specified frame)
   // Perform Subsumption Check : cube implies some C in R (at specified frame)
   for (uint32_t i = timedCube.first; i < _pdrFrame.size(); ++i) 
      if (_pdrFrame[i]->subsumes(timedCube.second)) return true;
   ///*
   // Check by SAT
   _pdrSvr->assumeRelease(); assumeReachability(timedCube.first);
   const V3NetVec& state = timedCube.second->getState(); addCubeToSolver(state, 0);
   for (uint32_t i = 0; i < state.size(); ++i)
      _pdrSvr->assumeProperty(_pdrSvr->getFormula(_vrfNtk->getLatch(state[i].id), 0), state[i].cp);
   if (profileON()) _solveStat->start();
   const bool result = _pdrSvr->assump_solve();
   if (profileON()) _solveStat->end();
   return !result;
   //*/
   //return false;
}

const bool
V3VrfMPDR::existInitial(const V3NetVec& state) {
   for (uint32_t i = 0; i < state.size(); ++i) {
      assert (state[i].id < _pdrInitConst.size());
      assert (state[i].id < _pdrInitValue.size());
      if (_pdrInitConst[state[i].id] && (_pdrInitValue[state[i].id] ^ state[i].cp)) return false;
   }
   return true;
}

void
V3VrfMPDR::assumeReachability(const unsigned& k) {
   uint32_t i = _pdrFrame.size();
   while (i-- > k) _pdrSvr->assumeProperty(_pdrFrame[i]->getActivator());
}
Ejemplo n.º 5
0
/* ---------------------------------------------------------------------------------------------------- *\
isIncKeepLastReachability(): If the last result is unsat, put the inductive invariant into the last frame.
isIncContinueOnLastSolver(): Reset the solver.
\* ---------------------------------------------------------------------------------------------------- */
void
V3VrfMPDR::startVerify(const uint32_t& p) {
vrfRestart: 
   // Check Shared Results
   if (_sharedBound && V3NtkUD == _sharedBound->getBound(p)) return;
   
   // Clear Verification Results
   clearResult(p); if (profileON()) _totalStat->start();
   
   // Consistency Check
   consistencyCheck(); assert (!_constr.size());
   if (!reportUnsupportedInitialState()) return;
   
   // Initialize Backup Frames
   for (uint32_t i = 0; i < _pdrBackup.size(); ++i) delete _pdrBackup[i]; _pdrBackup.clear();
   if (_pdrFrame.size()) {
      if (isIncKeepLastReachability()) {
         // Backup frames in the order: ..., 2, 1, INF
         assert (_pdrFrame.size() > 1); _pdrBackup.reserve(_pdrFrame.size() - 1);
         for (uint32_t i = _pdrFrame.size() - 2; i > 0; --i) _pdrBackup.push_back(_pdrFrame[i]);
         _pdrBackup.push_back(_pdrFrame.back()); delete _pdrFrame[0];
      }
      else { for (uint32_t i = 0; i < _pdrFrame.size(); ++i) delete _pdrFrame[i]; } _pdrFrame.clear();
   }

   // Initialize Other Members
   if (!isIncKeepLastReachability()) _pdrPriority.clear(); _pdrActCount = 0;
   if (_pdrBad) delete _pdrBad; _pdrBad = 0; if (_pdrGen) delete _pdrGen; _pdrGen = 0;
   if (dynamic_cast<V3BvNtk*>(_vrfNtk)) {
      _pdrGen = new V3AlgBvGeneralize(_handler); assert (_pdrGen);
      _pdrSim = dynamic_cast<V3AlgBvSimulate*>(_pdrGen); assert (_pdrSim);
   }
   else {
      _pdrGen = new V3AlgAigGeneralize(_handler); assert (_pdrGen);
      _pdrSim = dynamic_cast<V3AlgAigSimulate*>(_pdrGen); assert (_pdrSim);
   }
   V3NetVec simTargets(1, _vrfNtk->getOutput(p)); _pdrSim->reset(simTargets);

   // Initialize Pattern Input Size
   assert (p < _result.size()); assert (p < _vrfNtk->getOutputSize());
   const V3NetId& pId = _vrfNtk->getOutput(p); assert (V3NetUD != pId);
   _pdrSize = _vrfNtk->getInputSize() + _vrfNtk->getInoutSize();

   // Initialize Parameters
   const string flushSpace = string(100, ' ');
   uint32_t proved = V3NtkUD, fired = V3NtkUD;
   struct timeval inittime, curtime; gettimeofday(&inittime, NULL);
   
   // Initialize Signal Priority List
   if (_pdrPriority.size() != _vrfNtk->getLatchSize()) _pdrPriority.resize(_vrfNtk->getLatchSize(), 0);

   // Initialize Solver
   if (_pdrSvr && !isIncContinueOnLastSolver()) { delete _pdrSvr; _pdrSvr = 0; } initializeSolver();

   // Initialize Bad Cube
   _pdrBad = new V3MPDRCube(0); assert (_pdrBad); _pdrBad->setState(V3NetVec(1, pId));

   // Initialize Frame 0
   if (_vrfNtk->getLatchSize()) _pdrFrame.push_back(new V3MPDRFrame(_pdrSvr->setImplyInit()));  // R0 = I0
   else _pdrFrame.push_back(new V3MPDRFrame(_pdrSvr->reserveFormula()));
   assert (_pdrFrame.back()->getActivator()); assert (_pdrFrame.size() == 1);

   // Initialize Frame INF
   if (_pdrBackup.size()) { _pdrFrame.push_back(_pdrBackup.back()); _pdrBackup.pop_back(); addFrameInfoToSolver(1); }
   else _pdrFrame.push_back(new V3MPDRFrame(_pdrSvr->reserveFormula()));
   assert (_pdrFrame.back()->getActivator()); assert (_pdrFrame.size() == 2);

   // Check Shared Invariants
   if (_sharedInv) {
      V3NetTable sharedInv; _sharedInv->getInv(sharedInv);
      for (uint32_t i = 0; i < sharedInv.size(); ++i) {
         V3MPDRCube* const inv = new V3MPDRCube(0); assert (inv);
         inv->setState(sharedInv[i]); addBlockedCube(make_pair(getPDRFrame(), inv));
      }
   }

   // Continue on the Last Depth
   while (_pdrBackup.size() && (getIncLastDepthToKeepGoing() > getPDRFrame())) {
      _pdrFrame.push_back(_pdrFrame.back());  // Keep frame INF the last frame
      _pdrFrame[_pdrFrame.size() - 2] = _pdrBackup.back(); _pdrBackup.pop_back();
      addFrameInfoToSolver(_pdrFrame.size() - 2);
   }

   // Start PDR Based Verification
   V3MPDRCube* badCube = 0;
   while (true) {
      // Check Time Bounds
      gettimeofday(&curtime, NULL);
      if (_maxTime < getTimeUsed(inittime, curtime)) break;
      // Check Shared Results
      if (_sharedBound && (V3NtkUD == _sharedBound->getBound(p))) break;
      // Check Shared Networks
      if (_sharedNtk) {
         V3NtkHandler* const sharedNtk = _sharedNtk->getNtk(_handler);
         if (sharedNtk) {
            setIncKeepLastReachability(true); setIncContinueOnLastSolver(false); setIncLastDepthToKeepGoing(getPDRDepth());
            _handler = sharedNtk; _vrfNtk = sharedNtk->getNtk(); goto vrfRestart;
         }
      }
      // Find a Bad Cube as Initial Proof Obligation
      badCube = getInitialObligation();  // SAT(R ^ T ^ !p)
      if (!badCube) {
         if (!isIncKeepSilent() && intactON()) {
            if (!endLineON()) Msg(MSG_IFO) << "\r" + flushSpace + "\r";
            Msg(MSG_IFO) << setw(3) << left << getPDRDepth() << " :";
            const uint32_t j = (_pdrFrame.size() > 25) ? _pdrFrame.size() - 25 : 0; if (j) Msg(MSG_IFO) << " ...";
            for (uint32_t i = j; i < _pdrFrame.size(); ++i) 
               Msg(MSG_IFO) << " " << _pdrFrame[i]->getCubeList().size();
            if (svrInfoON()) { Msg(MSG_IFO) << "  ("; _pdrSvr->printInfo(); Msg(MSG_IFO) << ")"; }
            Msg(MSG_IFO) << endl;  // Always Endline At the End of Each Frame
         }
         if (_sharedBound) _sharedBound->updateBound(p, getPDRFrame());
         // Push New Frame
         _pdrFrame.push_back(_pdrFrame.back());  // Renders F Infinity to be the last in _pdrFrame
         if (_pdrBackup.size()) {
            _pdrFrame[_pdrFrame.size() - 2] = _pdrBackup.back(); _pdrBackup.pop_back();
            addFrameInfoToSolver(_pdrFrame.size() - 2);
         }
         else _pdrFrame[_pdrFrame.size() - 2] = new V3MPDRFrame(_pdrSvr->reserveFormula());  // New Frame
         if (propagateCubes()) { proved = getPDRDepth(); break; }
         if (_maxDepth <= (getPDRFrame() - 1)) break;
      }
      else {
         badCube = recursiveBlockCube(badCube);
         if (badCube) { fired = getPDRDepth(); break; }
         // Interactively Show the Number of Bad Cubes in Frames
         if (!isIncKeepSilent() && intactON()) {
            if (!endLineON()) Msg(MSG_IFO) << "\r" + flushSpace + "\r";
            Msg(MSG_IFO) << setw(3) << left << getPDRDepth() << " :";
            const uint32_t j = (_pdrFrame.size() > 25) ? _pdrFrame.size() - 25 : 0; if (j) Msg(MSG_IFO) << " ...";
            for (uint32_t i = j; i < _pdrFrame.size(); ++i) 
               Msg(MSG_IFO) << " " << _pdrFrame[i]->getCubeList().size();
            if (svrInfoON()) { Msg(MSG_IFO) << "  ("; _pdrSvr->printInfo(); Msg(MSG_IFO) << ")"; }
            if (endLineON()) Msg(MSG_IFO) << endl; else Msg(MSG_IFO) << flush;
         }
      }
   }

   // Report Verification Result
   if (!isIncKeepSilent() && reportON()) {
      if (intactON()) {
         if (endLineON()) Msg(MSG_IFO) << endl;
         else Msg(MSG_IFO) << "\r" << flushSpace << "\r";
      }
      if (V3NtkUD != proved) Msg(MSG_IFO) << "Inductive Invariant found at depth = " << ++proved;
      else if (V3NtkUD != fired) Msg(MSG_IFO) << "Counter-example found at depth = " << ++fired;
      else Msg(MSG_IFO) << "UNDECIDED at depth = " << _maxDepth;
      if (usageON()) {
         gettimeofday(&curtime, NULL);
         Msg(MSG_IFO) << "  (time = " << setprecision(5) << getTimeUsed(inittime, curtime) << "  sec)" << endl;
      }
      if (profileON()) {
         _totalStat->end();
         Msg(MSG_IFO) << *_initSvrStat << endl;
         Msg(MSG_IFO) << *_solveStat << endl;
         Msg(MSG_IFO) << *_generalStat << endl;
         Msg(MSG_IFO) << *_propagateStat << endl;
         Msg(MSG_IFO) << *_ternaryStat << endl;
         Msg(MSG_IFO) << *_totalStat << endl;
      }
   }

   // Record CounterExample Trace or Invariant
   if (V3NtkUD != fired) {  // Record Counter-Example
      // Compute PatternCount
      const V3MPDRCube* traceCube = badCube; assert (traceCube); assert (existInitial(traceCube->getState()));
      uint32_t patternCount = 0; while (_pdrBad != traceCube) { traceCube = traceCube->getNextCube(); ++patternCount; }
      V3CexTrace* const cex = new V3CexTrace(patternCount); assert (cex);
      _result[p].setCexTrace(cex); assert (_result[p].isCex());
      // Set Pattern Value
      traceCube = badCube; assert (traceCube); assert (existInitial(traceCube->getState()));
      while (_pdrBad != traceCube) {
         if (_pdrSize) cex->pushData(traceCube->getInputData());
         traceCube = traceCube->getNextCube(); assert (traceCube);
      }
      // Set Initial State Value
      if (_pdrInitValue.size()) {
         V3BitVecX initValue(_pdrInitValue.size());
         for (uint32_t i = 0; i < badCube->getState().size(); ++i) {
            assert (initValue.size() > badCube->getState()[i].id);
            if (badCube->getState()[i].cp) initValue.set0(badCube->getState()[i].id);
            else initValue.set1(badCube->getState()[i].id);
         }
         for (uint32_t i = 0; i < _pdrInitValue.size(); ++i)
            if (_pdrInitConst[i]) { if (_pdrInitValue[i]) initValue.set0(i); else initValue.set1(i); }
         cex->setInit(initValue);
      }
      // Delete Cubes on the Trace
      const V3MPDRCube* lastCube; traceCube = badCube;
      while (_pdrBad != traceCube) { lastCube = traceCube->getNextCube(); delete traceCube; traceCube = lastCube; }
      // Check Common Results
      if (isIncVerifyUsingCurResult()) checkCommonCounterexample(p, *cex);
   }
   else if (V3NtkUD != proved) {  // Record Inductive Invariant
      _result[p].setIndInv(_vrfNtk); assert (_result[p].isInv());
      // Put the Inductive Invariant to Frame INF
      uint32_t f = 1; for (; f < getPDRDepth(); ++f) if (!_pdrFrame[f]->getCubeList().size()) break;
      assert (f < getPDRDepth());
      for (uint32_t i = 1 + f; i < getPDRFrame(); ++i) {
         const V3MPDRCubeList& cubeList = _pdrFrame[i]->getCubeList(); V3MPDRCubeList::const_iterator it;
         for (it = cubeList.begin(); it != cubeList.end(); ++it) addBlockedCube(make_pair(getPDRFrame(), *it));
         _pdrFrame[i]->clearCubeList(); delete _pdrFrame[i];
      }
      // Remove Empty Frames
      _pdrFrame.back()->removeSelfSubsumed();
      _pdrFrame[f] = _pdrFrame.back(); while ((1 + f) != _pdrFrame.size()) _pdrFrame.pop_back();
      // Check Common Results
      if (isIncVerifyUsingCurResult()) {
         const V3MPDRCubeList& invCubeList = _pdrFrame.back()->getCubeList();
         V3NetTable invList; invList.clear(); invList.reserve(invCubeList.size());
         for (V3MPDRCubeList::const_iterator it = invCubeList.begin(); it != invCubeList.end(); ++it)
            invList.push_back((*it)->getState()); checkCommonProof(p, invList, false);
      }
   }
}