diff --git a/vvp/logic.cc b/vvp/logic.cc index fc5e433c0..164f902ec 100644 --- a/vvp/logic.cc +++ b/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); } } diff --git a/vvp/part.cc b/vvp/part.cc index 9631b6163..11eb81293 100644 --- a/vvp/part.cc +++ b/vvp/part.cc @@ -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); } } diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 58c361a0a..237b502e9 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.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 @@ -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) { diff --git a/vvp/schedule.h b/vvp/schedule.h index da915c751..966a9ee7e 100644 --- a/vvp/schedule.h +++ b/vvp/schedule.h @@ -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). */ diff --git a/vvp/sfunc.cc b/vvp/sfunc.cc index 3ef1e4540..77650e8b6 100644 --- a/vvp/sfunc.cc +++ b/vvp/sfunc.cc @@ -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() diff --git a/vvp/udp.cc b/vvp/udp.cc index 4b38b349d..4d33b07e6 100644 --- a/vvp/udp.cc +++ b/vvp/udp.cc @@ -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); }