diff --git a/include/verilated_random.cpp b/include/verilated_random.cpp index 989a79a05..0854a4a1e 100644 --- a/include/verilated_random.cpp +++ b/include/verilated_random.cpp @@ -998,24 +998,24 @@ bool VlRandomizer::nextPhased(VlRNG& rngr) { // Step 3: Solve phase by phase std::map solvedValues; // varName -> SMT value literal + bool hasNonEnumArray = false; + for (const auto& var : m_vars) { + if (var.second->dimension() == 0) continue; + if (var.second->countMatchingElements(m_arr_vars, var.second->name()) == 0) { + hasNonEnumArray = true; + break; + } + } + const char* const logicp = hasNonEnumArray ? "ALL" : "QF_ABV"; + for (size_t phase = 0; phase < layers.size(); phase++) { const bool isFinalPhase = (phase == layers.size() - 1); std::iostream& os = getSolver(); if (!os) return false; - // Solver session setup os << "(set-option :produce-models true)\n"; - // Non-enumerable containers are pinned as a whole array and need ALL. - bool hasNonEnumArray = false; - for (const auto& var : m_vars) { - if (var.second->dimension() > 0 - && var.second->countMatchingElements(m_arr_vars, var.second->name()) == 0) { - hasNonEnumArray = true; - break; - } - } - os << "(set-logic " << (hasNonEnumArray ? "ALL" : "QF_ABV") << ")\n"; + os << "(set-logic " << logicp << ")\n"; os << "(define-fun __Vbv ((b Bool)) (_ BitVec 1) (ite b #b1 #b0))\n"; os << "(define-fun __Vbool ((v (_ BitVec 1))) Bool (= #b1 v))\n"; @@ -1030,10 +1030,7 @@ bool VlRandomizer::nextPhased(VlRNG& rngr) { os << ")\n"; } - // Skip a pin the solver emitted as its own as-array/lambda model text. for (const auto& entry : solvedValues) { - if (entry.second.find("as-array") != std::string::npos) continue; - if (entry.second.find("(lambda") != std::string::npos) continue; os << "(assert (= " << entry.first << " " << entry.second << "))\n"; } @@ -1084,7 +1081,6 @@ bool VlRandomizer::nextPhased(VlRNG& rngr) { os << "(get-value ("; for (const auto& varName : layerVars) { const auto it = m_vars.find(varName); - if (it == m_vars.end()) continue; if (it->second->dimension() > 0) { auto arrVarsp = std::make_shared(m_arr_vars); it->second->setArrayInfo(arrVarsp); @@ -1125,25 +1121,20 @@ bool VlRandomizer::nextPhased(VlRNG& rngr) { // LHS: the queried term echoed back, a name or (select ...) group. os >> std::ws; std::string name; - char first; - os.get(first); - if (first == '(') { + if (os.peek() == '(') { + os.get(c); readGroup(name); } else { - name = first; - while (os.get(c) && c != ' ' && c != '\t' && c != '\n' && c != '\r') { - name += c; - } + os >> name; } os >> std::ws; std::string value; - os.get(first); - if (first == '(') { + if (os.peek() == '(') { + os.get(c); readGroup(value); os >> c; // pair-closing ')' } else { - value = first; while (os.get(c) && c != ')') { value += c; } const size_t end = value.find_last_not_of(" \t\n\r"); if (end != std::string::npos) value = value.substr(0, end + 1); diff --git a/test_regress/t/t_constraint_solve_before_array.v b/test_regress/t/t_constraint_solve_before_array.v index 75657c2b1..535b8f462 100644 --- a/test_regress/t/t_constraint_solve_before_array.v +++ b/test_regress/t/t_constraint_solve_before_array.v @@ -62,12 +62,23 @@ class Que; // dynamic container solved before a scalar } endclass +class ScFirst; // scalar solved before an array + rand int unsigned xw; + rand int unsigned a[2]; + constraint c { + solve xw before a; + xw inside {[1:5]}; + foreach (a[i]) a[i] == xw + i; + } +endclass + module t; OneD o1; TwoD o2; Mul om; Chain oc; Que oq; + ScFirst osf; int ok; initial begin o1 = new; @@ -75,6 +86,7 @@ module t; om = new; oc = new; oq = new; + osf = new; for (int i = 0; i < 10; ++i) begin ok = o1.randomize(); `checkd(ok, 1); @@ -98,6 +110,11 @@ module t; ok = oq.randomize(); `checkd(ok, 1); `checkd(oq.s, oq.q[0] + oq.q[1] + oq.q[2]); + + ok = osf.randomize(); + `checkd(ok, 1); + `checkd(osf.a[0], osf.xw); + `checkd(osf.a[1], osf.xw + 1); end $write("*-* All Finished *-*\n"); $finish;