diff --git a/configure.in b/configure.in index 71fcc1629..545518962 100644 --- a/configure.in +++ b/configure.in @@ -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 ])])]) + AC_MSG_CHECKING(for sys/times) AC_TRY_LINK( #include diff --git a/vpi_user.h b/vpi_user.h index f1157e1ac..d851b57d6 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -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 diff --git a/vvp/array.cc b/vvp/array.cc index a303e96d2..5fff2c28a 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -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 #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 + (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 diff --git a/vvp/codes.cc b/vvp/codes.cc index 7499e071d..54bbd4d6c 100644 --- a/vvp/codes.cc +++ b/vvp/codes.cc @@ -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 # include @@ -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 diff --git a/vvp/compile.cc b/vvp/compile.cc index 8fdbb5401..d73b7062e 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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(); diff --git a/vvp/compile.h b/vvp/compile.h index d8c5c7e89..c28036755 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -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 diff --git a/vvp/config.h.in b/vvp/config.h.in index 0a41bd44f..ef94b3202 100644 --- a/vvp/config.h.in +++ b/vvp/config.h.in @@ -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 diff --git a/vvp/delay.cc b/vvp/delay.cc index 66f3a0ffe..31b30367a 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2008 Stephen Williams + * Copyright (c) 2005-2009 Stephen Williams * * 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 #include #include @@ -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 diff --git a/vvp/event.cc b/vvp/event.cc index a51a711aa..f1f52c0cf 100644 --- a/vvp/event.cc +++ b/vvp/event.cc @@ -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 # include # include @@ -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_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_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 @@ -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 + (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 @@ -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 + (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 @@ -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 diff --git a/vvp/event.h b/vvp/event.h index 8a769d8af..7700f4329 100644 --- a/vvp/event.h +++ b/vvp/event.h @@ -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); diff --git a/vvp/main.cc b/vvp/main.cc index 979c34048..c55c4da17 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -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::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; } diff --git a/vvp/part.cc b/vvp/part.cc index 0db98b927..f3d98836e 100644 --- a/vvp/part.cc +++ b/vvp/part.cc @@ -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_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_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) { diff --git a/vvp/part.h b/vvp/part.h index b6ff2bf10..687b76063 100644 --- a/vvp/part.h +++ b/vvp/part.h @@ -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); diff --git a/vvp/udp.cc b/vvp/udp.cc index eb838b8e4..1fcb6e4a6 100644 --- a/vvp/udp.cc +++ b/vvp/udp.cc @@ -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 #ifdef HAVE_MALLOC_H #include @@ -33,8 +37,37 @@ #include #include +// 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; diff --git a/vvp/udp.h b/vvp/udp.h index 80c5d0648..70ab30a64 100644 --- a/vvp/udp.h +++ b/vvp/udp.h @@ -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 ) @@ -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_; }; /* diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 4ddc08d50..90f0f3926 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -29,6 +29,7 @@ # include "vvp_net.h" # include "schedule.h" # include "event.h" +# include "config.h" # include # include #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 diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index c802170a4..0773a4377 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -19,6 +19,10 @@ # include "vpi_priv.h" # include "compile.h" +# include "config.h" +#ifdef CHECK_WITH_VALGRIND +# include "vvp_cleanup.h" +#endif # include #ifdef HAVE_MALLOC_H # include @@ -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 diff --git a/vvp/vpi_mcd.cc b/vvp/vpi_mcd.cc index 0994637b7..57cc55557 100644 --- a/vvp/vpi_mcd.cc +++ b/vvp/vpi_mcd.cc @@ -18,7 +18,10 @@ */ # include "vpi_priv.h" +# include "config.h" +#ifdef CHECK_WITH_VALGRIND # include "vvp_cleanup.h" +#endif # include # include # include @@ -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. diff --git a/vvp/vpi_modules.cc b/vvp/vpi_modules.cc index 7e509a19b..7997ff24b 100644 --- a/vvp/vpi_modules.cc +++ b/vvp/vpi_modules.cc @@ -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 # include # include # include +#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; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 78f7de203..9870811e0 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -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; diff --git a/vvp/vpi_scope.cc b/vvp/vpi_scope.cc index 2875a1ce9..3aafd2bb9 100644 --- a/vvp/vpi_scope.cc +++ b/vvp/vpi_scope.cc @@ -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 #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) diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index b70974f1b..3944438d6 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -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 # include # include @@ -35,6 +39,9 @@ # include # include # include +#ifdef CHECK_WITH_VALGRIND +# include +#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 diff --git a/vvp/vpi_tasks.cc b/vvp/vpi_tasks.cc index ba9d94fd5..8614a7787 100644 --- a/vvp/vpi_tasks.cc +++ b/vvp/vpi_tasks.cc @@ -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 #ifdef HAVE_MALLOC_H # include @@ -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 diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index a0af6a223..6852f55a7 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -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 * * 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 +#endif # include #ifdef HAVE_MALLOC_H # include @@ -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 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::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 diff --git a/vvp/vpip_to_dec.cc b/vvp/vpip_to_dec.cc index 7816db438..a34a3b0a0 100644 --- a/vvp/vpip_to_dec.cc +++ b/vvp/vpip_to_dec.cc @@ -20,7 +20,9 @@ # include "config.h" # include "vpi_priv.h" +#ifdef CHECK_WITH_VALGRIND # include "vvp_cleanup.h" +#endif # include # include # include /* 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, diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 776c80af1..bdd41263d 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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 #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. diff --git a/vvp/vvp_cleanup.h b/vvp/vvp_cleanup.h index 228ed8613..bd7f21bdd 100644 --- a/vvp/vvp_cleanup.h +++ b/vvp/vvp_cleanup.h @@ -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 diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 3f8a3acf2..2be14fbba 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -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 # include # include +#ifdef CHECK_WITH_VALGRIND +# include +# include +#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_map; + +void vvp_net_delete(vvp_net_t *item) +{ + vvp_net_map[item] = true; +} + +void vvp_net_pool_delete() +{ + map::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 + (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_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 + (vvp_get_context_item(context, context_idx_)); + delete bits; +} +#endif + double vvp_fun_signal_real_aa::real_value() const { double*bits = static_cast diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 03cd8a288..55fcf987a 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -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 ostream& operator << (ostream&out, vvp_sub_pointer_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);