Make a pass at implementing cbAtEndOfSimTime.

In Icarus Verilog, AtEndOfSimTime is practically the same as
cbReadWriteSync, since the latter is after non-blocking events
in Icarus Verilog.
This commit is contained in:
Stephen Williams 2019-11-25 17:57:10 -08:00
parent b25df08c99
commit 7f95abc6ab
4 changed files with 93 additions and 16 deletions

View File

@ -495,6 +495,7 @@ typedef struct t_cb_data {
#define cbExitInteractive 22 #define cbExitInteractive 22
#define cbInteractiveScopeChange 23 #define cbInteractiveScopeChange 23
#define cbUnresolvedSystf 24 #define cbUnresolvedSystf 24
#define cbAtEndOfSimTime 31
extern vpiHandle vpi_register_cb(p_cb_data data); extern vpiHandle vpi_register_cb(p_cb_data data);
extern PLI_INT32 vpi_remove_cb(vpiHandle ref); extern PLI_INT32 vpi_remove_cb(vpiHandle ref);

View File

@ -1029,6 +1029,20 @@ void schedule_at_start_of_simtime(vvp_gen_event_t obj, vvp_time64_t delay)
schedule_event_(cur, delay, SEQ_START); schedule_event_(cur, delay, SEQ_START);
} }
/*
* In the vvp runtime of Icarus Verilog, the SEQ_RWSYNC time step is
* after all of the non-blocking assignments, so is effectively the
* same as the ReadWriteSync time.
*/
void schedule_at_end_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_RWSYNC);
}
static vvp_time64_t schedule_time; static vvp_time64_t schedule_time;
vvp_time64_t schedule_simtime(void) vvp_time64_t schedule_simtime(void)
{ return schedule_time; } { return schedule_time; }

View File

@ -148,6 +148,7 @@ extern void schedule_generic(vvp_gen_event_t obj, vvp_time64_t delay,
extern void schedule_functor(vvp_gen_event_t obj); 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);
extern void schedule_at_end_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). */
extern void schedule_del_thr(vthread_t thr); extern void schedule_del_thr(vthread_t thr);

View File

@ -357,7 +357,33 @@ static sync_callback* make_sync(p_cb_data data, bool readonly_flag)
return obj; return obj;
} }
static struct __vpiCallback* make_afterdelay(p_cb_data data, bool simtime_flag) static struct __vpiCallback* make_afterdelay(p_cb_data data)
{
sync_callback*obj = new sync_callback(data);
struct sync_cb*cb = new sync_cb;
cb->sync_flag = false;
cb->handle = obj;
obj->cb_sync = cb;
vvp_time64_t tv = 0;
switch (obj->cb_time.type) {
case vpiSimTime:
tv = vpip_timestruct_to_time(&obj->cb_time);
break;
default:
fprintf(stderr, "Unsupported time type %d.\n",
(int)obj->cb_time.type);
assert(0);
break;
}
schedule_generic(cb, tv, false);
return obj;
}
static struct __vpiCallback* make_at_start_of_sim_time(p_cb_data data)
{ {
sync_callback*obj = new sync_callback(data); sync_callback*obj = new sync_callback(data);
struct sync_cb*cb = new sync_cb; struct sync_cb*cb = new sync_cb;
@ -378,7 +404,6 @@ static struct __vpiCallback* make_afterdelay(p_cb_data data, bool simtime_flag)
break; break;
} }
if (simtime_flag) {
vvp_time64_t cur = schedule_simtime(); vvp_time64_t cur = schedule_simtime();
if (cur > tv) { if (cur > tv) {
tv = 0; tv = 0;
@ -389,10 +414,42 @@ static struct __vpiCallback* make_afterdelay(p_cb_data data, bool simtime_flag)
tv -= cur; tv -= cur;
} }
schedule_at_start_of_simtime(cb, tv); schedule_at_start_of_simtime(cb, tv);
} else {
schedule_generic(cb, tv, false); return obj;
} }
static struct __vpiCallback* make_at_end_of_sim_time(p_cb_data data)
{
sync_callback*obj = new sync_callback(data);
struct sync_cb*cb = new sync_cb;
cb->sync_flag = false;
cb->handle = obj;
obj->cb_sync = cb;
vvp_time64_t tv = 0;
switch (obj->cb_time.type) {
case vpiSimTime:
tv = vpip_timestruct_to_time(&obj->cb_time);
break;
default:
fprintf(stderr, "Unsupported time type %d.\n",
(int)obj->cb_time.type);
assert(0);
break;
}
vvp_time64_t cur = schedule_simtime();
if (cur > tv) {
tv = 0;
assert(0);
} else if (cur == tv) {
tv = 0;
} else {
tv -= cur;
}
schedule_at_end_of_simtime(cb, tv);
return obj; return obj;
} }
@ -573,11 +630,15 @@ vpiHandle vpi_register_cb(p_cb_data data)
break; break;
case cbAtStartOfSimTime: case cbAtStartOfSimTime:
obj = make_afterdelay(data, true); obj = make_at_start_of_sim_time(data);
break;
case cbAtEndOfSimTime:
obj = make_at_end_of_sim_time(data);
break; break;
case cbAfterDelay: case cbAfterDelay:
obj = make_afterdelay(data, false); obj = make_afterdelay(data);
break; break;
case cbEndOfCompile: case cbEndOfCompile: