mirror of
https://github.com/verilator/verilator.git
synced 2026-09-06 08:57:23 +02:00
Support soft foreach in constraint (#8174)
This commit is contained in:
+8
-2
@@ -1675,10 +1675,16 @@ public:
|
||||
// === AstNodeForeach ===
|
||||
class AstConstraintForeach final : public AstNodeForeach {
|
||||
// Constraint foreach statement
|
||||
bool m_soft; // is soft foreach, non-standard extension
|
||||
public:
|
||||
AstConstraintForeach(FileLine* fl, AstForeachHeader* headerp, AstNode* bodyp)
|
||||
: ASTGEN_SUPER_ConstraintForeach(fl, headerp, bodyp) {}
|
||||
AstConstraintForeach(FileLine* fl, AstForeachHeader* headerp, AstNode* bodyp,
|
||||
bool soft = false)
|
||||
: ASTGEN_SUPER_ConstraintForeach(fl, headerp, bodyp)
|
||||
, m_soft{soft} {}
|
||||
ASTGEN_MEMBERS_AstConstraintForeach;
|
||||
bool isSoft() const { return m_soft; }
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
class AstForeach final : public AstNodeForeach {
|
||||
public:
|
||||
|
||||
@@ -2307,6 +2307,14 @@ void AstCover::dumpJson(std::ostream& str) const {
|
||||
dumpJsonBoolFuncIf(str, isSeqEvent);
|
||||
this->AstNodeCoverOrAssert::dumpJson(str);
|
||||
}
|
||||
void AstConstraintForeach::dump(std::ostream& str) const {
|
||||
this->AstNodeForeach::dump(str);
|
||||
if (isSoft()) str << "[SOFT]";
|
||||
}
|
||||
void AstConstraintForeach::dumpJson(std::ostream& str) const {
|
||||
dumpJsonBoolFuncIf(str, isSoft);
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
void AstClocking::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (isDefault()) str << " [DEFAULT]";
|
||||
|
||||
@@ -298,6 +298,12 @@ class LinkParseVisitor final : public VNVisitor {
|
||||
v3Global.useRandomizeMethods(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstConstraintForeach* nodep) override {
|
||||
if (nodep->isSoft()) {
|
||||
nodep->v3warn(NONSTD, "Non-standard soft foreach");
|
||||
nodep->foreach([](AstConstraintExpr* exprp) { exprp->isSoft(true); });
|
||||
}
|
||||
}
|
||||
void visit(AstEnumDType* nodep) override {
|
||||
if (nodep->name() == "") {
|
||||
nodep->name(nameFromTypedef(nodep)); // Might still remain ""
|
||||
|
||||
@@ -8166,6 +8166,9 @@ constraint_expression<nodep>: // ==IEEE: constraint_expression
|
||||
// // IEEE says array_identifier here, but dotted accepted in VMM + 1800-2009
|
||||
| yFOREACH '(' idClassSelForeach ')' constraint_set
|
||||
{ $$ = new AstConstraintForeach{$1, $3, $5}; }
|
||||
// // Non-IEEE extension, soft foreach
|
||||
| ySOFT yFOREACH '(' idClassSelForeach ')' constraint_set
|
||||
{ $$ = new AstConstraintForeach{$2, $4, $6, true}; }
|
||||
// // soft is 1800-2012
|
||||
| yDISABLE ySOFT constraint_primary ';'
|
||||
{ AstConstraintExpr* const newp = new AstConstraintExpr{$1, $3};
|
||||
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
if not test.have_solver:
|
||||
test.skip("No constraint solver installed")
|
||||
|
||||
test.compile(verilator_flags2=["--Wno-NONSTD"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
@@ -0,0 +1,94 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
`define check_range(gotv,minv,maxv) do if ((gotv) < (minv) || (gotv) > (maxv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d-%0d\n", `__FILE__,`__LINE__, (gotv), (minv), (maxv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
class Cls1;
|
||||
rand int arr[10];
|
||||
constraint c_cls {
|
||||
soft foreach(arr[i]) arr[i] == i;
|
||||
}
|
||||
endclass
|
||||
|
||||
class Cls2;
|
||||
rand int arr[10];
|
||||
constraint c_cls {
|
||||
soft foreach(arr[i]) arr[i] == i;
|
||||
arr[1] == 10;
|
||||
}
|
||||
endclass
|
||||
|
||||
class Cls3;
|
||||
rand int arr[10];
|
||||
constraint c_cls {
|
||||
soft foreach(arr[i]) arr[i] < i;
|
||||
arr[5] == 3;
|
||||
}
|
||||
endclass
|
||||
|
||||
class Cls4;
|
||||
rand int arr[10][20];
|
||||
rand bit a;
|
||||
constraint c_cls {
|
||||
soft foreach(arr[i])
|
||||
foreach (arr[i][j])
|
||||
soft arr[i][j] == i + j;
|
||||
arr[5][10] == 2;
|
||||
}
|
||||
endclass
|
||||
|
||||
module t;
|
||||
Cls1 cls1;
|
||||
Cls2 cls2;
|
||||
Cls3 cls3;
|
||||
Cls4 cls4;
|
||||
int ok;
|
||||
|
||||
initial begin
|
||||
cls1 = new;
|
||||
cls2 = new;
|
||||
cls3 = new;
|
||||
cls4 = new;
|
||||
ok = cls1.randomize();
|
||||
`checkd(ok, 1);
|
||||
foreach(cls1.arr[i]) begin
|
||||
`checkd(cls1.arr[i], i);
|
||||
end
|
||||
|
||||
ok = cls2.randomize();
|
||||
`checkd(ok, 1);
|
||||
foreach(cls2.arr[i]) begin
|
||||
if (i != 1)
|
||||
`checkd(cls2.arr[i], i);
|
||||
end
|
||||
`checkd(cls2.arr[1], 10);
|
||||
|
||||
repeat (10) begin
|
||||
ok = cls3.randomize();
|
||||
`checkd(ok, 1);
|
||||
foreach(cls3.arr[i]) begin
|
||||
if (cls3.arr[i] >= i) $stop;
|
||||
end
|
||||
`checkd(cls3.arr[5], 3);
|
||||
end
|
||||
|
||||
ok = cls4.randomize();
|
||||
`checkd(ok, 1);
|
||||
foreach(cls4.arr[i, j]) begin
|
||||
if (i != 5 || j != 10) begin
|
||||
`checkd(cls4.arr[i][j], i+j);
|
||||
end
|
||||
end
|
||||
`checkd(cls4.arr[5][10], 2);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,15 @@
|
||||
%Warning-NONSTD: t/t_randomize_soft_foreach.v:16:10: Non-standard soft foreach
|
||||
16 | soft foreach(arr[i]) arr[i] == i;
|
||||
| ^~~~~~~
|
||||
... For warning description see https://verilator.org/warn/NONSTD?v=latest
|
||||
... Use "/* verilator lint_off NONSTD */" and lint_on around source to disable this message.
|
||||
%Warning-NONSTD: t/t_randomize_soft_foreach.v:23:10: Non-standard soft foreach
|
||||
23 | soft foreach(arr[i]) arr[i] == i;
|
||||
| ^~~~~~~
|
||||
%Warning-NONSTD: t/t_randomize_soft_foreach.v:31:10: Non-standard soft foreach
|
||||
31 | soft foreach(arr[i]) arr[i] < i;
|
||||
| ^~~~~~~
|
||||
%Warning-NONSTD: t/t_randomize_soft_foreach.v:40:10: Non-standard soft foreach
|
||||
40 | soft foreach(arr[i])
|
||||
| ^~~~~~~
|
||||
%Error: Exiting due to
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('linter')
|
||||
test.top_filename = 't/t_randomize_soft_foreach.v'
|
||||
|
||||
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
Reference in New Issue
Block a user