Put threads into scopes.

This commit is contained in:
steve 2001-04-18 04:21:23 +00:00
parent 41ce198a1f
commit 9e8005f7b7
14 changed files with 286 additions and 114 deletions

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: README.txt,v 1.15 2001/04/14 05:10:56 steve Exp $
* $Id: README.txt,v 1.16 2001/04/18 04:21:23 steve Exp $
*/
VVP SIMULATION ENGINE
@ -293,16 +293,11 @@ vvp.txt for .scope declarations.) The .thread statement placed in the
assembly source after a .scope statement causes the thread to join the
named scope.
Transient threads initially inherit the scope of the parent
thread. Right after the %fork statement, the new thread is created
within the scope of the thread that executes the %fork
statement. Transient threads leaf the parent scope and join a new
scope with the %scope instruction.
A thread normally executes a %scope instruction only once. At any
rate, a thread is only in a single scope, and does not remember past
scopes that it might have been a part of. This is how a new thread
switches out of the parent scope and into its own scope.
Transient threads join a scope that is the operand to the %fork
instruction. The scope is referenced by name, and the thread created
by the fork atomically joins that scope. Once the transient thread
joins the scope, it stays there until it ends. Threads never change
scopes, not even transient threads.
TRUTH TABLES

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: codes.h,v 1.19 2001/04/15 16:37:48 steve Exp $"
#ident "$Id: codes.h,v 1.20 2001/04/18 04:21:23 steve Exp $"
#endif
@ -43,6 +43,7 @@ extern bool of_CMPU(vthread_t thr, vvp_code_t code);
extern bool of_CMPX(vthread_t thr, vvp_code_t code);
extern bool of_CMPZ(vthread_t thr, vvp_code_t code);
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
extern bool of_DISABLE(vthread_t thr, vvp_code_t code);
extern bool of_END(vthread_t thr, vvp_code_t code);
extern bool of_FORK(vthread_t thr, vvp_code_t code);
extern bool of_INV(vthread_t thr, vvp_code_t code);
@ -75,12 +76,18 @@ struct vvp_code_s {
vvp_ipoint_t iptr;
vvp_cpoint_t cptr;
struct __vpiHandle*handle;
struct fork_extend*fork;
};
unsigned short bit_idx1;
unsigned short bit_idx2;
};
struct fork_extend {
vvp_cpoint_t cptr;
struct __vpiScope*scope;
};
/*
* This function clears the code space, ready for initialization. This
@ -110,6 +117,9 @@ extern void codespace_dump(FILE*fd);
/*
* $Log: codes.h,v $
* Revision 1.20 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.19 2001/04/15 16:37:48 steve
* add XOR support.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.cc,v 1.34 2001/04/15 16:37:48 steve Exp $"
#ident "$Id: compile.cc,v 1.35 2001/04/18 04:21:23 steve Exp $"
#endif
# include "compile.h"
@ -74,7 +74,6 @@ const static struct opcode_table_s opcode_table[] = {
{ "%cmp/z", of_CMPZ, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%fork", of_FORK, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
{ "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
@ -548,6 +547,72 @@ void compile_codelabel(char*label)
free(label);
}
void compile_disable(char*label, struct symb_s symb)
{
vvp_cpoint_t ptr = codespace_allocate();
/* First, I can give the label a value that is the current
codespace pointer. Don't need the text of the label after
this is done. */
if (label) {
symbol_value_t val;
val.num = ptr;
sym_set_value(sym_codespace, label, val);
}
/* Fill in the basics of the %disable in the instruction. */
vvp_code_t code = codespace_index(ptr);
code->opcode = of_DISABLE;
/* Figure out the target SCOPE. */
code->handle = compile_vpi_lookup(symb.text);
assert(code->handle);
free(label);
free(symb.text);
}
/*
* The %fork instruction is a little different from other instructions
* in that it has an extended field that holds the information needed
* to create the new thread. This includes the target PC and scope.
* I get these from the parser in the form of symbols.
*/
void compile_fork(char*label, struct symb_s dest, struct symb_s scope)
{
symbol_value_t tmp;
vvp_cpoint_t ptr = codespace_allocate();
/* First, I can give the label a value that is the current
codespace pointer. Don't need the text of the label after
this is done. */
if (label) {
symbol_value_t val;
val.num = ptr;
sym_set_value(sym_codespace, label, val);
}
/* Fill in the basics of the %fork in the instruction. */
vvp_code_t code = codespace_index(ptr);
code->opcode = of_FORK;
code->fork = new struct fork_extend;
/* Figure out the target PC. */
tmp = sym_get_value(sym_codespace, dest.text);
code->fork->cptr = tmp.num;
assert(code->fork->cptr);
/* Figure out the target SCOPE. */
vpiHandle sh = compile_vpi_lookup(scope.text);
assert(sh);
code->fork->scope = (struct __vpiScope*)sh;
free(label);
free(dest.text);
free(scope.text);
}
void compile_vpi_call(char*label, char*name, unsigned argc, vpiHandle*argv)
{
vvp_cpoint_t ptr = codespace_allocate();
@ -590,7 +655,7 @@ void compile_thread(char*start_sym)
return;
}
vthread_t thr = vthread_new(pc);
vthread_t thr = vthread_new(pc, vpip_peek_current_scope());
schedule_vthread(thr, 0);
free(start_sym);
}
@ -763,6 +828,9 @@ void compile_dump(FILE*fd)
/*
* $Log: compile.cc,v $
* Revision 1.35 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.34 2001/04/15 16:37:48 steve
* add XOR support.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.h,v 1.15 2001/04/14 05:10:56 steve Exp $"
#ident "$Id: compile.h,v 1.16 2001/04/18 04:21:23 steve Exp $"
#endif
# include <stdio.h>
@ -104,8 +104,11 @@ struct comp_operands_s {
typedef struct comp_operands_s*comp_operands_t;
extern void compile_code(char*label, char*mnem, comp_operands_t opa);
extern void compile_disable(char*label, struct symb_s symb);
extern void compile_vpi_call(char*label, char*name,
unsigned argc, vpiHandle*argv);
extern void compile_fork(char*label, struct symb_s targ_s,
struct symb_s scope_s);
extern void compile_codelabel(char*label);
/*
@ -139,6 +142,9 @@ extern void compile_dump(FILE*fd);
/*
* $Log: compile.h,v $
* Revision 1.16 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.15 2001/04/14 05:10:56 steve
* support the .event/or statement.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: functor.cc,v 1.11 2001/04/14 05:10:56 steve Exp $"
#ident "$Id: functor.cc,v 1.12 2001/04/18 04:21:23 steve Exp $"
#endif
# include "functor.h"
@ -274,8 +274,8 @@ void functor_dump(FILE*fd)
{
for (unsigned idx = 1 ; idx < functor_count ; idx += 1) {
functor_t cur = functor_index(idx*4);
fprintf(fd, "%10p: out=%x port={%x %x %x %x}\n",
(void*)(idx*4), cur->out, cur->port[0],
fprintf(fd, "%08x: out=%x port={%x %x %x %x}\n",
(idx*4), cur->out, cur->port[0],
cur->port[1], cur->port[2], cur->port[3]);
}
}
@ -306,6 +306,9 @@ const unsigned char ft_var[16] = {
/*
* $Log: functor.cc,v $
* Revision 1.12 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.11 2001/04/14 05:10:56 steve
* support the .event/or statement.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: lexor.lex,v 1.12 2001/04/14 05:10:56 steve Exp $"
#ident "$Id: lexor.lex,v 1.13 2001/04/18 04:21:23 steve Exp $"
#endif
# include "parse_misc.h"
@ -80,8 +80,9 @@
kind of instruction this really is. The few exceptions (that have
exceptional parameter requirements) are listed first. */
"%vpi_call" {
return K_vpi_call; }
"%vpi_call" { return K_vpi_call; }
"%disable" { return K_disable; }
"%fork" { return K_fork; }
"%"[.$_/a-zA-Z0-9]+ {
yylval.text = strdup(yytext);
@ -126,6 +127,9 @@ int yywrap()
/*
* $Log: lexor.lex,v $
* Revision 1.13 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.12 2001/04/14 05:10:56 steve
* support the .event/or statement.
*

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: opcodes.txt,v 1.13 2001/04/15 16:37:48 steve Exp $
* $Id: opcodes.txt,v 1.14 2001/04/18 04:21:23 steve Exp $
*/
@ -87,7 +87,14 @@ future to reschedule, and is >= 0. If the %delay is zero, then the
thread yields the processor for another thread, but will be resumed in
the current time step.
* %fork <code-label>
* %disable <scope-label>
This instruction terminates threads that are part of a specific
scope. The label identifies the scope in question, and the threads are
the threads that are currently within that scope.
* %fork <code-label>, <scope-label>
This instruction is similar to %jmp, except that it creates a new
thread to start executing at the specified address. The new thread is

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: parse.y,v 1.19 2001/04/14 05:10:56 steve Exp $"
#ident "$Id: parse.y,v 1.20 2001/04/18 04:21:23 steve Exp $"
#endif
# include "parse_misc.h"
@ -52,7 +52,7 @@ extern FILE*yyin;
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_SCOPE K_THREAD
%token K_VAR K_VAR_S K_vpi_call
%token K_VAR K_VAR_S K_vpi_call K_disable K_fork
%token K_vpi_module
%token <text> T_INSTR
@ -144,6 +144,16 @@ statement
| label_opt K_vpi_call T_STRING argument_opt ';'
{ compile_vpi_call($1, $3, $4.argc, $4.argv); }
/* %disable statements are instructions that takes a scope reference
as an operand. It therefore is parsed uniquely. */
| label_opt K_disable symbol ';'
{ compile_disable($1, $3); }
| label_opt K_fork symbol ',' symbol ';'
{ compile_fork($1, $3, $5); }
/* Scope statements come in two forms. There are the scope
declaration and the scope recall. */
@ -329,6 +339,9 @@ int compile_design(const char*path)
/*
* $Log: parse.y,v $
* Revision 1.20 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.19 2001/04/14 05:10:56 steve
* support the .event/or statement.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: schedule.cc,v 1.4 2001/03/31 19:00:43 steve Exp $"
#ident "$Id: schedule.cc,v 1.5 2001/04/18 04:21:23 steve Exp $"
#endif
# include "schedule.h"
@ -39,9 +39,10 @@ struct event_s {
struct event_s*next;
struct event_s*last;
};
const unsigned TYPE_THREAD = 0;
const unsigned TYPE_PROP = 1;
const unsigned TYPE_ASSIGN = 2;
const unsigned TYPE_NOOP = 0;
const unsigned TYPE_THREAD = 1;
const unsigned TYPE_PROP = 2;
const unsigned TYPE_ASSIGN = 3;
/*
* This is the head of the list of pending events.
@ -194,6 +195,9 @@ void schedule_simulate(void)
/*
* $Log: schedule.cc,v $
* Revision 1.5 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.4 2001/03/31 19:00:43 steve
* Add VPI support for the simulation time.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_priv.h,v 1.12 2001/04/05 01:34:26 steve Exp $"
#ident "$Id: vpi_priv.h,v 1.13 2001/04/18 04:21:23 steve Exp $"
#endif
# include "vpi_user.h"
@ -85,8 +85,11 @@ struct __vpiScope {
/* Keep an array of internal scope items. */
struct __vpiHandle**intern;
unsigned nintern;
/* Keep a list of threads in the scope. */
vthread_t threads;
};
extern vpiHandle vpip_peek_current_scope(void);
extern struct __vpiScope* vpip_peek_current_scope(void);
extern void vpip_attach_to_current_scope(vpiHandle obj);
/*
@ -96,7 +99,7 @@ extern void vpip_attach_to_current_scope(vpiHandle obj);
*/
struct __vpiSignal {
struct __vpiHandle base;
vpiHandle scope;
struct __vpiScope* scope;
/* The name of this reg/net object */
char*name;
/* The indices that define the width and access offset. */
@ -128,7 +131,7 @@ struct __vpiUserSystf {
struct __vpiSysTaskCall {
struct __vpiHandle base;
vpiHandle scope;
struct __vpiScope* scope;
struct __vpiUserSystf*defn;
unsigned nargs;
vpiHandle*args;
@ -193,6 +196,9 @@ vpiHandle vpip_sim_time(void);
/*
* $Log: vpi_priv.h,v $
* Revision 1.13 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.12 2001/04/05 01:34:26 steve
* Add the .var/s and .net/s statements for VPI support.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_scope.cc,v 1.3 2001/04/03 03:46:14 steve Exp $"
#ident "$Id: vpi_scope.cc,v 1.4 2001/04/18 04:21:23 steve Exp $"
#endif
# include "compile.h"
@ -94,12 +94,12 @@ static void attach_to_scope_(struct __vpiScope*scope, vpiHandle obj)
*/
void compile_scope_decl(char*label, char*name, char*parent)
{
struct __vpiScope*scope = (struct __vpiScope*)
malloc(sizeof(struct __vpiScope));
struct __vpiScope*scope = new struct __vpiScope;
scope->base.vpi_type = &vpip_scope_rt;
scope->name = name;
scope->intern = 0;
scope->nintern = 0;
scope->threads = 0;
current_scope = scope;
@ -121,9 +121,9 @@ void compile_scope_recall(char*symbol)
free(symbol);
}
vpiHandle vpip_peek_current_scope(void)
struct __vpiScope* vpip_peek_current_scope(void)
{
return &current_scope->base;
return current_scope;
}
void vpip_attach_to_current_scope(vpiHandle obj)
@ -134,6 +134,9 @@ void vpip_attach_to_current_scope(vpiHandle obj)
/*
* $Log: vpi_scope.cc,v $
* Revision 1.4 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.3 2001/04/03 03:46:14 steve
* VPI access time as a decimal string, and
* stub vpi access to the scopes.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_tasks.cc,v 1.4 2001/03/22 22:38:14 steve Exp $"
#ident "$Id: vpi_tasks.cc,v 1.5 2001/04/18 04:21:23 steve Exp $"
#endif
/*
@ -39,7 +39,7 @@ static vpiHandle systask_handle(int type, vpiHandle ref)
switch (type) {
case vpiScope:
return rfp->scope;
return &rfp->scope->base;
default:
return 0;
};
@ -197,6 +197,9 @@ void vpi_register_systf(const struct t_vpi_systf_data*ss)
/*
* $Log: vpi_tasks.cc,v $
* Revision 1.5 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.4 2001/03/22 22:38:14 steve
* Detect undefined system tasks at compile time.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vthread.cc,v 1.26 2001/04/15 16:37:48 steve Exp $"
#ident "$Id: vthread.cc,v 1.27 2001/04/18 04:21:23 steve Exp $"
#endif
# include "vthread.h"
@ -85,14 +85,16 @@ struct vthread_s {
unsigned nbits :16;
/* My parent sets this when it wants me to wake it up. */
unsigned schedule_parent_on_end :1;
unsigned i_have_ended :1;
unsigned i_have_ended :1;
unsigned waiting_for_event :1;
/* This points to the sole child of the thread. */
struct vthread_s*child;
/* This points to my parent, if I have one. */
struct vthread_s*parent;
/* This is used for keeping wait queues. */
struct vthread_s*next;
struct vthread_s*wait_next;
/* These are used to keep the thread in a scope. */
struct vthread_s*scope_next, *scope_prev;
};
static void thr_check_addr(struct vthread_s*thr, unsigned addr)
@ -129,7 +131,7 @@ static inline void thr_put_bit(struct vthread_s*thr,
/*
* Create a new thread with the given start address.
*/
vthread_t vthread_new(unsigned long pc)
vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
{
vthread_t thr = new struct vthread_s;
thr->pc = pc;
@ -137,7 +139,28 @@ vthread_t vthread_new(unsigned long pc)
thr->nbits = 16*4;
thr->child = 0;
thr->parent = 0;
thr->next = 0;
thr->wait_next = 0;
/* If the target scope never held a thread, then create a
header cell for it. This is a stub to make circular lists
easier to work with. */
if (scope->threads == 0) {
scope->threads = new struct vthread_s;
scope->threads->pc = 0;
scope->threads->bits = 0;
scope->threads->nbits = 0;
scope->threads->child = 0;
scope->threads->parent = 0;
scope->threads->scope_prev = scope->threads;
scope->threads->scope_next = scope->threads;
}
{ vthread_t tmp = scope->threads;
thr->scope_next = tmp->scope_next;
thr->scope_prev = tmp;
thr->scope_next->scope_prev = thr;
thr->scope_prev->scope_next = thr;
}
thr->schedule_parent_on_end = 0;
thr->i_have_ended = 0;
@ -147,20 +170,30 @@ vthread_t vthread_new(unsigned long pc)
thr_put_bit(thr, 1, 1);
thr_put_bit(thr, 2, 2);
thr_put_bit(thr, 3, 3);
return thr;
}
static void vthread_reap(vthread_t thr)
{
assert(thr->next == 0);
assert(thr->wait_next == 0);
assert(thr->child == 0);
free(thr->bits);
thr->bits = 0;
if (thr->child)
thr->child->parent = thr->parent;
if (thr->parent)
thr->parent->child = thr->child;
thr->child = 0;
thr->parent = 0;
thr->scope_next->scope_prev = thr->scope_prev;
thr->scope_prev->scope_next = thr->scope_next;
thr->pc = 0;
delete thr;
}
@ -187,7 +220,7 @@ void vthread_run(vthread_t thr)
}
/*
* This is called by an event functor to wait up all the threads on
* This is called by an event functor to wake up all the threads on
* its list. I in fact created that list in the %wait instruction, and
* I also am certain that the waiting_for_event flag is set.
*/
@ -195,9 +228,10 @@ void vthread_schedule_list(vthread_t thr)
{
while (thr) {
vthread_t tmp = thr;
thr = thr->next;
thr = thr->wait_next;
assert(tmp->waiting_for_event);
tmp->waiting_for_event = 0;
tmp->wait_next = 0;
schedule_vthread(tmp, 0);
}
}
@ -430,30 +464,87 @@ bool of_DELAY(vthread_t thr, vvp_code_t cp)
return false;
}
/*
* Implement the %disable instruction by scanning the target scope for
* all the target threads. Kill the target threads and wake up a
* parent that is attempting a %join.
*
* XXXX BUG BUG!
* The scheduler probably still has a pointer to me, and this reaping
* will destroy this object. The result: dangling pointer.
*/
bool of_DISABLE(vthread_t thr, vvp_code_t cp)
{
struct __vpiScope*scope = (struct __vpiScope*)cp->handle;
if (scope->threads == 0)
return true;
struct vthread_s*head = scope->threads;
while (head->scope_next != head) {
vthread_t tmp = head->scope_next;
/* Pull the target thread out of the scope. */
tmp->scope_next->scope_prev = tmp->scope_prev;
tmp->scope_prev->scope_next = tmp->scope_next;
/* XXXX I don't support disabling threads with children. */
assert(tmp->child == 0);
assert(tmp != thr);
/* XXXX Not supported yet. */
assert(tmp->waiting_for_event);
tmp->pc = 0;
tmp->i_have_ended = 1;
/* If a parent is waiting in a %join, wake it up. */
if (tmp->schedule_parent_on_end) {
assert(tmp->parent);
schedule_vthread(tmp->parent, 0);
}
if (tmp->parent == 0) {
vthread_reap(tmp);
}
}
return true;
}
/*
* This terminates the current thread. If there is a parent who is
* waiting for me to die, then I schedule it. At any rate, I mark
* myself as a zombie by setting my pc to 0.
*/
bool of_END(vthread_t thr, vvp_code_t cp)
bool of_END(vthread_t thr, vvp_code_t)
{
assert(! thr->waiting_for_event);
thr->i_have_ended = 1;
thr->pc = 0;
#if 0
/* Reap direct descendents that have already ended. Do
this in a loop until I run out of dead children. */
while (thr->child && (thr->child->i_have_ended)) {
fprintf(stderr, "vvp warning: A thread left dangling "
"children at %%end. This is caused\n"
" : by a missing %%join.\n");
vthread_t tmp = thr->child;
vthread_reap(tmp);
}
#else
/* If this thread has children, then there is a programming
error as there were not enough %join instructions to reap
all the children. */
assert(thr->child == 0);
#endif
/* If I have a parent who is waiting for me, then mark that I
have ended, and schedule that parent. The parent will reap
me, so don't do it here. */
me with a %join, so don't do it here. */
if (thr->schedule_parent_on_end) {
assert(thr->parent);
schedule_vthread(thr->parent, 0);
@ -464,10 +555,12 @@ bool of_END(vthread_t thr, vvp_code_t cp)
no reason to stick around. This can happen, for example if
I am an ``initial'' thread. */
if (thr->parent == 0) {
#if 0
if (thr->child)
fprintf(stderr, "vvp warning: A thread left dangling "
"children. This is probably caused\n"
" : a missing %%join in this thread.\n");
"children at delete. This is caused\n"
" : by a missing %%join.\n");
#endif
vthread_reap(thr);
return false;
}
@ -486,7 +579,7 @@ bool of_END(vthread_t thr, vvp_code_t cp)
*/
bool of_FORK(vthread_t thr, vvp_code_t cp)
{
vthread_t child = vthread_new(cp->cptr);
vthread_t child = vthread_new(cp->fork->cptr, cp->fork->scope);
child->child = thr->child;
child->parent = thr;
@ -562,11 +655,14 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
{
assert(thr->child);
assert(thr->child->parent == thr);
/* If the child has already ended, reap it now. */
if (thr->child->i_have_ended) {
vthread_reap(thr->child);
return true;
}
/* Otherwise, I get to start waiting. */
thr->child->schedule_parent_on_end = 1;
return false;
}
@ -683,7 +779,7 @@ bool of_WAIT(vthread_t thr, vvp_code_t cp)
functor_t fp = functor_index(cp->iptr);
assert((fp->mode == 1) || (fp->mode == 2));
vvp_event_t ep = fp->event;
thr->next = ep->threads;
thr->wait_next = ep->threads;
ep->threads = thr;
return false;
@ -764,13 +860,20 @@ bool of_XOR(vthread_t thr, vvp_code_t cp)
}
bool of_ZOMBIE(vthread_t, vvp_code_t)
bool of_ZOMBIE(vthread_t thr, vvp_code_t)
{
thr->pc = 0;
if ((thr->parent == 0) && (thr->child == 0))
delete thr;
return false;
}
/*
* $Log: vthread.cc,v $
* Revision 1.27 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.26 2001/04/15 16:37:48 steve
* add XOR support.
*
@ -794,61 +897,5 @@ bool of_ZOMBIE(vthread_t, vvp_code_t)
*
* Revision 1.19 2001/04/01 07:22:08 steve
* Implement the less-then and %or instructions.
*
* Revision 1.18 2001/04/01 06:12:14 steve
* Add the bitwise %and instruction.
*
* Revision 1.17 2001/04/01 04:34:28 steve
* Implement %cmp/x and %cmp/z instructions.
*
* Revision 1.16 2001/03/31 17:36:02 steve
* Add the jmp/1 instruction.
*
* Revision 1.15 2001/03/31 01:59:59 steve
* Add the ADD instrunction.
*
* Revision 1.14 2001/03/30 04:55:22 steve
* Add fork and join instructions.
*
* Revision 1.13 2001/03/29 03:46:36 steve
* Support named events as mode 2 functors.
*
* Revision 1.12 2001/03/26 04:00:39 steve
* Add the .event statement and the %wait instruction.
*
* Revision 1.11 2001/03/25 03:54:26 steve
* Add JMP0XZ and postpone net inputs when needed.
*
* Revision 1.10 2001/03/23 04:56:03 steve
* eq is x if either value of cmp/u has x or z.
*
* Revision 1.9 2001/03/23 01:53:46 steve
* Support set of functors from thread bits.
*
* Revision 1.8 2001/03/23 01:11:06 steve
* Handle vectors pulled out of a constant bit.
*
* Revision 1.7 2001/03/22 05:08:00 steve
* implement %load, %inv, %jum/0 and %cmp/u
*
* Revision 1.6 2001/03/20 06:16:24 steve
* Add support for variable vectors.
*
* Revision 1.5 2001/03/19 01:55:38 steve
* Add support for the vpiReset sim control.
*
* Revision 1.4 2001/03/16 01:44:34 steve
* Add structures for VPI support, and all the %vpi_call
* instruction. Get linking of VPI modules to work.
*
* Revision 1.3 2001/03/11 23:06:49 steve
* Compact the vvp_code_s structure.
*
* Revision 1.2 2001/03/11 22:42:11 steve
* Functor values and propagation.
*
* Revision 1.1 2001/03/11 00:29:39 steve
* Add the vvp engine to cvs.
*
*/

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vthread.h,v 1.3 2001/04/13 03:55:18 steve Exp $"
#ident "$Id: vthread.h,v 1.4 2001/04/18 04:21:23 steve Exp $"
#endif
/*
@ -40,7 +40,7 @@ typedef struct vthread_s*vthread_t;
* address. The generated thread is ready to run, but is not yet
* scheduled.
*/
extern vthread_t vthread_new(unsigned long sa);
extern vthread_t vthread_new(unsigned long sa, struct __vpiScope*scope);
/*
* Cause this thread to execute instructions until in is put to sleep
@ -59,6 +59,9 @@ extern void vthread_schedule_list(vthread_t thr);
/*
* $Log: vthread.h,v $
* Revision 1.4 2001/04/18 04:21:23 steve
* Put threads into scopes.
*
* Revision 1.3 2001/04/13 03:55:18 steve
* More complete reap of all threads.
*