diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index ad6d72d3e..0988eba8f 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -249,10 +249,6 @@ class LinkResolveVisitor final : public VNVisitor { letp->user2(false); return; } - if (nodep->taskp() && !nodep->scopeNamep() - && (nodep->taskp()->dpiContext() || nodep->taskp()->dpiExport())) { - nodep->scopeNamep(new AstScopeName{nodep->fileline(), false}); - } } void visit(AstCaseItem* nodep) override { diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 0c53467f4..58fc1baf2 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -711,8 +711,9 @@ class TaskVisitor final : public VNVisitor { if (needSyms) ccallp->argTypes("vlSymsp"); if (refp->taskp()->dpiContext()) { - AstScopeName* const snp = refp->scopeNamep()->unlinkFrBack(); + AstScopeName* const snp = refp->scopeNamep(); UASSERT_OBJ(snp, refp, "Missing scoping context"); + snp->unlinkFrBack(); FileLine* const flp = refp->fileline(); // __Vscopep ccallp->addArgsp(snp); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index b18c13f56..c6c3416c7 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6792,6 +6792,10 @@ class WidthVisitor final : public VNVisitor { nodep->v3error("Cannot call non-static member function " << nodep->prettyNameQ() << " without object (IEEE 1800-2023 8.10)"); } + if (nodep->taskp() && !nodep->scopeNamep() + && (nodep->taskp()->dpiContext() || nodep->taskp()->dpiExport())) { + nodep->scopeNamep(new AstScopeName{nodep->fileline(), false}); + } // And do the arguments to the task/function too processFTaskRefArgs(nodep); nodep->addPinsp(withp); diff --git a/test_regress/t/t_dpi_class_param.cpp b/test_regress/t/t_dpi_class_param.cpp new file mode 100644 index 000000000..f49b38d93 --- /dev/null +++ b/test_regress/t/t_dpi_class_param.cpp @@ -0,0 +1,15 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2024 by Antmicro. 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 +// +//************************************************************************* + +extern "C" int dpii_add() { + static int s_i; + return ++s_i; +} diff --git a/test_regress/t/t_dpi_class_param.py b/test_regress/t/t_dpi_class_param.py new file mode 100755 index 000000000..aae0ff397 --- /dev/null +++ b/test_regress/t/t_dpi_class_param.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=['--binary', test.pli_filename]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_dpi_class_param.v b/test_regress/t/t_dpi_class_param.v new file mode 100644 index 000000000..ab02fb58d --- /dev/null +++ b/test_regress/t/t_dpi_class_param.v @@ -0,0 +1,46 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +// verilog_format: off +`define stop $stop +`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0); +// verilog_format: on + +module t; + import "DPI-C" context function int dpii_add(); + + virtual class uvm_sequence #( + type RSP = int + ); + endclass + + class Cls extends uvm_sequence #(); + virtual function void check_reg(); + int paths[$]; + int i; + paths.push_back(1); + paths.push_back(2); + foreach (paths[p]) begin + i = dpii_add(); + end + endfunction + endclass + + initial begin + Cls c; + int i; + c = new; + i = dpii_add(); + `checkd(i, 1); + + c.check_reg(); + + i = dpii_add(); + `checkd(i, 4); + $finish; + end + +endmodule