Implement cbAtStartOfSimTime callback.

(cherry picked from commit 1b7a42ffcd)
This commit is contained in:
Stephen Williams 2009-11-01 09:26:09 -08:00
parent 70f15b472f
commit 23ea74a126
3 changed files with 70 additions and 31 deletions

View File

@ -56,9 +56,18 @@ struct event_s {
};
struct event_time_s {
event_time_s() { count_time_events += 1; }
event_time_s() {
count_time_events += 1;
start = 0;
active = 0;
nbassign = 0;
rwsync = 0;
rosync = 0;
del_thr = 0;
}
vvp_time64_t delay;
struct event_s*start;
struct event_s*active;
struct event_s*nbassign;
struct event_s*rwsync;
@ -383,8 +392,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,
DEL_THREAD } event_queue_t;
typedef enum event_queue_e { SEQ_START, 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)
@ -397,11 +406,6 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
/* Is the event_time list completely empty? Create the
first event_time object. */
ctim = new struct event_time_s;
ctim->active = 0;
ctim->nbassign = 0;
ctim->rwsync = 0;
ctim->rosync = 0;
ctim->del_thr = 0;
ctim->delay = delay;
ctim->next = 0;
sched_list = ctim;
@ -411,11 +415,6 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
/* Am I looking for an event before the first event_time?
If so, create a new event_time to go in front. */
struct event_time_s*tmp = new struct event_time_s;
tmp->active = 0;
tmp->nbassign = 0;
tmp->rwsync = 0;
tmp->rosync = 0;
tmp->del_thr = 0;
tmp->delay = delay;
tmp->next = ctim;
ctim->delay -= delay;
@ -433,11 +432,6 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
if (ctim->delay > delay) {
struct event_time_s*tmp = new struct event_time_s;
tmp->active = 0;
tmp->nbassign = 0;
tmp->rwsync = 0;
tmp->rosync = 0;
tmp->del_thr = 0;
tmp->delay = delay;
tmp->next = prev->next;
prev->next = tmp;
@ -450,11 +444,6 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
} else {
assert(ctim->next == 0);
struct event_time_s*tmp = new struct event_time_s;
tmp->active = 0;
tmp->nbassign = 0;
tmp->rwsync = 0;
tmp->rosync = 0;
tmp->del_thr = 0;
tmp->delay = delay - ctim->delay;
tmp->next = 0;
ctim->next = tmp;
@ -469,6 +458,16 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
switch (select_queue) {
case SEQ_START:
if (ctim->start == 0) {
ctim->start = cur;
} else {
cur->next = ctim->active->next;
ctim->active->next = cur;
ctim->active = cur;
}
break;
case SEQ_ACTIVE:
if (ctim->active == 0) {
ctim->active = cur;
@ -550,7 +549,6 @@ static void schedule_event_push_(struct event_s*cur)
ctim->active->next = cur;
}
void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag)
{
struct vthread_event_s*cur = new vthread_event_s;
@ -673,6 +671,15 @@ void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay,
sync_flag? (ro_flag?SEQ_ROSYNC:SEQ_RWSYNC) : SEQ_ACTIVE);
}
void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay)
{
struct generic_event_s*cur = new generic_event_s;
cur->obj = obj;
cur->delete_obj_when_done = false;
schedule_event_(cur, delay, SEQ_START);
}
static vvp_time64_t schedule_time;
vvp_time64_t schedule_simtime(void)
{ return schedule_time; }
@ -767,6 +774,17 @@ void schedule_simulate(void)
ctim->delay = 0;
vpiNextSimTime();
// Process the cbAtStartOfSimTime callbacks.
while (ctim->start) {
struct event_s*cur = ctim->start->next;
if (cur->next == cur) {
ctim->start = 0;
} else {
ctim->start->next = cur->next;
}
cur->run_run();
delete (cur);
}
}

View File

@ -103,6 +103,8 @@ extern void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay,
bool sync_flag, bool ro_flag =true,
bool delete_obj_when_done =false);
extern void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay);
/* Use this is schedule thread deletion (after rosync). */
extern void schedule_del_thr(vthread_t thr);

View File

@ -266,7 +266,7 @@ static struct __vpiCallback* make_sync(p_cb_data data, bool readonly_flag)
return obj;
}
static struct __vpiCallback* make_afterdelay(p_cb_data data)
static struct __vpiCallback* make_afterdelay(p_cb_data data, bool simtime_flag)
{
struct __vpiCallback*obj = new_vpi_callback();
obj->cb_data = *data;
@ -281,19 +281,34 @@ static struct __vpiCallback* make_afterdelay(p_cb_data data)
cb->handle = obj;
obj->cb_sync = cb;
vvp_time64_t tv;
switch (obj->cb_time.type) {
case vpiSimTime: {
vvp_time64_t tv = vpip_timestruct_to_time(&obj->cb_time);
schedule_generic(cb, tv, false);
break;
}
case vpiSimTime:
tv = vpip_timestruct_to_time(&obj->cb_time);
break;
default:
fprintf(stderr, "Unsupported time type %d.\n", obj->cb_time.type);
assert(0);
tv = 0;
break;
}
if (simtime_flag) {
vvp_time64_t cur = schedule_simtime();
if (cur > tv) {
tv = 0;
assert(0);
} else if (cur == tv) {
tv = 0;
} else {
tv -= cur;
}
schedule_at_start_of_simtime(cb, tv);
} else {
schedule_generic(cb, tv, false);
}
return obj;
}
@ -432,8 +447,12 @@ vpiHandle vpi_register_cb(p_cb_data data)
obj = make_sync(data, false);
break;
case cbAtStartOfSimTime:
obj = make_afterdelay(data, true);
break;
case cbAfterDelay:
obj = make_afterdelay(data);
obj = make_afterdelay(data, false);
break;
case cbEndOfCompile: