reformat
This commit is contained in:
parent
04f7251975
commit
12747ae18f
|
|
@ -307,7 +307,6 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
|||
// Process per-variable (object instance), not per-class
|
||||
// This allows multiple objects of the same class (e.g., obj1 and obj2 of type Sub)
|
||||
if (m_processedVars.insert(objVar).second) {
|
||||
|
||||
// Clone constraints from the top-level class (e.g., Level1 for obj_a)
|
||||
gConsClass->foreachMember([&](AstClass* const classp, AstConstraint* const constrp) {
|
||||
AstConstraint* const cloneConstrp = constrp->cloneTree(false);
|
||||
|
|
@ -611,7 +610,8 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
|||
if (VN_IS(nodep->fromp(), VarRef) || VN_IS(nodep->fromp(), MemberSel)) {
|
||||
markNestedGlobalConstrainedRecurse(nodep->fromp());
|
||||
} else if (VN_IS(nodep->fromp(), ArraySel)) {
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported in global constraint");
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: " << nodep->prettyTypeName()
|
||||
<< " within a global constraint");
|
||||
}
|
||||
// Global constraint processing algorithm:
|
||||
// 1. Detect globally constrained object variables in randomized classes
|
||||
|
|
@ -832,7 +832,6 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||
|
||||
AstMemberSel* membersel = nullptr;
|
||||
std::string smtName;
|
||||
|
||||
if (isGlobalConstrained && VN_IS(nodep->backp(), MemberSel)) {
|
||||
// For global constraints: build complete path from topmost MemberSel
|
||||
AstNode* topMemberSel = nodep->backp();
|
||||
|
|
@ -1119,11 +1118,9 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||
}
|
||||
void visit(AstMemberSel* nodep) override {
|
||||
if (nodep->varp()->rand().isRandomizable() && nodep->fromp()) {
|
||||
|
||||
AstNode* rootNode = nodep->fromp();
|
||||
while (const AstMemberSel* const selp = VN_CAST(rootNode, MemberSel))
|
||||
rootNode = selp->fromp();
|
||||
|
||||
// Check if the root variable participates in global constraints
|
||||
if (const AstVarRef* const varRefp = VN_CAST(rootNode, VarRef)) {
|
||||
AstVar* const constrainedVar = varRefp->varp();
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:41:20: Unsupported in global constraint
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:41:20: Unsupported: MEMBERSEL 'm_x' within a global constraint
|
||||
: ... note: In instance 't_constraint_global_arr_unsup'
|
||||
41 | mid.arr[0].x == 200;
|
||||
| ^
|
||||
41 | m_mid.m_arr[0].m_x == 200;
|
||||
| ^~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:42:20: Unsupported in global constraint
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:42:20: Unsupported: MEMBERSEL 'm_y' within a global constraint
|
||||
: ... note: In instance 't_constraint_global_arr_unsup'
|
||||
42 | mid.arr[0].y == 201;
|
||||
| ^
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:47:20: Unsupported in global constraint
|
||||
: ... note: In instance 't_constraint_global_arr_unsup'
|
||||
47 | mid_arr[0].obj.x == 300;
|
||||
42 | m_mid.m_arr[0].m_y == 201;
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:48:20: Unsupported in global constraint
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:47:18: Unsupported: MEMBERSEL 'm_obj' within a global constraint
|
||||
: ... note: In instance 't_constraint_global_arr_unsup'
|
||||
48 | mid_arr[0].obj.y == 301;
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:53:20: Unsupported in global constraint
|
||||
47 | m_mid_arr[0].m_obj.m_x == 300;
|
||||
| ^~~~~
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:48:18: Unsupported: MEMBERSEL 'm_obj' within a global constraint
|
||||
: ... note: In instance 't_constraint_global_arr_unsup'
|
||||
53 | mid_arr[1].arr[2].y == 400;
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:53:27: Unsupported in global constraint
|
||||
48 | m_mid_arr[0].m_obj.m_y == 301;
|
||||
| ^~~~~
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:53:18: Unsupported: MEMBERSEL 'm_arr' within a global constraint
|
||||
: ... note: In instance 't_constraint_global_arr_unsup'
|
||||
53 | mid_arr[1].arr[2].y == 400;
|
||||
| ^
|
||||
53 | m_mid_arr[1].m_arr[2].m_y == 400;
|
||||
| ^~~~~
|
||||
%Error-UNSUPPORTED: t/t_constraint_global_arr_unsup.v:53:27: Unsupported: MEMBERSEL 'm_y' within a global constraint
|
||||
: ... note: In instance 't_constraint_global_arr_unsup'
|
||||
53 | m_mid_arr[1].m_arr[2].m_y == 400;
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -6,81 +6,81 @@
|
|||
|
||||
/* verilator lint_off WIDTHTRUNC */
|
||||
class Inner;
|
||||
rand int x;
|
||||
rand int y;
|
||||
rand int m_x;
|
||||
rand int m_y;
|
||||
endclass
|
||||
|
||||
class Middle;
|
||||
rand Inner obj;
|
||||
rand Inner arr[3];
|
||||
rand Inner m_obj;
|
||||
rand Inner m_arr[3];
|
||||
endclass
|
||||
|
||||
class Outer;
|
||||
rand Middle mid;
|
||||
rand Middle mid_arr[2];
|
||||
rand Middle m_mid;
|
||||
rand Middle m_mid_arr[2];
|
||||
|
||||
function new();
|
||||
mid = new;
|
||||
mid.obj = new;
|
||||
foreach (mid.arr[i]) mid.arr[i] = new;
|
||||
foreach (mid_arr[i]) begin
|
||||
mid_arr[i] = new;
|
||||
mid_arr[i].obj = new;
|
||||
foreach (mid_arr[i].arr[j]) mid_arr[i].arr[j] = new;
|
||||
end
|
||||
endfunction
|
||||
function new();
|
||||
m_mid = new;
|
||||
m_mid.m_obj = new;
|
||||
foreach (m_mid.m_arr[i]) m_mid.m_arr[i] = new;
|
||||
foreach (m_mid_arr[i]) begin
|
||||
m_mid_arr[i] = new;
|
||||
m_mid_arr[i].m_obj = new;
|
||||
foreach (m_mid_arr[i].m_arr[j]) m_mid_arr[i].m_arr[j] = new;
|
||||
end
|
||||
endfunction
|
||||
|
||||
// Case 1: Simple nested member access (should work)
|
||||
constraint c_simple {
|
||||
mid.obj.x == 100;
|
||||
mid.obj.y == 101;
|
||||
}
|
||||
// Case 1: Simple nested member access (should work)
|
||||
constraint c_simple {
|
||||
m_mid.m_obj.m_x == 100;
|
||||
m_mid.m_obj.m_y == 101;
|
||||
}
|
||||
|
||||
// Case 2: Array indexing in the path (may not work)
|
||||
constraint c_array_index {
|
||||
mid.arr[0].x == 200;
|
||||
mid.arr[0].y == 201;
|
||||
}
|
||||
// Case 2: Array indexing in the path (may not work)
|
||||
constraint c_array_index {
|
||||
m_mid.m_arr[0].m_x == 200;
|
||||
m_mid.m_arr[0].m_y == 201;
|
||||
}
|
||||
|
||||
// Case 3: Nested array indexing
|
||||
constraint c_nested_array {
|
||||
mid_arr[0].obj.x == 300;
|
||||
mid_arr[0].obj.y == 301;
|
||||
}
|
||||
// Case 3: Nested array indexing
|
||||
constraint c_nested_array {
|
||||
m_mid_arr[0].m_obj.m_x == 300;
|
||||
m_mid_arr[0].m_obj.m_y == 301;
|
||||
}
|
||||
|
||||
// Case 4: Multiple array indices
|
||||
constraint c_multi_array {
|
||||
mid_arr[1].arr[2].y == 400;
|
||||
}
|
||||
// Case 4: Multiple array indices
|
||||
constraint c_multi_array {
|
||||
m_mid_arr[1].m_arr[2].m_y == 400;
|
||||
}
|
||||
endclass
|
||||
|
||||
module t_constraint_global_arr_unsup;
|
||||
initial begin
|
||||
Outer o = new;
|
||||
if (o.randomize()) begin
|
||||
$display("Case 1 - Simple: mid.obj.x = %0d (expected 100)", o.mid.obj.x);
|
||||
$display("Case 1 - Simple: mid.obj.y = %0d (expected 101)", o.mid.obj.y);
|
||||
$display("Case 2 - Array[0]: mid.arr[0].x = %0d (expected 200)", o.mid.arr[0].x);
|
||||
$display("Case 2 - Array[0]: mid.arr[0].y = %0d (expected 201)", o.mid.arr[0].y);
|
||||
$display("Case 3 - Nested[0]: mid_arr[0].obj.x = %0d (expected 300)", o.mid_arr[0].obj.x);
|
||||
$display("Case 3 - Nested[0]: mid_arr[0].obj.y = %0d (expected 301)", o.mid_arr[0].obj.y);
|
||||
$display("Case 4 - Multi[1][2]: mid_arr[1].arr[2].y = %0d (expected 400)", o.mid_arr[1].arr[2].y);
|
||||
initial begin
|
||||
Outer o = new;
|
||||
if (o.randomize()) begin
|
||||
$display("Case 1 - Simple: mid.obj.x = %0d (expected 100)", o.m_mid.m_obj.m_x);
|
||||
$display("Case 1 - Simple: mid.obj.y = %0d (expected 101)", o.m_mid.m_obj.m_y);
|
||||
$display("Case 2 - Array[0]: mid.arr[0].x = %0d (expected 200)", o.m_mid.m_arr[0].m_x);
|
||||
$display("Case 2 - Array[0]: mid.arr[0].y = %0d (expected 201)", o.m_mid.m_arr[0].m_y);
|
||||
$display("Case 3 - Nested[0]: mid_arr[0].obj.x = %0d (expected 300)", o.m_mid_arr[0].m_obj.m_x);
|
||||
$display("Case 3 - Nested[0]: mid_arr[0].obj.y = %0d (expected 301)", o.m_mid_arr[0].m_obj.m_y);
|
||||
$display("Case 4 - Multi[1][2]: mid_arr[1].arr[2].y = %0d (expected 400)", o.m_mid_arr[1].m_arr[2].m_y);
|
||||
|
||||
// Check results
|
||||
if (o.mid.obj.x == 100 && o.mid.obj.y == 101 &&
|
||||
o.mid.arr[0].x == 200 && o.mid.arr[0].y == 201 &&
|
||||
o.mid_arr[0].obj.x == 300 && o.mid_arr[0].obj.y == 301 &&
|
||||
o.mid_arr[1].arr[2].y == 400) begin
|
||||
$display("*-* All Finished *-*");
|
||||
$finish;
|
||||
end else begin
|
||||
$display("*-* FAILED *-*");
|
||||
$stop;
|
||||
end
|
||||
end else begin
|
||||
$display("*-* FAILED: randomize() returned 0 *-*");
|
||||
$stop;
|
||||
end
|
||||
// Check results
|
||||
if (o.m_mid.m_obj.m_x == 100 && o.m_mid.m_obj.m_y == 101 &&
|
||||
o.m_mid.m_arr[0].m_x == 200 && o.m_mid.m_arr[0].m_y == 201 &&
|
||||
o.m_mid_arr[0].m_obj.m_x == 300 && o.m_mid_arr[0].m_obj.m_y == 301 &&
|
||||
o.m_mid_arr[1].m_arr[2].m_y == 400) begin
|
||||
$display("*-* All Finished *-*");
|
||||
$finish;
|
||||
end else begin
|
||||
$display("*-* FAILED *-*");
|
||||
$stop;
|
||||
end
|
||||
end else begin
|
||||
$display("*-* FAILED: randomize() returned 0 *-*");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
/* verilator lint_off WIDTHTRUNC */
|
||||
|
|
|
|||
|
|
@ -5,81 +5,81 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
class Inner;
|
||||
rand int val;
|
||||
constraint c_local { val inside {[1:5]}; }
|
||||
function new(); val = 0; endfunction
|
||||
rand int m_val;
|
||||
constraint c_local { m_val inside {[1:5]}; }
|
||||
function new(); m_val = 0; endfunction
|
||||
endclass
|
||||
|
||||
class Mid;
|
||||
int limit;
|
||||
rand int x;
|
||||
rand Inner inner;
|
||||
constraint c_mid { x == limit; }
|
||||
function new(int lim);
|
||||
limit = lim;
|
||||
inner = new();
|
||||
endfunction
|
||||
int m_limit;
|
||||
rand int m_x;
|
||||
rand Inner m_inner;
|
||||
constraint c_mid { m_x == m_limit; }
|
||||
function new(int lim);
|
||||
m_limit = lim;
|
||||
m_inner = new();
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class Top;
|
||||
rand Mid m1;
|
||||
rand Mid m2;
|
||||
rand int y;
|
||||
rand Mid m_m1;
|
||||
rand Mid m_m2;
|
||||
rand int m_y;
|
||||
|
||||
constraint c_global {
|
||||
m1.inner.val < m2.inner.val;
|
||||
y > m1.x;
|
||||
y < m2.x;
|
||||
m1.inner.val + m2.inner.val < 8;
|
||||
}
|
||||
constraint c_global {
|
||||
m_m1.m_inner.m_val < m_m2.m_inner.m_val;
|
||||
m_y > m_m1.m_x;
|
||||
m_y < m_m2.m_x;
|
||||
m_m1.m_inner.m_val + m_m2.m_inner.m_val < 8;
|
||||
}
|
||||
|
||||
function new();
|
||||
m1 = new(3);
|
||||
m2 = new(5);
|
||||
y = 0;
|
||||
endfunction
|
||||
function new();
|
||||
m_m1 = new(3);
|
||||
m_m2 = new(5);
|
||||
m_y = 0;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t_constraint_global_random;
|
||||
int success;
|
||||
Top t;
|
||||
int success;
|
||||
Top t;
|
||||
|
||||
initial begin
|
||||
t = new();
|
||||
initial begin
|
||||
t = new();
|
||||
|
||||
// Test 1: Regular randomize() with global constraints
|
||||
success = t.randomize();
|
||||
if (success != 1) $stop;
|
||||
// Test 1: Regular randomize() with global constraints
|
||||
success = t.randomize();
|
||||
if (success != 1) $stop;
|
||||
|
||||
// $display("m1.x=%0d, m2.x=%0d, y=%0d", t.m1.x, t.m2.x, t.y);
|
||||
// $display("m1.inner.val=%0d, m2.inner.val=%0d", t.m1.inner.val, t.m2.inner.val);
|
||||
// $display("m1.x=%0d, m2.x=%0d, y=%0d", t.m_m1.m_x, t.m_m2.m_x, t.m_y);
|
||||
// $display("m1.inner.val=%0d, m2.inner.val=%0d", t.m_m1.m_inner.m_val, t.m_m2.m_inner.m_val);
|
||||
|
||||
if (t.m1.x != 3 || t.m2.x != 5) $stop;
|
||||
if (t.m1.inner.val >= t.m2.inner.val) $stop;
|
||||
if (t.y <= t.m1.x || t.y >= t.m2.x) $stop;
|
||||
if (t.m1.inner.val + t.m2.inner.val >= 8) $stop;
|
||||
if (t.m1.inner.val < 1 || t.m1.inner.val > 5 ||
|
||||
t.m2.inner.val < 1 || t.m2.inner.val > 5) $stop;
|
||||
if (t.m_m1.m_x != 3 || t.m_m2.m_x != 5) $stop;
|
||||
if (t.m_m1.m_inner.m_val >= t.m_m2.m_inner.m_val) $stop;
|
||||
if (t.m_y <= t.m_m1.m_x || t.m_y >= t.m_m2.m_x) $stop;
|
||||
if (t.m_m1.m_inner.m_val + t.m_m2.m_inner.m_val >= 8) $stop;
|
||||
if (t.m_m1.m_inner.m_val < 1 || t.m_m1.m_inner.m_val > 5 ||
|
||||
t.m_m2.m_inner.m_val < 1 || t.m_m2.m_inner.m_val > 5) $stop;
|
||||
|
||||
// Test 2: randomize() with inline constraint on global-constrained members
|
||||
success = 0;
|
||||
success = t.randomize() with {
|
||||
m1.inner.val == 2;
|
||||
m2.inner.val == 5;
|
||||
};
|
||||
if (success != 1) $stop;
|
||||
// Test 2: randomize() with inline constraint on global-constrained members
|
||||
success = 0;
|
||||
success = t.randomize() with {
|
||||
m_m1.m_inner.m_val == 2;
|
||||
m_m2.m_inner.m_val == 5;
|
||||
};
|
||||
if (success != 1) $stop;
|
||||
|
||||
// Verify inline constraints
|
||||
if (t.m1.inner.val != 2) $stop;
|
||||
if (t.m2.inner.val != 5) $stop;
|
||||
// Verify inline constraints
|
||||
if (t.m_m1.m_inner.m_val != 2) $stop;
|
||||
if (t.m_m2.m_inner.m_val != 5) $stop;
|
||||
|
||||
// Verify global constraints still hold
|
||||
if (t.m1.x != 3 || t.m2.x != 5) $stop;
|
||||
if (t.m1.inner.val >= t.m2.inner.val) $stop;
|
||||
if (t.y <= t.m1.x || t.y >= t.m2.x) $stop;
|
||||
if (t.m1.inner.val + t.m2.inner.val >= 8) $stop;
|
||||
// Verify global constraints still hold
|
||||
if (t.m_m1.m_x != 3 || t.m_m2.m_x != 5) $stop;
|
||||
if (t.m_m1.m_inner.m_val >= t.m_m2.m_inner.m_val) $stop;
|
||||
if (t.m_y <= t.m_m1.m_x || t.m_y >= t.m_m2.m_x) $stop;
|
||||
if (t.m_m1.m_inner.m_val + t.m_m2.m_inner.m_val >= 8) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
Loading…
Reference in New Issue