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: CFG liveness analysis
|
|
|
|
|
//
|
|
|
|
|
// 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
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Classical data flow analysis computing live variables input to a CFG
|
|
|
|
|
// https://en.wikipedia.org/wiki/Live-variable_analysis
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
|
|
|
|
|
|
|
|
|
#include "V3Ast.h"
|
|
|
|
|
#include "V3Cfg.h"
|
|
|
|
|
|
|
|
|
|
#include <limits>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
|
|
|
|
template <bool T_Scoped>
|
|
|
|
|
class CfgLiveVariables final : VNVisitorConst {
|
|
|
|
|
// TYPES
|
|
|
|
|
using Variable = std::conditional_t<T_Scoped, AstVarScope, AstVar>;
|
|
|
|
|
|
|
|
|
|
// State associted with each basic block
|
|
|
|
|
struct BlockState final {
|
|
|
|
|
// Variables used in block, before a complete assignment in the same block
|
|
|
|
|
std::unordered_set<Variable*> m_gen;
|
|
|
|
|
// Variables that are assigned a complete value in the basic block
|
|
|
|
|
std::unordered_set<Variable*> m_kill;
|
|
|
|
|
std::unordered_set<Variable*> m_liveIn; // Variables live on entry to the block
|
|
|
|
|
std::unordered_set<Variable*> m_liveOut; // Variables live on exit from the block
|
|
|
|
|
bool m_isOnWorkList = false; // Block is on work list
|
|
|
|
|
bool m_wasProcessed = false; // Already processed at least once
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// STATE
|
2025-08-25 14:47:45 +02:00
|
|
|
const CfgGraph& m_cfg; // The CFG beign analysed
|
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
|
|
|
// State for each block
|
2025-08-25 14:47:45 +02:00
|
|
|
CfgBlockMap<BlockState> m_blockState{m_cfg.makeBlockMap<BlockState>()};
|
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
|
|
|
BlockState* m_currp = nullptr; // State of current block being analysed
|
|
|
|
|
bool m_abort = false; // Abort analysis - unhandled construct
|
|
|
|
|
|
|
|
|
|
// METHODS
|
|
|
|
|
static Variable* getTarget(const AstNodeVarRef* 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());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is to match DFG, but can be extended independently - eventually should handle all
|
|
|
|
|
static bool isSupportedPackedDType(const AstNodeDType* dtypep) {
|
|
|
|
|
dtypep = dtypep->skipRefp();
|
|
|
|
|
if (const AstBasicDType* const typep = VN_CAST(dtypep, BasicDType)) {
|
|
|
|
|
return typep->keyword().isIntNumeric();
|
|
|
|
|
}
|
|
|
|
|
if (const AstPackArrayDType* const typep = VN_CAST(dtypep, PackArrayDType)) {
|
|
|
|
|
return isSupportedPackedDType(typep->subDTypep());
|
|
|
|
|
}
|
|
|
|
|
if (const AstNodeUOrStructDType* const typep = VN_CAST(dtypep, NodeUOrStructDType)) {
|
|
|
|
|
return typep->packed();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check and return if variable is incompatible
|
|
|
|
|
bool incompatible(Variable* varp) {
|
|
|
|
|
if (!isSupportedPackedDType(varp->dtypep())) return true;
|
2025-08-19 23:02:10 +02:00
|
|
|
const AstVar* astVarp = nullptr;
|
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
|
|
|
// TODO: remove the useless reinterpret_casts when C++17 'if constexpr' actually works
|
|
|
|
|
if VL_CONSTEXPR_CXX17 (T_Scoped) {
|
|
|
|
|
astVarp = reinterpret_cast<AstVarScope*>(varp)->varp();
|
|
|
|
|
} else {
|
|
|
|
|
astVarp = reinterpret_cast<AstVar*>(varp);
|
|
|
|
|
}
|
|
|
|
|
if (astVarp->ignoreSchedWrite()) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateGen(AstNode* nodep) {
|
|
|
|
|
UASSERT_OBJ(!m_abort, nodep, "Doing useless work");
|
|
|
|
|
m_abort = nodep->exists([&](const AstNodeVarRef* refp) {
|
|
|
|
|
// Cross reference is ambiguous
|
|
|
|
|
if (VN_IS(refp, VarXRef)) return true;
|
|
|
|
|
// Only care about reads
|
|
|
|
|
if (refp->access().isWriteOnly()) return false;
|
|
|
|
|
// Grab referenced variable
|
|
|
|
|
Variable* const tgtp = getTarget(refp);
|
|
|
|
|
// Bail if not a compatible type
|
|
|
|
|
if (incompatible(tgtp)) return true;
|
|
|
|
|
// Add to gen set, if not killed - assume whole variable read
|
|
|
|
|
if (m_currp->m_kill.count(tgtp)) return false;
|
|
|
|
|
m_currp->m_gen.emplace(tgtp);
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateKill(AstNode* nodep) {
|
|
|
|
|
UASSERT_OBJ(!m_abort, nodep, "Doing useless work");
|
|
|
|
|
m_abort = nodep->exists([&](const AstNodeVarRef* refp) {
|
|
|
|
|
// Cross reference is ambiguous
|
|
|
|
|
if (VN_IS(refp, VarXRef)) return true;
|
|
|
|
|
// Only care about writes
|
|
|
|
|
if (refp->access().isReadOnly()) return false;
|
|
|
|
|
// Grab referenced variable
|
|
|
|
|
Variable* const tgtp = getTarget(refp);
|
|
|
|
|
// Bail if not a compatible type
|
|
|
|
|
if (incompatible(tgtp)) return true;
|
|
|
|
|
// If whole written, add to kill set
|
|
|
|
|
if (refp->nextp()) return false;
|
|
|
|
|
if (VN_IS(refp->abovep(), Sel)) return false;
|
|
|
|
|
m_currp->m_kill.emplace(tgtp);
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void single(AstNode* nodep) {
|
|
|
|
|
// Assume all reads hapen before any writes
|
|
|
|
|
if (m_abort) return;
|
|
|
|
|
updateGen(nodep);
|
|
|
|
|
if (m_abort) return;
|
|
|
|
|
updateKill(nodep);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply transfer function of block, return true if changed
|
2025-08-25 14:47:45 +02:00
|
|
|
bool transfer(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
|
|
|
BlockState& state = m_blockState[bb];
|
|
|
|
|
|
|
|
|
|
// liveIn = gen union (liveOut - kill)
|
|
|
|
|
std::unordered_set<Variable*> liveIn = state.m_gen;
|
|
|
|
|
for (Variable* const varp : state.m_liveOut) {
|
|
|
|
|
if (state.m_kill.count(varp)) continue;
|
|
|
|
|
liveIn.insert(varp);
|
|
|
|
|
}
|
|
|
|
|
if (liveIn == state.m_liveIn) return false;
|
|
|
|
|
std::swap(liveIn, state.m_liveIn);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VISIT
|
|
|
|
|
void visit(AstNode* nodep) override { //
|
|
|
|
|
UASSERT_OBJ(!m_abort, nodep, "Repeat traversal after abort");
|
|
|
|
|
m_abort = true;
|
|
|
|
|
UINFO(9, "Unhandled AstNode type " << nodep->typeName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void visit(AstAssign* nodep) override { single(nodep); }
|
|
|
|
|
void visit(AstDisplay* nodep) override { single(nodep); }
|
|
|
|
|
void visit(AstFinish* nodep) override { single(nodep); }
|
|
|
|
|
void visit(AstStmtExpr* nodep) override { single(nodep); }
|
|
|
|
|
void visit(AstStop* nodep) override { single(nodep); }
|
|
|
|
|
|
|
|
|
|
// Only the condition check belongs to the terminated basic block
|
|
|
|
|
void visit(AstIf* nodep) override { single(nodep->condp()); }
|
|
|
|
|
void visit(AstWhile* nodep) override { single(nodep->condp()); }
|
|
|
|
|
|
|
|
|
|
// CONSTRUCTOR
|
2025-08-25 14:47:45 +02:00
|
|
|
explicit CfgLiveVariables(const 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_cfg{cfg} {
|
|
|
|
|
// For each basic block, compute the gen and kill set via visit
|
2025-08-25 14:47:45 +02:00
|
|
|
for (const V3GraphVertex& vtx : cfg.vertices()) {
|
|
|
|
|
const CfgBlock& bb = static_cast<const CfgBlock&>(vtx);
|
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 (m_abort) return;
|
|
|
|
|
VL_RESTORER(m_currp);
|
|
|
|
|
m_currp = &m_blockState[bb];
|
|
|
|
|
for (AstNode* const stmtp : bb.stmtps()) iterateConst(stmtp);
|
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
|
|
|
if (m_abort) return;
|
|
|
|
|
|
|
|
|
|
// Perform the flow analysis
|
2025-08-25 14:47:45 +02:00
|
|
|
std::deque<const CfgBlock*> workList;
|
|
|
|
|
const auto enqueue = [&](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
|
|
|
BlockState& state = m_blockState[bb];
|
|
|
|
|
if (state.m_isOnWorkList) return;
|
|
|
|
|
state.m_isOnWorkList = true;
|
|
|
|
|
workList.emplace_back(&bb);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enqueue(cfg.exit());
|
|
|
|
|
|
|
|
|
|
while (!workList.empty()) {
|
2025-08-25 14:47:45 +02:00
|
|
|
const CfgBlock* const currp = workList.front();
|
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
|
|
|
workList.pop_front();
|
|
|
|
|
BlockState& state = m_blockState[*currp];
|
|
|
|
|
state.m_isOnWorkList = false;
|
|
|
|
|
|
|
|
|
|
// Compute meet (liveOut = union liveIn of successors)
|
2025-08-25 14:47:45 +02:00
|
|
|
currp->forEachSuccessor([&](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
|
|
|
auto& liveIn = m_blockState[bb].m_liveIn;
|
|
|
|
|
state.m_liveOut.insert(liveIn.begin(), liveIn.end());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Apply transfer function of block
|
|
|
|
|
const bool changed = transfer(*currp);
|
|
|
|
|
// Enqueue predecessors
|
|
|
|
|
if (changed || !state.m_wasProcessed) currp->forEachPredecessor(enqueue);
|
|
|
|
|
// Mark as done with first visit
|
|
|
|
|
state.m_wasProcessed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2025-08-25 14:47:45 +02:00
|
|
|
static std::unique_ptr<std::vector<Variable*>> apply(const 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
|
|
|
CfgLiveVariables analysis{cfg};
|
|
|
|
|
// If failed, return nullptr
|
|
|
|
|
if (analysis.m_abort) return nullptr;
|
|
|
|
|
// Gather variables live in to the entry blockstd::unique_ptr<std::vector<Variable*>>
|
|
|
|
|
const std::unordered_set<Variable*>& lin = analysis.m_blockState[cfg.enter()].m_liveIn;
|
|
|
|
|
std::vector<Variable*>* const resultp = new std::vector<Variable*>{lin.begin(), lin.end()};
|
|
|
|
|
// Sort for stability
|
|
|
|
|
std::stable_sort(resultp->begin(), resultp->end(), [](Variable* ap, Variable* bp) { //
|
|
|
|
|
return ap->name() < bp->name();
|
|
|
|
|
});
|
|
|
|
|
return std::unique_ptr<std::vector<Variable*>>{resultp};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
std::unique_ptr<std::vector<AstVar*>> V3Cfg::liveVars(const 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
|
|
|
return CfgLiveVariables</* T_Scoped: */ false>::apply(cfg);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-25 14:47:45 +02:00
|
|
|
std::unique_ptr<std::vector<AstVarScope*>> V3Cfg::liveVarScopes(const 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
|
|
|
return CfgLiveVariables</* T_Scoped: */ true>::apply(cfg);
|
|
|
|
|
}
|