Internals: Dump Ast expression pattern statistics like Dfg (#7818)
Remove the expression combination counts from the default stats file, and add a new `--dump-ast-patterns` option, which will dump new `*_ast_patterns_*.txt` files. These contain the expression combinations in a similar S-expression format as Dfg already produces with `--dump-dfg-stats`. These dumps are not produced by just `--stats` as they are fairly expensive to compute. Currently the new option will dump at two points: just before we change to C types via widthMin usage, and just before emit.
This commit is contained in:
parent
fbea10b427
commit
eafe9636cf
|
|
@ -438,6 +438,7 @@ detailed descriptions of these arguments.
|
|||
--diagnostics-sarif-output <filename> Set SARIF diagnostics output file
|
||||
--dpi-hdr-only Only produce the DPI header file
|
||||
--dump-<srcfile> Enable dumping everything in source file
|
||||
--dump-ast-patterns Enable dumping Ast pattern statistics
|
||||
--dump-defines Show preprocessor defines with -E
|
||||
--dump-dfg Enable dumping DfgGraphs to .dot files
|
||||
--dump-dfg-patterns Enable dumping Dfg pattern statistics
|
||||
|
|
|
|||
|
|
@ -491,6 +491,10 @@ Summary:
|
|||
Rarely needed - for developer use. Enable all dumping in the given
|
||||
source file at level 3.
|
||||
|
||||
.. option:: --dump-ast-patterns
|
||||
|
||||
Rarely needed. Enable dumping AstNodeExpr pattern statistics.
|
||||
|
||||
.. option:: --dump-defines
|
||||
|
||||
With :vlopt:`-E`, suppress normal output, and instead print a list of
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ set(HEADERS
|
|||
V3AstNodeExpr.h
|
||||
V3AstNodeOther.h
|
||||
V3AstNodeStmt.h
|
||||
V3AstPatterns.h
|
||||
V3AstUserAllocator.h
|
||||
V3Begin.h
|
||||
V3Branch.h
|
||||
|
|
@ -250,7 +251,6 @@ set(COMMON_SOURCES
|
|||
V3DfgDataType.cpp
|
||||
V3DfgDecomposition.cpp
|
||||
V3DfgDfgToAst.cpp
|
||||
V3DfgDumpPatterns.cpp
|
||||
V3DfgOptimizer.cpp
|
||||
V3DfgPasses.cpp
|
||||
V3DfgPeephole.cpp
|
||||
|
|
@ -327,6 +327,7 @@ set(COMMON_SOURCES
|
|||
V3ParseGrammar.cpp
|
||||
V3ParseImp.cpp
|
||||
V3ParseLex.cpp
|
||||
V3PatternStats.cpp
|
||||
V3PreProc.cpp
|
||||
V3PreShell.cpp
|
||||
V3Premit.cpp
|
||||
|
|
|
|||
|
|
@ -264,7 +264,6 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||
V3DfgDataType.o \
|
||||
V3DfgDecomposition.o \
|
||||
V3DfgDfgToAst.o \
|
||||
V3DfgDumpPatterns.o \
|
||||
V3DfgOptimizer.o \
|
||||
V3DfgPasses.o \
|
||||
V3DfgPeephole.o \
|
||||
|
|
@ -314,6 +313,7 @@ RAW_OBJS_PCH_ASTNOMT = \
|
|||
V3OrderProcessDomains.o \
|
||||
V3OrderSerial.o \
|
||||
V3Param.o \
|
||||
V3PatternStats.o \
|
||||
V3Premit.o \
|
||||
V3ProtectLib.o \
|
||||
V3RandSequence.o \
|
||||
|
|
|
|||
150
src/V3Ast.cpp
150
src/V3Ast.cpp
|
|
@ -1745,6 +1745,156 @@ AstNodeDType* AstNode::getCommonClassTypep(AstNode* node1p, AstNode* node2p) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Renders the canonical pattern S-expression for a single AstNode
|
||||
|
||||
class VNPatternString final {
|
||||
std::ostream& m_os;
|
||||
|
||||
std::map<std::string, std::string> m_internedConsts; // Interned constants
|
||||
std::map<int, std::string> m_internedWordWidths; // Interned widths
|
||||
std::map<int, std::string> m_internedWideWidths; // Interned widths
|
||||
|
||||
// Whether to dump the widhtMin as well
|
||||
const bool m_dumpWidthMin = v3Global.widthMinUsage() != VWidthMinUsage::MATCHES_WIDTH;
|
||||
|
||||
static std::string toLetters(size_t value, bool lowerCase = false) {
|
||||
const char base = lowerCase ? 'a' : 'A';
|
||||
std::string s;
|
||||
do { s += static_cast<char>(base + value % 26); } while (value /= 26);
|
||||
return s;
|
||||
}
|
||||
|
||||
const std::string& internConst(const AstConst& nodep) {
|
||||
const auto pair = m_internedConsts.emplace(nodep.num().ascii(false), "");
|
||||
if (pair.second) pair.first->second += toLetters(m_internedConsts.size() - 1);
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
const std::string& internWordWidth(int value) {
|
||||
const auto pair = m_internedWordWidths.emplace(value, "");
|
||||
if (pair.second) pair.first->second += toLetters(m_internedWordWidths.size() - 1, true);
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
const std::string& internWideWidth(int value) {
|
||||
const auto pair = m_internedWideWidths.emplace(value, "");
|
||||
if (pair.second) pair.first->second += toLetters(m_internedWideWidths.size() - 1);
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
// True if the node has no operands (e.g. a VarRef or Const)
|
||||
static bool isLeaf(const AstNode* nodep) {
|
||||
const VNTypeInfo& typeInfo = VNType::typeInfo(nodep->type());
|
||||
for (const VNTypeInfo::OpEn& opType : typeInfo.m_opType) {
|
||||
if (opType != VNTypeInfo::OP_UNUSED) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Render operand, return true if not unused
|
||||
void renderOperand(VNTypeInfo::OpEn opType, const AstNode* const opp, uint32_t depth) {
|
||||
switch (opType) {
|
||||
case VNTypeInfo::OP_UNUSED: //
|
||||
break;
|
||||
case VNTypeInfo::OP_USED: //
|
||||
m_os << ' ';
|
||||
render(opp, depth);
|
||||
break;
|
||||
case VNTypeInfo::OP_LIST:
|
||||
m_os << " [";
|
||||
for (const AstNode* nodep = opp; nodep; nodep = nodep->nextp()) {
|
||||
if (nodep != opp) m_os << ", ";
|
||||
render(opp, depth);
|
||||
}
|
||||
m_os << ']';
|
||||
break;
|
||||
case VNTypeInfo::OP_OPTIONAL:
|
||||
if (opp) {
|
||||
m_os << " ";
|
||||
render(opp, depth);
|
||||
} else {
|
||||
m_os << " nil";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Render the node into the stream.
|
||||
void render(const AstNode* nodep, uint32_t depth) {
|
||||
if (const AstConst* const constp = VN_CAST(nodep, Const)) {
|
||||
// Base case 1: constant
|
||||
if (constp->isZero()) {
|
||||
m_os << "(CONST ZERO)";
|
||||
} else if (constp->isEqAllOnes()) {
|
||||
m_os << "(CONST ONES)";
|
||||
} else {
|
||||
m_os << "(CONST #" << internConst(*constp) << ')';
|
||||
}
|
||||
} else if (isLeaf(nodep)) {
|
||||
// Base case 2: expression with no operands (e.g. a variable reference)
|
||||
m_os << '(' << nodep->typeName() << ')';
|
||||
} else if (depth == 0) {
|
||||
// Base case 3: deep expression
|
||||
m_os << '_';
|
||||
} else {
|
||||
// Recursively print an S-expression for the expression
|
||||
m_os << '(';
|
||||
// Name
|
||||
m_os << nodep->typeName();
|
||||
// Operands
|
||||
const VNTypeInfo& typeInfo = VNType::typeInfo(nodep->type());
|
||||
renderOperand(typeInfo.m_opType[0], nodep->op1p(), depth - 1);
|
||||
renderOperand(typeInfo.m_opType[1], nodep->op2p(), depth - 1);
|
||||
renderOperand(typeInfo.m_opType[2], nodep->op3p(), depth - 1);
|
||||
renderOperand(typeInfo.m_opType[3], nodep->op4p(), depth - 1);
|
||||
// S-expression end
|
||||
m_os << ')';
|
||||
}
|
||||
|
||||
// Annotate type
|
||||
m_os << ':';
|
||||
const AstNodeDType* const dtypep = nodep->dtypep() ? nodep->dtypep()->skipRefp() : nullptr;
|
||||
if (!dtypep) {
|
||||
m_os << '?';
|
||||
} else if (dtypep->isCompound() || VN_IS(dtypep, UnpackArrayDType)) {
|
||||
dtypep->dumpSmall(m_os);
|
||||
} else {
|
||||
const int width = nodep->width();
|
||||
if (width == 1) {
|
||||
m_os << '1';
|
||||
} else if (width <= VL_QUADSIZE) {
|
||||
m_os << internWordWidth(width);
|
||||
} else {
|
||||
m_os << internWideWidth(width);
|
||||
}
|
||||
if (m_dumpWidthMin) {
|
||||
m_os << '/';
|
||||
const int widthMin = nodep->widthMin();
|
||||
if (widthMin == 1) {
|
||||
m_os << '1';
|
||||
} else if (widthMin <= VL_QUADSIZE) {
|
||||
m_os << internWordWidth(widthMin);
|
||||
} else {
|
||||
m_os << internWideWidth(widthMin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
VNPatternString(std::ostream& os, const AstNode* nodep, uint32_t depth)
|
||||
: m_os{os} {
|
||||
render(nodep, depth);
|
||||
}
|
||||
};
|
||||
|
||||
std::string AstNodeExpr::patternString(uint32_t depth) const {
|
||||
std::ostringstream oss;
|
||||
VNPatternString{oss, this, depth};
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// VNDeleter
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ public:
|
|||
// Returns an error message if widthMin() is not correct otherwise returns nullptr like
|
||||
// broken()
|
||||
virtual const char* widthMismatch() const VL_MT_STABLE { return nullptr; }
|
||||
|
||||
// S-expression inspired dump of node and operands for debugging
|
||||
std::string patternString(uint32_t depth = 0) const;
|
||||
};
|
||||
class AstNodeBiop VL_NOT_FINAL : public AstNodeExpr {
|
||||
// Binary expression
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Dump AstNodeExpr patterns for analysis
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// 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
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef VERILATOR_V3ASTPATTERNS_H_
|
||||
#define VERILATOR_V3ASTPATTERNS_H_
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
|
||||
class AstNetlist;
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3AstPatterns final {
|
||||
public:
|
||||
// Accumulate the patterns in the netlist, and dump the collected
|
||||
// statistics to '<prefix>__ast_patterns_<suffix>.txt'.
|
||||
static void dumpAll(const AstNetlist* nodep, const std::string& suffix) VL_MT_DISABLED;
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
@ -959,6 +959,9 @@ void DfgVertex::unlinkDelete(DfgGraph& dfg) {
|
|||
delete this;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Renders the canonical pattern S-expression for a single DfgVertex
|
||||
|
||||
class DfgPatternString final {
|
||||
std::ostream& m_os;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Implementations of simple passes over DfgGraph
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// 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
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef VERILATOR_V3DFGPATTERNSTATS_H_
|
||||
#define VERILATOR_V3DFGPATTERNSTATS_H_
|
||||
|
||||
#include "V3Dfg.h"
|
||||
#include "V3DfgPasses.h"
|
||||
#include "V3File.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
class V3DfgPatternStats final {
|
||||
static constexpr uint32_t MIN_PATTERN_DEPTH = 1;
|
||||
static constexpr uint32_t MAX_PATTERN_DEPTH = 4;
|
||||
|
||||
// Maps from pattern to the number of times it appears, for each pattern depth
|
||||
std::vector<std::unordered_map<std::string, size_t>> m_patterCounts{MAX_PATTERN_DEPTH + 1};
|
||||
|
||||
void dump(std::ostream& os) {
|
||||
using Line = std::pair<std::string, size_t>;
|
||||
for (uint32_t i = MIN_PATTERN_DEPTH; i <= MAX_PATTERN_DEPTH; ++i) {
|
||||
os << "DFG patterns with depth " << i << '\n';
|
||||
|
||||
// Pick up pattern accumulators with given depth
|
||||
auto& patternCounts = m_patterCounts[i];
|
||||
|
||||
// Remove patterns also present at shallower depths
|
||||
for (uint32_t j = MIN_PATTERN_DEPTH; j < i; ++j) {
|
||||
for (const auto& pair : m_patterCounts[j]) patternCounts.erase(pair.first);
|
||||
}
|
||||
|
||||
// Sort patterns, first by descending frequency, then lexically
|
||||
std::vector<Line> lines;
|
||||
lines.reserve(patternCounts.size());
|
||||
for (const auto& pair : patternCounts) lines.emplace_back(pair);
|
||||
std::sort(lines.begin(), lines.end(), [](const Line& a, const Line& b) {
|
||||
if (a.second != b.second) return a.second > b.second;
|
||||
return a.first < b.first;
|
||||
});
|
||||
|
||||
// Print each pattern
|
||||
for (const auto& line : lines) {
|
||||
os << ' ' << std::setw(12) << std::right << line.second;
|
||||
os << ' ' << std::left << line.first << '\n';
|
||||
}
|
||||
|
||||
// Trailing new-line to separate sections
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
V3DfgPatternStats() = default;
|
||||
~V3DfgPatternStats() {
|
||||
// File to dump to
|
||||
const std::string filename
|
||||
= v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + "__dfg_patterns.txt";
|
||||
// Open, write, close
|
||||
const std::unique_ptr<std::ofstream> ofp{V3File::new_ofstream(filename)};
|
||||
if (ofp->fail()) v3fatal("Can't write file: " << filename);
|
||||
dump(*ofp);
|
||||
}
|
||||
|
||||
void accumulate(const DfgGraph& dfg) {
|
||||
dfg.forEachVertex([&](const DfgVertex& vtx) {
|
||||
for (uint32_t i = MIN_PATTERN_DEPTH; i <= MAX_PATTERN_DEPTH; ++i) {
|
||||
m_patterCounts[i][vtx.patternString(i)] += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
void V3DfgPasses::dumpPatterns(const std::vector<std::unique_ptr<DfgGraph>>& graphs) {
|
||||
V3DfgPatternStats patternStats;
|
||||
for (auto& cp : graphs) patternStats.accumulate(*cp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -67,7 +67,8 @@ void regularize(DfgGraph&, V3DfgRegularizeContext&) VL_MT_DISABLED;
|
|||
// Convert DfgGraph back into Ast, and insert converted graph back into the Ast.
|
||||
void dfgToAst(DfgGraph&, V3DfgContext&) VL_MT_DISABLED;
|
||||
// Dump the patterns in the given graphs
|
||||
void dumpPatterns(const std::vector<std::unique_ptr<DfgGraph>>&) VL_MT_DISABLED;
|
||||
void dumpPatterns(const std::vector<std::unique_ptr<DfgGraph>>&,
|
||||
const std::string& suffix = "") VL_MT_DISABLED;
|
||||
|
||||
//===========================================================================
|
||||
// Intermediate/internal operations
|
||||
|
|
|
|||
|
|
@ -552,6 +552,9 @@ public:
|
|||
bool decorationNodes() const VL_MT_SAFE { return m_decorationNodes; }
|
||||
bool diagnosticsSarif() const VL_MT_SAFE { return m_diagnosticsSarif; }
|
||||
bool dpiHdrOnly() const { return m_dpiHdrOnly; }
|
||||
bool dumpAstPatterns() const {
|
||||
return m_dumpLevel.count("ast-patterns") && m_dumpLevel.at("ast-patterns");
|
||||
}
|
||||
bool dumpDefines() const { return m_dumpLevel.count("defines") && m_dumpLevel.at("defines"); }
|
||||
bool dumpDfgPatterns() const {
|
||||
return m_dumpLevel.count("dfg-patterns") && m_dumpLevel.at("dfg-patterns");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Dump data structure pattern frequencies for analysis
|
||||
//
|
||||
// Code available from: https://verilator.org
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// 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
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "V3PchAstNoMT.h"
|
||||
|
||||
#include "V3Ast.h"
|
||||
#include "V3AstPatterns.h"
|
||||
#include "V3Dfg.h"
|
||||
#include "V3DfgPasses.h"
|
||||
#include "V3File.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//============================================================================
|
||||
// Accumulates and dumps the pattern statistics
|
||||
|
||||
class V3PatternStats VL_NOT_FINAL {
|
||||
public:
|
||||
static constexpr uint32_t MIN_PATTERN_DEPTH = 1;
|
||||
static constexpr uint32_t MAX_PATTERN_DEPTH = 4;
|
||||
|
||||
private:
|
||||
const std::string m_what; // Description of what is being dumped
|
||||
// Maps from pattern to the number of times it appears, for each pattern depth
|
||||
std::vector<std::unordered_map<std::string, size_t>> m_patternCounts{MAX_PATTERN_DEPTH + 1};
|
||||
|
||||
void dump(std::ostream& os) {
|
||||
using Line = std::pair<std::string, size_t>;
|
||||
for (uint32_t i = MIN_PATTERN_DEPTH; i <= MAX_PATTERN_DEPTH; ++i) {
|
||||
os << m_what << " patterns with depth " << i << '\n';
|
||||
|
||||
// Pick up pattern accumulators with given depth
|
||||
auto& patternCounts = m_patternCounts[i];
|
||||
|
||||
// Remove patterns also present at shallower depths
|
||||
for (uint32_t j = MIN_PATTERN_DEPTH; j < i; ++j) {
|
||||
for (const auto& pair : m_patternCounts[j]) patternCounts.erase(pair.first);
|
||||
}
|
||||
|
||||
// Sort patterns, first by descending frequency, then lexically
|
||||
std::vector<Line> lines;
|
||||
lines.reserve(patternCounts.size());
|
||||
for (const auto& pair : patternCounts) lines.emplace_back(pair);
|
||||
std::sort(lines.begin(), lines.end(), [](const Line& a, const Line& b) {
|
||||
if (a.second != b.second) return a.second > b.second;
|
||||
return a.first < b.first;
|
||||
});
|
||||
|
||||
// Print each pattern
|
||||
for (const auto& line : lines) {
|
||||
os << ' ' << std::setw(12) << std::right << line.second;
|
||||
os << ' ' << std::left << line.first << '\n';
|
||||
}
|
||||
|
||||
// Trailing new-line to separate sections
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
V3PatternStats(const std::string& what)
|
||||
: m_what{what} {}
|
||||
~V3PatternStats() = default;
|
||||
|
||||
void accumulate(const std::string& pattern, uint32_t depth) {
|
||||
m_patternCounts[depth][pattern] += 1;
|
||||
}
|
||||
|
||||
void dumpToFile(const std::string& filename) {
|
||||
// Open, write, close
|
||||
const std::unique_ptr<std::ofstream> ofp{V3File::new_ofstream(filename)};
|
||||
if (ofp->fail()) v3fatal("Can't write file: " << filename);
|
||||
dump(*ofp);
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
// V3AstPatterns top level
|
||||
|
||||
void V3AstPatterns::dumpAll(const AstNetlist* nodep, const std::string& suffix) {
|
||||
UINFO(2, __FUNCTION__ << ":");
|
||||
V3PatternStats patternStats{"AST"};
|
||||
nodep->foreach([&](const AstNodeExpr* exprp) {
|
||||
for (uint32_t i = V3PatternStats::MIN_PATTERN_DEPTH;
|
||||
i <= V3PatternStats::MAX_PATTERN_DEPTH; ++i) {
|
||||
patternStats.accumulate(exprp->patternString(i), i);
|
||||
}
|
||||
});
|
||||
const std::string fileName = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix()
|
||||
+ "__ast_patterns_" + suffix + ".txt";
|
||||
patternStats.dumpToFile(fileName);
|
||||
V3Global::dumpCheckGlobalTree("astpatterns", 0, false, false);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// V3DfgPasses top level
|
||||
|
||||
void V3DfgPasses::dumpPatterns(const std::vector<std::unique_ptr<DfgGraph>>& graphs,
|
||||
const std::string& suffix) {
|
||||
V3PatternStats patternStats{"DFG"};
|
||||
for (auto& cp : graphs) {
|
||||
cp->forEachVertex([&](const DfgVertex& vtx) {
|
||||
for (uint32_t i = V3PatternStats::MIN_PATTERN_DEPTH;
|
||||
i <= V3PatternStats::MAX_PATTERN_DEPTH; ++i) {
|
||||
patternStats.accumulate(vtx.patternString(i), i);
|
||||
}
|
||||
});
|
||||
}
|
||||
const std::string fileName = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix()
|
||||
+ "__dfg_patterns" + suffix + ".txt";
|
||||
patternStats.dumpToFile(fileName);
|
||||
}
|
||||
|
|
@ -35,15 +35,12 @@ class StatsVisitor final : public VNVisitorConst {
|
|||
struct Counters final {
|
||||
// Nodes of given type
|
||||
std::array<uint64_t, VNType::NUM_TYPES()> m_statTypeCount{};
|
||||
// Nodes of given type with given type immediate child
|
||||
std::array<std::array<uint64_t, VNType::NUM_TYPES()>, VNType::NUM_TYPES()> m_statAbove{};
|
||||
// Prediction of given type
|
||||
std::array<uint64_t, VBranchPred::_ENUM_END> m_statPred{};
|
||||
};
|
||||
|
||||
// STATE
|
||||
const bool m_fastOnly; // When true, consider only fast functions
|
||||
const AstNodeExpr* m_parentExprp = nullptr; // Parent expression
|
||||
Counters m_counters; // The actual counts we will display
|
||||
Counters m_dumpster; // Alternate buffer to make discarding parts of the tree easier
|
||||
Counters* m_accump; // The currently active accumulator
|
||||
|
|
@ -75,14 +72,6 @@ class StatsVisitor final : public VNVisitorConst {
|
|||
countThenIterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstNodeExpr* nodep) override {
|
||||
// Count expression combinations
|
||||
if (m_parentExprp) ++m_accump->m_statAbove[m_parentExprp->type()][nodep->type()];
|
||||
VL_RESTORER(m_parentExprp);
|
||||
m_parentExprp = nodep;
|
||||
countThenIterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
// Track prediction
|
||||
++m_accump->m_statPred[nodep->branchPred()];
|
||||
|
|
@ -148,15 +137,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Expression combinations
|
||||
for (size_t t1 = 0; t1 < VNType::NUM_TYPES(); ++t1) {
|
||||
for (size_t t2 = 0; t2 < VNType::NUM_TYPES(); ++t2) {
|
||||
if (const uint64_t c = m_counters.m_statAbove[t1][t2]) {
|
||||
addStat("Expr combination, " + typeName(t1) + " over " + typeName(t2), c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Branch predictions
|
||||
for (int t = 0; t < VBranchPred::_ENUM_END; ++t) {
|
||||
if (const uint64_t c = m_counters.m_statPred[t]) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "V3AssertNfa.h"
|
||||
#include "V3AssertPre.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3AstPatterns.h"
|
||||
#include "V3Begin.h"
|
||||
#include "V3Branch.h"
|
||||
#include "V3Broken.h"
|
||||
|
|
@ -541,6 +542,8 @@ static void process() {
|
|||
V3Const::constifyAll(v3Global.rootp());
|
||||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
|
||||
if (v3Global.opt.dumpAstPatterns()) V3AstPatterns::dumpAll(v3Global.rootp(), "prec");
|
||||
|
||||
// Here down, widthMin() is the Verilog width, and width() is the C++ width
|
||||
// Bits between widthMin() and width() are irrelevant, but may be non-zero.
|
||||
v3Global.widthMinUsage(VWidthMinUsage::VERILOG_WIDTH);
|
||||
|
|
@ -635,6 +638,8 @@ static void process() {
|
|||
}
|
||||
}
|
||||
|
||||
if (v3Global.opt.dumpAstPatterns()) V3AstPatterns::dumpAll(v3Global.rootp(), "emit");
|
||||
|
||||
// Output the text
|
||||
if (!v3Global.opt.lintOnly() && !v3Global.opt.serializeOnly()
|
||||
&& !v3Global.opt.dpiHdrOnly()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,251 @@
|
|||
AST patterns with depth 1
|
||||
126 (CONST #A):a/a
|
||||
54 (VARREF):a/b
|
||||
36 (CCAST (VARREF):a/b):a/b
|
||||
34 (AND (CONST #A):a/a _:a/1):a/1
|
||||
29 (VARREF):a/a
|
||||
23 (CONST ZERO):a/a
|
||||
21 (VARREF):(w64)u[1:0]
|
||||
20 (CCAST _:a/1):a/1
|
||||
18 (AND (CONST #A):a/a _:a/a):a/a
|
||||
18 (SHIFTR _:a/b (CONST #A):a/a):a/1
|
||||
17 (VARREF):a/1
|
||||
15 (SHIFTL _:a/1 (CONST #A):a/a):a/a
|
||||
14 (NEGATE _:a/1):a/a
|
||||
12 (AND (CONST #A):a/a _:a/b):a/b
|
||||
12 (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):a/a):b/b
|
||||
12 (NOT _:a/b):a/b
|
||||
12 (VARREF):(w64)u[0:0]
|
||||
11 (OR _:a/a _:a/b):a/c
|
||||
9 (OR _:a/a _:a/1):a/b
|
||||
9 (VARREF):(G/str)
|
||||
8 (CCAST _:a/a):a/a
|
||||
8 (CCAST _:a/a):b/b
|
||||
8 (CRESET):a/a
|
||||
8 (NOT _:a/a):a/a
|
||||
8 (REDXOR _:a/b):a/1
|
||||
7 (SHIFTL _:a/b (CONST #A):a/a):a/a
|
||||
6 (AND _:a/b _:a/b):a/b
|
||||
6 (REDXOR _:a/a):b/1
|
||||
5 (CCAST _:a/a):b/1
|
||||
5 (OR _:a/a _:a/a):a/a
|
||||
4 (ADD _:a/a (VARREF):a/a):a/a
|
||||
4 (ARRAYSEL (VARREF):(w64)u[0:0] (CONST ZERO):a/a):b/b
|
||||
4 (CCAST (CONST #A):a/a):a/a
|
||||
4 (CCAST (VARREF):a/1):a/1
|
||||
4 (CCAST _:a/1):b/1
|
||||
4 (CONST #A):(G/str)
|
||||
4 (CONST #A):a/1
|
||||
4 (NEGATE _:a/1):a/b
|
||||
4 (SHIFTL _:a/a (CONST #A):b/b):a/a
|
||||
3 (AND (VARREF):a/a (CONST #A):b/b):a/a
|
||||
3 (CONST ZERO):a/1
|
||||
3 (CRESET):(w64)u[0:0]
|
||||
3 (CRESET):(w64)u[1:0]
|
||||
3 (NOT _:a/1):a/1
|
||||
3 (OR (CONST #A):a/a _:a/a):a/a
|
||||
2 (CCALL [(VARREF):(w64)u[0:0], (VARREF):(w64)u[0:0]]):a/a
|
||||
2 (CCALL [(VARREF):(w64)u[0:0]]):a/1
|
||||
2 (CCALL [(VARREF):(w64)u[1:0], (VARREF):(w64)u[1:0]]):a/a
|
||||
2 (CCALL [(VARREF):(w64)u[1:0]]):a/1
|
||||
2 (CCALL []):a/1
|
||||
2 (CRESET):(G/str)
|
||||
2 (GT (CONST #A):a/a (VARREF):a/a):a/1
|
||||
2 (LT (CONST #A):a/a (VARREF):a/a):a/1
|
||||
2 (NEQ _:a/b _:a/b):a/1
|
||||
2 (OR _:a/a _:a/a):a/b
|
||||
2 (REDXOR (VARREF):a/b):a/1
|
||||
2 (REDXOR _:a/a):a/1
|
||||
2 (REDXOR _:a/b):c/1
|
||||
2 (SHIFTR _:a/a (CONST #A):b/b):a/a
|
||||
1 (ARRAYSEL (VARREF):(w64)u[0:0] (VARREF):a/a):b/b
|
||||
1 (ARRAYSEL (VARREF):(w64)u[1:0] (CONST #A):a/a):b/b
|
||||
1 (ARRAYSEL (VARREF):(w64)u[1:0] (VARREF):a/a):b/b
|
||||
1 (CCAST _:a/1):b/b
|
||||
1 (CCAST _:a/b):a/b
|
||||
1 (CCAST _:a/b):c/c
|
||||
1 (CRESET):1/1
|
||||
1 (NEQ _:a/b _:a/b):a/c
|
||||
1 (VARREF):1/1
|
||||
|
||||
AST patterns with depth 2
|
||||
18 (AND (CONST #A):a/a (SHIFTR _:a/b (CONST #A):a/a):a/1):a/1
|
||||
18 (CCAST (AND (CONST #A):a/a _:a/1):a/1):a/1
|
||||
18 (SHIFTR (CCAST (VARREF):a/b):a/b (CONST #A):a/a):a/1
|
||||
14 (AND (CONST #A):a/a (SHIFTL _:a/1 (CONST #B):a/a):a/a):a/a
|
||||
12 (NOT (CCAST (VARREF):a/b):a/b):a/b
|
||||
10 (NEGATE (CCAST _:a/1):a/1):a/a
|
||||
8 (CCAST (CCAST _:a/a):a/a):b/b
|
||||
8 (CCAST (NOT _:a/a):a/a):a/a
|
||||
8 (NOT (NEGATE _:a/1):a/a):a/a
|
||||
8 (OR (AND (CONST #A):a/a _:a/a):a/a (AND (CONST #B):a/a _:a/1):a/1):a/b
|
||||
8 (REDXOR (AND (CONST #A):a/a _:a/b):a/b):a/1
|
||||
6 (AND (CONST #A):a/a (AND _:a/b _:a/b):a/b):a/b
|
||||
6 (AND (NOT _:a/b):a/b (NOT _:a/b):a/b):a/b
|
||||
6 (OR (AND (CONST #A):a/a _:a/a):a/a (OR _:a/a _:a/1):a/b):a/c
|
||||
6 (SHIFTL (OR _:a/a _:a/b):a/c (CONST #A):a/a):a/a
|
||||
5 (AND (CONST #A):a/a (CCAST _:b/b):a/1):a/1
|
||||
4 (ADD (CCAST (CONST #A):a/a):a/a (VARREF):a/a):a/a
|
||||
4 (AND (CONST #A):a/a (NEGATE _:a/1):a/b):a/b
|
||||
4 (AND (CONST #A):a/a (REDXOR _:a/b):a/1):a/1
|
||||
4 (AND (CONST #A):a/a (REDXOR _:b/b):a/1):a/1
|
||||
4 (CCAST (CCAST _:a/1):a/1):b/1
|
||||
4 (NEGATE (CCAST _:a/1):a/1):a/b
|
||||
4 (NEGATE (CCAST _:a/1):b/1):b/b
|
||||
4 (REDXOR (NEGATE _:a/1):a/a):b/1
|
||||
4 (SHIFTL (CCAST _:a/a):b/b (CONST #A):a/a):b/b
|
||||
4 (SHIFTL (REDXOR _:a/b):a/1 (CONST #A):a/a):a/a
|
||||
3 (AND (CONST #A):a/a (NOT _:a/1):a/1):a/1
|
||||
3 (OR (CONST #A):a/a (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):b/b):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (ARRAYSEL (VARREF):(w64)u[0:0] (CONST ZERO):b/b):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):b/b):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (OR _:a/a _:a/a):a/b):a/b
|
||||
2 (CCAST (SHIFTR _:a/a (CONST #A):b/b):a/a):b/1
|
||||
2 (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/1
|
||||
2 (NOT (CCAST _:a/1):a/1):a/1
|
||||
2 (OR (OR _:a/a _:a/a):a/a (OR _:a/a _:a/b):a/c):a/d
|
||||
2 (OR (SHIFTL _:a/a (CONST #A):b/b):a/a (CCAST _:b/b):a/a):a/a
|
||||
2 (OR (SHIFTL _:a/a (CONST #A):b/b):a/a (CCAST _:b/b):a/a):a/c
|
||||
2 (OR (SHIFTL _:a/b (CONST #A):a/a):a/a (OR _:a/a _:a/1):a/c):a/d
|
||||
2 (OR (SHIFTL _:a/b (CONST #A):a/a):a/a (SHIFTL _:a/b (CONST #B):a/a):a/a):a/a
|
||||
2 (REDXOR (AND (CONST #A):a/a _:a/b):a/b):c/1
|
||||
2 (REDXOR (NEGATE _:a/1):a/a):a/1
|
||||
2 (REDXOR (OR _:a/a _:a/a):a/a):b/1
|
||||
2 (SHIFTL (CCAST (VARREF):a/1):a/1 (CONST #A):a/a):a/a
|
||||
2 (SHIFTL (REDXOR (VARREF):a/b):a/1 (CONST #A):a/a):a/a
|
||||
2 (SHIFTL (REDXOR _:a/a):a/1 (CONST #A):a/a):a/a
|
||||
2 (SHIFTL (REDXOR _:a/a):b/1 (CONST #A):b/b):b/b
|
||||
2 (SHIFTL (REDXOR _:a/b):c/1 (CONST #A):c/c):c/c
|
||||
2 (SHIFTR (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):a/a):b/b (CONST #A):a/a):b/b
|
||||
1 (CCAST (ARRAYSEL (VARREF):(w64)u[0:0] (CONST ZERO):a/a):b/b):a/1
|
||||
1 (CCAST (ARRAYSEL (VARREF):(w64)u[1:0] (CONST #A):a/a):b/b):a/1
|
||||
1 (CCAST (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):a/a):b/b):a/1
|
||||
1 (CCAST (CCALL [(VARREF):(w64)u[0:0]]):a/1):a/1
|
||||
1 (CCAST (CCALL [(VARREF):(w64)u[1:0]]):a/1):a/1
|
||||
1 (CCAST (CCAST (VARREF):a/1):a/1):b/b
|
||||
1 (CCAST (CCAST _:a/b):a/b):c/c
|
||||
1 (CCAST (OR _:a/a _:a/b):a/c):a/c
|
||||
1 (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/c
|
||||
1 (NOT (CCAST (VARREF):a/1):a/1):a/1
|
||||
1 (OR (AND (CONST #A):a/a _:a/a):a/a (CCAST _:b/1):a/a):a/a
|
||||
1 (OR (SHIFTL _:a/1 (CONST #A):a/a):a/a (NEQ _:a/b _:a/b):a/1):a/c
|
||||
1 (OR (SHIFTL _:a/b (CONST #A):a/a):a/a (OR _:a/a _:a/1):a/b):a/c
|
||||
1 (SHIFTL (NEQ _:a/b _:a/b):a/1 (CONST #A):a/a):a/a
|
||||
1 (SHIFTL (NEQ _:a/b _:a/b):a/c (CONST #A):a/a):a/a
|
||||
|
||||
AST patterns with depth 3
|
||||
18 (AND (CONST #A):a/a (SHIFTR (CCAST (VARREF):a/b):a/b (CONST #A):a/a):a/1):a/1
|
||||
18 (CCAST (AND (CONST #A):a/a (SHIFTR _:a/b (CONST #A):a/a):a/1):a/1):a/1
|
||||
10 (NEGATE (CCAST (AND (CONST #A):a/a _:a/1):a/1):a/1):a/a
|
||||
8 (CCAST (CCAST (NOT _:a/a):a/a):a/a):b/b
|
||||
8 (CCAST (NOT (NEGATE _:a/1):a/a):a/a):a/a
|
||||
8 (NOT (NEGATE (CCAST _:a/1):a/1):a/a):a/a
|
||||
6 (AND (CONST #A):a/a (AND (NOT _:a/b):a/b (NOT _:a/b):a/b):a/b):a/b
|
||||
6 (AND (NOT (CCAST (VARREF):a/b):a/b):a/b (NOT (CCAST (VARREF):a/b):a/b):a/b):a/b
|
||||
6 (OR (AND (CONST #A):a/a (SHIFTL _:a/1 (CONST #B):a/a):a/a):a/a (OR (AND (CONST #B):a/a _:a/a):a/a (AND (CONST #C):a/a _:a/1):a/1):a/b):a/c
|
||||
6 (SHIFTL (OR (AND (CONST #A):a/a _:a/a):a/a (OR _:a/a _:a/1):a/b):a/c (CONST #B):a/a):a/a
|
||||
4 (AND (CONST #A):a/a (NEGATE (CCAST _:a/1):a/1):a/b):a/b
|
||||
4 (AND (CONST #A):a/a (REDXOR (AND (CONST #B):a/a _:a/b):a/b):a/1):a/1
|
||||
4 (AND (CONST #A):a/a (SHIFTL (REDXOR _:a/b):a/1 (CONST #B):a/a):a/a):a/a
|
||||
4 (CCAST (CCAST (AND (CONST #A):a/a _:a/1):a/1):a/1):b/1
|
||||
4 (NEGATE (CCAST (AND (CONST #A):a/a _:a/1):a/1):a/1):a/b
|
||||
4 (NEGATE (CCAST (CCAST _:a/1):a/1):b/1):b/b
|
||||
4 (OR (AND (CONST #A):a/a (SHIFTL _:a/1 (CONST #B):a/a):a/a):a/a (AND (CONST #B):a/a (REDXOR _:a/b):a/1):a/1):a/c
|
||||
4 (OR (AND (CONST #A):a/a (SHIFTL _:a/1 (CONST #B):a/a):a/a):a/a (AND (CONST #B):a/a (REDXOR _:b/b):a/1):a/1):a/c
|
||||
4 (REDXOR (AND (CONST #A):a/a (AND _:a/b _:a/b):a/b):a/b):a/1
|
||||
4 (REDXOR (AND (CONST #A):a/a (NEGATE _:a/1):a/b):a/b):a/1
|
||||
4 (REDXOR (NEGATE (CCAST _:a/1):b/1):b/b):a/1
|
||||
4 (SHIFTL (CCAST (CCAST _:a/a):a/a):b/b (CONST #A):a/a):b/b
|
||||
4 (SHIFTL (REDXOR (AND (CONST #A):a/a _:a/b):a/b):a/1 (CONST #B):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (NOT (CCAST _:a/1):a/1):a/1):a/1
|
||||
2 (AND (CONST #A):a/a (OR (SHIFTL _:a/a (CONST #B):b/b):a/a (CCAST _:b/b):a/a):a/c):a/c
|
||||
2 (AND (CONST #A):a/a (REDXOR (NEGATE _:b/1):b/b):a/1):a/1
|
||||
2 (AND (CONST #A):a/a (REDXOR (OR _:b/b _:b/b):b/b):a/1):a/1
|
||||
2 (AND (CONST #A):a/a (SHIFTL (CCAST (VARREF):a/1):a/1 (CONST #B):a/a):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (SHIFTL (REDXOR (VARREF):a/b):a/1 (CONST #B):a/a):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (SHIFTL (REDXOR _:a/a):a/1 (CONST #B):a/a):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (SHIFTL (REDXOR _:b/b):a/1 (CONST #B):a/a):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (SHIFTL (REDXOR _:b/c):a/1 (CONST #B):a/a):a/a):a/a
|
||||
2 (CCAST (SHIFTR (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):a/a):b/b (CONST #A):a/a):b/b):a/1
|
||||
2 (OR (OR (SHIFTL _:a/b (CONST #A):a/a):a/a (SHIFTL _:a/b (CONST #B):a/a):a/a):a/a (OR (SHIFTL _:a/b (CONST #C):a/a):a/a (OR _:a/a _:a/1):a/c):a/d):a/e
|
||||
2 (OR (SHIFTL (CCAST _:a/a):b/b (CONST #A):a/a):b/b (CCAST (CCAST _:a/a):a/a):b/b):b/b
|
||||
2 (OR (SHIFTL (CCAST _:a/a):b/b (CONST #A):a/a):b/b (CCAST (CCAST _:a/a):a/a):b/b):b/c
|
||||
2 (OR (SHIFTL (OR _:a/a _:a/b):a/c (CONST #A):a/a):a/a (OR (AND (CONST #A):a/a _:a/a):a/a (AND (CONST #B):a/a _:a/1):a/1):a/b):a/d
|
||||
2 (OR (SHIFTL (OR _:a/a _:a/b):a/c (CONST #A):a/a):a/a (SHIFTL (OR _:a/a _:a/b):a/c (CONST #B):a/a):a/a):a/a
|
||||
2 (REDXOR (AND (CONST #A):a/a (OR _:a/a _:a/a):a/b):a/b):c/1
|
||||
2 (REDXOR (NEGATE (CCAST _:a/1):a/1):a/a):a/1
|
||||
2 (REDXOR (OR (SHIFTL _:a/a (CONST #A):b/b):a/a (CCAST _:b/b):a/a):a/a):b/1
|
||||
2 (SHIFTL (REDXOR (AND (CONST #A):a/a _:a/b):a/b):c/1 (CONST #B):c/c):c/c
|
||||
2 (SHIFTL (REDXOR (NEGATE _:a/1):a/a):a/1 (CONST #A):a/a):a/a
|
||||
2 (SHIFTL (REDXOR (NEGATE _:a/1):a/a):b/1 (CONST #A):b/b):b/b
|
||||
1 (AND (CONST #A):a/a (CCAST (ARRAYSEL (VARREF):(w64)u[0:0] (CONST ZERO):a/a):b/b):a/1):a/1
|
||||
1 (AND (CONST #A):a/a (CCAST (ARRAYSEL (VARREF):(w64)u[1:0] (CONST #A):a/a):b/b):a/1):a/1
|
||||
1 (AND (CONST #A):a/a (CCAST (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):a/a):b/b):a/1):a/1
|
||||
1 (AND (CONST #A):a/a (CCAST (SHIFTR _:b/b (CONST #A):a/a):b/b):a/1):a/1
|
||||
1 (AND (CONST #A):a/a (CCAST (SHIFTR _:b/b (CONST #B):a/a):b/b):a/1):a/1
|
||||
1 (AND (CONST #A):a/a (NOT (CCAST (VARREF):a/1):a/1):a/1):a/1
|
||||
1 (CCAST (CCAST (OR _:a/a _:a/b):a/c):a/c):d/d
|
||||
1 (CCAST (OR (SHIFTL _:a/b (CONST #A):a/a):a/a (OR _:a/a _:a/1):a/b):a/c):a/c
|
||||
1 (NOT (CCAST (CCALL [(VARREF):(w64)u[0:0]]):a/1):a/1):a/1
|
||||
1 (NOT (CCAST (CCALL [(VARREF):(w64)u[1:0]]):a/1):a/1):a/1
|
||||
1 (OR (AND (CONST #A):a/a (ARRAYSEL (VARREF):(w64)u[0:0] (CONST ZERO):b/b):a/a):a/a (CCAST (CCAST (VARREF):b/1):b/1):a/a):a/a
|
||||
1 (OR (SHIFTL (NEQ _:a/b _:a/b):a/1 (CONST #A):a/a):a/a (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/1):a/c
|
||||
1 (OR (SHIFTL (NEQ _:a/b _:a/b):a/c (CONST #A):a/a):a/a (OR (SHIFTL _:a/1 (CONST #B):a/a):a/a (NEQ _:a/b _:a/b):a/1):a/c):a/b
|
||||
1 (SHIFTL (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/1 (CONST #A):a/a):a/a
|
||||
1 (SHIFTL (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/c (CONST #A):a/a):a/a
|
||||
|
||||
AST patterns with depth 4
|
||||
18 (CCAST (AND (CONST #A):a/a (SHIFTR (CCAST (VARREF):a/b):a/b (CONST #A):a/a):a/1):a/1):a/1
|
||||
10 (NEGATE (CCAST (AND (CONST #A):a/a (SHIFTR _:a/b (CONST #A):a/a):a/1):a/1):a/1):a/a
|
||||
8 (CCAST (CCAST (NOT (NEGATE _:a/1):a/a):a/a):a/a):b/b
|
||||
8 (CCAST (NOT (NEGATE (CCAST _:a/1):a/1):a/a):a/a):a/a
|
||||
8 (NOT (NEGATE (CCAST (AND (CONST #A):a/a _:a/1):a/1):a/1):a/a):a/a
|
||||
6 (AND (CONST #A):a/a (AND (NOT (CCAST (VARREF):a/b):a/b):a/b (NOT (CCAST (VARREF):a/b):a/b):a/b):a/b):a/b
|
||||
4 (AND (CONST #A):a/a (NEGATE (CCAST (AND (CONST #B):a/a _:a/1):a/1):a/1):a/b):a/b
|
||||
4 (AND (CONST #A):a/a (SHIFTL (REDXOR (AND (CONST #B):a/a _:a/b):a/b):a/1 (CONST #C):a/a):a/a):a/a
|
||||
4 (CCAST (CCAST (AND (CONST #A):a/a (SHIFTR _:a/b (CONST #A):a/a):a/1):a/1):a/1):c/1
|
||||
4 (NEGATE (CCAST (AND (CONST #A):a/a (SHIFTR _:a/b (CONST #A):a/a):a/1):a/1):a/1):a/c
|
||||
4 (NEGATE (CCAST (CCAST (AND (CONST #A):a/a _:a/1):a/1):a/1):b/1):b/b
|
||||
4 (REDXOR (AND (CONST #A):a/a (AND (NOT _:a/b):a/b (NOT _:a/b):a/b):a/b):a/b):a/1
|
||||
4 (REDXOR (AND (CONST #A):a/a (NEGATE (CCAST _:a/1):a/1):a/b):a/b):a/1
|
||||
4 (REDXOR (NEGATE (CCAST (CCAST _:a/1):a/1):b/1):b/b):a/1
|
||||
4 (SHIFTL (CCAST (CCAST (NOT _:a/a):a/a):a/a):b/b (CONST #A):a/a):b/b
|
||||
4 (SHIFTL (OR (AND (CONST #A):a/a (SHIFTL _:a/1 (CONST #B):a/a):a/a):a/a (OR (AND (CONST #B):a/a _:a/a):a/a (AND (CONST #C):a/a _:a/1):a/1):a/b):a/c (CONST #D):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (OR (SHIFTL (CCAST _:b/b):a/a (CONST #B):b/b):a/a (CCAST (CCAST _:b/b):b/b):a/a):a/c):a/c
|
||||
2 (AND (CONST #A):a/a (REDXOR (AND (CONST #B):a/a (AND _:a/b _:a/b):a/b):a/b):a/1):a/1
|
||||
2 (AND (CONST #A):a/a (REDXOR (AND (CONST #B):a/a (NEGATE _:a/1):a/b):a/b):a/1):a/1
|
||||
2 (AND (CONST #A):a/a (REDXOR (NEGATE (CCAST _:a/1):b/1):b/b):a/1):a/1
|
||||
2 (AND (CONST #A):a/a (REDXOR (OR (SHIFTL _:b/b (CONST #B):a/a):b/b (CCAST _:a/a):b/b):b/b):a/1):a/1
|
||||
2 (AND (CONST #A):a/a (SHIFTL (REDXOR (AND (CONST #B):b/b _:b/c):b/c):a/1 (CONST #C):a/a):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (SHIFTL (REDXOR (NEGATE _:a/1):a/a):a/1 (CONST #B):a/a):a/a):a/a
|
||||
2 (AND (CONST #A):a/a (SHIFTL (REDXOR (NEGATE _:b/1):b/b):a/1 (CONST #B):a/a):a/a):a/a
|
||||
2 (OR (AND (CONST #A):a/a (SHIFTL (CCAST (VARREF):a/1):a/1 (CONST #B):a/a):a/a):a/a (OR (AND (CONST #B):a/a (SHIFTL _:a/1 (CONST #C):a/a):a/a):a/a (AND (CONST #C):a/a (REDXOR _:a/b):a/1):a/1):a/c):a/d
|
||||
2 (OR (AND (CONST #A):a/a (SHIFTL (REDXOR (VARREF):a/b):a/1 (CONST #B):a/a):a/a):a/a (OR (AND (CONST #B):a/a (SHIFTL _:a/1 (CONST #C):a/a):a/a):a/a (AND (CONST #C):a/a (REDXOR _:a/b):a/1):a/1):a/c):a/d
|
||||
2 (OR (AND (CONST #A):a/a (SHIFTL (REDXOR _:a/a):a/1 (CONST #B):a/a):a/a):a/a (OR (AND (CONST #B):a/a (SHIFTL _:a/1 (CONST #C):a/a):a/a):a/a (AND (CONST #C):a/a (REDXOR _:b/b):a/1):a/1):a/c):a/d
|
||||
2 (OR (AND (CONST #A):a/a (SHIFTL (REDXOR _:a/b):a/1 (CONST #B):a/a):a/a):a/a (AND (CONST #B):a/a (REDXOR (AND (CONST #C):a/a _:a/b):a/b):a/1):a/1):a/c
|
||||
2 (OR (AND (CONST #A):a/a (SHIFTL (REDXOR _:a/b):a/1 (CONST #B):a/a):a/a):a/a (AND (CONST #B):a/a (REDXOR (AND (CONST #C):a/a _:a/c):a/c):a/1):a/1):a/d
|
||||
2 (OR (AND (CONST #A):a/a (SHIFTL (REDXOR _:b/b):a/1 (CONST #B):a/a):a/a):a/a (AND (CONST #B):a/a (REDXOR (OR _:b/b _:b/b):b/b):a/1):a/1):a/c
|
||||
2 (OR (AND (CONST #A):a/a (SHIFTL (REDXOR _:b/c):a/1 (CONST #B):a/a):a/a):a/a (AND (CONST #B):a/a (REDXOR (NEGATE _:b/1):b/b):a/1):a/1):a/d
|
||||
2 (OR (OR (SHIFTL (OR _:a/a _:a/b):a/c (CONST #A):a/a):a/a (SHIFTL (OR _:a/a _:a/b):a/c (CONST #B):a/a):a/a):a/a (OR (SHIFTL (OR _:a/a _:a/b):a/c (CONST #C):a/a):a/a (OR (AND (CONST #C):a/a _:a/a):a/a (AND (CONST #D):a/a _:a/1):a/1):a/b):a/d):a/e
|
||||
2 (OR (SHIFTL (CCAST (CCAST _:a/a):a/a):b/b (CONST #A):a/a):b/b (CCAST (CCAST (NOT _:a/a):a/a):a/a):b/b):b/b
|
||||
2 (OR (SHIFTL (CCAST (CCAST _:a/a):a/a):b/b (CONST #A):a/a):b/b (CCAST (CCAST (NOT _:a/a):a/a):a/a):b/b):b/c
|
||||
2 (OR (SHIFTL (OR (AND (CONST #A):a/a _:a/a):a/a (OR _:a/a _:a/1):a/b):a/c (CONST #B):a/a):a/a (OR (AND (CONST #B):a/a (SHIFTL _:a/1 (CONST #C):a/a):a/a):a/a (AND (CONST #C):a/a (REDXOR _:d/d):a/1):a/1):a/b):a/e
|
||||
2 (OR (SHIFTL (OR (AND (CONST #A):a/a _:a/a):a/a (OR _:a/a _:a/1):a/b):a/c (CONST #B):a/a):a/a (SHIFTL (OR (AND (CONST #A):a/a _:a/a):a/a (OR _:a/a _:a/1):a/b):a/c (CONST #C):a/a):a/a):a/a
|
||||
2 (REDXOR (AND (CONST #A):a/a (OR (SHIFTL _:a/a (CONST #B):b/b):a/a (CCAST _:b/b):a/a):a/c):a/c):b/1
|
||||
2 (REDXOR (NEGATE (CCAST (AND (CONST #A):a/a _:a/1):a/1):a/1):a/a):a/1
|
||||
2 (REDXOR (OR (SHIFTL (CCAST _:a/a):b/b (CONST #A):a/a):b/b (CCAST (CCAST _:a/a):a/a):b/b):b/b):a/1
|
||||
2 (SHIFTL (OR (AND (CONST #A):a/a (SHIFTL _:a/1 (CONST #B):a/a):a/a):a/a (OR (AND (CONST #B):a/a _:a/a):a/a (AND (CONST #C):a/a _:a/1):a/1):a/b):a/c (CONST #B):a/a):a/a
|
||||
2 (SHIFTL (REDXOR (AND (CONST #A):a/a (AND _:a/b _:a/b):a/b):a/b):a/1 (CONST #B):a/a):a/a
|
||||
2 (SHIFTL (REDXOR (AND (CONST #A):a/a (NEGATE _:a/1):a/b):a/b):a/1 (CONST #B):a/a):a/a
|
||||
2 (SHIFTL (REDXOR (AND (CONST #A):a/a (OR _:a/a _:a/a):a/b):a/b):c/1 (CONST #B):c/c):c/c
|
||||
2 (SHIFTL (REDXOR (NEGATE (CCAST _:a/1):a/1):a/a):a/1 (CONST #A):a/a):a/a
|
||||
2 (SHIFTL (REDXOR (NEGATE (CCAST _:a/1):b/1):b/b):a/1 (CONST #A):a/a):a/a
|
||||
1 (AND (CONST #A):a/a (CCAST (SHIFTR (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):a/a):b/b (CONST #A):a/a):b/b):a/1):a/1
|
||||
1 (AND (CONST #A):a/a (CCAST (SHIFTR (ARRAYSEL (VARREF):(w64)u[1:0] (CONST ZERO):a/a):b/b (CONST #B):a/a):b/b):a/1):a/1
|
||||
1 (AND (CONST #A):a/a (NOT (CCAST (CCALL [(VARREF):(w64)u[0:0]]):a/1):a/1):a/1):a/1
|
||||
1 (AND (CONST #A):a/a (NOT (CCAST (CCALL [(VARREF):(w64)u[1:0]]):a/1):a/1):a/1):a/1
|
||||
1 (CCAST (CCAST (OR (SHIFTL _:a/b (CONST #A):a/a):a/a (OR _:a/a _:a/1):a/b):a/c):a/c):d/d
|
||||
1 (CCAST (OR (SHIFTL (NEQ _:a/b _:a/b):a/c (CONST #A):a/a):a/a (OR (SHIFTL _:a/1 (CONST #B):a/a):a/a (NEQ _:a/b _:a/b):a/1):a/c):a/b):a/b
|
||||
1 (OR (SHIFTL (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/1 (CONST #A):a/a):a/a (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/1):a/c
|
||||
1 (OR (SHIFTL (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/c (CONST #A):a/a):a/a (OR (SHIFTL (NEQ _:a/b _:a/b):a/1 (CONST #B):a/a):a/a (NEQ (CCAST (VARREF):a/b):a/b (CCAST (VARREF):a/b):a/b):a/1):a/c):a/b
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.compile(verilator_flags2=["--dump-ast-patterns", "--no-skip-identical"])
|
||||
|
||||
test.files_identical(test.obj_dir + "/" + test.vm_prefix + "__ast_patterns_emit.txt",
|
||||
test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (
|
||||
input wire [3:0] a,
|
||||
input wire [3:0] b,
|
||||
input wire [3:0] c,
|
||||
output wire [10:0] o
|
||||
);
|
||||
wire [3:0] x = ~a & ~b;
|
||||
wire [3:0] y = ~b & ~c;
|
||||
wire [3:0] z = ~c & ~a;
|
||||
wire [0:0] w1 = x[0];
|
||||
wire [7:0] w8 = {8{x[1]}};
|
||||
wire [15:0] w16 = {2{w8}};
|
||||
wire [31:0] w32 = {2{w16}};
|
||||
wire [63:0] w64a = {2{w32}};
|
||||
wire [63:0] w64b = {2{~w32}};
|
||||
wire [62:0] w63 = 63'({2{~w32}});
|
||||
wire [95:0] w96 = 96'(w64a);
|
||||
|
||||
assign o = {^x, ^y, ^z, ^w1, ^w8, ^w16, ^w32, ^w64a, ^w64b, ^w63, ^w96};
|
||||
endmodule
|
||||
Loading…
Reference in New Issue