Working %disable and reap handling references from scheduler.

This commit is contained in:
steve 2001-04-21 00:34:39 +00:00
parent 3765bdd3ac
commit 66f83f3b08
4 changed files with 118 additions and 27 deletions

74
vvp/examples/disable.vvp Normal file
View File

@ -0,0 +1,74 @@
:vpi_module "system";
; Copyright (c) 2001 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
; General Public License as published by the Free Software
; Foundation; either version 2 of the License, or (at your option)
; any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
; This example is similar to the following Verilog code. The idea is
; to test the disable statement. The task creates a scope (called test)
; that is a hook for the disable statement to get at the thread that
; threatens to fail the test. If the disable statement works properly,
; the test task will be disabled before the #5 delay expires.
;
; module main;
; task test;
; begin
; #5 $display("FAILED...");
; $finish;
; end
; endtask
;
; initial begin
; fork
; test;
; #1 disable test;
; join
; $display("PASSED");
; end
; endmodule
;
S_main .scope "main";
S_test .scope "test", S_main;
; This code in the implementation of the thread that goes into the
; test scope. The idea is to disable this thread before it does its
; job and prints a failure.
.scope S_test;
T_0/1 ;
%delay 5;
%vpi_call "$display", "FAILED -- thread wasn't disbled";
%vpi_call "$finish";
%end;
; This is the main thread. Fork the thread under test, delay for a
; moment to let it run, then %disable the test thread. If I don't
; disable the test thread in time, then the child will print an error
; message and exit.
.scope S_main;
T_0 ;
%fork T_0/1, S_test;
%delay 1;
%disable S_test ; This is the statement that I'm testing.
%join;
%vpi_call "$display", "PASSED";
%end;
.thread T_0;

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.5 2001/04/18 04:21:23 steve Exp $"
#ident "$Id: schedule.cc,v 1.6 2001/04/21 00:34:39 steve Exp $"
#endif
# include "schedule.h"
@ -120,6 +120,7 @@ void schedule_vthread(vthread_t thr, unsigned delay)
cur->delay = delay;
cur->thr = thr;
cur->type = TYPE_THREAD;
vthread_mark_scheduled(thr);
schedule_event_(cur);
}
@ -195,6 +196,9 @@ void schedule_simulate(void)
/*
* $Log: schedule.cc,v $
* Revision 1.6 2001/04/21 00:34:39 steve
* Working %disable and reap handling references from scheduler.
*
* Revision 1.5 2001/04/18 04:21:23 steve
* Put threads into scopes.
*

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.28 2001/04/18 05:04:19 steve Exp $"
#ident "$Id: vthread.cc,v 1.29 2001/04/21 00:34:39 steve Exp $"
#endif
# include "vthread.h"
@ -87,6 +87,7 @@ struct vthread_s {
unsigned schedule_parent_on_end :1;
unsigned i_have_ended :1;
unsigned waiting_for_event :1;
unsigned is_scheduled :1;
/* This points to the sole child of the thread. */
struct vthread_s*child;
/* This points to my parent, if I have one. */
@ -194,9 +195,19 @@ static void vthread_reap(vthread_t thr)
thr->scope_prev->scope_next = thr->scope_next;
thr->pc = 0;
delete thr;
/* If this thread is not scheduled, then is it safe to delete
it now. Otherwise, let the schedule event (which will
execute the thread at of_ZOMBIE) delete the object. */
if (thr->is_scheduled == 0)
delete thr;
}
void vthread_mark_scheduled(vthread_t thr)
{
assert(thr->is_scheduled == 0);
thr->is_scheduled = 1;
}
/*
* This function runs a thread by fetching an instruction,
@ -204,6 +215,9 @@ static void vthread_reap(vthread_t thr)
*/
void vthread_run(vthread_t thr)
{
assert(thr->is_scheduled);
thr->is_scheduled = 0;
for (;;) {
vvp_code_t cp = codespace_index(thr->pc);
thr->pc += 1;
@ -492,18 +506,24 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
assert(tmp->child == 0);
assert(tmp != thr);
/* XXXX Not supported yet. */
assert(tmp->waiting_for_event);
assert(tmp->waiting_for_event == 0);
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) {
/* If a parent is waiting in a %join, wake it up. */
assert(tmp->parent);
schedule_vthread(tmp->parent, 0);
}
vthread_reap(tmp);
if (tmp->parent == 0) {
} else if (tmp->parent) {
/* If the parent is yet to %join me, let its %join
do the reaping. */
//assert(tmp->is_scheduled == 0);
} else {
/* No parent at all. Goodby. */
vthread_reap(tmp);
}
}
@ -523,23 +543,10 @@ bool of_END(vthread_t thr, vvp_code_t)
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
@ -556,12 +563,6 @@ bool of_END(vthread_t thr, vvp_code_t)
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 at delete. This is caused\n"
" : by a missing %%join.\n");
#endif
vthread_reap(thr);
return false;
}
@ -872,6 +873,9 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t)
/*
* $Log: vthread.cc,v $
* Revision 1.29 2001/04/21 00:34:39 steve
* Working %disable and reap handling references from scheduler.
*
* Revision 1.28 2001/04/18 05:04:19 steve
* %end complete the %join for the parent.
*

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.4 2001/04/18 04:21:23 steve Exp $"
#ident "$Id: vthread.h,v 1.5 2001/04/21 00:34:39 steve Exp $"
#endif
/*
@ -42,6 +42,12 @@ typedef struct vthread_s*vthread_t;
*/
extern vthread_t vthread_new(unsigned long sa, struct __vpiScope*scope);
/*
* This function marks the thread as scheduled. It is used only by the
* schedule_vthread function.
*/
extern void vthread_mark_scheduled(vthread_t thr);
/*
* Cause this thread to execute instructions until in is put to sleep
* by executing some sort of delay or wait instruction.
@ -59,6 +65,9 @@ extern void vthread_schedule_list(vthread_t thr);
/*
* $Log: vthread.h,v $
* 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.
*