Add --expand-limit argument (#3005).

This commit is contained in:
Wilson Snyder 2021-06-06 10:27:01 -04:00
parent b0c1ac7ea2
commit 1e89392e76
9 changed files with 92 additions and 1 deletions

View File

@ -14,6 +14,7 @@ Verilator 4.203 devel
**Minor:**
* Add --reloop-limit argument (#2943) (#2960). [Geza Lore]
* Add --expand-limit argument (#3005). [Julien Margetts]
* Add TRACE_THREADS to CMake (#2934). [Jonathan Drolet]
* Optimize large lookup tables to static data (#2925). [Geza Lore]
* Optimize reloop to accept constant index offsets (#2939). [Geza Lore]

View File

@ -315,6 +315,7 @@ detailed descriptions of these arguments.
-E Preprocess, but do not compile
--error-limit <value> Abort after this number of errors
--exe Link to create executable
--expand-limit <value> Set expand optimization limit
-F <file> Parse arguments from a file, relatively
-f <file> Parse arguments from a file
-FI <file> Force include of a file

View File

@ -403,6 +403,12 @@ Summary:
files on the command line that implement the main loop for your
simulation.
.. option:: --expand-limit <value>
Rarely needed. Fine-tune optimizations to set the maximum size of an
expression in 32-bit words to expand into separate word-based
statements.
.. option:: -F <file>
Read the specified file, and act as if all text inside it was specified

View File

@ -30,6 +30,7 @@
#include "V3Global.h"
#include "V3Expand.h"
#include "V3Stats.h"
#include "V3Ast.h"
#include <algorithm>
@ -45,10 +46,24 @@ private:
// STATE
AstNode* m_stmtp = nullptr; // Current statement
VDouble0 m_statWides; // Statistic tracking
VDouble0 m_statWideWords; // Statistic tracking
VDouble0 m_statWideLimited; // Statistic tracking
// METHODS
VL_DEBUG_FUNC; // Declare debug()
bool doExpand(AstNode* nodep) {
++m_statWides;
if (nodep->widthWords() <= v3Global.opt.expandLimit()) {
m_statWideWords += nodep->widthWords();
return true;
} else {
++m_statWideLimited;
return false;
}
}
int longOrQuadWidth(AstNode* nodep) {
return (nodep->width() + (VL_EDATASIZE - 1)) & ~(VL_EDATASIZE - 1);
}
@ -204,6 +219,7 @@ private:
bool expandWide(AstNodeAssign* nodep, AstConst* rhsp) {
UINFO(8, " Wordize ASSIGN(CONST) " << nodep << endl);
if (!doExpand(nodep)) return false;
// -> {for each_word{ ASSIGN(WORDSEL(wide,#),WORDSEL(CONST,#))}}
if (rhsp->num().isFourState()) {
rhsp->v3warn(E_UNSUPPORTED, // LCOV_EXCL_LINE // impossible?
@ -219,6 +235,7 @@ private:
//-------- Uniops
bool expandWide(AstNodeAssign* nodep, AstVarRef* rhsp) {
UINFO(8, " Wordize ASSIGN(VARREF) " << nodep << endl);
if (!doExpand(nodep)) return false;
for (int w = 0; w < nodep->widthWords(); w++) {
addWordAssign(nodep, w, newAstWordSelClone(rhsp, w));
}
@ -228,6 +245,7 @@ private:
UINFO(8, " Wordize ASSIGN(ARRAYSEL) " << nodep << endl);
UASSERT_OBJ(!VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType), nodep,
"ArraySel with unpacked arrays should have been removed in V3Slice");
if (!doExpand(nodep)) return false;
for (int w = 0; w < nodep->widthWords(); w++) {
addWordAssign(nodep, w, newAstWordSelClone(rhsp, w));
}
@ -236,6 +254,7 @@ private:
bool expandWide(AstNodeAssign* nodep, AstNot* rhsp) {
UINFO(8, " Wordize ASSIGN(NOT) " << nodep << endl);
// -> {for each_word{ ASSIGN(WORDSEL(wide,#),NOT(WORDSEL(lhs,#))) }}
if (!doExpand(nodep)) return false;
for (int w = 0; w < nodep->widthWords(); w++) {
addWordAssign(nodep, w,
new AstNot(rhsp->fileline(), newAstWordSelClone(rhsp->lhsp(), w)));
@ -245,6 +264,7 @@ private:
//-------- Biops
bool expandWide(AstNodeAssign* nodep, AstAnd* rhsp) {
UINFO(8, " Wordize ASSIGN(AND) " << nodep << endl);
if (!doExpand(nodep)) return false;
for (int w = 0; w < nodep->widthWords(); w++) {
addWordAssign(nodep, w,
new AstAnd(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w),
@ -254,6 +274,7 @@ private:
}
bool expandWide(AstNodeAssign* nodep, AstOr* rhsp) {
UINFO(8, " Wordize ASSIGN(OR) " << nodep << endl);
if (!doExpand(nodep)) return false;
for (int w = 0; w < nodep->widthWords(); w++) {
addWordAssign(nodep, w,
new AstOr(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w),
@ -263,6 +284,7 @@ private:
}
bool expandWide(AstNodeAssign* nodep, AstXor* rhsp) {
UINFO(8, " Wordize ASSIGN(XOR) " << nodep << endl);
if (!doExpand(nodep)) return false;
for (int w = 0; w < nodep->widthWords(); w++) {
addWordAssign(nodep, w,
new AstXor(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w),
@ -273,6 +295,7 @@ private:
//-------- Triops
bool expandWide(AstNodeAssign* nodep, AstNodeCond* rhsp) {
UINFO(8, " Wordize ASSIGN(COND) " << nodep << endl);
if (!doExpand(nodep)) return false;
for (int w = 0; w < nodep->widthWords(); w++) {
addWordAssign(nodep, w,
new AstCond(nodep->fileline(), rhsp->condp()->cloneTree(true),
@ -417,6 +440,7 @@ private:
bool expandWide(AstNodeAssign* nodep, AstSel* rhsp) {
UASSERT_OBJ(nodep->widthMin() == rhsp->widthConst(), nodep, "Width mismatch");
if (!doExpand(nodep)) return false;
if (VN_IS(rhsp->lsbp(), Const) && VL_BITBIT_E(rhsp->lsbConst()) == 0) {
int lsb = rhsp->lsbConst();
UINFO(8, " Wordize ASSIGN(SEL,align) " << nodep << endl);
@ -647,6 +671,7 @@ private:
}
bool expandWide(AstNodeAssign* nodep, AstConcat* rhsp) {
UINFO(8, " Wordize ASSIGN(CONCAT) " << nodep << endl);
if (!doExpand(rhsp)) return false;
// Lhs or Rhs may be word, long, or quad.
// newAstWordSelClone nicely abstracts the difference.
int rhsshift = rhsp->rhsp()->widthMin();
@ -701,6 +726,7 @@ private:
}
bool expandWide(AstNodeAssign* nodep, AstReplicate* rhsp) {
UINFO(8, " Wordize ASSIGN(REPLICATE) " << nodep << endl);
if (!doExpand(rhsp)) return false;
AstNode* lhsp = rhsp->lhsp();
int lhswidth = lhsp->widthMin();
const AstConst* constp = VN_CAST(rhsp->rhsp(), Const);
@ -857,6 +883,7 @@ private:
iterateChildren(nodep);
bool did = false;
if (nodep->isWide() && ((VN_IS(nodep->lhsp(), VarRef) || VN_IS(nodep->lhsp(), ArraySel)))
&& ((VN_IS(nodep->lhsp(), VarRef) || VN_IS(nodep->lhsp(), ArraySel)))
&& !AstVar::scVarRecurse(nodep->lhsp()) // Need special function for SC
&& !AstVar::scVarRecurse(nodep->rhsp())) {
if (AstConst* rhsp = VN_CAST(nodep->rhsp(), Const)) {
@ -897,7 +924,11 @@ private:
public:
// CONSTRUCTORS
explicit ExpandVisitor(AstNetlist* nodep) { iterate(nodep); }
virtual ~ExpandVisitor() override = default;
virtual ~ExpandVisitor() override {
V3Stats::addStat("Optimizations, expand wides", m_statWides);
V3Stats::addStat("Optimizations, expand wide words", m_statWideWords);
V3Stats::addStat("Optimizations, expand limited", m_statWideLimited);
}
};
//----------------------------------------------------------------------

View File

@ -1060,6 +1060,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
DECL_OPTION("-E", Set, &m_preprocOnly);
DECL_OPTION("-error-limit", CbVal, static_cast<void (*)(int)>(&V3Error::errorLimit));
DECL_OPTION("-exe", OnOff, &m_exe);
DECL_OPTION("-expand-limit", CbVal,
[this, fl](const char* valp) { m_expandLimit = std::atoi(valp); });
DECL_OPTION("-F", CbVal, [this, fl, &optdir](const char* valp) {
parseOptsFile(fl, parseFileArg(optdir, valp), true);

View File

@ -285,6 +285,7 @@ private:
int m_convergeLimit = 100; // main switch: --converge-limit
int m_coverageMaxWidth = 256; // main switch: --coverage-max-width
int m_dumpTree = 0; // main switch: --dump-tree
int m_expandLimit = 64; // main switch: --expand-limit
int m_gateStmts = 100; // main switch: --gate-stmts
int m_ifDepth = 0; // main switch: --if-depth
int m_inlineMult = 2000; // main switch: --inline-mult
@ -482,6 +483,7 @@ public:
int coverageMaxWidth() const { return m_coverageMaxWidth; }
int dumpTree() const { return m_dumpTree; }
bool dumpTreeAddrids() const { return m_dumpTreeAddrids; }
int expandLimit() const { return m_expandLimit; }
int gateStmts() const { return m_gateStmts; }
int ifDepth() const { return m_ifDepth; }
int inlineMult() const { return m_inlineMult; }

View File

@ -0,0 +1,20 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2008 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);
compile(
verilator_flags2 => ['--expand-limit 1 --stats'],
);
file_grep($Self->{stats}, qr/Optimizations, expand limited\s+(\d+)/i, 4);
ok(1);
1;

View File

@ -0,0 +1,27 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2021 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// issue3005
module t #(parameter NV = 2000)
(
input a,
input w1,
input [127:0] w2,
output [ 31:0] o,
input [319:0] bi,
output [319:0] bo
);
// verilator lint_off WIDTH
wire [NV-1:0] d = a ? NV'(0) : {NV{w2}};
// verilator lint_on WIDTH
assign o = d[31:0];
assign bo = ~bi;
endmodule

View File

@ -12,6 +12,7 @@ scenarios(simulator => 1);
compile(
verilator_flags2 => ["-unroll-count 1024",
"--expand-limit 1024",
$Self->wno_unopthreads_for_few_cores(),
"--stats"],
);