Fix for initial value propagation (part 2).

To ensure the initial propagation of 'x' values at time-0 does not
trigger any events, the propagation of these values needs to be
completed before any statements that wait on events are executed.
vvp has a pre-simulation event queue to handle this, but some
functors defeat this by postponing their output propagation using
the stratified event queue. This patch fixes this by using the
pre-simulation event queue to schedule functor output propagation
until initial value propagation is complete.
This commit is contained in:
Martin Whitaker 2010-04-08 12:13:35 +01:00 committed by Stephen Williams
parent c9f0d7e28f
commit 2bf704940b
6 changed files with 70 additions and 31 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -52,7 +52,7 @@ void vvp_fun_boolean_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
input_[port] = bit; input_[port] = bit;
if (net_ == 0) { if (net_ == 0) {
net_ = ptr.ptr(); net_ = ptr.ptr();
schedule_generic(this, 0, false); schedule_functor(this);
} }
} }
@ -71,7 +71,7 @@ void vvp_fun_boolean_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
input_[port] .set_vec(base, bit); input_[port] .set_vec(base, bit);
if (net_ == 0) { if (net_ == 0) {
net_ = ptr.ptr(); net_ = ptr.ptr();
schedule_generic(this, 0, false); schedule_functor(this);
} }
} }
@ -138,7 +138,7 @@ void vvp_fun_buf::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
if (net_ == 0) { if (net_ == 0) {
net_ = ptr.ptr(); net_ = ptr.ptr();
schedule_generic(this, 0, false); schedule_functor(this);
} }
} }
@ -229,7 +229,7 @@ void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
if (net_ == 0) { if (net_ == 0) {
net_ = ptr.ptr(); net_ = ptr.ptr();
schedule_generic(this, 0, false); schedule_functor(this);
} }
} }
@ -256,7 +256,7 @@ void vvp_fun_muxr::recv_real(vvp_net_ptr_t ptr, double bit,
if (net_ == 0) { if (net_ == 0) {
net_ = ptr.ptr(); net_ = ptr.ptr();
schedule_generic(this, 0, false); schedule_functor(this);
} }
} }
@ -335,7 +335,7 @@ void vvp_fun_muxz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
if (net_ == 0) { if (net_ == 0) {
net_ = ptr.ptr(); net_ = ptr.ptr();
schedule_generic(this, 0, false); schedule_functor(this);
} }
} }
@ -405,7 +405,7 @@ void vvp_fun_not::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
input_ = bit; input_ = bit;
if (net_ == 0) { if (net_ == 0) {
net_ = ptr.ptr(); net_ = ptr.ptr();
schedule_generic(this, 0, false); schedule_functor(this);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2004-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -70,7 +70,7 @@ void vvp_fun_part_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
if (net_ == 0) { if (net_ == 0) {
net_ = port.ptr(); net_ = port.ptr();
schedule_generic(this, 0, false); schedule_functor(this);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -534,6 +534,19 @@ static void signals_revert(void)
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
} }
/*
* This function puts an event on the end of the pre-simulation event queue.
*/
static void schedule_init_event(struct event_s*cur)
{
if (schedule_init_list == 0) {
cur->next = cur;
} else {
cur->next = schedule_init_list->next;
schedule_init_list->next = cur;
}
schedule_init_list = cur;
}
/* /*
* This function does all the hard work of putting an event into the * This function does all the hard work of putting an event into the
@ -810,8 +823,7 @@ void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector4_t bit)
cur->ptr = ptr; cur->ptr = ptr;
cur->base = 0; cur->base = 0;
cur->vwid = 0; cur->vwid = 0;
cur->next = schedule_init_list; schedule_init_event(cur);
schedule_init_list = cur;
} }
void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector8_t bit) void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector8_t bit)
@ -819,8 +831,7 @@ void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector8_t bit)
struct assign_vector8_event_s*cur = new struct assign_vector8_event_s; struct assign_vector8_event_s*cur = new struct assign_vector8_event_s;
cur->ptr = ptr; cur->ptr = ptr;
cur->val = bit; cur->val = bit;
cur->next = schedule_init_list; schedule_init_event(cur);
schedule_init_list = cur;
} }
void schedule_init_vector(vvp_net_ptr_t ptr, double bit) void schedule_init_vector(vvp_net_ptr_t ptr, double bit)
@ -828,16 +839,14 @@ void schedule_init_vector(vvp_net_ptr_t ptr, double bit)
struct assign_real_event_s*cur = new struct assign_real_event_s; struct assign_real_event_s*cur = new struct assign_real_event_s;
cur->ptr = ptr; cur->ptr = ptr;
cur->val = bit; cur->val = bit;
cur->next = schedule_init_list; schedule_init_event(cur);
schedule_init_list = cur;
} }
void schedule_init_propagate(vvp_net_t*net, vvp_vector4_t bit) void schedule_init_propagate(vvp_net_t*net, vvp_vector4_t bit)
{ {
struct propagate_vector4_event_s*cur = new struct propagate_vector4_event_s(bit); struct propagate_vector4_event_s*cur = new struct propagate_vector4_event_s(bit);
cur->net = net; cur->net = net;
cur->next = schedule_init_list; schedule_init_event(cur);
schedule_init_list = cur;
} }
void schedule_init_propagate(vvp_net_t*net, double bit) void schedule_init_propagate(vvp_net_t*net, double bit)
@ -845,8 +854,7 @@ void schedule_init_propagate(vvp_net_t*net, double bit)
struct propagate_real_event_s*cur = new struct propagate_real_event_s; struct propagate_real_event_s*cur = new struct propagate_real_event_s;
cur->net = net; cur->net = net;
cur->val = bit; cur->val = bit;
cur->next = schedule_init_list; schedule_init_event(cur);
schedule_init_list = cur;
} }
void schedule_del_thr(vthread_t thr) void schedule_del_thr(vthread_t thr)
@ -872,6 +880,21 @@ void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay,
vthread_delay_delete(); vthread_delay_delete();
} }
static bool sim_started;
void schedule_functor(vvp_gen_event_t obj)
{
struct generic_event_s*cur = new generic_event_s;
cur->obj = obj;
cur->delete_obj_when_done = false;
if (!sim_started) {
schedule_init_event(cur);
} else {
schedule_event_(cur, 0, SEQ_ACTIVE);
}
}
void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay) void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay)
{ {
struct generic_event_s*cur = new generic_event_s; struct generic_event_s*cur = new generic_event_s;
@ -934,6 +957,8 @@ static void run_rosync(struct event_time_s*ctim)
void schedule_simulate(void) void schedule_simulate(void)
{ {
sim_started = false;
schedule_time = 0; schedule_time = 0;
if (verbose_flag) { if (verbose_flag) {
@ -949,9 +974,12 @@ void schedule_simulate(void)
// Execute initialization events. // Execute initialization events.
while (schedule_init_list) { while (schedule_init_list) {
struct event_s*cur = schedule_init_list; struct event_s*cur = schedule_init_list->next;
schedule_init_list = cur->next; if (cur->next == cur) {
schedule_init_list = 0;
} else {
schedule_init_list->next = cur->next;
}
cur->run_run(); cur->run_run();
delete cur; delete cur;
} }
@ -963,6 +991,8 @@ void schedule_simulate(void)
// Execute start of simulation callbacks // Execute start of simulation callbacks
vpiStartOfSim(); vpiStartOfSim();
sim_started = true;
signals_capture(); signals_capture();
if (verbose_flag) { if (verbose_flag) {

View File

@ -1,7 +1,7 @@
#ifndef __schedule_H #ifndef __schedule_H
#define __schedule_H #define __schedule_H
/* /*
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -123,6 +123,15 @@ extern void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay,
bool sync_flag, bool ro_flag =true, bool sync_flag, bool ro_flag =true,
bool delete_obj_when_done =false); bool delete_obj_when_done =false);
/* Create a functor output event. This is placed in the pre-simulation
* event queue if the scheduler is still processing pre-simulation
* events, otherwise it is placed in the stratified event queue as an
* ACTIVE event with a delay of 0. It is up to the user to allocate/free
* the vvp_get_event_s object. The object is never referenced by the
* scheduler after the run method is called.
*/
extern void schedule_functor(vvp_gen_event_t obj);
extern void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay); extern void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay);
/* Use this is schedule thread deletion (after rosync). */ /* Use this is schedule thread deletion (after rosync). */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2006-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -59,7 +59,7 @@ sfunc_core::~sfunc_core()
void sfunc_core::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, void sfunc_core::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t) vvp_context_t)
{ {
schedule_generic(this, 0, false); schedule_functor(this);
} }
void sfunc_core::recv_vec4_from_inputs(unsigned port) void sfunc_core::recv_vec4_from_inputs(unsigned port)
@ -73,7 +73,7 @@ void sfunc_core::recv_vec4_from_inputs(unsigned port)
obj->bits = value(port); obj->bits = value(port);
/* Schedule the actual call after this finishes. */ /* Schedule the actual call after this finishes. */
schedule_generic(this, 0, false); schedule_functor(this);
} }
void sfunc_core::recv_real_from_inputs(unsigned port) void sfunc_core::recv_real_from_inputs(unsigned port)
@ -87,7 +87,7 @@ void sfunc_core::recv_real_from_inputs(unsigned port)
obj->value = value_r(port); obj->value = value_r(port);
/* Schedule the actual call after this finishes. */ /* Schedule the actual call after this finishes. */
schedule_generic(this, 0, false); schedule_functor(this);
} }
void sfunc_core::run_run() void sfunc_core::run_run()

View File

@ -911,7 +911,7 @@ vvp_udp_fun_core::vvp_udp_fun_core(vvp_net_t*net, vvp_udp_s*def)
current_.maskx = ~ ((-1UL) << port_count()); current_.maskx = ~ ((-1UL) << port_count());
if (cur_out_ != BIT4_X) if (cur_out_ != BIT4_X)
schedule_generic(this, 0, false); schedule_functor(this);
} }
vvp_udp_fun_core::~vvp_udp_fun_core() vvp_udp_fun_core::~vvp_udp_fun_core()
@ -962,7 +962,7 @@ void vvp_udp_fun_core::recv_vec4_from_inputs(unsigned port)
return; return;
cur_out_ = out_bit; cur_out_ = out_bit;
schedule_generic(this, 0, false); schedule_functor(this);
} }