Add parsing of solve-before inside foreach (#6934)

This commit is contained in:
Pawel Kojma 2026-01-20 13:14:11 +01:00 committed by GitHub
parent ea9752ab43
commit c4dcdeab9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 86 additions and 6 deletions

View File

@ -1309,8 +1309,9 @@ class ConstraintExprVisitor final : public VNVisitor {
// Convert to plain foreach
FileLine* const fl = nodep->fileline();
AstNode* const arrayp = nodep->arrayp()->unlinkFrBack();
if (m_wantSingle) {
if (!nodep->stmtsp()) {
nodep->unlinkFrBack();
} else if (m_wantSingle) {
AstNodeExpr* const itemp = editSingle(fl, nodep->stmtsp());
AstCStmt* const cstmtp = new AstCStmt{fl};
cstmtp->add("ret += \" \";\n");
@ -1320,14 +1321,17 @@ class ConstraintExprVisitor final : public VNVisitor {
AstCExpr* const cexprp = new AstCExpr{fl};
cexprp->dtypeSetString();
cexprp->add("([&]{\nstd::string ret;\n");
cexprp->add(new AstBegin{fl, "", new AstForeach{fl, arrayp, cstmtp}, true});
cexprp->add(new AstBegin{
fl, "", new AstForeach{fl, nodep->arrayp()->unlinkFrBack(), cstmtp}, true});
cexprp->add("return ret.empty() ? \"#b1\" : \"(bvand\" + ret + \")\";\n})()");
nodep->replaceWith(new AstSFormatF{fl, "%@", false, cexprp});
} else {
iterateAndNextNull(nodep->stmtsp());
nodep->replaceWith(new AstBegin{
fl, "", new AstForeach{fl, arrayp, nodep->stmtsp()->unlinkFrBackWithNext()},
true});
nodep->replaceWith(
new AstBegin{fl, "",
new AstForeach{fl, nodep->arrayp()->unlinkFrBack(),
nodep->stmtsp()->unlinkFrBackWithNext()},
true});
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}

View File

@ -7846,7 +7846,13 @@ constraint_primary<nodeExprp>: // ==IEEE: constraint_primary
constraint_expressionList<nodep>: // ==IEEE: { constraint_expression }
constraint_expression { $$ = $1; }
| ySOLVE solve_before_list yBEFORE solve_before_list ';'
{ ($<fl>1)->v3warn(CONSTRAINTIGN, "Ignoring unsupported: solve-before only supported as top-level constraint statement");
$$ = nullptr; DEL($2, $4); }
| constraint_expressionList constraint_expression { $$ = addNextNull($1, $2); }
| constraint_expressionList ySOLVE solve_before_list yBEFORE solve_before_list ';'
{ ($<fl>2)->v3warn(CONSTRAINTIGN, "Ignoring unsupported: solve-before only supported as top-level constraint statement");
$$ = $1; DEL($3, $5); }
;
constraint_expression<nodep>: // ==IEEE: constraint_expression

View File

@ -0,0 +1,12 @@
%Warning-CONSTRAINTIGN: t/t_constraint_solve_before_unsup.v:20:7: Ignoring unsupported: solve-before only supported as top-level constraint statement
20 | solve x before data[i];
| ^~~~~
... 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_constraint_solve_before_unsup.v:29:7: Ignoring unsupported: solve-before only supported as top-level constraint statement
29 | solve x before cfg[i].w, cfg[i].r;
| ^~~~~
%Warning-CONSTRAINTIGN: t/t_constraint_solve_before_unsup.v:30:7: Ignoring unsupported: solve-before only supported as top-level constraint statement
30 | solve cfg[i].l before cfg[i].x;
| ^~~~~
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# 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
import vltest_bootstrap
test.scenarios('vlt')
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,42 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2026 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
typedef struct {
rand bit l;
rand bit x;
rand bit w;
rand bit r;
} reg_t;
class Packet;
rand bit [7:0] data[5];
rand bit x;
constraint c_data {
foreach (data[i]) {
solve x before data[i];
data[i] inside {8'h10, 8'h20, 8'h30, 8'h40, 8'h50};
}
}
rand reg_t cfg[];
constraint solves_only_c {
foreach (cfg[i]) {
solve x before cfg[i].w, cfg[i].r;
solve cfg[i].l before cfg[i].x;
}
}
endclass
module t;
Packet p;
initial begin
p = new;
void'(p.randomize());
end
endmodule