diff --git a/include/verilated_types.h b/include/verilated_types.h index ac3ef8994..bae054c5f 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -1145,6 +1145,13 @@ public: if (it == m_map.rend()) return VlQueue{}; return VlQueue::consV(it->first); } + // Map method (IEEE 1800-2023 7.12.5) + template + VlQueue> map(T_Func with_func) const { + VlQueue> out; + for (const auto& i : m_map) out.push_back(with_func(i.first, i.second)); + return out; + } // Reduction operators VlQueue min() const { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index bff4aef37..660b7e73a 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -4035,9 +4035,16 @@ class WidthVisitor final : public VNVisitor { newp->dtypep(queueDTypeIndexedBy(adtypep->subDTypep())); if (!nodep->firstAbovep()) newp->dtypeSetVoid(); } else if (nodep->name() == "map") { - nodep->v3warn(E_UNSUPPORTED, - "Unsupported: Wildcard array 'map' method (IEEE 1800-2023 7.12.5)"); - nodep->dtypeFrom(adtypep->subDTypep()); // Best guess + AstWith* const withp + = methodWithClause(nodep, true, false, adtypep->subDTypep(), + adtypep->findStringDType(), adtypep->subDTypep()); + methodOkArguments(nodep, 0, 0); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); + newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), + VCMethod::ARRAY_MAP}; + newp->withp(withp); + newp->dtypep(queueDTypeIndexedBy(withp ? withp->dtypep() : adtypep->subDTypep())); + if (!nodep->firstAbovep()) newp->dtypeSetVoid(); } else { nodep->v3error("Unknown wildcard associative array method " << nodep->prettyNameQ()); nodep->dtypeFrom(adtypep->subDTypep()); // Best guess @@ -4148,9 +4155,15 @@ class WidthVisitor final : public VNVisitor { newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep())); if (!nodep->firstAbovep()) newp->dtypeSetVoid(); } else if (nodep->name() == "map") { - nodep->v3warn(E_UNSUPPORTED, - "Unsupported: Associative array 'map' method (IEEE 1800-2023 7.12.5)"); - nodep->dtypeFrom(adtypep->subDTypep()); // Best guess + AstWith* const withp = methodWithClause(nodep, true, false, adtypep->subDTypep(), + adtypep->keyDTypep(), adtypep->subDTypep()); + methodOkArguments(nodep, 0, 0); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); + newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), + VCMethod::ARRAY_MAP}; + newp->withp(withp); + newp->dtypep(queueDTypeIndexedBy(withp ? withp->dtypep() : adtypep->subDTypep())); + if (!nodep->firstAbovep()) newp->dtypeSetVoid(); } else { nodep->v3error("Unknown built-in associative array method " << nodep->prettyNameQ()); nodep->dtypeFrom(adtypep->subDTypep()); // Best guess diff --git a/test_regress/t/t_assoc_method.v b/test_regress/t/t_assoc_method.v index 82e4970a6..5405d1e37 100644 --- a/test_regress/t/t_assoc_method.v +++ b/test_regress/t/t_assoc_method.v @@ -208,6 +208,13 @@ module t; b = points_q.sum with (vec_len_squared(item) inside {5, 17, 20}); `checkh(b, 1'b1); + // Map method (IEEE 1800-2023 7.12.5) + q = '{1: 100, 2: 200, 3: 300}; + qv = q.map(el) with (el / 100); + `checkp(qv, "'{'h1, 'h2, 'h3}"); + qv = q.map(el) with (el.index * 10); + `checkp(qv, "'{'ha, 'h14, 'h1e}"); + $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_assoc_method_map.out b/test_regress/t/t_assoc_method_map.out deleted file mode 100644 index 62dd71bbc..000000000 --- a/test_regress/t/t_assoc_method_map.out +++ /dev/null @@ -1,6 +0,0 @@ -%Error-UNSUPPORTED: t/t_assoc_method_map.v:19:13: Unsupported: Associative array 'map' method (IEEE 1800-2023 7.12.5) - : ... note: In instance 't' - 19 | res = a.map(el) with (el == 2); - | ^~~ - ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error: Exiting due to diff --git a/test_regress/t/t_assoc_method_map.py b/test_regress/t/t_assoc_method_map.py deleted file mode 100755 index 3160d0589..000000000 --- a/test_regress/t/t_assoc_method_map.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# DESCRIPTION: Verilator: Verilog Test driver/expect definition -# -# 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-FileCopyrightText: 2024 Wilson Snyder -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -import vltest_bootstrap - -test.scenarios('vlt') - -test.lint(fails=True, expect_filename=test.golden_filename) - -test.passes() diff --git a/test_regress/t/t_assoc_method_map.v b/test_regress/t/t_assoc_method_map.v deleted file mode 100644 index 829b0baaf..000000000 --- a/test_regress/t/t_assoc_method_map.v +++ /dev/null @@ -1,25 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed under the Creative Commons Public Domain. -// SPDX-FileCopyrightText: 2024 Wilson Snyder -// SPDX-License-Identifier: CC0-1.0 - -// verilog_format: off -`define stop $stop -`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); -// verilog_format: on - -module t; - - initial begin - automatic int res[]; - automatic int a[int] = '{1: 100, 2: 200, 3: 300}; - - // TODO results not known to be correct - res = a.map(el) with (el == 2); - `checkh(res.size, 3); - `checkh(res[0], 0); - `checkh(res[1], 1); - `checkh(res[2], 0); - end -endmodule diff --git a/test_regress/t/t_assoc_wildcard_map.out b/test_regress/t/t_assoc_wildcard_map.out deleted file mode 100644 index fadf53e84..000000000 --- a/test_regress/t/t_assoc_wildcard_map.out +++ /dev/null @@ -1,6 +0,0 @@ -%Error-UNSUPPORTED: t/t_assoc_wildcard_map.v:19:13: Unsupported: Wildcard array 'map' method (IEEE 1800-2023 7.12.5) - : ... note: In instance 't' - 19 | res = a.map(el) with (el == 2); - | ^~~ - ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error: Exiting due to diff --git a/test_regress/t/t_assoc_wildcard_map.py b/test_regress/t/t_assoc_wildcard_map.py deleted file mode 100755 index 3160d0589..000000000 --- a/test_regress/t/t_assoc_wildcard_map.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# DESCRIPTION: Verilator: Verilog Test driver/expect definition -# -# 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-FileCopyrightText: 2024 Wilson Snyder -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -import vltest_bootstrap - -test.scenarios('vlt') - -test.lint(fails=True, expect_filename=test.golden_filename) - -test.passes() diff --git a/test_regress/t/t_assoc_wildcard_map.v b/test_regress/t/t_assoc_wildcard_map.v deleted file mode 100644 index 482e8a890..000000000 --- a/test_regress/t/t_assoc_wildcard_map.v +++ /dev/null @@ -1,25 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed under the Creative Commons Public Domain. -// SPDX-FileCopyrightText: 2023 Wilson Snyder -// SPDX-License-Identifier: CC0-1.0 - -// verilog_format: off -`define stop $stop -`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); -// verilog_format: on - -module t; - - initial begin - automatic int res[]; - automatic int a [*] = '{1: 100, 2: 200, 3: 300}; - - // TODO results not known to be correct - res = a.map(el) with (el == 2); - `checkh(res.size, 3); - `checkh(res[0], 0); - `checkh(res[1], 1); - `checkh(res[2], 0); - end -endmodule diff --git a/test_regress/t/t_assoc_wildcard_method.v b/test_regress/t/t_assoc_wildcard_method.v index 5c1e8ca6f..38c0f6248 100644 --- a/test_regress/t/t_assoc_wildcard_method.v +++ b/test_regress/t/t_assoc_wildcard_method.v @@ -150,6 +150,11 @@ module t; b = points_q.sum with (vec_len_squared(item) inside {5, 17, 20}); `checkh(b, 1'b1); + // Map method (IEEE 1800-2023 7.12.5) + q = '{"a": 100, "b": 200, "c": 300}; + qv = q.map(el) with (el / 100); + `checkp(qv, "'{'h1, 'h2, 'h3}"); + $write("*-* All Finished *-*\n"); $finish; end