diff --git a/src/V3DfgDecomposition.cpp b/src/V3DfgDecomposition.cpp index 4647d1484..38f31288e 100644 --- a/src/V3DfgDecomposition.cpp +++ b/src/V3DfgDecomposition.cpp @@ -345,16 +345,19 @@ class ExtractCyclicComponents final { void fixEdges(DfgVertexVar& vtx) { const size_t component = state(vtx).component; - // All variable vertices have at most a single source, and only variable - // vertices can have multiple sinks, therefore the source must be either: - // - in the same component as the variable vertex - // - be a variable vertex itself, which might be in a different component - // The later case will be fixed up when handling the source variable - DfgVertex* const srcp = vtx.srcp(); - UASSERT_OBJ(!srcp || srcp->is() || state(*srcp).component == component, &vtx, - "Driver of DfgVertexVar must be in the same component"); + // Fix up sources in a different component + vtx.forEachSourceEdge([&](DfgEdge& edge, size_t) { + DfgVertex* const srcp = edge.sourcep(); + if (!srcp) return; + const size_t sourceComponent = state(*srcp).component; + // Same component is OK + if (sourceComponent == component) return; + // Relink the source to write the clone + edge.unlinkSource(); + getClone(vtx, sourceComponent).srcp(srcp); + }); - // Fix up sinks in a differetn component + // Fix up sinks in a different component vtx.forEachSinkEdge([&](DfgEdge& edge) { const size_t sinkComponent = state(*edge.sinkp()).component; // Same component is OK diff --git a/test_regress/t/t_dfg_circular_merged_scc.py b/test_regress/t/t_dfg_circular_merged_scc.py new file mode 100755 index 000000000..319c0ff4a --- /dev/null +++ b/test_regress/t/t_dfg_circular_merged_scc.py @@ -0,0 +1,16 @@ +#!/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() + +test.passes() diff --git a/test_regress/t/t_dfg_circular_merged_scc.v b/test_regress/t/t_dfg_circular_merged_scc.v new file mode 100644 index 000000000..c9ccaddb9 --- /dev/null +++ b/test_regress/t/t_dfg_circular_merged_scc.v @@ -0,0 +1,27 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Geza Lore. +// SPDX-License-Identifier: CC0-1.0 + +module mul (input [8:0] A, input [16:0] B, output [25:0] Y); + assign Y = $signed(A) * $signed(B); +endmodule + +module A; + wire [26:0] C; + wire [26:0] D; + wire [8:0] E; + + // This yields a circular DFG with a fairly special form that used to trip + // decomposition. + mul mul ( + .A(9'd10), + .B(17'h0cccd), + .Y({ C[26], C[9:0], D[15:1] }) + ); + + assign E = { C[8:0] }; + assign C[25:10] = {16{C[26]}}; + +endmodule