diff --git a/bin/verilator b/bin/verilator index d1d40944e..5f5fd426f 100755 --- a/bin/verilator +++ b/bin/verilator @@ -379,6 +379,7 @@ detailed descriptions of these arguments. --dump- Enable dumping everything in source file --dump-defines Show preprocessor defines with -E --dump-dfg Enable dumping DfgGraphs to .dot files + --dump-dfg-patterns Enable dumping Dfg pattern statistics --dump-graph Enable dumping V3Graphs to .dot files --dump-inputs Enable dumping preprocessed input files --dump-tree Enable dumping Ast .tree files diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index dd16f6b19..eaf670669 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -478,6 +478,10 @@ Summary: Rarely needed. Enable dumping DfgGraph .dot debug files with dumping level 3. +.. option:: --dump-dfg-patterns + + Rarely needed. Enable dumping DfgGraph pattern statistics. + .. option:: --dump-graph Rarely needed. Enable dumping V3Graph .dot debug files with dumping diff --git a/src/V3Dfg.cpp b/src/V3Dfg.cpp index 20d2353ee..9a45eca16 100644 --- a/src/V3Dfg.cpp +++ b/src/V3Dfg.cpp @@ -936,6 +936,160 @@ void DfgVertex::unlinkDelete(DfgGraph& dfg) { delete this; } +class DfgPatternString final { + std::ostream& m_os; + + std::map m_internedConsts; // Interned constants + std::map m_internedSelLsbs; // Interned lsb value for selects + std::map m_internedWordWidths; // Interned widths + std::map m_internedWideWidths; // Interned widths + std::map m_internedVertices; // Interned vertices + // Multiplicity and depth of vertices + std::map> m_multiplicityAndDepth; + + static std::string toLetters(size_t value, bool lowerCase = false) { + const char base = lowerCase ? 'a' : 'A'; + std::string s; + do { s += static_cast(base + value % 26); } while (value /= 26); + return s; + } + + const std::string& internConst(const DfgConst& vtx) { + const auto pair = m_internedConsts.emplace(vtx.num().ascii(false), ""); + if (pair.second) pair.first->second += toLetters(m_internedConsts.size() - 1); + return pair.first->second; + } + + const std::string& internSelLsb(uint32_t value) { + const auto pair = m_internedSelLsbs.emplace(value, ""); + if (pair.second) pair.first->second += toLetters(m_internedSelLsbs.size() - 1); + return pair.first->second; + } + + const std::string& internWordWidth(uint32_t 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(uint32_t value) { + const auto pair = m_internedWideWidths.emplace(value, ""); + if (pair.second) pair.first->second += toLetters(m_internedWideWidths.size() - 1); + return pair.first->second; + } + + const std::string& internVertex(const DfgVertex& vtx) { + const auto pair = m_internedVertices.emplace(&vtx, ""); + if (pair.second) pair.first->second += toLetters(m_internedVertices.size() - 1); + return pair.first->second; + } + + void recordMultiplicityAndDepth(const DfgVertex& vtx, uint32_t depth) { + std::pair& value = m_multiplicityAndDepth + .emplace(std::piecewise_construct, // + std::forward_as_tuple(&vtx), // + std::forward_as_tuple(0, depth)) + .first->second; + value.first += 1; + value.second = std::max(value.second, depth); + if (!depth) return; + vtx.foreachSource([&](const DfgVertex& src) { + recordMultiplicityAndDepth(src, depth - 1); + return false; + }); + } + + // Render the vertx into ss, and return true if the recursion reached the given depth, + // meaning an S-expression with that nesting level has been rendered. + void render(const DfgVertex& vtx, uint32_t depth, bool isRoot = true) { + if (const DfgConst* const constp = vtx.cast()) { + // Base case 1: constant + if (constp->isZero()) { + m_os << "(CONST ZERO)"; + } else if (constp->isOnes()) { + m_os << "(CONST ONES)"; + } else { + m_os << "(CONST #" << internConst(*constp) << ')'; + } + } else if (!isRoot && m_multiplicityAndDepth.at(&vtx).first > 1) { + // Base case 2: vertex appearing multiple times + m_os << internVertex(vtx); + } else if (!vtx.foreachSource([&](const DfgVertex&) { return true; })) { + // Base case 3: vertex with no inputs (input variable) + m_os << '(' << vtx.typeName() << ')'; + } else if (depth == 0) { + // Base case 4: deep vertex (apperaing only once) + m_os << "_"; + } else { + // Recursively print an S-expression for the vertex + m_os << '('; + // Name + m_os << vtx.typeName(); + // Specials + if (const DfgSel* const selp = vtx.cast()) { + m_os << '@'; + if (selp->lsb() == 0) { + m_os << '0'; + } else { + m_os << internSelLsb(selp->lsb()); + } + } + // Operands + vtx.foreachSource([&](const DfgVertex& src) { + m_os << ' '; + render(src, depth - 1, false); + return false; + }); + // S-expression end + m_os << ')'; + } + + // Annotate type + m_os << ':'; + if (!vtx.dtype().isPacked()) { + vtx.dtype().astDtypep()->dumpSmall(m_os); + } else { + const uint32_t width = vtx.size(); + if (width == 1) { + m_os << '1'; + } else if (width <= VL_QUADSIZE) { + m_os << internWordWidth(width); + } else { + m_os << internWideWidth(width); + } + } + + // Mark it if it has multiple sinks + if (vtx.hasMultipleSinks()) m_os << '*'; + } + +public: + DfgPatternString(std::ostream& os, const DfgVertex& vtx, uint32_t depth) + : m_os{os} { + recordMultiplicityAndDepth(vtx, depth); + render(vtx, depth, false); + using Pair = std::pair; + std::vector vertices; + for (const auto& pair : m_multiplicityAndDepth) { + if (pair.second.first == 1) continue; + vertices.emplace_back(internVertex(*pair.first), pair.first); + } + std::sort(vertices.begin(), vertices.end(), [](const Pair& a, const Pair& b) { // + return a.first < b.first; + }); + for (const Pair& pair : vertices) { + m_os << " | " << pair.first << " is "; + render(*pair.second, m_multiplicityAndDepth.at(pair.second).second); + } + } +}; + +std::string DfgVertex::patternString(uint32_t depth) const { + std::ostringstream oss; + DfgPatternString{oss, *this, depth}; + return oss.str(); +} + //------------------------------------------------------------------------------ // DfgVisitor diff --git a/src/V3Dfg.h b/src/V3Dfg.h index fce033f9c..dd3016398 100644 --- a/src/V3Dfg.h +++ b/src/V3Dfg.h @@ -352,6 +352,9 @@ public: // Human-readable name for source operand with given index for debugging virtual std::string srcName(size_t idx) const = 0; + + // S-expression inspired dump of vertex and operands for debugging + std::string patternString(uint32_t depth = 0) const; }; // DfgVertex visitor diff --git a/src/V3DfgDumpPatterns.cpp b/src/V3DfgDumpPatterns.cpp index be7e765c3..18611f180 100644 --- a/src/V3DfgDumpPatterns.cpp +++ b/src/V3DfgDumpPatterns.cpp @@ -21,133 +21,27 @@ #include "V3DfgPasses.h" #include "V3File.h" -#include -#include #include class V3DfgPatternStats final { static constexpr uint32_t MIN_PATTERN_DEPTH = 1; static constexpr uint32_t MAX_PATTERN_DEPTH = 4; - std::map m_internedConsts; // Interned constants - std::map m_internedSelLsbs; // Interned lsb value for selects - std::map m_internedWordWidths; // Interned widths - std::map m_internedWideWidths; // Interned widths - std::map m_internedVertices; // Interned vertices - // Maps from pattern to the number of times it appears, for each pattern depth std::vector> m_patterCounts{MAX_PATTERN_DEPTH + 1}; - static std::string toLetters(size_t value, bool lowerCase = false) { - const char base = lowerCase ? 'a' : 'A'; - std::string s; - do { s += static_cast(base + value % 26); } while (value /= 26); - return s; - } - - const std::string& internConst(const DfgConst& vtx) { - const auto pair = m_internedConsts.emplace(vtx.num().ascii(false), "c"); - if (pair.second) pair.first->second += toLetters(m_internedConsts.size() - 1); - return pair.first->second; - } - - const std::string& internSelLsb(uint32_t value) { - const auto pair = m_internedSelLsbs.emplace(value, ""); - if (pair.second) pair.first->second += toLetters(m_internedSelLsbs.size() - 1); - return pair.first->second; - } - - const std::string& internWordWidth(uint32_t 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(uint32_t value) { - const auto pair = m_internedWideWidths.emplace(value, ""); - if (pair.second) pair.first->second += toLetters(m_internedWideWidths.size() - 1); - return pair.first->second; - } - - const std::string& internVertex(const DfgVertex& vtx) { - const auto pair = m_internedVertices.emplace(&vtx, ""); - if (pair.second) pair.first->second += toLetters(m_internedVertices.size() - 1); - return pair.first->second; - } - - // Render the vertx into ss, and return true if the recursion reached the given depth, - // meaning an S-expression with that nesting level has been rendered. - bool render(std::ostringstream& ss, const DfgVertex& vtx, uint32_t depth) { - bool deep = depth == 0; - - if (const DfgConst* const constp = vtx.cast()) { - // Base case 1: constant - if (constp->isZero()) { - ss << "'0"; - } else if (constp->isOnes()) { - ss << "'1"; - } else { - ss << internConst(*constp); - } - } else if (depth == 0) { - // Base case 2: deep vertex - ss << "_"; - } else { - // Recursively print an S-expression for the vertex - - // S-expression begin - ss << '('; - // Name - ss << vtx.typeName(); - // Specials - if (const DfgSel* const selp = vtx.cast()) { - ss << '@'; - if (selp->lsb() == 0) { - ss << '0'; - } else { - ss << internSelLsb(selp->lsb()); - } - } - // Operands - vtx.foreachSource([&](const DfgVertex& src) { - ss << ' '; - if (render(ss, src, depth - 1)) deep = true; - return false; - }); - // S-expression end - ss << ')'; - } - - // Annotate identity - ss << ":" << internVertex(vtx); - // Mark it if it has multiple sinks - if (vtx.hasMultipleSinks()) ss << '*'; - // Annotate type - ss << '/'; - if (!vtx.dtype().isPacked()) { - vtx.dtype().astDtypep()->dumpSmall(ss); - } else { - const uint32_t width = vtx.size(); - if (width == 1) { - ss << '1'; - } else if (width <= VL_QUADSIZE) { - ss << internWordWidth(width); - } else { - ss << internWideWidth(width); - } - } - - // Done - return deep; - } - void dump(std::ostream& os) { using Line = std::pair; 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 - const auto& patternCounts = m_patterCounts[i]; + 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 lines; @@ -173,8 +67,8 @@ public: V3DfgPatternStats() = default; ~V3DfgPatternStats() { // File to dump to - const std::string filename = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() - + "__stats_dfg_patterns.txt"; + const std::string filename + = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + "__dfg_patterns.txt"; // Open, write, close const std::unique_ptr ofp{V3File::new_ofstream(filename)}; if (ofp->fail()) v3fatal("Can't write file: " << filename); @@ -184,13 +78,7 @@ public: void accumulate(const DfgGraph& dfg) { dfg.forEachVertex([&](const DfgVertex& vtx) { for (uint32_t i = MIN_PATTERN_DEPTH; i <= MAX_PATTERN_DEPTH; ++i) { - std::ostringstream ss; - if (render(ss, vtx, i)) m_patterCounts[i][ss.str()] += 1; - m_internedConsts.clear(); - m_internedSelLsbs.clear(); - m_internedWordWidths.clear(); - m_internedWideWidths.clear(); - m_internedVertices.clear(); + m_patterCounts[i][vtx.patternString(i)] += 1; } }); } diff --git a/src/V3DfgOptimizer.cpp b/src/V3DfgOptimizer.cpp index 7bca7d2d4..b2fa0f9e8 100644 --- a/src/V3DfgOptimizer.cpp +++ b/src/V3DfgOptimizer.cpp @@ -154,9 +154,9 @@ class DataflowOptimize final { for (auto& cp : acyclicComps) V3DfgPasses::peephole(*cp, m_ctx.m_peepholeContext); endOfStage("peephole", dfg, acyclicComps); // Accumulate patterns for reporting - if (v3Global.opt.stats()) { + if (v3Global.opt.dumpDfgPatterns()) { V3DfgPasses::dumpPatterns(acyclicComps); - endOfStage("patterns"); + endOfStage("dumpPatterns"); } for (auto& cp : acyclicComps) V3DfgPasses::pushDownSels(*cp, m_ctx.m_pushDownSelsContext); endOfStage("pushDownSels", dfg, acyclicComps); diff --git a/src/V3Options.h b/src/V3Options.h index d99dd69de..868cd45a8 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -534,6 +534,9 @@ public: bool diagnosticsSarif() const VL_MT_SAFE { return m_diagnosticsSarif; } bool dpiHdrOnly() const { return m_dpiHdrOnly; } 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"); + } bool dumpTreeDot() const { return m_dumpLevel.count("tree-dot") && m_dumpLevel.at("tree-dot"); } diff --git a/test_regress/t/t_dfg_dump_patterns.out b/test_regress/t/t_dfg_dump_patterns.out new file mode 100644 index 000000000..0d686ee07 --- /dev/null +++ b/test_regress/t/t_dfg_dump_patterns.out @@ -0,0 +1,123 @@ +DFG patterns with depth 1 + 8 (CONCAT _:1 _:a):b + 5 (CONST #A):a + 5 (REDXOR _:a*):1 + 5 (VARPACKED _:a*):a + 3 (NOT (VARPACKED):a):a* + 3 (REDXOR _:a):1 + 3 (VARPACKED):a + 2 (AND _:a* _:a*):a + 1 (AND _:a* _:a*):a* + 1 (CONCAT _:1 _:1*):a + 1 (CONCAT _:1* _:a):b + 1 (NOT _:a*):a + 1 (REDXOR _:a):1* + 1 (REPLICATE _:1 (CONST #A):a):b* + 1 (REPLICATE _:a (CONST #A):a):b* + 1 (REPLICATE _:a* (CONST #A):a):b + 1 (REPLICATE _:a* (CONST #A):b):b* + 1 (REPLICATE _:a* (CONST #A):b):c* + 1 (SEL@0 _:a*):1 + 1 (SEL@0 _:a*):b + 1 (SEL@A _:a*):1 + 1 (VARPACKED _:a):a + +DFG patterns with depth 2 + 3 (CONCAT (REDXOR _:a*):1 (CONCAT _:1 _:b):c):d + 2 (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a + 2 (CONCAT (REDXOR _:a):1 (CONCAT _:1 _:b):c):d + 2 (REDXOR (AND _:a* _:a*):a):1 + 1 (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a* + 1 (CONCAT (REDXOR _:a):1 (REDXOR _:b):1*):c + 1 (CONCAT (REDXOR _:a):1* (CONCAT _:1 _:b):c):d + 1 (CONCAT (REDXOR _:a*):1 (CONCAT _:1 _:1*):b):c + 1 (CONCAT (REDXOR _:a*):1 (CONCAT _:1* _:b):c):d + 1 (CONCAT (SEL@0 _:a*):1 (CONCAT _:1 _:b):c):d + 1 (NOT (REPLICATE _:a* (CONST #A):b):b*):b + 1 (REDXOR (AND _:a* _:a*):a*):1 + 1 (REDXOR (REPLICATE _:1 (CONST #A):a):b*):1 + 1 (REDXOR (REPLICATE _:a (CONST #A):a):b*):1 + 1 (REDXOR (REPLICATE _:a* (CONST #A):a):b):1* + 1 (REDXOR (REPLICATE _:a* (CONST #A):b):b*):1 + 1 (REDXOR (REPLICATE _:a* (CONST #A):b):c*):1 + 1 (REDXOR (SEL@0 _:a*):b):1 + 1 (REPLICATE (NOT _:a*):a (CONST #A):a):b* + 1 (REPLICATE (REPLICATE _:1 (CONST #A):a):b* (CONST #B):a):c* + 1 (REPLICATE (REPLICATE _:a* (CONST #A):b):b* (CONST #A):b):c + 1 (REPLICATE (REPLICATE _:a* (CONST #A):b):c* (CONST #A):b):b* + 1 (REPLICATE (SEL@A _:a*):1 (CONST #A):b):c* + 1 (SEL@0 (AND _:a* _:a*):a*):1 + 1 (SEL@0 (REPLICATE _:a (CONST #A):a):b*):c + 1 (SEL@A (AND _:a* _:a*):a*):1 + 1 (VARPACKED (AND _:a* _:a*):a*):a + 1 (VARPACKED (CONCAT _:1 _:a):b):b + 1 (VARPACKED (REPLICATE _:1 (CONST #A):a):b*):b + 1 (VARPACKED (REPLICATE _:a (CONST #A):a):b*):b + 1 (VARPACKED (REPLICATE _:a* (CONST #A):b):b*):b + 1 (VARPACKED (REPLICATE _:a* (CONST #A):b):c*):c + +DFG patterns with depth 3 + 2 (REDXOR (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a):1 + 1 (CONCAT (REDXOR (AND _:a* _:a*):a):1 (CONCAT (REDXOR _:a):1 (CONCAT _:1 _:b):c):d):e + 1 (CONCAT (REDXOR (AND _:a* _:a*):a):1 (CONCAT (SEL@0 _:a*):1 (CONCAT _:1 _:b):c):d):e + 1 (CONCAT (REDXOR (AND _:a* _:a*):a*):1 (CONCAT (REDXOR _:a):1 (CONCAT _:1 _:b):c):d):e + 1 (CONCAT (REDXOR (REPLICATE _:1 (CONST #A):a):b*):1 (CONCAT (REDXOR _:c*):1 (CONCAT _:1 _:d):e):f):g + 1 (CONCAT (REDXOR (REPLICATE _:a (CONST #A):a):b*):1 (CONCAT (REDXOR _:c):1 (REDXOR _:b):1*):d):e + 1 (CONCAT (REDXOR (REPLICATE _:a* (CONST #A):b):b*):1 (CONCAT (REDXOR _:c):1* (CONCAT _:1 _:d):e):f):g + 1 (CONCAT (REDXOR (REPLICATE _:a* (CONST #A):b):c*):1 (CONCAT (REDXOR _:b*):1 (CONCAT _:1* _:d):e):f):g + 1 (CONCAT (REDXOR (SEL@0 _:a*):b):1 (REDXOR (REPLICATE _:c* (CONST #A):c):a):1*):d + 1 (CONCAT (SEL@0 (AND _:a* _:a*):a*):1 (CONCAT (REDXOR _:b*):1 (CONCAT _:1 _:c):d):e):b + 1 (CONCAT A:1* (CONCAT (REDXOR _:a*):1 (CONCAT _:1 A:1*):b):c):d | A is (REDXOR (REPLICATE _:e* (CONST #A):e):a):1* + 1 (NOT (REPLICATE (REPLICATE _:a* (CONST #A):b):c* (CONST #A):b):b*):b + 1 (REDXOR (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a*):1 + 1 (REDXOR (REPLICATE (NOT _:a*):a (CONST #A):a):b*):1 + 1 (REDXOR (REPLICATE (REPLICATE _:1 (CONST #A):a):b* (CONST #B):a):c*):1 + 1 (REDXOR (REPLICATE (REPLICATE _:a* (CONST #A):b):b* (CONST #A):b):c):1* + 1 (REDXOR (REPLICATE (REPLICATE _:a* (CONST #A):b):c* (CONST #A):b):b*):1 + 1 (REDXOR (REPLICATE (SEL@A _:a*):1 (CONST #A):b):c*):1 + 1 (REDXOR (SEL@0 (REPLICATE _:a (CONST #A):a):b*):c):1 + 1 (REPLICATE (NOT (REPLICATE _:a* (CONST #A):b):b*):b (CONST #A):b):c* + 1 (REPLICATE (REPLICATE (REPLICATE _:1 (CONST #A):a):b* (CONST #B):a):c* (CONST #B):a):a* + 1 (REPLICATE (REPLICATE (REPLICATE _:a* (CONST #A):b):c* (CONST #A):b):b* (CONST #A):b):d + 1 (REPLICATE (REPLICATE (SEL@A _:a*):1 (CONST #A):b):c* (CONST #B):b):d* + 1 (REPLICATE (SEL@A (AND _:a* _:a*):a*):1 (CONST #A):b):c* + 1 (SEL@0 (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a*):1 + 1 (SEL@0 (REPLICATE (NOT _:a*):a (CONST #A):a):b*):c + 1 (SEL@A (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a*):1 + 1 (VARPACKED (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a*):a + 1 (VARPACKED (CONCAT (REDXOR _:a*):1 (CONCAT _:1 _:b):c):d):d + 1 (VARPACKED (REPLICATE (NOT _:a*):a (CONST #A):a):b*):b + 1 (VARPACKED (REPLICATE (REPLICATE _:1 (CONST #A):a):b* (CONST #B):a):c*):c + 1 (VARPACKED (REPLICATE (REPLICATE _:a* (CONST #A):b):c* (CONST #A):b):b*):b + 1 (VARPACKED (REPLICATE (SEL@A _:a*):1 (CONST #A):b):c*):c + +DFG patterns with depth 4 + 1 (CONCAT (REDXOR (AND (NOT (VARPACKED):a):a* A:a*):a):1 (CONCAT (REDXOR (AND A:a* _:a*):a):1 (CONCAT (SEL@0 _:a*):1 (CONCAT _:1 _:b):c):d):e):f | A is (NOT (VARPACKED):a):a* + 1 (CONCAT (REDXOR (AND (NOT (VARPACKED):a):a* A:a*):a):1 (CONCAT (SEL@0 (AND A:a* _:a*):a*):1 (CONCAT (REDXOR _:b*):1 (CONCAT _:1 _:c):d):e):b):f | A is (NOT (VARPACKED):a):a* + 1 (CONCAT (REDXOR (AND (NOT (VARPACKED):a):a* A:a*):a*):1 (CONCAT (REDXOR (AND A:a* _:a*):a):1 (CONCAT (REDXOR _:a):1 (CONCAT _:1 _:b):c):d):e):f | A is (NOT (VARPACKED):a):a* + 1 (CONCAT (REDXOR (SEL@0 (REPLICATE _:a (CONST #A):a):b*):c):1 (REDXOR (REPLICATE (REPLICATE _:d* (CONST #A):a):a* (CONST #A):a):b):1*):e + 1 (CONCAT (REDXOR A:a*):1 (CONCAT (REDXOR (REPLICATE A:a* (CONST #A):b):b*):1 (CONCAT (REDXOR _:c):1* (CONCAT _:1 _:d):e):f):g):h | A is (REPLICATE (REPLICATE _:1 (CONST #B):b):i* (CONST #A):b):a* + 1 (CONCAT (REDXOR A:a*):1 (CONCAT (REDXOR (REPLICATE A:a* (CONST #A):b):c*):1 (CONCAT (REDXOR _:b*):1 (CONCAT _:1* _:d):e):f):g):h | A is (REPLICATE (SEL@A _:e*):1 (CONST #B):b):a* + 1 (CONCAT (REDXOR A:a*):1 (CONCAT (REDXOR (SEL@0 A:a*):b):1 (REDXOR (REPLICATE B:c* (CONST #A):c):a):1*):d):e | A is (REPLICATE (NOT B:c*):c (CONST #A):c):a* | B is _:c* + 1 (CONCAT (REDXOR A:a*):1 (CONCAT B:1* (CONCAT (REDXOR _:b*):1 (CONCAT _:1 B:1*):c):d):e):f | A is (REPLICATE (REPLICATE _:g* (CONST #A):a):h* (CONST #A):a):a* | B is (REDXOR (REPLICATE A:a* (CONST #A):a):b):1* + 1 (CONCAT (SEL@0 (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a*):1 (CONCAT (REDXOR (REPLICATE _:1 (CONST #A):b):c*):1 (CONCAT (REDXOR _:d*):1 (CONCAT _:1 _:a):e):f):g):c + 1 (CONCAT A:1* (CONCAT (REDXOR (REPLICATE _:a (CONST #A):a):b*):1 (CONCAT (REDXOR _:c):1 A:1*):d):e):f | A is (REDXOR B:b):1* | B is (REPLICATE (REPLICATE _:g* (CONST #A):a):a* (CONST #A):a):b + 1 (NOT (REPLICATE (REPLICATE (REPLICATE _:1 (CONST #A):a):b* (CONST #B):a):c* (CONST #B):a):a*):a + 1 (REDXOR (REPLICATE (NOT (REPLICATE _:a* (CONST #A):b):b*):b (CONST #A):b):c*):1 + 1 (REDXOR (REPLICATE (REPLICATE (REPLICATE _:1 (CONST #A):a):b* (CONST #B):a):c* (CONST #B):a):a*):1 + 1 (REDXOR (REPLICATE (REPLICATE (REPLICATE _:a* (CONST #A):b):c* (CONST #A):b):b* (CONST #A):b):d):1* + 1 (REDXOR (REPLICATE (REPLICATE (SEL@A _:a*):1 (CONST #A):b):c* (CONST #B):b):d*):1 + 1 (REDXOR (REPLICATE (SEL@A (AND _:a* _:a*):a*):1 (CONST #A):b):c*):1 + 1 (REDXOR (SEL@0 (REPLICATE (NOT _:a*):a (CONST #A):a):b*):c):1 + 1 (REPLICATE (NOT (REPLICATE (REPLICATE _:a* (CONST #A):b):c* (CONST #A):b):b*):b (CONST #A):b):d* + 1 (REPLICATE (REPLICATE (REPLICATE (REPLICATE _:1 (CONST #A):a):b* (CONST #B):a):c* (CONST #B):a):a* (CONST #B):a):d + 1 (REPLICATE (REPLICATE (REPLICATE (SEL@A _:a*):1 (CONST #A):b):c* (CONST #B):b):d* (CONST #B):b):b* + 1 (REPLICATE (REPLICATE (SEL@A (AND _:a* _:a*):a*):1 (CONST #A):b):c* (CONST #B):b):d* + 1 (REPLICATE (SEL@A (AND (NOT (VARPACKED):a):a* (NOT (VARPACKED):a):a*):a*):1 (CONST #A):b):c* + 1 (SEL@0 (REPLICATE (NOT (REPLICATE _:a* (CONST #A):b):b*):b (CONST #A):b):c*):d + 1 (VARPACKED (CONCAT (REDXOR (AND _:a* _:a*):a*):1 (CONCAT (REDXOR _:a):1 (CONCAT _:1 _:b):c):d):e):e + 1 (VARPACKED (REPLICATE (NOT (REPLICATE _:a* (CONST #A):b):b*):b (CONST #A):b):c*):c + 1 (VARPACKED (REPLICATE (REPLICATE (REPLICATE _:1 (CONST #A):a):b* (CONST #B):a):c* (CONST #B):a):a*):a + 1 (VARPACKED (REPLICATE (REPLICATE (SEL@A _:a*):1 (CONST #A):b):c* (CONST #B):b):d*):d + 1 (VARPACKED (REPLICATE (SEL@A (AND _:a* _:a*):a*):1 (CONST #A):b):c*):c + diff --git a/test_regress/t/t_dfg_stats_patterns.py b/test_regress/t/t_dfg_dump_patterns.py similarity index 71% rename from test_regress/t/t_dfg_stats_patterns.py rename to test_regress/t/t_dfg_dump_patterns.py index 858c7942e..d0f557d1d 100755 --- a/test_regress/t/t_dfg_stats_patterns.py +++ b/test_regress/t/t_dfg_dump_patterns.py @@ -10,11 +10,10 @@ import vltest_bootstrap test.scenarios('vlt') -test.top_filename = "t/t_dfg_stats_patterns.v" -test.compile(verilator_flags2=["--stats --no-skip-identical"]) +test.compile(verilator_flags2=["--dump-dfg-patterns --no-skip-identical"]) -test.files_identical(test.obj_dir + "/" + test.vm_prefix + "__stats_dfg_patterns.txt", +test.files_identical(test.obj_dir + "/" + test.vm_prefix + "__dfg_patterns.txt", test.golden_filename) test.passes() diff --git a/test_regress/t/t_dfg_stats_patterns.v b/test_regress/t/t_dfg_dump_patterns.v similarity index 100% rename from test_regress/t/t_dfg_stats_patterns.v rename to test_regress/t/t_dfg_dump_patterns.v diff --git a/test_regress/t/t_dfg_stats_patterns.out b/test_regress/t/t_dfg_stats_patterns.out deleted file mode 100644 index 59c6272db..000000000 --- a/test_regress/t/t_dfg_stats_patterns.out +++ /dev/null @@ -1,121 +0,0 @@ -DFG patterns with depth 1 - 8 (CONCAT _:A/1 _:B/a):C/b - 5 (REDXOR _:A*/a):B/1 - 5 (VARPACKED _:A*/a):B/a - 3 (NOT _:A/a):B*/a - 3 (REDXOR _:A/a):B/1 - 2 (AND _:A*/a _:B*/a):C/a - 1 (AND _:A*/a _:B*/a):C*/a - 1 (CONCAT _:A*/1 _:B/a):C/b - 1 (CONCAT _:A/1 _:B*/1):C/a - 1 (NOT _:A*/a):B/a - 1 (REDXOR _:A/a):B*/1 - 1 (REPLICATE _:A*/a cA:B/a):C/b - 1 (REPLICATE _:A*/a cA:B/b):C*/b - 1 (REPLICATE _:A*/a cA:B/b):C*/c - 1 (REPLICATE _:A/1 cA:B/a):C*/b - 1 (REPLICATE _:A/a cA:B/a):C*/b - 1 (SEL@0 _:A*/a):B/1 - 1 (SEL@0 _:A*/a):B/b - 1 (SEL@A _:A*/a):B/1 - 1 (VARPACKED _:A/a):B/a - -DFG patterns with depth 2 - 3 (CONCAT (REDXOR _:A*/a):B/1 (CONCAT _:C/1 _:D/b):E/c):F/d - 2 (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E/a - 2 (CONCAT (REDXOR _:A/a):B/1 (CONCAT _:C/1 _:D/b):E/c):F/d - 2 (REDXOR (AND _:A*/a _:B*/a):C/a):D/1 - 1 (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E*/a - 1 (CONCAT (REDXOR _:A*/a):B/1 (CONCAT _:C*/1 _:D/b):E/c):F/d - 1 (CONCAT (REDXOR _:A*/a):B/1 (CONCAT _:C/1 _:D*/1):E/b):F/c - 1 (CONCAT (REDXOR _:A/a):B*/1 (CONCAT _:C/1 _:D/b):E/c):F/d - 1 (CONCAT (REDXOR _:A/a):B/1 (REDXOR _:C/b):D*/1):E/c - 1 (CONCAT (SEL@0 _:A*/a):B/1 (CONCAT _:C/1 _:D/b):E/c):F/d - 1 (NOT (REPLICATE _:A*/a cA:B/b):C*/b):D/b - 1 (REDXOR (AND _:A*/a _:B*/a):C*/a):D/1 - 1 (REDXOR (REPLICATE _:A*/a cA:B/a):C/b):D*/1 - 1 (REDXOR (REPLICATE _:A*/a cA:B/b):C*/b):D/1 - 1 (REDXOR (REPLICATE _:A*/a cA:B/b):C*/c):D/1 - 1 (REDXOR (REPLICATE _:A/1 cA:B/a):C*/b):D/1 - 1 (REDXOR (REPLICATE _:A/a cA:B/a):C*/b):D/1 - 1 (REDXOR (SEL@0 _:A*/a):B/b):C/1 - 1 (REPLICATE (NOT _:A*/a):B/a cA:C/a):D*/b - 1 (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/b cA:D/b):E/c - 1 (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/c cA:D/b):E*/b - 1 (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c - 1 (REPLICATE (SEL@A _:A*/a):B/1 cA:C/b):D*/c - 1 (SEL@0 (AND _:A*/a _:B*/a):C*/a):D/1 - 1 (SEL@0 (REPLICATE _:A/a cA:B/a):C*/b):D/c - 1 (SEL@A (AND _:A*/a _:B*/a):C*/a):D/1 - 1 (VARPACKED (AND _:A*/a _:B*/a):C*/a):D/a - 1 (VARPACKED (CONCAT _:A/1 _:B/a):C/b):D/b - 1 (VARPACKED (REPLICATE _:A*/a cA:B/b):C*/b):D/b - 1 (VARPACKED (REPLICATE _:A*/a cA:B/b):C*/c):D/c - 1 (VARPACKED (REPLICATE _:A/1 cA:B/a):C*/b):D/b - 1 (VARPACKED (REPLICATE _:A/a cA:B/a):C*/b):D/b - -DFG patterns with depth 3 - 2 (REDXOR (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E/a):F/1 - 1 (CONCAT (REDXOR (AND _:A*/a _:B*/a):C*/a):D/1 (CONCAT (REDXOR _:E/a):F/1 (CONCAT _:G/1 _:H/b):I/c):J/d):K/e - 1 (CONCAT (REDXOR (AND _:A*/a _:B*/a):C/a):D/1 (CONCAT (REDXOR _:E/a):F/1 (CONCAT _:G/1 _:H/b):I/c):J/d):K/e - 1 (CONCAT (REDXOR (AND _:A*/a _:B*/a):C/a):D/1 (CONCAT (SEL@0 _:E*/a):F/1 (CONCAT _:G/1 _:H/b):I/c):J/d):K/e - 1 (CONCAT (REDXOR (REPLICATE _:A*/a cA:B/a):C/b):D*/1 (CONCAT (REDXOR _:E*/b):F/1 (CONCAT _:G/1 _:D*/1):H/c):I/d):J/e - 1 (CONCAT (REDXOR (REPLICATE _:A*/a cA:B/b):C*/b):D/1 (CONCAT (REDXOR _:E/c):F*/1 (CONCAT _:G/1 _:H/d):I/e):J/f):K/g - 1 (CONCAT (REDXOR (REPLICATE _:A*/a cA:B/b):C*/c):D/1 (CONCAT (REDXOR _:E*/b):F/1 (CONCAT _:G*/1 _:H/d):I/e):J/f):K/g - 1 (CONCAT (REDXOR (REPLICATE _:A/1 cA:B/a):C*/b):D/1 (CONCAT (REDXOR _:E*/c):F/1 (CONCAT _:G/1 _:H/d):I/e):J/f):K/g - 1 (CONCAT (REDXOR (REPLICATE _:A/a cA:B/a):C*/b):D/1 (CONCAT (REDXOR _:E/c):F/1 (REDXOR _:G/b):H*/1):I/d):J/e - 1 (CONCAT (REDXOR (SEL@0 _:A*/a):B/b):C/1 (REDXOR (REPLICATE _:D*/c cA:E/c):F/a):G*/1):H/d - 1 (CONCAT (SEL@0 (AND _:A*/a _:B*/a):C*/a):D/1 (CONCAT (REDXOR _:E*/b):F/1 (CONCAT _:G/1 _:H/c):I/d):J/e):K/b - 1 (NOT (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/c cA:D/b):E*/b):F/b - 1 (REDXOR (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E*/a):F/1 - 1 (REDXOR (REPLICATE (NOT _:A*/a):B/a cA:C/a):D*/b):E/1 - 1 (REDXOR (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/b cA:D/b):E/c):F*/1 - 1 (REDXOR (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/c cA:D/b):E*/b):F/1 - 1 (REDXOR (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c):F/1 - 1 (REDXOR (REPLICATE (SEL@A _:A*/a):B/1 cA:C/b):D*/c):E/1 - 1 (REDXOR (SEL@0 (REPLICATE _:A/a cA:B/a):C*/b):D/c):E/1 - 1 (REPLICATE (NOT (REPLICATE _:A*/a cA:B/b):C*/b):D/b cA:E/b):F*/c - 1 (REPLICATE (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/c cA:D/b):E*/b cA:F/b):G/d - 1 (REPLICATE (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c cB:F/a):G*/a - 1 (REPLICATE (REPLICATE (SEL@A _:A*/a):B/1 cA:C/b):D*/c cB:E/b):F*/d - 1 (REPLICATE (SEL@A (AND _:A*/a _:B*/a):C*/a):D/1 cA:E/b):F*/c - 1 (SEL@0 (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E*/a):F/1 - 1 (SEL@0 (REPLICATE (NOT _:A*/a):B/a cA:C/a):D*/b):E/c - 1 (SEL@A (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E*/a):F/1 - 1 (VARPACKED (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E*/a):F/a - 1 (VARPACKED (CONCAT (REDXOR _:A*/a):B/1 (CONCAT _:C/1 _:D/b):E/c):F/d):G/d - 1 (VARPACKED (REPLICATE (NOT _:A*/a):B/a cA:C/a):D*/b):E/b - 1 (VARPACKED (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/c cA:D/b):E*/b):F/b - 1 (VARPACKED (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c):F/c - 1 (VARPACKED (REPLICATE (SEL@A _:A*/a):B/1 cA:C/b):D*/c):E/c - -DFG patterns with depth 4 - 1 (CONCAT (REDXOR (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E*/a):F/1 (CONCAT (REDXOR (AND _:D*/a _:G*/a):H/a):I/1 (CONCAT (REDXOR _:J/a):K/1 (CONCAT _:L/1 _:M/b):N/c):O/d):P/e):Q/f - 1 (CONCAT (REDXOR (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E/a):F/1 (CONCAT (REDXOR (AND _:D*/a _:G*/a):H/a):I/1 (CONCAT (SEL@0 _:J*/a):K/1 (CONCAT _:L/1 _:M/b):N/c):O/d):P/e):Q/f - 1 (CONCAT (REDXOR (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E/a):F/1 (CONCAT (SEL@0 (AND _:D*/a _:G*/a):H*/a):I/1 (CONCAT (REDXOR _:J*/b):K/1 (CONCAT _:L/1 _:M/c):N/d):O/e):P/b):Q/f - 1 (CONCAT (REDXOR (REPLICATE (NOT _:A*/a):B/a cA:C/a):D*/b):E/1 (CONCAT (REDXOR (SEL@0 _:D*/b):F/c):G/1 (REDXOR (REPLICATE _:A*/a cA:H/a):I/b):J*/1):K/d):L/e - 1 (CONCAT (REDXOR (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/b cA:D/b):E/c):F*/1 (CONCAT (REDXOR (REPLICATE _:G/b cA:H/b):I*/c):J/1 (CONCAT (REDXOR _:K/d):L/1 (REDXOR _:E/c):F*/1):M/e):N/f):O/g - 1 (CONCAT (REDXOR (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/c cA:D/b):E*/b):F/1 (CONCAT (REDXOR (REPLICATE _:E*/b cA:G/b):H/d):I*/1 (CONCAT (REDXOR _:J*/d):K/1 (CONCAT _:L/1 _:I*/1):M/e):N/f):O/g):P/h - 1 (CONCAT (REDXOR (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c):F/1 (CONCAT (REDXOR (REPLICATE _:E*/c cB:G/a):H*/a):I/1 (CONCAT (REDXOR _:J/d):K*/1 (CONCAT _:L/1 _:M/e):N/f):O/g):P/h):Q/i - 1 (CONCAT (REDXOR (REPLICATE (SEL@A _:A*/a):B/1 cA:C/b):D*/c):E/1 (CONCAT (REDXOR (REPLICATE _:D*/c cB:F/b):G*/d):H/1 (CONCAT (REDXOR _:I*/b):J/1 (CONCAT _:K*/1 _:L/e):M/a):N/f):O/g):P/h - 1 (CONCAT (REDXOR (SEL@0 (REPLICATE _:A/a cA:B/a):C*/b):D/c):E/1 (REDXOR (REPLICATE (REPLICATE _:F*/d cA:G/a):H*/a cA:I/a):J/b):K*/1):L/e - 1 (CONCAT (SEL@0 (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E*/a):F/1 (CONCAT (REDXOR (REPLICATE _:G/1 cA:H/b):I*/c):J/1 (CONCAT (REDXOR _:K*/d):L/1 (CONCAT _:M/1 _:N/a):O/e):P/f):Q/g):R/c - 1 (NOT (REPLICATE (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c cB:F/a):G*/a):H/a - 1 (REDXOR (REPLICATE (NOT (REPLICATE _:A*/a cA:B/b):C*/b):D/b cA:E/b):F*/c):G/1 - 1 (REDXOR (REPLICATE (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/c cA:D/b):E*/b cA:F/b):G/d):H*/1 - 1 (REDXOR (REPLICATE (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c cB:F/a):G*/a):H/1 - 1 (REDXOR (REPLICATE (REPLICATE (SEL@A _:A*/a):B/1 cA:C/b):D*/c cB:E/b):F*/d):G/1 - 1 (REDXOR (REPLICATE (SEL@A (AND _:A*/a _:B*/a):C*/a):D/1 cA:E/b):F*/c):G/1 - 1 (REDXOR (SEL@0 (REPLICATE (NOT _:A*/a):B/a cA:C/a):D*/b):E/c):F/1 - 1 (REPLICATE (NOT (REPLICATE (REPLICATE _:A*/a cA:B/b):C*/c cA:D/b):E*/b):F/b cA:G/b):H*/d - 1 (REPLICATE (REPLICATE (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c cB:F/a):G*/a cB:H/a):I/d - 1 (REPLICATE (REPLICATE (REPLICATE (SEL@A _:A*/a):B/1 cA:C/b):D*/c cB:E/b):F*/d cB:G/b):H*/b - 1 (REPLICATE (REPLICATE (SEL@A (AND _:A*/a _:B*/a):C*/a):D/1 cA:E/b):F*/c cB:G/b):H*/d - 1 (REPLICATE (SEL@A (AND (NOT _:A/a):B*/a (NOT _:C/a):D*/a):E*/a):F/1 cA:G/b):H*/c - 1 (SEL@0 (REPLICATE (NOT (REPLICATE _:A*/a cA:B/b):C*/b):D/b cA:E/b):F*/c):G/d - 1 (VARPACKED (CONCAT (REDXOR (AND _:A*/a _:B*/a):C*/a):D/1 (CONCAT (REDXOR _:E/a):F/1 (CONCAT _:G/1 _:H/b):I/c):J/d):K/e):L/e - 1 (VARPACKED (REPLICATE (NOT (REPLICATE _:A*/a cA:B/b):C*/b):D/b cA:E/b):F*/c):G/c - 1 (VARPACKED (REPLICATE (REPLICATE (REPLICATE _:A/1 cA:B/a):C*/b cB:D/a):E*/c cB:F/a):G*/a):H/a - 1 (VARPACKED (REPLICATE (REPLICATE (SEL@A _:A*/a):B/1 cA:C/b):D*/c cB:E/b):F*/d):G/d - 1 (VARPACKED (REPLICATE (SEL@A (AND _:A*/a _:B*/a):C*/a):D/1 cA:E/b):F*/c):G/c -