Fix DFG assertion with SystemC (#5076)

Fixes #5050
This commit is contained in:
Geza Lore 2024-04-27 13:41:10 +01:00 committed by GitHub
parent 97680656d3
commit 27b7e70218
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 55 additions and 13 deletions

View File

@ -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<DfgVarPacked>()) {
if (sinkVarp->varp()->isSc()) return;
}
edge.relinkSource(driverp);
});
varp->forEachSinkEdge([=](DfgEdge& edge) { edge.relinkSource(driverp); });
}
}
}

View File

@ -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<DfgVarPacked*> varVtxps;
vtx.forEachSink([&](DfgVertex& sink) {
if (DfgVarPacked* const varVtxp = sink.cast<DfgVarPacked>()) {
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<DfgArraySel>()) 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<DfgVertexVar>([](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<DfgArraySel>()) 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);

View File

@ -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;

View File

@ -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