This commit is contained in:
parent
dfe28f7ed0
commit
d3e205f201
|
|
@ -505,6 +505,12 @@ public:
|
||||||
VlQueue& operator=(VlQueue&&) = default;
|
VlQueue& operator=(VlQueue&&) = default;
|
||||||
bool operator==(const VlQueue& rhs) const { return m_deque == rhs.m_deque; }
|
bool operator==(const VlQueue& rhs) const { return m_deque == rhs.m_deque; }
|
||||||
bool operator!=(const VlQueue& rhs) const { return m_deque != rhs.m_deque; }
|
bool operator!=(const VlQueue& rhs) const { return m_deque != rhs.m_deque; }
|
||||||
|
bool operator<(const VlQueue& rhs) const {
|
||||||
|
for (int index = 0; index < m_deque.size(); ++index) {
|
||||||
|
if (m_deque[index] < rhs.m_deque[index]) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Standard copy constructor works. Verilog: assoca = assocb
|
// Standard copy constructor works. Verilog: assoca = assocb
|
||||||
// Also must allow conversion from a different N_MaxSize queue
|
// Also must allow conversion from a different N_MaxSize queue
|
||||||
|
|
@ -1364,6 +1370,12 @@ public:
|
||||||
bool neq(const T_Value that[N_Depth]) const { return neq(*this, that); }
|
bool neq(const T_Value that[N_Depth]) const { return neq(*this, that); }
|
||||||
void assign(const T_Value that[N_Depth]) { std::copy_n(that, N_Depth, m_storage); }
|
void assign(const T_Value that[N_Depth]) { std::copy_n(that, N_Depth, m_storage); }
|
||||||
void operator=(const T_Value that[N_Depth]) { assign(that); }
|
void operator=(const T_Value that[N_Depth]) { assign(that); }
|
||||||
|
bool operator<(const VlUnpacked<T_Value, N_Depth>& that) const {
|
||||||
|
for (int index = 0; index < N_Depth; ++index) {
|
||||||
|
if (m_storage[index] < that.m_storage[index]) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// inside (set membership operator)
|
// inside (set membership operator)
|
||||||
bool inside(const T_Value& value) const {
|
bool inside(const T_Value& value) const {
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,23 @@ class EmitCHeader final : public EmitCConstInit {
|
||||||
putns(sdtypep, "bool operator!=(const " + EmitCBase::prefixNameProtect(sdtypep)
|
putns(sdtypep, "bool operator!=(const " + EmitCBase::prefixNameProtect(sdtypep)
|
||||||
+ "& rhs) const {\n");
|
+ "& rhs) const {\n");
|
||||||
puts("return !(*this == rhs);\n}\n");
|
puts("return !(*this == rhs);\n}\n");
|
||||||
|
putns(sdtypep, "\nbool operator<(const " + EmitCBase::prefixNameProtect(sdtypep)
|
||||||
|
+ "& rhs) const {\n");
|
||||||
|
puts("return ");
|
||||||
|
puts("std::tie(");
|
||||||
|
for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
|
||||||
|
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||||
|
if (itemp != sdtypep->membersp()) puts(", ");
|
||||||
|
putns(itemp, itemp->nameProtect());
|
||||||
|
}
|
||||||
|
puts(")\n < std::tie(");
|
||||||
|
for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
|
||||||
|
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||||
|
if (itemp != sdtypep->membersp()) puts(", ");
|
||||||
|
putns(itemp, "rhs." + itemp->nameProtect());
|
||||||
|
}
|
||||||
|
puts(");\n");
|
||||||
|
puts("}\n");
|
||||||
puts("};\n");
|
puts("};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -709,7 +709,7 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||||
void visit(AstAssocSel* nodep) override {
|
void visit(AstAssocSel* nodep) override {
|
||||||
if (editFormat(nodep)) return;
|
if (editFormat(nodep)) return;
|
||||||
FileLine* const fl = nodep->fileline();
|
FileLine* const fl = nodep->fileline();
|
||||||
if (VN_IS(nodep->bitp(), CvtPackString)) {
|
if (VN_IS(nodep->bitp(), CvtPackString) && VN_IS(nodep->bitp()->dtypep(), BasicDType)) {
|
||||||
AstCvtPackString* const stringp = VN_AS(nodep->bitp(), CvtPackString);
|
AstCvtPackString* const stringp = VN_AS(nodep->bitp(), CvtPackString);
|
||||||
const size_t stringSize = VN_AS(stringp->lhsp(), Const)->width();
|
const size_t stringSize = VN_AS(stringp->lhsp(), Const)->width();
|
||||||
if (stringSize > 128) {
|
if (stringSize > 128) {
|
||||||
|
|
@ -724,22 +724,32 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||||
handle.relink(idxp);
|
handle.relink(idxp);
|
||||||
editSMT(nodep, nodep->fromp(), idxp);
|
editSMT(nodep, nodep->fromp(), idxp);
|
||||||
} else {
|
} else {
|
||||||
VNRelinker handle;
|
if (VN_IS(nodep->bitp()->dtypep(), BasicDType)
|
||||||
const int actual_width = nodep->bitp()->width();
|
|| (VN_IS(nodep->bitp()->dtypep(), StructDType)
|
||||||
std::string fmt;
|
&& VN_AS(nodep->bitp()->dtypep(), StructDType)->packed())
|
||||||
// Normalize to standard bit width
|
|| VN_IS(nodep->bitp()->dtypep(), EnumDType)
|
||||||
if (actual_width <= 8) {
|
|| VN_IS(nodep->bitp()->dtypep(), PackArrayDType)) {
|
||||||
fmt = "#x%2x";
|
VNRelinker handle;
|
||||||
} else if (actual_width <= 16) {
|
const int actual_width = nodep->bitp()->width();
|
||||||
fmt = "#x%4x";
|
std::string fmt;
|
||||||
} else {
|
// Normalize to standard bit width
|
||||||
fmt = "#x%" + std::to_string(VL_WORDS_I(actual_width) * 8) + "x";
|
if (actual_width <= 8) {
|
||||||
}
|
fmt = "#x%2x";
|
||||||
|
} else if (actual_width <= 16) {
|
||||||
|
fmt = "#x%4x";
|
||||||
|
} else {
|
||||||
|
fmt = "#x%" + std::to_string(VL_WORDS_I(actual_width) * 8) + "x";
|
||||||
|
}
|
||||||
|
|
||||||
AstNodeExpr* const idxp
|
AstNodeExpr* const idxp
|
||||||
= new AstSFormatF{fl, fmt, false, nodep->bitp()->unlinkFrBack(&handle)};
|
= new AstSFormatF{fl, fmt, false, nodep->bitp()->unlinkFrBack(&handle)};
|
||||||
handle.relink(idxp);
|
handle.relink(idxp);
|
||||||
editSMT(nodep, nodep->fromp(), idxp);
|
editSMT(nodep, nodep->fromp(), idxp);
|
||||||
|
} else {
|
||||||
|
nodep->bitp()->v3error(
|
||||||
|
"Illegal non-integral expression or subexpression in random constraint."
|
||||||
|
" (IEEE 1800-2023 18.3)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstArraySel* nodep) override {
|
void visit(AstArraySel* nodep) override {
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,13 @@
|
||||||
| ^~~~~~~~~~~~~~~~~~~~
|
| ^~~~~~~~~~~~~~~~~~~~
|
||||||
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
|
... 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.
|
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.
|
||||||
|
%Error: t/t_constraint_assoc_arr_bad.v:30:26: Illegal non-integral expression or subexpression in random constraint. (IEEE 1800-2023 18.3)
|
||||||
|
30 | constraint c1 { data[cl] > 0;}
|
||||||
|
| ^~
|
||||||
|
%Error: t/t_constraint_assoc_arr_bad.v:44:44: Illegal non-integral expression or subexpression in random constraint. (IEEE 1800-2023 18.3)
|
||||||
|
44 | constraint c2 { foreach (data[i]) data[i] < 100; }
|
||||||
|
| ^
|
||||||
|
%Error: t/t_constraint_assoc_arr_bad.v:58:44: Illegal non-integral expression or subexpression in random constraint. (IEEE 1800-2023 18.3)
|
||||||
|
58 | constraint c3 { foreach (data[i]) data[i] > 0; }
|
||||||
|
| ^
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
// any use, without warranty, 2024 by PlanV GmbH.
|
// any use, without warranty, 2024 by PlanV GmbH.
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
class AssocArrayWarningTest;
|
// Long String index associative array
|
||||||
|
class AssocArrayString;
|
||||||
rand int string_arr [string];
|
rand int string_arr [string];
|
||||||
|
|
||||||
constraint c {
|
constraint c {
|
||||||
|
|
@ -14,20 +14,79 @@ class AssocArrayWarningTest;
|
||||||
function new();
|
function new();
|
||||||
string_arr["a_very_long_string"] = 0;
|
string_arr["a_very_long_string"] = 0;
|
||||||
endfunction
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class keyClass;
|
||||||
|
int id;
|
||||||
|
function new();
|
||||||
|
id = 3;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
// Class index associative array
|
||||||
|
class AssocArrayClass;
|
||||||
|
rand bit [31:0] data [keyClass];
|
||||||
|
keyClass cl;
|
||||||
|
// constraint c4 { foreach (data[i]) data[i] > 0;} Unsupported index type for an associative array in an iterative constraint.
|
||||||
|
constraint c1 { data[cl] > 0;} // Illegal index expression of unpacked type in constraint.
|
||||||
|
function new();
|
||||||
|
cl = new();
|
||||||
|
data[cl] = 32'd77;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
} UnpackedIndexType;
|
||||||
|
// Struct (unpacked) index associative array
|
||||||
|
class AssocArrayUnpackedStruct;
|
||||||
|
rand bit [31:0] data [UnpackedIndexType];
|
||||||
|
constraint c2 { foreach (data[i]) data[i] < 100; } // Illegal non-integral expression in random constraint.
|
||||||
|
|
||||||
|
function new();
|
||||||
|
UnpackedIndexType idx;
|
||||||
|
idx.a = 1;
|
||||||
|
idx.b = 2;
|
||||||
|
data[idx] = 32'd25;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
// Array (unpacked) index associative array
|
||||||
|
typedef logic [2:0] IndexArrayType[3];
|
||||||
|
class AssocArrayArrayIndex;
|
||||||
|
rand bit [31:0] data [IndexArrayType];
|
||||||
|
constraint c3 { foreach (data[i]) data[i] > 0; }
|
||||||
|
|
||||||
|
function new();
|
||||||
|
IndexArrayType idx;
|
||||||
|
for (int j = 0; j < 4; j++) begin
|
||||||
|
idx[j] = 3'd0;
|
||||||
|
end
|
||||||
|
data[idx] = 32'd75;
|
||||||
|
endfunction
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
module t_constraint_assoc_arr_bad;
|
module t_constraint_assoc_arr_bad;
|
||||||
|
|
||||||
AssocArrayWarningTest test_obj;
|
AssocArrayString test_str;
|
||||||
|
AssocArrayClass test_cls;
|
||||||
|
AssocArrayUnpackedStruct test_unp_struct;
|
||||||
|
AssocArrayArrayIndex test_unp_arr;
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
test_obj = new();
|
test_str = new();
|
||||||
repeat(2) begin
|
test_cls = new();
|
||||||
int success;
|
test_unp_struct = new();
|
||||||
success = test_obj.randomize();
|
test_unp_arr = new();
|
||||||
if (success != 1) $stop;
|
|
||||||
end
|
success += test_str.randomize();
|
||||||
|
success += test_cls.randomize();
|
||||||
|
success += test_unp_struct.randomize();
|
||||||
|
success += test_unp_arr.randomize();
|
||||||
|
|
||||||
|
if(success != 4) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/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('simulator')
|
||||||
|
|
||||||
|
if not test.have_solver:
|
||||||
|
test.skip("No constraint solver installed")
|
||||||
|
|
||||||
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by PlanV GmbH.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
// Enum-based associative array
|
||||||
|
typedef enum { RED, GREEN, YELLOW } color_t;
|
||||||
|
|
||||||
|
class AssocArrayEnum;
|
||||||
|
rand bit [7:0] colors [color_t];
|
||||||
|
constraint c1 { foreach (colors[i]) colors[i] == 4; }
|
||||||
|
|
||||||
|
function new();
|
||||||
|
colors[RED] = 8'd5;
|
||||||
|
colors[GREEN] = 8'd10;
|
||||||
|
colors[YELLOW] = 8'd15;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function void self_check();
|
||||||
|
foreach (colors[i]) begin
|
||||||
|
if (colors[i] != 4) $stop;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
// Struct (packed) index associative array
|
||||||
|
typedef struct packed {
|
||||||
|
bit [2:0] high;
|
||||||
|
bit [1:0] low;
|
||||||
|
} PackedIndexType;
|
||||||
|
|
||||||
|
class AssocArrayPackedStruct;
|
||||||
|
rand bit [31:0] data [PackedIndexType];
|
||||||
|
constraint c2 { foreach (data[i]) data[i] == 100; }
|
||||||
|
|
||||||
|
function new();
|
||||||
|
PackedIndexType idx;
|
||||||
|
idx.high = 3'd1;
|
||||||
|
idx.low = 2'd1;
|
||||||
|
data[idx] = 32'd50;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function void self_check();
|
||||||
|
foreach (data[i]) begin
|
||||||
|
if (data[i] != 100) $stop;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
// Array (packed) index associative array
|
||||||
|
typedef logic [2:0][7:0] IndexArrayType;
|
||||||
|
|
||||||
|
class AssocArrayArrayIndex;
|
||||||
|
rand bit [31:0] data [IndexArrayType];
|
||||||
|
constraint c3 { foreach (data[i]) data[i] == 0; }
|
||||||
|
|
||||||
|
function new();
|
||||||
|
IndexArrayType idx;
|
||||||
|
idx = 0;
|
||||||
|
data[idx] = 32'd75;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function void self_check();
|
||||||
|
foreach (data[i]) begin
|
||||||
|
if (data[i] != 0) $stop;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t_constraint_assoc_array_others;
|
||||||
|
|
||||||
|
AssocArrayEnum enum_arr;
|
||||||
|
AssocArrayPackedStruct packed_arr;
|
||||||
|
AssocArrayArrayIndex array_arr;
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Create instances of the classes
|
||||||
|
enum_arr = new();
|
||||||
|
packed_arr = new();
|
||||||
|
array_arr = new();
|
||||||
|
|
||||||
|
// Randomization and self-check
|
||||||
|
success = enum_arr.randomize();
|
||||||
|
if (success != 1) $stop;
|
||||||
|
enum_arr.self_check();
|
||||||
|
|
||||||
|
success = packed_arr.randomize();
|
||||||
|
if (success != 1) $stop;
|
||||||
|
packed_arr.self_check();
|
||||||
|
|
||||||
|
success = array_arr.randomize();
|
||||||
|
if (success != 1) $stop;
|
||||||
|
array_arr.self_check();
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue