mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-22 13:57:18 +02:00
Add memory freeing and pool management for valgrind.
This patch adds code to free most of the memory when vvp finishes. It also adds valgrind hooks to manage the various memory pools. The functionality is enabled by passing --with-valgrind to configure. It requires that the valgrind/memcheck.h header from a recent version of valgrind be available. It check for the existence of this file, but not that it is new enough (version 3.1.3 is known to not work and version 3.4.0 is known to work). You can still use valgrind when this option is not given, but you will have memory that is not released and the memory pools show as a single block. With this vvp is 100% clean for many of the tests in the test suite. There are still a few things that need to be cleaned up, but it should be much easier to find any real leaks now. Enabling this causes a negligible increase in run time and memory. The memory could be a problem for very large simulations. The increase in run time is only noticeable on very short simulations where it should not matter.
This commit is contained in:
@@ -25,7 +25,10 @@
|
||||
# include "vpi_priv.h"
|
||||
# include "vthread.h"
|
||||
# include "compile.h"
|
||||
# include "config.h"
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
# include "vvp_cleanup.h"
|
||||
#endif
|
||||
# include <stdio.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
@@ -520,6 +523,7 @@ static struct __vpiUserSystf* allocate_def(void)
|
||||
return def_table[def_count++];
|
||||
}
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void def_table_delete(void)
|
||||
{
|
||||
for (unsigned idx = 0; idx < def_count; idx += 1) {
|
||||
@@ -530,6 +534,7 @@ void def_table_delete(void)
|
||||
def_table = 0;
|
||||
def_count = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct __vpiUserSystf* vpip_find_systf(const char*name)
|
||||
{
|
||||
@@ -630,6 +635,42 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||
return &obj->base;
|
||||
}
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
void vpi_call_delete(vpiHandle item)
|
||||
{
|
||||
struct __vpiSysTaskCall*obj = (struct __vpiSysTaskCall *) item;
|
||||
for (unsigned arg = 0; arg < obj->nargs; arg += 1) {
|
||||
switch (obj->args[arg]->vpi_type->type_code) {
|
||||
case vpiConstant:
|
||||
switch (vpi_get(_vpiFromThr, obj->args[arg])) {
|
||||
case _vpiNoThr:
|
||||
constant_delete(obj->args[arg]);
|
||||
break;
|
||||
case _vpiVThr:
|
||||
thread_vthr_delete(obj->args[arg]);
|
||||
break;
|
||||
case _vpiWord:
|
||||
thread_word_delete(obj->args[arg]);
|
||||
break;
|
||||
default:
|
||||
assert(0);;
|
||||
}
|
||||
break;
|
||||
case vpiMemoryWord:
|
||||
if (vpi_get(_vpiFromThr, obj->args[arg]) == _vpi_at_A) {
|
||||
A_delete(obj->args[arg]);
|
||||
}
|
||||
break;
|
||||
case vpiPartSelect:
|
||||
assert(vpi_get(_vpiFromThr, obj->args[arg]) == _vpi_at_PV);
|
||||
PV_delete(obj->args[arg]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(obj->args);
|
||||
delete obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is used by the %vpi_call instruction to actually
|
||||
|
||||
Reference in New Issue
Block a user