HAL  v4.5.0-124-g47ab54673
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
python_bindings.cpp
Go to the documentation of this file.
1 
3 
10 
11 #pragma GCC diagnostic push
12 #pragma GCC diagnostic ignored "-Wshadow"
13 #ifdef COMPILER_CLANG
14 #pragma clang diagnostic ignored "-Wself-assign-overloaded"
15 #pragma clang diagnostic ignored "-Wnested-anon-types"
16 #pragma clang diagnostic ignored "-Wshadow-field-in-constructor-modified"
17 #endif
18 
19 #include "hal_core/defines.h"
20 #include "hal_core/netlist/gate.h"
21 #include "hal_core/netlist/net.h"
23 #include "hal_core/utilities/log.h"
25 #include "pybind11/operators.h"
26 #include "pybind11/pybind11.h"
27 #include "pybind11/stl.h"
28 #include "pybind11/stl_bind.h"
29 
30 #pragma GCC diagnostic pop
31 
32 namespace py = pybind11;
33 namespace hal
34 {
35 #ifdef PYBIND11_MODULE
36  PYBIND11_MODULE(graph_algorithm, m)
37  {
38  m.doc() = "Graph algorithms based on igraph operating on a netlist graph abstraction.";
39 #else
40  PYBIND11_PLUGIN(graph_algorithm)
41  {
42  py::module m("graph_algorithm", "Graph algorithms based on igraph operating on a netlist graph abstraction.");
43 #endif // ifdef PYBIND11_MODULE
44 
45  py::class_<GraphAlgorithmPlugin, RawPtrWrapper<GraphAlgorithmPlugin>, BasePluginInterface> py_graph_algorithm_plugin(m, "GraphAlgorithmPlugin");
46 
47  py_graph_algorithm_plugin.def_property_readonly("name", &GraphAlgorithmPlugin::get_name, R"(
48  The name of the plugin.
49 
50  :type: str
51  )");
52 
53  py_graph_algorithm_plugin.def("get_name", &GraphAlgorithmPlugin::get_name, R"(
54  Get the name of the plugin.
55 
56  :returns: The name of the plugin.
57  :rtype: str
58  )");
59 
60  py_graph_algorithm_plugin.def_property_readonly("version", &GraphAlgorithmPlugin::get_version, R"(
61  The version of the plugin.
62 
63  :type: str
64  )");
65 
66  py_graph_algorithm_plugin.def("get_version", &GraphAlgorithmPlugin::get_version, R"(
67  Get the version of the plugin.
68 
69  :returns: The version of the plugin.
70  :rtype: str
71  )");
72 
73  py_graph_algorithm_plugin.def_property_readonly("description", &GraphAlgorithmPlugin::get_description, R"(
74  The description of the plugin.
75 
76  :type: str
77  )");
78 
79  py_graph_algorithm_plugin.def("get_description", &GraphAlgorithmPlugin::get_description, R"(
80  Get the description of the plugin.
81 
82  :returns: The description of the plugin.
83  :rtype: str
84  )");
85 
86  py_graph_algorithm_plugin.def_property_readonly("dependencies", &GraphAlgorithmPlugin::get_dependencies, R"(
87  A set of plugin names that this plugin depends on.
88 
89  :type: set[str]
90  )");
91 
92  py_graph_algorithm_plugin.def("get_dependencies", &GraphAlgorithmPlugin::get_dependencies, R"(
93  Get a set of plugin names that this plugin depends on.
94 
95  :returns: A set of plugin names that this plugin depends on.
96  :rtype: set[str]
97  )");
98 
99  py::class_<graph_algorithm::NetlistGraph> py_netlist_graph(m, "NetlistGraph", R"(
100  Holds a directed graph corresponding to a netlist.
101  )");
102 
103  py::enum_<graph_algorithm::NetlistGraph::Direction>(py_netlist_graph, "Direction", R"(
104  The direction of exploration within the graph.
105  )")
106  .value("NONE", graph_algorithm::NetlistGraph::Direction::NONE, R"(No direction, invalid default setting.)")
107  .value("IN", graph_algorithm::NetlistGraph::Direction::IN, R"(Explore through the inputs of the current node, i.e., traverse backwards.)")
108  .value("OUT", graph_algorithm::NetlistGraph::Direction::OUT, R"(Explore through the outputs of the current node, i.e., traverse forwards.)")
109  .value("ALL", graph_algorithm::NetlistGraph::Direction::ALL, R"(Explore in both directions, i.e., treat the graph as undirected.)")
110  .export_values();
111 
112  py_netlist_graph.def_static(
113  "from_netlist",
114  [](Netlist* nl, bool create_dummy_vertices = false, const std::function<bool(const Net*)>& filter = nullptr) -> std::unique_ptr<graph_algorithm::NetlistGraph> {
115  auto res = graph_algorithm::NetlistGraph::from_netlist(nl, create_dummy_vertices, filter);
116  if (res.is_ok())
117  {
118  return res.get();
119  }
120  else
121  {
122  log_error("python_context", "error encountered while creating a graph from a netlist:\n{}", res.get_error().get());
123  return nullptr;
124  }
125  },
126  py::arg("nl"),
127  py::arg("create_dummy_vertices") = false,
128  py::arg("filter") = nullptr,
129  py::keep_alive<0, 1>(),
130  R"(Create a directed graph from a netlist. Optionally create dummy nodes at nets missing a source or destination. An optional filter can be applied to exclude undesired edges.
131 
132  :param hal_py.Netlist nl: The netlist.
133  :param bool create_dummy_vertices: Set ``True`` to create dummy vertices, ``False`` otherwise. Defaults to ``False``.
134  :param lambda filter: An optional filter that is evaluated on every net of the netlist. Defaults to ``None``.
135  :returns: The netlist graph on success, ``None`` otherwise.
136  :rtype: graph_algorithm.NetlistGraph or None
137  )");
138 
139  py_netlist_graph.def_static(
140  "from_netlist_no_edges",
141  [](Netlist* nl, const std::vector<Gate*>& gates = {}) -> std::unique_ptr<graph_algorithm::NetlistGraph> {
143  if (res.is_ok())
144  {
145  return res.get();
146  }
147  else
148  {
149  log_error("python_context", "error encountered while creating a graph from a netlist:\n{}", res.get_error().get());
150  return nullptr;
151  }
152  },
153  py::arg("nl"),
154  py::arg("gates") = std::vector<Gate*>(),
155  py::keep_alive<0, 1>(),
156  R"(Create an empty directed graph from a netlist, i.e., vertices for all gates are created, but no edges are added.
157 
158  :param hal_py.Netlist nl: The netlist.
159  :param list[hal_py.Gate] gates: The gates to include in the graph. If omitted, all gates of the netlist will be included.
160  :returns: The netlist graph on success, ``None`` otherwise.
161  :rtype: graph_algorithm.NetlistGraph or None
162  )");
163 
164  py_netlist_graph.def_static(
165  "from_gates",
166  [](const std::vector<Gate*>& gates, const std::set<Gate*>& split_gates = {}, const std::function<bool(const Net*)>& filter = nullptr) -> std::unique_ptr<graph_algorithm::NetlistGraph> {
167  auto res = graph_algorithm::NetlistGraph::from_gates(gates, split_gates, filter);
168  if (res.is_ok())
169  {
170  return res.get();
171  }
172  else
173  {
174  log_error("python_context", "error encountered while creating a graph from a set of gates:\n{}", res.get_error().get());
175  return nullptr;
176  }
177  },
178  py::arg("gates"),
179  py::arg("split_gates") = std::set<Gate*>(),
180  py::arg("filter") = nullptr,
181  py::keep_alive<0, 1>(),
182  R"(Create a directed graph from a subset of the gates of a netlist.
183 
184  Only the given gates become vertices and only nets between two of them become edges, so the graph is a closed world irrespective of what the gates are connected to elsewhere in the netlist.
185 
186  Gates in ``split_gates`` are represented by two vertices instead of one: a primary vertex carrying only the outgoing edges of the gate and a shadow vertex carrying only its incoming edges.
187  This breaks feedback through those gates, which makes a sequential loop such as the round function of a cipher acyclic without having to copy it into a netlist of its own.
188  Both vertices resolve back to the same gate, so use ``is_shadow_vertex`` to tell the two roles apart.
189  A shadow vertex is only created if the gate actually has incoming edges within the graph.
190 
191  Vertices are numbered in the order of ``gates``, so pass them in a deterministic order to obtain a reproducible graph.
192 
193  :param list[hal_py.Gate] gates: The gates to include in the graph. Must all belong to the same netlist.
194  :param set[hal_py.Gate] split_gates: The gates to represent by a primary and a shadow vertex. Gates that are not part of ``gates`` are ignored. Defaults to an empty set.
195  :param lambda filter: An optional filter that is evaluated on every net considered as an edge. Defaults to ``None``.
196  :returns: The netlist graph on success, ``None`` otherwise.
197  :rtype: graph_algorithm.NetlistGraph or None
198  )");
199 
200  py_netlist_graph.def(
201  "copy",
202  [](const graph_algorithm::NetlistGraph& self) -> std::unique_ptr<graph_algorithm::NetlistGraph> {
203  auto res = self.copy();
204  if (res.is_ok())
205  {
206  return res.get();
207  }
208  else
209  {
210  log_error("python_context", "error encountered while copying netlist graph:\n{}", res.get_error().get());
211  return nullptr;
212  }
213  },
214  py::keep_alive<0, 1>(),
215  R"(
216  Create a deep copy of the netlist graph.
217 
218  :returns: The copied netlist graph on success, ``None`` otherwise.
219  :rtype: graph_algorithm.NetlistGraph or None
220  )");
221 
222  py_netlist_graph.def("get_netlist", &graph_algorithm::NetlistGraph::get_netlist, py::return_value_policy::reference, R"(
223  Get the netlist associated with the netlist graph.
224 
225  :returns: The netlist.
226  :rtype: hal_py.Netlist
227  )");
228 
229  py_netlist_graph.def(
230  "get_gates_from_vertices",
231  [](const graph_algorithm::NetlistGraph& self, const std::vector<u32>& vertices) -> std::optional<std::vector<Gate*>> {
232  auto res = self.get_gates_from_vertices(vertices);
233  if (res.is_ok())
234  {
235  return res.get();
236  }
237  else
238  {
239  log_error("python_context", "error encountered while getting gates from vertices:\n{}", res.get_error().get());
240  return std::nullopt;
241  }
242  },
243  py::arg("vertices"),
244  borrowed(), R"(
245  Get the gates corresponding to the specified list of vertices.
246  The result may contain ``None`` for dummy vertices.
247 
248  :param list[int] vertices: A list of vertices.
249  :returns: A list of gates on success, ``None`` otherwise.
250  :rtype: list[hal_py.Gate] or None
251  )");
252 
253  py_netlist_graph.def(
254  "get_gates_from_vertices",
255  [](const graph_algorithm::NetlistGraph& self, const std::set<u32>& vertices) -> std::optional<std::vector<Gate*>> {
256  const auto res = self.get_gates_from_vertices(vertices);
257  if (res.is_ok())
258  {
259  return res.get();
260  }
261  else
262  {
263  log_error("python_context", "error encountered while getting gates from vertices:\n{}", res.get_error().get());
264  return std::nullopt;
265  }
266  },
267  py::arg("vertices"),
268  borrowed(), R"(
269  Get the gates corresponding to the specified set of vertices.
270  The result may contain ``None`` for dummy vertices.
271 
272  :param set[int] vertices: A set of vertices.
273  :returns: A list of gates on success, ``None`` otherwise.
274  :rtype: list[hal_py.Gate] or None
275  )");
276 
277  py_netlist_graph.def(
278  "get_gates_set_from_vertices",
279  [](const graph_algorithm::NetlistGraph& self, const std::vector<u32>& vertices) -> std::optional<std::set<Gate*>> {
280  auto res = self.get_gates_set_from_vertices(vertices);
281  if (res.is_ok())
282  {
283  return res.get();
284  }
285  else
286  {
287  log_error("python_context", "error encountered while getting gates from vertices:\n{}", res.get_error().get());
288  return std::nullopt;
289  }
290  },
291  py::arg("vertices"),
292  borrowed(), R"(
293  Get the gates corresponding to the specified list of vertices.
294 
295  :param list[int] vertices: A list of vertices.
296  :returns: A list of gates on success, ``None`` otherwise.
297  :rtype: set[hal_py.Gate] or None
298  )");
299 
300  py_netlist_graph.def(
301  "get_gates_set_from_vertices",
302  [](const graph_algorithm::NetlistGraph& self, const std::set<u32>& vertices) -> std::optional<std::set<Gate*>> {
303  const auto res = self.get_gates_set_from_vertices(vertices);
304  if (res.is_ok())
305  {
306  return res.get();
307  }
308  else
309  {
310  log_error("python_context", "error encountered while getting gates from vertices:\n{}", res.get_error().get());
311  return std::nullopt;
312  }
313  },
314  py::arg("vertices"),
315  borrowed(), R"(
316  Get the gates corresponding to the specified set of vertices.
317 
318  :param set[int] vertices: A set of vertices.
319  :returns: A list of gates on success, ``None`` otherwise.
320  :rtype: set[hal_py.Gate] or None
321  )");
322 
323  py_netlist_graph.def(
324  "get_gate_from_vertex",
325  [](const graph_algorithm::NetlistGraph& self, const u32 vertex) -> Gate* {
326  const auto res = self.get_gate_from_vertex(vertex);
327  if (res.is_ok())
328  {
329  return res.get();
330  }
331  else
332  {
333  log_error("python_context", "error encountered while getting gate from vertex:\n{}", res.get_error().get());
334  return nullptr;
335  }
336  },
337  py::arg("vertex"),
338  borrowed(), R"(
339  Get the gates corresponding to the specified vertex.
340 
341  :param int vertex: A vertex.
342  :returns: A gate on success, ``None`` otherwise.
343  :rtype: hal_py.Gate or None
344  )");
345 
346  py_netlist_graph.def(
347  "get_vertices_from_gates",
348  [](const graph_algorithm::NetlistGraph& self, const std::vector<Gate*>& gates) -> std::optional<std::vector<u32>> {
349  auto res = self.get_vertices_from_gates(gates);
350  if (res.is_ok())
351  {
352  return res.get();
353  }
354  else
355  {
356  log_error("python_context", "error encountered while getting vertices from gates:\n{}", res.get_error().get());
357  return std::nullopt;
358  }
359  },
360  py::arg("gates"),
361  R"(
362  Get the vertices corresponding to the specified list of gates.
363 
364  :param list[hal_py.Gate] gates: A list of gates.
365  :returns: A list of vertices on success, ``None`` otherwise.
366  :rtype: list[int] or None
367  )");
368 
369  py_netlist_graph.def(
370  "get_vertices_from_gates",
371  [](const graph_algorithm::NetlistGraph& self, const std::set<Gate*>& gates) -> std::optional<std::vector<u32>> {
372  auto res = self.get_vertices_from_gates(gates);
373  if (res.is_ok())
374  {
375  return res.get();
376  }
377  else
378  {
379  log_error("python_context", "error encountered while getting vertices from gates:\n{}", res.get_error().get());
380  return std::nullopt;
381  }
382  },
383  py::arg("gates"),
384  R"(
385  Get the vertices corresponding to the specified set of gates.
386 
387  :param set[hal_py.Gate] gates: A set of gates.
388  :returns: A list of vertices on success, ``None`` otherwise.
389  :rtype: list[int] or None
390  )");
391 
392  py_netlist_graph.def(
393  "get_vertex_from_gate",
394  [](const graph_algorithm::NetlistGraph& self, Gate* g) -> std::optional<u32> {
395  auto res = self.get_vertex_from_gate(g);
396  if (res.is_ok())
397  {
398  return res.get();
399  }
400  else
401  {
402  log_error("python_context", "error encountered while getting vertex from gate:\n{}", res.get_error().get());
403  return std::nullopt;
404  }
405  },
406  py::arg("g"),
407  R"(
408  Get the vertex corresponding to the specified gate.
409 
410  :param hal_py.Gate g: A gate.
411  :returns: A vertex on success, ``None`` otherwise.
412  :rtype: int or None
413  )");
414 
415  py_netlist_graph.def("is_shadow_vertex", &graph_algorithm::NetlistGraph::is_shadow_vertex, py::arg("vertex"), R"(
416  Check whether the specified vertex is a shadow vertex.
417 
418  A shadow vertex carries only the incoming edges of a gate that was split by ``from_gates``, while the primary vertex of that gate carries only its outgoing edges.
419  Both resolve to the same gate, so this is the only way to tell which of the two roles a vertex stands for.
420 
421  :param int vertex: A vertex.
422  :returns: ``True`` if the vertex is a shadow vertex, ``False`` otherwise.
423  :rtype: bool
424  )");
425 
426  py_netlist_graph.def(
427  "get_all_vertices_from_gate",
428  [](const graph_algorithm::NetlistGraph& self, Gate* g) -> std::optional<std::vector<u32>> {
429  auto res = self.get_all_vertices_from_gate(g);
430  if (res.is_ok())
431  {
432  return res.get();
433  }
434  else
435  {
436  log_error("python_context", "error encountered while getting vertices from gate:\n{}", res.get_error().get());
437  return std::nullopt;
438  }
439  },
440  py::arg("g"),
441  R"(
442  Get all vertices corresponding to the specified gate, i.e., its primary vertex and, if the gate was split by ``from_gates``, its shadow vertex.
443 
444  :param hal_py.Gate g: A gate.
445  :returns: The vertices of the gate on success, ``None`` otherwise.
446  :rtype: list[int] or None
447  )");
448 
449  py_netlist_graph.def("get_num_vertices", &graph_algorithm::NetlistGraph::get_num_vertices, py::arg("only_connected") = false, R"(
450  Get the number of vertices in the netlist graph.
451 
452  :param bool only_connected: Set ``True`` to only count vertices connected to at least one edge, ``False`` otherwise. Defaults to ``False``.
453  :returns: The number of vertices in the netlist graph.
454  :rtype: int
455  )");
456 
457  py_netlist_graph.def("get_num_edges", &graph_algorithm::NetlistGraph::get_num_edges, R"(
458  Get the number of edges in the netlist graph.
459 
460  :returns: The number of edges in the netlist graph.
461  :rtype: int
462  )");
463 
464  py_netlist_graph.def(
465  "get_vertices",
466  [](const graph_algorithm::NetlistGraph& self, bool only_connected = false) -> std::optional<std::vector<u32>> {
467  auto res = self.get_vertices(only_connected);
468  if (res.is_ok())
469  {
470  return res.get();
471  }
472  else
473  {
474  log_error("python_context", "error encountered while getting vertices:\n{}", res.get_error().get());
475  return std::nullopt;
476  }
477  },
478  py::arg("only_connected") = false,
479  R"(
480  Get the vertices in the netlist graph.
481 
482  :param bool only_connected: Set ``True`` to only return vertices connected to at least one edge, ``False`` otherwise. Defaults to ``False``.
483  :returns: A list of vertices on success, ``None`` otherwise.
484  :rtype: list[int] or None
485  )");
486 
487  py_netlist_graph.def(
488  "get_edges",
489  [](const graph_algorithm::NetlistGraph& self) -> std::optional<std::vector<std::pair<u32, u32>>> {
490  auto res = self.get_edges();
491  if (res.is_ok())
492  {
493  return res.get();
494  }
495  else
496  {
497  log_error("python_context", "error encountered while getting edges:\n{}", res.get_error().get());
498  return std::nullopt;
499  }
500  },
501  R"(
502  Get the edges between vertices in the netlist graph.
503 
504  :returns: A list of edges on success, ``None`` otherwise.
505  :rtype: list[tuple(int,int)] or None
506  )");
507 
508  py_netlist_graph.def(
509  "get_edges_in_netlist",
510  [](const graph_algorithm::NetlistGraph& self) -> std::optional<std::vector<std::pair<Gate*, Gate*>>> {
511  auto res = self.get_edges_in_netlist();
512  if (res.is_ok())
513  {
514  return res.get();
515  }
516  else
517  {
518  log_error("python_context", "error encountered while getting edges:\n{}", res.get_error().get());
519  return std::nullopt;
520  }
521  },
522  R"(
523  Get the edges between gates in the netlist corresponding to the netlist graph.
524 
525  :returns: A list of edges on success, ``None`` otherwise.
526  :rtype: list[tuple(hal_py.Gate,hal_py.Gate)] or None
527  )");
528 
529  py_netlist_graph.def(
530  "add_edges",
531  [](graph_algorithm::NetlistGraph& self, const std::vector<std::pair<Gate*, Gate*>>& edges) -> bool {
532  auto res = self.add_edges(edges);
533  if (res.is_ok())
534  {
535  return true;
536  }
537  else
538  {
539  log_error("python_context", "error encountered while adding edges:\n{}", res.get_error().get());
540  return false;
541  }
542  },
543  py::arg("edges"),
544  R"(
545  Add edges between the specified pairs of source and destination gates to the netlist graph.
546  The gates must already correspond to vertices in the graph.
547 
548  :param list[tuple(hal_py.Gate,hal_py.Gate)] edges: The edges to add as pairs of gates.
549  :returns: ``True`` on success, ``False`` otherwise.
550  :rtype: bool
551  )");
552 
553  py_netlist_graph.def(
554  "add_edges",
555  [](graph_algorithm::NetlistGraph& self, const std::vector<std::pair<u32, u32>>& edges) -> bool {
556  auto res = self.add_edges(edges);
557  if (res.is_ok())
558  {
559  return true;
560  }
561  else
562  {
563  log_error("python_context", "error encountered while adding edges:\n{}", res.get_error().get());
564  return false;
565  }
566  },
567  py::arg("edges"),
568  R"(
569  Add edges between the specified pairs of source and destination vertices to the netlist graph.
570  The vertices must already exist in the graph.
571 
572  :param list[tuple(int,int)] edges: The edges to add as pairs of vertices.
573  :returns: ``True`` on success, ``False`` otherwise.
574  :rtype: bool
575  )");
576 
577  py_netlist_graph.def(
578  "add_edges",
579  [](graph_algorithm::NetlistGraph& self, const std::map<Gate*, std::set<Gate*>>& edges) -> bool {
580  auto res = self.add_edges(edges);
581  if (res.is_ok())
582  {
583  return true;
584  }
585  else
586  {
587  log_error("python_context", "error encountered while adding edges:\n{}", res.get_error().get());
588  return false;
589  }
590  },
591  py::arg("edges"),
592  R"(
593  Add edges between the specified pairs of source and destination gates to the netlist graph.
594  The vertices must already exist in the graph.
595 
596  :param dict[hal_py.Gate,set[hal_py.Gate]] edges: The edges to add as a dict from source gate to its destination gates.
597  :returns: ``True`` on success, ``False`` otherwise.
598  :rtype: bool
599  )");
600 
601  py_netlist_graph.def(
602  "delete_edges",
603  [](graph_algorithm::NetlistGraph& self, const std::vector<std::pair<Gate*, Gate*>>& edges) -> bool {
604  auto res = self.delete_edges(edges);
605  if (res.is_ok())
606  {
607  return true;
608  }
609  else
610  {
611  log_error("python_context", "error encountered while deleting edges:\n{}", res.get_error().get());
612  return false;
613  }
614  },
615  py::arg("edges"),
616  R"(
617  Delete edges between the specified pairs of source and destination gates from the netlist graph.
618 
619  :param list[tuple(hal_py.Gate,hal_py.Gate)] edges: The edges to delete as pairs of gates.
620  :returns: ``True`` on success, ``False`` otherwise.
621  :rtype: bool
622  )");
623 
624  py_netlist_graph.def(
625  "delete_edges",
626  [](graph_algorithm::NetlistGraph& self, const std::vector<std::pair<u32, u32>>& edges) -> bool {
627  auto res = self.delete_edges(edges);
628  if (res.is_ok())
629  {
630  return true;
631  }
632  else
633  {
634  log_error("python_context", "error encountered while deleting edges:\n{}", res.get_error().get());
635  return false;
636  }
637  },
638  py::arg("edges"),
639  R"(
640  Delete edges between the specified pairs of source and destination vertices from the netlist graph.
641 
642  :param list[tuple(int,int)] edges: The edges to delete as pairs of vertices.
643  :returns: ``True`` on success, ``False`` otherwise.
644  :rtype: bool
645  )");
646 
647  py_netlist_graph.def("print", &graph_algorithm::NetlistGraph::print, R"(
648  Print the edge list of the graph to stdout.
649  )");
650 
651  m.def(
652  "get_connected_components",
653  [](graph_algorithm::NetlistGraph* graph, bool strong, u32 min_size = 0) -> std::optional<std::vector<std::vector<u32>>> {
654  auto res = graph_algorithm::get_connected_components(graph, strong, min_size);
655  if (res.is_ok())
656  {
657  return res.get();
658  }
659  else
660  {
661  log_error("python_context", "error encountered while computing connected components:\n{}", res.get_error().get());
662  return std::nullopt;
663  }
664  },
665  py::arg("graph"),
666  py::arg("strong"),
667  py::arg("min_size") = 0,
668  R"(
669  Compute the (strongly) connected components of the specified graph.
670  Returns each connected component as a list of vertices in the netlist graph.
671 
672  :param graph_algorithm.NetlistGraph graph: The netlist graph.
673  :param bool strong: Set ``True`` to compute strongly connected components, ``False`` otherwise.
674  :param int min_size: Minimal size of a connected component to be part of the result. Set to ``0`` to include all components. Defaults to ``0``.
675  :returns: A list of strongly connected components on success, ``None`` otherwise.
676  :rtype: list[list[int]] or None
677  )");
678 
679  m.def(
680  "get_neighborhood",
681  [](graph_algorithm::NetlistGraph* graph, const std::vector<Gate*>& start_gates, u32 order, graph_algorithm::NetlistGraph::Direction direction, u32 min_dist = 0)
682  -> std::optional<std::vector<std::vector<u32>>> {
683  auto res = graph_algorithm::get_neighborhood(graph, start_gates, order, direction, min_dist);
684  if (res.is_ok())
685  {
686  return res.get();
687  }
688  else
689  {
690  log_error("python_context", "error encountered while computing neighborhood:\n{}", res.get_error().get());
691  return std::nullopt;
692  }
693  },
694  py::arg("graph"),
695  py::arg("start_gates"),
696  py::arg("order"),
697  py::arg("direction"),
698  py::arg("min_dist") = 0,
699  R"(
700  Compute the neighborhood of the given order for each of the specified gates within the given netlist graph.
701  For order 0, only the vertex itself is returned. For order 1, the vertex itself and all vertices that are its direct predecessors and/or successors (depending on the specified direction). For order 2, the neighborhood of order 1 plus all direct predecessors and/or successors of the vertices in order 1 are returned, etc.
702  Returns each neighborhood as a list of vertices in the netlist graph.
703 
704  :param graph_algorithm.NetlistGraph graph: The netlist graph.
705  :param list[hal_py.Gate] start_gates: A list of gates for which to compute the neighborhood.
706  :param int order: The order of the neighborhood to compute.
707  :param graph_algorithm.NetlistGraph.Direction direction: The direction in which the neighborhood should be computed.
708  :param int min_dist: The minimum distance of the vertices to include in the result.
709  :returns: A list of neighborhoods of each of the provided start gates (in order) on success, ``None`` otherwise.
710  :rtype: list[list[int]] or None
711  )");
712 
713  m.def(
714  "get_neighborhood",
715  [](graph_algorithm::NetlistGraph* graph, const std::vector<u32>& start_vertices, u32 order, graph_algorithm::NetlistGraph::Direction direction, u32 min_dist = 0)
716  -> std::optional<std::vector<std::vector<u32>>> {
717  auto res = graph_algorithm::get_neighborhood(graph, start_vertices, order, direction, min_dist);
718  if (res.is_ok())
719  {
720  return res.get();
721  }
722  else
723  {
724  log_error("python_context", "error encountered while computing neighborhood:\n{}", res.get_error().get());
725  return std::nullopt;
726  }
727  },
728  py::arg("graph"),
729  py::arg("start_vertices"),
730  py::arg("order"),
731  py::arg("direction"),
732  py::arg("min_dist") = 0,
733  R"(
734  Compute the neighborhood of the given order for each of the specified vertices within the given netlist graph.
735  For order 0, only the vertex itself is returned. For order 1, the vertex itself and all vertices that are its direct predecessors and/or successors (depending on the specified direction). For order 2, the neighborhood of order 1 plus all direct predecessors and/or successors of the vertices in order 1 are returned, etc.
736  Returns each neighborhood as a list of vertices in the netlist graph.
737 
738  :param graph_algorithm.NetlistGraph graph: The netlist graph.
739  :param list[int] start_vertices: A list of vertices for which to compute the neighborhood.
740  :param int order: The order of the neighborhood to compute.
741  :param graph_algorithm.NetlistGraph.Direction direction: The direction in which the neighborhood should be computed.
742  :param int min_dist: The minimum distance of the vertices to include in the result.
743  :returns: A list of neighborhoods of each of the provided start vertices (in order) on success, ``None`` otherwise.
744  :rtype: list[list[int]] or None
745  )");
746 
747  m.def(
748  "get_shortest_paths",
749  [](graph_algorithm::NetlistGraph* graph, Gate* from_gate, const std::vector<Gate*>& to_gates, graph_algorithm::NetlistGraph::Direction direction)
750  -> std::optional<std::vector<std::vector<u32>>> {
751  auto res = graph_algorithm::get_shortest_paths(graph, from_gate, to_gates, direction);
752  if (res.is_ok())
753  {
754  return res.get();
755  }
756  else
757  {
758  log_error("python_context", "error encountered while computing shortest paths:\n{}", res.get_error().get());
759  return std::nullopt;
760  }
761  },
762  py::arg("graph"),
763  py::arg("from_gate"),
764  py::arg("to_gates"),
765  py::arg("direction"),
766  R"(
767  Compute a shortest path from the specified ``from_gate`` to each of the given ``to_gates`` by traversing in the provided direction.
768  Returns one shortest path for each end gate, even if multiple shortest paths exist.
769  Each shortest path is given as a list of vertices in the order of traversal.
770 
771  :param graph_algorithm.NetlistGraph graph: The netlist graph.
772  :param hal_py.Gate from_gate: The start gate of the shortest path.
773  :param list[hal_py.Gate] to_gates: A list of end gates of the shortest path.
774  :param graph_algorithm.NetlistGraph.Direction direction: The direction in which to compute the shortest paths starting at the ``from_gate``.
775  :returns: The shortest paths in order of the ``to_gates`` on success, an error otherwise.
776  :rtype: list[list[int]] or None
777  )");
778 
779  m.def(
780  "get_shortest_paths",
781  [](graph_algorithm::NetlistGraph* graph, u32 from_vertice, const std::vector<u32>& to_vertices, graph_algorithm::NetlistGraph::Direction direction)
782  -> std::optional<std::vector<std::vector<u32>>> {
783  auto res = graph_algorithm::get_shortest_paths(graph, from_vertice, to_vertices, direction);
784  if (res.is_ok())
785  {
786  return res.get();
787  }
788  else
789  {
790  log_error("python_context", "error encountered while computing shortest paths:\n{}", res.get_error().get());
791  return std::nullopt;
792  }
793  },
794  py::arg("graph"),
795  py::arg("from_vertex"),
796  py::arg("to_vertices"),
797  py::arg("direction"),
798  R"(
799  Compute a shortest path from the specified ``from_vertex`` to each of the given ``to_vertices`` by traversing in the provided direction.
800  Returns one shortest path for each end vertex, even if multiple shortest paths exist.
801  Each shortest path is given as a list of vertices in the order of traversal.
802 
803  :param graph_algorithm.NetlistGraph graph: The netlist graph.
804  :param int from_vertex: The start vertex of the shortest path.
805  :param list[int] to_vertices: A list of end vertices of the shortest path.
806  :param graph_algorithm.NetlistGraph.Direction direction: The direction in which to compute the shortest paths starting at the ``from_vertex``.
807  :returns: The shortest paths in order of the ``to_vertices`` on success, an error otherwise.
808  :rtype: list[list[int]] or None
809  )");
810 
811  m.def(
812  "get_all_shortest_paths",
813  [](graph_algorithm::NetlistGraph* graph, Gate* from_gate, const std::vector<Gate*>& to_gates, graph_algorithm::NetlistGraph::Direction direction)
814  -> std::optional<std::vector<std::vector<u32>>> {
815  auto res = graph_algorithm::get_all_shortest_paths(graph, from_gate, to_gates, direction);
816  if (res.is_ok())
817  {
818  return res.get();
819  }
820  else
821  {
822  log_error("python_context", "error encountered while computing all shortest paths:\n{}", res.get_error().get());
823  return std::nullopt;
824  }
825  },
826  py::arg("graph"),
827  py::arg("from_gate"),
828  py::arg("to_gates"),
829  py::arg("direction"),
830  R"(
831  Compute shortest paths from the specified ``from_gate`` to each of the given ``to_gates`` by traversing in the provided direction.
832  Returns all shortest paths for each end gate.
833  Each shortest path is given as a list of vertices in the order of traversal.
834 
835  :param graph_algorithm.NetlistGraph graph: The netlist graph.
836  :param hal_py.Gate from_gate: The start gate of the shortest path.
837  :param list[hal_py.Gate] to_gates: A list of end gates of the shortest path.
838  :param graph_algorithm.NetlistGraph.Direction direction: The direction in which to compute the shortest paths starting at the ``from_gate``.
839  :returns: The shortest paths in order of the ``to_gates`` on success, an error otherwise.
840  :rtype: list[list[int]] or None
841  )");
842 
843  m.def(
844  "get_all_shortest_paths",
845  [](graph_algorithm::NetlistGraph* graph, u32 from_vertice, const std::vector<u32>& to_vertices, graph_algorithm::NetlistGraph::Direction direction)
846  -> std::optional<std::vector<std::vector<u32>>> {
847  auto res = graph_algorithm::get_all_shortest_paths(graph, from_vertice, to_vertices, direction);
848  if (res.is_ok())
849  {
850  return res.get();
851  }
852  else
853  {
854  log_error("python_context", "error encountered while computing all shortest paths:\n{}", res.get_error().get());
855  return std::nullopt;
856  }
857  },
858  py::arg("graph"),
859  py::arg("from_vertex"),
860  py::arg("to_vertices"),
861  py::arg("direction"),
862  R"(
863  Compute shortest paths from the specified ``from_vertex`` to each of the given ``to_vertices`` by traversing in the provided direction.
864  Returns all shortest paths for each end gate.
865  Each shortest path is given as a list of vertices in the order of traversal.
866 
867  :param graph_algorithm.NetlistGraph graph: The netlist graph.
868  :param int from_vertex: The start vertex of the shortest path.
869  :param list[int] to_vertices: A list of end vertices of the shortest path.
870  :param graph_algorithm.NetlistGraph.Direction direction: The direction in which to compute the shortest paths starting at the ``from_vertex``.
871  :returns: The shortest paths in order of the ``to_vertices`` on success, an error otherwise.
872  :rtype: list[list[int]] or None
873  )");
874 
875  m.def(
876  "get_subgraph",
877  [](const graph_algorithm::NetlistGraph* graph, const std::vector<Gate*>& subgraph_gates) -> std::optional<std::unique_ptr<graph_algorithm::NetlistGraph>> {
878  auto res = graph_algorithm::get_subgraph(graph, subgraph_gates);
879  if (res.is_ok())
880  {
881  return res.get();
882  }
883  else
884  {
885  log_error("python_context", "error encountered while computing subgraph:\n{}", res.get_error().get());
886  return std::nullopt;
887  }
888  },
889  py::arg("graph"),
890  py::arg("subgraph_gates"),
891  py::keep_alive<0, 1>(),
892  R"(
893  Compute the subgraph induced by the specified gates, including all edges between the corresponding vertices.
894 
895  :param graph_algorithm.NetlistGraph graph: The netlist graph.
896  :param list[hal_py.Gate] subgraph_gates: A list of gates that make up the subgraph.
897  :returns: The subgraph as a new netlist graph on success, ``None`` otherwise.
898  :rtype: graph_algorithm.NetlistGraph or None
899  )");
900 
901  m.def(
902  "get_subgraph",
903  [](const graph_algorithm::NetlistGraph* graph, const std::set<Gate*>& subgraph_gates) -> std::optional<std::unique_ptr<graph_algorithm::NetlistGraph>> {
904  auto res = graph_algorithm::get_subgraph(graph, subgraph_gates);
905  if (res.is_ok())
906  {
907  return res.get();
908  }
909  else
910  {
911  log_error("python_context", "error encountered while computing subgraph:\n{}", res.get_error().get());
912  return std::nullopt;
913  }
914  },
915  py::arg("graph"),
916  py::arg("subgraph_gates"),
917  py::keep_alive<0, 1>(),
918  R"(
919  Compute the subgraph induced by the specified gates, including all edges between the corresponding vertices.
920 
921  :param graph_algorithm.NetlistGraph graph: The netlist graph.
922  :param set[hal_py.Gate] subgraph_gates: A set of gates that make up the subgraph.
923  :returns: The subgraph as a new netlist graph on success, ``None`` otherwise.
924  :rtype: graph_algorithm.NetlistGraph or None
925  )");
926 
927  m.def(
928  "get_subgraph",
929  [](const graph_algorithm::NetlistGraph* graph, const std::vector<u32>& subgraph_vertices) -> std::optional<std::unique_ptr<graph_algorithm::NetlistGraph>> {
930  auto res = graph_algorithm::get_subgraph(graph, subgraph_vertices);
931  if (res.is_ok())
932  {
933  return res.get();
934  }
935  else
936  {
937  log_error("python_context", "error encountered while computing subgraph:\n{}", res.get_error().get());
938  return std::nullopt;
939  }
940  },
941  py::arg("graph"),
942  py::arg("subgraph_vertices"),
943  py::keep_alive<0, 1>(),
944  R"(
945  Compute the subgraph induced by the specified vertices, including all edges between these vertices.
946 
947  :param graph_algorithm.NetlistGraph graph: The netlist graph.
948  :param list[int] subgraph_vertices: A list of vertices that make up the subgraph.
949  :returns: The subgraph as a new netlist graph on success, ``None`` otherwise.
950  :rtype: graph_algorithm.NetlistGraph or None
951  )");
952 
953  m.def(
954  "get_subgraph",
955  [](const graph_algorithm::NetlistGraph* graph, const std::set<u32>& subgraph_vertices) -> std::optional<std::unique_ptr<graph_algorithm::NetlistGraph>> {
956  auto res = graph_algorithm::get_subgraph(graph, subgraph_vertices);
957  if (res.is_ok())
958  {
959  return res.get();
960  }
961  else
962  {
963  log_error("python_context", "error encountered while computing subgraph:\n{}", res.get_error().get());
964  return std::nullopt;
965  }
966  },
967  py::arg("graph"),
968  py::arg("subgraph_vertices"),
969  py::keep_alive<0, 1>(),
970  R"(
971  Compute the subgraph induced by the specified vertices, including all edges between these vertices.
972 
973  :param graph_algorithm.NetlistGraph graph: The netlist graph.
974  :param set[int] subgraph_vertices: A set of vertices that make up the subgraph.
975  :returns: The subgraph as a new netlist graph on success, ``None`` otherwise.
976  :rtype: graph_algorithm.NetlistGraph or None
977  )");
978 
979 #ifndef PYBIND11_MODULE
980  return m.ptr();
981 #endif // PYBIND11_MODULE
982  }
983 } // namespace hal
Definition: gate.h:58
std::string get_description() const override
Get a short description of the plugin.
std::string get_version() const override
Get the version of the plugin.
std::set< std::string > get_dependencies() const override
Get the plugin dependencies.
std::string get_name() const override
Get the name of the plugin.
Definition: net.h:58
A directed graph corresponding to a netlist.
Definition: netlist_graph.h:60
Netlist * get_netlist() const
Get the netlist associated with the netlist graph.
u32 get_num_vertices(bool only_connected=false) const
Get the number of vertices in the netlist graph.
bool is_shadow_vertex(const u32 vertex) const
Check whether the specified vertex is a shadow vertex.
static Result< std::unique_ptr< NetlistGraph > > from_netlist(Netlist *nl, bool create_dummy_vertices=false, const std::function< bool(const Net *)> &filter=nullptr)
Create a directed graph from a netlist.
Direction
The direction of exploration within the graph.
Definition: netlist_graph.h:67
@ ALL
Explore in both directions, i.e., treat the graph as undirected.
@ NONE
No direction, invalid default setting.
@ IN
Explore through the inputs of the current node, i.e., traverse backwards.
@ OUT
Explore through the outputs of the current node, i.e., traverse forwards.
static Result< std::unique_ptr< NetlistGraph > > from_gates(const std::vector< Gate * > &gates, const std::set< Gate * > &split_gates={}, const std::function< bool(const Net *)> &filter=nullptr)
Create a directed graph from a subset of the gates of a netlist.
void print() const
Print the edge list of the graph to stdout.
u32 get_num_edges() const
Get the number of edges in the netlist graph.
static Result< std::unique_ptr< NetlistGraph > > from_netlist_no_edges(Netlist *nl, const std::vector< Gate * > &gates={})
Create an empty directed graph from a netlist.
This file contains functions related to graph components.
uint32_t u32
Definition: defines.h:41
#define log_error(channel,...)
Definition: log.h:78
const Module * module(const Gate *g, const NodeBoxes &boxes)
Result< std::vector< std::vector< u32 > > > get_all_shortest_paths(NetlistGraph *graph, Gate *from_gate, const std::vector< Gate * > &to_gates, NetlistGraph::Direction direction)
Compute shortest paths from the specified from_gate to each of the given to_gates by traversing in th...
Result< std::vector< std::vector< u32 > > > get_connected_components(const NetlistGraph *graph, bool strong, u32 min_size=0)
Compute the (strongly) connected components of the specified graph.
Definition: components.cpp:11
Result< std::vector< std::vector< u32 > > > get_shortest_paths(NetlistGraph *graph, Gate *from_gate, const std::vector< Gate * > &to_gates, NetlistGraph::Direction direction)
Compute a shortest path from the specified from_gate to each of the given to_gates by traversing in t...
Result< std::unique_ptr< NetlistGraph > > get_subgraph(const NetlistGraph *graph, const std::vector< Gate * > &subgraph_gates)
Compute the subgraph induced by the specified gates, including all edges between the corresponding ve...
Definition: subgraph.cpp:10
Result< std::vector< std::vector< u32 > > > get_neighborhood(NetlistGraph *graph, const std::vector< Gate * > &start_gates, u32 order, NetlistGraph::Direction direction, u32 min_dist=0)
Compute the neighborhood of the given order for each of the specified gates within the given netlist ...
Definition: neighborhood.cpp:9
Definition: defines.h:45
PYBIND11_PLUGIN(hal_py)
This file contains functions related to neighborhoods in graphs.
PinDirection direction
This file contains the class that holds a netlist graph.
This file contains all functions related to the HAL plugin API.
This file contains functions related to shortest paths in graphs.
This file contains functions related to subgraphs.