diff --git a/src/V3Dfg.cpp b/src/V3Dfg.cpp index 9c5db2b23..5e24236e9 100644 --- a/src/V3Dfg.cpp +++ b/src/V3Dfg.cpp @@ -552,6 +552,10 @@ DfgVertexVar* DfgVertex::getResultVar() { this->foreachSink([&resp](DfgVertex& sink) { DfgVertexVar* const varp = sink.cast(); if (!varp) return false; + + // Do not use it if value might differ from its drivers + if (varp->isVolatile()) return false; + // First variable found if (!resp) { resp = varp; @@ -559,12 +563,8 @@ DfgVertexVar* DfgVertex::getResultVar() { } // Prefer those variables that must be kept anyway - if (resp->hasExtRefs() != varp->hasExtRefs()) { - if (!resp->hasExtRefs()) resp = varp; - return false; - } - if (resp->hasModWrRefs() != varp->hasModWrRefs()) { - if (!resp->hasModWrRefs()) resp = varp; + if (resp->hasExtRdRefs() != varp->hasExtRdRefs()) { + if (!resp->hasExtRdRefs()) resp = varp; return false; } if (resp->hasDfgRefs() != varp->hasDfgRefs()) { diff --git a/test_regress/t/t_dfg_result_var_ext_write.py b/test_regress/t/t_dfg_result_var_ext_write.py new file mode 100755 index 000000000..aa5dacc93 --- /dev/null +++ b/test_regress/t/t_dfg_result_var_ext_write.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=["--binary"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_dfg_result_var_ext_write.v b/test_regress/t/t_dfg_result_var_ext_write.v new file mode 100644 index 000000000..5ce0e6828 --- /dev/null +++ b/test_regress/t/t_dfg_result_var_ext_write.v @@ -0,0 +1,65 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define check(got ,exp) do if ((got) !== (exp)) begin $write("%%Error: %s:%0d: $time=%0t got='h%x exp='h%x\n", `__FILE__,`__LINE__, $time, (got), (exp)); `stop; end while(0) + +module top; + + logic clk = 0; + always #5 clk = ~clk; + + int cnt = 0; + always @(posedge clk) cnt <= cnt + 1; + + wire forcedVar = &cnt[2:1]; + wire sharedTerm = &cnt[2:1]; + wire otherVar = ~sharedTerm; + + initial begin + repeat (50) begin + @(posedge clk); + `check(otherVar == ~forcedVar, 1); + end + + force forcedVar = 1'b1; + + repeat (50) begin + @(posedge clk); + `check(otherVar == ~forcedVar, cnt[2] & cnt[1]); + end + + release forcedVar; + + repeat (50) begin + @(posedge clk); + `check(otherVar == ~forcedVar, 1); + end + + force forcedVar = 1'b0; + + repeat (50) begin + @(posedge clk); + `check(otherVar == ~forcedVar, ~cnt[2] | ~cnt[1]); + end + + release forcedVar; + + repeat (50) begin + @(posedge clk); + `check(otherVar == ~forcedVar, 1); + end + + + $write("*-* All Finished *-*\n"); + $finish; + end + + always @(sharedTerm or otherVar) begin + `check(otherVar, ~sharedTerm); + end + +endmodule diff --git a/test_regress/t/t_inst_tree_inl0_pub1.py b/test_regress/t/t_inst_tree_inl0_pub1.py index 9d89a7285..3fa932f0e 100755 --- a/test_regress/t/t_inst_tree_inl0_pub1.py +++ b/test_regress/t/t_inst_tree_inl0_pub1.py @@ -42,7 +42,7 @@ if test.vlt_all: # We expect to combine sequent functions across multiple instances of # l2, l3, l4, l5. If this number drops, please confirm this has not broken. test.file_grep(test.stats, r'Optimizations, Combined CFuncs\s+(\d+)', - (99 if test.vltmt else 82)) + (85 if test.vltmt else 67)) # Everything should use relative references check_relative_refs("t", True)