// General Level Computation Functions for V3 Ntk void dfsComputeLevel(V3Ntk* const ntk, V3NetVec& orderMap, V3UI32Vec& levelData) { assert (ntk); assert (orderMap.size() <= ntk->getNetSize()); assert (levelData.size() == ntk->getNetSize()); // Set Net Levels According to the DFS Order V3NetId id, id1; V3GateType type; uint32_t inSize; for (uint32_t i = 0; i < orderMap.size(); ++i) { id = orderMap[i]; assert (id.id < levelData.size()); if (V3NtkUD != levelData[id.id]) continue; levelData[id.id] = 0; type = ntk->getGateType(id); assert (V3_XD > type); assert (V3_PI == type || V3_FF < type); if (V3_MODULE == type) { V3NtkModule* const moduleNtk = ntk->getModule(id); assert (moduleNtk); const V3NetVec& inputs = moduleNtk->getInputList(); inSize = inputs.size(); while (inSize--) { id1 = inputs[inSize]; assert (V3NtkUD != levelData[id1.id]); if (levelData[id.id] < levelData[id1.id]) levelData[id.id] = levelData[id1.id]; } } else { inSize = ntk->getInputNetSize(id); if (BV_SLICE == type || BV_CONST == type) --inSize; while (inSize--) { id1 = ntk->getInputNetId(id, inSize); assert (V3NtkUD != levelData[id1.id]); if (levelData[id.id] < levelData[id1.id]) levelData[id.id] = levelData[id1.id]; } } ++levelData[id.id]; } }
// 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 V3NtkElaborate::elaborateFSMInvariants(V3FSM* const fsm, V3NetVec& constrList) { // NOTE: We add constraints follow the reachability, and // For FSM with Milestones, we also add constraints follows the milestones. assert (fsm); assert (_handler == fsm->getNtkHandler()); constrList.clear(); if (!_ntk || !_p2cMap.size()) return; // Omit FSM Without Invariants: Every milestone is reachable from any states if (!fsm->getStateSize()) return; uint32_t comb = 0, seq = 0; // Extract Combinational Invariants : G (state != some forward unreachable state) V3NetId id1; V3NetVec stateNets; V3UI32Vec reachStates; V3InputVec inputs(2); V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); for (uint32_t j = 0; j < fsm->getStateSize(); ++j) { if (V3NtkUD != fsm->getStepFwdFromInit(j)) continue; stateNets.clear(); fsm->getStateNetId(j, stateNets); assert (stateNets.size()); attachToNtk(_handler, _ntk, stateNets, _p2cMap, _c2pMap, _netHash); assert (_ntk); id1 = elaborateFSMState(stateNets, false); assert (id1.id < _ntk->getNetSize()); constrList.push_back(~id1); ++comb; } // Elaborate Sequential Invariants : nextOpState -> (j -> Prev(OR (reachStates))) const bool hasMileStone = fsm->getMileStoneSize(); if (hasMileStone) { for (uint32_t j = 0; j < fsm->getStateSize(); ++j) { if (!fsm->isMileStone(j)) continue; assert (V3NtkUD != fsm->getStepBwdFromTerm(j)); fsm->getStateBwdReachable(j, reachStates, true); if (fsm->getStateSize() == reachStates.size()) continue; if (fsm->getStateSize() < (reachStates.size() << 2)) continue; stateNets.clear(); fsm->getStateNetId(j, stateNets); assert (stateNets.size()); attachToNtk(_handler, _ntk, stateNets, _p2cMap, _c2pMap, _netHash); assert (_ntk); id1 = elaborateFSMState(stateNets, false); assert (id1.id < _ntk->getNetSize()); inputs[0] = ~id1; for (uint32_t k = 0; k < reachStates.size(); ++k) { stateNets.clear(); fsm->getStateNetId(reachStates[k], stateNets); assert (stateNets.size()); attachToNtk(_handler, _ntk, stateNets, _p2cMap, _c2pMap, _netHash); assert (_ntk); id1 = elaborateFSMState(stateNets, true); assert (id1.id < _ntk->getNetSize()); inputs[0] = ~(inputs[0].id); inputs[1] = ~id1; ++seq; inputs[0] = bvNtk ? ~elaborateBvGate(bvNtk, BV_AND, inputs, _netHash) : ~elaborateAigGate(_ntk, AIG_NODE, inputs, _netHash); } // Record Invariants inputs[0] = ~(inputs[0].id); inputs[1] = _nextOpId; assert (V3NetUD != _nextOpId); inputs[0] = bvNtk ? ~elaborateBvGate(bvNtk, BV_AND, inputs, _netHash) : ~elaborateAigGate(_ntk, AIG_NODE, inputs, _netHash); constrList.push_back(inputs[0].id); } } }
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 V3Handler::setLastHandler() { assert (getHandlerCount()); if (_curHandlerId == _lastHandlerId) return; const uint32_t curHandlerId = _curHandlerId; assert (getHandler(curHandlerId)); V3UI32Vec curRefIdVec = _curRefIdVec; assert (curRefIdVec.size()); _curHandlerId = _lastHandlerId; _curRefIdVec = _lastRefIdVec; _lastHandlerId = curHandlerId; _lastRefIdVec = curRefIdVec; }
// 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; }
void V3Handler::setCurHandlerFromPath(const string& path) { assert (path.size()); string curPath = path; uint32_t i; // Split Path by '/' V3Vec<string>::Vec idStr; idStr.clear(); while (curPath.size()) { for (i = 0; i < curPath.size(); ++i) if ('/' == curPath[i]) break; if (!i) idStr.push_back(""); else idStr.push_back(curPath.substr(0, i)); if ((i + 1) >= curPath.size()) break; else curPath = curPath.substr(i + 1); } // Copy Current Handler and RefId const uint32_t curHandlerId = _curHandlerId; assert (getHandler(curHandlerId)); V3UI32Vec curRefIdVec = _curRefIdVec; assert (curRefIdVec.size()); V3NtkHandler* handler = 0; bool isRoot = false; int temp; for (i = 0; i < idStr.size(); ++i) { if (handler) { // Expecting Sub-Module Index if (!idStr[i].size()) continue; if (v3Str2Int(idStr[i], temp)) { const uint32_t id = (uint32_t)temp; if (id < handler->getNtk()->getModuleSize()) { handler = handler->getNtk()->getModule(id)->getNtkRef(); uint32_t j = 0; for (; j < _ntkHandlerList.size(); ++j) if (handler == _ntkHandlerList[j]) break; _curHandlerId = j; _curRefIdVec.push_back(id); } else { string recoverPath = ""; for (uint32_t j = 0; j < _curRefIdVec.size(); ++j) recoverPath += ("/" + v3Int2Str(_curRefIdVec[j])); Msg(MSG_ERR) << "Sub-Module of " << recoverPath << " with Index = " << idStr[i] << " Does NOT Exist !!" << endl; return; } } } else { // Expecting NtkID or Location Symbols (/, ./, ~/, .) if (!idStr[i].size()) isRoot = true; else { // Lex if current token is a SubModule Index if (v3Str2Int(idStr[i], temp)) { const uint32_t id = (uint32_t)temp; if (isRoot) { if (id < getHandlerCount()) { handler = getHandler(id); _curHandlerId = id; _curRefIdVec.clear(); _curRefIdVec.push_back(id); } else { Msg(MSG_ERR) << "Ntk with ID = " << idStr[i] << " Does NOT Exist !!" << endl; return; } } else { if (id < getCurHandler()->getNtk()->getModuleSize()) { handler = getCurHandler()->getNtk()->getModule(id)->getNtkRef(); uint32_t j = 0; for (; j < _ntkHandlerList.size(); ++j) if (handler == _ntkHandlerList[j]) break; _curHandlerId = j; _curRefIdVec.push_back(id); } else { string recoverPath = ""; for (uint32_t j = 0; j < _curRefIdVec.size(); ++j) recoverPath += ("/" + v3Int2Str(_curRefIdVec[j])); Msg(MSG_ERR) << "Sub-Module of " << recoverPath << " with Index = " << idStr[i] << " Does NOT Exist !!" << endl; return; } } } else if (idStr[i].size() > 1) { Msg(MSG_ERR) << "Unexpected Symbol \"" << idStr[i] << "\" in the Path !!" << endl; return; } else if ('~' == idStr[i][0]) { const uint32_t baseId = _curHandlerId = _curRefIdVec[0]; handler = getHandler(baseId); _curRefIdVec.clear(); _curRefIdVec.push_back(baseId); } else if ('.' == idStr[i][0]) handler = getCurHandler(); assert (handler); } } } // Copy Data for Last if Valid, Or Resume Data for Current if (_curHandlerId < _ntkHandlerList.size()) { _lastHandlerId = curHandlerId; _lastRefIdVec = curRefIdVec; } else { _curHandlerId = curHandlerId; _curRefIdVec = curRefIdVec; Msg(MSG_ERR) << "Network " << path << " was Implicitly Created and it is Currently Untraceable !!" << endl; } }
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; }