Free memory at EOS and convert to C code (vhdl_table.cc).
This patch converts the vhdl_table.cc file to C code and adds code to free the allocated memory at the end of simulation to make valgrind happy.
This commit is contained in:
parent
82e946b51a
commit
7f65f3b157
|
|
@ -151,7 +151,7 @@ va_math.vpi: $V ../vvp/libvpi.a
|
||||||
$(CC) @shared@ -o $@ $V -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS)
|
$(CC) @shared@ -o $@ $V -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS)
|
||||||
|
|
||||||
vhdl_sys.vpi: $(VHDL_SYS) ../vvp/libvpi.a
|
vhdl_sys.vpi: $(VHDL_SYS) ../vvp/libvpi.a
|
||||||
$(CXX) @shared@ -o $@ $(VHDL_SYS) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
|
$(CC) @shared@ -o $@ $(VHDL_SYS) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS)
|
||||||
|
|
||||||
stamp-vpi_config-h: $(srcdir)/vpi_config.h.in ../config.status
|
stamp-vpi_config-h: $(srcdir)/vpi_config.h.in ../config.status
|
||||||
@rm -f $@
|
@rm -f $@
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@
|
||||||
|
|
||||||
# include "vpi_config.h"
|
# include "vpi_config.h"
|
||||||
# include "vpi_user.h"
|
# include "vpi_user.h"
|
||||||
# include <cassert>
|
# include <assert.h>
|
||||||
|
# include "ivl_alloc.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The $ivlh_attribute_event implements the VHDL <varname>'event
|
* The $ivlh_attribute_event implements the VHDL <varname>'event
|
||||||
|
|
@ -32,14 +33,28 @@ struct monitor_data {
|
||||||
struct t_vpi_time last_event;
|
struct t_vpi_time last_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
static struct monitor_data **mdata = 0;
|
||||||
* All the following are called from C so define them for C linkage.
|
static unsigned mdata_count = 0;
|
||||||
*/
|
|
||||||
extern "C" {
|
/* To keep valgrind happy free the allocated memory. */
|
||||||
|
static PLI_INT32 cleanup_mdata(p_cb_data cause)
|
||||||
|
{
|
||||||
|
unsigned idx;
|
||||||
|
(void) cause; /* Unused argument. */
|
||||||
|
|
||||||
|
for (idx= 0; idx < mdata_count; idx += 1) {
|
||||||
|
free(mdata[idx]);
|
||||||
|
}
|
||||||
|
free(mdata);
|
||||||
|
mdata = 0;
|
||||||
|
mdata_count = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PLI_INT32 monitor_events(struct t_cb_data*cb)
|
static PLI_INT32 monitor_events(struct t_cb_data*cb)
|
||||||
{
|
{
|
||||||
struct monitor_data*mon = reinterpret_cast<monitor_data*> (cb->user_data);
|
struct monitor_data*mon = (struct monitor_data*)(cb->user_data);
|
||||||
|
|
||||||
assert(cb->time);
|
assert(cb->time);
|
||||||
assert(cb->time->type == vpiSimTime);
|
assert(cb->time->type == vpiSimTime);
|
||||||
|
|
@ -48,56 +63,71 @@ static PLI_INT32 monitor_events(struct t_cb_data*cb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PLI_INT32 ivlh_attribute_event_compiletf(ICARUS_VPI_CONST PLI_BYTE8*)
|
static PLI_INT32 ivlh_attribute_event_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||||
vpiHandle arg;
|
vpiHandle arg;
|
||||||
|
struct monitor_data*mon;
|
||||||
|
struct t_cb_data cb;
|
||||||
|
struct t_vpi_time tb;
|
||||||
|
|
||||||
// Check that there is at least 1 argument...
|
/* Check that there are arguments. */
|
||||||
if (argv == 0) {
|
if (argv == 0) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
|
||||||
vpi_printf("Call to %s missing its argument\n", vpi_get_str(vpiName,sys));
|
(int)vpi_get(vpiLineNo, sys));
|
||||||
|
vpi_printf("(compiler error) %s requires a single argument.\n",
|
||||||
|
name);
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Icarus either returns 0 above or has one argument. */
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
assert(arg);
|
assert(arg);
|
||||||
|
|
||||||
struct monitor_data*monitor_handle = new struct monitor_data;
|
mon = malloc(sizeof(struct monitor_data));
|
||||||
|
/* Add this to the list of data. */
|
||||||
|
mdata_count += 1;
|
||||||
|
mdata = (struct monitor_data **) realloc(mdata,
|
||||||
|
sizeof(struct monitor_data **) *
|
||||||
|
mdata_count);
|
||||||
|
mdata[mdata_count-1] = mon;
|
||||||
|
|
||||||
struct t_cb_data cb;
|
|
||||||
struct t_vpi_time tb;
|
|
||||||
tb.type = vpiSimTime;
|
tb.type = vpiSimTime;
|
||||||
cb.reason = cbValueChange;
|
cb.reason = cbValueChange;
|
||||||
cb.cb_rtn = monitor_events;
|
cb.cb_rtn = monitor_events;
|
||||||
cb.obj = arg;
|
cb.obj = arg;
|
||||||
cb.time = &tb;
|
cb.time = &tb;
|
||||||
cb.value = 0;
|
cb.value = 0;
|
||||||
cb.user_data = reinterpret_cast<char*>(monitor_handle);
|
cb.user_data = (char*) (mon);
|
||||||
vpi_register_cb(&cb);
|
vpi_register_cb(&cb);
|
||||||
vpi_put_userdata(sys, monitor_handle);
|
vpi_put_userdata(sys, mon);
|
||||||
|
|
||||||
// check that there is no more then 1 argument
|
/* Check that there are no more then one argument. */
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
|
||||||
vpi_printf("Too many arguments for call to %s.\n", vpi_get_str(vpiName,sys));
|
(int)vpi_get(vpiLineNo, sys));
|
||||||
|
vpi_printf("(compiler error) %s only takes a single argument.\n",
|
||||||
|
name);
|
||||||
|
vpi_free_object(argv);
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
|
static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
||||||
struct t_vpi_value rval;
|
struct t_vpi_value rval;
|
||||||
|
struct monitor_data*mon;
|
||||||
|
(void) name;
|
||||||
|
|
||||||
rval.format = vpiScalarVal;
|
rval.format = vpiScalarVal;
|
||||||
|
|
||||||
struct monitor_data*mon = reinterpret_cast<monitor_data*>(vpi_get_userdata(sys));
|
mon = (struct monitor_data*) (vpi_get_userdata(sys));
|
||||||
|
|
||||||
if (mon->last_event.type == 0) {
|
if (mon->last_event.type == 0) {
|
||||||
rval.value.scalar = vpi0;
|
rval.value.scalar = vpi0;
|
||||||
|
|
@ -105,7 +135,7 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
|
||||||
} else {
|
} else {
|
||||||
struct t_vpi_time tnow;
|
struct t_vpi_time tnow;
|
||||||
tnow.type = vpiSimTime;
|
tnow.type = vpiSimTime;
|
||||||
vpi_get_time(0,&tnow);
|
vpi_get_time(0, &tnow);
|
||||||
|
|
||||||
rval.value.scalar = vpi1;
|
rval.value.scalar = vpi1;
|
||||||
if (mon->last_event.high != tnow.high)
|
if (mon->last_event.high != tnow.high)
|
||||||
|
|
@ -119,14 +149,16 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PLI_INT32 ivlh_attribute_event_sizetf(ICARUS_VPI_CONST PLI_BYTE8*)
|
static PLI_INT32 ivlh_attribute_event_sizetf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
|
(void) name;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vhdl_register(void)
|
static void vhdl_register(void)
|
||||||
{
|
{
|
||||||
s_vpi_systf_data tf_data;
|
s_vpi_systf_data tf_data;
|
||||||
|
s_cb_data cb;
|
||||||
vpiHandle res;
|
vpiHandle res;
|
||||||
|
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
|
|
@ -138,11 +170,19 @@ static void vhdl_register(void)
|
||||||
tf_data.user_data = (PLI_BYTE8 *) "$ivlh_attribute_event";
|
tf_data.user_data = (PLI_BYTE8 *) "$ivlh_attribute_event";
|
||||||
res = vpi_register_systf(&tf_data);
|
res = vpi_register_systf(&tf_data);
|
||||||
vpip_make_systf_system_defined(res);
|
vpip_make_systf_system_defined(res);
|
||||||
|
|
||||||
|
/* Create a callback to clear the monitor data memory when the
|
||||||
|
* simulator finishes. */
|
||||||
|
cb.time = NULL;
|
||||||
|
cb.reason = cbEndOfSimulation;
|
||||||
|
cb.cb_rtn = cleanup_mdata;
|
||||||
|
cb.user_data = NULL;
|
||||||
|
cb.obj = NULL;
|
||||||
|
|
||||||
|
vpi_register_cb(&cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*vlog_startup_routines[])() = {
|
void (*vlog_startup_routines[])() = {
|
||||||
vhdl_register,
|
vhdl_register,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* extern "C" */
|
|
||||||
Loading…
Reference in New Issue