Merge pull request #900 from larsclausen/task-return
Support return in tasks
This commit is contained in:
commit
f22c1a519b
39
elaborate.cc
39
elaborate.cc
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "task_return1.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "normal",
|
||||
"source" : "task_return2.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "task_return_fail1.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "task_return_fail2.v",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue