Fix splitting coroutines (#4297) (#4307)

This commit is contained in:
Jiamin Zhu 2023-06-23 18:01:38 +08:00 committed by GitHub
parent 4522834f7a
commit 1c88c3083c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 116 additions and 14 deletions

View File

@ -125,8 +125,43 @@ void splitCheck(AstCFunc* ofuncp) {
int funcnum = 0;
int func_stmts = 0;
const bool is_ofuncp_coroutine = ofuncp->isCoroutine();
AstCFunc* funcp = nullptr;
const auto createNewSubFuncp = [&]() {
AstCFunc* const subFuncp = new AstCFunc{
ofuncp->fileline(), ofuncp->name() + "__" + cvtToStr(funcnum++), ofuncp->scopep()};
subFuncp->dontCombine(true);
subFuncp->isStatic(false);
subFuncp->isLoose(true);
subFuncp->slow(ofuncp->slow());
subFuncp->declPrivate(ofuncp->declPrivate());
func_stmts = 0;
return subFuncp;
};
const auto finishSubFuncp = [&](AstCFunc* subFuncp) {
ofuncp->scopep()->addBlocksp(subFuncp);
AstCCall* const callp = new AstCCall{subFuncp->fileline(), subFuncp};
callp->dtypeSetVoid();
if (is_ofuncp_coroutine && subFuncp->exists([](const AstCAwait*) {
return true;
})) { // Wrap call with co_await
subFuncp->rtnType("VlCoroutine");
AstCAwait* const awaitp = new AstCAwait{subFuncp->fileline(), callp};
awaitp->dtypeSetVoid();
ofuncp->addStmtsp(awaitp->makeStmt());
} else {
ofuncp->addStmtsp(callp->makeStmt());
}
};
funcp = createNewSubFuncp();
// Unlink all statements, then add item by item to new sub-functions
AstBegin* const tempp = new AstBegin{ofuncp->fileline(), "[EditWrapper]",
ofuncp->stmtsp()->unlinkFrBackWithNext()};
@ -135,24 +170,16 @@ void splitCheck(AstCFunc* ofuncp) {
while (tempp->stmtsp()) {
AstNode* const itemp = tempp->stmtsp()->unlinkFrBack();
const int stmts = itemp->nodeCount();
if (!funcp || (func_stmts + stmts) > v3Global.opt.outputSplitCFuncs()) {
// Make a new function
funcp = new AstCFunc{ofuncp->fileline(), ofuncp->name() + "__" + cvtToStr(funcnum++),
ofuncp->scopep()};
funcp->dontCombine(true);
funcp->isStatic(false);
funcp->isLoose(true);
funcp->slow(ofuncp->slow());
ofuncp->scopep()->addBlocksp(funcp);
//
AstCCall* const callp = new AstCCall{funcp->fileline(), funcp};
callp->dtypeSetVoid();
ofuncp->addStmtsp(callp->makeStmt());
func_stmts = 0;
if ((func_stmts + stmts) > v3Global.opt.outputSplitCFuncs()) {
finishSubFuncp(funcp);
funcp = createNewSubFuncp();
}
funcp->addStmtsp(itemp);
func_stmts += stmts;
}
finishSubFuncp(funcp);
VL_DO_DANGLING(tempp->deleteTree(), tempp);
}
@ -256,6 +283,7 @@ void orderSequentially(AstCFunc* funcp, const LogicByScope& lbs) {
}
}
subFuncp->addStmtsp(bodyp);
splitCheck(subFuncp);
}
} else {
logicp->unlinkFrBack();

View File

@ -0,0 +1,39 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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
scenarios(vlt_all => 1);
compile(
timing_loop => 1,
verilator_flags2 => ["--timing --output-split-cfuncs 1 -CFLAGS -Werror"],
);
execute(
check_finished => 1,
);
check_splits();
ok(1);
1;
sub check_splits {
my $got1;
my $gotSyms1;
foreach my $file (glob("$Self->{obj_dir}/*.cpp")) {
if ($file =~ /Syms__1/) {
$gotSyms1 = 1;
} elsif ($file =~ /__1/) {
$got1 = 1;
}
}
$got1 or error("No __1 split file found");
$gotSyms1 or error("No Syms__1 split file found");
}

View File

@ -0,0 +1,35 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Jomit626.
// SPDX-License-Identifier: CC0-1.0
module t ();
logic clk = 0;
logic data = 0;
always #5 clk <= ~clk;
task static foo();
@(negedge clk);
data = 1;
@(negedge clk);
data = 0;
endtask
`define foo8()\
foo();foo();foo();foo();foo();foo();foo();foo()
`define foo64()\
`foo8();`foo8();`foo8();`foo8();`foo8();`foo8();`foo8();`foo8()
`define foo512()\
`foo64();`foo64();`foo64();`foo64();`foo64();`foo64();`foo64();`foo64()
initial begin
`foo512();
`foo512();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule