Fix splitting functions containing fork logic (#7717)

This commit is contained in:
Mateusz Gancarz 2026-06-05 15:32:52 +02:00 committed by GitHub
parent 99f62fca62
commit 7e2fe64ae2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 8 deletions

View File

@ -711,14 +711,12 @@ class TimingControlVisitor final : public VNVisitor {
m_netlistp->typeTablep()->addTypesp(m_forkDtp);
return m_forkDtp;
}
// Move `insertBeforep` into `AstCLocalScope` if necessary to avoid jumping over
// a variable initialization that whould be inserted before `insertBeforep`. All
// access to this variable should be contained within returned `AstCLocalScope`.
AstCLocalScope* addCLocalScope(FileLine* const flp, AstNode* const insertBeforep) const {
if (!insertBeforep || !m_underJumpBlock) return nullptr;
// Move `nodep` into `AstCLocalScope`.
AstCLocalScope* addCLocalScope(FileLine* const flp, AstNode* const nodep) const {
if (!nodep) return nullptr;
VNRelinker handle;
insertBeforep->unlinkFrBack(&handle);
AstCLocalScope* const cscopep = new AstCLocalScope{flp, insertBeforep};
nodep->unlinkFrBack(&handle);
AstCLocalScope* const cscopep = new AstCLocalScope{flp, nodep};
handle.relink(cscopep);
return cscopep;
}
@ -781,6 +779,8 @@ class TimingControlVisitor final : public VNVisitor {
FileLine* const flp = forkp->fileline();
// Insert the sync var directly before the fork
AstNode* const insertBeforep = forkp;
// Make sure all references to the fork var are contained within a single scope to prevent
// moving statements accessing it in case of large functions splitting.
addCLocalScope(flp, insertBeforep);
AstVarScope* forkVscp
= createTemp(flp, forkp->name() + "__sync", getCreateForkSyncDTypep(), insertBeforep);
@ -1206,7 +1206,10 @@ class TimingControlVisitor final : public VNVisitor {
controlp = forkp;
}
UASSERT_OBJ(nodep, controlp, "Assignment should have timing control");
addCLocalScope(flp, insertBeforep);
// Move `insertBeforep` into `AstCLocalScope` if necessary to avoid jumping over
// a variable initialization that would be inserted before `insertBeforep`. All
// access to this variable should be contained within returned `AstCLocalScope`.
if (m_underJumpBlock) addCLocalScope(flp, insertBeforep);
// Function for replacing values with intermediate variables
const auto replaceWithIntermediate = [&](AstNodeExpr* const valuep,
const std::string& name) {

19
test_regress/t/t_fork_split.py Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Test for splitting fork C logic.
#
# 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.top_filename = "t/t_fork.v"
test.compile(verilator_flags2=["--timing", "--output-split-cfuncs 10"])
test.execute()
test.passes()