Fix gate optimization out of memory, add --gate-stmts, bug1260.

This commit is contained in:
Wilson Snyder 2018-01-27 15:06:51 -05:00
parent 652b68a5a0
commit 71fcf45d73
6 changed files with 78 additions and 1 deletions

View File

@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 3.919 devel
**** Fix gate optimization out of memory, add --gate-stmts, bug1260. [Alex Solomatnikov]
**** Fix compile error on public real parameters by suppressing, bug1261. [Alex Solomatnikov]
**** Fix input-only tristate comparisons, bug1267. [Alexis G]

View File

@ -289,6 +289,7 @@ descriptions in the next sections for more information.
--getenv <var> Get environment variable with defaults
--help Display this help
-I<dir> Directory to search for includes
--gate-stmts <value> Tune gate optimizer depth
--if-depth <value> Tune IFDEPTH warning
+incdir+<dir> Directory to search for includes
--inhibit-sim Create function to turn off sim
@ -750,6 +751,11 @@ them properly, e.g. as -GSTR="\"My String\"" or -GSTR='"My String"'.
=back
=item --gate-stmts I<value>
Rarely needed. Set the maximum number of statements that may be present in
an equation for the gate substitution optimization to inline that equation.
=item --gdb
Run Verilator underneath an interactive GDB (or VERILATOR_GDB environment

View File

@ -195,6 +195,7 @@ private:
bool m_buffersOnly; // Set when we only allow simple buffering, no equations (for clocks)
AstNodeVarRef* m_lhsVarRef; // VarRef on lhs of assignment (what we're replacing)
bool m_dedupe; // Set when we use isGateDedupable instead of isGateOptimizable
int m_ops; // Operation count
// METHODS
void clearSimple(const char* because) {
@ -205,6 +206,7 @@ private:
}
// VISITORS
virtual void visit(AstNodeVarRef* nodep) {
++m_ops;
nodep->iterateChildren(*this);
// We only allow a LHS ref for the var being set, and a RHS ref for something else being read.
if (nodep->varScopep()->varp()->isSc()) {
@ -254,6 +256,9 @@ private:
virtual void visit(AstNode* nodep) {
// *** Special iterator
if (!m_isSimple) return; // Fastpath
if (++m_ops > v3Global.opt.gateStmts()) {
clearSimple("--gate-stmts exceeded");
}
if (!(m_dedupe ? nodep->isGateDedupable() : nodep->isGateOptimizable())
|| !nodep->isPure()
|| nodep->isBrancher()) {
@ -270,6 +275,7 @@ public:
m_buffersOnly = buffersOnly;
m_lhsVarRef = NULL;
m_dedupe = dedupe;
m_ops = 0;
// Iterate
nodep->accept(*this);
// Check results
@ -327,7 +333,7 @@ private:
// METHODS
void iterateNewStmt(AstNode* nodep, const char* nonReducibleReason, const char* consumeReason) {
if (m_scopep) {
UINFO(4," STMT "<<nodep<<endl);
UINFO(5," STMT "<<nodep<<endl);
// m_activep is null under AstCFunc's, that's ok.
m_logicVertexp = new GateLogicVertex(&m_graph, m_scopep, nodep, m_activep, m_inSlow);
if (nonReducibleReason) {

View File

@ -787,6 +787,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( !strncmp (sw, "-G", strlen("-G"))) {
addParameter(string (sw+strlen("-G")), false);
}
else if ( !strcmp (sw, "-gate-stmts") && (i+1)<argc ) {
shift;
m_gateStmts = atoi(argv[i]);
}
else if ( !strcmp (sw, "-getenv") && (i+1)<argc ) {
shift;
cout<<V3Options::getenvBuiltins(argv[i])<<endl;
@ -1252,6 +1256,7 @@ V3Options::V3Options() {
m_convergeLimit = 100;
m_dumpTree = 0;
m_gateStmts = 100;
m_ifDepth = 0;
m_inlineMult = 2000;
m_moduleRecursion = 100;

View File

@ -107,6 +107,7 @@ class V3Options {
int m_convergeLimit;// main switch: --converge-limit
int m_dumpTree; // main switch: --dump-tree
int m_gateStmts; // main switch: --gate-stmts
int m_ifDepth; // main switch: --if-depth
int m_inlineMult; // main switch: --inline-mult
int m_moduleRecursion;// main switch: --module-recursion-depth
@ -254,6 +255,7 @@ class V3Options {
int convergeLimit() const { return m_convergeLimit; }
int dumpTree() const { return m_dumpTree; }
int gateStmts() const { return m_gateStmts; }
int ifDepth() const { return m_ifDepth; }
int inlineMult() const { return m_inlineMult; }
int moduleRecursionDepth() const { return m_moduleRecursion; }

View File

@ -0,0 +1,56 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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.
use IO::File;
sub gen {
my $filename = shift;
my $fh = IO::File->new(">$filename");
$fh->print("// Generated by t_gate_chained.pl\n");
$fh->print("module t (clk,i,sel,o);\n");
$fh->print(" input clk;\n");
$fh->print(" input [63:0] i;\n");
$fh->print(" input [15:0] sel;\n");
$fh->print(" output [63:0] o;\n");
$fh->print("\n");
my $prev = "i";
my $n = 9000;
for (my $i=1; $i<$n; ++$i) {
$fh->printf(" wire [63:0] ass%04x = (sel == 16'h%04x) ? 64'h0 : $prev;\n", $i, $i);
$prev = sprintf("ass%04x", $i);
}
$fh->print("\n");
$fh->print(" wire [63:0] o = $prev;\n");
$fh->print("\n");
$fh->print(" always @ (posedge clk) begin\n");
$fh->print(' $write("*-* All Finished *-*\n");',"\n");
$fh->print(' $finish;',"\n");
$fh->print(" end\n");
$fh->print("endmodule\n");
}
top_filename("$Self->{obj_dir}/t_gate_chained.v");
gen($Self->{top_filename});
compile (
verilator_flags2=>["--stats --x-assign fast --x-initial fast"],
);
execute (
check_finished=>1,
);
# Must be <<9000 above to prove this worked
file_grep ($Self->{stats}, qr/Optimizations, Gate sigs deleted\s+(\d+)/i, 8575);
ok(1);
1;