From cc962310bb1a509937e322c72418b4dfeb98440e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 5 Mar 2023 09:15:59 -0800 Subject: [PATCH 1/2] Connect continuous array assignments in the right order In SystemVerilog arrays assignments are supposed to be connected left to right. This means if the left to right direction differs between the two arrays they will be connected in reverse order. E.g. ``` logic a[1:0]; logic b[0:1]; assign b = a; ``` should connect a[0] to b[1] and a[1] to b[0]. Things get a bit more tricky for multi-dimensional arrays where some dimensions have a matching direction and some do not. The current implementation always connects them low to high, which results in incorrect behavior. Signed-off-by: Lars-Peter Clausen --- netmisc.cc | 70 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 8 deletions(-) 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); } /* From e1691c48fecc429f74392b02b076b6c6a6b155d9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 15 Apr 2023 18:00:07 -0700 Subject: [PATCH 2/2] Add regression tests for reversed continuous array assignment Check that assigning array that have opposite left-to-righto order for their dimensions have their elements assigned in reversed order. Signed-off-by: Lars-Peter Clausen --- ivtest/gold/sv_array_cassign7-vvp-stdout.gold | 106 ++++++++++++++++++ ivtest/ivltests/sv_array_cassign6.v | 21 ++++ ivtest/ivltests/sv_array_cassign7.v | 37 ++++++ ivtest/regress-vvp.list | 2 + ivtest/vvp_tests/sv_array_cassign6.json | 5 + ivtest/vvp_tests/sv_array_cassign7.json | 6 + 6 files changed, 177 insertions(+) create mode 100644 ivtest/gold/sv_array_cassign7-vvp-stdout.gold create mode 100644 ivtest/ivltests/sv_array_cassign6.v create mode 100644 ivtest/ivltests/sv_array_cassign7.v create mode 100644 ivtest/vvp_tests/sv_array_cassign6.json create mode 100644 ivtest/vvp_tests/sv_array_cassign7.json 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" +}