Add regression tests for methods with signed return values

Check that the signedness of the return value of methods is handled
correctly.
  * When sign extending
  * When passing as a value to a system function

Check this for both methods on user defined class as well as built-in
methods on SystemVerilog types.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-04-03 14:02:04 +02:00
parent 3a26bbb59a
commit 0c123b8498
12 changed files with 759 additions and 0 deletions

View File

@ -0,0 +1,156 @@
// Check that the signedness of methods on the built-in enum type is handled
// correctly when calling the method with parenthesis.
module test;
bit failed = 1'b0;
`define check(x) \
if (!(x)) begin \
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
failed = 1'b1; \
end
int unsigned x = 10;
int y = 10;
int z;
enum shortint {
A = -1,
B = -2,
C = -3
} es;
enum bit [15:0] {
X = 65535,
Y = 65534,
Z = 65533
} eu;
initial begin
es = B;
eu = Y;
// These all evaluate as signed
`check($signed(eu.first()) < 0)
`check(es.first() < 0)
`check($signed(eu.last()) < 0)
`check(es.last() < 0)
`check($signed(eu.prev()) < 0)
`check(es.prev() < 0)
`check($signed(eu.next()) < 0)
`check(es.next() < 0)
// These all evaluate as unsigned
`check(eu.first() > 0)
`check({es.first()} > 0)
`check($unsigned(es.first()) > 0)
`check(es.first() > 16'h0)
`check(eu.last() > 0)
`check({es.last()} > 0)
`check($unsigned(es.last()) > 0)
`check(es.last() > 16'h0)
`check(eu.prev() > 0)
`check({es.prev()} > 0)
`check($unsigned(es.prev()) > 0)
`check(es.prev() > 16'h0)
`check(eu.next() > 0)
`check({es.next()} > 0)
`check($unsigned(es.next()) > 0)
`check(es.next() > 16'h0)
// In arithmetic expressions if one operand is unsigned all operands are
// considered unsigned
z = eu.first() + x;
`check(z === 65545)
z = eu.first() + y;
`check(z === 65545)
z = eu.last() + x;
`check(z === 65543)
z = eu.last() + y;
`check(z === 65543)
z = eu.prev() + x;
`check(z === 65545)
z = eu.prev() + y;
`check(z === 65545)
z = eu.next() + x;
`check(z === 65543)
z = eu.next() + y;
`check(z === 65543)
z = es.first() + x;
`check(z === 65545)
z = es.first() + y;
`check(z === 9)
z = es.last() + x;
`check(z === 65543)
z = es.last() + y;
`check(z === 7)
z = es.prev() + x;
`check(z === 65545)
z = es.prev() + y;
`check(z === 9)
z = es.next() + x;
`check(z === 65543)
z = es.next() + y;
`check(z === 7)
// For ternary operators if one operand is unsigned the result is unsigend
z = x ? eu.first() : x;
`check(z === 65535)
z = x ? eu.first() : y;
`check(z === 65535)
z = x ? eu.last() : x;
`check(z === 65533)
z = x ? eu.last() : y;
`check(z === 65533)
z = x ? eu.prev() : x;
`check(z === 65535)
z = x ? eu.prev() : y;
`check(z === 65535)
z = x ? eu.next() : x;
`check(z === 65533)
z = x ? eu.next() : y;
`check(z === 65533)
z = x ? es.first() : x;
`check(z === 65535)
z = x ? es.first() : y;
`check(z === -1)
z = x ? es.last() : x;
`check(z === 65533)
z = x ? es.last() : y;
`check(z === -3)
z = x ? es.prev() : x;
`check(z === 65535)
z = x ? es.prev() : y;
`check(z === -1)
z = x ? es.next() : x;
`check(z === 65533)
z = x ? es.next() : y;
`check(z === -3)
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,35 @@
// Check that the signedness of methods on the built-in enum type is handled
// correctly when calling the function with parenthesis and passing the result
// to a system function.
module test;
enum shortint {
A = -1,
B = -2,
C = -3
} es;
enum bit [15:0] {
X = 65535,
Y = 65534,
Z = 65533
} eu;
string s;
initial begin
es = B;
eu = Y;
s = $sformatf("%0d %0d %0d %0d %0d %0d %0d %0d",
es.first(), es.last(), es.prev(), es.next(),
eu.first(), eu.last(), eu.prev(), eu.next());
if (s == "-1 -3 -1 -3 65535 65533 65535 65533") begin
$display("PASSED");
end else begin
$display("FAILED s=%s", s);
end
end
endmodule

View File

@ -0,0 +1,156 @@
// Check that the signedness of methods on the built-in enum type is handled
// correctly when calling the method without parenthesis.
module test;
bit failed = 1'b0;
`define check(x) \
if (!(x)) begin \
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
failed = 1'b1; \
end
int unsigned x = 10;
int y = 10;
int z;
enum shortint {
A = -1,
B = -2,
C = -3
} es;
enum bit [15:0] {
X = 65535,
Y = 65534,
Z = 65533
} eu;
initial begin
es = B;
eu = Y;
// These all evaluate as signed
`check($signed(eu.first) < 0)
`check(es.first < 0)
`check($signed(eu.last) < 0)
`check(es.last < 0)
`check($signed(eu.prev) < 0)
`check(es.prev < 0)
`check($signed(eu.next) < 0)
`check(es.next < 0)
// These all evaluate as unsigned
`check(eu.first > 0)
`check({es.first} > 0)
`check($unsigned(es.first) > 0)
`check(es.first > 16'h0)
`check(eu.last > 0)
`check({es.last} > 0)
`check($unsigned(es.last) > 0)
`check(es.last > 16'h0)
`check(eu.prev > 0)
`check({es.prev} > 0)
`check($unsigned(es.prev) > 0)
`check(es.prev > 16'h0)
`check(eu.next > 0)
`check({es.next} > 0)
`check($unsigned(es.next) > 0)
`check(es.next > 16'h0)
// In arithmetic expressions if one operand is unsigned all operands are
// considered unsigned
z = eu.first + x;
`check(z === 65545)
z = eu.first + y;
`check(z === 65545)
z = eu.last + x;
`check(z === 65543)
z = eu.last + y;
`check(z === 65543)
z = eu.prev + x;
`check(z === 65545)
z = eu.prev + y;
`check(z === 65545)
z = eu.next + x;
`check(z === 65543)
z = eu.next + y;
`check(z === 65543)
z = es.first + x;
`check(z === 65545)
z = es.first + y;
`check(z === 9)
z = es.last + x;
`check(z === 65543)
z = es.last + y;
`check(z === 7)
z = es.prev + x;
`check(z === 65545)
z = es.prev + y;
`check(z === 9)
z = es.next + x;
`check(z === 65543)
z = es.next + y;
`check(z === 7)
// For ternary operators if one operand is unsigned the result is unsigend
z = x ? eu.first : x;
`check(z === 65535)
z = x ? eu.first : y;
`check(z === 65535)
z = x ? eu.last : x;
`check(z === 65533)
z = x ? eu.last : y;
`check(z === 65533)
z = x ? eu.prev : x;
`check(z === 65535)
z = x ? eu.prev : y;
`check(z === 65535)
z = x ? eu.next : x;
`check(z === 65533)
z = x ? eu.next : y;
`check(z === 65533)
z = x ? es.first : x;
`check(z === 65535)
z = x ? es.first : y;
`check(z === -1)
z = x ? es.last : x;
`check(z === 65533)
z = x ? es.last : y;
`check(z === -3)
z = x ? es.prev : x;
`check(z === 65535)
z = x ? es.prev : y;
`check(z === -1)
z = x ? es.next : x;
`check(z === 65533)
z = x ? es.next : y;
`check(z === -3)
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,35 @@
// Check that the signedness of methods on the built-in enum type is handled
// correctly when calling the function without parenthesis and passing the
// result to a system function.
module test;
enum shortint {
A = -1,
B = -2,
C = -3
} es;
enum bit [15:0] {
X = 65535,
Y = 65534,
Z = 65533
} eu;
string s;
initial begin
es = B;
eu = Y;
s = $sformatf("%0d %0d %0d %0d %0d %0d %0d %0d",
es.first, es.last, es.prev, es.next,
eu.first, eu.last, eu.prev, eu.next);
if (s == "-1 -3 -1 -3 65535 65533 65535 65533") begin
$display("PASSED");
end else begin
$display("FAILED s=%s", s);
end
end
endmodule

View File

@ -0,0 +1,71 @@
// Check that the signedness of methods on user defined classes is handled
// correctly.
module test;
bit failed = 1'b0;
`define check(x) \
if (!(x)) begin \
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
failed = 1'b1; \
end
class C;
function shortint s;
return -1;
endfunction
function bit [15:0] u;
return -1;
endfunction
endclass
C c;
int unsigned x = 10;
int y = 10;
int z;
initial begin
c = new;
// These all evaluate as signed
`check($signed(c.u()) < 0)
`check(c.s() < 0)
// These all evaluate as unsigned
`check(c.u() > 0)
`check({c.s()} > 0)
`check($unsigned(c.s()) > 0)
`check(c.s() > 16'h0)
// In arithmetic expressions if one operand is unsigned all operands are
// considered unsigned
z = c.u() + x;
`check(z === 65545)
z = c.u() + y;
`check(z === 65545)
z = c.s() + x;
`check(z === 65545)
z = c.s() + y;
`check(z === 9)
// For ternary operators if one operand is unsigned the result is unsigend
z = x ? c.u() : x;
`check(z === 65535)
z = x ? c.u() : y;
`check(z === 65535)
z = x ? c.s() : x;
`check(z === 65535)
z = x ? c.s() : y;
`check(z === -1)
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,30 @@
// Check that the signedness of methods on user defined classes is handled
// correctly when passing the result to a system function.
module test;
class C;
function shortint s;
return -1;
endfunction
function bit [15:0] u;
return -1;
endfunction
endclass
C c;
string s;
initial begin
c = new;
s = $sformatf("%0d %0d", c.s(), c.u());
if (s == "-1 65535") begin
$display("PASSED");
end else begin
$display("FAILED s=%s", s);
end
end
endmodule

View File

@ -0,0 +1,99 @@
// Check that the signedness of the element type of a queue is correctly handled
// whenn calling one of the pop methods with parenthesis.
module test;
bit failed = 1'b0;
`define check(x) \
if (!(x)) begin \
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
failed = 1'b1; \
end
int unsigned x = 10;
int y = 10;
int z;
longint w;
shortint qs[$];
bit [15:0] qu[$];
initial begin
for (int i = 0; i < 16; i++) begin
qu.push_back(-1);
qs.push_back(-1);
end
// These all evaluate as signed
`check($signed(qu.pop_back()) < 0)
`check(qs.pop_back() < 0)
`check($signed(qu.pop_front()) < 0)
`check(qs.pop_front() < 0)
// These all evaluate as unsigned
`check(qu.pop_back() > 0)
`check({qs.pop_back()} > 0)
`check($unsigned(qs.pop_back()) > 0)
`check(qs.pop_back() > 16'h0)
`check(qu.pop_front() > 0)
`check({qs.pop_front()} > 0)
`check($unsigned(qs.pop_front()) > 0)
`check(qs.pop_front() > 16'h0)
// In arithmetic expressions if one operand is unsigned all operands are
// considered unsigned
z = qu.pop_back() + x;
`check(z === 65545)
z = qu.pop_back() + y;
`check(z === 65545)
z = qu.pop_front() + x;
`check(z === 65545)
z = qu.pop_front() + y;
`check(z === 65545)
z = qs.pop_back() + x;
`check(z === 65545)
z = qs.pop_back() + y;
`check(z === 9)
z = qs.pop_front() + x;
`check(z === 65545)
z = qs.pop_front() + y;
`check(z === 9)
// For ternary operators if one operand is unsigned the result is unsigend
z = x ? qu.pop_back() : x;
`check(z === 65535)
z = x ? qu.pop_back() : y;
`check(z === 65535)
z = x ? qu.pop_front() : x;
`check(z === 65535)
z = x ? qu.pop_front() : y;
`check(z === 65535)
z = x ? qs.pop_back() : x;
`check(z === 65535)
z = x ? qs.pop_back() : y;
`check(z === -1)
z = x ? qs.pop_front() : x;
`check(z === 65535)
z = x ? qs.pop_front() : y;
`check(z === -1)
// Size return value is always positive, but check that it gets padded
// properly
w = x ? qu.size() : 64'h123;
`check(w === 64'h4)
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,29 @@
// Check that the signedness of the element type of a queue is correctly handled
// when passing the result of one of the pop methods as an argument to a system
// function.
module test;
shortint qs[$];
bit [15:0] qu[$];
string s;
initial begin
qs.push_back(-1);
qs.push_back(-2);
qu.push_back(-1);
qu.push_back(-2);
// Values popped from qs should be treated as signed, values popped from qu
// should be treated as unsigned
s = $sformatf("%0d %0d %0d %0d", qs.pop_front(), qs.pop_back(),
qu.pop_front(), qu.pop_back());
if (s == "-1 -2 65535 65534") begin
$display("PASSED");
end else begin
$display("FAILED s=%s", s);
end
end
endmodule

View File

@ -0,0 +1,99 @@
// Check that the signedness of the element type of a queue is correctly handled
// whenn calling one of the pop methods with parenthesis.
module test;
bit failed = 1'b0;
`define check(x) \
if (!(x)) begin \
$display("FAILED(%0d): ", `__LINE__, `"x`"); \
failed = 1'b1; \
end
int unsigned x = 10;
int y = 10;
int z;
longint w;
shortint qs[$];
bit [15:0] qu[$];
initial begin
for (int i = 0; i < 16; i++) begin
qu.push_back(-1);
qs.push_back(-1);
end
// These all evaluate as signed
`check($signed(qu.pop_back) < 0)
`check(qs.pop_back < 0)
`check($signed(qu.pop_front) < 0)
`check(qs.pop_front < 0)
// These all evaluate as unsigned
`check(qu.pop_back > 0)
`check({qs.pop_back} > 0)
`check($unsigned(qs.pop_back) > 0)
`check(qs.pop_back > 16'h0)
`check(qu.pop_front > 0)
`check({qs.pop_front} > 0)
`check($unsigned(qs.pop_front) > 0)
`check(qs.pop_front > 16'h0)
// In arithmetic expressions if one operand is unsigned all operands are
// considered unsigned
z = qu.pop_back + x;
`check(z === 65545)
z = qu.pop_back + y;
`check(z === 65545)
z = qu.pop_front + x;
`check(z === 65545)
z = qu.pop_front + y;
`check(z === 65545)
z = qs.pop_back + x;
`check(z === 65545)
z = qs.pop_back + y;
`check(z === 9)
z = qs.pop_front + x;
`check(z === 65545)
z = qs.pop_front + y;
`check(z === 9)
// For ternary operators if one operand is unsigned the result is unsigend
z = x ? qu.pop_back : x;
`check(z === 65535)
z = x ? qu.pop_back : y;
`check(z === 65535)
z = x ? qu.pop_front : x;
`check(z === 65535)
z = x ? qu.pop_front : y;
`check(z === 65535)
z = x ? qs.pop_back : x;
`check(z === 65535)
z = x ? qs.pop_back : y;
`check(z === -1)
z = x ? qs.pop_front : x;
`check(z === 65535)
z = x ? qs.pop_front : y;
`check(z === -1)
// Size return value is always positive, but check that it gets padded
// properly
w = x ? qu.size : 64'h123;
`check(w === 64'h4)
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -0,0 +1,29 @@
// Check that the signedness of the element type of a queue is correctly handled
// when passing the result of one of the pop methods as an argument to a system
// function.
module test;
shortint qs[$];
bit [15:0] qu[$];
string s;
initial begin
qs.push_back(-1);
qs.push_back(-2);
qu.push_back(-1);
qu.push_back(-2);
// Values popped from qs should be treated as signed, values popped from qu
// should be treated as unsigned
s = $sformatf("%0d %0d %0d %0d", qs.pop_front, qs.pop_back,
qu.pop_front, qu.pop_back);
if (s == "-1 -2 65535 65534") begin
$display("PASSED");
end else begin
$display("FAILED s=%s", s);
end
end
endmodule

View File

@ -265,6 +265,10 @@ enum_in_struct normal,-g2005-sv ivltests
enum_in_class normal,-g2005-sv ivltests
enum_in_class_name_coll CE,-g2005-sv ivltests
enum_line_info CE,-g2005-sv ivltests gold=enum_line_info.gold
enum_method_signed1 normal,-g2005-sv ivltests
enum_method_signed2 normal,-g2005-sv ivltests
enum_method_signed3 normal,-g2005-sv ivltests
enum_method_signed4 normal,-g2005-sv ivltests
enum_next normal,-g2005-sv ivltests
enum_order normal,-g2005-sv ivltests
enum_ports normal,-g2005-sv ivltests
@ -488,6 +492,8 @@ sv_class_extends_scoped normal,-g2009 ivltests
sv_class_localparam normal,-g2009 ivltests
sv_class_new_init normal,-g2009 ivltests
sv_class_in_module_decl normal,-g2009 ivltests
sv_class_method_signed1 normal,-g2009 ivltests
sv_class_method_signed2 normal,-g2009 ivltests
sv_class_static_prop1 normal,-g2009 ivltests
sv_class_static_prop2 normal,-g2009 ivltests
sv_class_static_prop3 normal,-g2009 ivltests
@ -571,6 +577,10 @@ sv_queue_parray_fail CE,-g2009 ivltests gold=sv_queue_parray_fail.gold
sv_queue_real normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real.gold
sv_queue_real_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real_bounded.gold
sv_queue_real_fail CE,-g2009 ivltests gold=sv_queue_real_fail.gold
sv_queue_method_signed1 normal,-g2009 ivltests
sv_queue_method_signed2 normal,-g2009 ivltests
sv_queue_method_signed3 normal,-g2009 ivltests
sv_queue_method_signed4 normal,-g2009 ivltests
sv_queue_string normal,-g2009,-pfileline=1 ivltests gold=sv_queue_string.gold
sv_queue_string_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_string_bounded.gold
sv_queue_string_fail CE,-g2009 ivltests gold=sv_queue_string_fail.gold

View File

@ -384,6 +384,8 @@ sv_class_extends_scoped CE,-g2009 ivltests
sv_class_localparam CE,-g2009 ivltests
sv_class_new_init CE,-g2009 ivltests
sv_class_in_module_decl CE,-g2009 ivltests
sv_class_method_signed1 CE,-g2009,-pallowsigned=1 ivltests
sv_class_method_signed2 CE,-g2009,-pallowsigned=1 ivltests
sv_class_static_prop1 CE,-g2009 ivltests
sv_class_static_prop2 CE,-g2009 ivltests
sv_class_static_prop3 CE,-g2009 ivltests
@ -438,6 +440,10 @@ br_gh436 CE,-g2012,-pallowsigned=1 ivltests # queues/strings
br_gh672 CE,-g2009 ivltests # join_none
br_mw20200501 CE,-g2009 ivltests # queues
disable_fork_cmd CE,-g2009 ivltests # disable fork and join_*
enum_method_signed1 CE,-g2009,-pallowsigned=1 ivltests
enum_method_signed2 CE,-g2009,-pallowsigned=1 ivltests
enum_method_signed3 CE,-g2009,-pallowsigned=1 ivltests
enum_method_signed4 CE,-g2009,-pallowsigned=1 ivltests
enum_next CE,-g2009,-pallowsigned=1 ivltests # enum
enum_test1 CE,-g2009 ivltests # enum
fork_join_any CE,-g2009,-pallowsigned=1 ivltests # join_any
@ -611,6 +617,10 @@ br_gh433 CE,-g2009,-pallowsigned=1 ivltests
sv_queue1 CE,-g2009,-pallowsigned=1 ivltests
sv_queue2 CE,-g2009,-pallowsigned=1 ivltests
sv_queue3 CE,-g2009 ivltests
sv_queue_method_signed1 CE,-g2009,-pallowsigned=1 ivltests
sv_queue_method_signed2 CE,-g2009,-pallowsigned=1 ivltests
sv_queue_method_signed3 CE,-g2009,-pallowsigned=1 ivltests
sv_queue_method_signed4 CE,-g2009,-pallowsigned=1 ivltests
sv_queue_real CE,-g2009 ivltests
sv_queue_real_bounded CE,-g2009 ivltests
sv_queue_real_fail CE,-g2009 ivltests