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:
parent
c9f0d7e28f
commit
2bf704940b
16
vvp/logic.cc
16
vvp/logic.cc
|
|
@ -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
|
||||
* 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;
|
||||
if (net_ == 0) {
|
||||
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);
|
||||
if (net_ == 0) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
if (net_ == 0) {
|
||||
net_ = ptr.ptr();
|
||||
schedule_generic(this, 0, false);
|
||||
schedule_functor(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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) {
|
||||
net_ = port.ptr();
|
||||
schedule_generic(this, 0, false);
|
||||
schedule_functor(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
|
@ -810,8 +823,7 @@ void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
|||
cur->ptr = ptr;
|
||||
cur->base = 0;
|
||||
cur->vwid = 0;
|
||||
cur->next = schedule_init_list;
|
||||
schedule_init_list = cur;
|
||||
schedule_init_event(cur);
|
||||
}
|
||||
|
||||
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;
|
||||
cur->ptr = ptr;
|
||||
cur->val = bit;
|
||||
cur->next = schedule_init_list;
|
||||
schedule_init_list = cur;
|
||||
schedule_init_event(cur);
|
||||
}
|
||||
|
||||
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;
|
||||
cur->ptr = ptr;
|
||||
cur->val = bit;
|
||||
cur->next = schedule_init_list;
|
||||
schedule_init_list = cur;
|
||||
schedule_init_event(cur);
|
||||
}
|
||||
|
||||
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);
|
||||
cur->net = net;
|
||||
cur->next = schedule_init_list;
|
||||
schedule_init_list = cur;
|
||||
schedule_init_event(cur);
|
||||
}
|
||||
|
||||
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;
|
||||
cur->net = net;
|
||||
cur->val = bit;
|
||||
cur->next = schedule_init_list;
|
||||
schedule_init_list = cur;
|
||||
schedule_init_event(cur);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
sim_started = false;
|
||||
|
||||
schedule_time = 0;
|
||||
|
||||
if (verbose_flag) {
|
||||
|
|
@ -949,9 +974,12 @@ void schedule_simulate(void)
|
|||
|
||||
// Execute initialization events.
|
||||
while (schedule_init_list) {
|
||||
struct event_s*cur = schedule_init_list;
|
||||
schedule_init_list = cur->next;
|
||||
|
||||
struct event_s*cur = schedule_init_list->next;
|
||||
if (cur->next == cur) {
|
||||
schedule_init_list = 0;
|
||||
} else {
|
||||
schedule_init_list->next = cur->next;
|
||||
}
|
||||
cur->run_run();
|
||||
delete cur;
|
||||
}
|
||||
|
|
@ -963,6 +991,8 @@ void schedule_simulate(void)
|
|||
// Execute start of simulation callbacks
|
||||
vpiStartOfSim();
|
||||
|
||||
sim_started = true;
|
||||
|
||||
signals_capture();
|
||||
|
||||
if (verbose_flag) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __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
|
||||
* 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 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);
|
||||
|
||||
/* Use this is schedule thread deletion (after rosync). */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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,
|
||||
vvp_context_t)
|
||||
{
|
||||
schedule_generic(this, 0, false);
|
||||
schedule_functor(this);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Schedule the actual call after this finishes. */
|
||||
schedule_generic(this, 0, false);
|
||||
schedule_functor(this);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Schedule the actual call after this finishes. */
|
||||
schedule_generic(this, 0, false);
|
||||
schedule_functor(this);
|
||||
}
|
||||
|
||||
void sfunc_core::run_run()
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
if (cur_out_ != BIT4_X)
|
||||
schedule_generic(this, 0, false);
|
||||
schedule_functor(this);
|
||||
}
|
||||
|
||||
vvp_udp_fun_core::~vvp_udp_fun_core()
|
||||
|
|
@ -962,7 +962,7 @@ void vvp_udp_fun_core::recv_vec4_from_inputs(unsigned port)
|
|||
return;
|
||||
|
||||
cur_out_ = out_bit;
|
||||
schedule_generic(this, 0, false);
|
||||
schedule_functor(this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue