Skip to content

Commit

Permalink
Fix DFG assertion with SystemC
Browse files Browse the repository at this point in the history
  • Loading branch information
gezalore committed Apr 27, 2024
1 parent 9768065 commit cce2ebe
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 13 deletions.
8 changes: 1 addition & 7 deletions src/V3DfgPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); });
}
}
}
Expand Down
28 changes: 22 additions & 6 deletions src/V3DfgRegularize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
});

Expand Down Expand Up @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions test_regress/t/t_dfg_regularize_driver_of_sc_var.pl
Original file line number Diff line number Diff line change
@@ -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;
14 changes: 14 additions & 0 deletions test_regress/t/t_dfg_regularize_driver_of_sc_var.v
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit cce2ebe

Please sign in to comment.