Fix waking --sc wrapper when DPI/delay makes work runnable (#8394) (#8534)

Fixes #8394
This commit is contained in:
Nazar Zibilyuk
2026-10-01 12:01:17 +01:00
committed by GitHub
parent 71c6638ccf
commit ea536a54b8
10 changed files with 188 additions and 1 deletions
+1
View File
@@ -249,6 +249,7 @@ Natan Kreimer
Nathan Graybeal
Nathan Kohagen
Nathan Myers
Nazar Zibilyuk
Nick Brereton
Nikolai Kumar
Nikolay Puzanov
+5 -1
View File
@@ -352,6 +352,10 @@ class EmitCModel final : public EmitCFunc {
// Create sensitivity list for when to evaluate the model.
putsDecoration(nullptr, "// Sensitivities on all clocks and combinational inputs\n");
puts("SC_METHOD(eval);\n");
if (v3Global.usesTiming()) {
putsDecoration(nullptr, "// Notified by pending time delays/DPI exports\n");
puts("sensitive << vlSymsp->__Vm_wakeEvent;\n");
}
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (const AstVar* const varp = VN_CAST(nodep, Var)) {
if (varp->isNonOutput() && (varp->isScSensitive() || varp->isPrimaryClock())) {
@@ -430,7 +434,7 @@ class EmitCModel final : public EmitCFunc {
puts("if (eventsPending()) {\n");
puts("sc_core::sc_time dt = sc_core::sc_time::from_value(nextTimeSlot() - "
"contextp()->time());\n");
puts("next_trigger(dt);\n");
puts("vlSymsp->__Vm_wakeEvent.notify(dt);\n");
puts("}\n");
puts("}\n");
}
+1
View File
@@ -999,6 +999,7 @@ void EmitCSyms::emitSymHdr() {
}
if (v3Global.hasClasses()) puts("VlDeleter __Vm_deleter;\n");
puts("bool& __Vm_didInit;\n");
if (v3Global.opt.systemC()) puts("sc_core::sc_event __Vm_wakeEvent;\n");
if (v3Global.opt.mtasks()) {
puts("\n// MULTI-THREADING\n");
+7
View File
@@ -1534,6 +1534,13 @@ class TaskVisitor final : public VNVisitor {
} else {
cfuncp->addStmtsp(assignp);
}
// With --sc, also wake the SystemC wrapper: it cannot see the flag, and may
// otherwise sleep until its next timed slot. (usesTiming() is not known yet.)
if (v3Global.opt.systemC()) {
assignp->addNextHere(new AstCStmt{
flp, "vlSymsp->__Vm_wakeEvent.notify(sc_core::SC_ZERO_TIME);\n"});
}
}
}
@@ -0,0 +1,24 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 ViraSemi Inc.
// SPDX-License-Identifier: CC0-1.0
#include VM_PREFIX_INCLUDE
using namespace sc_core;
// A 10ns clock drives the model while it waits on a long delay
int sc_main(int argc, char* argv[]) {
sc_clock clk{"clk", 10, SC_NS};
VM_PREFIX* tb = new VM_PREFIX{"tb"};
tb->clk(clk);
while (!Verilated::gotFinish() && sc_time_stamp() < sc_time(2, SC_US)) sc_start(1, SC_NS);
if (!Verilated::gotFinish())
vl_fatal(__FILE__, __LINE__, "tb", "Timeout; never got a $finish\n");
tb->final();
VL_DO_DANGLING(delete tb, tb);
return 0;
}
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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('vlt')
if not test.have_sc:
test.skip("No SystemC installed")
if re.search(r'clang', test.cxx_version):
test.skip("Known clang bug on ubuntu-26.04")
test.compile(make_main=False, verilator_flags2=["-sc --exe --timing", test.pli_filename])
test.execute()
test.passes()
@@ -0,0 +1,28 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 ViraSemi Inc.
// SPDX-License-Identifier: CC0-1.0
module t (
input clk
);
int edges = 0;
always @(posedge clk) edges <= edges + 1;
initial begin
// Every clock edge must be seen while this delay is pending
#995ns;
if (edges != 100) begin
$write("%%Error: %0d clock edges seen while a delay was pending, expected 100\n", edges);
$stop;
end
// No delay is pending from here on; the clock alone must keep the model running
wait (edges == 150);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+37
View File
@@ -0,0 +1,37 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 ViraSemi Inc.
// SPDX-License-Identifier: CC0-1.0
#include VM_PREFIX_INCLUDE
#include "svdpi.h"
using namespace sc_core;
// Exported by the model
extern "C" void sv_trigger();
// Calls into the model at 10ns, from outside its own evaluation
SC_MODULE(poker) {
SC_CTOR(poker) { SC_THREAD(run); }
void run() {
wait(10, SC_NS);
svScope scope = svGetScopeFromName("tb.t");
if (!scope) vl_fatal(__FILE__, __LINE__, "tb", "svGetScopeFromName failed\n");
svSetScope(scope);
sv_trigger();
}
};
int sc_main(int argc, char* argv[]) {
VM_PREFIX* tb = new VM_PREFIX{"tb"};
poker p{"poker"};
sc_start();
tb->final();
VL_DO_DANGLING(delete tb, tb);
return 0;
}
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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('vlt')
if not test.have_sc:
test.skip("No SystemC installed")
if re.search(r'clang', test.cxx_version):
test.skip("Known clang bug on ubuntu-26.04")
test.compile(make_main=False, verilator_flags2=["-sc --exe --timing", test.pli_filename])
test.execute()
test.passes()
+37
View File
@@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 ViraSemi Inc.
// SPDX-License-Identifier: CC0-1.0
`timescale 1ns/1ps
module t;
event hit;
time woke_at = 0;
export "DPI-C" function sv_trigger;
// Called from SystemC at 10ns. Triggers an event a process is already waiting on.
function automatic void sv_trigger();
->hit;
endfunction
initial begin
@(hit);
woke_at = $time;
end
initial begin
#50;
if (woke_at != 10) begin
$write("%%Error: the waiting process was released at %0t, expected 10ns\n", woke_at);
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule