diff --git a/Changes b/Changes index 59fe2a096..48a50fe42 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix genvar to be signed, so "< 0" works properly. [Niranjan Prabhu] +**** Fix assignments to inputs inside functions/tasks. [Patricio Kaplan] + * Verilator 3.658 2008/02/25 **** Fix unistd compile error in 3.657. [Patricio Kaplan, Jonathan Kimmitt] diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 17e4d0e53..86eb241d5 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -45,6 +45,7 @@ private: // STATE bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments + AstNodeFTask* m_ftaskp; // Function or task we're inside //int debug() { return 9; } @@ -59,7 +60,9 @@ private: } if (nodep->varp()) { if (nodep->lvalue() && nodep->varp()->isInOnly()) { - nodep->v3error("Assigning to input variable: "<prettyName()); + if (!m_ftaskp) { + nodep->v3error("Assigning to input variable: "<prettyName()); + } } } nodep->iterateChildren(*this); @@ -150,6 +153,11 @@ private: } m_setRefLvalue = last_setRefLvalue; } + virtual void visit(AstNodeFTask* nodep, AstNUser*) { + m_ftaskp = nodep; + nodep->iterateChildren(*this); + m_ftaskp = NULL; + } virtual void visit(AstNode* nodep, AstNUser*) { // Default: Just iterate @@ -160,6 +168,7 @@ public: // CONSTUCTORS LinkLValueVisitor(AstNetlist* rootp) { m_setRefLvalue = false; + m_ftaskp = NULL; rootp->accept(*this); } virtual ~LinkLValueVisitor() {} diff --git a/test_regress/t/t_func_mlog2.pl b/test_regress/t/t_func_mlog2.pl new file mode 100755 index 000000000..7bfdbe852 --- /dev/null +++ b/test_regress/t/t_func_mlog2.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# $Id$ +# 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 +# General Public License or the Perl Artistic License. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_mlog2.v b/test_regress/t/t_func_mlog2.v new file mode 100644 index 000000000..286c5fc99 --- /dev/null +++ b/test_regress/t/t_func_mlog2.v @@ -0,0 +1,56 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003-2008 by Wilson Snyder. + +module t (clk); + input clk; + + integer cyc; initial cyc=1; + integer sum; + integer cpre; + always @ (posedge clk) begin + if (cyc!=0) begin + cpre = cyc; + cyc <= cyc + 1; + if (cyc==1) begin + if (mlog2(32'd0) != 32'd0) $stop; + if (mlog2(32'd1) != 32'd0) $stop; + if (mlog2(32'd3) != 32'd2) $stop; + sum <= 32'd0; + end + else if (cyc<90) begin + // (cyc) so if we trash the variable things will get upset. + sum <= mlog2(cyc) + sum * 32'd42; + if (cpre != cyc) $stop; + end + else if (cyc==90) begin + if (sum !== 32'h0f12bb51) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end + end + + function integer mlog2; + input [31:0] value; + integer i; + begin + if(value < 32'd1) begin + mlog2 = 0; + end + else begin + value = value - 32'd1; + mlog2 = 0; + for(i=0;i<32;i=i+1) begin + if(value > 32'd0) begin + mlog2 = mlog2 + 1; + end + value = value >> 1; + end + end + end + endfunction + +endmodule