forked from github/verilator
Add --expand-limit argument (#3005).
This commit is contained in:
parent
b0c1ac7ea2
commit
1e89392e76
1
Changes
1
Changes
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
20
test_regress/t/t_flag_expand_limit.pl
Executable file
20
test_regress/t/t_flag_expand_limit.pl
Executable 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;
|
27
test_regress/t/t_flag_expand_limit.v
Normal file
27
test_regress/t/t_flag_expand_limit.v
Normal 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
|
@ -12,6 +12,7 @@ scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
verilator_flags2 => ["-unroll-count 1024",
|
||||
"--expand-limit 1024",
|
||||
$Self->wno_unopthreads_for_few_cores(),
|
||||
"--stats"],
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user