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:
Cary R 2009-01-29 17:23:09 -08:00 committed by Stephen Williams
parent 51307c0a3e
commit 7b1905b997
29 changed files with 812 additions and 23 deletions

View File

@ -79,6 +79,18 @@ AC_CHECK_LIB(bz2, BZ2_bzdopen, HAVE_LIBBZ2=yes, HAVE_LIBBZ2=no)
fi
AC_SUBST(HAVE_LIBBZ2)
# valgrind checks
AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind],
[Add valgrind hooks])],
[], [check_valgrind=yes])
AS_IF([test "x$check_valgrind" == xyes],
[AC_MSG_NOTICE([Not using valgrind hooks])],
[AC_CHECK_HEADER([valgrind/memcheck.h],
[AC_DEFINE([CHECK_WITH_VALGRIND], [1],
[Define to one to use the valgrind hooks])],
[AC_MSG_ERROR([Could not find <valgrind/memcheck.h>])])])
AC_MSG_CHECKING(for sys/times)
AC_TRY_LINK(
#include <unistd.h>

View File

@ -1,7 +1,7 @@
#ifndef __vpi_user_H
#define __vpi_user_H
/*
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -353,6 +353,12 @@ typedef struct t_vpi_delay {
#define vpiSigned 65
/* IVL private properties */
#define _vpiNexusId 0x1000000
#define _vpiFromThr 0x1000001
# define _vpiNoThr 0
# define _vpiVThr 1
# define _vpiWord 2
# define _vpi_at_PV 3
# define _vpi_at_A 4
/* DELAY MODES */
#define vpiNoDelay 1

View File

@ -21,6 +21,10 @@
#include "symbols.h"
#include "schedule.h"
#include "vpi_priv.h"
#include "config.h"
#ifdef CHECK_WITH_VALGRIND
#include "vvp_cleanup.h"
#endif
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
@ -448,6 +452,9 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
decode_array_word_pointer(obj, parent);
switch (code) {
case vpiLineNo:
return 0; // Not implemented for now!
case vpiSize:
return (int) parent->vals4->width();
@ -460,6 +467,11 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
case vpiAutomatic:
return (int) parent->scope->is_automatic;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
return 0;
}
@ -646,6 +658,11 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref)
case vpiAutomatic:
return (int) parent->scope->is_automatic;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpi_at_A;
#endif
// If address_handle is not zero we definitely have a
// variable. If the wid is not zero we have a calculation
// from thread space which probably includes a variable.
@ -1093,6 +1110,9 @@ class vvp_fun_arrayport_aa : public vvp_fun_arrayport, public automatic_hooks_s
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
void check_word_change(unsigned long addr);
@ -1138,6 +1158,15 @@ void vvp_fun_arrayport_aa::reset_instance(vvp_context_t context)
*addr = addr_;
}
#ifdef CHECK_WITH_VALGRIND
void vvp_fun_arrayport_aa::free_instance(vvp_context_t context)
{
unsigned long*addr = static_cast<unsigned long*>
(vvp_get_context_item(context, context_idx_));
delete addr;
}
#endif
void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t context)
{
@ -1476,3 +1505,39 @@ void compile_array_cleanup(void)
array_table = 0;
}
}
#ifdef CHECK_WITH_VALGRIND
void memory_delete(vpiHandle item)
{
struct __vpiArray*arr = ARRAY_HANDLE(item);
if (arr->vals_words) delete [] (arr->vals_words-1);
if (arr->vals4) {
delete arr->vals4;
// Delete the individual words.
// constant_delete(handle)
}
if (arr->valsr) {
delete arr->valsr;
// Delete the individual words.
// constant_delete(handle)
}
if (arr->nets) {
for (unsigned idx = 0; idx < arr->array_count; idx += 1) {
// Why are only the real words still here?
// Delete the individual words.
// constant_delete(handle)
}
free(arr->nets);
}
free(arr);
}
void A_delete(vpiHandle item)
{
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*) item;
free(obj);
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,6 +19,10 @@
# include "codes.h"
# include "statistics.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <string.h>
# include <assert.h>
@ -92,3 +96,24 @@ vvp_code_t codespace_null(void)
return first_chunk + 0;
}
#ifdef CHECK_WITH_VALGRIND
void codespace_delete(void)
{
vvp_code_t cur = first_chunk;
do {
vvp_code_t next = cur[code_chunk_size-1].cptr;
for (unsigned idx = 0 ; idx < code_chunk_size; idx += 1) {
count_opcodes -= 1;
if ((cur+idx)->opcode == &of_VPI_CALL) {
vpi_call_delete((cur+idx)->handle);
}
if (count_opcodes == 0) break;
}
/* Don't count the &of_CHUNK_LINK opcode. */
if (count_opcodes != 0) count_opcodes += 1;
delete [] cur;
cur = next;
} while (cur != 0);
}
#endif

View File

@ -659,6 +659,8 @@ void compile_cleanup(void)
delete_symbol_table(sym_functors);
sym_functors = 0;
delete_udp_symbols();
compile_island_cleanup();
compile_array_cleanup();

View File

