diff --git a/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h b/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h index 7878641fe10..57d964e36c0 100644 --- a/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h +++ b/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h @@ -214,6 +214,15 @@ namespace hal */ Result add_edges(const std::vector>& edges); + /** + * Add edges between the specified pairs of source and destination gates to the netlist graph. + * The vertices must already exist in the graph. + * + * @param[in] edges - The edges to add as a map from source gate to its destination gates. + * @returns OK on success, an error otherwise. + */ + Result add_edges(const std::map>& edges); + /** * Delete edges between the specified pairs of source and destination gates from the netlist graph. * diff --git a/plugins/graph_algorithm/python/python_bindings.cpp b/plugins/graph_algorithm/python/python_bindings.cpp index f5f47b387e0..f474e657b38 100644 --- a/plugins/graph_algorithm/python/python_bindings.cpp +++ b/plugins/graph_algorithm/python/python_bindings.cpp @@ -406,6 +406,30 @@ namespace hal :rtype: bool )"); + py_netlist_graph.def( + "add_edges", + [](graph_algorithm::NetlistGraph& self, const std::map>& edges) -> bool { + auto res = self.add_edges(edges); + if (res.is_ok()) + { + return true; + } + else + { + log_error("python_context", "error encountered while adding edges:\n{}", res.get_error().get()); + return false; + } + }, + py::arg("edges"), + R"( + Add edges between the specified pairs of source and destination gates to the netlist graph. + The vertices must already exist in the graph. + + :param dict[hal_py.Gate,set[hal_py.Gate]] edges: The edges to add as a dict from source gate to its destination gates. + :returns: ``True`` on success, ``False`` otherwise. + :rtype: bool + )"); + py_netlist_graph.def( "delete_edges", [](graph_algorithm::NetlistGraph& self, const std::vector>& edges) -> bool { diff --git a/plugins/graph_algorithm/src/netlist_graph.cpp b/plugins/graph_algorithm/src/netlist_graph.cpp index b4a09f564df..3f9f3a5dd7f 100644 --- a/plugins/graph_algorithm/src/netlist_graph.cpp +++ b/plugins/graph_algorithm/src/netlist_graph.cpp @@ -600,6 +600,60 @@ namespace hal return OK({}); } + Result NetlistGraph::add_edges(const std::map>& edges) + { + u32 edge_count = 0; + for (const auto& [_, dst_gates] : edges) + { + edge_count += dst_gates.size(); + } + + igraph_vector_int_t e_vec; + if (auto err = igraph_vector_int_init(&e_vec, 2 * edge_count); err != IGRAPH_SUCCESS) + { + return ERR(igraph_strerror(err)); + } + + u32 edge_index = 0; + for (const auto& [src_gate, dst_gates] : edges) + { + u32 src_vertex; + if (auto it = m_gates_to_nodes.find(src_gate); it != m_gates_to_nodes.end()) + { + src_vertex = it->second; + } + else + { + igraph_vector_int_destroy(&e_vec); + return ERR("no node for gate '" + src_gate->get_name() + "' with ID " + std::to_string(src_gate->get_id()) + " exists in graph for netlist with ID " + + std::to_string(m_nl->get_id())); + } + + for (auto* dst_gate : dst_gates) + { + if (auto it = m_gates_to_nodes.find(dst_gate); it != m_gates_to_nodes.end()) + { + VECTOR(e_vec)[edge_index++] = src_vertex; + VECTOR(e_vec)[edge_index++] = it->second; + } + else + { + igraph_vector_int_destroy(&e_vec); + return ERR("no node for gate '" + dst_gate->get_name() + "' with ID " + std::to_string(dst_gate->get_id()) + " exists in graph for netlist with ID " + + std::to_string(m_nl->get_id())); + } + } + } + + if (auto err = igraph_add_edges(&m_graph, &e_vec, nullptr); err != IGRAPH_SUCCESS) + { + igraph_vector_int_destroy(&e_vec); + return ERR(igraph_strerror(err)); + } + + return OK({}); + } + Result NetlistGraph::delete_edges(const std::vector>& edges) { igraph_vector_int_t e_vec;