Skip to content

Commit

Permalink
Add --expand-limit argument (verilator#3005).
Browse files Browse the repository at this point in the history
  • Loading branch information
wsnyder committed Jun 6, 2021
1 parent b0c1ac7 commit 1e89392
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 1 deletion.
1 change: 1 addition & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
1 change: 1 addition & 0 deletions bin/verilator
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions docs/guide/exe_verilator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 32 additions & 1 deletion src/V3Expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "V3Global.h"
#include "V3Expand.h"
#include "V3Stats.h"
#include "V3Ast.h"

#include <algorithm>
Expand All @@ -45,10 +46,24 @@ class ExpandVisitor final : public AstNVisitor {

// 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);
}
Expand Down Expand Up @@ -204,6 +219,7 @@ class ExpandVisitor final : public AstNVisitor {

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?
Expand All @@ -219,6 +235,7 @@ class ExpandVisitor final : public AstNVisitor {
//-------- 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));
}
Expand All @@ -228,6 +245,7 @@ class ExpandVisitor final : public AstNVisitor {
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));
}
Expand All @@ -236,6 +254,7 @@ class ExpandVisitor final : public AstNVisitor {
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)));
Expand All @@ -245,6 +264,7 @@ class ExpandVisitor final : public AstNVisitor {
//-------- 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),
Expand All @@ -254,6 +274,7 @@ class ExpandVisitor final : public AstNVisitor {
}
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),
Expand All @@ -263,6 +284,7 @@ class ExpandVisitor final : public AstNVisitor {
}
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),
Expand All @@ -273,6 +295,7 @@ class ExpandVisitor final : public AstNVisitor {
//-------- 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),
Expand Down Expand Up @@ -417,6 +440,7 @@ class ExpandVisitor final : public AstNVisitor {

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);
Expand Down Expand Up @@ -647,6 +671,7 @@ class ExpandVisitor final : public AstNVisitor {
}
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();
Expand Down Expand Up @@ -701,6 +726,7 @@ class ExpandVisitor final : public AstNVisitor {
}
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);
Expand Down Expand Up @@ -857,6 +883,7 @@ class ExpandVisitor final : public AstNVisitor {
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)) {
Expand Down Expand Up @@ -897,7 +924,11 @@ class ExpandVisitor final : public AstNVisitor {
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);
}
};

//----------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions src/V3Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/V3Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ class V3Options final {
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
Expand Down Expand Up @@ -482,6 +483,7 @@ class V3Options final {
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; }
Expand Down
20 changes: 20 additions & 0 deletions test_regress/t/t_flag_expand_limit.pl
Original file line number Diff line number Diff line change
@@ -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 changes: 27 additions & 0 deletions test_regress/t/t_flag_expand_limit.v
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions test_regress/t/t_reloop_cam.pl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

compile(
verilator_flags2 => ["-unroll-count 1024",
"--expand-limit 1024",
$Self->wno_unopthreads_for_few_cores(),
"--stats"],
);
Expand Down

0 comments on commit 1e89392

Please sign in to comment.