From fa771415194a36ad9bb33c025fdf4b1fbd98e291 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 18 Nov 2020 20:12:14 -0500 Subject: [PATCH] Fix unpacked array parameters near functions (#2639). --- Changes | 2 ++ src/V3Param.cpp | 11 ++---- test_regress/t/t_param_array6.pl | 21 +++++++++++ test_regress/t/t_param_array6.v | 61 ++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 9 deletions(-) create mode 100755 test_regress/t/t_param_array6.pl create mode 100644 test_regress/t/t_param_array6.v diff --git a/Changes b/Changes index 5fed7394f4..a89ef1124b 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] +**** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] + * Verilator 4.104 2020-11-14 diff --git a/src/V3Param.cpp b/src/V3Param.cpp index e27824c74d..a73845d39c 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -245,7 +245,6 @@ class ParamVisitor : public AstNVisitor { typedef std::deque CellList; CellList m_cellps; // Cells left to process (in this module) - AstNodeFTask* m_ftaskp = nullptr; // Function/task reference AstNodeModule* m_modp = nullptr; // Current module being processed string m_unlinkedTxt; // Text for AstUnlinkedRef UnrollStateful m_unroller; // Loop unroller @@ -605,13 +604,6 @@ class ParamVisitor : public AstNVisitor { nodep->user5p(genHierNamep); m_cellps.push_back(nodep); } - virtual void visit(AstNodeFTask* nodep) override { - VL_RESTORER(m_ftaskp); - { - m_ftaskp = nodep; - iterateChildren(nodep); - } - } // Make sure all parameters are constantified virtual void visit(AstVar* nodep) override { @@ -633,7 +625,7 @@ class ParamVisitor : public AstNVisitor { new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), nodep->valuep()->cloneTree(true)))); - if (m_ftaskp) { + if (nodep->isFuncLocal()) { // We put the initial in wrong place under a function. We // should move the parameter out of the function and to the // module, with appropriate dotting, but this confuses LinkDot @@ -648,6 +640,7 @@ class ParamVisitor : public AstNVisitor { } // Make sure varrefs cause vars to constify before things above virtual void visit(AstVarRef* nodep) override { + // Might jump across functions, so beware if ever add a m_funcp if (nodep->varp()) iterate(nodep->varp()); } bool ifaceParamReplace(AstVarXRef* nodep, AstNode* candp) { diff --git a/test_regress/t/t_param_array6.pl b/test_regress/t/t_param_array6.pl new file mode 100755 index 0000000000..b46d46042d --- /dev/null +++ b/test_regress/t/t_param_array6.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_param_array6.v b/test_regress/t/t_param_array6.v new file mode 100644 index 0000000000..34766e731b --- /dev/null +++ b/test_regress/t/t_param_array6.v @@ -0,0 +1,61 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Anderson Ignacio da Silva. +// SPDX-License-Identifier: CC0-1.0 + +package test_pkg; + localparam [31:0] test_arr [4][4:0] + = '{ + '{'h0000, 'h1000, 'h2000, 'h3000, 'h4000}, + '{'h0FFF, 'h1FFF, 'h2FFF, 'h3FFF, 'h4FFF}, + '{ 'd0, 'd0, 'd0, 'd0, 'd0}, + '{ 'd0, 'd1, 'd2, 'd3, 'd4} + }; + + typedef struct packed{ + logic [7:0] val_1; + logic [7:0] val_2; + } test_ret_t; +endpackage + +module t import test_pkg::*; (clk); + input clk; + + function automatic test_ret_t test_f(logic [31:0] val); + test_ret_t temp; + + temp = test_ret_t'(0); + for (int i=0; i<5; i++) begin + if (val >= test_arr[0][i] && val <= test_arr[1][i]) begin + temp.val_1 = test_arr[2][i][7:0]; + temp.val_2 = test_arr[3][i][7:0]; + end + end + return temp; + endfunction + + test_ret_t temp; + logic [31:0] random; + + int cyc; + bit [63:0] sum; + + always @ (posedge clk) begin + cyc <= cyc + 1; + random <= {17'b0, cyc[3:0], 11'b0}; + temp <= test_f(random); +`ifdef TEST_VERBOSE + $display("rand: %h / Values -> val_1: %d / val_2: %d", random, temp.val_1, temp.val_2); +`endif + if (cyc > 10 && cyc < 90) begin + sum <= {48'h0, temp} ^ {sum[62:0],sum[63]^sum[2]^sum[0]}; + end + else if (cyc == 99) begin + $displayh(sum); + if (sum != 64'h74d34ea7a775f994) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule