diff --git a/vvp/schedule.cc b/vvp/schedule.cc index bbc088b21..5dee5aab4 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -16,9 +16,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: schedule.cc,v 1.45 2007/01/16 05:44:16 steve Exp $" -#endif # include "schedule.h" # include "memory.h" @@ -63,6 +60,7 @@ struct event_time_s { struct event_s*nbassign; struct event_s*rwsync; struct event_s*rosync; + struct event_s*del_thr; struct event_time_s*next; @@ -88,6 +86,16 @@ void vthread_event_s::run_run(void) vthread_run(thr); } +struct del_thr_event_s : public event_s { + vthread_t thr; + void run_run(void); +}; + +void del_thr_event_s::run_run(void) +{ + vthread_delete(thr); +} + struct assign_vector4_event_s : public event_s { /* Where to do the assign. */ vvp_net_ptr_t ptr; @@ -280,7 +288,8 @@ static void signals_revert(void) * itself, and the structure is placed in the right place in the * queue. */ -typedef enum event_queue_e { SEQ_ACTIVE, SEQ_NBASSIGN, SEQ_RWSYNC, SEQ_ROSYNC } event_queue_t; +typedef enum event_queue_e { SEQ_ACTIVE, SEQ_NBASSIGN, SEQ_RWSYNC, SEQ_ROSYNC, + DEL_THREAD } event_queue_t; static void schedule_event_(struct event_s*cur, vvp_time64_t delay, event_queue_t select_queue) @@ -297,6 +306,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, ctim->nbassign = 0; ctim->rwsync = 0; ctim->rosync = 0; + ctim->del_thr = 0; ctim->delay = delay; ctim->next = 0; sched_list = ctim; @@ -310,6 +320,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, tmp->nbassign = 0; tmp->rwsync = 0; tmp->rosync = 0; + tmp->del_thr = 0; tmp->delay = delay; tmp->next = ctim; ctim->delay -= delay; @@ -331,6 +342,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, tmp->nbassign = 0; tmp->rwsync = 0; tmp->rosync = 0; + tmp->del_thr = 0; tmp->delay = delay; tmp->next = prev->next; prev->next = tmp; @@ -347,6 +359,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, tmp->nbassign = 0; tmp->rwsync = 0; tmp->rosync = 0; + tmp->del_thr = 0; tmp->delay = delay - ctim->delay; tmp->next = 0; ctim->next = tmp; @@ -408,6 +421,18 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, ctim->rosync = cur; } break; + + case DEL_THREAD: + if (ctim->del_thr == 0) { + ctim->del_thr = cur; + + } else { + /* Put the cur event on the end of the active list. */ + cur->next = ctim->del_thr->next; + ctim->del_thr->next = cur; + ctim->del_thr = cur; + } + break; } } @@ -549,6 +574,15 @@ void schedule_init_vector(vvp_net_ptr_t ptr, double bit) schedule_init_list = cur; } +void schedule_del_thr(vthread_t thr) +{ + struct del_thr_event_s*cur = new del_thr_event_s; + + cur->thr = thr; + + schedule_event_(cur, 0, DEL_THREAD); +} + void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay, bool sync_flag, bool ro_flag) { @@ -576,6 +610,9 @@ extern void vpiNextSimTime(void); * it is legal for a rosync callback to create other rosync * callbacks. It is *not* legal for them to create any other kinds of * events, and that is why the rosync is treated specially. + * + * Once all the rosync callbacks are done we can safely delete any + * threads that finished during this time step. */ static void run_rosync(struct event_time_s*ctim) { @@ -591,6 +628,18 @@ static void run_rosync(struct event_time_s*ctim) delete cur; } + while (ctim->del_thr) { + struct event_s*cur = ctim->del_thr->next; + if (cur->next == cur) { + ctim->del_thr = 0; + } else { + ctim->del_thr->next = cur->next; + } + + cur->run_run(); + delete cur; + } + if (ctim->active || ctim->nbassign || ctim->rwsync) { fprintf(stderr, "SCHEDULER ERROR: read-only sync events " "created RW events!\n"); @@ -655,7 +704,8 @@ void schedule_simulate(void) ctim->rwsync = 0; /* If out of rw events, then run the rosync - events and delete this timestep. */ + events and delete this timestep. This also + deletes threads as needed. */ if (ctim->active == 0) { run_rosync(ctim); sched_list = ctim->next; @@ -686,4 +736,3 @@ void schedule_simulate(void) // Execute post-simulation callbacks vpiPostsim(); } - diff --git a/vvp/schedule.h b/vvp/schedule.h index b1ccdb5d0..689694397 100644 --- a/vvp/schedule.h +++ b/vvp/schedule.h @@ -1,7 +1,7 @@ #ifndef __schedule_H #define __schedule_H /* - * Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: schedule.h,v 1.29 2007/01/16 05:44:16 steve Exp $" -#endif # include "vthread.h" # include "pointers.h" @@ -110,6 +107,9 @@ typedef struct vvp_gen_event_s *vvp_gen_event_t; extern void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay, bool sync_flag, bool ro_flag =true); +/* Use this is schedule thread deletion (after rosync). */ +extern void schedule_del_thr(vthread_t thr); + struct vvp_gen_event_s { virtual ~vvp_gen_event_s() =0; diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 09ea32382..6343a88e5 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -265,8 +265,6 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope) */ static void vthread_reap(vthread_t thr) { - thr->bits4 = vvp_vector4_t(); - if (thr->child) { assert(thr->child->parent == thr); thr->child->parent = thr->parent; @@ -290,10 +288,16 @@ static void vthread_reap(vthread_t thr) if ((thr->is_scheduled == 0) && (thr->waiting_for_event == 0)) { assert(thr->fork_count == 0); assert(thr->wait_next == 0); - delete thr; + schedule_del_thr(thr); } } +void vthread_delete(vthread_t thr) +{ + thr->bits4 = vvp_vector4_t(); + delete thr; +} + void vthread_mark_scheduled(vthread_t thr) { while (thr != 0) { diff --git a/vvp/vthread.h b/vvp/vthread.h index e9ef81c5b..b6ee59cf0 100644 --- a/vvp/vthread.h +++ b/vvp/vthread.h @@ -1,7 +1,7 @@ #ifndef __vthread_H #define __vthread_H /* - * Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: vthread.h,v 1.12 2005/08/27 02:34:43 steve Exp $" -#endif # include "vvp_net.h" @@ -77,48 +74,7 @@ extern void vthread_put_bit(struct vthread_s*thr, unsigned addr, vvp_bit4_t bit) extern double vthread_get_real(struct vthread_s*thr, unsigned addr); extern void vthread_put_real(struct vthread_s*thr, unsigned addr, double val); -/* - * $Log: vthread.h,v $ - * Revision 1.12 2005/08/27 02:34:43 steve - * Bring threads into the vvp_vector4_t structure. - * - * Revision 1.11 2003/07/03 20:03:36 steve - * Remove the vvp_cpoint_t indirect code pointer. - * - * Revision 1.10 2003/01/27 00:14:37 steve - * Support in various contexts the $realtime - * system task. - * - * Revision 1.9 2003/01/26 18:16:22 steve - * Add %cvt/ir and %cvt/ri instructions, and support - * real values passed as arguments to VPI tasks. - * - * Revision 1.8 2002/08/12 01:35:09 steve - * conditional ident string using autoconfig. - * - * Revision 1.7 2001/05/20 00:45:43 steve - * include missing externs on vthread_put_bit. - * - * Revision 1.6 2001/05/10 00:26:53 steve - * VVP support for memories in expressions, - * including general support for thread bit - * vectors as system task parameters. - * (Stephan Boettcher) - * - * Revision 1.5 2001/04/21 00:34:39 steve - * Working %disable and reap handling references from scheduler. - * - * 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. - * - * Revision 1.2 2001/03/26 04:00:39 steve - * Add the .event statement and the %wait instruction. - * - * Revision 1.1 2001/03/11 00:29:39 steve - * Add the vvp engine to cvs. - * - */ +/* This is used to actually delete a thread once we are done with it. */ +extern void vthread_delete(vthread_t thr); + #endif