From a4eeea75ce636b62c7dfa60ae137473138698bed Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 26 May 2022 21:19:59 +0200 Subject: [PATCH 1/2] tgt-vvp: Handle assignment operator on real array entries The basic structure for supporting assignment operators on real arrays exists in the tgt-vvp backend. But there are a few problems, most importantly it generates the wrong instruction for loading data from the real array. The instruction it uses is `%load/reala`, but that instruction does not exist, the correct name is `%load/ar`. In addition to this there are a few minor problems. * Out-of-bounds access on the array triggers an assert * Missing `%pop/real` instruction when skipping a write due to out-of-bounds access Address these so assignment operators are supported on real array entries. Signed-off-by: Lars-Peter Clausen --- tgt-vvp/stmt_assign.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 123b2d405..3095fe1a9 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -648,8 +648,10 @@ static void get_real_from_lval(ivl_lval_t lval, struct real_lval_info*slice) it to select the word, and pay no further heed to the expression itself. */ if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) { - assert(! number_is_unknown(word_ix)); - use_word = get_number_immediate(word_ix); + if (number_is_unknown(word_ix)) + use_word = ULONG_MAX; // The largest valid index is ULONG_MAX - 1 + else + use_word = get_number_immediate(word_ix); word_ix = 0; } @@ -673,7 +675,8 @@ static void get_real_from_lval(ivl_lval_t lval, struct real_lval_info*slice) if (use_word < ivl_signal_array_count(sig)) { fprintf(vvp_out, " %%ix/load 3, %lu, 0;\n", use_word); - fprintf(vvp_out, " %%load/reala v%p, 3;\n", sig); + fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); + fprintf(vvp_out, " %%load/ar v%p, 3;\n", sig); } else { fprintf(vvp_out, " %%pushi/real 0, 0;\n"); } @@ -688,7 +691,7 @@ static void get_real_from_lval(ivl_lval_t lval, struct real_lval_info*slice) draw_eval_expr_into_integer(word_ix, slice->u_.memory_word_dynamic.word_idx_reg); fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.memory_word_dynamic.x_flag); - fprintf(vvp_out, " %%load/reala v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg); + fprintf(vvp_out, " %%load/ar v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg); } else { assert(0); @@ -728,6 +731,7 @@ static void put_real_to_lval(ivl_lval_t lval, struct real_lval_info*slice) clr_word(word_idx); } else { fprintf(vvp_out," ; Skip this slice write to v%p [%lu]\n", sig, slice->u_.memory_word_static.use_word); + fprintf(vvp_out," %%pop/real 1;\n"); } break; From 5ae7425fdb74d4537478d0facee46f92a3bb754d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 26 May 2022 21:44:14 +0200 Subject: [PATCH 2/2] Add regression tests for assignment operator on real array entries Check that assignment operators on real array entries are supported. Also check that * out-of-bounds indices work as expected * it works after a comparison that set vvp flag 4 to 0 Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/assign_op_after_cmp3.v | 24 ++++++++++++ ivtest/ivltests/assign_op_real_array.v | 34 +++++++++++++++++ ivtest/ivltests/assign_op_real_array_oob.v | 43 ++++++++++++++++++++++ ivtest/regress-sv.list | 3 ++ ivtest/regress-vlog95.list | 3 ++ 5 files changed, 107 insertions(+) create mode 100644 ivtest/ivltests/assign_op_after_cmp3.v create mode 100644 ivtest/ivltests/assign_op_real_array.v create mode 100644 ivtest/ivltests/assign_op_real_array_oob.v diff --git a/ivtest/ivltests/assign_op_after_cmp3.v b/ivtest/ivltests/assign_op_after_cmp3.v new file mode 100644 index 000000000..4475d57d9 --- /dev/null +++ b/ivtest/ivltests/assign_op_after_cmp3.v @@ -0,0 +1,24 @@ +// Check that a assignment operator on an real array entry with an immediate +// index works if it happes after a comparison that sets vvp flag 4 to 0. + +module test; + + real r[1:0]; + logic a = 1'b0; + + initial begin + r[0] = 8.0; + if (a == 0) begin + // Make sure that this update happens, even though the compare above + // cleared set vvp flag 4 + r[0] *= 2.0; + end + + if (r[0] == 16.0) begin + $display("PASSED"); + end else begin + $display("FAILED. Expected %f, got %f", 16.0, r[0]); + end + end + +endmodule diff --git a/ivtest/ivltests/assign_op_real_array.v b/ivtest/ivltests/assign_op_real_array.v new file mode 100644 index 000000000..64b92aab5 --- /dev/null +++ b/ivtest/ivltests/assign_op_real_array.v @@ -0,0 +1,34 @@ +// Check that assignment operators on real arrays are supported. + +module test; + + real r[1:0]; + integer i = 1; + + initial begin + // Immediate index + r[0] = 8.0; + r[0] += 1.0; + r[0] -= 2.0; + r[0] *= 3.0; + r[0] /= 7.0; + r[0]++; + r[0]--; + + // Variable index + r[i] = 8.0; + r[i] += 1.0; + r[i] -= 2.0; + r[i] *= 3.0; + r[i] /= 7.0; + r[i]++; + r[i]--; + + if (r[0] == 3.0 && r[1] == 3.0) begin + $display("PASSED"); + end else begin + $display("FAILED. Expected %f, got %f and %f", 3.0, r[0], r[1]); + end + end + +endmodule diff --git a/ivtest/ivltests/assign_op_real_array_oob.v b/ivtest/ivltests/assign_op_real_array_oob.v new file mode 100644 index 000000000..305364afe --- /dev/null +++ b/ivtest/ivltests/assign_op_real_array_oob.v @@ -0,0 +1,43 @@ +// Check that the assignment operator is supported for out-of-bounds indices on +// real arrays. The write should be skipped, but side effects of the right-hand +// side expression should still get evaluated. + +module test; + + real a[1:0]; + integer i; + real r = 0; + + function real f; + r += 0.125; + return r; + endfunction + + initial begin + a[0] = 23.0; + a[1] = 42.0; + + // Immediate out-of-bounds indices + a[-1] += f(); + a[2] += f(); + a['hx] += f(); + + // Variable out-of-bounds indices + i = -1; + a[i] += f(); + i = 2; + a[i] += f(); + i = 'hx; + a[i] += f(); + + // Check that the in-bounds elements do not get affected by out-of-bounds + // updates. Check that the left-hand side of the operator assignment gets + // evaluated. + if (a[0] == 23.0 && a[1] == 42.0 && r == 0.75) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index bcc4f0047..db483b203 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -98,8 +98,11 @@ array_unpacked_sysfunct normal,-g2005-sv ivltests array_packed normal,-g2005-sv ivltests assign_op_after_cmp1 normal,-g2009 ivltests assign_op_after_cmp2 normal,-g2009 ivltests +assign_op_after_cmp3 normal,-g2009 ivltests assign_op_concat normal,-g2009 ivltests assign_op_oob normal,-g2009 ivltests +assign_op_real_array normal,-g2009 ivltests +assign_op_real_array_oob normal,-g2009 ivltests assign_op_type normal,-g2009 ivltests bitp1 normal,-g2005-sv ivltests bits normal,-g2005-sv ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 5886acce3..5805ffdde 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -212,6 +212,9 @@ array_select CE,-pallowsigned=1 ivltests array_select_a CE ivltests array_unpacked_sysfunct CE,-g2005-sv ivltests array_word_width2 CE ivltests +assign_op_after_cmp3 CE,-g2009 ivltests +assign_op_real_array CE,-g2009 ivltests +assign_op_real_array_oob CE,-g2009 ivltests br1008 CE ivltests br1019 CE ivltests br_gh556 CE,-g2009 ivltests