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_ZOMBIE(vthread_t thr, vvp_code_t code);
|
||||||
|
|
||||||
extern bool of_EXEC_UFUNC(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);
|
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
|
/* Construct some phantom code that is the thread of the
|
||||||
function call. The first instruction, at the start_address
|
function call. The first instruction, at the start_address
|
||||||
of the function, loads the points and calls the function.
|
of the function, loads the ports and calls the function.
|
||||||
The last instruction is the usual %end. So the thread looks
|
The second instruction collects the function result. The
|
||||||
|
last instruction is the usual %end. So the thread looks
|
||||||
like this:
|
like this:
|
||||||
|
|
||||||
%exec_ufunc <core>;
|
%exec_ufunc <core>;
|
||||||
|
%reap_ufunc <core>;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
The %exec_ufunc copies the input values into local regs,
|
The %exec_ufunc copies the input values into local regs
|
||||||
runs the function code, then copies the output values to
|
and runs the function code. The %reap_ufunc then copies
|
||||||
the destination net functors. */
|
the output value to the destination net functor. */
|
||||||
|
|
||||||
vvp_code_t start_code = codespace_allocate();
|
vvp_code_t exec_code = codespace_allocate();
|
||||||
start_code->opcode = of_EXEC_UFUNC;
|
exec_code->opcode = of_EXEC_UFUNC;
|
||||||
code_label_lookup(start_code, code);
|
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();
|
vvp_code_t end_code = codespace_allocate();
|
||||||
end_code->opcode = &of_END;
|
end_code->opcode = &of_END;
|
||||||
|
|
@ -204,13 +209,14 @@ void compile_ufunc(char*label, char*code, unsigned wid,
|
||||||
that will contain the execution. */
|
that will contain the execution. */
|
||||||
vvp_net_t*ptr = new vvp_net_t;
|
vvp_net_t*ptr = new vvp_net_t;
|
||||||
ufunc_core*fcore = new ufunc_core(wid, ptr, portc, ports,
|
ufunc_core*fcore = new ufunc_core(wid, ptr, portc, ports,
|
||||||
start_code, call_scope,
|
exec_code, call_scope,
|
||||||
retv.text, scope_label);
|
retv.text, scope_label);
|
||||||
ptr->fun = fcore;
|
ptr->fun = fcore;
|
||||||
define_functor_symbol(label, ptr);
|
define_functor_symbol(label, ptr);
|
||||||
free(label);
|
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);
|
wide_inputs_connect(fcore, argc, argv);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6468,23 +6468,40 @@ bool of_EXEC_UFUNC(vthread_t thr, vvp_code_t cp)
|
||||||
atomically. */
|
atomically. */
|
||||||
cp->ufunc_core_ptr->assign_bits_to_ports(child_context);
|
cp->ufunc_core_ptr->assign_bits_to_ports(child_context);
|
||||||
|
|
||||||
/* Create a temporary thread and run it immediately. A function
|
/* Create a temporary thread and run it immediately. */
|
||||||
may not contain any blocking statements, so vthread_run() can
|
|
||||||
only return when the %end opcode is reached. */
|
|
||||||
vthread_t child = vthread_new(cp->cptr, child_scope);
|
vthread_t child = vthread_new(cp->cptr, child_scope);
|
||||||
child->wt_context = child_context;
|
child->wt_context = child_context;
|
||||||
child->rd_context = child_context;
|
child->rd_context = child_context;
|
||||||
|
|
||||||
|
child->parent = thr;
|
||||||
child->is_scheduled = 1;
|
child->is_scheduled = 1;
|
||||||
vthread_run(child);
|
vthread_run(child);
|
||||||
running_thread = thr;
|
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. */
|
ports of the .ufunc device. */
|
||||||
cp->ufunc_core_ptr->finish_thread();
|
cp->ufunc_core_ptr->finish_thread();
|
||||||
|
|
||||||
/* If an automatic function, free the context for this call. */
|
/* If an automatic function, free the context for this call. */
|
||||||
if (child_scope->is_automatic) {
|
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->wt_context = 0;
|
||||||
thr->rd_context = 0;
|
thr->rd_context = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue