This commit is contained in:
parent
4357aee09a
commit
ed3aa43657
|
|
@ -3338,6 +3338,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());
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
// 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];
|
||||
int first_seq, all_same, this_seq;
|
||||
|
||||
// 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);
|
||||
`checkd(c.color <= BLACK, 1);
|
||||
`checkd(c.color == BLACK, 0);
|
||||
end
|
||||
|
||||
// Test 2: randc enum with range constraint - run multiple trials,
|
||||
// verify only valid enum members produced and sequence varies
|
||||
all_same = 1;
|
||||
first_seq = 0;
|
||||
for (int trial = 0; trial < 3; trial++) begin
|
||||
ac = new;
|
||||
this_seq = 0;
|
||||
for (int j = 0; j < 4; j++) color_seen[j] = 0;
|
||||
repeat (40) begin
|
||||
`checkd(ac.randomize(), 1);
|
||||
`checkd(ac.color <= WHITE, 1);
|
||||
color_seen[ac.color] = 1;
|
||||
end
|
||||
// Record first 4 values for sequence comparison
|
||||
repeat (4) begin
|
||||
`checkd(ac.randomize(), 1);
|
||||
this_seq = this_seq * 8 + int'(ac.color);
|
||||
end
|
||||
`checkd(color_seen[0], 1);
|
||||
`checkd(color_seen[1], 1);
|
||||
`checkd(color_seen[2], 1);
|
||||
`checkd(color_seen[3], 1);
|
||||
if (trial == 0) first_seq = this_seq;
|
||||
else if (this_seq != first_seq) all_same = 0;
|
||||
end
|
||||
`checkd(all_same, 0);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Loading…
Reference in New Issue