Skip to content

Commit

Permalink
Boost performance by net endpoint hash
Browse files Browse the repository at this point in the history
  • Loading branch information
joern274 committed Mar 14, 2024
1 parent 95b424a commit 4be7b36
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 59 deletions.
43 changes: 39 additions & 4 deletions include/hal_core/netlist/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,49 @@
#include <string>
#include <tuple>
#include <vector>
#include <unordered_map>

namespace hal
{
class Gate;
class GatePin;
class Endpoint;

struct EndpointKey
{
const Gate* gate;
const GatePin* pin;
EndpointKey(const Gate* g, const GatePin* p)
: gate(g), pin(p) {;}

EndpointKey(const Endpoint* ep);

bool operator==(const EndpointKey& other) const { return gate==other.gate && pin==other.pin; }
};
}

const int move_bits = sizeof(size_t) * 4;

// std function must not be in hal namespace
template <> struct std::hash<struct hal::EndpointKey>
{
size_t operator()(const hal::EndpointKey& epk) const
{
size_t h1 = hash<unsigned int>()((uintptr_t) epk.gate);
size_t h2 = hash<unsigned int>()((uintptr_t) epk.pin);
h1 ^= (h2 << (move_bits+1) );
h1 ^= (h2 >> (move_bits-1) );
return h1;
}
};

namespace hal
{
/* forward declaration */
class Netlist;
class Gate;
class Grouping;
class NetlistInternalManager;
class Endpoint;


/**
* Net class containing information about a net including its source and destination.
Expand Down Expand Up @@ -396,6 +430,7 @@ namespace hal
bool is_global_output_net() const;

private:

friend class NetlistInternalManager;
explicit Net(NetlistInternalManager* internal_manager, EventHandler* event_handler, const u32 id, const std::string& name = "");

Expand All @@ -418,8 +453,8 @@ namespace hal
/* stores the dst gate and pin id of the dst gate */
std::vector<std::unique_ptr<Endpoint>> m_destinations;
std::vector<std::unique_ptr<Endpoint>> m_sources;
std::vector<Endpoint*> m_destinations_raw;
std::vector<Endpoint*> m_sources_raw;
std::unordered_map<EndpointKey,Endpoint*> m_destinations_hash;
std::unordered_map<EndpointKey,Endpoint*> m_sources_hash;

EventHandler* m_event_handler;
};
Expand Down
82 changes: 41 additions & 41 deletions src/netlist/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,18 @@ namespace hal
return false;
}

const std::vector<Endpoint*>& sources_n2 = other.get_sources();
for (const Endpoint* ep_n1 : m_sources_raw)
for (auto ep_n1_it = m_sources_hash.begin(); ep_n1_it != m_sources_hash.end(); ++ep_n1_it)
{
if (std::find_if(sources_n2.begin(), sources_n2.end(), [ep_n1](const Endpoint* ep_n2) { return *ep_n1->get_pin() == *ep_n2->get_pin() && *ep_n1->get_gate() == *ep_n2->get_gate(); })
== sources_n2.end())
if (other.m_sources_hash.find(ep_n1_it->second) == other.m_sources_hash.end())
{
log_debug("net", "the nets with IDs {} and {} are not equal due to an unequal source endpoint.", m_id, other.get_id());
return false;
}
}

const std::vector<Endpoint*>& destinations_n2 = other.get_destinations();
for (const Endpoint* ep_n1 : m_destinations_raw)
for (auto ep_n1_it = m_destinations_hash.begin(); ep_n1_it != m_destinations_hash.end(); ++ep_n1_it)
{
if (std::find_if(
destinations_n2.begin(), destinations_n2.end(), [ep_n1](const Endpoint* ep_n2) { return *ep_n1->get_pin() == *ep_n2->get_pin() && *ep_n1->get_gate() == *ep_n2->get_gate(); })
== destinations_n2.end())
if (other.m_destinations_hash.find(ep_n1_it->second) == other.m_destinations_hash.end())
{
log_debug("net", "the nets with IDs {} and {} are not equal due to an unequal destination endpoint.", m_id, other.get_id());
return false;
Expand Down Expand Up @@ -147,9 +142,10 @@ namespace hal

bool Net::remove_source(Gate* gate, const GatePin* pin)
{
if (auto it = std::find_if(m_sources_raw.begin(), m_sources_raw.end(), [gate, pin](auto ep) { return ep->get_gate() == gate && *ep->get_pin() == *pin; }); it != m_sources_raw.end())
auto it = m_sources_hash.find(EndpointKey(gate,pin));
if (it != m_sources_hash.end())
{
return m_internal_manager->net_remove_source(this, *it);
return m_internal_manager->net_remove_source(this, it->second);
}
return false;
}
Expand Down Expand Up @@ -186,13 +182,11 @@ namespace hal

bool Net::is_a_source(const Gate* gate) const
{
if (gate == nullptr)
{
log_warning("net", "could not check if gate is a source: nullptr given for gate");
return false;
}
for (const Endpoint* ep : gate->get_fan_out_endpoints())
if (m_sources_hash.find(EndpointKey(ep)) != m_sources_hash.end())
return true;

return std::find_if(m_sources_raw.begin(), m_sources_raw.end(), [gate](const auto* ep) { return ep->get_gate() == gate; }) != m_sources_raw.end();
return false;
}

bool Net::is_a_source(const Gate* gate, const GatePin* pin) const
Expand All @@ -209,7 +203,7 @@ namespace hal
return false;
}

return std::find_if(m_sources_raw.begin(), m_sources_raw.end(), [gate, pin](const auto* ep) { return ep->get_gate() == gate && *ep->get_pin() == *pin; }) != m_sources_raw.end();
return m_sources_hash.find(EndpointKey(gate,pin)) != m_sources_hash.end();
}

bool Net::is_a_source(const Gate* gate, const std::string& pin_name) const
Expand Down Expand Up @@ -240,29 +234,30 @@ namespace hal
return false;
}

return std::find(m_sources_raw.begin(), m_sources_raw.end(), ep) != m_sources_raw.end();
return m_sources_hash.find(EndpointKey(ep)) != m_sources_hash.end();
}

u32 Net::get_num_of_sources() const
{
return (u32)m_sources_raw.size();
return (u32)m_sources_hash.size();
}

std::vector<Endpoint*> Net::get_sources(const std::function<bool(Endpoint* ep)>& filter) const
{
std::vector<Endpoint*> srcs;
if (!filter)
{
return m_sources_raw;
for (auto it = m_sources_hash.begin(); it != m_sources_hash.end(); ++it)
srcs.push_back(it->second);
}

std::vector<Endpoint*> srcs;
for (auto src : m_sources_raw)
else
{
if (!filter(src))
for (auto it = m_sources_hash.begin(); it != m_sources_hash.end(); ++it)
{
continue;
Endpoint* src = it->second;
if (!filter(src)) continue;
srcs.push_back(src);
}
srcs.push_back(src);
}
return srcs;
}
Expand Down Expand Up @@ -295,10 +290,10 @@ namespace hal

bool Net::remove_destination(Gate* gate, const GatePin* pin)
{
if (auto it = std::find_if(m_destinations_raw.begin(), m_destinations_raw.end(), [gate, pin](const auto* ep) { return ep->get_gate() == gate && *ep->get_pin() == *pin; });
it != m_destinations_raw.end())
auto it = m_destinations_hash.find(EndpointKey(gate,pin));
if (it != m_destinations_hash.end())
{
return m_internal_manager->net_remove_destination(this, *it);
return m_internal_manager->net_remove_destination(this, it->second);
}
return false;
}
Expand Down Expand Up @@ -341,7 +336,11 @@ namespace hal
return false;
}

return std::find_if(m_destinations_raw.begin(), m_destinations_raw.end(), [gate](const auto* ep) { return ep->get_gate() == gate; }) != m_destinations_raw.end();
for (const Endpoint* ep : gate->get_fan_in_endpoints())
if (m_destinations_hash.find(EndpointKey(ep)) != m_destinations_hash.end())
return true;

return false;
}

bool Net::is_a_destination(const Gate* gate, const GatePin* pin) const
Expand All @@ -358,7 +357,7 @@ namespace hal
return false;
}

return std::find_if(m_destinations_raw.begin(), m_destinations_raw.end(), [gate, pin](const auto* ep) { return ep->get_gate() == gate && *ep->get_pin() == *pin; }) != m_destinations_raw.end();
return m_destinations_hash.find(EndpointKey(gate,pin)) != m_destinations_hash.end();
}

bool Net::is_a_destination(const Gate* gate, const std::string& pin_name) const
Expand Down Expand Up @@ -389,29 +388,30 @@ namespace hal
return false;
}

return std::find(m_destinations_raw.begin(), m_destinations_raw.end(), ep) != m_destinations_raw.end();
return m_destinations_hash.find(EndpointKey(ep))!=m_destinations_hash.end();
}

u32 Net::get_num_of_destinations() const
{
return (u32)m_destinations_raw.size();
return (u32)m_destinations_hash.size();
}

std::vector<Endpoint*> Net::get_destinations(const std::function<bool(Endpoint* ep)>& filter) const
{
std::vector<Endpoint*> dsts;
if (!filter)
{
return m_destinations_raw;
for (auto it = m_destinations_hash.begin(); it != m_destinations_hash.end(); ++it)
dsts.push_back(it->second);
}

std::vector<Endpoint*> dsts;
for (auto dst : m_destinations_raw)
else
{
if (!filter(dst))
for (auto it = m_destinations_hash.begin(); it != m_destinations_hash.end(); ++it)
{
continue;
Endpoint* dst = it->second;
if (!filter(dst)) continue;
dsts.push_back(dst);
}
dsts.push_back(dst);
}
return dsts;
}
Expand Down
31 changes: 17 additions & 14 deletions src/netlist/netlist_internal_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,19 +442,17 @@ namespace hal
return false;
}

auto dsts = net->m_destinations_raw;
for (auto dst : dsts)
for (auto dst_it = net->m_destinations_hash.begin(); dst_it != net->m_destinations_hash.end(); ++dst_it)
{
if (!this->net_remove_destination(net, dst))
if (!this->net_remove_destination(net, dst_it->second))
{
return false;
}
}

auto srcs = net->m_sources_raw;
for (auto src : srcs)
for (auto src_it = net->m_sources_hash.begin(); src_it != net->m_sources_hash.end(); ++src_it)
{
if (!this->net_remove_source(net, src))
if (!this->net_remove_source(net, src_it->second))
{
return false;
}
Expand Down Expand Up @@ -533,7 +531,7 @@ namespace hal
auto new_endpoint = std::unique_ptr<Endpoint>(new Endpoint(gate, pin, net, false));
auto new_endpoint_raw = new_endpoint.get();
net->m_sources.push_back(std::move(new_endpoint));
net->m_sources_raw.push_back(new_endpoint_raw);
net->m_sources_hash[EndpointKey(new_endpoint_raw)] = new_endpoint_raw;
gate->m_out_endpoints.push_back(new_endpoint_raw);
gate->m_out_nets.push_back(net);

Expand Down Expand Up @@ -573,14 +571,14 @@ namespace hal
bool removed = false;
for (u32 i = 0; i < net->m_sources.size(); ++i)
{
if (net->m_sources_raw[i] == ep)
auto src_it = net->m_sources_hash.find(EndpointKey(ep));
if (src_it != net->m_sources_hash.end())
{
utils::unordered_vector_erase(gate->m_out_endpoints, ep);
utils::unordered_vector_erase(gate->m_out_nets, net);
net->m_sources[i] = std::move(net->m_sources.back());
net->m_sources.pop_back();
net->m_sources_raw[i] = net->m_sources_raw.back();
net->m_sources_raw.pop_back();
net->m_sources_hash.erase(src_it);
m_event_handler->notify(NetEvent::event::src_removed, net, gate->get_id());
removed = true;
break;
Expand Down Expand Up @@ -671,7 +669,7 @@ namespace hal
std::unique_ptr<Endpoint> new_endpoint = std::unique_ptr<Endpoint>(new Endpoint(gate, pin, net, true));
Endpoint* new_endpoint_raw = new_endpoint.get();
net->m_destinations.push_back(std::move(new_endpoint));
net->m_destinations_raw.push_back(new_endpoint_raw);
net->m_destinations_hash[EndpointKey(new_endpoint_raw)] = new_endpoint_raw;
gate->m_in_endpoints.push_back(new_endpoint_raw);
gate->m_in_nets.push_back(net);

Expand Down Expand Up @@ -710,14 +708,14 @@ namespace hal
bool removed = false;
for (u32 i = 0; i < net->m_destinations.size(); ++i)
{
if (net->m_destinations_raw[i] == ep)
auto dst_it = net->m_destinations_hash.find(EndpointKey(ep));
if (dst_it != net->m_destinations_hash.end())
{
utils::unordered_vector_erase(gate->m_in_endpoints, ep);
utils::unordered_vector_erase(gate->m_in_nets, net);
net->m_destinations[i] = std::move(net->m_destinations.back());
net->m_destinations.pop_back();
net->m_destinations_raw[i] = net->m_destinations_raw.back();
net->m_destinations_raw.pop_back();
net->m_destinations_hash.erase(dst_it);
m_event_handler->notify(NetEvent::event::dst_removed, net, gate->get_id());
removed = true;
break;
Expand Down Expand Up @@ -1304,4 +1302,9 @@ namespace hal
{
m_lut_function_cache.clear();
}

EndpointKey::EndpointKey(const Endpoint* ep)
: gate(ep->get_gate()), pin(ep->get_pin())
{;}

} // namespace hal

0 comments on commit 4be7b36

Please sign in to comment.