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

(cherry picked from commit 8234f1845d)
This commit is contained in:
Martin Whitaker 2016-06-09 21:27:20 +01:00
parent 27a46f4afe
commit 86968e3752
3 changed files with 35 additions and 8 deletions

View File

@ -949,6 +949,10 @@ extern void vpiStartOfSim();
extern void vpiPostsim(); extern void vpiPostsim();
extern void vpiNextSimTime(void); 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 * The scheduler uses this function to drain the rosync events of the
* current time. The ctim object is still in the event queue, because * current time. The ctim object is still in the event queue, because
@ -961,6 +965,7 @@ extern void vpiNextSimTime(void);
*/ */
static void run_rosync(struct event_time_s*ctim) static void run_rosync(struct event_time_s*ctim)
{ {
sim_at_rosync = true;
while (ctim->rosync) { while (ctim->rosync) {
struct event_s*cur = ctim->rosync->next; struct event_s*cur = ctim->rosync->next;
if (cur->next == cur) { if (cur->next == cur) {
@ -972,6 +977,7 @@ static void run_rosync(struct event_time_s*ctim)
cur->run_run(); cur->run_run();
delete cur; delete cur;
} }
sim_at_rosync = false;
while (ctim->del_thr) { while (ctim->del_thr) {
struct event_s*cur = ctim->del_thr->next; struct event_s*cur = ctim->del_thr->next;

View File

@ -155,6 +155,13 @@ extern void schedule_simulate(void);
*/ */
extern vvp_time64_t schedule_simtime(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 * This function is the equivalent of the $finish system task. It
* tells the simulator that simulation is done, the current thread * 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 * 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
@ -1067,13 +1067,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
vvp_time64_t dly; vvp_time64_t dly;
int scale; int scale;
if (vpi_get(vpiAutomatic, obj)) { if (vpi_get(vpiAutomatic, obj)) {
fprintf(stderr, "vpi error: cannot put a value with " fprintf(stderr, "VPI error: cannot put a value with "
"a delay on automatically allocated " "a delay on automatically allocated "
"variable '%s'\n", "variable '%s'.\n",
vpi_get_str(vpiName, obj)); vpi_get_str(vpiName, obj));
return 0; return 0;
} }
assert(when != 0); assert(when != 0);
@ -1095,6 +1095,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
break; 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; vpip_put_value_event*put = new vpip_put_value_event;
put->handle = obj; put->handle = obj;
put->value = *vp; put->value = *vp;
@ -1132,6 +1139,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
return 0; 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); obj->vpi_put_value(vp, flags);
return 0; return 0;