diff --git a/src/V3Sched.cpp b/src/V3Sched.cpp index 78f09d44b..a725d3e82 100644 --- a/src/V3Sched.cpp +++ b/src/V3Sched.cpp @@ -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(); diff --git a/test_regress/t/t_timing_split.pl b/test_regress/t/t_timing_split.pl new file mode 100755 index 000000000..ef1465996 --- /dev/null +++ b/test_regress/t/t_timing_split.pl @@ -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"); +} diff --git a/test_regress/t/t_timing_split.v b/test_regress/t/t_timing_split.v new file mode 100644 index 000000000..f7fd5d8de --- /dev/null +++ b/test_regress/t/t_timing_split.v @@ -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