Fix concurrency for mailbox and semaphores (#5222)

This commit is contained in:
Liam Braun 2024-07-03 23:29:32 +02:00 committed by GitHub
parent a6d438d111
commit ca4858eb7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 156 additions and 8 deletions

View File

@ -120,6 +120,7 @@ Krzysztof Boronski
Krzysztof Boroński
Kuba Ober
Larry Doolittle
Liam Braun
Ludwig Rogiers
Lukasz Dalek
Maarten De Braekeleer

View File

@ -40,7 +40,7 @@ package std;
task put(T message);
`ifdef VERILATOR_TIMING
if (m_bound != 0)
while (m_bound != 0 && m_queue.size() >= m_bound)
wait (m_queue.size() < m_bound);
m_queue.push_back(message);
`endif
@ -56,7 +56,9 @@ package std;
task get(ref T message);
`ifdef VERILATOR_TIMING
wait (m_queue.size() > 0);
while (m_queue.size() == 0) begin
wait (m_queue.size() > 0);
end
message = m_queue.pop_front();
`endif
endtask
@ -71,7 +73,9 @@ package std;
task peek(ref T message);
`ifdef VERILATOR_TIMING
wait (m_queue.size() > 0);
while (m_queue.size() == 0) begin
wait (m_queue.size() > 0);
end
message = m_queue[0];
`endif
endtask
@ -98,7 +102,9 @@ package std;
task get(int keyCount = 1);
`ifdef VERILATOR_TIMING
wait (m_keyCount >= keyCount);
while (m_keyCount < keyCount) begin
wait (m_keyCount >= keyCount);
end
m_keyCount -= keyCount;
`endif
endtask

View File

@ -525,10 +525,10 @@
{"type":"BASICDTYPE","name":"logic","addr":"(L)","loc":"c,33:32,33:33","dtypep":"(L)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(UE)","loc":"c,50:22,50:24","dtypep":"(UE)","keyword":"logic","generic":true,"rangep": []},
{"type":"VOIDDTYPE","name":"","addr":"(HI)","loc":"c,51:21,51:30","dtypep":"(HI)","generic":false},
{"type":"BASICDTYPE","name":"logic","addr":"(QD)","loc":"c,119:22,119:23","dtypep":"(QD)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(JI)","loc":"c,121:22,121:23","dtypep":"(JI)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(KI)","loc":"c,156:17,156:56","dtypep":"(KI)","keyword":"logic","range":"295:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"string","addr":"(BG)","loc":"c,156:10,156:16","dtypep":"(BG)","keyword":"string","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(QD)","loc":"c,125:22,125:23","dtypep":"(QD)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(JI)","loc":"c,127:22,127:23","dtypep":"(JI)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(KI)","loc":"c,162:17,162:56","dtypep":"(KI)","keyword":"logic","range":"295:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"string","addr":"(BG)","loc":"c,162:10,162:16","dtypep":"(BG)","keyword":"string","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(Q)","loc":"d,14:9,14:11","dtypep":"(Q)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(BB)","loc":"d,18:10,18:12","dtypep":"(BB)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(MC)","loc":"d,33:26,33:31","dtypep":"(MC)","keyword":"logic","range":"31:0","generic":true,"rangep": []},

View File

@ -0,0 +1,7 @@
mailbox read 0
mailbox read 1
mailbox read 2
mailbox write 3
mailbox write 4
mailbox write 5
*-* All Finished *-*

View File

@ -0,0 +1,23 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Liam Braun and 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(simulator => 1);
compile(
verilator_flags2 => ["--binary --timing"]
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,49 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Liam Braun.
// SPDX-License-Identifier: CC0-1.0
module t();
mailbox #(int) m;
task automatic test_get;
int v;
m.get(v);
// Only one thread should be here at a time (mailbox empty)
$display("mailbox read %0t", $time);
#1;
m.put(v);
endtask
task automatic test_put;
int v;
m.put(42);
// Only one thread should be here at a time (mailbox full)
$display("mailbox write %0t", $time);
#1;
m.get(v);
endtask
initial begin
m = new(1);
m.put(42);
fork
test_get();
test_get();
test_get();
join
m = new(1);
fork
test_put();
test_put();
test_put();
join
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,5 @@
0
1
2
3
*-* All Finished *-*

View File

@ -0,0 +1,23 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Liam Braun and 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(simulator => 1);
compile(
verilator_flags2 => ["--binary --timing"]
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,34 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Liam Braun.
// SPDX-License-Identifier: CC0-1.0
module t();
semaphore s;
// Stand-in for a task that should only be run by one thread at a time
task automatic exclusive_task;
$display("%0t", $time);
#1;
endtask
task automatic call_exclusive_task;
s.get(1);
exclusive_task();
s.put(1);
endtask
initial begin
s = new(1);
fork
call_exclusive_task();
call_exclusive_task();
call_exclusive_task();
call_exclusive_task();
join
$write("*-* All Finished *-*\n");
$finish;
end
endmodule