Skip to content

Commit

Permalink
added functionality to create garph algorithm netlist graph from a ne…
Browse files Browse the repository at this point in the history
…tlist abstraction
  • Loading branch information
Simon Klix committed Dec 5, 2024
1 parent cb8b290 commit e78d1d9
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ namespace hal
const std::function<bool(const Endpoint*, const u32 current_depth)>& exit_endpoint_filter = nullptr,
const std::function<bool(const Endpoint*, const u32 current_depth)>& entry_endpoint_filter = nullptr);

const std::vector<Gate*>& get_target_gates() const;

/**
* @brief Gets the predecessors of a gate within the abstraction.
*
Expand Down Expand Up @@ -136,6 +138,14 @@ namespace hal
*/
Result<std::vector<Net*>> get_global_input_predecessors(const Endpoint* endpoint) const;

/**
* @brief Gets the global input nets that are predecessors of a gate.
*
* @param[in] gate - The gate to get global input predecessors for.
* @returns A vector of global input nets.
*/
Result<std::vector<Net*>> get_global_input_predecessors(const Gate* gate) const;

/**
* @brief Gets the global output nets that are successors of an endpoint.
*
Expand All @@ -144,9 +154,20 @@ namespace hal
*/
Result<std::vector<Net*>> get_global_output_successors(const Endpoint* endpoint) const;

/**
* @brief Gets the global output nets that are successors of a gate.
*
* @param[in] gate - The gate to get global output successors for.
* @returns A vector of global output nets.
*/
Result<std::vector<Net*>> get_global_output_successors(const Gate* gate) const;

private:
NetlistAbstraction() = default;

std::vector<Gate*> m_target_gates;
// std::vector<Gate*> m_included_gates;

/**
* @brief Maps endpoints to their successor endpoints within the abstraction.
*/
Expand Down
15 changes: 15 additions & 0 deletions plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace hal
class Netlist;
class Gate;
class Net;
class NetlistAbstraction;

namespace graph_algorithm
{
Expand Down Expand Up @@ -121,6 +122,20 @@ namespace hal
*/
static Result<std::unique_ptr<NetlistGraph>> from_netlist_no_edges(Netlist* nl, const std::vector<Gate*>& gates = {});

/**
* @brief Create a directed graph from a netlist abstraction.
*
* Optionally create dummy vertices at global input and output nets
* An optional filter can be applied to exclude undesired edges.
*
* @param[in] nl_abstr - The netlist abstraction.
* @param[in] create_dummy_vertices - Set `true` to create dummy vertices, `false` otherwise. Defaults to `false`.
* @param[in] filter - An optional filter that is evaluated on every edge in the netlist abstraction. Defaults to `nullptr`.
* @returns The netlist graph on success, an error otherwise.
*/
static Result<std::unique_ptr<NetlistGraph>>
from_netlist_abstraction(const NetlistAbstraction* nl_asbtr, const bool create_dummy_vertices = false, const std::function<bool(const Endpoint*, const Endpoint*)>& filter = nullptr);

/**
* @brief Create a deep copy of the netlist graph.
*
Expand Down
100 changes: 99 additions & 1 deletion plugins/graph_algorithm/src/netlist_graph.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "graph_algorithm/netlist_graph.h"

#include "hal_core/netlist/decorators/netlist_abstraction_decorator.h"
#include "hal_core/netlist/endpoint.h"
#include "hal_core/netlist/gate.h"
#include "hal_core/netlist/net.h"
Expand Down Expand Up @@ -186,6 +186,104 @@ namespace hal
return OK(std::move(graph));
}

Result<std::unique_ptr<NetlistGraph>>
NetlistGraph::from_netlist_abstraction(const NetlistAbstraction* nl_asbtr, const bool create_dummy_vertices, const std::function<bool(const Endpoint*, const Endpoint*)>& filter)
{
if (!nl_asbtr)
{
return ERR("netlist abstraction is a nullptr");
}

if (nl_asbtr->get_target_gates().empty())
{
return ERR("netlist abstraction has no target gates");
}

auto graph = std::unique_ptr<NetlistGraph>(new NetlistGraph(nl_asbtr->get_target_gates().front()->get_netlist()));

// count all edges as this number is needed to create a new graph
u32 edge_counter = 0;
for (const auto* gate : nl_asbtr->get_target_gates())
{
edge_counter += nl_asbtr->get_unique_successors(gate).get().size();

if (create_dummy_vertices)
{
edge_counter += nl_asbtr->get_global_input_predecessors(gate).get().size();
edge_counter += nl_asbtr->get_global_output_successors(gate).get().size();
}
}

// initialize edge vector
igraph_vector_int_t edges;
auto err = igraph_vector_int_init(&edges, 2 * edge_counter);
if (err != IGRAPH_SUCCESS)
{
return ERR(igraph_strerror(err));
}

// we need dummy gates for input/outputs
u32 node_counter = 0;
u32 edge_index = 0;

for (auto* g : nl_asbtr->get_target_gates())
{
const u32 node = node_counter++;
graph->m_gates_to_nodes[g] = node;
graph->m_nodes_to_gates[node] = g;
}

std::map<Net*, u32> global_in_to_node;
std::map<Net*, u32> global_out_to_node;
for (auto* src_gate : nl_asbtr->get_target_gates())
{
for (auto* dst_gate : nl_asbtr->get_unique_successors(src_gate).get())
{
VECTOR(edges)[edge_index++] = graph->m_gates_to_nodes.at(src_gate);
VECTOR(edges)[edge_index++] = graph->m_gates_to_nodes.at(dst_gate);
}

if (create_dummy_vertices)
{
for (auto* global_in : nl_asbtr->get_global_input_predecessors(src_gate).get())
{
if (global_in_to_node.find(global_in) == global_in_to_node.end())
{
// create dummy node for global input
global_in_to_node[global_in] = node_counter++;
}

VECTOR(edges)[edge_index++] = global_in_to_node.at(global_in);
VECTOR(edges)[edge_index++] = graph->m_gates_to_nodes.at(src_gate);
}

for (auto* global_out : nl_asbtr->get_global_output_successors(src_gate).get())
{
if (global_out_to_node.find(global_out) == global_out_to_node.end())
{
// create dummy node for global output
global_out_to_node[global_out] = node_counter++;
}

VECTOR(edges)[edge_index++] = graph->m_gates_to_nodes.at(src_gate);
VECTOR(edges)[edge_index++] = global_out_to_node.at(global_out);
}
}
}

graph->m_graph_ptr = &(graph->m_graph);
err = igraph_create(graph->m_graph_ptr, &edges, node_counter, IGRAPH_DIRECTED);

igraph_vector_int_destroy(&edges);

if (err != IGRAPH_SUCCESS)
{
return ERR(igraph_strerror(err));
}

return OK(std::move(graph));
}

Result<std::unique_ptr<NetlistGraph>> NetlistGraph::copy() const
{
auto graph = std::unique_ptr<NetlistGraph>(new NetlistGraph(m_nl));
Expand Down
68 changes: 62 additions & 6 deletions src/netlist/decorators/netlist_abstraction_decorator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ namespace hal
const auto nl_trav_dec = NetlistTraversalDecorator(*netlist);

// transform gates into set to check fast if a gate is part of abstraction
const auto gates_set = utils::to_unordered_set(gates);
const auto& included_gates = include_all_netlist_gates ? netlist->get_gates() : gates;
const auto target_gates_set = utils::to_unordered_set(gates);
const auto& included_gates = include_all_netlist_gates ? netlist->get_gates() : gates;

auto new_abstraction = std::shared_ptr<NetlistAbstraction>(new NetlistAbstraction());
new_abstraction->m_target_gates = gates;
// new_abstraction->m_included_gates = included_gates;

auto new_abstraction = std::shared_ptr<NetlistAbstraction>(new NetlistAbstraction());
const u32 approximated_endpoint_count = included_gates.size() * 8;
new_abstraction->m_successors.reserve(approximated_endpoint_count);
new_abstraction->m_predecessors.reserve(approximated_endpoint_count);
Expand All @@ -38,7 +41,7 @@ namespace hal
const auto successors = nl_trav_dec.get_next_matching_endpoints(
ep_out,
true,
[gates_set](const auto& ep) { return ep->is_destination_pin() && gates_set.find(ep->get_gate()) != gates_set.end(); },
[target_gates_set](const auto& ep) { return ep->is_destination_pin() && target_gates_set.find(ep->get_gate()) != target_gates_set.end(); },
false,
exit_endpoint_filter,
entry_endpoint_filter);
Expand Down Expand Up @@ -80,8 +83,8 @@ namespace hal
{
new_abstraction->m_predecessors.insert({ep_in, {}});

const auto predecessors =
nl_trav_dec.get_next_matching_endpoints(ep_in, false, [gates_set](const auto& ep) { return ep->is_source_pin() && gates_set.find(ep->get_gate()) != gates_set.end(); });
const auto predecessors = nl_trav_dec.get_next_matching_endpoints(
ep_in, false, [target_gates_set](const auto& ep) { return ep->is_source_pin() && target_gates_set.find(ep->get_gate()) != target_gates_set.end(); });

if (predecessors.is_error())
{
Expand Down Expand Up @@ -118,6 +121,11 @@ namespace hal
return OK(new_abstraction);
}

const std::vector<Gate*>& NetlistAbstraction::get_target_gates() const
{
return m_target_gates;
}

Result<std::vector<Endpoint*>> NetlistAbstraction::get_predecessors(const Gate* gate) const
{
std::vector<Endpoint*> predecessors;
Expand Down Expand Up @@ -277,6 +285,30 @@ namespace hal
return OK(it->second);
}

Result<std::vector<Net*>> NetlistAbstraction::get_global_input_predecessors(const Gate* gate) const
{
std::vector<Net*> global_input_predecessors;
for (auto* ep : gate->get_fan_out_endpoints())
{
const auto new_global_input_predecessors = get_global_input_predecessors(ep);
if (new_global_input_predecessors.is_error())
{
return ERR_APPEND(new_global_input_predecessors.get_error(),
"failed to get global input predecessors of gate " + gate->get_name() + " with ID " + std::to_string(gate->get_id()) + " in netlist abstraction");
}

for (auto* pred_net : new_global_input_predecessors.get())
{
global_input_predecessors.push_back(pred_net);
}
}

std::sort(global_input_predecessors.begin(), global_input_predecessors.end());
global_input_predecessors.erase(std::unique(global_input_predecessors.begin(), global_input_predecessors.end()), global_input_predecessors.end());

return OK(global_input_predecessors);
}

Result<std::vector<Net*>> NetlistAbstraction::get_global_output_successors(const Endpoint* endpoint) const
{
const auto it = m_global_output_successors.find(endpoint);
Expand All @@ -288,6 +320,30 @@ namespace hal
return OK(it->second);
}

Result<std::vector<Net*>> NetlistAbstraction::get_global_output_successors(const Gate* gate) const
{
std::vector<Net*> global_output_successors;
for (auto* ep : gate->get_fan_out_endpoints())
{
const auto new_global_output_successors = get_global_output_successors(ep);
if (new_global_output_successors.is_error())
{
return ERR_APPEND(new_global_output_successors.get_error(),
"failed to get global output successors of gate " + gate->get_name() + " with ID " + std::to_string(gate->get_id()) + " in netlist abstraction");
}

for (auto* succ_net : new_global_output_successors.get())
{
global_output_successors.push_back(succ_net);
}
}

std::sort(global_output_successors.begin(), global_output_successors.end());
global_output_successors.erase(std::unique(global_output_successors.begin(), global_output_successors.end()), global_output_successors.end());

return OK(global_output_successors);
}

NetlistAbstractionDecorator::NetlistAbstractionDecorator(const hal::NetlistAbstraction& abstraction) : m_abstraction(abstraction){};

Result<std::optional<u32>> NetlistAbstractionDecorator::get_shortest_path_distance_internal(const std::vector<Endpoint*>& start,
Expand Down

0 comments on commit e78d1d9

Please sign in to comment.