diff --git a/ivtest/gold/sv_array_cassign7-vvp-stdout.gold b/ivtest/gold/sv_array_cassign7-vvp-stdout.gold new file mode 100644 index 000000000..bd6e65e86 --- /dev/null +++ b/ivtest/gold/sv_array_cassign7-vvp-stdout.gold @@ -0,0 +1,106 @@ + 0 6 0 1 + 0 6 1 2 + 0 6 2 3 + 0 6 3 4 + 0 6 4 5 + 0 5 0 6 + 0 5 1 7 + 0 5 2 8 + 0 5 3 9 + 0 5 4 10 + 0 4 0 11 + 0 4 1 12 + 0 4 2 13 + 0 4 3 14 + 0 4 4 15 + 0 3 0 16 + 0 3 1 17 + 0 3 2 18 + 0 3 3 19 + 0 3 4 20 + 0 2 0 21 + 0 2 1 22 + 0 2 2 23 + 0 2 3 24 + 0 2 4 25 + 0 1 0 26 + 0 1 1 27 + 0 1 2 28 + 0 1 3 29 + 0 1 4 30 + 0 0 0 31 + 0 0 1 32 + 0 0 2 33 + 0 0 3 34 + 0 0 4 35 + 1 6 0 36 + 1 6 1 37 + 1 6 2 38 + 1 6 3 39 + 1 6 4 40 + 1 5 0 41 + 1 5 1 42 + 1 5 2 43 + 1 5 3 44 + 1 5 4 45 + 1 4 0 46 + 1 4 1 47 + 1 4 2 48 + 1 4 3 49 + 1 4 4 50 + 1 3 0 51 + 1 3 1 52 + 1 3 2 53 + 1 3 3 54 + 1 3 4 55 + 1 2 0 56 + 1 2 1 57 + 1 2 2 58 + 1 2 3 59 + 1 2 4 60 + 1 1 0 61 + 1 1 1 62 + 1 1 2 63 + 1 1 3 64 + 1 1 4 65 + 1 0 0 66 + 1 0 1 67 + 1 0 2 68 + 1 0 3 69 + 1 0 4 70 + 2 6 0 71 + 2 6 1 72 + 2 6 2 73 + 2 6 3 74 + 2 6 4 75 + 2 5 0 76 + 2 5 1 77 + 2 5 2 78 + 2 5 3 79 + 2 5 4 80 + 2 4 0 81 + 2 4 1 82 + 2 4 2 83 + 2 4 3 84 + 2 4 4 85 + 2 3 0 86 + 2 3 1 87 + 2 3 2 88 + 2 3 3 89 + 2 3 4 90 + 2 2 0 91 + 2 2 1 92 + 2 2 2 93 + 2 2 3 94 + 2 2 4 95 + 2 1 0 96 + 2 1 1 97 + 2 1 2 98 + 2 1 3 99 + 2 1 4 100 + 2 0 0 101 + 2 0 1 102 + 2 0 2 103 + 2 0 3 104 + 2 0 4 105 +PASSED diff --git a/ivtest/ivltests/sv_array_cassign6.v b/ivtest/ivltests/sv_array_cassign6.v new file mode 100644 index 000000000..64d8bb7ff --- /dev/null +++ b/ivtest/ivltests/sv_array_cassign6.v @@ -0,0 +1,21 @@ +// Check that continuous array assignment behaves correctly when left-to-right +// order is reversed. + +module test; + + wire [31:0] x[1:0]; + wire [31:0] y[0:1]; + + assign x[0] = 1; + assign x[1] = 2; + assign y = x; + + final begin + if (y[0] === 2 || y[1] === 1) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_array_cassign7.v b/ivtest/ivltests/sv_array_cassign7.v new file mode 100644 index 000000000..625a5164b --- /dev/null +++ b/ivtest/ivltests/sv_array_cassign7.v @@ -0,0 +1,37 @@ +// Check that continuous array assignment for multi-dimensional arrays behaves +// correctly when left-to-right order is reversed. + +module test; + + logic [31:0] x[2:0][6:0][4:0]; + wire [31:0] y[0:2][6:0][0:4]; + + assign y = x; + + initial begin + static integer idx = 1; + static bit failed = 1'b0; + + foreach (x[i,j,k]) begin + x[i][j][k] = idx; + idx++; + end + + #1 + + idx = 1; + foreach (y[i,j,k]) begin + $display(i, j, k, y[i][j][k]); + if (y[i][j][k] !== idx) begin + $display("FAILED"); + failed = 1'b1; + end + idx++; + end + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 2dd09bb7a..beecf80b2 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -33,6 +33,8 @@ pr903 vvp_tests/pr903.json pr903-vlog95 vvp_tests/pr903-vlog95.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 +sv_array_cassign7 vvp_tests/sv_array_cassign7.json sv_foreach9 vvp_tests/sv_foreach9.json sv_foreach10 vvp_tests/sv_foreach10.json sdf_header vvp_tests/sdf_header.json diff --git a/ivtest/vvp_tests/sv_array_cassign6.json b/ivtest/vvp_tests/sv_array_cassign6.json new file mode 100644 index 000000000..9df5c88e1 --- /dev/null +++ b/ivtest/vvp_tests/sv_array_cassign6.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_array_cassign6.v", + "iverilog-args" : [ "-g2009" ] +} diff --git a/ivtest/vvp_tests/sv_array_cassign7.json b/ivtest/vvp_tests/sv_array_cassign7.json new file mode 100644 index 000000000..672129f22 --- /dev/null +++ b/ivtest/vvp_tests/sv_array_cassign7.json @@ -0,0 +1,6 @@ +{ + "type" : "normal", + "source" : "sv_array_cassign7.v", + "iverilog-args" : [ "-g2009" ], + "gold" : "sv_array_cassign7" +} diff --git a/netmisc.cc b/netmisc.cc index 13b79f14b..5aa6f83b0 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1628,21 +1628,75 @@ NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net, return res; } + +static void assign_unpacked_with_bufz_dim(Design *des, NetScope *scope, + const LineInfo *loc, + NetNet *lval, NetNet *rval, + const std::vector &stride, + unsigned int dim = 0, + unsigned int idx_l = 0, + unsigned int idx_r = 0) +{ + int inc_l, inc_r; + bool up_l, up_r; + + const auto &l_dims = lval->unpacked_dims(); + const auto &r_dims = rval->unpacked_dims(); + + up_l = l_dims[dim].get_msb() < l_dims[dim].get_lsb(); + up_r = r_dims[dim].get_msb() < r_dims[dim].get_lsb(); + + inc_l = inc_r = stride[dim]; + + /* + * Arrays dimensions get connected left-to-right. This means if the + * left-to-right order differs for a particular dimension between the two + * arrays the elements for that dimension will get connected in reverse + * order. + */ + + if (!up_l) { + /* Go to the last element and count down */ + idx_l += inc_l * (l_dims[dim].width() - 1); + inc_l = -inc_l; + } + + if (!up_r) { + /* Go to the last element and count down */ + idx_r += inc_r * (r_dims[dim].width() - 1); + inc_r = -inc_r; + } + + for (unsigned int idx = 0; idx < l_dims[dim].width(); idx++) { + if (dim == l_dims.size() - 1) { + NetBUFZ *driver = new NetBUFZ(scope, scope->local_symbol(), + lval->vector_width(), false); + driver->set_line(*loc); + des->add_node(driver); + + connect(lval->pin(idx_l), driver->pin(0)); + connect(driver->pin(1), rval->pin(idx_r)); + } else { + assign_unpacked_with_bufz_dim(des, scope, loc, lval, rval, + stride, dim + 1, idx_l, idx_r); + } + + idx_l += inc_l; + idx_r += inc_r; + } +} + void assign_unpacked_with_bufz(Design*des, NetScope*scope, const LineInfo*loc, NetNet*lval, NetNet*rval) { ivl_assert(*loc, lval->pin_count()==rval->pin_count()); - for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1) { - NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(), - lval->vector_width(), false); - driver->set_line(*loc); - des->add_node(driver); + const auto &dims = lval->unpacked_dims(); + vector stride(dims.size()); - connect(lval->pin(idx), driver->pin(0)); - connect(driver->pin(1), rval->pin(idx)); - } + make_strides(dims, stride); + assign_unpacked_with_bufz_dim(des, scope, loc, lval, rval, stride); } /*