Implement fork-join_none in vvp.

This commit is contained in:
Stephen Williams 2012-05-20 11:39:52 -07:00
parent 47ddf5220c
commit 3b7619b46c
4 changed files with 85 additions and 13 deletions

View File

@ -1314,55 +1314,85 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope)
{ {
unsigned idx; unsigned idx;
int rc = 0; int rc = 0;
unsigned cnt = ivl_stmt_block_count(net); unsigned join_count = ivl_stmt_block_count(net);
unsigned join_detach_count = 0;
ivl_scope_t scope = ivl_stmt_block_scope(net); ivl_scope_t scope = ivl_stmt_block_scope(net);
unsigned is_named = (scope != 0); int is_named = (scope != 0);
/* This is TRUE if it is allowed to embed one of the threads
into this thread. */
int is_embeddable = 1;
unsigned out = transient_id++; unsigned out = transient_id++;
unsigned id_base = transient_id; unsigned id_base = transient_id;
/* Children are certainly not embeddable if they are going
into a new scope. */
if (is_named)
is_embeddable = 0;
switch (ivl_statement_type(net)) {
case IVL_ST_FORK:
break;
case IVL_ST_FORK_JOIN_ANY:
if (join_count < 2)
break;
is_embeddable = 0;
join_detach_count = join_count - 1;
join_count = 1;
break;
case IVL_ST_FORK_JOIN_NONE:
is_embeddable = 0;
join_detach_count = join_count;
join_count = 0;
break;
default:
assert(0);
}
/* cnt is the number of sub-threads. If the fork-join has no /* cnt is the number of sub-threads. If the fork-join has no
name, then we can put one of the sub-threads in the current name, then we can put one of the sub-threads in the current
thread, so decrement the count by one and use the current thread, so decrement the count by one and use the current
scope for all the threads. */ scope for all the threads. */
if (! is_named) { if (is_embeddable)
cnt -= 1; join_count -= 1;
if (scope==0)
scope = sscope; scope = sscope;
}
transient_id += cnt; transient_id += join_count;
/* Draw a fork statement for all but one of the threads of the /* Draw a fork statement for all but one of the threads of the
fork/join. Send the threads off to a bit of code where they fork/join. Send the threads off to a bit of code where they
are implemented. */ are implemented. */
for (idx = 0 ; idx < cnt ; idx += 1) { for (idx = 0 ; idx < (join_count+join_detach_count) ; idx += 1) {
fprintf(vvp_out, " %%fork t_%u, S_%p;\n", fprintf(vvp_out, " %%fork t_%u, S_%p;\n",
id_base+idx, scope); id_base+idx, scope);
} }
/* If we are putting one sub-thread into the current thread, /* If we are putting one sub-thread into the current thread,
then draw its code here. */ then draw its code here. */
if (! is_named) if (is_embeddable)
rc += show_statement(ivl_stmt_block_stmt(net, cnt), scope); rc += show_statement(ivl_stmt_block_stmt(net, join_count), scope);
/* Generate enough joins to collect all the sub-threads. */ /* Generate enough joins to collect all the sub-threads. */
for (idx = 0 ; idx < cnt ; idx += 1) { for (idx = 0 ; idx < join_count ; idx += 1)
fprintf(vvp_out, " %%join;\n"); fprintf(vvp_out, " %%join;\n");
} if (join_detach_count > 0)
fprintf(vvp_out, " %%join/detach %u;\n", join_detach_count);
/* Jump around all the threads that I'm creating. */
fprintf(vvp_out, " %%jmp t_%u;\n", out); fprintf(vvp_out, " %%jmp t_%u;\n", out);
/* Change the compiling scope to be the named forks scope. */ /* Change the compiling scope to be the named forks scope. */
if (is_named) fprintf(vvp_out, " .scope S_%p;\n", scope); if (is_named) fprintf(vvp_out, " .scope S_%p;\n", scope);
/* Generate the sub-threads themselves. */ /* Generate the sub-threads themselves. */
for (idx = 0 ; idx < cnt ; idx += 1) { for (idx = 0 ; idx < (join_count + join_detach_count) ; idx += 1) {
fprintf(vvp_out, "t_%u ;\n", id_base+idx); fprintf(vvp_out, "t_%u ;\n", id_base+idx);
clear_expression_lookaside(); clear_expression_lookaside();
rc += show_statement(ivl_stmt_block_stmt(net, idx), scope); rc += show_statement(ivl_stmt_block_stmt(net, idx), scope);
fprintf(vvp_out, " %%end;\n"); fprintf(vvp_out, " %%end;\n");
} }
/* Return to the previous scope. */ /* Return to the previous scope. */
if (is_named) fprintf(vvp_out, " .scope S_%p;\n", sscope); if (sscope) fprintf(vvp_out, " .scope S_%p;\n", sscope);
/* This is the label for the out. Use this to branch around /* This is the label for the out. Use this to branch around
the implementations of all the child threads. */ the implementations of all the child threads. */
@ -2073,6 +2103,8 @@ static int show_statement(ivl_statement_t net, ivl_scope_t sscope)
break; break;
case IVL_ST_FORK: case IVL_ST_FORK:
case IVL_ST_FORK_JOIN_ANY:
case IVL_ST_FORK_JOIN_NONE:
rc += show_stmt_fork(net, sscope); rc += show_stmt_fork(net, sscope);
break; break;

View File

@ -115,6 +115,7 @@ extern bool of_JMP0(vthread_t thr, vvp_code_t code);
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code); extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
extern bool of_JMP1(vthread_t thr, vvp_code_t code); extern bool of_JMP1(vthread_t thr, vvp_code_t code);
extern bool of_JOIN(vthread_t thr, vvp_code_t code); extern bool of_JOIN(vthread_t thr, vvp_code_t code);
extern bool of_JOIN_DETACH(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code);

View File

@ -157,6 +157,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} }, { "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} }, { "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} },
{ "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },

View File

@ -2892,6 +2892,44 @@ bool of_JOIN(vthread_t thr, vvp_code_t)
return false; return false;
} }
/*
* This %join/detach <n> instruction causes the thread to detach
* threads that were created by an earlier %fork.
*/
bool of_JOIN_DETACH(vthread_t thr, vvp_code_t cp)
{
unsigned long count = cp->number;
while (count > 0) {
assert(thr->child);
assert(thr->child->parent == thr);
assert(thr->fork_count > 0);
assert(thr->child->wt_context == 0);
thr->fork_count -= 1;
if (thr->child->i_have_ended) {
/* If the child has already ended, then reap it
instead of pulling it from the list. */
vthread_reap(thr->child);
} else {
/* Pull the child from the parent->child list. */
struct vthread_s*tmp = thr->child;
assert(tmp->fork_count == 0);
thr->child = tmp->child;
if (thr->child)
thr->child->parent = thr;
/* set up detach. */
tmp->parent = 0;
tmp->child = 0;
}
count -= 1;
}
return true;
}
/* /*
* %load/ar <bit>, <array-label>, <index>; * %load/ar <bit>, <array-label>, <index>;
*/ */