Support IEEE-compliant force/release handling (#7391)
This commit is contained in:
parent
280cff06f3
commit
a1a8b9624c
|
|
@ -0,0 +1,258 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
// Copyright 2026-2026 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: Runtime support for force/release statements
|
||||
///
|
||||
/// This file provides runtime data structures for efficient dynamic
|
||||
/// resolution of force/release statements. A sorted list of active
|
||||
/// forces is maintained that can be efficiently queried and modified
|
||||
/// at runtime.
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef VERILATOR_VERILATED_FORCE_H_
|
||||
#define VERILATOR_VERILATED_FORCE_H_
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
template <typename T>
|
||||
using VlForceBaseType = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
||||
|
||||
// VlForceRead - Helper functions to read a forced value
|
||||
//
|
||||
// These functions combine original value with forced values based on
|
||||
// VlForceVec entries.
|
||||
// This achieves O(k) complexity where k = number of active forces.
|
||||
|
||||
template <typename T>
|
||||
struct VlForceTypeInfo final {
|
||||
using Type = VlForceBaseType<T>;
|
||||
static constexpr bool bitwise
|
||||
= std::is_integral<Type>::value || std::is_enum<Type>::value || VlIsVlWide<Type>::value;
|
||||
static constexpr bool unpackedArray = false;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct VlForceArrayIndexer final {
|
||||
static constexpr std::size_t size = 1;
|
||||
|
||||
static T& elem(T& value, std::size_t) { return value; }
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct VlForceArrayIndexer<VlUnpacked<T, N>> final {
|
||||
static constexpr std::size_t size = N * VlForceArrayIndexer<T>::size;
|
||||
|
||||
static auto& elem(VlUnpacked<T, N>& array, std::size_t index) {
|
||||
constexpr std::size_t subSize = VlForceArrayIndexer<T>::size;
|
||||
return VlForceArrayIndexer<T>::elem(array[index / subSize], index % subSize);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct VlForceTypeInfo<VlUnpacked<T, N>> final {
|
||||
using Type = VlUnpacked<T, N>;
|
||||
static constexpr bool bitwise = false;
|
||||
static constexpr bool unpackedArray = true;
|
||||
};
|
||||
|
||||
template <typename T, bool = std::is_enum<T>::value>
|
||||
struct VlForceStorageTypeOf final {
|
||||
using type = typename std::make_unsigned<T>::type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct VlForceStorageTypeOf<T, true> final {
|
||||
using type = typename std::make_unsigned<typename std::underlying_type<T>::type>::type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using VlForceStorageType = typename VlForceStorageTypeOf<VlForceBaseType<T>>::type;
|
||||
|
||||
//=============================================================================
|
||||
// VlForceVec - Vector of active force entries for a signal
|
||||
//
|
||||
// This class maintains a sorted vector of non-overlapping force entries.
|
||||
// When a new force is added, it removes or trims existing entries that
|
||||
// overlap with the new range.
|
||||
//
|
||||
// The generated code will:
|
||||
// 1. Use addForce/release to update the active forces
|
||||
// 2. Call a generated read function that iterates entries and evaluates RHS
|
||||
|
||||
class VlForceVec final {
|
||||
private:
|
||||
struct Entry final {
|
||||
int m_lsb; // Inclusive lower bit
|
||||
int m_msb; // Inclusive upper bit
|
||||
int m_rhsLsb; // Destination index that maps to RHS index 0
|
||||
const void* m_rhsDatap; // Pointer to RHS storage
|
||||
|
||||
bool operator<(const Entry& other) const { return m_msb < other.m_msb; }
|
||||
};
|
||||
|
||||
std::vector<Entry> m_entries; // Sorted by msb, non-overlapping
|
||||
|
||||
std::vector<Entry>::iterator trimEntries(int lsb, int msb) {
|
||||
auto it = std::lower_bound(m_entries.begin(), m_entries.end(), lsb,
|
||||
[](const Entry& e, int bit) { return e.m_msb < bit; });
|
||||
while (it != m_entries.end() && it->m_lsb <= msb) {
|
||||
if (it->m_lsb < lsb && it->m_msb > msb) {
|
||||
const Entry right{msb + 1, it->m_msb, it->m_rhsLsb, it->m_rhsDatap};
|
||||
it->m_msb = lsb - 1;
|
||||
return m_entries.insert(++it, right);
|
||||
}
|
||||
if (it->m_lsb < lsb) {
|
||||
it->m_msb = lsb - 1;
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
if (it->m_msb > msb) {
|
||||
it->m_lsb = msb + 1;
|
||||
return it;
|
||||
}
|
||||
it = m_entries.erase(it);
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
static QData extractRhsChunk(const Entry& entry, int rhsLsb, int width) {
|
||||
assert(width > 0 && width <= VL_QUADSIZE);
|
||||
assert(rhsLsb >= 0);
|
||||
|
||||
const QData mask = static_cast<QData>(VL_MASK_Q(width));
|
||||
const int rhsWidth = entry.m_msb - entry.m_rhsLsb + 1;
|
||||
if (rhsWidth <= VL_QUADSIZE) {
|
||||
const QData rhsVal = static_cast<QData>(*static_cast<const QData*>(entry.m_rhsDatap));
|
||||
return (rhsVal >> rhsLsb) & mask;
|
||||
}
|
||||
|
||||
const EData* const rhswp = static_cast<const EData*>(entry.m_rhsDatap);
|
||||
return VL_SEL_QWII(rhsWidth, rhswp, rhsLsb, width) & mask;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T applyBits(T cur, const Entry& entry, int lsb, int width, int rhsLsb) {
|
||||
const T lowMask = static_cast<T>(VL_MASK_Q(width));
|
||||
const T mask = static_cast<T>(lowMask << lsb);
|
||||
const T rhsBits = static_cast<T>(
|
||||
(static_cast<T>(extractRhsChunk(entry, rhsLsb, width)) & lowMask) << lsb);
|
||||
return static_cast<T>((cur & ~mask) | (rhsBits & mask));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename std::enable_if<VlIsVlWide<T>::value, T>::type applyEntry(T result,
|
||||
const Entry& entry) {
|
||||
EData* const reswp = result.data();
|
||||
const int lword = VL_BITWORD_E(entry.m_lsb);
|
||||
const int hword = VL_BITWORD_E(entry.m_msb);
|
||||
for (int word = lword; word <= hword; ++word) {
|
||||
const int wordLsb = word * VL_EDATASIZE;
|
||||
const int segLsb = std::max(entry.m_lsb, wordLsb);
|
||||
const int segMsb = std::min(entry.m_msb, wordLsb + VL_EDATASIZE - 1);
|
||||
const int segWidth = segMsb - segLsb + 1;
|
||||
const int bitOffset = segLsb - wordLsb;
|
||||
const int rhsLsb = segLsb - entry.m_rhsLsb;
|
||||
reswp[word] = applyBits(reswp[word], entry, bitOffset, segWidth, rhsLsb);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename std::enable_if<!VlIsVlWide<T>::value && VlForceTypeInfo<T>::bitwise, T>::type
|
||||
applyEntry(T result, const Entry& entry) {
|
||||
using U = VlForceStorageType<T>;
|
||||
const int width = entry.m_msb - entry.m_lsb + 1;
|
||||
const int bits = static_cast<int>(sizeof(U) * 8);
|
||||
const int rhsLsb = entry.m_lsb - entry.m_rhsLsb;
|
||||
const QData rhsChunk = extractRhsChunk(entry, rhsLsb, width);
|
||||
if (width >= bits) return static_cast<T>(static_cast<U>(rhsChunk));
|
||||
return static_cast<T>(
|
||||
applyBits(static_cast<U>(result), entry, entry.m_lsb, width, rhsLsb));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static typename std::enable_if<!VlForceTypeInfo<T>::bitwise, T>::type
|
||||
applyEntry(T result, const Entry& entry) {
|
||||
static_cast<void>(result);
|
||||
return *static_cast<const VlForceBaseType<T>*>(entry.m_rhsDatap);
|
||||
}
|
||||
|
||||
public:
|
||||
VlForceVec() = default;
|
||||
|
||||
template <typename T>
|
||||
T read(T val) const {
|
||||
if VL_CONSTEXPR_CXX17 (VlForceTypeInfo<T>::unpackedArray) {
|
||||
// Handling the case of a nested flattened array using recursion
|
||||
using ElemRef
|
||||
= decltype(VlForceArrayIndexer<T>::elem(val, static_cast<std::size_t>(0)));
|
||||
using Elem = VlForceBaseType<ElemRef>;
|
||||
const int total = static_cast<int>(VlForceArrayIndexer<T>::size);
|
||||
for (const auto& entry : m_entries) {
|
||||
const Elem* const rhsBasep = static_cast<const Elem*>(entry.m_rhsDatap);
|
||||
const int startIdx = entry.m_lsb;
|
||||
const int endIdx = entry.m_msb;
|
||||
for (int idx = startIdx; idx <= endIdx; idx++) {
|
||||
const int rhsIndex = idx - entry.m_rhsLsb;
|
||||
const std::size_t uidx = static_cast<std::size_t>(idx);
|
||||
VlForceArrayIndexer<T>::elem(val, uidx) = rhsBasep[rhsIndex];
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
for (const auto& entry : m_entries) { val = applyEntry(val, entry); }
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T readIndex(T origVal, int index) const {
|
||||
if (m_entries.empty()) return origVal;
|
||||
|
||||
const auto it = std::lower_bound(m_entries.begin(), m_entries.end(), index,
|
||||
[](const Entry& e, int idx) { return e.m_msb < idx; });
|
||||
if (it != m_entries.end() && it->m_lsb <= index) {
|
||||
const int rhsIndex = index - it->m_rhsLsb;
|
||||
const T* const rhsBasep = static_cast<const T*>(it->m_rhsDatap);
|
||||
return rhsBasep[rhsIndex];
|
||||
}
|
||||
return origVal;
|
||||
}
|
||||
|
||||
void addForce(int lsb, int msb, const void* rhsDatap, int rhsLsb) {
|
||||
assert(lsb <= msb);
|
||||
assert(rhsDatap);
|
||||
assert(rhsLsb <= lsb);
|
||||
|
||||
auto it = trimEntries(lsb, msb);
|
||||
m_entries.insert(it, {lsb, msb, rhsLsb, rhsDatap});
|
||||
}
|
||||
|
||||
void release(int lsb, int msb) {
|
||||
assert(lsb <= msb);
|
||||
trimEntries(lsb, msb);
|
||||
}
|
||||
|
||||
void touch() {}
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
|
@ -809,6 +809,11 @@ public:
|
|||
EVENT_FIRE,
|
||||
EVENT_IS_FIRED,
|
||||
EVENT_IS_TRIGGERED,
|
||||
FORCE_ADD,
|
||||
FORCE_READ,
|
||||
FORCE_READ_INDEX,
|
||||
FORCE_RELEASE,
|
||||
FORCE_TOUCH,
|
||||
FORK_DONE,
|
||||
FORK_INIT,
|
||||
FORK_JOIN,
|
||||
|
|
@ -955,6 +960,11 @@ inline std::ostream& operator<<(std::ostream& os, const VCMethod& rhs) {
|
|||
{EVENT_FIRE, "fire", false}, \
|
||||
{EVENT_IS_FIRED, "isFired", true}, \
|
||||
{EVENT_IS_TRIGGERED, "isTriggered", true}, \
|
||||
{FORCE_ADD, "addForce", false}, \
|
||||
{FORCE_READ, "read", true}, \
|
||||
{FORCE_READ_INDEX, "readIndex", true}, \
|
||||
{FORCE_RELEASE, "release", false}, \
|
||||
{FORCE_TOUCH, "touch", false}, \
|
||||
{FORK_DONE, "done", false}, \
|
||||
{FORK_INIT, "init", false}, \
|
||||
{FORK_JOIN, "join", false}, \
|
||||
|
|
|
|||
|
|
@ -663,6 +663,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
if (v3Global.opt.coverage()) puts("#include \"verilated_cov.h\"\n");
|
||||
if (v3Global.usesTiming()) puts("#include \"verilated_timing.h\"\n");
|
||||
if (v3Global.useRandomizeMethods()) puts("#include \"verilated_random.h\"\n");
|
||||
if (v3Global.usesForce()) puts("#include \"verilated_force.h\"\n");
|
||||
|
||||
std::set<string> cuse_set;
|
||||
auto add_to_cuse_set = [&](string s) { cuse_set.insert(s); };
|
||||
|
|
|
|||
1509
src/V3Force.cpp
1509
src/V3Force.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -125,6 +125,7 @@ class V3Global final {
|
|||
bool m_usesProbDist = false; // Uses $dist_*
|
||||
bool m_usesStdPackage = false; // Design uses the std package
|
||||
bool m_usesTiming = false; // Design uses timing constructs
|
||||
bool m_usesForce = false; // Design uses force/release statements
|
||||
bool m_usesZeroDelay = false; // Design uses #0 delay (or non-constant delay)
|
||||
bool m_hasForceableSignals = false; // Need to apply V3Force pass
|
||||
bool m_hasSystemCSections = false; // Has AstSystemCSection that need to be emitted
|
||||
|
|
@ -205,6 +206,8 @@ public:
|
|||
void setUsesZeroDelay() { m_usesZeroDelay = true; }
|
||||
bool hasForceableSignals() const { return m_hasForceableSignals; }
|
||||
void setHasForceableSignals() { m_hasForceableSignals = true; }
|
||||
bool usesForce() const { return m_usesForce; }
|
||||
void setUsesForce() { m_usesForce = true; }
|
||||
bool hasSystemCSections() const VL_MT_SAFE { return m_hasSystemCSections; }
|
||||
void setHasSystemCSections() { m_hasSystemCSections = true; }
|
||||
V3HierGraph* hierGraphp() const { return m_hierGraphp; }
|
||||
|
|
|
|||
|
|
@ -263,6 +263,10 @@ class PremitVisitor final : public VNVisitor {
|
|||
iterateChildren(nodep);
|
||||
checkNode(nodep);
|
||||
}
|
||||
void visit(AstCMethodHard* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkNode(nodep);
|
||||
}
|
||||
void visit(AstCvtArrayToPacked* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkNode(nodep);
|
||||
|
|
|
|||
|
|
@ -403,9 +403,9 @@ module t (
|
|||
wire logic [63:0] volatile_packed_out_of_cycle /* verilator forceable */ = rand_a;
|
||||
assign VOLATILE_PACKED_OUT_OF_CYCLE = volatile_packed_out_of_cycle ^ 64'(VOLATILE_PACKED_OUT_OF_CYCLE[63:1]);
|
||||
|
||||
wire logic [2:0] volatile_packed_in_cycle /* verilator forceable */;
|
||||
// verilator lint_off UNOPTFLAT
|
||||
`signal(VOLATILE_PACKED_IN_CYCLE, 3);
|
||||
wire logic [2:0] volatile_packed_in_cycle /* verilator forceable */;
|
||||
assign volatile_packed_in_cycle = rand_a[2:0] ^ 3'(volatile_packed_in_cycle[2:1]);
|
||||
assign VOLATILE_PACKED_IN_CYCLE = volatile_packed_in_cycle;
|
||||
// verilator lint_on
|
||||
|
|
|
|||
|
|
@ -10,14 +10,29 @@
|
|||
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module t_assert;
|
||||
logic clk;
|
||||
logic zeroize;
|
||||
logic [7:0] key_mem [0:0];
|
||||
assert property (@(posedge clk) zeroize |=> (key_mem[0] == 0));
|
||||
initial force zeroize = 0;
|
||||
endmodule
|
||||
|
||||
module t (
|
||||
input clk
|
||||
);
|
||||
|
||||
t_assert t_assert_i();
|
||||
|
||||
integer cyc = 0;
|
||||
localparam logic [95:0] WIDE_INIT = 96'h12345678_9abcdef0_13579bdf;
|
||||
localparam logic [94:0] WIDE_FORCE95 = {3'b101, 32'h12345678, 32'h89abcdef, 28'h2468ace};
|
||||
|
||||
reg [3:0] in;
|
||||
tri [3:0] bus = in;
|
||||
logic [95:0] wide_src;
|
||||
wire [95:0] wide_bus = wide_src;
|
||||
logic [7:0] unpacked [0:3];
|
||||
|
||||
int never_driven;
|
||||
int never_forced;
|
||||
|
|
@ -98,6 +113,25 @@ module t (
|
|||
`checkh(bus, 4'b0101);
|
||||
end
|
||||
//
|
||||
else if (cyc == 35) begin
|
||||
force bus = 4'b1111;
|
||||
end
|
||||
else if (cyc == 36) begin
|
||||
`checkh(bus, 4'b1111);
|
||||
force bus[3:1] = 3'b000;
|
||||
end
|
||||
else if (cyc == 37) begin
|
||||
`checkh(bus, 4'b0001);
|
||||
release bus[2];
|
||||
end
|
||||
else if (cyc == 38) begin
|
||||
`checkh(bus, 4'b0101);
|
||||
release bus;
|
||||
end
|
||||
else if (cyc == 39) begin
|
||||
`checkh(bus, 4'b0101);
|
||||
end
|
||||
//
|
||||
else if (cyc == 40) begin
|
||||
r <= 1.25;
|
||||
end
|
||||
|
|
@ -117,6 +151,66 @@ module t (
|
|||
`checkr(r, 2.5);
|
||||
end
|
||||
//
|
||||
else if (cyc == 50) begin
|
||||
wide_src <= WIDE_INIT;
|
||||
end
|
||||
else if (cyc == 51) begin
|
||||
`checkh(wide_bus, WIDE_INIT);
|
||||
end
|
||||
else if (cyc == 52) begin
|
||||
force wide_bus[95:1] = WIDE_FORCE95;
|
||||
end
|
||||
else if (cyc == 53) begin
|
||||
`checkh(wide_bus, {WIDE_FORCE95, WIDE_INIT[0]});
|
||||
end
|
||||
else if (cyc == 54) begin
|
||||
release wide_bus[95:1];
|
||||
end
|
||||
else if (cyc == 55) begin
|
||||
`checkh(wide_bus, WIDE_INIT);
|
||||
end
|
||||
//
|
||||
else if (cyc == 60) begin
|
||||
unpacked[0] <= 8'h10;
|
||||
unpacked[1] <= 8'h20;
|
||||
unpacked[2] <= 8'h30;
|
||||
unpacked[3] <= 8'h40;
|
||||
end
|
||||
else if (cyc == 61) begin
|
||||
`checkh(unpacked[0], 8'h10);
|
||||
`checkh(unpacked[1], 8'h20);
|
||||
`checkh(unpacked[2], 8'h30);
|
||||
`checkh(unpacked[3], 8'h40);
|
||||
end
|
||||
else if (cyc == 62) begin
|
||||
force unpacked[1] = 8'hb1;
|
||||
force unpacked[2] = 8'hc2;
|
||||
end
|
||||
else if (cyc == 63) begin
|
||||
`checkh(unpacked[0], 8'h10);
|
||||
`checkh(unpacked[1], 8'hb1);
|
||||
`checkh(unpacked[2], 8'hc2);
|
||||
`checkh(unpacked[3], 8'h40);
|
||||
end
|
||||
else if (cyc == 64) begin
|
||||
release unpacked[1];
|
||||
release unpacked[2];
|
||||
end
|
||||
else if (cyc == 65) begin
|
||||
`checkh(unpacked[0], 8'h10);
|
||||
`checkh(unpacked[1], 8'hb1);
|
||||
`checkh(unpacked[2], 8'hc2);
|
||||
`checkh(unpacked[3], 8'h40);
|
||||
unpacked[1] <= 8'h21;
|
||||
unpacked[2] <= 8'h32;
|
||||
end
|
||||
else if (cyc == 66) begin
|
||||
`checkh(unpacked[0], 8'h10);
|
||||
`checkh(unpacked[1], 8'h21);
|
||||
`checkh(unpacked[2], 8'h32);
|
||||
`checkh(unpacked[3], 8'h40);
|
||||
end
|
||||
//
|
||||
else if (cyc == 99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
%Error: t/t_force_chained.v:30: got='h0 exp='h00000001
|
||||
%Error: t/t_force_chained.v:36: got='h0 exp='h00000002
|
||||
%Error: t/t_force_chained.v:43: got='h0 exp='h00000003
|
||||
%Error: t/t_force_chained.v:49: got='h0 exp='h00000003
|
||||
|
|
@ -13,6 +13,6 @@ test.scenarios('vlt')
|
|||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute(expect_filename=test.golden_filename)
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
// SPDX-FileCopyrightText: 2025 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop // TODO
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: off
|
||||
|
||||
module t;
|
||||
reg [1:0] a;
|
||||
|
|
@ -26,7 +26,6 @@ module t;
|
|||
#1;
|
||||
`checkh(a, 1);
|
||||
`checkh(b, 1);
|
||||
// TODO implement inter-dependency resolution between force statements
|
||||
`checkh(c, 1);
|
||||
|
||||
a = 2;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/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')
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by Antmicro.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
|
||||
`define IMPURE_ONE |($random | $random)
|
||||
|
||||
module t;
|
||||
reg [1:0] a = 2;
|
||||
bit [1:0] b = 1;
|
||||
bit [1:0] c = 0;
|
||||
|
||||
initial begin
|
||||
force a = b;
|
||||
if (`IMPURE_ONE == 1) force a = c;
|
||||
if (`IMPURE_ONE == 0) force a = b;
|
||||
c = 3;
|
||||
b = 2;
|
||||
#1;
|
||||
`checkh(a, 3);
|
||||
if (`IMPURE_ONE == 1) force a = b;
|
||||
if (`IMPURE_ONE == 0) force a = c;
|
||||
c = 2;
|
||||
b = 1;
|
||||
#1;
|
||||
`checkh(a, 1);
|
||||
#1 $finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
%Error-UNSUPPORTED: t/t_force_forceable_readwrite_unsup.v:15:14: Unsupported: Signals used via read-write reference cannot be forced
|
||||
15 | take_ref(value);
|
||||
| ^~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: Exiting due to
|
||||
|
|
@ -4,12 +4,12 @@
|
|||
# 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: 2024 Wilson Snyder
|
||||
# SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t;
|
||||
logic value /* verilator forceable */;
|
||||
|
||||
task take_ref(ref logic i);
|
||||
// verilator no_inline_task
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
take_ref(value);
|
||||
force value = 1'b1;
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/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')
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
module t (
|
||||
input clk
|
||||
);
|
||||
integer cyc = 0;
|
||||
logic src_1 = 0;
|
||||
logic [7:0] src_8 = 8'h10;
|
||||
logic dst_1 /* verilator forceable */;
|
||||
logic [7:0] dst_8 /* verilator forceable */;
|
||||
|
||||
always @* dst_1 = src_1;
|
||||
always @* dst_8 = src_8;
|
||||
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
case (cyc)
|
||||
0: begin
|
||||
force dst_1 = src_1;
|
||||
force dst_8 = src_8 ^ 8'hf0;
|
||||
`checkh(dst_1, 1'b0);
|
||||
`checkh(dst_8, 8'he0);
|
||||
end
|
||||
1: begin
|
||||
release dst_1;
|
||||
release dst_8;
|
||||
src_1 = 1'b1;
|
||||
src_8 = 8'h23;
|
||||
end
|
||||
2: begin
|
||||
`checkh(dst_1, 1'b1);
|
||||
`checkh(dst_8, 8'h23);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
default: begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -9,35 +9,35 @@
|
|||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
input clk
|
||||
);
|
||||
module t ( /*AUTOARG*/
|
||||
// Inputs
|
||||
input clk
|
||||
);
|
||||
|
||||
integer cyc = 0;
|
||||
integer cyc = 0;
|
||||
|
||||
logic [3:0] busa;
|
||||
logic [3:0] busb;
|
||||
logic [3:0] busa;
|
||||
logic [3:0] busb;
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 0) begin
|
||||
busa <= 4'b0101;
|
||||
busb <= 4'b0111;
|
||||
end
|
||||
else if (cyc == 1) begin
|
||||
force {busa, busb} = 8'b1111_1101;
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
`checkh(busa, 4'b1111);
|
||||
`checkh(busb, 4'b1101);
|
||||
end
|
||||
//
|
||||
else if (cyc == 99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
// Test loop
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 0) begin
|
||||
busa <= 4'b0101;
|
||||
busb <= 4'b0111;
|
||||
end
|
||||
else if (cyc == 1) begin
|
||||
force {busa, busb} = 8'b1111_1101;
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
`checkh(busa, 4'b1111);
|
||||
`checkh(busb, 4'b1101);
|
||||
end
|
||||
//
|
||||
else if (cyc == 99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by Antmicro.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
typedef struct {
|
||||
logic [31:0] val;
|
||||
logic [31:0] other;
|
||||
} St1;
|
||||
|
||||
typedef struct {
|
||||
St1 inner;
|
||||
logic [31:0] tail;
|
||||
} St2;
|
||||
|
||||
module m;
|
||||
St2 st2;
|
||||
St2 forced;
|
||||
St2 snapshot;
|
||||
initial begin
|
||||
st2.inner.val = 32'h11;
|
||||
st2.inner.other = 32'h12;
|
||||
st2.tail = 32'h13;
|
||||
forced.inner.val = 32'h21;
|
||||
forced.inner.other = 32'h22;
|
||||
forced.tail = 32'h23;
|
||||
force st2 = forced;
|
||||
snapshot = st2;
|
||||
`checkh(snapshot.inner.val, 32'h21);
|
||||
`checkh(snapshot.inner.val[0], 1'b1);
|
||||
force st2.inner.val = 32'h30;
|
||||
release st2.inner.val;
|
||||
snapshot = st2;
|
||||
`checkh(snapshot.inner.val, 32'h21);
|
||||
`checkh(snapshot.inner.val[0], 1'b1);
|
||||
`checkh(snapshot.inner.other, 32'h22);
|
||||
`checkh(snapshot.tail, 32'h23);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2026 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026 by Antmicro.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:0] value;
|
||||
} Entry;
|
||||
|
||||
typedef struct packed {
|
||||
Entry [1:0][1:0] entries;
|
||||
} DataBlock;
|
||||
|
||||
module sub;
|
||||
DataBlock data_block;
|
||||
endmodule
|
||||
|
||||
module t;
|
||||
sub sub1 ();
|
||||
logic [31:0] forced_value;
|
||||
initial begin
|
||||
forced_value = 32'h00000001;
|
||||
force sub1.data_block.entries[0][0].value = forced_value[31:0];
|
||||
`checkh(sub1.data_block.entries[0][0].value[0], 1'b1);
|
||||
`checkh(sub1.data_block.entries[0][0].value, 32'h00000001);
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -9,69 +9,75 @@
|
|||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
// verilog_format: on
|
||||
|
||||
module sub(
|
||||
input wire [7:0] i,
|
||||
output wire [7:0] o
|
||||
module sub (
|
||||
input wire [7:0] i,
|
||||
output wire [7:0] o
|
||||
);
|
||||
// Must inline this module
|
||||
// verilator inline_module
|
||||
// Must inline this module
|
||||
// verilator inline_module
|
||||
|
||||
wire [7:0] m;
|
||||
assign m = i;
|
||||
assign o = m;
|
||||
wire [7:0] m;
|
||||
assign m = i;
|
||||
assign o = m;
|
||||
endmodule
|
||||
|
||||
module top;
|
||||
// Variable input
|
||||
reg [7:0] i = 8'h01;
|
||||
reg [7:0] o_v;
|
||||
sub sub_v(i, o_v);
|
||||
// Variable input
|
||||
reg [7:0] i = 8'h01;
|
||||
reg [7:0] o_v;
|
||||
sub sub_v (
|
||||
i,
|
||||
o_v
|
||||
);
|
||||
|
||||
// Constant input
|
||||
reg [7:0] o_c;
|
||||
sub sub_c(8'h10, o_c);
|
||||
// Constant input
|
||||
reg [7:0] o_c;
|
||||
sub sub_c (
|
||||
8'h10,
|
||||
o_c
|
||||
);
|
||||
|
||||
logic clk = 1'b0;
|
||||
always #1 clk = ~clk;
|
||||
int cyc = 0;
|
||||
logic clk = 1'b0;
|
||||
always #1 clk = ~clk;
|
||||
int cyc = 0;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 1) begin
|
||||
`checkh(i, 8'h01);
|
||||
`checkh(sub_v.i, 8'h01);
|
||||
`checkh(sub_v.m, 8'h01);
|
||||
`checkh(sub_v.o, 8'h01);
|
||||
`checkh(o_v, 8'h01);
|
||||
`checkh(sub_c.i, 8'h10);
|
||||
`checkh(sub_c.m, 8'h10);
|
||||
`checkh(sub_c.o, 8'h10);
|
||||
`checkh(o_c, 8'h10);
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
force sub_v.i = 8'h02;
|
||||
force sub_v.m = 8'h03;
|
||||
force sub_v.o = 8'h04;
|
||||
force sub_c.i = 8'h20;
|
||||
force sub_c.m = 8'h30;
|
||||
force sub_c.o = 8'h40;
|
||||
end
|
||||
else if (cyc == 3) begin
|
||||
`checkh(i, 8'h01);
|
||||
`checkh(sub_v.i, 8'h02);
|
||||
`checkh(sub_v.m, 8'h03);
|
||||
`checkh(sub_v.o, 8'h04);
|
||||
`checkh(o_v, 8'h04);
|
||||
`checkh(sub_c.i, 8'h20);
|
||||
`checkh(sub_c.m, 8'h30);
|
||||
`checkh(sub_c.o, 8'h40);
|
||||
`checkh(o_c, 8'h40);
|
||||
end
|
||||
//
|
||||
else if (cyc == 99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 1) begin
|
||||
`checkh(i, 8'h01);
|
||||
`checkh(sub_v.i, 8'h01);
|
||||
`checkh(sub_v.m, 8'h01);
|
||||
`checkh(sub_v.o, 8'h01);
|
||||
`checkh(o_v, 8'h01);
|
||||
`checkh(sub_c.i, 8'h10);
|
||||
`checkh(sub_c.m, 8'h10);
|
||||
`checkh(sub_c.o, 8'h10);
|
||||
`checkh(o_c, 8'h10);
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
force sub_v.i = 8'h02;
|
||||
force sub_v.m = 8'h03;
|
||||
force sub_v.o = 8'h04;
|
||||
force sub_c.i = 8'h20;
|
||||
force sub_c.m = 8'h30;
|
||||
force sub_c.o = 8'h40;
|
||||
end
|
||||
else if (cyc == 3) begin
|
||||
`checkh(i, 8'h01);
|
||||
`checkh(sub_v.i, 8'h02);
|
||||
`checkh(sub_v.m, 8'h03);
|
||||
`checkh(sub_v.o, 8'h04);
|
||||
`checkh(o_v, 8'h04);
|
||||
`checkh(sub_c.i, 8'h20);
|
||||
`checkh(sub_c.m, 8'h30);
|
||||
`checkh(sub_c.o, 8'h40);
|
||||
`checkh(o_c, 8'h40);
|
||||
end
|
||||
//
|
||||
else if (cyc == 99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -2,7 +2,4 @@
|
|||
19 | cls.take_ref(a);
|
||||
| ^
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_force_readwrite_unsup.v:20:18: Unsupported: Signals used via read-write reference cannot be forced
|
||||
20 | cls.take_ref(b);
|
||||
| ^
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
%Error-UNSUPPORTED: t/t_force_unpacked_unsup.v:26:7: Unsupported: Force of variable with >= 1000 unpacked elements
|
||||
26 | bit big_array[40][40][40];
|
||||
| ^~~~~~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_force_unpacked_unsup.v:25:12: Unsupported: Force of variable with >= 1000 unpacked elements
|
||||
25 | struct_t s_array[3000];
|
||||
| ^~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_force_unpacked_unsup.v:27:11: Forcing variable of unsupported type: REFDTYPE 'union_t'
|
||||
27 | union_t my_union;
|
||||
| ^~~~~~~~
|
||||
%Error: Internal Error: t/t_force_unpacked_unsup.v:27:11: ../V3Force.cpp:#: Unsupported: Force of variable of unhandled data type
|
||||
27 | union_t my_union;
|
||||
| ^~~~~~~~
|
||||
... This fatal error may be caused by the earlier error(s); resolve those first.
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
|
||||
`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module t (
|
||||
input clk
|
||||
);
|
||||
|
||||
integer cyc = 0;
|
||||
|
||||
typedef struct {int x;} struct_t;
|
||||
typedef union {
|
||||
int x;
|
||||
logic y;
|
||||
} union_t;
|
||||
|
||||
struct_t s_array[3000];
|
||||
bit big_array[40][40][40];
|
||||
union_t my_union;
|
||||
|
||||
// Test loop
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 0) begin
|
||||
big_array[1][2][3] <= 1;
|
||||
s_array[1].x <= 1;
|
||||
my_union.x <= 1;
|
||||
end
|
||||
else if (cyc == 1) begin
|
||||
`checkr(big_array[1][2][3], 1);
|
||||
`checkh(s_array[1].x, 1);
|
||||
`checkh(my_union.x, 1);
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
force big_array[1][2][3] = 0;
|
||||
force s_array[1].x = 0;
|
||||
force my_union.x = 0;
|
||||
end
|
||||
else if (cyc == 3) begin
|
||||
`checkr(big_array[1][2][3], 0);
|
||||
big_array[1][2][3] <= 1;
|
||||
`checkh(s_array[1].x, 0);
|
||||
s_array[1].x <= 1;
|
||||
`checkh(my_union.x, 0);
|
||||
my_union.x <= 1;
|
||||
end
|
||||
else if (cyc == 4) begin
|
||||
`checkr(big_array[1][2][3], 0);
|
||||
`checkh(s_array[1].x, 0);
|
||||
`checkh(my_union.x, 0);
|
||||
end
|
||||
else if (cyc == 5) begin
|
||||
release big_array[1][2][3];
|
||||
release s_array[1].x;
|
||||
release my_union.x;
|
||||
end
|
||||
else if (cyc == 6) begin
|
||||
`checkr(big_array[1][2][3], 0);
|
||||
big_array[1][2][3] <= 1;
|
||||
`checkh(s_array[1].x, 0);
|
||||
s_array[1].x <= 1;
|
||||
`checkh(my_union.x, 0);
|
||||
my_union.x <= 1;
|
||||
end
|
||||
else if (cyc == 7) begin
|
||||
`checkr(big_array[1][2][3], 1);
|
||||
`checkh(s_array[1].x, 1);
|
||||
`checkh(my_union.x, 1);
|
||||
end
|
||||
else if (cyc == 8) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -14,7 +14,6 @@ test.scenarios('vlt')
|
|||
test.compile()
|
||||
|
||||
files = test.glob_some(test.obj_dir + "/" + test.vm_prefix + "*.h")
|
||||
test.file_grep_any(files, r' u_sub__DOT__a__VforceRd')
|
||||
test.file_grep_any(files, r' u_sub__DOT__a__VforceEn')
|
||||
test.file_grep_any(files, r' u_sub__DOT__a__VforceVal')
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ module t (
|
|||
endmodule
|
||||
|
||||
module sub (
|
||||
input a /* verilator forceable */ /* verilator public_flat */,
|
||||
input a /* verilator forceable */ /* verilator public_flat */,
|
||||
input b,
|
||||
output c
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,8 +2,4 @@
|
|||
8 | string str /*verilator forceable*/;
|
||||
| ^~~
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error-UNSUPPORTED: t/t_forceable_string_bad.v:8:10: Forcing variable of unsupported type: BASICDTYPE 'string'
|
||||
8 | string str /*verilator forceable*/;
|
||||
| ^~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module t (
|
|||
int cyc;
|
||||
integer rand_result;
|
||||
integer seed = 123;
|
||||
|
||||
integer frc;
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc != 0) begin
|
||||
|
|
@ -27,6 +27,7 @@ module t (
|
|||
c = new;
|
||||
rand_result = c.randomize();
|
||||
$display("rand: %x x: %x ", rand_result, c.x); // Get verilated_random.cpp
|
||||
force frc=42; // Get verilated_force.h
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue