diff --git a/src/V3DfgPasses.cpp b/src/V3DfgPasses.cpp index b5ef851ee..355a85a4f 100644 --- a/src/V3DfgPasses.cpp +++ b/src/V3DfgPasses.cpp @@ -169,13 +169,7 @@ void V3DfgPasses::inlineVars(DfgGraph& dfg) { if (astVarp->isForceable()) continue; } - varp->forEachSinkEdge([=](DfgEdge& edge) { - // If sink is a SystemC variable, don't inline that sink - if (DfgVertexVar* const sinkVarp = edge.sinkp()->cast()) { - if (sinkVarp->varp()->isSc()) return; - } - edge.relinkSource(driverp); - }); + varp->forEachSinkEdge([=](DfgEdge& edge) { edge.relinkSource(driverp); }); } } } diff --git a/src/V3DfgRegularize.cpp b/src/V3DfgRegularize.cpp index a4875ef5c..7ab1529d6 100644 --- a/src/V3DfgRegularize.cpp +++ b/src/V3DfgRegularize.cpp @@ -45,11 +45,15 @@ class DfgRegularize final { // Return canonical variable that can be used to hold the value of this vertex DfgVarPacked* getCanonicalVariable(DfgVertex& vtx) { - // First gather all existing variables fully written by this vertex + // First gather all existing variables fully written by this vertex. Ignore SystemC + // variables, those cannot act as canonical variables, as they cannot participate in + // expressions or be assigned rvalues. std::vector varVtxps; vtx.forEachSink([&](DfgVertex& sink) { if (DfgVarPacked* const varVtxp = sink.cast()) { - if (varVtxp->isDrivenFullyByDfg()) varVtxps.push_back(varVtxp); + if (varVtxp->isDrivenFullyByDfg() && !varVtxp->varp()->isSc()) { + varVtxps.push_back(varVtxp); + } } }); @@ -95,10 +99,22 @@ class DfgRegularize final { // Ensure intermediate values used multiple times are written to variables for (DfgVertex& vtx : m_dfg.opVertices()) { - // Operations without multiple sinks need no variables - if (!vtx.hasMultipleSinks()) continue; - // Array selects need no variables, they are just memory references - if (vtx.is()) continue; + const bool needsIntermediateVariable = [&]() { + // Anything that drives an SC variable needs an intermediate, + // as we can only assign simple variables to SC variables at runtime. + const bool hasScSink = vtx.findSink([](const DfgVertexVar& var) { // + return var.varp()->isSc(); + }); + if (hasScSink) return true; + // Operations without multiple sinks need no variables + if (!vtx.hasMultipleSinks()) return false; + // Array selects need no variables, they are just memory references + if (vtx.is()) return false; + // Otherwise needs an intermediate variable + return true; + }(); + + if (!needsIntermediateVariable) continue; // This is an op which has multiple sinks. Ensure it is assigned to a variable. DfgVarPacked* const varp = getCanonicalVariable(vtx); diff --git a/test_regress/t/t_dfg_regularize_driver_of_sc_var.pl b/test_regress/t/t_dfg_regularize_driver_of_sc_var.pl new file mode 100755 index 000000000..9158675cc --- /dev/null +++ b/test_regress/t/t_dfg_regularize_driver_of_sc_var.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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 + +scenarios(vlt => 1); + +compile( + verilator_flags2 => ["--sc"] + ); + +ok(1); +1; diff --git a/test_regress/t/t_dfg_regularize_driver_of_sc_var.v b/test_regress/t/t_dfg_regularize_driver_of_sc_var.v new file mode 100644 index 000000000..507d9adf1 --- /dev/null +++ b/test_regress/t/t_dfg_regularize_driver_of_sc_var.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module sub(input in, output out); + assign out = in; +endmodule + +module top(input clk, output out); + logic one = '1; + sub sub_inst(.in(one), .out(out)); +endmodule