From 278e071b35682ffca1e4b2197f8848c32bd35e2d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Jan 2022 17:42:15 +0100 Subject: [PATCH 1/3] netqueue_t: Remove redundant get_signed() method The get_signed() method for the netqueue_t class is identical to that of its base class netdarray_t. Remove the redundant re-implementation of the method. Signed-off-by: Lars-Peter Clausen --- netqueue.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/netqueue.h b/netqueue.h index ecc64be1f..13061ca33 100644 --- a/netqueue.h +++ b/netqueue.h @@ -38,9 +38,6 @@ class netqueue_t : public netdarray_t { // IVL_VT_QUEUE for queues. ivl_variable_type_t base_type() const; - // A queue may have a type that is signed. - inline bool get_signed() const { return element_type()->get_signed(); } - // Use the packed width to pass the element width long packed_width(void) const { return element_type()->packed_width(); } From abc3ad95e63615f7783c20c7ff29a4e3251e2e35 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Jan 2022 18:23:08 +0100 Subject: [PATCH 2/3] Return value of correct width for dynamic array out-of-bound access Commit e1870acfacc9 ("Return the correct value when a queue or darray references an undefined element") added support for specifying the width of the vector elements stored in a queue or dynamic array, so that an out-of-bounds access can create a word with the right width. To get the element width of a queue or dynamic array it uses the `packed_width()` method. But this method is only implemented for `netqueue_t` and returns always 1 for dynamic arrays. As a result out-of-bounds access on a dynamic array will push a vector of the wrong width onto the stack if the vector element is wider than 1 bit. This will usually trigger an assert in vvp. Fix this by moving the `packed_width()` method implementation from `netqueue_t` to its base class `netdarray_t` so that it works for all types of dynamic arrays. Signed-off-by: Lars-Peter Clausen --- netdarray.h | 3 +++ netqueue.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/netdarray.h b/netdarray.h index 326f07d4c..890995ad1 100644 --- a/netdarray.h +++ b/netdarray.h @@ -36,6 +36,9 @@ class netdarray_t : public netarray_t { // A dynamic array may have a type that is signed. inline bool get_signed() const { return element_type()->get_signed(); } + // Use the packed width to pass the element width + long packed_width() const { return element_type()->packed_width(); } + // This is the base_type() of the element of the array. We // need this in some cases in order to get the base type of // the element, and not the IVL_VT_DARRAY of the array itself. diff --git a/netqueue.h b/netqueue.h index 13061ca33..1e04e4535 100644 --- a/netqueue.h +++ b/netqueue.h @@ -38,9 +38,6 @@ class netqueue_t : public netdarray_t { // IVL_VT_QUEUE for queues. ivl_variable_type_t base_type() const; - // Use the packed width to pass the element width - long packed_width(void) const { return element_type()->packed_width(); } - long max_idx(void) const { return max_idx_; } std::ostream& debug_dump(std::ostream&) const; From b83daa3ae36891a372655652e53c9b4eefdfcafa Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 14 May 2022 13:57:18 +0200 Subject: [PATCH 3/3] Add regression tests for dynamic array and queue out-of-bounds access Check that out-of-bounds access on a dynamic array or queue works and returns the correct value. * 2-state vectors: '0 with the element width * 4-state vectors: 'x with the element width * reals: 0.0 * strings: "" Note that the 2-state test currently still fails as out-of-bounds access on a 2-state vector incorrectly returns 'x. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_darray_oob_real.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_darray_oob_string.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_darray_oob_vec2.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_darray_oob_vec4.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_queue_oob_real.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_queue_oob_string.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_queue_oob_vec2.v | 18 ++++++++++++++++++ ivtest/ivltests/sv_queue_oob_vec4.v | 18 ++++++++++++++++++ ivtest/regress-fsv.list | 2 ++ ivtest/regress-sv.list | 6 ++++++ ivtest/regress-vlog95.list | 8 ++++++++ 11 files changed, 160 insertions(+) create mode 100644 ivtest/ivltests/sv_darray_oob_real.v create mode 100644 ivtest/ivltests/sv_darray_oob_string.v create mode 100644 ivtest/ivltests/sv_darray_oob_vec2.v create mode 100644 ivtest/ivltests/sv_darray_oob_vec4.v create mode 100644 ivtest/ivltests/sv_queue_oob_real.v create mode 100644 ivtest/ivltests/sv_queue_oob_string.v create mode 100644 ivtest/ivltests/sv_queue_oob_vec2.v create mode 100644 ivtest/ivltests/sv_queue_oob_vec4.v diff --git a/ivtest/ivltests/sv_darray_oob_real.v b/ivtest/ivltests/sv_darray_oob_real.v new file mode 100644 index 000000000..29fd5a821 --- /dev/null +++ b/ivtest/ivltests/sv_darray_oob_real.v @@ -0,0 +1,18 @@ +// Check that out-of-bounds access on a real typed dynamic array works and +// returns the correct value. + +module test; + + real d[]; + real x; + + initial begin + x = d[1]; + if (x == 0.0) begin + $display("PASSED"); + end else begin + $display("FAILED. Expected 0.0, got %f", x); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_oob_string.v b/ivtest/ivltests/sv_darray_oob_string.v new file mode 100644 index 000000000..2d8878662 --- /dev/null +++ b/ivtest/ivltests/sv_darray_oob_string.v @@ -0,0 +1,18 @@ +// Check that out-of-bounds access on a string typed dynamic array works and +// returns the right value. + +module test; + + string d[]; + string x; + + initial begin + x = d[1]; + if (x == "") begin + $display("PASSED"); + end else begin + $display("FAILED. Expected '', got '%s'", x); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_oob_vec2.v b/ivtest/ivltests/sv_darray_oob_vec2.v new file mode 100644 index 000000000..92468f335 --- /dev/null +++ b/ivtest/ivltests/sv_darray_oob_vec2.v @@ -0,0 +1,18 @@ +// Check that out-of-bounds access on a 2-state vector dynamic array works and +// returns the correct value. + +module test; + + bit [7:0] d[]; + logic [7:0] x; + + initial begin + x = d[1]; + if (x === 8'h00) begin + $display("PASSED"); + end else begin + $display("FAILED. Expected 00000000, got %b",x); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_oob_vec4.v b/ivtest/ivltests/sv_darray_oob_vec4.v new file mode 100644 index 000000000..fd77bd283 --- /dev/null +++ b/ivtest/ivltests/sv_darray_oob_vec4.v @@ -0,0 +1,18 @@ +// Check that out-of-bounds access on a 4-state vector dynamic array works and +// returns the correct value. + +module test; + + logic [7:0] d[]; + logic [7:0] x; + + initial begin + x = d[1]; + if (x === 8'hxx) begin + $display("PASSED"); + end else begin + $display("FAILED. Expected xxxxxxxx, got %b", x); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_oob_real.v b/ivtest/ivltests/sv_queue_oob_real.v new file mode 100644 index 000000000..f59256993 --- /dev/null +++ b/ivtest/ivltests/sv_queue_oob_real.v @@ -0,0 +1,18 @@ +// Check that out-of-bounds access on a real typed queue works and returns the +// correct value. + +module test; + + real q[$]; + real x; + + initial begin + x = q[1]; + if (x == 0.0) begin + $display("PASSED"); + end else begin + $display("FAILED. Expected 0.0, got %f", x); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_oob_string.v b/ivtest/ivltests/sv_queue_oob_string.v new file mode 100644 index 000000000..5126e4c8f --- /dev/null +++ b/ivtest/ivltests/sv_queue_oob_string.v @@ -0,0 +1,18 @@ +// Check that out-of-bounds access on a string typed queue works and returns the +// right value. + +module test; + + string q[$]; + string x; + + initial begin + x = q[1]; + if (x == "") begin + $display("PASSED"); + end else begin + $display("FAILED. Expected '', got '%s'", x); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_oob_vec2.v b/ivtest/ivltests/sv_queue_oob_vec2.v new file mode 100644 index 000000000..495d7e37b --- /dev/null +++ b/ivtest/ivltests/sv_queue_oob_vec2.v @@ -0,0 +1,18 @@ +// Check that out-of-bounds access on a 2-state vector queue works and returns +// the correct value. + +module test; + + bit [7:0] q[$]; + logic [7:0] x; + + initial begin + x = q[1]; + if (x === 8'h00) begin + $display("PASSED"); + end else begin + $display("FAILED. Expected 00000000, got %b",x); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_oob_vec4.v b/ivtest/ivltests/sv_queue_oob_vec4.v new file mode 100644 index 000000000..ca1a90afc --- /dev/null +++ b/ivtest/ivltests/sv_queue_oob_vec4.v @@ -0,0 +1,18 @@ +// Check that out-of-bounds access on a 4-state vector queue works and returns +// the correct value. + +module test; + + logic [7:0] q[$]; + logic [7:0] x; + + initial begin + x = q[1]; + if (x === 8'hxx) begin + $display("PASSED"); + end else begin + $display("FAILED. Expected xxxxxxxx, got %b", x); + end + end + +endmodule diff --git a/ivtest/regress-fsv.list b/ivtest/regress-fsv.list index 2bcbcd4aa..f8e0625a8 100644 --- a/ivtest/regress-fsv.list +++ b/ivtest/regress-fsv.list @@ -129,6 +129,7 @@ sv_darray_nest1 normal ivltests sv_darray_nest2 normal ivltests sv_darray_nest3 normal ivltests sv_darray_nest4 normal ivltests +sv_darray_oob_vec2 normal ivltests sv_deferred_assert1 normal ivltests sv_deferred_assert2 normal ivltests sv_deferred_assume1 normal ivltests @@ -137,3 +138,4 @@ sv_queue_nest1 normal ivltests sv_queue_nest2 normal ivltests sv_queue_nest3 normal ivltests sv_queue_nest4 normal ivltests +sv_queue_oob_vec2 normal ivltests diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 2aa6adcbe..70ae36555 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -531,6 +531,9 @@ sv_darray_args3 normal,-g2009 ivltests sv_darray_args4 normal,-g2009 ivltests sv_darray_decl_assign normal,-g2009 ivltests sv_darray_function normal,-g2009 ivltests +sv_darray_oob_real normal,-g2009 ivltests +sv_darray_oob_string normal,-g2009 ivltests +sv_darray_oob_vec4 normal,-g2009 ivltests sv_darray_signed normal,-g2009 ivltests sv_darray_word_size normal,-g2005-sv ivltests sv_default_port_value1 normal,-g2009 ivltests @@ -589,6 +592,9 @@ sv_queue2 normal,-g2009 ivltests sv_queue3 normal,-g2009 ivltests sv_queue_function1 normal,-g2009 ivltests sv_queue_function2 normal,-g2009 ivltests +sv_queue_oob_real normal,-g2009 ivltests +sv_queue_oob_string normal,-g2009 ivltests +sv_queue_oob_vec4 normal,-g2009 ivltests sv_queue_parray normal,-g2009,-pfileline=1 ivltests gold=sv_queue_parray.gold sv_queue_parray_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_parray_bounded.gold sv_queue_parray_fail CE,-g2009 ivltests gold=sv_queue_parray_fail.gold diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 48fc76b7c..cd6a919e5 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -342,6 +342,10 @@ sv_darray_args3 CE,-g2009,-pallowsigned=1 ivltests sv_darray_args4 CE,-g2009,-pallowsigned=1 ivltests # Also string sv_darray_decl_assign CE,-g2009,-pallowsigned=1 ivltests sv_darray_function CE,-g2009,-pallowsigned=1 ivltests +sv_darray_oob_real CE,-g2009 ivltests +sv_darray_oob_string CE,-g2009 ivltests # Also string +sv_darray_oob_vec2 CE,-g2009 ivltests # Also 2-state +sv_darray_oob_vec4 CE,-g2009 ivltests sv_darray_signed CE,-g2009,-pallowsigned=1 ivltests # Also string sv_darray_word_size CE,-g2009 ivltests sv_new_array_error CE,-g2009, ivltests @@ -475,6 +479,10 @@ pr3390385d CE,-g2009 ivltests # ++ pr3462145 CE,-g2009 ivltests # ++ sv_queue_function1 CE,-g2009,-pallowsigned=1 ivltests # queue sv_queue_function2 CE,-g2009,-pallowsigned=1 ivltests # queue +sv_queue_oob_real CE,-g2009 ivltests # queue +sv_queue_oob_string CE,-g2009 ivltests # queue, string +sv_queue_oob_vec2 CE,-g2009 ivltests # queue, 2-state +sv_queue_oob_vec4 CE,-g2009 ivltests # queue sv_typedef_darray_base1 CE,-g2009 ivltests # Dyanmic array sv_typedef_darray_base2 CE,-g2009 ivltests # Dyanmic array sv_typedef_darray_base3 CE,-g2009 ivltests # Dyanmic array