From 993240091eda586c03b422154d7f5ebf33288f96 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Fri, 26 Aug 2022 19:05:31 +0100 Subject: [PATCH] Handle side effects in pulse reject interval expression. Fixed #527 --- src/lower.c | 42 ++++++++++++++++++++++++--------------- test/regress/issue527.vhd | 25 +++++++++++++++++++++++ test/regress/testlist.txt | 1 + test/test_lower.c | 16 +++++++-------- 4 files changed, 60 insertions(+), 24 deletions(-) create mode 100644 test/regress/issue527.vhd diff --git a/src/lower.c b/src/lower.c index 3a09205c..63ed2612 100644 --- a/src/lower.c +++ b/src/lower.c @@ -5109,12 +5109,6 @@ static void lower_disconnect_target(target_part_t **ptr, vcode_reg_t reject, static void lower_signal_assign(tree_t stmt) { - vcode_reg_t reject; - if (tree_has_reject(stmt)) - reject = lower_reify_expr(tree_reject(stmt)); - else - reject = emit_const(vtype_int(INT64_MIN, INT64_MAX), 0); - tree_t target = tree_target(stmt); const int nparts = lower_count_target_parts(target, 0); @@ -5128,11 +5122,30 @@ static void lower_signal_assign(tree_t stmt) for (int i = 0; i < nwaveforms; i++) { tree_t w = tree_waveform(stmt, i); - vcode_reg_t after; - if (tree_has_delay(w)) - after = lower_reify_expr(tree_delay(w)); + tree_t delay = NULL; + vcode_reg_t delay_reg; + if (tree_has_delay(w)) { + delay = tree_delay(w); + delay_reg = lower_reify_expr(delay); + } else - after = emit_const(vtype_int(INT64_MIN, INT64_MAX), 0); + delay_reg = emit_const(vtype_int(INT64_MIN, INT64_MAX), 0); + + vcode_reg_t reject_reg; + if (i == 0 && tree_has_reject(stmt)) { + tree_t reject = tree_reject(stmt); + if (reject == delay) { + // If delay is the same as reject ensure the expression is + // only evaluated once + reject_reg = delay_reg; + } + else + reject_reg = lower_reify_expr(reject); + } + else { + // All but the first waveform have zero reject time + reject_reg = emit_const(vtype_int(INT64_MIN, INT64_MAX), 0); + } vcode_var_t tmp_var = VCODE_INVALID_VAR; @@ -5176,16 +5189,13 @@ static void lower_signal_assign(tree_t stmt) VCODE_INVALID_REG); } - lower_signal_assign_target(&ptr, wvalue, rhs, wtype, reject, after); + lower_signal_assign_target(&ptr, wvalue, rhs, wtype, + reject_reg, delay_reg); } else - lower_disconnect_target(&ptr, reject, after); + lower_disconnect_target(&ptr, reject_reg, delay_reg); assert(ptr == parts + nparts); - // All but the first waveform have zero reject time - if (nwaveforms > 1 && tree_has_reject(stmt)) - reject = emit_const(vtype_int(INT64_MIN, INT64_MAX), 0); - if (tmp_var != VCODE_INVALID_VAR) lower_release_temp(tmp_var); } diff --git a/test/regress/issue527.vhd b/test/regress/issue527.vhd new file mode 100644 index 00000000..0878f47e --- /dev/null +++ b/test/regress/issue527.vhd @@ -0,0 +1,25 @@ +library ieee; +use ieee.math_real.all; + +entity issue527 is +end entity; + +architecture test of issue527 is + signal s : bit; +begin + + p1: process (s) is + variable s1, s2 : positive := 12345; + + impure function random (x, y : delay_length) return delay_length is + variable r : real; + begin + uniform(s1, s2, r); + return x + r * (y - x); + end function; + + begin + s <= not s after random(1 ns, 2 ns); + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 3c4486b3..911a06f0 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -651,3 +651,4 @@ issue516 normal libdir3 shell elab35 normal issue524 shell +issue527 normal,stop=1us diff --git a/test/test_lower.c b/test/test_lower.c index b9551429..e576e33a 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -649,9 +649,9 @@ START_TEST(test_signal1) { VCODE_OP_CMP, .cmp = VCODE_CMP_EQ }, { VCODE_OP_DEBUG_LOCUS }, { VCODE_OP_ASSERT }, - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_CONST, .value = 6 }, { VCODE_OP_SCHED_WAVEFORM }, { VCODE_OP_WAIT, .target = 2 } @@ -1338,9 +1338,9 @@ START_TEST(test_signal4) { VCODE_OP_INDEX, .name = "V" }, { VCODE_OP_ARRAY_REF }, { VCODE_OP_STORE_INDIRECT }, - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_CONST, .value = 4 }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_SCHED_WAVEFORM }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_RESOLVED }, @@ -1380,11 +1380,11 @@ START_TEST(test_staticwait) CHECK_BB(0); EXPECT_BB(1) = { - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_VAR_UPREF, .name = "X", .hops = 1 }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_CONST, .value = 0 }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_SCHED_WAVEFORM }, { VCODE_OP_WAIT, .target = 2 } }; @@ -2390,8 +2390,8 @@ START_TEST(test_sigvar) vcode_select_unit(v0); EXPECT_BB(0) = { - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_UARRAY_LEN }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_DEBUG_LOCUS }, { VCODE_OP_UARRAY_LEN }, { VCODE_OP_LENGTH_CHECK }, @@ -2604,10 +2604,10 @@ START_TEST(test_iffold) vcode_select_unit(v0); EXPECT_BB(1) = { - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_VAR_UPREF, .name = "X", .hops = 1 }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_CONST, .value = 5 }, { VCODE_OP_SCHED_WAVEFORM }, { VCODE_OP_JUMP, .target = 1 } @@ -4151,11 +4151,11 @@ START_TEST(test_array2) vcode_select_unit(vu); EXPECT_BB(1) = { - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_VAR_UPREF, .name = "S", .hops = 1 }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_CONST, .value = 2 }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_INDEX, .name = "*tmp" }, { VCODE_OP_LOAD, .name = "X" }, { VCODE_OP_CONST, .value = 0 }, @@ -4261,11 +4261,11 @@ START_TEST(test_concat) vcode_select_unit(vu); EXPECT_BB(1) = { - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_VAR_UPREF, .name = "S", .hops = 1 }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_CONST, .value = 3 }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_INDEX, .name = "*tmp" }, { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_CONST, .value = 2 }, @@ -4543,9 +4543,9 @@ START_TEST(test_recsignal1) vcode_select_unit(vu); EXPECT_BB(1) = { - { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_VAR_UPREF, .hops = 1, .name = "P" }, { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_VAR_UPREF, .hops = 1, .name = "Q" }, { VCODE_OP_RECORD_REF, .field = 0 }, { VCODE_OP_RECORD_REF, .field = 0 }, -- 2.39.2