2025-07-26 21:37:01 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Persistent context for DFG algorithms
|
|
|
|
|
//
|
|
|
|
|
// Code available from: https://verilator.org
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2026-01-27 02:24:34 +01:00
|
|
|
// 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-FileCopyrightText: 2003-2026 Wilson Snyder
|
2025-07-26 21:37:01 +02:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Various context objects hold data that need to persist across invocations
|
|
|
|
|
// of a DFG algorithms.
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
#ifndef VERILATOR_V3DFGCONTEXT_H_
|
|
|
|
|
#define VERILATOR_V3DFGCONTEXT_H_
|
|
|
|
|
|
|
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
|
|
|
|
|
2026-04-09 14:32:16 +02:00
|
|
|
#include "V3Ast.h"
|
2025-07-26 21:37:01 +02:00
|
|
|
#include "V3DfgPeepholePatterns.h"
|
2026-04-09 14:32:16 +02:00
|
|
|
#include "V3Error.h"
|
2025-07-26 21:37:01 +02:00
|
|
|
#include "V3File.h"
|
2026-04-09 14:32:16 +02:00
|
|
|
#include "V3Global.h"
|
2025-07-26 21:37:01 +02:00
|
|
|
#include "V3Stats.h"
|
|
|
|
|
|
|
|
|
|
class V3DfgContext;
|
|
|
|
|
|
2025-09-07 23:18:23 +02:00
|
|
|
//######################################################################
|
2025-07-26 21:37:01 +02:00
|
|
|
// Base class for all context objects
|
|
|
|
|
|
|
|
|
|
class V3DfgSubContext VL_NOT_FINAL {
|
|
|
|
|
const std::string m_name; // Pass/algorithm name, to be used in statistics
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgSubContext(const std::string& name)
|
|
|
|
|
: m_name{name} {}
|
2025-07-26 21:37:01 +02:00
|
|
|
|
|
|
|
|
void addStat(const std::string& what, double value) {
|
2026-04-09 14:31:12 +02:00
|
|
|
V3Stats::addStat("Optimizations, DFG, " + m_name + ", " + what, value);
|
2025-07-26 21:37:01 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-07 23:18:23 +02:00
|
|
|
//######################################################################
|
2025-07-26 21:37:01 +02:00
|
|
|
// Contexts for various algorithms - keep sorted
|
|
|
|
|
|
|
|
|
|
class V3DfgAstToDfgContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
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
|
|
|
VDouble0 m_inputs; // Number of input processes (logic constructs)
|
2025-07-26 21:37:01 +02:00
|
|
|
VDouble0 m_representable; // Number of combinational equations representable
|
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
|
|
|
VDouble0 m_nonRepCfg; // Non-representable due to failing to build CFG
|
|
|
|
|
VDouble0 m_nonRepLive; // Non-representable due to failing liveness analysis
|
|
|
|
|
VDouble0 m_nonRepVar; // Non-representable due to unsupported variable properties
|
2025-07-26 21:37:01 +02:00
|
|
|
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgAstToDfgContext()
|
|
|
|
|
: V3DfgSubContext{"AstToDfg"} {}
|
2025-07-26 21:37:01 +02:00
|
|
|
~V3DfgAstToDfgContext() {
|
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
|
|
|
addStat("input processes", m_inputs);
|
2025-07-26 21:37:01 +02:00
|
|
|
addStat("representable", m_representable);
|
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
|
|
|
addStat("non-representable (cfg)", m_nonRepCfg);
|
|
|
|
|
addStat("non-representable (live)", m_nonRepLive);
|
|
|
|
|
addStat("non-representable (var)", m_nonRepVar);
|
2025-07-26 21:37:01 +02:00
|
|
|
// Check the stats are consistent
|
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(m_representable + m_nonRepCfg + m_nonRepLive + m_nonRepVar == m_inputs,
|
2025-07-26 21:37:01 +02:00
|
|
|
"Inconsistent statistics");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
class V3DfgBinToOneHotContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
|
|
|
|
VDouble0 m_decodersCreated; // Number of bianry to one-hot decoders created
|
|
|
|
|
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgBinToOneHotContext()
|
|
|
|
|
: V3DfgSubContext{"BinToOneHot"} {}
|
2025-07-26 21:37:01 +02:00
|
|
|
~V3DfgBinToOneHotContext() { addStat("decoders created", m_decodersCreated); }
|
|
|
|
|
};
|
|
|
|
|
class V3DfgBreakCyclesContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
|
|
|
|
VDouble0 m_nFixed; // Number of graphs that became acyclic
|
|
|
|
|
VDouble0 m_nImproved; // Number of graphs that were imporoved but still cyclic
|
|
|
|
|
VDouble0 m_nUnchanged; // Number of graphs that were left unchanged
|
|
|
|
|
VDouble0 m_nTrivial; // Number of graphs that were not changed
|
|
|
|
|
VDouble0 m_nImprovements; // Number of changes made to graphs
|
|
|
|
|
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgBreakCyclesContext()
|
|
|
|
|
: V3DfgSubContext{"BreakCycles"} {}
|
2025-07-26 21:37:01 +02:00
|
|
|
~V3DfgBreakCyclesContext() {
|
|
|
|
|
addStat("made acyclic", m_nFixed);
|
|
|
|
|
addStat("improved", m_nImproved);
|
|
|
|
|
addStat("left unchanged", m_nUnchanged);
|
|
|
|
|
addStat("trivial", m_nTrivial);
|
|
|
|
|
addStat("changes applied", m_nImprovements);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
class V3DfgCseContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
|
|
|
|
VDouble0 m_eliminated; // Number of common sub-expressions eliminated
|
|
|
|
|
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
explicit V3DfgCseContext(const std::string& label)
|
|
|
|
|
: V3DfgSubContext{"CSE " + label} {}
|
2025-07-26 21:37:01 +02:00
|
|
|
~V3DfgCseContext() { addStat("expressions eliminated", m_eliminated); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class V3DfgDfgToAstContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
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
|
|
|
VDouble0 m_outputVariables; // Number of output variables
|
|
|
|
|
VDouble0 m_outputVariablesWithDefault; // Number of outptu variables with a default driver
|
2025-07-26 21:37:01 +02:00
|
|
|
VDouble0 m_resultEquations; // Number of result combinational equations
|
2026-04-01 11:52:56 +02:00
|
|
|
VDouble0 m_expressionsInlined; // Number of expressions inlined directly into the Ast
|
|
|
|
|
VDouble0 m_varRefsSubstituted; // Number of variable references substituted in the Ast
|
2025-07-26 21:37:01 +02:00
|
|
|
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgDfgToAstContext()
|
|
|
|
|
: V3DfgSubContext{"DfgToAst"} {}
|
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
|
|
|
~V3DfgDfgToAstContext() {
|
|
|
|
|
addStat("output variables", m_outputVariables);
|
|
|
|
|
addStat("output variables with default driver", m_outputVariablesWithDefault);
|
|
|
|
|
addStat("result equations", m_resultEquations);
|
2026-04-01 11:52:56 +02:00
|
|
|
addStat("expressions inlined", m_expressionsInlined);
|
|
|
|
|
addStat("var refs substituted", m_varRefsSubstituted);
|
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-07-26 21:37:01 +02:00
|
|
|
};
|
|
|
|
|
class V3DfgPeepholeContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
|
|
|
|
// Enable flags for each optimization
|
|
|
|
|
std::array<bool, VDfgPeepholePattern::_ENUM_END> m_enabled;
|
|
|
|
|
// Count of applications for each optimization (for statistics)
|
|
|
|
|
std::array<VDouble0, VDfgPeepholePattern::_ENUM_END> m_count;
|
2026-04-01 11:52:56 +02:00
|
|
|
std::vector<AstNode*> m_deleteps; // AstVar/AstVarScope that can be deleted at the end
|
2025-07-26 21:37:01 +02:00
|
|
|
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgPeepholeContext()
|
|
|
|
|
: V3DfgSubContext{"Peephole"} {
|
|
|
|
|
const auto checkEnabled = [this](VDfgPeepholePattern id) {
|
|
|
|
|
std::string str{id.ascii()};
|
|
|
|
|
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { //
|
|
|
|
|
return c == '_' ? '-' : std::tolower(c);
|
|
|
|
|
});
|
|
|
|
|
m_enabled[id] = v3Global.opt.fDfgPeepholeEnabled(str);
|
|
|
|
|
};
|
|
|
|
|
#define OPTIMIZATION_CHECK_ENABLED(id, name) checkEnabled(VDfgPeepholePattern::id);
|
|
|
|
|
FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION(OPTIMIZATION_CHECK_ENABLED)
|
|
|
|
|
#undef OPTIMIZATION_CHECK_ENABLED
|
|
|
|
|
}
|
|
|
|
|
~V3DfgPeepholeContext() {
|
|
|
|
|
for (AstNode* const nodep : m_deleteps) {
|
|
|
|
|
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
|
|
|
|
}
|
|
|
|
|
const auto emitStat = [this](VDfgPeepholePattern id) {
|
|
|
|
|
std::string str{id.ascii()};
|
|
|
|
|
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { //
|
|
|
|
|
return c == '_' ? ' ' : std::tolower(c);
|
|
|
|
|
});
|
|
|
|
|
addStat(str, m_count[id]);
|
|
|
|
|
};
|
|
|
|
|
#define OPTIMIZATION_EMIT_STATS(id, name) emitStat(VDfgPeepholePattern::id);
|
|
|
|
|
FOR_EACH_DFG_PEEPHOLE_OPTIMIZATION(OPTIMIZATION_EMIT_STATS)
|
|
|
|
|
#undef OPTIMIZATION_EMIT_STATS
|
|
|
|
|
}
|
2025-07-26 21:37:01 +02:00
|
|
|
};
|
2026-02-07 19:06:12 +01:00
|
|
|
class V3DfgPushDownSelsContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
|
|
|
|
size_t m_pushedDown = 0; // Number of selects pushed down through concatenations
|
|
|
|
|
size_t m_wouldBeCyclic = 0; // Number of selects not pushed due to cycle
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgPushDownSelsContext()
|
|
|
|
|
: V3DfgSubContext{"PushDownSels"} {}
|
2026-02-07 19:06:12 +01:00
|
|
|
~V3DfgPushDownSelsContext() {
|
|
|
|
|
addStat("sels pushed down", m_pushedDown);
|
|
|
|
|
addStat("would be cyclic", m_wouldBeCyclic);
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-07-26 21:37:01 +02:00
|
|
|
class V3DfgRegularizeContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
2025-09-10 13:38:49 +02:00
|
|
|
std::vector<AstNode*> m_deleteps; // AstVar/AstVarScope that can be deleted at the end
|
|
|
|
|
VDouble0 m_usedVarsInlined; // Number of used variables inlined
|
|
|
|
|
VDouble0 m_unusedRemoved; // Number of unused vertices remoevd
|
2026-04-01 11:52:56 +02:00
|
|
|
VDouble0 m_temporariesIntroduced; // Number of temporaries introduced for reuse
|
2025-09-10 13:38:49 +02:00
|
|
|
|
2025-07-26 21:37:01 +02:00
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgRegularizeContext()
|
|
|
|
|
: V3DfgSubContext{"Regularize"} {}
|
2025-09-10 13:38:49 +02:00
|
|
|
~V3DfgRegularizeContext() {
|
|
|
|
|
for (AstNode* const nodep : m_deleteps) {
|
|
|
|
|
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
|
|
|
|
}
|
|
|
|
|
addStat("used variables inlined", m_usedVarsInlined);
|
|
|
|
|
addStat("unused vertices removed", m_unusedRemoved);
|
|
|
|
|
addStat("temporaries introduced", m_temporariesIntroduced);
|
|
|
|
|
}
|
2025-07-26 21:37:01 +02:00
|
|
|
};
|
2026-02-17 09:28:06 +01:00
|
|
|
class V3DfgRemoveUnobservableContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
|
|
|
|
VDouble0 m_varsRemoved; // Number of variables removed from the Dfg
|
|
|
|
|
VDouble0 m_varsDeleted; // Number of variables removed from the Dfg and the Ast
|
|
|
|
|
VDouble0 m_logicRemoved; // Number of logic blocks removed from the Dfg
|
|
|
|
|
VDouble0 m_logicDeleted; // Number of logic blocks removed from the Dfg and the Ast
|
|
|
|
|
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgRemoveUnobservableContext()
|
|
|
|
|
: V3DfgSubContext{"RemoveUnobservable"} {}
|
2026-02-17 09:28:06 +01:00
|
|
|
~V3DfgRemoveUnobservableContext() {
|
|
|
|
|
addStat("variables removed", m_varsRemoved);
|
|
|
|
|
addStat("variables deleted", m_varsDeleted);
|
|
|
|
|
addStat("logic removed", m_logicRemoved);
|
|
|
|
|
addStat("logic deleted", m_logicDeleted);
|
|
|
|
|
}
|
|
|
|
|
};
|
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
|
|
|
class V3DfgSynthesisContext final : public V3DfgSubContext {
|
|
|
|
|
// Only V3DfgContext can create an instance
|
|
|
|
|
friend class V3DfgContext;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
|
|
|
|
|
|
|
|
|
// Stats for conversion
|
|
|
|
|
struct {
|
|
|
|
|
// Inputs
|
|
|
|
|
VDouble0 inputAssignments; // Number of input assignments
|
|
|
|
|
VDouble0 inputExpressions; // Number of input equations
|
|
|
|
|
// Successful
|
|
|
|
|
VDouble0 representable; // Number of representable constructs
|
|
|
|
|
// Unsuccessful
|
|
|
|
|
VDouble0 nonRepImpure; // Non representable: impure
|
|
|
|
|
VDouble0 nonRepDType; // Non representable: unsupported data type
|
|
|
|
|
VDouble0 nonRepLValue; // Non representable: unsupported LValue form
|
|
|
|
|
VDouble0 nonRepVarRef; // Non representable: unsupported var reference
|
2025-09-07 21:38:50 +02:00
|
|
|
VDouble0 nonRepOOBSel; // Non representable: out of bounds select
|
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
|
|
|
VDouble0 nonRepNode; // Non representable: unsupported AstNode type
|
|
|
|
|
VDouble0 nonRepUnknown; // Non representable: unhandled AstNode type
|
|
|
|
|
} m_conv;
|
|
|
|
|
|
|
|
|
|
// Stats for synthesis
|
|
|
|
|
struct {
|
|
|
|
|
// Inputs
|
|
|
|
|
VDouble0 inputAlways; // Number of always blocks attempted
|
|
|
|
|
VDouble0 inputAssign; // Number of continuous assignments attempted
|
|
|
|
|
// Successful
|
|
|
|
|
VDouble0 synthAlways; // Number of always blocks successfully synthesized
|
|
|
|
|
VDouble0 synthAssign; // Number of continuous assignments successfully synthesized
|
|
|
|
|
// Unsuccessful
|
2026-03-12 00:53:23 +01:00
|
|
|
VDouble0 nonSynConv; // Non-synthesizable: non-representable (above)
|
|
|
|
|
VDouble0 nonSynExtWrite; // Non-synthesizable: has externally written variable
|
|
|
|
|
VDouble0 nonSynLoop; // Non-synthesizable: loop in CFG
|
|
|
|
|
VDouble0 nonSynStmt; // Non-synthesizable: unsupported statement
|
|
|
|
|
VDouble0 nonSynMultidrive; // Non-synthesizable: multidriven value within statement
|
|
|
|
|
VDouble0 nonSynArray; // Non-synthesizable: array type unhandled
|
|
|
|
|
VDouble0 nonSynLatch; // Non-synthesizable: maybe latch
|
|
|
|
|
VDouble0 nonSynJoinInput; // Non-synthesizable: needing to join input variable
|
|
|
|
|
VDouble0 nonSynFalseWrite; // Non-synthesizable: does not write output
|
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
|
|
|
// Reverted
|
|
|
|
|
VDouble0 revertNonSyn; // Reverted due to being driven from non-synthesizable vertex
|
|
|
|
|
VDouble0 revertMultidrive; // Reverted due to multiple drivers
|
2025-08-25 14:47:45 +02:00
|
|
|
// Additional stats
|
|
|
|
|
VDouble0 cfgTrivial; // Trivial input CFGs
|
|
|
|
|
VDouble0 cfgSp; // Series-paralel input CFGs
|
|
|
|
|
VDouble0 cfgDag; // Generic loop free input CFGs
|
|
|
|
|
VDouble0 cfgCyclic; // Cyclic input CFGs
|
|
|
|
|
VDouble0 joinUsingPathPredicate; // Num control flow joins using full path predicate
|
|
|
|
|
VDouble0 joinUsingBranchCondition; // Num Control flow joins using dominating branch cond
|
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_synt;
|
|
|
|
|
|
|
|
|
|
private:
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgSynthesisContext()
|
|
|
|
|
: V3DfgSubContext{"Synthesis"} {}
|
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
|
|
|
~V3DfgSynthesisContext() {
|
|
|
|
|
// Conversion statistics
|
|
|
|
|
addStat("conv / input assignments", m_conv.inputAssignments);
|
|
|
|
|
addStat("conv / input expressions", m_conv.inputExpressions);
|
|
|
|
|
addStat("conv / representable inputs", m_conv.representable);
|
|
|
|
|
addStat("conv / non-representable (impure)", m_conv.nonRepImpure);
|
|
|
|
|
addStat("conv / non-representable (dtype)", m_conv.nonRepDType);
|
|
|
|
|
addStat("conv / non-representable (lhs)", m_conv.nonRepLValue);
|
|
|
|
|
addStat("conv / non-representable (varref)", m_conv.nonRepVarRef);
|
2025-09-07 21:38:50 +02:00
|
|
|
addStat("conv / non-representable (oobsel)", m_conv.nonRepOOBSel);
|
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
|
|
|
addStat("conv / non-representable (node)", m_conv.nonRepNode);
|
|
|
|
|
addStat("conv / non-representable (unknown)", m_conv.nonRepUnknown);
|
|
|
|
|
VDouble0 nConvNonRep;
|
|
|
|
|
nConvNonRep += m_conv.nonRepImpure;
|
|
|
|
|
nConvNonRep += m_conv.nonRepDType;
|
|
|
|
|
nConvNonRep += m_conv.nonRepLValue;
|
|
|
|
|
nConvNonRep += m_conv.nonRepVarRef;
|
2025-09-07 21:38:50 +02:00
|
|
|
nConvNonRep += m_conv.nonRepOOBSel;
|
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
|
|
|
nConvNonRep += m_conv.nonRepNode;
|
|
|
|
|
nConvNonRep += m_conv.nonRepUnknown;
|
|
|
|
|
VDouble0 nConvExpect;
|
|
|
|
|
nConvExpect += m_conv.inputAssignments;
|
|
|
|
|
nConvExpect += m_conv.inputExpressions;
|
|
|
|
|
nConvExpect -= m_conv.representable;
|
|
|
|
|
UASSERT(nConvNonRep == nConvExpect, "Inconsistent statistics / conv");
|
|
|
|
|
|
|
|
|
|
// Synthesis statistics
|
|
|
|
|
addStat("synt / always blocks considered", m_synt.inputAlways);
|
|
|
|
|
addStat("synt / always blocks synthesized", m_synt.synthAlways);
|
|
|
|
|
addStat("synt / continuous assignments considered", m_synt.inputAssign);
|
|
|
|
|
addStat("synt / continuous assignments synthesized", m_synt.synthAssign);
|
|
|
|
|
addStat("synt / non-synthesizable (conv)", m_synt.nonSynConv);
|
|
|
|
|
addStat("synt / non-synthesizable (ext write)", m_synt.nonSynExtWrite);
|
|
|
|
|
addStat("synt / non-synthesizable (loop)", m_synt.nonSynLoop);
|
|
|
|
|
addStat("synt / non-synthesizable (stmt)", m_synt.nonSynStmt);
|
|
|
|
|
addStat("synt / non-synthesizable (multidrive)", m_synt.nonSynMultidrive);
|
|
|
|
|
addStat("synt / non-synthesizable (array)", m_synt.nonSynArray);
|
|
|
|
|
addStat("synt / non-synthesizable (latch)", m_synt.nonSynLatch);
|
|
|
|
|
addStat("synt / non-synthesizable (join input)", m_synt.nonSynJoinInput);
|
|
|
|
|
addStat("synt / non-synthesizable (false write)", m_synt.nonSynFalseWrite);
|
|
|
|
|
addStat("synt / reverted (non-synthesizable)", m_synt.revertNonSyn);
|
|
|
|
|
addStat("synt / reverted (multidrive)", m_synt.revertMultidrive);
|
|
|
|
|
|
|
|
|
|
VDouble0 nSyntNonSyn;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynConv;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynExtWrite;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynLoop;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynStmt;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynMultidrive;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynArray;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynLatch;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynJoinInput;
|
|
|
|
|
nSyntNonSyn += m_synt.nonSynFalseWrite;
|
|
|
|
|
VDouble0 nSyntExpect;
|
|
|
|
|
nSyntExpect += m_synt.inputAlways;
|
|
|
|
|
nSyntExpect += m_synt.inputAssign;
|
|
|
|
|
nSyntExpect -= m_synt.synthAlways;
|
|
|
|
|
nSyntExpect -= m_synt.synthAssign;
|
|
|
|
|
UASSERT(nSyntNonSyn == nSyntExpect, "Inconsistent statistics / synt");
|
2025-08-25 14:47:45 +02:00
|
|
|
|
|
|
|
|
addStat("synt / input CFG trivial", m_synt.cfgTrivial);
|
|
|
|
|
addStat("synt / input CFG sp", m_synt.cfgSp);
|
|
|
|
|
addStat("synt / input CFG dag", m_synt.cfgDag);
|
|
|
|
|
addStat("synt / input CFG cyclic", m_synt.cfgCyclic);
|
|
|
|
|
|
|
|
|
|
addStat("synt / joins using path predicate", m_synt.joinUsingPathPredicate);
|
|
|
|
|
addStat("synt / joins using branch condition", m_synt.joinUsingBranchCondition);
|
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-07-26 21:37:01 +02:00
|
|
|
|
2025-09-07 23:18:23 +02:00
|
|
|
//######################################################################
|
2025-07-26 21:37:01 +02:00
|
|
|
// Top level V3DfgContext
|
|
|
|
|
|
|
|
|
|
class V3DfgContext final {
|
|
|
|
|
public:
|
|
|
|
|
// STATE
|
|
|
|
|
|
|
|
|
|
// Sub contexts - keep sorted by type
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgAstToDfgContext m_ast2DfgContext;
|
|
|
|
|
V3DfgBinToOneHotContext m_binToOneHotContext;
|
|
|
|
|
V3DfgBreakCyclesContext m_breakCyclesContext;
|
|
|
|
|
V3DfgCseContext m_cseContext0{"1st"};
|
|
|
|
|
V3DfgCseContext m_cseContext1{"2nd"};
|
|
|
|
|
V3DfgDfgToAstContext m_dfg2AstContext;
|
|
|
|
|
V3DfgPeepholeContext m_peepholeContext;
|
|
|
|
|
V3DfgPushDownSelsContext m_pushDownSelsContext;
|
|
|
|
|
V3DfgRegularizeContext m_regularizeContext;
|
|
|
|
|
V3DfgRemoveUnobservableContext m_removeUnobservableContext;
|
|
|
|
|
V3DfgSynthesisContext m_synthContext;
|
2025-07-26 21:37:01 +02:00
|
|
|
|
|
|
|
|
// CONSTRUCTOR
|
2026-04-09 14:31:12 +02:00
|
|
|
V3DfgContext() = default;
|
2026-04-09 13:32:57 +02:00
|
|
|
~V3DfgContext() = default;
|
2025-07-26 21:37:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif //VERILATOR_V3DFGCONTEXT_H_
|