vvp: Handle %fork in `final` procedures
In the current implementation a `%fork` instruction in a final block will get scheduled, but never executed. And while SystemVerilog requires a `final` procedure to execute in 0 time and so no SystemVerilog `fork` is allowed inside of it, there are some other scenarios where iverilog generates `%fork` statements. For example when declaring variables in a sub-block a sub-scope with its own thread is is used to allocate the storage for those variables and `%fork` is used to execute the child thread. E.g. the following, while being valid SystemVerilog, will never execute the loop because the generated code will implement the loop as a child thread being executed by a `%fork` statement. ``` final for (int i = 0; i < 10; i++) $display(i); ``` To mitigate this treat final statements the same as functions and rather than scheduling a child thread, execute it immediately when using the `%fork` statement. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
b210eb8264
commit
df30eda3a3
|
|
@ -855,6 +855,7 @@ void schedule_final_vthread(vthread_t thr)
|
|||
struct vthread_event_s*cur = new vthread_event_s;
|
||||
|
||||
cur->thr = thr;
|
||||
vthread_mark_final(thr);
|
||||
vthread_mark_scheduled(thr);
|
||||
|
||||
schedule_final_event(cur);
|
||||
|
|
|
|||
|
|
@ -833,6 +833,19 @@ void vthread_mark_scheduled(vthread_t thr)
|
|||
}
|
||||
}
|
||||
|
||||
void vthread_mark_final(vthread_t thr)
|
||||
{
|
||||
/*
|
||||
* The behavior in a final thread is the same as in a function. Any
|
||||
* child thread will be executed immediately rather than being
|
||||
* scheduled.
|
||||
*/
|
||||
while (thr != 0) {
|
||||
thr->i_am_in_function = 1;
|
||||
thr = thr->wait_next;
|
||||
}
|
||||
}
|
||||
|
||||
void vthread_delay_delete()
|
||||
{
|
||||
if (running_thread)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ extern vthread_t vthread_new(vvp_code_t sa, __vpiScope*scope);
|
|||
*/
|
||||
extern void vthread_mark_scheduled(vthread_t thr);
|
||||
|
||||
/*
|
||||
* This function marks the thread as being a final procedure.
|
||||
*/
|
||||
extern void vthread_mark_final(vthread_t thr);
|
||||
|
||||
/*
|
||||
* This function causes deletion of the currently running thread to
|
||||
* be delayed until after all sync events have been processed for the
|
||||
|
|
|
|||
Loading…
Reference in New Issue