Four-state logic squash

Signed-off-by: Igor Zaworski <izaworski@antmicro.com>
This commit is contained in:
Igor Zaworski 2026-04-22 10:19:37 +02:00
parent 276f2f344d
commit e5dcf11cb8
152 changed files with 6224 additions and 173 deletions

View File

@ -443,6 +443,24 @@ List Of Warnings
in decreased performance.
.. option:: CASTFOURSTATE
Warns about not supported four-state logic feature.
When two-state logic variant of a feature is fully supported,
an implicit cast to two-state type is made
.. code-block:: sv
:linenos:
:emphasize-lines: 5
module t;
integer fd;
initial begin
$fflush(fd); // <- implicit conversion to two-state value
end
endmodule
.. option:: CDCRSTLOGIC
Historical, never issued since version 5.008.
@ -1346,7 +1364,6 @@ List Of Warnings
:option:`ASCRANGE`. While :option:`LITENDIAN` remains for
backwards compatibility, new projects should use :option:`ASCRANGE`.
.. option:: MINTYPMAXDLY
.. code-block:: sv

View File

@ -383,6 +383,14 @@ void VerilatedFstBuffer::emitBit(uint32_t code, CData newval) {
m_fst->emitValueChange(m_symbolp[code], uint64_t(newval));
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitLogic(uint32_t code, CData newval, CData newvalXZ) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
m_owner.emitTimeChangeMaybe();
const uint32_t newvals[2] = {static_cast<uint32_t>(newval), static_cast<uint32_t>(newvalXZ)};
m_fst->emitValueChange(m_symbolp[code], newvals, fst::EncodingType::VERILOG);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitCData(uint32_t code, CData newval, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
@ -390,6 +398,14 @@ void VerilatedFstBuffer::emitCData(uint32_t code, CData newval, int) {
m_fst->emitValueChange(m_symbolp[code], newval);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitFourstateCData(uint32_t code, CData newval, CData newvalXZ, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
m_owner.emitTimeChangeMaybe();
const uint32_t newvals[2] = {static_cast<uint32_t>(newval), static_cast<uint32_t>(newvalXZ)};
m_fst->emitValueChange(m_symbolp[code], newvals, fst::EncodingType::VERILOG);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitSData(uint32_t code, SData newval, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
@ -397,6 +413,14 @@ void VerilatedFstBuffer::emitSData(uint32_t code, SData newval, int) {
m_fst->emitValueChange(m_symbolp[code], newval);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitFourstateSData(uint32_t code, SData newval, SData newvalXZ, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
m_owner.emitTimeChangeMaybe();
const uint32_t newvals[2] = {static_cast<uint32_t>(newval), static_cast<uint32_t>(newvalXZ)};
m_fst->emitValueChange(m_symbolp[code], newvals, fst::EncodingType::VERILOG);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitIData(uint32_t code, IData newval, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
@ -404,6 +428,14 @@ void VerilatedFstBuffer::emitIData(uint32_t code, IData newval, int) {
m_fst->emitValueChange(m_symbolp[code], newval);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitFourstateIData(uint32_t code, IData newval, IData newvalXZ, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
m_owner.emitTimeChangeMaybe();
const uint32_t newvals[2] = {newval, newvalXZ};
m_fst->emitValueChange(m_symbolp[code], newvals, fst::EncodingType::VERILOG);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitQData(uint32_t code, QData newval, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
@ -412,12 +444,38 @@ void VerilatedFstBuffer::emitQData(uint32_t code, QData newval, int) {
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitWData(uint32_t code, WDataInP newval, int) {
void VerilatedFstBuffer::emitFourstateQData(uint32_t code, QData newval, QData newvalXZ, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
m_owner.emitTimeChangeMaybe();
const uint64_t newvals[2] = {newval, newvalXZ};
m_fst->emitValueChange(m_symbolp[code], newvals, fst::EncodingType::VERILOG);
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitWData(uint32_t code, const WDataInP newval, int) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
m_owner.emitTimeChangeMaybe();
m_fst->emitValueChange(m_symbolp[code], newval.datap());
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitFourstateWData(uint32_t code, const WDataInP newval,
const WDataInP newvalXZ, int bits) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
// TODO: When four-states will be shuffled remove it since copying will be no longer necessary
std::vector<uint32_t> newvals;
const size_t wordCount = static_cast<size_t>(VL_WORDS_I(bits));
newvals.resize(wordCount);
for (size_t i = 0; i < wordCount; ++i) {
newvals.push_back(newval[i]);
newvals.push_back(newvalXZ[i]);
}
m_owner.emitTimeChangeMaybe();
// call emitValueChange(handle, uint32_t*)
m_fst->emitValueChange(m_symbolp[code], newvals.data());
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitDouble(uint32_t code, double newval) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE

View File

@ -228,11 +228,18 @@ class VerilatedFstBuffer VL_NOT_FINAL {
// called from only one place (the full* methods), so always inline them.
VL_ATTR_ALWINLINE void emitEvent(uint32_t code);
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
VL_ATTR_ALWINLINE void emitLogic(uint32_t code, CData newval, CData newvalXZ);
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int);
VL_ATTR_ALWINLINE void emitFourstateCData(uint32_t code, CData newval, CData newvalXZ, int);
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int);
VL_ATTR_ALWINLINE void emitFourstateSData(uint32_t code, SData newval, SData newvalXZ, int);
VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int);
VL_ATTR_ALWINLINE void emitFourstateIData(uint32_t code, IData newval, IData newvalXZ, int);
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int);
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ, int);
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int);
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, WDataInP newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
};

View File

@ -65,20 +65,23 @@
class VerilatedSaifActivityBit final {
// MEMBERS
bool m_lastVal = false; // Last emitted activity bit value
bool m_lastValXZ = false; // Last emitted activity bit value
uint64_t m_highTime = 0; // Total time when bit was high
size_t m_transitions = 0; // Total number of bit transitions
public:
// METHODS
VL_ATTR_ALWINLINE
void aggregateVal(uint64_t dt, bool newVal) {
m_transitions += newVal != m_lastVal ? 1 : 0;
void aggregateVal(uint64_t dt, bool newVal, bool newValXZ = false) {
m_transitions += (newVal != m_lastVal || m_lastValXZ != newValXZ) ? 1 : 0;
m_highTime += m_lastVal ? dt : 0;
m_lastVal = newVal;
m_lastValXZ = newValXZ;
}
// ACCESSORS
VL_ATTR_ALWINLINE bool bitValue() const { return m_lastVal; }
VL_ATTR_ALWINLINE bool bitValueXZ() const { return m_lastValXZ; }
VL_ATTR_ALWINLINE uint64_t highTime() const { return m_highTime; }
VL_ATTR_ALWINLINE uint64_t toggleCount() const { return m_transitions; }
};
@ -104,6 +107,7 @@ public:
// METHODS
VL_ATTR_ALWINLINE void emitBit(uint64_t time, CData newval);
VL_ATTR_ALWINLINE void emitLogic(uint64_t time, CData newval, CData newvalXZ);
template <typename DataType>
VL_ATTR_ALWINLINE void emitData(uint64_t time, DataType newval, uint32_t bits) {
@ -117,7 +121,24 @@ public:
updateLastTime(time);
}
template <typename DataType>
VL_ATTR_ALWINLINE void emitFourstateData(uint64_t time, DataType newval, DataType newvalXZ,
uint32_t bits) {
static_assert(std::is_integral<DataType>::value,
"The emitted value must be of integral type");
const uint64_t dt = time - m_lastTime;
for (size_t i = 0; i < std::min(m_width, bits); ++i) {
m_bits[i].aggregateVal(dt, newval & 1, newvalXZ & 1);
newval >>= 1;
newvalXZ >>= 1;
}
updateLastTime(time);
}
VL_ATTR_ALWINLINE void emitWData(uint64_t time, WDataInP newval, uint32_t bits);
VL_ATTR_ALWINLINE void emitFourstateWData(uint64_t time, WDataInP newval, WDataInP newvalXZ,
uint32_t bits);
VL_ATTR_ALWINLINE void updateLastTime(uint64_t val) { m_lastTime = val; }
// ACCESSORS
@ -229,7 +250,15 @@ void VerilatedSaifActivityVar::emitBit(const uint64_t time, const CData newval)
}
VL_ATTR_ALWINLINE
void VerilatedSaifActivityVar::emitWData(const uint64_t time, WDataInP newval,
void VerilatedSaifActivityVar::emitLogic(const uint64_t time, const CData newval,
const CData newvalXZ) {
assert(m_lastTime <= time);
m_bits[0].aggregateVal(time - m_lastTime, newval, newvalXZ);
updateLastTime(time);
}
VL_ATTR_ALWINLINE
void VerilatedSaifActivityVar::emitWData(const uint64_t time, const WDataInP newval,
const uint32_t bits) {
assert(m_lastTime <= time);
const uint64_t dt = time - m_lastTime;
@ -241,6 +270,20 @@ void VerilatedSaifActivityVar::emitWData(const uint64_t time, WDataInP newval,
updateLastTime(time);
}
VL_ATTR_ALWINLINE
void VerilatedSaifActivityVar::emitFourstateWData(const uint64_t time, const WDataInP newval,
const WDataInP newvalXZ, const uint32_t bits) {
assert(m_lastTime <= time);
const uint64_t dt = time - m_lastTime;
for (std::size_t i = 0; i < std::min(m_width, bits); ++i) {
const size_t wordIndex = i / VL_EDATASIZE;
m_bits[i].aggregateVal(dt, (newval[wordIndex] >> VL_BITBIT_E(i)) & 1,
(newvalXZ[wordIndex] >> VL_BITBIT_E(i)) & 1);
}
updateLastTime(time);
}
VerilatedSaifActivityBit& VerilatedSaifActivityVar::bit(const std::size_t index) {
assert(index < m_width);
return m_bits[index];
@ -633,6 +676,15 @@ void VerilatedSaifBuffer::emitBit(const uint32_t code, const CData newval) {
activity.emitBit(m_owner.currentTime(), newval);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitLogic(uint32_t code, CData newval, CData newvalXZ) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
&& "Activity must be declared earlier");
VerilatedSaifActivityVar& activity
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
activity.emitLogic(m_owner.currentTime(), newval, newvalXZ);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitCData(const uint32_t code, const CData newval, const int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
@ -642,6 +694,16 @@ void VerilatedSaifBuffer::emitCData(const uint32_t code, const CData newval, con
activity.emitData<CData>(m_owner.currentTime(), newval, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitFourstateCData(uint32_t code, CData newval, CData newvalXZ,
int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
&& "Activity must be declared earlier");
VerilatedSaifActivityVar& activity
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
activity.emitFourstateData<CData>(m_owner.currentTime(), newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitSData(const uint32_t code, const SData newval, const int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
@ -651,6 +713,16 @@ void VerilatedSaifBuffer::emitSData(const uint32_t code, const SData newval, con
activity.emitData<SData>(m_owner.currentTime(), newval, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitFourstateSData(uint32_t code, SData newval, SData newvalXZ,
int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
&& "Activity must be declared earlier");
VerilatedSaifActivityVar& activity
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
activity.emitFourstateData<SData>(m_owner.currentTime(), newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitIData(const uint32_t code, const IData newval, const int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
@ -660,6 +732,16 @@ void VerilatedSaifBuffer::emitIData(const uint32_t code, const IData newval, con
activity.emitData<IData>(m_owner.currentTime(), newval, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitFourstateIData(uint32_t code, IData newval, IData newvalXZ,
int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
&& "Activity must be declared earlier");
VerilatedSaifActivityVar& activity
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
activity.emitFourstateData<IData>(m_owner.currentTime(), newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitQData(const uint32_t code, const QData newval, const int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
@ -670,7 +752,17 @@ void VerilatedSaifBuffer::emitQData(const uint32_t code, const QData newval, con
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitWData(const uint32_t code, WDataInP newval, const int bits) {
void VerilatedSaifBuffer::emitFourstateQData(uint32_t code, QData newval, QData newvalXZ,
int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
&& "Activity must be declared earlier");
VerilatedSaifActivityVar& activity
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
activity.emitFourstateData<QData>(m_owner.currentTime(), newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitWData(const uint32_t code, const WDataInP newval, const int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
&& "Activity must be declared earlier");
VerilatedSaifActivityVar& activity
@ -678,6 +770,16 @@ void VerilatedSaifBuffer::emitWData(const uint32_t code, WDataInP newval, const
activity.emitWData(m_owner.currentTime(), newval, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitFourstateWData(const uint32_t code, const WDataInP newval,
const WDataInP newvalXZ, const int bits) {
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
&& "Activity must be declared earlier");
VerilatedSaifActivityVar& activity
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
activity.emitFourstateWData(m_owner.currentTime(), newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitDouble(const uint32_t code, const double newval) {
// NOP

View File

@ -243,11 +243,22 @@ class VerilatedSaifBuffer VL_NOT_FINAL {
// called from only one place (the full* methods), so always inline them.
VL_ATTR_ALWINLINE void emitEvent(uint32_t code);
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
VL_ATTR_ALWINLINE void emitLogic(uint32_t code, CData newval, CData newvalXZ);
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateCData(uint32_t code, CData newval, CData newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateSData(uint32_t code, SData newval, SData newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateIData(uint32_t code, IData newval, IData newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, WDataInP newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
};

View File

@ -385,11 +385,17 @@ public:
// Write to previous value buffer value and emit trace entry.
void fullBit(uint32_t* oldp, CData newval);
void fullLogic(uint32_t* oldp, CData newval, CData newvalXZ);
void fullCData(uint32_t* oldp, CData newval, int bits);
void fullFourstateCData(uint32_t* oldp, CData newval, CData newvalXZ, int bits);
void fullSData(uint32_t* oldp, SData newval, int bits);
void fullFourstateSData(uint32_t* oldp, SData newval, SData newvalXZ, int bits);
void fullIData(uint32_t* oldp, IData newval, int bits);
void fullFourstateIData(uint32_t* oldp, IData newval, IData newvalXZ, int bits);
void fullQData(uint32_t* oldp, QData newval, int bits);
void fullFourstateQData(uint32_t* oldp, QData newval, QData newvalXZ, int bits);
void fullWData(uint32_t* oldp, WDataInP newval, int bits);
void fullFourstateWData(uint32_t* oldp, WDataInP newval, WDataInP newvalXZ, int bits);
void fullDouble(uint32_t* oldp, double newval);
void fullEvent(uint32_t* oldp, const VlEventBase* newvalp);
void fullEventTriggered(uint32_t* oldp);
@ -399,32 +405,71 @@ public:
const uint32_t diff = *oldp ^ newval;
if (VL_UNLIKELY(diff)) fullBit(oldp, newval);
}
VL_ATTR_ALWINLINE void chgLogic(uint32_t* oldp, CData newval, CData newvalXZ) {
CData* oldcp = reinterpret_cast<CData*>(oldp);
const uint32_t diff = (oldcp[0] ^ newval) | (oldcp[1] ^ newvalXZ);
if (VL_UNLIKELY(diff)) fullLogic(oldp, newval, newvalXZ);
}
VL_ATTR_ALWINLINE void chgCData(uint32_t* oldp, CData newval, int bits) {
const uint32_t diff = *oldp ^ newval;
if (VL_UNLIKELY(diff)) fullCData(oldp, newval, bits);
}
VL_ATTR_ALWINLINE void chgFourstateCData(uint32_t* oldp, CData newval, CData newvalXZ,
int bits) {
CData* oldcp = reinterpret_cast<CData*>(oldp);
const uint32_t diff = (oldcp[0] ^ newval) | (oldcp[1] ^ newvalXZ);
if (VL_UNLIKELY(diff)) fullFourstateCData(oldp, newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE void chgSData(uint32_t* oldp, SData newval, int bits) {
const uint32_t diff = *oldp ^ newval;
if (VL_UNLIKELY(diff)) fullSData(oldp, newval, bits);
}
VL_ATTR_ALWINLINE void chgFourstateSData(uint32_t* oldp, SData newval, SData newvalXZ,
int bits) {
SData* oldcp = reinterpret_cast<SData*>(oldp);
const uint32_t diff = (oldcp[0] ^ newval) | (oldcp[1] ^ newvalXZ);
if (VL_UNLIKELY(diff)) fullFourstateSData(oldp, newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE void chgIData(uint32_t* oldp, IData newval, int bits) {
const uint32_t diff = *oldp ^ newval;
if (VL_UNLIKELY(diff)) fullIData(oldp, newval, bits);
}
VL_ATTR_ALWINLINE void chgFourstateIData(uint32_t* oldp, IData newval, IData newvalXZ,
int bits) {
IData* oldcp = reinterpret_cast<IData*>(oldp);
const uint32_t diff = (oldcp[0] ^ newval) | (oldcp[1] ^ newvalXZ);
if (VL_UNLIKELY(diff)) fullFourstateIData(oldp, newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE void chgQData(uint32_t* oldp, QData newval, int bits) {
QData old;
std::memcpy(&old, oldp, sizeof(old));
const uint64_t diff = old ^ newval;
if (VL_UNLIKELY(diff)) fullQData(oldp, newval, bits);
}
VL_ATTR_ALWINLINE void chgWData(uint32_t* oldp, WDataInP newval, int bits) {
for (int i = 0; i < (bits + 31) / 32; ++i) {
VL_ATTR_ALWINLINE void chgFourstateQData(uint32_t* oldp, QData newval, QData newvalXZ,
int bits) {
QData* oldcp = reinterpret_cast<QData*>(oldp);
const uint32_t diff = (oldcp[0] ^ newval) | (oldcp[1] ^ newvalXZ);
if (VL_UNLIKELY(diff)) fullFourstateQData(oldp, newval, newvalXZ, bits);
}
VL_ATTR_ALWINLINE void chgWData(uint32_t* oldp, const WDataInP newval, int bits) {
for (int i = 0; i < VL_WORDS_I(bits); ++i) {
if (VL_UNLIKELY(oldp[i] ^ newval[i])) {
fullWData(oldp, newval, bits);
return;
}
}
}
VL_ATTR_ALWINLINE void chgFourstateWData(uint32_t* oldp, const WDataInP newval,
const WDataInP newvalXZ, int bits) {
for (int i = 0; i < VL_WORDS_I(bits); ++i) {
const int oldIdx = i << 1;
if (VL_UNLIKELY((oldp[oldIdx] ^ newval[i]) | (oldp[oldIdx | 1] ^ newvalXZ[i]))) {
fullFourstateWData(oldp, newval, newvalXZ, bits);
return;
}
}
}
VL_ATTR_ALWINLINE void chgEvent(uint32_t* oldp, const VlEventBase* newvalp) {
if (newvalp->isTriggered()) fullEvent(oldp, newvalp);
}

View File

@ -555,6 +555,16 @@ void VerilatedTraceBuffer<VL_BUF_T>::fullBit(uint32_t* oldp, CData newval) {
emitBit(code, newval);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullLogic(uint32_t* oldp, CData newval, CData newvalXZ) {
const uint32_t code = oldp - m_sigs_oldvalp;
CData* oldcp = reinterpret_cast<CData*>(oldp);
oldcp[0] = newval; // Still copy even if not tracing so chg doesn't call full
oldcp[1] = newvalXZ;
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
emitLogic(code, newval, newvalXZ);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullEvent(uint32_t* oldp, const VlEventBase* newvalp) {
const uint32_t code = oldp - m_sigs_oldvalp;
@ -577,6 +587,17 @@ void VerilatedTraceBuffer<VL_BUF_T>::fullCData(uint32_t* oldp, CData newval, int
emitCData(code, newval, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullFourstateCData(uint32_t* oldp, CData newval,
CData newvalXZ, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
CData* oldcp = reinterpret_cast<CData*>(oldp);
oldcp[0] = newval; // Still copy even if not tracing so chg doesn't call full
oldcp[1] = newvalXZ;
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
emitFourstateCData(code, newval, newvalXZ, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullSData(uint32_t* oldp, SData newval, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
@ -585,6 +606,17 @@ void VerilatedTraceBuffer<VL_BUF_T>::fullSData(uint32_t* oldp, SData newval, int
emitSData(code, newval, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullFourstateSData(uint32_t* oldp, SData newval,
SData newvalXZ, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
SData* oldcp = reinterpret_cast<SData*>(oldp);
oldcp[0] = newval; // Still copy even if not tracing so chg doesn't call full
oldcp[1] = newvalXZ;
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
emitFourstateSData(code, newval, newvalXZ, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullIData(uint32_t* oldp, IData newval, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
@ -593,6 +625,17 @@ void VerilatedTraceBuffer<VL_BUF_T>::fullIData(uint32_t* oldp, IData newval, int
emitIData(code, newval, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullFourstateIData(uint32_t* oldp, IData newval,
IData newvalXZ, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
IData* oldcp = reinterpret_cast<IData*>(oldp);
oldcp[0] = newval; // Still copy even if not tracing so chg doesn't call full
oldcp[1] = newvalXZ;
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
emitFourstateIData(code, newval, newvalXZ, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullQData(uint32_t* oldp, QData newval, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
@ -602,13 +645,37 @@ void VerilatedTraceBuffer<VL_BUF_T>::fullQData(uint32_t* oldp, QData newval, int
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullWData(uint32_t* oldp, WDataInP newval, int bits) {
void VerilatedTraceBuffer<VL_BUF_T>::fullFourstateQData(uint32_t* oldp, QData newval,
QData newvalXZ, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
QData* oldcp = reinterpret_cast<QData*>(oldp);
oldcp[0] = newval; // Still copy even if not tracing so chg doesn't call full
oldcp[1] = newvalXZ;
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
emitFourstateQData(code, newval, newvalXZ, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullWData(uint32_t* oldp, const WDataInP newval, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
for (int i = 0; i < VL_WORDS_I(bits); ++i) oldp[i] = newval[i];
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
emitWData(code, newval, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullFourstateWData(uint32_t* oldp, const WDataInP newval,
const WDataInP newvalXZp, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;
for (int i = 0; i < VL_WORDS_I(bits); ++i) {
const int oldIdx = i << 1;
oldp[oldIdx] = newval[i];
oldp[oldIdx | 1] = newvalXZp[i];
}
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
emitFourstateWData(code, newval, newvalXZp, bits);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullDouble(uint32_t* oldp, double newval) {
const uint32_t code = oldp - m_sigs_oldvalp;

View File

@ -635,6 +635,18 @@ void VerilatedVcdBuffer::emitBit(uint32_t code, CData newval) {
finishLine(code, wp);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitLogic(uint32_t code, CData newval, CData newvalXZ) {
// Don't prefetch suffix as it's a bit too late;
char* wp = m_writep;
if (newval) {
*wp++ = newvalXZ ? 'x' : '1';
} else {
*wp++ = newvalXZ ? 'z' : '0';
}
finishLine(code, wp);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitCData(uint32_t code, CData newval, int bits) {
char* wp = m_writep;
@ -643,6 +655,19 @@ void VerilatedVcdBuffer::emitCData(uint32_t code, CData newval, int bits) {
finishLine(code, wp + bits);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitFourstateCData(uint32_t code, CData newval, CData newvalXZ,
int bits) {
char* wp = m_writep;
*wp++ = 'b';
for (int i = bits - 1; i >= 0; --i) {
const CData mask = 1 << i;
*wp++ = (newvalXZ & mask) ? (newval & mask ? 'x' : 'z')
: ('0' | (static_cast<char>(newval >> i) & 1));
}
finishLine(code, wp);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitSData(uint32_t code, SData newval, int bits) {
char* wp = m_writep;
@ -651,6 +676,19 @@ void VerilatedVcdBuffer::emitSData(uint32_t code, SData newval, int bits) {
finishLine(code, wp + bits);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitFourstateSData(uint32_t code, SData newval, SData newvalXZ,
int bits) {
char* wp = m_writep;
*wp++ = 'b';
for (int i = bits - 1; i >= 0; --i) {
const SData mask = 1 << i;
*wp++ = (newvalXZ & mask) ? (newval & mask ? 'x' : 'z')
: ('0' | (static_cast<char>(newval >> i) & 1));
}
finishLine(code, wp);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitIData(uint32_t code, IData newval, int bits) {
char* wp = m_writep;
@ -659,6 +697,19 @@ void VerilatedVcdBuffer::emitIData(uint32_t code, IData newval, int bits) {
finishLine(code, wp + bits);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitFourstateIData(uint32_t code, IData newval, IData newvalXZ,
int bits) {
char* wp = m_writep;
*wp++ = 'b';
for (int i = bits - 1; i >= 0; --i) {
const IData mask = 1 << i;
*wp++ = (newvalXZ & mask) ? (newval & mask ? 'x' : 'z')
: ('0' | (static_cast<char>(newval >> i) & 1));
}
finishLine(code, wp);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitQData(uint32_t code, QData newval, int bits) {
char* wp = m_writep;
@ -668,7 +719,20 @@ void VerilatedVcdBuffer::emitQData(uint32_t code, QData newval, int bits) {
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitWData(uint32_t code, WDataInP newval, int bits) {
void VerilatedVcdBuffer::emitFourstateQData(uint32_t code, QData newval, QData newvalXZ,
int bits) {
char* wp = m_writep;
*wp++ = 'b';
for (int i = bits - 1; i >= 0; --i) {
const QData mask = 1 << i;
*wp++ = (newvalXZ & mask) ? (newval & mask ? 'x' : 'z')
: ('0' | (static_cast<char>(newval >> i) & 1));
}
finishLine(code, wp);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitWData(uint32_t code, const WDataInP newval, int bits) {
int words = VL_WORDS_I(bits);
char* wp = m_writep;
*wp++ = 'b';
@ -684,6 +748,33 @@ void VerilatedVcdBuffer::emitWData(uint32_t code, WDataInP newval, int bits) {
finishLine(code, wp);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitFourstateWData(uint32_t code, const WDataInP newval,
const WDataInP newvalXZ, int bits) {
char* wp = m_writep;
*wp++ = 'b';
const int lastIdx = (bits - 1) / VL_EDATASIZE;
{
const EData value = newval[lastIdx];
const EData xz = newvalXZ[lastIdx];
for (int i = (bits - 1) % VL_EDATASIZE; i >= 0; --i) {
const EData mask = 1 << i;
*wp++ = (xz & mask) ? (value & mask ? 'x' : 'z')
: ('0' | (static_cast<char>(value >> i) & 1));
}
}
for (int w = lastIdx - 1; w >= 0; --w) {
const EData value = newval[w];
const EData xz = newvalXZ[w];
for (int i = VL_EDATASIZE - 1; i >= 0; --i) {
const EData mask = 1 << i;
*wp++ = (xz & mask) ? (value & mask ? 'x' : 'z')
: ('0' | (static_cast<char>(value >> i) & 1));
}
}
finishLine(code, wp);
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitDouble(uint32_t code, double newval) {
char* wp = m_writep;

View File

@ -247,11 +247,22 @@ class VerilatedVcdBuffer VL_NOT_FINAL {
// called from only one place (the full* methods), so always inline them.
VL_ATTR_ALWINLINE void emitEvent(uint32_t code);
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
VL_ATTR_ALWINLINE void emitLogic(uint32_t code, CData newval, CData newvalXZ);
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateCData(uint32_t code, CData newval, CData newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateSData(uint32_t code, SData newval, SData newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateIData(uint32_t code, IData newval, IData newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int bits);
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, WDataInP newvalXZ,
int bits);
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
};

View File

@ -104,6 +104,7 @@ set(HEADERS
V3Force.h
V3FsmDetect.h
V3Fork.h
V3Fourstate.h
V3FuncOpt.h
V3FunctionTraits.h
V3Gate.h
@ -280,6 +281,7 @@ set(COMMON_SOURCES
V3Force.cpp
V3FsmDetect.cpp
V3Fork.cpp
V3Fourstate.cpp
V3FuncOpt.cpp
V3Gate.cpp
V3Global.cpp

View File

@ -282,6 +282,7 @@ RAW_OBJS_PCH_ASTNOMT = \
V3Force.o \
V3FsmDetect.o \
V3Fork.o \
V3Fourstate.o \
V3Gate.o \
V3HierBlock.o \
V3Inline.o \

View File

@ -1675,6 +1675,27 @@ public:
bool sameNode(const AstNode* /*samep*/) const override { return true; }
bool isSystemFunc() const override { return true; }
};
class AstFourstateExpr final : public AstNodeExpr {
// When AstNode wants a value as an child and that value is a splitted four-state value (so, it
// has value and xz part) this node shall be used to put them both there
// @astgen op1 := valuep : AstNodeExpr // value part of a four-state expression
// @astgen op2 := xzp : AstNodeExpr // xz part of a four-state expression
public:
AstFourstateExpr(FileLine* fl, AstNodeExpr* const valuePartp, AstNodeExpr* const xzPartp)
: ASTGEN_SUPER_FourstateExpr(fl) {
UASSERT_OBJ(valuePartp->width() == xzPartp->width(), this,
"Value and XZ part shall have same width but they have: "
<< valuePartp->width() << " and " << xzPartp->width());
valuep(valuePartp);
xzp(xzPartp);
dtypeSetLogicUnsized(valuePartp->width(), valuePartp->dtypep()->widthMin(),
valuePartp->dtypep()->numeric());
}
ASTGEN_MEMBERS_AstFourstateExpr;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
};
class AstFuture final : public AstNodeExpr {
// Verilog $future_gclk
// @astgen op1 := exprp : AstNodeExpr
@ -5504,6 +5525,7 @@ public:
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
string emitVerilog() override { return "(%l)"; }
string emitC() override { V3ERROR_NA_RETURN(""); }
string emitSMT() const override { return "%l"; }
bool cleanOut() const override { return false; }
bool cleanLhs() const override { return false; }
bool sizeMattersLhs() const override { return false; }

View File

@ -2117,6 +2117,8 @@ class AstVar final : public AstNode {
// @astgen op4 := attrsp : List[AstNode] // Attributes during early parse
// @astgen ptr := m_sensIfacep : Optional[AstIface] // Interface type to which reads from this
// var are sensitive
// @astgen ptr := m_fourstateComplementp : Optional[AstVar] // Set in four-state value part -
// points to an xz part
string m_name; // Name of variable
string m_origName; // Original name before dot addition
@ -2126,6 +2128,8 @@ class AstVar final : public AstNode {
VDirection m_declDirection; // Declared direction input/output etc
VLifetime m_lifetime; // Lifetime
VRandAttr m_rand; // Randomizability of this variable (rand, randc, etc)
VBasicDTypeKwd
m_fourstateOriginalDTypeKwd; // Original dtype of a four-state var - before splitting
int m_pinNum = 0; // For JSON, if non-zero the connection pin number
bool m_ansi : 1; // Params or pins declared in the module header, rather than the body
bool m_declTyped : 1; // Declared as type (for dedup check)
@ -2190,7 +2194,9 @@ class AstVar final : public AstNode {
bool m_isStdRandomizeArg : 1; // Argument variable created for std::randomize (__Varg*)
bool m_processQueue : 1; // Process queue variable
bool m_mtaskCacheLineAlign : 1; // Start MTask affinity group on a cache line
bool m_isFourstateComplement : 1; // Set in four-state xz part
void init() {
m_fourstateOriginalDTypeKwd = VBasicDTypeKwd::UNKNOWN;
m_ansi = false;
m_declTyped = false;
m_tristate = false;
@ -2254,6 +2260,7 @@ class AstVar final : public AstNode {
m_isStdRandomizeArg = false;
m_processQueue = false;
m_mtaskCacheLineAlign = false;
m_isFourstateComplement = false;
}
public:
@ -2356,6 +2363,19 @@ public:
void ansi(bool flag) { m_ansi = flag; }
void declTyped(bool flag) { m_declTyped = flag; }
void sensIfacep(AstIface* nodep) { m_sensIfacep = nodep; }
void fourstateComplementp(AstVar* const varp) {
UASSERT_OBJ(!isFourstateComplement(), this, "Varp is four-state complement i");
UASSERT_OBJ(!m_fourstateComplementp, this, "Varp already has a complement");
UASSERT_OBJ(!varp->isFourstateComplement(), varp, "It is already a four-state complement");
varp->m_isFourstateComplement = true;
m_fourstateComplementp = varp;
}
AstVar* fourstateComplementp() const { return m_fourstateComplementp; }
VBasicDTypeKwd fourstateOriginalDTypeKwd() const { return m_fourstateOriginalDTypeKwd; }
void fourstateOriginalDTypeKwd(const VBasicDTypeKwd dtypeKwd) {
m_fourstateOriginalDTypeKwd = dtypeKwd;
}
bool isFourstateComplement() const { return m_isFourstateComplement; }
void attrFileDescr(bool flag) { m_fileDescr = flag; }
void attrScBv(bool flag) { m_attrScBv = flag; }
void attrScBigUint(bool flag) { m_attrScBigUint = flag; }

View File

@ -1297,8 +1297,10 @@ class AstTraceDecl final : public AstNodeStmt {
const VNumRange m_arrayRange; // Property of var the trace details
const VVarType m_varType; // Type of variable (for localparam vs. param)
const VDirection m_declDirection; // Declared direction input/output etc
const VBasicDTypeKwd m_dtypeKwd; // dtype keyword of traced signal
const bool m_inDtypeFunc; // Trace decl inside type init function
int m_codeInc{0}; // Code increment for type
public:
AstTraceDecl(FileLine* fl, const string& showname,
AstVar* varp, // For input/output state etc
@ -1310,6 +1312,7 @@ public:
, m_arrayRange{arrayRange}
, m_varType{varp->varType()}
, m_declDirection{varp->declDirection()}
, m_dtypeKwd{varp->fourstateOriginalDTypeKwd()}
, m_inDtypeFunc{inDtypeFunc} {
dtypeFrom(valuep);
this->valuep(valuep);
@ -1335,12 +1338,15 @@ public:
if (m_codeInc) { return m_codeInc; }
return (m_arrayRange.ranged() ? m_arrayRange.elements() : 1)
* valuep()->dtypep()->widthWords()
* (1 + VN_IS(valuep(), FourstateExpr)) // Fourstate variables take twice
// as much space as they are wide
* (VL_EDATASIZE / 32); // A code is always 32-bits
}
const VNumRange& bitRange() const { return m_bitRange; }
const VNumRange& arrayRange() const { return m_arrayRange; }
VVarType varType() const { return m_varType; }
VDirection declDirection() const { return m_declDirection; }
VBasicDTypeKwd dtypeKwd() const { return m_dtypeKwd; }
AstCCall* dtypeCallp() const { return m_dtypeCallp; }
void dtypeCallp(AstCCall* const callp) { m_dtypeCallp = callp; }
AstTraceDecl* dtypeDeclp() const { return m_dtypeDeclp; }

View File

@ -3846,8 +3846,9 @@ class ConstVisitor final : public VNVisitor {
nodep->condp(new AstLogNot{condp->fileline(),
condp}); // LogNot, as C++ optimization also possible
nodep->addThensp(elsesp);
} else if (((VN_IS(nodep->condp(), Not) && nodep->condp()->width() == 1)
|| VN_IS(nodep->condp(), LogNot))
} else if (v3Global.fourstateHandled()
&& ((VN_IS(nodep->condp(), Not) && nodep->condp()->width() == 1)
|| VN_IS(nodep->condp(), LogNot))
&& nodep->thensp() && nodep->elsesp()) {
UINFO(4, "IF(NOT {x}) => IF(x) swapped if/else" << nodep);
AstNodeExpr* const condp
@ -3859,7 +3860,7 @@ class ConstVisitor final : public VNVisitor {
ifp->branchPred(nodep->branchPred().invert());
nodep->replaceWith(ifp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (ifSameAssign(nodep)) {
} else if (v3Global.fourstateHandled() && ifSameAssign(nodep)) {
UINFO(4,
"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})");
AstNodeAssign* const thensp = VN_AS(nodep->thensp(), NodeAssign);

View File

@ -489,8 +489,12 @@ class DeadVisitor final : public VNVisitor {
retry = false;
for (std::vector<AstVar*>::iterator it = m_varsp.begin(); it != m_varsp.end(); ++it) {
AstVar* const varp = *it;
if (!varp) continue;
if (!varp || varp->isFourstateComplement()) continue;
if (varp->user1() == 0) {
if (AstVar* const varComplementp = varp->fourstateComplementp()) {
if (varComplementp->user1() != 0) continue;
deleting(varComplementp);
}
UINFO(4, " Dead " << varp);
if (varp->dtypep()) varp->dtypep()->user1Inc(-1);
deleting(varp);

View File

@ -645,6 +645,23 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, bool constructing,
UASSERT_OBJ(constp, varp, "non-const initializer for variable");
out += cvtToStr(constp->num().edataWord(0)) + "U;\n";
out += ";\n";
} else if (v3Global.opt.fourstate()
&& (varp->fourstateComplementp() || varp->isFourstateComplement())) {
V3Number xNum{varp->fileline(), varp->width(), 0};
bool setTozero = false;
if (varp->varType() == VVarType::PORT) {
const AstNode* iter = varp;
while (!iter->firstAbovep()) iter = iter->backp();
if (AstModule* const modep = VN_CAST(iter->firstAbovep(), Module)) {
setTozero = modep->isTop();
}
}
if (!setTozero && (varp->isFourstateComplement() || !varp->varType().isNet())) {
xNum.setAllBits1();
}
out += " = ";
out += xNum.emitC();
out += ";\n";
} else if (zeroit) {
out += " = 0;\n";
} else {

View File

@ -740,8 +740,9 @@ class EmitCTrace final : public EmitCFunc {
void emitTraceChangeOne(AstTraceInc* nodep, int arrayindex) {
// Note: Both VTraceType::CHANGE and VTraceType::FULL use the 'full' methods
const std::string func = nodep->traceType() == VTraceType::CHANGE ? "chg" : "full";
std::string func = nodep->traceType() == VTraceType::CHANGE ? "chg" : "full";
bool emitWidth = true;
const bool isFourstate = VN_IS(nodep->valuep(), FourstateExpr);
string stype;
if (nodep->dtypep()->basicp()->isDouble()) {
stype = "Double";
@ -759,10 +760,14 @@ class EmitCTrace final : public EmitCFunc {
} else if (nodep->dtypep()->basicp()->isEvent()) {
stype = "Event";
emitWidth = false;
} else if (isFourstate) {
stype = "Logic";
emitWidth = false;
} else {
stype = "Bit";
emitWidth = false;
}
if (isFourstate && stype != "Logic") func += "Fourstate";
putns(nodep, "bufp->" + func + stype);
const uint32_t offset = (arrayindex < 0) ? 0 : (arrayindex * nodep->declp()->widthWords());
@ -781,8 +786,8 @@ class EmitCTrace final : public EmitCFunc {
}
void emitTraceValue(const AstTraceInc* nodep, int arrayindex) {
if (AstVarRef* const varrefp = VN_CAST(nodep->valuep(), VarRef)) {
const AstVar* const varp = varrefp->varp();
auto putVarRef = [this, nodep, arrayindex](AstVarRef* const varrefp) {
AstVar* const varp = varrefp->varp();
if (varp->isEvent()) puts("&");
puts("(");
if (emitTraceIsScBigUint(nodep)) {
@ -801,12 +806,29 @@ class EmitCTrace final : public EmitCFunc {
puts(")");
}
puts(")");
};
puts("(");
if (AstFourstateExpr* const exprp = VN_CAST(nodep->valuep(), FourstateExpr)) {
if (AstVarRef* const varrefp = VN_CAST(exprp->valuep(), VarRef)) {
putVarRef(varrefp);
} else {
iterateConst(exprp->valuep());
}
puts("), (");
if (AstVarRef* const varrefp = VN_CAST(exprp->xzp(), VarRef)) {
putVarRef(varrefp);
} else {
iterateConst(exprp->xzp());
}
} else if (AstVarRef* const varrefp = VN_CAST(nodep->valuep(), VarRef)) {
putVarRef(varrefp);
} else {
puts("(");
iterateConst(nodep->valuep());
emitTraceIndex(nodep, arrayindex);
puts(")");
}
puts(")");
}
void emitTraceIndex(const AstTraceInc* const nodep, int arrayindex) {

View File

@ -639,6 +639,13 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
iterateConst(nodep->exprp());
puts(";\n");
}
void visit(AstFourstateExpr* const nodep) override {
puts("Four-state expression: (Value part: ");
iterateConst(nodep->valuep());
puts(", XZ part:");
iterateConst(nodep->xzp());
puts(")");
}
// Nodes involing AstText
void visit(AstText* nodep) override {

View File

@ -90,6 +90,7 @@ public:
CASEWITHX, // Case with X values
CASEX, // Casex
CASTCONST, // Cast is constant
CASTFOURSTATE, // Implicit logic (between 2/4 state logic)
CDCRSTLOGIC, // Logic in async reset path. Historical, never issued.
CLKDATA, // Clock used as data. Historical, never issued.
CMPCONST, // Comparison is constant due to limited range
@ -226,24 +227,24 @@ public:
" EC_FIRST_WARN", "ALWCOMBORDER", "ALWNEVER", "ASCRANGE", "ASSIGNDLY", "ASSIGNEQEXPR",
"ASSIGNIN", "BADSTDPRAGMA", "BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ",
"BSSPACE", "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST",
"CDCRSTLOGIC", "CLKDATA", "CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN",
"CONTASSREG", "COVERIGN", "DECLFILENAME", "DEFOVERRIDE", "DEFPARAM", "DEPRECATED",
"ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE", "FINALDLY",
"FSMMULTI", "FUNCTIMECTL", "FUTURE", "GENCLK", "GENUNNAMED", "HIERBLOCK", "HIERPARAM",
"IEEEMAYDEPRECATE", "IFDEPTH", "IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT",
"IMPLICITSTATIC", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY",
"INSECURE", "INSIDETRUE", "LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP",
"MODMISSING", "MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD",
"NORETURN", "NOTREDOP", "NULLPORT", "PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING",
"PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT",
"PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED", "PROTOTYPEMIS", "RANDC", "REALCVT",
"REDEFMACRO", "RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPECIFYIGN",
"SPLITVAR", "STATICVAR", "STMTDLY", "SUPERNFIRST", "SYMRSVDWORD", "SYNCASYNCNET",
"TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNPACKED", "UNSATCONSTR", "UNSIGNED", "UNUSED", "UNUSEDGENVAR", "UNUSEDLOOP",
"UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL", "USERINFO", "USERWARN",
"VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT", "WIDTHEXPAND", "WIDTHTRUNC",
"WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"};
"CASTFOURSTATE", "CDCRSTLOGIC", "CLKDATA", "CMPCONST", "COLONPLUS", "COMBDLY",
"CONSTRAINTIGN", "CONTASSREG", "COVERIGN", "DECLFILENAME", "DEFOVERRIDE", "DEFPARAM",
"DEPRECATED", "ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE",
"FINALDLY", "FSMMULTI", "FUNCTIMECTL", "FUTURE", "GENCLK", "GENUNNAMED", "HIERBLOCK",
"HIERPARAM", "IEEEMAYDEPRECATE", "IFDEPTH", "IGNOREDRETURN", "IMPERFECTSCH",
"IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP",
"INITIALDLY", "INSECURE", "INSIDETRUE", "LATCH", "LITENDIAN", "MINTYPMAXDLY",
"MISINDENT", "MODDUP", "MODMISSING", "MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT",
"NOLATCH", "NONSTD", "NORETURN", "NOTREDOP", "NULLPORT", "PARAMNODEFAULT",
"PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL",
"PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED",
"PROTOTYPEMIS", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY", "SELRANGE",
"SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR", "STATICVAR", "STMTDLY",
"SUPERNFIRST", "SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN",
"UNOPT", "UNOPTFLAT", "UNOPTTHREADS", "UNPACKED", "UNSATCONSTR", "UNSIGNED", "UNUSED",
"UNUSEDGENVAR", "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL",
"USERINFO", "USERWARN", "VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT",
"WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"};
return names[m_e];
}
// Warnings that default to off

2412
src/V3Fourstate.cpp Normal file

File diff suppressed because it is too large Load Diff

32
src/V3Fourstate.h Normal file
View File

@ -0,0 +1,32 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Four-state logic handler
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// 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
//
//*************************************************************************
#ifndef VERILATOR_V3FOURSTATE_METHOD_H_
#define VERILATOR_V3FOURSTATE_METHOD_H_
#include "config_build.h"
#include "verilatedos.h"
class AstNetlist;
//============================================================================
class V3Fourstate final {
public:
static void fourstateAll(AstNetlist* nodep) VL_MT_DISABLED;
};
#endif // Guard

View File

@ -135,6 +135,7 @@ class V3Global final {
bool m_useCovergroup = false; // Has covergroup declarations
bool m_useRandomizeMethods = false; // Need to define randomize() class methods
bool m_hasPrintedObjects = false; // Design has format args printed with to_string()
bool m_fourstateHandled = false; // There should be no more fourstate values
uint64_t m_currentHierBlockCost = 0; // Total cost of this hier block, used for scheduling
// Memory address to short string mapping (for debug)
@ -224,6 +225,8 @@ public:
bool useCovergroup() const { return m_useCovergroup; }
void useCovergroup(bool flag) { m_useCovergroup = flag; }
bool useRandomizeMethods() const { return m_useRandomizeMethods; }
void setFourstateHandled() { m_fourstateHandled = true; }
bool fourstateHandled() const { return !opt.fourstate() || m_fourstateHandled; }
void useRandomizeMethods(bool flag) { m_useRandomizeMethods = flag; }
bool hasPrintedObjects() const { return m_hasPrintedObjects; }
void hasPrintedObjects(bool flag) { m_hasPrintedObjects = flag; }

View File

@ -1339,6 +1339,16 @@ V3Number& V3Number::opBitsOne(const V3Number& lhs) { // 1->1, 0/X/Z->0
}
return *this;
}
V3Number& V3Number::opBitsOneX(const V3Number& lhs) {
// op i, L(lhs) bit return
NUM_ASSERT_OP_ARGS1(lhs);
NUM_ASSERT_LOGIC_ARGS1(lhs);
setZero();
for (int bit = 0; bit < width(); ++bit) {
if (lhs.bitIs1(bit) || lhs.bitIsX(bit)) setBit(bit, 1);
}
return *this;
}
V3Number& V3Number::opBitsXZ(const V3Number& lhs) { // 0/1->1, X/Z->0
// op i, L(lhs) bit return
NUM_ASSERT_OP_ARGS1(lhs);

View File

@ -744,6 +744,7 @@ public:
// "this" is the output, as we need the output width before some computations
V3Number& opBitsNonXZ(const V3Number& lhs); // 0/1->1, X/Z->0
V3Number& opBitsOne(const V3Number& lhs); // 1->1, 0/X/Z->0
V3Number& opBitsOneX(const V3Number& lhs); // 1/X->1, 0/Z->0
V3Number& opBitsXZ(const V3Number& lhs); // 0/1->0, X/Z->1
V3Number& opBitsZ(const V3Number& lhs); // Z->1, 0/1/X->0
//

View File

@ -1054,6 +1054,9 @@ void V3Options::notify() VL_MT_DISABLED {
cmdfl->v3warn(E_UNSUPPORTED,
"--fourstate is not supported with hierarchical Verilation");
}
if (traceEnabledFst()) {
cmdfl->v3warn(E_UNSUPPORTED, "--fourstate is not supported with fst trace");
}
}
if (coverage() && savable()) {

View File

@ -246,10 +246,40 @@ private:
= [this, flp, senp]() { return new AstVarRef{flp, getPrev(senp), VAccess::READ}; };
const auto lsb = [=](AstNodeExpr* opp) { return new AstSel{flp, opp, 0, 1}; };
// Four-state expression handlers
AstFourstateExpr* const fourstateExpr = VN_CAST(senp, FourstateExpr);
auto currValp = [this, fourstateExpr]() { return getCurr(fourstateExpr->valuep()); };
auto currXZp = [this, fourstateExpr]() { return getCurr(fourstateExpr->xzp()); };
auto prevValp = [this, fourstateExpr, flp]() {
return new AstVarRef{flp, getPrev(fourstateExpr->valuep()), VAccess::READ};
};
auto prevXZp = [this, fourstateExpr, flp]() {
return new AstVarRef{flp, getPrev(fourstateExpr->xzp()), VAccess::READ};
};
// All event signals should be 1-bit at this point
switch (senItemp->edgeType()) {
case VEdgeType::ET_CHANGED:
case VEdgeType::ET_HYBRID: //
if (fourstateExpr) {
if (VN_IS(senp->dtypep()->skipRefp(), UnpackArrayDType)) {
AstCMethodHard* const resultValp
= new AstCMethodHard{flp, prevp(), VCMethod::UNPACKED_NEQ, currValp()};
AstCMethodHard* const resultXZp
= new AstCMethodHard{flp, prevp(), VCMethod::UNPACKED_NEQ, currXZp()};
resultValp->dtypeSetBit();
resultXZp->dtypeSetBit();
return {wrapExprWithNullCheck(flp, new AstOr{flp, resultValp, resultXZp},
baseClassRefp),
true};
}
return {wrapExprWithNullCheck(
flp,
lsb(new AstOr{flp, new AstXor{flp, prevValp(), currValp()},
new AstXor{flp, prevXZp(), currXZp()}}),
baseClassRefp),
true};
}
if (VN_IS(senp->dtypep()->skipRefp(), UnpackArrayDType)) {
// operand order reversed to avoid calling neq() method on non-VlUnpacked type, see
// issue #5125
@ -261,15 +291,46 @@ private:
return {wrapExprWithNullCheck(flp, new AstNeq{flp, currp(), prevp()}, baseClassRefp),
true};
case VEdgeType::ET_BOTHEDGE: //
if (fourstateExpr) {
return {wrapExprWithNullCheck(
flp,
lsb(new AstOr{flp, new AstXor{flp, currXZp(), prevXZp()},
new AstAnd{flp, new AstNot{flp, prevXZp()},
new AstXor{flp, currValp(), prevValp()}}}),
baseClassRefp),
false};
}
return {
wrapExprWithNullCheck(flp, lsb(new AstXor{flp, currp(), prevp()}), baseClassRefp),
false};
case VEdgeType::ET_POSEDGE: //
if (fourstateExpr) {
return {wrapExprWithNullCheck(
flp,
lsb(new AstAnd{
flp,
new AstAnd{flp, new AstOr{flp, currValp(), currXZp()},
new AstOr{flp, prevXZp(), new AstNot{flp, prevValp()}}},
new AstNot{flp, new AstAnd{flp, prevXZp(), currXZp()}}}),
baseClassRefp),
false};
}
return {wrapExprWithNullCheck(flp,
lsb(new AstAnd{flp, currp(), new AstNot{flp, prevp()}}),
baseClassRefp),
false};
case VEdgeType::ET_NEGEDGE: //
if (fourstateExpr) {
return {wrapExprWithNullCheck(
flp,
lsb(new AstAnd{
flp,
new AstAnd{flp, new AstOr{flp, prevValp(), prevXZp()},
new AstOr{flp, currXZp(), new AstNot{flp, currValp()}}},
new AstNot{flp, new AstAnd{flp, prevXZp(), currXZp()}}}),
baseClassRefp),
false};
}
return {wrapExprWithNullCheck(flp,
lsb(new AstAnd{flp, new AstNot{flp, currp()}, prevp()}),
baseClassRefp),
@ -293,6 +354,9 @@ private:
return {wrapExprWithNullCheck(flp, callp, baseClassRefp), false};
}
case VEdgeType::ET_TRUE: //
if (fourstateExpr) {
return {lsb(new AstAnd{flp, currValp(), new AstNot{flp, currXZp()}}), false};
}
return {currp(), false};
case VEdgeType::ET_INITIAL_NBA: //
return {new AstConst{flp, AstConst::BitFalse{}}, true};

View File

@ -230,8 +230,11 @@ class TraceDeclVisitor final : public VNVisitor {
FileLine& fileline() const { return m_vscp ? *m_vscp->fileline() : *m_cellp->fileline(); }
};
std::vector<TraceEntry> m_entries; // Trace entries under current scope
std::map<const AstVar*, AstVarScope*>
m_varxzToVscp; // Map from variable with xz part to its variable scope
AstVarScope* m_traVscp = nullptr; // Current AstVarScope we are constructing AstTraceDecls for
AstNodeExpr* m_traValuep = nullptr; // Value expression for current signal
AstNodeExpr* m_traValueXZp = nullptr; // ValueXZ expression for current signal
string m_traName; // Name component for current signal
VDouble0 m_statSigs; // Statistic tracking
@ -334,6 +337,10 @@ class TraceDeclVisitor final : public VNVisitor {
}
FileLine* const flp = m_traVscp->fileline();
AstNodeExpr* valuep = m_traValuep->cloneTree(false);
if (m_traValueXZp) {
valuep = new AstFourstateExpr{m_traVscp->fileline(), valuep,
m_traValueXZp->cloneTree(false)};
}
const bool validOffset = m_offset != std::numeric_limits<uint32_t>::max();
AstTraceDecl* const newp
= new AstTraceDecl{flp, m_traName, m_traVscp->varp(), valuep,
@ -685,6 +692,12 @@ class TraceDeclVisitor final : public VNVisitor {
// traversal.
m_traValuep
= new AstVarRef{m_traVscp->fileline(), m_traVscp, VAccess::READ};
if (AstVar* const complementp
= m_traVscp->varp()->fourstateComplementp()) {
m_traValueXZp
= new AstVarRef{m_traVscp->fileline(),
m_varxzToVscp.at(complementp), VAccess::READ};
}
// Recurse into data type of the signal. The visit methods will add
// AstTraceDecls.
iterate(m_traVscp->varp()->dtypep()->skipRefToEnump());
@ -694,6 +707,10 @@ class TraceDeclVisitor final : public VNVisitor {
// Note: Sometimes VL_DANGLING is a no-op, but we have assertions
// on m_traValuep being nullptr, so make sure it is.
m_traValuep = nullptr;
if (m_traValueXZp) {
VL_DO_DANGLING(m_traValueXZp->deleteTree(), m_traValueXZp);
m_traValueXZp = nullptr;
}
}
}
} else {
@ -795,8 +812,12 @@ class TraceDeclVisitor final : public VNVisitor {
if (nodep->varp()->isParam() && VN_IS(nodep->scopep()->modp(), Package)) return;
}
// Add to traced signal list
m_entries.emplace_back(m_currScopep, nodep);
if (nodep->varp()->isFourstateComplement()) {
m_varxzToVscp.emplace(nodep->varp(), nodep);
} else {
// Add to traced signal list
m_entries.emplace_back(m_currScopep, nodep);
}
}
// VISITORS - Data types when tracing

View File

@ -394,7 +394,7 @@ class UnknownVisitor final : public VNVisitor {
void visit(AstSel* nodep) override {
iterateChildren(nodep);
if (!nodep->user1SetOnce()) {
if (!v3Global.opt.fourstate() && !nodep->user1SetOnce()) {
// Guard against reading/writing past end of bit vector array
const AstNode* const basefromp = AstArraySel::baseFromp(nodep, true);
bool lvalue = false;

View File

@ -1071,7 +1071,8 @@ class WidthVisitor final : public VNVisitor {
const bool inParameterizedTemplate
= m_modep && (m_modep->dead() || m_modep->parameterizedTemplate());
if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() < nodep->lsbConst()) {
if (!v3Global.opt.fourstate() && VN_IS(nodep->lsbp(), Const)
&& nodep->msbConst() < nodep->lsbConst()) {
// Likely impossible given above width check
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: left < right of bit extract: " // LCOV_EXCL_LINE
@ -1145,22 +1146,24 @@ class WidthVisitor final : public VNVisitor {
UINFO(1, " Related node: " << nodep);
}
if (lrefp) UINFO(9, " Select extend lrefp " << lrefp);
if (lrefp && lrefp->access().isWriteOrRW()) {
// lvarref[X] = ..., the expression assigned is too wide
// WTF to do
// Don't change the width of this lhsp, instead propagate up
// to upper assign/expression the correct width
AstNodeDType* const subDTypep
= nodep->findLogicDType(width, width, nodep->fromp()->dtypep()->numeric());
widthCheckSized(nodep, "errorless...", nodep->fromp(), subDTypep, EXTEND_EXP,
false /*noerror*/);
} else {
// Extend it
const int extendTo = nodep->msbConst() + 1;
AstNodeDType* const subDTypep = nodep->findLogicDType(
extendTo, extendTo, nodep->fromp()->dtypep()->numeric());
widthCheckSized(nodep, "errorless...", nodep->fromp(), subDTypep, EXTEND_EXP,
false /*noerror*/);
if (!v3Global.opt.fourstate()) {
if (lrefp && lrefp->access().isWriteOrRW()) {
// lvarref[X] = ..., the expression assigned is too wide
// WTF to do
// Don't change the width of this lhsp, instead propagate up
// to upper assign/expression the correct width
AstNodeDType* const subDTypep = nodep->findLogicDType(
width, width, nodep->fromp()->dtypep()->numeric());
widthCheckSized(nodep, "errorless...", nodep->fromp(), subDTypep,
EXTEND_EXP, false /*noerror*/);
} else {
// Extend it
const int extendTo = nodep->msbConst() + 1;
AstNodeDType* const subDTypep = nodep->findLogicDType(
extendTo, extendTo, nodep->fromp()->dtypep()->numeric());
widthCheckSized(nodep, "errorless...", nodep->fromp(), subDTypep,
EXTEND_EXP, false /*noerror*/);
}
}
}
// iterate FINAL is two blocks above
@ -1168,7 +1171,7 @@ class WidthVisitor final : public VNVisitor {
// If we have a width problem with GENERATE etc, this will reduce
// it down and mask it, so we have no chance of finding a real
// error in the future. So don't do this for them.
if (!m_doGenerate) {
if (!v3Global.opt.fourstate() && !m_doGenerate) {
// lsbp() must be self-determined, however for performance
// we want the select to be truncated to fit within the
// maximum select range, e.g. turn Xs outside of the select

View File

@ -278,9 +278,6 @@ private:
void visit(AstCastWrap* nodep) override {
iterateChildren(nodep);
editDType(nodep);
UINFO(6, " Replace " << nodep << " w/ " << nodep->lhsp());
nodep->replaceWith(nodep->lhsp()->unlinkFrBack());
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void visit(AstConstraint* nodep) override {
iterateChildren(nodep);
@ -557,3 +554,19 @@ void V3WidthCommit::widthCommit(AstNetlist* nodep) {
{ WidthCommitVisitor{nodep}; } // Destruct before checking
V3Global::dumpCheckGlobalTree("widthcommit", 0, dumpTreeEitherLevel() >= 6);
}
void V3WidthCommit::widthCommitClean(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ":");
{
std::vector<AstCastWrap*> castWrapsToDelete;
v3Global.rootp()->foreach([&castWrapsToDelete](AstCastWrap* nodep) {
UINFO(6, " Replace " << nodep << " w/ " << nodep->lhsp());
castWrapsToDelete.push_back(nodep);
});
for (AstCastWrap* const nodep : castWrapsToDelete) {
nodep->replaceWith(nodep->lhsp()->unlinkFrBack());
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
V3Global::dumpCheckGlobalTree("widthcommit_clean", 0, dumpTreeEitherLevel() >= 6);
}

View File

@ -42,6 +42,7 @@ public:
// Final step... Mark all widths as equal
static void widthCommit(AstNetlist* nodep) VL_MT_DISABLED;
static void widthCommitClean(AstNetlist* nodep) VL_MT_DISABLED;
};
//######################################################################

View File

@ -57,6 +57,7 @@
#include "V3File.h"
#include "V3Force.h"
#include "V3Fork.h"
#include "V3Fourstate.h"
#include "V3FsmDetect.h"
#include "V3FuncOpt.h"
#include "V3Gate.h"
@ -301,6 +302,8 @@ static void process() {
// No more AstGenBlocks after this
V3Begin::debeginAll(v3Global.rootp()); // Flatten cell names, before inliner
if (v3Global.opt.fourstate()) V3Fourstate::fourstateAll(v3Global.rootp());
V3WidthCommit::widthCommitClean(v3Global.rootp());
// Expand inouts, stage 2
// Also simplify pin connections to always be AssignWs in prep for V3Unknown
V3Tristate::tristateAll(v3Global.rootp());

View File

@ -2,7 +2,7 @@
"modulesp": [
{"type":"MODULE","name":"t","addr":"(F)","loc":"d,67:8,67:9","origName":"t","verilogName":"t","level":1,"timeunit":"1ps","inlinesp": [],
"stmtsp": [
{"type":"VAR","name":"p","addr":"(G)","loc":"d,69:10,69:11","dtypep":"(H)","origName":"p","verilogName":"p","direction":"NONE","lifetime":"VSTATICI","varType":"VAR","dtypeName":"Packet","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"p","addr":"(G)","loc":"d,69:10,69:11","dtypep":"(H)","origName":"p","verilogName":"p","direction":"NONE","lifetime":"VSTATICI","varType":"VAR","dtypeName":"Packet","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"INITIAL","name":"","addr":"(I)","loc":"d,71:3,71:10",
"stmtsp": [
{"type":"BEGIN","name":"","addr":"(J)","loc":"d,71:11,71:16","unnamed":true,"declsp": [],
@ -19,21 +19,21 @@
"stmtsp": [
{"type":"CLASS","name":"Packet","addr":"(O)","loc":"d,7:1,7:6","origName":"Packet","verilogName":"Packet","level":3,"timeunit":"1ps","classOrPackagep":"UNLINKED","inlinesp": [],
"stmtsp": [
{"type":"VAR","name":"header","addr":"(P)","loc":"d,8:12,8:18","dtypep":"(Q)","origName":"header","verilogName":"header","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"int","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"length","addr":"(R)","loc":"d,9:12,9:18","dtypep":"(Q)","origName":"length","verilogName":"length","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"int","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"sublength","addr":"(S)","loc":"d,10:12,10:21","dtypep":"(Q)","origName":"sublength","verilogName":"sublength","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"int","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"if_4","addr":"(T)","loc":"d,11:12,11:16","dtypep":"(U)","origName":"if_4","verilogName":"if_4","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"iff_5_6","addr":"(V)","loc":"d,12:12,12:19","dtypep":"(U)","origName":"iff_5_6","verilogName":"iff_5_6","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"if_state_ok","addr":"(W)","loc":"d,13:12,13:23","dtypep":"(U)","origName":"if_state_ok","verilogName":"if_state_ok","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"array","addr":"(X)","loc":"d,15:12,15:17","dtypep":"(Y)","origName":"array","verilogName":"array","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"state","addr":"(Z)","loc":"d,17:10,17:15","dtypep":"(M)","origName":"state","verilogName":"state","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"string","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"header","addr":"(P)","loc":"d,8:12,8:18","dtypep":"(Q)","origName":"header","verilogName":"header","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"int","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"length","addr":"(R)","loc":"d,9:12,9:18","dtypep":"(Q)","origName":"length","verilogName":"length","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"int","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"sublength","addr":"(S)","loc":"d,10:12,10:21","dtypep":"(Q)","origName":"sublength","verilogName":"sublength","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"int","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"if_4","addr":"(T)","loc":"d,11:12,11:16","dtypep":"(U)","origName":"if_4","verilogName":"if_4","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"bit","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"iff_5_6","addr":"(V)","loc":"d,12:12,12:19","dtypep":"(U)","origName":"iff_5_6","verilogName":"iff_5_6","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"bit","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"if_state_ok","addr":"(W)","loc":"d,13:12,13:23","dtypep":"(U)","origName":"if_state_ok","verilogName":"if_state_ok","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"bit","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"array","addr":"(X)","loc":"d,15:12,15:17","dtypep":"(Y)","origName":"array","verilogName":"array","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"state","addr":"(Z)","loc":"d,17:10,17:15","dtypep":"(M)","origName":"state","verilogName":"state","direction":"NONE","lifetime":"VAUTOMI","varType":"MEMBER","dtypeName":"string","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"FUNC","name":"strings_equal","addr":"(AB)","loc":"d,61:16,61:29","dtypep":"(U)","method":true,"cname":"strings_equal",
"fvarp": [
{"type":"VAR","name":"strings_equal","addr":"(BB)","loc":"d,61:16,61:29","dtypep":"(U)","origName":"strings_equal","verilogName":"strings_equal","direction":"OUTPUT","noCReset":true,"icoMaybeWritten":true,"isFuncReturn":true,"isFuncLocal":true,"lifetime":"VAUTOM","varType":"VAR","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}
{"type":"VAR","name":"strings_equal","addr":"(BB)","loc":"d,61:16,61:29","dtypep":"(U)","origName":"strings_equal","verilogName":"strings_equal","direction":"OUTPUT","noCReset":true,"icoMaybeWritten":true,"isFuncReturn":true,"isFuncLocal":true,"lifetime":"VAUTOM","varType":"VAR","dtypeName":"bit","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}
],"classOrPackagep": [],
"stmtsp": [
{"type":"VAR","name":"a","addr":"(CB)","loc":"d,61:37,61:38","dtypep":"(M)","origName":"a","verilogName":"a","direction":"INPUT","isFuncLocal":true,"lifetime":"VAUTOMI","varType":"PORT","dtypeName":"string","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"b","addr":"(DB)","loc":"d,61:47,61:48","dtypep":"(M)","origName":"b","verilogName":"b","direction":"INPUT","isFuncLocal":true,"lifetime":"VAUTOMI","varType":"PORT","dtypeName":"string","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"a","addr":"(CB)","loc":"d,61:37,61:38","dtypep":"(M)","origName":"a","verilogName":"a","direction":"INPUT","isFuncLocal":true,"lifetime":"VAUTOMI","varType":"PORT","dtypeName":"string","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"b","addr":"(DB)","loc":"d,61:47,61:48","dtypep":"(M)","origName":"b","verilogName":"b","direction":"INPUT","isFuncLocal":true,"lifetime":"VAUTOMI","varType":"PORT","dtypeName":"string","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"ASSIGN","name":"","addr":"(EB)","loc":"d,61:16,61:29","dtypep":"(U)",
"rhsp": [
{"type":"CONST","name":"1'h0","addr":"(FB)","loc":"d,61:16,61:29","dtypep":"(U)"}
@ -56,7 +56,7 @@
],"timingControlp": []}
],"scopeNamep": []},
{"type":"FUNC","name":"new","addr":"(MB)","loc":"d,7:1,7:6","dtypep":"(NB)","method":true,"cname":"new","fvarp": [],"classOrPackagep": [],"stmtsp": [],"scopeNamep": []},
{"type":"VAR","name":"constraint","addr":"(OB)","loc":"d,7:1,7:6","dtypep":"(PB)","origName":"constraint","verilogName":"constraint","direction":"NONE","lifetime":"NONE","varType":"MEMBER","dtypeName":"VlRandomizer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}
{"type":"VAR","name":"constraint","addr":"(OB)","loc":"d,7:1,7:6","dtypep":"(PB)","origName":"constraint","verilogName":"constraint","direction":"NONE","lifetime":"NONE","varType":"MEMBER","dtypeName":"VlRandomizer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}
],"extendsp": []}
]}
],"filesp": [],

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute()
test.passes()

View File

@ -0,0 +1,84 @@
// 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
`ifdef VERILATOR
`define IMPURE_ONE ($c(1))
`else
`define IMPURE_ONE (|($random | $random))
`endif
module t;
function integer f(integer x);
if (`IMPURE_ONE) return x;
return 'x;
endfunction
function logic [31:0] g(logic [31:0] x);
if (`IMPURE_ONE) return x;
return 'x;
endfunction
initial begin
if ((f(10) + f(-5)) !== 5) $stop;
if ((f(10) + f('b11x)) !== 'x) $stop;
if ((f(10) + f('b11z)) !== 'x) $stop;
if ((g(10) + g(5)) !== 15) $stop;
if ((g(10) + g('x)) !== 'x) $stop;
if ((f(10) - f(-5)) !== 15) $stop;
if ((f(10) - f('b11x)) !== 'x) $stop;
if ((f(10) - f('b11z)) !== 'x) $stop;
if ((g(10) - g(5)) !== 5) $stop;
if ((g(10) - g('x)) !== 'x) $stop;
if ((f(10) * f(-5)) !== -50) $stop;
if ((f(10) * f('b11x)) !== 'x) $stop;
if ((f(10) * f('b11z)) !== 'x) $stop;
if ((g(10) * g(5)) !== 50) $stop;
if ((g(10) * g('x)) !== 'x) $stop;
if ((f(10) / f(5)) !== 2) $stop;
if ((f(9) / f(5)) !== 1) $stop;
if ((f(10) / f(2)) !== 5) $stop;
if ((f(-10) / f(5)) !== -2) $stop;
if ((f(9) / f(-5)) !== -1) $stop;
if ((f('bx) / f('bx)) !== 'x) $stop;
if ((f('bz) / f(5)) !== 'x) $stop;
if ((f(10) / f(0)) !== 'x) $stop;
if ((f(0) / f(0)) !== 'x) $stop;
if ((f(0) / f('z)) !== 'x) $stop;
if ((g(10) / g(5)) !== 2) $stop;
if ((g(9) / g(5)) !== 1) $stop;
if ((g(10) / g(2)) !== 5) $stop;
if ((g('bx) / g('bx)) !== 'x) $stop;
if ((g('bz) / g(5)) !== 'x) $stop;
if ((g(10) / g(0)) !== 'x) $stop;
if ((g(0) / g(0)) !== 'x) $stop;
if ((g(0) / g('z)) !== 'x) $stop;
if ((f(10) % f(5)) !== 0) $stop;
if ((f(9) % f(5)) !== 4) $stop;
if ((f(10) % f(2)) !== 0) $stop;
if ((f(-10) % f(5)) !== 0) $stop;
if ((f(9) % f(-5)) !== 4) $stop;
if ((f('bx) % f('bx)) !== 'x) $stop;
if ((f('bz) % f(5)) !== 'x) $stop;
if ((f(10) % f(0)) !== 'x) $stop;
if ((f(0) % f(0)) !== 'x) $stop;
if ((f(0) % f('z)) !== 'x) $stop;
if ((g(10) % g(5)) !== 0) $stop;
if ((g(9) % g(5)) !== 4) $stop;
if ((g(10) % g(2)) !== 0) $stop;
if ((g('bx) % g('bx)) !== 'x) $stop;
if ((g('bz) % g(5)) !== 'x) $stop;
if ((g(10) % g(0)) !== 'x) $stop;
if ((g(0) % g(0)) !== 'x) $stop;
if ((g(0) % g('z)) !== 'x) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,6 @@
%Error-UNSUPPORTED: t/t_fourstate_assign_complex_lhs_unsup.v:10:10: Fourstate LHS other than a simple variable reference is not supported
: ... note: In instance 't'
10 | x[1] = 1;
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -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('linter')
test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,12 @@
// 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;
initial begin
static logic [2:0] x;
x[1] = 1;
end
endmodule

View File

@ -0,0 +1,20 @@
%Error-UNSUPPORTED: t/t_case_onehot.v:88:15: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't.test'
88 | in[ST_0]: out <= 32'h1234;
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_case_onehot.v:89:15: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't.test'
89 | in[ST_1]: out <= 32'h4356;
| ^
%Error-UNSUPPORTED: t/t_case_onehot.v:90:15: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't.test'
90 | in[ST_2]: out <= 32'h9874;
| ^
%Error-UNSUPPORTED: t/t_case_onehot.v:87:5: Unsupported: Operator ONEHOT not supported in the four-state mode
87 | case (1'b1) /*verilator parallel_case*/
| ^~~~
%Error-UNSUPPORTED: t/t_case_onehot.v:87:5: Unsupported: Operator LOGNOT not supported in the four-state mode
87 | case (1'b1) /*verilator parallel_case*/
| ^~~~
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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('linter')
test.top_filename = 't/t_case_onehot.v'
test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE', '-Wno-CASTFOURSTATE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,82 @@
%Error-UNSUPPORTED: t/t_case_x.v:21:5: All case statements with four-state value as an expression are unsupported with --fourstate
: ... note: In instance 't'
21 | case (value)
| ^~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_case_x.v:22:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
22 | 4'b1xxx: $stop;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:23:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
23 | 4'b1???: $stop;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:27:5: All case statements with four-state value as an expression are unsupported with --fourstate
: ... note: In instance 't'
27 | case (valuex)
| ^~~~
%Error-UNSUPPORTED: t/t_case_x.v:28:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
28 | 4'b1???: $stop;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:29:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
29 | 4'b1xxx: ;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:35:5: All case statements with four-state value as an expression are unsupported with --fourstate
: ... note: In instance 't'
35 | casex (value)
| ^~~~~
%Error-UNSUPPORTED: t/t_case_x.v:36:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
36 | 4'b100x: ;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:39:5: All case statements with four-state value as an expression are unsupported with --fourstate
: ... note: In instance 't'
39 | casex (value)
| ^~~~~
%Error-UNSUPPORTED: t/t_case_x.v:40:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
40 | 4'b100?: ;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:43:5: All case statements with four-state value as an expression are unsupported with --fourstate
: ... note: In instance 't'
43 | casex (valuex)
| ^~~~~
%Error-UNSUPPORTED: t/t_case_x.v:44:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
44 | 4'b100x: ;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:47:5: All case statements with four-state value as an expression are unsupported with --fourstate
: ... note: In instance 't'
47 | casex (valuex)
| ^~~~~
%Error-UNSUPPORTED: t/t_case_x.v:48:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
48 | 4'b100?: ;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:52:5: All case statements with four-state value as an expression are unsupported with --fourstate
: ... note: In instance 't'
52 | casez (value)
| ^~~~~
%Error-UNSUPPORTED: t/t_case_x.v:53:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
53 | 4'bxxxx: $stop;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:54:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
54 | 4'b100?: ;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:57:5: All case statements with four-state value as an expression are unsupported with --fourstate
: ... note: In instance 't'
57 | casez (valuex)
| ^~~~~
%Error-UNSUPPORTED: t/t_case_x.v:58:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
58 | 4'b1xx?: ;
| ^
%Error-UNSUPPORTED: t/t_case_x.v:59:14: Four-state case items values are unsupported with --fourstate
: ... note: In instance 't'
59 | 4'b100?: ;
| ^
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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('linter')
test.top_filename = "t/t_case_x.v"
test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute()
test.passes()

View File

@ -0,0 +1,16 @@
// 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;
initial begin
static int n = 12;
static integer m = 'x;
static int v = 1 + int'(1 + (n + m));
if (v != 1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute()
test.passes()

View File

@ -0,0 +1,157 @@
// 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
`ifdef VERILATOR
`define IMPURE_ONE ($c(1))
`else
`define IMPURE_ONE (|($random | $random))
`endif
module t;
function integer f(integer x);
if (`IMPURE_ONE) return x;
return 'x;
endfunction
function logic [31:0] g(logic [31:0] x);
if (`IMPURE_ONE) return x;
return 'x;
endfunction
initial begin
if ((f('b1) == f('b1)) !== 1'b1) $stop;
if ((f('b1) == f('b0)) !== 1'b0) $stop;
if ((f('b0) == f('b0)) !== 1'b1) $stop;
if ((f('b0) == f('b1)) !== 1'b0) $stop;
if ((f('b0) == f('bx)) !== 1'bx) $stop;
if ((f('b0) == f('bx)) !== 1'bx) $stop;
if ((f('b1) == f('bx)) !== 1'bx) $stop;
if ((f('bx) == f('bx)) !== 1'bx) $stop;
if ((f('bx) == f('bz)) !== 1'bx) $stop;
if ((f('bz) == f('bz)) !== 1'bx) $stop;
if ((f('bz) == f('b1)) !== 1'bx) $stop;
if ((f('bz) == f('b0)) !== 1'bx) $stop;
if ((f('b1) != f('b1)) !== 1'b0) $stop;
if ((f('b1) != f('b0)) !== 1'b1) $stop;
if ((f('b0) != f('b0)) !== 1'b0) $stop;
if ((f('b0) != f('b1)) !== 1'b1) $stop;
if ((f('b0) != f('bx)) !== 1'bx) $stop;
if ((f('b0) != f('bx)) !== 1'bx) $stop;
if ((f('b1) != f('bx)) !== 1'bx) $stop;
if ((f('bx) != f('bx)) !== 1'bx) $stop;
if ((f('bx) != f('bz)) !== 1'bx) $stop;
if ((f('bz) != f('bz)) !== 1'bx) $stop;
if ((f('bz) != f('b1)) !== 1'bx) $stop;
if ((f('bz) != f('b0)) !== 1'bx) $stop;
if ((f('b1) < f('b1)) !== 1'b0) $stop;
if ((f('b1) < f('b0)) !== 1'b0) $stop;
if ((f('b0) < f('b0)) !== 1'b0) $stop;
if ((f('b0) < f('b1)) !== 1'b1) $stop;
if ((f('b0) < f('bx)) !== 1'bx) $stop;
if ((f('b0) < f('bx)) !== 1'bx) $stop;
if ((f('b1) < f('bx)) !== 1'bx) $stop;
if ((f('bx) < f('bx)) !== 1'bx) $stop;
if ((f('bx) < f('bz)) !== 1'bx) $stop;
if ((f('bz) < f('bz)) !== 1'bx) $stop;
if ((f('bz) < f('b1)) !== 1'bx) $stop;
if ((f('bz) < f('b0)) !== 1'bx) $stop;
if ((f('b1) <= f('b1)) !== 1'b1) $stop;
if ((f('b1) <= f('b0)) !== 1'b0) $stop;
if ((f('b0) <= f('b0)) !== 1'b1) $stop;
if ((f('b0) <= f('b1)) !== 1'b1) $stop;
if ((f('b0) <= f('bx)) !== 1'bx) $stop;
if ((f('b0) <= f('bx)) !== 1'bx) $stop;
if ((f('b1) <= f('bx)) !== 1'bx) $stop;
if ((f('bx) <= f('bx)) !== 1'bx) $stop;
if ((f('bx) <= f('bz)) !== 1'bx) $stop;
if ((f('bz) <= f('bz)) !== 1'bx) $stop;
if ((f('bz) <= f('b1)) !== 1'bx) $stop;
if ((f('bz) <= f('b0)) !== 1'bx) $stop;
if ((f('b1) > f('b1)) !== 1'b0) $stop;
if ((f('b1) > f('b0)) !== 1'b1) $stop;
if ((f('b0) > f('b0)) !== 1'b0) $stop;
if ((f('b0) > f('b1)) !== 1'b0) $stop;
if ((f('b0) > f('bx)) !== 1'bx) $stop;
if ((f('b0) > f('bx)) !== 1'bx) $stop;
if ((f('b1) > f('bx)) !== 1'bx) $stop;
if ((f('bx) > f('bx)) !== 1'bx) $stop;
if ((f('bx) > f('bz)) !== 1'bx) $stop;
if ((f('bz) > f('bz)) !== 1'bx) $stop;
if ((f('bz) > f('b1)) !== 1'bx) $stop;
if ((f('bz) > f('b0)) !== 1'bx) $stop;
if ((f('b1) >= f('b1)) !== 1'b1) $stop;
if ((f('b1) >= f('b0)) !== 1'b1) $stop;
if ((f('b0) >= f('b0)) !== 1'b1) $stop;
if ((f('b0) >= f('b1)) !== 1'b0) $stop;
if ((f('b0) >= f('bx)) !== 1'bx) $stop;
if ((f('b0) >= f('bx)) !== 1'bx) $stop;
if ((f('b1) >= f('bx)) !== 1'bx) $stop;
if ((f('bx) >= f('bx)) !== 1'bx) $stop;
if ((f('bx) >= f('bz)) !== 1'bx) $stop;
if ((f('bz) >= f('bz)) !== 1'bx) $stop;
if ((f('bz) >= f('b1)) !== 1'bx) $stop;
if ((f('bz) >= f('b0)) !== 1'bx) $stop;
// Unsigned
if ((g('b1) < g('b1)) !== 1'b0) $stop;
if ((g('b1) < g('b0)) !== 1'b0) $stop;
if ((g('b0) < g('b0)) !== 1'b0) $stop;
if ((g('b0) < g('b1)) !== 1'b1) $stop;
if ((g('b0) < g('bx)) !== 1'bx) $stop;
if ((g('b0) < g('bx)) !== 1'bx) $stop;
if ((g('b1) < g('bx)) !== 1'bx) $stop;
if ((g('bx) < g('bx)) !== 1'bx) $stop;
if ((g('bx) < g('bz)) !== 1'bx) $stop;
if ((g('bz) < g('bz)) !== 1'bx) $stop;
if ((g('bz) < g('b1)) !== 1'bx) $stop;
if ((g('bz) < g('b0)) !== 1'bx) $stop;
if ((g('b1) <= g('b1)) !== 1'b1) $stop;
if ((g('b1) <= g('b0)) !== 1'b0) $stop;
if ((g('b0) <= g('b0)) !== 1'b1) $stop;
if ((g('b0) <= g('b1)) !== 1'b1) $stop;
if ((g('b0) <= g('bx)) !== 1'bx) $stop;
if ((g('b0) <= g('bx)) !== 1'bx) $stop;
if ((g('b1) <= g('bx)) !== 1'bx) $stop;
if ((g('bx) <= g('bx)) !== 1'bx) $stop;
if ((g('bx) <= g('bz)) !== 1'bx) $stop;
if ((g('bz) <= g('bz)) !== 1'bx) $stop;
if ((g('bz) <= g('b1)) !== 1'bx) $stop;
if ((g('bz) <= g('b0)) !== 1'bx) $stop;
if ((g('b1) > g('b1)) !== 1'b0) $stop;
if ((g('b1) > g('b0)) !== 1'b1) $stop;
if ((g('b0) > g('b0)) !== 1'b0) $stop;
if ((g('b0) > g('b1)) !== 1'b0) $stop;
if ((g('b0) > g('bx)) !== 1'bx) $stop;
if ((g('b0) > g('bx)) !== 1'bx) $stop;
if ((g('b1) > g('bx)) !== 1'bx) $stop;
if ((g('bx) > g('bx)) !== 1'bx) $stop;
if ((g('bx) > g('bz)) !== 1'bx) $stop;
if ((g('bz) > g('bz)) !== 1'bx) $stop;
if ((g('bz) > g('b1)) !== 1'bx) $stop;
if ((g('bz) > g('b0)) !== 1'bx) $stop;
if ((g('b1) >= g('b1)) !== 1'b1) $stop;
if ((g('b1) >= g('b0)) !== 1'b1) $stop;
if ((g('b0) >= g('b0)) !== 1'b1) $stop;
if ((g('b0) >= g('b1)) !== 1'b0) $stop;
if ((g('b0) >= g('bx)) !== 1'bx) $stop;
if ((g('b0) >= g('bx)) !== 1'bx) $stop;
if ((g('b1) >= g('bx)) !== 1'bx) $stop;
if ((g('bx) >= g('bx)) !== 1'bx) $stop;
if ((g('bx) >= g('bz)) !== 1'bx) $stop;
if ((g('bz) >= g('bz)) !== 1'bx) $stop;
if ((g('bz) >= g('b1)) !== 1'bx) $stop;
if ((g('bz) >= g('b0)) !== 1'bx) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,15 @@
1
1
x
1
0
1
x
0
0
x
0
0
z
0
*-* All Finished *-*

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute(expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,29 @@
// 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;
function logic f(logic a);
if (a === 1'b1) $write("1");
else if (a === 1'b0) $write("0");
else if (a === 1'bx) $write("x");
else if (a === 1'bz) $write("z");
else $stop;
$write("\n");
return a;
endfunction
initial begin
if ((
((f(1) ? f(1) : f('z)) && (f('x) ? f(1) : f(0))) ?
(((f(1) || f('z)) && (f('x))) && ((f(0) ? f('x) : f(0)))) :
((f('x) || f(0)) && (f(0) || (f('z) && (f(0) && f('z))))
)) !== 0) begin
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,6 @@
%Error-UNSUPPORTED: t/t_fourstate_complex_pin_unsup.v:13:8: Cells with pins that are not a variable reference or a constant are not supported with --fourstate
: ... note: In instance 't'
13 | y h(x[0]);
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -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.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,15 @@
// 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 y(input x);
initial $write("%d\n", bit'(x));
endmodule
module t;
logic [2:0] x;
y h(x[0]);
initial x = 3;
endmodule

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute()
test.passes()

View File

@ -0,0 +1,43 @@
// 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
`ifdef VERILATOR
`define IMPURE_ONE ($c(1))
`else
`define IMPURE_ONE (|($random | $random))
`endif
module t;
function logic f(logic x);
if (`IMPURE_ONE) return x;
return 'x;
endfunction
initial begin
if ({f(1'b0), f(1'b0)} !== 2'b00) $stop;
if ({f(1'b0), f(1'b1)} !== 2'b01) $stop;
if ({f(1'b0), f(1'bx)} !== 2'b0x) $stop;
if ({f(1'b0), f(1'bz)} !== 2'b0z) $stop;
if ({f(1'b1), f(1'b0)} !== 2'b10) $stop;
if ({f(1'b1), f(1'b1)} !== 2'b11) $stop;
if ({f(1'b1), f(1'bx)} !== 2'b1x) $stop;
if ({f(1'b1), f(1'bz)} !== 2'b1z) $stop;
if ({f(1'bz), f(1'b0)} !== 2'bz0) $stop;
if ({f(1'bz), f(1'b1)} !== 2'bz1) $stop;
if ({f(1'bz), f(1'bx)} !== 2'bzx) $stop;
if ({f(1'bz), f(1'bz)} !== 2'bzz) $stop;
if ({f(1'bx), f(1'b0)} !== 2'bx0) $stop;
if ({f(1'bx), f(1'b1)} !== 2'bx1) $stop;
if ({f(1'bx), f(1'bx)} !== 2'bxx) $stop;
if ({f(1'bx), f(1'bz)} !== 2'bxz) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,17 @@
0
0
1
1
x
1
0
x
1
1
z
1
0
z
0
0
*-* All Finished *-*

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute(expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,44 @@
// 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
`ifdef VERILATOR
`define IMPURE_ONE ($c(1))
`else
`define IMPURE_ONE (|($random | $random))
`endif
module t;
static int calls = 0;
function logic f(logic a);
if (a === 1'b1) $write("1");
else if (a === 1'b0) $write("0");
else if (a === 1'bx) $write("x");
else if (a === 1'bz) $write("z");
else $stop;
$write("\n");
return a;
endfunction
function logic bar();
calls++;
return 'x;
endfunction
initial begin
if ((f(0) ? f(1) : f(0)) !== 0) $stop;
if ((f(1) ? f(1) : f(0)) !== 1) $stop;
if ((f('x) ? f(1) : f(0)) !== 'x) $stop;
if ((f('x) ? f(1) : f(1)) !== 1) $stop;
if ((f('z) ? f(1) : f(0)) !== 'x) $stop;
if ((f('z) ? f(0) : f(0)) !== 0) $stop;
if ((`IMPURE_ONE ? 0 : bar()) !== 0) $stop;
if (calls !== 0) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
%Error-UNSUPPORTED: t/t_delay_var.v:14:8: Continuous assignment delays are unsupported with --fourstate
: ... note: In instance 't'
14 | wire #1.1 d_const = in;
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_delay_var.v:15:8: Continuous assignment delays are unsupported with --fourstate
: ... note: In instance 't'
15 | wire #idly d_int = in;
| ^
%Error-UNSUPPORTED: t/t_delay_var.v:16:8: Continuous assignment delays are unsupported with --fourstate
: ... note: In instance 't'
16 | wire #rdly d_real = in;
| ^
%Error-UNSUPPORTED: t/t_delay_var.v:17:8: Continuous assignment delays are unsupported with --fourstate
: ... note: In instance 't'
17 | wire #PDLY d_param = in;
| ^
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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.top_filename = 't/t_delay_var.v'
test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,21 @@
res: x
res: x
res: 1
res: 1
res: 0
ZERO | ONE | X | Z
ZERO 0 ^ 0 == 0 | 0 ^ 1 == 1 | 0 ^ x == x | 0 ^ z == x |
ONE 1 ^ 0 == 1 | 1 ^ 1 == 0 | 1 ^ x == x | 1 ^ z == x |
X x ^ 0 == x | x ^ 1 == x | x ^ x == x | x ^ z == x |
Z z ^ 0 == x | z ^ 1 == x | z ^ x == x | z ^ z == x |
x wire: 1
z wor: 1
u triand: 1
t wire: 1
x wire: 1
z wor: 1
u triand: 1
t wire: 1
vvv: x
Bye
*-* All Finished *-*

View File

@ -0,0 +1,185 @@
$version Generated by VerilatedVcd $end
$timescale 1ps $end
$scope module t $end
$var wire 1 C clk $end
$var wire 1 D x $end
$var wire 1 L y $end
$var wire 1 F t $end
$var wire 1 H u $end
$var wire 1 J z $end
$var wire 1 N z3 $end
$var wire 4 P z2 [3:0] $end
$var wire 1 R lost $end
$var wire 1 T open $end
$var wire 129 / xx [128:0] $end
$var wire 129 % xy [128:0] $end
$var wire 129 9 xz [128:0] $end
$var wire 1 V one $end
$var wire 1 W vvv $end
$scope module unnamedblk1 $end
$var wire 32 " n [31:0] $end
$var wire 32 # res [31:0] $end
$upscope $end
$upscope $end
$enddefinitions $end
#1
b00000000000000000000000000001100 "
b000000000000000000000000000011xx #
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 %
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 /
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 9
1C
1D
1F
1H
1J
zL
zN
bzzzz P
zR
zT
1V
xW
#5
0C
0D
0F
0H
0J
#10
bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /
b010110011011001111110010010011010000100110110000011101010111001111111101010010100010100000111110010101110101010100101001101011110 9
1C
1D
1F
1H
1J
#15
0C
0D
0F
0H
0J
#20
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 /
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 9
1C
1D
1F
1H
1J
#25
0C
0D
0F
0H
0J
#30
bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /
b010110011011001111110010010011010000100110110000011101010111001111111101010010100010100000111110010101110101010100101001101011110 9
1C
1D
1F
1H
1J
#35
0C
0D
0F
0H
0J
#40
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 /
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 9
1C
1D
1F
1H
1J
#45
0C
0D
0F
0H
0J
#50
bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /
b010110011011001111110010010011010000100110110000011101010111001111111101010010100010100000111110010101110101010100101001101011110 9
1C
1D
1F
1H
1J
#55
0C
0D
0F
0H
0J
#60
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 /
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 9
1C
1D
1F
1H
1J
#65
0C
0D
0F
0H
0J
#70
bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /
b010110011011001111110010010011010000100110110000011101010111001111111101010010100010100000111110010101110101010100101001101011110 9
1C
1D
1F
1H
1J
#75
0C
0D
0F
0H
0J
#80
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 /
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 9
1C
1D
1F
1H
1J
#85
0C
0D
0F
0H
0J
#90
bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /
b010110011011001111110010010011010000100110110000011101010111001111111101010010100010100000111110010101110101010100101001101011110 9
1C
1D
1F
1H
1J
#95
0C
0D
0F
0H
0J
#100
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 /
b101001100100110000001101101100101111011001001111100010101000110000000010101101011101011111000001101010001010101011010110010100001 9
1C
1D
1F
1H
1J
#102

View File

@ -0,0 +1,20 @@
#!/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', '--fourstate', '--trace-vcd', '-Wno-FUTURE'])
test.execute(expect_filename=test.golden_filename)
test.vcd_identical(test.trace_filename, test.golden_filename + '.vcd')
test.passes()

View File

@ -0,0 +1,141 @@
// 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
`define STRINGIFY(x) `"x`"
module t;
bit clk = 1;
wire x;
tri y;
wire t;
triand u;
wor z;
wor z3;
wor [3:0] z2;
wire lost;
wire open = 'z;
assign x = clk;
assign z = x;
assign z = y;
assign u = z;
assign u = x;
assign t = u;
assign t = x;
assign t = y;
wire [128:0] xx;
logic [128:0] xy;
logic [128:0] xz;
bit one = 1;
always #5 clk <= ~clk;
always #10 xz = ~xz;
assign xx = xy;
assign xx = xz;
logic vvv;
// logic example;
task writeFourState(logic a);
if (a === 1'b1) $write("1");
else if (a === 1'b0) $write("0");
else if (a === 1'bx) $write("x");
else if (a === 1'bz) $write("z");
else $stop;
endtask
task print(logic a, logic b);
// $write(" %1d & %1d == %1d |", a, b, a & b);
$write(" ");
writeFourState(a);
$write(" ^ ");
writeFourState(b);
$write(" == ");
writeFourState(a ^ b);
$write(" |");
endtask
initial begin
static int n = integer'('b0z0x1100);
static integer res = 'b01xz | n;
if ((int'('b01xz | n)) === n);
else $stop;
#1;
xy = 442093479423423857275364882039482723489;
xz = 442093479423423857275364882039482723489;
$dumpfile(`STRINGIFY(`TEST_DUMPFILE));
$dumpvars();
$write("res: ");
writeFourState(res[0]);
$write("\n");
$write("res: ");
writeFourState(res[1]);
$write("\n");
$write("res: ");
writeFourState(res[2]);
$write("\n");
$write("res: ");
writeFourState(res[3]);
$write("\n");
$write("res: ");
writeFourState(res[31]);
$write("\n");
$write(" ZERO | ONE | X | Z \n");
$write("ZERO ");
print(0, 0);
print(0, 1);
print(0, 'x);
print(0, 'z);
$write("\nONE ");
print(1, 0);
print(1, 1);
print(1, 'x);
print(1, 'z);
$write("\nX ");
print('x, 0);
print('x, 1);
print('x, 'x);
print('x, 'z);
$write("\nZ ");
print('z, 0);
print('z, 1);
print('z, 'x);
print('z, 'z);
$write("\n");
$write("x wire: ");
writeFourState(x);
$write("\n");
$write("z wor: ");
writeFourState(z);
$write("\n");
$write("u triand: ");
writeFourState(u);
$write("\n");
$write("t wire: ");
writeFourState(t);
$write("\n");
#1;
$write("x wire: ");
writeFourState(x);
$write("\n");
$write("z wor: ");
writeFourState(z);
$write("\n");
$write("u triand: ");
writeFourState(u);
$write("\n");
$write("t wire: ");
writeFourState(t);
$write("\n");
$write("vvv: ");
writeFourState(vvv);
$write("\n");
if ('x & (t !== 0)) $stop;
else if (t != 1) $stop;
else if (~(t & one | t)) $stop;
else if (t | one) $write("Bye\n");
else $stop;
#100;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,17 @@
[out] xxxx
[out] xxxx
[out] xxxx
[out] xxxx
[out] xxxx
[out] 0000
[out] 0001
[out] 0010
[out] 0011
[out] 0100
[out] 0101
[out] 0110
[out] 0111
[out] 1000
[out] 1001
*-* All Finished *-*
[out] 1010

View File

@ -0,0 +1,99 @@
$version Generated by VerilatedVcd $end
$timescale 1ps $end
$scope module tb_counter $end
$var wire 1 " clk $end
$var wire 1 $ rstn $end
$var wire 4 & out [3:0] $end
$scope module c $end
$var wire 1 " clk $end
$var wire 1 $ rstn $end
$var wire 4 & out [3:0] $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
x"
x$
bzzzz &
#20
1$
#40
1"
bxxxx &
#45
0"
#50
1"
#55
0"
#60
1"
#65
0"
#70
1"
#75
0"
#80
1"
#85
0"
0$
#90
1"
b0000 &
#95
0"
1$
#100
1"
b0001 &
#105
0"
#110
1"
b0010 &
#115
0"
#120
1"
b0011 &
#125
0"
#130
1"
b0100 &
#135
0"
#140
1"
b0101 &
#145
0"
#150
1"
b0110 &
#155
0"
#160
1"
b0111 &
#165
0"
#170
1"
b1000 &
#175
0"
#180
1"
b1001 &
#185
0"
#190
1"
b1010 &
#195
0"

View File

@ -0,0 +1,20 @@
#!/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', '--fourstate', '--trace-vcd', '-Wno-FUTURE'])
test.execute(expect_filename=test.golden_filename)
test.vcd_identical(test.trace_filename, test.golden_filename + '.vcd')
test.passes()

View File

@ -0,0 +1,65 @@
// 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
`define STRINGIFY(x) `"x`"
task writeFourState(logic a);
if (a === 1'b1) $write("1");
else if (a === 1'b0) $write("0");
else if (a === 1'bx) $write("x");
else if (a === 1'bz) $write("z");
else $stop;
endtask
module counter (
input clk,
input rstn,
output reg [3:0] out
);
always @(posedge clk) begin
if (!rstn) out <= 0;
else out <= out + 1;
end
endmodule
module tb_counter;
reg clk;
reg rstn;
wire [3:0] out;
counter c (
.clk (clk),
.rstn(rstn),
.out (out)
);
always #5 begin
if (clk) begin
$write("[out] ");
writeFourState(out[3]);
writeFourState(out[2]);
writeFourState(out[1]);
writeFourState(out[0]);
$write("\n");
end
clk = ~clk;
end
initial begin
$dumpfile(`STRINGIFY(`TEST_DUMPFILE));
$dumpvars();
#20 rstn = 1;
#20 clk = 0;
#25 rstn = 1;
#20 rstn = 0;
#10 rstn = 1;
#100;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,25 @@
#!/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('vlt')
test.top_filename = 't/t_dfg_bin_to_one_hot.v'
test.skip("TODO: DFG does not detect one hot pattern created by V3Fourstate")
test.compile(
verilator_flags2=["--fourstate", "-Wno-FUTURE", "--stats", "-fno-table", "-fno-inline"])
test.execute()
test.file_grep(test.stats, r'Optimizations, DFG, BinToOneHot, decoders created\s+(\d+)', 5)
test.passes()

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute()
test.passes()

View File

@ -0,0 +1,18 @@
// 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;
initial begin
if (1 / $c(0) !== 'x) $stop;
if ($c(1) / $c(0) !== 'x) $stop;
if ($c(1) / 0 !== 'x) $stop;
if (1 / 0 !== 'x) $stop;
if (6 / 3 !== 2) $stop;
if ($c(6) / 3 !== 2) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
%Error-UNSUPPORTED: t/t_fourstate_dtype_unsup.v:13:9: Variables of type: 'logic$[$]' are unsupported with --fourstate
: ... note: In instance 't'
13 | logic q [$];
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_fourstate_dtype_unsup.v:14:9: Variables of type: 'logic$[0:12]' are unsupported with --fourstate
: ... note: In instance 't'
14 | logic p [13];
| ^
%Error-UNSUPPORTED: t/t_fourstate_dtype_unsup.v:15:9: Variables of type: 'logic$[integer]' are unsupported with --fourstate
: ... note: In instance 't'
15 | logic a [integer];
| ^
%Error-UNSUPPORTED: t/t_fourstate_dtype_unsup.v:16:7: Variables of type: 'struct{}$unit::bar' are unsupported with --fourstate
: ... note: In instance 't'
16 | bar c;
| ^
%Error: Exiting due to

View File

@ -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.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,17 @@
// 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
typedef struct packed {
logic x;
logic y;
} bar;
module t;
logic q [$];
logic p [13];
logic a [integer];
bar c;
endmodule

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute()
test.passes()

View File

@ -0,0 +1,35 @@
// 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
`ifdef VERILATOR
`define IMPURE_ONE ($c(1))
`else
`define IMPURE_ONE (|($random | $random))
`endif
module t;
function integer f(integer x);
if (`IMPURE_ONE) return x;
return 'x;
endfunction
initial begin
if ((f('b101) ==? f('b101)) !== 1) $stop;
if ((f('b101) ==? f('b10x)) !== 1) $stop;
if ((f('b101) ==? f('b1xz)) !== 1) $stop;
if ((f('b101) ==? f('b10z)) !== 1) $stop;
if ((f('b1z1) ==? f('b10z)) !== 'x) $stop;
if ((f('b1xx) ==? f('b1xx)) !== 1) $stop;
if ((f('b1x1) ==? f('b101)) !== 'x) $stop;
if ((f('b1zz) ==? f('b1xz)) !== 1) $stop;
if ((f('bz01) ==? f('b1zx)) !== 'x) $stop;
if ((f('b001) ==? f('b1zx)) !== 0) $stop;
if ((f('b001) ==? f('b111)) !== 0) $stop;
if ((f('bx00) ==? f('bxz1)) !== 0) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute()
test.passes()

View File

@ -0,0 +1,116 @@
// 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;
bit posedgeTriggered = 0;
bit negedgeTriggered = 0;
bit bothedgeTriggered = 0;
bit changeTriggered = 0;
bit initialized = 0;
logic val = 0;
typedef enum bit [1:0] {
POS,
NEG,
CHANGE,
NONE
} expected_event_t;
task assertTriggered(expected_event_t eventType);
if (eventType == POS) begin
if (!posedgeTriggered) $stop;
if (negedgeTriggered) $stop;
if (!bothedgeTriggered) $stop;
if (!changeTriggered) $stop;
end else if (eventType == NEG) begin
if (posedgeTriggered) $stop;
if (!negedgeTriggered) $stop;
if (!bothedgeTriggered) $stop;
if (!changeTriggered) $stop;
end else if (eventType == CHANGE) begin
if (posedgeTriggered) $stop;
if (negedgeTriggered) $stop;
if (bothedgeTriggered) $stop;
if (!changeTriggered) $stop;
end else if (eventType == NONE) begin
if (posedgeTriggered) $stop;
if (negedgeTriggered) $stop;
if (bothedgeTriggered) $stop;
if (changeTriggered) $stop;
end
posedgeTriggered = 0;
negedgeTriggered = 0;
bothedgeTriggered = 0;
changeTriggered = 0;
endtask
always @(val) begin
if (initialized & changeTriggered) $stop;
changeTriggered = 1;
end
always @(edge val) begin
if (bothedgeTriggered) $stop;
bothedgeTriggered = 1;
end
always @(posedge val) begin
if (posedgeTriggered) $stop;
posedgeTriggered = 1;
end
always @(negedge val) begin
if (negedgeTriggered) $stop;
negedgeTriggered = 1;
end
initial begin
#1 changeTriggered = 0;
initialized = 1;
#1 val = 1;
#1 assertTriggered(POS);
#1 val = 1;
#1 assertTriggered(NONE);
#1 val = 'x;
#1 assertTriggered(NEG);
#1 val = 'z;
#1 assertTriggered(CHANGE);
#1 val = 0;
#1 assertTriggered(NEG);
#1 val = 'z;
#1 assertTriggered(POS);
#1 val = 'z;
#1 assertTriggered(NONE);
#1 val = 'x;
#1 assertTriggered(CHANGE);
#1 val = 'x;
#1 assertTriggered(NONE);
#1 val = 'z;
#1 assertTriggered(CHANGE);
#1 val = 'x;
#1 assertTriggered(CHANGE);
#1 val = 0;
#1 assertTriggered(NEG);
#1 val = 1;
#1 assertTriggered(POS);
#1 val = 0;
#1 assertTriggered(NEG);
#1 val = 'x;
#1 assertTriggered(POS);
#1 val = 1;
#1 assertTriggered(POS);
#1 val = 'z;
#1 assertTriggered(NEG);
#1 val = 1;
#1 assertTriggered(POS);
#1 val = 0;
#1 assertTriggered(NEG);
#1 val = 0;
#1 assertTriggered(NONE);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,10 @@
%Error-UNSUPPORTED: t/t_fourstate_expr_not_handled_unsup.v:10:9: This four-state expression has not been handled
: ... note: In instance 't'
10 | alias y = x;
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_fourstate_expr_not_handled_unsup.v:10:13: This four-state expression has not been handled
: ... note: In instance 't'
10 | alias y = x;
| ^
%Error: Exiting due to

View File

@ -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.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,11 @@
// 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;
wire x;
wire y;
alias y = x;
endmodule

View File

@ -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', '--fourstate', '-Wno-FUTURE'])
test.execute()
test.passes()

View File

@ -0,0 +1,20 @@
// 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
typedef logic unsigned [31:0] uinteger;
module t;
initial begin
static logic unsigned [15:0] foo = 16'bz000000000000001;
static logic signed [15:0] foo2 = 16'bz000000000000001;
static integer bar = integer'(foo);
if (bar !== 32'b0000000000000000z000000000000001) $stop;
bar = uinteger'(foo2);
if (bar !== 32'bzzzzzzzzzzzzzzzzz000000000000001) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,6 @@
0
0
0
1
3
*-* All Finished *-*

View File

@ -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', '--fourstate', '-Wno-FUTURE', '-Wno-CASTFOURSTATE'])
test.execute(expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,25 @@
// 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;
function integer foo(integer a, integer b);
return a + b;
endfunction
initial begin
static logic v = 'x;
$write("%d\n", v);
v = 'z;
$write("%d\n", v);
v = 0;
$write("%d\n", v);
v = 1;
$write("%d\n", v);
$write("%d\n", foo(1, 2));
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,23 @@
%Warning-CASTFOURSTATE: t/t_fourstate_format.v:14:20: Some features are not supported with four-state values - cast it to two-state logic or suppress this warning and it will be done implicitly
: ... note: In instance 't'
14 | $write("%d\n", v);
| ^
... For warning description see https://verilator.org/warn/CASTFOURSTATE?v=latest
... Use "/* verilator lint_off CASTFOURSTATE */" and lint_on around source to disable this message.
%Warning-CASTFOURSTATE: t/t_fourstate_format.v:16:20: Some features are not supported with four-state values - cast it to two-state logic or suppress this warning and it will be done implicitly
: ... note: In instance 't'
16 | $write("%d\n", v);
| ^
%Warning-CASTFOURSTATE: t/t_fourstate_format.v:18:20: Some features are not supported with four-state values - cast it to two-state logic or suppress this warning and it will be done implicitly
: ... note: In instance 't'
18 | $write("%d\n", v);
| ^
%Warning-CASTFOURSTATE: t/t_fourstate_format.v:20:20: Some features are not supported with four-state values - cast it to two-state logic or suppress this warning and it will be done implicitly
: ... note: In instance 't'
20 | $write("%d\n", v);
| ^
%Warning-CASTFOURSTATE: t/t_fourstate_format.v:21:20: Some features are not supported with four-state values - cast it to two-state logic or suppress this warning and it will be done implicitly
: ... note: In instance 't'
21 | $write("%d\n", foo(1, 2));
| ^~~
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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.top_filename = "t/t_fourstate_format.v"
test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,6 @@
%Warning-FUTURE: --fourstate is not supported as is under development
... For warning description see https://verilator.org/warn/FUTURE?v=latest
... Use "/* verilator lint_off FUTURE */" and lint_on around source to disable this message.
%Error-UNSUPPORTED: --fourstate is not supported with fst trace
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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.top_filename = "t_trace_split_cfuncs.v"
test.lint(verilator_flags2=['--fourstate', '--trace-fst'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

0
test_regress/t/t_fourstate_fourstate_unsup.out Executable file → Normal file
View File

View File

@ -0,0 +1,4 @@
0
0
0
1

View File

@ -0,0 +1,20 @@
#!/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=['--fourstate', '-Wno-FUTURE', '-Wno-CASTFOURSTATE'])
test.execute()
test.files_identical(test.obj_dir + "/" + test.name + "_logger.log", test.golden_filename)
test.passes()

View File

@ -0,0 +1,26 @@
// 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
`define STRINGIFY(x) `"x`"
module t;
integer cycles;
initial begin
integer fd;
fd = $fopen({`STRINGIFY(`TEST_OBJ_DIR), "/t_fourstate_fwrite_logger.log"}, "w");
$fwrite(fd, "%0d\n", cycles);
cycles++;
$fwrite(fd, "%0d\n", cycles);
cycles = 0;
$fwrite(fd, "%0d\n", cycles);
cycles++;
$fwrite(fd, "%0d\n", cycles);
$fflush(fd);
$fclose(fd);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,3 @@
%Error-UNSUPPORTED: --fourstate is not supported with hierarchical Verilation
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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('linter')
test.top_filename = 't/t_hier_block_type_param.v'
test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE', '--hierarchical'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,10 @@
%Error-UNSUPPORTED: t/t_inst_sv.v:14:17: supply0/tri0 and supply1/tri1 are not supported with --fourstate
: ... note: In instance 't'
14 | supply0 [1:0] low;
| ^~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_inst_sv.v:15:17: supply0/tri0 and supply1/tri1 are not supported with --fourstate
: ... note: In instance 't'
15 | supply1 [1:0] high;
| ^~~~
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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('linter')
test.top_filename = 't/t_inst_sv.v'
test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,10 @@
%Error-UNSUPPORTED: t/t_lint_unused_iface.v:10:23: modports are not supported with --fourstate
: ... note: In instance 't.sub'
10 | modport slave(input signal);
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_lint_unused_iface.v:12:25: modports are not supported with --fourstate
: ... note: In instance 't.sub'
12 | modport master(output signal);
| ^~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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('linter')
test.top_filename = 't/t_lint_unused_iface.v'
test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE', '--Wall', '-Wno-DECLFILENAME'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

Some files were not shown because too many files have changed in this diff Show More