diff --git a/vvp/codes.h b/vvp/codes.h index 9f16b0a77..1aae56f78 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: codes.h,v 1.59 2003/03/28 02:33:56 steve Exp $" +#ident "$Id: codes.h,v 1.60 2003/05/07 03:39:12 steve Exp $" #endif @@ -117,7 +117,8 @@ 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_CALL_UFUNC(vthread_t thr, vvp_code_t code); +extern bool of_FORK_UFUNC(vthread_t thr, vvp_code_t code); +extern bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t code); /* * This is the format of a machine code instruction. @@ -171,6 +172,9 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr); /* * $Log: codes.h,v $ + * Revision 1.60 2003/05/07 03:39:12 steve + * ufunc calls to functions can have scheduling complexities. + * * Revision 1.59 2003/03/28 02:33:56 steve * Add support for division of real operands. * diff --git a/vvp/ufunc.cc b/vvp/ufunc.cc index defea9506..0dd878e32 100644 --- a/vvp/ufunc.cc +++ b/vvp/ufunc.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ufunc.cc,v 1.2 2002/08/12 01:35:08 steve Exp $" +#ident "$Id: ufunc.cc,v 1.3 2003/05/07 03:39:12 steve Exp $" #endif # include "compile.h" @@ -32,6 +32,7 @@ #endif # include # include +# include # include #ifdef __MINGW32__ @@ -171,12 +172,36 @@ 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. */ + The last instruction is the usual %end. So the thread looks + like this: + + %fork_ufunc ; + %join; + %join_ufunc; + %end; + + The %fork_ufunc starts the user defined function by copying + the input values into local regs, forking a thread and + pushing that thread. The %join waits on that thread. The + $join_ufunc then copies the output values to the + destination net functors. */ + vvp_cpoint_t start_address = codespace_allocate(); vvp_code_t start_code = codespace_index(start_address); - start_code->opcode = of_CALL_UFUNC; + start_code->opcode = of_FORK_UFUNC; code_label_lookup(start_code, code); + { vvp_cpoint_t cur = codespace_allocate(); + vvp_code_t codep = codespace_index(cur); + codep->opcode = &of_JOIN; + } + + vvp_code_t ujoin_code; + { vvp_cpoint_t cur = codespace_allocate(); + ujoin_code = codespace_index(cur); + ujoin_code->opcode = &of_JOIN_UFUNC; + } + { vvp_cpoint_t cur = codespace_allocate(); vvp_code_t codep = codespace_index(cur); codep->opcode = &of_END; @@ -191,6 +216,7 @@ void compile_ufunc(char*label, char*code, unsigned wid, start_address, vpip_peek_current_scope()); start_code->ufunc_core_ptr = core; + ujoin_code->ufunc_core_ptr = core; /* create enough input functors to connect to all the input bits of the function. These are used to detect changes and @@ -215,6 +241,9 @@ void compile_ufunc(char*label, char*code, unsigned wid, /* * $Log: ufunc.cc,v $ + * Revision 1.3 2003/05/07 03:39:12 steve + * ufunc calls to functions can have scheduling complexities. + * * Revision 1.2 2002/08/12 01:35:08 steve * conditional ident string using autoconfig. * diff --git a/vvp/vthread.cc b/vvp/vthread.cc index eb38970b5..26fe6b48a 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vthread.cc,v 1.106 2003/03/28 02:33:57 steve Exp $" +#ident "$Id: vthread.cc,v 1.107 2003/05/07 03:39:12 steve Exp $" #endif # include "vthread.h" @@ -2653,28 +2653,43 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t) } /* - * This is a phantom opcode used to call user defined functions. It is - * used in code generated by the .ufunc statement. This instruction - * contains a pointer to executable code of the function, and to a + * These are phantom opcode used to call user defined functions. + * They are used in code generated by the .ufunc statement. They + * contain a pointer to executable code of the function, and to a * ufunc_core object that has all the port information about the * function. */ -bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp) +bool of_FORK_UFUNC(vthread_t thr, vvp_code_t cp) { /* Copy all the inputs to the ufunc object to the port variables of the function. This copies all the values atomically. */ cp->ufunc_core_ptr->assign_bits_to_ports(); - /* Create a temporary thread, and execute it manually. This is - necessary so that the previous step (assign_bits_to_ports) - and the execution of the function itself are an atomic - unit. If it were not, then the inputs might change between - setup and execution, causing really bad things to happen. */ - vthread_t child = vthread_new(cp->cptr, cp->ufunc_core_ptr->scope()); - vthread_mark_scheduled(child); - vthread_run(child); + assert(thr->child == 0); + assert(thr->fork_count == 0); + /* Create a temporary thread, and push its execution. This is + done so that the assign_bits_to_ports above is atomic with + this startup. */ + vthread_t child = vthread_new(cp->cptr, cp->ufunc_core_ptr->scope()); + + child->child = 0; + child->parent = thr; + thr->child = child; + + thr->fork_count += 1; + schedule_vthread(child, 0, true); + + /* After this function, the .ufunc code has placed an of_JOIN + to pause this thread. Since the child was pushed by the + flag to schecule_vthread, the called function starts up + immediately. */ + return true; +} + +bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp) +{ /* Now copy the output from the result variable to the output ports of the .ufunc device. */ cp->ufunc_core_ptr->finish_thread(thr); @@ -2684,6 +2699,9 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp) /* * $Log: vthread.cc,v $ + * Revision 1.107 2003/05/07 03:39:12 steve + * ufunc calls to functions can have scheduling complexities. + * * Revision 1.106 2003/03/28 02:33:57 steve * Add support for division of real operands. *