From dda197e39bd43d4a144481f02fb5a4451bd40867 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 6 Jan 2010 18:43:53 -0800 Subject: [PATCH 1/2] Rework the scope thread list to use a std::set The scope contains the threads running within. The rework of this patch allows all threads to know their scope, and cleans up the handling of threads listed in the scope. --- vvp/vpi_priv.h | 4 +++- vvp/vpi_scope.cc | 1 - vvp/vthread.cc | 60 +++++++++++------------------------------------- 3 files changed, 16 insertions(+), 49 deletions(-) diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 7a9737029..325e550fe 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -23,6 +23,8 @@ # include "vvp_net.h" # include "config.h" +# include + /* * Added to use some "vvp_fun_modpath_src" * and "vvp_fun_modpath" classes definitions @@ -204,7 +206,7 @@ struct __vpiScope { /* Keep a list of freed contexts. */ vvp_context_t free_contexts; /* Keep a list of threads in the scope. */ - vthread_t threads; + std::set threads; signed int time_units :8; signed int time_precision :8; }; diff --git a/vvp/vpi_scope.cc b/vvp/vpi_scope.cc index 34dfb9dda..7fc0281a7 100644 --- a/vvp/vpi_scope.cc +++ b/vvp/vpi_scope.cc @@ -447,7 +447,6 @@ compile_scope_decl(char*label, char*type, char*name, char*tname, scope->nitem = 0; scope->live_contexts = 0; scope->free_contexts = 0; - scope->threads = 0; current_scope = scope; diff --git a/vvp/vthread.cc b/vvp/vthread.cc index b98890557..b9ac926df 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -116,17 +116,12 @@ struct vthread_s { unsigned fork_count :8; /* This points to the sole child of the thread. */ struct vthread_s*child; - union { - /* This points to my parent, if I have one. */ - struct vthread_s*parent; - /* If this is a header cell, then point to the - containing scope. */ - struct __vpiScope*parent_scope; - }; + /* This points to my parent, if I have one. */ + struct vthread_s*parent; + /* This points to the containing scope. */ + struct __vpiScope*parent_scope; /* This is used for keeping wait queues. */ struct vthread_s*wait_next; - /* These are used to keep the thread in a scope. */ - struct vthread_s*scope_next, *scope_prev; /* These are used to access automatically allocated items. */ vvp_context_t wt_context, rd_context; /* These are used to pass non-blocking event control information. */ @@ -136,10 +131,6 @@ struct vthread_s { struct __vpiScope* vthread_scope(struct vthread_s*thr) { - while (thr->bits4.size() > 0) { - thr = thr->scope_next; - } - return thr->parent_scope; } @@ -413,31 +404,11 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope) thr->bits4 = vvp_vector4_t(32); thr->child = 0; thr->parent = 0; + thr->parent_scope = scope; thr->wait_next = 0; thr->wt_context = 0; thr->rd_context = 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 = codespace_null(); - scope->threads->bits4 = vvp_vector4_t(); - scope->threads->child = 0; - scope->threads->parent = 0; - scope->threads->parent_scope = scope; - 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->is_scheduled = 0; thr->i_have_ended = 0; @@ -452,6 +423,7 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope) thr_put_bit(thr, 2, BIT4_X); thr_put_bit(thr, 3, BIT4_Z); + scope->threads .insert(thr); return thr; } @@ -518,8 +490,8 @@ static void vthread_reap(vthread_t thr) thr->child = 0; thr->parent = 0; - thr->scope_next->scope_prev = thr->scope_prev; - thr->scope_prev->scope_next = thr->scope_next; + // Remove myself from the containing scope. + thr->parent_scope->threads.erase(thr); thr->pc = codespace_null(); @@ -1955,8 +1927,7 @@ static bool do_disable(vthread_t thr, vthread_t match) bool flag = false; /* Pull the target thread out of its scope. */ - thr->scope_next->scope_prev = thr->scope_prev; - thr->scope_prev->scope_next = thr->scope_next; + thr->parent_scope->threads.erase(thr); /* Turn the thread off by setting is program counter to zero and setting an OFF bit. */ @@ -2011,23 +1982,18 @@ static bool do_disable(vthread_t thr, vthread_t match) 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; bool disabled_myself_flag = false; - while (head->scope_next != head) { - vthread_t tmp = head->scope_next; + while (scope->threads.size() > 0) { + set::iterator cur = scope->threads.begin(); /* If I am disabling myself, that remember that fact so that I can finish this statement differently. */ - if (tmp == thr) + if (*cur == thr) disabled_myself_flag = true; - - if (do_disable(tmp, thr)) + if (do_disable(*cur, thr)) disabled_myself_flag = true; } From 5533252cc14c5a1371be2c9be74d120d6ed6f234 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 6 Jan 2010 21:40:26 -0800 Subject: [PATCH 2/2] Add generic single-step-display for vvp_gen_event_s objects. This gives a little bit more specificity to the event step display. --- vvp/schedule.cc | 17 +++++++++++++++++ vvp/schedule.h | 1 + 2 files changed, 18 insertions(+) diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 4d9d87941..a3eb41cc7 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -94,6 +94,11 @@ vvp_gen_event_s::~vvp_gen_event_s() { } +void vvp_gen_event_s::single_step_display(void) +{ + cerr << "vvp_gen_event_s: Step into event " << typeid(*this).name() << endl; +} + /* * Derived event types */ @@ -326,6 +331,7 @@ struct propagate_vector4_event_s : public event_s { vvp_vector4_t val; /* Action */ void run_run(void); + void single_step_display(void); }; void propagate_vector4_event_s::run_run(void) @@ -333,6 +339,11 @@ void propagate_vector4_event_s::run_run(void) net->send_vec4(val, 0); } +void propagate_vector4_event_s::single_step_display(void) +{ + cerr << "propagate_vector4_event: Propagate val=" << val << endl; +} + struct assign_array_r_word_s : public event_s { vvp_array_t mem; unsigned adr; @@ -368,6 +379,7 @@ struct generic_event_s : public event_s { vvp_gen_event_t obj; bool delete_obj_when_done; void run_run(void); + void single_step_display(void); static void* operator new(size_t); static void operator delete(void*); @@ -383,6 +395,11 @@ void generic_event_s::run_run(void) } } +void generic_event_s::single_step_display(void) +{ + obj->single_step_display(); +} + static const size_t GENERIC_CHUNK_COUNT = 131072 / sizeof(struct generic_event_s); static slab_t generic_event_heap; diff --git a/vvp/schedule.h b/vvp/schedule.h index ce1edc494..5393e3417 100644 --- a/vvp/schedule.h +++ b/vvp/schedule.h @@ -125,6 +125,7 @@ struct vvp_gen_event_s { virtual ~vvp_gen_event_s() =0; virtual void run_run() =0; + virtual void single_step_display(void); }; /*