// Functions for Checking Common Results void V3VrfBase::checkCommonCounterexample(const uint32_t& p, const V3CexTrace& cex) { assert (_result[p].isCex()); assert (cex.getTraceSize()); // 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); if (!unsolved.size()) return; assert (!_constr.size()); V3UI32Vec firedIndex, firedDepth; firedIndex.clear(); firedDepth.clear(); // 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; firedIndex.push_back(unsolved[i]); firedDepth.push_back(cex.getTraceSize()); unsolved.erase(unsolved.begin() + i); --i; } // Create Simulator V3AlgSimulate* simulator = 0; V3BitVecX pattern; if (dynamic_cast<V3BvNtk*>(_vrfNtk)) simulator = new V3AlgBvSimulate(_handler); else simulator = new V3AlgAigSimulate(_handler); assert (simulator); // For each time-frame, set pattern from counter-example for (uint32_t i = 0, k; i < cex.getTraceSize(); ++i) { if (!unsolved.size()) break; // Update FF Next State Values simulator->updateNextStateValue(); // Set Initial State Values if (!i && cex.getInit()) { V3BitVecX* const initValue = cex.getInit(); k = 0; for (uint32_t j = 0; j < _vrfNtk->getLatchSize(); ++j, ++k) simulator->setSource(_vrfNtk->getLatch(j), initValue->bv_slice(k, k)); } // Set PI Values if (cex.getTraceDataSize()) pattern = cex.getData(i); k = 0; for (uint32_t j = 0; j < _vrfNtk->getInputSize(); ++j, ++k) simulator->setSource(_vrfNtk->getInput(j), pattern.bv_slice(k, k)); for (uint32_t j = 0; j < _vrfNtk->getInoutSize(); ++j, ++k) simulator->setSource(_vrfNtk->getInout(j), pattern.bv_slice(k, k)); // Simulate Ntk for a Cycle simulator->simulate(); // Check Property Assertion for (uint32_t j = 0; j < unsolved.size(); ++j) { if ('1' == simulator->getSimValue(_vrfNtk->getOutput(unsolved[j])).bv_slice(0, 0)[0]) { firedIndex.push_back(unsolved[j]); firedDepth.push_back(1 + i); unsolved.erase(unsolved.begin() + j); --j; } } } delete simulator; simulator = 0; assert (firedIndex.size() == firedDepth.size()); // Set Sub-Traces for Cex to Fired Properties for (uint32_t i = 0; i < firedIndex.size(); ++i) { V3CexTrace* const subTrace = new V3CexTrace(firedDepth[i]); assert (subTrace); if (cex.getTraceDataSize()) for (uint32_t j = 0; j < firedDepth[i]; ++j) subTrace->pushData(cex.getData(j)); if (cex.getInit()) subTrace->setInit(*(cex.getInit())); _result[firedIndex[i]].setCexTrace(subTrace); } }
// Verification Main Functions void V3VrfSIM::startVerify(const uint32_t& pIndex) { // Initialize V3Ntk* const ntk = _handler->getNtk(); assert (ntk); V3AlgSimulate* simulator = 0; if (dynamic_cast<V3BvNtk*>(ntk)) simulator = new V3AlgBvSimulate(_handler); else simulator = new V3AlgAigSimulate(_handler); assert (simulator); 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 cycle = V3NtkUD, cycleReached = 0; double runtime = clock(), timeBound = clock() + (CLOCKS_PER_SEC * _maxTime); // Start SIM Based Verification const uint32_t Cycle = 10000; uint32_t i = 0, j = 0; for (uint32_t k = 0, n = (uint32_t)(ceil(_maxDepth / Cycle)); k < n; ++k) { j = Cycle + i; if (j > _maxDepth) j = _maxDepth; for (i = Cycle * k; i < j; ++i) { // Update FF Next State Values simulator->updateNextStateValue(); // Purely Random Simulation simulator->setSourceFree(V3_PI, true); simulator->setSourceFree(V3_PIO, true); // Simulate for One Cycle simulator->simulate(); // Record Simulation Data simulator->recordSimValue(); // Check if Property Asserted if (simulator->getSimValue(pId).exist1()) { cycle = i; break; } } if (V3NtkUD != cycle) break; // Report Verification Progress if (intactON()) { if (!endLineON()) Msg(MSG_IFO) << "\r" + flushSpace + "\r"; Msg(MSG_IFO) << "Simulation completed under cycle = " << setw(logMaxWidth) << i; if (endLineON()) Msg(MSG_IFO) << endl; else Msg(MSG_IFO) << flush; // Check if Time Bound Reached if (clock() >= timeBound) { cycleReached = i; break; } } } // 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 != cycle) Msg(MSG_IFO) << "Counter-example found at cycle = " << ++cycle; else Msg(MSG_IFO) << "UNDECIDED at cycle = " << ((clock() >= timeBound) ? cycleReached : _maxDepth); if (usageON()) Msg(MSG_IFO) << " (time = " << setprecision(5) << runtime << " sec)" << endl; if (profileON()) { /* Report some profiling here ... */ } } // Record CounterExample Trace if (V3NtkUD == cycle) return; // Compute Pattern Size and Initialize Trace V3CexTrace* const cex = new V3CexTrace(cycle); assert (cex); _result[pIndex].setCexTrace(cex); assert (_result[pIndex].isCex()); 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)); if (!patternSize) return; // Record Counter-Example V3SimTrace pattern(ntk->getInputSize()); V3BitVecX trace(patternSize); if (dynamic_cast<V3BvNtk*>(ntk)) { for (uint32_t i = 0; i < cycle; ++i) { simulator->getSimRecordData(i, pattern); uint32_t k = 0; for (uint32_t j = 0; j < ntk->getInputSize(); ++j) { assert (pattern[j].size() == ntk->getNetWidth(ntk->getInput(j))); for (uint32_t x = 0; x < pattern[j].size(); ++x, ++k) if ('1' == pattern[j][x]) trace.set1(k); else if ('0' == pattern[j][x]) trace.set0(k); } for (uint32_t j = 0; j < ntk->getInoutSize(); ++j) { assert (pattern[j].size() == ntk->getNetWidth(ntk->getInout(j))); for (uint32_t x = 0; x < pattern[j].size(); ++x, ++k) if ('1' == pattern[j][x]) trace.set1(k); else if ('0' == pattern[j][x]) trace.set0(k); } cex->pushData(trace); trace.clear(); } } else { const uint32_t p = simulator->getSimValue(pId).first1(); assert (p < simulator->getSimValue(pId).size()); assert (pattern.size() == trace.size()); for (uint32_t i = 0; i < cycle; ++i) { simulator->getSimRecordData(i, pattern); for (uint32_t j = 0; j < pattern.size(); ++j) if ('1' == pattern[j][p]) trace.set1(j); else if ('0' == pattern[j][p]) trace.set0(j); cex->pushData(trace); trace.clear(); } } }
// Simulation-Based Checker const int cycleSimulateResult(const V3CexTrace& cex, const V3NetVec& constrList, const V3NetVec& fairList, const bool& safe, const V3NtkHandler* const handler, const uint32_t& index) { // Check Counterexample Directly on Input Ntk assert (cex.getTraceSize()); assert (handler); assert (!safe || !fairList.size()); V3Ntk* const ntk = handler->getNtk(); assert (ntk); // Create Simulator V3AlgSimulate* simulator = 0; if (dynamic_cast<V3BvNtk*>(ntk)) simulator = new V3AlgBvSimulate(handler); else simulator = new V3AlgAigSimulate(handler); assert (simulator); // Add Constraints to Simulator V3NetVec targetNets; targetNets.clear(); targetNets.reserve(constrList.size() + fairList.size() + 1); for (uint32_t i = 0; i < constrList.size(); ++i) targetNets.push_back(constrList[i]); for (uint32_t i = 0; i < fairList.size(); ++i) targetNets.push_back(fairList[i]); targetNets.push_back(ntk->getOutput(index)); simulator->reset(targetNets); // Storage for Liveness Properties V3Vec<V3BitVec>::Vec fairVec(fairList.size() ? fairList.size() : 1, V3BitVec(cex.getTraceSize())); V3Vec<V3BitVecX>::Vec stateVec; stateVec.clear(); // For each time-frame, set pattern from counter-example V3BitVecX pattern, value; for (uint32_t i = 0, k; i < cex.getTraceSize(); ++i) { // Update FF Next State Values simulator->updateNextStateValue(); // Set Initial State Values if (!i && cex.getInit()) { V3BitVecX* const initValue = cex.getInit(); k = 0; for (uint32_t j = 0; j < ntk->getLatchSize(); ++j) { pattern = simulator->getSimValue(ntk->getLatch(j)).bv_slice(ntk->getNetWidth(ntk->getLatch(j)) - 1, 0); value = initValue->bv_slice(k + ntk->getNetWidth(ntk->getLatch(j)) - 1, k); if (!pattern.bv_cover(value)) { reportUnexpectedState(1, j, value, pattern); return -1; } simulator->setSource(ntk->getLatch(j), value); k += ntk->getNetWidth(ntk->getLatch(j)); assert (k <= initValue->size()); } } // Set PI Values if (cex.getTraceDataSize()) pattern = cex.getData(i); k = 0; for (uint32_t j = 0; j < ntk->getInputSize(); ++j) { simulator->setSource(ntk->getInput(j), pattern.bv_slice(k + ntk->getNetWidth(ntk->getInput(j)) - 1, k)); k += ntk->getNetWidth(ntk->getInput(j)); assert (k <= pattern.size()); } for (uint32_t j = 0; j < ntk->getInoutSize(); ++j) { simulator->setSource(ntk->getInout(j), pattern.bv_slice(k + ntk->getNetWidth(ntk->getInout(j)) - 1, k)); k += ntk->getNetWidth(ntk->getInout(j)); assert (k <= pattern.size()); } // Simulate Ntk for a Cycle simulator->simulate(); // Check Invariant Constraints for (uint32_t j = 0; j < constrList.size(); ++j) { assert (1 == ntk->getNetWidth(constrList[j])); value = simulator->getSimValue(constrList[j]).bv_slice(0, 0); if ('1' != value[0]) { reportUnsatisfiedConstraint(1 + i, j, value); return -1; } } // Check Property Assertion value = simulator->getSimValue(ntk->getOutput(index)).bv_slice(0, 0); if (safe) { if ((i < (cex.getTraceSize() - 1)) && ('1' == value[0])) reportShorterTrace(1 + i, value[0]); } else if ('1' != value[0]) { Msg(MSG_IFO) << "Cycle = " << i << ", Root Constraint has unexpected value = " << value << endl; return -1; } // Record Data for Liveness Checking if (!safe) { for (uint32_t j = 0; j < fairList.size(); ++j) { assert (1 == ntk->getNetWidth(fairList[j])); value = simulator->getSimValue(fairList[j]).bv_slice(0, 0); if ('1' == value[0]) fairVec[j].set1(i); } for (uint32_t j = 0; j < ntk->getLatchSize(); ++j) { const uint32_t width = ntk->getNetWidth(ntk->getLatch(j)); if (!j) value = simulator->getSimValue(ntk->getLatch(j)).bv_slice(width - 1, 0); else value = value.bv_concat(simulator->getSimValue(ntk->getLatch(j)).bv_slice(width - 1, 0)); } stateVec.push_back(value); } } delete simulator; simulator = 0; if (!safe) { // Check the Existence of Loop uint32_t looped = stateVec.size() - 1; assert (stateVec.size()); while (looped--) { if (stateVec.back() != stateVec[looped]) continue; // Check Fairness Constraints uint32_t i = 0, j; for (; i < fairList.size(); ++i) { for (j = looped; j < stateVec.size(); ++j) if (fairVec[i][j]) break; if (stateVec.size() == j) break; } if (fairList.size() == i) return 1; } return -1; } else return ('1' == value[0]) ? 1 : -1; }