From 4ab59dd55e28a3084ed9a54ddd9ecdfba3967a6a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 4 Jun 2023 15:57:38 -0700 Subject: [PATCH] Add regression tests for oob write to function return value Check that partial and fully out-of-bound writes to a function's return value are handled correctly. Check this for both 4-state and 2-state vectors. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/pv_wr_fn_vec2.v | 99 ++++++++++++++++++++++++++ ivtest/ivltests/pv_wr_fn_vec4.v | 106 ++++++++++++++++++++++++++++ ivtest/regress-vvp.list | 2 + ivtest/vvp_tests/pv_wr_fn_vec2.json | 5 ++ ivtest/vvp_tests/pv_wr_fn_vec4.json | 4 ++ 5 files changed, 216 insertions(+) create mode 100644 ivtest/ivltests/pv_wr_fn_vec2.v create mode 100644 ivtest/ivltests/pv_wr_fn_vec4.v create mode 100644 ivtest/vvp_tests/pv_wr_fn_vec2.json create mode 100644 ivtest/vvp_tests/pv_wr_fn_vec4.json diff --git a/ivtest/ivltests/pv_wr_fn_vec2.v b/ivtest/ivltests/pv_wr_fn_vec2.v new file mode 100644 index 000000000..04bedb284 --- /dev/null +++ b/ivtest/ivltests/pv_wr_fn_vec2.v @@ -0,0 +1,99 @@ +// Check that blocking partial writes to a 2-state vector function return value +// are correctly handled. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + function bit [3:0] f; + integer i; + + // Immediate index + + // Within bounds + f = 'h0; + f[2:1] = 2'b10; + `check(f, 4'b0100) + + // Partially oob at high and low side + f = 'h0; + f[4:-1] = 6'b101010; + `check(f, 4'b0101) + // Partially oob at low side + f = 'h0; + f[0:-1] = 2'b10; + `check(f, 4'b0001) + // Partially oob at high side + f = 'h0; + f[4:3] = 2'b01; + `check(f, 4'b1000) + // Fully oob at low side + f = 'h0; + f[-1:-2] = 2'b11; + `check(f, 4'b0000) + // Fully oob at high side + f = 'h0; + f[6:5] = 2'b11; + `check(f, 4'b0000) + + // Variable index + + // Within bounds + i = 1; + f = 'h0; + f[i+:2] = 2'b10; + `check(f, 4'b0100) + + // Partially oob at high and low side + i = -1; + f = 'h0; + f[i+:6] = 6'b101010; + `check(f, 4'b0101) + + // Partially oob at low side + i = -1; + f = 'h0; + f[i+:2] = 2'b10; + `check(f, 4'b0001) + + // Partially oob at high side + i = 3; + f = 'h0; + f[i+:2] = 2'b01; + `check(f, 4'b1000) + + // Fully oob at low side + i = -2; + f = 'h0; + f[i+:2] = 2'b11; + `check(f, 4'b0000) + + // Fully oob at high side + i = 5; + f = 'h0; + f[i+:2] = 2'b11; + `check(f, 4'b0000) + + // Undefined index + i = 'hx; + f = 'h0; + f[i+:2] = 2'b11; + `check(f, 4'b0000) + endfunction + + initial begin + bit [3:0] x; + x = f(); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_fn_vec4.v b/ivtest/ivltests/pv_wr_fn_vec4.v new file mode 100644 index 000000000..88fddd4f0 --- /dev/null +++ b/ivtest/ivltests/pv_wr_fn_vec4.v @@ -0,0 +1,106 @@ +// Check that blocking partial writes to a 4-state vector function return value +// are correctly handled. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + integer i; + + function reg [3:0] f(input reg unused); + begin + // Immediate index + + // Within bounds + f = 'hx; + f[2:1] = 2'b10; + `check(f, 4'bx10x) + + // Partially oob at high and low side + f = 'hx; + f[4:-1] = 6'b101010; + `check(f, 4'b0101) + + // Partially oob at low side + f = 'hx; + f[0:-1] = 2'b10; + `check(f, 4'bxxx1) + + // Partially oob at high side + f = 'hx; + f[4:3] = 2'b01; + `check(f, 4'b1xxx) + + // Fully oob at low side + f = 'hx; + f[-1:-2] = 2'b11; + `check(f, 4'bxxxx) + + // Fully oob at high side + f = 'hx; + f[6:5] = 2'b11; + `check(f, 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + f = 'hx; + f[i+:2] = 2'b10; + `check(f, 4'bx10x) + + // Partially oob at high and low side + i = -1; + f = 'hx; + f[i+:6] = 6'b101010; + `check(f, 4'b0101) + + // Partially oob at low side + i = -1; + f = 'hx; + f[i+:2] = 2'b10; + `check(f, 4'bxxx1) + + // Partially oob at high side + i = 3; + f = 'hx; + f[i+:2] = 2'b01; + `check(f, 4'b1xxx) + + // Fully oob at low side + i = -2; + f = 'hx; + f[i+:2] = 2'b11; + `check(f, 4'bxxxx) + + // Fully oob at high side + i = 5; + f = 'hx; + f[i+:2] = 2'b11; + `check(f, 4'bxxxx) + + // Undefined index + i = 'hx; + f = 'hx; + f[i+:2] = 2'b11; + `check(f, 4'bxxxx) + end + endfunction + + reg [3:0] x; + + initial begin + x = f(1'b0); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index beecf80b2..36e24c387 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -31,6 +31,8 @@ pr1388974 vvp_tests/pr1388974.json pr1388974-vlog95 vvp_tests/pr1388974-vlog95.json pr903 vvp_tests/pr903.json pr903-vlog95 vvp_tests/pr903-vlog95.json +pv_wr_fn_vec2 vvp_tests/pv_wr_fn_vec2.json +pv_wr_fn_vec4 vvp_tests/pv_wr_fn_vec4.json struct_packed_write_read vvp_tests/struct_packed_write_read.json struct_packed_write_read2 vvp_tests/struct_packed_write_read2.json sv_array_cassign6 vvp_tests/sv_array_cassign6.json diff --git a/ivtest/vvp_tests/pv_wr_fn_vec2.json b/ivtest/vvp_tests/pv_wr_fn_vec2.json new file mode 100644 index 000000000..577fe52a2 --- /dev/null +++ b/ivtest/vvp_tests/pv_wr_fn_vec2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "pv_wr_fn_vec2.v", + "iverilog-args" : [ "-g2009" ] +} diff --git a/ivtest/vvp_tests/pv_wr_fn_vec4.json b/ivtest/vvp_tests/pv_wr_fn_vec4.json new file mode 100644 index 000000000..7e787d84d --- /dev/null +++ b/ivtest/vvp_tests/pv_wr_fn_vec4.json @@ -0,0 +1,4 @@ +{ + "type" : "normal", + "source" : "pv_wr_fn_vec4.v" +}