Add support for SV wait fork to the run time.

This commit is contained in:
Cary R 2013-10-22 15:58:59 -07:00
parent 3c7d7a7856
commit 4047ed7976
5 changed files with 49 additions and 9 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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} },

View File

@ -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,

View File

@ -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)
{