Support foreach constraints (#5302)

Signed-off-by: Arkadiusz Kozdra <akozdra@antmicro.com>
This commit is contained in:
Arkadiusz Kozdra 2024-08-02 16:03:55 +02:00 committed by GitHub
parent a61178bd89
commit 54f9f4b6a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 108 additions and 11 deletions

View File

@ -513,9 +513,31 @@ class ConstraintExprVisitor final : public VNVisitor {
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void visit(AstForeach* nodep) override {}
void visit(AstConstraintForeach* nodep) override {
nodep->v3warn(CONSTRAINTIGN, "Constraint expression ignored (unsupported)");
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
// Convert to plain foreach
FileLine* const fl = nodep->fileline();
if (m_wantSingle) {
AstNode* const itemp = editSingle(fl, nodep->stmtsp());
AstNode* const cstmtp = new AstText{fl, "ret += \" \" + "};
cstmtp->addNext(itemp);
cstmtp->addNext(new AstText{fl, ";"});
AstNode* const exprsp = new AstText{fl, "([&]{ std::string ret = \"(and\";"};
exprsp->addNext(new AstBegin{
fl, "",
new AstForeach{fl, nodep->arrayp()->unlinkFrBack(), new AstCStmt{fl, cstmtp}},
false, true});
exprsp->addNext(new AstText{fl, "return ret + \")\"; })()"});
AstNodeExpr* const newp = new AstCExpr{fl, exprsp};
newp->dtypeSetString();
nodep->replaceWith(new AstSFormatF{fl, "%@", false, newp});
} else {
iterateAndNextNull(nodep->stmtsp());
nodep->replaceWith(new AstForeach{fl, nodep->arrayp()->unlinkFrBack(),
nodep->stmtsp()->unlinkFrBackWithNext()});
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void visit(AstConstraintBefore* nodep) override {
nodep->v3warn(CONSTRAINTIGN, "Constraint expression ignored (unsupported)");

View File

@ -0,0 +1,25 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
if (!$Self->have_solver) {
skip("No constraint solver installed");
} else {
compile(
);
execute(
check_finished => 1,
);
}
ok(1);
1;

View File

@ -0,0 +1,58 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
`define check_rand(cl, field, cond) \
begin \
longint prev_result; \
int ok = 0; \
for (int i = 0; i < 10; i++) begin \
longint result; \
if (!bit'(cl.randomize())) $stop; \
result = longint'(field); \
if (!(cond)) $stop; \
if (i > 0 && result != prev_result) ok = 1; \
prev_result = result; \
end \
if (ok != 1) $stop; \
end
class C;
rand int x;
int q[$] = {0, 0, 0, 0, 0};
constraint fore {
x < 7;
foreach(q[i])
x > i;
};
endclass
class D;
rand bit posit;
rand int x;
int q[$] = {0, 0, 0, 0, 0};
constraint fore {
if (posit == 1) {
x < 7;
foreach(q[i])
x > i;
} else {
x > -3;
foreach(q[i])
x < i;
}
};
endclass
module t;
initial begin
C c = new;
D d = new;
`check_rand(c, c.x, 4 < c.x && c.x < 7);
`check_rand(d, d.posit, (d.posit ? 4 : -3) < d.x && d.x < (d.posit ? 7 : 0));
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -4,10 +4,6 @@
| ^~~~
... 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.v:37:7: Constraint expression ignored (unsupported)
: ... note: In instance 't'
37 | foreach (array[i]) {
| ^~~~~~~
%Warning-CONSTRAINTIGN: t/t_randomize.v:40:7: Constraint expression ignored (unsupported)
: ... note: In instance 't'
40 | unique { array[0], array[1] };
@ -16,8 +12,4 @@
: ... note: In instance 't'
43 | constraint order { solve length before header; }
| ^~~~~
%Error-UNSUPPORTED: t/t_randomize.v:14:13: Unsupported: random member variable with type 'int$[0:1]'
: ... note: In instance 't'
14 | rand int array[2];
| ^~~~~
%Error: Exiting due to

View File

@ -11,7 +11,7 @@ class Packet;
rand bit if_4;
rand bit iff_5_6;
rand int array[2]; // 2,4,6
/*rand*/ int array[2]; // 2,4,6 // TODO: add rand when supported
constraint empty {}