parent
446bec3d1a
commit
9b1b9a5b3b
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "verilated_random.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
|
@ -367,13 +368,90 @@ void VlRandomizer::randomConstraint(std::ostream& os, VlRNG& rngr, int bits) {
|
|||
os << ')';
|
||||
}
|
||||
|
||||
size_t VlRandomizer::hashConstraints() const {
|
||||
size_t h = 0;
|
||||
for (const auto& c : m_constraints) {
|
||||
h ^= std::hash<std::string>{}(c) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
void VlRandomizer::enumerateRandcValues(const std::string& varName, VlRNG& rngr) {
|
||||
std::vector<uint64_t> values;
|
||||
const auto varIt = m_vars.find(varName);
|
||||
if (varIt == m_vars.end()) return;
|
||||
const int width = varIt->second->width();
|
||||
|
||||
std::iostream& os = getSolver();
|
||||
if (!os) return;
|
||||
|
||||
// Set up a single incremental solver session for enumeration
|
||||
os << "(set-option :produce-models true)\n";
|
||||
os << "(set-logic QF_ABV)\n";
|
||||
os << "(define-fun __Vbv ((b Bool)) (_ BitVec 1) (ite b #b1 #b0))\n";
|
||||
os << "(define-fun __Vbool ((v (_ BitVec 1))) Bool (= #b1 v))\n";
|
||||
|
||||
// Declare all variables (solver needs full context for cross-var constraints)
|
||||
for (const auto& var : m_vars) {
|
||||
if (var.second->dimension() > 0) {
|
||||
auto arrVarsp = std::make_shared<const ArrayInfoMap>(m_arr_vars);
|
||||
var.second->setArrayInfo(arrVarsp);
|
||||
}
|
||||
os << "(declare-fun " << var.first << " () ";
|
||||
var.second->emitType(os);
|
||||
os << ")\n";
|
||||
}
|
||||
|
||||
// Assert all user constraints
|
||||
for (const std::string& constraint : m_constraints) {
|
||||
os << "(assert (= #b1 " << constraint << "))\n";
|
||||
}
|
||||
|
||||
// Incrementally enumerate all valid values for this randc variable
|
||||
while (true) {
|
||||
os << "(check-sat)\n";
|
||||
std::string sat;
|
||||
do { std::getline(os, sat); } while (sat.empty());
|
||||
if (sat != "sat") break;
|
||||
|
||||
// Read just this variable's value
|
||||
os << "(get-value (" << varName << "))\n";
|
||||
char c;
|
||||
os >> c; // '('
|
||||
os >> c; // '('
|
||||
std::string name, value;
|
||||
os >> name; // Consume variable name token from solver output
|
||||
(void)name;
|
||||
std::getline(os, value, ')');
|
||||
os >> c; // ')'
|
||||
|
||||
// Parse the SMT value to uint64_t
|
||||
VlWide<VL_WQ_WORDS_E> qowp;
|
||||
VL_SET_WQ(qowp, 0ULL);
|
||||
if (!parseSMTNum(width, qowp, value)) break;
|
||||
const uint64_t numVal = (width <= 32) ? qowp[0] : VL_SET_QW(qowp);
|
||||
|
||||
values.push_back(numVal);
|
||||
|
||||
// Exclude this value for next iteration (incremental)
|
||||
os << "(assert (not (= " << varName << " (_ bv" << numVal << " " << width << "))))\n";
|
||||
}
|
||||
|
||||
os << "(reset)\n";
|
||||
|
||||
// Shuffle using Fisher-Yates
|
||||
for (size_t i = values.size(); i > 1; --i) {
|
||||
const size_t j = VL_RANDOM_RNG_I(rngr) % i;
|
||||
std::swap(values[i - 1], values[j]);
|
||||
}
|
||||
|
||||
m_randcValueQueues[varName] = std::deque<uint64_t>(values.begin(), values.end());
|
||||
}
|
||||
|
||||
bool VlRandomizer::next(VlRNG& rngr) {
|
||||
if (m_vars.empty() && m_unique_arrays.empty()) return true;
|
||||
for (const std::string& baseName : m_unique_arrays) {
|
||||
const auto it = m_vars.find(baseName);
|
||||
|
||||
// Look up the actual size we stored earlier
|
||||
// const uint32_t size = m_unique_array_sizes[baseName];
|
||||
const uint32_t size = m_unique_array_sizes.at(baseName);
|
||||
|
||||
if (it != m_vars.end()) {
|
||||
|
|
@ -388,6 +466,30 @@ bool VlRandomizer::next(VlRNG& rngr) {
|
|||
}
|
||||
}
|
||||
|
||||
// Randc queue-based cycling: enumerate valid values once, then pop per call
|
||||
if (!m_randcVarNames.empty()) {
|
||||
const size_t currentHash = hashConstraints();
|
||||
// Invalidate queues if constraints changed (e.g., constraint_mode toggled)
|
||||
if (currentHash != m_randcConstraintHash) {
|
||||
m_randcValueQueues.clear();
|
||||
m_randcConstraintHash = currentHash;
|
||||
}
|
||||
// Refill empty queues (start of new cycle)
|
||||
for (const auto& name : m_randcVarNames) {
|
||||
auto& queue = m_randcValueQueues[name];
|
||||
if (queue.empty()) enumerateRandcValues(name, rngr);
|
||||
}
|
||||
}
|
||||
|
||||
// Pop randc values from queues (will be pinned in solver)
|
||||
std::map<std::string, uint64_t> randcPinned;
|
||||
for (const auto& name : m_randcVarNames) {
|
||||
auto& queue = m_randcValueQueues[name];
|
||||
if (queue.empty()) return false; // No valid values exist
|
||||
randcPinned[name] = queue.front();
|
||||
queue.pop_front();
|
||||
}
|
||||
|
||||
std::iostream& os = getSolver();
|
||||
if (!os) return false;
|
||||
|
||||
|
|
@ -408,6 +510,13 @@ bool VlRandomizer::next(VlRNG& rngr) {
|
|||
for (const std::string& constraint : m_constraints) {
|
||||
os << "(assert (= #b1 " << constraint << "))\n";
|
||||
}
|
||||
|
||||
// Pin randc values from pre-enumerated queues
|
||||
for (const auto& pair : randcPinned) {
|
||||
const int w = m_vars.at(pair.first)->width();
|
||||
os << "(assert (= " << pair.first << " (_ bv" << pair.second << " " << w << ")))\n";
|
||||
}
|
||||
|
||||
os << "(check-sat)\n";
|
||||
|
||||
bool sat = parseSolution(os, true);
|
||||
|
|
@ -620,8 +729,13 @@ void VlRandomizer::clearConstraints() {
|
|||
void VlRandomizer::clearAll() {
|
||||
m_constraints.clear();
|
||||
m_vars.clear();
|
||||
m_randcVarNames.clear();
|
||||
m_randcValueQueues.clear();
|
||||
m_randcConstraintHash = 0;
|
||||
}
|
||||
|
||||
void VlRandomizer::markRandc(const char* name) { m_randcVarNames.insert(name); }
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
void VlRandomizer::dump() const {
|
||||
for (const auto& var : m_vars) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "verilated.h"
|
||||
|
||||
#include <deque>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
|
@ -209,10 +210,16 @@ class VlRandomizer VL_NOT_FINAL {
|
|||
std::map<std::string, uint32_t> m_unique_array_sizes;
|
||||
const VlQueue<CData>* m_randmodep = nullptr; // rand_mode state;
|
||||
int m_index = 0; // Internal counter for key generation
|
||||
std::set<std::string> m_randcVarNames; // Names of randc variables for cyclic tracking
|
||||
std::map<std::string, std::deque<uint64_t>>
|
||||
m_randcValueQueues; // Remaining values per randc var (queue-based cycling)
|
||||
size_t m_randcConstraintHash = 0; // Hash of constraints when queues were built
|
||||
|
||||
// PRIVATE METHODS
|
||||
void randomConstraint(std::ostream& os, VlRNG& rngr, int bits);
|
||||
bool parseSolution(std::iostream& file, bool log = false);
|
||||
void enumerateRandcValues(const std::string& varName, VlRNG& rngr);
|
||||
size_t hashConstraints() const;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -585,6 +592,7 @@ public:
|
|||
const char* source = "");
|
||||
void clearConstraints();
|
||||
void clearAll(); // Clear both constraints and variables
|
||||
void markRandc(const char* name); // Mark variable as randc for cyclic tracking
|
||||
void set_randmode(const VlQueue<CData>& randmode) { m_randmodep = &randmode; }
|
||||
#ifdef VL_DEBUG
|
||||
void dump() const;
|
||||
|
|
|
|||
|
|
@ -815,6 +815,7 @@ public:
|
|||
RANDOMIZER_CLEARALL,
|
||||
RANDOMIZER_HARD,
|
||||
RANDOMIZER_UNIQUE,
|
||||
RANDOMIZER_MARK_RANDC,
|
||||
RANDOMIZER_WRITE_VAR,
|
||||
RNG_GET_RANDSTATE,
|
||||
RNG_SET_RANDSTATE,
|
||||
|
|
@ -947,6 +948,7 @@ inline std::ostream& operator<<(std::ostream& os, const VCMethod& rhs) {
|
|||
{RANDOMIZER_CLEARALL, "clearAll", false}, \
|
||||
{RANDOMIZER_HARD, "hard", false}, \
|
||||
{RANDOMIZER_UNIQUE, "rand_unique", false}, \
|
||||
{RANDOMIZER_MARK_RANDC, "markRandc", false}, \
|
||||
{RANDOMIZER_WRITE_VAR, "write_var", false}, \
|
||||
{RNG_GET_RANDSTATE, "__Vm_rng.get_randstate", true}, \
|
||||
{RNG_SET_RANDSTATE, "__Vm_rng.set_randstate", false}, \
|
||||
|
|
|
|||
|
|
@ -1135,6 +1135,20 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
initTaskp->addStmtsp(methodp->makeStmt());
|
||||
// If randc, also emit markRandc() for cyclic tracking
|
||||
if (varp->isRandC()) {
|
||||
AstCMethodHard* const markp = new AstCMethodHard{
|
||||
varp->fileline(),
|
||||
new AstVarRef{varp->fileline(), VN_AS(m_genp->user2p(), NodeModule),
|
||||
m_genp, VAccess::READWRITE},
|
||||
VCMethod::RANDOMIZER_MARK_RANDC};
|
||||
markp->dtypeSetVoid();
|
||||
AstNodeExpr* const nameExprp = new AstCExpr{
|
||||
varp->fileline(), AstCExpr::Pure{}, "\"" + smtName + "\"", varp->width()};
|
||||
nameExprp->dtypep(varp->dtypep());
|
||||
markp->addPinsp(nameExprp);
|
||||
initTaskp->addStmtsp(markp->makeStmt());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Variable already written, clean up cloned membersel if any
|
||||
|
|
@ -3194,7 +3208,8 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
stmtp = stmtp->nextp()) {
|
||||
bool foundClearConstraints = false;
|
||||
stmtp->foreach([&](AstCMethodHard* methodp) {
|
||||
if (methodp->method() == VCMethod::RANDOMIZER_WRITE_VAR) {
|
||||
if (methodp->method() == VCMethod::RANDOMIZER_WRITE_VAR
|
||||
|| methodp->method() == VCMethod::RANDOMIZER_MARK_RANDC) {
|
||||
randomizep->addStmtsp(stmtp->cloneTree(false));
|
||||
} else if (methodp->method()
|
||||
== VCMethod::RANDOMIZER_CLEARCONSTRAINTS) {
|
||||
|
|
@ -3544,7 +3559,8 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
for (AstNode* stmtp = mainRandomizep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
bool foundClearConstraints = false;
|
||||
stmtp->foreach([&](AstCMethodHard* methodp) {
|
||||
if (methodp->method() == VCMethod::RANDOMIZER_WRITE_VAR) {
|
||||
if (methodp->method() == VCMethod::RANDOMIZER_WRITE_VAR
|
||||
|| methodp->method() == VCMethod::RANDOMIZER_MARK_RANDC) {
|
||||
randomizeFuncp->addStmtsp(stmtp->cloneTree(false));
|
||||
} else if (methodp->method() == VCMethod::RANDOMIZER_CLEARCONSTRAINTS) {
|
||||
foundClearConstraints = true;
|
||||
|
|
|
|||
|
|
@ -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,272 @@
|
|||
// 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
|
||||
|
||||
// Test: randc variables with additional constraints limiting values
|
||||
// IEEE 1800 Section 18.4.2: randc cyclic behavior over constrained domain
|
||||
|
||||
// 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);
|
||||
`define check_range(gotv,minv,maxv) do if ((gotv) < (minv) || (gotv) > (maxv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d-%0d\n", `__FILE__,`__LINE__, (gotv), (minv), (maxv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
class RandcRange;
|
||||
randc bit [3:0] value; // 4-bit: unconstrained domain = 0-15
|
||||
|
||||
constraint c_range {
|
||||
value >= 3;
|
||||
value <= 10;
|
||||
}
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[16];
|
||||
automatic int domain_size = 8; // values 3..10
|
||||
automatic int randomize_result;
|
||||
$display("Test randc with range constraint [3:10]");
|
||||
// Run 3 full cycles
|
||||
for (int trial = 0; trial < 3; ++trial) begin
|
||||
for (int i = 0; i < domain_size; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
`check_range(value, 3, 10);
|
||||
++count[value];
|
||||
end
|
||||
end
|
||||
// After 3 full cycles, each value in [3,10] should appear exactly 3 times
|
||||
for (int v = 3; v <= 10; ++v) begin
|
||||
`checkd(count[v], 3);
|
||||
end
|
||||
// Values outside [3,10] should never appear
|
||||
for (int v = 0; v < 3; ++v) begin
|
||||
`checkd(count[v], 0);
|
||||
end
|
||||
for (int v = 11; v < 16; ++v) begin
|
||||
`checkd(count[v], 0);
|
||||
end
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class RandcSmall;
|
||||
randc bit [1:0] val; // 4 possible values: 0,1,2,3
|
||||
constraint c_exclude { val != 0; } // 3 valid values: 1,2,3
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[4];
|
||||
automatic int domain_size = 3;
|
||||
automatic int randomize_result;
|
||||
$display("Test randc with exclude constraint (val != 0)");
|
||||
// Run 4 full cycles
|
||||
for (int trial = 0; trial < 4; ++trial) begin
|
||||
for (int i = 0; i < domain_size; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
`checkd(val == 0, 0);
|
||||
++count[val];
|
||||
end
|
||||
end
|
||||
// After 4 full cycles, each of 1,2,3 should appear exactly 4 times
|
||||
`checkd(count[0], 0);
|
||||
for (int v = 1; v <= 3; ++v) begin
|
||||
`checkd(count[v], 4);
|
||||
end
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
// Test 3: Inheritance - parent randc with constraint, child inherits
|
||||
class RandcParent;
|
||||
randc bit [2:0] code; // 8 values: 0-7
|
||||
constraint c_positive { code > 0; } // 7 valid values: 1-7
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[8];
|
||||
automatic int domain_size = 7;
|
||||
automatic int randomize_result;
|
||||
$display("Test randc parent with constraint (code > 0)");
|
||||
for (int trial = 0; trial < 3; ++trial) begin
|
||||
for (int i = 0; i < domain_size; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
`checkd(code == 0, 0);
|
||||
++count[code];
|
||||
end
|
||||
end
|
||||
for (int v = 1; v <= 7; ++v) begin
|
||||
`checkd(count[v], 3);
|
||||
end
|
||||
`checkd(count[0], 0);
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class RandcChild extends RandcParent;
|
||||
// Inherits randc code and c_positive constraint
|
||||
constraint c_upper { code <= 5; } // Further restrict: 1-5 (5 values)
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[8];
|
||||
automatic int domain_size = 5;
|
||||
automatic int randomize_result;
|
||||
$display("Test randc child with inherited + additional constraint (1 <= code <= 5)");
|
||||
for (int trial = 0; trial < 4; ++trial) begin
|
||||
for (int i = 0; i < domain_size; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
`check_range(code, 1, 5);
|
||||
++count[code];
|
||||
end
|
||||
end
|
||||
for (int v = 1; v <= 5; ++v) begin
|
||||
`checkd(count[v], 4);
|
||||
end
|
||||
for (int v = 6; v <= 7; ++v) begin
|
||||
`checkd(count[v], 0);
|
||||
end
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
// Test 5: constraint_mode() interaction
|
||||
// Verifies randc cyclic behavior adapts when constraints are toggled at runtime.
|
||||
// Note: randc cycles are continuous, not per-phase, so we verify constraint
|
||||
// enforcement and that all valid values eventually appear rather than exact counts.
|
||||
class RandcModeSwitch;
|
||||
randc bit [1:0] x; // 4 values: 0-3
|
||||
constraint c_nonzero { x != 0; } // 3 valid values: 1,2,3
|
||||
|
||||
function void test_mode_switch;
|
||||
automatic int randomize_result;
|
||||
automatic bit seen_zero;
|
||||
|
||||
// Phase 1: constraint ON -> x should never be 0, and all of {1,2,3} should appear
|
||||
$display("Test constraint_mode: phase 1 (constraint ON)");
|
||||
begin
|
||||
automatic bit seen[4] = '{0, 0, 0, 0};
|
||||
// Run 2 full cycles (6 calls) to ensure all constrained values appear
|
||||
for (int i = 0; i < 6; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
`checkd(x == 0, 0);
|
||||
seen[x] = 1;
|
||||
end
|
||||
for (int v = 1; v <= 3; ++v) begin
|
||||
`checkd(seen[v], 1);
|
||||
end
|
||||
end
|
||||
|
||||
// Phase 2: constraint OFF -> x=0 should eventually appear
|
||||
$display("Test constraint_mode: phase 2 (constraint OFF)");
|
||||
c_nonzero.constraint_mode(0);
|
||||
seen_zero = 0;
|
||||
// Run enough calls (2 full cycles of 4 + margin) to see all values
|
||||
for (int i = 0; i < 12; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
if (x == 0) seen_zero = 1;
|
||||
end
|
||||
`checkd(seen_zero, 1);
|
||||
|
||||
// Phase 3: constraint back ON -> x should never be 0 again
|
||||
$display("Test constraint_mode: phase 3 (constraint ON again)");
|
||||
c_nonzero.constraint_mode(1);
|
||||
for (int i = 0; i < 9; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
`checkd(x == 0, 0);
|
||||
end
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
// Test 6: Enum randc with constraint excluding some values
|
||||
// Use a 2-bit enum where all bit values are valid enum members,
|
||||
// so the solver domain matches the enum domain exactly.
|
||||
class RandcEnumConstrained;
|
||||
typedef enum bit [1:0] {
|
||||
RED = 0,
|
||||
GREEN = 1,
|
||||
BLUE = 2,
|
||||
WHITE = 3
|
||||
} color_t;
|
||||
|
||||
randc color_t color;
|
||||
constraint c_no_white { color != WHITE; } // 3 valid: RED, GREEN, BLUE
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[4] = '{0, 0, 0, 0};
|
||||
automatic int domain_size = 3;
|
||||
automatic int randomize_result;
|
||||
$display("Test randc enum with constraint (exclude WHITE)");
|
||||
for (int trial = 0; trial < 4; ++trial) begin
|
||||
for (int i = 0; i < domain_size; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
`checkd(color == WHITE, 0);
|
||||
++count[color];
|
||||
end
|
||||
end
|
||||
for (int v = 0; v <= 2; ++v) begin
|
||||
`checkd(count[v], 4);
|
||||
end
|
||||
`checkd(count[3], 0);
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
// Test 7: Deep cyclic - full 4-bit range 0:15 (16 values, no constraint)
|
||||
class RandcDeep;
|
||||
randc bit [3:0] val;
|
||||
|
||||
function void test_cyclic;
|
||||
automatic int count[16];
|
||||
automatic int domain_size = 16;
|
||||
automatic int randomize_result;
|
||||
$display("Test randc deep cyclic [0:15] (16 values)");
|
||||
// Run 3 full cycles
|
||||
for (int trial = 0; trial < 3; ++trial) begin
|
||||
for (int i = 0; i < domain_size; ++i) begin
|
||||
randomize_result = randomize();
|
||||
`checkd(randomize_result, 1);
|
||||
++count[val];
|
||||
end
|
||||
end
|
||||
// Each value 0..15 should appear exactly 3 times
|
||||
for (int v = 0; v < 16; ++v) begin
|
||||
`checkd(count[v], 3);
|
||||
end
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
RandcRange rr;
|
||||
RandcSmall rs;
|
||||
RandcParent rp;
|
||||
RandcChild rc;
|
||||
RandcModeSwitch rms;
|
||||
RandcEnumConstrained rec;
|
||||
RandcDeep rd;
|
||||
|
||||
initial begin
|
||||
rr = new;
|
||||
rr.test_cyclic();
|
||||
|
||||
rs = new;
|
||||
rs.test_cyclic();
|
||||
|
||||
rp = new;
|
||||
rp.test_cyclic();
|
||||
|
||||
rc = new;
|
||||
rc.test_cyclic();
|
||||
|
||||
rms = new;
|
||||
rms.test_mode_switch();
|
||||
|
||||
rec = new;
|
||||
rec.test_cyclic();
|
||||
|
||||
rd = new;
|
||||
rd.test_cyclic();
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish();
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue