From b73edc0564f0bf30ef70e7bcd12e4cdd2a4d17c9 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 15 Oct 2014 21:29:37 -0400 Subject: [PATCH] Fix generate unrolling with function call, bug830. --- Changes | 2 ++ src/V3Unroll.cpp | 40 +++++++++++++++++++++++---------- test_regress/t/t_unroll_genf.pl | 18 +++++++++++++++ test_regress/t/t_unroll_genf.v | 29 ++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 12 deletions(-) create mode 100755 test_regress/t/t_unroll_genf.pl create mode 100644 test_regress/t/t_unroll_genf.v diff --git a/Changes b/Changes index 65704ec22..ffcf180ce 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.865 devel +**** Fix generate unrolling with function call, bug830. [Steven Slatter] + * Verilator 3.864 2014-09-21 diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 80d66f436..135560d89 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -164,15 +164,27 @@ private: bool gt = condp->castGt() || condp->castGtS(); bool gte = condp->castGte() || condp->castGteS(); if (!lt && !lte && !gt && !gte) - return cantUnroll(nodep, "condition not <= or <"); - AstNodeBiop* condBip = condp->castNodeBiop(); - if (!condBip->rhsp()->castVarRef()) + return cantUnroll(nodep, "condition not <=, <, >= or >"); + AstNodeBiop* cmpInstrp = condp->castNodeBiop(); + bool cmpVarLhs; + if (cmpInstrp->lhsp()->castVarRef() + && cmpInstrp->lhsp()->castVarRef()->varp() == m_forVarp + && cmpInstrp->lhsp()->castVarRef()->varScopep() == m_forVscp) { + cmpVarLhs = true; + } else if (cmpInstrp->rhsp()->castVarRef() + && cmpInstrp->rhsp()->castVarRef()->varp() == m_forVarp + && cmpInstrp->rhsp()->castVarRef()->varScopep() == m_forVscp) { + cmpVarLhs = false; + } else if (!cmpInstrp->rhsp()->castVarRef()) { return cantUnroll(nodep, "no variable on rhs of condition"); - if (condBip->rhsp()->castVarRef()->varp() != m_forVarp - || condBip->rhsp()->castVarRef()->varScopep() != m_forVscp) + } else { return cantUnroll(nodep, "different variable in condition"); - if (m_generate) V3Const::constifyParamsEdit(condBip->lhsp()); // rhsp may change - AstConst* constStopp = condBip->lhsp()->castConst(); + } + + if (m_generate) V3Const::constifyParamsEdit(cmpVarLhs ? cmpInstrp->rhsp() + : cmpInstrp->lhsp()); // rhsp/lhsp may change + AstConst* constStopp = (cmpVarLhs ? cmpInstrp->rhsp()->castConst() + : cmpInstrp->lhsp()->castConst()); if (!constStopp) return cantUnroll(nodep, "non-constant final value"); UINFO(8, " Stop expr ok: "<num(), - condBip, constStopp->num(), + cmpInstrp, constStopp->num(), cmpVarLhs, incInstrp, constIncp->num()); nodep = NULL; // Cleanup return true; @@ -227,10 +239,10 @@ private: void forUnroller(AstNode* nodep, AstNode* initp, - AstNode* precondsp, AstNode* condp, + AstNode* precondsp, AstNode* incp, AstNode* bodysp, const V3Number& numInit, - AstNodeBiop* cmpInstrp, const V3Number& numStop, + AstNodeBiop* cmpInstrp, const V3Number& numStop, bool cmpVarLhs, AstNodeBiop* incInstrp, const V3Number& numInc) { UINFO(4, " Unroll for var="<fileline(), 1); - cmpInstrp->numberOperate(contin, numStop, loopValue); + if (cmpVarLhs) { + cmpInstrp->numberOperate(contin, loopValue, numStop); + } else { + cmpInstrp->numberOperate(contin, numStop, loopValue); + } if (contin.isEqZero()) { break; // Done with the loop } else { diff --git a/test_regress/t/t_unroll_genf.pl b/test_regress/t/t_unroll_genf.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_unroll_genf.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_genf.v b/test_regress/t/t_unroll_genf.v new file mode 100644 index 000000000..776f1b328 --- /dev/null +++ b/test_regress/t/t_unroll_genf.v @@ -0,0 +1,29 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2004 by Wilson Snyder. + +//bug830 +module sub(); +endmodule + +function integer cdiv(input integer x); + begin + cdiv = 10; + end +endfunction + +module t (/*AUTOARG*/); + + genvar j; + generate + for (j = 0; j < cdiv(10); j=j+1) + sub sub(); + endgenerate + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule