Merge pull request #900 from larsclausen/task-return

Support return in tasks
This commit is contained in:
Cary R 2023-06-04 21:07:30 -07:00 committed by GitHub
commit f22c1a519b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 147 additions and 8 deletions

View File

@ -2977,6 +2977,9 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
return tmp;
}
if (type != NetBlock::SEQU)
des->fork_enter();
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) {
assert(list_[idx]);
@ -3018,6 +3021,9 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
cur->append(tmp);
}
if (type != NetBlock::SEQU)
des->fork_exit();
// Update flags in parent scope.
if (!nscope->is_const_func())
scope->is_const_func(false);
@ -5763,23 +5769,27 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
{
NetScope*target = scope;
if (des->is_in_fork()) {
cerr << get_fileline() << ": error: "
<< "Return statement is not allowed within fork-join block." << endl;
des->errors += 1;
return 0;
}
for (;;) {
if (target == 0) {
cerr << get_fileline() << ": error: "
<< "Return statement is not in a function." << endl;
<< "Return statement is not in a function or task."
<< endl;
des->errors += 1;
return 0;
}
if (target->type() == NetScope::FUNC)
break;
if (target->type() == NetScope::TASK) {
cerr << get_fileline() << ": error: "
<< "Cannot \"return\" from tasks." << endl;
des->errors += 1;
return 0;
}
if (target->type() == NetScope::TASK)
break;
if (target->type()==NetScope::BEGIN_END) {
target = target->parent();
@ -5791,6 +5801,19 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
des->errors += 1;
return 0;
}
if (target->type() == NetScope::TASK) {
if (expr_) {
cerr << get_fileline() << ": error: "
<< "A value cannot be returned from a task." << endl;
des->errors += 1;
return 0;
}
NetDisable *disa = new NetDisable(target, true);
disa->set_line(*this);
return disa;
}
ivl_assert(*this, target->type() == NetScope::FUNC);
if (target->func_def()->is_void()) {

View File

@ -0,0 +1,31 @@
// Check that it is possible to exit from a task using the return statement with
// affecting other concurrently running instances of the same task.
module test;
task automatic t(input integer a, output integer b);
if (a == 0) begin
b = 1;
return;
end
#10
b = 100;
endtask
integer b1;
integer b2;
initial begin
fork
t(0, b1);
t(1, b2);
join
if (b1 == 1 && b2 == 100) begin
$display("PASSED");
end else begin
$display("FAILED b1=%0d, b2=%0d", b1, b2);
end
end
endmodule

View File

@ -0,0 +1,22 @@
// Check that it is possible to return from a named sub-block of a task using a
// `return` statement.
module test;
task t(input integer a);
begin : subblock
if (a == 1) begin : condition
return;
end
end
$display("FAILED");
$finish;
endtask
initial begin
t(1);
#10
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,15 @@
// Check that using a return value when using the return statement in a task
// results in an error.
module test;
task t;
return 10; // This is an error, tasks can not have return values.
endtask
initial begin
t();
$display("FAILED");
end
endmodule

View File

@ -0,0 +1,18 @@
// Check that using a return statment inside a parallel block in a task results
// in an error.
module test;
task t;
fork
// This is an error it is not possible to return from inside a parallel block
return;
join
endtask
initial begin
t();
$display("FAILED");
end
endmodule

View File

@ -38,3 +38,7 @@ sv_array_cassign7 vvp_tests/sv_array_cassign7.json
sv_foreach9 vvp_tests/sv_foreach9.json
sv_foreach10 vvp_tests/sv_foreach10.json
sdf_header vvp_tests/sdf_header.json
task_return1 vvp_tests/task_return1.json
task_return2 vvp_tests/task_return2.json
task_return_fail1 vvp_tests/task_return_fail1.json
task_return_fail2 vvp_tests/task_return_fail2.json

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "task_return1.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "task_return2.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -0,0 +1,5 @@
{
"type" : "CE",
"source" : "task_return_fail1.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -0,0 +1,5 @@
{
"type" : "CE",
"source" : "task_return_fail2.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -5124,6 +5124,12 @@ class Design {
// detected. It prevents code being emitted.
unsigned errors;
void fork_enter() { in_fork++; };
void fork_exit() { in_fork--; };
bool is_in_fork() { return in_fork != 0; }
unsigned int in_fork = 0;
private:
NetScope* find_scope_(NetScope*, const hname_t&name,
NetScope::TYPE type = NetScope::MODULE) const;