From 9a9931fb9d8e899c7eb1c8cb4d27c39df60b54c5 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Nov 2020 13:46:14 -0500 Subject: [PATCH] Support complex function arguments. --- Changes | 8 ++-- include/verilated_heavy.h | 2 + src/V3AstNodes.h | 21 +++++----- src/V3Width.cpp | 15 ++----- test_regress/t/t_func_complex.pl | 21 ++++++++++ test_regress/t/t_func_complex.v | 54 ++++++++++++++++++++++++++ test_regress/t/t_func_complex_noinl.pl | 24 ++++++++++++ test_regress/t/t_func_refio_bad.out | 5 +++ test_regress/t/t_func_refio_bad.pl | 19 +++++++++ test_regress/t/t_func_refio_bad.v | 18 +++++++++ 10 files changed, 163 insertions(+), 24 deletions(-) create mode 100755 test_regress/t/t_func_complex.pl create mode 100644 test_regress/t/t_func_complex.v create mode 100755 test_regress/t/t_func_complex_noinl.pl create mode 100644 test_regress/t/t_func_refio_bad.out create mode 100755 test_regress/t/t_func_refio_bad.pl create mode 100644 test_regress/t/t_func_refio_bad.v diff --git a/Changes b/Changes index e740aff86..b2a3a5f9b 100644 --- a/Changes +++ b/Changes @@ -5,16 +5,18 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.105 devel -*** Change -sv option to select 1800-2017 instead of 1800-2005. +** Change -sv option to select 1800-2017 instead of 1800-2005. + +*** Check for proper 'local' and 'protected' (#2228). *** Support $random and $urandom seeds. +*** Support complex function arguments. + *** Support 'super'. *** Support 'with item.index'. -*** Check for proper 'local' and 'protected' (#2228). - **** Fix trace signal names getting hashed (#2643). [Barbara Gigerl] **** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva] diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index f6cb8dd71..0fd47d274 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -154,6 +154,7 @@ public: // METHODS T_Value& atDefault() { return m_defaultValue; } + const T_Value& atDefault() const { return m_defaultValue; } const Deque& privateDeque() const { return m_deque; } // Size. Verilog: function int size(), or int num() @@ -512,6 +513,7 @@ public: // METHODS T_Value& atDefault() { return m_defaultValue; } + const T_Value& atDefault() const { return m_defaultValue; } // Size of array. Verilog: function int size(), or int num() int size() const { return m_map.size(); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 09d1cdc91..38fa9d26d 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -395,7 +395,8 @@ public: virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } virtual bool similarDType(AstNodeDType* samep) const override { const AstParamTypeDType* sp = static_cast(samep); - return (sp && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp())); + return type() == samep->type() && sp + && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()); } virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } @@ -545,8 +546,8 @@ public: } virtual bool similarDType(AstNodeDType* samep) const override { const AstAssocArrayDType* asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } virtual string prettyDTypeName() const override; virtual void dumpSmall(std::ostream& str) const override; @@ -643,8 +644,8 @@ public: } virtual bool similarDType(AstNodeDType* samep) const override { const AstAssocArrayDType* asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } virtual string prettyDTypeName() const override; virtual void dumpSmall(std::ostream& str) const override; @@ -753,8 +754,8 @@ public: } virtual bool similarDType(AstNodeDType* samep) const override { const AstNodeArrayDType* asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } virtual void dumpSmall(std::ostream& str) const override; virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } @@ -1013,7 +1014,7 @@ public: return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep); } virtual bool similarDType(AstNodeDType* samep) const override { - return this == samep || same(samep); + return this == samep || (type() == samep->type() && same(samep)); } virtual V3Hash sameHash() const override { return V3Hash(V3Hash(m_classp), V3Hash(m_classOrPackagep)); @@ -1127,8 +1128,8 @@ public: } virtual bool similarDType(AstNodeDType* samep) const override { const AstQueueDType* asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } virtual void dumpSmall(std::ostream& str) const override; virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index af2a557c5..edba6166d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1787,13 +1787,6 @@ private: nodep->dtypep(newp); v3Global.rootp()->typeTablep()->addTypesp(newp); } - } else if (nodep->isIO() - && !(VN_IS(nodep->dtypeSkipRefp(), BasicDType) - || VN_IS(nodep->dtypeSkipRefp(), ClassRefDType) - || VN_IS(nodep->dtypeSkipRefp(), NodeArrayDType) - || VN_IS(nodep->dtypeSkipRefp(), NodeUOrStructDType))) { - nodep->v3warn(E_UNSUPPORTED, - "Unsupported: Inputs and outputs must be simple data types"); } if (VN_IS(nodep->dtypep()->skipRefToConstp(), ConstDType)) nodep->isConst(true); // Parameters if implicit untyped inherit from what they are assigned to @@ -1999,7 +1992,7 @@ private: } virtual void visit(AstConsAssoc* nodep) override { // Type computed when constructed here - auto* vdtypep = VN_CAST(m_vup->dtypep(), AssocArrayDType); + auto* vdtypep = VN_CAST(m_vup->dtypep()->skipRefp(), AssocArrayDType); UASSERT_OBJ(vdtypep, nodep, "ConsAssoc requires assoc upper parent data type"); if (m_vup->prelim()) { nodep->dtypeFrom(vdtypep); @@ -2011,7 +2004,7 @@ private: } virtual void visit(AstSetAssoc* nodep) override { // Type computed when constructed here - auto* vdtypep = VN_CAST(m_vup->dtypep(), AssocArrayDType); + auto* vdtypep = VN_CAST(m_vup->dtypep()->skipRefp(), AssocArrayDType); UASSERT_OBJ(vdtypep, nodep, "SetsAssoc requires assoc upper parent data type"); if (m_vup->prelim()) { nodep->dtypeFrom(vdtypep); @@ -2024,7 +2017,7 @@ private: } virtual void visit(AstConsDynArray* nodep) override { // Type computed when constructed here - AstDynArrayDType* vdtypep = VN_CAST(m_vup->dtypep(), DynArrayDType); + AstDynArrayDType* vdtypep = VN_CAST(m_vup->dtypep()->skipRefp(), DynArrayDType); UASSERT_OBJ(vdtypep, nodep, "ConsDynArray requires queue upper parent data type"); if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(vdtypep, PRELIM).p()); @@ -2056,7 +2049,7 @@ private: } virtual void visit(AstConsQueue* nodep) override { // Type computed when constructed here - AstQueueDType* vdtypep = VN_CAST(m_vup->dtypep(), QueueDType); + AstQueueDType* vdtypep = VN_CAST(m_vup->dtypep()->skipRefp(), QueueDType); UASSERT_OBJ(vdtypep, nodep, "ConsQueue requires queue upper parent data type"); if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(vdtypep, PRELIM).p()); diff --git a/test_regress/t/t_func_complex.pl b/test_regress/t/t_func_complex.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_func_complex.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_func_complex.v b/test_regress/t/t_func_complex.v new file mode 100644 index 000000000..142088d35 --- /dev/null +++ b/test_regress/t/t_func_complex.v @@ -0,0 +1,54 @@ +// 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(); + typedef integer q_t[$]; + + function void queue_set(ref q_t q); +`ifdef TEST_NOINLINE + // verilator no_inline_task +`endif + q.push_back(42); + endfunction + + function void queue_check_nref(q_t q); +`ifdef TEST_NOINLINE + // verilator no_inline_task +`endif + q[0] = 11; + if (q[0] != 11) $stop; + endfunction + + function void queue_check_ref(const ref q_t q); +`ifdef TEST_NOINLINE + // verilator no_inline_task +`endif + if (q[0] != 42) $stop; + endfunction + + function q_t queue_ret(); +`ifdef TEST_NOINLINE + // verilator no_inline_task +`endif + queue_ret = '{101}; + endfunction + + initial begin + q_t iq; + queue_set(iq); + queue_check_ref(iq); + + iq[0] = 44; + queue_check_nref(iq); + if (iq[0] != 44) $stop; + + iq = queue_ret(); + if (iq[0] != 101) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_func_complex_noinl.pl b/test_regress/t/t_func_complex_noinl.pl new file mode 100755 index 000000000..e7a493593 --- /dev/null +++ b/test_regress/t/t_func_complex_noinl.pl @@ -0,0 +1,24 @@ +#!/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 + +top_filename("t/t_func_complex.v"); + +scenarios(simulator => 1); + +compile( + v_flags2 => ["+define+TEST_NOINLINE"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_refio_bad.out b/test_regress/t/t_func_refio_bad.out new file mode 100644 index 000000000..7d92bd42a --- /dev/null +++ b/test_regress/t/t_func_refio_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_func_refio_bad.v:16:17: Ref argument requires matching types; port 'q' requires VAR 'q' but connection is CONST '?32?sh2a'. + : ... In instance t + 16 | queue_set(42); + | ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_func_refio_bad.pl b/test_regress/t/t_func_refio_bad.pl new file mode 100755 index 000000000..59ba0d6c6 --- /dev/null +++ b/test_regress/t/t_func_refio_bad.pl @@ -0,0 +1,19 @@ +#!/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(linter => 1); + +lint( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_refio_bad.v b/test_regress/t/t_func_refio_bad.v new file mode 100644 index 000000000..dc117ac4f --- /dev/null +++ b/test_regress/t/t_func_refio_bad.v @@ -0,0 +1,18 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(); + typedef integer q_t[$]; + + function void queue_set(ref q_t q); + q.push_back(42); + endfunction + + initial begin + q_t iq; + queue_set(42); // 42 is bad, meant iq + end +endmodule