diff --git a/docs/guide/warnings.rst b/docs/guide/warnings.rst index ce3a0d58c..2a6b68540 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -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 diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index 0e3706725..6a34318b3 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -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(newval), static_cast(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(newval), static_cast(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(newval), static_cast(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 newvals; + const size_t wordCount = static_cast(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 diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index de1b0eeca..25281126d 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -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); }; diff --git a/include/verilated_saif_c.cpp b/include/verilated_saif_c.cpp index 18f579ec2..a4cb08852 100644 --- a/include/verilated_saif_c.cpp +++ b/include/verilated_saif_c.cpp @@ -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 VL_ATTR_ALWINLINE void emitData(uint64_t time, DataType newval, uint32_t bits) { @@ -117,7 +121,24 @@ public: updateLastTime(time); } + template + VL_ATTR_ALWINLINE void emitFourstateData(uint64_t time, DataType newval, DataType newvalXZ, + uint32_t bits) { + static_assert(std::is_integral::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(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(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(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(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(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(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(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 diff --git a/include/verilated_saif_c.h b/include/verilated_saif_c.h index 63cc717c0..96e04a34e 100644 --- a/include/verilated_saif_c.h +++ b/include/verilated_saif_c.h @@ -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); }; diff --git a/include/verilated_trace.h b/include/verilated_trace.h index de8f89946..15ecfbed6 100644 --- a/include/verilated_trace.h +++ b/include/verilated_trace.h @@ -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(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(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(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(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(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); } diff --git a/include/verilated_trace_imp.h b/include/verilated_trace_imp.h index 0843f1843..10d29f48c 100644 --- a/include/verilated_trace_imp.h +++ b/include/verilated_trace_imp.h @@ -555,6 +555,16 @@ void VerilatedTraceBuffer::fullBit(uint32_t* oldp, CData newval) { emitBit(code, newval); } +template <> +void VerilatedTraceBuffer::fullLogic(uint32_t* oldp, CData newval, CData newvalXZ) { + const uint32_t code = oldp - m_sigs_oldvalp; + CData* oldcp = reinterpret_cast(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::fullEvent(uint32_t* oldp, const VlEventBase* newvalp) { const uint32_t code = oldp - m_sigs_oldvalp; @@ -577,6 +587,17 @@ void VerilatedTraceBuffer::fullCData(uint32_t* oldp, CData newval, int emitCData(code, newval, bits); } +template <> +void VerilatedTraceBuffer::fullFourstateCData(uint32_t* oldp, CData newval, + CData newvalXZ, int bits) { + const uint32_t code = oldp - m_sigs_oldvalp; + CData* oldcp = reinterpret_cast(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::fullSData(uint32_t* oldp, SData newval, int bits) { const uint32_t code = oldp - m_sigs_oldvalp; @@ -585,6 +606,17 @@ void VerilatedTraceBuffer::fullSData(uint32_t* oldp, SData newval, int emitSData(code, newval, bits); } +template <> +void VerilatedTraceBuffer::fullFourstateSData(uint32_t* oldp, SData newval, + SData newvalXZ, int bits) { + const uint32_t code = oldp - m_sigs_oldvalp; + SData* oldcp = reinterpret_cast(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::fullIData(uint32_t* oldp, IData newval, int bits) { const uint32_t code = oldp - m_sigs_oldvalp; @@ -593,6 +625,17 @@ void VerilatedTraceBuffer::fullIData(uint32_t* oldp, IData newval, int emitIData(code, newval, bits); } +template <> +void VerilatedTraceBuffer::fullFourstateIData(uint32_t* oldp, IData newval, + IData newvalXZ, int bits) { + const uint32_t code = oldp - m_sigs_oldvalp; + IData* oldcp = reinterpret_cast(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::fullQData(uint32_t* oldp, QData newval, int bits) { const uint32_t code = oldp - m_sigs_oldvalp; @@ -602,13 +645,37 @@ void VerilatedTraceBuffer::fullQData(uint32_t* oldp, QData newval, int } template <> -void VerilatedTraceBuffer::fullWData(uint32_t* oldp, WDataInP newval, int bits) { +void VerilatedTraceBuffer::fullFourstateQData(uint32_t* oldp, QData newval, + QData newvalXZ, int bits) { + const uint32_t code = oldp - m_sigs_oldvalp; + QData* oldcp = reinterpret_cast(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::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::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::fullDouble(uint32_t* oldp, double newval) { const uint32_t code = oldp - m_sigs_oldvalp; diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index c0ca9281b..368177740 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -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(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(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(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(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(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(value >> i) & 1)); + } + } + finishLine(code, wp); +} + VL_ATTR_ALWINLINE void VerilatedVcdBuffer::emitDouble(uint32_t code, double newval) { char* wp = m_writep; diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index 931035bed..cc2eef1ae 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -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); }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 90a0d3ab4..38401432b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index f5a728063..5053ab171 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -282,6 +282,7 @@ RAW_OBJS_PCH_ASTNOMT = \ V3Force.o \ V3FsmDetect.o \ V3Fork.o \ + V3Fourstate.o \ V3Gate.o \ V3HierBlock.o \ V3Inline.o \ diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index e8f065861..f687b06fe 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -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; } diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 3c25a9992..d07d34eb2 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -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; } diff --git a/src/V3AstNodeStmt.h b/src/V3AstNodeStmt.h index 25de3ad08..e7b2fd60b 100644 --- a/src/V3AstNodeStmt.h +++ b/src/V3AstNodeStmt.h @@ -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; } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 203fef45a..50907a1c1 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -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); diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 411ec57eb..f88020d43 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -489,8 +489,12 @@ class DeadVisitor final : public VNVisitor { retry = false; for (std::vector::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); diff --git a/src/V3EmitCFunc.cpp b/src/V3EmitCFunc.cpp index 11f2ac14a..6e6c175c9 100644 --- a/src/V3EmitCFunc.cpp +++ b/src/V3EmitCFunc.cpp @@ -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 { diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index 0f968d486..1cc2a912f 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -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) { diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index db0798e38..7a412aac4 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -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 { diff --git a/src/V3Error.h b/src/V3Error.h index 01e7d6447..2fcdcf207 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -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 diff --git a/src/V3Fourstate.cpp b/src/V3Fourstate.cpp new file mode 100644 index 000000000..fabfa1f26 --- /dev/null +++ b/src/V3Fourstate.cpp @@ -0,0 +1,2412 @@ +// -*- 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 +// +//************************************************************************* +// +// - Splits four-state variables into two two-state variables +// - Handles wire conflicts +// +//************************************************************************* + +#include "V3PchAstNoMT.h" + +#include "V3Fourstate.h" + +#include "V3UniqueNames.h" + +#include +#include +#include +#include + +VL_DEFINE_DEBUG_FUNCTIONS; + +/* TODOs: + * - Rest of operators + * - Statements - cases etc. + * - split asswignw into multiple statements + * - four-states printing + */ + +#define VALUE_SUFFIX "" // Needs to be empty so C++ api won't change +#define XZ_SUFFIX "__Vxz" + +namespace { +struct FourstatePair final { + AstNodeExpr* valuep; + AstNodeExpr* xzp; +}; + +enum LogicType : char { + UNINITIALIZED = 0, // Logic type has not been evaluated + TWO_STATE, // Two-state expression + TWO_STATE_HARD, // Expression is guaranteed by user that it won't be a four-state (propagator + // may not change it) + TWO_STATE_WITH_FOUR_STATE_IN_SUBTREE, // Two-state expression with four-state expression in + // its subtree - this is necessary since some AstNodes + // (e.g.: AstCastWrap or AstSel) may contain four-state + // expression as a child but itself be a two-state. When + // this occurs we need to know that for the sake of + // short-circuiting (because we use precalculation + // statements we need to know that we cannot put them + // before current expression unconditionally) + FOUR_STATE, // Four-state expression +}; + +static void setLogicType(AstNodeExpr* const exprp, const LogicType logic) { + exprp->user4(static_cast(logic)); +} + +static LogicType getLogicType(const AstNodeExpr* const exprp) { + return static_cast(exprp->user4()); +} + +static bool isTwostateHard(const AstNodeExpr* const exprp) { + return getLogicType(exprp) == TWO_STATE_HARD; +} + +static void setTwostate(AstNodeExpr* const exprp, bool hard = true) { + setLogicType(exprp, hard ? TWO_STATE_HARD : TWO_STATE); +} + +static void setFourstate(AstNodeExpr* const exprp, bool fourstate = true, + bool fourstateInSubTree = false) { + if (isTwostateHard(exprp)) return; + setLogicType(exprp, fourstate ? FOUR_STATE + : (fourstateInSubTree ? TWO_STATE_WITH_FOUR_STATE_IN_SUBTREE + : TWO_STATE)); +} + +static bool isFourstate(const AstNodeExpr* const exprp) { + const LogicType logic = getLogicType(exprp); + UASSERT_OBJ(logic != UNINITIALIZED, exprp, + "Logic type of expression: " << exprp->typeName() << " is unevaluated"); + return logic == FOUR_STATE; +} + +// Return true when the expression is two-state and has four-state expression in sub-tree +static bool hasFourstateInSubtree(const AstNodeExpr* const exprp) { + return getLogicType(exprp) == TWO_STATE_WITH_FOUR_STATE_IN_SUBTREE; +} + +template +struct ReducerTrait final : std::false_type {}; +template +struct ReducerTrait< + T, std::enable_if_t()(std::declval(), + std::declval())), + FourstatePair>::value>> + final : std::true_type {}; + +static bool isStaticallyGte(const V3Number& msb, const AstNodeExpr* const exprp) { + FileLine* const flp = exprp->fileline(); + const int exprpWidth = exprp->width(); + if (V3Number{flp, 1, 0} + .opGte(msb, V3Number{flp, exprpWidth, 0}.opSub( + V3Number{flp, exprpWidth, 0}.opShiftL( + V3Number{flp, exprpWidth, 1}, + V3Number{flp, exprpWidth, static_cast(exprpWidth)}), + V3Number{flp, exprpWidth, 1})) + .isEqOne()) { + return true; + } + if (const AstConst* const constp = VN_CAST(exprp, Const)) { + if (V3Number{flp, 1, 0}.opGte(msb, constp->num()).isEqOne()) return true; + } + return false; +} +static bool isStaticallyNGte(const V3Number& msb, const AstNodeExpr* const exprp) { + FileLine* const flp = exprp->fileline(); + if (const AstConst* const constp = VN_CAST(exprp, Const)) { + return constp->num().isAnyXZ() || V3Number{flp, 1, 0}.opLt(msb, constp->num()).isNeqZero(); + } + return false; +} +static bool needsSplitting(const AstNodeDType* const dtypep) { + if (const AstBasicDType* const basicp = VN_CAST(dtypep->skipRefp(), BasicDType)) { + return basicp->isFourstate(); + } + return false; +} + +class FTaskPortsHelper final { + std::vector + m_currentFTaskRefPortps; // Ports of FTask in order so we can connect AstArgs to them + std::map + m_currentFTaskRefPortpsNamesToVarps; // Ports names to their Vars so we can handle + // named arguments + +public: + explicit FTaskPortsHelper(const AstNodeFTask* const ftaskp) { + // TODO: Add caching + UASSERT_OBJ(m_currentFTaskRefPortps.empty(), ftaskp, + "Tried to build a port map while another exists"); + UASSERT_OBJ(m_currentFTaskRefPortpsNamesToVarps.empty(), ftaskp, + "Tried to build a port map while another exists"); + for (AstNode* stmtp = ftaskp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (AstVar* const varp = VN_CAST(stmtp, Var)) { + if (varp->direction().isAny() + && !(varp->fourstateComplementp() || varp->isFourstateComplement())) { + m_currentFTaskRefPortps.push_back(varp); + m_currentFTaskRefPortpsNamesToVarps[varp->name()] = varp; + } + } + } + } + + AstVar* getArgPortVar(const std::string& name, const size_t idx) const { + return name.empty() ? m_currentFTaskRefPortps.at(idx) + : m_currentFTaskRefPortpsNamesToVarps.at(name); + } + AstVar* lastp() const { + return m_currentFTaskRefPortps.empty() ? nullptr : m_currentFTaskRefPortps.back(); + } +}; +} // namespace + +// Propagates the logic type (two or four-state) on AstNodeExpr +// Needed as V3Width not always gives a correct logic type +class FourstateLogicTypePropagator final : public VNVisitor { + bool m_fourstateInSubtree + = false; // Whether a four-state expression is present in a sub-tree of an expression + + void iterateChildrenSeparately(AstNode* const nodep) { + auto foreach = [this](AstNode* nodep) { + bool fourstateInSubtree = false; + for (; nodep; nodep = nodep->nextp()) { + m_fourstateInSubtree = false; + iterate(nodep); + fourstateInSubtree |= m_fourstateInSubtree; + } + return fourstateInSubtree; + }; + // Cast to char so, there is no warnings + m_fourstateInSubtree = static_cast(static_cast(foreach(nodep->op1p())) + | static_cast(foreach(nodep->op2p())) + | static_cast(foreach(nodep->op3p())) + | static_cast(foreach(nodep->op4p()))); + } + + void visit(AstConst* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, nodep->num().isAnyXZ(), m_fourstateInSubtree); + m_fourstateInSubtree |= isFourstate(nodep); + } + + void visit(AstNodeVarRef* const nodep) override { + setFourstate(nodep, needsSplitting(nodep->varp()->dtypep()), m_fourstateInSubtree); + m_fourstateInSubtree |= isFourstate(nodep); + } + + void visit(AstNodeFTaskRef* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, + nodep->taskp()->fvarp() && needsSplitting(nodep->taskp()->fvarp()->dtypep()), + m_fourstateInSubtree); + m_fourstateInSubtree |= isFourstate(nodep); + } + + void visit(AstNodeUniop* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, isFourstate(nodep->lhsp()), m_fourstateInSubtree); + } + + void visit(AstCastWrap* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, needsSplitting(nodep->dtypep()), m_fourstateInSubtree); + m_fourstateInSubtree |= isFourstate(nodep); + } + + void visit(AstNodeBiop* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, isFourstate(nodep->lhsp()) || isFourstate(nodep->rhsp()), + m_fourstateInSubtree); + } + + void visit(AstEqCase* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstNeqCase* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstDiv* nodep) override { + iterateChildrenSeparately(nodep); + if (AstConst* const constp = VN_CAST(nodep->rhsp(), Const)) { + setFourstate(nodep, + isFourstate(nodep->lhsp()) || constp->num().isEqZero() + || constp->num().isAnyXZ(), + m_fourstateInSubtree); + } else { + setFourstate(nodep, true, m_fourstateInSubtree); + } + m_fourstateInSubtree |= isFourstate(nodep); + } + + void visit(AstNodeTriop* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, + isFourstate(nodep->lhsp()) || isFourstate(nodep->rhsp()) + || isFourstate(nodep->thsp()), + m_fourstateInSubtree); + } + + void visit(AstCReset* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstSFormatArg* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, isFourstate(nodep->exprp()), m_fourstateInSubtree); + } + + void visit(AstSel* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, isFourstate(nodep->fromp()), m_fourstateInSubtree); + } + + void visit(AstCExprUser* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstRedOr* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, isFourstate(nodep->lhsp()), m_fourstateInSubtree); + } + + void visit(AstTime* const nodep) override { + iterateChildrenSeparately(nodep); + // Time is actually a fourstate but we never put `x` or `z` there + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstScopeName* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstClassOrPackageRef* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + // void visit(AstCMethodHard* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, false, m_fourstateInSubtree); + // } + + void visit(AstCExpr* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstRand* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + // void visit(AstRandRNG* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, false, m_fourstateInSubtree); + // } + + void visit(AstMemberSel* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, needsSplitting(nodep->varp()->dtypep()), m_fourstateInSubtree); + } + + void visit(AstSFormatF* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstStructSel* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, isFourstate(nodep->fromp()), m_fourstateInSubtree); + } + + // void visit(AstExprStmt* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, isFourstate(nodep->resultp()), m_fourstateInSubtree); + // } + + // void visit(AstConsPackMember* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, isFourstate(nodep->rhsp()), m_fourstateInSubtree); + // } + + void visit(AstFOpen* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + // void visit(AstFOpenMcd* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, false, m_fourstateInSubtree); + // } + + // void visit(AstLambdaArgRef* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, needsSplitting(nodep->dtypep()), m_fourstateInSubtree); + // } + + // void visit(AstTestPlusArgs* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, false, m_fourstateInSubtree); + // } + + // void visit(AstValuePlusArgs* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, false, m_fourstateInSubtree); + // } + + // void visit(AstCvtArrayToPacked* const nodep) override { + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, needsSplitting(nodep->fromp()->dtypep()), m_fourstateInSubtree); + // } + + void visit(AstSScanF* const nodep) override { + iterateChildrenSeparately(nodep); + setFourstate(nodep, false, m_fourstateInSubtree); + } + + // void visit(AstFScanF* const nodep) override { // We want to get UNSUPPORTED error right now + // iterateChildrenSeparately(nodep); + // setFourstate(nodep, false, m_fourstateInSubtree); + // } + + void visit(AstFourstateExpr* const nodep) override { + iterateChildrenSeparately(nodep); + // The `false` is a lie but this visitor is here just for debug purposes so, after + // FourstateVisitor we can check whether any four-state expression has not been handled. + // This lie is safe since before V3Fourstate no AstFourstateExpr exists + setFourstate(nodep, false, m_fourstateInSubtree); + } + + void visit(AstNodeExpr* const nodep) override { + iterateChildrenSeparately(nodep); + if (AstBasicDType* const basicp = VN_CAST(nodep->dtypep()->skipRefOrNullp(), BasicDType)) { + if (basicp->keyword().isIntNumeric()) { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: Operator " + << nodep->typeName() + << " not supported in the four-state mode"); + } + } + setFourstate(nodep, false, m_fourstateInSubtree); // Set an arbitrary logic type + } + + void visit(AstNode* nodep) override { + VL_RESTORER(m_fourstateInSubtree); + iterateChildrenSeparately(nodep); + } + +public: + FourstateLogicTypePropagator(AstNode* const nodep) { iterate(nodep); } + ~FourstateLogicTypePropagator() override = default; +}; + +// Splits AstVar of four-state type into two two-states +// Transforms four-state logic expressions into two-states +// Handles AssignW conflict resolution +class FourstateVisitor final : public VNVisitor { + const VNUser1InUse m_user1InUse; + const VNUser2InUse m_user2InUse; + const VNUser3InUse m_user3InUse; + const VNUser4InUse m_user4InUse; + // Node status + // AstVar::user1p -> AstVar*. Where is value part of splitted variable - xz + // AstNodeExpr::user1p -> AstNodeExpr*. Expression evaluating value component + // AstNodeExpr::user2p -> AstNodeExpr*. Expression evaluating xz component + // AstSel::user3 -> bool. Whether it has been handled + // AstNodeFTaskRef::user3 -> bool. Whether it has been handled + // AstNodeExpr::user4 -> LogicType. Expression logic type (whether it is four + // or two state) + + static void setValuePartVarp(AstVar* const varp, AstVar* const valuep) { + varp->user1p(valuep); + } + static AstVar* getValuePartVarp(AstVar* const varp) { return VN_AS(varp->user1p(), Var); } + static void setSelpHandled(AstSel* const selp) { selp->user3(1); } + static bool isSelpHandled(AstSel* const selp) { return selp->user3(); } + static void setFTaskRefHandled(AstNodeFTaskRef* const ftaskRefp) { ftaskRefp->user3(1); } + static bool isFTaskRefHandled(AstNodeFTaskRef* const ftaskRefp) { return ftaskRefp->user3(); } + static void setExprValuep(AstNodeExpr* const fourstateExprp, AstNode* const valuep) { + fourstateExprp->user1p(valuep); + } + static AstNodeExpr* getExprValuep(const AstNodeExpr* const fourstateExprp) { + return VN_AS(fourstateExprp->user1p(), NodeExpr); + } + static void setExprXZp(AstNodeExpr* const fourstateExprp, AstNode* const xzp) { + fourstateExprp->user2p(xzp); + } + static AstNodeExpr* getExprXZp(const AstNodeExpr* const fourstateExprp) { + return VN_AS(fourstateExprp->user2p(), NodeExpr); + } + + V3UniqueNames m_tmpNames; // Unique names generator for temporary variables + + AstNode* m_currentTmpSpotp = nullptr; // Node after which put AstVar* for temporary variable + bool m_tmpFuncLocal + = false; // Whether temporary variables shall be created as function locals + AstNodeStmt* m_currentStmtp = nullptr; // Current statement + std::vector m_varpsToRemove; // Vars to unlink and remove in destructor + + std::vector m_ftaskPortHelpers; // Cache of FTaskPortsHelpers + + // array - whether numeric + // map - width + std::array>, 2> + m_tmpUnusedVarps; // Existing not in use temporary variables + std::vector m_tmpVarpsInUse; // Temporary variables that are being currently used + + // Original AstVar* and pair of assignments + using NetToAssignwps + = std::map>>; + NetToAssignwps m_assignWToTrior; // Map from variables to their AssingWs + NetToAssignwps m_assignWToTriand; // Map from variables to their AssingWs + NetToAssignwps m_assignWToWire; // Map from variables to their AssingWs + + static FourstatePair triReducer(const FourstatePair& a, const FourstatePair& b) { + FileLine* const flp = a.valuep->fileline(); + FourstatePair result; + { + // a.value | b.value + result.valuep = new AstOr{flp, a.valuep, b.valuep}; + } + { + // (a.value & a.xz) | (b.value & b.xz) | (a.xz & b.xz) | (a.value & ~b.value & ~b.xz) | + // (b.value & ~a.value & ~a.xz) + result.xzp = new AstOr{ + flp, + new AstOr{flp, + new AstOr{flp, new AstAnd{flp, a.valuep->cloneTree(false), a.xzp}, + new AstAnd{flp, b.valuep->cloneTree(false), b.xzp}}, + new AstAnd{flp, a.xzp->cloneTree(false), b.xzp->cloneTree(false)}}, + new AstOr{flp, + new AstAnd{flp, + new AstAnd{flp, a.valuep->cloneTree(false), + new AstNot{flp, b.valuep->cloneTree(false)}}, + new AstNot{flp, b.xzp->cloneTree(false)}}, + new AstAnd{flp, + new AstAnd{flp, b.valuep->cloneTree(false), + new AstNot{flp, a.valuep->cloneTree(false)}}, + new AstNot{flp, a.xzp->cloneTree(false)}}}}; + } + return result; + } + static FourstatePair triandReducer(const FourstatePair& a, const FourstatePair& b) { + FileLine* const flp = a.valuep->fileline(); + FourstatePair result; + { + // (a.value & b.xz) | (b.value & a.xz) | (a.value & b.value) + result.valuep = new AstOr{ + flp, + new AstOr{flp, new AstAnd{flp, a.valuep, b.xzp}, new AstAnd{flp, b.valuep, a.xzp}}, + new AstAnd{flp, a.valuep->cloneTree(false), b.valuep->cloneTree(false)}}; + } + { + // (a.xz & b.xz) | (a.value & b.value & a.xz) | (a.value & b.value & b.xz) + result.xzp = new AstOr{ + flp, + new AstOr{flp, new AstAnd{flp, a.xzp->cloneTree(false), b.xzp->cloneTree(false)}, + new AstAnd{flp, + new AstAnd{flp, a.valuep->cloneTree(false), + b.valuep->cloneTree(false)}, + b.xzp->cloneTree(false)}}, + new AstAnd{flp, + new AstAnd{flp, a.valuep->cloneTree(false), b.valuep->cloneTree(false)}, + b.xzp->cloneTree(false)}}; + } + return result; + } + static FourstatePair triorReducer(const FourstatePair& a, const FourstatePair& b) { + FileLine* const flp = a.valuep->fileline(); + FourstatePair result; + { + // a.value | b.value + result.valuep = new AstOr{flp, a.valuep, b.valuep}; + } + { + // (a.value | b.xz) & (b.value | a.xz) & (a.xz | ~a.value) & (b.xz | ~b.value) + result.xzp + = new AstAnd{flp, + new AstAnd{flp, new AstOr{flp, a.valuep->cloneTree(false), b.xzp}, + new AstOr{flp, b.valuep->cloneTree(false), a.xzp}}, + new AstAnd{flp, + new AstOr{flp, a.xzp->cloneTree(false), + new AstNot{flp, a.valuep->cloneTree(false)}}, + new AstOr{flp, b.xzp->cloneTree(false), + new AstNot{flp, b.valuep->cloneTree(false)}}}}; + } + return result; + } + + template + static FourstatePair buildTree(std::vector exprps, Reducer_T&& reducer) { + static_assert(ReducerTrait::value, "Reducer_T shall fullfill reducer trait"); + while (exprps.size() > 1) { + const size_t halfSize = exprps.size() / 2; + for (size_t i = 0; i < halfSize; ++i) { + exprps[i] = reducer(exprps[i], exprps.back()); + exprps.pop_back(); + } + } + return exprps[0]; + } + + template + static void triorTriandReduce(const NetToAssignwps& assignWs, Reducer_T&& reducer) { + for (const auto& pair : assignWs) { + const auto& assignps = pair.second; + if (assignps.size() < 2) continue; + std::vector exprps; + exprps.reserve(assignps.size()); + for (const auto& assignp : assignps) { + exprps.push_back({assignp.first->rhsp()->unlinkFrBack(), + assignp.second->rhsp()->unlinkFrBack()}); + const AstVarXRef* xarefp = nullptr; + if (exprps.back().valuep->exists([&xarefp](const AstVarXRef* const refp) { + xarefp = refp; + return true; + })) { + // The issue is when hierarchical reference is being moved to another module. + // Then it shall be fixed + xarefp->v3warn( + E_UNSUPPORTED, + "Hierarchical references are unsupported in assigns with --fourstate"); + } + } + FourstatePair result = buildTree(std::move(exprps), reducer); + assignps[0].first->rhsp(result.valuep); + assignps[0].second->rhsp(result.xzp); + for (size_t i = 1; i < assignps.size(); ++i) { + assignps[i].first->unlinkFrBack()->deleteTree(); + assignps[i].second->unlinkFrBack()->deleteTree(); + } + } + } + + static AstConst* createZeroOrOnesp(const AstNodeExpr* const exprp, const bool ones = false) { + AstConst* const resultp + = new AstConst{exprp->fileline(), AstConst::WidthedValue{}, exprp->width(), 0}; + resultp->dtypeSetBitUnsized(exprp->width(), exprp->widthMin(), exprp->dtypep()->numeric()); + if (ones) resultp->num().setAllBits1(); + setFourstate(resultp, false); + return resultp; + } + + // {whether supported, whether four state} - second is needed for the recursion + static std::pair isDTypepSupported(const AstNodeDType* const dtypep) { + if (const AstBasicDType* const basicp = VN_CAST(dtypep, BasicDType)) { + return {true, basicp->isFourstate()}; + } + if (const AstNodeUOrStructDType* const containerDTypep + = VN_CAST(dtypep, NodeUOrStructDType)) { + return {!containerDTypep->isFourstate(), containerDTypep->isFourstate()}; + } + if (const AstSampleQueueDType* const containerDTypep = VN_CAST(dtypep, SampleQueueDType)) { + std::pair subDtype + = isDTypepSupported(containerDTypep->subDTypep()->skipRefp()); + return {subDtype.first && !subDtype.second, false}; + } + if (const AstQueueDType* const containerDTypep = VN_CAST(dtypep, QueueDType)) { + std::pair subDtype + = isDTypepSupported(containerDTypep->subDTypep()->skipRefp()); + return {subDtype.first && !subDtype.second, false}; + } + if (const AstAssocArrayDType* const containerDTypep = VN_CAST(dtypep, AssocArrayDType)) { + std::pair subDtype + = isDTypepSupported(containerDTypep->subDTypep()->skipRefp()); + return {subDtype.first && !subDtype.second, false}; + } + if (const AstUnpackArrayDType* const containerDTypep = VN_CAST(dtypep, UnpackArrayDType)) { + std::pair subDtype + = isDTypepSupported(containerDTypep->subDTypep()->skipRefp()); + return {subDtype.first && !subDtype.second, false}; + } + if (const AstPackArrayDType* const containerDTypep = VN_CAST(dtypep, PackArrayDType)) { + std::pair subDtype + = isDTypepSupported(containerDTypep->subDTypep()->skipRefp()); + return {subDtype.first && !subDtype.second, false}; + } + return {true, false}; + } + + void assignWConflictResolution(AstVar* const varp, AstAssignW* const assignwValuep, + AstAssignW* const assignwXzp) { + // Assignments to different things are unsupported + switch (varp->varType()) { + case VVarType::TRIOR: + m_assignWToTrior[varp].emplace_back(assignwValuep, assignwXzp); + break; + case VVarType::TRIAND: + m_assignWToTriand[varp].emplace_back(assignwValuep, assignwXzp); + break; + case VVarType::VAR: + case VVarType::TRIWIRE: + case VVarType::PORT: // The issue with ports is that we lose information about the wire + // type (tri/triand/trior) + case VVarType::WIRE: m_assignWToWire[varp].emplace_back(assignwValuep, assignwXzp); break; + case VVarType::SUPPLY0: + case VVarType::SUPPLY1: + case VVarType::TRI0: + case VVarType::TRI1: + varp->v3warn(E_UNSUPPORTED, + "supply0/tri0 and supply1/tri1 are not supported with --fourstate"); + break; + default: // LCOV_EXCL_LINE + assignwValuep->v3fatalSrc( + "Unexpected variable type on lhs of assign: " << varp->varType().ascii()); + break; + } + } + + class StatementPlaceHolder final { + FourstateVisitor& m_visitor; + AstNodeStmt* const m_prevStmtp; + AstNodeStmt* const m_stmtp; + + public: + explicit StatementPlaceHolder(FourstateVisitor& visitor, FileLine* const flp) + : m_visitor{visitor} + , m_prevStmtp{m_visitor.m_currentStmtp} + , m_stmtp{new AstStmtExpr{flp, new AstConst{flp, 0}}} { + m_visitor.m_currentStmtp = m_stmtp; + } + ~StatementPlaceHolder() { + UASSERT_OBJ(m_stmtp->backp(), m_stmtp, + "Placeholder statement never used - maybe it is unnecessary?"); + m_stmtp->unlinkFrBack()->deleteTree(); + m_visitor.m_currentStmtp = m_prevStmtp; + } + AstNodeStmt* stmtp() const { return m_stmtp; } + }; + + struct TmpVarsReleaser final { + FourstateVisitor& m_visitor; + const size_t m_tmpVarpsInUseLen; + explicit TmpVarsReleaser(FourstateVisitor& visitor) + : m_visitor{visitor} + , m_tmpVarpsInUseLen{m_visitor.m_tmpVarpsInUse.size()} {} + ~TmpVarsReleaser() { + UASSERT(m_tmpVarpsInUseLen <= m_visitor.m_tmpVarpsInUse.size(), + "There is less used tmp variables than before"); + for (size_t i = m_tmpVarpsInUseLen; i < m_visitor.m_tmpVarpsInUse.size(); ++i) { + AstVar* const varp = m_visitor.m_tmpVarpsInUse[i]; + m_visitor + .m_tmpUnusedVarps[varp->dtypep()->numeric().isSigned() ? 1 : 0][varp->width()] + .push_back(varp); + } + m_visitor.m_tmpVarpsInUse.resize(m_tmpVarpsInUseLen); + } + }; + + // Takes expression or AstVar and creates a new temporary variable + AstVar* createTmp(AstNode* const nodep) { + UASSERT_OBJ( + VN_IS(nodep, NodeExpr) || VN_IS(nodep, Var), nodep, + "This function shall only be called on expressions or variables, but was called on: " + << nodep); + UASSERT_OBJ(m_currentTmpSpotp, nodep, "No where to place tmp variable"); + AstNodeDType* const dtypep = nodep->dtypep(); + auto& pool = m_tmpUnusedVarps[dtypep->numeric().isSigned() ? 1 : 0]; + if (!pool[dtypep->width()].empty()) { + AstVar* varp = pool[dtypep->width()].back(); + pool[dtypep->width()].pop_back(); + return varp; + } + AstVar* const varp = new AstVar{nodep->fileline(), VVarType::STMTTEMP, + m_tmpNames.get(nodep), VFlagBitPacked{}, nodep->width()}; + m_currentTmpSpotp->addHereThisAsNext(varp); + varp->funcLocal(m_tmpFuncLocal); + varp->noSubst(true); + m_tmpVarpsInUse.push_back(varp); + return varp; + } + + void splitVar(AstVar* const varp) { + UASSERT_OBJ(needsSplitting(varp->dtypep()), varp, + "Split shall be called only on four-state variables"); + if (getValuePartVarp(varp)) return; + m_varpsToRemove.push_back(varp); + if (AstNodeFTask* const ftaskp = VN_CAST(varp->backp(), NodeFTask)) { + if (ftaskp->fvarp() == varp) { + AstVar* const portEndp = getFTaskPortHelper(ftaskp).lastp(); + AstVar* const returnValuep + = new AstVar{varp->fileline(), VVarType::PORT, varp->name() + VALUE_SUFFIX, + VFlagBitPacked{}, varp->width()}; + AstVar* const returnXzp + = new AstVar{varp->fileline(), VVarType::PORT, varp->name() + XZ_SUFFIX, + VFlagBitPacked{}, varp->width()}; + returnValuep->direction(VDirection::OUTPUT); + returnXzp->direction(VDirection::OUTPUT); + returnValuep->funcLocal(true); + returnXzp->funcLocal(true); + returnValuep->lifetime(VLifetime::AUTOMATIC_IMPLICIT); + returnXzp->lifetime(VLifetime::AUTOMATIC_IMPLICIT); + returnValuep->trace(varp->isTrace()); + returnValuep->fourstateOriginalDTypeKwd(varp->dtypep()->basicp()->keyword()); + returnXzp->fourstateOriginalDTypeKwd(varp->dtypep()->basicp()->keyword()); + FileLine* const flp = varp->fileline(); + // CReset is not used because V3Task may inline function call and then CReset will + // be assigned to tmp variable - which does not contain information whether it is + // uased as an complement or what + AstConst* const constp + = new AstConst{flp, AstConst::DTyped{}, returnXzp->dtypep()}; + constp->num().setAllBits1(); + AstAssign* const valueResetp + = new AstAssign{flp, new AstVarRef{flp, returnValuep, VAccess::WRITE}, + constp->cloneTree(false)}; + AstAssign* const xzResetp + = new AstAssign{flp, new AstVarRef{flp, returnXzp, VAccess::WRITE}, constp}; + if (portEndp) { + portEndp->addNextHere(xzResetp); + portEndp->addNextHere(valueResetp); + portEndp->addNextHere(returnXzp); + portEndp->addNextHere(returnValuep); + } else if (AstNode* const stmtp = ftaskp->stmtsp()) { + stmtp->addHereThisAsNext(returnValuep); + stmtp->addHereThisAsNext(returnXzp); + stmtp->addHereThisAsNext(valueResetp); + stmtp->addHereThisAsNext(xzResetp); + } else { + ftaskp->addStmtsp(returnValuep); + ftaskp->addStmtsp(returnXzp); + ftaskp->addStmtsp(valueResetp); + ftaskp->addStmtsp(xzResetp); + } + FourstateLogicTypePropagator{ftaskp}; + setValuePartVarp(varp, returnValuep); + returnValuep->fourstateComplementp(returnXzp); + ftaskp->dtypeSetVoid(); + return; + } + } + AstVar* const newXzp = varp->cloneTree(false); + newXzp->name(newXzp->name() + XZ_SUFFIX); + newXzp->fourstateOriginalDTypeKwd(varp->dtypep()->basicp()->keyword()); + newXzp->dtypeSetBitUnsized(varp->width(), varp->widthMin(), varp->dtypep()->numeric()); + if (AstNodeExpr* const valuep = VN_CAST(newXzp->valuep(), NodeExpr)) { + valuep->unlinkFrBack(); + newXzp->valuep(getFourstateExpressionXZ(valuep)); + valuep->deleteTree(); + } + varp->addNextHere(newXzp); + AstVar* const newValuep = varp->cloneTree(false); + newValuep->name(newValuep->name() + VALUE_SUFFIX); + newValuep->trace(varp->isTrace()); + newValuep->fourstateOriginalDTypeKwd(varp->dtypep()->basicp()->keyword()); + newValuep->dtypeSetBitUnsized(varp->width(), varp->widthMin(), varp->dtypep()->numeric()); + if (AstNodeExpr* const valuep = VN_CAST(newValuep->valuep(), NodeExpr)) { + valuep->unlinkFrBack(); + newValuep->valuep(getFourstateExpressionValue(valuep)); + valuep->deleteTree(); + } + newValuep->fourstateComplementp(newXzp); + varp->addNextHere(newValuep); + setValuePartVarp(varp, newValuep); + } + + static AstVar* getSplittedValue(AstVar* const varp) { + UASSERT_OBJ(needsSplitting(varp->dtypep()), varp, + "Split shall be called only on four-state variables"); + AstVar* const result = getValuePartVarp(varp); + UASSERT_OBJ(result, varp, "Variable shall be split first"); + return result; + } + + static AstVar* getSplittedXZ(AstVar* const varp) { + return getSplittedValue(varp)->fourstateComplementp(); + } + + const FTaskPortsHelper& getFTaskPortHelper(AstNodeFTask* const ftaskp) { + if (ftaskp->user1()) return m_ftaskPortHelpers[ftaskp->user1() - 1]; + ftaskp->user1(m_ftaskPortHelpers.size() + 1); + m_ftaskPortHelpers.emplace_back(static_cast(ftaskp)); + return m_ftaskPortHelpers.back(); + } + + void addPrecalculation(AstNodeStmt* const nodep) { + FourstateLogicTypePropagator{nodep}; + m_currentStmtp->addHereThisAsNext(nodep); + } + + AstNodeExpr* getFourstateExpressionSelHandler(AstSel* const selp, + AstNodeExpr* const valueExprp, + const bool defaultsToZero) { + FileLine* const flp = selp->fileline(); + AstNodeExpr* lsbp = selp->lsbp(); + V3Number maxmsb{flp, 32, static_cast(selp->fromp()->dtypep()->width() - 1)}; + if (isStaticallyNGte(maxmsb, lsbp)) { + if (!selp->fromp()->isPure()) { + addPrecalculation(new AstStmtExpr{flp, valueExprp}); + // No precalculation of lsbp because right now: + // isStaticallyNGte(lsbp) => VN_IS(lsbp, Const) + } else { + valueExprp->deleteTree(); + } + return createZeroOrOnesp(selp, !defaultsToZero); + } + AstSel* const newp = [selp] { + AstNodeExpr* const fromp = selp->fromp()->unlinkFrBack(); + AstNodeExpr* const lsbp = selp->lsbp()->unlinkFrBack(); + AstSel* const newp = selp->cloneTree(false); + selp->fromp(fromp); + selp->lsbp(lsbp); + return newp; + }(); + setSelpHandled(newp); + newp->fromp(valueExprp); + const bool isStaticallyInRange = isStaticallyGte(maxmsb, lsbp); + const bool isLsbpFourstete = isFourstate(lsbp); + if (isStaticallyInRange && !isLsbpFourstete) { + newp->lsbp(lsbp->cloneTree(false)); + return newp; + } + AstNodeExpr* conditionp; + if (isLsbpFourstete) { + conditionp = getFourstateExpressionXZ(lsbp, isFourstate(selp)); + if (!isStaticallyInRange) { + conditionp = new AstOr{flp, conditionp, + new AstLt{flp, new AstConst{flp, maxmsb}, + getFourstateExpressionValue(lsbp, true)}}; + } + lsbp = getFourstateExpressionValue(lsbp, true); + } else { + if (!VN_IS(lsbp, + NodeVarRef) /*&& !VN_IS(lsbp, Const)*/) { // Not being a Cosnt is + // guarateed by logic above - if + // lsbp is a AstConst then it is + // either statically inside or + // outside range + AstVar* const lsbTmpp = createTmp(lsbp); + addPrecalculation(new AstAssign{flp, new AstVarRef{flp, lsbTmpp, VAccess::WRITE}, + lsbp->cloneTree(false)}); + lsbp = new AstVarRef{flp, lsbTmpp, VAccess::READ}; + } else { + lsbp = lsbp->cloneTree(false); + } + conditionp = new AstLt{flp, new AstConst{flp, maxmsb}, lsbp->cloneTree(false)}; + } + newp->lsbp(lsbp); + return new AstCond{flp, conditionp, createZeroOrOnesp(selp, !defaultsToZero), newp}; + } + + // Base visitor for Value and XZ visitor, contains some common functionalities + class FourstateExpressionVisitor VL_NOT_FINAL : public VNVisitor { + protected: + FourstateVisitor& m_fourstateVisitor; + AstNodeExpr* m_resultp = nullptr; + + private: + bool m_noTmp = false; + bool m_enforceTmp = false; + + virtual AstNodeExpr* getCache(const AstNodeExpr* keyp) = 0; + virtual void setCache(AstNodeExpr* keyp, AstNodeExpr* valuep) = 0; + + protected: + void noTmp() { m_noTmp = true; } + void enforceTmp() { m_enforceTmp = true; } + + void addPrecalculation(AstNodeStmt* const nodep) { + FourstateLogicTypePropagator{nodep}; + m_fourstateVisitor.m_currentStmtp->addHereThisAsNext(nodep); + } + + void fourstateExpressionFuncRefHandler(AstNodeFTaskRef* const funcRefp) { + // Its ok to use this instead of output since we only need width which is the same + AstVar* const functionReturnVarp = VN_AS(VN_AS(funcRefp->taskp(), Func)->fvarp(), Var); + AstVar* const resultValuep = m_fourstateVisitor.createTmp(functionReturnVarp); + AstVar* const resultXzp = m_fourstateVisitor.createTmp(functionReturnVarp); + AstNodeFTaskRef* const newCallp = funcRefp->cloneTree(false); + UASSERT_OBJ(!isFTaskRefHandled(newCallp), funcRefp, + "Trying to handle already handled four-state function call"); + setFTaskRefHandled(newCallp); + if (newCallp->argsp()) newCallp->argsp()->unlinkFrBackWithNext()->deleteTree(); + FileLine* const flp = funcRefp->fileline(); + { + size_t argIdx = 0; + const FTaskPortsHelper& ftaskPortsHelper + = m_fourstateVisitor.getFTaskPortHelper(funcRefp->taskp()); + for (AstArg* argp = funcRefp->argsp(); argp; argp = VN_AS(argp->nextp(), Arg)) { + const AstVar* const varp + = ftaskPortsHelper.getArgPortVar(argp->name(), argIdx); + ++argIdx; + if (needsSplitting(varp->dtypep())) { + newCallp->addArgsp(new AstArg{ + flp, "", getFourstateExpressionValue(argp->exprp(), false)}); + newCallp->addArgsp( + new AstArg{flp, "", getFourstateExpressionXZ(argp->exprp(), false)}); + } else if (isFourstate(argp->exprp())) { + newCallp->addArgsp(new AstArg{ + flp, "", m_fourstateVisitor.getTwoStateCast(argp->exprp())}); + } else { + newCallp->addArgsp(argp->cloneTree(false)); + } + } + } + AstVarRef* const resultValueRefp = new AstVarRef{flp, resultValuep, VAccess::WRITE}; + AstVarRef* const resultXzRefp = new AstVarRef{flp, resultXzp, VAccess::WRITE}; + setFourstate(resultValueRefp, false); + setFourstate(resultXzRefp, false); + { + std::string resultName = funcRefp->taskp()->fvarp()->name(); + AstArg* const resultValueArgp + = new AstArg{flp, resultName + VALUE_SUFFIX, resultValueRefp}; + AstArg* const resultXZArgp + = new AstArg{flp, std::move(resultName) + XZ_SUFFIX, resultXzRefp}; + newCallp->addArgsp(resultValueArgp); + newCallp->addArgsp(resultXZArgp); + } + AstStmtExpr* const newStmtExprp = new AstStmtExpr{flp, newCallp}; + addPrecalculation(newStmtExprp); + AstVarRef* const varRefValuep = new AstVarRef{flp, resultValuep, VAccess::READ}; + AstVarRef* const varRefXzp = new AstVarRef{flp, resultXzp, VAccess::READ}; + pushDeletep(varRefValuep); + pushDeletep(varRefXzp); + setExprValuep(funcRefp, varRefValuep); + setExprXZp(funcRefp, varRefXzp); + } + + void fourstateExpressionCondHandler(AstCond* const condp) { + FileLine* const flp = condp->fileline(); + AstVar* const resultValueTmpVarp = m_fourstateVisitor.createTmp(condp->thenp()); + AstVar* const resultXZTmpVarp = m_fourstateVisitor.createTmp(condp->thenp()); + AstIf* ifp = new AstIf{flp, isFourstate(condp->condp()) + ? getFourstateExpressionXZ(condp->condp()) + : condp->condp()->cloneTree(false)}; + // Those must be here so expr is always evaluated fully in the right place + AstIf* twoStateIfp = ifp; + if (isFourstate(condp->condp())) { + // Condition is X/Z + AstNodeExpr* conditionValuep = getFourstateExpressionValue(condp->condp()); + AstNodeExpr* const thenCopyp = condp->thenp()->cloneTree(false); + AstNodeExpr* const elseCopyp = condp->elsep()->cloneTree(false); + StatementPlaceHolder thenPlaceholder{m_fourstateVisitor, flp}; + ifp->addThensp(thenPlaceholder.stmtp()); + TmpVarsReleaser tmpVarsReleaser{m_fourstateVisitor}; + addPrecalculation( + new AstAssign{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::WRITE}, + getFourstateExpressionValue(thenCopyp, false)}); + addPrecalculation( + new AstAssign{flp, new AstVarRef{flp, resultXZTmpVarp, VAccess::WRITE}, + getFourstateExpressionXZ(thenCopyp, false)}); + AstIf* const thenifp = new AstIf{ + flp, new AstOr{ + flp, + new AstXor{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::READ}, + getFourstateExpressionValue(elseCopyp, false)}, + new AstXor{flp, new AstVarRef{flp, resultXZTmpVarp, VAccess::READ}, + getFourstateExpressionXZ(elseCopyp, false)}}}; + ifp->addThensp(thenifp); + thenifp->addThensp( + new AstAssign{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::WRITE}, + createZeroOrOnesp(thenCopyp, true)}); + thenifp->addThensp( + new AstAssign{flp, new AstVarRef{flp, resultXZTmpVarp, VAccess::WRITE}, + createZeroOrOnesp(thenCopyp, true)}); + thenCopyp->deleteTree(); + elseCopyp->deleteTree(); + twoStateIfp = new AstIf{flp, conditionValuep}; + ifp->addElsesp(twoStateIfp); + } + { + // Condition is 1/0 + { + // Condition is 1 + StatementPlaceHolder thenPlaceholder{m_fourstateVisitor, flp}; + twoStateIfp->addThensp(thenPlaceholder.stmtp()); + TmpVarsReleaser tmpVarsReleaser{m_fourstateVisitor}; + addPrecalculation( + new AstAssign{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::WRITE}, + getFourstateExpressionValue(condp->thenp(), false)}); + addPrecalculation( + new AstAssign{flp, new AstVarRef{flp, resultXZTmpVarp, VAccess::WRITE}, + getFourstateExpressionXZ(condp->thenp(), false)}); + } + { + // Condition is 0 + StatementPlaceHolder elsePlaceholder{m_fourstateVisitor, flp}; + twoStateIfp->addElsesp(elsePlaceholder.stmtp()); + TmpVarsReleaser tmpVarsReleaser{m_fourstateVisitor}; + addPrecalculation( + new AstAssign{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::WRITE}, + getFourstateExpressionValue(condp->elsep(), false)}); + addPrecalculation( + new AstAssign{flp, new AstVarRef{flp, resultXZTmpVarp, VAccess::WRITE}, + getFourstateExpressionXZ(condp->elsep(), false)}); + } + } + addPrecalculation(ifp); + AstVarRef* const resultValueTmpVarRefp + = new AstVarRef{flp, resultValueTmpVarp, VAccess::READ}; + AstVarRef* const resultXZTmpVarRefp + = new AstVarRef{flp, resultXZTmpVarp, VAccess::READ}; + pushDeletep(resultValueTmpVarRefp); + pushDeletep(resultXZTmpVarRefp); + setExprValuep(condp, resultValueTmpVarRefp); + setExprXZp(condp, resultXZTmpVarRefp); + } + + void fourstateExpressionLogAndHandler(AstLogAnd* const logAndp) { + FileLine* const flp = logAndp->fileline(); + AstVar* const resultValueTmpVarp = m_fourstateVisitor.createTmp(logAndp); + AstVar* const resultXZTmpVarp = m_fourstateVisitor.createTmp(logAndp); + addPrecalculation(new AstAssign{flp, + new AstVarRef{flp, resultXZTmpVarp, VAccess::WRITE}, + getFourstateExpressionXZ(logAndp->lhsp(), false)}); + addPrecalculation( + new AstAssign{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::WRITE}, + new AstOr{flp, new AstVarRef{flp, resultXZTmpVarp, VAccess::READ}, + getFourstateExpressionValue(logAndp->lhsp(), false)}}); + AstIf* const ifp + = new AstIf{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::READ}}; + addPrecalculation(ifp); + { + // Lhs is non zero + StatementPlaceHolder placeholderStmt{m_fourstateVisitor, flp}; + ifp->addThensp(placeholderStmt.stmtp()); + TmpVarsReleaser{m_fourstateVisitor}; + addPrecalculation(new AstAssign{ + flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::WRITE}, + new AstOr{flp, getFourstateExpressionValue(logAndp->rhsp(), false), + getFourstateExpressionXZ(logAndp->rhsp())}}); + addPrecalculation(new AstAssign{ + flp, new AstVarRef{flp, resultXZTmpVarp, VAccess::WRITE}, + new AstLogAnd{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::READ}, + new AstOr{flp, + new AstVarRef{flp, resultXZTmpVarp, VAccess::READ}, + getFourstateExpressionXZ(logAndp->rhsp())}}}); + } + AstVarRef* const resultValueTmpVarRefp + = new AstVarRef{flp, resultValueTmpVarp, VAccess::READ}; + AstVarRef* const resultXZTmpVarRefp + = new AstVarRef{flp, resultXZTmpVarp, VAccess::READ}; + pushDeletep(resultValueTmpVarRefp); + pushDeletep(resultXZTmpVarRefp); + setExprValuep(logAndp, resultValueTmpVarRefp); + setExprXZp(logAndp, resultXZTmpVarRefp); + } + + void fourstateExpressionLogOrHandler(AstLogOr* const logOrp) { + FileLine* const flp = logOrp->fileline(); + AstVar* const resultValueTmpVarp = m_fourstateVisitor.createTmp(logOrp); + AstVar* const resultXZTmpVarp = m_fourstateVisitor.createTmp(logOrp); + addPrecalculation(new AstAssign{flp, + new AstVarRef{flp, resultXZTmpVarp, VAccess::WRITE}, + getFourstateExpressionXZ(logOrp->lhsp(), false)}); + addPrecalculation(new AstAssign{flp, + new AstVarRef{flp, resultValueTmpVarp, VAccess::WRITE}, + getFourstateExpressionValue(logOrp->lhsp(), false)}); + AstIf* const ifp = new AstIf{ + flp, + new AstOr{flp, + new AstNot{flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::READ}}, + new AstVarRef{flp, resultXZTmpVarp, VAccess::READ}}}; + addPrecalculation(ifp); + { + // Lhs is non one + StatementPlaceHolder placeholderStmt{m_fourstateVisitor, flp}; + ifp->addThensp(placeholderStmt.stmtp()); + TmpVarsReleaser{m_fourstateVisitor}; + addPrecalculation(new AstAssign{ + flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::WRITE}, + new AstOr{flp, getFourstateExpressionValue(logOrp->rhsp()), + new AstOr{flp, getFourstateExpressionXZ(logOrp->rhsp()), + new AstVarRef{flp, resultXZTmpVarp, VAccess::READ}}}}); + addPrecalculation(new AstAssign{ + flp, new AstVarRef{flp, resultXZTmpVarp, VAccess::WRITE}, + new AstLogAnd{ + flp, new AstVarRef{flp, resultValueTmpVarp, VAccess::READ}, + new AstOr{flp, + new AstNot{flp, getFourstateExpressionValue(logOrp->rhsp())}, + getFourstateExpressionXZ(logOrp->rhsp())}}}); + } + AstVarRef* const resultValueTmpVarRefp + = new AstVarRef{flp, resultValueTmpVarp, VAccess::READ}; + AstVarRef* const resultXZTmpVarRefp + = new AstVarRef{flp, resultXZTmpVarp, VAccess::READ}; + pushDeletep(resultValueTmpVarRefp); + pushDeletep(resultXZTmpVarRefp); + setExprValuep(logOrp, resultValueTmpVarRefp); + setExprXZp(logOrp, resultXZTmpVarRefp); + } + + AstNodeExpr* get(AstNodeExpr* const exprp, bool putIntoTmp = true) { + if (AstNodeExpr* result = getCache(exprp)) return result->cloneTree(false); + m_resultp = nullptr; + VL_RESTORER(m_noTmp); + VL_RESTORER(m_enforceTmp); + m_noTmp = false; + m_enforceTmp = false; + iterate(exprp); + UASSERT_OBJ(m_resultp, exprp, + "Result shall always be returned - even if it is just a place holder"); + UASSERT_OBJ(!(m_noTmp && m_enforceTmp), exprp, + "Expression may not enforce and omit tmp variable at the same time"); + if (m_enforceTmp || (putIntoTmp && !m_noTmp)) { + FileLine* const flp = exprp->fileline(); + AstVar* const varp = m_fourstateVisitor.createTmp(exprp); + AstVarRef* const varRefp = new AstVarRef{flp, varp, VAccess::WRITE}; + AstAssign* const assignp = new AstAssign{flp, varRefp, m_resultp}; + addPrecalculation(assignp); + m_resultp = new AstVarRef{flp, varp, VAccess::READ}; + setFourstate(m_resultp, false); + } + setCache(exprp, m_resultp); + return m_resultp; + } + + public: + explicit FourstateExpressionVisitor(FourstateVisitor& fourstateVisitor) + : m_fourstateVisitor{fourstateVisitor} {} + ~FourstateExpressionVisitor() override = default; + + virtual AstNodeExpr* getFourstateExpressionValue(AstNodeExpr* const exprp, + bool putIntoTmp = true) { + return m_fourstateVisitor.m_fourstateGeneratorValueVisitor.getFourstateExpressionValue( + exprp, putIntoTmp); + } + + virtual AstNodeExpr* getFourstateExpressionXZ(AstNodeExpr* const exprp, + const bool putIntoTmp = true) { + return m_fourstateVisitor.m_fourstateGeneratorXZVisitor.getFourstateExpressionXZ( + exprp, putIntoTmp); + } + }; + + // Visitor used to get an expression with a value of a value part of a four-state expression + // This can be thought as a function - but a Visitor was used to be able to use vtable, create + // some enclosing namespace and benefit from inheritance + class FourstateExpressionValueVisitor final : public FourstateExpressionVisitor { + + void visit(AstAnd* const andp) override { + // (a.value | a.xz) & (b.value | b.xz) + FileLine* const flp = andp->fileline(); + m_resultp = new AstAnd{flp, + new AstOr{flp, getFourstateExpressionValue(andp->lhsp()), + getFourstateExpressionXZ(andp->lhsp())}, + new AstOr{flp, getFourstateExpressionValue(andp->rhsp()), + getFourstateExpressionXZ(andp->rhsp())}}; + } + + void visit(AstOr* const orp) override { + // a.value | b.value | a.xz | b.xz + FileLine* const flp = orp->fileline(); + m_resultp = new AstOr{flp, + new AstOr{flp, getFourstateExpressionValue(orp->lhsp()), + getFourstateExpressionValue(orp->rhsp())}, + new AstOr{flp, getFourstateExpressionXZ(orp->lhsp()), + getFourstateExpressionXZ(orp->rhsp())}}; + } + + void visit(AstXor* const xorp) override { + // (a.value ^ b.value) | a.xz | b.xz + FileLine* const flp = xorp->fileline(); + m_resultp = new AstOr{flp, + new AstXor{flp, getFourstateExpressionValue(xorp->lhsp(), false), + getFourstateExpressionValue(xorp->rhsp(), false)}, + getFourstateExpressionXZ(xorp)}; + } + + void visit(AstNot* const notp) override { + // ~a.value | a.xz + FileLine* const flp = notp->fileline(); + m_resultp = new AstOr{flp, new AstNot{flp, getFourstateExpressionValue(notp->lhsp())}, + getFourstateExpressionXZ(notp->lhsp())}; + } + + template + void visitCompare(CompoarisonOp_T* const cmpp) { + // |(a.xz | b.xz) | (a.value op b.value) + FileLine* const flp = cmpp->fileline(); + m_resultp + = new AstOr{flp, getFourstateExpressionXZ(cmpp), + new CompoarisonOp_T{flp, getFourstateExpressionValue(cmpp->lhsp()), + getFourstateExpressionValue(cmpp->rhsp())}}; + } + + void visit(AstEq* const eqp) override { visitCompare(eqp); } + void visit(AstNeq* const neqp) override { visitCompare(neqp); } + void visit(AstGt* const gtp) override { visitCompare(gtp); } + void visit(AstGte* const gtep) override { visitCompare(gtep); } + void visit(AstLt* const ltp) override { visitCompare(ltp); } + void visit(AstLte* const ltep) override { visitCompare(ltep); } + + void visit(AstGtS* const gtp) override { visitCompare(gtp); } + void visit(AstGteS* const gtep) override { visitCompare(gtep); } + void visit(AstLtS* const ltp) override { visitCompare(ltp); } + void visit(AstLteS* const ltep) override { visitCompare(ltep); } + + void visit(AstEqWild* const eqWildp) override { + // ((a.value | b.xz) == (b.value | b.xz)) | |(a.xz & ~b.xz) + FileLine* const flp = eqWildp->fileline(); + m_resultp = new AstOr{ + flp, + new AstEq{flp, + new AstOr{flp, getFourstateExpressionValue(eqWildp->lhsp(), false), + getFourstateExpressionXZ(eqWildp->rhsp())}, + new AstOr{flp, getFourstateExpressionValue(eqWildp->rhsp(), false), + getFourstateExpressionXZ(eqWildp->rhsp())}}, + getFourstateExpressionXZ(eqWildp)}; + } + + void visit(AstNeqWild* const neqWildp) override { + // ((a.value | b.xz) != (b.value | b.xz)) | |(a.xz & ~b.xz) + FileLine* const flp = neqWildp->fileline(); + m_resultp = new AstOr{ + flp, + new AstNeq{flp, + new AstOr{flp, getFourstateExpressionValue(neqWildp->lhsp(), false), + getFourstateExpressionXZ(neqWildp->rhsp())}, + new AstOr{flp, getFourstateExpressionValue(neqWildp->rhsp(), false), + getFourstateExpressionXZ(neqWildp->rhsp())}}, + getFourstateExpressionXZ(neqWildp)}; + } + + void visit(AstShiftL* const shiftlp) override { + // |b.xz ? '1 : (a.value << b.value) + FileLine* const flp = shiftlp->fileline(); + m_resultp = new AstCond{ + flp, new AstRedOr{flp, getFourstateExpressionXZ(shiftlp->rhsp())}, + createZeroOrOnesp(shiftlp->lhsp(), true), + new AstShiftL{ + flp, + getFourstateExpressionValue( + shiftlp->lhsp(), true /*must be in tmp so it always gets evaluated*/), + getFourstateExpressionValue(shiftlp->rhsp())}}; + } + + void visit(AstShiftR* const shiftrp) override { + // |b.xz ? '1 : (a.value >> b.value) + FileLine* const flp = shiftrp->fileline(); + m_resultp = new AstCond{ + flp, new AstRedOr{flp, getFourstateExpressionXZ(shiftrp->rhsp())}, + createZeroOrOnesp(shiftrp->lhsp(), true), + new AstShiftR{ + flp, + getFourstateExpressionValue( + shiftrp->lhsp(), true /*must be in tmp so it always gets evaluated*/), + getFourstateExpressionValue(shiftrp->rhsp())}}; + } + + void visit(AstExtend* const extendp) override { + FileLine* const flp = extendp->fileline(); + m_resultp = new AstExtend{flp, getFourstateExpressionValue(extendp->lhsp(), false), + extendp->width()}; + } + + void visit(AstExtendS* const extendsp) override { + FileLine* const flp = extendsp->fileline(); + m_resultp = new AstExtendS{flp, getFourstateExpressionValue(extendsp->lhsp(), false), + extendsp->width()}; + } + + void visit(AstCReset* const cresetp) override { // LCOV_EXCL_LINE + cresetp->v3fatalSrc("This shall never be reached - CReset shall never be under " + "anything but AstNodeAssign"); + } + + void visit(AstConst* const constp) override { + noTmp(); + AstConst* const newp = constp->cloneTree(false); + newp->num().opBitsOneX(constp->num()); + newp->dtypeSetBitUnsized(newp->width(), newp->dtypep()->widthMin(), + newp->dtypep()->numeric()); + m_resultp = newp; + } + + void visit(AstNodeFTaskRef* const funcp) override { + fourstateExpressionFuncRefHandler(funcp); + noTmp(); + m_resultp = getExprValuep(funcp)->cloneTree(false); + } + + void visit(AstCond* const condp) override { + fourstateExpressionCondHandler(condp); + noTmp(); + m_resultp = getExprValuep(condp)->cloneTree(false); + } + + void visit(AstLogAnd* const logAndp) override { + fourstateExpressionLogAndHandler(logAndp); + noTmp(); + m_resultp = getExprValuep(logAndp)->cloneTree(false); + } + + void visit(AstLogOr* const logOrp) override { + fourstateExpressionLogOrHandler(logOrp); + noTmp(); + m_resultp = getExprValuep(logOrp)->cloneTree(false); + } + + void visit(AstSel* const selp) override { + m_resultp = m_fourstateVisitor.getFourstateExpressionSelHandler( + selp, getFourstateExpressionValue(selp->fromp(), false), false); + } + + void visit(AstRedAnd* const redAndp) override { + // &(a.value | a.xz) + enforceTmp(); + FileLine* const flp = redAndp->fileline(); + m_resultp = new AstRedAnd{ + flp, new AstOr{flp, getFourstateExpressionValue(redAndp->lhsp(), false), + getFourstateExpressionXZ(redAndp->lhsp())}}; + } + + void visit(AstRedOr* const redOrp) override { + // |(a.value | a.xz) + FileLine* const flp = redOrp->fileline(); + m_resultp + = new AstRedOr{flp, new AstOr{flp, getFourstateExpressionValue(redOrp->lhsp()), + getFourstateExpressionXZ(redOrp->lhsp())}}; + } + + void visit(AstRedXor* const redXorp) override { + // |a.xz | ^a.value + FileLine* const flp = redXorp->fileline(); + m_resultp = new AstOr{ + flp, new AstRedOr{flp, getFourstateExpressionXZ(redXorp->lhsp())}, + new AstRedXor{flp, getFourstateExpressionValue(redXorp->lhsp(), false)}}; + } + + template + void getFourstateExpressionArithmeticValue(CompoarisonOp_T* const biop) { + // |(a.xz | b.xz) ? '1 : (a op b) + FileLine* const flp = biop->fileline(); + m_resultp = new AstCond{ + flp, + new AstRedOr{flp, new AstOr{flp, getFourstateExpressionXZ(biop->lhsp()), + getFourstateExpressionXZ(biop->rhsp())}}, + createZeroOrOnesp(biop, true), + new CompoarisonOp_T{ + flp, + getFourstateExpressionValue( + biop->lhsp(), true /*must be in tmp so it always gets evaluated*/), + getFourstateExpressionValue( + biop->rhsp(), true /*must be in tmp so it always gets evaluated*/)}}; + } + + void visit(AstAdd* const addp) override { getFourstateExpressionArithmeticValue(addp); } + void visit(AstSub* const subp) override { getFourstateExpressionArithmeticValue(subp); } + void visit(AstMul* const mulp) override { getFourstateExpressionArithmeticValue(mulp); } + void visit(AstMulS* const mulsp) override { getFourstateExpressionArithmeticValue(mulsp); } + + template + void getFourstateExpressionDivValue(CompoarisonOp_T* const biop) { + // |(a.xz | b.xz) | ~|b.value ? '1 : (a op b) + FileLine* const flp = biop->fileline(); + CompoarisonOp_T* const resultp = new CompoarisonOp_T{ + flp, + getFourstateExpressionValue(biop->lhsp(), + true /*must be in tmp so it always gets evaluated*/), + getFourstateExpressionValue(biop->rhsp(), + true /*must be in tmp so it always gets evaluated*/)}; + setTwostate(resultp); + m_resultp = new AstCond{ + flp, + new AstOr{ + flp, + new AstRedOr{flp, new AstOr{flp, getFourstateExpressionXZ(biop->lhsp()), + getFourstateExpressionXZ(biop->rhsp())}}, + new AstNot{flp, new AstRedOr{flp, getFourstateExpressionValue(biop->rhsp())}}}, + createZeroOrOnesp(biop, true), resultp}; + } + + void visit(AstDiv* const divp) override { getFourstateExpressionDivValue(divp); } + void visit(AstDivS* const divsp) override { getFourstateExpressionDivValue(divsp); } + void visit(AstModDiv* const moddivp) override { getFourstateExpressionDivValue(moddivp); } + void visit(AstModDivS* const moddivsp) override { + getFourstateExpressionDivValue(moddivsp); + } + + void visit(AstConcat* const concatp) override { + // {a.value, b.value} + m_resultp = new AstConcat{concatp->fileline(), + getFourstateExpressionValue(concatp->lhsp(), false), + getFourstateExpressionValue(concatp->rhsp(), false)}; + } + + void visit(AstReplicate* const replicatep) override { + // {count{src.value}} + // IEEE 1800-2023 11.4.12.1 Replication operator: + // 'A replication operator (also called a multiple concatenation) is expressed by a + // concatenation preceded by a non-negative, non-x, and non-z constant expression, + // called a multiplier'... + // Because of that `replicatep->countp()` is just cloned + m_resultp = new AstReplicate{replicatep->fileline(), + getFourstateExpressionValue(replicatep->srcp(), false), + replicatep->countp()->cloneTree(false)}; + m_resultp->dtypeSetBitUnsized(replicatep->width(), replicatep->dtypep()->widthMin(), + replicatep->dtypep()->numeric()); + } + + void visit(AstCastWrap* const castWrapp) override { + // Cast to anything to fourstate + m_resultp = getFourstateExpressionValue(castWrapp->lhsp(), false); + } + + void visit(AstNodeVarRef* const varRefp) override { + noTmp(); + m_fourstateVisitor.splitVar(varRefp->varp()); + AstNodeVarRef* const newp = varRefp->cloneTree(false); + if (!newp->name().empty()) newp->name(newp->name() + VALUE_SUFFIX); + newp->varp(getSplittedValue(varRefp->varp())); + newp->dtypeSetBitSized(varRefp->varp()->width(), varRefp->varp()->dtypep()->numeric()); + m_resultp = newp; + } + + void visit(AstNodeExpr* const nodep) override { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: Operator " + << nodep->typeName() + << " not supported in the four-state mode"); + // Workaround to avoid Internal errors + m_resultp = new AstConst{nodep->fileline(), AstConst::BitFalse{}}; + } + + void visit(AstNode* const nodep) override { // LCOV_EXCL_LINE + nodep->v3fatalSrc("This node shall be unreachable in this visitor"); + } + + AstNodeExpr* getCache(const AstNodeExpr* const keyp) override { + return getExprValuep(keyp); + } + void setCache(AstNodeExpr* keyp, AstNodeExpr* const valuep) override { + setExprValuep(keyp, valuep); + } + + public: + using FourstateExpressionVisitor::FourstateExpressionVisitor; + ~FourstateExpressionValueVisitor() override = default; + + AstNodeExpr* getFourstateExpressionValue(AstNodeExpr* const exprp, + bool putIntoTmp = true) override { + if (!isFourstate(exprp)) { + AstStmtExpr* const holderp + = new AstStmtExpr{exprp->fileline(), exprp->cloneTree(false)}; + m_fourstateVisitor.iterateChildren(holderp); + AstNodeExpr* const resultp = holderp->exprp()->unlinkFrBack(); + holderp->deleteTree(); + return resultp; + } + return get(exprp, putIntoTmp); + } + }; + + // Visitor used to get an expression with a value of an xz part of a four-state expression + // This can be thought as a function - but a Visitor was used to be able to use vtable, create + // some enclosing namespace and benefit from inheritance + class FourstateExpressionXZVisitor final : public FourstateExpressionVisitor { + + void visit(AstAnd* const andp) override { + // (a.value & b.xz) | (b.value & a.xz) | (a.xz & b.xz) + FileLine* const flp = andp->fileline(); + m_resultp + = new AstOr{flp, + new AstOr{flp, + new AstAnd{flp, getFourstateExpressionValue(andp->lhsp()), + getFourstateExpressionXZ(andp->rhsp())}, + new AstAnd{flp, getFourstateExpressionValue(andp->rhsp()), + getFourstateExpressionXZ(andp->lhsp())}}, + new AstAnd{flp, getFourstateExpressionXZ(andp->lhsp()), + getFourstateExpressionXZ(andp->rhsp())}}; + } + + void visit(AstOr* const orp) override { + // (a.xz & b.xz) | (a.xz & ~b.value) | (b.xz & ~a.value) + FileLine* const flp = orp->fileline(); + m_resultp = new AstOr{ + flp, + new AstOr{flp, + new AstAnd{flp, getFourstateExpressionXZ(orp->lhsp()), + getFourstateExpressionXZ(orp->rhsp())}, + new AstAnd{flp, getFourstateExpressionXZ(orp->lhsp()), + new AstNot{flp, getFourstateExpressionValue(orp->rhsp())}}}, + new AstAnd{flp, getFourstateExpressionXZ(orp->rhsp()), + new AstNot{flp, getFourstateExpressionValue(orp->lhsp())}}}; + } + + void visit(AstXor* const xorp) override { + // a.xz | b.xz + FileLine* const flp = xorp->fileline(); + m_resultp = new AstOr{flp, getFourstateExpressionXZ(xorp->lhsp()), + getFourstateExpressionXZ(xorp->rhsp())}; + } + + void visit(AstNot* const notp) override { + // a.xz + m_resultp = getFourstateExpressionXZ(notp->lhsp()); + } + + void visitCompare(AstNodeBiop* const cmpp) { + // |(a.xz | b.xz) + enforceTmp(); + FileLine* const flp = cmpp->fileline(); + m_resultp = new AstRedOr{flp, new AstOr{flp, getFourstateExpressionXZ(cmpp->lhsp()), + getFourstateExpressionXZ(cmpp->rhsp())}}; + } + + void visit(AstEq* const eqp) override { visitCompare(eqp); } + void visit(AstNeq* const neqp) override { visitCompare(neqp); } + void visit(AstGt* const gtp) override { visitCompare(gtp); } + void visit(AstGte* const gtep) override { visitCompare(gtep); } + void visit(AstLt* const ltp) override { visitCompare(ltp); } + void visit(AstLte* const ltep) override { visitCompare(ltep); } + + void visit(AstGtS* const gtp) override { visitCompare(gtp); } + void visit(AstGteS* const gtep) override { visitCompare(gtep); } + void visit(AstLtS* const ltp) override { visitCompare(ltp); } + void visit(AstLteS* const ltep) override { visitCompare(ltep); } + + void visit(AstEqWild* const eqWildp) override { + // |(a.xz & ~b.xz) + enforceTmp(); + FileLine* const flp = eqWildp->fileline(); + m_resultp = new AstRedOr{ + flp, new AstAnd{flp, getFourstateExpressionXZ(eqWildp->lhsp(), false), + new AstNot{flp, getFourstateExpressionXZ(eqWildp->rhsp())}}}; + } + + void visit(AstNeqWild* const neqWildp) override { + // |(a.xz & ~b.xz) + enforceTmp(); + FileLine* const flp = neqWildp->fileline(); + m_resultp = new AstRedOr{ + flp, new AstAnd{flp, getFourstateExpressionXZ(neqWildp->lhsp(), false), + new AstNot{flp, getFourstateExpressionXZ(neqWildp->rhsp())}}}; + } + + void visit(AstShiftL* const shiftlp) override { + // |b.xz ? '1 : (a.xz << b.value) + FileLine* const flp = shiftlp->fileline(); + m_resultp + = new AstCond{flp, new AstRedOr{flp, getFourstateExpressionXZ(shiftlp->rhsp())}, + createZeroOrOnesp(shiftlp->lhsp(), true), + new AstShiftL{flp, getFourstateExpressionXZ(shiftlp->lhsp(), false), + getFourstateExpressionValue(shiftlp->rhsp())}}; + } + + void visit(AstShiftR* const shiftrp) override { + // |b.xz ? '1 : (a.xz >> b.value) + FileLine* const flp = shiftrp->fileline(); + m_resultp + = new AstCond{flp, new AstRedOr{flp, getFourstateExpressionXZ(shiftrp->rhsp())}, + createZeroOrOnesp(shiftrp->lhsp(), true), + new AstShiftR{flp, getFourstateExpressionXZ(shiftrp->lhsp(), false), + getFourstateExpressionValue(shiftrp->rhsp())}}; + } + + void visit(AstExtend* const extendp) override { + FileLine* const flp = extendp->fileline(); + m_resultp = new AstExtend{flp, getFourstateExpressionXZ(extendp->lhsp(), false), + extendp->width()}; + } + + void visit(AstExtendS* const extendsp) override { + FileLine* const flp = extendsp->fileline(); + m_resultp = new AstExtendS{flp, getFourstateExpressionXZ(extendsp->lhsp(), false), + extendsp->width()}; + } + + void visit(AstCReset* const cresetp) override { // LCOV_EXCL_LINE + cresetp->v3fatalSrc("This shall never be reached - CReset shall never be under " + "anything but AstNodeAssign"); + } + + void visit(AstConst* const constp) override { + noTmp(); + AstConst* const newp = constp->cloneTree(false); + newp->num().opBitsXZ(constp->num()); + newp->dtypeSetBitSized(newp->width(), newp->dtypep()->numeric()); + m_resultp = newp; + } + + void visit(AstRedAnd* const redAndp) override { + // &(a.value | a.xz) & |a.xz + FileLine* const flp = redAndp->fileline(); + m_resultp = new AstAnd{flp, getFourstateExpressionValue(redAndp), + new AstRedOr{flp, getFourstateExpressionXZ(redAndp->lhsp())}}; + } + + void visit(AstRedOr* const redOrp) override { + // |a.xz & ~|(a.value & ~a.xz) + FileLine* const flp = redOrp->fileline(); + m_resultp = new AstAnd{ + flp, new AstRedOr{flp, getFourstateExpressionXZ(redOrp->lhsp())}, + new AstNot{ + flp, + new AstRedOr{flp, new AstAnd{flp, getFourstateExpressionValue(redOrp->lhsp()), + new AstNot{flp, getFourstateExpressionXZ( + redOrp->lhsp())}}}}}; + } + + void visit(AstRedXor* const redXorp) override { + // |a.xz + m_resultp + = new AstRedOr{redXorp->fileline(), getFourstateExpressionXZ(redXorp->lhsp())}; + } + + void getFourstateExpressionArithmeticXZ(AstNodeBiop* const biop) { + // |(a.xz | b.xz) ? '1 : '0 + FileLine* const flp = biop->fileline(); + m_resultp = new AstCond{ + flp, + new AstRedOr{flp, new AstOr{flp, getFourstateExpressionXZ(biop->lhsp()), + getFourstateExpressionXZ(biop->rhsp())}}, + createZeroOrOnesp(biop, true), createZeroOrOnesp(biop)}; + } + + void visit(AstAdd* const addp) override { getFourstateExpressionArithmeticXZ(addp); } + void visit(AstSub* const subp) override { getFourstateExpressionArithmeticXZ(subp); } + void visit(AstMul* const mulp) override { getFourstateExpressionArithmeticXZ(mulp); } + void visit(AstMulS* const mulsp) override { getFourstateExpressionArithmeticXZ(mulsp); } + + void getFourstateExpressionDivValue(AstNodeBiop* const biop) { + // |(a.xz | b.xz) | ~|b.value ? '1 : '0 + FileLine* const flp = biop->fileline(); + m_resultp = new AstCond{ + flp, + new AstOr{ + flp, + new AstRedOr{flp, new AstOr{flp, getFourstateExpressionXZ(biop->lhsp()), + getFourstateExpressionXZ(biop->rhsp())}}, + new AstNot{flp, new AstRedOr{flp, getFourstateExpressionValue(biop->rhsp())}}}, + createZeroOrOnesp(biop, true), createZeroOrOnesp(biop, false)}; + } + + void visit(AstDiv* const divp) override { getFourstateExpressionDivValue(divp); } + void visit(AstDivS* const divsp) override { getFourstateExpressionDivValue(divsp); } + void visit(AstModDiv* const moddivp) override { getFourstateExpressionDivValue(moddivp); } + void visit(AstModDivS* const moddivsp) override { + getFourstateExpressionDivValue(moddivsp); + } + + void visit(AstConcat* const concatp) override { + // {a.xz, b.xz} + m_resultp = new AstConcat{concatp->fileline(), + getFourstateExpressionXZ(concatp->lhsp(), false), + getFourstateExpressionXZ(concatp->rhsp(), false)}; + } + + void visit(AstReplicate* const replicatep) override { + // {count{src.value}} + // IEEE 1800-2023 11.4.12.1 Replication operator: + // 'A replication operator (also called a multiple concatenation) is expressed by a + // concatenation preceded by a non-negative, non-x, and non-z constant expression, + // called a multiplier'... + // Because of that `replicatep->countp()` is just cloned + m_resultp = new AstReplicate{replicatep->fileline(), + getFourstateExpressionXZ(replicatep->srcp(), false), + replicatep->countp()->cloneTree(false)}; + m_resultp->dtypeSetBitUnsized(replicatep->width(), replicatep->dtypep()->widthMin(), + replicatep->dtypep()->numeric()); + } + + void visit(AstCastWrap* const castWrapp) override { + // Cast to anything to fourstate + m_resultp = getFourstateExpressionXZ(castWrapp->lhsp(), false); + } + + void visit(AstNodeFTaskRef* const funcp) override { + fourstateExpressionFuncRefHandler(funcp); + noTmp(); + m_resultp = getExprXZp(funcp)->cloneTree(false); + } + + void visit(AstCond* const condp) override { + fourstateExpressionCondHandler(condp); + noTmp(); + m_resultp = getExprXZp(condp)->cloneTree(false); + } + + void visit(AstLogAnd* const logAndp) override { + fourstateExpressionLogAndHandler(logAndp); + noTmp(); + m_resultp = getExprXZp(logAndp)->cloneTree(false); + } + + void visit(AstLogOr* const logOrp) override { + fourstateExpressionLogOrHandler(logOrp); + noTmp(); + m_resultp = getExprXZp(logOrp)->cloneTree(false); + } + + void visit(AstSel* const selp) override { + m_resultp = m_fourstateVisitor.getFourstateExpressionSelHandler( + selp, getFourstateExpressionXZ(selp->fromp(), false), false); + } + + void visit(AstNodeVarRef* const varRefp) override { + noTmp(); + m_fourstateVisitor.splitVar(varRefp->varp()); + AstNodeVarRef* const newp = varRefp->cloneTree(false); + if (!newp->name().empty()) newp->name(newp->name() + XZ_SUFFIX); + newp->varp(getSplittedXZ(varRefp->varp())); + newp->dtypeSetBitSized(varRefp->varp()->width(), varRefp->varp()->dtypep()->numeric()); + m_resultp = newp; + } + + void visit(AstNodeExpr* const nodep) override { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: Operator " + << nodep->typeName() + << " not supported in the four-state mode"); + // Workaround to avoid Internal errors + m_resultp = new AstConst{nodep->fileline(), AstConst::BitFalse{}}; + } + + void visit(AstNode* const nodep) override { // LCOV_EXCL_LINE + nodep->v3fatalSrc("This node shall be unreachable in this visitor"); + } + + AstNodeExpr* getCache(const AstNodeExpr* const keyp) override { return getExprXZp(keyp); } + void setCache(AstNodeExpr* keyp, AstNodeExpr* const valuep) override { + setExprXZp(keyp, valuep); + } + + public: + using FourstateExpressionVisitor::FourstateExpressionVisitor; + ~FourstateExpressionXZVisitor() override = default; + + AstNodeExpr* getFourstateExpressionXZ(AstNodeExpr* const exprp, + bool putIntoTmp = true) override { + if (!isFourstate(exprp)) return createZeroOrOnesp(exprp); + return get(exprp, putIntoTmp); + } + }; + + FourstateExpressionValueVisitor + m_fourstateGeneratorValueVisitor; // Generator of four-state expressions (value part) + FourstateExpressionXZVisitor + m_fourstateGeneratorXZVisitor; // Generator of four-state expressions (xz part) + + AstNodeExpr* getFourstateExpressionValue(AstNodeExpr* const exprp, bool putIntoTmp = false) { + if (AstCReset* const cresetp = VN_CAST(exprp, CReset)) { + // This is here instead in the visitor because CReset shall never be nested into + // the expression and also it is a very special case + return cresetp->cloneTree(false); + } + AstNodeExpr* const result + = m_fourstateGeneratorValueVisitor.getFourstateExpressionValue(exprp, putIntoTmp); + FourstateLogicTypePropagator{result}; + return result; + } + + AstNodeExpr* getFourstateExpressionXZ(AstNodeExpr* const exprp, bool putIntoTmp = false) { + if (AstCReset* const cresetp = VN_CAST(exprp, CReset)) { + // This is here instead in the visitor because CReset shall never be nested into + // the expression and also it is a very special case + return cresetp->cloneTree(false); + } + AstNodeExpr* const result + = m_fourstateGeneratorXZVisitor.getFourstateExpressionXZ(exprp, putIntoTmp); + FourstateLogicTypePropagator{result}; + return result; + } + + AstNodeExpr* getTruthExpr(AstNodeExpr* const exprp) { + UASSERT_OBJ(isFourstate(exprp), exprp, + "This function is ment to be called on four-state expressions"); + // a.value && !a.xz + FileLine* const flp = exprp->fileline(); + AstLogAnd* const result + = new AstLogAnd{flp, getFourstateExpressionValue(exprp), + new AstLogNot{flp, getFourstateExpressionXZ(exprp)}}; + setFourstate(result, false); + setFourstate(result->rhsp(), false); + return result; + } + + AstNodeExpr* getTwoStateCast(AstNodeExpr* const exprp) { + UASSERT_OBJ(isFourstate(exprp), exprp, + "This function is ment to be called on four-state expressions"); + // (a.value & (~a.xz)) + FileLine* const flp = exprp->fileline(); + AstAnd* const result = new AstAnd{flp, getFourstateExpressionValue(exprp), + new AstNot{flp, getFourstateExpressionXZ(exprp)}}; + setFourstate(result, false); + setFourstate(result->rhsp(), false); + return result; + } + + void visit(AstNodeAssign* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + TmpVarsReleaser tmpVarsReleaser{*this}; + if (isFourstate(nodep->lhsp())) { + AstNodeVarRef* const lhsVarRefp = VN_CAST(nodep->lhsp(), NodeVarRef); + if (VL_UNLIKELY(!lhsVarRefp)) { + nodep->v3warn( + E_UNSUPPORTED, + "Fourstate LHS other than a simple variable reference is not supported"); + return; + } + AstNodeAssign* const assignXZp = nodep->cloneTree(false); + { + assignXZp->lhsp()->unlinkFrBack()->deleteTree(); + assignXZp->rhsp()->unlinkFrBack()->deleteTree(); + AstNodeExpr* const newLhsp = getFourstateExpressionXZ(lhsVarRefp); + assignXZp->lhsp(newLhsp); + assignXZp->rhsp(getFourstateExpressionXZ(nodep->rhsp())); + assignXZp->dtypeFrom(newLhsp); + nodep->addNextHere(assignXZp); + } + { + AstNodeExpr* const newRhsp = getFourstateExpressionValue(nodep->rhsp()); + AstNodeExpr* const newLhsp = getFourstateExpressionValue(lhsVarRefp); + pushDeletep(nodep->lhsp()->unlinkFrBack()); + pushDeletep(nodep->rhsp()->unlinkFrBack()); + nodep->lhsp(newLhsp); + nodep->rhsp(newRhsp); + nodep->dtypeFrom(newLhsp); + } + if (AstAssignW* const assignWValuep = VN_CAST(nodep, AssignW)) { + assignWConflictResolution(lhsVarRefp->varp(), assignWValuep, + VN_AS(assignXZp, AssignW)); + if (const AstNode* const timingControlp = assignWValuep->timingControlp()) { + timingControlp->v3warn( + E_UNSUPPORTED, + "Continuous assignment delays are unsupported with --fourstate"); + } + } + } else if (isFourstate(nodep->rhsp())) { + AstNodeExpr* const newRhsp = getTwoStateCast(nodep->rhsp()); + pushDeletep(nodep->rhsp()->unlinkFrBack()); + nodep->rhsp(newRhsp); + } + iterateChildren(nodep); + } + + void visit(AstStmtExpr* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + TmpVarsReleaser tmpVarsReleaser{*this}; + auto isFourState = [nodep]() -> bool { + if (AstNodeFTaskRef* const taskRefp = VN_CAST(nodep->exprp(), NodeFTaskRef)) { + return isFourstate(taskRefp) && !isFTaskRefHandled(taskRefp); + } + return isFourstate(nodep->exprp()); + }; + if (isFourState()) { + AstNodeExpr* const exprp = nodep->exprp()->unlinkFrBack(); + nodep->exprp(getFourstateExpressionValue(exprp)); + AstNodeExpr* const newXzp = getFourstateExpressionXZ(exprp); + iterateChildren(newXzp); + AstStmtExpr* const newStmtExprp = new AstStmtExpr{nodep->fileline(), newXzp}; + nodep->addNextHere(newStmtExprp); + exprp->deleteTree(); + } + iterateChildren(nodep); + } + + void visit(AstLoopTest* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + TmpVarsReleaser tmpVarsReleaser{*this}; + if (isFourstate(nodep->condp())) { + AstNodeExpr* const condp = nodep->condp()->unlinkFrBack(); + nodep->condp(getTruthExpr(condp)); + condp->deleteTree(); + } + iterateChildren(nodep); + } + + void visit(AstNodeIf* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + if (isFourstate(nodep->condp())) { + AstNodeExpr* const condp = nodep->condp()->unlinkFrBack(); + nodep->condp(getTruthExpr(condp)); + condp->deleteTree(); + } + { + TmpVarsReleaser tmpVarsReleaser{*this}; + iterateAndNextNull(nodep->condp()); + } + iterateAndNextNull(nodep->thensp()); + iterateAndNextNull(nodep->elsesp()); + } + + void visit(AstCase* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + if (isFourstate(nodep->exprp())) { + nodep->v3warn(E_UNSUPPORTED, "All case statements with four-state value as an " + "expression are unsupported with --fourstate"); + } else { + iterate(nodep->exprp()); + } + iterateAndNextNull(nodep->itemsp()); + iterateAndNextNull(nodep->notParallelp()); + } + + void visit(AstCaseItem* const nodep) override { + for (AstNodeExpr* condp = nodep->condsp(); condp; + condp = VN_AS(condp->nextp(), NodeExpr)) { + if (isFourstate(condp)) { + nodep->v3warn(E_UNSUPPORTED, + "Four-state case items values are unsupported with --fourstate"); + } else { + iterate(condp); + } + } + iterateAndNextNull(nodep->stmtsp()); + } + + void visit(AstSenItem* const nodep) override { + if (!VN_IS(nodep->sensp(), FourstateExpr) && isFourstate(nodep->sensp())) { + AstNodeExpr* const sensp = nodep->sensp()->unlinkFrBack(); + nodep->sensp(new AstFourstateExpr{nodep->fileline(), + getFourstateExpressionValue(sensp), + getFourstateExpressionXZ(sensp)}); + sensp->deleteTree(); + } + iterateChildren(nodep); + } + + void visit(AstDisplay* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + if (nodep->filep() && isFourstate(nodep->filep())) { + nodep->filep()->v3warn( + CASTFOURSTATE, + "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"); + AstNodeExpr* const newp = getTwoStateCast(nodep->filep()); + nodep->filep()->unlinkFrBack()->deleteTree(); + nodep->filep(newp); + } + iterateChildren(nodep); + } + + void visit(AstFClose* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + if (isFourstate(nodep->filep())) { + nodep->filep()->v3warn( + CASTFOURSTATE, + "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"); + AstNodeExpr* const newp = getTwoStateCast(nodep->filep()); + nodep->filep()->unlinkFrBack()->deleteTree(); + nodep->filep(newp); + } + iterateChildren(nodep); + } + + void visit(AstFFlush* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + if (nodep->filep() && isFourstate(nodep->filep())) { + nodep->filep()->v3warn( + CASTFOURSTATE, + "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"); + AstNodeExpr* const newp = getTwoStateCast(nodep->filep()); + nodep->filep()->unlinkFrBack()->deleteTree(); + nodep->filep(newp); + } + iterateChildren(nodep); + } + + void cArgsHandler(AstNode* nodep) { + for (; nodep; nodep = nodep->nextp()) { + if (AstNodeExpr* const exprp = VN_CAST(nodep, NodeExpr)) { + if (isFourstate(exprp)) { + exprp->v3warn( + CASTFOURSTATE, + "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"); + AstNodeExpr* const newp = getTwoStateCast(exprp); + exprp->replaceWith(newp); + exprp->deleteTree(); + nodep = newp; + } + } + } + } + + void visit(AstCStmtUser* const nodep) override { + VL_RESTORER(m_currentStmtp); + m_currentStmtp = nodep; + cArgsHandler(nodep->nodesp()); + } + + void visit(AstCExprUser* const nodep) override { cArgsHandler(nodep->nodesp()); } + void visit(AstCExpr* const nodep) override { cArgsHandler(nodep->nodesp()); } + + void visit(AstSFormatF* const nodep) override { + for (AstNodeExpr* exprp = nodep->exprsp(); exprp; + exprp = VN_AS(exprp->nextp(), NodeExpr)) { + if (isFourstate(exprp)) { + exprp->v3warn( + CASTFOURSTATE, + "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"); + if (AstSFormatArg* const sformatArgp = VN_CAST(exprp, SFormatArg)) { + AstNodeExpr* const currentExprp = sformatArgp->exprp(); + currentExprp->replaceWith(getTwoStateCast(currentExprp)); + currentExprp->deleteTree(); + setFourstate(exprp, isFourstate(sformatArgp->exprp())); + } else { + AstNodeExpr* const newp = getTwoStateCast(exprp); + exprp->replaceWith(newp); + exprp->deleteTree(); + exprp = newp; + } + } + } + iterateChildren(nodep); + } + + void visit(AstPin* const nodep) override { + AstVar* const varp = nodep->modVarp(); + if (!(varp->fourstateComplementp() || varp->isFourstateComplement())) { + if (AstNodeExpr* const exprp = VN_CAST(nodep->exprp(), NodeExpr)) { + if (VL_UNLIKELY(!(VN_IS(exprp, NodeVarRef) || VN_IS(exprp, Const)))) { + // The issue lays in need for precalculations, potential side effects and lack + // of arguments order evaluation guarantees. The idea to support it is to do + // something like: + // Pin(foo()) + // will turn into: + // wire tmp; + // always assign tmp = foo; // <-- AstNodeAssign visitor will handle this + // Pin(tmp, tmp__Vxz) + exprp->v3warn(E_UNSUPPORTED, + "Cells with pins that are not a variable reference or a " + "constant are not supported with --fourstate"); + return; + } + if (needsSplitting(varp->dtypep())) { + AstPin* const newp + = new AstPin{nodep->fileline(), nodep->pinNum(), + nodep->name().empty() ? "" : nodep->name() + XZ_SUFFIX, + getFourstateExpressionXZ(exprp)}; + nodep->addNextHere(newp); + AstNodeExpr* const oldp = exprp->unlinkFrBack(); + nodep->exprp(getFourstateExpressionValue(oldp)); + oldp->deleteTree(); + splitVar(varp); // Ensure that variable is splitted + nodep->modVarp(getSplittedValue(varp)); + newp->modVarp(getSplittedXZ(varp)); + } else if (isFourstate(exprp)) { + AstNodeExpr* const oldp = exprp->unlinkFrBack(); + nodep->exprp(getTwoStateCast(oldp)); + oldp->deleteTree(); + } + } else if (!nodep->exprp() && needsSplitting(varp->dtypep())) { + AstPin* const newp + = new AstPin{nodep->fileline(), nodep->pinNum(), + nodep->name().empty() ? "" : nodep->name() + XZ_SUFFIX, nullptr}; + nodep->addNextHere(newp); + splitVar(varp); // Ensure that variable is splitted + nodep->modVarp(getSplittedValue(varp)); + newp->modVarp(getSplittedXZ(varp)); + } + } + iterateChildren(nodep); + } + + void visit(AstNodeFTaskRef* const nodep) override { + if (!isFTaskRefHandled(nodep)) { + setFTaskRefHandled(nodep); + size_t currentArgIdx = 0; + const FTaskPortsHelper& fTaskPortsHelper = getFTaskPortHelper(nodep->taskp()); + for (AstArg* argp = nodep->argsp(); argp; argp = VN_AS(argp->nextp(), Arg)) { + AstVar* const varp = fTaskPortsHelper.getArgPortVar(argp->name(), currentArgIdx); + ++currentArgIdx; + if (needsSplitting(varp->dtypep())) { + AstArg* const newp = new AstArg{ + argp->fileline(), argp->name().empty() ? "" : (varp->name() + XZ_SUFFIX), + getFourstateExpressionXZ(argp->exprp())}; + argp->addNextHere(newp); + AstNodeExpr* const oldp = argp->exprp()->unlinkFrBack(); + argp->exprp(getFourstateExpressionValue(oldp)); + oldp->deleteTree(); + if (!argp->name().empty()) argp->name(argp->name() + VALUE_SUFFIX); + argp = VN_AS(argp->nextp(), Arg); + } else if (isFourstate(argp->exprp())) { + AstNodeExpr* const oldp = argp->exprp()->unlinkFrBack(); + argp->exprp(getTwoStateCast(oldp)); + oldp->deleteTree(); + } + } + } + iterateChildren(nodep); + } + + void visit(AstCastWrap* const nodep) override { + if (!isFourstate(nodep) && isFourstate(nodep->lhsp())) { + AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack(); + nodep->lhsp(getTwoStateCast(lhsp)); + lhsp->deleteTree(); + } + iterateChildren(nodep); + } + + void visit(AstEqCase* const nodep) override { + FileLine* const flp = nodep->fileline(); + AstNodeExpr* newp; + if (isFourstate(nodep->lhsp()) && isFourstate(nodep->rhsp())) { + newp = new AstAnd{flp, + new AstEq{flp, getFourstateExpressionXZ(nodep->lhsp()), + getFourstateExpressionXZ(nodep->rhsp())}, + new AstEq{flp, getFourstateExpressionValue(nodep->lhsp()), + getFourstateExpressionValue(nodep->rhsp())}}; + } else if (isFourstate(nodep->lhsp()) || isFourstate(nodep->rhsp())) { + AstNodeExpr* const fourstateHsp + = isFourstate(nodep->lhsp()) ? nodep->lhsp() : nodep->rhsp(); + AstNodeExpr* const twostateHsp = isFourstate(nodep->lhsp()) + ? nodep->rhsp()->unlinkFrBack() + : nodep->lhsp()->unlinkFrBack(); + newp = new AstAnd{ + flp, new AstNot{flp, getFourstateExpressionXZ(fourstateHsp)}, + new AstEq{flp, getFourstateExpressionValue(fourstateHsp), twostateHsp}}; + } else { + newp = new AstEq{flp, nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack()}; + } + { FourstateLogicTypePropagator{newp}; } + VNRelinker relinker; + nodep->unlinkFrBack(&relinker); + relinker.relink(newp); + nodep->deleteTree(); + } + + void visit(AstNeqCase* const nodep) override { + FileLine* const flp = nodep->fileline(); + AstNodeExpr* newp; + if (isFourstate(nodep->lhsp()) && isFourstate(nodep->rhsp())) { + newp = new AstRedOr{ + flp, new AstOr{flp, + new AstXor{flp, getFourstateExpressionValue(nodep->lhsp()), + getFourstateExpressionValue(nodep->rhsp())}, + new AstXor{flp, getFourstateExpressionXZ(nodep->lhsp()), + getFourstateExpressionXZ(nodep->rhsp())}}}; + } else if (isFourstate(nodep->lhsp()) || isFourstate(nodep->rhsp())) { + AstNodeExpr* const fourstateHsp + = isFourstate(nodep->lhsp()) ? nodep->lhsp() : nodep->rhsp(); + AstNodeExpr* const twostateHsp = isFourstate(nodep->lhsp()) + ? nodep->rhsp()->unlinkFrBack() + : nodep->lhsp()->unlinkFrBack(); + newp = new AstRedOr{ + flp, new AstOr{ + flp, getFourstateExpressionXZ(fourstateHsp), + new AstXor{flp, getFourstateExpressionValue(fourstateHsp), twostateHsp}}}; + } else { + newp = new AstNeq{flp, nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack()}; + } + { FourstateLogicTypePropagator{newp}; } + VNRelinker relinker; + nodep->unlinkFrBack(&relinker); + relinker.relink(newp); + nodep->deleteTree(); + } + + void visit(AstSel* const nodep) override { + UASSERT_OBJ(!isFourstate(nodep), nodep, + "This visitor shall never be reached for four-state AstSel"); + if (!isSelpHandled(nodep)) { + setSelpHandled(nodep); + AstNodeExpr* const newp + = getFourstateExpressionSelHandler(nodep, nodep->fromp()->cloneTree(false), true); + { FourstateLogicTypePropagator{newp}; } + VNRelinker relinker; + nodep->unlinkFrBack(&relinker); + relinker.relink(newp); + nodep->deleteTree(); + } else { + iterateChildren(nodep); + } + } + + void visit(AstLogOr* const nodep) override { + if (!hasFourstateInSubtree(nodep->rhsp())) { + iterateChildren(nodep); + return; + } + UASSERT_OBJ(!isFourstate(nodep), nodep, + "This shall be reached only by two-state expressions"); + FileLine* const flp = nodep->fileline(); + AstVar* resultVarp = createTmp(nodep); + addPrecalculation(new AstAssign{flp, new AstVarRef{flp, resultVarp, VAccess::WRITE}, + new AstRedOr{flp, nodep->lhsp()->unlinkFrBack()}}); + addPrecalculation( + new AstIf{flp, new AstNot{flp, new AstVarRef{flp, resultVarp, VAccess::READ}}, + new AstAssign{flp, new AstVarRef{flp, resultVarp, VAccess::WRITE}, + new AstRedOr{flp, nodep->rhsp()->unlinkFrBack()}}}); + AstVarRef* const newp = new AstVarRef{flp, resultVarp, VAccess::READ}; + setFourstate(newp, false); + VNRelinker relinker; + nodep->unlinkFrBack(&relinker); + relinker.relink(newp); + nodep->deleteTree(); + } + + void visit(AstLogAnd* const nodep) override { + if (!hasFourstateInSubtree(nodep->rhsp())) { + iterateChildren(nodep); + return; + } + UASSERT_OBJ(!isFourstate(nodep), nodep, + "This shall be reached only by two-state expressions"); + FileLine* const flp = nodep->fileline(); + AstVar* resultVarp = createTmp(nodep); + addPrecalculation(new AstAssign{flp, new AstVarRef{flp, resultVarp, VAccess::WRITE}, + new AstRedOr{flp, nodep->lhsp()->unlinkFrBack()}}); + addPrecalculation( + new AstIf{flp, new AstVarRef{flp, resultVarp, VAccess::READ}, + new AstAssign{flp, new AstVarRef{flp, resultVarp, VAccess::WRITE}, + new AstRedOr{flp, nodep->rhsp()->unlinkFrBack()}}}); + AstVarRef* const newp = new AstVarRef{flp, resultVarp, VAccess::READ}; + setFourstate(newp, false); + VNRelinker relinker; + nodep->unlinkFrBack(&relinker); + relinker.relink(newp); + nodep->deleteTree(); + } + + void visit(AstCond* const nodep) override { + UASSERT_OBJ(!isFourstate(nodep), nodep, + "This shall be reached only by two-state expressions"); + if (!hasFourstateInSubtree(nodep->thenp()) && !hasFourstateInSubtree(nodep->elsep())) { + iterateChildren(nodep); + return; + } + FileLine* const flp = nodep->fileline(); + AstVar* resultVarp = createTmp(nodep); + addPrecalculation( + new AstIf{flp, nodep->condp()->unlinkFrBack(), + new AstAssign{flp, new AstVarRef{flp, resultVarp, VAccess::WRITE}, + nodep->thenp()->unlinkFrBack()}, + new AstAssign{flp, new AstVarRef{flp, resultVarp, VAccess::WRITE}, + nodep->elsep()->unlinkFrBack()}}); + AstVarRef* const newp = new AstVarRef{flp, resultVarp, VAccess::READ}; + setFourstate(newp, false); + VNRelinker relinker; + nodep->unlinkFrBack(&relinker); + relinker.relink(newp); + nodep->deleteTree(); + } + + void visit(AstCvtPackedToArray* const) override { + // Skip this tree since this expr is not supported anyway + } + void visit(AstTestPlusArgs* const) override { + // Skip this tree since this expr is not supported anyway + } + void visit(AstValuePlusArgs* const) override { + // Skip this tree since this expr is not supported anyway + } + void visit(AstFOpenMcd* const) override { + // Skip this tree since this expr is not supported anyway + } + void visit(AstCMethodHard* const) override { + // Skip this tree since this expr is not supported anyway + } + void visit(AstConsPackUOrStruct* const) override { + // Skip this tree since this expr is not supported anyway + } + + void visit(AstNodeFTask* const nodep) override { + VL_RESTORER(m_currentTmpSpotp); + VL_RESTORER(m_tmpUnusedVarps); + VL_RESTORER(m_tmpFuncLocal); + m_tmpFuncLocal = true; + m_currentTmpSpotp = nodep->stmtsp(); + TmpVarsReleaser releaser{*this}; + // Make sure FTasks use only local variables - prevents using tmp + // which may be used by a caller + for (auto& it : m_tmpUnusedVarps) it.clear(); + iterateChildren(nodep); + } + + void visit(AstVar* const nodep) override { + if (VL_UNLIKELY(!isDTypepSupported(nodep->dtypep()->skipRefp()).first)) { + nodep->v3warn(E_UNSUPPORTED, + "Variables of type: " << nodep->dtypep()->prettyDTypeNameQ() + << " are unsupported with --fourstate"); + } else if (needsSplitting(nodep->dtypep())) { + splitVar(nodep); + } + iterateChildren(nodep); + } + + void visit(AstPull* const nodep) override { + nodep->v3warn(E_UNSUPPORTED, "Pullups and pulldowns are unsupported with --fourstate"); + } + + void visit(AstModportVarRef* const nodep) override { + if ((nodep->exprp() && isFourstate(nodep->exprp())) + || (nodep->varp() && needsSplitting(nodep->varp()->dtypep()))) { + nodep->v3warn(E_UNSUPPORTED, "modports are not supported with --fourstate"); + } else { + iterateChildren(nodep); + } + } + + void visit(AstNodeModule* const nodep) override { + VL_RESTORER(m_currentTmpSpotp); + VL_RESTORER(m_tmpUnusedVarps); + m_currentTmpSpotp = nodep->stmtsp(); + iterateChildren(nodep); + } + + void visit(AstNodeStmt* const nodep) override { + VL_RESTORER(m_currentStmtp); + TmpVarsReleaser tmpVarsReleaser{*this}; + m_currentStmtp = nodep; + iterateChildren(nodep); + } + + void visit(AstNode* const nodep) override { iterateChildren(nodep); } + +public: + explicit FourstateVisitor(AstNetlist* const netlistp) + : m_tmpNames{"__VfourstateTmp"} + , m_fourstateGeneratorValueVisitor{*this} + , m_fourstateGeneratorXZVisitor{*this} { + { FourstateLogicTypePropagator{netlistp}; } + iterate(netlistp); + triorTriandReduce(m_assignWToTriand, triandReducer); + triorTriandReduce(m_assignWToTrior, triorReducer); + triorTriandReduce(m_assignWToWire, triReducer); + V3Error::abortIfErrors(); + { FourstateLogicTypePropagator{netlistp}; } + netlistp->foreach([](const AstNodeExpr* const nodep) { + if (VN_IS(nodep, NodeFTaskRef)) { + // Changing it in type propagador is unnecessary since those will be 100% handled + return; + } + if (isFourstate(nodep)) { + nodep->v3warn(E_UNSUPPORTED, "This four-state expression has not been handled"); + } + }); + V3Error::abortIfErrors(); + for (AstVar* const varp : m_varpsToRemove) varp->unlinkFrBack()->deleteTree(); + } + ~FourstateVisitor() override = default; +}; + +void V3Fourstate::fourstateAll(AstNetlist* netlistp) { + UINFO(2, __FUNCTION__ << ":"); + { FourstateVisitor{netlistp}; } + v3Global.setFourstateHandled(); + V3Global::dumpCheckGlobalTree("fourstate", 0, dumpTreeEitherLevel() >= 6); +} diff --git a/src/V3Fourstate.h b/src/V3Fourstate.h new file mode 100644 index 000000000..668a133b1 --- /dev/null +++ b/src/V3Fourstate.h @@ -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 diff --git a/src/V3Global.h b/src/V3Global.h index 4825a540a..86996aa50 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -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; } diff --git a/src/V3Number.cpp b/src/V3Number.cpp index d97e4ed50..8bba71f99 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -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); diff --git a/src/V3Number.h b/src/V3Number.h index d81e32d72..a5696c1f1 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -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 // diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 7a85c848d..fced12409 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -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()) { diff --git a/src/V3SenExprBuilder.h b/src/V3SenExprBuilder.h index ac9abf196..8d9dff56a 100644 --- a/src/V3SenExprBuilder.h +++ b/src/V3SenExprBuilder.h @@ -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}; diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 1a1ad6b89..44bef9df4 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -230,8 +230,11 @@ class TraceDeclVisitor final : public VNVisitor { FileLine& fileline() const { return m_vscp ? *m_vscp->fileline() : *m_cellp->fileline(); } }; std::vector m_entries; // Trace entries under current scope + std::map + 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::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 diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 57e12e478..712dcc03c 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -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; diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 86d688cc7..9e38ef9c2 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -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 diff --git a/src/V3WidthCommit.cpp b/src/V3WidthCommit.cpp index 651bff963..acfbc60fa 100644 --- a/src/V3WidthCommit.cpp +++ b/src/V3WidthCommit.cpp @@ -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 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); +} diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 03b18d23d..218d0c086 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -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; }; //###################################################################### diff --git a/src/Verilator.cpp b/src/Verilator.cpp index b1f0a9af0..da955925a 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -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()); diff --git a/test_regress/t/t_constraint_json_only.out b/test_regress/t/t_constraint_json_only.out index c18d8a989..323a32f19 100644 --- a/test_regress/t/t_constraint_json_only.out +++ b/test_regress/t/t_constraint_json_only.out @@ -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": [], diff --git a/test_regress/t/t_fourstate_arithmetics.py b/test_regress/t/t_fourstate_arithmetics.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_arithmetics.py @@ -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() diff --git a/test_regress/t/t_fourstate_arithmetics.v b/test_regress/t/t_fourstate_arithmetics.v new file mode 100644 index 000000000..ff18744d3 --- /dev/null +++ b/test_regress/t/t_fourstate_arithmetics.v @@ -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 diff --git a/test_regress/t/t_fourstate_assign_complex_lhs_unsup.out b/test_regress/t/t_fourstate_assign_complex_lhs_unsup.out new file mode 100644 index 000000000..3eac819dc --- /dev/null +++ b/test_regress/t/t_fourstate_assign_complex_lhs_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_assign_complex_lhs_unsup.py b/test_regress/t/t_fourstate_assign_complex_lhs_unsup.py new file mode 100755 index 000000000..df4b415fc --- /dev/null +++ b/test_regress/t/t_fourstate_assign_complex_lhs_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_assign_complex_lhs_unsup.v b/test_regress/t/t_fourstate_assign_complex_lhs_unsup.v new file mode 100644 index 000000000..63129c67c --- /dev/null +++ b/test_regress/t/t_fourstate_assign_complex_lhs_unsup.v @@ -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 diff --git a/test_regress/t/t_fourstate_case_onehot_unsup.out b/test_regress/t/t_fourstate_case_onehot_unsup.out new file mode 100644 index 000000000..676e33e70 --- /dev/null +++ b/test_regress/t/t_fourstate_case_onehot_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_case_onehot_unsup.py b/test_regress/t/t_fourstate_case_onehot_unsup.py new file mode 100755 index 000000000..dac5d252e --- /dev/null +++ b/test_regress/t/t_fourstate_case_onehot_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_casex_unsup.out b/test_regress/t/t_fourstate_casex_unsup.out new file mode 100644 index 000000000..c6e77dd43 --- /dev/null +++ b/test_regress/t/t_fourstate_casex_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_casex_unsup.py b/test_regress/t/t_fourstate_casex_unsup.py new file mode 100755 index 000000000..0b799ccab --- /dev/null +++ b/test_regress/t/t_fourstate_casex_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_cast.py b/test_regress/t/t_fourstate_cast.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_cast.py @@ -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() diff --git a/test_regress/t/t_fourstate_cast.v b/test_regress/t/t_fourstate_cast.v new file mode 100644 index 000000000..c4891344f --- /dev/null +++ b/test_regress/t/t_fourstate_cast.v @@ -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 diff --git a/test_regress/t/t_fourstate_comparison.py b/test_regress/t/t_fourstate_comparison.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_comparison.py @@ -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() diff --git a/test_regress/t/t_fourstate_comparison.v b/test_regress/t/t_fourstate_comparison.v new file mode 100644 index 000000000..6e728ed84 --- /dev/null +++ b/test_regress/t/t_fourstate_comparison.v @@ -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 diff --git a/test_regress/t/t_fourstate_complex_expr.out b/test_regress/t/t_fourstate_complex_expr.out new file mode 100644 index 000000000..4f5f5e20e --- /dev/null +++ b/test_regress/t/t_fourstate_complex_expr.out @@ -0,0 +1,15 @@ +1 +1 +x +1 +0 +1 +x +0 +0 +x +0 +0 +z +0 +*-* All Finished *-* diff --git a/test_regress/t/t_fourstate_complex_expr.py b/test_regress/t/t_fourstate_complex_expr.py new file mode 100755 index 000000000..45e8cf9cf --- /dev/null +++ b/test_regress/t/t_fourstate_complex_expr.py @@ -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() diff --git a/test_regress/t/t_fourstate_complex_expr.v b/test_regress/t/t_fourstate_complex_expr.v new file mode 100644 index 000000000..14c912db1 --- /dev/null +++ b/test_regress/t/t_fourstate_complex_expr.v @@ -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 diff --git a/test_regress/t/t_fourstate_complex_pin_unsup.out b/test_regress/t/t_fourstate_complex_pin_unsup.out new file mode 100644 index 000000000..8af2a4815 --- /dev/null +++ b/test_regress/t/t_fourstate_complex_pin_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_complex_pin_unsup.py b/test_regress/t/t_fourstate_complex_pin_unsup.py new file mode 100755 index 000000000..e89c716d0 --- /dev/null +++ b/test_regress/t/t_fourstate_complex_pin_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_complex_pin_unsup.v b/test_regress/t/t_fourstate_complex_pin_unsup.v new file mode 100644 index 000000000..6faf01111 --- /dev/null +++ b/test_regress/t/t_fourstate_complex_pin_unsup.v @@ -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 diff --git a/test_regress/t/t_fourstate_concat.py b/test_regress/t/t_fourstate_concat.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_concat.py @@ -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() diff --git a/test_regress/t/t_fourstate_concat.v b/test_regress/t/t_fourstate_concat.v new file mode 100644 index 000000000..bc1566282 --- /dev/null +++ b/test_regress/t/t_fourstate_concat.v @@ -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 diff --git a/test_regress/t/t_fourstate_cond.out b/test_regress/t/t_fourstate_cond.out new file mode 100644 index 000000000..7d94b78b5 --- /dev/null +++ b/test_regress/t/t_fourstate_cond.out @@ -0,0 +1,17 @@ +0 +0 +1 +1 +x +1 +0 +x +1 +1 +z +1 +0 +z +0 +0 +*-* All Finished *-* diff --git a/test_regress/t/t_fourstate_cond.py b/test_regress/t/t_fourstate_cond.py new file mode 100755 index 000000000..45e8cf9cf --- /dev/null +++ b/test_regress/t/t_fourstate_cond.py @@ -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() diff --git a/test_regress/t/t_fourstate_cond.v b/test_regress/t/t_fourstate_cond.v new file mode 100644 index 000000000..8ad269fc0 --- /dev/null +++ b/test_regress/t/t_fourstate_cond.v @@ -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 diff --git a/test_regress/t/t_fourstate_delay_var_unsup.out b/test_regress/t/t_fourstate_delay_var_unsup.out new file mode 100644 index 000000000..de04dc395 --- /dev/null +++ b/test_regress/t/t_fourstate_delay_var_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_delay_var_unsup.py b/test_regress/t/t_fourstate_delay_var_unsup.py new file mode 100755 index 000000000..5835cd937 --- /dev/null +++ b/test_regress/t/t_fourstate_delay_var_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_demo.out b/test_regress/t/t_fourstate_demo.out new file mode 100644 index 000000000..88c01b13e --- /dev/null +++ b/test_regress/t/t_fourstate_demo.out @@ -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 *-* diff --git a/test_regress/t/t_fourstate_demo.out.vcd b/test_regress/t/t_fourstate_demo.out.vcd new file mode 100644 index 000000000..58ac28b80 --- /dev/null +++ b/test_regress/t/t_fourstate_demo.out.vcd @@ -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 diff --git a/test_regress/t/t_fourstate_demo.py b/test_regress/t/t_fourstate_demo.py new file mode 100755 index 000000000..917b3981f --- /dev/null +++ b/test_regress/t/t_fourstate_demo.py @@ -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() diff --git a/test_regress/t/t_fourstate_demo.v b/test_regress/t/t_fourstate_demo.v new file mode 100644 index 000000000..520b47576 --- /dev/null +++ b/test_regress/t/t_fourstate_demo.v @@ -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 diff --git a/test_regress/t/t_fourstate_demo2.out b/test_regress/t/t_fourstate_demo2.out new file mode 100644 index 000000000..f7095935c --- /dev/null +++ b/test_regress/t/t_fourstate_demo2.out @@ -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 diff --git a/test_regress/t/t_fourstate_demo2.out.vcd b/test_regress/t/t_fourstate_demo2.out.vcd new file mode 100644 index 000000000..4d463dfce --- /dev/null +++ b/test_regress/t/t_fourstate_demo2.out.vcd @@ -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" diff --git a/test_regress/t/t_fourstate_demo2.py b/test_regress/t/t_fourstate_demo2.py new file mode 100755 index 000000000..917b3981f --- /dev/null +++ b/test_regress/t/t_fourstate_demo2.py @@ -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() diff --git a/test_regress/t/t_fourstate_demo2.v b/test_regress/t/t_fourstate_demo2.v new file mode 100644 index 000000000..bac28a4e1 --- /dev/null +++ b/test_regress/t/t_fourstate_demo2.v @@ -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 diff --git a/test_regress/t/t_fourstate_dfg_bin_to_one_hot.py b/test_regress/t/t_fourstate_dfg_bin_to_one_hot.py new file mode 100755 index 000000000..4a62360e3 --- /dev/null +++ b/test_regress/t/t_fourstate_dfg_bin_to_one_hot.py @@ -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() diff --git a/test_regress/t/t_fourstate_div.py b/test_regress/t/t_fourstate_div.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_div.py @@ -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() diff --git a/test_regress/t/t_fourstate_div.v b/test_regress/t/t_fourstate_div.v new file mode 100644 index 000000000..2023f1ae9 --- /dev/null +++ b/test_regress/t/t_fourstate_div.v @@ -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 diff --git a/test_regress/t/t_fourstate_dtype_unsup.out b/test_regress/t/t_fourstate_dtype_unsup.out new file mode 100644 index 000000000..319fc5d39 --- /dev/null +++ b/test_regress/t/t_fourstate_dtype_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_dtype_unsup.py b/test_regress/t/t_fourstate_dtype_unsup.py new file mode 100755 index 000000000..e89c716d0 --- /dev/null +++ b/test_regress/t/t_fourstate_dtype_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_dtype_unsup.v b/test_regress/t/t_fourstate_dtype_unsup.v new file mode 100644 index 000000000..2941e6018 --- /dev/null +++ b/test_regress/t/t_fourstate_dtype_unsup.v @@ -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 diff --git a/test_regress/t/t_fourstate_eqwild.py b/test_regress/t/t_fourstate_eqwild.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_eqwild.py @@ -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() diff --git a/test_regress/t/t_fourstate_eqwild.v b/test_regress/t/t_fourstate_eqwild.v new file mode 100644 index 000000000..6cc581e7e --- /dev/null +++ b/test_regress/t/t_fourstate_eqwild.v @@ -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 diff --git a/test_regress/t/t_fourstate_event_detection.py b/test_regress/t/t_fourstate_event_detection.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_event_detection.py @@ -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() diff --git a/test_regress/t/t_fourstate_event_detection.v b/test_regress/t/t_fourstate_event_detection.v new file mode 100644 index 000000000..a64115424 --- /dev/null +++ b/test_regress/t/t_fourstate_event_detection.v @@ -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 diff --git a/test_regress/t/t_fourstate_expr_not_handled_unsup.out b/test_regress/t/t_fourstate_expr_not_handled_unsup.out new file mode 100644 index 000000000..1b462b846 --- /dev/null +++ b/test_regress/t/t_fourstate_expr_not_handled_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_expr_not_handled_unsup.py b/test_regress/t/t_fourstate_expr_not_handled_unsup.py new file mode 100755 index 000000000..e89c716d0 --- /dev/null +++ b/test_regress/t/t_fourstate_expr_not_handled_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_expr_not_handled_unsup.v b/test_regress/t/t_fourstate_expr_not_handled_unsup.v new file mode 100644 index 000000000..a00b36c85 --- /dev/null +++ b/test_regress/t/t_fourstate_expr_not_handled_unsup.v @@ -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 diff --git a/test_regress/t/t_fourstate_extend.py b/test_regress/t/t_fourstate_extend.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_extend.py @@ -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() diff --git a/test_regress/t/t_fourstate_extend.v b/test_regress/t/t_fourstate_extend.v new file mode 100644 index 000000000..96ce9fbb0 --- /dev/null +++ b/test_regress/t/t_fourstate_extend.v @@ -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 diff --git a/test_regress/t/t_fourstate_format.out b/test_regress/t/t_fourstate_format.out new file mode 100644 index 000000000..36c2e68a2 --- /dev/null +++ b/test_regress/t/t_fourstate_format.out @@ -0,0 +1,6 @@ +0 +0 +0 +1 + 3 +*-* All Finished *-* diff --git a/test_regress/t/t_fourstate_format.py b/test_regress/t/t_fourstate_format.py new file mode 100755 index 000000000..29e3ad91e --- /dev/null +++ b/test_regress/t/t_fourstate_format.py @@ -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() diff --git a/test_regress/t/t_fourstate_format.v b/test_regress/t/t_fourstate_format.v new file mode 100644 index 000000000..bbea6a9b3 --- /dev/null +++ b/test_regress/t/t_fourstate_format.v @@ -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 diff --git a/test_regress/t/t_fourstate_format_unsup.out b/test_regress/t/t_fourstate_format_unsup.out new file mode 100644 index 000000000..6cd056d47 --- /dev/null +++ b/test_regress/t/t_fourstate_format_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_format_unsup.py b/test_regress/t/t_fourstate_format_unsup.py new file mode 100755 index 000000000..34889bce8 --- /dev/null +++ b/test_regress/t/t_fourstate_format_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_fourstate_fst_unsup.out b/test_regress/t/t_fourstate_fourstate_fst_unsup.out new file mode 100644 index 000000000..73959e760 --- /dev/null +++ b/test_regress/t/t_fourstate_fourstate_fst_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_fourstate_fst_unsup.py b/test_regress/t/t_fourstate_fourstate_fst_unsup.py new file mode 100755 index 000000000..3b8bc4a32 --- /dev/null +++ b/test_regress/t/t_fourstate_fourstate_fst_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_fourstate_unsup.out b/test_regress/t/t_fourstate_fourstate_unsup.out old mode 100755 new mode 100644 diff --git a/test_regress/t/t_fourstate_fwrite.out b/test_regress/t/t_fourstate_fwrite.out new file mode 100644 index 000000000..530a8a796 --- /dev/null +++ b/test_regress/t/t_fourstate_fwrite.out @@ -0,0 +1,4 @@ +0 +0 +0 +1 diff --git a/test_regress/t/t_fourstate_fwrite.py b/test_regress/t/t_fourstate_fwrite.py new file mode 100755 index 000000000..883638308 --- /dev/null +++ b/test_regress/t/t_fourstate_fwrite.py @@ -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() diff --git a/test_regress/t/t_fourstate_fwrite.v b/test_regress/t/t_fourstate_fwrite.v new file mode 100644 index 000000000..9526edd87 --- /dev/null +++ b/test_regress/t/t_fourstate_fwrite.v @@ -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 diff --git a/test_regress/t/t_fourstate_hier_block_type_param_unsup.out b/test_regress/t/t_fourstate_hier_block_type_param_unsup.out new file mode 100644 index 000000000..7c08c08b6 --- /dev/null +++ b/test_regress/t/t_fourstate_hier_block_type_param_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_hier_block_type_param_unsup.py b/test_regress/t/t_fourstate_hier_block_type_param_unsup.py new file mode 100755 index 000000000..a5be5a470 --- /dev/null +++ b/test_regress/t/t_fourstate_hier_block_type_param_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_inst_unsup.out b/test_regress/t/t_fourstate_inst_unsup.out new file mode 100644 index 000000000..e5b4dc0bf --- /dev/null +++ b/test_regress/t/t_fourstate_inst_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_inst_unsup.py b/test_regress/t/t_fourstate_inst_unsup.py new file mode 100755 index 000000000..2e1d8023d --- /dev/null +++ b/test_regress/t/t_fourstate_inst_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_lint_unused_iface_unsup.out b/test_regress/t/t_fourstate_lint_unused_iface_unsup.out new file mode 100644 index 000000000..55c88f356 --- /dev/null +++ b/test_regress/t/t_fourstate_lint_unused_iface_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_lint_unused_iface_unsup.py b/test_regress/t/t_fourstate_lint_unused_iface_unsup.py new file mode 100755 index 000000000..0254d6d10 --- /dev/null +++ b/test_regress/t/t_fourstate_lint_unused_iface_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_logand.out b/test_regress/t/t_fourstate_logand.out new file mode 100644 index 000000000..4b40ce433 --- /dev/null +++ b/test_regress/t/t_fourstate_logand.out @@ -0,0 +1,29 @@ +0 +0 +0 +0 +1 +0 +1 +1 +1 +x +1 +z +x +0 +x +1 +x +x +x +z +z +0 +z +1 +z +x +z +z +*-* All Finished *-* diff --git a/test_regress/t/t_fourstate_logand.py b/test_regress/t/t_fourstate_logand.py new file mode 100755 index 000000000..45e8cf9cf --- /dev/null +++ b/test_regress/t/t_fourstate_logand.py @@ -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() diff --git a/test_regress/t/t_fourstate_logand.v b/test_regress/t/t_fourstate_logand.v new file mode 100644 index 000000000..bb4202180 --- /dev/null +++ b/test_regress/t/t_fourstate_logand.v @@ -0,0 +1,41 @@ +// 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(0) && f(0)) !== 0) $stop; + if ((f(0) && f(1)) !== 0) $stop; + if ((f(0) && f('x)) !== 0) $stop; + if ((f(0) && f('z)) !== 0) $stop; + + if ((f(1) && f(0)) !== 0) $stop; + if ((f(1) && f(1)) !== 1) $stop; + if ((f(1) && f('x)) !== 'x) $stop; + if ((f(1) && f('z)) !== 'x) $stop; + + if ((f('x) && f(0)) !== 0) $stop; + if ((f('x) && f(1)) !== 'x) $stop; + if ((f('x) && f('x)) !== 'x) $stop; + if ((f('x) && f('z)) !== 'x) $stop; + + if ((f('z) && f(0)) !== 0) $stop; + if ((f('z) && f(1)) !== 'x) $stop; + if ((f('z) && f('x)) !== 'x) $stop; + if ((f('z) && f('z)) !== 'x) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_logor.out b/test_regress/t/t_fourstate_logor.out new file mode 100644 index 000000000..130a3017b --- /dev/null +++ b/test_regress/t/t_fourstate_logor.out @@ -0,0 +1,29 @@ +0 +0 +0 +1 +0 +x +0 +z +1 +1 +1 +1 +x +0 +x +1 +x +x +x +z +z +0 +z +1 +z +x +z +z +*-* All Finished *-* diff --git a/test_regress/t/t_fourstate_logor.py b/test_regress/t/t_fourstate_logor.py new file mode 100755 index 000000000..45e8cf9cf --- /dev/null +++ b/test_regress/t/t_fourstate_logor.py @@ -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() diff --git a/test_regress/t/t_fourstate_logor.v b/test_regress/t/t_fourstate_logor.v new file mode 100644 index 000000000..510feeee6 --- /dev/null +++ b/test_regress/t/t_fourstate_logor.v @@ -0,0 +1,41 @@ +// 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(0) || f(0)) !== 0) $stop; + if ((f(0) || f(1)) !== 1) $stop; + if ((f(0) || f('x)) !== 'x) $stop; + if ((f(0) || f('z)) !== 'x) $stop; + + if ((f(1) || f(0)) !== 1) $stop; + if ((f(1) || f(1)) !== 1) $stop; + if ((f(1) || f('x)) !== 1) $stop; + if ((f(1) || f('z)) !== 1) $stop; + + if ((f('x) || f(0)) !== 'x) $stop; + if ((f('x) || f(1)) !== 1) $stop; + if ((f('x) || f('x)) !== 'x) $stop; + if ((f('x) || f('z)) !== 'x) $stop; + + if ((f('z) || f(0)) !== 'x) $stop; + if ((f('z) || f(1)) !== 1) $stop; + if ((f('z) || f('x)) !== 'x) $stop; + if ((f('z) || f('z)) !== 'x) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_loop.py b/test_regress/t/t_fourstate_loop.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_loop.py @@ -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() diff --git a/test_regress/t/t_fourstate_loop.v b/test_regress/t/t_fourstate_loop.v new file mode 100644 index 000000000..a4630452e --- /dev/null +++ b/test_regress/t/t_fourstate_loop.v @@ -0,0 +1,23 @@ +// 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 bit foo; + static logic bar; + + if (bar !== 'x) $stop; + while (!bar) $stop; + while (bar) $stop; + while (bar) $stop; + while (!foo) foo++; + while (!bar) bar++; + while (!foo) $stop; + while (!bar) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_math_wide_inc.py b/test_regress/t/t_fourstate_math_wide_inc.py new file mode 100755 index 000000000..ae26390b8 --- /dev/null +++ b/test_regress/t/t_fourstate_math_wide_inc.py @@ -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: 2024 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.top_filename = 't/t_math_wide_inc.v' + +test.compile(verilator_flags2=['--fourstate', '-Wno-FUTURE']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_fourstate_mixed_short_circuting.py b/test_regress/t/t_fourstate_mixed_short_circuting.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_mixed_short_circuting.py @@ -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() diff --git a/test_regress/t/t_fourstate_mixed_short_circuting.v b/test_regress/t/t_fourstate_mixed_short_circuting.v new file mode 100644 index 000000000..f21e6550d --- /dev/null +++ b/test_regress/t/t_fourstate_mixed_short_circuting.v @@ -0,0 +1,30 @@ +// 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 bar(); + calls++; + return 'x; + endfunction + + initial begin + if ((bit'(`IMPURE_ONE) || bit'(bar() || ('x && 1))) !== 1) $stop; + if ((bit'(!`IMPURE_ONE) && bit'(bar() || ('x && 1))) !== 0) $stop; + if ((`IMPURE_ONE ? 0 : bit'(bar())) !== 0) $stop; + if (calls !== 0) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_mod_interface_array4.py b/test_regress/t/t_fourstate_mod_interface_array4.py new file mode 100755 index 000000000..9c4e3fd5d --- /dev/null +++ b/test_regress/t/t_fourstate_mod_interface_array4.py @@ -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_mod_interface_array4.v" + +test.compile(v_flags2=["--fourstate", "--Wno-FUTURE", "-Wno-CASTFOURSTATE"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_fourstate_mod_interface_array5.out b/test_regress/t/t_fourstate_mod_interface_array5.out new file mode 100644 index 000000000..ed07a3992 --- /dev/null +++ b/test_regress/t/t_fourstate_mod_interface_array5.out @@ -0,0 +1,8 @@ +%Error-UNSUPPORTED: t/t_mod_interface_array5.v:60:55: Hierarchical references are unsupported in assigns with --fourstate + 60 | assign muxIn[muxIdx].value = demuxOut[demuxIdx].value; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_mod_interface_array5.v:24:71: Hierarchical references are unsupported in assigns with --fourstate + 24 | for (i = 0; i < N; i = i + 1) assign downstream[i].value = upstream.value; + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_fourstate_mod_interface_array5.py b/test_regress/t/t_fourstate_mod_interface_array5.py new file mode 100755 index 000000000..33e7f557e --- /dev/null +++ b/test_regress/t/t_fourstate_mod_interface_array5.py @@ -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_mod_interface_array5.v' + +test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE', '-Wno-CASTFOURSTATE'], + fails=True, + expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_fourstate_module_input_default_value_unsup.out b/test_regress/t/t_fourstate_module_input_default_value_unsup.out new file mode 100644 index 000000000..55c88f356 --- /dev/null +++ b/test_regress/t/t_fourstate_module_input_default_value_unsup.out @@ -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 diff --git a/test_regress/t/t_fourstate_module_input_default_value_unsup.py b/test_regress/t/t_fourstate_module_input_default_value_unsup.py new file mode 100755 index 000000000..72be2018f --- /dev/null +++ b/test_regress/t/t_fourstate_module_input_default_value_unsup.py @@ -0,0 +1,22 @@ +#!/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_module_input_default_value.v' + +test.top_filename = 't/t_lint_unused_iface.v' + +test.lint(verilator_flags2=['--fourstate', '-Wno-FUTURE'], + fails=True, + expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_fourstate_neqwild.py b/test_regress/t/t_fourstate_neqwild.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_neqwild.py @@ -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() diff --git a/test_regress/t/t_fourstate_neqwild.v b/test_regress/t/t_fourstate_neqwild.v new file mode 100644 index 000000000..aec1c41ae --- /dev/null +++ b/test_regress/t/t_fourstate_neqwild.v @@ -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)) !== 0) $stop; + if ((f('b101) !=? f('b10x)) !== 0) $stop; + if ((f('b101) !=? f('b1xz)) !== 0) $stop; + if ((f('b101) !=? f('b10z)) !== 0) $stop; + if ((f('b1z1) !=? f('b10z)) !== 'x) $stop; + if ((f('b1xx) !=? f('b1xx)) !== 0) $stop; + if ((f('b1x1) !=? f('b101)) !== 'x) $stop; + if ((f('b1zz) !=? f('b1xz)) !== 0) $stop; + if ((f('bz01) !=? f('b1zx)) !== 'x) $stop; + if ((f('b001) !=? f('b1zx)) !== 1) $stop; + if ((f('b001) !=? f('b111)) !== 1) $stop; + if ((f('bx00) !=? f('bxz1)) !== 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_noreturn.py b/test_regress/t/t_fourstate_noreturn.py new file mode 100755 index 000000000..f4af2006f --- /dev/null +++ b/test_regress/t/t_fourstate_noreturn.py @@ -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-NORETURN']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_fourstate_noreturn.v b/test_regress/t/t_fourstate_noreturn.v new file mode 100644 index 000000000..43b6b9f55 --- /dev/null +++ b/test_regress/t/t_fourstate_noreturn.v @@ -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 + +module t; + function logic foo(); + $c(";"); + endfunction + function logic bar(); + endfunction + + initial begin + if (foo() !== 'x) $stop; + if (bar() !== 'x) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_operator_unsup.out b/test_regress/t/t_fourstate_operator_unsup.out new file mode 100644 index 000000000..3aa476472 --- /dev/null +++ b/test_regress/t/t_fourstate_operator_unsup.out @@ -0,0 +1,6 @@ +%Error-UNSUPPORTED: t/t_fourstate_operator_unsup.v:11:11: Unsupported: Operator POWSS not supported in the four-state mode + : ... note: In instance 't' + 11 | y = 2 ** x; + | ^~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_fourstate_operator_unsup.py b/test_regress/t/t_fourstate_operator_unsup.py new file mode 100755 index 000000000..df4b415fc --- /dev/null +++ b/test_regress/t/t_fourstate_operator_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_operator_unsup.v b/test_regress/t/t_fourstate_operator_unsup.v new file mode 100644 index 000000000..1f72e2ff0 --- /dev/null +++ b/test_regress/t/t_fourstate_operator_unsup.v @@ -0,0 +1,13 @@ +// 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 integer x; + static integer y; + y = 2 ** x; + end +endmodule diff --git a/test_regress/t/t_fourstate_pull_unsup.out b/test_regress/t/t_fourstate_pull_unsup.out new file mode 100644 index 000000000..e3acee275 --- /dev/null +++ b/test_regress/t/t_fourstate_pull_unsup.out @@ -0,0 +1,18 @@ +%Error-UNSUPPORTED: t/t_fourstate_pull_unsup.v:10:10: Pullups and pulldowns are unsupported with --fourstate + : ... note: In instance 't' + 10 | pullup d_0_pup (iolines[0]); + | ^~~~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_fourstate_pull_unsup.v:11:10: Pullups and pulldowns are unsupported with --fourstate + : ... note: In instance 't' + 11 | pullup d_1_pup (iolines[1]); + | ^~~~~~~ +%Error-UNSUPPORTED: t/t_fourstate_pull_unsup.v:12:12: Pullups and pulldowns are unsupported with --fourstate + : ... note: In instance 't' + 12 | pulldown d_2_pdown (iolines[2]); + | ^~~~~~~~~ +%Error-UNSUPPORTED: t/t_fourstate_pull_unsup.v:13:12: Pullups and pulldowns are unsupported with --fourstate + : ... note: In instance 't' + 13 | pulldown d_3_pdown (iolines[3]); + | ^~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_fourstate_pull_unsup.py b/test_regress/t/t_fourstate_pull_unsup.py new file mode 100755 index 000000000..e89c716d0 --- /dev/null +++ b/test_regress/t/t_fourstate_pull_unsup.py @@ -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() diff --git a/test_regress/t/t_fourstate_pull_unsup.v b/test_regress/t/t_fourstate_pull_unsup.v new file mode 100644 index 000000000..fe45e0145 --- /dev/null +++ b/test_regress/t/t_fourstate_pull_unsup.v @@ -0,0 +1,14 @@ +// 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 ( + inout [7:0] iolines +); + pullup d_0_pup (iolines[0]); + pullup d_1_pup (iolines[1]); + pulldown d_2_pdown (iolines[2]); + pulldown d_3_pdown (iolines[3]); +endmodule diff --git a/test_regress/t/t_fourstate_redand.py b/test_regress/t/t_fourstate_redand.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_redand.py @@ -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() diff --git a/test_regress/t/t_fourstate_redand.v b/test_regress/t/t_fourstate_redand.v new file mode 100644 index 000000000..1c79694c4 --- /dev/null +++ b/test_regress/t/t_fourstate_redand.v @@ -0,0 +1,36 @@ +// 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('b00000000000000000000000000000000) !== 0) $stop; + if (&f('b00000000000000000000000000000100) !== 0) $stop; + if (&f('b10000000000000000000000000010100) !== 0) $stop; + if (&f('b0000000000000000000000000000000x) !== 0) $stop; + if (&f('b00000000000000000000000000000z0x) !== 0) $stop; + if (&f('b00000000000000000000000000000z00) !== 0) $stop; + if (&f('b0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) !== 0) $stop; + if (&f('b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) !== 'x) $stop; + if (&f('b1zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz) !== 'x) $stop; + if (&f('b1zzzzzzzzzzzzzzzzzzzzzxxxxxxxxxx) !== 'x) $stop; + if (&f('b1111111111111111111111111111111x) !== 'x) $stop; + if (&f('b1111111111111111111111111111111z) !== 'x) $stop; + if (&f('b11111111111111111111111111111111) !== 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_redor.py b/test_regress/t/t_fourstate_redor.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_redor.py @@ -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() diff --git a/test_regress/t/t_fourstate_redor.v b/test_regress/t/t_fourstate_redor.v new file mode 100644 index 000000000..21cd682b2 --- /dev/null +++ b/test_regress/t/t_fourstate_redor.v @@ -0,0 +1,30 @@ +// 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(0) !== 0) $stop; + if (|f(1) !== 1) $stop; + if (|f('x) !== 'x) $stop; + if (|f('z) !== 'x) $stop; + if (|f('b0000z0000) !== 'x) $stop; + if (|f('b0000x0000) !== 'x) $stop; + if (|f('b0000z0010) !== 1) $stop; + if (|f('b0000x0100) !== 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_redxor.py b/test_regress/t/t_fourstate_redxor.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_redxor.py @@ -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() diff --git a/test_regress/t/t_fourstate_redxor.v b/test_regress/t/t_fourstate_redxor.v new file mode 100644 index 000000000..167d1a708 --- /dev/null +++ b/test_regress/t/t_fourstate_redxor.v @@ -0,0 +1,34 @@ +// 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(0) !== 0) $stop; + if (^f(1) !== 1) $stop; + if (^f('x) !== 'x) $stop; + if (^f('z) !== 'x) $stop; + if (^f('b0000z0000) !== 'x) $stop; + if (^f('b0000x0000) !== 'x) $stop; + if (^f('b0000z0010) !== 'x) $stop; + if (^f('b0000x0100) !== 'x) $stop; + if (^f('b0000z0011) !== 'x) $stop; + if (^f('b0000x0101) !== 'x) $stop; + if (^f('b000000011) !== 0) $stop; + if (^f('b000000101) !== 0) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_replicate.py b/test_regress/t/t_fourstate_replicate.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_replicate.py @@ -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() diff --git a/test_regress/t/t_fourstate_replicate.v b/test_regress/t/t_fourstate_replicate.v new file mode 100644 index 000000000..04601e613 --- /dev/null +++ b/test_regress/t/t_fourstate_replicate.v @@ -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 ({1{f(1'b0)}} !== 1'b0) $stop; + if ({1{f(1'b1)}} !== 1'b1) $stop; + if ({1{f(1'bx)}} !== 1'bx) $stop; + if ({1{f(1'bz)}} !== 1'bz) $stop; + + if ({2{f(1'b0)}} !== 2'b00) $stop; + if ({2{f(1'b1)}} !== 2'b11) $stop; + if ({2{f(1'bx)}} !== 2'bxx) $stop; + if ({2{f(1'bz)}} !== 2'bzz) $stop; + + if ({3{f(1'b0)}} !== 3'b000) $stop; + if ({3{f(1'b1)}} !== 3'b111) $stop; + if ({3{f(1'bx)}} !== 3'bxxx) $stop; + if ({3{f(1'bz)}} !== 3'bzzz) $stop; + + if ({4{f(1'b0)}} !== 4'b0000) $stop; + if ({4{f(1'b1)}} !== 4'b1111) $stop; + if ({4{f(1'bx)}} !== 4'bxxxx) $stop; + if ({4{f(1'bz)}} !== 4'bzzzz) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_sel.out b/test_regress/t/t_fourstate_sel.out new file mode 100644 index 000000000..acc0a9ed7 --- /dev/null +++ b/test_regress/t/t_fourstate_sel.out @@ -0,0 +1,23 @@ +0: 0 +1: z +2: x +3: 1 +4: x +y: z +z: 0 +w: x +a: 1 +b: 1 +c: x +0: 0 +1: 0 +2: 0 +3: 1 +4: 1 +y: 0 +z: 0 +w: 0 +a: 1 +b: 1 +c: 0 +*-* All Finished *-* diff --git a/test_regress/t/t_fourstate_sel.py b/test_regress/t/t_fourstate_sel.py new file mode 100755 index 000000000..a693598e2 --- /dev/null +++ b/test_regress/t/t_fourstate_sel.py @@ -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', '-Wno-FUTURE', '-Wno-WIDTHEXPAND', '-Wno-WIDTHTRUNC' +]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_fourstate_sel.v b/test_regress/t/t_fourstate_sel.v new file mode 100644 index 000000000..c0579f525 --- /dev/null +++ b/test_regress/t/t_fourstate_sel.v @@ -0,0 +1,100 @@ +// 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 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 [5:0] bar(); + $write("Side effect\n"); + return 'b1x01xz; + endfunction + + bit sideEffect = 0; + function logic [13:0] foo(); + sideEffect = 1; + return 'z; + endfunction + + initial begin + static logic [4:0] x = 5'bx1xz0; + static bit [4:0] xx = 5'b11000; + static logic y = 1; + static bit [15:0] yy = `IMPURE_ONE; + static logic z = 0; + static logic [3:0] w = 7; + static logic [3:0] a = 3; + static bit [3:0] b = 3; + static bit [3:0] c = 7; + $write("0: "); + f(x[`IMPURE_ONE ? 0 : 'x]); + $write("1: "); + f(x[`IMPURE_ONE ? 1 : 'x]); + $write("2: "); + f(x[`IMPURE_ONE ? 2 : 'x]); + $write("3: "); + f(x[`IMPURE_ONE ? 3 : 'x]); + $write("4: "); + f(x[`IMPURE_ONE ? 4 : 'x]); + $write("y: "); + f(x[`IMPURE_ONE ? y : 'x]); + $write("z: "); + f(x[`IMPURE_ONE ? z : 'x]); + $write("w: "); + f(x[`IMPURE_ONE ? w : 'x]); + $write("a: "); + f(x[`IMPURE_ONE ? a : 'x]); + $write("b: "); + f(x[`IMPURE_ONE ? b : 0]); + $write("c: "); + f(x[`IMPURE_ONE ? c : 'x]); + $write("0: "); + f(xx[`IMPURE_ONE ? 0 : 'x]); + $write("1: "); + f(xx[`IMPURE_ONE ? 1 : 'x]); + $write("2: "); + f(xx[`IMPURE_ONE ? 2 : 'x]); + $write("3: "); + f(xx[`IMPURE_ONE ? 3 : 'x]); + $write("4: "); + f(xx[`IMPURE_ONE ? 4 : 'x]); + $write("y: "); + f(xx[`IMPURE_ONE ? y : 'x]); + $write("z: "); + f(xx[`IMPURE_ONE ? z : 'x]); + $write("w: "); + f(xx[`IMPURE_ONE ? w : 'x]); + $write("a: "); + f(xx[`IMPURE_ONE ? a : 'x]); + $write("b: "); + f(xx[`IMPURE_ONE ? b : 'x]); + $write("c: "); + f(xx[`IMPURE_ONE ? c : 'x]); + if (xx[yy] !== 0) $stop; + if (x[yy] !== 'z) $stop; + // verilator lint_off SELRANGE + if (foo() [101] !== 'x) $stop; + if (x[7] !== 'x) $stop; + if (xx[7] !== 0) $stop; + // verilator lint_on SELRANGE + if (sideEffect !== 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_shift.py b/test_regress/t/t_fourstate_shift.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_shift.py @@ -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() diff --git a/test_regress/t/t_fourstate_shift.v b/test_regress/t/t_fourstate_shift.v new file mode 100644 index 000000000..911d1b577 --- /dev/null +++ b/test_regress/t/t_fourstate_shift.v @@ -0,0 +1,39 @@ +// 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('b1) << f('b0)) !== 'b1) $stop; + if ((f('b1) << f('b1)) !== 'b10) $stop; + if ((f('b1) << f('b10)) !== 'b100) $stop; + if ((f('b0x01) << f('b10)) !== 'b0x0100) $stop; + if ((f('b0zx01) << f('b10)) !== 'b0zx0100) $stop; + if ((f('b1) << f('b1x)) !== 'x) $stop; + if ((f('b1) << f('b1z)) !== 'x) $stop; + + if ((f('b1) >> f('b0)) !== 'b1) $stop; + if ((f('b10) >> f('b0)) !== 'b10) $stop; + if ((f('b1) >> f('b1)) !== 'b0) $stop; + if ((f('b100) >> f('b10)) !== 'b1) $stop; + if ((f('b0x010000) >> f('b10)) !== 'b0x0100) $stop; + if ((f('b0zx01) >> f('b10)) !== 'b0zx) $stop; + if ((f('b1) >> f('b1x)) !== 'x) $stop; + if ((f('b1) >> f('b1z)) !== 'x) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_fourstate_twostate.py b/test_regress/t/t_fourstate_twostate.py new file mode 100755 index 000000000..1d8214921 --- /dev/null +++ b/test_regress/t/t_fourstate_twostate.py @@ -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() diff --git a/test_regress/t/t_fourstate_twostate.v b/test_regress/t/t_fourstate_twostate.v new file mode 100644 index 000000000..8ae5119f3 --- /dev/null +++ b/test_regress/t/t_fourstate_twostate.v @@ -0,0 +1,32 @@ +// 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 + +class Foo; + task test(logic x, bit y, bit z); + if (x !== 'z) $stop; + if (y !== 0) $stop; + if (z !== 0) $stop; + endtask + + function bit foo(bit z); + if (!z) $stop; + return 0; + endfunction + + function bit bar(logic x, bit y, bit z); + return x || !y || z || (foo(z) || foo(z)); + endfunction +endclass + +module t; + initial begin + static Foo foo = new; + foo.test('z, 'z, 0); + if (foo.bar('z, 'z, 0) !== 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_iface_typedef_scale.py b/test_regress/t/t_iface_typedef_scale.py index 3d1724e3e..818ac8fd9 100755 --- a/test_regress/t/t_iface_typedef_scale.py +++ b/test_regress/t/t_iface_typedef_scale.py @@ -19,7 +19,7 @@ test.scenarios('vlt') test.top_filename = test.obj_dir + "/t_iface_typedef_scale.sv" N_TYPEDEFS = 5000 -MAX_COMPILE_SECS = 10 # Generous budget; catches O(N^2) explosion where 5k typedefs would take minutes without the cache +MAX_COMPILE_SECS = 20 # Generous budget; catches O(N^2) explosion where 5k typedefs would take minutes without the cache def gen(filename, n): diff --git a/test_regress/t/t_json_only_begin_hier.out b/test_regress/t/t_json_only_begin_hier.out index 68cc2bd11..4c008fcb1 100644 --- a/test_regress/t/t_json_only_begin_hier.out +++ b/test_regress/t/t_json_only_begin_hier.out @@ -2,7 +2,7 @@ "modulesp": [ {"type":"MODULE","name":"test","addr":"(E)","loc":"d,21:8,21:12","origName":"test","verilogName":"test","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"N","addr":"(F)","loc":"d,22:10,22:11","dtypep":"(G)","origName":"N","verilogName":"N","direction":"NONE","isUsedLoopIdx":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"GENVAR","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"N","addr":"(F)","loc":"d,22:10,22:11","dtypep":"(G)","origName":"N","verilogName":"N","direction":"NONE","isUsedLoopIdx":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"GENVAR","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"GENBLOCK","name":"FOR_GENERATE","addr":"(H)","loc":"d,24:5,24:8","implied":true,"genforp": [],"itemsp": []}, {"type":"GENBLOCK","name":"FOR_GENERATE[0]","addr":"(I)","loc":"d,25:14,25:24","genforp": [], "itemsp": [ @@ -27,7 +27,7 @@ "stmtsp": [ {"type":"GENBLOCK","name":"submod_gen","addr":"(T)","loc":"d,11:18,11:28","genforp": [], "itemsp": [ - {"type":"VAR","name":"l1_sig","addr":"(U)","loc":"d,12:10,12:16","dtypep":"(V)","origName":"l1_sig","verilogName":"l1_sig","direction":"NONE","lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"l1_sig","addr":"(U)","loc":"d,12:10,12:16","dtypep":"(V)","origName":"l1_sig","verilogName":"l1_sig","direction":"NONE","lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"GENBLOCK","name":"nested_gen","addr":"(W)","loc":"d,13:20,13:30","genforp": [], "itemsp": [ {"type":"CELL","name":"submod_nested","addr":"(X)","loc":"d,14:15,14:28","origName":"submod_nested","verilogName":"submod_nested","modp":"(Y)","pinsp": [],"paramsp": [],"rangep": [],"intfRefsp": []} diff --git a/test_regress/t/t_json_only_first.out b/test_regress/t/t_json_only_first.out index 0f60e9c25..b41e5f17a 100644 --- a/test_regress/t/t_json_only_first.out +++ b/test_regress/t/t_json_only_first.out @@ -2,22 +2,22 @@ "modulesp": [ {"type":"MODULE","name":"t","addr":"(E)","loc":"d,7:8,7:9","origName":"t","verilogName":"t","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"q","addr":"(F)","loc":"d,16:21,16:22","dtypep":"(G)","origName":"q","verilogName":"q","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"clk","addr":"(H)","loc":"d,14:9,14:12","dtypep":"(I)","origName":"clk","verilogName":"clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"d","addr":"(J)","loc":"d,15:15,15:16","dtypep":"(G)","origName":"d","verilogName":"d","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"between","addr":"(K)","loc":"d,18:15,18:22","dtypep":"(G)","origName":"between","verilogName":"between","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"direct_named","addr":"(L)","loc":"d,19:9,19:21","dtypep":"(I)","origName":"direct_named","verilogName":"direct_named","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"computed_named","addr":"(M)","loc":"d,20:9,20:23","dtypep":"(I)","origName":"computed_named","verilogName":"computed_named","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"anonymous_expr","addr":"(N)","loc":"d,21:9,21:23","dtypep":"(I)","origName":"anonymous_expr","verilogName":"anonymous_expr","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"S_IDLE","addr":"(O)","loc":"d,23:26,23:32","dtypep":"(P)","origName":"S_IDLE","verilogName":"S_IDLE","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"q","addr":"(F)","loc":"d,16:21,16:22","dtypep":"(G)","origName":"q","verilogName":"q","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(H)","loc":"d,14:9,14:12","dtypep":"(I)","origName":"clk","verilogName":"clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"d","addr":"(J)","loc":"d,15:15,15:16","dtypep":"(G)","origName":"d","verilogName":"d","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"between","addr":"(K)","loc":"d,18:15,18:22","dtypep":"(G)","origName":"between","verilogName":"between","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"direct_named","addr":"(L)","loc":"d,19:9,19:21","dtypep":"(I)","origName":"direct_named","verilogName":"direct_named","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"computed_named","addr":"(M)","loc":"d,20:9,20:23","dtypep":"(I)","origName":"computed_named","verilogName":"computed_named","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"anonymous_expr","addr":"(N)","loc":"d,21:9,21:23","dtypep":"(I)","origName":"anonymous_expr","verilogName":"anonymous_expr","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"S_IDLE","addr":"(O)","loc":"d,23:26,23:32","dtypep":"(P)","origName":"S_IDLE","verilogName":"S_IDLE","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"2'h0","addr":"(Q)","loc":"d,23:35,23:40","dtypep":"(R)"} ],"attrsp": []}, - {"type":"VAR","name":"S_FETCH","addr":"(S)","loc":"d,24:26,24:33","dtypep":"(P)","origName":"S_FETCH","verilogName":"S_FETCH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"S_FETCH","addr":"(S)","loc":"d,24:26,24:33","dtypep":"(P)","origName":"S_FETCH","verilogName":"S_FETCH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"2'h1","addr":"(T)","loc":"d,24:36,24:41","dtypep":"(R)"} ],"attrsp": []}, - {"type":"VAR","name":"S_EXEC","addr":"(U)","loc":"d,25:26,25:32","dtypep":"(P)","origName":"S_EXEC","verilogName":"S_EXEC","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"S_EXEC","addr":"(U)","loc":"d,25:26,25:32","dtypep":"(P)","origName":"S_EXEC","verilogName":"S_EXEC","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"2'h2","addr":"(V)","loc":"d,25:43,25:44","dtypep":"(P)"} ],"attrsp": []}, @@ -120,9 +120,9 @@ ]}, {"type":"MODULE","name":"mod2","addr":"(IC)","loc":"d,61:8,61:12","origName":"mod2","verilogName":"mod2","level":2,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"clk","addr":"(QC)","loc":"d,62:11,62:14","dtypep":"(I)","origName":"clk","verilogName":"clk","direction":"INPUT","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"d","addr":"(KC)","loc":"d,63:17,63:18","dtypep":"(G)","origName":"d","verilogName":"d","direction":"INPUT","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"q","addr":"(NC)","loc":"d,64:23,64:24","dtypep":"(G)","origName":"q","verilogName":"q","direction":"OUTPUT","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(QC)","loc":"d,62:11,62:14","dtypep":"(I)","origName":"clk","verilogName":"clk","direction":"INPUT","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"d","addr":"(KC)","loc":"d,63:17,63:18","dtypep":"(G)","origName":"d","verilogName":"d","direction":"INPUT","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"q","addr":"(NC)","loc":"d,64:23,64:24","dtypep":"(G)","origName":"q","verilogName":"q","direction":"OUTPUT","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"ALWAYS","name":"","addr":"(SC)","loc":"d,67:12,67:13","keyword":"cont_assign","sentreep": [], "stmtsp": [ {"type":"ASSIGNW","name":"","addr":"(TC)","loc":"d,67:12,67:13","dtypep":"(G)", @@ -136,14 +136,14 @@ ]}, {"type":"MODULE","name":"mod1__W4","addr":"(XB)","loc":"d,47:8,47:12","origName":"mod1","verilogName":"mod1","level":2,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"WIDTH","addr":"(WC)","loc":"d,48:15,48:20","dtypep":"(XC)","origName":"WIDTH","verilogName":"WIDTH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"GPARAM","dtypeName":"logic","isGParam":true,"isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"WIDTH","addr":"(WC)","loc":"d,48:15,48:20","dtypep":"(XC)","origName":"WIDTH","verilogName":"WIDTH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"GPARAM","dtypeName":"logic","isGParam":true,"isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"32'sh4","addr":"(YC)","loc":"d,32:14,32:15","dtypep":"(ZC)"} ],"attrsp": []}, - {"type":"VAR","name":"clk","addr":"(CC)","loc":"d,50:11,50:14","dtypep":"(I)","origName":"clk","verilogName":"clk","direction":"INPUT","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"d","addr":"(FC)","loc":"d,51:23,51:24","dtypep":"(G)","origName":"d","verilogName":"d","direction":"INPUT","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"q","addr":"(ZB)","loc":"d,52:30,52:31","dtypep":"(G)","origName":"q","verilogName":"q","direction":"OUTPUT","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"IGNORED","addr":"(AD)","loc":"d,55:14,55:21","dtypep":"(XC)","origName":"IGNORED","verilogName":"IGNORED","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"clk","addr":"(CC)","loc":"d,50:11,50:14","dtypep":"(I)","origName":"clk","verilogName":"clk","direction":"INPUT","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"d","addr":"(FC)","loc":"d,51:23,51:24","dtypep":"(G)","origName":"d","verilogName":"d","direction":"INPUT","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"q","addr":"(ZB)","loc":"d,52:30,52:31","dtypep":"(G)","origName":"q","verilogName":"q","direction":"OUTPUT","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"IGNORED","addr":"(AD)","loc":"d,55:14,55:21","dtypep":"(XC)","origName":"IGNORED","verilogName":"IGNORED","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"32'sh1","addr":"(BD)","loc":"d,55:24,55:25","dtypep":"(ZC)"} ],"attrsp": []}, diff --git a/test_regress/t/t_json_only_flat.out b/test_regress/t/t_json_only_flat.out index 6b3d6ca6c..7c8326507 100644 --- a/test_regress/t/t_json_only_flat.out +++ b/test_regress/t/t_json_only_flat.out @@ -2,39 +2,39 @@ "modulesp": [ {"type":"MODULE","name":"$root","addr":"(F)","loc":"d,7:8,7:9","origName":"$root","verilogName":"$root","level":1,"modPublic":true,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"q","addr":"(G)","loc":"d,16:21,16:22","dtypep":"(H)","origName":"q","verilogName":"q","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"clk","addr":"(I)","loc":"d,14:9,14:12","dtypep":"(J)","origName":"clk","verilogName":"clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"d","addr":"(K)","loc":"d,15:15,15:16","dtypep":"(H)","origName":"d","verilogName":"d","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.q","addr":"(L)","loc":"d,16:21,16:22","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.clk","addr":"(M)","loc":"d,14:9,14:12","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.d","addr":"(N)","loc":"d,15:15,15:16","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.between","addr":"(O)","loc":"d,18:15,18:22","dtypep":"(H)","origName":"between","verilogName":"between","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.direct_named","addr":"(P)","loc":"d,19:9,19:21","dtypep":"(J)","origName":"direct_named","verilogName":"direct_named","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.computed_named","addr":"(Q)","loc":"d,20:9,20:23","dtypep":"(J)","origName":"computed_named","verilogName":"computed_named","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.anonymous_expr","addr":"(R)","loc":"d,21:9,21:23","dtypep":"(J)","origName":"anonymous_expr","verilogName":"anonymous_expr","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.S_IDLE","addr":"(S)","loc":"d,23:26,23:32","dtypep":"(T)","origName":"S_IDLE","verilogName":"S_IDLE","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"q","addr":"(G)","loc":"d,16:21,16:22","dtypep":"(H)","origName":"q","verilogName":"q","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(I)","loc":"d,14:9,14:12","dtypep":"(J)","origName":"clk","verilogName":"clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"d","addr":"(K)","loc":"d,15:15,15:16","dtypep":"(H)","origName":"d","verilogName":"d","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.q","addr":"(L)","loc":"d,16:21,16:22","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.clk","addr":"(M)","loc":"d,14:9,14:12","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.d","addr":"(N)","loc":"d,15:15,15:16","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.between","addr":"(O)","loc":"d,18:15,18:22","dtypep":"(H)","origName":"between","verilogName":"between","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.direct_named","addr":"(P)","loc":"d,19:9,19:21","dtypep":"(J)","origName":"direct_named","verilogName":"direct_named","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.computed_named","addr":"(Q)","loc":"d,20:9,20:23","dtypep":"(J)","origName":"computed_named","verilogName":"computed_named","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.anonymous_expr","addr":"(R)","loc":"d,21:9,21:23","dtypep":"(J)","origName":"anonymous_expr","verilogName":"anonymous_expr","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.S_IDLE","addr":"(S)","loc":"d,23:26,23:32","dtypep":"(T)","origName":"S_IDLE","verilogName":"S_IDLE","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"2'h0","addr":"(U)","loc":"d,23:35,23:40","dtypep":"(V)"} ],"attrsp": []}, - {"type":"VAR","name":"t.S_FETCH","addr":"(W)","loc":"d,24:26,24:33","dtypep":"(T)","origName":"S_FETCH","verilogName":"S_FETCH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"t.S_FETCH","addr":"(W)","loc":"d,24:26,24:33","dtypep":"(T)","origName":"S_FETCH","verilogName":"S_FETCH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"2'h1","addr":"(X)","loc":"d,24:36,24:41","dtypep":"(V)"} ],"attrsp": []}, - {"type":"VAR","name":"t.S_EXEC","addr":"(Y)","loc":"d,25:26,25:32","dtypep":"(T)","origName":"S_EXEC","verilogName":"S_EXEC","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"t.S_EXEC","addr":"(Y)","loc":"d,25:26,25:32","dtypep":"(T)","origName":"S_EXEC","verilogName":"S_EXEC","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"2'h2","addr":"(Z)","loc":"d,25:43,25:44","dtypep":"(T)"} ],"attrsp": []}, - {"type":"VAR","name":"t.cell2.clk","addr":"(AB)","loc":"d,62:11,62:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell2.d","addr":"(BB)","loc":"d,63:17,63:18","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell2.q","addr":"(CB)","loc":"d,64:23,64:24","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.WIDTH","addr":"(DB)","loc":"d,48:15,48:20","dtypep":"(EB)","origName":"WIDTH","verilogName":"WIDTH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"GPARAM","dtypeName":"logic","isGParam":true,"isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"t.cell2.clk","addr":"(AB)","loc":"d,62:11,62:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell2.d","addr":"(BB)","loc":"d,63:17,63:18","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell2.q","addr":"(CB)","loc":"d,64:23,64:24","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.WIDTH","addr":"(DB)","loc":"d,48:15,48:20","dtypep":"(EB)","origName":"WIDTH","verilogName":"WIDTH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"GPARAM","dtypeName":"logic","isGParam":true,"isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"32'sh4","addr":"(FB)","loc":"d,32:14,32:15","dtypep":"(GB)"} ],"attrsp": []}, - {"type":"VAR","name":"t.cell1.clk","addr":"(HB)","loc":"d,50:11,50:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.d","addr":"(IB)","loc":"d,51:23,51:24","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.q","addr":"(JB)","loc":"d,52:30,52:31","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.IGNORED","addr":"(KB)","loc":"d,55:14,55:21","dtypep":"(EB)","origName":"IGNORED","verilogName":"IGNORED","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"t.cell1.clk","addr":"(HB)","loc":"d,50:11,50:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.d","addr":"(IB)","loc":"d,51:23,51:24","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.q","addr":"(JB)","loc":"d,52:30,52:31","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.IGNORED","addr":"(KB)","loc":"d,55:14,55:21","dtypep":"(EB)","origName":"IGNORED","verilogName":"IGNORED","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"32'sh1","addr":"(LB)","loc":"d,55:24,55:25","dtypep":"(GB)"} ],"attrsp": []}, diff --git a/test_regress/t/t_json_only_flat_no_inline_mod.out b/test_regress/t/t_json_only_flat_no_inline_mod.out index b87493b24..158a3ccaf 100644 --- a/test_regress/t/t_json_only_flat_no_inline_mod.out +++ b/test_regress/t/t_json_only_flat_no_inline_mod.out @@ -2,9 +2,9 @@ "modulesp": [ {"type":"MODULE","name":"$root","addr":"(F)","loc":"d,11:8,11:11","origName":"$root","verilogName":"$root","level":1,"modPublic":true,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"i_clk","addr":"(G)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"top.i_clk","addr":"(I)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"top.f.i_clk","addr":"(J)","loc":"d,7:24,7:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"i_clk","addr":"(G)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"top.i_clk","addr":"(I)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"top.f.i_clk","addr":"(J)","loc":"d,7:24,7:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,11:8,11:11","senTreesp": [], "scopep": [ {"type":"SCOPE","name":"TOP","addr":"(K)","loc":"d,11:8,11:11","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(F)", diff --git a/test_regress/t/t_json_only_flat_pub_mod.out b/test_regress/t/t_json_only_flat_pub_mod.out index b87493b24..158a3ccaf 100644 --- a/test_regress/t/t_json_only_flat_pub_mod.out +++ b/test_regress/t/t_json_only_flat_pub_mod.out @@ -2,9 +2,9 @@ "modulesp": [ {"type":"MODULE","name":"$root","addr":"(F)","loc":"d,11:8,11:11","origName":"$root","verilogName":"$root","level":1,"modPublic":true,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"i_clk","addr":"(G)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"top.i_clk","addr":"(I)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"top.f.i_clk","addr":"(J)","loc":"d,7:24,7:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"i_clk","addr":"(G)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"top.i_clk","addr":"(I)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"top.f.i_clk","addr":"(J)","loc":"d,7:24,7:29","dtypep":"(H)","origName":"i_clk","verilogName":"i_clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,11:8,11:11","senTreesp": [], "scopep": [ {"type":"SCOPE","name":"TOP","addr":"(K)","loc":"d,11:8,11:11","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(F)", diff --git a/test_regress/t/t_json_only_flat_vlvbound.out b/test_regress/t/t_json_only_flat_vlvbound.out index 1725da9ef..e008c3350 100644 --- a/test_regress/t/t_json_only_flat_vlvbound.out +++ b/test_regress/t/t_json_only_flat_vlvbound.out @@ -2,14 +2,14 @@ "modulesp": [ {"type":"MODULE","name":"$root","addr":"(F)","loc":"d,7:8,7:21","origName":"$root","verilogName":"$root","level":1,"modPublic":true,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"i_a","addr":"(G)","loc":"d,8:24,8:27","dtypep":"(H)","origName":"i_a","verilogName":"i_a","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"i_b","addr":"(I)","loc":"d,9:24,9:27","dtypep":"(H)","origName":"i_b","verilogName":"i_b","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"o_a","addr":"(J)","loc":"d,10:24,10:27","dtypep":"(K)","origName":"o_a","verilogName":"o_a","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"o_b","addr":"(L)","loc":"d,11:24,11:27","dtypep":"(K)","origName":"o_b","verilogName":"o_b","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"vlvbound_test.i_a","addr":"(M)","loc":"d,8:24,8:27","dtypep":"(H)","origName":"i_a","verilogName":"i_a","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"vlvbound_test.i_b","addr":"(N)","loc":"d,9:24,9:27","dtypep":"(H)","origName":"i_b","verilogName":"i_b","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"vlvbound_test.o_a","addr":"(O)","loc":"d,10:24,10:27","dtypep":"(K)","origName":"o_a","verilogName":"o_a","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"vlvbound_test.o_b","addr":"(P)","loc":"d,11:24,11:27","dtypep":"(K)","origName":"o_b","verilogName":"o_b","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"i_a","addr":"(G)","loc":"d,8:24,8:27","dtypep":"(H)","origName":"i_a","verilogName":"i_a","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"i_b","addr":"(I)","loc":"d,9:24,9:27","dtypep":"(H)","origName":"i_b","verilogName":"i_b","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"o_a","addr":"(J)","loc":"d,10:24,10:27","dtypep":"(K)","origName":"o_a","verilogName":"o_a","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"o_b","addr":"(L)","loc":"d,11:24,11:27","dtypep":"(K)","origName":"o_b","verilogName":"o_b","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"vlvbound_test.i_a","addr":"(M)","loc":"d,8:24,8:27","dtypep":"(H)","origName":"i_a","verilogName":"i_a","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"vlvbound_test.i_b","addr":"(N)","loc":"d,9:24,9:27","dtypep":"(H)","origName":"i_b","verilogName":"i_b","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"vlvbound_test.o_a","addr":"(O)","loc":"d,10:24,10:27","dtypep":"(K)","origName":"o_a","verilogName":"o_a","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"vlvbound_test.o_b","addr":"(P)","loc":"d,11:24,11:27","dtypep":"(K)","origName":"o_b","verilogName":"o_b","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,7:8,7:21","senTreesp": [], "scopep": [ {"type":"SCOPE","name":"TOP","addr":"(Q)","loc":"d,7:8,7:21","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(F)", @@ -318,14 +318,14 @@ ]} ],"inlinesp": []} ]}, - {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__0__Vfuncout","addr":"(QB)","loc":"d,14:34,14:37","dtypep":"(K)","origName":"__Vfunc_vlvbound_test__DOT__foo__0__Vfuncout","verilogName":"__Vfunc_vlvbound_test.foo__0__Vfuncout","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__0__val","addr":"(SB)","loc":"d,14:57,14:60","dtypep":"(H)","origName":"__Vfunc_vlvbound_test__DOT__foo__0__val","verilogName":"__Vfunc_vlvbound_test.foo__0__val","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__0__ret","addr":"(UB)","loc":"d,15:17,15:20","dtypep":"(K)","origName":"__Vfunc_vlvbound_test__DOT__foo__0__ret","verilogName":"__Vfunc_vlvbound_test.foo__0__ret","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__0__i","addr":"(XB)","loc":"d,16:13,16:14","dtypep":"(WB)","origName":"__Vfunc_vlvbound_test__DOT__foo__0__i","verilogName":"__Vfunc_vlvbound_test.foo__0__i","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__1__Vfuncout","addr":"(ZB)","loc":"d,14:34,14:37","dtypep":"(K)","origName":"__Vfunc_vlvbound_test__DOT__foo__1__Vfuncout","verilogName":"__Vfunc_vlvbound_test.foo__1__Vfuncout","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__1__val","addr":"(BC)","loc":"d,14:57,14:60","dtypep":"(H)","origName":"__Vfunc_vlvbound_test__DOT__foo__1__val","verilogName":"__Vfunc_vlvbound_test.foo__1__val","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__1__ret","addr":"(DC)","loc":"d,15:17,15:20","dtypep":"(K)","origName":"__Vfunc_vlvbound_test__DOT__foo__1__ret","verilogName":"__Vfunc_vlvbound_test.foo__1__ret","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__1__i","addr":"(FC)","loc":"d,16:13,16:14","dtypep":"(WB)","origName":"__Vfunc_vlvbound_test__DOT__foo__1__i","verilogName":"__Vfunc_vlvbound_test.foo__1__i","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__0__Vfuncout","addr":"(QB)","loc":"d,14:34,14:37","dtypep":"(K)","origName":"__Vfunc_vlvbound_test__DOT__foo__0__Vfuncout","verilogName":"__Vfunc_vlvbound_test.foo__0__Vfuncout","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__0__val","addr":"(SB)","loc":"d,14:57,14:60","dtypep":"(H)","origName":"__Vfunc_vlvbound_test__DOT__foo__0__val","verilogName":"__Vfunc_vlvbound_test.foo__0__val","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__0__ret","addr":"(UB)","loc":"d,15:17,15:20","dtypep":"(K)","origName":"__Vfunc_vlvbound_test__DOT__foo__0__ret","verilogName":"__Vfunc_vlvbound_test.foo__0__ret","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__0__i","addr":"(XB)","loc":"d,16:13,16:14","dtypep":"(WB)","origName":"__Vfunc_vlvbound_test__DOT__foo__0__i","verilogName":"__Vfunc_vlvbound_test.foo__0__i","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__1__Vfuncout","addr":"(ZB)","loc":"d,14:34,14:37","dtypep":"(K)","origName":"__Vfunc_vlvbound_test__DOT__foo__1__Vfuncout","verilogName":"__Vfunc_vlvbound_test.foo__1__Vfuncout","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__1__val","addr":"(BC)","loc":"d,14:57,14:60","dtypep":"(H)","origName":"__Vfunc_vlvbound_test__DOT__foo__1__val","verilogName":"__Vfunc_vlvbound_test.foo__1__val","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__1__ret","addr":"(DC)","loc":"d,15:17,15:20","dtypep":"(K)","origName":"__Vfunc_vlvbound_test__DOT__foo__1__ret","verilogName":"__Vfunc_vlvbound_test.foo__1__ret","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"__Vfunc_vlvbound_test.foo__1__i","addr":"(FC)","loc":"d,16:13,16:14","dtypep":"(WB)","origName":"__Vfunc_vlvbound_test__DOT__foo__1__i","verilogName":"__Vfunc_vlvbound_test.foo__1__i","direction":"NONE","lifetime":"NONE","varType":"BLOCKTEMP","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]} ],"filesp": [], "miscsp": [ diff --git a/test_regress/t/t_json_only_output.out b/test_regress/t/t_json_only_output.out index c66ad57a3..698954810 100644 --- a/test_regress/t/t_json_only_output.out +++ b/test_regress/t/t_json_only_output.out @@ -2,7 +2,7 @@ "modulesp": [ {"type":"MODULE","name":"m","addr":"(E)","loc":"d,7:8,7:9","origName":"m","verilogName":"m","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"clk","addr":"(F)","loc":"d,8:11,8:14","dtypep":"(G)","origName":"clk","verilogName":"clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"clk","addr":"(F)","loc":"d,8:11,8:14","dtypep":"(G)","origName":"clk","verilogName":"clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]} ],"filesp": [], "miscsp": [ diff --git a/test_regress/t/t_json_only_primary_io.out b/test_regress/t/t_json_only_primary_io.out index a611f6917..cfeef6c7f 100644 --- a/test_regress/t/t_json_only_primary_io.out +++ b/test_regress/t/t_json_only_primary_io.out @@ -2,11 +2,11 @@ "modulesp": [ {"type":"MODULE","name":"top","addr":"(E)","loc":"d,7:8,7:11","origName":"top","verilogName":"top","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"clk","addr":"(F)","loc":"d,13:9,13:12","dtypep":"(G)","origName":"clk","verilogName":"clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"a1","addr":"(H)","loc":"d,14:9,14:11","dtypep":"(G)","origName":"a1","verilogName":"a1","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"a2","addr":"(I)","loc":"d,15:9,15:11","dtypep":"(G)","origName":"a2","verilogName":"a2","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"ready","addr":"(J)","loc":"d,16:10,16:15","dtypep":"(G)","origName":"ready","verilogName":"ready","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"ready_reg","addr":"(K)","loc":"d,18:8,18:17","dtypep":"(G)","origName":"ready_reg","verilogName":"ready_reg","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(F)","loc":"d,13:9,13:12","dtypep":"(G)","origName":"clk","verilogName":"clk","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"a1","addr":"(H)","loc":"d,14:9,14:11","dtypep":"(G)","origName":"a1","verilogName":"a1","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"a2","addr":"(I)","loc":"d,15:9,15:11","dtypep":"(G)","origName":"a2","verilogName":"a2","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"ready","addr":"(J)","loc":"d,16:10,16:15","dtypep":"(G)","origName":"ready","verilogName":"ready","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"ready_reg","addr":"(K)","loc":"d,18:8,18:17","dtypep":"(G)","origName":"ready_reg","verilogName":"ready_reg","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"CELL","name":"and_cell","addr":"(L)","loc":"d,20:11,20:19","origName":"and_cell","verilogName":"and_cell","modp":"(M)", "pinsp": [ {"type":"PIN","name":"a1","addr":"(N)","loc":"d,21:8,21:10","svDotName":true,"modVarp":"(O)","modPTypep":"UNLINKED", @@ -35,9 +35,9 @@ ]}, {"type":"MODULE","name":"and2_x1","addr":"(M)","loc":"d,29:8,29:15","origName":"and2_x1","verilogName":"and2_x1","level":2,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"a1","addr":"(O)","loc":"d,30:16,30:18","dtypep":"(G)","origName":"a1","verilogName":"a1","direction":"INPUT","lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"a2","addr":"(R)","loc":"d,31:16,31:18","dtypep":"(G)","origName":"a2","verilogName":"a2","direction":"INPUT","lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"zn","addr":"(U)","loc":"d,32:17,32:19","dtypep":"(G)","origName":"zn","verilogName":"zn","direction":"OUTPUT","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"a1","addr":"(O)","loc":"d,30:16,30:18","dtypep":"(G)","origName":"a1","verilogName":"a1","direction":"INPUT","lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"a2","addr":"(R)","loc":"d,31:16,31:18","dtypep":"(G)","origName":"a2","verilogName":"a2","direction":"INPUT","lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"zn","addr":"(U)","loc":"d,32:17,32:19","dtypep":"(G)","origName":"zn","verilogName":"zn","direction":"OUTPUT","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"ALWAYS","name":"","addr":"(AB)","loc":"d,34:13,34:14","keyword":"cont_assign","sentreep": [], "stmtsp": [ {"type":"ASSIGNW","name":"","addr":"(BB)","loc":"d,34:13,34:14","dtypep":"(G)", diff --git a/test_regress/t/t_json_only_tag.out b/test_regress/t/t_json_only_tag.out index c7e9999c6..f82fb2592 100644 --- a/test_regress/t/t_json_only_tag.out +++ b/test_regress/t/t_json_only_tag.out @@ -2,14 +2,14 @@ "modulesp": [ {"type":"MODULE","name":"m","addr":"(E)","loc":"d,12:8,12:9","origName":"m","verilogName":"m","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"clk_ip","addr":"(F)","loc":"d,13:11,13:17","dtypep":"(G)","origName":"clk_ip","verilogName":"clk_ip","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"rst_ip","addr":"(H)","loc":"d,14:11,14:17","dtypep":"(G)","origName":"rst_ip","verilogName":"rst_ip","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"foo_op","addr":"(I)","loc":"d,15:12,15:18","dtypep":"(G)","origName":"foo_op","verilogName":"foo_op","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk_ip","addr":"(F)","loc":"d,13:11,13:17","dtypep":"(G)","origName":"clk_ip","verilogName":"clk_ip","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"rst_ip","addr":"(H)","loc":"d,14:11,14:17","dtypep":"(G)","origName":"rst_ip","verilogName":"rst_ip","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"foo_op","addr":"(I)","loc":"d,15:12,15:18","dtypep":"(G)","origName":"foo_op","verilogName":"foo_op","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TYPEDEF","name":"my_struct","addr":"(J)","loc":"d,25:5,25:14","dtypep":"(K)","childDTypep": [],"attrsp": []}, {"type":"CELL","name":"itop","addr":"(L)","loc":"d,29:7,29:11","origName":"itop","verilogName":"itop","modp":"(M)","pinsp": [],"paramsp": [],"rangep": [],"intfRefsp": []}, - {"type":"VAR","name":"itop","addr":"(N)","loc":"d,29:7,29:11","dtypep":"(O)","origName":"itop__Viftop","verilogName":"itop__Viftop","direction":"NONE","lifetime":"VSTATICI","varType":"IFACEREF","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"this_struct","addr":"(P)","loc":"d,31:13,31:24","dtypep":"(Q)","origName":"this_struct","verilogName":"this_struct","direction":"NONE","lifetime":"VSTATICI","varType":"VAR","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"dotted","addr":"(R)","loc":"d,33:15,33:21","dtypep":"(S)","origName":"dotted","verilogName":"dotted","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"itop","addr":"(N)","loc":"d,29:7,29:11","dtypep":"(O)","origName":"itop__Viftop","verilogName":"itop__Viftop","direction":"NONE","lifetime":"VSTATICI","varType":"IFACEREF","dtypeName":"","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"this_struct","addr":"(P)","loc":"d,31:13,31:24","dtypep":"(Q)","origName":"this_struct","verilogName":"this_struct","direction":"NONE","lifetime":"VSTATICI","varType":"VAR","dtypeName":"","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"dotted","addr":"(R)","loc":"d,33:15,33:21","dtypep":"(S)","origName":"dotted","verilogName":"dotted","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"ALWAYS","name":"","addr":"(T)","loc":"d,33:22,33:23","keyword":"cont_assign","sentreep": [], "stmtsp": [ {"type":"ASSIGNW","name":"","addr":"(U)","loc":"d,33:22,33:23","dtypep":"(S)", @@ -22,7 +22,7 @@ ]}, {"type":"TASK","name":"f","addr":"(Z)","loc":"d,35:17,35:18","cname":"f","fvarp": [],"classOrPackagep": [], "stmtsp": [ - {"type":"VAR","name":"m","addr":"(AB)","loc":"d,35:32,35:33","dtypep":"(BB)","origName":"m","verilogName":"m","direction":"INPUT","isFuncLocal":true,"lifetime":"VAUTOMI","varType":"PORT","dtypeName":"string","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"m","addr":"(AB)","loc":"d,35:32,35:33","dtypep":"(BB)","origName":"m","verilogName":"m","direction":"INPUT","isFuncLocal":true,"lifetime":"VAUTOMI","varType":"PORT","dtypeName":"string","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"DISPLAY","name":"","addr":"(CB)","loc":"d,36:5,36:13", "fmtp": [ {"type":"SFORMATF","name":"%s","addr":"(DB)","loc":"d,36:5,36:13","dtypep":"(BB)", @@ -53,7 +53,7 @@ ]}, {"type":"IFACE","name":"ifc","addr":"(M)","loc":"d,7:11,7:14","origName":"ifc","verilogName":"ifc","level":2,"inLibrary":true,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"value","addr":"(X)","loc":"d,8:11,8:16","dtypep":"(W)","origName":"value","verilogName":"value","direction":"NONE","lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"value","addr":"(X)","loc":"d,8:11,8:16","dtypep":"(W)","origName":"value","verilogName":"value","direction":"NONE","lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"MODPORT","name":"out_modport","addr":"(NB)","loc":"d,9:11,9:22", "varsp": [ {"type":"MODPORTVARREF","name":"value","addr":"(OB)","loc":"d,9:30,9:35","direction":"OUTPUT","varp":"(X)","exprp": []} diff --git a/test_regress/t/t_var_port_json_only.out b/test_regress/t/t_var_port_json_only.out index cdd5447dc..97a83a624 100644 --- a/test_regress/t/t_var_port_json_only.out +++ b/test_regress/t/t_var_port_json_only.out @@ -2,68 +2,68 @@ "modulesp": [ {"type":"MODULE","name":"mh2","addr":"(E)","loc":"d,18:8,18:11","origName":"mh2","verilogName":"mh2","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_inout_wire_integer","addr":"(F)","loc":"d,18:27,18:47","dtypep":"(G)","origName":"x_inout_wire_integer","verilogName":"x_inout_wire_integer","isPrimaryIO":true,"direction":"INOUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_inout_wire_integer","addr":"(F)","loc":"d,18:27,18:47","dtypep":"(G)","origName":"x_inout_wire_integer","verilogName":"x_inout_wire_integer","isPrimaryIO":true,"direction":"INOUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh5","addr":"(H)","loc":"d,24:8,24:11","origName":"mh5","verilogName":"mh5","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_input_wire_logic","addr":"(I)","loc":"d,24:19,24:37","dtypep":"(J)","origName":"x_input_wire_logic","verilogName":"x_input_wire_logic","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_input_wire_logic","addr":"(I)","loc":"d,24:19,24:37","dtypep":"(J)","origName":"x_input_wire_logic","verilogName":"x_input_wire_logic","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh6","addr":"(K)","loc":"d,26:8,26:11","origName":"mh6","verilogName":"mh6","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_input_var_logic","addr":"(L)","loc":"d,26:23,26:40","dtypep":"(J)","origName":"x_input_var_logic","verilogName":"x_input_var_logic","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_input_var_logic","addr":"(L)","loc":"d,26:23,26:40","dtypep":"(J)","origName":"x_input_var_logic","verilogName":"x_input_var_logic","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh7","addr":"(M)","loc":"d,28:8,28:11","origName":"mh7","verilogName":"mh7","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_input_var_integer","addr":"(N)","loc":"d,28:31,28:50","dtypep":"(G)","origName":"x_input_var_integer","verilogName":"x_input_var_integer","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_input_var_integer","addr":"(N)","loc":"d,28:31,28:50","dtypep":"(G)","origName":"x_input_var_integer","verilogName":"x_input_var_integer","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh8","addr":"(O)","loc":"d,30:8,30:11","origName":"mh8","verilogName":"mh8","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_wire_logic","addr":"(P)","loc":"d,30:20,30:39","dtypep":"(J)","origName":"x_output_wire_logic","verilogName":"x_output_wire_logic","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_wire_logic","addr":"(P)","loc":"d,30:20,30:39","dtypep":"(J)","origName":"x_output_wire_logic","verilogName":"x_output_wire_logic","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh9","addr":"(Q)","loc":"d,32:8,32:11","origName":"mh9","verilogName":"mh9","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_var_logic","addr":"(R)","loc":"d,32:24,32:42","dtypep":"(J)","origName":"x_output_var_logic","verilogName":"x_output_var_logic","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_var_logic","addr":"(R)","loc":"d,32:24,32:42","dtypep":"(J)","origName":"x_output_var_logic","verilogName":"x_output_var_logic","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh10","addr":"(S)","loc":"d,34:8,34:12","origName":"mh10","verilogName":"mh10","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_wire_logic_signed_p6","addr":"(T)","loc":"d,34:33,34:62","dtypep":"(U)","origName":"x_output_wire_logic_signed_p6","verilogName":"x_output_wire_logic_signed_p6","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_wire_logic_signed_p6","addr":"(T)","loc":"d,34:33,34:62","dtypep":"(U)","origName":"x_output_wire_logic_signed_p6","verilogName":"x_output_wire_logic_signed_p6","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh11","addr":"(V)","loc":"d,36:8,36:12","origName":"mh11","verilogName":"mh11","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_var_integer","addr":"(W)","loc":"d,36:28,36:48","dtypep":"(G)","origName":"x_output_var_integer","verilogName":"x_output_var_integer","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_var_integer","addr":"(W)","loc":"d,36:28,36:48","dtypep":"(G)","origName":"x_output_var_integer","verilogName":"x_output_var_integer","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh12","addr":"(X)","loc":"d,38:8,38:12","origName":"mh12","verilogName":"mh12","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_ref_logic_p6","addr":"(Y)","loc":"d,38:23,38:37","dtypep":"(Z)","origName":"x_ref_logic_p6","verilogName":"x_ref_logic_p6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_ref_logic_p6","addr":"(Y)","loc":"d,38:23,38:37","dtypep":"(Z)","origName":"x_ref_logic_p6","verilogName":"x_ref_logic_p6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh13","addr":"(AB)","loc":"d,40:8,40:12","origName":"mh13","verilogName":"mh13","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_ref_var_logic_u6","addr":"(BB)","loc":"d,40:17,40:35","dtypep":"(CB)","origName":"x_ref_var_logic_u6","verilogName":"x_ref_var_logic_u6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_ref_var_logic_u6","addr":"(BB)","loc":"d,40:17,40:35","dtypep":"(CB)","origName":"x_ref_var_logic_u6","verilogName":"x_ref_var_logic_u6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh17","addr":"(DB)","loc":"d,50:8,50:12","origName":"mh17","verilogName":"mh17","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_input_var_integer","addr":"(EB)","loc":"d,50:31,50:50","dtypep":"(G)","origName":"x_input_var_integer","verilogName":"x_input_var_integer","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_input_wire_logic","addr":"(FB)","loc":"d,50:57,50:75","dtypep":"(J)","origName":"y_input_wire_logic","verilogName":"y_input_wire_logic","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_input_var_integer","addr":"(EB)","loc":"d,50:31,50:50","dtypep":"(G)","origName":"x_input_var_integer","verilogName":"x_input_var_integer","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_input_wire_logic","addr":"(FB)","loc":"d,50:57,50:75","dtypep":"(J)","origName":"y_input_wire_logic","verilogName":"y_input_wire_logic","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh18","addr":"(GB)","loc":"d,52:8,52:12","origName":"mh18","verilogName":"mh18","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_var_logic","addr":"(HB)","loc":"d,52:24,52:42","dtypep":"(J)","origName":"x_output_var_logic","verilogName":"x_output_var_logic","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_input_wire_logic","addr":"(IB)","loc":"d,52:50,52:68","dtypep":"(J)","origName":"y_input_wire_logic","verilogName":"y_input_wire_logic","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_var_logic","addr":"(HB)","loc":"d,52:24,52:42","dtypep":"(J)","origName":"x_output_var_logic","verilogName":"x_output_var_logic","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_input_wire_logic","addr":"(IB)","loc":"d,52:50,52:68","dtypep":"(J)","origName":"y_input_wire_logic","verilogName":"y_input_wire_logic","isPrimaryIO":true,"direction":"INPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh19","addr":"(JB)","loc":"d,54:8,54:12","origName":"mh19","verilogName":"mh19","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_wire_logic_signed_p6","addr":"(KB)","loc":"d,54:33,54:62","dtypep":"(U)","origName":"x_output_wire_logic_signed_p6","verilogName":"x_output_wire_logic_signed_p6","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_output_var_integer","addr":"(LB)","loc":"d,54:72,54:92","dtypep":"(G)","origName":"y_output_var_integer","verilogName":"y_output_var_integer","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"integer","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_wire_logic_signed_p6","addr":"(KB)","loc":"d,54:33,54:62","dtypep":"(U)","origName":"x_output_wire_logic_signed_p6","verilogName":"x_output_wire_logic_signed_p6","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_output_var_integer","addr":"(LB)","loc":"d,54:72,54:92","dtypep":"(G)","origName":"y_output_var_integer","verilogName":"y_output_var_integer","isPrimaryIO":true,"direction":"OUTPUT","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"integer","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh20","addr":"(MB)","loc":"d,56:8,56:12","origName":"mh20","verilogName":"mh20","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_ref_var_logic_p6","addr":"(NB)","loc":"d,56:23,56:41","dtypep":"(Z)","origName":"x_ref_var_logic_p6","verilogName":"x_ref_var_logic_p6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_ref_var_logic_p6","addr":"(OB)","loc":"d,56:43,56:61","dtypep":"(Z)","origName":"y_ref_var_logic_p6","verilogName":"y_ref_var_logic_p6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_ref_var_logic_p6","addr":"(NB)","loc":"d,56:23,56:41","dtypep":"(Z)","origName":"x_ref_var_logic_p6","verilogName":"x_ref_var_logic_p6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_ref_var_logic_p6","addr":"(OB)","loc":"d,56:43,56:61","dtypep":"(Z)","origName":"y_ref_var_logic_p6","verilogName":"y_ref_var_logic_p6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]}, {"type":"MODULE","name":"mh21","addr":"(PB)","loc":"d,58:8,58:12","origName":"mh21","verilogName":"mh21","level":1,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"ref_var_logic_u6","addr":"(QB)","loc":"d,58:17,58:33","dtypep":"(RB)","origName":"ref_var_logic_u6","verilogName":"ref_var_logic_u6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_ref_var_logic","addr":"(SB)","loc":"d,58:41,58:56","dtypep":"(J)","origName":"y_ref_var_logic","verilogName":"y_ref_var_logic","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"ref_var_logic_u6","addr":"(QB)","loc":"d,58:17,58:33","dtypep":"(RB)","origName":"ref_var_logic_u6","verilogName":"ref_var_logic_u6","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_ref_var_logic","addr":"(SB)","loc":"d,58:41,58:56","dtypep":"(J)","origName":"y_ref_var_logic","verilogName":"y_ref_var_logic","isPrimaryIO":true,"direction":"REF","isSigPublic":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","fourstateComplementp":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ]} ],"filesp": [], "miscsp": [