Allow pure functions in sensitivity lists (#6393)

Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
This commit is contained in:
Krzysztof Bieganski 2025-09-10 17:37:34 +02:00 committed by GitHub
parent 1923d23cff
commit 5349b51e71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 57 additions and 29 deletions

View File

@ -746,7 +746,9 @@ const TriggerKit createTriggers(AstNetlist* netlistp, AstCFunc* const initFuncp,
ss << "@(";
V3EmitV::verilogForTree(senItemp, ss);
ss << ")";
addDebug(triggerNumber, VString::quoteBackslash(ss.str()));
std::string desc = VString::quoteBackslash(ss.str());
desc = VString::replaceSubstr(desc, "\n", "\\n");
addDebug(triggerNumber, desc);
//
++triggerNumber;

View File

@ -1458,8 +1458,9 @@ class TaskVisitor final : public VNVisitor {
UASSERT_OBJ(!m_insStmtp, nodep, "Didn't finish out last statement");
}
void visit(AstNodeFTaskRef* nodep) override {
if (m_inSensesp) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: function calls in sensitivity lists");
if (m_inSensesp && !nodep->isPure()) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: Impure function calls in sensitivity lists");
nodep->taskp(nullptr); // So V3Broken doesn't complain
return;
}

View File

@ -50,10 +50,8 @@ endmodule
`EXPR_TEST(queue, 0, (input int q[$]), q[0])
`EXPR_TEST(queue_mul, 0, (input int q[$], int i), q[0]*i)
`ifdef UNSUP
function int id(int x); return x; endfunction
`EXPR_TEST(func, 0, (input int cyc), id(cyc))
`endif
//========================================================================
// Class tests (special case as V3Width doesn't always properly handle
@ -78,27 +76,25 @@ endmodule
`CLASS_TEST(class, obj.k)
`ifdef UNSUP
`CLASS_TEST(method, obj.get_k())
`endif
`endif
//========================================================================
// $c test has to be written out explicitly as the STRINGIFY macro can't handle it
//
module t_cstmt;
logic last = 0;
always @($c("vlSelf->clk")) begin
if ($time > 0 && logic'($c("vlSelf->clk")) == last) $stop;
last <= logic'($c("vlSelf->clk"));
always @($c("vlSymsp->TOP.clk")) begin
if ($time > 0 && logic'($c("vlSymsp->TOP.clk")) == last) $stop;
last <= logic'($c("vlSymsp->TOP.clk"));
end
always @(posedge $c("vlSelf->clk")) begin
`WRITE_VERBOSE(("[%0t] cstmt [posedge] $c(\"vlSelf->clk\")=%0b, last=%b\n", $time, $c("vlSelf->clk"), last));
if ($time > 0 && (~logic'($c("vlSelf->clk")) || last)) $stop;
always @(posedge $c("vlSymsp->TOP.clk")) begin
`WRITE_VERBOSE(("[%0t] cstmt [posedge] $c(\"vlSymsp->TOP.clk\")=%0b, last=%b\n", $time, $c("vlSymsp->TOP.clk"), last));
if ($time > 0 && (~logic'($c("vlSymsp->TOP.clk")) || last)) $stop;
end
always @(negedge $c("vlSelf->clk")) begin
`WRITE_VERBOSE(("[%0t] cstmt [negedge] $c(\"vlSelf->clk\")=%0b, last=%b\n", $time, $c("vlSelf->clk"), last));
if ($time > 0 && (logic'($c("vlSelf->clk")) || !last)) $stop;
always @(negedge $c("vlSymsp->TOP.clk")) begin
`WRITE_VERBOSE(("[%0t] cstmt [negedge] $c(\"vlSymsp->TOP.clk\")=%0b, last=%b\n", $time, $c("vlSymsp->TOP.clk"), last));
if ($time > 0 && (logic'($c("vlSymsp->TOP.clk")) || !last)) $stop;
end
endmodule
@ -129,17 +125,13 @@ module t(/*AUTOARG*/
t_queue u_queue(.*);
t_queue_mul u_queue_mul(.*);
`ifdef UNSUP
t_func u_func(.*);
`endif
int k;
assign k = i + j;
`ifndef NO_CLASS
t_class u_class(.*);
`ifdef UNSUP
t_method u_method(.*);
`endif
`endif
t_cstmt u_cstmt();

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 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.top_filename = 't_event_control_expr.v'
test.compile(
# do not test classes for multithreaded, as V3InstrCount doesn't handle MemberSel
verilator_flags2=(['-fno-inline'] + ['-DNO_CLASS'] if test.vltmt else []))
test.execute()
test.passes()

View File

@ -1,9 +1,5 @@
%Error-UNSUPPORTED: t/t_event_control_expr.v:55:13: Unsupported: function calls in sensitivity lists
55 | always @(id(cyc)) begin
| ^~
%Error-UNSUPPORTED: t/t_event_control_expr_unsup.v:15:21: Unsupported: Impure function calls in sensitivity lists
15 | always @(posedge foo());
| ^~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_event_control_expr.v:82:17: Unsupported: function calls in sensitivity lists
: ... note: In instance 't.u_method'
82 | always @(obj.get_k()) begin
| ^~~~~
%Error: Exiting due to

View File

@ -10,8 +10,7 @@
import vltest_bootstrap
test.scenarios('vlt') # no vltmt, as AstMemberSel is unhandled in V3InstrCount
test.top_filename = "t_event_control_expr.v"
test.lint(verilator_flags2=['-DUNSUP'], fails=True, expect_filename=test.golden_filename)
test.lint(fails=True, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
module t;
int x;
function bit foo;
x += 1;
return bit'(x % 2);
endfunction
always @(posedge foo());
endmodule