From 662e82c013ac69a4e53e96ab942d8fda6440d37b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Jan 2022 09:36:52 +0100 Subject: [PATCH 1/2] Handle signedness of struct members struct members are currently always treated as unsigned. This leads to incorrect behavior in contexts where the sign makes a difference. E.g. ``` struct packed { int x; } s; s.x = -1; if (s.x > 0) $display("FAILED"); ``` Query the signedness of the struct member form the type of the member. Signed-off-by: Lars-Peter Clausen --- netstruct.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netstruct.h b/netstruct.h index 767819e4b..211796f06 100644 --- a/netstruct.h +++ b/netstruct.h @@ -34,8 +34,8 @@ class netstruct_t : public LineInfo, public ivl_type_s { ivl_type_t net_type; inline ivl_variable_type_t data_type() const { return net_type->base_type(); }; - // We need to keep the individual element sign information. - bool get_signed() const { return false; }; + bool get_signed() const + { return net_type->get_signed(); } }; public: From 1c0955178d58b7c48f997dfdae38f20553052ed0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 27 Jan 2022 10:35:56 +0100 Subject: [PATCH 2/2] Add regression test for struct member signedness Check that when using a struct member in an expression its signedness is handled correctly. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/struct_member_signed.v | 41 ++++++++++++++++++++++++++ ivtest/regress-sv.list | 1 + ivtest/regress-vlog95.list | 1 + 3 files changed, 43 insertions(+) create mode 100644 ivtest/ivltests/struct_member_signed.v diff --git a/ivtest/ivltests/struct_member_signed.v b/ivtest/ivltests/struct_member_signed.v new file mode 100644 index 000000000..87256bead --- /dev/null +++ b/ivtest/ivltests/struct_member_signed.v @@ -0,0 +1,41 @@ +// Tests that the signedness for struct members is handled correctly + +module test; + + struct packed { + logic [15:0] x; + logic signed [15:0] y; + } s; + + bit failed = 1'b0; + + `define check(x) \ + if (!(x)) begin \ + $display("FAILED: ", `"x`"); \ + failed = 1'b1; \ + end + + initial begin + s.x = -1; + s.y = -1; + + `check(!$is_signed(s.x)); + `check($is_signed(s.y)); + + // These evaluate as signed + `check($signed(s.x) < 0); + `check(s.y < 0); + + // These all evaluate as unsigned + `check(s.x > 0); + `check(s.y[15:0] > 0) + `check({s.y} > 0) + `check($unsigned(s.y) > 0) + `check(s.y > 16'h0) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index b65e12961..a0bfc15e6 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -383,6 +383,7 @@ struct7 normal,-g2009 ivltests struct8 normal,-g2009 ivltests struct9 normal,-g2009 ivltests struct_line_info CE,-g2009 ivltests gold=struct_line_info.gold +struct_member_signed normal,-g2009 ivltests struct_packed_array normal,-g2009 ivltests struct_packed_array2 normal,-g2009 ivltests struct_packed_sysfunct normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 402e8e351..b140c0a89 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -839,6 +839,7 @@ simple_longint normal,-g2009,-pallowsigned=1 ivltests simple_shortint normal,-g2009,-pallowsigned=1 ivltests size_cast3 normal,-g2009,-pallowsigned=1 ivltests size_cast5 normal,-g2009,-pallowsigned=1 ivltests +struct_member_signed normal,-g2009,-pallowsigned=1 ivltests struct_packed_array normal,-g2009,-pallowsigned=1 ivltests struct_packed_array2 normal,-g2009,-pallowsigned=1 ivltests struct_signed normal,-g2009,-pallowsigned=1 ivltests