Fix unique constraint in derived class (#7022)

This commit is contained in:
Igor Zaworski 2026-02-09 15:56:38 +01:00 committed by GitHub
parent a28bd5a085
commit a660fa54a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 198 additions and 7 deletions

View File

@ -1339,15 +1339,34 @@ class ConstraintExprVisitor final : public VNVisitor {
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
void visit(AstConstraintUnique* nodep) override {
if (!m_classp) return;
if (!m_classp) {
nodep->v3warn(CONSTRAINTIGN,
"Unsupported: Unique constraint in std::randomize() with {}");
pushDeletep(nodep->unlinkFrBack());
return;
}
UASSERT_OBJ(m_classp, nodep, "m_classp not set");
FileLine* const fl = nodep->fileline();
AstNodeFTask* const initTaskp = VN_AS(m_memberMap.findMember(m_classp, "new"), NodeFTask);
if (!initTaskp) return;
UASSERT_OBJ(initTaskp, nodep, "Class has no init Task");
AstVar* const genVarp = VN_AS(m_classp->user3p(), Var);
if (!genVarp) return;
AstVar* const genVarp = [](const AstClass* classp) {
while (classp->extendsp()) classp = classp->extendsp()->classp();
return VN_AS(classp->user3p(), Var);
}(m_classp);
// UASSERT_OBJ(genVarp, nodep, "No generator variable");
if (!genVarp) {
// This shall be substituted with an assert when it will be supported
nodep->v3warn(CONSTRAINTIGN, "Unsupported: Unique constraint in randomize() with {}");
pushDeletep(nodep->unlinkFrBack());
return;
}
AstNodeModule* const modp = VN_AS(genVarp->user2p(), NodeModule);
UASSERT_OBJ(modp, nodep, "genVarp has no NodeModule set");
for (AstNode* itemp = nodep->rangesp(); itemp; itemp = itemp->nextp()) {
if (AstVarRef* const varRefp = VN_CAST(itemp, VarRef)) {
@ -1380,8 +1399,9 @@ class ConstraintExprVisitor final : public VNVisitor {
continue;
}
AstCMethodHard* const wCallp = new AstCMethodHard{
fl, new AstVarRef{fl, genVarp, VAccess::READ}, VCMethod::RANDOMIZER_WRITE_VAR};
AstCMethodHard* const wCallp
= new AstCMethodHard{fl, new AstVarRef{fl, modp, genVarp, VAccess::READ},
VCMethod::RANDOMIZER_WRITE_VAR};
wCallp->addPinsp(new AstVarRef{fl, varp, VAccess::READ});
wCallp->addPinsp(new AstConst{fl, AstConst::Unsized64{},
static_cast<uint64_t>(varp->dtypep()->width())});
@ -1406,7 +1426,7 @@ class ConstraintExprVisitor final : public VNVisitor {
uPins->addNext(new AstConst{fl, arraySize});
AstCMethodHard* const uCallp
= new AstCMethodHard{fl, new AstVarRef{fl, genVarp, VAccess::READ},
= new AstCMethodHard{fl, new AstVarRef{fl, modp, genVarp, VAccess::READ},
VCMethod::RANDOMIZER_UNIQUE, uPins};
uCallp->dtypep(nodep->findVoidDType());
initTaskp->addStmtsp(new AstStmtExpr{fl, uCallp});

View File

@ -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()
test.execute()
test.passes()

View File

@ -0,0 +1,51 @@
// 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
typedef enum bit [4:0] {
ZERO = 5'b00000,
RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7,
S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6
} EnumType;
class Base;
rand EnumType b_scratch_reg;
rand EnumType b_pmp_reg[2];
rand EnumType b_sp;
rand EnumType b_tp;
constraint b_example_constraint {
unique {b_pmp_reg};
{b_pmp_reg[0] > 0};
{b_pmp_reg[0] < 3};
{b_pmp_reg[1] > 0};
{b_pmp_reg[1] < 3};
}
endclass
class Foo extends Base;
rand EnumType scratch_reg;
rand EnumType pmp_reg[2];
rand EnumType sp;
rand EnumType tp;
constraint example_constraint {
unique {pmp_reg};
{pmp_reg[0] > 0};
{pmp_reg[0] < 3};
{pmp_reg[1] > 0};
{pmp_reg[1] < 3};
}
endclass
module t;
Foo foo;
initial begin
foo = new;
repeat(100) if (foo.randomize() != 1 || foo.pmp_reg[0] == foo.pmp_reg[1]) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,7 @@
%Warning-CONSTRAINTIGN: t/t_constraint_unq_arr_derived_inline_unsup.v:32:7: Unsupported: Unique constraint in randomize() with {}
: ... note: In instance 't'
32 | unique{foo.pmp_reg};
| ^~~~~~
... 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.
%Error: Exiting due to

View File

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

View File

@ -0,0 +1,39 @@
// 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
typedef enum bit [4:0] {
ZERO = 5'b00000,
RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7,
S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6
} EnumType;
class Base;
rand EnumType b_scratch_reg;
rand EnumType b_pmp_reg[2];
rand EnumType b_sp;
rand EnumType b_tp;
endclass
class Foo extends Base;
rand EnumType scratch_reg;
rand EnumType pmp_reg[2];
rand EnumType sp;
rand EnumType tp;
endclass
module t;
Foo foo;
initial begin
foo = new;
repeat(100) if (foo.randomize() with {
unique{foo.pmp_reg};
foo.pmp_reg[0] inside {1,2};
foo.pmp_reg[1] inside {1,2};}
!= 1 || foo.pmp_reg[0] == foo.pmp_reg[1]) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,7 @@
%Warning-CONSTRAINTIGN: t/t_std_randomize_unsup_unq_arr.v:10:39: Unsupported: Unique constraint in std::randomize() with {}
: ... note: In instance 't'
10 | if (!bit'(std::randomize(x) with {unique{x};}) || x[0] == x[1]) $stop;
| ^~~~~~
... 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.
%Error: Exiting due to

View File

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

View File

@ -0,0 +1,14 @@
// 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
module t;
initial begin
bit x[2];
if (!bit'(std::randomize(x) with {unique{x};}) || x[0] == x[1]) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule