mirror of
https://github.com/verilator/verilator.git
synced 2025-01-21 05:44:03 +00:00
Dump DFG patterns with --stats (#4889)
With --stats, we will print DFG pattern combinations, one per line, as S-expressions to new stat files, together with their frequency, to aid discovery of new peephole patterns.
This commit is contained in:
parent
d667b73e8d
commit
cbc76a7816
@ -1267,6 +1267,8 @@ Summary:
|
|||||||
|
|
||||||
Creates a dump file with statistics on the design in
|
Creates a dump file with statistics on the design in
|
||||||
:file:`<prefix>__stats.txt`.
|
:file:`<prefix>__stats.txt`.
|
||||||
|
Also dumps DFG patterns to
|
||||||
|
:file:`<prefix>__stats_dfg_patterns__*.txt`.
|
||||||
|
|
||||||
.. option:: --stats-vars
|
.. option:: --stats-vars
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include "V3AstUserAllocator.h"
|
#include "V3AstUserAllocator.h"
|
||||||
#include "V3Dfg.h"
|
#include "V3Dfg.h"
|
||||||
#include "V3DfgPasses.h"
|
#include "V3DfgPasses.h"
|
||||||
|
#include "V3DfgPatternStats.h"
|
||||||
|
#include "V3File.h"
|
||||||
#include "V3Graph.h"
|
#include "V3Graph.h"
|
||||||
#include "V3UniqueNames.h"
|
#include "V3UniqueNames.h"
|
||||||
|
|
||||||
@ -252,6 +254,8 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
|||||||
|
|
||||||
V3DfgOptimizationContext ctx{label};
|
V3DfgOptimizationContext ctx{label};
|
||||||
|
|
||||||
|
V3DfgPatternStats patternStats;
|
||||||
|
|
||||||
// Run the optimization phase
|
// Run the optimization phase
|
||||||
for (AstNode* nodep = netlistp->modulesp(); nodep; nodep = nodep->nextp()) {
|
for (AstNode* nodep = netlistp->modulesp(); nodep; nodep = nodep->nextp()) {
|
||||||
// Only optimize proper modules
|
// Only optimize proper modules
|
||||||
@ -295,10 +299,34 @@ void V3DfgOptimizer::optimize(AstNetlist* netlistp, const string& label) {
|
|||||||
dfg->addGraph(*component);
|
dfg->addGraph(*component);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulate patterns from the optimized graph for reporting
|
||||||
|
if (v3Global.opt.stats()) patternStats.accumulate(*dfg);
|
||||||
|
|
||||||
// Convert back to Ast
|
// Convert back to Ast
|
||||||
if (dumpDfgLevel() >= 8) dfg->dumpDotFilePrefixed(ctx.prefix() + "whole-optimized");
|
if (dumpDfgLevel() >= 8) dfg->dumpDotFilePrefixed(ctx.prefix() + "whole-optimized");
|
||||||
AstModule* const resultModp = V3DfgPasses::dfgToAst(*dfg, ctx);
|
AstModule* const resultModp = V3DfgPasses::dfgToAst(*dfg, ctx);
|
||||||
UASSERT_OBJ(resultModp == modp, modp, "Should be the same module");
|
UASSERT_OBJ(resultModp == modp, modp, "Should be the same module");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print the collected patterns
|
||||||
|
if (v3Global.opt.stats()) {
|
||||||
|
// Label to lowercase, without spaces
|
||||||
|
std::string ident = label;
|
||||||
|
std::transform(ident.begin(), ident.end(), ident.begin(), [](unsigned char c) { //
|
||||||
|
return c == ' ' ? '_' : std::tolower(c);
|
||||||
|
});
|
||||||
|
|
||||||
|
// File to dump to
|
||||||
|
const std::string filename = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix()
|
||||||
|
+ "__stats_dfg_patterns__" + ident + ".txt";
|
||||||
|
|
||||||
|
// Open, write, close
|
||||||
|
std::ofstream* const ofp = V3File::new_ofstream(filename);
|
||||||
|
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||||
|
patternStats.dump(label, *ofp);
|
||||||
|
ofp->close();
|
||||||
|
VL_DO_DANGLING(delete ofp, ofp);
|
||||||
|
}
|
||||||
|
|
||||||
V3Global::dumpCheckGlobalTree("dfg-optimize", 0, dumpTreeEitherLevel() >= 3);
|
V3Global::dumpCheckGlobalTree("dfg-optimize", 0, dumpTreeEitherLevel() >= 3);
|
||||||
}
|
}
|
||||||
|
197
src/V3DfgPatternStats.h
Normal file
197
src/V3DfgPatternStats.h
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Implementations of simple passes over DfgGraph
|
||||||
|
//
|
||||||
|
// Code available from: https://verilator.org
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2024 by Wilson Snyder. This program is free software; you
|
||||||
|
// can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
// Version 2.0.
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#include "V3PchAstNoMT.h"
|
||||||
|
|
||||||
|
#include "V3Dfg.h"
|
||||||
|
#include "V3DfgPasses.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class V3DfgPatternStats final {
|
||||||
|
static constexpr uint32_t MIN_PATTERN_DEPTH = 1;
|
||||||
|
static constexpr uint32_t MAX_PATTERN_DEPTH = 4;
|
||||||
|
|
||||||
|
std::map<std::string, std::string> m_internedConsts; // Interned constants
|
||||||
|
std::map<const AstVar*, std::string> m_internedVars; // Interned variables
|
||||||
|
std::map<uint32_t, std::string> m_internedSelLsbs; // Interned lsb value for selects
|
||||||
|
std::map<uint32_t, std::string> m_internedWordWidths; // Interned widths
|
||||||
|
std::map<uint32_t, std::string> m_internedWideWidths; // Interned widths
|
||||||
|
std::map<const DfgVertex*, std::string> m_internedVertices; // Interned vertices
|
||||||
|
|
||||||
|
// 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};
|
||||||
|
|
||||||
|
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 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& internVar(const DfgVertexVar& vtx) {
|
||||||
|
const auto pair = m_internedVars.emplace(vtx.varp(), "v");
|
||||||
|
if (pair.second) pair.first->second += toLetters(m_internedVars.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<DfgConst>()) {
|
||||||
|
// Base case 1: constant
|
||||||
|
if (constp->isZero()) {
|
||||||
|
ss << "'0";
|
||||||
|
} else if (constp->isOnes()) {
|
||||||
|
ss << "'1";
|
||||||
|
} else {
|
||||||
|
ss << internConst(*constp);
|
||||||
|
}
|
||||||
|
} else if (const DfgVertexVar* const varp = vtx.cast<DfgVertexVar>()) {
|
||||||
|
// Base case 2: variable
|
||||||
|
ss << internVar(*varp);
|
||||||
|
} else if (depth == 0) {
|
||||||
|
// Base case 3: deep vertex
|
||||||
|
ss << internVertex(vtx);
|
||||||
|
} 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<DfgSel>()) {
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
// S-expression end
|
||||||
|
ss << ')';
|
||||||
|
|
||||||
|
// Mark it if it has multiple sinks
|
||||||
|
if (vtx.hasMultipleSinks()) ss << '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotate type
|
||||||
|
ss << ':';
|
||||||
|
const AstNodeDType* const dtypep = vtx.dtypep();
|
||||||
|
if (!VN_IS(dtypep, BasicDType)) {
|
||||||
|
dtypep->dumpSmall(ss);
|
||||||
|
} else {
|
||||||
|
const uint32_t width = dtypep->width();
|
||||||
|
if (width == 1) {
|
||||||
|
ss << '1';
|
||||||
|
} else if (width <= VL_QUADSIZE) {
|
||||||
|
ss << internWordWidth(width);
|
||||||
|
} else {
|
||||||
|
ss << internWideWidth(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done
|
||||||
|
return deep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
V3DfgPatternStats() = default;
|
||||||
|
|
||||||
|
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_internedVars.clear();
|
||||||
|
m_internedSelLsbs.clear();
|
||||||
|
m_internedWordWidths.clear();
|
||||||
|
m_internedWideWidths.clear();
|
||||||
|
m_internedVertices.clear();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump(const std::string& stage, 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 '" << stage << "' patterns with depth " << i << '\n';
|
||||||
|
|
||||||
|
// Pick up pattern accumulators with given depth
|
||||||
|
const auto& patternCounts = m_patterCounts[i];
|
||||||
|
|
||||||
|
// 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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -279,7 +279,7 @@ static void process() {
|
|||||||
|
|
||||||
if (v3Global.opt.fDfgPreInline()) {
|
if (v3Global.opt.fDfgPreInline()) {
|
||||||
// Pre inline DFG optimization
|
// Pre inline DFG optimization
|
||||||
V3DfgOptimizer::optimize(v3Global.rootp(), " pre inline");
|
V3DfgOptimizer::optimize(v3Global.rootp(), "pre inline");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(v3Global.opt.serializeOnly() && !v3Global.opt.flatten())) {
|
if (!(v3Global.opt.serializeOnly() && !v3Global.opt.flatten())) {
|
||||||
|
37
test_regress/t/t_dfg_stats_patterns.v
Normal file
37
test_regress/t/t_dfg_stats_patterns.v
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2024 by 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 [3:0] x,
|
||||||
|
output wire [3:0] y,
|
||||||
|
output wire [3:0] z,
|
||||||
|
output wire [ 0:0] w1,
|
||||||
|
output wire [ 7:0] w8,
|
||||||
|
output wire [15:0] w16,
|
||||||
|
output wire [31:0] w32,
|
||||||
|
output wire [63:0] w64a,
|
||||||
|
output wire [63:0] w64b,
|
||||||
|
output wire [62:0] w63,
|
||||||
|
output wire [95:0] w96
|
||||||
|
);
|
||||||
|
|
||||||
|
assign x = ~a & ~b;
|
||||||
|
assign y = ~b & ~c;
|
||||||
|
assign z = ~c & ~a;
|
||||||
|
assign w1 = x[0];
|
||||||
|
assign w8 = {8{x[1]}};
|
||||||
|
assign w16 = {2{w8}};
|
||||||
|
assign w32 = {2{w16}};
|
||||||
|
assign w64a = {2{w32}};
|
||||||
|
assign w64b = {2{~w32}};
|
||||||
|
assign w63 = 63'({2{~w32}});
|
||||||
|
assign w96 = 96'(w64a);
|
||||||
|
|
||||||
|
endmodule
|
50
test_regress/t/t_dfg_stats_patterns_post_inline.out
Normal file
50
test_regress/t/t_dfg_stats_patterns_post_inline.out
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
DFG 'post inline' patterns with depth 1
|
||||||
|
3 (NOT vA:a)*:a
|
||||||
|
2 (AND _A:a _B:a):a
|
||||||
|
2 (REPLICATE _A:a cA:a)*:b
|
||||||
|
1 (AND _A:a _B:a)*:a
|
||||||
|
1 (CONCAT '0:a _A:b):A
|
||||||
|
1 (NOT _A:a):a
|
||||||
|
1 (REPLICATE _A:1 cA:a)*:b
|
||||||
|
1 (REPLICATE _A:a cA:b)*:b
|
||||||
|
1 (REPLICATE _A:a cA:b)*:c
|
||||||
|
1 (SEL@0 _A:a):1
|
||||||
|
1 (SEL@0 _A:a):b
|
||||||
|
1 (SEL@A _A:a):1
|
||||||
|
|
||||||
|
DFG 'post inline' patterns with depth 2
|
||||||
|
2 (AND (NOT vA:a)*:a (NOT vB:a)*:a):a
|
||||||
|
1 (AND (NOT vA:a)*:a (NOT vB:a)*:a)*:a
|
||||||
|
1 (CONCAT '0:a (REPLICATE _A:a cA:a)*:b):A
|
||||||
|
1 (NOT (REPLICATE _A:a cA:b)*:b):b
|
||||||
|
1 (REPLICATE (NOT _A:a):a cA:a)*:b
|
||||||
|
1 (REPLICATE (REPLICATE _A:1 cA:a)*:b cB:a)*:c
|
||||||
|
1 (REPLICATE (REPLICATE _A:a cA:b)*:b cA:b)*:c
|
||||||
|
1 (REPLICATE (REPLICATE _A:a cA:b)*:c cA:b)*:b
|
||||||
|
1 (REPLICATE (SEL@A _A:a):1 cA:b)*:c
|
||||||
|
1 (SEL@0 (AND _A:a _B:a)*:a):1
|
||||||
|
1 (SEL@0 (REPLICATE _A:a cA:a)*:b):c
|
||||||
|
1 (SEL@A (AND _A:a _B:a)*:a):1
|
||||||
|
|
||||||
|
DFG 'post inline' patterns with depth 3
|
||||||
|
1 (CONCAT '0:a (REPLICATE (REPLICATE _A:b cA:a)*:a cA:a)*:c):A
|
||||||
|
1 (NOT (REPLICATE (REPLICATE _A:a cA:b)*:c cA:b)*:b):b
|
||||||
|
1 (REPLICATE (NOT (REPLICATE _A:a cA:b)*:b):b cA:b)*:c
|
||||||
|
1 (REPLICATE (REPLICATE (REPLICATE _A:1 cA:a)*:b cB:a)*:c cB:a)*:a
|
||||||
|
1 (REPLICATE (REPLICATE (REPLICATE _A:a cA:b)*:c cA:b)*:b cA:b)*:d
|
||||||
|
1 (REPLICATE (REPLICATE (SEL@A _A:a):1 cA:b)*:c cB:b)*:d
|
||||||
|
1 (REPLICATE (SEL@A (AND _A:a _B:a)*:a):1 cA:b)*:c
|
||||||
|
1 (SEL@0 (AND (NOT vA:a)*:a (NOT vB:a)*:a)*:a):1
|
||||||
|
1 (SEL@0 (REPLICATE (NOT _A:a):a cA:a)*:b):c
|
||||||
|
1 (SEL@A (AND (NOT vA:a)*:a (NOT vB:a)*:a)*:a):1
|
||||||
|
|
||||||
|
DFG 'post inline' patterns with depth 4
|
||||||
|
1 (CONCAT '0:a (REPLICATE (REPLICATE (REPLICATE _A:b cA:a)*:c cA:a)*:a cA:a)*:d):A
|
||||||
|
1 (NOT (REPLICATE (REPLICATE (REPLICATE _A:1 cA:a)*:b cB:a)*:c cB:a)*:a):a
|
||||||
|
1 (REPLICATE (NOT (REPLICATE (REPLICATE _A:a cA:b)*:c cA:b)*:b):b cA:b)*:d
|
||||||
|
1 (REPLICATE (REPLICATE (REPLICATE (REPLICATE _A:1 cA:a)*:b cB:a)*:c cB:a)*:a cB:a)*:d
|
||||||
|
1 (REPLICATE (REPLICATE (REPLICATE (SEL@A _A:a):1 cA:b)*:c cB:b)*:d cB:b)*:b
|
||||||
|
1 (REPLICATE (REPLICATE (SEL@A (AND _A:a _B:a)*:a):1 cA:b)*:c cB:b)*:d
|
||||||
|
1 (REPLICATE (SEL@A (AND (NOT vA:a)*:a (NOT vB:a)*:a)*:a):1 cA:b)*:c
|
||||||
|
1 (SEL@0 (REPLICATE (NOT (REPLICATE _A:a cA:b)*:b):b cA:b)*:c):d
|
||||||
|
|
23
test_regress/t/t_dfg_stats_patterns_post_inline.pl
Executable file
23
test_regress/t/t_dfg_stats_patterns_post_inline.pl
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
|
top_filename("t/t_dfg_stats_patterns.v");
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ["--stats --no-skip-identical -fno-dfg-pre-inline"],
|
||||||
|
);
|
||||||
|
|
||||||
|
my $f = glob_one("$Self->{obj_dir}/$Self->{vm_prefix}__stats_dfg_patterns*");
|
||||||
|
files_identical($f, $Self->{golden_filename});
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
50
test_regress/t/t_dfg_stats_patterns_pre_inline.out
Normal file
50
test_regress/t/t_dfg_stats_patterns_pre_inline.out
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
DFG 'pre inline' patterns with depth 1
|
||||||
|
3 (NOT vA:a)*:a
|
||||||
|
2 (AND _A:a _B:a):a
|
||||||
|
2 (REPLICATE _A:a cA:a)*:b
|
||||||
|
1 (AND _A:a _B:a)*:a
|
||||||
|
1 (CONCAT '0:a _A:b):A
|
||||||
|
1 (NOT _A:a):a
|
||||||
|
1 (REPLICATE _A:1 cA:a)*:b
|
||||||
|
1 (REPLICATE _A:a cA:b)*:b
|
||||||
|
1 (REPLICATE _A:a cA:b)*:c
|
||||||
|
1 (SEL@0 _A:a):1
|
||||||
|
1 (SEL@0 _A:a):b
|
||||||
|
1 (SEL@A _A:a):1
|
||||||
|
|
||||||
|
DFG 'pre inline' patterns with depth 2
|
||||||
|
2 (AND (NOT vA:a)*:a (NOT vB:a)*:a):a
|
||||||
|
1 (AND (NOT vA:a)*:a (NOT vB:a)*:a)*:a
|
||||||
|
1 (CONCAT '0:a (REPLICATE _A:a cA:a)*:b):A
|
||||||
|
1 (NOT (REPLICATE _A:a cA:b)*:b):b
|
||||||
|
1 (REPLICATE (NOT _A:a):a cA:a)*:b
|
||||||
|
1 (REPLICATE (REPLICATE _A:1 cA:a)*:b cB:a)*:c
|
||||||
|
1 (REPLICATE (REPLICATE _A:a cA:b)*:b cA:b)*:c
|
||||||
|
1 (REPLICATE (REPLICATE _A:a cA:b)*:c cA:b)*:b
|
||||||
|
1 (REPLICATE (SEL@A _A:a):1 cA:b)*:c
|
||||||
|
1 (SEL@0 (AND _A:a _B:a)*:a):1
|
||||||
|
1 (SEL@0 (REPLICATE _A:a cA:a)*:b):c
|
||||||
|
1 (SEL@A (AND _A:a _B:a)*:a):1
|
||||||
|
|
||||||
|
DFG 'pre inline' patterns with depth 3
|
||||||
|
1 (CONCAT '0:a (REPLICATE (REPLICATE _A:b cA:a)*:a cA:a)*:c):A
|
||||||
|
1 (NOT (REPLICATE (REPLICATE _A:a cA:b)*:c cA:b)*:b):b
|
||||||
|
1 (REPLICATE (NOT (REPLICATE _A:a cA:b)*:b):b cA:b)*:c
|
||||||
|
1 (REPLICATE (REPLICATE (REPLICATE _A:1 cA:a)*:b cB:a)*:c cB:a)*:a
|
||||||
|
1 (REPLICATE (REPLICATE (REPLICATE _A:a cA:b)*:c cA:b)*:b cA:b)*:d
|
||||||
|
1 (REPLICATE (REPLICATE (SEL@A _A:a):1 cA:b)*:c cB:b)*:d
|
||||||
|
1 (REPLICATE (SEL@A (AND _A:a _B:a)*:a):1 cA:b)*:c
|
||||||
|
1 (SEL@0 (AND (NOT vA:a)*:a (NOT vB:a)*:a)*:a):1
|
||||||
|
1 (SEL@0 (REPLICATE (NOT _A:a):a cA:a)*:b):c
|
||||||
|
1 (SEL@A (AND (NOT vA:a)*:a (NOT vB:a)*:a)*:a):1
|
||||||
|
|
||||||
|
DFG 'pre inline' patterns with depth 4
|
||||||
|
1 (CONCAT '0:a (REPLICATE (REPLICATE (REPLICATE _A:b cA:a)*:c cA:a)*:a cA:a)*:d):A
|
||||||
|
1 (NOT (REPLICATE (REPLICATE (REPLICATE _A:1 cA:a)*:b cB:a)*:c cB:a)*:a):a
|
||||||
|
1 (REPLICATE (NOT (REPLICATE (REPLICATE _A:a cA:b)*:c cA:b)*:b):b cA:b)*:d
|
||||||
|
1 (REPLICATE (REPLICATE (REPLICATE (REPLICATE _A:1 cA:a)*:b cB:a)*:c cB:a)*:a cB:a)*:d
|
||||||
|
1 (REPLICATE (REPLICATE (REPLICATE (SEL@A _A:a):1 cA:b)*:c cB:b)*:d cB:b)*:b
|
||||||
|
1 (REPLICATE (REPLICATE (SEL@A (AND _A:a _B:a)*:a):1 cA:b)*:c cB:b)*:d
|
||||||
|
1 (REPLICATE (SEL@A (AND (NOT vA:a)*:a (NOT vB:a)*:a)*:a):1 cA:b)*:c
|
||||||
|
1 (SEL@0 (REPLICATE (NOT (REPLICATE _A:a cA:b)*:b):b cA:b)*:c):d
|
||||||
|
|
23
test_regress/t/t_dfg_stats_patterns_pre_inline.pl
Executable file
23
test_regress/t/t_dfg_stats_patterns_pre_inline.pl
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
|
top_filename("t/t_dfg_stats_patterns.v");
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ["--stats --no-skip-identical -fno-dfg-post-inline"],
|
||||||
|
);
|
||||||
|
|
||||||
|
my $f = glob_one("$Self->{obj_dir}/$Self->{vm_prefix}__stats_dfg_patterns*");
|
||||||
|
files_identical($f, $Self->{golden_filename});
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
Loading…
Reference in New Issue
Block a user