From 046c0a7aa1d930e7c82819d0db9891e899cfe699 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 24 Oct 2020 22:08:11 -0400 Subject: [PATCH] Fix queue assignment with different limits, negative indicies --- include/verilated_heavy.h | 31 +++++++++++++++++++++---------- test_regress/t/t_queue_slice.v | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index e7a01f21c..e8d9dbde3 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -272,7 +272,15 @@ public: // m_defaultValue isn't defaulted. Caller's constructor must do it. } ~VlQueue() {} + // Standard copy constructor works. Verilog: assoca = assocb + // Also must allow conversion from a different T_MaxSize queue + template VlQueue operator=(const VlQueue& rhs) { + m_deque = rhs.privateDeque(); + if (VL_UNLIKELY(T_MaxSize && T_MaxSize < m_deque.size())) m_deque.resize(T_MaxSize - 1); + return *this; + } + static VlQueue cons(const T_Value& lhs) { VlQueue out; out.push_back(lhs); @@ -302,13 +310,15 @@ public: // METHODS T_Value& atDefault() { return m_defaultValue; } + const Deque& privateDeque() const { return m_deque; } // Size. Verilog: function int size(), or int num() int size() const { return m_deque.size(); } // Clear array. Verilog: function void delete([input index]) void clear() { m_deque.clear(); } - void erase(size_t index) { - if (VL_LIKELY(index < m_deque.size())) m_deque.erase(m_deque.begin() + index); + void erase(vlsint32_t index) { + if (VL_LIKELY(index >= 0 && index < m_deque.size())) + m_deque.erase(m_deque.begin() + index); } // Dynamic array new[] becomes a renew() @@ -353,10 +363,10 @@ public: // Setting. Verilog: assoc[index] = v // Can't just overload operator[] or provide a "at" reference to set, // because we need to be able to insert only when the value is set - T_Value& at(size_t index) { + T_Value& at(vlsint32_t index) { static T_Value s_throwAway; // Needs to work for dynamic arrays, so does not use T_MaxSize - if (VL_UNLIKELY(index >= m_deque.size())) { + if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) { s_throwAway = atDefault(); return s_throwAway; } else { @@ -364,27 +374,28 @@ public: } } // Accessing. Verilog: v = assoc[index] - const T_Value& at(size_t index) const { + const T_Value& at(vlsint32_t index) const { static T_Value s_throwAway; // Needs to work for dynamic arrays, so does not use T_MaxSize - if (VL_UNLIKELY(index >= m_deque.size())) { + if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) { return atDefault(); } else { return m_deque[index]; } } // function void q.insert(index, value); - void insert(size_t index, const T_Value& value) { - if (VL_UNLIKELY(index >= m_deque.size())) return; + void insert(vlsint32_t index, const T_Value& value) { + if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) return; m_deque.insert(m_deque.begin() + index, value); } // Return slice q[lsb:msb] - VlQueue slice(size_t lsb, size_t msb) const { + VlQueue slice(vlsint32_t lsb, vlsint32_t msb) const { VlQueue out; + if (VL_UNLIKELY(lsb < 0)) lsb = 0; if (VL_UNLIKELY(lsb >= m_deque.size())) lsb = m_deque.size() - 1; if (VL_UNLIKELY(msb >= m_deque.size())) msb = m_deque.size() - 1; - for (size_t i = lsb; i <= msb; ++i) out.push_back(m_deque[i]); + for (vlsint32_t i = lsb; i <= msb; ++i) out.push_back(m_deque[i]); return out; } diff --git a/test_regress/t/t_queue_slice.v b/test_regress/t/t_queue_slice.v index b1cd39408..3ee6e2844 100644 --- a/test_regress/t/t_queue_slice.v +++ b/test_regress/t/t_queue_slice.v @@ -13,6 +13,8 @@ module t (/*AUTOARG*/); string q[$]; string v; int i; + int qi[$:5]; + int ri[$]; q.push_front("non-empty"); i = q.size(); `checkh(i, 1); @@ -43,6 +45,9 @@ module t (/*AUTOARG*/); // Slicing q = '{"q", "b", "c", "d", "e", "f"}; + q = q[-1:0]; + v = $sformatf("%p", q); `checks(v, "'{\"q\"} "); + q = '{"q", "b", "c", "d", "e", "f"}; q = q[2:3]; v = $sformatf("%p", q); `checks(v, "'{\"c\", \"d\"} "); q = '{"q", "b", "c", "d", "e", "f"}; @@ -80,7 +85,34 @@ module t (/*AUTOARG*/); v = q.pop_front(); `checks(v, "CC"); end + begin + qi.push_back(0); + qi.push_back(1); + qi.push_back(2); + qi.push_back(3); + qi.push_back(4); + qi.push_back(5); + + // Assignment to unsized queue from sized queue + ri = qi[ 2 : 4 ]; + `checkh(ri.size, 3); + ri = qi[ 4 : 2 ]; + `checkh(ri.size, 0); + ri = qi[ 2 : 2 ]; + `checkh(ri.size, 1); + ri = qi[ -2 : 2 ]; // 2 - 0 + 1 = 3 + `checkh(ri.size, 3); + ri = qi[ 2 : 10 ]; // 5 - 2 + 1 = 4 + `checkh(ri.size, 4); + + // Assignment from unsized to sized + ri = '{1,2,3,4,5,6,7,8,9}; + qi = ri; + `checkh(qi.size, 5); + end + $write("*-* All Finished *-*\n"); $finish; end + endmodule