parent
44f49669a3
commit
0380a36c76
|
@ -282,6 +282,7 @@ std::string parseNestedSelect(const std::string& nested_select_expr,
|
|||
indices.push_back(idx);
|
||||
return name;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// VlRandomizer:: Methods
|
||||
|
||||
|
@ -467,10 +468,19 @@ bool VlRandomizer::parseSolution(std::iostream& f) {
|
|||
"hex_index contains invalid format");
|
||||
continue;
|
||||
}
|
||||
const long long index = std::stoll(hex_index.substr(start + 2), nullptr, 16);
|
||||
oss << "[" << index << "]";
|
||||
std::string trimmed_hex = hex_index.substr(start + 2);
|
||||
|
||||
if (trimmed_hex.size() <= 8) { // Small numbers: <= 32 bits
|
||||
// Convert to decimal and output directly
|
||||
oss << "[" << std::to_string(std::stoll(trimmed_hex, nullptr, 16)) << "]";
|
||||
} else { // Large numbers: > 32 bits
|
||||
// Trim leading zeros and handle empty case
|
||||
trimmed_hex.erase(0, trimmed_hex.find_first_not_of('0'));
|
||||
oss << "[" << (trimmed_hex.empty() ? "0" : trimmed_hex) << "]";
|
||||
}
|
||||
}
|
||||
const std::string indexed_name = oss.str();
|
||||
|
||||
const auto it = std::find_if(m_arr_vars.begin(), m_arr_vars.end(),
|
||||
[&indexed_name](const auto& entry) {
|
||||
return entry.second->m_name == indexed_name;
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
|
||||
#include "verilated.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
//=============================================================================
|
||||
// VlRandomExpr and subclasses represent expressions for the constraint solver.
|
||||
|
@ -38,10 +40,10 @@ public:
|
|||
m_name; // Name of the array variable, including index notation (e.g., arr[2][1])
|
||||
void* const m_datap; // Reference to the array variable data
|
||||
const int m_index; // Flattened (1D) index of the array element
|
||||
const std::vector<size_t> m_indices; // Multi-dimensional indices of the array element
|
||||
const std::vector<IData> m_indices; // Multi-dimensional indices of the array element
|
||||
const std::vector<size_t> m_idxWidths; // Multi-dimensional indices' bit widths
|
||||
|
||||
ArrayInfo(const std::string& name, void* datap, int index, const std::vector<size_t>& indices,
|
||||
ArrayInfo(const std::string& name, void* datap, int index, const std::vector<IData>& indices,
|
||||
const std::vector<size_t>& idxWidths)
|
||||
: m_name(name)
|
||||
, m_datap(datap)
|
||||
|
@ -110,16 +112,31 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
void emitSelect(std::ostream& s, const std::vector<size_t>& indices,
|
||||
void emitHexs(std::ostream& s, const std::vector<IData>& indices, const size_t bit_width,
|
||||
size_t idx) const {
|
||||
for (int j = bit_width - 4; j >= 0; j -= 4) {
|
||||
s << "0123456789abcdef"[(indices[idx] >> j) & 0xf];
|
||||
}
|
||||
}
|
||||
void emitSelect(std::ostream& s, const std::vector<IData>& indices,
|
||||
const std::vector<size_t>& idxWidths) const {
|
||||
for (size_t idx = 0; idx < indices.size(); ++idx) s << "(select ";
|
||||
const size_t num_indices = idxWidths.size();
|
||||
size_t wide_size = 0;
|
||||
|
||||
for (size_t idx = 0; idx < num_indices; ++idx) s << "(select ";
|
||||
s << name();
|
||||
for (size_t idx = 0; idx < indices.size(); ++idx) {
|
||||
s << " #x";
|
||||
|
||||
for (size_t idx = 0; idx < num_indices; ++idx) {
|
||||
const size_t bit_width = idxWidths[idx];
|
||||
for (int j = bit_width - 4; j >= 0; j -= 4) {
|
||||
s << "0123456789abcdef"[(indices[idx] >> j) & 0xf];
|
||||
s << " #x";
|
||||
|
||||
const size_t emit_count = (bit_width > 32) ? (idxWidths[idx] / 32) : 1;
|
||||
|
||||
for (size_t i = 0; i < emit_count; ++i) {
|
||||
emitHexs(s, indices, (bit_width > 32) ? 32 : bit_width, wide_size + i);
|
||||
}
|
||||
|
||||
wide_size += (idxWidths[idx] > 32) ? (idxWidths[idx] / 32) : 1;
|
||||
s << ")";
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +146,7 @@ public:
|
|||
const std::string indexed_name = name() + std::to_string(i);
|
||||
const auto it = m_arrVarsRefp->find(indexed_name);
|
||||
if (it != m_arrVarsRefp->end()) {
|
||||
const std::vector<size_t>& indices = it->second->m_indices;
|
||||
const std::vector<IData>& indices = it->second->m_indices;
|
||||
const std::vector<size_t>& idxWidths = it->second->m_idxWidths;
|
||||
emitSelect(s, indices, idxWidths);
|
||||
} else {
|
||||
|
@ -165,7 +182,7 @@ public:
|
|||
const std::string indexed_name = name() + std::to_string(j);
|
||||
const auto it = m_arrVarsRefp->find(indexed_name);
|
||||
if (it != m_arrVarsRefp->end()) {
|
||||
const std::vector<size_t>& indices = it->second->m_indices;
|
||||
const std::vector<IData>& indices = it->second->m_indices;
|
||||
const std::vector<size_t>& idxWidths = it->second->m_idxWidths;
|
||||
emitSelect(s, indices, idxWidths);
|
||||
} else {
|
||||
|
@ -176,7 +193,6 @@ public:
|
|||
};
|
||||
//=============================================================================
|
||||
// VlRandomizer is the object holding constraints and variable references.
|
||||
|
||||
class VlRandomizer final {
|
||||
// MEMBERS
|
||||
std::vector<std::string> m_constraints; // Solver-dependent constraints
|
||||
|
@ -200,45 +216,89 @@ public:
|
|||
bool next(VlRNG& rngr);
|
||||
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<std::is_integral<T_Key>::value>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, size_t& integral_index,
|
||||
typename std::enable_if<std::is_integral<T_Key>::value && (sizeof(T_Key) <= 4)>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
const std::string& base_name, size_t& idx_width) {
|
||||
integral_index = static_cast<size_t>(key);
|
||||
indexed_name = base_name + "[" + std::to_string(integral_index) + "]";
|
||||
integral_index.push_back(static_cast<size_t>(key));
|
||||
indexed_name
|
||||
= base_name + "[" + std::to_string(integral_index[integral_index.size() - 1]) + "]";
|
||||
idx_width = sizeof(T_Key) * 8;
|
||||
}
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<std::is_same<T_Key, std::string>::value>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, size_t& integral_index,
|
||||
typename std::enable_if<std::is_integral<T_Key>::value && (sizeof(T_Key) > 4)>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
const std::string& base_name, size_t& idx_width) {
|
||||
integral_index = string_to_integral(key);
|
||||
indexed_name = base_name + "[" + std::to_string(integral_index) + "]";
|
||||
idx_width = 64; // 64-bit mask
|
||||
constexpr size_t segment_bits = 32;
|
||||
constexpr T_Key mask = (static_cast<T_Key>(1) << segment_bits) - 1;
|
||||
integral_index.push_back(static_cast<size_t>(key >> segment_bits));
|
||||
integral_index.push_back(static_cast<size_t>(key & mask));
|
||||
|
||||
std::ostringstream hex_stream;
|
||||
hex_stream << std::hex << key;
|
||||
std::string index_string = hex_stream.str();
|
||||
index_string.erase(0, index_string.find_first_not_of('0'));
|
||||
index_string = index_string.empty() ? "0" : index_string;
|
||||
|
||||
indexed_name = base_name + "[" + index_string + "]";
|
||||
|
||||
idx_width = sizeof(T_Key) * 8;
|
||||
}
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<VlIsVlWide<T_Key>::value>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
const std::string& base_name, size_t& idx_width) {
|
||||
std::ostringstream hex_stream;
|
||||
for (size_t i = key.size(); i > 0; --i) {
|
||||
const size_t segment_value = key.at(i - 1);
|
||||
hex_stream << std::hex << segment_value;
|
||||
integral_index.push_back(segment_value);
|
||||
}
|
||||
std::string index_string = hex_stream.str();
|
||||
index_string.erase(0, index_string.find_first_not_of('0'));
|
||||
index_string = index_string.empty() ? "0" : index_string;
|
||||
|
||||
indexed_name = base_name + "[" + index_string + "]";
|
||||
idx_width = key.size() * 32;
|
||||
}
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<std::is_same<T_Key, std::string>::value>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
const std::string& base_name, size_t& idx_width) {
|
||||
// Convert the input string to its ASCII hexadecimal representation
|
||||
std::ostringstream oss;
|
||||
for (unsigned char c : key) {
|
||||
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::string hex_str = oss.str();
|
||||
// Ensure the hex string is exactly 128 bits (32 hex characters)
|
||||
hex_str = hex_str.size() > 32 ? hex_str.substr(0, 32)
|
||||
: std::string(32 - hex_str.size(), '0') + hex_str;
|
||||
|
||||
// Split the hex string into 4 segments (32-bit per segment)
|
||||
integral_index.clear();
|
||||
for (size_t i = 0; i < hex_str.size(); i += 8) {
|
||||
integral_index.push_back(std::stoul(hex_str.substr(i, 8), nullptr, 16));
|
||||
}
|
||||
|
||||
indexed_name = base_name + "["
|
||||
+ (hex_str.find_first_not_of('0') == std::string::npos
|
||||
? "0"
|
||||
: hex_str.substr(hex_str.find_first_not_of('0')))
|
||||
+ "]";
|
||||
|
||||
idx_width = 128;
|
||||
}
|
||||
template <typename T_Key>
|
||||
typename std::enable_if<!std::is_integral<T_Key>::value
|
||||
&& !std::is_same<T_Key, std::string>::value>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, size_t& integral_index,
|
||||
&& !std::is_same<T_Key, std::string>::value
|
||||
&& !VlIsVlWide<T_Key>::value>::type
|
||||
process_key(const T_Key& key, std::string& indexed_name, std::vector<size_t>& integral_index,
|
||||
const std::string& base_name, size_t& idx_width) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "randomize",
|
||||
"Unsupported: Only integral and string index of associative array is "
|
||||
"supported currently.");
|
||||
}
|
||||
|
||||
uint64_t string_to_integral(const std::string& str) {
|
||||
uint64_t result = 0;
|
||||
for (char c : str) { result = (result << 8) | static_cast<uint64_t>(c); }
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
if (seen_values.count(result) > 0 && seen_values[result] != str)
|
||||
VL_WARN_MT(__FILE__, __LINE__, "randomize",
|
||||
"Conflict detected: Different strings mapped to the same 64-bit index.");
|
||||
seen_values[result] = str;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_var(T& var, int width, const char* name, int dimension,
|
||||
std::uint32_t randmodeIdx = std::numeric_limits<std::uint32_t>::max()) {
|
||||
|
@ -296,14 +356,14 @@ public:
|
|||
|
||||
template <typename T>
|
||||
void record_arr_table(T& var, const std::string name, int dimension,
|
||||
std::vector<size_t> indices, std::vector<size_t> idxWidths) {
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
const std::string key = generateKey(name, idx);
|
||||
m_arr_vars[key] = std::make_shared<ArrayInfo>(name, &var, idx, indices, idxWidths);
|
||||
++idx;
|
||||
}
|
||||
template <typename T>
|
||||
void record_arr_table(VlQueue<T>& var, const std::string name, int dimension,
|
||||
std::vector<size_t> indices, std::vector<size_t> idxWidths) {
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
if ((dimension > 0) && (var.size() != 0)) {
|
||||
idxWidths.push_back(32);
|
||||
for (size_t i = 0; i < var.size(); ++i) {
|
||||
|
@ -316,7 +376,7 @@ public:
|
|||
}
|
||||
template <typename T, std::size_t N_Depth>
|
||||
void record_arr_table(VlUnpacked<T, N_Depth>& var, const std::string name, int dimension,
|
||||
std::vector<size_t> indices, std::vector<size_t> idxWidths) {
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
if ((dimension > 0) && (N_Depth != 0)) {
|
||||
idxWidths.push_back(32);
|
||||
for (size_t i = 0; i < N_Depth; ++i) {
|
||||
|
@ -330,20 +390,27 @@ public:
|
|||
}
|
||||
template <typename T_Key, typename T_Value>
|
||||
void record_arr_table(VlAssocArray<T_Key, T_Value>& var, const std::string name, int dimension,
|
||||
std::vector<size_t> indices, std::vector<size_t> idxWidths) {
|
||||
std::vector<IData> indices, std::vector<size_t> idxWidths) {
|
||||
if ((dimension > 0) && (var.size() != 0)) {
|
||||
for (auto it = var.begin(); it != var.end(); ++it) {
|
||||
const T_Key& key = it->first;
|
||||
const T_Value& value = it->second;
|
||||
|
||||
std::string indexed_name;
|
||||
size_t integral_index;
|
||||
size_t idx_width;
|
||||
std::vector<size_t> integral_index;
|
||||
size_t idx_width = 0;
|
||||
|
||||
process_key(key, indexed_name, integral_index, name, idx_width);
|
||||
|
||||
// Update indices and widths
|
||||
idxWidths.push_back(idx_width);
|
||||
indices.push_back(integral_index);
|
||||
indices.insert(indices.end(), integral_index.begin(), integral_index.end());
|
||||
|
||||
record_arr_table(var.at(key), indexed_name, dimension - 1, indices, idxWidths);
|
||||
|
||||
// Cleanup indices and widths
|
||||
idxWidths.pop_back();
|
||||
indices.pop_back();
|
||||
indices.resize(indices.size() - integral_index.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -451,6 +451,7 @@ struct VlWide final {
|
|||
// METHODS
|
||||
const EData& at(size_t index) const { return m_storage[index]; }
|
||||
EData& at(size_t index) { return m_storage[index]; }
|
||||
size_t size() const { return N_Words; }
|
||||
WData* data() { return &m_storage[0]; }
|
||||
const WData* data() const { return &m_storage[0]; }
|
||||
bool operator<(const VlWide<N_Words>& rhs) const {
|
||||
|
|
|
@ -710,15 +710,19 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||
if (editFormat(nodep)) return;
|
||||
FileLine* const fl = nodep->fileline();
|
||||
if (VN_IS(nodep->bitp(), CvtPackString)) {
|
||||
// Extract and truncate the string index to fit within 64 bits
|
||||
AstCvtPackString* const stringp = VN_AS(nodep->bitp(), CvtPackString);
|
||||
const size_t stringSize = VN_AS(stringp->lhsp(), Const)->width();
|
||||
if (stringSize > 128) {
|
||||
stringp->v3warn(
|
||||
CONSTRAINTIGN,
|
||||
"Unsupported: Constrained randomization of associative array keys of "
|
||||
<< stringSize << "bits, limit is 128 bits");
|
||||
}
|
||||
VNRelinker handle;
|
||||
AstNodeExpr* const strIdxp = new AstSFormatF{
|
||||
fl, "#x%16x", false,
|
||||
new AstAnd{fl, stringp->lhsp()->unlinkFrBack(&handle),
|
||||
new AstConst(fl, AstConst::Unsized64{}, 0xFFFFFFFFFFFFFFFF)}};
|
||||
handle.relink(strIdxp);
|
||||
editSMT(nodep, nodep->fromp(), strIdxp);
|
||||
AstNodeExpr* const idxp
|
||||
= new AstSFormatF{fl, "#x%32x", false, stringp->lhsp()->unlinkFrBack(&handle)};
|
||||
handle.relink(idxp);
|
||||
editSMT(nodep, nodep->fromp(), idxp);
|
||||
} else {
|
||||
VNRelinker handle;
|
||||
const int actual_width = nodep->bitp()->width();
|
||||
|
@ -728,16 +732,10 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||
fmt = "#x%2x";
|
||||
} else if (actual_width <= 16) {
|
||||
fmt = "#x%4x";
|
||||
} else if (actual_width <= 32) {
|
||||
fmt = "#x%8x";
|
||||
} else if (actual_width <= 64) {
|
||||
fmt = "#x%16x";
|
||||
} else {
|
||||
nodep->v3warn(CONSTRAINTIGN,
|
||||
"Unsupported: Associative array index "
|
||||
"widths of more than 64 bits during constraint randomization.");
|
||||
return;
|
||||
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);
|
||||
|
@ -1450,11 +1448,8 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
AstNodeStmt* stmtsp = nullptr;
|
||||
auto createLoopIndex = [&](AstNodeDType* tempDTypep) {
|
||||
if (VN_IS(tempDTypep, AssocArrayDType)) {
|
||||
return new AstVar{
|
||||
fl, VVarType::VAR, uniqueNamep->get(""),
|
||||
dtypep->findBasicDType(
|
||||
((AstBasicDType*)VN_AS(tempDTypep, AssocArrayDType)->keyDTypep())
|
||||
->keyword())};
|
||||
return new AstVar{fl, VVarType::VAR, uniqueNamep->get(""),
|
||||
VN_AS(tempDTypep, AssocArrayDType)->keyDTypep()};
|
||||
}
|
||||
return new AstVar{fl, VVarType::VAR, uniqueNamep->get(""),
|
||||
dtypep->findBasicDType(VBasicDTypeKwd::UINT32)};
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
%Warning-CONSTRAINTIGN: t/t_constraint_assoc_arr_bad.v:14:22: Unsupported: Associative array index widths of more than 64 bits during constraint randomization.
|
||||
14 | bit_index_arr[79'd66] == 65;
|
||||
| ^
|
||||
%Warning-CONSTRAINTIGN: t/t_constraint_assoc_arr_bad.v:12:20: Unsupported: Constrained randomization of associative array keys of 144bits, limit is 128 bits
|
||||
12 | string_arr["a_very_long_string"] == 65;
|
||||
| ^~~~~~~~~~~~~~~~~~~~
|
||||
... 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.
|
||||
%Warning-CONSTRAINTIGN: t/t_constraint_assoc_arr_bad.v:15:24: Unsupported: Associative array index widths of more than 64 bits during constraint randomization.
|
||||
15 | logic_index_arr[65'd3] == 70;
|
||||
| ^
|
||||
%Error: Exiting due to
|
||||
|
|
|
@ -4,19 +4,15 @@
|
|||
// any use, without warranty, 2024 by PlanV GmbH.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
|
||||
class AssocArrayWarningTest;
|
||||
|
||||
rand int bit_index_arr [bit[78:0]];
|
||||
rand int logic_index_arr [logic[64:0]];
|
||||
rand int string_arr [string];
|
||||
|
||||
constraint c {
|
||||
bit_index_arr[79'd66] == 65;
|
||||
logic_index_arr[65'd3] == 70;
|
||||
string_arr["a_very_long_string"] == 65;
|
||||
}
|
||||
function new();
|
||||
bit_index_arr = '{79'd66:0};
|
||||
logic_index_arr = '{65'd3:0};
|
||||
string_arr["a_very_long_string"] = 0;
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
|
|
@ -147,11 +147,33 @@ class constrained_2d_associative_array;
|
|||
/* verilator lint_off SIDEEFFECT */
|
||||
endclass
|
||||
|
||||
class AssocArray64bitMoreTest;
|
||||
|
||||
rand int bit_index_arr [bit[78:0]];
|
||||
rand int logic_index_arr [logic[64:0]];
|
||||
|
||||
constraint c {
|
||||
bit_index_arr[79'd66] == 65;
|
||||
logic_index_arr[65'd3] == 70;
|
||||
}
|
||||
function new();
|
||||
bit_index_arr = '{79'd66:0};
|
||||
logic_index_arr = '{65'd3:0};
|
||||
endfunction
|
||||
function void self_check();
|
||||
if (bit_index_arr[79'd66] != 65) $stop;
|
||||
if (logic_index_arr[65'd3] != 70) $stop;
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
module t_constraint_assoc_arr_basic;
|
||||
|
||||
constrained_associative_array_basic my_array;
|
||||
constrained_1d_associative_array my_1d_array;
|
||||
constrained_2d_associative_array my_2d_array;
|
||||
|
||||
AssocArray64bitMoreTest test_obj;
|
||||
int success;
|
||||
|
||||
initial begin
|
||||
|
@ -165,10 +187,16 @@ module t_constraint_assoc_arr_basic;
|
|||
if (success == 0) $stop;
|
||||
my_1d_array.self_check();
|
||||
|
||||
my_1d_array = new();
|
||||
success = my_1d_array.randomize();
|
||||
my_2d_array = new();
|
||||
success = my_2d_array.randomize();
|
||||
if (success == 0) $stop;
|
||||
my_1d_array.self_check();
|
||||
my_2d_array.self_check();
|
||||
|
||||
test_obj = new();
|
||||
repeat(2) begin
|
||||
success = test_obj.randomize();
|
||||
if (success != 1) $stop;
|
||||
end
|
||||
|
||||
// my_1d_array.debug_display();
|
||||
// my_2d_array.debug_display();
|
||||
|
|
|
@ -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,115 @@
|
|||
// 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
|
||||
|
||||
class AssocIntegralWide;
|
||||
|
||||
rand bit [31:0] assoc_array[bit[64:0]];
|
||||
rand bit [31:0] assoc_array_128[bit[128:0]];
|
||||
rand bit [31:0] assoc_array_2d[bit[64:0]][bit[128:0]];
|
||||
|
||||
constraint valid_entries {
|
||||
assoc_array[65'd6] == 32'd8;
|
||||
assoc_array[65'h1FFFFFFFFFFFFFFFF] == 32'hDEADBEEF;
|
||||
|
||||
assoc_array_128[129'd6] == 32'd16;
|
||||
assoc_array_128[129'h1FFFFFFFFFFFFFFFFFFFFFFFF] == 32'hCAFEBABE;
|
||||
|
||||
assoc_array_2d[65'd6][129'd6] == 32'd32;
|
||||
assoc_array_2d[65'h1FFFFFFFFFFFFFFFF][129'h1FFFFFFFFFFFFFFFFFFFFFFFF] == 32'hBADF00D;
|
||||
}
|
||||
|
||||
// Constructor to initialize arrays
|
||||
function new();
|
||||
assoc_array[65'd0] = 32'd0;
|
||||
assoc_array[65'd6] = 32'd0;
|
||||
assoc_array[65'h1FFFFFFFFFFFFFFFF] = 32'd0;
|
||||
|
||||
assoc_array_128[129'd0] = 32'd0;
|
||||
assoc_array_128[129'd6] = 32'd0;
|
||||
assoc_array_128[129'h1FFFFFFFFFFFFFFFFFFFFFFFF] = 32'd0;
|
||||
|
||||
assoc_array_2d[65'd6][129'd6] = 32'd0;
|
||||
assoc_array_2d[65'h1FFFFFFFFFFFFFFFF][129'h1FFFFFFFFFFFFFFFFFFFFFFFF] = 32'd0;
|
||||
endfunction
|
||||
|
||||
// Self-check function to verify constraints
|
||||
function void self_check();
|
||||
if (assoc_array[65'd6] != 32'd8)
|
||||
$stop;
|
||||
if (assoc_array[65'h1FFFFFFFFFFFFFFFF] != 32'hDEADBEEF)
|
||||
$stop;
|
||||
|
||||
if (assoc_array_128[129'd6] != 32'd16)
|
||||
$stop;
|
||||
if (assoc_array_128[129'h1FFFFFFFFFFFFFFFFFFFFFFFF] != 32'hCAFEBABE)
|
||||
$stop;
|
||||
|
||||
if (assoc_array_2d[65'd6][129'd6] != 32'd32)
|
||||
$stop;
|
||||
if (assoc_array_2d[65'h1FFFFFFFFFFFFFFFF][129'h1FFFFFFFFFFFFFFFFFFFFFFFF] != 32'hBADF00D)
|
||||
$stop;
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
class AssocStringWide;
|
||||
|
||||
rand bit [31:0] array_32[string];
|
||||
rand bit [31:0] array_64[string];
|
||||
rand bit [31:0] array_96[string];
|
||||
rand bit [31:0] array_128[string];
|
||||
|
||||
constraint valid_entries {
|
||||
// <= 32 bits
|
||||
array_32["pv"] == 32'd10;
|
||||
// > 32 and <= 64 bits
|
||||
array_64["verilog"] == 32'd20;
|
||||
// > 32 and <= 64 bits
|
||||
array_96["verilator"] == 32'd30;
|
||||
// > 64 and <= 96 bits
|
||||
array_128["systemverilog"] == 32'd40;
|
||||
}
|
||||
|
||||
function new();
|
||||
array_32["pv"] = 32'd0;
|
||||
array_64["verilog"] = 32'd0;
|
||||
array_96["verilator"] = 32'd0;
|
||||
array_128["systemverilog"] = 32'd0;
|
||||
endfunction
|
||||
|
||||
function void self_check();
|
||||
if (array_32["pv"] != 32'd10) $stop;
|
||||
if (array_64["verilog"] != 32'd20) $stop;
|
||||
if (array_96["verilator"] != 32'd30) $stop;
|
||||
if (array_128["systemverilog"] != 32'd40) $stop;
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
|
||||
module t_constraint_assoc_arr_wide;
|
||||
|
||||
AssocIntegralWide integral_wide;
|
||||
AssocStringWide string_wide;
|
||||
|
||||
int success;
|
||||
initial begin
|
||||
|
||||
integral_wide = new();
|
||||
string_wide = new();
|
||||
|
||||
success = integral_wide.randomize();
|
||||
if (success != 1) $stop;
|
||||
integral_wide.self_check();
|
||||
|
||||
success = string_wide.randomize();
|
||||
if (success != 1) $stop;
|
||||
string_wide.self_check();
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
Loading…
Reference in New Issue