@ -472,4 +472,6 @@ extern void compile_island_tranif(int sense, char*island,
extern void compile_island_tranvp(char*island, char*ba, char*bb,
unsigned width, unsigned part, unsigned off);
extern void delete_udp_symbols(void);
#endif

View File

@ -1,7 +1,7 @@
#ifndef __config_H
#define __config_H
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -49,6 +49,12 @@
# undef HAVE_LROUND
# undef HAVE_NAN
/*
* Define this is you want to compile vvp with memory freeing and
* special valgrind hooks for the memory pools.
*/
# undef CHECK_WITH_VALGRIND
/* Figure if I can use readline. */
#undef USE_READLINE
#ifdef HAVE_LIBREADLINE

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005-2008 Stephen Williams <steve@icarus.com>
* Copyright (c) 2005-2009 Stephen Williams <steve@icarus.com>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -20,6 +20,10 @@
#include "delay.h"
#include "schedule.h"
#include "vpi_priv.h"
#include "config.h"
#ifdef CHECK_WITH_VALGRIND
#include "vvp_cleanup.h"
#endif
#include <iostream>
#include <cstdlib>
#include <list>
@ -855,6 +859,11 @@ static void initialize_path_term(struct __vpiModPathTerm&obj)
* respective functor
*/
#ifdef CHECK_WITH_VALGRIND
static struct __vpiModPath**mp_list = 0;
static unsigned mp_count = 0;
#endif
struct __vpiModPath* vpip_make_modpath(vvp_net_t *net)
{
struct __vpiModPath*obj = (struct __vpiModPath *)calloc(1, sizeof ( struct __vpiModPath ) );
@ -863,9 +872,26 @@ struct __vpiModPath* vpip_make_modpath(vvp_net_t *net)
initialize_path_term(obj->path_term_out);
obj->input_net = net ;
#ifdef CHECK_WITH_VALGRIND
mp_count += 1;
mp_list = (struct __vpiModPath **) realloc(mp_list,
mp_count*sizeof(struct __vpiModPath **));
mp_list[mp_count-1] = obj;
#endif
return obj;
}
#ifdef CHECK_WITH_VALGRIND
void modpath_delete()
{
for (unsigned idx = 0; idx < mp_count; idx += 1) {
free(mp_list[idx]);
}
free(mp_list);
mp_list = 0;
mp_count = 0;
}
#endif
/*
* This function will construct a vpiModPathIn

View File

@ -22,7 +22,10 @@
# include "vthread.h"
# include "schedule.h"
# include "vpi_priv.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <string.h>
# include <assert.h>
# include <stdlib.h>
@ -268,6 +271,14 @@ void vvp_fun_edge_aa::reset_instance(vvp_context_t context)
state->bits[idx] = BIT4_X;
}
#ifdef CHECK_WITH_VALGRIND
void vvp_fun_edge_aa::free_instance(vvp_context_t context)
{
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
(vvp_get_context_item(context, context_idx_));
delete state;
}
#endif
vthread_t vvp_fun_edge_aa::add_waiting_thread(vthread_t thread)
{
@ -419,6 +430,15 @@ void vvp_fun_anyedge_aa::reset_instance(vvp_context_t context)
}
}
#ifdef CHECK_WITH_VALGRIND
void vvp_fun_anyedge_aa::free_instance(vvp_context_t context)
{
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
(vvp_get_context_item(context, context_idx_));
delete state;
}
#endif
vthread_t vvp_fun_anyedge_aa::add_waiting_thread(vthread_t thread)
{
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
@ -526,6 +546,15 @@ void vvp_fun_event_or_aa::reset_instance(vvp_context_t context)
state->threads = 0;
}
#ifdef CHECK_WITH_VALGRIND
void vvp_fun_event_or_aa::free_instance(vvp_context_t context)
{
waitable_state_s*state = static_cast<waitable_state_s*>
(vvp_get_context_item(context, context_idx_));
delete state;
}
#endif
vthread_t vvp_fun_event_or_aa::add_waiting_thread(vthread_t thread)
{
waitable_state_s*state = static_cast<waitable_state_s*>
@ -615,6 +644,15 @@ void vvp_named_event_aa::reset_instance(vvp_context_t context)
state->threads = 0;
}
#ifdef CHECK_WITH_VALGRIND
void vvp_named_event_aa::free_instance(vvp_context_t context)
{
waitable_state_s*state = static_cast<waitable_state_s*>
(vvp_get_context_item(context, context_idx_));
delete state;
}
#endif
vthread_t vvp_named_event_aa::add_waiting_thread(vthread_t thread)
{
waitable_state_s*state = static_cast<waitable_state_s*>
@ -741,3 +779,10 @@ void compile_named_event(char*label, char*name)
free(label);
delete[] name;
}
#ifdef CHECK_WITH_VALGRIND
void named_event_delete(struct __vpiHandle*handle)
{
free(handle);
}
#endif

View File

@ -1,7 +1,7 @@
#ifndef __event_H
#define __event_H
/*
* Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -22,6 +22,7 @@
# include "vvp_net.h"
# include "pointers.h"
# include "array.h"
# include "config.h"
class evctl {
@ -178,6 +179,9 @@ class vvp_fun_edge_aa : public vvp_fun_edge, public automatic_hooks_s {
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
vthread_t add_waiting_thread(vthread_t thread);
@ -247,6 +251,9 @@ class vvp_fun_anyedge_aa : public vvp_fun_anyedge, public automatic_hooks_s {
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
vthread_t add_waiting_thread(vthread_t thread);
@ -301,6 +308,9 @@ class vvp_fun_event_or_aa : public vvp_fun_event_or, public automatic_hooks_s {
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
vthread_t add_waiting_thread(vthread_t thread);
@ -356,6 +366,9 @@ class vvp_named_event_aa : public vvp_named_event, public automatic_hooks_s {
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
vthread_t add_waiting_thread(vthread_t thread);

View File

@ -420,19 +420,28 @@ int main(int argc, char*argv[])
count_gen_events, count_gen_pool());
}
/*
* We only need to cleanup the memory if we are checking with valgrind.
*/
#ifdef CHECK_WITH_VALGRIND
/* Clean up the memory. */
for (vector<const char*>::iterator cur = file_names.begin();
cur != file_names.end() ; cur++) {
delete[] *cur;
}
(void)need_result_buf(0, RBUF_DEL);
// These are not finished.
// codespace_delete();
// root_table_delete();
codespace_delete();
root_table_delete();
def_table_delete();
vpi_mcd_delete();
dec_str_delete();
modpath_delete();
vpi_handle_delete();
udp_defns_delete();
load_module_delete();
signal_pool_delete();
vvp_net_pool_delete();
#endif
return vvp_return_value;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -127,6 +127,15 @@ void vvp_fun_part_aa::reset_instance(vvp_context_t context)
val->set_to_x();
}
#ifdef CHECK_WITH_VALGRIND
void vvp_fun_part_aa::free_instance(vvp_context_t context)
{
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
(vvp_get_context_item(context, context_idx_));
delete val;
}
#endif
void vvp_fun_part_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t context)
{
@ -339,6 +348,15 @@ void vvp_fun_part_var_aa::reset_instance(vvp_context_t context)
state->ref.set_to_x();
}
#ifdef CHECK_WITH_VALGRIND
void vvp_fun_part_var_aa::free_instance(vvp_context_t context)
{
vvp_fun_part_var_state_s*state = static_cast<vvp_fun_part_var_state_s*>
(vvp_get_context_item(context, context_idx_));
delete state;
}
#endif
void vvp_fun_part_var_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t context)
{

View File

@ -1,7 +1,7 @@
#ifndef __part_H
#define __part_H
/*
* Copyright (c) 2005-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -20,6 +20,7 @@
*/
# include "schedule.h"
# include "config.h"
/* vvp_fun_part
* This node takes a part select of the input vector. Input 0 is the
@ -75,6 +76,9 @@ class vvp_fun_part_aa : public vvp_fun_part, public automatic_hooks_s {
public:
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t context);
@ -168,6 +172,9 @@ class vvp_fun_part_var_aa : public vvp_fun_part_var, public automatic_hooks_s {
public:
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t context);

View File

@ -24,6 +24,10 @@
#include "schedule.h"
#include "symbols.h"
#include "compile.h"
#include "config.h"
#ifdef CHECK_WITH_VALGRIND
#include "vvp_cleanup.h"
#endif
#include <assert.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
@ -33,8 +37,37 @@
#include <stdio.h>
#include <iostream>
// We may need these later when we build the VPI interface to
// UDP definitions.
#ifdef CHECK_WITH_VALGRIND
static vvp_udp_s **udp_defns = 0;
static unsigned udp_defns_count = 0;
void udp_defns_delete()
{
for (unsigned idx = 0; idx < udp_defns_count; idx += 1) {
if (udp_defns[idx]->is_sequential()) {
vvp_udp_seq_s *obj = (vvp_udp_seq_s *) udp_defns[idx];
delete obj;
} else {
vvp_udp_comb_s *obj = (vvp_udp_comb_s *) udp_defns[idx];
delete obj;
}
}
free(udp_defns);
udp_defns = 0;
udp_defns_count = 0;
}
#endif
static symbol_table_t udp_table;
void delete_udp_symbols()
{
delete_symbol_table(udp_table);
udp_table = 0;
}
struct vvp_udp_s *udp_find(const char *label)
{
symbol_value_t v = sym_get_value(udp_table, label);
@ -49,8 +82,8 @@ ostream& operator <<(ostream&o, const struct udp_levels_table&table)
return o;
}
vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init)
: ports_(ports), init_(init)
vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init, bool type)
: ports_(ports), init_(init), seq_(type)
{
if (!udp_table)
udp_table = new_symbol_table();
@ -60,6 +93,13 @@ vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init)
symbol_value_t v;
v.ptr = this;
sym_set_value(udp_table, label, v);
#ifdef CHECK_WITH_VALGRIND
udp_defns_count += 1;
udp_defns = (vvp_udp_s **) realloc(udp_defns,
udp_defns_count*sizeof(vvp_udp_s **));
udp_defns[udp_defns_count-1] = this;
#endif
}
vvp_udp_s::~vvp_udp_s()
@ -77,7 +117,7 @@ vvp_bit4_t vvp_udp_s::get_init() const
}
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name, unsigned ports)
: vvp_udp_s(label, ports, BIT4_X)
: vvp_udp_s(label, ports, BIT4_X, false)
{
name_ = name;
levels0_ = 0;
@ -257,7 +297,7 @@ void vvp_udp_comb_s::compile_table(char**tab)
vvp_udp_seq_s::vvp_udp_seq_s(char*label, char*name,
unsigned ports, vvp_bit4_t init)
: vvp_udp_s(label, ports, init)
: vvp_udp_s(label, ports, init, true)
{
levels0_ = 0;
levels1_ = 0;

View File

@ -1,7 +1,7 @@
#ifndef __udp_H
#define __udp_H
/*
* Copyright (c) 2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2009 Stephen Williams (steve@icarus.com)
*
* (This is a rewrite of code that was ...
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>)
@ -31,13 +31,15 @@ struct udp_levels_table;
struct vvp_udp_s {
public:
explicit vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init);
explicit vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init,
bool type);
virtual ~vvp_udp_s();
// Return the number of input ports for the defined UDP. This
// does *not* include the current output value for a
// sequential UDP.
unsigned port_count() const;
bool is_sequential() const {return seq_;};
// Return the initial output value.
vvp_bit4_t get_init() const;
@ -49,6 +51,7 @@ struct vvp_udp_s {
private:
unsigned ports_;
vvp_bit4_t init_;
bool seq_;
};
/*

View File

@ -29,6 +29,7 @@
# include "vvp_net.h"
# include "schedule.h"
# include "event.h"
# include "config.h"
# include <stdio.h>
# include <assert.h>
#ifdef HAVE_MALLOC_H
@ -515,6 +516,17 @@ void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
vpi_callbacks_ = cb;
}
#ifdef CHECK_WITH_VALGRIND
void vvp_vpi_callback::clear_all_callbacks()
{
while (vpi_callbacks_) {
__vpiCallback*tmp = vpi_callbacks_->next;
delete_vpi_callback(vpi_callbacks_);
vpi_callbacks_ = tmp;
}
}
#endif
/*
* A vvp_fun_signal uses this method to run its callbacks whenever it
* has a value change. If the cb_rtn is non-nil, then call the

View File

@ -19,6 +19,10 @@
# include "vpi_priv.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>
@ -50,6 +54,11 @@ static int string_get(int code, vpiHandle ref)
case vpiAutomatic:
return 0;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
fprintf(stderr, "vvp error: get %d not supported "
"by vpiStringConst\n", code);
@ -181,7 +190,7 @@ static int free_temp_string(vpiHandle obj)
struct __vpiStringConst*rfp = (struct __vpiStringConst*)obj;
assert(obj->vpi_type->type_code == vpiConstant);
free(rfp->value);
delete [] rfp->value;
free(rfp);
return 1;
}
@ -356,6 +365,11 @@ static int binary_get(int code, vpiHandle ref)
case vpiAutomatic:
return 0;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
fprintf(stderr, "vvp error: get %d not supported "
"by vpiBinaryConst\n", code);
@ -552,6 +566,11 @@ static int dec_get(int code, vpiHandle ref)
case vpiAutomatic:
return 0;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
fprintf(stderr, "vvp error: get %d not supported "
"by vpiDecConst\n", code);
@ -658,6 +677,11 @@ static int real_get(int code, vpiHandle ref)
case vpiAutomatic:
return 0;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
fprintf(stderr, "vvp error: get %d not supported "
"by vpiDecConst\n", code);
@ -789,3 +813,55 @@ vpiHandle vpip_make_real_param(char*name, double value,
return &obj->base;
}
#ifdef CHECK_WITH_VALGRIND
void constant_delete(vpiHandle item)
{
assert(item->vpi_type->type_code == vpiConstant);
switch(vpi_get(vpiConstType, item)) {
case vpiStringConst: {
struct __vpiStringConst*rfp = (struct __vpiStringConst*)item;
delete [] rfp->value;
free(rfp);
break; }
case vpiDecConst: {
struct __vpiDecConst*rfp = (struct __vpiDecConst*)item;
free(rfp);
break; }
case vpiBinaryConst: {
struct __vpiBinaryConst*rfp = (struct __vpiBinaryConst*)item;
delete rfp;
break; }
case vpiRealConst: {
struct __vpiRealConst*rfp = (struct __vpiRealConst*)item;
free(rfp);
break; }
default:
assert(0);
}
}
void parameter_delete(vpiHandle item)
{
switch(vpi_get(vpiConstType, item)) {
case vpiStringConst: {
struct __vpiStringParam*rfp = (struct __vpiStringParam*)item;
delete [] rfp->basename;
delete [] rfp->value;
free(rfp);
break; }
case vpiBinaryConst: {
struct __vpiBinaryParam*rfp = (struct __vpiBinaryParam*)item;
delete [] rfp->basename;
delete rfp;
break; }
case vpiRealConst: {
struct __vpiRealParam*rfp = (struct __vpiRealParam*)item;
delete [] rfp->basename;
free(rfp);
break; }
default:
assert(0);
}
}
#endif

View File

@ -18,7 +18,10 @@
*/
# include "vpi_priv.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <assert.h>
# include <stdarg.h>
# include <stdio.h>
@ -68,6 +71,7 @@ void vpi_mcd_init(FILE *log)
logfile = log;
}
#ifdef CHECK_WITH_VALGRIND
void vpi_mcd_delete(void)
{
free(mcd_table[0].filename);
@ -86,6 +90,7 @@ void vpi_mcd_delete(void)
fd_table[2].filename = 0;
fd_table[2].fp = 0;
}
#endif
/*
* close one or more channels. we silently refuse to close the preopened ones.

View File

@ -20,14 +20,18 @@
# include "config.h"
# include "vpi_priv.h"
# include "ivl_dlfcn.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <stdio.h>
# include <string.h>
# include <sys/types.h>
# include <sys/stat.h>
#ifdef CHECK_WITH_VALGRIND
static ivl_dll_t*dll_list = 0;
static unsigned dll_list_cnt = 0;
#endif
typedef void (*vlog_startup_routines_t)(void);
@ -51,6 +55,7 @@ unsigned vpip_module_path_cnt = 0
#endif
;
#ifdef CHECK_WITH_VALGRIND
void load_module_delete(void)
{
for (unsigned idx = 0; idx < dll_list_cnt; idx += 1) {
@ -60,6 +65,7 @@ void load_module_delete(void)
dll_list = 0;
dll_list_cnt = 0;
}
#endif
void vpip_load_module(const char*name)
{
@ -156,10 +162,12 @@ void vpip_load_module(const char*name)
return;
}
#ifdef CHECK_WITH_VALGRIND
/* Add the dll to the list so it can be closed when we are done. */
dll_list_cnt += 1;
dll_list = (ivl_dll_t*)realloc(dll_list, dll_list_cnt*sizeof(ivl_dll_t));
dll_list[dll_list_cnt-1] = dll;
#endif
vpi_mode_flag = VPI_MODE_REGISTER;
vlog_startup_routines_t*routines = (vlog_startup_routines_t*)table;

View File

@ -22,7 +22,7 @@
# include "vpi_user.h"
# include "pointers.h"
# include "vvp_net.h"
# include "config.h"
/*
* Added to use some "vvp_fun_modpath_src"
@ -210,6 +210,9 @@ extern void vpip_make_root_iterator(struct __vpiHandle**&table,
*/
struct __vpiSignal {
struct __vpiHandle base;
#ifdef CHECK_WITH_VALGRIND
struct __vpiSignal *pool;
#endif
union { // The scope or parent array that contains me.
vpiHandle parent;
struct __vpiScope* scope;

View File

@ -21,6 +21,10 @@
# include "vpi_priv.h"
# include "symbols.h"
# include "statistics.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
@ -45,6 +49,70 @@ void vpip_make_root_iterator(struct __vpiHandle**&table, unsigned&ntable)
ntable = vpip_root_table_cnt;
}
#ifdef CHECK_WITH_VALGRIND
static void delete_sub_scopes(struct __vpiScope *scope)
{
for (unsigned idx = 0; idx < scope->nintern; idx += 1) {
struct __vpiScope*lscope = (__vpiScope*)(scope->intern)[idx];
switch(scope->intern[idx]->vpi_type->type_code) {
case vpiFunction:
case vpiTask:
contexts_delete(lscope);
case vpiModule:
case vpiNamedBegin:
case vpiNamedFork:
delete_sub_scopes(lscope);
vthreads_delete(lscope->threads);
delete (scope->intern)[idx];
break;
case vpiIntegerVar:
break;
case vpiMemory:
memory_delete((scope->intern)[idx]);
break;
case vpiModPath:
/* The destination ModPath is cleaned up later. */
free((scope->intern)[idx]);
break;
break;
case vpiNamedEvent:
named_event_delete((scope->intern)[idx]);
break;
case vpiNet:
case vpiReg:
signal_delete((scope->intern)[idx]);
break;
case vpiParameter:
parameter_delete((scope->intern)[idx]);
break;
case vpiRealVar:
free((scope->intern)[idx]);
break;
default:
fprintf(stderr, "Need support for type: %d\n",
scope->intern[idx]->vpi_type->type_code);
assert(0);
break;
}
}
free(scope->intern);
}
void root_table_delete(void)
{
for (unsigned idx = 0; idx < vpip_root_table_cnt; idx += 1) {
struct __vpiScope *scope = (__vpiScope *)vpip_root_table_ptr[idx];
delete_sub_scopes(scope);
vthreads_delete(scope->threads);
delete scope;
}
free(vpip_root_table_ptr);
vpip_root_table_ptr = 0;
vpip_root_table_cnt = 0;
}
#endif
static bool handle_is_scope(vpiHandle obj)
{
return (obj->vpi_type->type_code == vpiModule)

View File

@ -26,6 +26,10 @@
# include "vpi_priv.h"
# include "schedule.h"
# include "statistics.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <math.h>
# include <iostream>
# include <stdio.h>
@ -35,6 +39,9 @@
# include <stdlib.h>
# include <string.h>
# include <assert.h>
#ifdef CHECK_WITH_VALGRIND
# include <valgrind/memcheck.h>
#endif
/*
* Hex digits that represent 4-value bits of Verilog are not as
@ -889,6 +896,10 @@ vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
obj->vpi_type = &vpip_reg_rt;
return obj;
}
#ifdef CHECK_WITH_VALGRIND
static struct __vpiSignal **signal_pool = 0;
static unsigned signal_pool_count = 0;
#endif
static struct __vpiSignal* allocate_vpiSignal(void)
{
@ -900,13 +911,49 @@ static struct __vpiSignal* allocate_vpiSignal(void)
alloc_array = (struct __vpiSignal*)
calloc(alloc_count, sizeof(struct __vpiSignal));
alloc_index = 0;
#ifdef CHECK_WITH_VALGRIND
VALGRIND_MAKE_MEM_NOACCESS(alloc_array, alloc_count *
sizeof(struct __vpiSignal));
VALGRIND_CREATE_MEMPOOL(alloc_array, 0, 1);
signal_pool_count += 1;
signal_pool = (__vpiSignal **) realloc(signal_pool,
signal_pool_count*sizeof(__vpiSignal **));
signal_pool[signal_pool_count-1] = alloc_array;
#endif
}
struct __vpiSignal*cur = alloc_array + alloc_index;
#ifdef CHECK_WITH_VALGRIND
VALGRIND_MEMPOOL_ALLOC(alloc_array, cur, sizeof(struct __vpiSignal));
cur->pool = alloc_array;
#endif
alloc_index += 1;
return cur;
}
#ifdef CHECK_WITH_VALGRIND
void signal_delete(vpiHandle item)
{
struct __vpiSignal *obj = (__vpiSignal *) item;
vvp_fun_signal_base*sig_fun;
sig_fun = (vvp_fun_signal_base*) obj->node->fun;
sig_fun->clear_all_callbacks();
vvp_net_delete(obj->node);
VALGRIND_MEMPOOL_FREE(obj->pool, obj);
}
void signal_pool_delete()
{
for (unsigned idx = 0; idx < signal_pool_count; idx += 1) {
VALGRIND_DESTROY_MEMPOOL(signal_pool[idx]);
free(signal_pool[idx]);
}
free(signal_pool);
signal_pool = 0;
signal_pool_count = 0;
}
#endif
/*
* Construct a vpiNet object. Give the object specified dimensions,
* and point to the specified functor for the lsb.
@ -991,6 +1038,11 @@ static int PV_get(int code, vpiHandle ref)
case vpiAutomatic:
return vpi_get(vpiAutomatic, rfp->parent);
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpi_at_PV;
#endif
default:
fprintf(stderr, "PV_get: property %d is unknown\n", code);
}
@ -1235,3 +1287,14 @@ void vpip_part_select_value_change(struct __vpiCallback*cbh, vpiHandle ref)
/* Attach the __vpiCallback object to the signal. */
sig_fun->add_vpi_callback(cbh);
}
#ifdef CHECK_WITH_VALGRIND
void PV_delete(vpiHandle item)
{
struct __vpiPV *obj = (__vpiPV *) item;
vvp_fun_signal_base*sig_fun;
sig_fun = (vvp_fun_signal_base*) obj->net->fun;
sig_fun->clear_all_callbacks();
free(obj);
}
#endif

View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
*
* This source code is free software; you can redistribute it
@ -25,6 +25,11 @@
# include "vpi_priv.h"
# include "vthread.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
# include <map>
#endif
# include <stdio.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
@ -91,6 +96,11 @@ static int vthr_vec_get(int code, vpiHandle ref)
case vpiSize:
return rfp->wid;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiVThr;
#endif
default:
return 0;
}
@ -461,6 +471,21 @@ vpiHandle vpip_make_vthr_vector(unsigned base, unsigned wid, bool signed_flag)
return &obj->base;
}
#ifdef CHECK_WITH_VALGRIND
static map<vpiHandle, bool> handle_map;
void thread_vthr_delete(vpiHandle item)
{
handle_map[item] = true;
}
static void thread_vthr_delete_real(vpiHandle item)
{
struct __vpiVThrVec*obj = (struct __vpiVThrVec*)item;
free (obj);
}
#endif
struct __vpiVThrWord {
struct __vpiHandle base;
const char* name;
@ -479,6 +504,11 @@ static int vthr_word_get(int code, vpiHandle ref)
case vpiConstType:
return rfp->subtype;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiWord;
#endif
default:
return 0;
}
@ -581,3 +611,25 @@ vpiHandle vpip_make_vthr_word(unsigned base, const char*type)
return &obj->base;
}
#ifdef CHECK_WITH_VALGRIND
void thread_word_delete(vpiHandle item)
{
handle_map[item] = false;
}
static void thread_word_delete_real(vpiHandle item)
{
struct __vpiVThrWord*obj = (struct __vpiVThrWord*)item;
free(obj);
}
void vpi_handle_delete()
{
map<vpiHandle, bool>::iterator iter;
for (iter = handle_map.begin(); iter != handle_map.end(); iter++) {
if (iter->second) thread_vthr_delete_real(iter->first);
else thread_word_delete_real(iter->first);
}
}
#endif

