forked from verilator/verilator
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add prepareClone and atClone APIs for Verilated models (verilator#3503)…
… (verilator#4444) This API is used if the user copies the process using `fork` and similar OS-level mechanisms. The `at_clone` member function ensures that all model-allocated resources are re-allocated, such that the copied child process/model can simulate correctly. A typical allocated resource is the thread pool, which every model has its own pool.
- Loading branch information
1 parent
ca6ab58
commit b4b74d7
Showing
10 changed files
with
232 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// | ||
// DESCRIPTION: Verilator: Verilog Test module for prepareClone/atClone APIs | ||
// | ||
// This file ONLY is placed into the Public Domain, for any use, | ||
// without warranty, 2023 by Yinan Xu. | ||
// SPDX-License-Identifier: CC0-1.0 | ||
|
||
#include <verilated.h> | ||
|
||
#include <unistd.h> | ||
|
||
#include <sys/wait.h> | ||
|
||
// These require the above. Comment prevents clang-format moving them | ||
#include "TestCheck.h" | ||
|
||
#include VM_PREFIX_INCLUDE | ||
|
||
double sc_time_stamp() { return 0; } | ||
|
||
// Note: Since the pthread_atfork API accepts only function pointers, | ||
// we are using a static variable for the TOP just for a simple example. | ||
// Without using the pthread_atfork API, the user can instead manually call | ||
// prepareClone and atClone before and after calling fork, and topp can be | ||
// allocated dynamically. | ||
static VM_PREFIX* topp = nullptr; | ||
static auto prepareClone = []() { topp->prepareClone(); }; | ||
static auto atClone = []() { topp->atClone(); }; | ||
|
||
void single_cycle(VM_PREFIX* topp) { | ||
topp->clock = 1; | ||
topp->eval(); | ||
|
||
topp->clock = 0; | ||
topp->eval(); | ||
} | ||
|
||
int main(int argc, char** argv) { | ||
// We disable the buffering for stdout in this test. | ||
// Redirecting the stdout to files with buffering causes duplicated stdout | ||
// outputs in both parent and child processes, even if they are actually | ||
// called before the fork. | ||
setvbuf(stdout, nullptr, _IONBF, 0); | ||
|
||
VerilatedContext* contextp = new VerilatedContext; | ||
topp = new VM_PREFIX{contextp}; | ||
|
||
// To avoid resource leaks, prepareClone must be called before fork to | ||
// free all the allocated resources. Though this would bring performance | ||
// overhead to the parent process, we believe that fork should not be | ||
// called frequently, and the overhead is minor compared to simulation. | ||
pthread_atfork(prepareClone, atClone, atClone); | ||
|
||
// If you care about critical performance, prepareClone can be avoided, | ||
// with atClone being called only at the child process, as follows. | ||
// It has the same functionality as the previous one, but has memory leaks. | ||
// According to the sanitizer, 288 bytes are leaked for one fork call. | ||
// pthread_atfork(nullptr, nullptr, atClone); | ||
|
||
topp->reset = 1; | ||
topp->is_parent = 0; | ||
for (int i = 0; i < 5; i++) { single_cycle(topp); } | ||
|
||
topp->reset = 0; | ||
while (!contextp->gotFinish()) { | ||
single_cycle(topp); | ||
|
||
if (topp->do_clone) { | ||
const int pid = fork(); | ||
if (pid < 0) { | ||
printf("fork failed\n"); | ||
} else if (pid == 0) { | ||
printf("child: here we go\n"); | ||
} else { | ||
while (wait(nullptr) > 0) | ||
; | ||
printf("parent: here we go\n"); | ||
topp->is_parent = 1; | ||
} | ||
} | ||
} | ||
|
||
topp->final(); | ||
|
||
VL_DO_DANGLING(delete topp, topp); | ||
VL_DO_DANGLING(delete contextp, contextp); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
counter = 0 | ||
counter = 1 | ||
counter = 2 | ||
counter = 3 | ||
counter = 4 | ||
counter = 5 | ||
child: here we go | ||
counter = 6 | ||
counter = 7 | ||
counter = 8 | ||
parent: here we go | ||
counter = 6 | ||
counter = 7 | ||
counter = 8 | ||
*-* All Finished *-* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#!/usr/bin/env perl | ||
if (!$::Driver) { use strict; use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } | ||
# DESCRIPTION: Verilator: Verilog Test module for prepareClone/atClone APIs | ||
# | ||
# This file ONLY is placed into the Public Domain, for any use, | ||
# without warranty, 2023 by Yinan Xu. | ||
# SPDX-License-Identifier: CC0-1.0 | ||
|
||
scenarios(vlt_all => 1); | ||
|
||
compile( | ||
make_top_shell => 0, | ||
make_main => 0, | ||
verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp", | ||
"-cc"], | ||
threads => $Self->{vltmt} ? 2 : 1, | ||
); | ||
|
||
execute( | ||
check_finished => 1, | ||
expect_filename => $Self->{golden_filename}, | ||
); | ||
|
||
ok(1); | ||
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// DESCRIPTION: Verilator: Verilog Test module for prepareClone/atClone APIs | ||
// | ||
// This model counts from 0 to 8. It forks a child process (in C++) at 6 | ||
// and waits for the child to simulate and exit for resumption (of the parent). | ||
// | ||
// This file ONLY is placed into the Public Domain, for any use, | ||
// without warranty, 2023 by Yinan Xu. | ||
// SPDX-License-Identifier: CC0-1.0 | ||
|
||
module top( | ||
input clock, | ||
input reset, | ||
input is_parent, | ||
output do_clone | ||
); | ||
|
||
reg [3:0] counter; | ||
|
||
assign do_clone = counter == 4'h6; | ||
|
||
always @(posedge clock) begin | ||
if (reset) begin | ||
counter <= 4'h0; | ||
end | ||
else begin | ||
counter <= counter + 4'h1; | ||
$write("counter = %d\n", counter); | ||
end | ||
|
||
if (counter[3]) begin | ||
if (is_parent) begin | ||
$write("*-* All Finished *-*\n"); | ||
end | ||
$finish(0); | ||
end | ||
end | ||
|
||
endmodule |