This commit is contained in:
Yilou Wang 2026-02-15 10:04:43 +01:00 committed by GitHub
commit cd6d2e769c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 118 additions and 0 deletions

View File

@ -3224,6 +3224,34 @@ class RandomizeVisitor final : public VNVisitor {
}
}
randomizep->addStmtsp(implementConstraintsClear(fl, genp));
// Restrict enum variables in solver to valid members only
{
AstNodeModule* const genModp = VN_AS(genp->user2p(), NodeModule);
nodep->foreachMember([&](AstClass*, AstVar* memberVarp) {
if (!memberVarp->user3()) return;
AstEnumDType* const enumDtp
= VN_CAST(memberVarp->dtypep()->skipRefToEnump(), EnumDType);
if (!enumDtp) return;
const int width = enumDtp->width();
const std::string smtName = memberVarp->name();
std::string constraint = "(__Vbv (or";
for (AstEnumItem* itemp = enumDtp->itemsp(); itemp;
itemp = VN_AS(itemp->nextp(), EnumItem)) {
const AstConst* const vconstp = VN_AS(itemp->valuep(), Const);
constraint += " (= " + smtName + " (_ bv" + cvtToStr(vconstp->toUInt())
+ " " + cvtToStr(width) + "))";
}
constraint += "))";
AstCMethodHard* const callp = new AstCMethodHard{
fl, new AstVarRef{fl, genModp, genp, VAccess::READWRITE},
VCMethod::RANDOMIZER_HARD,
new AstCExpr{fl, AstCExpr::Pure{}, "\"" + constraint + "\""}};
callp->dtypeSetVoid();
randomizep->addStmtsp(callp->makeStmt());
});
}
AstTask* setupAllTaskp = getCreateConstraintSetupFunc(nodep);
AstTaskRef* const setupTaskRefp = new AstTaskRef{fl, setupAllTaskp, nullptr};
randomizep->addStmtsp(setupTaskRefp->makeStmt());

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,69 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 PlanV GmbH
// 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);
// verilog_format: on
// Test that randc enum variables with user constraints only produce
// valid enum members (not arbitrary bitvector values).
module t;
typedef enum bit [2:0] {
RED = 0,
GREEN = 1,
BLUE = 2,
WHITE = 3,
BLACK = 4
} color_t;
class ColorClass;
randc color_t color;
constraint c_no_dark { color != BLACK; }
endclass
// Test with all enum values allowed (no exclusion constraint)
class AllColorsClass;
randc color_t color;
constraint c_range { color <= WHITE; }
endclass
initial begin
ColorClass c;
AllColorsClass ac;
int color_seen[5];
// Test 1: randc enum with exclusion constraint
// Values must be valid enum members (0-4) and not BLACK (4)
c = new;
repeat (40) begin
`checkd(c.randomize(), 1);
// Must be a valid enum member (not 5, 6, 7)
`checkd(c.color <= BLACK, 1);
// Must not be BLACK (excluded by constraint)
`checkd(c.color == BLACK, 0);
end
// Test 2: randc enum with range constraint - verify all valid values seen
ac = new;
repeat (40) begin
`checkd(ac.randomize(), 1);
`checkd(ac.color <= WHITE, 1);
color_seen[ac.color] = 1;
end
// After 40 iterations (10 full cycles of 4), all values should appear
`checkd(color_seen[0], 1);
`checkd(color_seen[1], 1);
`checkd(color_seen[2], 1);
`checkd(color_seen[3], 1);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule