Add support for REadOnlySync and monitors.
This commit is contained in:
parent
13ef84bc35
commit
da828a218f
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: arith.cc,v 1.9 2001/07/07 02:57:33 steve Exp $"
|
||||
#ident "$Id: arith.cc,v 1.10 2001/07/11 02:27:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
|
|
@ -110,8 +110,6 @@ vvp_arith_sum::~vvp_arith_sum()
|
|||
|
||||
void vvp_arith_sum::set(vvp_ipoint_t i, functor_t f, bool push)
|
||||
{
|
||||
assert(wid_ <= 8*sizeof(unsigned long));
|
||||
|
||||
unsigned page = 0;
|
||||
unsigned pbit = 0;
|
||||
unsigned long carry = 0;
|
||||
|
|
@ -468,6 +466,9 @@ void vvp_shiftr::set(vvp_ipoint_t i, functor_t f, bool push)
|
|||
|
||||
/*
|
||||
* $Log: arith.cc,v $
|
||||
* Revision 1.10 2001/07/11 02:27:21 steve
|
||||
* Add support for REadOnlySync and monitors.
|
||||
*
|
||||
* Revision 1.9 2001/07/07 02:57:33 steve
|
||||
* Add the .shift/r functor.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: memory.cc,v 1.4 2001/06/15 03:28:31 steve Exp $"
|
||||
#ident "$Id: memory.cc,v 1.5 2001/07/11 02:27:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "memory.h"
|
||||
|
|
@ -437,6 +437,8 @@ inline static struct mem_assign_s* ma_alloc()
|
|||
cur = (struct mem_assign_s*) malloc(sizeof(struct mem_assign_s));
|
||||
else
|
||||
ma_free_list = cur->next;
|
||||
|
||||
cur->sync_flag = false;
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
|
|
|||
112
vvp/schedule.cc
112
vvp/schedule.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: schedule.cc,v 1.10 2001/05/30 03:02:35 steve Exp $"
|
||||
#ident "$Id: schedule.cc,v 1.11 2001/07/11 02:27:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "schedule.h"
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
# include <malloc.h>
|
||||
# include <assert.h>
|
||||
|
||||
# include <stdio.h>
|
||||
/*
|
||||
* The event queue is arranged as a skip list, with the simulation
|
||||
* time the key to the list. The simulation time is stored in each
|
||||
|
|
@ -90,9 +91,20 @@ inline static void e_free(struct event_s* cur)
|
|||
}
|
||||
|
||||
/*
|
||||
* This is the head of the list of pending events.
|
||||
* This is the head of the list of pending events. This includes all
|
||||
* the events that have not been executed yet, and reaches into the
|
||||
* future.
|
||||
*/
|
||||
static struct event_s* list = 0;
|
||||
static struct event_s* sched_list = 0;
|
||||
|
||||
/*
|
||||
* At the current time, events that are marked as synch events are put
|
||||
* into this list and held off until the time step is about to
|
||||
* advance. Then the events in this list are run and the clock is
|
||||
* allowed to advance.
|
||||
*/
|
||||
static struct event_s* synch_list = 0;
|
||||
|
||||
|
||||
/*
|
||||
* This flag is true until a VPI task or function finishes the
|
||||
|
|
@ -122,20 +134,20 @@ static void schedule_event_(struct event_s*cur)
|
|||
|
||||
/* If the list is completely empty, then start the list with
|
||||
this the only event. */
|
||||
if (list == 0) {
|
||||
list = cur;
|
||||
if (sched_list == 0) {
|
||||
sched_list = cur;
|
||||
cur->next = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
struct event_s*idx = list;
|
||||
struct event_s*idx = sched_list;
|
||||
if (cur->delay < idx->delay) {
|
||||
/* If this new event is earlier then even the first
|
||||
event, then insert it in front. Adjust the delay of
|
||||
the next event, and set the start to me. */
|
||||
idx->delay -= cur->delay;
|
||||
cur->next = idx;
|
||||
list = cur;
|
||||
sched_list = cur;
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -173,6 +185,43 @@ static void schedule_event_(struct event_s*cur)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The synch_list is managed as a doubly-linked circular list. There is
|
||||
* no need for the skip capabilities, so use the "last" member as a
|
||||
* prev pointer. This function appends the event to the synch_list.
|
||||
*/
|
||||
static void postpone_sync_event(struct event_s*cur)
|
||||
{
|
||||
if (synch_list == 0) {
|
||||
synch_list = cur;
|
||||
cur->next = cur;
|
||||
cur->last = cur;
|
||||
return;
|
||||
}
|
||||
|
||||
cur->next = synch_list;
|
||||
cur->last = synch_list->last;
|
||||
cur->next->last = cur;
|
||||
cur->last->next = cur;
|
||||
}
|
||||
|
||||
static struct event_s* pull_sync_event(void)
|
||||
{
|
||||
if (synch_list == 0)
|
||||
return 0;
|
||||
|
||||
struct event_s*cur = synch_list;
|
||||
synch_list = cur->next;
|
||||
if (cur == synch_list) {
|
||||
synch_list = 0;
|
||||
} else {
|
||||
cur->next->last = cur->last;
|
||||
cur->last->next = cur->next;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
void schedule_vthread(vthread_t thr, unsigned delay)
|
||||
{
|
||||
struct event_s*cur = e_alloc();
|
||||
|
|
@ -228,30 +277,47 @@ void schedule_simulate(void)
|
|||
{
|
||||
schedule_time = 0;
|
||||
|
||||
while (schedule_runnable && list) {
|
||||
while (schedule_runnable && sched_list) {
|
||||
|
||||
/* Pull the first item off the list. Fixup the last
|
||||
pointer in the next cell, if necessary. */
|
||||
struct event_s*cur = list;
|
||||
list = cur->next;
|
||||
struct event_s*cur = sched_list;
|
||||
sched_list = cur->next;
|
||||
if (cur->last != cur) {
|
||||
assert(list);
|
||||
assert(list->delay == 0);
|
||||
list->last = cur->last;
|
||||
assert(sched_list);
|
||||
assert(sched_list->delay == 0);
|
||||
sched_list->last = cur->last;
|
||||
|
||||
}
|
||||
|
||||
schedule_time += cur->delay;
|
||||
//printf("TIME: %u\n", schedule_time);
|
||||
/* If the time is advancing, then first run the
|
||||
postponed sync events. Run them all. */
|
||||
if (cur->delay > 0) {
|
||||
struct event_s*sync_cur;
|
||||
while ( (sync_cur = pull_sync_event()) ) {
|
||||
assert(sync_cur->type == TYPE_GEN);
|
||||
if (sync_cur->obj && sync_cur->obj->run) {
|
||||
assert(sync_cur->obj->sync_flag);
|
||||
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
|
||||
}
|
||||
e_free(sync_cur);
|
||||
}
|
||||
|
||||
|
||||
schedule_time += cur->delay;
|
||||
//printf("TIME: %u\n", schedule_time);
|
||||
}
|
||||
|
||||
switch (cur->type) {
|
||||
case TYPE_THREAD:
|
||||
vthread_run(cur->thr);
|
||||
e_free(cur);
|
||||
break;
|
||||
|
||||
case TYPE_PROP:
|
||||
//printf("Propagate %p\n", cur->fun);
|
||||
functor_propagate(cur->fun);
|
||||
e_free(cur);
|
||||
break;
|
||||
|
||||
case TYPE_ASSIGN:
|
||||
|
|
@ -269,21 +335,31 @@ void schedule_simulate(void)
|
|||
functor_set(cur->fun, cur->val, HiZ, false);
|
||||
break;
|
||||
}
|
||||
e_free(cur);
|
||||
break;
|
||||
|
||||
case TYPE_GEN:
|
||||
if (cur->obj && cur->obj->run)
|
||||
cur->obj->run(cur->obj, cur->val);
|
||||
if (cur->obj && cur->obj->run) {
|
||||
if (cur->obj->sync_flag == false) {
|
||||
cur->obj->run(cur->obj, cur->val);
|
||||
e_free(cur);
|
||||
|
||||
} else {
|
||||
postpone_sync_event(cur);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
e_free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: schedule.cc,v $
|
||||
* Revision 1.11 2001/07/11 02:27:21 steve
|
||||
* Add support for REadOnlySync and monitors.
|
||||
*
|
||||
* Revision 1.10 2001/05/30 03:02:35 steve
|
||||
* Propagate strength-values instead of drive strengths.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: schedule.h,v 1.6 2001/05/02 01:38:13 steve Exp $"
|
||||
#ident "$Id: schedule.h,v 1.7 2001/07/11 02:27:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vthread.h"
|
||||
|
|
@ -63,7 +63,8 @@ extern void schedule_generic(vvp_gen_event_t obj, unsigned char val,
|
|||
|
||||
struct vvp_gen_event_s
|
||||
{
|
||||
void (*run)(vvp_gen_event_t obj, unsigned char val);
|
||||
void (*run)(vvp_gen_event_t obj, unsigned char val);
|
||||
bool sync_flag;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -94,6 +95,9 @@ extern bool schedule_finished(void);
|
|||
|
||||
/*
|
||||
* $Log: schedule.h,v $
|
||||
* Revision 1.7 2001/07/11 02:27:21 steve
|
||||
* Add support for REadOnlySync and monitors.
|
||||
*
|
||||
* Revision 1.6 2001/05/02 01:38:13 steve
|
||||
* Describe a generic event a bit.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_callback.cc,v 1.2 2001/06/21 23:05:08 steve Exp $"
|
||||
#ident "$Id: vpi_callback.cc,v 1.3 2001/07/11 02:27:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -58,7 +58,11 @@ static struct __vpiCallback* make_value_change(p_cb_data data)
|
|||
struct __vpiCallback*obj = new __vpiCallback;
|
||||
obj->base.vpi_type = &callback_rt;
|
||||
obj->cb_data = *data;
|
||||
obj->cb_time = *(data->time);
|
||||
obj->cb_data.time = &obj->cb_time;
|
||||
|
||||
assert(data->obj);
|
||||
assert(data->obj->vpi_type);
|
||||
assert((data->obj->vpi_type->type_code == vpiReg)
|
||||
|| (data->obj->vpi_type->type_code == vpiNet));
|
||||
struct __vpiSignal*sig = reinterpret_cast<__vpiSignal*>(data->obj);
|
||||
|
|
@ -81,6 +85,45 @@ static struct __vpiCallback* make_value_change(p_cb_data data)
|
|||
return obj;
|
||||
}
|
||||
|
||||
struct sync_cb : public vvp_gen_event_s {
|
||||
struct __vpiCallback*handle;
|
||||
};
|
||||
|
||||
static void make_sync_run(vvp_gen_event_t obj, unsigned char)
|
||||
{
|
||||
struct sync_cb*cb = (struct sync_cb*)obj;
|
||||
if (cb->handle == 0)
|
||||
return;
|
||||
|
||||
struct __vpiCallback*cur = cb->handle;
|
||||
cur->cb_data.time->type = vpiSimTime;
|
||||
cur->cb_data.time->low = schedule_simtime();
|
||||
cur->cb_data.time->high = 0;
|
||||
(cur->cb_data.cb_rtn)(&cur->cb_data);
|
||||
|
||||
delete cur;
|
||||
}
|
||||
|
||||
static struct __vpiCallback* make_sync(p_cb_data data)
|
||||
{
|
||||
struct __vpiCallback*obj = new __vpiCallback;
|
||||
obj->base.vpi_type = &callback_rt;
|
||||
obj->cb_data = *data;
|
||||
obj->cb_time = *(data->time);
|
||||
obj->cb_data.time = &obj->cb_time;
|
||||
|
||||
obj->next = 0;
|
||||
|
||||
struct sync_cb*cb = new sync_cb;
|
||||
cb->sync_flag = true;
|
||||
cb->run = &make_sync_run;
|
||||
cb->handle = obj;
|
||||
obj->cb_sync = cb;
|
||||
|
||||
schedule_generic(cb, 0, 0);
|
||||
return obj;
|
||||
}
|
||||
|
||||
vpiHandle vpi_register_cb(p_cb_data data)
|
||||
{
|
||||
struct __vpiCallback*obj = 0;
|
||||
|
|
@ -91,6 +134,10 @@ vpiHandle vpi_register_cb(p_cb_data data)
|
|||
obj = make_value_change(data);
|
||||
break;
|
||||
|
||||
case cbReadOnlySynch:
|
||||
obj = make_sync(data);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vpi error: vpi_register_cb invalid or "
|
||||
"unsupported callback reason: %d\n",
|
||||
|
|
@ -104,6 +151,8 @@ vpiHandle vpi_register_cb(p_cb_data data)
|
|||
|
||||
int vpi_remove_cb(vpiHandle ref)
|
||||
{
|
||||
assert(ref);
|
||||
assert(ref->vpi_type);
|
||||
assert(ref->vpi_type->type_code == vpiCallback);
|
||||
|
||||
struct __vpiCallback*obj = reinterpret_cast<__vpiCallback*>(ref);
|
||||
|
|
@ -150,6 +199,9 @@ void vpip_trip_monitor_callbacks(void)
|
|||
|
||||
/*
|
||||
* $Log: vpi_callback.cc,v $
|
||||
* Revision 1.3 2001/07/11 02:27:21 steve
|
||||
* Add support for REadOnlySync and monitors.
|
||||
*
|
||||
* Revision 1.2 2001/06/21 23:05:08 steve
|
||||
* Some documentation of callback behavior.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_priv.cc,v 1.7 2001/06/30 23:03:17 steve Exp $"
|
||||
#ident "$Id: vpi_priv.cc,v 1.8 2001/07/11 02:27:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
|
|
@ -55,12 +55,12 @@ static int vpip_get_global(int property)
|
|||
|
||||
int vpi_get(int property, vpiHandle ref)
|
||||
{
|
||||
if (property == vpiType)
|
||||
return ref->vpi_type->type_code;
|
||||
|
||||
if (ref == 0)
|
||||
return vpip_get_global(property);
|
||||
|
||||
if (property == vpiType)
|
||||
return ref->vpi_type->type_code;
|
||||
|
||||
if (ref->vpi_type->vpi_get_ == 0)
|
||||
return -1;
|
||||
|
||||
|
|
@ -151,6 +151,9 @@ extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
|
|||
|
||||
/*
|
||||
* $Log: vpi_priv.cc,v $
|
||||
* Revision 1.8 2001/07/11 02:27:21 steve
|
||||
* Add support for REadOnlySync and monitors.
|
||||
*
|
||||
* Revision 1.7 2001/06/30 23:03:17 steve
|
||||
* support fast programming by only writing the bits
|
||||
* that are listed in the input file.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_priv.h,v 1.18 2001/06/30 23:03:17 steve Exp $"
|
||||
#ident "$Id: vpi_priv.h,v 1.19 2001/07/11 02:27:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
|
|
@ -125,10 +125,15 @@ extern struct __vpiSignal*vpip_sig_from_ptr(vvp_ipoint_t ptr);
|
|||
* callback. The handle is stored by the run time, and it triggered
|
||||
* when the run-time thing that it is waiting for happens.
|
||||
*/
|
||||
|
||||
struct sync_cb;
|
||||
struct __vpiCallback {
|
||||
struct __vpiHandle base;
|
||||
|
||||
struct t_cb_data cb_data;
|
||||
struct t_vpi_time cb_time;
|
||||
|
||||
struct sync_cb* cb_sync;
|
||||
|
||||
struct __vpiCallback*next;
|
||||
};
|
||||
|
|
@ -254,6 +259,9 @@ extern void vpip_set_time_precision(int pres);
|
|||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.19 2001/07/11 02:27:21 steve
|
||||
* Add support for REadOnlySync and monitors.
|
||||
*
|
||||
* Revision 1.18 2001/06/30 23:03:17 steve
|
||||
* support fast programming by only writing the bits
|
||||
* that are listed in the input file.
|
||||
|
|
|
|||
Loading…
Reference in New Issue