From e78d1d93e856f12447b27b7c43df889840d3dde2 Mon Sep 17 00:00:00 2001 From: Simon Klix Date: Thu, 5 Dec 2024 23:02:53 +0100 Subject: [PATCH] added functionality to create garph algorithm netlist graph from a netlist abstraction --- .../netlist_abstraction_decorator.h | 21 ++++ .../include/graph_algorithm/netlist_graph.h | 15 +++ plugins/graph_algorithm/src/netlist_graph.cpp | 100 +++++++++++++++++- .../netlist_abstraction_decorator.cpp | 68 ++++++++++-- 4 files changed, 197 insertions(+), 7 deletions(-) diff --git a/include/hal_core/netlist/decorators/netlist_abstraction_decorator.h b/include/hal_core/netlist/decorators/netlist_abstraction_decorator.h index d56c194a445..6283422de36 100644 --- a/include/hal_core/netlist/decorators/netlist_abstraction_decorator.h +++ b/include/hal_core/netlist/decorators/netlist_abstraction_decorator.h @@ -64,6 +64,8 @@ namespace hal const std::function& exit_endpoint_filter = nullptr, const std::function& entry_endpoint_filter = nullptr); + const std::vector& get_target_gates() const; + /** * @brief Gets the predecessors of a gate within the abstraction. * @@ -136,6 +138,14 @@ namespace hal */ Result> 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> get_global_input_predecessors(const Gate* gate) const; + /** * @brief Gets the global output nets that are successors of an endpoint. * @@ -144,9 +154,20 @@ namespace hal */ Result> 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> get_global_output_successors(const Gate* gate) const; + private: NetlistAbstraction() = default; + std::vector m_target_gates; + // std::vector m_included_gates; + /** * @brief Maps endpoints to their successor endpoints within the abstraction. */ diff --git a/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h b/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h index 75feb79317b..38529baae19 100644 --- a/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h +++ b/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h @@ -44,6 +44,7 @@ namespace hal class Netlist; class Gate; class Net; + class NetlistAbstraction; namespace graph_algorithm { @@ -121,6 +122,20 @@ namespace hal */ static Result> from_netlist_no_edges(Netlist* nl, const std::vector& 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> + from_netlist_abstraction(const NetlistAbstraction* nl_asbtr, const bool create_dummy_vertices = false, const std::function& filter = nullptr); + /** * @brief Create a deep copy of the netlist graph. * diff --git a/plugins/graph_algorithm/src/netlist_graph.cpp b/plugins/graph_algorithm/src/netlist_graph.cpp index 4c90111093a..62c9ab3856d 100644 --- a/plugins/graph_algorithm/src/netlist_graph.cpp +++ b/plugins/graph_algorithm/src/netlist_graph.cpp @@ -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" @@ -186,6 +186,104 @@ namespace hal return OK(std::move(graph)); } + Result> + NetlistGraph::from_netlist_abstraction(const NetlistAbstraction* nl_asbtr, const bool create_dummy_vertices, const std::function& 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(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 global_in_to_node; + std::map 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> NetlistGraph::copy() const { auto graph = std::unique_ptr(new NetlistGraph(m_nl)); diff --git a/src/netlist/decorators/netlist_abstraction_decorator.cpp b/src/netlist/decorators/netlist_abstraction_decorator.cpp index 74a610659ce..5943f62a354 100644 --- a/src/netlist/decorators/netlist_abstraction_decorator.cpp +++ b/src/netlist/decorators/netlist_abstraction_decorator.cpp @@ -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(new NetlistAbstraction()); + new_abstraction->m_target_gates = gates; + // new_abstraction->m_included_gates = included_gates; - auto new_abstraction = std::shared_ptr(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); @@ -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); @@ -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()) { @@ -118,6 +121,11 @@ namespace hal return OK(new_abstraction); } + const std::vector& NetlistAbstraction::get_target_gates() const + { + return m_target_gates; + } + Result> NetlistAbstraction::get_predecessors(const Gate* gate) const { std::vector predecessors; @@ -277,6 +285,30 @@ namespace hal return OK(it->second); } + Result> NetlistAbstraction::get_global_input_predecessors(const Gate* gate) const + { + std::vector 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> NetlistAbstraction::get_global_output_successors(const Endpoint* endpoint) const { const auto it = m_global_output_successors.find(endpoint); @@ -288,6 +320,30 @@ namespace hal return OK(it->second); } + Result> NetlistAbstraction::get_global_output_successors(const Gate* gate) const + { + std::vector 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> NetlistAbstractionDecorator::get_shortest_path_distance_internal(const std::vector& start,