Merge branch 'master' into vec4-stack
This commit is contained in:
commit
88e4938074
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
26
vvp/ufunc.cc
26
vvp/ufunc.cc
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue