Skip to content

Commit

Permalink
Schedule wait lists of threads as a single event,
Browse files Browse the repository at this point in the history
 to save on events. Also, improve efficiency of
 event_s allocation. Add some event statistics to
 get an idea where performance is really going.
  • Loading branch information
steve committed Jan 6, 2003
1 parent dedae73 commit aa3a6db
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 56 deletions.
10 changes: 8 additions & 2 deletions vvp/event.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: event.cc,v 1.10 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: event.cc,v 1.11 2003/01/06 23:57:26 steve Exp $"
#endif

# include "event.h"
Expand Down Expand Up @@ -80,7 +80,7 @@ void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned)
vthread_t tmp = threads;
threads = 0;
vthread_schedule_list(tmp);

if (out) {
functor_set(out, 0, St0, true);
}
Expand Down Expand Up @@ -189,6 +189,12 @@ void compile_named_event(char*label, char*name)

/*
* $Log: event.cc,v $
* Revision 1.11 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.10 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
Expand Down
19 changes: 18 additions & 1 deletion vvp/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.31 2002/09/18 03:34:07 steve Exp $"
#ident "$Id: main.cc,v 1.32 2003/01/06 23:57:26 steve Exp $"
#endif

# include "config.h"
Expand Down Expand Up @@ -273,13 +273,30 @@ int main(int argc, char*argv[])
print_rusage(stderr, cycles+2, cycles+1);
if (logfile && logfile != stderr)
print_rusage(logfile, cycles+2, cycles+1);

fprintf(stderr, "Event counts: (event pool = %lu)\n",
count_event_pool);
fprintf(stderr, " %8lu thread schedule events\n",
count_thread_events);
fprintf(stderr, " %8lu propagation events\n",
count_prop_events);
fprintf(stderr, " %8lu assign events\n",
count_assign_events);
fprintf(stderr, " %8lu other events\n",
count_gen_events);
}

return 0;
}

/*
* $Log: main.cc,v $
* Revision 1.32 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.31 2002/09/18 03:34:07 steve
* printf size warning.
*
Expand Down
82 changes: 55 additions & 27 deletions vvp/schedule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: schedule.cc,v 1.20 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: schedule.cc,v 1.21 2003/01/06 23:57:26 steve Exp $"
#endif

# include "schedule.h"
Expand All @@ -31,6 +31,13 @@
# include <assert.h>

# include <stdio.h>

unsigned long count_assign_events = 0;
unsigned long count_gen_events = 0;
unsigned long count_prop_events = 0;
unsigned long count_thread_events = 0;
unsigned long count_event_pool = 0;

/*
* The event queue is arranged as a skip list, with the simulation
* time the key to the list. The simulation time is stored in each
Expand Down Expand Up @@ -60,6 +67,9 @@ struct event_s {

struct event_s*next;
struct event_s*last;

void* operator new (size_t);
void operator delete(void*obj, size_t s);
};
const unsigned TYPE_GEN = 0;
const unsigned TYPE_THREAD = 1;
Expand All @@ -72,27 +82,35 @@ const unsigned TYPE_ASSIGN = 3;
*/

static struct event_s* free_list = 0;
static const unsigned CHUNK_COUNT = 8192 / sizeof(struct event_s);

inline static struct event_s* e_alloc()
inline void* event_s::operator new (size_t size)
{
struct event_s* cur = free_list;
if (!cur)
{
cur = (struct event_s*) malloc(sizeof(struct event_s));
// cur = (struct event_s*) calloc(1, sizeof(struct event_s));
}
else
{
free_list = cur->next;
// memset(cur, 0, sizeof(struct event_s));
}
return cur;
assert(size == sizeof(struct event_s));

struct event_s* cur = free_list;
if (!cur) {
cur = (struct event_s*)
malloc(CHUNK_COUNT * sizeof(struct event_s));
for (unsigned idx = 1 ; idx < CHUNK_COUNT ; idx += 1) {
cur[idx].next = free_list;
free_list = cur + idx;
}

count_event_pool += CHUNK_COUNT;

} else {
free_list = cur->next;
}

return cur;
}

inline static void e_free(struct event_s* cur)
inline void event_s::operator delete(void*obj, size_t size)
{
cur->next = free_list;
free_list = cur;
struct event_s*cur = reinterpret_cast<event_s*>(obj);
cur->next = free_list;
free_list = cur;
}

/*
Expand Down Expand Up @@ -246,7 +264,7 @@ static struct event_s* pull_sync_event(void)

void schedule_vthread(vthread_t thr, unsigned delay, bool push_flag)
{
struct event_s*cur = e_alloc();
struct event_s*cur = new event_s;

cur->delay = delay;
cur->thr = thr;
Expand All @@ -267,7 +285,7 @@ void schedule_vthread(vthread_t thr, unsigned delay, bool push_flag)

void functor_s::schedule(unsigned delay)
{
struct event_s*cur = e_alloc();
struct event_s*cur = new event_s;

cur->delay = delay;
cur->funp = this;
Expand All @@ -280,7 +298,7 @@ void functor_s::schedule(unsigned delay)

void schedule_assign(vvp_ipoint_t fun, unsigned char val, unsigned delay)
{
struct event_s*cur = e_alloc();
struct event_s*cur = new event_s;

cur->delay = delay;
cur->fun = fun;
Expand All @@ -292,7 +310,7 @@ void schedule_assign(vvp_ipoint_t fun, unsigned char val, unsigned delay)

void schedule_generic(vvp_gen_event_t obj, unsigned char val, unsigned delay)
{
struct event_s*cur = e_alloc();
struct event_s*cur = new event_s;

cur->delay = delay;
cur->obj = obj;
Expand Down Expand Up @@ -339,7 +357,7 @@ void schedule_simulate(void)
assert(sync_cur->obj->sync_flag);
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
}
e_free(sync_cur);
delete sync_cur;
}


Expand All @@ -349,17 +367,20 @@ void schedule_simulate(void)

switch (cur->type) {
case TYPE_THREAD:
count_thread_events += 1;
vthread_run(cur->thr);
e_free(cur);
delete cur;
break;

case TYPE_PROP:
//printf("Propagate %p\n", cur->fun);
count_prop_events += 1;
cur->funp->propagate(false);
e_free(cur);
delete(cur);
break;

case TYPE_ASSIGN:
count_assign_events += 1;
switch (cur->val) {
case 0:
functor_set(cur->fun, cur->val, St0, false);
Expand All @@ -374,14 +395,15 @@ void schedule_simulate(void)
functor_set(cur->fun, cur->val, HiZ, false);
break;
}
e_free(cur);
delete(cur);
break;

case TYPE_GEN:
count_gen_events += 1;
if (cur->obj && cur->obj->run) {
if (cur->obj->sync_flag == false) {
cur->obj->run(cur->obj, cur->val);
e_free(cur);
delete (cur);

} else {
postpone_sync_event(cur);
Expand All @@ -405,7 +427,7 @@ void schedule_simulate(void)
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
}

e_free(sync_cur);
delete (sync_cur);
}


Expand All @@ -415,6 +437,12 @@ void schedule_simulate(void)

/*
* $Log: schedule.cc,v $
* Revision 1.21 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.20 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
Expand Down
16 changes: 15 additions & 1 deletion vvp/schedule.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: schedule.h,v 1.11 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: schedule.h,v 1.12 2003/01/06 23:57:26 steve Exp $"
#endif

# include "vthread.h"
Expand Down Expand Up @@ -90,9 +90,23 @@ extern vvp_time64_t schedule_simtime(void);
extern void schedule_finish(int rc);
extern bool schedule_finished(void);

/*
* These are event counters for the sake of performance measurements.
*/
extern unsigned long count_assign_events;
extern unsigned long count_gen_events;
extern unsigned long count_prop_events;
extern unsigned long count_thread_events;
extern unsigned long count_event_pool;

/*
* $Log: schedule.h,v $
* Revision 1.12 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.11 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
Expand Down
65 changes: 40 additions & 25 deletions vvp/vthread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.95 2002/11/22 00:01:50 steve Exp $"
#ident "$Id: vthread.cc,v 1.96 2003/01/06 23:57:26 steve Exp $"
#endif

# include "vthread.h"
Expand Down Expand Up @@ -290,32 +290,43 @@ static void vthread_reap(vthread_t thr)

void vthread_mark_scheduled(vthread_t thr)
{
assert(thr->is_scheduled == 0);
thr->is_scheduled = 1;
while (thr != 0) {
assert(thr->is_scheduled == 0);
thr->is_scheduled = 1;
thr = thr->wait_next;
}
}

/*
* This function runs a thread by fetching an instruction,
* incrementing the PC, and executing the instruction.
* This function runs each thread by fetching an instruction,
* incrementing the PC, and executing the instruction. The thread may
* be the head of a list, so each thread is run so far as possible.
*/
void vthread_run(vthread_t thr)
{
assert(thr->is_scheduled);
thr->is_scheduled = 0;
while (thr != 0) {
vthread_t tmp = thr->wait_next;
thr->wait_next = 0;

for (;;) {
vvp_code_t cp = codespace_index(thr->pc);
thr->pc += 1;
assert(thr->is_scheduled);
thr->is_scheduled = 0;

assert(cp);
assert(cp->opcode);
for (;;) {
vvp_code_t cp = codespace_index(thr->pc);
thr->pc += 1;

/* Run the opcode implementation. If the execution of
the opcode returns false, then the thread is meant to
be paused, so break out of the loop. */
bool rc = (cp->opcode)(thr, cp);
if (rc == false)
return;
assert(cp);
assert(cp->opcode);

/* Run the opcode implementation. If the execution of
the opcode returns false, then the thread is meant to
be paused, so break out of the loop. */
bool rc = (cp->opcode)(thr, cp);
if (rc == false)
break;
}

thr = tmp;
}
}

Expand All @@ -326,14 +337,12 @@ void vthread_run(vthread_t thr)
*/
void vthread_schedule_list(vthread_t thr)
{
while (thr) {
vthread_t tmp = thr;
thr = thr->wait_next;
assert(tmp->waiting_for_event);
tmp->waiting_for_event = 0;
tmp->wait_next = 0;
schedule_vthread(tmp, 0);
for (vthread_t cur = thr ; cur ; cur = cur->wait_next) {
assert(cur->waiting_for_event);
cur->waiting_for_event = 0;
}

schedule_vthread(thr, 0);
}


Expand Down Expand Up @@ -2496,6 +2505,12 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)

/*
* $Log: vthread.cc,v $
* Revision 1.96 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.95 2002/11/22 00:01:50 steve
* Careful of left operands to shift that are constant.
*
Expand Down

0 comments on commit aa3a6db

Please sign in to comment.