2024-02-06 10:04:13 +01:00
|
|
|
#if defined(TEST_SCALED_TIME)
|
2024-02-05 23:04:29 +01:00
|
|
|
#define TIME_TYPE vpiScaledRealTime
|
2024-02-06 10:04:13 +01:00
|
|
|
#elif defined(TEST_SIM_TIME)
|
2024-02-05 23:04:29 +01:00
|
|
|
#define TIME_TYPE vpiSimTime
|
2024-02-06 10:04:13 +01:00
|
|
|
#else
|
|
|
|
|
#define TIME_TYPE vpiSuppressTime
|
2024-02-05 23:04:29 +01:00
|
|
|
#endif
|
|
|
|
|
|
2024-02-07 01:02:58 +01:00
|
|
|
#include <sv_vpi_user.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <string.h>
|
2024-02-05 23:04:29 +01:00
|
|
|
|
|
|
|
|
static PLI_INT32 report_change(p_cb_data cb)
|
|
|
|
|
{
|
|
|
|
|
vpiHandle handle = (vpiHandle)(cb->user_data);
|
|
|
|
|
|
2024-02-06 10:04:13 +01:00
|
|
|
s_vpi_time time;
|
|
|
|
|
|
|
|
|
|
#ifndef TEST_NULL_TIME
|
2024-02-05 23:04:29 +01:00
|
|
|
assert(cb->time && (cb->time->type == TIME_TYPE));
|
2024-02-06 10:04:13 +01:00
|
|
|
#endif
|
2024-02-05 23:04:29 +01:00
|
|
|
assert(cb->value);
|
|
|
|
|
|
2024-02-06 10:04:13 +01:00
|
|
|
#if defined(TEST_SCALED_TIME) || defined(TEST_SIM_TIME)
|
|
|
|
|
time = *(cb->time);
|
|
|
|
|
#else
|
|
|
|
|
time.type = vpiSimTime;
|
|
|
|
|
vpi_get_time(NULL, &time);
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-02-05 23:04:29 +01:00
|
|
|
switch (cb->value->format) {
|
|
|
|
|
case vpiIntVal:
|
2024-02-06 10:04:13 +01:00
|
|
|
#if defined(TEST_SCALED_TIME)
|
|
|
|
|
vpi_printf("At time %f %s = %d\n", time.real, vpi_get_str(vpiName, handle), cb->value->value.integer);
|
2024-02-05 23:04:29 +01:00
|
|
|
#else
|
2024-02-06 10:04:13 +01:00
|
|
|
vpi_printf("At time %d %s = %d\n", time.low, vpi_get_str(vpiName, handle), cb->value->value.integer);
|
2024-02-05 23:04:29 +01:00
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
case vpiRealVal:
|
|
|
|
|
#ifdef TEST_SCALED_TIME
|
2024-02-06 10:04:13 +01:00
|
|
|
vpi_printf("At time %f %s = %f\n", time.real, vpi_get_str(vpiName, handle), cb->value->value.real);
|
2024-02-05 23:04:29 +01:00
|
|
|
#else
|
2024-02-06 10:04:13 +01:00
|
|
|
vpi_printf("At time %d %s = %f\n", time.low, vpi_get_str(vpiName, handle), cb->value->value.real);
|
2024-02-05 23:04:29 +01:00
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
case vpiSuppressVal:
|
|
|
|
|
#ifdef TEST_SCALED_TIME
|
2024-02-06 10:04:13 +01:00
|
|
|
vpi_printf("At time %f %s changed\n", time.real, vpi_get_str(vpiName, handle));
|
2024-02-05 23:04:29 +01:00
|
|
|
#else
|
2024-02-06 10:04:13 +01:00
|
|
|
vpi_printf("At time %d %s changed\n", time.low, vpi_get_str(vpiName, handle));
|
2024-02-05 23:04:29 +01:00
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
vpi_printf("ERROR: unexpected value format %d\n", cb->value->format);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static s_cb_data cb;
|
|
|
|
|
static s_vpi_time time;
|
|
|
|
|
static s_vpi_value value;
|
|
|
|
|
|
|
|
|
|
static PLI_INT32 my_monitor_calltf(PLI_BYTE8 *xx)
|
|
|
|
|
{
|
|
|
|
|
(void)xx; /* Parameter is not used. */
|
|
|
|
|
|
|
|
|
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
|
|
|
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
|
|
|
|
|
|
|
|
|
vpiHandle handle;
|
|
|
|
|
|
|
|
|
|
memset(&cb, 0, sizeof(cb));
|
|
|
|
|
memset(&time, 0, sizeof(time));
|
|
|
|
|
memset(&value, 0, sizeof(value));
|
|
|
|
|
|
|
|
|
|
time.type = TIME_TYPE;
|
|
|
|
|
|
|
|
|
|
cb.reason = cbValueChange;
|
|
|
|
|
cb.cb_rtn = report_change;
|
|
|
|
|
cb.time = &time;
|
|
|
|
|
cb.value = &value;
|
|
|
|
|
|
|
|
|
|
while ((handle = vpi_scan(argv))) {
|
|
|
|
|
PLI_INT32 type = vpi_get(vpiType, handle);
|
|
|
|
|
cb.obj = handle;
|
|
|
|
|
cb.user_data = (char *)handle;
|
|
|
|
|
switch (type) {
|
|
|
|
|
case vpiNet:
|
|
|
|
|
case vpiReg:
|
|
|
|
|
case vpiIntegerVar:
|
|
|
|
|
case vpiBitVar:
|
|
|
|
|
case vpiByteVar:
|
|
|
|
|
case vpiShortIntVar:
|
|
|
|
|
case vpiIntVar:
|
|
|
|
|
case vpiLongIntVar:
|
|
|
|
|
case vpiPartSelect:
|
|
|
|
|
case vpiMemoryWord:
|
|
|
|
|
case vpiMemory:
|
|
|
|
|
value.format = vpiIntVal;
|
|
|
|
|
break;
|
|
|
|
|
case vpiRealVar:
|
|
|
|
|
value.format = vpiRealVal;
|
|
|
|
|
break;
|
|
|
|
|
case vpiNamedEvent:
|
|
|
|
|
value.format = vpiSuppressVal;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
vpi_printf("ERROR: unexpected object type %d\n", type);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
vpi_register_cb(&cb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(&cb, 0, sizeof(cb));
|
|
|
|
|
memset(&time, 0, sizeof(time));
|
|
|
|
|
memset(&value, 0, sizeof(value));
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void my_monitor_register(void)
|
|
|
|
|
{
|
|
|
|
|
s_vpi_systf_data tf_data;
|
|
|
|
|
|
|
|
|
|
tf_data.type = vpiSysTask;
|
|
|
|
|
tf_data.tfname = "$my_monitor";
|
|
|
|
|
tf_data.calltf = my_monitor_calltf;
|
|
|
|
|
tf_data.compiletf = 0;
|
|
|
|
|
tf_data.sizetf = 0;
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void (*vlog_startup_routines[])(void) = {
|
|
|
|
|
my_monitor_register,
|
|
|
|
|
0
|
|
|
|
|
};
|