From 6d04110cc74d723515592fc3567dcfe82be07297 Mon Sep 17 00:00:00 2001 From: Bryan Murdock Date: Wed, 1 Apr 2026 13:58:59 -0600 Subject: [PATCH 1/6] added test for q.size() == 1 case --- test_regress/t/t_queue_slice.v | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test_regress/t/t_queue_slice.v b/test_regress/t/t_queue_slice.v index cae6faf09..6c8b7e5fe 100644 --- a/test_regress/t/t_queue_slice.v +++ b/test_regress/t/t_queue_slice.v @@ -84,6 +84,11 @@ module t; q = {q, q}; `checkp(q, "'{\"a\", \"b\", \"a\", \"b\"}"); + q = {"a"}; + q = q[1:$]; + i = q.size(); + `checkh(i, 0); + begin static string ai[$] = '{"Foo", "Bar"}; q = ai; // Copy From a4c09ffe0215949144a0739c25e20f60efaf1406 Mon Sep 17 00:00:00 2001 From: Bryan Murdock Date: Wed, 1 Apr 2026 14:08:54 -0600 Subject: [PATCH 2/6] added myself to CONTRIBUTORS --- docs/CONTRIBUTORS | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index f67c45ae2..11e840cd8 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -30,6 +30,7 @@ AUDIY Aylon Chaim Porat Bartłomiej Chmiel Brian Li +Bryan Murdock Cameron Kirk Cameron Waite Chih-Mao Chen From a31d14e8e659f893bbbc8201fa59f53a810b0e29 Mon Sep 17 00:00:00 2001 From: Bryan Murdock Date: Fri, 3 Apr 2026 09:10:14 -0600 Subject: [PATCH 3/6] fix slice method, reuse other slice test stuff for [1:0] case --- include/verilated_types.h | 8 +++++++- test_regress/t/t_queue_slice.v | 8 +++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/verilated_types.h b/include/verilated_types.h index 8a3360016..da82102fe 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -650,8 +650,14 @@ public: // Return slice q[lsb:msb] VlQueue slice(int32_t lsb, int32_t msb) const { VlQueue out; + if (VL_UNLIKELY(lsb > msb)) return out; + if (VL_UNLIKELY(lsb == msb)) { + if (lsb > 0 && lsb < m_deque.size()) { + out.push_back(m_deque[lsb]); + } + return 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 (int32_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 6c8b7e5fe..32a7ae9dc 100644 --- a/test_regress/t/t_queue_slice.v +++ b/test_regress/t/t_queue_slice.v @@ -68,6 +68,9 @@ module t; `checkp(q, "'{\"d\", \"e\", \"f\"}"); q = q[$:$]; `checkp(q, "'{\"f\"}"); + q = q[1:$]; + `checkp("'{}"); + // Similar using implied notation q = '{"f"}; @@ -84,11 +87,6 @@ module t; q = {q, q}; `checkp(q, "'{\"a\", \"b\", \"a\", \"b\"}"); - q = {"a"}; - q = q[1:$]; - i = q.size(); - `checkh(i, 0); - begin static string ai[$] = '{"Foo", "Bar"}; q = ai; // Copy From 4b66d61818348a2f8d381d4244e4d994a11b5966 Mon Sep 17 00:00:00 2001 From: Bryan Murdock Date: Sun, 3 May 2026 16:17:57 -0600 Subject: [PATCH 4/6] better organized and more complete tests for queue slicing --- test_regress/t/t_queue_slice.v | 120 +++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 6 deletions(-) diff --git a/test_regress/t/t_queue_slice.v b/test_regress/t/t_queue_slice.v index 32a7ae9dc..7b3d5703d 100644 --- a/test_regress/t/t_queue_slice.v +++ b/test_regress/t/t_queue_slice.v @@ -56,21 +56,129 @@ module t; `checks(v, "ins2"); `checkp(q, "'{\"ins0\", \"q\", \"ins2\", \"c\", \"d\", \"e\", \"f\"}"); - // Slicing - q = '{"q", "b", "c", "d", "e", "f"}; - q = q[-1:0]; - `checkp(q, "'{\"q\"}"); + // Slicing. + + // The simple cases: q = '{"q", "b", "c", "d", "e", "f"}; q = q[2:3]; `checkp(q, "'{\"c\", \"d\"}"); q = '{"q", "b", "c", "d", "e", "f"}; q = q[3:$]; `checkp(q, "'{\"d\", \"e\", \"f\"}"); + + // These are all the special cases straight from the LRM. We + // repeat tests for queues with size 1 specially because they are + // tricky. + + // If a > b, then Q[a:b] yields the empty queue {}. + q = '{"q", "b", "c", "d", "e", "f"}; + q = q[4:0]; + `checkp(q, "'{}"); + // FIX! + // q = '{"q", "b", "c", "d", "e", "f"}; + // q = q[$:0]; + // `checkp(q, "'{}"); + q = '{"q"}; + q = q[1:0]; + `checkp(q, "'{}"); + // Or another way of writing the above (this case is specifically + // described under section 7.10.4, Updating a queue using + // assignment) + q = '{"q"}; + q = q[1:$]; + `checkp(q, "'{}"); + + + // Q[ n : n ] yields a queue with one item, the one at position n + q = '{"q", "b", "c", "d", "e", "f"}; + q = q[1:1]; + `checkp(q, "'{\"b\"}"); + q = '{"q", "b", "c", "d", "e", "f"}; q = q[$:$]; `checkp(q, "'{\"f\"}"); - q = q[1:$]; - `checkp("'{}"); + // FIX! + // q = '{"q"}; + // q = q[0:0]; + // `checkp(q, "'{\"q\"}"); + // FIX! + // q = '{"q"}; + // q = q[0:$]; + // `checkp(q, "'{\"q\"}"); + // FIX! + // q = '{"q"}; + // q = q[$:$]; + // `checkp(q, "'{\"q\"}"); + // If n lies outside Q’s range (n < 0 or n > $), then Q[n:n] + // yields the empty queue {} + q = '{"q", "b", "c", "d", "e", "f"}; + q = q[7:7]; + `checkp(q, "'{}"); + q = '{"q"}; + q = q[7:7]; + `checkp(q, "'{}"); + + // If either a or b are 4-state expressions containing X or Z + // values, it yields the empty queue {} + // TODO: z not supported? + // q = '{"q", "b", "c", "d", "e", "f"}; + // q = q['hz:3]; + // `checkp(q, "'{}"); + // TODO: z not supported? + // q = '{"q", "b", "c", "d", "e", "f"}; + // q = q[3:'hz]; + // `checkp(q, "'{}"); + // FIX! + // q = '{"q", "b", "c", "d", "e", "f"}; + // Q = q['hx:3]; + // `checkp(q, "'{}"); + q = '{"q", "b", "c", "d", "e", "f"}; + q = q[3:'hx]; + `checkp(q, "'{}"); + // TODO: z not supported? + // q = '{"q"}; + // q = q['hz:0]; + // `checkp(q, "'{}"); + // TODO: z not supported? + // q = '{"q"}; + // q = q[0:'hz]; + // `checkp(q, "'{}"); + q = '{"q"}; + q = q['bx:0]; + `checkp(q, "'{}"); + q = '{"q"}; + q = q[0:'bx]; + `checkp(q, "'{}"); + + // Q[ a : b ] where a < 0 is the same as Q[ 0 : b ] + q = '{"q", "b", "c", "d", "e", "f"}; + q = q[-1:0]; + `checkp(q, "'{\"q\"}"); + q = '{"q"}; + q = q[-1:0]; + `checkp(q, "'{\"q\"}"); + + // Q[ a : b ] where b > $ is the same as Q[ a : $ ] + q = '{"q", "b", "c", "d", "e", "f"}; + q = q[3:7]; + `checkp(q, "'{\"d\", \"e\", \"f\"}"); + q = '{"q"}; + q = q[0:3]; + `checkp(q, "'{\"q\"}"); + + // There isn't actually a clear statement in the LRM for when a > + // $ and b > $, but in the same section as all the above rules it + // says, "An invalid index value (i.e., a 4-state expression whose + // value has one or more x or z bits, or a value that lies outside + // 0...$) shall cause a read operation to return the value + // appropriate for a nonexistent array entry of the queue’s + // element type (as described in Table 7-1 in 7.4.6)" + q = '{"q", "b", "c", "d", "e", "f"}; + q = q[6:8]; + `checkp(q, "'{}"); + q = '{"q"}; + q = q[6:8]; + `checkp(q, "'{}"); // Similar using implied notation q = '{"f"}; From 12483ab00be73b8212f7047406833eac4fd5c5a8 Mon Sep 17 00:00:00 2001 From: Bryan Murdock Date: Fri, 8 May 2026 19:29:22 -0600 Subject: [PATCH 5/6] let all tests run, remove non-ASCII character --- test_regress/t/t_queue_slice.v | 61 +++++++++------------------------- 1 file changed, 16 insertions(+), 45 deletions(-) diff --git a/test_regress/t/t_queue_slice.v b/test_regress/t/t_queue_slice.v index 7b3d5703d..810247518 100644 --- a/test_regress/t/t_queue_slice.v +++ b/test_regress/t/t_queue_slice.v @@ -75,9 +75,9 @@ module t; q = q[4:0]; `checkp(q, "'{}"); // FIX! - // q = '{"q", "b", "c", "d", "e", "f"}; - // q = q[$:0]; - // `checkp(q, "'{}"); + q = '{"q", "b", "c", "d", "e", "f"}; + q = q[$:0]; + `checkp(q, "'{}"); q = '{"q"}; q = q[1:0]; `checkp(q, "'{}"); @@ -96,20 +96,19 @@ module t; q = '{"q", "b", "c", "d", "e", "f"}; q = q[$:$]; `checkp(q, "'{\"f\"}"); + q = '{"q"}; + q = q[0:0]; + `checkp(q, "'{\"q\"}"); // FIX! - // q = '{"q"}; - // q = q[0:0]; - // `checkp(q, "'{\"q\"}"); + q = '{"q"}; + q = q[0:$]; + `checkp(q, "'{\"q\"}"); // FIX! - // q = '{"q"}; - // q = q[0:$]; - // `checkp(q, "'{\"q\"}"); - // FIX! - // q = '{"q"}; - // q = q[$:$]; - // `checkp(q, "'{\"q\"}"); + q = '{"q"}; + q = q[$:$]; + `checkp(q, "'{\"q\"}"); - // If n lies outside Q’s range (n < 0 or n > $), then Q[n:n] + // If n lies outside Q's range (n < 0 or n > $), then Q[n:n] // yields the empty queue {} q = '{"q", "b", "c", "d", "e", "f"}; q = q[7:7]; @@ -118,37 +117,9 @@ module t; q = q[7:7]; `checkp(q, "'{}"); - // If either a or b are 4-state expressions containing X or Z - // values, it yields the empty queue {} - // TODO: z not supported? - // q = '{"q", "b", "c", "d", "e", "f"}; - // q = q['hz:3]; - // `checkp(q, "'{}"); - // TODO: z not supported? - // q = '{"q", "b", "c", "d", "e", "f"}; - // q = q[3:'hz]; - // `checkp(q, "'{}"); - // FIX! - // q = '{"q", "b", "c", "d", "e", "f"}; - // Q = q['hx:3]; - // `checkp(q, "'{}"); - q = '{"q", "b", "c", "d", "e", "f"}; - q = q[3:'hx]; - `checkp(q, "'{}"); - // TODO: z not supported? - // q = '{"q"}; - // q = q['hz:0]; - // `checkp(q, "'{}"); - // TODO: z not supported? - // q = '{"q"}; - // q = q[0:'hz]; - // `checkp(q, "'{}"); - q = '{"q"}; - q = q['bx:0]; - `checkp(q, "'{}"); - q = '{"q"}; - q = q[0:'bx]; - `checkp(q, "'{}"); + // Skipping until verilator gets X/Z support: If either a or b are + // 4-state expressions containing X or Z values, it yields the + // empty queue {} // Q[ a : b ] where a < 0 is the same as Q[ 0 : b ] q = '{"q", "b", "c", "d", "e", "f"}; From 2a45c7db02fd3a0d4bffe1649af7a4ef7b90dc52 Mon Sep 17 00:00:00 2001 From: Bryan Murdock Date: Fri, 8 May 2026 19:29:57 -0600 Subject: [PATCH 6/6] fix conditional --- include/verilated_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/verilated_types.h b/include/verilated_types.h index da82102fe..6296f9f60 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -652,7 +652,7 @@ public: VlQueue out; if (VL_UNLIKELY(lsb > msb)) return out; if (VL_UNLIKELY(lsb == msb)) { - if (lsb > 0 && lsb < m_deque.size()) { + if (lsb >= 0 && lsb < m_deque.size()) { out.push_back(m_deque[lsb]); } return out;