From 470f99694e0913ea7e8c306400c841f079b6d011 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 26 Jul 2025 17:59:52 -0400 Subject: [PATCH] Revert d8dbb08a: Support bit queue streaming (#5830) (#6103) --- include/verilated_funcs.h | 211 +---------- src/V3Ast.cpp | 3 - src/V3AstNodeExpr.h | 31 -- src/V3AstNodes.cpp | 14 - src/V3Const.cpp | 126 +------ src/V3EmitCFunc.h | 33 -- src/V3Width.cpp | 28 -- test_regress/t/t_queue_concat_assign.v | 31 +- test_regress/t/t_stream_bad.out | 20 +- test_regress/t/t_stream_bad.v | 10 +- test_regress/t/t_stream_bitqueue.py | 18 - test_regress/t/t_stream_bitqueue.v | 490 ------------------------- test_regress/t/t_stream_crc_example.py | 18 - test_regress/t/t_stream_crc_example.v | 105 ------ test_regress/t/t_stream_unpack.v | 4 +- 15 files changed, 45 insertions(+), 1097 deletions(-) delete mode 100755 test_regress/t/t_stream_bitqueue.py delete mode 100644 test_regress/t/t_stream_bitqueue.v delete mode 100755 test_regress/t/t_stream_crc_example.py delete mode 100644 test_regress/t/t_stream_crc_example.v diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index 09e0be17e..2bcb7f5fc 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -2232,173 +2232,6 @@ static inline WDataOutP VL_SEL_WWII(int obits, int lbits, WDataOutP owp, WDataIn return owp; } -template -static inline VlQueue VL_CLONE_Q(const VlQueue& from, int lbits, int srcElementBits, - int dstElementBits) { - VlQueue ret; - VL_COPY_Q(ret, from, lbits, srcElementBits, dstElementBits); - return ret; -} - -template -static inline VlQueue VL_REVCLONE_Q(const VlQueue& from, int lbits, int srcElementBits, - int dstElementBits) { - VlQueue ret; - VL_REVCOPY_Q(ret, from, lbits, srcElementBits, dstElementBits); - return ret; -} - -// Helper function to get a bit from a queue at a specific bit index -template -static inline bool VL_GET_QUEUE_BIT(const VlQueue& queue, int srcElementBits, size_t bitIndex) { - const size_t elemIdx = bitIndex / srcElementBits; - if (VL_UNLIKELY(elemIdx >= queue.size())) return false; - - const T element = queue.at(elemIdx); - if (srcElementBits == 1) { - return element & 1; - } else { - const size_t bitInElem = bitIndex % srcElementBits; - const size_t actualBitPos = srcElementBits - 1 - bitInElem; - return (element >> actualBitPos) & 1; - } -} - -// Helper function to set a bit in the destination queue -template -static inline void VL_SET_QUEUE_BIT(VlQueue& queue, int dstElementBits, size_t bitIndex, - bool value) { - if (dstElementBits == 1) { - if (VL_UNLIKELY(bitIndex >= queue.size())) return; - queue.atWrite(bitIndex) = value ? 1 : 0; - } else { - const size_t elemIdx = bitIndex / dstElementBits; - if (VL_UNLIKELY(elemIdx >= queue.size())) return; - const size_t bitInElem = bitIndex % dstElementBits; - const size_t actualBitPos = dstElementBits - 1 - bitInElem; - if (value) { - queue.atWrite(elemIdx) |= (static_cast(1) << actualBitPos); - } else { - queue.atWrite(elemIdx) &= ~(static_cast(1) << actualBitPos); - } - } -} - -// Helper function to get a bit from a VlWide queue at a specific bit index -template -static inline bool VL_GET_QUEUE_BIT(const VlQueue>& queue, int srcElementBits, - size_t bitIndex) { - const size_t elemIdx = bitIndex / srcElementBits; - if (VL_UNLIKELY(elemIdx >= queue.size())) return false; - - const VlWide& element = queue.at(elemIdx); - const size_t bitInElem = bitIndex % srcElementBits; - const size_t actualBitPos = srcElementBits - 1 - bitInElem; - - return VL_BITISSET_W(element.data(), actualBitPos); -} - -// Helper function to set a bit in a VlWide queue at a specific bit index -template -static inline void VL_SET_QUEUE_BIT(VlQueue>& queue, int dstElementBits, - size_t bitIndex, bool value) { - const size_t elemIdx = bitIndex / dstElementBits; - if (VL_UNLIKELY(elemIdx >= queue.size())) return; - - const size_t bitInElem = bitIndex % dstElementBits; - const size_t actualBitPos = dstElementBits - 1 - bitInElem; - - VlWide& element = queue.atWrite(elemIdx); - if (value) { - VL_ASSIGNBIT_WO(actualBitPos, element.data()); - } else { - VL_ASSIGNBIT_WI(actualBitPos, element.data(), 0); - } -} - -template -static inline void VL_ZERO_INIT_QUEUE_ELEM(T& elem) { - elem = 0; -} - -template -static inline void VL_ZERO_INIT_QUEUE_ELEM(VlWide& elem) { - for (size_t j = 0; j < N_Words; ++j) { elem.at(j) = 0; } -} - -// This specialization works for both VlQueue (and similar) as well -// as VlQueue>. -template -static inline void VL_COPY_Q(VlQueue& q, const VlQueue& from, int lbits, int srcElementBits, - int dstElementBits) { - if (srcElementBits == dstElementBits) { - // Simple case: same element bit width, direct copy of each element - if (VL_UNLIKELY(&q == &from)) return; // Skip self-assignment when it's truly a no-op - q = from; - } else { - // Different element bit widths: use streaming conversion - VlQueue srcCopy = from; - const size_t srcTotalBits = from.size() * srcElementBits; - const size_t dstSize = (srcTotalBits + dstElementBits - 1) / dstElementBits; - q.renew(dstSize); - for (size_t i = 0; i < dstSize; ++i) { VL_ZERO_INIT_QUEUE_ELEM(q.atWrite(i)); } - for (size_t bitIndex = 0; bitIndex < srcTotalBits; ++bitIndex) { - VL_SET_QUEUE_BIT(q, dstElementBits, bitIndex, - VL_GET_QUEUE_BIT(srcCopy, srcElementBits, bitIndex)); - } - } -} - -// This specialization works for both VlQueue (and similar) as well -// as VlQueue>. -template -static inline void VL_REVCOPY_Q(VlQueue& q, const VlQueue& from, int lbits, - int srcElementBits, int dstElementBits) { - const size_t srcTotalBits = from.size() * srcElementBits; - const size_t dstSize = (srcTotalBits + dstElementBits - 1) / dstElementBits; - - // Always make a copy to handle the case where q and from are the same queue - VlQueue srcCopy = from; - - q.renew(dstSize); - - // Initialize all elements to zero using appropriate method - for (size_t i = 0; i < dstSize; ++i) { VL_ZERO_INIT_QUEUE_ELEM(q.atWrite(i)); } - - if (lbits == 1) { - // Simple bit reversal: write directly to destination - for (int i = srcTotalBits - 1; i >= 0; --i) { - VL_SET_QUEUE_BIT(q, dstElementBits, srcTotalBits - 1 - i, - VL_GET_QUEUE_BIT(srcCopy, srcElementBits, i)); - } - } else { - // Generalized block-reversal for lbits > 1: - // 1. Reverse all bits using 1-bit blocks - // 2. Split into lbits-sized blocks and pad incomplete blocks on the left - // 3. Reverse each lbits-sized block using 1-bit blocks - - const size_t numCompleteBlocks = srcTotalBits / lbits; - const size_t remainderBits = srcTotalBits % lbits; - const size_t srcBlocks = numCompleteBlocks + (remainderBits > 0 ? 1 : 0); - - size_t dstBitIndex = 0; - - for (size_t block = 0; block < srcBlocks; ++block) { - const size_t blockStart = block * lbits; - const int bitsToProcess = VL_LIKELY(block < numCompleteBlocks) ? lbits : remainderBits; - - for (int bit = bitsToProcess - 1; bit >= 0; --bit) { - const size_t reversedBitIndex = blockStart + bit; - const size_t originalBitIndex = srcTotalBits - 1 - reversedBitIndex; - VL_SET_QUEUE_BIT(q, dstElementBits, dstBitIndex++, - VL_GET_QUEUE_BIT(srcCopy, srcElementBits, originalBitIndex)); - } - - dstBitIndex += lbits - bitsToProcess; - } - } -} - //====================================================================== // Expressions needing insert/select @@ -2406,49 +2239,49 @@ static inline void VL_UNPACK_RI_I(int lbits, int rbits, VlQueue& q, IData const size_t size = (rbits + lbits - 1) / lbits; q.renew(size); const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < size; ++i) q.atWrite(size - 1 - i) = (from >> (i * lbits)) & mask; + for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask; } static inline void VL_UNPACK_RI_I(int lbits, int rbits, VlQueue& q, IData from) { const size_t size = (rbits + lbits - 1) / lbits; q.renew(size); const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < size; ++i) q.atWrite(size - 1 - i) = (from >> (i * lbits)) & mask; + for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask; } static inline void VL_UNPACK_RI_I(int lbits, int rbits, VlQueue& q, IData from) { const size_t size = (rbits + lbits - 1) / lbits; q.renew(size); const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < size; ++i) q.atWrite(size - 1 - i) = (from >> (i * lbits)) & mask; + for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask; } static inline void VL_UNPACK_RI_Q(int lbits, int rbits, VlQueue& q, QData from) { const size_t size = (rbits + lbits - 1) / lbits; q.renew(size); const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < size; ++i) q.atWrite(size - 1 - i) = (from >> (i * lbits)) & mask; + for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask; } static inline void VL_UNPACK_RI_Q(int lbits, int rbits, VlQueue& q, QData from) { const size_t size = (rbits + lbits - 1) / lbits; q.renew(size); const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < size; ++i) q.atWrite(size - 1 - i) = (from >> (i * lbits)) & mask; + for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask; } static inline void VL_UNPACK_RI_Q(int lbits, int rbits, VlQueue& q, QData from) { const size_t size = (rbits + lbits - 1) / lbits; q.renew(size); const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < size; ++i) q.atWrite(size - 1 - i) = (from >> (i * lbits)) & mask; + for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask; } static inline void VL_UNPACK_RQ_Q(int lbits, int rbits, VlQueue& q, QData from) { const size_t size = (rbits + lbits - 1) / lbits; q.renew(size); const QData mask = VL_MASK_Q(lbits); - for (size_t i = 0; i < size; ++i) q.atWrite(size - 1 - i) = (from >> (i * lbits)) & mask; + for (size_t i = 0; i < size; ++i) q.atWrite(q.size() - 1 - i) = (from >> (i * lbits)) & mask; } static inline void VL_UNPACK_RI_W(int lbits, int rbits, VlQueue& q, WDataInP rwp) { @@ -2456,11 +2289,7 @@ static inline void VL_UNPACK_RI_W(int lbits, int rbits, VlQueue& q, WData q.renew(size); const IData mask = VL_MASK_I(lbits); for (size_t i = 0; i < size; ++i) { - // Extract from MSB to LSB: MSB goes to index 0 - const int bitPos = rbits - (i + 1) * lbits; - const int actualBitPos = (bitPos < 0) ? 0 : bitPos; - const int actualWidth = (bitPos < 0) ? (lbits + bitPos) : lbits; - q.atWrite(i) = VL_SEL_IWII(rbits, rwp, actualBitPos, actualWidth) & mask; + q.atWrite(i) = VL_SEL_IWII(rbits, rwp, i * lbits, lbits) & mask; } } @@ -2469,11 +2298,7 @@ static inline void VL_UNPACK_RI_W(int lbits, int rbits, VlQueue& q, WData q.renew(size); const IData mask = VL_MASK_I(lbits); for (size_t i = 0; i < size; ++i) { - // Extract from MSB to LSB: MSB goes to index 0 - const int bitPos = rbits - (i + 1) * lbits; - const int actualBitPos = (bitPos < 0) ? 0 : bitPos; - const int actualWidth = (bitPos < 0) ? (lbits + bitPos) : lbits; - q.atWrite(i) = VL_SEL_IWII(rbits, rwp, actualBitPos, actualWidth) & mask; + q.atWrite(i) = VL_SEL_IWII(rbits, rwp, i * lbits, lbits) & mask; } } @@ -2482,11 +2307,7 @@ static inline void VL_UNPACK_RI_W(int lbits, int rbits, VlQueue& q, WData q.renew(size); const IData mask = VL_MASK_I(lbits); for (size_t i = 0; i < size; ++i) { - // Extract from MSB to LSB: MSB goes to index 0 - const int bitPos = rbits - (i + 1) * lbits; - const int actualBitPos = (bitPos < 0) ? 0 : bitPos; - const int actualWidth = (bitPos < 0) ? (lbits + bitPos) : lbits; - q.atWrite(i) = VL_SEL_IWII(rbits, rwp, actualBitPos, actualWidth) & mask; + q.atWrite(i) = VL_SEL_IWII(rbits, rwp, i * lbits, lbits) & mask; } } @@ -2495,11 +2316,7 @@ static inline void VL_UNPACK_RQ_W(int lbits, int rbits, VlQueue& q, WData q.renew(size); const QData mask = VL_MASK_Q(lbits); for (size_t i = 0; i < size; ++i) { - // Extract from MSB to LSB: MSB goes to index 0 - const int bitPos = rbits - (i + 1) * lbits; - const int actualBitPos = (bitPos < 0) ? 0 : bitPos; - const int actualWidth = (bitPos < 0) ? (lbits + bitPos) : lbits; - q.atWrite(i) = VL_SEL_QWII(rbits, rwp, actualBitPos, actualWidth) & mask; + q.atWrite(i) = VL_SEL_QWII(rbits, rwp, i * lbits, lbits) & mask; } } @@ -2509,11 +2326,7 @@ static inline void VL_UNPACK_RW_W(int lbits, int rbits, VlQueue> const int size = (rbits + lbits - 1) / lbits; q.renew(size); for (size_t i = 0; i < size; ++i) { - // Extract from MSB to LSB: MSB goes to index 0 - const int bitPos = rbits - (i + 1) * lbits; - const int actualBitPos = (bitPos < 0) ? 0 : bitPos; - const int actualWidth = (bitPos < 0) ? (lbits + bitPos) : lbits; - VL_SEL_WWII(actualWidth, rbits, q.atWrite(i), rwp, actualBitPos, actualWidth); + VL_SEL_WWII(lbits, rbits, q.atWrite(i), rwp, i * lbits, lbits); } } diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index b0d8f7cfe..995a06020 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -1613,9 +1613,6 @@ static VCastable computeCastableImp(const AstNodeDType* toDtp, const AstNodeDTyp if (VN_IS(fromBaseDtp, EnumDType) && toDtp->sameTree(fromDtp)) return VCastable::ENUM_IMPLICIT; if (fromNumericable) return VCastable::ENUM_EXPLICIT; - } else if (VN_IS(toDtp, QueueDType) - && (VN_IS(fromDtp, BasicDType) || VN_IS(fromDtp, StreamDType))) { - return VCastable::COMPATIBLE; } else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromConstp, Const)) { if (fromConstp->isNull()) return VCastable::COMPATIBLE; } else if (VN_IS(toDtp, ClassRefDType) && VN_IS(fromDtp, ClassRefDType)) { diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index d0b448719..d816fa2d5 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -1129,37 +1129,6 @@ public: string emitC() final override { V3ERROR_NA_RETURN(""); } bool cleanOut() const final override { V3ERROR_NA_RETURN(true); } }; -class AstCvtArrayToArray final : public AstNodeExpr { - // Copy/Cast from dynamic/unpacked types to dynamic/unpacked types - // @astgen op1 := fromp : AstNodeExpr -private: - const bool m_reverse; // whether ordering gets reversed in this operation (ex: {<<{expr}}) - const int m_blockSize; // num bits per block in a streaming operation (ex: 4 in {<<4{expr}})) - const int m_dstElementBits; // num bits in lhs (ex: 8 if to byte-queue, 1 if to bit-queue) - const int m_srcElementBits; // num bits in rhs (ex 8 if from byte-queue, 1 if from bit-queue) - -public: - AstCvtArrayToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp, bool reverse, - int blockSize, int dstElementBits, int srcElementBits) - : ASTGEN_SUPER_CvtArrayToArray(fl) - , m_reverse{reverse} - , m_blockSize{blockSize} - , m_dstElementBits{dstElementBits} - , m_srcElementBits{srcElementBits} { - this->fromp(fromp); - dtypeFrom(dtp); - } - ASTGEN_MEMBERS_AstCvtArrayToArray; - void dump(std::ostream& str) const override; - void dumpJson(std::ostream& str) const override; - string emitVerilog() override { V3ERROR_NA_RETURN(""); } - string emitC() override { V3ERROR_NA_RETURN(""); } - bool cleanOut() const override { return true; } - bool reverse() const { return m_reverse; } - int blockSize() const { return m_blockSize; } - int dstElementBits() const { return m_dstElementBits; } - int srcElementBits() const { return m_srcElementBits; } -}; class AstCvtArrayToPacked final : public AstNodeExpr { // Cast from dynamic queue data type to packed array // @astgen op1 := fromp : AstNodeExpr diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index b02358d5d..68901b507 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1696,20 +1696,6 @@ void AstCCast::dumpJson(std::ostream& str) const { dumpJsonNumFunc(str, size); dumpJsonGen(str); } -void AstCvtArrayToArray::dump(std::ostream& str) const { - this->AstNodeExpr::dump(str); - str << " reverse=" << reverse(); - str << " blockSize=" << blockSize(); - str << " dstElementBits=" << dstElementBits(); - str << " srcElementBits=" << srcElementBits(); -} -void AstCvtArrayToArray::dumpJson(std::ostream& str) const { - dumpJsonBoolFunc(str, reverse); - dumpJsonNumFunc(str, blockSize); - dumpJsonNumFunc(str, dstElementBits); - dumpJsonNumFunc(str, srcElementBits); - dumpJsonGen(str); -} void AstCell::dump(std::ostream& str) const { this->AstNode::dump(str); if (recursive()) str << " [RECURSIVE]"; diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 058bf0493..c8d54a8c9 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -2205,23 +2205,8 @@ class ConstVisitor final : public VNVisitor { AstStreamR* const streamp = VN_AS(nodep->rhsp(), StreamR)->unlinkFrBack(); AstNodeExpr* srcp = streamp->lhsp()->unlinkFrBack(); AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp(); - const AstNodeDType* const dstDTypep = nodep->lhsp()->dtypep()->skipRefp(); if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType)) { - if (VN_IS(dstDTypep, QueueDType) || VN_IS(dstDTypep, DynArrayDType)) { - int srcElementBits = 0; - if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) { - srcElementBits = elemDtp->width(); - } - int dstElementBits = 0; - if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) { - dstElementBits = elemDtp->width(); - } - srcp = new AstCvtArrayToArray{ - srcp->fileline(), srcp, nodep->dtypep(), false, 1, - dstElementBits, srcElementBits}; - } else { - srcp = new AstCvtArrayToPacked{srcp->fileline(), srcp, nodep->dtypep()}; - } + srcp = new AstCvtArrayToPacked{srcp->fileline(), srcp, nodep->dtypep()}; } else if (VN_IS(srcDTypep, UnpackArrayDType)) { srcp = new AstCvtArrayToPacked{srcp->fileline(), srcp, srcDTypep}; // Handling the case where lhs is wider than rhs by inserting zeros. StreamL does @@ -2304,50 +2289,15 @@ class ConstVisitor final : public VNVisitor { // Further reduce, any of the nodes may have more reductions. return true; } else if (m_doV && VN_IS(nodep->rhsp(), StreamL)) { + AstNodeDType* const lhsDtypep = nodep->lhsp()->dtypep()->skipRefp(); AstStreamL* streamp = VN_AS(nodep->rhsp(), StreamL); - AstNodeExpr* srcp = streamp->lhsp(); - AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp(); - AstNodeDType* const dstDTypep = nodep->lhsp()->dtypep()->skipRefp(); - if ((VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType) - || VN_IS(srcDTypep, UnpackArrayDType))) { - if (VN_IS(dstDTypep, QueueDType) || VN_IS(dstDTypep, DynArrayDType)) { - int blockSize = 1; - if (const AstConst* const constp = VN_CAST(streamp->rhsp(), Const)) { - blockSize = constp->toSInt(); - if (VL_UNLIKELY(blockSize <= 0)) { - // Not reachable due to higher level checks when parsing stream - // operators commented out to not fail v3error-coverage-checks. - // nodep->v3error("Stream block size must be positive, got " << - // blockSize); nodep->v3error("Stream block size must be positive, got - // " << blockSize); - blockSize = 1; - } - } - // Not reachable due to higher level checks when parsing stream operators - // commented out to not fail v3error-coverage-checks. - // else { - // nodep->v3error("Stream block size must be constant (got " << - // streamp->rhsp()->prettyTypeName() << ")"); - // } - int srcElementBits = 0; - if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) { - srcElementBits = elemDtp->width(); - } - int dstElementBits = 0; - if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) { - dstElementBits = elemDtp->width(); - } - streamp->unlinkFrBack(); - srcp = new AstCvtArrayToArray{ - srcp->fileline(), srcp->unlinkFrBack(), dstDTypep, true, - blockSize, dstElementBits, srcElementBits}; - nodep->rhsp(srcp); - VL_DO_DANGLING(pushDeletep(streamp), streamp); - } else { - streamp->lhsp(new AstCvtArrayToPacked{srcp->fileline(), srcp->unlinkFrBack(), - dstDTypep}); - streamp->dtypeFrom(dstDTypep); - } + AstNodeExpr* const srcp = streamp->lhsp(); + const AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp(); + if (VN_IS(srcDTypep, QueueDType) || VN_IS(srcDTypep, DynArrayDType) + || VN_IS(srcDTypep, UnpackArrayDType)) { + streamp->lhsp( + new AstCvtArrayToPacked{srcp->fileline(), srcp->unlinkFrBack(), lhsDtypep}); + streamp->dtypeFrom(lhsDtypep); } } else if (m_doV && replaceAssignMultiSel(nodep)) { return true; @@ -3133,64 +3083,6 @@ class ConstVisitor final : public VNVisitor { varrefp->varp()->valuep(initvaluep); } } - void visit(AstCvtArrayToArray* nodep) override { - iterateChildren(nodep); - // Handle the case where we have a stream operation inside a cast conversion - // To avoid infinite recursion, mark the node as processed by setting user1. - if (!nodep->user1()) { - nodep->user1(true); - // Check for both StreamL and StreamR operations - AstNodeStream* streamp = nullptr; - bool isReverse = false; - if (AstStreamL* const streamLp = VN_CAST(nodep->fromp(), StreamL)) { - streamp = streamLp; - isReverse = true; // StreamL reverses the operation - } else if (AstStreamR* const streamRp = VN_CAST(nodep->fromp(), StreamR)) { - streamp = streamRp; - isReverse = false; // StreamR doesn't reverse the operation - } - if (streamp) { - AstNodeExpr* srcp = streamp->lhsp(); - AstNodeDType* const srcDTypep = srcp->dtypep()->skipRefp(); - AstNodeDType* const dstDTypep = nodep->dtypep()->skipRefp(); - if (VN_IS(srcDTypep, QueueDType) && VN_IS(dstDTypep, QueueDType)) { - int blockSize = 1; - if (AstConst* const constp = VN_CAST(streamp->rhsp(), Const)) { - blockSize = constp->toSInt(); - if (VL_UNLIKELY(blockSize <= 0)) { - // Not reachable due to higher level checks when parsing stream - // operators commented out to not fail v3error-coverage-checks. - // nodep->v3error("Stream block size must be positive, got " << - // blockSize); - blockSize = 1; - } - } - // Not reachable due to higher level checks when parsing stream operators - // commented out to not fail v3error-coverage-checks. - // else { - // nodep->v3error("Stream block size must be constant (got " << - // streamp->rhsp()->prettyTypeName() << ")"); - // } - int srcElementBits = 0; - if (AstNodeDType* const elemDtp = srcDTypep->subDTypep()) { - srcElementBits = elemDtp->width(); - } - int dstElementBits = 0; - if (AstNodeDType* const elemDtp = dstDTypep->subDTypep()) { - dstElementBits = elemDtp->width(); - } - streamp->unlinkFrBack(); - AstNodeExpr* newp = new AstCvtArrayToArray{ - srcp->fileline(), srcp->unlinkFrBack(), dstDTypep, isReverse, - blockSize, dstElementBits, srcElementBits}; - nodep->replaceWith(newp); - VL_DO_DANGLING(pushDeletep(streamp), streamp); - VL_DO_DANGLING(pushDeletep(nodep), nodep); - return; - } - } - } - } void visit(AstRelease* nodep) override { if (AstConcat* const concatp = VN_CAST(nodep->lhsp(), Concat)) { FileLine* const flp = nodep->fileline(); diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index e489ae07c..c5e5c1efb 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -426,22 +426,6 @@ public: emitVarDecl(nodep); } - void visit(AstCvtArrayToArray* nodep) override { - if (nodep->reverse()) { - puts("VL_REVCLONE_Q("); - } else { - puts("VL_CLONE_Q("); - } - iterateAndNextConstNull(nodep->fromp()); - puts(", "); - puts(cvtToStr(nodep->blockSize())); - puts(", "); - puts(cvtToStr(nodep->srcElementBits())); - puts(", "); - puts(cvtToStr(nodep->dstElementBits())); - puts(")"); - } - void visit(AstCvtArrayToPacked* nodep) override { AstNodeDType* const fromDtp = nodep->fromp()->dtypep()->skipRefp(); AstNodeDType* const elemDtp = fromDtp->subDTypep()->skipRefp(); @@ -530,23 +514,6 @@ public: puts(", "); rhs = false; iterateAndNextConstNull(castp->fromp()); - } else if (const AstCvtArrayToArray* const castp - = VN_CAST(nodep->rhsp(), CvtArrayToArray)) { - if (castp->reverse()) { - putns(castp, "VL_REVCOPY_Q("); - } else { - putns(castp, "VL_COPY_Q("); - } - iterateAndNextConstNull(nodep->lhsp()); - puts(", "); - rhs = false; - iterateAndNextConstNull(castp->fromp()); - puts(", "); - puts(cvtToStr(castp->blockSize())); - puts(", "); - puts(cvtToStr(castp->srcElementBits())); - puts(", "); - puts(cvtToStr(castp->dstElementBits())); } else if (nodep->isWide() && VN_IS(nodep->lhsp(), VarRef) // && !VN_IS(nodep->rhsp(), CExpr) // && !VN_IS(nodep->rhsp(), CMethodHard) // diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 603846fdf..5edaa1cd6 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1598,12 +1598,6 @@ class WidthVisitor final : public VNVisitor { userIterateAndNext(nodep->fromp(), WidthVP{SELF, BOTH}.p()); // Type set in constructor } - void visit(AstCvtArrayToArray* nodep) override { - if (nodep->didWidthAndSet()) return; - // Opaque returns, so arbitrary - userIterateAndNext(nodep->fromp(), WidthVP{SELF, BOTH}.p()); - // Type set in constructor - } void visit(AstCvtArrayToPacked* nodep) override { if (nodep->didWidthAndSet()) return; // Opaque returns, so arbitrary @@ -2207,28 +2201,6 @@ class WidthVisitor final : public VNVisitor { // Can just remove cast, but need extend placeholder // so we can avoid warning message } - } else if (VN_IS(toDtp, QueueDType)) { - if (VN_IS(fromDtp, BasicDType)) { - newp = new AstCvtPackedToArray{nodep->fileline(), - nodep->fromp()->unlinkFrBack(), toDtp}; - } else if (VN_IS(fromDtp, QueueDType) || VN_IS(fromDtp, StreamDType)) { - int srcElementBits = 1; - int dstElementBits = 1; - if (AstNodeDType* const elemDtp = fromDtp->subDTypep()) { - srcElementBits = elemDtp->width(); - } - const AstQueueDType* const dstQueueDtp = VN_AS(toDtp, QueueDType); - if (AstNodeDType* const elemDtp = dstQueueDtp->subDTypep()) { - dstElementBits = elemDtp->width(); - } - newp = new AstCvtArrayToArray{nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - toDtp, - false, - 1, - dstElementBits, - srcElementBits}; - } } else if (VN_IS(toDtp, ClassRefDType)) { // Can just remove cast } else { diff --git a/test_regress/t/t_queue_concat_assign.v b/test_regress/t/t_queue_concat_assign.v index 2af584e29..b3860878e 100644 --- a/test_regress/t/t_queue_concat_assign.v +++ b/test_regress/t/t_queue_concat_assign.v @@ -4,25 +4,20 @@ // any use, without warranty, 2024 by Antmicro. // SPDX-License-Identifier: CC0-1.0 -module t ( /*AUTOARG*/); - initial begin - bit q1[$] = {1'b1}; - bit q2[$]; - bit q3[$]; - bit [1:0] d1[] = {2'b10}; - bit [1:0] d2[]; - // TODO: queue streaming support broke assignment like this. - // It's something to do witih computeCastable and V3Width.cpp - // q2 = {q1}; - // if (q2[0] != 1) $stop; +module t (/*AUTOARG*/); + initial begin + bit q1[$] = {1'b1}; + bit q2[$]; + bit [1:0] d1[] = {2'b10}; + bit [1:0] d2[]; + q2 = {q1}; + if (q2[0] != 1) $stop; - q3 = q1; - if (q3[0] != 1) $stop; + d2 = {2'b11}; + if (d2[0] != 2'b11) $stop; - d2 = {2'b11}; - if (d2[0] != 2'b11) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end - $write("*-* All Finished *-*\n"); - $finish; - end endmodule diff --git a/test_regress/t/t_stream_bad.out b/test_regress/t/t_stream_bad.out index acf856f50..ad2c9c4c4 100644 --- a/test_regress/t/t_stream_bad.out +++ b/test_regress/t/t_stream_bad.out @@ -1,18 +1,10 @@ -%Error: t/t_stream_bad.v:14:25: Expecting expression to be constant, but can't convert a RAND to constant. +%Error: t/t_stream_bad.v:12:32: Expecting expression to be constant, but can't convert a RAND to constant. : ... note: In instance 't' - 14 | packed_data_32 = {<<$random{byte_in}}; - | ^~~~~~~ + 12 | initial packed_data_32 = {<<$random{byte_in}}; + | ^~~~~~~ ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. -%Error: t/t_stream_bad.v:14:23: Slice size isn't a constant or basic data type. +%Error: t/t_stream_bad.v:12:30: Slice size isn't a constant or basic data type. : ... note: In instance 't' - 14 | packed_data_32 = {<<$random{byte_in}}; - | ^~ -%Error: t/t_stream_bad.v:15:25: Expecting expression to be constant, but variable isn't const: 'x' - : ... note: In instance 't' - 15 | packed_data_32 = {<>{4'hd}}); - `checkh(bit_q[0], 1'b1); - `checkh(bit_q[1], 1'b1); - `checkh(bit_q[2], 1'b0); - `checkh(bit_q[3], 1'b1); - - bit_q = bit_q_t'({<<{4'hc}}); - `checkh(bit_q[0], 1'b0); - `checkh(bit_q[1], 1'b0); - `checkh(bit_q[2], 1'b1); - `checkh(bit_q[3], 1'b1); - - bit_q = {>>{bit_q_t'(4'he)}}; - `checkh(bit_q[0], 1'b1); - `checkh(bit_q[1], 1'b1); - `checkh(bit_q[2], 1'b1); - `checkh(bit_q[3], 1'b0); - - bit_q = {<<{bit_q_t'(4'hd)}}; - `checkh(bit_q[0], 1'b1); - `checkh(bit_q[1], 1'b0); - `checkh(bit_q[2], 1'b1); - `checkh(bit_q[3], 1'b1); - - bit_qq = {>>{bit_q}}; - `checkh(bit_qq[0], 1'b1); - `checkh(bit_qq[1], 1'b0); - `checkh(bit_qq[2], 1'b1); - `checkh(bit_qq[3], 1'b1); - - bit_qq = {<<{bit_q}}; - `checkh(bit_qq[0], 1'b1); - `checkh(bit_qq[1], 1'b1); - `checkh(bit_qq[2], 1'b0); - `checkh(bit_qq[3], 1'b1); - - bit_q = bit_q_t'({>>{4'hd}}); - `checkh(bit_q[0], 1'b1); - `checkh(bit_q[1], 1'b1); - `checkh(bit_q[2], 1'b0); - `checkh(bit_q[3], 1'b1); - - bit_q = bit_q_t'({>>2{4'hd}}); - `checkh(bit_q[0], 1'b1); - `checkh(bit_q[1], 1'b1); - `checkh(bit_q[2], 1'b0); - `checkh(bit_q[3], 1'b1); - - bit_qq = bit_q_t'({>>{bit_q}}); - `checkh(bit_qq[0], 1'b1); - `checkh(bit_qq[1], 1'b1); - `checkh(bit_qq[2], 1'b0); - `checkh(bit_qq[3], 1'b1); - - bit_qq = bit_q_t'({>>2{bit_q}}); - `checkh(bit_qq[0], 1'b1); - `checkh(bit_qq[1], 1'b1); - `checkh(bit_qq[2], 1'b0); - `checkh(bit_qq[3], 1'b1); - - bit_qq = bit_q_t'({<<{bit_q}}); - `checkh(bit_qq[0], 1'b1); - `checkh(bit_qq[1], 1'b0); - `checkh(bit_qq[2], 1'b1); - `checkh(bit_qq[3], 1'b1); - - bit_qq = {<<2{bit_qq}}; - `checkh(bit_qq[0], 1'b1); - `checkh(bit_qq[1], 1'b1); - `checkh(bit_qq[2], 1'b1); - `checkh(bit_qq[3], 1'b0); - - bit_qq = {<<2{bit_q_t'({<<{bit_q}})}}; - `checkh(bit_qq[0], 1'b1); - `checkh(bit_qq[1], 1'b1); - `checkh(bit_qq[2], 1'b1); - `checkh(bit_qq[3], 1'b0); - end - - begin - cdata_q_t cdata_q, cdata_qq; - - cdata_q = cdata_q_t'(32'hdeadbeef); - `checkh(cdata_q[0], 8'hde); - `checkh(cdata_q[1], 8'had); - `checkh(cdata_q[2], 8'hbe); - `checkh(cdata_q[3], 8'hef); - - cdata_qq = cdata_q_t'({<<{cdata_q}}); - `checkh(cdata_qq[0], 8'hf7); - `checkh(cdata_qq[1], 8'h7d); - `checkh(cdata_qq[2], 8'hb5); - `checkh(cdata_qq[3], 8'h7b); - - cdata_qq = {<<2{cdata_q}}; - `checkh(cdata_qq[0], 8'hfb); - `checkh(cdata_qq[1], 8'hbe); - `checkh(cdata_qq[2], 8'h7a); - `checkh(cdata_qq[3], 8'hb7); - end - - begin - sdata_logic_q_t sdata_q, sdata_qq; - - sdata_q = sdata_logic_q_t'(64'hfeedface_deadbeef); - `checkh(sdata_q[0], 16'hfeed); - `checkh(sdata_q[1], 16'hface); - `checkh(sdata_q[2], 16'hdead); - `checkh(sdata_q[3], 16'hbeef); - - sdata_qq = sdata_logic_q_t'({<<{sdata_q}}); - `checkh(sdata_qq[0], 16'hf77d); - `checkh(sdata_qq[1], 16'hb57b); - `checkh(sdata_qq[2], 16'h735f); - `checkh(sdata_qq[3], 16'hb77f); - - sdata_qq = {<<2{sdata_q}}; - `checkh(sdata_qq[0], 16'hfbbe); - `checkh(sdata_qq[1], 16'h7ab7); - `checkh(sdata_qq[2], 16'hb3af); - `checkh(sdata_qq[3], 16'h7bbf); - end - - begin - idata_logic_q_t idata_q, idata_qq; - - idata_q = idata_logic_q_t'(64'h12345678_9abcdef0); - `checkh(idata_q[0], 32'h12345678); - `checkh(idata_q[1], 32'h9abcdef0); - - idata_qq = idata_logic_q_t'({<<{idata_q}}); - `checkh(idata_qq[0], 32'h0f7b3d59); - `checkh(idata_qq[1], 32'h1e6a2c48); - - idata_q = idata_logic_q_t'(128'hfeedface_deadbeef_cafebabe_12345678); - `checkh(idata_q[0], 32'hfeedface); - `checkh(idata_q[1], 32'hdeadbeef); - `checkh(idata_q[2], 32'hcafebabe); - `checkh(idata_q[3], 32'h12345678); - - idata_qq = {<<2{idata_logic_q_t'({<<{idata_q}})}}; - `checkh(idata_qq[0], 32'hfddef5cd); - `checkh(idata_qq[1], 32'hed5e7ddf); - `checkh(idata_qq[2], 32'hc5fd757d); - `checkh(idata_qq[3], 32'h2138a9b4); - end - - begin - qdata_logic_q_t qdata_q, qdata_qq; - - qdata_q.push_back(64'hdeadbeef_cafebabe); - qdata_q.push_back(64'hfeedface_12345678); - `checkh(qdata_q[0], 64'hdeadbeef_cafebabe); - `checkh(qdata_q[1], 64'hfeedface_12345678); - - qdata_qq = qdata_logic_q_t'({<<{qdata_q}}); - `checkh(qdata_qq[0], 64'h1e6a2c48735fb77f); - `checkh(qdata_qq[1], 64'h7d5d7f53f77db57b); - - qdata_q.push_back(64'h1111222233334444); - qdata_q.push_back(64'h5555666677778888); - qdata_qq = {<<2{qdata_q}}; - `checkh(qdata_qq[0], 64'h2222dddd99995555); - `checkh(qdata_qq[1], 64'h1111cccc88884444); - `checkh(qdata_qq[2], 64'h2d951c84b3af7bbf); - `checkh(qdata_qq[3], 64'hbeaebfa3fbbe7ab7); - end - - begin - wide_q_t wide_q, wide_qq; - - wide_q.push_back(128'hdeadbeef_cafebabe_feedface_12345678); - wide_q.push_back(128'h11112222_33334444_55556666_77778888); - `checkh(wide_q[0], 128'hdeadbeef_cafebabe_feedface_12345678); - `checkh(wide_q[1], 128'h11112222_33334444_55556666_77778888); - - wide_qq = wide_q_t'({<<{wide_q}}); - `checkh(wide_qq[0], 128'h1111eeee6666aaaa2222cccc44448888); - `checkh(wide_qq[1], 128'h1e6a2c48735fb77f7d5d7f53f77db57b); - - wide_q.push_back(128'haaaabbbb_ccccdddd_eeeeffff_00001111); - wide_q.push_back(128'h22223333_44445555_66667777_88889999); - - wide_qq = wide_q_t'({<<{wide_q}}); - wide_qq = {<<2{wide_q}}; - `checkh(wide_qq[0], 128'h66662222dddd999955551111cccc8888); - `checkh(wide_qq[1], 128'h44440000ffffbbbb77773333eeeeaaaa); - `checkh(wide_qq[2], 128'h2222dddd999955551111cccc88884444); - `checkh(wide_qq[3], 128'h2d951c84b3af7bbfbeaebfa3fbbe7ab7); - end - - begin - byte_q_t bytq_init; - byte_q_t bytq; - bit_q_t bitq; - - bytq_init.push_back(8'h84); - bytq_init.push_back(8'haa); - `checkh(bytq_init[0], 8'h84); - `checkh(bytq_init[1], 8'haa); - s = $sformatf("bytq_init=%p", bytq_init); - `checks(s, "bytq_init='{'h84, 'haa} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bitq=%p", bitq); - `checks(s, - "bitq='{'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1} "); - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa} "); - - /* - Generalized block-reversal semantics for the outer left-stream when blockSize > 1. - This seemingly complicated approach is what is required to match commercial simulators, - otherwise the straggler bit [1] in the padded byte might end up as 0x01 instead of 0x80. - - Starting with result of inner {<<{bitq}}: [1,1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,0] (17 bits), - apply outer {<<8{...}} using generalized block-reversal like this: - - Reverse all bits: [0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,1,1] - - Split into 8-bit blocks from left and pad incomplete blocks on the left: - - Block 0: [0,0,1,0,0,0,0,1] (complete) - - Block 1: [0,1,0,1,0,1,0,1] (complete) - - Block 2: [1] -> pad on left -> [0,0,0,0,0,0,0,1] - - Reverse bits within each 8-bit block: - - Block 0: [0,0,1,0,0,0,0,1] -> [1,0,0,0,0,1,0,0] = 0x84 - - Block 1: [0,1,0,1,0,1,0,1] -> [1,0,1,0,1,0,1,0] = 0xaa - - Block 2: [0,0,0,0,0,0,0,1] -> [1,0,0,0,0,0,0,0] = 0x80 - */ - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bitq=%p", bitq); - `checks(s, - "bitq='{'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h1} "); - `checkh(bytq[0], 8'h84); - `checkh(bytq[1], 8'haa); - `checkh(bytq[2], 8'h80); - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'h80} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bitq=%p", bitq); - `checks(s, - "bitq='{'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h1, 'h1} "); - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'hc0} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'he0} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'h70} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bitq.push_back(1'b1); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'hb8} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'h5c} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bitq.push_back(1'b0); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'h2e} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bitq.push_back(1'b0); - bitq.push_back(1'b1); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'h97} "); - - bytq = bytq_init; - bitq = {<<8{bit_q_t'({<<{bytq}})}}; - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bitq.push_back(1'b1); - bitq.push_back(1'b0); - bitq.push_back(1'b0); - bitq.push_back(1'b1); - bitq.push_back(1'b1); - bytq = {<<8{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h84, 'haa, 'h97, 'h80} "); - end - - // Test StreamR (>>) operations - fairly simple since this should maintain left-to-right order. - begin - bit_q_t bitq; - byte_q_t bytq; - - bitq = {1'b1, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0}; - bitq = {>>4{bit_q_t'({<<{bitq}})}}; - s = $sformatf("bitq=%p", bitq); - `checks(s, "bitq='{'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1} "); - - bytq = {8'h84, 8'haa}; - bitq = {>>{bit_q_t'({<<{bytq}})}}; - s = $sformatf("bitq=%p", bitq); - `checks(s, - "bitq='{'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1} "); - - bitq = { - 1'b1, - 1'b0, - 1'b1, - 1'b0, - 1'b1, - 1'b0, - 1'b1, - 1'b0, - 1'b1, - 1'b1, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b1, - 1'b0 - }; - bytq = {>>2{byte_q_t'({<<{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h43, 'h55} "); - - bytq = {8'h12, 8'h34, 8'h56}; - bytq = {>>{byte_q_t'({<<{bytq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h6a, 'h2c, 'h48} "); - - bitq = {1'b1, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0}; - bitq = {>>6{bit_q_t'({>>{bitq}})}}; - s = $sformatf("bitq=%p", bitq); - `checks(s, "bitq='{'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0} "); - - bytq = {8'h84, 8'haa}; - bitq = {>>{bit_q_t'({>>{bytq}})}}; - s = $sformatf("bitq=%p", bitq); - `checks(s, - "bitq='{'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0} "); - - bitq = { - 1'b1, - 1'b0, - 1'b1, - 1'b0, - 1'b1, - 1'b0, - 1'b1, - 1'b0, - 1'b1, - 1'b1, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b1, - 1'b0 - }; - bytq = {>>8{byte_q_t'({>>{bitq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'haa, 'hc2} "); - - bytq = {8'h12, 8'h34, 8'h56}; - bytq = {>>{byte_q_t'({>>{bytq}})}}; - s = $sformatf("bytq=%p", bytq); - `checks(s, "bytq='{'h12, 'h34, 'h56} "); - end - - $write("*-* All Finished *-*\n"); - $finish; - end - -endmodule diff --git a/test_regress/t/t_stream_crc_example.py b/test_regress/t/t_stream_crc_example.py deleted file mode 100755 index d4f986441..000000000 --- a/test_regress/t/t_stream_crc_example.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 -# DESCRIPTION: Verilator: Verilog Test driver/expect definition -# -# Copyright 2024 by Wilson Snyder. This program is free software; you -# can redistribute it and/or modify it under the terms of either the GNU -# Lesser General Public License Version 3 or the Perl Artistic License -# Version 2.0. -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -import vltest_bootstrap - -test.scenarios('simulator') - -test.compile() - -test.execute() - -test.passes() diff --git a/test_regress/t/t_stream_crc_example.v b/test_regress/t/t_stream_crc_example.v deleted file mode 100644 index 642ae5be8..000000000 --- a/test_regress/t/t_stream_crc_example.v +++ /dev/null @@ -1,105 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed into the Public Domain, for any use, -// without warranty, 2025 by Wilson Snyder. -// SPDX-License-Identifier: CC0-1.0 -`define stop $stop -`define checkh(gotv, - expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); -`define checks(gotv, - expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); - -typedef bit bit_q_t[$]; - -module t ( /*AUTOARG*/ - // Inputs - clk -); - input clk; - integer cyc = 0; - reg [63:0] crc = '0; - reg [63:0] sum = '0; - - // Take CRC data and apply to testblock inputs - wire [31:0] in = crc[31:0]; - - /*AUTOWIRE*/ - // Beginning of automatic wires (for undeclared instantiated-module outputs) - wire [31:0] out; // From test of Test.v - // End of automatics - - Test test ( - .clk, - .in, - .out - ); - - // Aggregate outputs into a single result vector - wire [63:0] result = {32'h0, out}; - - initial begin - byte unsigned p[$]; - byte unsigned po[$]; - bit bits[$]; - string s; - - p = {8'h84, 8'haa}; - `checkh(p[0], 8'h84); - `checkh(p[1], 8'haa); - - bits = {<<8{bit_q_t'({<<{p}})}}; - bits.push_front(1'b0); - po = {<<8{bit_q_t'({<<{bits}})}}; - - s = $sformatf("p=%p", p); - `checks(s, "p='{'h84, 'haa} "); - - s = $sformatf("bits=%p", bits); - `checks(s, - "bits='{'h0, 'h0, 'h0, 'h1, 'h0, 'h0, 'h0, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1, 'h0, 'h1} "); - - s = $sformatf("po=%p", po); - `checks(s, "po='{'h8, 'h55, 'h80} "); - end - - always_ff @(posedge clk) begin -`ifdef TEST_VERBOSE - $write("[%0t] cyc==%0d crc=%x result=%x sum=%x\n", $time, cyc, crc, result, sum); -`endif - - cyc <= cyc + 1; - crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]}; - sum <= result ^ {sum[62:0], sum[63] ^ sum[2] ^ sum[0]}; - - if (cyc == 0) begin - crc <= 64'h5aef0c8d_d70a4497; - sum <= '0; - end else if (cyc < 10) begin - sum <= '0; - end else if (cyc == 99) begin - `checkh(crc, 64'hc77bb9b3784ea091); - `checkh(sum, 64'h9721d4e989defb24); - $write("*-* All Finished *-*\n"); - $finish; - end - end - -endmodule - -module Test ( - input logic clk, - input logic [31:0] in, - output logic [31:0] out -); - byte unsigned p[$]; - byte unsigned po[$]; - bit bits[$]; - - always_ff @(posedge clk) begin - p = {in[31:24], in[23:16], in[15:8], in[7:0]}; - bits = {<<8{bit_q_t'({<<{p}})}}; - bits.push_front(1'b0); - po = {<<8{bit_q_t'({<<{bits}})}}; - out <= {po[3], po[2], po[1], po[0]}; - end -endmodule diff --git a/test_regress/t/t_stream_unpack.v b/test_regress/t/t_stream_unpack.v index ee6514123..b83ea9174 100644 --- a/test_regress/t/t_stream_unpack.v +++ b/test_regress/t/t_stream_unpack.v @@ -280,8 +280,8 @@ module t (/*AUTOARG*/); o = {<<128{p}}; `checkh(o, 256'habcd0123456789abfadecafedeadbeeffadecafedeadbeefabcd0123456789ab); {>>{p}} = o; - `checkh(p[0], 128'habcd0123456789abfadecafedeadbeef); - `checkh(p[1], 128'hfadecafedeadbeefabcd0123456789ab); + `checkh(p[0], 128'hfadecafedeadbeefabcd0123456789ab); + `checkh(p[1], 128'habcd0123456789abfadecafedeadbeef); $write("*-* All Finished *-*\n"); $finish;