diff --git a/ivtest/ivltests/pv_wr_vec2.v b/ivtest/ivltests/pv_wr_vec2.v new file mode 100644 index 000000000..4d82175c0 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2.v @@ -0,0 +1,95 @@ +// Check that blocking partial writes to a 2-state vector are correctly +// handlded. + +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 + + bit [3:0] x; + integer i; + + initial begin + // Immediate index + + // Within bounds + x = 'h0; + x[2:1] = 2'b10; + `check(x, 4'b0100) + + // Partially oob at high and low side + x = 'h0; + x[4:-1] = 6'b101010; + `check(x, 4'b0101) + // Partially oob at low side + x = 'h0; + x[0:-1] = 2'b10; + `check(x, 4'b0001) + // Partially oob at high side + x = 'h0; + x[4:3] = 2'b01; + `check(x, 4'b1000) + // Fully oob at low side + x = 'h0; + x[-1:-2] = 2'b11; + `check(x, 4'b0000) + // Fully oob at high side + x = 'h0; + x[6:5] = 2'b11; + `check(x, 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x = 'h0; + x[i+:2] = 2'b10; + `check(x, 4'b0100) + + // Partially oob at high and low side + i = -1; + x = 'h0; + x[i+:6] = 6'b101010; + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'h0; + x[i+:2] = 2'b10; + `check(x, 4'b0001) + + // Partially oob at high side + i = 3; + x = 'h0; + x[i+:2] = 2'b01; + `check(x, 4'b1000) + + // Fully oob at low side + i = -2; + x = 'h0; + x[i+:2] = 2'b11; + `check(x, 4'b0000) + + // Fully oob at high side + i = 5; + x = 'h0; + x[i+:2] = 2'b11; + `check(x, 4'b0000) + + // Undefined index + i = 'hx; + x = 'h0; + x[i+:2] = 2'b11; + `check(x, 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2_nb.v b/ivtest/ivltests/pv_wr_vec2_nb.v new file mode 100644 index 000000000..a457551a6 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2_nb.v @@ -0,0 +1,112 @@ +// Check that non-blocking partial writes to a 2-state vector are correctly +// handlded. + +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 + + bit [3:0] x; + integer i; + + initial begin + // Immediate index + + // Within bounds + x = 'h0; + x[2:1] <= 2'b10; + #1 + `check(x, 4'b0100) + + // Partially oob at high and low side + x = 'h0; + x[4:-1] <= 6'b101010; + #1 + `check(x, 4'b0101) + + // Partially oob at low side + x = 'h0; + x[0:-1] <= 2'b10; + #1 + `check(x, 4'b0001) + + // Partially oob at high side + x = 'h0; + x[4:3] <= 2'b01; + #1 + `check(x, 4'b1000) + + // Fully oob at low side + x = 'h0; + x[-1:-2] <= 2'b11; + #1 + `check(x, 4'b0000) + + // Fully oob at high side + x = 'h0; + x[6:5] <= 2'b11; + #1 + `check(x, 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x = 'h0; + x[i+:2] <= 2'b10; + #1 + `check(x, 4'b0100) + + // Partially oob at high and low side + i = -1; + x = 'h0; + x[i+:6] <= 6'b101010; + #1 + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'h0; + x[i+:2] <= 2'b10; + #1 + `check(x, 4'b0001) + + // Partially oob at high side + i = 3; + x = 'h0; + x[i+:2] <= 2'b01; + #1 + `check(x, 4'b1000) + + // Fully oob at low side + i = -2; + x = 'h0; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'b0000) + + // Fully oob at high side + i = 5; + x = 'h0; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'b0000) + + // Undefined index + i = 'hx; + x = 'h0; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2_nb_ec.v b/ivtest/ivltests/pv_wr_vec2_nb_ec.v new file mode 100644 index 000000000..c81966665 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2_nb_ec.v @@ -0,0 +1,114 @@ +// Check that non-blocking event controlled partial writes to a 2-state vector +// are correctly handlded. + +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 + + bit [3:0] x; + integer i; + + event e; + + initial begin + // Immediate index + + // Within bounds + x = 'h0; + x[2:1] <= @e 2'b10; + -> e; + `check(x, 4'b0100) + + // Partially oob at high and low side + x = 'h0; + x[4:-1] <= @e 6'b101010; + -> e; + `check(x, 4'b0101) + + // Partially oob at low side + x = 'h0; + x[0:-1] <= @e 2'b10; + -> e; + `check(x, 4'b0001) + + // Partially oob at high side + x = 'h0; + x[4:3] <= @e 2'b01; + -> e; + `check(x, 4'b1000) + + // Fully oob at low side + x = 'h0; + x[-1:-2] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + // Fully oob at high side + x = 'h0; + x[6:5] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x = 'h0; + x[i+:2] <= @e 2'b10; + -> e; + `check(x, 4'b0100) + + // Partially oob at high and low side + i = -1; + x = 'h0; + x[i+:6] <= @e 6'b101010; + -> e; + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'h0; + x[i+:2] <= @e 2'b10; + -> e; + `check(x, 4'b0001) + + // Partially oob at high side + i = 3; + x = 'h0; + x[i+:2] <= @e 2'b01; + -> e; + `check(x, 4'b1000) + + // Fully oob at low side + i = -2; + x = 'h0; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + // Fully oob at high side + i = 5; + x = 'h0; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + // Undefined index + i = 'hx; + x = 'h0; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2a.v b/ivtest/ivltests/pv_wr_vec2a.v new file mode 100644 index 000000000..d97d21d8d --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2a.v @@ -0,0 +1,95 @@ +// Check that blocking partial writes to a 2-state vector array element are +// correctly handlded. + +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 + + bit [3:0] x[1:0]; + integer i; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'h0; + x[0][2:1] = 2'b10; + `check(x[0], 4'b0100) + + // Partially oob at high and low side + x[0] = 'h0; + x[0][4:-1] = 6'b101010; + `check(x[0], 4'b0101) + // Partially oob at low side + x[0] = 'h0; + x[0][0:-1] = 2'b10; + `check(x[0], 4'b0001) + // Partially oob at high side + x[0] = 'h0; + x[0][4:3] = 2'b01; + `check(x[0], 4'b1000) + // Fully oob at low side + x[0] = 'h0; + x[0][-1:-2] = 2'b11; + `check(x[0], 4'b0000) + // Fully oob at high side + x[0] = 'h0; + x[0][6:5] = 2'b11; + `check(x[0], 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'h0; + x[0][i+:2] = 2'b10; + `check(x[0], 4'b0100) + + // Partially oob at high and low side + i = -1; + x[0] = 'h0; + x[0][i+:6] = 6'b101010; + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'h0; + x[0][i+:2] = 2'b10; + `check(x[0], 4'b0001) + + // Partially oob at high side + i = 3; + x[0] = 'h0; + x[0][i+:2] = 2'b01; + `check(x[0], 4'b1000) + + // Fully oob at low side + i = -2; + x[0] = 'h0; + x[0][i+:2] = 2'b11; + `check(x[0], 4'b0000) + + // Fully oob at high side + i = 5; + x[0] = 'h0; + x[0][i+:2] = 2'b11; + `check(x[0], 4'b0000) + + // Undefined index + i = 'hx; + x[0] = 'h0; + x[0][i+:2] = 2'b11; + `check(x[0], 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2a_nb.v b/ivtest/ivltests/pv_wr_vec2a_nb.v new file mode 100644 index 000000000..2093d9bf2 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2a_nb.v @@ -0,0 +1,112 @@ +// Check that non-blocking partial writes to a 2-state vector array element are +// correctly handlded. + +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 + + bit [3:0] x[1:0]; + integer i; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'h0; + x[0][2:1] <= 2'b10; + #1 + `check(x[0], 4'b0100) + + // Partially oob at high and low side + x[0] = 'h0; + x[0][4:-1] <= 6'b101010; + #1 + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'h0; + x[0][0:-1] <= 2'b10; + #1 + `check(x[0], 4'b0001) + + // Partially oob at high side + x[0] = 'h0; + x[0][4:3] <= 2'b01; + #1 + `check(x[0], 4'b1000) + + // Fully oob at low side + x[0] = 'h0; + x[0][-1:-2] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + // Fully oob at high side + x[0] = 'h0; + x[0][6:5] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'h0; + x[0][i+:2] = 2'b10; + #1 + `check(x[0], 4'b0100) + + // Partially oob at high and low side + i = -1; + x[0] = 'h0; + x[0][i+:6] <= 6'b101010; + #1 + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'h0; + x[0][i+:2] <= 2'b10; + #1 + `check(x[0], 4'b0001) + + // Partially oob at high side + i = 3; + x[0] = 'h0; + x[0][i+:2] <= 2'b01; + #1 + `check(x[0], 4'b1000) + + // Fully oob at low side + i = -2; + x[0] = 'h0; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + // Fully oob at high side + i = 5; + x[0] = 'h0; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + // Undefined index + i = 'hx; + x[0] = 'h0; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2a_nb_ec.v b/ivtest/ivltests/pv_wr_vec2a_nb_ec.v new file mode 100644 index 000000000..479dbe5a2 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2a_nb_ec.v @@ -0,0 +1,114 @@ +// Check that non-blocking event controlled partial writes to a 2-state vector +// array element are correctly handlded. + +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 + + bit [3:0] x[1:0]; + integer i; + + event e; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'h0; + x[0][2:1] <= @e 2'b10; + -> e; + `check(x[0], 4'b0100) + + // Partially oob at high and low side + x[0] = 'h0; + x[0][4:-1] <= @e 6'b101010; + -> e; + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'h0; + x[0][0:-1] <= @e 2'b10; + -> e; + `check(x[0], 4'b0001) + + // Partially oob at high side + x[0] = 'h0; + x[0][4:3] <= @e 2'b01; + -> e; + `check(x[0], 4'b1000) + + // Fully oob at low side + x[0] = 'h0; + x[0][-1:-2] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + // Fully oob at high side + x[0] = 'h0; + x[0][6:5] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b10; + -> e; + `check(x[0], 4'b0100) + + // Partially oob at high and low side + i = -1; + x[0] = 'h0; + x[0][i+:6] <= @e 6'b101010; + -> e; + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b10; + -> e; + `check(x[0], 4'b0001) + + // Partially oob at high side + i = 3; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b01; + -> e; + `check(x[0], 4'b1000) + + // Fully oob at low side + i = -2; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + // Fully oob at high side + i = 5; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + // Undefined index + i = 'hx; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4.v b/ivtest/ivltests/pv_wr_vec4.v new file mode 100644 index 000000000..3db3ab043 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4.v @@ -0,0 +1,99 @@ +// Check that blocking partial writes to a 4-state vector are correctly +// handlded. + +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 + + reg [3:0] x; + integer i; + + initial begin + // Immediate index + + // Within bounds + x = 'hx; + x[2:1] = 2'b10; + `check(x, 4'bx10x) + + // Partially oob at high and low side + x = 'hx; + x[4:-1] = 6'b101010; + `check(x, 4'b0101) + + // Partially oob at low side + x = 'hx; + x[0:-1] = 2'b10; + `check(x, 4'bxxx1) + + // Partially oob at high side + x = 'hx; + x[4:3] = 2'b01; + `check(x, 4'b1xxx) + + // Fully oob at low side + x = 'hx; + x[-1:-2] = 2'b11; + `check(x, 4'bxxxx) + + // Fully oob at high side + x = 'hx; + x[6:5] = 2'b11; + `check(x, 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x = 'hx; + x[i+:2] = 2'b10; + `check(x, 4'bx10x) + + // Partially oob at high and low side + i = -1; + x = 'hx; + x[i+:6] = 6'b101010; + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'hx; + x[i+:2] = 2'b10; + `check(x, 4'bxxx1) + + // Partially oob at high side + i = 3; + x = 'hx; + x[i+:2] = 2'b01; + `check(x, 4'b1xxx) + + // Fully oob at low side + i = -2; + x = 'hx; + x[i+:2] = 2'b11; + `check(x, 4'bxxxx) + + // Fully oob at high side + i = 5; + x = 'hx; + x[i+:2] = 2'b11; + `check(x, 4'bxxxx) + + // Undefined index + i = 'hx; + x = 'hx; + x[i+:2] = 2'b11; + `check(x, 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4_nb.v b/ivtest/ivltests/pv_wr_vec4_nb.v new file mode 100644 index 000000000..2d8149b0d --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4_nb.v @@ -0,0 +1,111 @@ +// Check that non-blocking partial writes to a 4-state vector are correctly +// handlded. + +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 + + reg [3:0] x; + integer i; + + initial begin + // Immediate index + + // Within bounds + x = 'hx; + x[2:1] <= 2'b10; + #1 + `check(x, 4'bx10x) + + // Partially oob at high and low side + x = 'hx; + x[4:-1] <= 6'b101010; + #1 + `check(x, 4'b0101) + + // Partially oob at low side + x = 'hx; + x[0:-1] <= 2'b10; + #1 + `check(x, 4'bxxx1) + + // Partially oob at high side + x = 'hx; + x[4:3] <= 2'b01; + #1 + `check(x, 4'b1xxx) + + // Fully oob at low side + x = 'hx; + x[-1:-2] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + // Fully oob at high side + x = 'hx; + x[6:5] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x = 'hx; + x[i+:2] = 2'b10; + `check(x, 4'bx10x) + + // Partially oob at high and low side + i = -1; + x = 'hx; + x[i+:6] <= 6'b101010; + #1 + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'hx; + x[i+:2] <= 2'b10; + #1 + `check(x, 4'bxxx1) + + // Partially oob at high side + i = 3; + x = 'hx; + x[i+:2] <= 2'b01; + #1 + `check(x, 4'b1xxx) + + // Fully oob at low side + i = -2; + x = 'hx; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + // Fully oob at high side + i = 5; + x = 'hx; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + // Undefined index + i = 'hx; + x = 'hx; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4_nb_ec.v b/ivtest/ivltests/pv_wr_vec4_nb_ec.v new file mode 100644 index 000000000..b89029871 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4_nb_ec.v @@ -0,0 +1,114 @@ +// Check that non-blocking event controlled partial writes to a 4-state vector +// are correctly handlded. + +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 + + reg [3:0] x; + integer i; + + event e; + + initial begin + // Immediate index + + // Within bounds + x = 'hx; + x[2:1] <= @e 2'b10; + -> e; + `check(x, 4'bx10x) + + // Partially oob at high and low side + x = 'hx; + x[4:-1] <= @e 6'b101010; + -> e; + `check(x, 4'b0101) + + // Partially oob at low side + x = 'hx; + x[0:-1] <= @e 2'b10; + -> e; + `check(x, 4'bxxx1) + + // Partially oob at high side + x = 'hx; + x[4:3] <= @e 2'b01; + -> e; + `check(x, 4'b1xxx) + + // Fully oob at low side + x = 'hx; + x[-1:-2] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + // Fully oob at high side + x = 'hx; + x[6:5] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x = 'hx; + x[i+:2] <= @e 2'b10; + -> e; + `check(x, 4'bx10x) + + // Partially oob at high and low side + i = -1; + x = 'hx; + x[i+:6] <= @e 6'b101010; + -> e; + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'hx; + x[i+:2] <= @e 2'b10; + -> e; + `check(x, 4'bxxx1) + + // Partially oob at high side + i = 3; + x = 'hx; + x[i+:2] <= @e 2'b01; + -> e; + `check(x, 4'b1xxx) + + // Fully oob at low side + i = -2; + x = 'hx; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + // Fully oob at high side + i = 5; + x = 'hx; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + // Undefined index + i = 'hx; + x = 'hx; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4a.v b/ivtest/ivltests/pv_wr_vec4a.v new file mode 100644 index 000000000..a4765c17c --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4a.v @@ -0,0 +1,99 @@ +// Check that blocking partial writes to a 4-state vector array element are +// correctly handlded. + +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 + + reg [3:0] x[1:0]; + integer i; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'hx; + x[0][2:1] = 2'b10; + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + x[0] = 'hx; + x[0][4:-1] = 6'b101010; + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'hx; + x[0][0:-1] = 2'b10; + `check(x[0], 4'bxxx1) + + // Partially oob at high side + x[0] = 'hx; + x[0][4:3] = 2'b01; + `check(x[0], 4'b1xxx) + + // Fully oob at low side + x[0] = 'hx; + x[0][-1:-2] = 2'b11; + `check(x[0], 4'bxxxx) + + // Fully oob at high side + x[0] = 'hx; + x[0][6:5] = 2'b11; + `check(x[0], 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'hx; + x[0][i+:2] = 2'b10; + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + i = -1; + x[0] = 'hx; + x[0][i+:6] = 6'b101010; + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'hx; + x[0][i+:2] = 2'b10; + `check(x[0], 4'bxxx1) + + // Partially oob at high side + i = 3; + x[0] = 'hx; + x[0][i+:2] = 2'b01; + `check(x[0], 4'b1xxx) + + // Fully oob at low side + i = -2; + x[0] = 'hx; + x[0][i+:2] = 2'b11; + `check(x[0], 4'bxxxx) + + // Fully oob at high side + i = 5; + x[0] = 'hx; + x[0][i+:2] = 2'b11; + `check(x[0], 4'bxxxx) + + // Undefined index + i = 'hx; + x[0] = 'hx; + x[0][i+:2] = 2'b11; + `check(x[0], 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4a_nb.v b/ivtest/ivltests/pv_wr_vec4a_nb.v new file mode 100644 index 000000000..926991c92 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4a_nb.v @@ -0,0 +1,112 @@ +// Check that non-blocking partial writes to a 4-state vector array element are +// correctly handlded. + +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 + + reg [3:0] x[1:0]; + integer i; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'hx; + x[0][2:1] <= 2'b10; + #1 + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + x[0] = 'hx; + x[0][4:-1] <= 6'b101010; + #1 + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'hx; + x[0][0:-1] <= 2'b10; + #1 + `check(x[0], 4'bxxx1) + + // Partially oob at high side + x[0] = 'hx; + x[0][4:3] <= 2'b01; + #1 + `check(x[0], 4'b1xxx) + + // Fully oob at low side + x[0] = 'hx; + x[0][-1:-2] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + // Fully oob at high side + x[0] = 'hx; + x[0][6:5] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'hx; + x[0][i+:2] <= 2'b10; + #1 + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + i = -1; + x[0] = 'hx; + x[0][i+:6] <= 6'b101010; + #1 + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'hx; + x[0][i+:2] <= 2'b10; + #1 + `check(x[0], 4'bxxx1) + + // Partially oob at high side + i = 3; + x[0] = 'hx; + x[0][i+:2] <= 2'b01; + #1 + `check(x[0], 4'b1xxx) + + // Fully oob at low side + i = -2; + x[0] = 'hx; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + // Fully oob at high side + i = 5; + x[0] = 'hx; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + // Undefined index + i = 5; + x[0] = 'hx; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4a_nb_ec.v b/ivtest/ivltests/pv_wr_vec4a_nb_ec.v new file mode 100644 index 000000000..c2c08c024 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4a_nb_ec.v @@ -0,0 +1,114 @@ +// Check that non-blocking event controlled partial writes to a 4-state vector +// array element are correctly handlded. + +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 + + reg [3:0] x[1:0]; + integer i; + + event e; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'hx; + x[0][2:1] <= @e 2'b10; + -> e; + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + x[0] = 'hx; + x[0][4:-1] <= @e 6'b101010; + -> e; + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'hx; + x[0][0:-1] <= @e 2'b10; + -> e; + `check(x[0], 4'bxxx1) + + // Partially oob at high side + x[0] = 'hx; + x[0][4:3] <= @e 2'b01; + -> e; + `check(x[0], 4'b1xxx) + + // Fully oob at low side + x[0] = 'hx; + x[0][-1:-2] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + // Fully oob at high side + x[0] = 'hx; + x[0][6:5] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b10; + -> e; + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + i = -1; + x[0] = 'hx; + x[0][i+:6] <= @e 6'b101010; + -> e; + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b10; + -> e; + `check(x[0], 4'bxxx1) + + // Partially oob at high side + i = 3; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b01; + -> e; + `check(x[0], 4'b1xxx) + + // Fully oob at low side + i = -2; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + // Fully oob at high side + i = 5; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + // Undefined index + i = 'hx; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 1c26458d5..a605f9843 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -415,6 +415,12 @@ program5a CE,-g2009 ivltests program5b CE,-g2009 ivltests program_hello normal,-g2009 ivltests program_hello2 CE,-g2009 ivltests +pv_wr_vec2 normal,-g2005-sv ivltests +pv_wr_vec2_nb normal,-g2005-sv ivltests +pv_wr_vec2_nb_ec normal,-g2005-sv ivltests +pv_wr_vec2a normal,-g2005-sv ivltests +pv_wr_vec2a_nb normal,-g2005-sv ivltests +pv_wr_vec2a_nb_ec normal,-g2005-sv ivltests recursive_func2 normal,-g2005-sv ivltests gold=recursive_func.gold recursive_func_const2 normal,-g2005-sv ivltests gold=recursive_func_const.gold sbyte_test normal,-g2005-sv ivltests diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index 5300f4d2b..b42886e66 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -1435,6 +1435,12 @@ pullupdown normal ivltests # Contributed test pullupdown2 normal ivltests # Contributed test pullupdown3 normal ivltests # Contributed test pv_undef_sig_sel normal ivltests +pv_wr_vec4 normal ivltests +pv_wr_vec4_nb normal ivltests +pv_wr_vec4_nb_ec normal ivltests +pv_wr_vec4a normal ivltests +pv_wr_vec4a_nb normal ivltests +pv_wr_vec4a_nb_ec normal ivltests qmark normal ivltests qmark1 normal ivltests qmark3 normal ivltests diff --git a/vvp/array.cc b/vvp/array.cc index 6f7d01c5d..4727a4ebf 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -602,10 +602,21 @@ void __vpiArray::set_word(unsigned address, unsigned part_off, const vvp_vector4 if (vals) { assert(nets == 0); - // FIXME: For now, assume no part select of word? - assert(part_off==0); - assert(val.size() == vals_width); - vals->set_word(address, val); + if (part_off != 0 || val.size() != vals_width) { + vvp_vector4_t tmp; + vals->get_word(address, tmp); + if ((part_off + val.size()) > tmp.size()) { + cerr << "part_off=" << part_off + << " val.size()=" << val.size() + << " vals[address].size()=" << tmp.size() + << " vals_width=" << vals_width << endl; + assert(0); + } + tmp.set_vec(part_off, val); + vals->set_word(address, tmp); + } else { + vals->set_word(address, val); + } word_change(address); return; } diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 439e7529b..41950c58e 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1134,6 +1134,50 @@ bool of_ASSIGN_VEC4(vthread_t thr, vvp_code_t cp) return true; } +/* + * Resizes a vector value for a partial assignment so that the value is fully + * in-bounds of the target signal. Both `val` and `off` will be updated if + * necessary. + * + * Returns false if the value is fully out-of-bounds and the assignment should + * be skipped. Otherwise returns true. + */ +static bool resize_rval_vec(vvp_vector4_t &val, int64_t &off, + unsigned int sig_wid) +{ + unsigned int wid = val.size(); + + // Fully in bounds, most likely case + if (off >= 0 && (uint64_t)off + wid <= sig_wid) + return true; + + unsigned int base = 0; + if (off >= 0) { + // Fully out-of-bounds + if ((uint64_t)off >= sig_wid) + return false; + } else { + // Fully out-of-bounds */ + if ((uint64_t)(-off) >= wid) + return false; + + // If the index is below the vector, then only assign the high + // bits that overlap with the target + base = -off; + wid += off; + off = 0; + } + + // If the value is partly above the target, then only assign + // the bits that overlap + if ((uint64_t)off + wid > sig_wid) + wid = sig_wid - (uint64_t)off; + + val = val.subvalue(base, wid); + + return true; +} + /* * %assign/vec4/a/d , , */ @@ -1143,35 +1187,19 @@ bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t cp) int del_idx = cp->bit_idx[1]; int adr_idx = 3; - long off = off_idx? thr->words[off_idx].w_int : 0; + int64_t off = off_idx ? thr->words[off_idx].w_int : 0; vvp_time64_t del = del_idx? thr->words[del_idx].w_uint : 0; long adr = thr->words[adr_idx].w_int; vvp_vector4_t val = thr->pop_vec4(); - unsigned wid = val.size(); - const unsigned array_wid = cp->array->get_word_size(); // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. if (thr->flags[4] == BIT4_1) return true; - if (off >= (long)array_wid) + if (!resize_rval_vec(val, off, cp->array->get_word_size())) return true; - if (off < 0) { - if ((unsigned)-off >= array_wid) - return true; - - int use_off = -off; - assert(wid > (unsigned)use_off); - unsigned use_wid = wid - use_off; - val = val.subvalue(use_off, use_wid); - off = 0; - wid = use_wid; - } - if (off+wid > array_wid) { - val = val.subvalue(0, array_wid-off); - } schedule_assign_array_word(cp->array, adr, off, val, del); @@ -1186,34 +1214,18 @@ bool of_ASSIGN_VEC4_A_E(vthread_t thr, vvp_code_t cp) int off_idx = cp->bit_idx[0]; int adr_idx = 3; - long off = off_idx? thr->words[off_idx].w_int : 0; + int64_t off = off_idx ? thr->words[off_idx].w_int : 0; long adr = thr->words[adr_idx].w_int; vvp_vector4_t val = thr->pop_vec4(); - unsigned wid = val.size(); - const unsigned array_wid = cp->array->get_word_size(); // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. if (thr->flags[4] == BIT4_1) return true; - if (off >= (long)array_wid) + if (!resize_rval_vec(val, off, cp->array->get_word_size())) return true; - if (off < 0) { - if ((unsigned)-off >= array_wid) - return true; - - int use_off = -off; - assert(wid > (unsigned)use_off); - unsigned use_wid = wid - use_off; - val = val.subvalue(use_off, use_wid); - off = 0; - wid = use_wid; - } - if (off+wid > array_wid) { - val = val.subvalue(0, array_wid-off); - } if (thr->ecount == 0) { schedule_assign_array_word(cp->array, adr, off, val, 0); @@ -1233,9 +1245,8 @@ bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t cp) unsigned off_index = cp->bit_idx[0]; unsigned del_index = cp->bit_idx[1]; vvp_vector4_t val = thr->pop_vec4(); - unsigned wid = val.size(); - int off = thr->words[off_index].w_int; + int64_t off = thr->words[off_index].w_int; vvp_time64_t del = thr->words[del_index].w_uint; // Abort if flags[4] is set. This can happen if the calculation @@ -1246,22 +1257,8 @@ bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t cp) vvp_signal_value*sig = dynamic_cast (cp->net->fil); assert(sig); - if (off >= (long)sig->value_size()) + if (!resize_rval_vec(val, off, sig->value_size())) return true; - if (off < 0) { - if ((unsigned)-off >= wid) - return true; - - int use_off = -off; - assert(wid > (unsigned)use_off); - unsigned use_wid = wid - use_off; - val = val.subvalue(use_off, use_wid); - off = 0; - wid = use_wid; - } - if (off+wid > sig->value_size()) { - val = val.subvalue(0, sig->value_size()-off); - } schedule_assign_vector(ptr, off, sig->value_size(), val, del); return true; @@ -1275,9 +1272,8 @@ bool of_ASSIGN_VEC4_OFF_E(vthread_t thr, vvp_code_t cp) vvp_net_ptr_t ptr (cp->net, 0); unsigned off_index = cp->bit_idx[0]; vvp_vector4_t val = thr->pop_vec4(); - unsigned wid = val.size(); - int off = thr->words[off_index].w_int; + int64_t off = thr->words[off_index].w_int; // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. @@ -1287,22 +1283,8 @@ bool of_ASSIGN_VEC4_OFF_E(vthread_t thr, vvp_code_t cp) vvp_signal_value*sig = dynamic_cast (cp->net->fil); assert(sig); - if (off >= (long)sig->value_size()) + if (!resize_rval_vec(val, off, sig->value_size())) return true; - if (off < 0) { - if ((unsigned)-off >= wid) - return true; - - int use_off = -off; - assert((int)wid > use_off); - unsigned use_wid = wid - use_off; - val = val.subvalue(use_off, use_wid); - off = 0; - wid = use_wid; - } - if (off+wid > sig->value_size()) { - val = val.subvalue(0, sig->value_size()-off); - } if (thr->ecount == 0) { schedule_assign_vector(ptr, off, sig->value_size(), val, 0); @@ -5455,58 +5437,31 @@ bool of_RET_VEC4(vthread_t thr, vvp_code_t cp) { size_t index = cp->number; unsigned off_index = cp->bit_idx[0]; - int wid = cp->bit_idx[1]; + unsigned int wid = cp->bit_idx[1]; vvp_vector4_t&val = thr->peek_vec4(); vthread_t fun_thr = get_func(thr); assert(index < get_max(fun_thr, val)); unsigned depth = get_depth(fun_thr, index, val); - int off = off_index? thr->words[off_index].w_int : 0; - const int sig_value_size = fun_thr->parent->peek_vec4(depth).size(); - - unsigned val_size = val.size(); + int64_t off = off_index ? thr->words[off_index].w_int : 0; + unsigned int sig_value_size = fun_thr->parent->peek_vec4(depth).size(); if (off_index!=0 && thr->flags[4] == BIT4_1) { thr->pop_vec4(1); return true; } - if (off <= -wid) { + if (!resize_rval_vec(val, off, sig_value_size)) { thr->pop_vec4(1); return true; } - if (off >= sig_value_size) { - thr->pop_vec4(1); - return true; - } - - // If the index is below the vector, then only assign the high - // bits that overlap with the target - if (off < 0) { - int use_off = -off; - wid -= use_off; - val = val.subvalue(use_off, wid); - val_size = wid; - off = 0; - } - - // If the value is partly above the target, then only assign - // the bits that overlap - if ((off+wid) > sig_value_size) { - wid = sig_value_size - off; - val = val.subvalue(0, wid); - val.resize(wid); - val_size = wid; - } - - if (off==0 && val_size==(unsigned)sig_value_size) { + if (off == 0 && val.size() == sig_value_size) { fun_thr->parent->poke_vec4(depth, val); - } else { vvp_vector4_t tmp_dst = fun_thr->parent->peek_vec4(depth); - assert(wid>=0 && val.size() == (unsigned)wid); + assert(val.size() == wid); tmp_dst.set_vec(off, val); fun_thr->parent->poke_vec4(depth, tmp_dst); } @@ -6247,23 +6202,22 @@ bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp) vvp_net_ptr_t ptr(cp->net, 0); vvp_signal_value*sig = dynamic_cast (cp->net->fil); unsigned off_index = cp->bit_idx[0]; - int wid = cp->bit_idx[1]; + unsigned int wid = cp->bit_idx[1]; - int off = off_index? thr->words[off_index].w_int : 0; - const int sig_value_size = sig->value_size(); + int64_t off = off_index ? thr->words[off_index].w_int : 0; + unsigned int sig_value_size = sig->value_size(); vvp_vector4_t&val = thr->peek_vec4(); unsigned val_size = val.size(); - if ((int)val_size < wid) { + if (val_size < wid) { cerr << thr->get_fileline() << "XXXX Internal error: val.size()=" << val_size << ", expecting >= " << wid << endl; } - assert((int)val_size >= wid); - if ((int)val_size > wid) { + assert(val_size >= wid); + if (val_size > wid) { val.resize(wid); - val_size = wid; } // If there is a problem loading the index register, flags-4 @@ -6273,36 +6227,12 @@ bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp) return true; } - if (off <= -wid) { - thr->pop_vec4(1); - return true; - } - if (off >= sig_value_size) { + if (!resize_rval_vec(val, off, sig_value_size)) { thr->pop_vec4(1); return true; } - // If the index is below the vector, then only assign the high - // bits that overlap with the target. - if (off < 0) { - int use_off = -off; - wid -= use_off; - val = val.subvalue(use_off, wid); - val_size = wid; - off = 0; - } - - // If the value is partly above the target, then only assign - // the bits that overlap. - if ((off+wid) > sig_value_size) { - wid = sig_value_size - off; - val = val.subvalue(0, wid); - val.resize(wid); - val_size = wid; - } - - - if (off==0 && val_size==(unsigned)sig_value_size) + if (off == 0 && val.size() == sig_value_size) vvp_send_vec4(ptr, val, thr->wt_context); else vvp_send_vec4_pv(ptr, val, off, sig_value_size, thr->wt_context); @@ -6319,10 +6249,8 @@ bool of_STORE_VEC4A(vthread_t thr, vvp_code_t cp) unsigned adr_index = cp->bit_idx[0]; unsigned off_index = cp->bit_idx[1]; - const vvp_vector4_t&value = thr->peek_vec4(); - long adr = adr_index? thr->words[adr_index].w_int : 0; - long off = off_index? thr->words[off_index].w_int : 0; + int64_t off = off_index ? thr->words[off_index].w_int : 0; // Suppress action if flags-4 is true. if (thr->flags[4] == BIT4_1) { @@ -6330,6 +6258,13 @@ bool of_STORE_VEC4A(vthread_t thr, vvp_code_t cp) return true; } + vvp_vector4_t &value = thr->peek_vec4(); + + if (!resize_rval_vec(value, off, cp->array->get_word_size())) { + thr->pop_vec4(1); + return true; + } + cp->array->set_word(adr, off, value); thr->pop_vec4(1);