// 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); } }
// 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 size_t V3SvrBoolector::setTargetValue(const V3NetId& id, const V3BitVecX& value, const uint32_t& depth, const size_t& prev) { // Construct formula y = b0 & b1' & b3 & ... & bn', and return expr y if (prev) assert (!isNegFormula(prev)); // Constrain input prev expr should NOT be negative! uint32_t size = value.size(); assert (size == _ntk->getNetWidth(id)); BtorExp* const aExp = getVerifyData(id, depth); assert (aExp); BtorExp* pExp = (prev) ? boolector_copy(_Solver, getOriExp(prev)) : 0, *bExp, *cExp, *eExp; char* bv_value = new char[size + 1]; 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); eExp = boolector_eq(_Solver, bExp, cExp); boolector_release(_Solver, bExp); boolector_release(_Solver, cExp); if (pExp) { bExp = boolector_and(_Solver, pExp, eExp); boolector_release(_Solver, pExp); boolector_release(_Solver, eExp); pExp = bExp; } else pExp = eExp; j = 0; } } 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); eExp = boolector_eq(_Solver, bExp, cExp); boolector_release(_Solver, bExp); boolector_release(_Solver, cExp); if (pExp) { bExp = boolector_and(_Solver, pExp, eExp); boolector_release(_Solver, pExp); boolector_release(_Solver, eExp); pExp = bExp; } else pExp = eExp; } delete[] bv_value; assert (!isNegFormula(getPosExp(pExp))); return getPosExp(pExp); }
void SfMgr::solveSat(){ _satSolver = new V3SvrBoolector(_mergeNtk); uint32_t z=0; for(uint32_t i=0; i<_satNets.size();i++){ const V3NetId outid=_satNets[i]; static_cast<V3SvrBase*>(_satSolver)->addBoundedVerifyData(outid,z ); _satSolver->assumeProperty(outid, false, z); } _satSolver->simplify(); cout<<(_satSolver->assump_solve() ? "SAT" : "UNSAT")<<endl; V3BitVecX dataValue; for (int j = _mergeNtk->getOutputSize()-1; j >= 0; --j) { if (_satSolver->existVerifyData(_mergeNtk->getOutput(j), z)) { dataValue = _satSolver->getDataValue(_mergeNtk->getOutput(j), z); assert (dataValue.size() == _mergeNtk->getNetWidth(_mergeNtk->getOutput(j))); Msg(MSG_IFO) << dataValue[0]; } else Msg(MSG_IFO) << 'x'; } }
const string V3NtkHandler::getNetRecurExpression(const V3NetId& id) const { assert (_ntk); assert (id.id < _ntk->getNetSize()); string name = ""; const V3GateType& type = _ntk->getGateType(id); assert (V3_XD > type); if (V3_FF >= type) return (id.cp ? V3AuxNameInvPrefix : "") + v3Int2Str(id.id); else if (V3_MODULE == type) { Msg(MSG_WAR) << "Currently Expression Over Module Instances has NOT Been Implemented !!" << endl; } else { if (dynamic_cast<V3BvNtk*>(_ntk)) { assert (AIG_FALSE < type); if (isV3PairType(type)) { const string name1 = getNetExpression(_ntk->getInputNetId(id, 0)); assert (name1.size()); const string name2 = getNetExpression(_ntk->getInputNetId(id, 1)); assert (name2.size()); if (BV_MERGE == type) name = "{" + name1 + ", " + name2 + "}"; else { switch (type) { case BV_AND : name = "(" + name1 + " & " + name2 + ")"; break; case BV_XOR : name = "(" + name1 + " ^ " + name2 + ")"; break; case BV_ADD : name = "(" + name1 + " + " + name2 + ")"; break; case BV_SUB : name = "(" + name1 + " - " + name2 + ")"; break; case BV_MULT : name = "(" + name1 + " * " + name2 + ")"; break; case BV_SHL : name = "(" + name1 + " << " + name2 + ")"; break; case BV_SHR : name = "(" + name1 + " >> " + name2 + ")"; break; case BV_DIV : name = "(" + name1 + " / " + name2 + ")"; break; case BV_MODULO : name = "(" + name1 + " % " + name2 + ")"; break; case BV_EQUALITY : return "(" + name1 + (id.cp ? " != " : " == ") + name2 + ")"; case BV_GEQ : return "(" + name1 + (id.cp ? " < " : " >= ") + name2 + ")"; default : assert (0); } } } else if (isV3ReducedType(type)) { const string name1 = getNetExpression(_ntk->getInputNetId(id, 0)); assert (name1.size()); switch (type) { case BV_RED_AND : name = "(&(" + name1 + "))"; break; case BV_RED_OR : name = "(|(" + name1 + "))"; break; case BV_RED_XOR : name = "(^(" + name1 + "))"; break; default : assert (0); } } else if (BV_MUX == type) { const string fName = getNetExpression(_ntk->getInputNetId(id, 0)); assert (fName.size()); const string tName = getNetExpression(_ntk->getInputNetId(id, 1)); assert (tName.size()); const string sName = getNetExpression(_ntk->getInputNetId(id, 2)); assert (sName.size()); name = "(" + sName + " ? " + tName + " : " + fName + ")"; } else if (BV_SLICE == type) { const string name1 = getNetExpression(_ntk->getInputNetId(id, 0)); assert (name1.size()); const uint32_t msb = dynamic_cast<V3BvNtk*>(_ntk)->getInputSliceBit(id, true); const uint32_t lsb = dynamic_cast<V3BvNtk*>(_ntk)->getInputSliceBit(id, false); const uint32_t width = _ntk->getNetWidth(_ntk->getInputNetId(id, 0)); assert (width); name = ((msb >= lsb) && (width == (1 + msb - lsb))) ? name1 : (msb == lsb) ? ("(" + name1 + ")[" + v3Int2Str(msb) + "]") : ("(" + name1 + ")[" + v3Int2Str(msb) + ":" + v3Int2Str(lsb) + "]"); } else { assert (BV_CONST == type); const V3BitVecX value = dynamic_cast<V3BvNtk*>(_ntk)->getInputConstValue(id); return v3Int2Str(value.size()) + "'b" + value.regEx(); } } else { assert (AIG_FALSE >= type); if (AIG_NODE == type) { const string name1 = getNetExpression(_ntk->getInputNetId(id, 0)); assert (name1.size()); const string name2 = getNetExpression(_ntk->getInputNetId(id, 1)); assert (name2.size()); name = "(" + name1 + " && " + name2 + ")"; } else { assert (AIG_FALSE == type); return (id.cp ? "AIGER_TRUE" : "AIGER_FALSE"); } } } return (id.cp ? V3AuxNameInvPrefix : "") + name; }