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)) {
|
if ((ivl_stmt_nevent(net) == 1) && (ivl_stmt_events(net, 0) == 0)) {
|
||||||
assert(ivl_statement_type(ivl_stmt_sub_stmt(net)) == IVL_ST_NOOP);
|
assert(ivl_statement_type(ivl_stmt_sub_stmt(net)) == IVL_ST_NOOP);
|
||||||
show_stmt_file_line(net, "Wait fork statement.");
|
show_stmt_file_line(net, "Wait fork statement.");
|
||||||
fprintf(vvp_out, " %%wait_fork;\n");
|
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;
|
|
||||||
return 0;
|
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_TEST_NUL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_VPI_CALL(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(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_XNOR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_XNORR(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);
|
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} },
|
{ "%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} },
|
{ "%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", 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", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%xnor/r", of_XNORR, 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} },
|
{ "%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
|
on the functor, a thread schedule event is created for all the threads
|
||||||
in its list and the list is cleared.
|
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>
|
* %xnor <dst>, <src>, <wid>
|
||||||
|
|
||||||
This does a bitwise exclusive nor (~^) of the <src> and <dst> vector,
|
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. */
|
/* My parent sets this when it wants me to wake it up. */
|
||||||
unsigned i_am_joining :1;
|
unsigned i_am_joining :1;
|
||||||
unsigned i_am_detached :1;
|
unsigned i_am_detached :1;
|
||||||
|
unsigned i_am_waiting :1;
|
||||||
unsigned i_have_ended :1;
|
unsigned i_have_ended :1;
|
||||||
unsigned waiting_for_event :1;
|
unsigned waiting_for_event :1;
|
||||||
unsigned is_scheduled :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_joining = 0;
|
||||||
thr->i_am_detached = 0;
|
thr->i_am_detached = 0;
|
||||||
|
thr->i_am_waiting = 0;
|
||||||
thr->is_scheduled = 0;
|
thr->is_scheduled = 0;
|
||||||
thr->i_have_ended = 0;
|
thr->i_have_ended = 0;
|
||||||
thr->delay_delete = 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
|
/* 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) {
|
if (thr->i_am_detached) {
|
||||||
assert(thr->parent);
|
vthread_t tmp = thr->parent;
|
||||||
size_t res = thr->parent->detached_children.erase(thr);
|
assert(tmp);
|
||||||
|
size_t res = tmp->detached_children.erase(thr);
|
||||||
assert(res == 1);
|
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
|
/* 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;
|
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)
|
bool of_XNOR(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue