Unify some duplicated heap management.

Create the permaheap class to hold common code from the vvp_net_fun_t
and vvp_net_fil_t classes.
This commit is contained in:
Stephen Williams 2009-09-30 22:10:35 -07:00
parent 5a96b397e4
commit d64b1f0275
10 changed files with 125 additions and 74 deletions

View File

@ -73,8 +73,8 @@ vpip_to_dec.o vpip_format.o vvp_vpi.o
O = main.o parse.o parse_misc.o lexor.o arith.o array.o bufif.o compile.o \
concat.o \
dff.o extend.o npmos.o part.o reduce.o resolv.o sfunc.o stop.o symbols.o \
ufunc.o codes.o \
dff.o extend.o npmos.o part.o permaheap.o reduce.o resolv.o sfunc.o stop.o \
symbols.o ufunc.o codes.o \
vthread.o schedule.o statistics.o tables.o udp.o vvp_island.o vvp_net.o \
vvp_net_sig.o event.o logic.o delay.o words.o island_tran.o $V

View File

@ -373,11 +373,13 @@ int main(int argc, char*argv[])
if (verbose_flag) {
vpi_mcd_printf(1, " ... %8lu functors (net_fun pool=%zu bytes)\n",
count_functors, size_vvp_net_funs);
count_functors, vvp_net_fun_t::heap_total());
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);
vpi_mcd_printf(1, " %8lu signals\n", count_functors_sig);
vpi_mcd_printf(1, " ... %8lu filters (net_fil pool=%zu bytes)\n",
count_filters, vvp_net_fil_t::heap_total());
vpi_mcd_printf(1, " ... %8lu opcodes (%zu bytes)\n",
count_opcodes, size_opcodes);
vpi_mcd_printf(1, " ... %8lu nets\n", count_vpi_nets);

52
vvp/permaheap.cc Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "permaheap.h"
# include <assert.h>
permaheap::permaheap()
{
chunk_ptr_ = initial_chunk_.bytes;
chunk_remaining_ = sizeof(initial_chunk_);
heap_total_ = chunk_remaining_;
}
permaheap::~permaheap()
{
}
void* permaheap::alloc(size_t size)
{
assert(size <= CHUNK_SIZE);
if (size > chunk_remaining_) {
chunk_ptr_ = ::new char[CHUNK_SIZE];
chunk_remaining_ = CHUNK_SIZE;
heap_total_ += CHUNK_SIZE;
}
assert( (size%sizeof(void*)) == 0 );
void*res = chunk_ptr_;
chunk_ptr_ += size;
chunk_remaining_ -= size;
return res;
}

47
vvp/permaheap.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef __permaheap_H
#define __permaheap_H
/*
* Copyright (c) 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <stdlib.h>
class permaheap {
public:
explicit permaheap();
~permaheap();
void* alloc(size_t size);
size_t heap_total() const { return heap_total_; }
private:
enum { INITIAL_CHUNK_SIZE = 512*1024, CHUNK_SIZE=256*1024 };
union {
void*align;
char bytes[INITIAL_CHUNK_SIZE];
} initial_chunk_;
char*chunk_ptr_;
size_t chunk_remaining_;
size_t heap_total_;
};
#endif

View File

@ -30,6 +30,7 @@ unsigned long count_functors_bufif = 0;
unsigned long count_functors_resolv= 0;
unsigned long count_functors_sig = 0;
unsigned long count_filters = 0;
unsigned long count_vpi_nets = 0;
unsigned long count_vpi_scopes = 0;

View File

@ -27,6 +27,7 @@ extern unsigned long count_functors_logic;
extern unsigned long count_functors_bufif;
extern unsigned long count_functors_resolv;
extern unsigned long count_functors_sig;
extern unsigned long count_filters;
extern unsigned long count_vvp_nets;
extern unsigned long count_vpi_nets;
extern unsigned long count_vpi_scopes;

View File

@ -35,6 +35,9 @@
# include <map>
#endif
permaheap vvp_net_fun_t::heap_;
permaheap vvp_net_fil_t::heap_;
// 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;
@ -47,7 +50,6 @@ 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)
{
@ -156,39 +158,6 @@ void vvp_net_t::unlink(vvp_net_ptr_t dst_ptr)
net->port[net_port] = vvp_net_ptr_t(0,0);
}
void* vvp_net_fun_t::permalloc(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);
@ -199,6 +168,7 @@ vvp_net_fil_t::vvp_net_fil_t()
{
force_link_ = 0;
force_propagate_ = false;
count_filters += 1;
}
vvp_net_fil_t::~vvp_net_fil_t()
@ -291,38 +261,6 @@ void vvp_net_fil_t::force_link(vvp_net_t*dst, vvp_net_t*src)
src->link(dst_ptr);
}
void*vvp_net_fil_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;
}
assert( (size%sizeof(void*)) == 0 );
void*res = chunk_ptr;
chunk_ptr += size;
chunk_remaining -= size;
return res;
}
void vvp_net_fil_t::operator delete(void*)
{
assert(0);

View File

@ -22,6 +22,7 @@
# include "config.h"
# include "vpi_user.h"
# include "vvp_vpi_callback.h"
# include "permaheap.h"
# include <stddef.h>
# include <stdlib.h>
# include <string.h>
@ -1093,10 +1094,13 @@ class vvp_net_fun_t {
unsigned base, unsigned wid);
public: // These objects are only permallocated.
static void* operator new(std::size_t size) { return permalloc(size); }
static void* operator new(std::size_t size) { return heap_.alloc(size); }
static void operator delete(void*); // not implemented
static std::size_t heap_total() { return heap_.heap_total(); }
protected:
static void* permalloc(std::size_t size);
static permaheap heap_;
private: // not implemented
vvp_net_fun_t(const vvp_net_fun_t&);
@ -1157,8 +1161,14 @@ class vvp_net_fil_t : public vvp_vpi_callback {
virtual void force_fil_real(double val, vvp_vector2_t mask) =0;
public: // These objects are only permallocated.
static void* operator new(std::size_t size);
static void* operator new(std::size_t size) { return heap_.alloc(size); }
static void operator delete(void*); // not implemented
static size_t heap_total() { return heap_.heap_total(); }
private:
static permaheap heap_;
private: // not implemented
vvp_net_fil_t(const vvp_net_fil_t&);
vvp_net_fil_t& operator= (const vvp_net_fil_t&);

View File

@ -604,7 +604,7 @@ vvp_vector4_t vvp_fun_signal_real_aa::vec4_value() const
void* vvp_fun_signal_real_aa::operator new(std::size_t size)
{
return vvp_net_fun_t::permalloc(size);
return vvp_net_fun_t::heap_.alloc(size);
}
void vvp_fun_signal_real_aa::operator delete(void*)

View File

@ -186,7 +186,7 @@ class vvp_fun_signal4_aa : public vvp_fun_signal_vec, public automatic_signal_ba
vvp_vector4_t vec4_unfiltered_value() const;
public: // These objects are only permallocated.
static void* operator new(std::size_t size) { return permalloc(size); }
static void* operator new(std::size_t size) { return vvp_net_fun_t::heap_.alloc(size); }
static void operator delete(void*obj);
private: