diff --git a/ivtest/ivltests/final3.v b/ivtest/ivltests/final3.v new file mode 100644 index 000000000..b943e9656 --- /dev/null +++ b/ivtest/ivltests/final3.v @@ -0,0 +1,20 @@ +// Check that sub-blocks with variable declarations inside final procedures get +// executed + + +module test; + + final begin + static int x = -1; + for (int i = 0; i < 1; i++) begin + x = i; + end + + if (x === 0) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 31e20b9e1..8b0ce376c 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -23,6 +23,7 @@ dffsynth9 vvp_tests/dffsynth9.json dffsynth10 vvp_tests/dffsynth10.json dffsynth11 vvp_tests/dffsynth11.json dumpfile vvp_tests/dumpfile.json +final3 vvp_tests/final3.json macro_str_esc vvp_tests/macro_str_esc.json memsynth1 vvp_tests/memsynth1.json param-width vvp_tests/param-width.json diff --git a/ivtest/vvp_tests/final3.json b/ivtest/vvp_tests/final3.json new file mode 100644 index 000000000..99b4572c5 --- /dev/null +++ b/ivtest/vvp_tests/final3.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "final3.v", + "iverilog-args" : [ "-g2009" ] +} diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 78920dee9..961aa36e6 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -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); diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 2b35315b0..02c7c179d 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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) diff --git a/vvp/vthread.h b/vvp/vthread.h index 75d7929c8..1658c6839 100644 --- a/vvp/vthread.h +++ b/vvp/vthread.h @@ -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