diff --git a/vvp/main.cc b/vvp/main.cc index e503c3ba5..d500b611e 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -274,7 +274,8 @@ int main(int argc, char*argv[]) } if (verbose_flag) { - vpi_mcd_printf(1, " ... %8lu functors\n", count_functors); + vpi_mcd_printf(1, " ... %8lu functors (net_fun pool=%zu bytes)\n", + count_functors, size_vvp_net_funs); vpi_mcd_printf(1, " %8lu logic\n", count_functors_logic); vpi_mcd_printf(1, " %8lu bufif\n", count_functors_bufif); vpi_mcd_printf(1, " %8lu resolv\n",count_functors_resolv); diff --git a/vvp/statistics.h b/vvp/statistics.h index 120021459..71cc39c98 100644 --- a/vvp/statistics.h +++ b/vvp/statistics.h @@ -46,5 +46,6 @@ extern unsigned long count_gen_pool(void); extern size_t size_opcodes; extern size_t size_vvp_nets; +extern size_t size_vvp_net_funs; #endif diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 883cc4640..662d9b058 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -38,6 +38,7 @@ static size_t vvp_net_alloc_remaining = 0; // chunks allocated. unsigned long count_vvp_nets = 0; size_t size_vvp_nets = 0; +size_t size_vvp_net_funs = 0; void* vvp_net_t::operator new (size_t size) { @@ -54,7 +55,45 @@ void* vvp_net_t::operator new (size_t size) count_vvp_nets += 1; return return_this; } - + +void* vvp_net_fun_t::operator new(size_t size) +{ + // Link in an initial chunk of space for net_fun_t + // objects. This chunk doesn't need to be the same size as the + // subsequent chunks, but we do need to make sure it is + // aligned with pointer alignment. (Hence the union with "align".) + static union { void*align; char bytes[512*1024]; } initial_chunk; + + // Initialize the pointer to the initial chunk. + static char*chunk_ptr = initial_chunk.bytes; + static size_t chunk_remaining = sizeof(initial_chunk); + + // Once the initial chunk fills up, allocate new chunks in + // fairly large blocks to reduce the system allocator + // overhead, but not such big chunks that we create our own + // waste. (Expect the typical waste to be CHUNK_BYTES/2.) + const size_t CHUNK_BYTES = 256*1024; + + if (size > chunk_remaining) { + chunk_ptr = ::new char[CHUNK_BYTES]; + chunk_remaining = CHUNK_BYTES; + size_vvp_net_funs += CHUNK_BYTES; + } + + assert( (size%sizeof(void*)) == 0 ); + + void*res = chunk_ptr; + chunk_ptr += size; + chunk_remaining -= size; + + return res; +} + +void vvp_net_fun_t::operator delete(void*) +{ + assert(0); +} + /* *** BIT operations *** */ vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c) { diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index fbed7bf09..0caa36887 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -809,9 +809,14 @@ class vvp_net_fun_t { virtual void recv_long_pv(vvp_net_ptr_t port, long bit, unsigned base, unsigned wid); + public: // These objects are only permallocated. + static void* operator new(std::size_t size); + static void operator delete(void*); // not implemented private: // not implemented vvp_net_fun_t(const vvp_net_fun_t&); vvp_net_fun_t& operator= (const vvp_net_fun_t&); + static void* operator new[](std::size_t size); + static void operator delete[](void*); }; /* **** Some core net functions **** */