From b49351356e17abc392710d2a60cbff60d1dbad83 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 30 Mar 2025 16:40:22 -0400 Subject: [PATCH] Fix delays inside interface functions, and classes inside interfaces (#5846). --- Changes | 1 + src/V3Fork.cpp | 2 ++ src/V3TraceDecl.cpp | 8 +++++-- test_regress/t/t_fork_dynscope_interface.py | 18 ++++++++++++++ test_regress/t/t_fork_dynscope_interface.v | 26 +++++++++++++++++++++ 5 files changed, 53 insertions(+), 2 deletions(-) create mode 100755 test_regress/t/t_fork_dynscope_interface.py create mode 100644 test_regress/t/t_fork_dynscope_interface.v diff --git a/Changes b/Changes index ffdd266d3..a28d9285d 100644 --- a/Changes +++ b/Changes @@ -46,6 +46,7 @@ Verilator 5.035 devel * Fix assignment pattern as function argument (#5839). * Fix checking built-in method arguments (#5839). * Fix splitting of packed ports with non-zero based ranges (#5842). [Geza Lore] +* Fix delays inside interface functions, and classes inside interfaces (#5846). * Fix NBA shared flag reuse (#5848). [Geza Lore] * Fix multiple expression coverage issues (#5849 partial) (#5867) (#5870). [Todd Strader] * Fix unresolved typedefs as parameters (#5850). [Eugene Feinberg, Brian Li] diff --git a/src/V3Fork.cpp b/src/V3Fork.cpp index 81594d856..60b14a268 100644 --- a/src/V3Fork.cpp +++ b/src/V3Fork.cpp @@ -24,10 +24,12 @@ // FORKs that spawn tasks which might outlive their parents require those // tasks to carry their own frames and as such they require their own // variable scopes. +// // There are two mechanisms that work together to achieve that. ForkVisitor // moves bodies of forked processes into new tasks, which results in them getting their // own scopes. The original statements get replaced with a call to the task which // passes the required variables by value. +// // The second mechanism, DynScopeVisitor, is designed to handle variables which can't be // captured by value and instead require a reference. Those variables get moved into an // "anonymous" object, ie. a class with appropriate fields gets generated and an object diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index a4a83c3d5..ff7d92f4b 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -434,10 +434,14 @@ class TraceDeclVisitor final : public VNVisitor { // Save the hierarchical names of interface references that reference this scope const AstCell* const cellp = nodep->aboveCellp(); - if (cellp && VN_IS(cellp->modp(), Iface)) { + if (cellp + && VN_IS(cellp->modp(), Iface) + // Exclude classes that were inside interfaces, the cell's modp is an interface, + // but the nodep->module is the Class + && VN_IS(nodep->modp(), Iface)) { const size_t lastDot = path.find_last_of('.'); UASSERT_OBJ(lastDot != string::npos, nodep, - "Expected an interface scope name to have at least one dot"); + "Expected an interface scope name to have at least one dot: " << path); const std::string parentPath = path.substr(0, lastDot + 1); for (AstIntfRef *intfRefp = cellp->intfRefsp(), *nextp; intfRefp; intfRefp = nextp) { diff --git a/test_regress/t/t_fork_dynscope_interface.py b/test_regress/t/t_fork_dynscope_interface.py new file mode 100755 index 000000000..c1c09c48b --- /dev/null +++ b/test_regress/t/t_fork_dynscope_interface.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 --trace-fst']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_fork_dynscope_interface.v b/test_regress/t/t_fork_dynscope_interface.v new file mode 100644 index 000000000..593a3eb6b --- /dev/null +++ b/test_regress/t/t_fork_dynscope_interface.v @@ -0,0 +1,26 @@ +// 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 + +module t; + Iface ifc(); + + initial begin + #1; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + +interface Iface; + int tck; + int tdo; + + task tsk(input int data_i, output int data_o); + @(posedge tck); + data_o <= tdo; + endtask + +endinterface