View File

@ -20,7 +20,9 @@
# include "config.h"
# include "vpi_priv.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <stdio.h>
# include <string.h>
# include <limits.h> /* for CHAR_BIT */
@ -108,12 +110,14 @@ static inline int write_digits(unsigned long v, char **buf,
static unsigned long *valv=NULL;
static unsigned int vlen_alloc=0;
#ifdef CHECK_WITH_VALGRIND
void dec_str_delete(void)
{
free(valv);
valv = 0;
vlen_alloc = 0;
}
#endif
unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
char *buf, unsigned int nbuf,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -24,6 +24,9 @@
# include "ufunc.h"
# include "event.h"
# include "vpi_priv.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
@ -354,6 +357,23 @@ static void vthread_free_context(vvp_context_t context, struct __vpiScope*scope)
scope->free_contexts = context;
}
#ifdef CHECK_WITH_VALGRIND
void contexts_delete(struct __vpiScope*scope)
{
vvp_context_t context = scope->free_contexts;
while (context) {
scope->free_contexts = vvp_get_next_context(context);
for (unsigned idx = 0; idx < scope->nitem; idx += 1) {
scope->item[idx]->free_instance(context);
}
free(context);
context = scope->free_contexts;
}
free(scope->item);
}
#endif
/*
* Create a new thread with the given start address.
*/
@ -404,6 +424,51 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope)
return thr;
}
#ifdef CHECK_WITH_VALGRIND
#if 0
/*
* These are not currently correct. If you use them you will get
* double delete messages. There is still a leak related to a
* waiting event that needs to be investigated.
*/
static void wait_next_delete(vthread_t base)
{
while (base) {
vthread_t tmp = base->wait_next;
delete base;
base = tmp;
if (base->waiting_for_event == 0) break;
}
}
static void child_delete(vthread_t base)
{
while (base) {
vthread_t tmp = base->child;
delete base;
base = tmp;
}
}
#endif
void vthreads_delete(vthread_t base)
{
if (base == 0) return;
vthread_t cur = base->scope_next;
while (base != cur) {
vthread_t tmp = cur->scope_next;
// if (cur->waiting_for_event) wait_next_delete(cur->wait_next);
// child_delete(cur->child);
delete cur;
cur = tmp;
}
/* This is a stub so does not have a wait_next queue. */
delete base;
}
#endif
/*
* Reaping pulls the thread out of the stack of threads. If I have a
* child, then hand it over to my parent.

View File

@ -25,9 +25,30 @@
/* Routines used to cleanup the runtime memory when it is all finished. */
extern void codespace_delete(void);
extern void root_table_delete(void);
extern void def_table_delete(void);
extern void vpi_mcd_delete(void);
extern void dec_str_delete(void);
extern void load_module_delete(void);
extern void modpath_delete(void);
extern void signal_pool_delete(void);
extern void udp_defns_delete(void);
extern void vpi_handle_delete(void);
extern void vvp_net_pool_delete(void);
extern void A_delete(struct __vpiHandle *item);
extern void PV_delete(struct __vpiHandle *item);
extern void constant_delete(struct __vpiHandle *item);
extern void contexts_delete(struct __vpiScope *scope);
extern void memory_delete(struct __vpiHandle *item);
extern void named_event_delete(struct __vpiHandle *item);
extern void parameter_delete(struct __vpiHandle *item);
extern void signal_delete(struct __vpiHandle *item);
extern void thread_vthr_delete(struct __vpiHandle *item);
extern void thread_word_delete(struct __vpiHandle *item);
extern void vpi_call_delete(struct __vpiHandle *item);
extern void vthreads_delete(vthread_t base);
extern void vvp_net_delete(vvp_net_t *item);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -30,10 +30,18 @@
# include <limits.h>
# include <math.h>
# include <assert.h>
#ifdef CHECK_WITH_VALGRIND
# include <valgrind/memcheck.h>
# include <map>
#endif
// Allocate around 1Megbytes/chunk.
static const size_t VVP_NET_CHUNK = 1024*1024/sizeof(vvp_net_t);
static vvp_net_t*vvp_net_alloc_table = 0;
#ifdef CHECK_WITH_VALGRIND
static vvp_net_t **vvp_net_pool = 0;
static unsigned vvp_net_pool_count = 0;
#endif
static size_t vvp_net_alloc_remaining = 0;
// For statistics, count the vvp_nets allocated and the bytes of alloc
// chunks allocated.
@ -48,15 +56,53 @@ void* vvp_net_t::operator new (size_t size)
vvp_net_alloc_table = ::new vvp_net_t[VVP_NET_CHUNK];
vvp_net_alloc_remaining = VVP_NET_CHUNK;
size_vvp_nets += size*VVP_NET_CHUNK;
#ifdef CHECK_WITH_VALGRIND
VALGRIND_MAKE_MEM_NOACCESS(vvp_net_alloc_table, size*VVP_NET_CHUNK);
VALGRIND_CREATE_MEMPOOL(vvp_net_alloc_table, 0, 0);
vvp_net_pool_count += 1;
vvp_net_pool = (vvp_net_t **) realloc(vvp_net_pool,
vvp_net_pool_count*sizeof(vvp_net_t **));
vvp_net_pool[vvp_net_pool_count-1] = vvp_net_alloc_table;
#endif
}
vvp_net_t*return_this = vvp_net_alloc_table;
#ifdef CHECK_WITH_VALGRIND
VALGRIND_MEMPOOL_ALLOC(vvp_net_pool[vvp_net_pool_count-1],
return_this, size);
return_this->pool = vvp_net_pool[vvp_net_pool_count-1];
#endif
vvp_net_alloc_table += 1;
vvp_net_alloc_remaining -= 1;
count_vvp_nets += 1;
return return_this;
}
#ifdef CHECK_WITH_VALGRIND
static map<vvp_net_t*, bool> vvp_net_map;
void vvp_net_delete(vvp_net_t *item)
{
vvp_net_map[item] = true;
}
void vvp_net_pool_delete()
{
map<vvp_net_t*, bool>::iterator iter;
for (iter = vvp_net_map.begin(); iter != vvp_net_map.end(); iter++) {
VALGRIND_MEMPOOL_FREE(iter->first->pool, iter->first);
}
for (unsigned idx = 0; idx < vvp_net_pool_count; idx += 1) {
VALGRIND_DESTROY_MEMPOOL(vvp_net_pool[idx])
::delete [] vvp_net_pool[idx];
}
free(vvp_net_pool);
vvp_net_pool = 0;
vvp_net_pool_count = 0;
}
#endif
void vvp_net_t::operator delete(void*)
{
assert(0);
@ -1486,6 +1532,15 @@ void vvp_vector4array_aa::reset_instance(vvp_context_t context)
}
}
#ifdef CHECK_WITH_VALGRIND
void vvp_vector4array_aa::free_instance(vvp_context_t context)
{
v4cell*cell = static_cast<v4cell*>
(vvp_get_context_item(context, context_idx_));
delete [] cell;
}
#endif
void vvp_vector4array_aa::set_word(unsigned index, const vvp_vector4_t&that)
{
assert(index < words_);
@ -2754,6 +2809,15 @@ void vvp_fun_signal4_aa::reset_instance(vvp_context_t context)
bits->set_to_x();
}
#ifdef CHECK_WITH_VALGRIND
void vvp_fun_signal4_aa::free_instance(vvp_context_t context)
{
vvp_vector4_t*bits = static_cast<vvp_vector4_t*>
(vvp_get_context_item(context, context_idx_));
delete bits;
}
#endif
/*
* Continuous and forced assignments are not permitted on automatic
* variables. So we only expect to receive on port 0.
@ -3114,6 +3178,15 @@ void vvp_fun_signal_real_aa::reset_instance(vvp_context_t context)
*bits = 0.0;
}
#ifdef CHECK_WITH_VALGRIND
void vvp_fun_signal_real_aa::free_instance(vvp_context_t context)
{
double*bits = static_cast<double*>
(vvp_get_context_item(context, context_idx_));
delete bits;
}
#endif
double vvp_fun_signal_real_aa::real_value() const
{
double*bits = static_cast<double*>

View File

@ -1,7 +1,7 @@
#ifndef __vvp_net_H
#define __vvp_net_H
/*
* Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -110,6 +110,9 @@ struct automatic_hooks_s {
virtual void alloc_instance(vvp_context_t context) = 0;
virtual void reset_instance(vvp_context_t context) = 0;
#ifdef CHECK_WITH_VALGRIND
virtual void free_instance(vvp_context_t context) = 0;
#endif
};
/*
@ -552,6 +555,9 @@ class vvp_vector4array_aa : public vvp_vector4array_t, public automatic_hooks_s
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
vvp_vector4_t get_word(unsigned idx) const;
void set_word(unsigned idx, const vvp_vector4_t&that);
@ -958,6 +964,9 @@ template <class T> ostream& operator << (ostream&out, vvp_sub_pointer_t<T> val)
* all the fan-out chain, delivering the specified value.
*/
struct vvp_net_t {
#ifdef CHECK_WITH_VALGRIND
vvp_net_t *pool;
#endif
vvp_net_ptr_t port[4];
vvp_net_ptr_t out;
vvp_net_fun_t*fun;
@ -1194,6 +1203,10 @@ class vvp_vpi_callback {
virtual void run_vpi_callbacks();
void add_vpi_callback(struct __vpiCallback*);
#ifdef CHECK_WITH_VALGRIND
/* This has only been tested at EOS. */
void clear_all_callbacks(void);
#endif
virtual void get_value(struct t_vpi_value*value) =0;
@ -1315,6 +1328,9 @@ class vvp_fun_signal4_aa : public vvp_fun_signal4, public automatic_hooks_s {
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t context);
@ -1421,6 +1437,9 @@ class vvp_fun_signal_real_aa : public vvp_fun_signal_real, public automatic_hook
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
#ifdef CHECK_WITH_VALGRIND
void free_instance(vvp_context_t context);
#endif
void recv_real(vvp_net_ptr_t port, double bit,
vvp_context_t context);