diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 0390e3cbc..c920cc1cb 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -438,26 +438,16 @@ class RandomizeMarkVisitor final : public VNVisitor { if (nodep->varp()->lifetime().isStatic()) m_staticRefs.emplace(nodep); - if (!nodep->varp()->rand().isRandomizable()) return; - for (AstNode* backp = nodep; backp != m_constraintExprGenp && !backp->user1(); - backp = backp->backp()) - backp->user1(true); + if (nodep->varp()->rand().isRandomizable()) nodep->user1(true); } void visit(AstMemberSel* nodep) override { if (!m_constraintExprGenp) return; - if (VN_IS(nodep->fromp(), LambdaArgRef)) { - if (!nodep->varp()->rand().isRandomizable()) return; - for (AstNode* backp = nodep; backp != m_constraintExprGenp && !backp->user1(); - backp = backp->backp()) - backp->user1(true); - } - } - void visit(AstArraySel* nodep) override { - if (!m_constraintExprGenp) return; - for (AstNode* backp = nodep; backp != m_constraintExprGenp && !backp->user1(); - backp = backp->backp()) - backp->user1(true); iterateChildrenConst(nodep); + // Member select are randomized when both object and member are marked as rand. + // Variable references in with clause are converted to member selects and their from() is + // of type AstLambdaArgRef. They are randomized too. + const bool randObject = nodep->fromp()->user1() || VN_IS(nodep->fromp(), LambdaArgRef); + nodep->user1(randObject && nodep->varp()->rand().isRandomizable()); } void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); @@ -473,6 +463,14 @@ class RandomizeMarkVisitor final : public VNVisitor { iterateChildrenConst(nodep); } + void visit(AstNodeExpr* nodep) override { + iterateChildrenConst(nodep); + if (!m_constraintExprGenp) return; + nodep->user1((nodep->op1p() && nodep->op1p()->user1()) + || (nodep->op2p() && nodep->op2p()->user1()) + || (nodep->op3p() && nodep->op3p()->user1()) + || (nodep->op4p() && nodep->op4p()->user1())); + } void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } public: @@ -735,6 +733,12 @@ class ConstraintExprVisitor final : public VNVisitor { handle.relink(indexp); editSMT(nodep, nodep->fromp(), indexp); } + void visit(AstMemberSel* nodep) override { + if (nodep->user1()) { + nodep->v3warn(CONSTRAINTIGN, "Global constraints ignored (unsupported)"); + } + editFormat(nodep); + } void visit(AstSFormatF* nodep) override {} void visit(AstStmtExpr* nodep) override {} void visit(AstConstraintIf* nodep) override { diff --git a/test_regress/t/t_constraint_state.v b/test_regress/t/t_constraint_state.v index 799dea166..f89f2819a 100644 --- a/test_regress/t/t_constraint_state.v +++ b/test_regress/t/t_constraint_state.v @@ -4,12 +4,50 @@ // any use, without warranty, 2023 by Antmicro Ltd. // SPDX-License-Identifier: CC0-1.0 + +`define check_rand(cl, field, cond) \ +begin \ + longint prev_result; \ + int ok = 0; \ + if (!bit'(cl.randomize())) $stop; \ + prev_result = longint'(field); \ + if (!(cond)) $stop; \ + repeat(9) begin \ + longint result; \ + if (!bit'(cl.randomize())) $stop; \ + result = longint'(field); \ + if (!(cond)) $stop; \ + if (result != prev_result) ok = 1; \ + prev_result = result; \ + end \ + if (ok != 1) $stop; \ +end + +class Foo; + int x; +endclass + +class Bar; + rand int y; +endclass + class Packet; rand int rf; int state; + rand int a; + rand Foo foo; + Bar bar; - constraint c { rf == state; } + constraint c1 { rf == state; } + constraint c2 { a > foo.x; a < bar.y; } + function new(int s, int x, int y); + state = s; + foo = new; + foo.x = x; + bar = new; + bar.y = y; + endfunction endclass module t (/*AUTOARG*/); @@ -19,12 +57,15 @@ module t (/*AUTOARG*/); int v; initial begin - p = new; - p.state = 123; + p = new(123, 10, 20); v = p.randomize(); if (v != 1) $stop; if (p.rf != 123) $stop; + `check_rand(p, p.a, p.a > 10 && p.a < 20) + if (p.foo.x != 10) $stop; + if (p.bar.y != 20) $stop; + p.state = 234; v = p.randomize(); if (v != 1) $stop; diff --git a/test_regress/t/t_randomize_method_types_unsup.out b/test_regress/t/t_randomize_method_types_unsup.out index 4b53e95ef..4dd60a0a9 100644 --- a/test_regress/t/t_randomize_method_types_unsup.out +++ b/test_regress/t/t_randomize_method_types_unsup.out @@ -1,17 +1,20 @@ -%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:17:17: Unsupported: randomizing this expression, treating as state - 17 | dynarr[1].size < 10; +%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:23:17: Unsupported: randomizing this expression, treating as state + 23 | dynarr[1].size < 10; | ^~~~ ... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest ... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message. -%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:21:9: Size constraint combined with element constraint may not work correctly +%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:27:9: Size constraint combined with element constraint may not work correctly : ... note: In instance 't' - 21 | q.size < 5; + 27 | q.size < 5; | ^~~~ -%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:11:13: Unsupported: random member variable with the type of the containing class +%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:31:10: Global constraints ignored (unsupported) + 31 | foo.x < y; + | ^ +%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:13: Unsupported: random member variable with the type of the containing class : ... note: In instance 't' - 11 | rand Cls cls; + 15 | rand Cls cls; | ^~~ -%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:33:43: Unsupported: randomizing this expression, treating as state - 33 | res = obj.randomize() with { dynarr.size > 2; }; +%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:43:43: Unsupported: randomizing this expression, treating as state + 43 | res = obj.randomize() with { dynarr.size > 2; }; | ^~~~ %Error: Exiting due to diff --git a/test_regress/t/t_randomize_method_types_unsup.v b/test_regress/t/t_randomize_method_types_unsup.v index b68abf141..f100eeac9 100644 --- a/test_regress/t/t_randomize_method_types_unsup.v +++ b/test_regress/t/t_randomize_method_types_unsup.v @@ -4,12 +4,18 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +class Foo; + rand int x; +endclass + class Cls; rand int assocarr[string]; rand int dynarr[][]; rand int q[$]; rand Cls cls; rand int i; + rand Foo foo; + rand int y; int st; constraint dynsize { dynarr.size < 20; @@ -21,6 +27,9 @@ class Cls; q.size < 5; q[i] < 10; } + constraint global_constraint { + foo.x < y; + } endclass module t (/*AUTOARG*/); @@ -29,6 +38,7 @@ module t (/*AUTOARG*/); initial begin obj = new; + obj.foo = new; res = obj.randomize(); res = obj.randomize() with { dynarr.size > 2; }; end