diff --git a/Changes b/Changes index 3d140f445..7b91b9fb4 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 3.891 devel +**** Fix internal error on double-for loop unrolling, bug1044. [Jan Egil Ruud] + * Verilator 3.890 2016-11-25 diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 516820453..a49898ae4 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -353,7 +353,9 @@ private: AstNode* valuep = nodep->itemp()->valuep(); if (valuep) { valuep->iterateAndNext(*this); - newNumber(nodep)->opAssign(*fetchNumber(valuep)); + if (optimizable()) { + newNumber(nodep)->opAssign(*fetchNumber(valuep)); + } } else { clearOptimizable(nodep, "No value found for enum item"); } @@ -394,11 +396,13 @@ private: nodep->iterateChildren(*this); } else { nodep->lhsp()->accept(*this); - if (fetchNumber(nodep->lhsp())->isNeqZero()) { - nodep->rhsp()->accept(*this); - newNumber(nodep)->opAssign(*fetchNumber(nodep->rhsp())); - } else { - newNumber(nodep)->opAssign(*fetchNumber(nodep->lhsp())); // a zero + if (optimizable()) { + if (fetchNumber(nodep->lhsp())->isNeqZero()) { + nodep->rhsp()->accept(*this); + newNumber(nodep)->opAssign(*fetchNumber(nodep->rhsp())); + } else { + newNumber(nodep)->opAssign(*fetchNumber(nodep->lhsp())); // a zero + } } } } @@ -410,11 +414,13 @@ private: nodep->iterateChildren(*this); } else { nodep->lhsp()->accept(*this); - if (fetchNumber(nodep->lhsp())->isNeqZero()) { - newNumber(nodep)->opAssign(*fetchNumber(nodep->lhsp())); // a one - } else { - nodep->rhsp()->accept(*this); - newNumber(nodep)->opAssign(*fetchNumber(nodep->rhsp())); + if (optimizable()) { + if (fetchNumber(nodep->lhsp())->isNeqZero()) { + newNumber(nodep)->opAssign(*fetchNumber(nodep->lhsp())); // a one + } else { + nodep->rhsp()->accept(*this); + newNumber(nodep)->opAssign(*fetchNumber(nodep->rhsp())); + } } } } @@ -426,11 +432,13 @@ private: nodep->iterateChildren(*this); } else { nodep->lhsp()->accept(*this); - if (fetchNumber(nodep->lhsp())->isEqZero()) { - newNumber(nodep)->opAssign(V3Number(nodep->fileline(), 1, 1)); // a one - } else { - nodep->rhsp()->accept(*this); - newNumber(nodep)->opAssign(*fetchNumber(nodep->rhsp())); + if (optimizable()) { + if (fetchNumber(nodep->lhsp())->isEqZero()) { + newNumber(nodep)->opAssign(V3Number(nodep->fileline(), 1, 1)); // a one + } else { + nodep->rhsp()->accept(*this); + newNumber(nodep)->opAssign(*fetchNumber(nodep->rhsp())); + } } } } @@ -443,12 +451,14 @@ private: nodep->iterateChildren(*this); } else { nodep->condp()->accept(*this); - if (fetchNumber(nodep->condp())->isNeqZero()) { - nodep->expr1p()->accept(*this); - newNumber(nodep)->opAssign(*fetchNumber(nodep->expr1p())); - } else { - nodep->expr2p()->accept(*this); - newNumber(nodep)->opAssign(*fetchNumber(nodep->expr2p())); + if (optimizable()) { + if (fetchNumber(nodep->condp())->isNeqZero()) { + nodep->expr1p()->accept(*this); + newNumber(nodep)->opAssign(*fetchNumber(nodep->expr1p())); + } else { + nodep->expr2p()->accept(*this); + newNumber(nodep)->opAssign(*fetchNumber(nodep->expr2p())); + } } } } @@ -670,6 +680,7 @@ private: virtual void visit(AstFuncRef* nodep) { if (jumpingOver(nodep)) return; + if (!optimizable()) return; // Accelerate UINFO(5," FUNCREF "<taskp()->castNodeFTask(); if (!funcp) nodep->v3fatalSrc("Not linked"); @@ -717,6 +728,7 @@ private: virtual void visit(AstSFormatF *nodep) { if (jumpingOver(nodep)) return; + if (!optimizable()) return; // Accelerate nodep->iterateChildren(*this); if (m_params) { AstNode* nextArgp = nodep->exprsp(); @@ -761,6 +773,7 @@ private: virtual void visit(AstDisplay *nodep) { if (jumpingOver(nodep)) return; + if (!optimizable()) return; // Accelerate nodep->iterateChildren(*this); if (m_params) { switch (nodep->displayType()) { diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 91cfa96b3..ebc08bbd1 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -269,6 +269,7 @@ private: AstNode* condp, AstNode* precondsp, AstNode* incp, AstNode* bodysp) { + UINFO(9, "forUnroller "<fileline()); if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) { return false; @@ -354,7 +355,7 @@ private: if (precondsp) { pushDeletep(precondsp); VL_DANGLING(precondsp); } if (initp) { pushDeletep(initp); VL_DANGLING(initp); } if (incp && !incp->backp()) { pushDeletep(incp); VL_DANGLING(incp); } - if (debug()>=9) newbodysp->dumpTree(cout,"- _new: "); + if (debug()>=9 && newbodysp) newbodysp->dumpTree(cout,"- _new: "); return true; } diff --git a/test_regress/t/t_unroll_forfor.pl b/test_regress/t/t_unroll_forfor.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_unroll_forfor.pl @@ -0,0 +1,18 @@ +#!/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. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_unroll_forfor.v b/test_regress/t/t_unroll_forfor.v new file mode 100644 index 000000000..fee7b8c00 --- /dev/null +++ b/test_regress/t/t_unroll_forfor.v @@ -0,0 +1,35 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This files is used to generated the following error: +// %Error: Internal Error: t/t_unroll_forfor.v:27: ../V3Simulate.h:177: No value found for node. +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2016 by Jan Egil Ruud. + +module t (/*AUTOARG*/ + // Inputs + clk, in + ); + input clk; + input [71:0] in; + + reg [71:0] in_tmp; + + localparam [71:0] TEST_PARAM = {72{1'b0}}; + + // Test loop + always @* + begin: testmap + byte i, j; + // bug1044 + for ( i = 0; i < 9; i = i + 1 ) + for ( j=0; j<(TEST_PARAM[i*8+:8]); j=j+1 ) + begin + // verilator lint_off WIDTH + in_tmp[TEST_PARAM[i*8+:8]+j] = in[TEST_PARAM[i*8+:8]+j]; + // verilator lint_on WIDTH + end + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule