Added a phashmap_t object for faster lookups. (nw)

This commit is contained in:
couriersud 2015-07-18 20:05:52 +02:00
parent f6ea498ecf
commit 1c9b70aabd
4 changed files with 164 additions and 45 deletions

View File

@ -136,27 +136,6 @@ device_t *setup_t::register_dev(const pstring &classname, const pstring &name)
} }
} }
void setup_t::remove_dev(const pstring &name)
{
device_t *dev = netlist().m_devices.find_by_name(name);
pstring temp = name + ".";
if (dev == NULL)
netlist().error("Device %s does not exist\n", name.cstr());
remove_start_with<tagmap_terminal_t>(m_terminals, temp);
remove_start_with<tagmap_param_t>(m_params, temp);
const link_t *p = m_links.data();
while (p != NULL)
{
const link_t *n = p+1;
if (temp.equals(p->e1.substr(0,temp.len())) || temp.equals(p->e2.substr(0,temp.len())))
m_links.remove(*p);
p = n;
}
netlist().m_devices.remove_by_name(name);
}
void setup_t::register_model(const pstring &model) void setup_t::register_model(const pstring &model)
{ {
m_models.add(model); m_models.add(model);
@ -164,7 +143,7 @@ void setup_t::register_model(const pstring &model)
void setup_t::register_alias_nofqn(const pstring &alias, const pstring &out) void setup_t::register_alias_nofqn(const pstring &alias, const pstring &out)
{ {
if (!(m_alias.add(link_t(alias, out), false)==true)) if (!m_alias.add(alias, out))
netlist().error("Error adding alias %s to alias list\n", alias.cstr()); netlist().error("Error adding alias %s to alias list\n", alias.cstr());
} }
@ -266,9 +245,9 @@ void setup_t::register_object(device_t &dev, const pstring &name, object_t &obj)
{ {
param_t &param = dynamic_cast<param_t &>(obj); param_t &param = dynamic_cast<param_t &>(obj);
//printf("name: %s\n", name.cstr()); //printf("name: %s\n", name.cstr());
const pstring val = m_params_temp.find_by_name(name).e2; if (m_params_temp.contains(name))
if (val != "")
{ {
const pstring val = m_params_temp[name];
switch (param.param_type()) switch (param.param_type())
{ {
case param_t::DOUBLE: case param_t::DOUBLE:
@ -302,7 +281,7 @@ void setup_t::register_object(device_t &dev, const pstring &name, object_t &obj)
netlist().error("Parameter is not supported %s : %s\n", name.cstr(), val.cstr()); netlist().error("Parameter is not supported %s : %s\n", name.cstr(), val.cstr());
} }
} }
if (!(m_params.add(&param, false)==true)) if (!m_params.add(param.name(), &param))
netlist().error("Error adding parameter %s to parameter list\n", name.cstr()); netlist().error("Error adding parameter %s to parameter list\n", name.cstr());
} }
break; break;
@ -400,16 +379,16 @@ void setup_t::register_param(const pstring &param, const pstring &value)
{ {
pstring fqn = build_fqn(param); pstring fqn = build_fqn(param);
int idx = m_params_temp.index_by_name(fqn); int idx = m_params_temp.index_of(fqn);
if (idx < 0) if (idx < 0)
{ {
if (!(m_params_temp.add(link_t(fqn, value), false)==true)) if (!m_params_temp.add(fqn, value))
netlist().error("Unexpected error adding parameter %s to parameter list\n", param.cstr()); netlist().error("Unexpected error adding parameter %s to parameter list\n", param.cstr());
} }
else else
{ {
netlist().warning("Overwriting %s old <%s> new <%s>\n", fqn.cstr(), m_params_temp[idx].e2.cstr(), value.cstr()); netlist().warning("Overwriting %s old <%s> new <%s>\n", fqn.cstr(), m_params_temp.value_at(idx).cstr(), value.cstr());
m_params_temp[idx].e2 = value; m_params_temp[fqn] = value;
} }
} }
@ -421,7 +400,8 @@ const pstring setup_t::resolve_alias(const pstring &name) const
/* FIXME: Detect endless loop */ /* FIXME: Detect endless loop */
do { do {
ret = temp; ret = temp;
temp = m_alias.find_by_name(ret).e2; int p = m_alias.index_of(ret);
temp = (p>=0 ? m_alias.value_at(p) : "");
} while (temp != ""); } while (temp != "");
NL_VERBOSE_OUT(("%s==>%s\n", name.cstr(), ret.cstr())); NL_VERBOSE_OUT(("%s==>%s\n", name.cstr(), ret.cstr()));
@ -480,14 +460,14 @@ param_t *setup_t::find_param(const pstring &param_in, bool required)
const pstring param_in_fqn = build_fqn(param_in); const pstring param_in_fqn = build_fqn(param_in);
const pstring &outname = resolve_alias(param_in_fqn); const pstring &outname = resolve_alias(param_in_fqn);
param_t *ret; int ret;
ret = m_params.find_by_name(outname); ret = m_params.index_of(outname);
if (ret == NULL && required) if (ret < 0 && required)
netlist().error("parameter %s(%s) not found!\n", param_in_fqn.cstr(), outname.cstr()); netlist().error("parameter %s(%s) not found!\n", param_in_fqn.cstr(), outname.cstr());
if (ret != NULL) if (ret != -1)
NL_VERBOSE_OUT(("Found parameter %s\n", outname.cstr())); NL_VERBOSE_OUT(("Found parameter %s\n", outname.cstr()));
return ret; return (ret == -1 ? NULL : m_params.value_at(ret));
} }
// FIXME avoid dynamic cast here // FIXME avoid dynamic cast here

View File

@ -32,9 +32,6 @@
#define NET_REGISTER_DEV_X(_type, _name) \ #define NET_REGISTER_DEV_X(_type, _name) \
setup.register_dev(# _type, # _name); setup.register_dev(# _type, # _name);
#define NET_REMOVE_DEV(_name) \
setup.remove_dev(# _name);
#define NET_REGISTER_SIGNAL(_type, _name) \ #define NET_REGISTER_SIGNAL(_type, _name) \
NET_REGISTER_DEV(_type ## _ ## sig, _name) NET_REGISTER_DEV(_type ## _ ## sig, _name)
@ -133,10 +130,8 @@ namespace netlist
const pstring &name() const { return e1; } const pstring &name() const { return e1; }
}; };
typedef pnamedlist_t<link_t> tagmap_nstring_t; //typedef pnamedlist_t<link_t> tagmap_nstring_t;
typedef pnamedlist_t<param_t *> tagmap_param_t;
typedef pnamedlist_t<core_terminal_t *> tagmap_terminal_t; typedef pnamedlist_t<core_terminal_t *> tagmap_terminal_t;
typedef plist_t<link_t> tagmap_link_t;
setup_t(netlist_t *netlist); setup_t(netlist_t *netlist);
~setup_t(); ~setup_t();
@ -217,10 +212,11 @@ namespace netlist
netlist_t *m_netlist; netlist_t *m_netlist;
tagmap_nstring_t m_alias; phashmap_t<pstring, pstring> m_alias;
tagmap_param_t m_params; phashmap_t<pstring, param_t *> m_params;
tagmap_link_t m_links; phashmap_t<pstring, pstring> m_params_temp;
tagmap_nstring_t m_params_temp;
plist_t<link_t> m_links;
factory_list_t *m_factory; factory_list_t *m_factory;
@ -245,6 +241,7 @@ namespace netlist
const pstring resolve_alias(const pstring &name) const; const pstring resolve_alias(const pstring &name) const;
devices::nld_base_proxy *get_d_a_proxy(core_terminal_t &out); devices::nld_base_proxy *get_d_a_proxy(core_terminal_t &out);
#if 0
template <class T> template <class T>
void remove_start_with(T &hm, pstring &sw) void remove_start_with(T &hm, pstring &sw)
{ {
@ -258,6 +255,7 @@ namespace netlist
} }
} }
} }
#endif
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------

View File

@ -606,6 +606,146 @@ public:
} }
}; };
// ----------------------------------------------------------------------------------------
// hashmap list
// ----------------------------------------------------------------------------------------
template <class C>
struct phash_functor
{
unsigned hash(const C &v) { return (unsigned) v; }
};
template <>
struct phash_functor<pstring>
{
unsigned hash(const pstring &v)
{
const char *string = v.cstr();
unsigned result = *string++;
for (UINT8 c = *string++; c != 0; c = *string++)
result = (result*33) ^ c;
return result;
}
};
/* some primes 53, 97, 193, 389, 769, 1543, 3079, 6151 */
template <class K, class V, class H = phash_functor<K> >
class phashmap_t
{
public:
phashmap_t() : m_hash(389)
{
for (unsigned i=0; i<m_hash.size(); i++)
m_hash[i] = -1;
}
struct element_t
{
element_t() { }
element_t(K key, unsigned hash, V value)
: m_key(key), m_hash(hash), m_value(value), m_next(-1)
{}
K m_key;
unsigned m_hash;
V m_value;
int m_next;
};
void clear()
{
m_values.clear();
for (unsigned i=0; i<m_hash.size(); i++)
m_hash[i] = -1;
}
bool contains(const K &key) const
{
return (get_idx(key) >= 0);
}
int index_of(const K &key) const
{
return get_idx(key);
}
unsigned size() const { return m_values.size(); }
bool add(const K &key, const V &value)
{
H h;
const unsigned hash=h.hash(key);
const unsigned pos = hash % m_hash.size();
if (m_hash[pos] == -1)
{
unsigned vpos = m_values.size();
m_values.add(element_t(key, hash, value));
m_hash[pos] = vpos;
}
else
{
int ep = m_hash[pos];
for (; ep != -1; ep = m_values[ep].m_next)
{
if (m_values[ep].m_hash == hash && m_values[ep].m_key == key )
return false; /* duplicate */
}
unsigned vpos = m_values.size();
m_values.add(element_t(key, hash, value));
m_values[vpos].m_next = m_hash[pos];
m_hash[pos] = vpos;
}
return true;
}
V& operator[](const K &key)
{
int p = get_idx(key);
if (p == -1)
{
p = m_values.size();
add(key, V());
}
return m_values[p].m_value;
}
const V& operator[](const K &key) const
{
int p = get_idx(key);
if (p == -1)
{
p = m_values.size();
add(key, V());
}
return m_values[p].m_value;
}
V& value_at(const unsigned pos) { return m_values[pos].m_value; }
const V& value_at(const unsigned pos) const { return m_values[pos].m_value; }
V& key_at(const unsigned pos) const { return m_values[pos].m_key; }
private:
int get_idx(const K &key) const
{
H h;
const unsigned hash=h.hash(key);
const unsigned pos = hash % m_hash.size();
for (int ep = m_hash[pos]; ep != -1; ep = m_values[ep].m_next)
{
if (m_values[ep].m_hash == hash && m_values[ep].m_key == key )
return ep;
}
return -1;
}
plist_t<element_t> m_values;
parray_t<int> m_hash;
};
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// sort a list ... slow, I am lazy // sort a list ... slow, I am lazy
// elements must support ">" operator. // elements must support ">" operator.

View File

@ -75,3 +75,4 @@ template<> ATTR_COLD void pstate_manager_t::save_item(pstate_callback_t &state,
m_save.add(p); m_save.add(p);
state.register_state(*this, stname); state.register_state(*this, stname);
} }