From 50d9a32d56b425940c40eea7c9ea4ac4528e32f0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 2 Sep 2024 18:25:41 +0200 Subject: [PATCH 1/2] tgt-vvp: Use signedness of expression instead of signal for index load When loading a signal into into an index register currently the signedness of the signal is used when deciding whether sign-extension should be performed or not. But this can lead to incorrect results, instead the signedness of the expression must be used as that might be different from the signal. E.g. ``` reg signed [1:0] = 2'b10; $display(1 << x[1:0]); ``` gives the wrong result without this. Signed-off-by: Lars-Peter Clausen --- tgt-vvp/eval_expr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 443a821ebb..4103bc735b 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -226,12 +226,12 @@ void eval_logic_into_integer(ivl_expr_t expr, unsigned ix) reading index values directly from variables. In this case, try to use that special instruction. */ case IVL_EX_SIGNAL: { + const char*type = ivl_expr_signed(expr) ? "/s" : ""; ivl_signal_t sig = ivl_expr_signal(expr); unsigned word = 0; if (ivl_signal_dimensions(sig) > 0) { ivl_expr_t ixe; - const char*type = ivl_expr_signed(expr) ? "/s" : ""; /* Detect the special case that this is a variable array. In this case, the ix/getv @@ -252,7 +252,6 @@ void eval_logic_into_integer(ivl_expr_t expr, unsigned ix) break; } } - const char*type = ivl_signal_signed(sig) ? "/s" : ""; fprintf(vvp_out, " %%ix/getv%s %u, v%p_%u;\n", type, ix, sig, word); break; From 841e5a9d9e0a4bfefa4834efffc5aa46e0f030b2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 2 Sep 2024 19:05:02 +0200 Subject: [PATCH 2/2] ivtest: Add regression test to check that shift rhs is always unsigned Add a regression test to check that the right-hand side of a shift operation is always treated as unsigned, even if it is a signed registers or a variation thereof. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/shift6.v | 51 ++++++++++++++++++++++++++++++++++++ ivtest/regress-vvp.list | 1 + ivtest/vvp_tests/shift6.json | 5 ++++ 3 files changed, 57 insertions(+) create mode 100644 ivtest/ivltests/shift6.v create mode 100644 ivtest/vvp_tests/shift6.json diff --git a/ivtest/ivltests/shift6.v b/ivtest/ivltests/shift6.v new file mode 100644 index 0000000000..7dd09a75cf --- /dev/null +++ b/ivtest/ivltests/shift6.v @@ -0,0 +1,51 @@ +module test; + +// Check that the right hand side for a shift instruction is always treated as +// unsigned. Even if its a signed register, or a transformation thereof. + + reg failed = 1'b0; + + `define check(val, exp) \ + if ((val) !== (exp)) begin \ + $display("FAILED(%0d): `%s`, expected `%0d`, got `%0d`.", `__LINE__, \ + `"val`", (exp), (val), 4); \ + failed = 1'b1; \ + end + + reg signed [1:0] shift = 2'b10; + + initial begin + `check(1 << shift, 4) + `check(1 << shift[1:0], 4) + `check(2 << shift[1], 4) + `check(1 << $unsigned(shift), 4) + `check(1 << $signed(shift), 4) + `check(1 << {shift}, 4) + + `check(1 <<< shift, 4) + `check(1 <<< shift[1:0], 4) + `check(2 <<< shift[1], 4) + `check(1 <<< $unsigned(shift), 4) + `check(1 <<< $signed(shift), 4) + `check(1 <<< {shift}, 4) + + `check(16 >> shift, 4) + `check(16 >> shift[1:0], 4) + `check(8 >> shift[1], 4) + `check(16 >> $unsigned(shift), 4) + `check(16 >> $signed(shift), 4) + `check(16 >> {shift}, 4) + + `check(16 >>> shift, 4) + `check(16 >>> shift[1:0], 4) + `check(8 >>> shift[1], 4) + `check(16 >>> $unsigned(shift), 4) + `check(16 >>> $signed(shift), 4) + `check(16 >>> {shift}, 4) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 6f3d6da748..0d9dcbe919 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -185,6 +185,7 @@ sf_countones_fail vvp_tests/sf_countones_fail.json sf_isunknown_fail vvp_tests/sf_isunknown_fail.json sf_onehot_fail vvp_tests/sf_onehot_fail.json sf_onehot0_fail vvp_tests/sf_onehot0_fail.json +shift6 vvp_tests/shift6.json single_element_array vvp_tests/single_element_array.json struct_enum_partsel vvp_tests/struct_enum_partsel.json struct_field_left_right vvp_tests/struct_field_left_right.json diff --git a/ivtest/vvp_tests/shift6.json b/ivtest/vvp_tests/shift6.json new file mode 100644 index 0000000000..b88acf95c4 --- /dev/null +++ b/ivtest/vvp_tests/shift6.json @@ -0,0 +1,5 @@ + +{ + "type" : "normal", + "source" : "shift6.v" +}