Fix lambda coroutines (#6106) (#7135)

This commit is contained in:
Nick Brereton 2026-02-28 09:52:02 -05:00 committed by GitHub
parent 1716423d07
commit 02c1dbc5dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 123 additions and 3 deletions

View File

@ -1199,7 +1199,7 @@ public:
if (VN_IS(nodep->exprp()->dtypep()->skipRefp(), VoidDType)) {
putns(nodep, "");
} else {
putns(nodep, "(void)"); // Prevent unused expression warning in C
putns(nodep, "std::ignore = ");
}
iterateConst(nodep->exprp());
puts(";\n");
@ -1293,6 +1293,22 @@ public:
}
void visit(AstExprStmt* nodep) override {
VL_RESTORER(m_createdScopeHash);
const bool containsAwait = nodep->exists([](AstCAwait*) -> bool { return true; });
if (containsAwait) {
UASSERT_OBJ(m_cfuncp && m_cfuncp->isCoroutine(), nodep,
"AstExprStmt with CAwait must be in coroutine");
putnbs(nodep, "(co_await ([&]() -> VlCoroutine {\n");
iterateAndNextConstNull(nodep->stmtsp());
puts("co_return;\n");
if (!nodep->hasResult()) {
puts("}()))");
return;
}
puts("}()), ");
iterateAndNextConstNull(nodep->resultp());
puts(")");
return;
}
// GCC allows compound statements in expressions, but this is not standard.
// So we use an immediate-evaluation lambda and comma operator
putnbs(nodep, "([&]() {\n");

View File

@ -4504,7 +4504,7 @@ class WidthVisitor final : public VNVisitor {
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::RNG_SET_RANDSTATE, exprp->unlinkFrBack()};
newp->usePtr(true);
newp->dtypeSetString();
newp->dtypeSetVoid();
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
@ -6994,7 +6994,7 @@ class WidthVisitor final : public VNVisitor {
= new AstCExpr{nodep->fileline(), "__Vm_rng.set_randstate(", 1};
newp->add(exprp->unlinkFrBack());
newp->add(")");
newp->dtypeSetString();
newp->dtypeSetVoid();
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Coroutine call inside AstExprStmt lambda
#
# 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: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=[
"--binary",
"--timing",
"-Wno-FUNCTIMECTL",
"-Wno-WIDTHTRUNC",
])
test.passes()

View File

@ -0,0 +1,83 @@
// DESCRIPTION: Verilator: Coroutine call inside AstExprStmt lambda test module
//
// 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: 2026 Wilson Snyder
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
interface cpu_if(input logic clk);
endinterface
package p;
virtual class WriterIf;
virtual function void write(input int t);
endfunction
endclass
class BlockingWriter;
virtual cpu_if vif;
task write(int t);
@(posedge vif.clk);
endtask
endclass
class WriterAdapter extends WriterIf;
BlockingWriter m_impl;
function new(BlockingWriter impl);
m_impl = impl;
endfunction
function void write(input int t);
m_impl.write(t); // function -> task path
endfunction
endclass
class QueueLike;
WriterIf sink;
mailbox #(int) m;
function bit try_get(output int t);
if (!m.try_get(t)) begin
end
sink.write(t); // can become coroutine call
endfunction
endclass
class DriverLike;
QueueLike reqq;
function void item_done();
int t;
if (reqq.try_get(t) == 0) begin
end
endfunction
endclass
endpackage
module t;
import p::*;
logic clk = 0;
cpu_if vif(clk);
always #1 clk = ~clk;
initial begin
BlockingWriter writer;
WriterAdapter adapter;
QueueLike reqq;
DriverLike drv;
writer = new();
writer.vif = vif;
adapter = new(writer);
reqq = new();
reqq.sink = adapter;
drv = new();
drv.reqq = reqq;
drv.item_done();
#2 $finish;
end
endmodule