Merge pull request #930 from larsclausen/fix-fn-partial-oob-write

Fix incorrect assert for partial oob write to function return value
This commit is contained in:
Cary R 2023-06-10 18:00:06 -07:00 committed by GitHub
commit bff91566ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 217 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -33,6 +33,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

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "pv_wr_fn_vec2.v",
"iverilog-args" : [ "-g2009" ]
}

View File

@ -0,0 +1,4 @@
{
"type" : "normal",
"source" : "pv_wr_fn_vec4.v"
}

View File

@ -5466,6 +5466,7 @@ bool of_RET_VEC4(vthread_t thr, vvp_code_t cp)
vthread_t fun_thr = get_func(thr);
assert(index < get_max(fun_thr, val));
assert(val.size() == wid);
unsigned depth = get_depth(fun_thr, index, val);
int64_t off = off_index ? thr->words[off_index].w_int : 0;
@ -5485,7 +5486,6 @@ bool of_RET_VEC4(vthread_t thr, vvp_code_t cp)
fun_thr->parent->poke_vec4(depth, val);
} else {
vvp_vector4_t tmp_dst = fun_thr->parent->peek_vec4(depth);
assert(val.size() == wid);
tmp_dst.set_vec(off, val);
fun_thr->parent->poke_vec4(depth, tmp_dst);
}