void V3SVrfIPDR::generalizeSimulation2(const uint32_t& d, V3SIPDRCube* const cube, const V3SIPDRCube* const nextCube) { assert (d < _pdrSvr.size()); assert (cube); assert (nextCube); assert (nextCube == cube->getNextCube()); assert (_pdrSim); // Set Values for Simulator for (uint32_t i = 0; i < _vrfNtk->getInputSize(); ++i) { if (!_pdrSvr[d]->existVerifyData(_vrfNtk->getInput(i), 0)) _pdrSim->clearSource(_vrfNtk->getInput(i), true); else _pdrSim->setSource(_vrfNtk->getInput(i), _pdrSvr[d]->getDataValue(_vrfNtk->getInput(i), 0)); } for (uint32_t i = 0; i < _vrfNtk->getLatchSize(); ++i) { if (!_pdrSvr[d]->existVerifyData(_vrfNtk->getLatch(i), 0)) _pdrSim->clearSource(_vrfNtk->getLatch(i), true); else _pdrSim->setSource(_vrfNtk->getLatch(i), _pdrSvr[d]->getDataValue(_vrfNtk->getLatch(i), 0)); } _pdrSim->simulate(); // Perform SAT Generalization if (_pdrBad != nextCube) _pdrGen->setTargetNets2(V3NetVec(), nextCube->getState(), _decompDepth); else { V3NetVec constrCube(1, nextCube->getState()[0]); assert (1 == nextCube->getState().size()); _pdrGen->setTargetNets(constrCube); } // Set Priority V3UI32Vec prioNets; prioNets.clear(); prioNets.reserve(_pdrPriority.size()); for (uint32_t i = 0; i < _pdrPriority.size(); ++i) if (!_pdrPriority[i]) prioNets.push_back(i); for (uint32_t i = 0; i < _pdrPriority.size(); ++i) if ( _pdrPriority[i]) prioNets.push_back(i); //_pdrGen->_tem = true; _pdrGen->performSetXForNotCOIVars(false); _pdrGen->performXPropForExtensibleVars(prioNets,false); cube->setState(_pdrGen->getGeneralizationResult()); }
// 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); } }
V3Formula::V3Formula(V3NtkHandler* const handler, const uint32_t& constrSize, const uint32_t& maxCard, const V3GateType& gateType, const uint32_t& noPIorFF) : _handler(handler) { assert (handler); assert (constrSize); assert (maxCard); assert (!(noPIorFF & ~3ul)); assert (BV_AND == gateType || BV_OR == gateType || BV_XOR == gateType || BV_XNOR == gateType); // Collect Leaf Candidates V3Ntk* const ntk = handler->getNtk(); assert (ntk); V3NetVec leafId; leafId.clear(); leafId.reserve(ntk->getInputSize() + ntk->getInoutSize() + ntk->getLatchSize()); if (!(1ul & noPIorFF)) { for (uint32_t i = 0; i < ntk->getInputSize(); ++i) if (1 == ntk->getNetWidth(ntk->getInput(i))) leafId.push_back(ntk->getInput(i)); for (uint32_t i = 0; i < ntk->getInoutSize(); ++i) if (1 == ntk->getNetWidth(ntk->getInout(i))) leafId.push_back(ntk->getInout(i)); } if (!(2ul & noPIorFF)) { for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) if (1 == ntk->getNetWidth(ntk->getLatch(i))) leafId.push_back(ntk->getLatch(i)); } V3UI32Vec constrId; constrId.clear(); constrId.reserve(constrSize); _formula.clear(); // Create Constraints for (uint32_t i = 0; i < constrSize; ++i) { const uint32_t startId = _formula.size(); // Create Leaf Nodes for (uint32_t j = 0; j < maxCard; ++j) { if (j && !(rand() % maxCard)) break; const V3NetId id = (rand() % 5) ? leafId[rand() % leafId.size()] : ~leafId[rand() % leafId.size()]; _formula.push_back(make_pair(V3_PI, V3InputVec())); _formula.back().second.push_back(V3NetType(id)); } assert (startId < _formula.size()); // Link Leaf Nodes with the Specified GateType for (uint32_t j = 0, k = _formula.size() - startId; j < k; ++j) { if (!j) constrId.push_back(startId + j); else { _formula.push_back(make_pair(gateType, V3InputVec())); _formula.back().second.push_back(constrId.back()); _formula.back().second.push_back(startId + j); constrId.back() = _formula.size() - 1; } } assert ((1 + i) == constrId.size()); } // Combine Constraints for (uint32_t i = 0; i < constrId.size(); ++i) { if (!i) _rootId = constrId[i]; else { _formula.push_back(make_pair(BV_AND, V3InputVec())); _formula.back().second.push_back(_rootId); _formula.back().second.push_back(constrId[i]); _rootId = _formula.size() - 1; } } }
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; }
// Constructor for Random Formula V3Formula::V3Formula(V3NtkHandler* const handler, const V3SimTraceVec& cexTrace, const double& strength) : _handler(handler) { assert (handler); assert (cexTrace.size()); assert (strength > 0 && strength <= 1.00); V3UI32Vec constrId; constrId.clear(); constrId.reserve(cexTrace.size()); _formula.clear(); // Create Constraints V3Ntk* const ntk = handler->getNtk(); assert (ntk); for (uint32_t i = 0; i < cexTrace.size(); ++i) { const uint32_t startId = _formula.size(), end = 1 + (uint32_t)(strength * ntk->getLatchSize()); assert (cexTrace[i].size()); assert (ntk->getLatchSize() == cexTrace[i].size()); for (uint32_t j = 0; j < end; ++j) { const uint32_t index = rand() % cexTrace[i].size(); assert (1 == ntk->getNetWidth(ntk->getLatch(index))); const V3NetId id = ('0' == cexTrace[i][index][0]) ? ~(ntk->getLatch(index)) : ntk->getLatch(index); _formula.push_back(make_pair(V3_PI, V3InputVec())); _formula.back().second.push_back(V3NetType(id)); } assert (startId <= _formula.size()); // Conjunction of Leaf Nodes for (uint32_t j = 0, k = _formula.size() - startId; j < k; ++j) { if (!j) constrId.push_back(startId + j); else { _formula.push_back(make_pair(BV_AND, V3InputVec())); _formula.back().second.push_back(constrId.back()); _formula.back().second.push_back(startId + j); constrId.back() = _formula.size() - 1; } } } // Disjunction of Constraints for (uint32_t i = 0; i < constrId.size(); ++i) { if (!i) _rootId = constrId[i]; else { _formula.push_back(make_pair(BV_OR, V3InputVec())); _formula.back().second.push_back(_rootId); _formula.back().second.push_back(constrId[i]); _rootId = _formula.size() - 1; } } }
//---------------------------------------------------------------------- // MITer NTk <(unsigned ntkId1)> <(unsigned ntkId2)> // [-Name <(string miterNtkName)>] [| -SEC | -CEC] [-Merge] //---------------------------------------------------------------------- V3CmdExecStatus V3MiterNtkCmd::exec(const string& option) { vector<string> options; V3CmdExec::lexOptions(option, options); uint32_t id1 = V3NtkUD, id2 = V3NtkUD; bool miterName = false, miterNameON = false; bool sec = false, cec = false, merge = false; string miterNtkName = ""; int temp; size_t n = options.size(); for (size_t i = 0; i < n; ++i) { const string& token = options[i]; if (v3StrNCmp("-Name", token, 2) == 0) { if (miterName) return V3CmdExec::errorOption(CMD_OPT_EXTRA, token); else miterName = miterNameON = true; } else if (v3StrNCmp("-SEC", token, 4) == 0) { if (sec || cec) return V3CmdExec::errorOption(CMD_OPT_EXTRA, token); else sec = true; } else if (v3StrNCmp("-CEC", token, 4) == 0) { if (sec || cec) return V3CmdExec::errorOption(CMD_OPT_EXTRA, token); else cec = true; } else if (v3StrNCmp("-Merge", token, 2) == 0) { if (merge) return V3CmdExec::errorOption(CMD_OPT_EXTRA, token); else merge = true; } else if (miterNameON) { miterNameON = false; miterNtkName = token; } else if (V3NtkUD == id1) { if (!v3Str2Int(token, temp)) return V3CmdExec::errorOption(CMD_OPT_ILLEGAL, "(unsigned ntkId1)"); else if (temp < 0) return V3CmdExec::errorOption(CMD_OPT_ILLEGAL, "(unsigned ntkId1)"); id1 = (uint32_t)temp; } else if (V3NtkUD == id2) { if (!v3Str2Int(token, temp)) return V3CmdExec::errorOption(CMD_OPT_ILLEGAL, "(unsigned ntkId2)"); else if (temp < 0) return V3CmdExec::errorOption(CMD_OPT_ILLEGAL, "(unsigned ntkId2)"); id2 = (uint32_t)temp; } else return V3CmdExec::errorOption(CMD_OPT_ILLEGAL, token); } if (V3NtkUD == id1) return V3CmdExec::errorOption(CMD_OPT_MISSING, "(unsigned ntkId1)"); if (V3NtkUD == id2) return V3CmdExec::errorOption(CMD_OPT_MISSING, "(unsigned ntkId2)"); if (miterNameON) return V3CmdExec::errorOption(CMD_OPT_MISSING, "(string miterNtkName)"); V3NtkHandler* const handler = v3Handler.getCurHandler(); if (handler) { if (id1 >= v3Handler.getHandlerCount()) Msg(MSG_ERR) << "Network with id = " << id1 << " Does NOT Exist !!" << endl; else if (id2 >= v3Handler.getHandlerCount()) Msg(MSG_ERR) << "Network with id = " << id2 << " Does NOT Exist !!" << endl; else { V3NtkHandler* const handler1 = v3Handler.getHandler(id1); assert (handler); V3NtkHandler* const handler2 = v3Handler.getHandler(id2); assert (handler); if (!(reportIncompatibleModule(handler1, handler2) || reportIncompatibleModule(handler1, handler2))) { if (!cec) { V3NtkMiter* const miterHandler = new V3NtkMiter(handler1, handler2, merge, miterNtkName); assert (miterHandler); v3Handler.pushAndSetCurHandler(miterHandler); } else { // Compute Name Mapping for Latches Between Two Networks if (handler1->getNtk()->getLatchSize() == handler2->getNtk()->getLatchSize()) { V3Map<string, uint32_t>::Map nameMap; nameMap.clear(); for (uint32_t i = 0; i < handler2->getNtk()->getLatchSize(); ++i) nameMap.insert(make_pair(handler2->getNetName(handler2->getNtk()->getLatch(i)), i)); if (handler2->getNtk()->getLatchSize() == nameMap.size()) { V3Map<string, uint32_t>::Map::const_iterator it; V3UI32Vec latchMap; latchMap.clear(); latchMap.reserve(handler1->getNtk()->getLatchSize()); for (uint32_t i = 0; i < nameMap.size(); ++i) { it = nameMap.find(handler1->getNetName(handler1->getNtk()->getLatch(i))); if ((nameMap.end() == it) || (handler1->getNtk()->getNetWidth(handler1->getNtk()->getLatch(i)) != handler2->getNtk()->getNetWidth(handler2->getNtk()->getLatch(it->second)))) break; else latchMap.push_back(it->second); } if (handler1->getNtk()->getLatchSize() == latchMap.size()) { V3NtkMiter* const miterHandler = new V3NtkMiter(handler1, handler2, latchMap, merge, miterNtkName); assert (miterHandler); v3Handler.pushAndSetCurHandler(miterHandler); } else Msg(MSG_ERR) << "Unmapped Latch " << latchMap.size() << " Found in Network " << id1 << " !!" << endl; } else Msg(MSG_ERR) << "Repeated or Missing Latch Names Exist !!" << endl; } else Msg(MSG_ERR) << "Number of Latches in Networks NOT Matched : " << id1 << "(" << handler1->getNtk()->getLatchSize() << ") != " << id2 << "(" << handler2->getNtk()->getLatchSize() << ") !!" << endl; } } } } else Msg(MSG_ERR) << "Empty Ntk !!" << endl; return CMD_EXEC_DONE; }
const V3NetId V3NtkElaborate::elaborateL2S(const V3NetId& id) { assert (_ntk); assert (_p2cMap.size()); assert (id.id < _ntk->getNetSize()); assert (isMutable()); assert (_shadow.size() == _handler->getNtk()->getLatchSize()); // Create L2S Data Members if NOT Exist V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); V3InputVec inputs; inputs.clear(); inputs.reserve(4); if (V3NetUD == _saved || V3NetUD == _1stSave || V3NetUD == _inLoop) { assert (V3NetUD == _saved && V3NetUD == _1stSave && V3NetUD == _inLoop); _saved = _ntk->createNet(1); // Create Latch (_saved) for "In the Loop" const V3NetId oracle = _ntk->createNet(1), inSaved = _ntk->createNet(1); inputs.push_back(~_saved); inputs.push_back(~oracle); _ntk->setInput(inSaved, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), inSaved); inputs.clear(); inputs.push_back(~inSaved); inputs.push_back(0); _ntk->setInput(_saved, inputs); _ntk->createLatch(_saved); inputs.clear(); _ntk->createInput(oracle); _1stSave = _ntk->createNet(1); // Create Net (_1stSave) for "Loop Start" inputs.push_back(oracle); inputs.push_back(~_saved); _ntk->setInput(_1stSave, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), _1stSave); inputs.clear(); _inLoop = _ntk->createNet(1); // Create Net (_inLoop) for "_1stSave || _saved" inputs.push_back(~_1stSave); inputs.push_back(~_saved); _ntk->setInput(_inLoop, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), _inLoop); inputs.clear(); _inLoop = ~_inLoop; } // Create Equivalence Logic and Shadow FF if NOT Exist V3NetId ffId; V3GateType type; V3UI32Vec newShadow; newShadow.clear(); for (uint32_t i = 0; i < _shadow.size(); ++i) { ffId = _p2cMap[_handler->getNtk()->getLatch(i).id]; assert (V3_FF == _ntk->getGateType(ffId)); if (V3NetUD == ffId || V3NetUD != _shadow[i]) continue; newShadow.push_back(i); // Create Net for Shadow FF _shadow[i] = _ntk->createNet(_ntk->getNetWidth(ffId)); assert (V3NetUD != _shadow[i]); V3NetId shadowMux = V3NetUD; // Create Input MUX of Shadow FF if (bvNtk) { inputs.push_back(_shadow[i]); inputs.push_back(ffId); inputs.push_back(_1stSave); type = BV_MUX; shadowMux = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { inputs.push_back(_1stSave); inputs.push_back(ffId); inputs.push_back(~_1stSave); inputs.push_back(_shadow[i]); type = AIG_NODE; shadowMux = elaborateAigAndOrAndGate(_ntk, inputs, _netHash); } // Create Shadow FF assert (V3NetUD != shadowMux); inputs.clear(); inputs.push_back(shadowMux); if (_ntk->getNetWidth(ffId) == 1) inputs.push_back(0); else { V3InputVec constInputs(1, bvNtk->hashV3ConstBitVec(v3Int2Str(_ntk->getNetWidth(ffId)) + "'d0")); type = BV_CONST; inputs.push_back(elaborateBvGate(bvNtk, type, constInputs, _netHash)); } _ntk->setInput(_shadow[i], inputs); _ntk->createLatch(_shadow[i]); inputs.clear(); // Create Equivalence Gate and Update _shadow if (bvNtk) { inputs.push_back(ffId); inputs.push_back(_shadow[i]); type = BV_EQUALITY; _shadow[i] = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { inputs.push_back(ffId); inputs.push_back(_shadow[i]); inputs.push_back(~ffId); inputs.push_back(~_shadow[i]); _shadow[i] = elaborateAigAndOrAndGate(_ntk, inputs, _netHash); } assert (V3NetUD != _shadow[i]); assert (1 == _ntk->getNetWidth(_shadow[i])); inputs.clear(); } // Create or Update Net (_looped) for "Loop Found" if NOT Exist if (V3NetUD == _looped) _looped = _saved; for (uint32_t i = 0; i < newShadow.size(); ++i) { assert (V3NetUD != _p2cMap[_handler->getNtk()->getLatch(i).id]); assert (V3NetUD != _shadow[i]); inputs.push_back(_looped); inputs.push_back(_shadow[i]); if (bvNtk) { type = BV_AND; _looped = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { type = AIG_NODE; _looped = elaborateAigGate(_ntk, type, inputs, _netHash); } assert (V3NetUD != _looped); inputs.clear(); } if (V3NetId::makeNetId(0) == ~id) return _looped; // Create Latch (pLatch) for Recording Existence of Violation to id const V3NetId pLatch = _ntk->createNet(1), in_pLatch = _ntk->createNet(1); inputs.push_back(~pLatch); inputs.push_back(id); _ntk->setInput(in_pLatch, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), in_pLatch); inputs.clear(); inputs.push_back(~in_pLatch); inputs.push_back(0); _ntk->setInput(pLatch, inputs); _ntk->createLatch(pLatch); inputs.clear(); // Create L2S Property Output (to Witness "_looped && in_pLatch") V3NetId pId = V3NetUD; inputs.push_back(_looped); inputs.push_back(in_pLatch); if (bvNtk) { type = BV_AND; pId = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { type = AIG_NODE; pId = elaborateAigGate(_ntk, type, inputs, _netHash); } assert (V3NetUD != pId); inputs.clear(); return pId; }