Generate code for task calls.

This commit is contained in:
steve 2001-04-02 02:28:12 +00:00
parent e6c36597eb
commit f40d006c26
17 changed files with 209 additions and 37 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: elaborate.cc,v 1.208 2001/02/15 06:59:36 steve Exp $"
#ident "$Id: elaborate.cc,v 1.209 2001/04/02 02:28:12 steve Exp $"
#endif
/*
@ -1366,7 +1366,8 @@ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const
NetScope*scope = des->find_scope(path);
assert(scope);
NetTaskDef*def = des->find_task(scope, name_);
NetScope*task = des->find_task(scope, name_);
NetTaskDef*def = task->task_def();
if (def == 0) {
cerr << get_line() << ": error: Enable of unknown task ``" <<
scope->name() << "." << name_ << "''." << endl;
@ -1386,7 +1387,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const
/* Handle tasks with no parameters specially. There is no need
to make a sequential block to hold the generated code. */
if (nparms() == 0) {
cur = new NetUTask(def);
cur = new NetUTask(task);
return cur;
}
@ -1425,7 +1426,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, const string&path) const
}
/* Generate the task call proper... */
cur = new NetUTask(def);
cur = new NetUTask(task);
block->append(cur);
@ -2171,7 +2172,8 @@ NetProc* PRepeat::elaborate(Design*des, const string&path) const
void PTask::elaborate(Design*des, const string&path) const
{
NetTaskDef*def = des->find_task(path);
NetScope*task = des->find_task(path);
NetTaskDef*def = task->task_def();
assert(def);
NetProc*st;
@ -2367,6 +2369,9 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.209 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.208 2001/02/15 06:59:36 steve
* FreeBSD port has a maintainer now.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: emit.cc,v 1.56 2001/03/27 03:31:06 steve Exp $"
#ident "$Id: emit.cc,v 1.57 2001/04/02 02:28:12 steve Exp $"
#endif
/*
@ -357,7 +357,7 @@ void NetScope::emit_defs(struct target_t*tgt) const
tgt->func_def(this->func_def());
break;
case TASK:
tgt->task_def(this->task_def());
tgt->task_def(this);
break;
}
@ -478,6 +478,9 @@ bool emit(const Design*des, const char*type)
/*
* $Log: emit.cc,v $
* Revision 1.57 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.56 2001/03/27 03:31:06 steve
* Support error code from target_t::end_design method.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: ivl_target.h,v 1.44 2001/04/02 00:28:35 steve Exp $"
#ident "$Id: ivl_target.h,v 1.45 2001/04/02 02:28:12 steve Exp $"
#endif
#ifdef __cplusplus
@ -249,6 +249,7 @@ typedef enum ivl_statement_type_e {
IVL_ST_FORK,
IVL_ST_STASK,
IVL_ST_TRIGGER,
IVL_ST_UTASK,
IVL_ST_WAIT,
IVL_ST_WHILE
} ivl_statement_type_t;
@ -540,6 +541,10 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
* If the scope has no children, this method will return 0 and
* otherwise do nothing.
*
* ivl_scope_def
* Task definition scopes carry a task definition, in the form of
* a statement. This method accesses that definition.
*
* ivl_scope_event
* ivl_scope_events
* Scopes have 0 or more event objects in them.
@ -569,6 +574,9 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
extern int ivl_scope_children(ivl_scope_t net,
ivl_scope_f func, void*cd);
extern ivl_statement_t ivl_scope_def(ivl_scope_t net);
extern unsigned ivl_scope_events(ivl_scope_t net);
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_logs(ivl_scope_t net);
@ -674,6 +682,8 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
extern unsigned ivl_stmt_block_count(ivl_statement_t net);
/* IVL_ST_BLOCK, IVL_ST_FORK */
extern ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, unsigned i);
/* IVL_ST_UTASK */
extern ivl_scope_t ivl_stmt_call(ivl_statement_t net);
/* IVL_ST_CASE */
extern unsigned ivl_stmt_case_count(ivl_statement_t net);
/* IVL_ST_CASE */
@ -725,6 +735,9 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.45 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.44 2001/04/02 00:28:35 steve
* Support the scope expression node.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: net_design.cc,v 1.18 2001/01/14 23:04:56 steve Exp $"
#ident "$Id: net_design.cc,v 1.19 2001/04/02 02:28:12 steve Exp $"
#endif
/*
@ -393,20 +393,20 @@ NetFuncDef* Design::find_function(const string&key)
return 0;
}
NetTaskDef* Design::find_task(NetScope*scope, const string&name)
NetScope* Design::find_task(NetScope*scope, const string&name)
{
NetScope*task = find_scope(scope, name);
if (task && (task->type() == NetScope::TASK))
return task->task_def();
return task;
return 0;
}
NetTaskDef* Design::find_task(const string&key)
NetScope* Design::find_task(const string&key)
{
NetScope*task = find_scope(key);
if (task && (task->type() == NetScope::TASK))
return task->task_def();
return task;
return 0;
}
@ -473,6 +473,9 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.19 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.18 2001/01/14 23:04:56 steve
* Generalize the evaluation of floating point delays, and
* get it working with delay assignment statements.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.cc,v 1.157 2001/02/10 21:20:38 steve Exp $"
#ident "$Id: netlist.cc,v 1.158 2001/04/02 02:28:12 steve Exp $"
#endif
# include <cassert>
@ -1752,7 +1752,7 @@ NetEUFunc* NetEUFunc::dup_expr() const
return 0;
}
NetUTask::NetUTask(NetTaskDef*def)
NetUTask::NetUTask(NetScope*def)
: task_(def)
{
}
@ -1761,6 +1761,16 @@ NetUTask::~NetUTask()
{
}
const string& NetUTask::name() const
{
return task_->name();
}
const NetScope* NetUTask::task() const
{
return task_;
}
NetExpr::NetExpr(unsigned w)
: width_(w)
{
@ -2460,6 +2470,9 @@ bool NetUDP::sequ_glob_(string input, char output)
/*
* $Log: netlist.cc,v $
* Revision 1.158 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.157 2001/02/10 21:20:38 steve
* Binary operators with operands of indefinite width
* has itself an indefinite width.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.h,v 1.200 2001/03/29 02:52:01 steve Exp $"
#ident "$Id: netlist.h,v 1.201 2001/04/02 02:28:12 steve Exp $"
#endif
/*
@ -1979,16 +1979,18 @@ class NetEUFunc : public NetExpr {
class NetUTask : public NetProc {
public:
NetUTask(NetTaskDef*);
NetUTask(NetScope*);
~NetUTask();
const string& name() const { return task_->name(); }
const string& name() const;
const NetScope* task() const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
private:
NetTaskDef*task_;
NetScope*task_;
};
/*
@ -2784,8 +2786,8 @@ class Design {
NetFuncDef* find_function(const string&path);
// Tasks
NetTaskDef* find_task(NetScope*scope, const string&name);
NetTaskDef* find_task(const string&key);
NetScope* find_task(NetScope*scope, const string&name);
NetScope* find_task(const string&key);
// NODES
void add_node(NetNode*);
@ -2870,6 +2872,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.201 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.200 2001/03/29 02:52:01 steve
* Add const probe method to NetEvent.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll-api.cc,v 1.31 2001/04/02 00:28:35 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.32 2001/04/02 02:28:12 steve Exp $"
#endif
# include "t-dll.h"
@ -452,6 +452,12 @@ extern "C" int ivl_scope_children(ivl_scope_t net,
return 0;
}
extern "C" ivl_statement_t ivl_scope_def(ivl_scope_t net)
{
assert(net);
return net->def;
}
extern "C" unsigned ivl_scope_events(ivl_scope_t net)
{
assert(net);
@ -608,6 +614,17 @@ extern "C" ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net,
}
}
extern "C" ivl_scope_t ivl_stmt_call(ivl_statement_t net)
{
switch (net->type_) {
case IVL_ST_UTASK:
return net->u_.utask_.def;
default:
assert(0);
return 0;
}
}
extern "C" unsigned ivl_stmt_case_count(ivl_statement_t net)
{
switch (net->type_) {
@ -812,6 +829,9 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.32 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.31 2001/04/02 00:28:35 steve
* Support the scope expression node.
*

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll-proc.cc,v 1.19 2001/04/01 06:52:28 steve Exp $"
#ident "$Id: t-dll-proc.cc,v 1.20 2001/04/02 02:28:12 steve Exp $"
#endif
# include "target.h"
@ -74,6 +74,22 @@ bool dll_target::process(const NetProcTop*net)
return true;
}
void dll_target::task_def(const NetScope*net)
{
ivl_scope_t scope = lookup_scope_(net);
const NetTaskDef*def = net->task_def();
assert(stmt_cur_ == 0);
stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_);
assert(stmt_cur_);
def->proc()->emit_proc(this);
assert(stmt_cur_);
scope->def = stmt_cur_;
stmt_cur_ = 0;
}
/*
*/
void dll_target::proc_assign(const NetAssign*net)
@ -330,6 +346,15 @@ bool dll_target::proc_trigger(const NetEvTrig*net)
return true;
}
void dll_target::proc_utask(const NetUTask*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
stmt_cur_->type_ = IVL_ST_UTASK;
stmt_cur_->u_.utask_.def = lookup_scope_(net->task());
}
bool dll_target::proc_wait(const NetEvWait*net)
{
assert(stmt_cur_);
@ -438,6 +463,9 @@ void dll_target::proc_while(const NetWhile*net)
/*
* $Log: t-dll-proc.cc,v $
* Revision 1.20 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.19 2001/04/01 06:52:28 steve
* support the NetWhile statement.
*

15
t-dll.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll.h,v 1.31 2001/04/02 00:28:35 steve Exp $"
#ident "$Id: t-dll.h,v 1.32 2001/04/02 02:28:12 steve Exp $"
#endif
# include "target.h"
@ -84,9 +84,12 @@ struct dll_target : public target_t, public expr_scan_t {
bool proc_delay(const NetPDelay*);
void proc_stask(const NetSTask*);
bool proc_trigger(const NetEvTrig*);
void proc_utask(const NetUTask*);
bool proc_wait(const NetEvWait*);
void proc_while(const NetWhile*);
void task_def(const NetScope*);
struct ivl_expr_s*expr_;
void expr_binary(const NetEBinary*);
void expr_concat(const NetEConcat*);
@ -304,6 +307,9 @@ struct ivl_scope_s {
unsigned nlpm_;
ivl_lpm_t* lpm_;
/* Scopes that are tasks have a definition. */
ivl_statement_t def;
};
/*
@ -385,6 +391,10 @@ struct ivl_statement_s {
ivl_event_t event_;
} trig_;
struct { /* IVL_ST_UTASK */
ivl_scope_t def;
} utask_;
struct { /* IVL_ST_WAIT */
ivl_event_t event_;
ivl_statement_t stmt_;
@ -399,6 +409,9 @@ struct ivl_statement_s {
/*
* $Log: t-dll.h,v $
* Revision 1.32 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.31 2001/04/02 00:28:35 steve
* Support the scope expression node.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-vvm.cc,v 1.203 2001/03/27 03:31:06 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.204 2001/04/02 02:28:12 steve Exp $"
#endif
# include <iostream>
@ -150,7 +150,7 @@ class target_vvm : public target_t {
virtual void event(const NetEvent*);
virtual void signal(const NetNet*);
virtual void memory(const NetMemory*);
virtual void task_def(const NetTaskDef*);
virtual void task_def(const NetScope*);
virtual void func_def(const NetFuncDef*);
virtual void lpm_add_sub(const NetAddSub*);
@ -1357,8 +1357,10 @@ void target_vvm::memory(const NetMemory*mem)
mem->count() << ");" << endl;
}
void target_vvm::task_def(const NetTaskDef*def)
void target_vvm::task_def(const NetScope*scope)
{
const NetTaskDef*def = scope->task_def();
thread_step_ = 0;
const string name = mangle(def->name());
const string save_thread_class = thread_class_;
@ -3636,6 +3638,9 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.204 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.203 2001/03/27 03:31:06 steve
* Support error code from target_t::end_design method.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: target.cc,v 1.50 2001/03/27 03:31:06 steve Exp $"
#ident "$Id: target.cc,v 1.51 2001/04/02 02:28:13 steve Exp $"
#endif
# include "target.h"
@ -49,7 +49,7 @@ void target_t::func_def(const NetFuncDef*)
"Unhandled function definition." << endl;
}
void target_t::task_def(const NetTaskDef*)
void target_t::task_def(const NetScope*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled task definition." << endl;
@ -389,6 +389,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* Revision 1.51 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.50 2001/03/27 03:31:06 steve
* Support error code from target_t::end_design method.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: target.h,v 1.49 2001/03/27 03:31:06 steve Exp $"
#ident "$Id: target.h,v 1.50 2001/04/02 02:28:13 steve Exp $"
#endif
# include "netlist.h"
@ -69,7 +69,7 @@ struct target_t {
virtual void memory(const NetMemory*);
/* Output a defined task. */
virtual void task_def(const NetTaskDef*);
virtual void task_def(const NetScope*);
virtual void func_def(const NetFuncDef*);
/* LPM style components are handled here. */
@ -160,6 +160,9 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* Revision 1.50 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.49 2001/03/27 03:31:06 steve
* Support error code from target_t::end_design method.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: stub.c,v 1.34 2001/04/01 01:48:21 steve Exp $"
#ident "$Id: stub.c,v 1.35 2001/04/02 02:28:13 steve Exp $"
#endif
/*
@ -238,6 +238,10 @@ static void show_statement(ivl_statement_t net, unsigned ind)
fprintf(out, "%*s-> ...\n", ind, "");
break;
case IVL_ST_UTASK:
fprintf(out, "%*scall task ...\n", ind, "");
break;
case IVL_ST_WAIT: {
ivl_event_t evnt = ivl_stmt_event(net);
fprintf(out, "%*s@(%s)\n", ind, "", ivl_event_name(evnt));
@ -480,6 +484,9 @@ DECLARE_CYGWIN_DLL(DllMain);
/*
* $Log: stub.c,v $
* Revision 1.35 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.34 2001/04/01 01:48:21 steve
* Redesign event information to support arbitrary edge combining.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vvp_priv.h,v 1.6 2001/03/31 17:36:39 steve Exp $"
#ident "$Id: vvp_priv.h,v 1.7 2001/04/02 02:28:13 steve Exp $"
#endif
# include "ivl_target.h"
@ -38,6 +38,8 @@ extern FILE* vvp_out;
*/
extern int draw_process(ivl_process_t net, void*x);
extern int draw_task_definition(ivl_scope_t scope);
extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent);
/*
@ -71,6 +73,9 @@ extern void clr_vector(struct vector_info vec);
/*
* $Log: vvp_priv.h,v $
* Revision 1.7 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.6 2001/03/31 17:36:39 steve
* Generate vvp code for case statements.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vvp_process.c,v 1.18 2001/04/02 00:27:53 steve Exp $"
#ident "$Id: vvp_process.c,v 1.19 2001/04/02 02:28:13 steve Exp $"
#endif
# include "vvp_priv.h"
@ -335,6 +335,15 @@ static int show_stmt_trigger(ivl_statement_t net)
return 0;
}
static int show_stmt_utask(ivl_statement_t net)
{
ivl_scope_t task = ivl_stmt_call(net);
fprintf(vvp_out, " %%fork TD_%s;\n", ivl_scope_name(task));
fprintf(vvp_out, " %%join;\n");
return 0;
}
static int show_stmt_wait(ivl_statement_t net)
{
ivl_event_t ev = ivl_stmt_event(net);
@ -496,6 +505,10 @@ static int show_statement(ivl_statement_t net)
rc += show_stmt_trigger(net);
break;
case IVL_ST_UTASK:
rc += show_stmt_utask(net);
break;
case IVL_ST_WAIT:
rc += show_stmt_wait(net);
break;
@ -561,8 +574,27 @@ int draw_process(ivl_process_t net, void*x)
return rc;
}
int draw_task_definition(ivl_scope_t scope)
{
int rc = 0;
ivl_statement_t def = ivl_scope_def(scope);
fprintf(vvp_out, "TD_%s ;\n", ivl_scope_name(scope));
assert(def);
rc += show_statement(def);
fprintf(vvp_out, " %%end;\n");
thread_count += 1;
return rc;
}
/*
* $Log: vvp_process.c,v $
* Revision 1.19 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.18 2001/04/02 00:27:53 steve
* Scopes and numbers as vpi_call parameters.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vvp_scope.c,v 1.11 2001/04/01 21:34:48 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.12 2001/04/02 02:28:13 steve Exp $"
#endif
# include "vvp_priv.h"
@ -257,12 +257,19 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
draw_event_in_scope(event);
}
if (ivl_scope_type(net) == IVL_SCT_TASK)
draw_task_definition(net);
ivl_scope_children(net, (ivl_scope_f*) draw_scope, net);
return 0;
}
/*
* $Log: vvp_scope.c,v $
* Revision 1.12 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.11 2001/04/01 21:34:48 steve
* Recognize the BUF device.
*

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: README.txt,v 1.11 2001/03/30 04:55:22 steve Exp $
* $Id: README.txt,v 1.12 2001/04/02 02:28:13 steve Exp $
*/
VVP SIMULATION ENGINE
@ -242,12 +242,19 @@ A transient thread is created with a %fork instruction. When a
transient thread is created this way, the operand to the %fork gives
the starting address, and the new thread is said to be a child of the
forking thread. The children of a thread are pushed onto a stack of
children.
children. A thread can have only one direct child.
A transient thread is reaped with a %join instruction. %join waits for
the top thread in the stack of children to complete, then
continues. It is an error to %join when there are no children.
As you can see, the transient thread in VVP is a cross between a
conventional thread and a function call. In fact, there is no %call
instruction in vvp, the job is accomplished with %fork/%join in the
caller and %end in the callee. The %fork, then is simply a
generalization of a function call, where the caller does not
necessarily wait for the callee.
TRUTH TABLES
The logic that a functor represents is expressed as a truth table. The