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)
|
||||
|
||||
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
|
||||
@rm -f $@
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
# include "vpi_config.h"
|
||||
# include "vpi_user.h"
|
||||
# include <cassert>
|
||||
# include <assert.h>
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
/*
|
||||
* The $ivlh_attribute_event implements the VHDL <varname>'event
|
||||
|
|
@ -32,14 +33,28 @@ struct monitor_data {
|
|||
struct t_vpi_time last_event;
|
||||
};
|
||||
|
||||
/*
|
||||
* All the following are called from C so define them for C linkage.
|
||||
*/
|
||||
extern "C" {
|
||||
static struct monitor_data **mdata = 0;
|
||||
static unsigned mdata_count = 0;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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->type == vpiSimTime);
|
||||
|
|
@ -48,56 +63,71 @@ static PLI_INT32 monitor_events(struct t_cb_data*cb)
|
|||
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 argv = vpi_iterate(vpiArgument, sys);
|
||||
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) {
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
|
||||
vpi_printf("Call to %s missing its argument\n", vpi_get_str(vpiName,sys));
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
|
||||
(int)vpi_get(vpiLineNo, sys));
|
||||
vpi_printf("(compiler error) %s requires a single argument.\n",
|
||||
name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Icarus either returns 0 above or has one argument. */
|
||||
arg = vpi_scan(argv);
|
||||
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;
|
||||
cb.reason = cbValueChange;
|
||||
cb.cb_rtn = monitor_events;
|
||||
cb.obj = arg;
|
||||
cb.time = &tb;
|
||||
cb.value = 0;
|
||||
cb.user_data = reinterpret_cast<char*>(monitor_handle);
|
||||
cb.user_data = (char*) (mon);
|
||||
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);
|
||||
if (arg != 0) {
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys), vpi_get(vpiLineNo, sys));
|
||||
vpi_printf("Too many arguments for call to %s.\n", vpi_get_str(vpiName,sys));
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, 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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
struct t_vpi_value rval;
|
||||
struct monitor_data*mon;
|
||||
(void) name;
|
||||
|
||||
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) {
|
||||
rval.value.scalar = vpi0;
|
||||
|
|
@ -105,7 +135,7 @@ static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*)
|
|||
} else {
|
||||
struct t_vpi_time tnow;
|
||||
tnow.type = vpiSimTime;
|
||||
vpi_get_time(0,&tnow);
|
||||
vpi_get_time(0, &tnow);
|
||||
|
||||
rval.value.scalar = vpi1;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void vhdl_register(void)
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
s_cb_data cb;
|
||||
vpiHandle res;
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
|
|
@ -138,11 +170,19 @@ static void vhdl_register(void)
|
|||
tf_data.user_data = (PLI_BYTE8 *) "$ivlh_attribute_event";
|
||||
res = vpi_register_systf(&tf_data);
|
||||
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[])() = {
|
||||
vhdl_register,
|
||||
0
|
||||
};
|
||||
|
||||
} /* extern "C" */
|
||||
Loading…
Reference in New Issue