Add support for SV wait fork to the run time.
This commit is contained in:
parent
3c7d7a7856
commit
4047ed7976
|
|
@ -1728,12 +1728,7 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
|
|||
if ((ivl_stmt_nevent(net) == 1) && (ivl_stmt_events(net, 0) == 0)) {
|
||||
assert(ivl_statement_type(ivl_stmt_sub_stmt(net)) == IVL_ST_NOOP);
|
||||
show_stmt_file_line(net, "Wait fork statement.");
|
||||
fprintf(vvp_out, " %%wait_fork;\n");
|
||||
|
||||
fprintf(stderr, "%s:%u: vvp.tgt sorry: wait fork is not currently "
|
||||
"supported.\n",
|
||||
ivl_stmt_file(net), ivl_stmt_lineno(net));
|
||||
vvp_errors += 1;
|
||||
fprintf(vvp_out, " %%wait/fork;\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ extern bool of_SUBSTR_V(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_TEST_NUL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_WAIT(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_WAIT_FORK(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_XNOR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_XNORR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_XOR(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%substr/v",of_SUBSTR_V,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%test_nul", of_TEST_NUL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||
{ "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%wait/fork",of_WAIT_FORK,0,{OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%xnor", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%xnor/r", of_XNORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%xor", of_XOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
|
|
|
|||
|
|
@ -1159,6 +1159,12 @@ threads that await the functor. When the defined sort of event occurs
|
|||
on the functor, a thread schedule event is created for all the threads
|
||||
in its list and the list is cleared.
|
||||
|
||||
* %wait/fork
|
||||
|
||||
This instruction puts the current thread to sleep until all the detached
|
||||
children have finished executing. The last detached child is responsible
|
||||
for restarting the parent when it finishes.
|
||||
|
||||
* %xnor <dst>, <src>, <wid>
|
||||
|
||||
This does a bitwise exclusive nor (~^) of the <src> and <dst> vector,
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ struct vthread_s {
|
|||
/* My parent sets this when it wants me to wake it up. */
|
||||
unsigned i_am_joining :1;
|
||||
unsigned i_am_detached :1;
|
||||
unsigned i_am_waiting :1;
|
||||
unsigned i_have_ended :1;
|
||||
unsigned waiting_for_event :1;
|
||||
unsigned is_scheduled :1;
|
||||
|
|
@ -543,6 +544,7 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope)
|
|||
|
||||
thr->i_am_joining = 0;
|
||||
thr->i_am_detached = 0;
|
||||
thr->i_am_waiting = 0;
|
||||
thr->is_scheduled = 0;
|
||||
thr->i_have_ended = 0;
|
||||
thr->delay_delete = 0;
|
||||
|
|
@ -2604,11 +2606,22 @@ bool of_END(vthread_t thr, vvp_code_t)
|
|||
}
|
||||
|
||||
/* If this thread is not fully detached then remove it from the
|
||||
* parents detached_children set. */
|
||||
* parents detached_children set and reap it. */
|
||||
if (thr->i_am_detached) {
|
||||
assert(thr->parent);
|
||||
size_t res = thr->parent->detached_children.erase(thr);
|
||||
vthread_t tmp = thr->parent;
|
||||
assert(tmp);
|
||||
size_t res = tmp->detached_children.erase(thr);
|
||||
assert(res == 1);
|
||||
/* If the parent is waiting for the detached children to
|
||||
* finish then the last detached child needs to tell the
|
||||
* parent to wake up when it is finished. */
|
||||
if (tmp->i_am_waiting && tmp->detached_children.empty()) {
|
||||
tmp->i_am_waiting = 0;
|
||||
schedule_vthread(tmp, 0, true);
|
||||
}
|
||||
/* Fully detach this thread so it will be reaped below. */
|
||||
thr->i_am_detached = 0;
|
||||
thr->parent = 0;
|
||||
}
|
||||
|
||||
/* If I have no parent, then no one can %join me and there is
|
||||
|
|
@ -5590,6 +5603,30 @@ bool of_WAIT(vthread_t thr, vvp_code_t cp)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the %wait/fork (SystemVerilog) instruction by suspending
|
||||
* the current thread until all the detached children have finished.
|
||||
*/
|
||||
bool of_WAIT_FORK(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
/* If a %wait/fork is being executed then the parent thread
|
||||
* cannot be waiting in a join or already waiting. */
|
||||
assert(! thr->i_am_joining);
|
||||
assert(! thr->i_am_waiting);
|
||||
|
||||
/* There should be no active children when waiting. */
|
||||
assert(thr->children.empty());
|
||||
|
||||
/* If there are no detached children then there is nothing to
|
||||
* wait for. */
|
||||
if (thr->detached_children.empty()) return true;
|
||||
|
||||
/* Flag that this process is waiting for the detached children
|
||||
* to finish and suspend it. */
|
||||
thr->i_am_waiting = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool of_XNOR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue