Merge branch 'master' into vec4-stack

This commit is contained in:
Stephen Williams 2014-03-04 19:08:56 -08:00
commit 88e4938074
3 changed files with 39 additions and 15 deletions

View File

@ -242,6 +242,7 @@ extern bool of_XORR(vthread_t thr, vvp_code_t code);
extern bool of_ZOMBIE(vthread_t thr, vvp_code_t code);
extern bool of_EXEC_UFUNC(vthread_t thr, vvp_code_t code);
extern bool of_REAP_UFUNC(vthread_t thr, vvp_code_t code);
extern bool of_CHUNK_LINK(vthread_t thr, vvp_code_t code);

View File

@ -173,20 +173,25 @@ void compile_ufunc(char*label, char*code, unsigned wid,
/* Construct some phantom code that is the thread of the
function call. The first instruction, at the start_address
of the function, loads the points and calls the function.
The last instruction is the usual %end. So the thread looks
of the function, loads the ports and calls the function.
The second instruction collects the function result. The
last instruction is the usual %end. So the thread looks
like this:
%exec_ufunc <core>;
%reap_ufunc <core>;
%end;
The %exec_ufunc copies the input values into local regs,
runs the function code, then copies the output values to
the destination net functors. */
The %exec_ufunc copies the input values into local regs
and runs the function code. The %reap_ufunc then copies
the output value to the destination net functor. */
vvp_code_t start_code = codespace_allocate();
start_code->opcode = of_EXEC_UFUNC;
code_label_lookup(start_code, code);
vvp_code_t exec_code = codespace_allocate();
exec_code->opcode = of_EXEC_UFUNC;
code_label_lookup(exec_code, code);
vvp_code_t reap_code = codespace_allocate();
reap_code->opcode = of_REAP_UFUNC;
vvp_code_t end_code = codespace_allocate();
end_code->opcode = &of_END;
@ -204,13 +209,14 @@ void compile_ufunc(char*label, char*code, unsigned wid,
that will contain the execution. */
vvp_net_t*ptr = new vvp_net_t;
ufunc_core*fcore = new ufunc_core(wid, ptr, portc, ports,
start_code, call_scope,
exec_code, call_scope,
retv.text, scope_label);
ptr->fun = fcore;
define_functor_symbol(label, ptr);
free(label);
start_code->ufunc_core_ptr = fcore;
exec_code->ufunc_core_ptr = fcore;
reap_code->ufunc_core_ptr = fcore;
wide_inputs_connect(fcore, argc, argv);

View File

@ -6468,23 +6468,40 @@ bool of_EXEC_UFUNC(vthread_t thr, vvp_code_t cp)
atomically. */
cp->ufunc_core_ptr->assign_bits_to_ports(child_context);
/* Create a temporary thread and run it immediately. A function
may not contain any blocking statements, so vthread_run() can
only return when the %end opcode is reached. */
/* Create a temporary thread and run it immediately. */
vthread_t child = vthread_new(cp->cptr, child_scope);
child->wt_context = child_context;
child->rd_context = child_context;
child->parent = thr;
child->is_scheduled = 1;
vthread_run(child);
running_thread = thr;
/* Now copy the output from the result variable to the output
if (child->i_have_ended)
return true;
thr->children.insert(child);
thr->i_am_joining = 1;
return false;
}
/*
* This is a phantom opcode used to harvest the result of calling a user
* defined function. It is used in code generated by the .ufunc statement.
*/
bool of_REAP_UFUNC(vthread_t thr, vvp_code_t cp)
{
struct __vpiScope*child_scope = cp->ufunc_core_ptr->func_scope();
assert(child_scope);
/* Copy the output from the result variable to the output
ports of the .ufunc device. */
cp->ufunc_core_ptr->finish_thread();
/* If an automatic function, free the context for this call. */
if (child_scope->is_automatic) {
vthread_free_context(child_context, child_scope);
vthread_free_context(thr->rd_context, child_scope);
thr->wt_context = 0;
thr->rd_context = 0;
}