Optimize code generator scope access / tweak ivl_net_const performance
Child scopes need to be accessed quickly, so use O(LogN) maps for the children instead of O(N) lists. Also, ivl_net_const_s objects exist in huge abundance for some kinds of designs, so put some effort into reducing their memory footprint.
This commit is contained in:
parent
534207bb83
commit
7311047f80
|
|
@ -1606,8 +1606,9 @@ extern "C" int ivl_scope_children(ivl_scope_t net,
|
||||||
ivl_scope_f func,
|
ivl_scope_f func,
|
||||||
void*cd)
|
void*cd)
|
||||||
{
|
{
|
||||||
for (ivl_scope_t cur = net->child_; cur; cur = cur->sibling_) {
|
for (map<hname_t,ivl_scope_t>::iterator cur = net->children.begin()
|
||||||
int rc = func(cur, cd);
|
; cur != net->children.end() ; cur ++) {
|
||||||
|
int rc = func(cur->second, cd);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
81
t-dll.cc
81
t-dll.cc
|
|
@ -110,23 +110,29 @@ inline const char*dlerror(void)
|
||||||
* permanently allocated, and allocating them in blocks reduces the
|
* permanently allocated, and allocating them in blocks reduces the
|
||||||
* allocation overhead.
|
* allocation overhead.
|
||||||
*/
|
*/
|
||||||
static struct ivl_nexus_s * nexus_pool_ptr = 0;
|
|
||||||
static int nexus_pool_remaining = 0;
|
template <class TYPE> void* pool_permalloc(size_t s)
|
||||||
static const size_t NEXUS_POOL_SIZE = 4096;
|
{
|
||||||
|
static TYPE * pool_ptr = 0;
|
||||||
|
static int pool_remaining = 0;
|
||||||
|
static const size_t POOL_SIZE = 4096;
|
||||||
|
|
||||||
|
assert(s == sizeof(TYPE));
|
||||||
|
if (pool_remaining <= 0) {
|
||||||
|
pool_ptr = new TYPE[POOL_SIZE];
|
||||||
|
pool_remaining = POOL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE*tmp = pool_ptr;
|
||||||
|
pool_ptr += 1;
|
||||||
|
pool_remaining -= 1;
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
void* ivl_nexus_s::operator new(size_t s)
|
void* ivl_nexus_s::operator new(size_t s)
|
||||||
{
|
{
|
||||||
assert(s == sizeof(struct ivl_nexus_s));
|
return pool_permalloc<struct ivl_nexus_s>(s);
|
||||||
if (nexus_pool_remaining <= 0) {
|
|
||||||
nexus_pool_ptr = new struct ivl_nexus_s[NEXUS_POOL_SIZE];
|
|
||||||
nexus_pool_remaining = NEXUS_POOL_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ivl_nexus_s*tmp = nexus_pool_ptr;
|
|
||||||
nexus_pool_ptr += 1;
|
|
||||||
nexus_pool_remaining -= 1;
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ivl_nexus_s::operator delete(void*, size_t)
|
void ivl_nexus_s::operator delete(void*, size_t)
|
||||||
|
|
@ -134,6 +140,18 @@ void ivl_nexus_s::operator delete(void*, size_t)
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* ivl_net_const_s::operator new(size_t s)
|
||||||
|
{
|
||||||
|
return pool_permalloc<struct ivl_net_const_s>(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ivl_net_const_s::operator delete(void*, size_t)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static StringHeapLex net_const_strings;
|
||||||
|
|
||||||
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||||
{
|
{
|
||||||
inst += strlen(ivl_scope_name(scope));
|
inst += strlen(ivl_scope_name(scope));
|
||||||
|
|
@ -227,19 +245,19 @@ ivl_attribute_s* dll_target::fill_in_attributes(const Attrib*net)
|
||||||
*/
|
*/
|
||||||
static ivl_scope_t find_scope_from_root(ivl_scope_t root, const NetScope*cur)
|
static ivl_scope_t find_scope_from_root(ivl_scope_t root, const NetScope*cur)
|
||||||
{
|
{
|
||||||
ivl_scope_t parent, tmp;
|
|
||||||
perm_string cur_name = make_scope_name(cur->fullname());
|
|
||||||
|
|
||||||
if (const NetScope*par = cur->parent()) {
|
if (const NetScope*par = cur->parent()) {
|
||||||
parent = find_scope_from_root(root, par);
|
ivl_scope_t parent = find_scope_from_root(root, par);
|
||||||
if (parent == 0)
|
if (parent == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (tmp = parent->child_ ; tmp ; tmp = tmp->sibling_)
|
map<hname_t,ivl_scope_t>::iterator idx = parent->children.find(cur->fullname());
|
||||||
if (strcmp(tmp->name_, cur_name) == 0)
|
if (idx == parent->children.end())
|
||||||
return tmp;
|
return 0;
|
||||||
|
else
|
||||||
|
return idx->second;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
perm_string cur_name = make_scope_name(cur->fullname());
|
||||||
if (strcmp(root->name_, cur_name) == 0)
|
if (strcmp(root->name_, cur_name) == 0)
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
@ -559,8 +577,6 @@ void dll_target::add_root(ivl_design_s &des__, const NetScope *s)
|
||||||
perm_string name = s->basename();
|
perm_string name = s->basename();
|
||||||
root_->name_ = name;
|
root_->name_ = name;
|
||||||
FILE_NAME(root_, s);
|
FILE_NAME(root_, s);
|
||||||
root_->child_ = 0;
|
|
||||||
root_->sibling_ = 0;
|
|
||||||
root_->parent = 0;
|
root_->parent = 0;
|
||||||
root_->nsigs_ = 0;
|
root_->nsigs_ = 0;
|
||||||
root_->sigs_ = 0;
|
root_->sigs_ = 0;
|
||||||
|
|
@ -2267,6 +2283,8 @@ bool dll_target::net_const(const NetConst*net)
|
||||||
{
|
{
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
char*bits;
|
char*bits;
|
||||||
|
static char*bits_tmp = 0;
|
||||||
|
static size_t bits_cnt = 0;
|
||||||
|
|
||||||
struct ivl_net_const_s *obj = new struct ivl_net_const_s;
|
struct ivl_net_const_s *obj = new struct ivl_net_const_s;
|
||||||
|
|
||||||
|
|
@ -2281,8 +2299,11 @@ bool dll_target::net_const(const NetConst*net)
|
||||||
bits = obj->b.bit_;
|
bits = obj->b.bit_;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
obj->b.bits_ = (char*)malloc(obj->width_);
|
if (obj->width_+1 > bits_cnt) {
|
||||||
bits = obj->b.bits_;
|
bits_tmp = (char*)realloc(bits_tmp, obj->width_+1);
|
||||||
|
bits_cnt = obj->width_+1;
|
||||||
|
}
|
||||||
|
bits = bits_tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (idx = 0 ; idx < obj->width_ ; idx += 1)
|
for (idx = 0 ; idx < obj->width_ ; idx += 1)
|
||||||
|
|
@ -2305,6 +2326,11 @@ bool dll_target::net_const(const NetConst*net)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->width_ > sizeof(obj->b.bit_)) {
|
||||||
|
bits[obj->width_] = 0;
|
||||||
|
obj->b.bits_ = net_const_strings.make(bits);
|
||||||
|
}
|
||||||
|
|
||||||
/* Connect to all the nexus objects. Note that the one-bit
|
/* Connect to all the nexus objects. Note that the one-bit
|
||||||
case can be handled more efficiently without allocating
|
case can be handled more efficiently without allocating
|
||||||
array space. */
|
array space. */
|
||||||
|
|
@ -2375,8 +2401,6 @@ void dll_target::scope(const NetScope*net)
|
||||||
scop = new struct ivl_scope_s;
|
scop = new struct ivl_scope_s;
|
||||||
scop->name_ = sname;
|
scop->name_ = sname;
|
||||||
FILE_NAME(scop, net);
|
FILE_NAME(scop, net);
|
||||||
scop->child_ = 0;
|
|
||||||
scop->sibling_ = 0;
|
|
||||||
scop->parent = find_scope(des_, net->parent());
|
scop->parent = find_scope(des_, net->parent());
|
||||||
assert(scop->parent);
|
assert(scop->parent);
|
||||||
scop->nsigs_ = 0;
|
scop->nsigs_ = 0;
|
||||||
|
|
@ -2433,8 +2457,7 @@ void dll_target::scope(const NetScope*net)
|
||||||
|
|
||||||
assert(scop->parent != 0);
|
assert(scop->parent != 0);
|
||||||
|
|
||||||
scop->sibling_= scop->parent->child_;
|
scop->parent->children[net->fullname()] = scop;
|
||||||
scop->parent->child_ = scop;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
16
t-dll.h
16
t-dll.h
|
|
@ -25,6 +25,7 @@
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include <vector>
|
# include <vector>
|
||||||
|
# include <map>
|
||||||
|
|
||||||
#if defined(__MINGW32__)
|
#if defined(__MINGW32__)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
@ -426,19 +427,21 @@ struct ivl_lval_s {
|
||||||
* structural context.
|
* structural context.
|
||||||
*/
|
*/
|
||||||
struct ivl_net_const_s {
|
struct ivl_net_const_s {
|
||||||
ivl_variable_type_t type;
|
ivl_variable_type_t type : 3;
|
||||||
unsigned width_;
|
unsigned width_ : 24;
|
||||||
unsigned signed_ : 1;
|
unsigned signed_ : 1;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
double real_value;
|
double real_value;
|
||||||
char bit_[sizeof(char*)];
|
char bit_[sizeof(char*)];
|
||||||
char *bits_;
|
const char* bits_;
|
||||||
} b;
|
} b;
|
||||||
|
|
||||||
ivl_nexus_t pin_;
|
ivl_nexus_t pin_;
|
||||||
|
|
||||||
ivl_expr_t delay[3];
|
ivl_expr_t delay[3];
|
||||||
|
|
||||||
|
void* operator new (size_t s);
|
||||||
|
void operator delete(void*obj, size_t s); // Not implemented
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -577,7 +580,8 @@ struct ivl_process_s {
|
||||||
* there.
|
* there.
|
||||||
*/
|
*/
|
||||||
struct ivl_scope_s {
|
struct ivl_scope_s {
|
||||||
ivl_scope_t child_, sibling_, parent;
|
ivl_scope_t parent;
|
||||||
|
std::map<hname_t,ivl_scope_t> children;
|
||||||
|
|
||||||
perm_string name_;
|
perm_string name_;
|
||||||
perm_string tname_;
|
perm_string tname_;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue