Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Convert DfgLogic into primitive operations
|
|
|
|
|
//
|
|
|
|
|
// Code available from: https://verilator.org
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Copyright 2003-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
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Synthesize DfgLogic vertices in as a graph, as created by V3DfgAstToDfg
|
|
|
|
|
// into primitive vertices.
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
|
|
|
|
|
|
|
|
|
#include "V3Cfg.h"
|
|
|
|
|
#include "V3Const.h"
|
|
|
|
|
#include "V3Dfg.h"
|
|
|
|
|
#include "V3DfgPasses.h"
|
|
|
|
|
#include "V3EmitV.h"
|
|
|
|
|
#include "V3Os.h"
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <iterator>
|
|
|
|
|
|
|
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
// Create a DfgVertex out of a AstNodeExpr. For most AstNodeExpr subtypes, this can be done
|
|
|
|
|
// automatically. For the few special cases, we provide specializations below
|
|
|
|
|
template <typename T_Vertex, typename T_Node>
|
|
|
|
|
T_Vertex* makeVertex(const T_Node* nodep, DfgGraph& dfg) {
|
2025-09-02 17:50:40 +02:00
|
|
|
return new T_Vertex{dfg, nodep->fileline(), V3Dfg::toDfgDType(nodep->dtypep())};
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
DfgArraySel* makeVertex<DfgArraySel, AstArraySel>(const AstArraySel* nodep, DfgGraph& dfg) {
|
|
|
|
|
// Some earlier passes create malformed ArraySels, just bail on those...
|
|
|
|
|
// See t_bitsel_wire_array_bad
|
|
|
|
|
if (VN_IS(nodep->fromp(), Const)) return nullptr;
|
|
|
|
|
if (!VN_IS(nodep->fromp()->dtypep()->skipRefp(), UnpackArrayDType)) return nullptr;
|
2025-09-02 17:50:40 +02:00
|
|
|
return new DfgArraySel{dfg, nodep->fileline(), V3Dfg::toDfgDType(nodep->dtypep())};
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
// Visitor that can convert Ast statements and expressions in Dfg vertices
|
|
|
|
|
template <bool T_Scoped>
|
|
|
|
|
class AstToDfgConverter final : public VNVisitor {
|
|
|
|
|
// NODE STATE
|
|
|
|
|
// AstNodeExpr/AstVar/AstVarScope::user2p -> DfgVertex* for this Node
|
|
|
|
|
// AstVar::user3() -> int temporary counter for variable
|
|
|
|
|
const VNUser3InUse m_user3InUse;
|
|
|
|
|
|
|
|
|
|
// TYPES
|
|
|
|
|
using Variable = std::conditional_t<T_Scoped, AstVarScope, AstVar>;
|
|
|
|
|
|
|
|
|
|
// STATE
|
|
|
|
|
DfgGraph& m_dfg; // The graph being built
|
|
|
|
|
V3DfgSynthesisContext& m_ctx; // The context for stats
|
|
|
|
|
|
|
|
|
|
// Current logic vertex we are synthesizing
|
|
|
|
|
DfgLogic* m_logicp = nullptr;
|
|
|
|
|
// Variable updates produced by currently converted statement. This almost
|
|
|
|
|
// always have a single element, so a vector is ok
|
|
|
|
|
std::vector<std::pair<Variable*, DfgVertexVar*>>* m_updatesp = nullptr;
|
|
|
|
|
|
|
|
|
|
bool m_foundUnhandled = false; // Found node not implemented as DFG or not implemented 'visit'
|
|
|
|
|
bool m_converting = false; // We are trying to convert some logic at the moment
|
|
|
|
|
|
2025-09-02 17:50:40 +02:00
|
|
|
size_t m_nUnpack = 0; // Sequence numbers for temporaries
|
|
|
|
|
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// METHODS
|
|
|
|
|
static Variable* getTarget(const AstVarRef* refp) {
|
|
|
|
|
// TODO: remove the useless reinterpret_casts when C++17 'if constexpr' actually works
|
|
|
|
|
if VL_CONSTEXPR_CXX17 (T_Scoped) {
|
|
|
|
|
return reinterpret_cast<Variable*>(refp->varScopep());
|
|
|
|
|
} else {
|
|
|
|
|
return reinterpret_cast<Variable*>(refp->varp());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocate a new non-variable vertex, add it to the currently synthesized logic
|
|
|
|
|
template <typename Vertex, typename... Args>
|
|
|
|
|
Vertex* make(Args&&... args) {
|
|
|
|
|
static_assert(!std::is_base_of<DfgVertexVar, Vertex>::value, "Do not use for variables");
|
|
|
|
|
static_assert(std::is_base_of<DfgVertex, Vertex>::value, "'Vertex' must be a 'DfgVertex'");
|
|
|
|
|
Vertex* const vtxp = new Vertex{m_dfg, std::forward<Args>(args)...};
|
|
|
|
|
m_logicp->synth().emplace_back(vtxp);
|
|
|
|
|
return vtxp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns true if the expression cannot (or should not) be represented by DFG
|
|
|
|
|
bool unhandled(AstNodeExpr* nodep) {
|
|
|
|
|
// Short-circuiting if something was already unhandled
|
|
|
|
|
if (!m_foundUnhandled) {
|
|
|
|
|
// Impure nodes cannot be represented
|
|
|
|
|
if (!nodep->isPure()) {
|
|
|
|
|
m_foundUnhandled = true;
|
|
|
|
|
++m_ctx.m_conv.nonRepImpure;
|
|
|
|
|
}
|
|
|
|
|
// Check node has supported dtype
|
2025-09-02 17:50:40 +02:00
|
|
|
if (!V3Dfg::isSupported(nodep->dtypep())) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
m_foundUnhandled = true;
|
|
|
|
|
++m_ctx.m_conv.nonRepDType;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return m_foundUnhandled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isSupported(const AstVarRef* nodep) {
|
|
|
|
|
// Cannot represent cross module references
|
|
|
|
|
if (nodep->classOrPackagep()) return false;
|
|
|
|
|
// Check target
|
2025-09-02 17:50:40 +02:00
|
|
|
return V3Dfg::isSupported(getTarget(nodep));
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Given an RValue expression, return the equivalent Vertex, or nullptr if not representable.
|
|
|
|
|
DfgVertex* convertRValue(AstNodeExpr* nodep) {
|
|
|
|
|
UASSERT_OBJ(!m_converting, nodep, "'convertingRValue' should not be called recursively");
|
|
|
|
|
VL_RESTORER(m_converting);
|
|
|
|
|
VL_RESTORER(m_foundUnhandled);
|
|
|
|
|
m_converting = true;
|
|
|
|
|
m_foundUnhandled = false;
|
|
|
|
|
|
|
|
|
|
// Convert the expression
|
|
|
|
|
iterate(nodep);
|
|
|
|
|
|
|
|
|
|
// If falied to convert, return nullptr
|
|
|
|
|
if (m_foundUnhandled) return nullptr;
|
|
|
|
|
|
|
|
|
|
// Traversal set user2p to the equivalent vertex
|
|
|
|
|
DfgVertex* const vtxp = nodep->user2u().to<DfgVertex*>();
|
|
|
|
|
UASSERT_OBJ(vtxp, nodep, "Missing Dfg vertex after covnersion");
|
|
|
|
|
return vtxp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Given an LValue expression, return the splice node that writes the
|
|
|
|
|
// destination, together with the index to use for splicing in the value.
|
|
|
|
|
// Returns {nullptr, 0}, if the given LValue expression is not supported.
|
|
|
|
|
std::pair<DfgVertexSplice*, uint32_t> convertLValue(AstNodeExpr* nodep) {
|
|
|
|
|
if (const AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
|
|
|
|
|
if (!isSupported(vrefp)) {
|
|
|
|
|
++m_ctx.m_conv.nonRepLValue;
|
|
|
|
|
return {nullptr, 0};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get (or create a new) temporary for this variable
|
2025-08-20 19:21:24 +02:00
|
|
|
const DfgVertexVar* const vtxp = [&]() -> DfgVertexVar* {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// The variable being assigned
|
|
|
|
|
Variable* const tgtp = getTarget(vrefp);
|
|
|
|
|
|
|
|
|
|
// Find existing one, if any
|
|
|
|
|
for (const auto& pair : *m_updatesp) {
|
|
|
|
|
if (pair.first == tgtp) return pair.second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create new one
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexVar* const newp = createTmp(*m_logicp, tgtp, "SynthAssign");
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
m_updatesp->emplace_back(tgtp, newp);
|
|
|
|
|
|
|
|
|
|
// Create the Splice driver for the new temporary
|
|
|
|
|
if (newp->is<DfgVarPacked>()) {
|
|
|
|
|
newp->srcp(make<DfgSplicePacked>(newp->fileline(), newp->dtypep()));
|
|
|
|
|
} else if (newp->is<DfgVarArray>()) {
|
|
|
|
|
newp->srcp(make<DfgSpliceArray>(newp->fileline(), newp->dtypep()));
|
|
|
|
|
} else {
|
|
|
|
|
nodep->v3fatalSrc("Unhandled DfgVertexVar sub-type"); // LCOV_EXCL_LINE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use new temporary
|
|
|
|
|
return newp;
|
|
|
|
|
}();
|
|
|
|
|
|
|
|
|
|
// Return the Splice driver
|
|
|
|
|
return {vtxp->srcp()->as<DfgVertexSplice>(), 0};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const AstSel* selp = VN_CAST(nodep, Sel)) {
|
|
|
|
|
// Only handle constant selects
|
|
|
|
|
const AstConst* const lsbp = VN_CAST(selp->lsbp(), Const);
|
|
|
|
|
if (!lsbp) {
|
|
|
|
|
++m_ctx.m_conv.nonRepLValue;
|
|
|
|
|
return {nullptr, 0};
|
|
|
|
|
}
|
|
|
|
|
uint32_t lsb = lsbp->toUInt();
|
|
|
|
|
|
|
|
|
|
// Convert the 'fromp' sub-expression
|
|
|
|
|
const auto pair = convertLValue(selp->fromp());
|
|
|
|
|
if (!pair.first) return {nullptr, 0};
|
|
|
|
|
DfgSplicePacked* const splicep = pair.first->template as<DfgSplicePacked>();
|
|
|
|
|
// Adjust index.
|
|
|
|
|
lsb += pair.second;
|
|
|
|
|
|
|
|
|
|
// AstSel doesn't change type kind (array vs packed), so we can use
|
|
|
|
|
// the existing splice driver with adjusted lsb
|
|
|
|
|
return {splicep, lsb};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const AstArraySel* const aselp = VN_CAST(nodep, ArraySel)) {
|
|
|
|
|
// Only handle constant selects
|
|
|
|
|
const AstConst* const indexp = VN_CAST(aselp->bitp(), Const);
|
|
|
|
|
if (!indexp) {
|
|
|
|
|
++m_ctx.m_conv.nonRepLValue;
|
|
|
|
|
return {nullptr, 0};
|
|
|
|
|
}
|
|
|
|
|
uint32_t index = indexp->toUInt();
|
|
|
|
|
|
|
|
|
|
// Convert the 'fromp' sub-expression
|
|
|
|
|
const auto pair = convertLValue(aselp->fromp());
|
|
|
|
|
if (!pair.first) return {nullptr, 0};
|
|
|
|
|
DfgSpliceArray* const splicep = pair.first->template as<DfgSpliceArray>();
|
|
|
|
|
// Adjust index. Note pair.second is always 0, but we might handle array slices later..
|
|
|
|
|
index += pair.second;
|
|
|
|
|
|
|
|
|
|
// Ensure the Splice driver exists for this element
|
|
|
|
|
if (!splicep->driverAt(index)) {
|
|
|
|
|
FileLine* const flp = nodep->fileline();
|
2025-09-02 17:50:40 +02:00
|
|
|
AstNodeDType* const dtypep = V3Dfg::toDfgDType(nodep->dtypep());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (VN_IS(dtypep, BasicDType)) {
|
|
|
|
|
DfgSplicePacked* const newp = make<DfgSplicePacked>(flp, dtypep);
|
2025-09-02 17:50:40 +02:00
|
|
|
AstNodeDType* const uaDtypep = V3Dfg::dtypeArray(dtypep, 1);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgUnitArray* const uap = make<DfgUnitArray>(flp, uaDtypep);
|
|
|
|
|
uap->srcp(newp);
|
2025-09-02 17:50:40 +02:00
|
|
|
splicep->addDriver(uap, index, flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
} else if (VN_IS(dtypep, UnpackArrayDType)) {
|
|
|
|
|
DfgSpliceArray* const newp = make<DfgSpliceArray>(flp, dtypep);
|
2025-09-02 17:50:40 +02:00
|
|
|
splicep->addDriver(newp, index, flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
} else {
|
|
|
|
|
nodep->v3fatalSrc("Unhandled AstNodeDType sub-type"); // LCOV_EXCL_LINE
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return the splice driver
|
|
|
|
|
DfgVertex* driverp = splicep->driverAt(index);
|
2025-08-20 19:21:24 +02:00
|
|
|
if (const DfgUnitArray* const uap = driverp->cast<DfgUnitArray>()) {
|
|
|
|
|
driverp = uap->srcp();
|
|
|
|
|
}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
return {driverp->as<DfgVertexSplice>(), 0};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++m_ctx.m_conv.nonRepLValue;
|
|
|
|
|
return {nullptr, 0};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Given the LHS of an assignment, and the vertex representing the RHS,
|
|
|
|
|
// connect up the RHS to drive the targets.
|
|
|
|
|
// Returns true on success, false if the LHS is not representable.
|
|
|
|
|
bool convertAssignment(FileLine* flp, AstNodeExpr* lhsp, DfgVertex* vtxp) {
|
|
|
|
|
// Represents a DFG assignment contributed by the AST assignment with the above 'lhsp'.
|
|
|
|
|
// There might be multiple of these if 'lhsp' is a concatenation.
|
|
|
|
|
struct Assignment final {
|
|
|
|
|
DfgVertexSplice* m_lhsp;
|
|
|
|
|
uint32_t m_idx;
|
|
|
|
|
DfgVertex* m_rhsp;
|
|
|
|
|
Assignment() = delete;
|
|
|
|
|
Assignment(DfgVertexSplice* lhsp, uint32_t idx, DfgVertex* rhsp)
|
|
|
|
|
: m_lhsp{lhsp}
|
|
|
|
|
, m_idx{idx}
|
|
|
|
|
, m_rhsp{rhsp} {}
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-02 17:50:40 +02:00
|
|
|
// Simplify the LHS, to get rid of things like SEL(CONCAT(_, _), _)
|
|
|
|
|
lhsp = VN_AS(V3Const::constifyExpensiveEdit(lhsp), NodeExpr);
|
|
|
|
|
|
|
|
|
|
// Assigning compound expressions to a concatenated LHS requires a temporary
|
|
|
|
|
// to avoid multiple use of the expression
|
|
|
|
|
if (VN_IS(lhsp, Concat) && !vtxp->is<DfgVertexVar>() && !vtxp->is<DfgConst>()) {
|
|
|
|
|
const size_t n = ++m_nUnpack;
|
|
|
|
|
DfgVertexVar* const tmpp = createTmp(*m_logicp, flp, vtxp->dtypep(), "Unpack", n);
|
|
|
|
|
tmpp->srcp(vtxp);
|
|
|
|
|
vtxp = tmpp;
|
|
|
|
|
}
|
|
|
|
|
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Convert each concatenation LHS separately, gather all assignments
|
|
|
|
|
// we need to do into 'assignments', return true if all LValues
|
|
|
|
|
// converted successfully.
|
|
|
|
|
std::vector<Assignment> assignments;
|
2025-09-02 17:50:40 +02:00
|
|
|
const std::function<bool(AstNodeExpr*, uint32_t)> convertAllLValues
|
|
|
|
|
= [&](AstNodeExpr* subp, uint32_t lsb) -> bool {
|
|
|
|
|
// Concatenation on the LHS, convert each part
|
|
|
|
|
if (AstConcat* const concatp = VN_CAST(subp, Concat)) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
AstNodeExpr* const cRhsp = concatp->rhsp();
|
2025-09-02 17:50:40 +02:00
|
|
|
AstNodeExpr* const cLhsp = concatp->lhsp();
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Convert Rigth of concat
|
2025-09-02 17:50:40 +02:00
|
|
|
if (!convertAllLValues(cRhsp, lsb)) return false;
|
|
|
|
|
// Convert Left of concat
|
|
|
|
|
return convertAllLValues(cLhsp, lsb + cRhsp->width());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Non-concatenation, convert the LValue
|
2025-09-02 17:50:40 +02:00
|
|
|
const auto pair = convertLValue(subp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (!pair.first) return false;
|
2025-09-02 17:50:40 +02:00
|
|
|
|
|
|
|
|
// If whole lhs, just use it
|
|
|
|
|
if (subp == lhsp) {
|
|
|
|
|
assignments.emplace_back(pair.first, pair.second, vtxp);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise select the relevant bits
|
|
|
|
|
DfgSel* const selp = make<DfgSel>(subp->fileline(), V3Dfg::toDfgDType(subp->dtypep()));
|
|
|
|
|
selp->fromp(vtxp);
|
|
|
|
|
selp->lsb(lsb);
|
|
|
|
|
assignments.emplace_back(pair.first, pair.second, selp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Convert the given LHS assignment, give up if any LValues failed to convert
|
2025-09-02 17:50:40 +02:00
|
|
|
if (!convertAllLValues(lhsp, 0)) return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// All successful, connect the drivers
|
|
|
|
|
for (const Assignment& item : assignments) {
|
|
|
|
|
if (DfgSplicePacked* const spp = item.m_lhsp->template cast<DfgSplicePacked>()) {
|
2025-09-02 17:50:40 +02:00
|
|
|
spp->addDriver(item.m_rhsp, item.m_idx, flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
} else if (DfgSpliceArray* const sap = item.m_lhsp->template cast<DfgSpliceArray>()) {
|
|
|
|
|
AstUnpackArrayDType* const lDtp = VN_AS(sap->dtypep(), UnpackArrayDType);
|
|
|
|
|
const AstNodeDType* const lEleDtp = lDtp->subDTypep();
|
|
|
|
|
AstNodeDType* const rDtp = item.m_rhsp->dtypep();
|
|
|
|
|
if (lEleDtp->isSame(rDtp)) {
|
|
|
|
|
// RHS is assigning an element of this array. Need a DfgUnitArray adapter.
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgUnitArray* const uap = make<DfgUnitArray>(flp, V3Dfg::dtypeArray(rDtp, 1));
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
uap->srcp(item.m_rhsp);
|
2025-09-02 17:50:40 +02:00
|
|
|
sap->addDriver(uap, item.m_idx, flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
} else {
|
|
|
|
|
// RHS is assigning an array (or array slice). Should be the same element type.
|
|
|
|
|
const AstNodeDType* const rEleDtp = VN_AS(rDtp, UnpackArrayDType)->subDTypep();
|
|
|
|
|
UASSERT_OBJ(lEleDtp->isSame(rEleDtp), item.m_rhsp, "Mismatched array types");
|
2025-09-02 17:50:40 +02:00
|
|
|
sap->addDriver(item.m_rhsp, item.m_idx, flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
item.m_lhsp->v3fatalSrc("Unhandled DfgVertexSplice sub-type"); // LCOV_EXCL_LINE
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VISITORS
|
|
|
|
|
|
|
|
|
|
// Unhandled node
|
|
|
|
|
void visit(AstNode* nodep) override {
|
|
|
|
|
if (!m_foundUnhandled && m_converting) ++m_ctx.m_conv.nonRepUnknown;
|
|
|
|
|
m_foundUnhandled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Expressions - mostly auto generated, but a few special ones
|
|
|
|
|
void visit(AstVarRef* nodep) override {
|
|
|
|
|
UASSERT_OBJ(m_converting, nodep, "AstToDfg visit called without m_converting");
|
|
|
|
|
UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
|
|
|
|
|
if (unhandled(nodep)) return;
|
|
|
|
|
// This visit method is only called on RValues, where only read refs are supported
|
|
|
|
|
if (!nodep->access().isReadOnly() || !isSupported(nodep)) {
|
|
|
|
|
m_foundUnhandled = true;
|
|
|
|
|
++m_ctx.m_conv.nonRepVarRef;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Variable should have been bound before starting conversion
|
|
|
|
|
DfgVertex* const vtxp = getTarget(nodep)->user2u().template to<DfgVertexVar*>();
|
|
|
|
|
UASSERT_OBJ(vtxp, nodep, "Referenced variable has no associated DfgVertexVar");
|
|
|
|
|
nodep->user2p(vtxp);
|
|
|
|
|
}
|
|
|
|
|
void visit(AstConst* nodep) override {
|
|
|
|
|
UASSERT_OBJ(m_converting, nodep, "AstToDfg visit called without m_converting");
|
|
|
|
|
UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
|
|
|
|
|
if (unhandled(nodep)) return;
|
|
|
|
|
DfgVertex* const vtxp = make<DfgConst>(nodep->fileline(), nodep->num());
|
|
|
|
|
nodep->user2p(vtxp);
|
|
|
|
|
}
|
|
|
|
|
void visit(AstSel* nodep) override {
|
|
|
|
|
UASSERT_OBJ(m_converting, nodep, "AstToDfg visit called without m_converting");
|
|
|
|
|
UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
|
|
|
|
|
if (unhandled(nodep)) return;
|
|
|
|
|
|
|
|
|
|
iterate(nodep->fromp());
|
|
|
|
|
if (m_foundUnhandled) return;
|
|
|
|
|
|
|
|
|
|
FileLine* const flp = nodep->fileline();
|
|
|
|
|
DfgVertex* vtxp = nullptr;
|
|
|
|
|
if (const AstConst* const constp = VN_CAST(nodep->lsbp(), Const)) {
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgSel* const selp = make<DfgSel>(flp, V3Dfg::toDfgDType(nodep->dtypep()));
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
selp->fromp(nodep->fromp()->user2u().to<DfgVertex*>());
|
|
|
|
|
selp->lsb(constp->toUInt());
|
|
|
|
|
vtxp = selp;
|
|
|
|
|
} else {
|
|
|
|
|
iterate(nodep->lsbp());
|
|
|
|
|
if (m_foundUnhandled) return;
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgMux* const muxp = make<DfgMux>(flp, V3Dfg::toDfgDType(nodep->dtypep()));
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
muxp->fromp(nodep->fromp()->user2u().to<DfgVertex*>());
|
|
|
|
|
muxp->lsbp(nodep->lsbp()->user2u().to<DfgVertex*>());
|
|
|
|
|
vtxp = muxp;
|
|
|
|
|
}
|
|
|
|
|
nodep->user2p(vtxp);
|
|
|
|
|
}
|
|
|
|
|
// The rest of the visit methods for expressions are generated by 'astgen'
|
|
|
|
|
#include "V3Dfg__gen_ast_to_dfg.h"
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// PUBLIC METHODS
|
|
|
|
|
|
2025-09-02 17:50:40 +02:00
|
|
|
// Create temporay variable capable of holding the given type
|
|
|
|
|
DfgVertexVar* createTmp(DfgLogic& logic, FileLine* flp, AstNodeDType* dtypep,
|
|
|
|
|
const std::string& prefix, size_t tmpCount) {
|
|
|
|
|
const std::string name = m_dfg.makeUniqueName(prefix, tmpCount);
|
|
|
|
|
DfgVertexVar* const vtxp = m_dfg.makeNewVar(flp, name, dtypep, logic.scopep());
|
|
|
|
|
logic.synth().emplace_back(vtxp);
|
|
|
|
|
vtxp->varp()->isInternal(true);
|
|
|
|
|
vtxp->tmpForp(vtxp->nodep());
|
|
|
|
|
return vtxp;
|
|
|
|
|
}
|
|
|
|
|
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Create a new temporary variable capable of holding 'varp'
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexVar* createTmp(DfgLogic& logic, Variable* varp, const std::string& prefix) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
AstVar* const astVarp = T_Scoped ? reinterpret_cast<AstVarScope*>(varp)->varp()
|
|
|
|
|
: reinterpret_cast<AstVar*>(varp);
|
|
|
|
|
const std::string prfx = prefix + "_" + astVarp->name();
|
2025-09-02 17:50:40 +02:00
|
|
|
const std::string name = m_dfg.makeUniqueName(prfx, astVarp->user3Inc());
|
|
|
|
|
FileLine* const flp = astVarp->fileline();
|
|
|
|
|
AstNodeDType* const dtypep = V3Dfg::toDfgDType(astVarp->dtypep());
|
|
|
|
|
DfgVertexVar* const vtxp = m_dfg.makeNewVar(flp, name, dtypep, logic.scopep());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
logic.synth().emplace_back(vtxp);
|
|
|
|
|
vtxp->varp()->isInternal(true);
|
|
|
|
|
vtxp->tmpForp(varp);
|
|
|
|
|
return vtxp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert AstAssign to Dfg, return true if successful.
|
|
|
|
|
// Fills 'updates' with bindings for assigned variables.
|
|
|
|
|
bool convert(std::vector<std::pair<Variable*, DfgVertexVar*>>& updates, DfgLogic& vtx,
|
|
|
|
|
AstAssign* nodep) {
|
|
|
|
|
UASSERT_OBJ(updates.empty(), nodep, "'updates' should be empty");
|
|
|
|
|
VL_RESTORER(m_updatesp);
|
|
|
|
|
VL_RESTORER(m_logicp);
|
|
|
|
|
m_updatesp = &updates;
|
|
|
|
|
m_logicp = &vtx;
|
|
|
|
|
// Assignment with timing control shouldn't make it this far
|
|
|
|
|
UASSERT_OBJ(!nodep->timingControlp(), nodep, "Shouldn't make it this far");
|
|
|
|
|
// Convert it
|
|
|
|
|
++m_ctx.m_conv.inputAssignments;
|
|
|
|
|
AstNodeExpr* const lhsp = nodep->lhsp();
|
|
|
|
|
AstNodeExpr* const rhsp = nodep->rhsp();
|
|
|
|
|
// Check data types are compatible.
|
2025-09-02 17:50:40 +02:00
|
|
|
if (!V3Dfg::isSupported(lhsp->dtypep()) || !V3Dfg::isSupported(rhsp->dtypep())) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
++m_ctx.m_conv.nonRepDType;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// For now, only direct array assignment is supported (e.g. a = b, but not a = _ ? b : c)
|
|
|
|
|
if (VN_IS(rhsp->dtypep()->skipRefp(), UnpackArrayDType) && !VN_IS(rhsp, VarRef)) {
|
|
|
|
|
++m_ctx.m_conv.nonRepDType;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Widths should match at this point
|
|
|
|
|
UASSERT_OBJ(lhsp->width() == rhsp->width(), nodep, "Mismatched width reached DFG");
|
|
|
|
|
// Convert the RHS expression
|
|
|
|
|
DfgVertex* const rVtxp = convertRValue(rhsp);
|
|
|
|
|
if (!rVtxp) return false;
|
|
|
|
|
// Connect the RHS vertex to the LHS targets
|
|
|
|
|
const bool success = convertAssignment(nodep->fileline(), lhsp, rVtxp);
|
|
|
|
|
if (success) ++m_ctx.m_conv.representable;
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert RValue expression to Dfg. Returns nullptr if failed.
|
|
|
|
|
DfgVertex* convert(DfgLogic& vtx, AstNodeExpr* nodep) {
|
|
|
|
|
VL_RESTORER(m_logicp);
|
|
|
|
|
m_logicp = &vtx;
|
|
|
|
|
// Convert it
|
|
|
|
|
++m_ctx.m_conv.inputExpressions;
|
|
|
|
|
DfgVertex* const vtxp = convertRValue(nodep);
|
|
|
|
|
if (vtxp) ++m_ctx.m_conv.representable;
|
|
|
|
|
return vtxp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CONSTRUCTOR
|
|
|
|
|
AstToDfgConverter(DfgGraph& dfg, V3DfgSynthesisContext& ctx)
|
|
|
|
|
: m_dfg{dfg}
|
|
|
|
|
, m_ctx{ctx} {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// For debugging, we can stop synthesizing after a certain number of vertices.
|
|
|
|
|
// for this we need a global counter (inside the template makes multiple copies)
|
|
|
|
|
static size_t s_dfgSynthDebugCount = 0;
|
|
|
|
|
// The number of vertices we stop after can be passed in through the environment
|
|
|
|
|
// you can then use a bisection search over this value and look at the dumps
|
|
|
|
|
// produced with the lowest failing value
|
|
|
|
|
static const size_t s_dfgSynthDebugLimit
|
|
|
|
|
= std::stoull(V3Os::getenvStr("VERILATOR_DFG_SYNTH_DEBUG", "0"));
|
|
|
|
|
|
|
|
|
|
template <bool T_Scoped>
|
|
|
|
|
class AstToDfgSynthesize final {
|
|
|
|
|
// NODE STATE
|
|
|
|
|
// AstNodeExpr/AstVar/AstVarScope::user2p -> DfgVertex* for this Node
|
|
|
|
|
|
|
|
|
|
// TYPES
|
|
|
|
|
using Variable = std::conditional_t<T_Scoped, AstVarScope, AstVar>;
|
|
|
|
|
using SymTab = std::unordered_map<Variable*, DfgVertexVar*>;
|
|
|
|
|
|
|
|
|
|
// Represents a [potentially partial] driver of a variable
|
|
|
|
|
struct Driver final {
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertex* m_vtxp = nullptr; // Driving vertex
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
uint32_t m_lo = 0; // Low index of driven range (internal, not Verilog)
|
|
|
|
|
uint32_t m_hi = 0; // High index of driven range (internal, not Verilog)
|
2025-09-02 17:50:40 +02:00
|
|
|
FileLine* m_flp = nullptr; // Location of driver in source
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
Driver() = default;
|
2025-09-02 17:50:40 +02:00
|
|
|
Driver(DfgVertex* vtxp, uint32_t lo, FileLine* flp)
|
|
|
|
|
: m_vtxp{vtxp}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
, m_lo{lo}
|
|
|
|
|
, m_hi{lo + vtxp->size() - 1}
|
2025-09-02 17:50:40 +02:00
|
|
|
, m_flp{flp} {}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
operator bool() const { return m_vtxp != nullptr; }
|
|
|
|
|
|
|
|
|
|
bool operator<(const Driver& other) const {
|
|
|
|
|
if (m_lo != other.m_lo) return m_lo < other.m_lo;
|
|
|
|
|
if (m_hi != other.m_hi) return m_hi < other.m_hi;
|
|
|
|
|
return m_flp->operatorCompare(*other.m_flp) < 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator<=(const Driver& other) const { return !(other < *this); }
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// STATE - Persistent
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgGraph& m_dfg; // The graph being built
|
|
|
|
|
V3DfgSynthesisContext& m_ctx; // The context for stats
|
|
|
|
|
AstToDfgConverter<T_Scoped> m_converter; // The convert instance to use for each construct
|
2025-09-02 17:50:40 +02:00
|
|
|
size_t m_nBranchCond = 0; // Sequence numbers for temporaries
|
|
|
|
|
size_t m_nPathPred = 0; // Sequence numbers for temporaries
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// STATE - for current DfgLogic being synthesized
|
|
|
|
|
DfgLogic* m_logicp = nullptr; // Current logic vertex we are synthesizing
|
|
|
|
|
CfgBlockMap<SymTab> m_bbToISymTab; // Map from CfgBlock -> input symbol table
|
|
|
|
|
CfgBlockMap<SymTab> m_bbToOSymTab; // Map from CfgBlock -> output symbol table
|
2025-09-02 17:50:40 +02:00
|
|
|
CfgBlockMap<DfgVertexVar*> m_bbToCondp; // Map from CfgBlock -> terminating branch condition
|
|
|
|
|
CfgEdgeMap<DfgVertexVar*> m_edgeToPredicatep; // Map CfgGraphEdge -> path predicate to there
|
2025-08-25 14:47:45 +02:00
|
|
|
CfgDominatorTree m_domTree; // The dominator tree of the current CFG
|
|
|
|
|
|
|
|
|
|
// STATE - Some debug aid
|
|
|
|
|
// We stop after synthesizing s_dfgSynthDebugLimit vertices (if non-zero).
|
|
|
|
|
// This is the problematic logic (last one we synthesize), assuming a
|
|
|
|
|
// bisection search over s_dfgSynthDebugLimit.
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgLogic* m_debugLogicp = nullptr;
|
|
|
|
|
// Source (upstream) cone of outputs of m_debugLogicp
|
|
|
|
|
std::unique_ptr<std::unordered_set<const DfgVertex*>> m_debugOSrcConep{nullptr};
|
|
|
|
|
|
|
|
|
|
// METHODS
|
|
|
|
|
|
|
|
|
|
// Dump current graph for debugging ...
|
|
|
|
|
void debugDump(const char* name) {
|
|
|
|
|
// If we have the debugged logic, compute the vertices feeding its outputs
|
|
|
|
|
if (VL_UNLIKELY(m_debugLogicp)) {
|
|
|
|
|
std::vector<const DfgVertex*> outputs;
|
2025-09-02 17:50:40 +02:00
|
|
|
m_debugLogicp->foreachSink([&outputs](const DfgVertex& v) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
outputs.emplace_back(v.singleSink()->as<DfgVertexVar>());
|
2025-09-02 17:50:40 +02:00
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
m_debugOSrcConep = m_dfg.sourceCone(outputs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (VL_UNLIKELY(dumpDfgLevel() >= 9 || m_debugOSrcConep)) {
|
|
|
|
|
const auto label = m_ctx.prefix() + name;
|
|
|
|
|
m_dfg.dumpDotFilePrefixed(label);
|
|
|
|
|
if (m_debugOSrcConep) {
|
|
|
|
|
// Dump only the subgraph involving the inputs and outputs of the bad vertex
|
|
|
|
|
m_dfg.dumpDotFilePrefixed(label + "-min", [&](const DfgVertex& v) -> bool {
|
|
|
|
|
return m_debugOSrcConep->count(&v);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static AstVar* getAstVar(Variable* vp) {
|
|
|
|
|
// TODO: remove the useless reinterpret_casts when C++17 'if constexpr' actually works
|
|
|
|
|
if VL_CONSTEXPR_CXX17 (T_Scoped) {
|
|
|
|
|
return reinterpret_cast<AstVarScope*>(vp)->varp();
|
|
|
|
|
} else {
|
|
|
|
|
return reinterpret_cast<AstVar*>(vp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocate a new non-variable vertex, add it to the currently synthesized logic
|
|
|
|
|
template <typename Vertex, typename... Args>
|
|
|
|
|
Vertex* make(Args&&... args) {
|
|
|
|
|
static_assert(!std::is_base_of<DfgVertexVar, Vertex>::value, "Do not use for variables");
|
|
|
|
|
static_assert(std::is_base_of<DfgVertex, Vertex>::value, "'Vertex' must be a 'DfgVertex'");
|
|
|
|
|
Vertex* const vtxp = new Vertex{m_dfg, std::forward<Args>(args)...};
|
|
|
|
|
if (m_logicp) m_logicp->synth().emplace_back(vtxp);
|
|
|
|
|
return vtxp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gather all drivers of a resolved variable
|
2025-09-02 17:50:40 +02:00
|
|
|
static std::vector<Driver> gatherDrivers(DfgVertexSplice* vtxp) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Collect them all, check if they are sorted
|
|
|
|
|
std::vector<Driver> drivers;
|
2025-09-02 17:50:40 +02:00
|
|
|
drivers.reserve(vtxp->nInputs());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
bool sorted = true;
|
2025-09-02 17:50:40 +02:00
|
|
|
vtxp->foreachDriver([&](DfgVertex& src, uint32_t lo, FileLine* flp) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Collect the driver
|
2025-09-02 17:50:40 +02:00
|
|
|
drivers.emplace_back(&src, lo, flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Check if drivers are sorted - most often they are
|
|
|
|
|
const size_t n = drivers.size();
|
|
|
|
|
if (n >= 2 && drivers[n - 1] < drivers[n - 2]) sorted = false;
|
2025-09-02 17:50:40 +02:00
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Sort if unsorted
|
|
|
|
|
if (!sorted) std::stable_sort(drivers.begin(), drivers.end());
|
|
|
|
|
|
|
|
|
|
// Done
|
2025-09-02 17:50:40 +02:00
|
|
|
return drivers;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gather all synthesized drivers of an unresolved variable
|
2025-09-02 17:50:40 +02:00
|
|
|
static std::vector<Driver> gatherDriversUnresolved(DfgUnresolved* vtxp) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
std::vector<Driver> drivers;
|
2025-09-02 17:50:40 +02:00
|
|
|
drivers.reserve(vtxp->nInputs());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// For better locations in error reporting, we unpick concatenations
|
|
|
|
|
// which are sometimes introduced by combinint assignments in V3Const.
|
2025-09-02 17:50:40 +02:00
|
|
|
const std::function<void(DfgVertex*, uint32_t, FileLine*)> gather
|
|
|
|
|
= [&](DfgVertex* vtxp, uint32_t lo, FileLine* flp) -> void {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (DfgConcat* const concatp = vtxp->cast<DfgConcat>()) {
|
|
|
|
|
DfgVertex* const rhsp = concatp->rhsp();
|
2025-09-02 17:50:40 +02:00
|
|
|
gather(rhsp, lo, rhsp->fileline());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgVertex* const lhsp = concatp->lhsp();
|
2025-09-02 17:50:40 +02:00
|
|
|
gather(lhsp, lo + rhsp->width(), lhsp->fileline());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2025-09-02 17:50:40 +02:00
|
|
|
drivers.emplace_back(vtxp, lo, flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Gather all synthesized drivers
|
2025-09-02 17:50:40 +02:00
|
|
|
vtxp->foreachSource([&](DfgVertex& src) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Can ignore the original DfgLogic
|
2025-09-02 17:50:40 +02:00
|
|
|
if (src.is<DfgLogic>()) return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Synthesized drivers must be a splice at this point
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexSplice* const splicep = src.as<DfgVertexSplice>();
|
|
|
|
|
// Collect the driver
|
|
|
|
|
splicep->foreachDriver([&](DfgVertex& src, uint32_t lo, FileLine* flp) {
|
|
|
|
|
gather(&src, lo, flp);
|
|
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
2025-09-02 17:50:40 +02:00
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Sort the drivers
|
|
|
|
|
std::stable_sort(drivers.begin(), drivers.end());
|
|
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
return drivers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Given two drivers, combine the driven sub-ranges into the first one if
|
|
|
|
|
// possible. First bool returned indicates successfully combined and there
|
|
|
|
|
// are no multi-driven bits. Second bool returned indicates we warned
|
|
|
|
|
// already about multi-driven bits.
|
|
|
|
|
std::pair<bool, bool> combineDrivers(DfgVertexVar& var, const std::string& sub, //
|
|
|
|
|
Driver& a, const Driver& b) {
|
|
|
|
|
// We can only combine array drivers ...
|
|
|
|
|
if (a.m_vtxp->isPacked()) return {false, false};
|
|
|
|
|
// ... that both drive a single element ...
|
|
|
|
|
if (a.m_lo != b.m_lo) return {false, false};
|
|
|
|
|
const DfgUnitArray* const aUap = a.m_vtxp->template cast<DfgUnitArray>();
|
|
|
|
|
if (!aUap) return {false, false};
|
|
|
|
|
const DfgUnitArray* const bUap = b.m_vtxp->template cast<DfgUnitArray>();
|
|
|
|
|
if (!bUap) return {false, false};
|
|
|
|
|
// ... and are themeselves partial
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgSplicePacked* const aSp = aUap->srcp()->template cast<DfgSplicePacked>();
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (!aSp) return {false, false};
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgSplicePacked* const bSp = bUap->srcp()->template cast<DfgSplicePacked>();
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (!bSp) return {false, false};
|
|
|
|
|
UASSERT_OBJ(aSp->dtypep()->isSame(bSp->dtypep()), &var, "DTypes should match");
|
|
|
|
|
|
|
|
|
|
// Gather drivers of a
|
2025-09-02 17:50:40 +02:00
|
|
|
std::vector<Driver> aDrivers = gatherDrivers(aSp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Gather drivers of b
|
2025-09-02 17:50:40 +02:00
|
|
|
std::vector<Driver> bDrivers = gatherDrivers(bSp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Merge them
|
|
|
|
|
std::vector<Driver> abDrivers;
|
|
|
|
|
abDrivers.reserve(aDrivers.size() + bDrivers.size());
|
|
|
|
|
std::merge( //
|
|
|
|
|
aDrivers.begin(), aDrivers.end(), //
|
|
|
|
|
bDrivers.begin(), bDrivers.end(), //
|
|
|
|
|
std::back_inserter(abDrivers) //
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Attempt to resolve them
|
|
|
|
|
if (!normalizeDrivers(var, abDrivers, sub + "[" + std::to_string(a.m_lo) + "]")) {
|
|
|
|
|
return {false, true};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Successfully resolved. Needs a new splice and unit.
|
|
|
|
|
FileLine* const flp = var.fileline();
|
|
|
|
|
DfgSplicePacked* const splicep = make<DfgSplicePacked>(flp, aSp->dtypep());
|
2025-09-02 17:50:40 +02:00
|
|
|
for (const Driver& d : abDrivers) splicep->addDriver(d.m_vtxp, d.m_lo, d.m_flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgUnitArray* const uap = make<DfgUnitArray>(flp, aUap->dtypep());
|
|
|
|
|
uap->srcp(splicep);
|
|
|
|
|
a.m_vtxp = uap;
|
|
|
|
|
return {true, false};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Combine and coalesce the given drivers.
|
|
|
|
|
// Returns true iff no multi-driven bits are present.
|
|
|
|
|
bool normalizeDrivers(DfgVertexVar& var, std::vector<Driver>& drivers,
|
|
|
|
|
const std::string& sub = "") {
|
|
|
|
|
if (drivers.empty()) return true;
|
|
|
|
|
|
|
|
|
|
// What type of values are we combining
|
|
|
|
|
const bool isPacked = drivers[0].m_vtxp->isPacked();
|
|
|
|
|
|
|
|
|
|
// Found a multidriven part ?
|
|
|
|
|
bool multiDriven = false;
|
|
|
|
|
|
|
|
|
|
// Iterate through the sorted drivers. Index 'i' is the driver we are
|
|
|
|
|
// resolving driver 'j' agains, and if required, we merge 'j' into 'i'.
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
for (size_t j = 1; j < drivers.size();) {
|
|
|
|
|
UASSERT_OBJ(i < j, &var, "Invalid iteration");
|
|
|
|
|
Driver& iD = drivers[i];
|
|
|
|
|
Driver& jD = drivers[j];
|
|
|
|
|
|
|
|
|
|
// If 'j' was moved, step forward
|
|
|
|
|
if (!jD) {
|
|
|
|
|
++j;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// If 'i' was moved, move 'j' in it's place
|
|
|
|
|
if (!iD) {
|
|
|
|
|
iD = jD;
|
|
|
|
|
jD = Driver{};
|
|
|
|
|
++j;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We have 2 valid drivers now
|
|
|
|
|
UASSERT_OBJ(iD <= jD, &var, "Should always be sorted");
|
|
|
|
|
UASSERT_OBJ(jD.m_vtxp->isPacked() == isPacked, &var, "Mixed type drivers");
|
|
|
|
|
|
|
|
|
|
// If no overlap, consider next pair
|
|
|
|
|
if (iD.m_hi < jD.m_lo) {
|
|
|
|
|
++i;
|
|
|
|
|
if (i == j) ++j;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// There is an overlap. Attempt to combine them.
|
|
|
|
|
bool combined = false;
|
|
|
|
|
bool warned = false;
|
|
|
|
|
std::tie(combined, warned) = combineDrivers(var, sub, iD, jD);
|
|
|
|
|
|
|
|
|
|
// If sucessfully combined, 'j' is no longer needed, it was combined into 'i'
|
|
|
|
|
if (combined) {
|
|
|
|
|
jD = Driver{};
|
|
|
|
|
++j;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Found overlap that cannot be resolved
|
|
|
|
|
multiDriven = true;
|
|
|
|
|
// Compare next driver
|
|
|
|
|
++j;
|
|
|
|
|
|
|
|
|
|
// Do not warn again if we warned during 'combineDrivers'
|
|
|
|
|
if (warned) continue;
|
|
|
|
|
|
|
|
|
|
// The variable to warn on
|
|
|
|
|
AstNode* const nodep = var.tmpForp() ? var.tmpForp() : var.nodep();
|
|
|
|
|
Variable* const varp = reinterpret_cast<Variable*>(nodep);
|
|
|
|
|
|
|
|
|
|
// Loop index often abused, so suppress
|
|
|
|
|
if (getAstVar(varp)->isUsedLoopIdx()) continue;
|
|
|
|
|
|
|
|
|
|
// Warn the user now
|
|
|
|
|
const std::string lo = std::to_string(jD.m_lo);
|
|
|
|
|
const std::string hi = std::to_string(std::min(iD.m_hi, jD.m_hi));
|
|
|
|
|
const std::string kind = isPacked ? "Bit" : "Element";
|
|
|
|
|
const std::string part = hi == lo ? (" [" + lo + "]") : ("s [" + hi + ":" + lo + "]");
|
|
|
|
|
|
|
|
|
|
varp->v3warn( //
|
|
|
|
|
MULTIDRIVEN, //
|
|
|
|
|
kind << part << " of signal '" << varp->prettyName() << sub << "'"
|
|
|
|
|
<< " have multiple combinational drivers."
|
|
|
|
|
<< " This can cause performance degradation.\n"
|
|
|
|
|
<< iD.m_flp->warnOther() << "... Location of offending driver\n"
|
|
|
|
|
<< iD.m_flp->warnContextPrimary() << '\n'
|
|
|
|
|
<< jD.m_flp->warnOther() << "... Location of offending driver\n"
|
|
|
|
|
<< jD.m_flp->warnContextSecondary());
|
|
|
|
|
}
|
|
|
|
|
// Rightsize vector
|
|
|
|
|
drivers.resize(i + 1);
|
|
|
|
|
|
|
|
|
|
// Coalesce adjacent drivers
|
|
|
|
|
if (!multiDriven && isPacked) coalesceDrivers(drivers);
|
|
|
|
|
|
|
|
|
|
return !multiDriven;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Coalesce adjacent drivers into single ones
|
|
|
|
|
void coalesceDrivers(std::vector<Driver>& drivers) {
|
|
|
|
|
UASSERT(!drivers.empty(), "Can't coalesce 0 drivers");
|
|
|
|
|
UASSERT_OBJ(drivers[0].m_vtxp->isPacked(), drivers[0].m_vtxp, "Can only coalesce packed");
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
for (size_t j = 1; j < drivers.size();) {
|
|
|
|
|
UASSERT(i < j, "Invalid iteration");
|
|
|
|
|
Driver& iD = drivers[i];
|
|
|
|
|
Driver& jD = drivers[j];
|
|
|
|
|
|
|
|
|
|
// If 'j' was moved, step forward
|
|
|
|
|
if (!jD) {
|
|
|
|
|
++j;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// If 'i' was moved, move 'j' in it's place
|
|
|
|
|
if (!iD) {
|
|
|
|
|
iD = jD;
|
|
|
|
|
jD = Driver{};
|
|
|
|
|
++j;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We have 2 valid drivers now
|
|
|
|
|
UASSERT(iD <= jD, "Should always be sorted");
|
|
|
|
|
|
|
|
|
|
// If not adjacent, move on
|
|
|
|
|
if (iD.m_hi + 1 != jD.m_lo) {
|
|
|
|
|
++i;
|
|
|
|
|
if (i == j) ++j;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Coalesce Adjacent ranges,
|
2025-09-02 17:50:40 +02:00
|
|
|
const auto dtypep = V3Dfg::dtypePacked(iD.m_vtxp->width() + jD.m_vtxp->width());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgConcat* const concatp = make<DfgConcat>(iD.m_flp, dtypep);
|
|
|
|
|
concatp->rhsp(iD.m_vtxp);
|
|
|
|
|
concatp->lhsp(jD.m_vtxp);
|
|
|
|
|
iD.m_vtxp = concatp;
|
|
|
|
|
iD.m_hi = jD.m_hi;
|
|
|
|
|
jD = Driver{};
|
|
|
|
|
|
|
|
|
|
// Consider next driver
|
|
|
|
|
++j;
|
|
|
|
|
}
|
|
|
|
|
// Rightsize vector
|
|
|
|
|
drivers.resize(i + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make a new splice with the given drivers
|
|
|
|
|
DfgVertexSplice* makeSplice(DfgVertexVar& var, const std::vector<Driver>& newDrivers) {
|
|
|
|
|
UASSERT_OBJ(!newDrivers.empty(), &var, "'makeSplice' called with no new drivers");
|
|
|
|
|
// Create new driver
|
|
|
|
|
DfgVertexSplice* splicep = nullptr;
|
|
|
|
|
if (var.is<DfgVarPacked>()) {
|
|
|
|
|
splicep = make<DfgSplicePacked>(var.fileline(), var.dtypep());
|
|
|
|
|
} else if (var.is<DfgVarArray>()) {
|
|
|
|
|
splicep = make<DfgSpliceArray>(var.fileline(), var.dtypep());
|
|
|
|
|
} else {
|
|
|
|
|
var.v3fatalSrc("Unhandled DfgVertexVar sub-type"); // LCOV_EXCL_LINE
|
|
|
|
|
}
|
2025-09-02 17:50:40 +02:00
|
|
|
for (const Driver& d : newDrivers) splicep->addDriver(d.m_vtxp, d.m_lo, d.m_flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
return splicep;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If any written variables are forced or otherwise udpated from outside,
|
2025-08-26 00:47:08 +02:00
|
|
|
// we generally cannot synthesize the construct, as we will likely need to
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// introduce intermediate values that would not be updated.
|
|
|
|
|
static bool hasExternallyWrittenVariable(DfgLogic& vtx) {
|
2025-09-02 17:50:40 +02:00
|
|
|
return vtx.foreachSink([&](const DfgVertex& sink) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// 'sink' is a splice (for which 'vtxp' is an unresolved driver),
|
|
|
|
|
// which drives the target variable.
|
|
|
|
|
const DfgVertexVar* varp = sink.singleSink()->as<DfgVertexVar>();
|
|
|
|
|
if (varp->hasXRefs()) return true; // Target of a hierarchical reference
|
|
|
|
|
const AstVar* const astVarp = varp->varp();
|
|
|
|
|
if (astVarp->isForced()) return true; // Forced
|
|
|
|
|
if (astVarp->isSigPublic()) return true; // Public
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// Initialzie input symbol table of entry CfgBlock
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
void initializeEntrySymbolTable(SymTab& iSymTab) {
|
2025-09-02 17:50:40 +02:00
|
|
|
m_logicp->foreachSource([&](DfgVertex& src) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgVertexVar* const vvp = src.as<DfgVertexVar>();
|
|
|
|
|
Variable* const varp = reinterpret_cast<Variable*>(vvp->nodep());
|
|
|
|
|
iSymTab[varp] = vvp;
|
2025-09-02 17:50:40 +02:00
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Join variable drivers across a control flow confluence (insert muxes ...)
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexVar* joinDrivers(Variable* varp, DfgVertexVar* predicatep, //
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgVertexVar* thenp, DfgVertexVar* elsep) {
|
|
|
|
|
AstNode* const thenVarp = thenp->tmpForp() ? thenp->tmpForp() : thenp->nodep();
|
|
|
|
|
AstNode* const elseVarp = elsep->tmpForp() ? elsep->tmpForp() : elsep->nodep();
|
|
|
|
|
UASSERT_OBJ(thenVarp == elseVarp, varp, "Attempting to join unrelated variables");
|
|
|
|
|
|
|
|
|
|
// If both bindings are the the same (variable not updated through either path),
|
2025-08-26 00:47:08 +02:00
|
|
|
// then there is nothing to do, can use the same binding
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (thenp == elsep) return thenp;
|
|
|
|
|
|
|
|
|
|
// We can't join the input variable just yet, so bail
|
|
|
|
|
if (thenp->nodep() == varp) {
|
|
|
|
|
++m_ctx.m_synt.nonSynJoinInput;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (elsep->nodep() == varp) {
|
|
|
|
|
++m_ctx.m_synt.nonSynJoinInput;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Can't do arrays yet
|
|
|
|
|
if (VN_IS(thenp->dtypep(), UnpackArrayDType)) {
|
|
|
|
|
++m_ctx.m_synt.nonSynArray;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gather drivers of 'thenp' - only if 'thenp' is not an input to the synthesized block
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertex* const tDefaultp = thenp->defaultp();
|
|
|
|
|
std::vector<Driver> tDrivers = gatherDrivers(thenp->srcp()->as<DfgVertexSplice>());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Gather drivers of 'elsep' - only if 'thenp' is not an input to the synthesized block
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertex* const eDefaultp = elsep->defaultp();
|
|
|
|
|
std::vector<Driver> eDrivers = gatherDrivers(elsep->srcp()->as<DfgVertexSplice>());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Default drivers should be the same or not present on either
|
|
|
|
|
UASSERT_OBJ(tDefaultp == eDefaultp, varp, "Different default drivers");
|
|
|
|
|
|
|
|
|
|
// Location to use for the join vertices
|
|
|
|
|
FileLine* const flp = predicatep->fileline();
|
|
|
|
|
|
|
|
|
|
// Create a fresh temporary for the joined value
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexVar* const joinp = m_converter.createTmp(*m_logicp, varp, "SynthJoin");
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgVertexSplice* const joinSplicep = make<DfgSplicePacked>(flp, joinp->dtypep());
|
|
|
|
|
joinp->srcp(joinSplicep);
|
|
|
|
|
|
|
|
|
|
// If both paths are fully driven, just create a simple conditional
|
|
|
|
|
if (tDrivers.size() == 1 //
|
|
|
|
|
&& tDrivers[0].m_lo == 0 //
|
|
|
|
|
&& tDrivers[0].m_hi == thenp->width() - 1 //
|
|
|
|
|
&& eDrivers.size() == 1 //
|
|
|
|
|
&& eDrivers[0].m_lo == 0 //
|
|
|
|
|
&& eDrivers[0].m_hi == elsep->width() - 1) {
|
|
|
|
|
UASSERT_OBJ(!tDefaultp, varp, "Fully driven variable have default driver");
|
|
|
|
|
|
|
|
|
|
DfgCond* const condp = make<DfgCond>(flp, joinp->dtypep());
|
|
|
|
|
condp->condp(predicatep);
|
|
|
|
|
condp->thenp(thenp);
|
|
|
|
|
condp->elsep(elsep);
|
2025-09-02 17:50:40 +02:00
|
|
|
joinSplicep->addDriver(condp, 0, tDrivers[0].m_flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
return joinp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise we need to merge them part by part
|
|
|
|
|
|
|
|
|
|
// If different bits are driven, then some might not have been assigned.. Latch?
|
|
|
|
|
if (tDrivers.size() != eDrivers.size()) {
|
|
|
|
|
++m_ctx.m_synt.nonSynLatch;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < tDrivers.size(); ++i) {
|
|
|
|
|
const Driver& tDriver = tDrivers[i];
|
|
|
|
|
const Driver& eDriver = eDrivers[i];
|
|
|
|
|
// If different bits are driven, then some might not have been assigned.. Latch?
|
|
|
|
|
if (tDriver.m_lo != eDriver.m_lo || tDriver.m_hi != eDriver.m_hi) {
|
|
|
|
|
++m_ctx.m_synt.nonSynLatch;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-02 17:50:40 +02:00
|
|
|
AstNodeDType* const dtypep = V3Dfg::dtypePacked(tDriver.m_hi - tDriver.m_lo + 1);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgCond* const condp = make<DfgCond>(flp, dtypep);
|
|
|
|
|
condp->condp(predicatep);
|
|
|
|
|
|
|
|
|
|
// We actally need to select the bits from the joined variables, not use the drivers
|
|
|
|
|
DfgSel* const thenSelp = make<DfgSel>(flp, tDriver.m_vtxp->dtypep());
|
|
|
|
|
thenSelp->lsb(tDriver.m_lo);
|
|
|
|
|
thenSelp->fromp(thenp);
|
|
|
|
|
condp->thenp(thenSelp);
|
|
|
|
|
|
|
|
|
|
// Same for the 'else' part
|
|
|
|
|
DfgSel* const elseSelp = make<DfgSel>(flp, eDriver.m_vtxp->dtypep());
|
|
|
|
|
elseSelp->lsb(eDriver.m_lo);
|
|
|
|
|
elseSelp->fromp(elsep);
|
|
|
|
|
condp->elsep(elseSelp);
|
|
|
|
|
|
|
|
|
|
// Add it as a driver to the join
|
2025-09-02 17:50:40 +02:00
|
|
|
joinSplicep->addDriver(condp, tDriver.m_lo, tDriver.m_flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there was a default driver, add it to te join
|
2025-09-02 17:50:40 +02:00
|
|
|
if (tDefaultp) joinp->defaultp(tDefaultp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
return joinp;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// Merge 'thenSymTab' into 'elseSymTab' using the given predicate to join values
|
2025-09-02 17:50:40 +02:00
|
|
|
bool joinSymbolTables(SymTab& elseSymTab, DfgVertexVar* predicatep, const SymTab& thenSymTab) {
|
2025-08-25 14:47:45 +02:00
|
|
|
// Give up if something is not assigned on all paths ... Latch?
|
|
|
|
|
if (thenSymTab.size() != elseSymTab.size()) {
|
|
|
|
|
++m_ctx.m_synt.nonSynLatch;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Join each symbol
|
|
|
|
|
for (std::pair<Variable* const, DfgVertexVar*>& pair : elseSymTab) {
|
|
|
|
|
Variable* const varp = pair.first;
|
|
|
|
|
// Find same variable on the else path
|
|
|
|
|
auto it = thenSymTab.find(varp);
|
|
|
|
|
// Give up if something is not assigned on all paths ... Latch?
|
|
|
|
|
if (it == thenSymTab.end()) {
|
|
|
|
|
++m_ctx.m_synt.nonSynLatch;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Join paths with the predicate
|
|
|
|
|
DfgVertexVar* const thenp = it->second;
|
|
|
|
|
DfgVertexVar* const elsep = pair.second;
|
|
|
|
|
DfgVertexVar* const newp = joinDrivers(varp, predicatep, thenp, elsep);
|
|
|
|
|
if (!newp) return false;
|
|
|
|
|
pair.second = newp;
|
|
|
|
|
}
|
|
|
|
|
// Done
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Given two joining control flow edges, compute how to join their symbols.
|
|
|
|
|
// Returns the predicaete to join over, and the 'then' and 'else' blocks.
|
2025-09-02 17:50:40 +02:00
|
|
|
std::tuple<DfgVertexVar*, const CfgBlock*, const CfgBlock*> //
|
2025-08-25 14:47:45 +02:00
|
|
|
howToJoin(const CfgEdge* const ap, const CfgEdge* const bp) {
|
|
|
|
|
// Find the closest common dominator of the two paths
|
|
|
|
|
const CfgBlock* const domp = m_domTree.closestCommonDominator(ap->srcp(), bp->srcp());
|
|
|
|
|
// These paths join here, so 'domp' must be a branch, otherwise it's not the closest
|
|
|
|
|
UASSERT_OBJ(domp->isBranch(), domp, "closestCommonDominator is not a branch");
|
|
|
|
|
|
|
|
|
|
// The branches of the common dominator
|
|
|
|
|
const CfgEdge* const takenEdgep = domp->takenEdgep();
|
|
|
|
|
const CfgEdge* const untknEdgep = domp->untknEdgep();
|
|
|
|
|
|
|
|
|
|
// We check if the taken branch dominates the path to either blocks,
|
|
|
|
|
// and if the untaken branch dominates the path to the other block.
|
|
|
|
|
// If so, we can use the branch condition as predicate, otherwise
|
|
|
|
|
// we must use the path predicate as there are ways to get from one
|
|
|
|
|
// branch of the dominator to the other. We need to be careful if
|
|
|
|
|
// either branches are directly to the join block. This is fine,
|
|
|
|
|
// it's as if there was an empty block on that critical edge which
|
|
|
|
|
// is dominated by that path.
|
|
|
|
|
|
|
|
|
|
if (takenEdgep == ap || m_domTree.dominates(takenEdgep->dstp(), ap->srcp())) {
|
|
|
|
|
if (untknEdgep == bp || m_domTree.dominates(untknEdgep->dstp(), bp->srcp())) {
|
|
|
|
|
// Taken path dominates 'ap' and untaken dominates 'bp', use the branch condition
|
|
|
|
|
++m_ctx.m_synt.joinUsingBranchCondition;
|
|
|
|
|
return std::make_tuple(m_bbToCondp[domp], ap->srcp(), bp->srcp());
|
|
|
|
|
}
|
|
|
|
|
} else if (takenEdgep == bp || m_domTree.dominates(takenEdgep->dstp(), bp->srcp())) {
|
|
|
|
|
if (untknEdgep == ap || m_domTree.dominates(untknEdgep->dstp(), ap->srcp())) {
|
|
|
|
|
// Taken path dominates 'bp' and untaken dominates 'ap', use the branch condition
|
|
|
|
|
++m_ctx.m_synt.joinUsingBranchCondition;
|
|
|
|
|
return std::make_tuple(m_bbToCondp[domp], bp->srcp(), ap->srcp());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The branches don't dominate the joined blocks, must use the path predicate
|
|
|
|
|
++m_ctx.m_synt.joinUsingPathPredicate;
|
|
|
|
|
|
|
|
|
|
// TODO: We could do better here: use the path predicate of the closest
|
|
|
|
|
// cominating blocks, pick the one from the lower rank, etc, but this
|
|
|
|
|
// generic case is very rare, most synthesizable logic has
|
|
|
|
|
// series-parallel CFGs which are covered by the earlier cases.
|
|
|
|
|
return std::make_tuple(m_edgeToPredicatep[ap], ap->srcp(), bp->srcp());
|
|
|
|
|
}
|
|
|
|
|
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Combine the output symbol tables of the predecessors of the given
|
2025-08-25 14:47:45 +02:00
|
|
|
// block to compute the input symtol table for the given block.
|
|
|
|
|
bool createInputSymbolTable(const CfgBlock& bb) {
|
|
|
|
|
// The input symbol table of the given block, we are computing it now
|
|
|
|
|
SymTab& joined = m_bbToISymTab[bb];
|
|
|
|
|
|
|
|
|
|
// Input symbol table of entry block is special
|
|
|
|
|
if (bb.isEnter()) {
|
|
|
|
|
initializeEntrySymbolTable(joined);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// Current input symbol table should be empty, we will fill it in here
|
|
|
|
|
UASSERT(joined.empty(), "Unprocessed input symbol table should be empty");
|
|
|
|
|
|
|
|
|
|
// Fast path if there is only one predecessor - TODO: use less copying
|
|
|
|
|
if (!bb.isJoin()) {
|
|
|
|
|
joined = m_bbToOSymTab[bb.firstPredecessorp()];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We also have a simpler job if there are 2 predecessors
|
|
|
|
|
if (bb.isTwoWayJoin()) {
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexVar* predicatep = nullptr;
|
2025-08-25 14:47:45 +02:00
|
|
|
const CfgBlock* thenp = nullptr;
|
|
|
|
|
const CfgBlock* elsep = nullptr;
|
|
|
|
|
std::tie(predicatep, thenp, elsep)
|
|
|
|
|
= howToJoin(bb.firstPredecessorEdgep(), bb.lastPredecessorEdgep());
|
|
|
|
|
// Copy from else
|
|
|
|
|
joined = m_bbToOSymTab[elsep];
|
|
|
|
|
// Join with then
|
|
|
|
|
return joinSymbolTables(joined, predicatep, m_bbToOSymTab[*thenp]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// General hard way
|
|
|
|
|
|
|
|
|
|
// Gather predecessors
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
struct Predecessor final {
|
2025-08-25 14:47:45 +02:00
|
|
|
const CfgBlock* m_bbp; // Predeccessor block
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexVar* m_predicatep; // Predicate predecessor reached this block with
|
2025-08-25 14:47:45 +02:00
|
|
|
const SymTab* m_oSymTabp; // Output symbol table or predecessor
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
Predecessor() = delete;
|
2025-09-02 17:50:40 +02:00
|
|
|
Predecessor(const CfgBlock* bbp, DfgVertexVar* predicatep, const SymTab* oSymTabp)
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
: m_bbp{bbp}
|
2025-08-25 14:47:45 +02:00
|
|
|
, m_predicatep{predicatep}
|
|
|
|
|
, m_oSymTabp{oSymTabp} {}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const std::vector<Predecessor> predecessors = [&]() {
|
|
|
|
|
std::vector<Predecessor> res;
|
|
|
|
|
for (const V3GraphEdge& edge : bb.inEdges()) {
|
2025-08-25 14:47:45 +02:00
|
|
|
const CfgEdge& cfgEdge = static_cast<const CfgEdge&>(edge);
|
|
|
|
|
const CfgBlock* const predecessorp = cfgEdge.srcp();
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexVar* const predicatep = m_edgeToPredicatep[cfgEdge];
|
2025-08-25 14:47:45 +02:00
|
|
|
const SymTab* const oSymTabp = &m_bbToOSymTab[predecessorp];
|
|
|
|
|
res.emplace_back(predecessorp, predicatep, oSymTabp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
2025-08-25 14:47:45 +02:00
|
|
|
// Sort predecessors reverse topologically. This way earlier blocks
|
|
|
|
|
// will come after later blocks, and the entry block is last if present.
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
std::sort(res.begin(), res.end(), [](const Predecessor& a, const Predecessor& b) { //
|
2025-08-25 14:47:45 +02:00
|
|
|
return *a.m_bbp > *b.m_bbp;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
return res;
|
|
|
|
|
}();
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// Start by copying the bindings from the frist predecessor
|
|
|
|
|
joined = *predecessors[0].m_oSymTabp;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Join over all other predecessors
|
|
|
|
|
for (size_t i = 1; i < predecessors.size(); ++i) {
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexVar* const predicatep = predecessors[i].m_predicatep;
|
2025-08-25 14:47:45 +02:00
|
|
|
const SymTab& oSymTab = *predecessors[i].m_oSymTabp;
|
|
|
|
|
if (!joinSymbolTables(joined, predicatep, oSymTab)) return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-02 17:50:40 +02:00
|
|
|
std::vector<Driver> computePropagatedDrivers(const std::vector<Driver>& newDrivers,
|
|
|
|
|
DfgVertexVar* oldp) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Gather drivers of 'oldp' - they are in incresing range order with no overlaps
|
2025-09-02 17:50:40 +02:00
|
|
|
std::vector<Driver> oldDrivers = gatherDrivers(oldp->srcp()->as<DfgVertexSplice>());
|
|
|
|
|
UASSERT_OBJ(!oldDrivers.empty(), oldp, "Should have a proper driver");
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Additional drivers of 'newp' propagated from 'oldp'
|
2025-09-02 17:50:40 +02:00
|
|
|
std::vector<Driver> propagatedDrivers;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Add bits between 'msb' and 'lsb' from 'oldp' to 'pDrivers'
|
2025-09-02 17:50:40 +02:00
|
|
|
const auto addOldDriver = [&](FileLine* const flp, uint32_t msb, uint32_t lsb) {
|
|
|
|
|
UASSERT_OBJ(propagatedDrivers.empty() || lsb > propagatedDrivers.back().m_hi, flp,
|
|
|
|
|
"Drivers should be in ascending order");
|
|
|
|
|
DfgSel* const selp = make<DfgSel>(flp, V3Dfg::dtypePacked(msb - lsb + 1));
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
selp->lsb(lsb);
|
|
|
|
|
selp->fromp(oldp);
|
2025-09-02 17:50:40 +02:00
|
|
|
propagatedDrivers.emplace_back(selp, lsb, flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Incorporate old drivers
|
2025-09-02 17:50:40 +02:00
|
|
|
for (const Driver& oDriver : oldDrivers) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
FileLine* const flp = oDriver.m_flp;
|
|
|
|
|
// Range to consider inserting, we will adjust oldLo as we process drivers
|
|
|
|
|
uint32_t oldLo = oDriver.m_lo;
|
|
|
|
|
const uint32_t oldHi = oDriver.m_hi;
|
|
|
|
|
|
|
|
|
|
// Loop for now, can move to bisection search if this is a problem, shouldn't be ...
|
2025-09-02 17:50:40 +02:00
|
|
|
for (const Driver& nDriver : newDrivers) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
UASSERT_OBJ(oldHi >= oldLo, flp, "Should have stopped iteration");
|
|
|
|
|
// If new driver is entirely below old driver, move on to
|
|
|
|
|
if (nDriver.m_hi < oldLo) continue;
|
|
|
|
|
// If new driver is entirely above old driver, we can stop
|
|
|
|
|
if (oldHi < nDriver.m_lo) break;
|
|
|
|
|
|
|
|
|
|
// There is an overlap between 'oDriver' and 'nDriver'.
|
|
|
|
|
// Insert the low bits and adjust the insertion range.
|
|
|
|
|
// The rest will take care of itself on subsequent iterations.
|
2025-09-02 17:50:40 +02:00
|
|
|
if (oldLo < nDriver.m_lo) addOldDriver(flp, nDriver.m_lo - 1, oldLo);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
oldLo = nDriver.m_hi + 1;
|
|
|
|
|
|
|
|
|
|
// Stop if no more bits remaining in the old driver
|
|
|
|
|
if (oldLo > oldHi) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Insert remaining bits if any
|
2025-09-02 17:50:40 +02:00
|
|
|
if (oldHi >= oldLo) addOldDriver(flp, oldHi, oldLo);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-09-02 17:50:40 +02:00
|
|
|
return propagatedDrivers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Given the drivers of a variable after converting a single statement
|
|
|
|
|
// 'newp', add drivers from 'oldp' that were not reassigned be drivers
|
|
|
|
|
// in newp. This computes the total result of all previous assignments.
|
|
|
|
|
bool incorporatePreviousValue(Variable* varp, DfgVertexVar* newp, DfgVertexVar* oldp) {
|
|
|
|
|
UASSERT_OBJ(newp->srcp(), varp, "Assigned variable has no driver");
|
|
|
|
|
|
|
|
|
|
// Easy if there is no old value...
|
|
|
|
|
if (!oldp) return true;
|
|
|
|
|
|
|
|
|
|
// New driver was not yet coalesced, so should always be a splice
|
|
|
|
|
DfgVertexSplice* const nSplicep = newp->srcp()->as<DfgVertexSplice>();
|
|
|
|
|
|
|
|
|
|
// If the old value is the real variable we just computed the new value for,
|
|
|
|
|
// then it is the circular feedback into the synthesized block, add it as default driver.
|
|
|
|
|
if (oldp->nodep() == varp) {
|
|
|
|
|
if (!nSplicep->wholep()) newp->defaultp(oldp);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UASSERT_OBJ(oldp->srcp(), varp, "Previously assigned variable has no driver");
|
|
|
|
|
|
|
|
|
|
// Can't do arrays yet
|
|
|
|
|
if (VN_IS(newp->dtypep(), UnpackArrayDType)) {
|
|
|
|
|
++m_ctx.m_synt.nonSynArray;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gather drivers of 'newp' - they are in incresing range order with no overlaps
|
|
|
|
|
UASSERT_OBJ(!newp->defaultp(), newp, "Converted value should not have default");
|
|
|
|
|
std::vector<Driver> nDrivers = gatherDrivers(newp->srcp()->as<DfgVertexSplice>());
|
|
|
|
|
UASSERT_OBJ(!nDrivers.empty(), newp, "Should have a proper driver");
|
|
|
|
|
|
|
|
|
|
// Additional drivers of 'newp' propagated from 'oldp'
|
|
|
|
|
std::vector<Driver> pDrivers = computePropagatedDrivers(nDrivers, oldp);
|
|
|
|
|
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (!pDrivers.empty()) {
|
2025-09-02 17:50:40 +02:00
|
|
|
// Need to merge propagated sources, so reset the splice
|
|
|
|
|
nSplicep->resetDrivers();
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Merge drivers - they are both sorted and non-overlapping
|
|
|
|
|
std::vector<Driver> drivers;
|
|
|
|
|
drivers.reserve(nDrivers.size() + pDrivers.size());
|
|
|
|
|
std::merge(nDrivers.begin(), nDrivers.end(), pDrivers.begin(), pDrivers.end(),
|
|
|
|
|
std::back_inserter(drivers));
|
|
|
|
|
// Coalesce adjacent ranges
|
|
|
|
|
coalesceDrivers(drivers);
|
|
|
|
|
// Reinsert drivers in order
|
2025-09-02 17:50:40 +02:00
|
|
|
for (const Driver& d : drivers) nSplicep->addDriver(d.m_vtxp, d.m_lo, d.m_flp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the old had a default, add to the new one too, unless redundant
|
2025-09-02 17:50:40 +02:00
|
|
|
if (oldp->defaultp() && !nSplicep->wholep()) newp->defaultp(oldp->defaultp());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Done
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthesize the given statements with the given input symbol table.
|
2025-08-25 14:47:45 +02:00
|
|
|
// Returns true if successfolly synthesized.
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Populates the given output symbol table.
|
|
|
|
|
// Populates the given reference with the condition of the terminator branch, if any.
|
|
|
|
|
bool synthesizeBasicBlock(SymTab& oSymTab, DfgVertex*& condpr,
|
|
|
|
|
const std::vector<AstNodeStmt*>& stmtps, const SymTab& iSymTab) {
|
|
|
|
|
// Use fresh set of vertices in m_converter
|
|
|
|
|
const VNUser2InUse user2InUse;
|
|
|
|
|
|
|
|
|
|
// Initialize Variable -> Vertex bindings available in this block
|
|
|
|
|
for (const auto& pair : iSymTab) {
|
|
|
|
|
Variable* const varp = pair.first;
|
|
|
|
|
DfgVertexVar* const vtxp = pair.second;
|
|
|
|
|
varp->user2p(vtxp);
|
|
|
|
|
oSymTab[varp] = vtxp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthesize each statement one after the other
|
|
|
|
|
std::vector<std::pair<Variable*, DfgVertexVar*>> updates;
|
|
|
|
|
for (AstNodeStmt* const stmtp : stmtps) {
|
|
|
|
|
// Regular statements
|
|
|
|
|
if (AstAssign* const ap = VN_CAST(stmtp, Assign)) {
|
|
|
|
|
// Convert this assignment
|
|
|
|
|
if (!m_converter.convert(updates, *m_logicp, ap)) {
|
|
|
|
|
++m_ctx.m_synt.nonSynConv;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Apply variable updates from this statement
|
|
|
|
|
for (const auto& pair : updates) {
|
|
|
|
|
// The target variable that was assigned to
|
|
|
|
|
Variable* const varp = pair.first;
|
|
|
|
|
// The new, potentially partially assigned value
|
|
|
|
|
DfgVertexVar* const newp = pair.second;
|
|
|
|
|
// Normalize drivers within this statement, bail if multidriven
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertexSplice* const srcp = newp->srcp()->as<DfgVertexSplice>();
|
|
|
|
|
std::vector<Driver> drivers = gatherDrivers(srcp);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
const bool single = drivers.size() == 1;
|
|
|
|
|
if (!normalizeDrivers(*newp, drivers)) {
|
|
|
|
|
getAstVar(varp)->setDfgMultidriven();
|
|
|
|
|
++m_ctx.m_synt.nonSynMultidrive;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-09-02 17:50:40 +02:00
|
|
|
// If there were more than one driver (often not), re-add in case coalesced
|
|
|
|
|
if (!single) {
|
|
|
|
|
srcp->resetDrivers();
|
|
|
|
|
for (const Driver& d : drivers) srcp->addDriver(d.m_vtxp, d.m_lo, d.m_flp);
|
|
|
|
|
}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// The old value, if any
|
|
|
|
|
DfgVertexVar* const oldp = varp->user2u().template to<DfgVertexVar*>();
|
|
|
|
|
// Inncorporate old value into the new value
|
|
|
|
|
if (!incorporatePreviousValue(varp, newp, oldp)) return false;
|
|
|
|
|
// Update binding of target variable
|
|
|
|
|
varp->user2p(newp);
|
|
|
|
|
// Update output symbol table of this block
|
|
|
|
|
oSymTab[varp] = newp;
|
|
|
|
|
}
|
|
|
|
|
updates.clear();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Terminator branches
|
|
|
|
|
if (AstIf* const ifp = VN_CAST(stmtp, If)) {
|
|
|
|
|
UASSERT_OBJ(ifp == stmtps.back(), ifp, "Branch should be last statement");
|
|
|
|
|
// Convert condition, give up if failed
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertex* condp = m_converter.convert(*m_logicp, ifp->condp());
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (!condp) {
|
|
|
|
|
++m_ctx.m_synt.nonSynConv;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-09-02 17:50:40 +02:00
|
|
|
// Single bit condition can be use directly, otherwise: use 'condp != 0'
|
|
|
|
|
if (condp->width() != 1) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
FileLine* const flp = condp->fileline();
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgNeq* const neqp = make<DfgNeq>(flp, V3Dfg::dtypePacked(1));
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
neqp->lhsp(make<DfgConst>(flp, condp->width(), 0U));
|
|
|
|
|
neqp->rhsp(condp);
|
2025-09-02 17:50:40 +02:00
|
|
|
condp = neqp;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
2025-09-02 17:50:40 +02:00
|
|
|
condpr = condp;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unhandled
|
|
|
|
|
++m_ctx.m_synt.nonSynStmt;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-26 00:47:08 +02:00
|
|
|
// Assign path predicates to the outgoing control flow edges of the given block
|
2025-08-25 14:47:45 +02:00
|
|
|
void assignPathPredicates(const CfgBlock& bb) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Nothing to do for the exit block
|
2025-08-25 14:47:45 +02:00
|
|
|
if (bb.isExit()) return;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Get the predicate of this block
|
|
|
|
|
DfgVertex* const predp = [&]() -> DfgVertex* {
|
|
|
|
|
// Entry block has no predecessors, use constant true
|
2025-08-25 14:47:45 +02:00
|
|
|
if (bb.isEnter()) return make<DfgConst>(m_logicp->fileline(), 1U, 1U);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// For any other block, 'or' together all the incoming predicates
|
|
|
|
|
const auto& inEdges = bb.inEdges();
|
|
|
|
|
auto it = inEdges.begin();
|
2025-08-25 14:47:45 +02:00
|
|
|
DfgVertex* resp = m_edgeToPredicatep[static_cast<const CfgEdge&>(*it)];
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
while (++it != inEdges.end()) {
|
|
|
|
|
DfgOr* const orp = make<DfgOr>(resp->fileline(), resp->dtypep());
|
|
|
|
|
orp->rhsp(resp);
|
2025-08-25 14:47:45 +02:00
|
|
|
orp->lhsp(m_edgeToPredicatep[static_cast<const CfgEdge&>(*it)]);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
resp = orp;
|
|
|
|
|
}
|
|
|
|
|
return resp;
|
|
|
|
|
}();
|
|
|
|
|
|
2025-09-02 17:50:40 +02:00
|
|
|
size_t n = m_nPathPred++; // Sequence number for temporaries
|
|
|
|
|
AstNodeDType* const dtypep = predp->dtypep();
|
|
|
|
|
|
|
|
|
|
const auto mkTmp = [&](FileLine* flp, const char* name, DfgVertex* srcp) {
|
|
|
|
|
std::string prefix;
|
|
|
|
|
prefix += "_BB";
|
|
|
|
|
prefix += std::to_string(bb.id());
|
|
|
|
|
prefix += "_";
|
|
|
|
|
prefix += name;
|
|
|
|
|
DfgVertexVar* const tmpp = m_converter.createTmp(*m_logicp, flp, dtypep, prefix, n);
|
|
|
|
|
tmpp->srcp(srcp);
|
|
|
|
|
return tmpp;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Assign it to a variable in case it's used multiple times
|
|
|
|
|
DfgVertexVar* const pInp = mkTmp(predp->fileline(), "PathIn", predp);
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// For uncondional branches, the successor predicate edge is the same
|
|
|
|
|
if (!bb.isBranch()) {
|
2025-09-02 17:50:40 +02:00
|
|
|
m_edgeToPredicatep[bb.takenEdgep()] = mkTmp(pInp->fileline(), "Goto", pInp);
|
2025-08-25 14:47:45 +02:00
|
|
|
return;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
2025-08-25 14:47:45 +02:00
|
|
|
|
|
|
|
|
// For branches, we need to factor in the branch condition
|
|
|
|
|
DfgVertex* const condp = m_bbToCondp[bb];
|
|
|
|
|
FileLine* const flp = condp->fileline();
|
|
|
|
|
|
|
|
|
|
// Predicate for taken branch: 'predp & condp'
|
2025-09-02 17:50:40 +02:00
|
|
|
{
|
|
|
|
|
DfgAnd* const takenPredp = make<DfgAnd>(flp, dtypep);
|
|
|
|
|
takenPredp->lhsp(pInp);
|
|
|
|
|
takenPredp->rhsp(condp);
|
|
|
|
|
m_edgeToPredicatep[bb.takenEdgep()] = mkTmp(flp, "Taken", takenPredp);
|
|
|
|
|
}
|
2025-08-25 14:47:45 +02:00
|
|
|
|
|
|
|
|
// Predicate for untaken branch: 'predp & ~condp'
|
2025-09-02 17:50:40 +02:00
|
|
|
{
|
|
|
|
|
DfgAnd* const untknPredp = make<DfgAnd>(flp, dtypep);
|
|
|
|
|
untknPredp->lhsp(pInp);
|
|
|
|
|
DfgNot* const notp = make<DfgNot>(flp, dtypep);
|
|
|
|
|
notp->srcp(condp);
|
|
|
|
|
untknPredp->rhsp(notp);
|
|
|
|
|
m_edgeToPredicatep[bb.untknEdgep()] = mkTmp(flp, "Untkn", untknPredp);
|
|
|
|
|
}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the synthesized values as drivers to the output variables of the current DfgLogic
|
|
|
|
|
bool addSynthesizedOutput(SymTab& oSymTab) {
|
|
|
|
|
// It's possible we think a variable is written by the DfgLogic when
|
|
|
|
|
// it actauly isn't, e.g.: '{a[0], b[0]}[1] = ...' does not write 'b'.
|
|
|
|
|
// These LHS forms can happen after some earlier tranforms. We
|
2025-08-26 00:47:08 +02:00
|
|
|
// should just run V3Const on them earlier, but we will do belt and
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// braces and check here too. We can't touch any output variables if so.
|
2025-09-02 17:50:40 +02:00
|
|
|
const bool missing = m_logicp->foreachSink([&](const DfgVertex& sink) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
const DfgUnresolved* const unresolvedp = sink.as<DfgUnresolved>();
|
|
|
|
|
AstNode* const tgtp = unresolvedp->singleSink()->as<DfgVertexVar>()->nodep();
|
2025-08-20 19:21:24 +02:00
|
|
|
// cppcheck-suppress constVariablePointer
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
Variable* const varp = reinterpret_cast<Variable*>(tgtp);
|
|
|
|
|
return !oSymTab.count(varp);
|
|
|
|
|
});
|
|
|
|
|
if (missing) {
|
|
|
|
|
++m_ctx.m_synt.nonSynFalseWrite;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add sinks to read the computed values for the target variables
|
2025-09-02 17:50:40 +02:00
|
|
|
bool hasUsedArrayOutput = false;
|
|
|
|
|
m_logicp->foreachSink([&](DfgVertex& sink) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgUnresolved* const unresolvedp = sink.as<DfgUnresolved>();
|
|
|
|
|
AstNode* const tgtp = unresolvedp->singleSink()->as<DfgVertexVar>()->nodep();
|
2025-08-20 19:21:24 +02:00
|
|
|
// cppcheck-suppress constVariablePointer
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
Variable* const varp = reinterpret_cast<Variable*>(tgtp);
|
|
|
|
|
DfgVertexVar* const resp = oSymTab.at(varp);
|
|
|
|
|
UASSERT_OBJ(resp->srcp(), resp, "Undriven result");
|
2025-09-02 17:50:40 +02:00
|
|
|
|
|
|
|
|
// If the output is not used further in the synthesized logic itself,
|
|
|
|
|
// then resp will be deleted before we return, so we can just use
|
|
|
|
|
// its splice directly without ending up with a multi-use operation.
|
|
|
|
|
if (!resp->hasSinks()) {
|
|
|
|
|
unresolvedp->addDriver(resp->srcp()->as<DfgVertexSplice>());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: computePropagatedDrivers cannot handle arrays, should
|
|
|
|
|
// never happen with AssignW
|
|
|
|
|
if (!resp->isPacked()) {
|
|
|
|
|
if (!hasUsedArrayOutput) ++m_ctx.m_synt.nonSynArray;
|
|
|
|
|
hasUsedArrayOutput = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We need to add a new splice to avoid multi-use of the original splice
|
|
|
|
|
DfgSplicePacked* const splicep
|
|
|
|
|
= new DfgSplicePacked{m_dfg, resp->fileline(), resp->dtypep()};
|
|
|
|
|
// Drivers are the same
|
|
|
|
|
const std::vector<Driver> drivers = computePropagatedDrivers({}, resp);
|
|
|
|
|
for (const Driver& d : drivers) splicep->addDriver(d.m_vtxp, d.m_lo, d.m_flp);
|
|
|
|
|
unresolvedp->addDriver(splicep);
|
|
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
2025-09-02 17:50:40 +02:00
|
|
|
return !hasUsedArrayOutput;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthesize the given AstAssignW. Returns true on success.
|
|
|
|
|
bool synthesizeAssignW(AstAssignW* nodep) {
|
|
|
|
|
++m_ctx.m_synt.inputAssign;
|
|
|
|
|
|
|
|
|
|
// Construct an equivalent AstAssign
|
|
|
|
|
AstNodeExpr* const lhsp = nodep->lhsp()->cloneTree(false);
|
|
|
|
|
AstNodeExpr* const rhsp = nodep->rhsp()->cloneTree(false);
|
|
|
|
|
AstAssign* const assignp = new AstAssign{nodep->fileline(), lhsp, rhsp};
|
|
|
|
|
|
|
|
|
|
// The input and output symbol tables
|
|
|
|
|
SymTab iSymTab;
|
|
|
|
|
SymTab oSymTab;
|
|
|
|
|
|
|
|
|
|
// Initialzie input symbol table
|
|
|
|
|
initializeEntrySymbolTable(iSymTab);
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// Synthesize as if it was in a single CfgBlock CFG
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgVertex* condp = nullptr;
|
|
|
|
|
const bool success = synthesizeBasicBlock(oSymTab, condp, {assignp}, iSymTab);
|
|
|
|
|
UASSERT_OBJ(!condp, nodep, "Conditional AstAssignW ???");
|
|
|
|
|
// Delete auxiliary AstAssign
|
|
|
|
|
VL_DO_DANGLING(assignp->deleteTree(), assignp);
|
|
|
|
|
if (!success) return false;
|
|
|
|
|
|
|
|
|
|
// Add resolved output variable drivers
|
|
|
|
|
return addSynthesizedOutput(oSymTab);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthesize the given AstAlways. Returns true on success.
|
2025-08-25 14:47:45 +02:00
|
|
|
bool synthesizeCfg(CfgGraph& cfg) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
++m_ctx.m_synt.inputAlways;
|
|
|
|
|
|
|
|
|
|
if (hasExternallyWrittenVariable(*m_logicp)) {
|
|
|
|
|
++m_ctx.m_synt.nonSynExtWrite;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there is a backward edge (loop), we can't synthesize it
|
|
|
|
|
if (cfg.containsLoop()) {
|
|
|
|
|
++m_ctx.m_synt.nonSynLoop;
|
2025-08-25 14:47:45 +02:00
|
|
|
++m_ctx.m_synt.cfgCyclic;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// If it's a trivial CFG we can save on some work
|
|
|
|
|
if (cfg.nBlocks() == 1) {
|
|
|
|
|
++m_ctx.m_synt.cfgTrivial;
|
|
|
|
|
} else {
|
|
|
|
|
// Insert two-way join blocks to aid multiplexer ordering
|
|
|
|
|
if (cfg.insertTwoWayJoins()) {
|
|
|
|
|
++m_ctx.m_synt.cfgSp;
|
|
|
|
|
} else {
|
|
|
|
|
++m_ctx.m_synt.cfgDag;
|
|
|
|
|
}
|
|
|
|
|
// Initialize maps needed for non-trivial CFGs
|
|
|
|
|
m_domTree = CfgDominatorTree{cfg};
|
2025-09-02 17:50:40 +02:00
|
|
|
m_edgeToPredicatep = cfg.makeEdgeMap<DfgVertexVar*>();
|
2025-08-25 14:47:45 +02:00
|
|
|
}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
// Initialize CfgMaps
|
|
|
|
|
m_bbToISymTab = cfg.makeBlockMap<SymTab>();
|
|
|
|
|
m_bbToOSymTab = cfg.makeBlockMap<SymTab>();
|
2025-09-02 17:50:40 +02:00
|
|
|
m_bbToCondp = cfg.makeBlockMap<DfgVertexVar*>();
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// Synthesize all blocks
|
2025-08-25 14:47:45 +02:00
|
|
|
for (const V3GraphVertex& vtx : cfg.vertices()) {
|
|
|
|
|
const CfgBlock& bb = static_cast<const CfgBlock&>(vtx);
|
|
|
|
|
// Prepare the input symbol table of this block (enter, or join predecessor blocks)
|
|
|
|
|
if (!createInputSymbolTable(bb)) return false;
|
|
|
|
|
// Synthesize this block
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgVertex* condp = nullptr;
|
|
|
|
|
if (!synthesizeBasicBlock(m_bbToOSymTab[bb], condp, bb.stmtps(), m_bbToISymTab[bb])) {
|
2025-08-25 14:47:45 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2025-09-02 17:50:40 +02:00
|
|
|
// Create a temporary for the branch condition as it might be used multiple times
|
|
|
|
|
if (condp) {
|
|
|
|
|
FileLine* const flp = condp->fileline();
|
|
|
|
|
AstNodeDType* const dtypep = condp->dtypep();
|
|
|
|
|
const std::string prefix = "_BB" + std::to_string(bb.id()) + "_Cond";
|
|
|
|
|
const size_t n = m_nBranchCond++;
|
|
|
|
|
DfgVertexVar* const vp = m_converter.createTmp(*m_logicp, flp, dtypep, prefix, n);
|
|
|
|
|
vp->srcp(condp);
|
|
|
|
|
m_bbToCondp[bb] = vp;
|
|
|
|
|
}
|
2025-08-25 14:47:45 +02:00
|
|
|
// Set the path predicates on the successor edges
|
|
|
|
|
assignPathPredicates(bb);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add resolved output variable drivers
|
2025-08-25 14:47:45 +02:00
|
|
|
return addSynthesizedOutput(m_bbToOSymTab[cfg.exit()]);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthesize a DfgLogic into regular vertices. Returns ture on success.
|
|
|
|
|
bool synthesize(DfgLogic& vtx) {
|
|
|
|
|
VL_RESTORER(m_logicp);
|
|
|
|
|
m_logicp = &vtx;
|
|
|
|
|
|
|
|
|
|
if (AstAssignW* const nodep = VN_CAST(vtx.nodep(), AssignW)) {
|
|
|
|
|
if (!synthesizeAssignW(nodep)) return false;
|
|
|
|
|
++m_ctx.m_synt.synthAssign;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!synthesizeCfg(vtx.cfg())) return false;
|
|
|
|
|
++m_ctx.m_synt.synthAlways;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Revert synthesis of the given DfgLogic
|
|
|
|
|
void revert(DfgLogic& vtx) {
|
|
|
|
|
for (DfgVertex* const p : vtx.synth()) VL_DO_DANGLING(p->unlinkDelete(m_dfg), p);
|
|
|
|
|
vtx.synth().clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Revert all logic driving the given unresolved driver, delete it,
|
|
|
|
|
// and transitively the same for variables driven by the reverted logic.
|
|
|
|
|
void revertTransivelyAndRemove(DfgUnresolved* vtxp, VDouble0& statCountr) {
|
|
|
|
|
// The result variable will be driven from Ast code, mark as such
|
|
|
|
|
vtxp->singleSink()->as<DfgVertexVar>()->setHasModWrRefs();
|
|
|
|
|
|
|
|
|
|
// Gather all logic driving this unresolved driver
|
|
|
|
|
std::vector<DfgLogic*> logicps;
|
2025-09-02 17:50:40 +02:00
|
|
|
logicps.reserve(vtxp->nInputs());
|
|
|
|
|
vtxp->foreachSource([&](DfgVertex& src) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (DfgLogic* const p = src.cast<DfgLogic>()) logicps.emplace_back(p);
|
2025-09-02 17:50:40 +02:00
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Delete the unresolved driver
|
|
|
|
|
VL_DO_DANGLING(vtxp->unlinkDelete(m_dfg), vtxp);
|
|
|
|
|
|
|
|
|
|
// Transitively for the rest
|
|
|
|
|
for (DfgLogic* const logicp : logicps) {
|
|
|
|
|
if (!logicp->synth().empty()) {
|
|
|
|
|
++statCountr;
|
|
|
|
|
revert(*logicp);
|
|
|
|
|
}
|
|
|
|
|
while (DfgVertex* const sinkp = logicp->firtsSinkp()) {
|
|
|
|
|
revertTransivelyAndRemove(sinkp->as<DfgUnresolved>(), statCountr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthesize all of the given vertices
|
|
|
|
|
void main(const std::vector<DfgLogic*>& logicps) {
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
UINFO(5, "Step 1: Attempting to synthesize each of the given DfgLogic");
|
|
|
|
|
for (DfgLogic* const logicp : logicps) {
|
|
|
|
|
// Debug aid
|
|
|
|
|
if (VL_UNLIKELY(s_dfgSynthDebugLimit)) {
|
|
|
|
|
if (s_dfgSynthDebugCount == s_dfgSynthDebugLimit) break;
|
|
|
|
|
++s_dfgSynthDebugCount;
|
|
|
|
|
if (s_dfgSynthDebugCount == s_dfgSynthDebugLimit) {
|
|
|
|
|
// This is the breaking logic
|
|
|
|
|
m_debugLogicp = logicp;
|
|
|
|
|
// Dump it
|
|
|
|
|
UINFOTREE(0, logicp->nodep(), "Problematic DfgLogic: " << logicp, " ");
|
|
|
|
|
V3EmitV::debugVerilogForTree(logicp->nodep(), std::cout);
|
|
|
|
|
debugDump("synth-lastok");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthesize it, revert partial construction if failed
|
|
|
|
|
if (!synthesize(*logicp)) revert(*logicp);
|
|
|
|
|
}
|
|
|
|
|
debugDump("synth-converted");
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
UINFO(5, "Step 2: Revert drivers of variables with unsynthesizeable drivers");
|
|
|
|
|
// We do this as the variables might be multi-driven, we just can't know at this point
|
2025-08-20 19:21:24 +02:00
|
|
|
for (const DfgVertexVar& var : m_dfg.varVertices()) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (!var.srcp()) continue;
|
|
|
|
|
DfgUnresolved* const unresolvedp = var.srcp()->cast<DfgUnresolved>();
|
|
|
|
|
if (!unresolvedp) break; // Stop when reached the synthesized temporaries
|
|
|
|
|
|
|
|
|
|
// Check if any driver have failed to synthesize
|
2025-09-02 17:50:40 +02:00
|
|
|
const bool failed = unresolvedp->foreachSource([&](DfgVertex& src) {
|
|
|
|
|
DfgLogic* const driverp = src.cast<DfgLogic>();
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
return driverp && driverp->synth().empty();
|
|
|
|
|
});
|
|
|
|
|
// Revert all logic involved
|
|
|
|
|
if (failed) revertTransivelyAndRemove(unresolvedp, m_ctx.m_synt.revertNonSyn);
|
|
|
|
|
}
|
|
|
|
|
debugDump("synth-reverted");
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
UINFO(5, "Step 3: Resolve synthesized drivers of original (non-temporary) variables");
|
|
|
|
|
// List of multi-driven variables
|
|
|
|
|
std::vector<DfgVertexVar*> multidrivenps;
|
|
|
|
|
// Map from variable to its resolved driver
|
2025-08-20 19:21:24 +02:00
|
|
|
std::unordered_map<const DfgVertexVar*, DfgVertexSplice*> resolvedDrivers;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Compute resolved drivers of all variablees
|
|
|
|
|
for (DfgVertexVar& var : m_dfg.varVertices()) {
|
|
|
|
|
if (!var.srcp()) continue;
|
2025-09-02 17:50:40 +02:00
|
|
|
DfgUnresolved* const unresolvedp = var.srcp()->cast<DfgUnresolved>();
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (!unresolvedp) break; // Stop when reached the synthesized temporaries
|
|
|
|
|
|
|
|
|
|
// Resolve the synthesized drivers
|
|
|
|
|
DfgVertexSplice* const resolvedp = [&]() -> DfgVertexSplice* {
|
|
|
|
|
// All synthesized drivers were normalized already,
|
|
|
|
|
// so if there is only one, it can be used directly
|
2025-09-02 17:50:40 +02:00
|
|
|
if (unresolvedp->nInputs() == 1) {
|
|
|
|
|
return unresolvedp->inputp(0)->as<DfgVertexSplice>();
|
|
|
|
|
}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Otherwise gather the synthesized drivers
|
|
|
|
|
std::vector<Driver> drivers = gatherDriversUnresolved(unresolvedp);
|
|
|
|
|
// Normalize them, make resolved driver if all good
|
|
|
|
|
if (normalizeDrivers(var, drivers)) return makeSplice(var, drivers);
|
|
|
|
|
// If mutlidriven, record and ignore
|
|
|
|
|
multidrivenps.emplace_back(&var);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}();
|
|
|
|
|
// Bail if multidriven
|
|
|
|
|
if (!resolvedp) continue;
|
|
|
|
|
// Add to map for next loop
|
|
|
|
|
const bool newEntry = resolvedDrivers.emplace(&var, resolvedp).second;
|
|
|
|
|
UASSERT_OBJ(newEntry, &var, "Dupliacte driver");
|
|
|
|
|
}
|
|
|
|
|
// Revert and remove drivers of multi-driven variables
|
2025-08-20 19:21:24 +02:00
|
|
|
for (const DfgVertexVar* const vtxp : multidrivenps) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Mark as multidriven for future DFG runs - here, so we get all warning before
|
|
|
|
|
vtxp->varp()->setDfgMultidriven();
|
|
|
|
|
// Might not have a driver if transitively removed on an earlier iteration
|
|
|
|
|
if (!vtxp->srcp()) continue;
|
|
|
|
|
// Revert all logic involved
|
|
|
|
|
DfgUnresolved* const unresolvedp = vtxp->srcp()->as<DfgUnresolved>();
|
|
|
|
|
revertTransivelyAndRemove(unresolvedp, m_ctx.m_synt.revertMultidrive);
|
|
|
|
|
}
|
|
|
|
|
// Replace all DfgUnresolved with the resolved drivers
|
2025-08-20 19:21:24 +02:00
|
|
|
for (const DfgVertexVar& var : m_dfg.varVertices()) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
if (!var.srcp()) continue;
|
|
|
|
|
DfgUnresolved* const srcp = var.srcp()->cast<DfgUnresolved>();
|
|
|
|
|
if (!srcp) break; // Stop when reached the synthesized temporaries
|
|
|
|
|
|
|
|
|
|
// Replace it
|
|
|
|
|
srcp->replaceWith(resolvedDrivers.at(&var));
|
|
|
|
|
VL_DO_DANGLING(srcp->unlinkDelete(m_dfg), srcp);
|
|
|
|
|
}
|
|
|
|
|
debugDump("synth-resolved");
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
UINFO(5, "Step 4: Remove all DfgLogic and DfgUnresolved");
|
|
|
|
|
for (DfgVertex* const vtxp : m_dfg.opVertices().unlinkable()) {
|
|
|
|
|
// Previous step should have removed all DfgUnresolved
|
|
|
|
|
UASSERT_OBJ(!vtxp->is<DfgUnresolved>(), vtxp, "DfgUnresolved remains");
|
|
|
|
|
|
|
|
|
|
// Process only DfgLogic
|
|
|
|
|
DfgLogic* const logicp = vtxp->cast<DfgLogic>();
|
|
|
|
|
if (!logicp) continue;
|
|
|
|
|
|
|
|
|
|
// Earlier pass should have removed all sinks
|
|
|
|
|
UASSERT_OBJ(!logicp->hasSinks(), logicp, "DfgLogic sink remains");
|
|
|
|
|
|
|
|
|
|
if (!logicp->synth().empty()) {
|
|
|
|
|
// If synthesized, delete the corresponding AstNode. It is now in Dfg.
|
|
|
|
|
logicp->nodep()->unlinkFrBack()->deleteTree();
|
|
|
|
|
} else {
|
|
|
|
|
// Not synthesized. Logic stays in Ast. Mark source variables
|
|
|
|
|
//as read in module. Outputs already marked by revertTransivelyAndRemove.
|
2025-09-02 17:50:40 +02:00
|
|
|
logicp->foreachSource([](DfgVertex& src) { //
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
src.as<DfgVertexVar>()->setHasModRdRefs();
|
2025-09-02 17:50:40 +02:00
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete this DfgLogic
|
|
|
|
|
VL_DO_DANGLING(logicp->unlinkDelete(m_dfg), logicp);
|
|
|
|
|
}
|
|
|
|
|
// Reset the debug pointer, we have deleted it in the loop above ...
|
|
|
|
|
m_debugLogicp = nullptr;
|
|
|
|
|
debugDump("synth-rmlogics");
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
UINFO(5, "Step 5: Remove unnecessary splices");
|
|
|
|
|
for (DfgVertex* const vtxp : m_dfg.opVertices().unlinkable()) {
|
|
|
|
|
DfgVertexSplice* const splicep = vtxp->cast<DfgVertexSplice>();
|
|
|
|
|
if (!splicep) continue;
|
|
|
|
|
|
|
|
|
|
// Might not have a sink if the driving logic was revered, remove
|
|
|
|
|
if (!splicep->hasSinks()) {
|
|
|
|
|
VL_DO_DANGLING(splicep->unlinkDelete(m_dfg), splicep);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// It should alway have drivers
|
2025-09-02 17:50:40 +02:00
|
|
|
UASSERT_OBJ(splicep->nInputs(), splicep, "Splice with no drivers");
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// If redundant, remove it
|
|
|
|
|
if (DfgVertex* const wholep = splicep->wholep()) {
|
|
|
|
|
if (DfgVertexVar* const varp = splicep->singleSink()->cast<DfgVertexVar>()) {
|
|
|
|
|
varp->driverFileLine(splicep->driverFileLine(0));
|
|
|
|
|
}
|
|
|
|
|
splicep->replaceWith(wholep);
|
|
|
|
|
VL_DO_DANGLING(splicep->unlinkDelete(m_dfg), splicep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
debugDump("synth-rmsplice");
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
UINFO(5, "Step 6: Remove all unused vertices");
|
|
|
|
|
V3DfgPasses::removeUnused(m_dfg);
|
|
|
|
|
debugDump("synth-rmunused");
|
2025-09-02 17:50:40 +02:00
|
|
|
|
|
|
|
|
// No operation vertex should have multiple sinks. Cyclic decomoposition
|
|
|
|
|
// depends on this and it can easily be ensured by using temporaries.
|
|
|
|
|
// Also, all sources should be connected at this point
|
|
|
|
|
if (v3Global.opt.debugCheck()) {
|
|
|
|
|
for (DfgVertex& vtx : m_dfg.opVertices()) {
|
|
|
|
|
UASSERT_OBJ(!vtx.hasMultipleSinks(), &vtx, "Operation has multiple sinks");
|
|
|
|
|
for (size_t i = 0; i < vtx.nInputs(); ++i) {
|
|
|
|
|
UASSERT_OBJ(vtx.inputp(i), &vtx, "Unconnected source operand");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CONSTRUCTOR
|
|
|
|
|
AstToDfgSynthesize(DfgGraph& dfg, const std::vector<DfgLogic*>& logicps,
|
|
|
|
|
V3DfgSynthesisContext& ctx)
|
|
|
|
|
: m_dfg{dfg}
|
|
|
|
|
, m_ctx{ctx}
|
|
|
|
|
, m_converter{dfg, ctx} {}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static void apply(DfgGraph& dfg, const std::vector<DfgLogic*>& logicps,
|
|
|
|
|
V3DfgSynthesisContext& ctx) {
|
|
|
|
|
AstToDfgSynthesize{dfg, logicps, ctx}.main(logicps);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void V3DfgPasses::synthesize(DfgGraph& dfg, V3DfgContext& ctx) {
|
|
|
|
|
// The vertices to synthesize
|
|
|
|
|
std::vector<DfgLogic*> logicps;
|
|
|
|
|
|
|
|
|
|
if (v3Global.opt.fDfgSynthesizeAll()) {
|
|
|
|
|
// If we are told to synthesize everything, we will do so ...
|
|
|
|
|
for (DfgVertex& vtx : dfg.opVertices()) {
|
|
|
|
|
if (DfgLogic* const logicp = vtx.cast<DfgLogic>()) logicps.emplace_back(logicp);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Otherwise figure out which vertices are worth synthesizing.
|
|
|
|
|
|
|
|
|
|
// Find cycles
|
2025-09-02 23:21:24 +02:00
|
|
|
DfgUserMap<uint64_t> scc = dfg.makeUserMap<uint64_t>();
|
|
|
|
|
V3DfgPasses::colorStronglyConnectedComponents(dfg, scc);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
|
|
|
|
|
// First, gather variables, we will then attempt to synthesize all their drivers
|
|
|
|
|
std::vector<DfgVertexVar*> varps;
|
|
|
|
|
for (DfgVertexVar& var : dfg.varVertices()) {
|
|
|
|
|
// Can ignore variables with no drivers
|
|
|
|
|
if (!var.srcp()) continue;
|
|
|
|
|
|
|
|
|
|
// Circular variable - synthesize
|
2025-09-02 23:21:24 +02:00
|
|
|
if (scc.at(var)) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
varps.emplace_back(&var);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Must be driven from a DfgUnresolved at this point, pick it up
|
|
|
|
|
const DfgUnresolved* const unresolvedp = var.srcp()->as<DfgUnresolved>();
|
|
|
|
|
|
|
|
|
|
// Inspect drivers to figure out if we should synthesize them
|
2025-09-02 17:50:40 +02:00
|
|
|
const bool doIt = unresolvedp->foreachSource([&](const DfgVertex& src) {
|
|
|
|
|
const DfgLogic* const logicp = src.as<DfgLogic>();
|
|
|
|
|
// Synthesize continuous assignments (this is the earlier behaviour).
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
// Synthesize always blocks with no more than 4 basic blocks and 4 edges
|
|
|
|
|
// These are usually simple branches (if (rst) ... else ...), or close to it
|
2025-09-02 17:50:40 +02:00
|
|
|
return VN_IS(logicp->nodep(), AssignW) //
|
|
|
|
|
|| (logicp->cfg().nBlocks() <= 4 && logicp->cfg().nEdges() <= 4);
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
if (doIt) varps.emplace_back(&var);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gather all drivers of the selected variables
|
|
|
|
|
const VNUser2InUse user2InUse; // AstNode (logic) -> bool: already collected
|
|
|
|
|
for (const DfgVertexVar* const varp : varps) {
|
2025-09-02 17:50:40 +02:00
|
|
|
varp->srcp()->as<DfgUnresolved>()->foreachSource([&](DfgVertex& source) {
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
DfgLogic* const logicp = source.as<DfgLogic>();
|
|
|
|
|
if (!logicp->nodep()->user2Inc()) logicps.emplace_back(logicp);
|
2025-09-02 17:50:40 +02:00
|
|
|
return false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthesize them - also removes un-synthesized DfgLogic, so must run even if logicps.empty()
|
|
|
|
|
if (dfg.modulep()) {
|
|
|
|
|
AstToDfgSynthesize</* T_Scoped: */ false>::apply(dfg, logicps, ctx.m_synthContext);
|
|
|
|
|
} else {
|
|
|
|
|
AstToDfgSynthesize</* T_Scoped: */ true>::apply(dfg, logicps, ctx.m_synthContext);
|
|
|
|
|
}
|
|
|
|
|
}
|