// Manipulation Helper Functions void V3SvrBoolector::setTargetValue(const V3NetId& id, const V3BitVecX& value, const uint32_t& depth, V3SvrDataVec& formula) { // Note : This Function will set formula such that AND(formula) represents (id == value) uint32_t size = value.size(); assert (size == _ntk->getNetWidth(id)); BtorExp* const aExp = getVerifyData(id, depth); assert (aExp); char* bv_value = new char[size + 1]; BtorExp *bExp, *cExp; uint32_t i = size, j = 0; while (i--) { if ('1' == value[i]) bv_value[j++] = '1'; else if ('0' == value[i]) bv_value[j++] = '0'; else if (j) { bv_value[j] = '\0'; bExp = boolector_slice(_Solver, aExp, i + j, i + 1); cExp = boolector_const(_Solver, bv_value); j = 0; formula.push_back(getPosExp(boolector_eq(_Solver, bExp, cExp))); boolector_release(_Solver, bExp); boolector_release(_Solver, cExp); } } if (j) { bv_value[j] = '\0'; if (j == size) bExp = boolector_copy(_Solver, aExp); else bExp = boolector_slice(_Solver, aExp, j - 1, 0); cExp = boolector_const(_Solver, bv_value); formula.push_back(getPosExp(boolector_eq(_Solver, bExp, cExp))); boolector_release(_Solver, bExp); boolector_release(_Solver, cExp); } delete[] bv_value; }
const bool V3VrfMPDR::removeFromProof(V3MPDRTimedCube& timedCube, const bool& pushForward) { // This function can ONLY be called after UNSAT of (R ^ T ^ cube') // Generate UNSAT Source from Solver if Possible V3SvrDataVec coreProofVars; coreProofVars.clear(); _pdrSvr->getDataConflict(coreProofVars); if (!coreProofVars.size()) return false; // Solver does not Support Analyze Conflict V3SvrDataSet coreProofVarSet; coreProofVarSet.clear(); for (uint32_t i = 0; i < coreProofVars.size(); ++i) coreProofVarSet.insert(coreProofVars[i]); const bool isSvrDataInvolved = coreProofVarSet.end() != coreProofVarSet.find(_pdrSvrData); // Get Generalized State from Solver Proof assert (!existInitial(timedCube.second->getState())); resolveInitial(timedCube.second, coreProofVarSet); assert (!existInitial(timedCube.second->getState())); if (!pushForward) return isSvrDataInvolved; // Return the Smallest Activity Index Used uint32_t i = timedCube.first; for (; i < getPDRFrame(); ++i) if (coreProofVarSet.find(_pdrFrame[i - 1]->getActivator()) != coreProofVarSet.end()) { timedCube.first = i; break; } if (i == getPDRFrame()) { if (coreProofVarSet.find(_pdrFrame[getPDRDepth()]->getActivator()) == coreProofVarSet.end()) timedCube.first = getPDRFrame(); else timedCube.first = getPDRDepth(); } assert (!checkReachability(timedCube.first, timedCube.second->getState())); return isSvrDataInvolved; }
const bool V3SVrfIPDR::checkReachability2(const uint32_t& frame, const V3NetVec& cubeState, const bool& extend, const bool& notImportant) { if(heavy_debug && !notImportant){ cerr << "\n!!!!!!checkReachability2 frame : " << frame << " cube : "; printState(cubeState); cerr << endl; } assert (frame > 0); assert (frame < getPDRFrame()); const uint32_t& d = frame - 1; _pdrSvr[d]->assumeRelease(); // Assume cube' addCubeToSolver2(d, cubeState, 0); /*V3SSvrMiniSat * gg= (V3SSvrMiniSat *)_pdrSvr[d]; for (unsigned i = 0; i < 40; ++i){ cerr << i << " : " << gg->getVerifyData( i ,0 ) << endl; }*/ for (uint32_t i = 0; i < cubeState.size(); ++i) _pdrSvr[d]->assumeProperty(_pdrSvr[d]->getFormula(_handler->_latchMap->at(_decompDepth)[cubeState[i].id], 0), cubeState[i].cp); if (extend) { // Assume ~cube addCubeToSolver(d, cubeState, 0); V3SvrDataVec blockCube; blockCube.clear(); blockCube.reserve(cubeState.size()); size_t fId; for (uint32_t i = 0; i < cubeState.size(); ++i) { fId = _pdrSvr[d]->getFormula(_vrfNtk->getLatch(cubeState[i].id), 0); blockCube.push_back(cubeState[i].cp ? fId : _pdrSvr[d]->getNegFormula(fId)); } _pdrSvrData = _pdrSvr[d]->setImplyUnion(blockCube); assert (_pdrSvrData); _pdrSvr[d]->assumeProperty(_pdrSvrData); // Check Reachability by SAT Calling if (profileON()) _solveStat->start(); _pdrSvr[d]->simplify(); const bool result = _pdrSvr[d]->assump_solve(); if (profileON()) _solveStat->end(); _pdrSvr[d]->assertProperty(_pdrSvr[d]->getNegFormula(_pdrSvrData)); // Invalidate ~cube in future solving if(heavy_debug && !notImportant) cerr << "result: " << result << endl << endl; return result; } else { if (profileON()) _solveStat->start(); /*V3SSvrMiniSat * GG = (V3SSvrMiniSat *)_pdrSvr[d]; for (unsigned i = 0, s = GG->_assump.size(); i < s; ++i){ cout << var(GG->_assump[i]) << ":" << sign(GG->_assump[i]) << endl; }*/ _pdrSvr[d]->simplify(); const bool result = _pdrSvr[d]->assump_solve(); if (profileON()) _solveStat->end(); if(heavy_debug && !notImportant) cerr << "result: " << result << endl << endl; return result; } }
void V3VrfMPDR::addBlockedCube(const V3MPDRTimedCube& cube) { assert (cube.first <= getPDRFrame()); assert (cube.second->getState().size()); // Push cube into corresponding frame that it should be blocked if (!_pdrFrame[cube.first]->pushCube(cube.second)) return; // Renders this cube to be blocked as frame activator is asserted const V3NetVec& state = cube.second->getState(); addCubeToSolver(state, 0); V3SvrDataVec formula; formula.clear(); formula.reserve(1 + state.size()); size_t fId; formula.push_back(_pdrSvr->getNegFormula(_pdrFrame[cube.first]->getActivator())); for (uint32_t i = 0; i < state.size(); ++i) { fId = _pdrSvr->getFormula(_vrfNtk->getLatch(state[i].id), 0); formula.push_back(state[i].cp ? fId : _pdrSvr->getNegFormula(fId)); ++_pdrPriority[state[i].id]; // Increase Signal Priority } _pdrSvr->assertProperty(_pdrSvr->setImplyUnion(formula)); // Share Invariants if (_sharedInv && (cube.first == getPDRFrame())) _sharedInv->updateInv(state); }
const bool V3SVrfIPDR::removeFromProof2(V3SIPDRTimedCube& timedCube) { // This function can ONLY be called after UNSAT of (R ^ T ^ cube') // Generate UNSAT Source from Solver if Possible V3SvrDataVec coreProofVars; coreProofVars.clear(); assert (timedCube.first < _pdrSvr.size()); assert (timedCube.first); _pdrSvr[timedCube.first - 1]->getDataConflict(coreProofVars); if (!coreProofVars.size()) return false; // Solver does not Support Analyze Conflict V3SvrDataSet coreProofVarSet; coreProofVarSet.clear(); for (uint32_t i = 0; i < coreProofVars.size(); ++i) coreProofVarSet.insert(coreProofVars[i]); const bool isSvrDataInvolved = coreProofVarSet.end() != coreProofVarSet.find(_pdrSvrData); // not used var // Get Proof Related State Variables in UNSAT core assert (!existInitial2(timedCube.second->getState())); const V3NetVec& state = timedCube.second->getState(); // Remove Variables to Form New State assert (!existInitial2(state)); bool conflictInitial = false; V3NetId conflictId = V3NetUD; uint32_t pos = 0; V3NetVec newState; newState.reserve(state.size()); for (uint32_t i = 0; i < state.size(); ++i) { if (coreProofVarSet.end() != coreProofVarSet.find( _pdrSvr[timedCube.first - 1]->getFormula(_vrfNtk->getLatch(state[i].id), 1))) { newState.push_back(state[i]); //OrzOrz if (!conflictInitial && (_pdrInitValue[state[i].id] ^ state[i].cp)) { assert (!existInitial2(newState)); conflictInitial = true; } } else if (!conflictInitial && V3NetUD == conflictId) { if (_pdrInitValue[state[i].id] ^ state[i].cp) { conflictId = state[i]; assert (V3NetUD != conflictId); pos = newState.size(); } } } // Resolve Intersection with Initial State if (!conflictInitial && V3NetUD != conflictId) { newState.insert(newState.begin() + pos, conflictId); } else if( !conflictInitial ) cerr << "GGGG in removing UNSATCore" << endl; if (newState.size() < state.size()) timedCube.second->setState(newState); //checkCubeSorted(newState); assert (!existInitial2(timedCube.second->getState())); assert (!checkReachability(timedCube.first, timedCube.second->getState())); return isSvrDataInvolved; }
const size_t V3SvrBoolector::setImplyIntersection(const V3SvrDataVec& Exps) { if (Exps.size() == 0) return 0; vector<size_t>::const_iterator it = Exps.begin(); assert (*it); BtorExp *aExp = (isNegFormula(*it) ? boolector_not(_Solver, getOriExp(*it)) : boolector_copy(_Solver, getOriExp(*it))); BtorExp *bExp, *oExp; ++it; for (; it != Exps.end(); ++it) { assert (*it); assert (aExp); bExp = (isNegFormula(*it) ? boolector_not(_Solver, getOriExp(*it)) : boolector_copy(_Solver, getOriExp(*it))); oExp = boolector_and(_Solver, aExp, bExp); assert (oExp); boolector_release(_Solver, aExp); boolector_release(_Solver, bExp); aExp = oExp; } bExp = boolector_var(_Solver, 1, NULL); oExp = boolector_implies(_Solver, bExp, aExp); boolector_assert(_Solver, oExp); boolector_release(_Solver, oExp); boolector_release(_Solver, aExp); assert (!isNegFormula(getPosExp(bExp))); assert (bExp); return getPosExp(bExp); }
void V3VrfBase::checkCommonProof(const uint32_t& p, const V3NetTable& invList, const bool& checkInitial) { assert (_result[p].isInv()); // Collect Unsolved Properties V3UI32Vec unsolved; unsolved.clear(); unsolved.reserve(_result.size()); for (uint32_t i = 0; i < _result.size(); ++i) if (!(_result[i].isCex() || _result[i].isInv())) unsolved.push_back(i); // Check Same Property const V3NetId pId = _vrfNtk->getOutput(p); for (uint32_t i = 0; i < unsolved.size(); ++i) { if (pId != _vrfNtk->getOutput(unsolved[i])) continue; _result[unsolved[i]].setIndInv(_vrfNtk); unsolved.erase(unsolved.begin() + i); --i; } if (!unsolved.size()) return; assert (!_constr.size()); // Create Solver V3SvrBase* const solver = allocSolver(getSolver(), _vrfNtk); assert (solver); V3SvrDataVec formula; formula.clear(); V3NetId id; uint32_t d = 0; // Set Inductive Invariant for (uint32_t i = 0; i < invList.size(); ++i) { formula.clear(); formula.reserve(invList[i].size()); for (uint32_t j = 0; j < invList[i].size(); ++j) { id = invList[i][j]; assert (_vrfNtk->getLatchSize() > id.id); assert (!d); if (!solver->existVerifyData(_vrfNtk->getLatch(id.id), d)) solver->addBoundedVerifyData(_vrfNtk->getLatch(id.id), d); assert (solver->existVerifyData(_vrfNtk->getLatch(id.id), d)); formula.push_back(solver->getFormula(_vrfNtk->getLatch(id.id), 0, d)); if (!id.cp) formula.back() = solver->getNegFormula(formula.back()); } solver->assertImplyUnion(formula); } if (checkInitial) { solver->assumeRelease(); solver->assumeInit(); if (solver->assump_solve()) { delete solver; return; } } // Check if the bad State Signal is Inconsistent with the Inductive Invariant for (uint32_t i = 0, j = 0; i < unsolved.size(); ++i) { solver->assumeRelease(); assert (!d); if (!solver->existVerifyData(_vrfNtk->getOutput(unsolved[i]), d)) solver->addBoundedVerifyData(_vrfNtk->getOutput(unsolved[i]), d); assert (solver->existVerifyData(_vrfNtk->getOutput(unsolved[i]), d)); solver->assumeProperty(_vrfNtk->getOutput(unsolved[i]), false, d); if (!solver->assump_solve()) { _result[unsolved[i]].setIndInv(_vrfNtk); j = 0; } else if (++j > 100) break; // Avoid Spending Too Much Effort on the Check } delete solver; }
void V3VrfMPDR::addFrameInfoToSolver(const uint32_t& f) { assert (f); assert (f < _pdrFrame.size()); _pdrFrame[f]->setActivator(_pdrSvr->reserveFormula()); const V3MPDRCubeList& cubeList = _pdrFrame[f]->getCubeList(); V3SvrDataVec formula; formula.clear(); size_t fId; for (V3MPDRCubeList::const_reverse_iterator it = cubeList.rbegin(); it != cubeList.rend(); ++it) { addCubeToSolver((*it)->getState(), 0); formula.reserve(1 + (*it)->getState().size()); formula.push_back(_pdrSvr->getNegFormula(_pdrFrame[f]->getActivator())); for (uint32_t j = 0; j < (*it)->getState().size(); ++j) { fId = _pdrSvr->getFormula(_vrfNtk->getLatch((*it)->getState()[j].id), 0); formula.push_back((*it)->getState()[j].cp ? fId : _pdrSvr->getNegFormula(fId)); } _pdrSvr->assertProperty(_pdrSvr->setImplyUnion(formula)); formula.clear(); } }
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()); }