Fix for GitHub issue #106 - prevent VPI writes during read-only synch.

This commit is contained in:
Martin Whitaker 2016-06-09 21:27:20 +01:00
parent 332170d36b
commit 8234f1845d
3 changed files with 35 additions and 8 deletions

View File

@ -1038,6 +1038,10 @@ extern void vpiStartOfSim();
extern void vpiPostsim();
extern void vpiNextSimTime(void);
static bool sim_at_rosync = false;
bool schedule_at_rosync(void)
{ return sim_at_rosync; }
/*
* The scheduler uses this function to drain the rosync events of the
* current time. The ctim object is still in the event queue, because
@ -1050,6 +1054,7 @@ extern void vpiNextSimTime(void);
*/
static void run_rosync(struct event_time_s*ctim)
{
sim_at_rosync = true;
while (ctim->rosync) {
struct event_s*cur = ctim->rosync->next;
if (cur->next == cur) {
@ -1061,6 +1066,7 @@ static void run_rosync(struct event_time_s*ctim)
cur->run_run();
delete cur;
}
sim_at_rosync = false;
while (ctim->del_thr) {
struct event_s*cur = ctim->del_thr->next;

View File

@ -164,6 +164,13 @@ extern void schedule_simulate(void);
*/
extern vvp_time64_t schedule_simtime(void);
/*
* Indicate that the simulator is running the rosync callbacks. This is
* used to prevent the callbacks from performing any write operations
* in the current simulation time slot.
*/
extern bool schedule_at_rosync(void);
/*
* This function is the equivalent of the $finish system task. It
* tells the simulator that simulation is done, the current thread

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2016 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
@ -1067,13 +1067,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
vvp_time64_t dly;
int scale;
if (vpi_get(vpiAutomatic, obj)) {
fprintf(stderr, "vpi error: cannot put a value with "
"a delay on automatically allocated "
"variable '%s'\n",
vpi_get_str(vpiName, obj));
return 0;
}
if (vpi_get(vpiAutomatic, obj)) {
fprintf(stderr, "VPI error: cannot put a value with "
"a delay on automatically allocated "
"variable '%s'.\n",
vpi_get_str(vpiName, obj));
return 0;
}
assert(when != 0);
@ -1095,6 +1095,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
break;
}
if ((dly == 0) && schedule_at_rosync()) {
fprintf(stderr, "VPI error: attempted to put a value to "
"variable '%s' during a read-only synch "
"callback.\n", vpi_get_str(vpiName, obj));
return 0;
}
vpip_put_value_event*put = new vpip_put_value_event;
put->handle = obj;
put->value = *vp;
@ -1132,6 +1139,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
return 0;
}
if (schedule_at_rosync()) {
fprintf(stderr, "VPI error: attempted to put a value to "
"variable '%s' during a read-only synch "
"callback.\n", vpi_get_str(vpiName, obj));
return 0;
}
obj->vpi_put_value(vp, flags);
return 0;