From 1488f9130d277cbdaf768fa338162f50b81060a4 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 15 Jul 2020 19:31:19 -0400 Subject: [PATCH] Enable simple function localparams (#2461) --- include/verilated_save.h | 4 +- src/V3LinkDot.cpp | 6 --- src/V3Param.cpp | 18 +++++++++ test_regress/t/t_param_func2.pl | 21 +++++++++++ test_regress/t/t_param_func2.v | 52 ++++++++++++++++++++++++++ test_regress/t/t_param_in_func_bad.out | 6 +-- 6 files changed, 95 insertions(+), 12 deletions(-) create mode 100755 test_regress/t/t_param_func2.pl create mode 100644 test_regress/t/t_param_func2.v diff --git a/include/verilated_save.h b/include/verilated_save.h index 9925194ef..cf6c3a5a5 100644 --- a/include/verilated_save.h +++ b/include/verilated_save.h @@ -55,7 +55,7 @@ public: } virtual ~VerilatedSerialize() { close(); - if (m_bufp) VL_DO_CLEAR(delete [] m_bufp, m_bufp = NULL); + if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = NULL); } // METHODS bool isOpen() const { return m_isOpen; } @@ -118,7 +118,7 @@ public: } virtual ~VerilatedDeserialize() { close(); - if (m_bufp) VL_DO_CLEAR(delete [] m_bufp, m_bufp = NULL); + if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = NULL); } // METHODS bool isOpen() const { return m_isOpen; } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index df29eec9f..18af595a0 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1008,12 +1008,6 @@ class LinkDotFindVisitor : public AstNVisitor { // Var: Remember its name for later resolution UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?"); iterateChildren(nodep); - if (m_ftaskp && nodep->isParam()) { - nodep->v3warn(E_UNSUPPORTED, - "Unsupported: Parameters in functions"); // Big3 unsupported too - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - return; - } if (nodep->isFuncLocal() && nodep->lifetime().isStatic()) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: 'static' function/task variables"); } else if (nodep->isClassMember() && nodep->lifetime().isStatic()) { diff --git a/src/V3Param.cpp b/src/V3Param.cpp index ad43808c2..2159ff938 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -106,6 +106,8 @@ private: typedef std::deque CellList; CellList m_cellps; // Cells left to process (in this module) + AstNodeFTask* m_ftaskp; // Function/task reference + AstNodeModule* m_modp; // Current module being processed string m_unlinkedTxt; // Text for AstUnlinkedRef @@ -302,6 +304,11 @@ private: nodep->user5p(genHierNamep); m_cellps.push_back(nodep); } + virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + m_ftaskp = nodep; + iterateChildren(nodep); + m_ftaskp = NULL; + } // Make sure all parameters are constantified virtual void visit(AstVar* nodep) VL_OVERRIDE { @@ -323,6 +330,16 @@ private: new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true), nodep->valuep()->cloneTree(true)))); + if (m_ftaskp) { + // 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 + // (as then name isn't found later), so punt - probably can + // treat as static function variable when that is supported. + nodep->v3warn( + E_UNSUPPORTED, + "Unsupported: Parameters in functions with complex assign"); + } } } } @@ -556,6 +573,7 @@ public: // CONSTRUCTORS explicit ParamVisitor(AstNetlist* nodep) { m_longId = 0; + m_ftaskp = NULL; m_modp = NULL; m_nextValue = 1; // diff --git a/test_regress/t/t_param_func2.pl b/test_regress/t/t_param_func2.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_param_func2.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_func2.v b/test_regress/t/t_param_func2.v new file mode 100644 index 000000000..432d2914d --- /dev/null +++ b/test_regress/t/t_param_func2.v @@ -0,0 +1,52 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + sub #(.WIDTH(4)) sub4(); + sub #(.WIDTH(8)) sub8(); + + logic [3:0] out4; + logic [7:0] out8; + + initial begin + out4 = sub4.orer(4'b1000); + out8 = sub8.orer(8'b10000000); + if (out4 != 4'b1011) $stop; + if (out8 != 8'b10111111) $stop; + out4 = sub4.orer2(4'b1000); + out8 = sub8.orer2(8'b10000000); + if (out4 != 4'b1001) $stop; + if (out8 != 8'b10011111) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + + +module sub; + parameter WIDTH = 1; + + function [WIDTH-1:0] orer; + input [WIDTH-1:0] in; + // IEEE provices no way to override this parameter, basically it's a localparam + parameter MASK_W = WIDTH - 2; + localparam [MASK_W-1:0] MASK = '1; + // verilator lint_off WIDTH + return in | MASK; + // verilator lint_on WIDTH + endfunction + + function [WIDTH-1:0] orer2; + input [WIDTH-1:0] in; + // Same param names as other function to check we disambiguate + // IEEE provices no way to override this parameter, basically it's a localparam + parameter MASK_W = WIDTH - 3; + localparam [MASK_W-1:0] MASK = '1; + // verilator lint_off WIDTH + return in | MASK; + // verilator lint_on WIDTH + endfunction +endmodule diff --git a/test_regress/t/t_param_in_func_bad.out b/test_regress/t/t_param_in_func_bad.out index f152cd026..683490111 100644 --- a/test_regress/t/t_param_in_func_bad.out +++ b/test_regress/t/t_param_in_func_bad.out @@ -1,7 +1,5 @@ -%Error-UNSUPPORTED: t/t_param_in_func_bad.v:24:26: Unsupported: Parameters in functions +%Error-UNSUPPORTED: t/t_param_in_func_bad.v:24:26: Unsupported: Parameters in functions with complex assign + : ... In instance t 24 | localparam logic[7:0] digits[10] | ^~~~~~ -%Error: t/t_param_in_func_bad.v:28:11: Can't find definition of variable: 'digits' - 28 | return digits[d]; - | ^~~~~~ %Error: Exiting due to