// PDR Initialization Functions void V3VrfMPDR::initializeSolver() { if (profileON()) _initSvrStat->start(); const bool isNewSolver = !_pdrSvr; if (!_pdrSvr) { _pdrSvr = allocSolver(getSolver(), _vrfNtk); assert (_pdrSvr->totalSolves() == 0); } else _pdrSvr->reset(); _pdrActCount = _pdrRecycle; // Set Initial State to Solver for (uint32_t i = 0; i < _vrfNtk->getLatchSize(); ++i) _pdrSvr->addBoundedVerifyData(_vrfNtk->getLatch(i), 0); if (isNewSolver) _pdrSvr->simplify(); if (profileON()) _initSvrStat->end(); }
void V3SVrfIPDR::initializeSolver2(const uint32_t& d, const bool& isReuse) { //cerr << "initializeSolver depth: " << d << endl; if (profileON()) _initSvrStat->start(); if(!d){ _pdrSvr.push_back(allocSolver(getSolver(), _vrfNtk)); } else{ assert (d == _pdrSvr.size()); _pdrSvr.push_back(d ? referenceSolver(_pdrSvr[0]) : allocSolver(getSolver(), _vrfNtk)); } for (uint32_t i = 0; i < _vrfNtk->getLatchSize(); ++i) _pdrSvr[d]->addBoundedVerifyData(_vrfNtk->getLatch(i), 0); _pdrSvr[d]->addBoundedVerifyData(_pdrBad->getState()[0], 0); if (d != getPDRDepth()) _pdrSvr[d]->assertProperty(_pdrBad->getState()[0], true, 0); // Consistency Check assert (_pdrFrame.size() == _pdrSvr.size()); _pdrSvr[d]->simplify(); if (profileON()) _initSvrStat->end(); _pdrSvr[d]->printVerbose(); }
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; }
// Private Verification Main Functions void V3VrfUMC::startVerify(const uint32_t& pIndex) { // Consistency Check if (_preDepth > _maxDepth) _maxDepth = _preDepth; assert (_maxDepth >= _preDepth); if (_incDepth && ((_maxDepth - _preDepth) % _incDepth)) _maxDepth -= (_maxDepth - _preDepth) % _incDepth; assert (!_incDepth || !((_maxDepth - _preDepth) % _incDepth)); assert (_maxDepth >= _preDepth); if ((_maxDepth > _preDepth) && !_incDepth) _maxDepth = _preDepth; // Initialize V3Ntk* const ntk = _handler->getNtk(); assert (ntk); if (_solver) delete _solver; _solver = allocSolver(getSolver(), ntk); assert (_solver); assert (_solver->totalSolves() == 0); assert (pIndex < _result.size()); assert (pIndex < ntk->getOutputSize()); const V3NetId& pId = ntk->getOutput(pIndex); assert (V3NetUD != pId); const uint32_t logMaxWidth = (uint32_t)(ceil(log10(_maxDepth))); const string flushSpace = string(100, ' '); uint32_t proved = V3NtkUD, fired = V3NtkUD; double runtime = clock(); uint32_t boundDepth = _preDepth ? _preDepth : _incDepth; // Solver Data V3SvrData pFormulaData; V3PtrVec pFormula; pFormula.reserve((_preDepth > _incDepth) ? _preDepth : _incDepth); // Start UMC Based Verification for (uint32_t i = 0, j = _maxDepth; i < j; ++i) { // Add time frame expanded circuit to SAT Solver _solver->addBoundedVerifyData(pId, i); pFormula.push_back(_solver->getFormula(pId, i)); // Check if the bound is achieved if ((1 + i) < boundDepth) continue; assert ((1 + i) == boundDepth); assert ((1 + i) >= pFormula.size()); boundDepth += _incDepth; // Add assume for assumption solve only _solver->assumeRelease(); if (1 == pFormula.size()) _solver->assumeProperty(pId, false, i); else { pFormulaData = _solver->setImplyUnion(pFormula); assert (pFormulaData); _solver->assumeProperty(pFormulaData); } _solver->simplify(); // Report Verification Progress if (intactON()) { if (!endLineON()) Msg(MSG_IFO) << "\r" + flushSpace + "\r"; Msg(MSG_IFO) << "Verification completed under depth = " << setw(logMaxWidth) << (i + 1); if (svrInfoON()) { Msg(MSG_IFO) << " ("; _solver->printInfo(); Msg(MSG_IFO) << ")"; } if (endLineON()) Msg(MSG_IFO) << endl; else Msg(MSG_IFO) << flush; } // Assumption Solve : If UNSAT, proved! if (!isFireOnly() && !_solver->assump_solve()) { if (!isProveOnly()) { proved = i; break; } } // Assumption Solve : If SAT, disproved! if (!isProveOnly()) { _solver->assumeInit(); // Conjunction with initial condition if (_solver->assump_solve()) { for (uint32_t k = 0; k < pFormula.size(); ++k) if ('0' != _solver->getDataValue(pFormula[k])) { fired = (1 + i + k - pFormula.size()); break; } assert (V3NtkUD != fired); break; } } // Add assert back to the property if (1 < pFormula.size()) { assert (pFormulaData); _solver->assertProperty(pFormulaData, true); } for (uint32_t k = i - pFormula.size(); k < i; ++k) _solver->assertProperty(pId, true, k); pFormula.clear(); pFormulaData = 0; } // Report Verification Result if (reportON()) { runtime = (clock() - runtime) / CLOCKS_PER_SEC; 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()) Msg(MSG_IFO) << " (time = " << setprecision(5) << runtime << " sec)" << endl; if (profileON()) { /* Report some profiling here ... */ } } else { if (V3NtkUD != proved) ++proved; else if (V3NtkUD != fired) ++fired; } // Record CounterExample Trace or Invariant if (V3NtkUD != fired) { // Record Counter-Example V3CexTrace* const cex = new V3CexTrace(fired); assert (cex); _result[pIndex].setCexTrace(cex); assert (_result[pIndex].isCex()); // Compute Pattern Size (PI + PIO) uint32_t patternSize = 0; for (uint32_t i = 0; i < ntk->getInputSize(); ++i) patternSize += ntk->getNetWidth(ntk->getInput(i)); for (uint32_t i = 0; i < ntk->getInoutSize(); ++i) patternSize += ntk->getNetWidth(ntk->getInout(i)); // Set Pattern Value (PI + PIO) V3BitVecX dataValue, patternValue(patternSize ? patternSize : 1); for (uint32_t i = 0; i < fired; ++i) { patternSize = 0; patternValue.clear(); for (uint32_t j = 0; j < ntk->getInputSize(); ++j) { if (_solver->existVerifyData(ntk->getInput(j), i)) { dataValue = _solver->getDataValue(ntk->getInput(j), i); assert (dataValue.size() == ntk->getNetWidth(ntk->getInput(j))); for (uint32_t k = 0; k < dataValue.size(); ++k, ++patternSize) { if ('0' == dataValue[k]) patternValue.set0(patternSize); else if ('1' == dataValue[k]) patternValue.set1(patternSize); } } else patternSize += ntk->getNetWidth(ntk->getInput(j)); } for (uint32_t j = 0; j < ntk->getInoutSize(); ++j) { if (_solver->existVerifyData(ntk->getInout(j), i)) { dataValue = _solver->getDataValue(ntk->getInout(j), i); assert (dataValue.size() == ntk->getNetWidth(ntk->getInout(j))); for (uint32_t k = 0; k < dataValue.size(); ++k, ++patternSize) { if ('0' == dataValue[k]) patternValue.set0(patternSize); else if ('1' == dataValue[k]) patternValue.set1(patternSize); } } else patternSize += ntk->getNetWidth(ntk->getInout(j)); } assert (_solver->existVerifyData(pId, i)); assert (!patternSize || patternSize == patternValue.size()); cex->pushData(patternValue); } } else if (V3NtkUD != proved) { // Record Inductive Invariant _result[pIndex].setIndInv(ntk); assert (_result[pIndex].isInv()); } }
// Private Verification Main Functions void V3SVrfBMC::startVerify(const uint32_t& p) { // Clear Verification Results clearResult(p); // Initialize Parameters const string flushSpace = string(100, ' '); uint32_t fired = V3NtkUD; struct timeval inittime, curtime; gettimeofday(&inittime, NULL); uint32_t lastDepth = getIncLastDepthToKeepGoing(); if (10000000 < lastDepth) lastDepth = 0; uint32_t boundDepth = lastDepth ? lastDepth : 0; // Start BMC Based Verification V3Ntk* simpNtk = 0; V3SvrBase* solver = 0; while (boundDepth < _maxDepth) { // Check Time Bounds gettimeofday(&curtime, NULL); if (_maxTime < getTimeUsed(inittime, curtime)) break; boundDepth += 1; // Expand Network and Set Initial States V3NtkExpand* const pNtk = new V3NtkExpand(_handler, boundDepth, true); assert (pNtk); //printNetlist(pNtk); V3NetId id; V3NetVec p2cMap, c2pMap; V3RepIdHash repIdHash; repIdHash.clear(); simpNtk = duplicateNtk(pNtk, p2cMap, c2pMap); assert (simpNtk); //printNetlist(simpNtk); // Create Outputs for the Unrolled Property Signals for (uint32_t i = boundDepth - 1, j = 0; j < 1; ++i, ++j) { id = pNtk->getNtk()->getOutput(p + (_vrfNtk->getOutputSize() * i)); simpNtk->createOutput(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); } // Set CONST 0 to Proven Property Signals for (uint32_t i = 0, j = boundDepth - 1, k = p; i < j; ++i, k += _vrfNtk->getOutputSize()) { id = pNtk->getNtk()->getOutput(k); id = V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp); repIdHash.insert(make_pair(id.id, V3NetId::makeNetId(0, id.cp))); } if (repIdHash.size()) simpNtk->replaceFanin(repIdHash); delete pNtk; p2cMap.clear(); c2pMap.clear(); // Initialize Solver solver = allocSolver(getSolver(), simpNtk); assert (solver); solver->addBoundedVerifyData(simpNtk->getOutput(0), 0); solver->simplify(); solver->assumeRelease(); solver->assumeProperty(simpNtk->getOutput(0), false, 0); if (solver->assump_solve()) { fired = boundDepth; break; } solver->assertProperty(simpNtk->getOutput(0), true, 0); if (!endLineON()) Msg(MSG_IFO) << "\r" + flushSpace + "\r"; Msg(MSG_IFO) << "Verification completed under depth = " << boundDepth; if (V3NtkUD != fired) break; delete solver; delete simpNtk; } // Report Verification Result if (V3NtkUD != fired) Msg(MSG_IFO) << "Counter-example found at depth = " << fired; else Msg(MSG_IFO) << "UNDECIDED at depth = " << _maxDepth; // Record CounterExample Trace or Invariant if (V3NtkUD != fired) { // Record Counter-Example V3CexTrace* const cex = new V3CexTrace(fired); assert (cex); // Set Pattern Value uint32_t patternSize = _vrfNtk->getInputSize() + _vrfNtk->getInoutSize(); V3BitVecX dataValue, patternValue(patternSize ? patternSize : 1); for (uint32_t i = 0, inSize = 0, ioSize = 0; i < fired; ++i) { patternSize = 0; patternValue.clear(); for (uint32_t j = 0; j < _vrfNtk->getInputSize(); ++j, ++patternSize, ++inSize) { if (!solver->existVerifyData(simpNtk->getInput(inSize), 0)) continue; dataValue = solver->getDataValue(simpNtk->getInput(inSize), 0); if ('0' == dataValue[0]) patternValue.set0(patternSize); else if ('1' == dataValue[0]) patternValue.set1(patternSize); } for (uint32_t j = 0; j < _vrfNtk->getInoutSize(); ++j, ++patternSize, ++ioSize) { if (!solver->existVerifyData(simpNtk->getInout(ioSize), 0)) continue; dataValue = solver->getDataValue(simpNtk->getInout(ioSize), 0); if ('0' == dataValue[0]) patternValue.set0(patternSize); else if ('1' == dataValue[0]) patternValue.set1(patternSize); } assert (!patternSize || patternSize == patternValue.size()); cex->pushData(patternValue); } // Set Initial State Value if (_vrfNtk->getLatchSize()) { const uint32_t piSize = boundDepth * _vrfNtk->getInputSize(); patternValue.resize(_vrfNtk->getLatchSize()); patternValue.clear(); V3NetId id; uint32_t k = 0; for (uint32_t j = 0; j < _vrfNtk->getLatchSize(); ++j) { id = _vrfNtk->getInputNetId(_vrfNtk->getLatch(j), 1); if (!id.id) { if (id.cp) patternValue.set1(j); else patternValue.set0(j); } else { if (solver->existVerifyData(simpNtk->getInput(piSize + k), 0)) { dataValue = solver->getDataValue(simpNtk->getInput(piSize + k), 0); if ('0' == dataValue[0]) patternValue.set0(j); else if ('1' == dataValue[0]) patternValue.set1(j); } ++k; } } cex->setInit(patternValue); } delete solver; delete simpNtk; _result[p].setCexTrace(cex); } }