This commit is contained in:
parent
dfe28f7ed0
commit
d3e205f201
|
@ -505,6 +505,12 @@ public:
|
|||
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 {
|
||||
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
|
||||
// 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); }
|
||||
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); }
|
||||
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)
|
||||
bool inside(const T_Value& value) const {
|
||||
|
|
|
@ -262,6 +262,23 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
putns(sdtypep, "bool operator!=(const " + EmitCBase::prefixNameProtect(sdtypep)
|
||||
+ "& rhs) const {\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");
|
||||
}
|
||||
|
||||
|
|
|
@ -709,7 +709,7 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||
void visit(AstAssocSel* nodep) override {
|
||||
if (editFormat(nodep)) return;
|
||||
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);
|
||||
const size_t stringSize = VN_AS(stringp->lhsp(), Const)->width();
|
||||
if (stringSize > 128) {
|
||||
|
@ -724,22 +724,32 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||
handle.relink(idxp);
|
||||
editSMT(nodep, nodep->fromp(), idxp);
|
||||
} else {
|
||||
VNRelinker handle;
|
||||
const int actual_width = nodep->bitp()->width();
|
||||
std::string fmt;
|
||||
// Normalize to standard bit width
|
||||
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";
|
||||
}
|
||||
if (VN_IS(nodep->bitp()->dtypep(), BasicDType)
|
||||
|| (VN_IS(nodep->bitp()->dtypep(), StructDType)
|
||||
&& VN_AS(nodep->bitp()->dtypep(), StructDType)->packed())
|
||||
|| VN_IS(nodep->bitp()->dtypep(), EnumDType)
|
||||
|| VN_IS(nodep->bitp()->dtypep(), PackArrayDType)) {
|
||||
VNRelinker handle;
|
||||
const int actual_width = nodep->bitp()->width();
|
||||
std::string fmt;
|
||||
// Normalize to standard bit width
|
||||
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
|
||||
= new AstSFormatF{fl, fmt, false, nodep->bitp()->unlinkFrBack(&handle)};
|
||||
handle.relink(idxp);
|
||||
editSMT(nodep, nodep->fromp(), idxp);
|
||||
AstNodeExpr* const idxp
|
||||
= new AstSFormatF{fl, fmt, false, nodep->bitp()->unlinkFrBack(&handle)};
|
||||
handle.relink(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 {
|
||||
|
|
|
@ -3,4 +3,13 @@
|
|||
| ^~~~~~~~~~~~~~~~~~~~
|
||||
... 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: 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
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
// any use, without warranty, 2024 by PlanV GmbH.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
class AssocArrayWarningTest;
|
||||
|
||||
// Long String index associative array
|
||||
class AssocArrayString;
|
||||
rand int string_arr [string];
|
||||
|
||||
constraint c {
|
||||
|
@ -14,20 +14,79 @@ class AssocArrayWarningTest;
|
|||
function new();
|
||||
string_arr["a_very_long_string"] = 0;
|
||||
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
|
||||
|
||||
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
|
||||
test_obj = new();
|
||||
repeat(2) begin
|
||||
int success;
|
||||
success = test_obj.randomize();
|
||||
if (success != 1) $stop;
|
||||
end
|
||||
test_str = new();
|
||||
test_cls = new();
|
||||
test_unp_struct = new();
|
||||
test_unp_arr = new();
|
||||
|
||||
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");
|
||||
$finish;
|
||||
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