HAL
python_bindings.cpp
Go to the documentation of this file.
2 
4 #include "pybind11/operators.h"
5 #include "pybind11/pybind11.h"
6 #include "pybind11/stl.h"
7 #include "pybind11/stl_bind.h"
8 
9 namespace py = pybind11;
10 namespace hal
11 {
12 #ifdef PYBIND11_MODULE
13  PYBIND11_MODULE(dataflow, m)
14  {
15  m.doc() = "Dataflow analysis tool DANA to recover word-level structures such as registers from gate-level netlists.";
16 #else
17  PYBIND11_PLUGIN(dataflow)
18  {
19  py::module m("dataflow", "Dataflow analysis tool DANA to recover word-level structures such as registers from gate-level netlists.");
20 #endif // ifdef PYBIND11_MODULE
21  py::class_<DataflowPlugin, RawPtrWrapper<DataflowPlugin>, BasePluginInterface> py_dataflow_plugin(
22  m, "DataflowPlugin", R"(This class provides an interface to integrate the DANA tool as a plugin within the HAL framework.)");
23 
24  py_dataflow_plugin.def_property_readonly("name", &DataflowPlugin::get_name, R"(
25  The name of the plugin.
26 
27  :type: str
28  )");
29 
30  py_dataflow_plugin.def("get_name", &DataflowPlugin::get_name, R"(
31  Get the name of the plugin.
32 
33  :returns: The name of the plugin.
34  :rtype: str
35  )");
36 
37  py_dataflow_plugin.def_property_readonly("description", &DataflowPlugin::get_description, R"(
38  The short description of the plugin.
39 
40  :type: str
41  )");
42 
43  py_dataflow_plugin.def("get_description", &DataflowPlugin::get_description, R"(
44  Get the short description of the plugin.
45 
46  :returns: The short description of the plugin.
47  :rtype: str
48  )");
49 
50  py_dataflow_plugin.def_property_readonly("version", &DataflowPlugin::get_version, R"(
51  The version of the plugin.
52 
53  :type: str
54  )");
55 
56  py_dataflow_plugin.def("get_version", &DataflowPlugin::get_version, R"(
57  Get the version of the plugin.
58 
59  :returns: The version of the plugin.
60  :rtype: str
61  )");
62 
63  py::class_<dataflow::Configuration, RawPtrWrapper<dataflow::Configuration>> py_dataflow_configuration(m, "Configuration", R"(
64  This class holds all information relevant for the configuration of a dataflow analysis run, including the netlist to analyze.
65  )");
66 
67  py_dataflow_configuration.def(py::init<Netlist*>(), py::arg("nl"), R"(
68  Construct a new dataflow analysis configuration for the given netlist.
69 
70  :param hal_py.Netlist nl: The netlist.
71  )");
72 
73  py_dataflow_configuration.def_readwrite("min_group_size", &dataflow::Configuration::min_group_size, R"(
74  Minimum size of a group. Smaller groups will be penalized during analysis. Defaults to 8.
75 
76  :type: int
77  )");
78 
79  py_dataflow_configuration.def_readwrite("expected_sizes", &dataflow::Configuration::expected_sizes, R"(
80  Expected group sizes. Groups of these sizes will be prioritized. Defaults to an empty list.
81 
82  :type: list[int]
83  )");
84 
85  py_dataflow_configuration.def_readwrite("known_gate_groups", &dataflow::Configuration::known_gate_groups, R"(
86  Groups of gates that have already been identified as word-level groups beforehand. All gates of a group must be of one of the target gate types. Defaults to an empty list.
87 
88  :type: list[list[hal_py.Gate]]
89  )");
90 
91  py_dataflow_configuration.def_readwrite("known_net_groups", &dataflow::Configuration::known_net_groups, R"(
92  Groups of nets that have been identified as word-level datapathes beforehand. Defaults to an empty list.
93 
94  :type: list[list[hal_py.Net]]
95  )");
96 
97  py_dataflow_configuration.def_readwrite("gate_types", &dataflow::Configuration::gate_types, R"(
98  The gate types to be grouped by dataflow analysis. Defaults to an empty set.
99 
100  :type: set[hal_py.GateType]
101  )");
102 
103  py_dataflow_configuration.def_readwrite("control_pin_types", &dataflow::Configuration::control_pin_types, R"(
104  The pin types of the pins to be considered control pins. Defaults to an empty set.
105 
106  :type: set[hal_py.PinType]
107  )");
108 
109  py_dataflow_configuration.def_readwrite("enable_stages", &dataflow::Configuration::enable_stages, R"(
110  Enable stage identification as part of dataflow analysis. Defaults to ``False``.
111 
112  :type: bool
113  )");
114 
115  py_dataflow_configuration.def_readwrite("enforce_type_consistency", &dataflow::Configuration::enforce_type_consistency, R"(
116  Enforce gate type consistency inside of a group. Defaults to ``False``.
117 
118  :type: bool
119  )");
120 
121  py_dataflow_configuration.def("with_min_group_size", &dataflow::Configuration::with_min_group_size, py::arg("size"), R"(
122  Set the minimum size of a group. Smaller groups will be penalized during analysis.
123 
124  :param int size: The minimum group size.
125  :returns: The updated dataflow analysis configuration.
126  :rtype: dataflow.Dataflow.Configuration
127  )");
128 
129  py_dataflow_configuration.def("with_expected_sizes", &dataflow::Configuration::with_expected_sizes, py::arg("sizes"), R"(
130  Set the expected group sizes. Groups of these sizes will be prioritized.
131 
132  :param list[int] sizes: The expected group sizes.
133  :returns: The updated dataflow analysis configuration.
134  :rtype: dataflow.Dataflow.Configuration
135  )");
136 
137  py_dataflow_configuration.def(
138  "with_known_structures", py::overload_cast<const std::vector<Module*>&, bool>(&dataflow::Configuration::with_known_structures), py::arg("structures"), py::arg("overwrite") = false, R"(
139  Add modules to the set of previously identified word-level structures.
140  The gates contained in the modules do not have to be of the target gate types.
141  The input and output pin groups of these modules will be used to guide datapath analysis.
142  Only pin groups larger than ``min_group_size`` will be considered.
143 
144  :param list[hal_py.Module] structures: A list of modules.
145  :param bool overwrite: Set ``True`` to overwrite the existing known word-level structures, ``False`` otherwise. Defaults to ``False``.
146  :returns: The updated dataflow analysis configuration.
147  :rtype: dataflow.Dataflow.Configuration
148  )");
149 
150  py_dataflow_configuration.def("with_known_structures",
151  py::overload_cast<const std::vector<std::pair<Module*, std::vector<PinGroup<ModulePin>*>>>&, bool>(&dataflow::Configuration::with_known_structures),
152  py::arg("structures"),
153  py::arg("overwrite") = false,
154  R"(
155  Add modules to the set of previously identified word-level structures.
156  The gates contained in the modules do not have to be of the target gate types.
157  The input and output pin groups of these modules will be used to guide datapath analysis.
158  For each module, the input and output pin groups to be considered for analysis must be specified.
159  An empty pin group vector results in all pin groups of the module being considered.
160  Only pin groups larger than ``min_group_size`` will be considered.
161 
162  :param list[tuple(hal_py.Module,list[hal_py.ModulePinGroup])] structures: A list of modules, each of them with a list of module pin groups.
163  :param bool overwrite: Set ``True`` to overwrite the existing known word-level structures, ``False`` otherwise. Defaults to ``False``.
164  :returns: The updated dataflow analysis configuration.
165  :rtype: dataflow.Dataflow.Configuration
166  )");
167 
168  py_dataflow_configuration.def(
169  "with_known_structures", py::overload_cast<const std::vector<Gate*>&, bool>(&dataflow::Configuration::with_known_structures), py::arg("structures"), py::arg("overwrite") = false, R"(
170  Add (typically large) gates to the set of previously identified word-level structures.
171  The gates do not have to be of the target gate types.
172  The input and output pin groups of these gates will be used to guide datapath analysis.
173  Only pin groups larger than ``min_group_size`` will be considered.
174 
175  :param list[hal_py.Gate] structures: A list of gates.
176  :param bool overwrite: Set ``True`` to overwrite the existing known word-level structures, ``False`` otherwise. Defaults to ``False``.
177  :returns: The updated dataflow analysis configuration.
178  :rtype: dataflow.Dataflow.Configuration
179  )");
180 
181  py_dataflow_configuration.def("with_known_structures",
182  py::overload_cast<const std::vector<std::pair<Gate*, std::vector<PinGroup<GatePin>*>>>&, bool>(&dataflow::Configuration::with_known_structures),
183  py::arg("structures"),
184  py::arg("overwrite") = false,
185  R"(
186  Add (typically large) gates to the set of previously identified word-level structures.
187  The gates do not have to be of the target gate types.
188  The input and output pin groups of these gates will be used to guide datapath analysis.
189  For each gate, the input and output pin groups to be considered for analysis must be specified.
190  An empty pin group vector results in all pin groups of the gate being considered.
191  Only pin groups larger than ``min_group_size`` will be considered.
192 
193  :param list[tuple(hal_py.Gate,list[hal_py.GatePinGroup])] structures: A list of gates, each of them with a list of gate pin groups.
194  :param bool overwrite: Set ``True`` to overwrite the existing known word-level structures, ``False`` otherwise. Defaults to ``False``.
195  :returns: The updated dataflow analysis configuration.
196  :rtype: dataflow.Dataflow.Configuration
197  )");
198 
199  py_dataflow_configuration.def("with_known_structures",
200  py::overload_cast<const std::unordered_set<const GateType*>&, bool>(&dataflow::Configuration::with_known_structures),
201  py::arg("structures"),
202  py::arg("overwrite") = false,
203  R"(
204  Add all gates of a (typically large) gate type to the set of previously identified word-level structures.
205  The gate types do not have to be part of the target gate types.
206  The input and output pin groups of the gates of these types will be used to guide datapath analysis.
207  Only pin groups larger than ``min_group_size`` will be considered.
208 
209  :param set[hal_py.GateType] structures: A set of gates.
210  :param bool overwrite: Set ``True`` to overwrite the existing known word-level structures, ``False`` otherwise. Defaults to ``False``.
211  :returns: The updated dataflow analysis configuration.
212  :rtype: dataflow.Dataflow.Configuration
213  )");
214 
215  py_dataflow_configuration.def("with_known_structures",
216  py::overload_cast<const std::unordered_map<const GateType*, std::vector<PinGroup<GatePin>*>>&, bool>(&dataflow::Configuration::with_known_structures),
217  py::arg("structures"),
218  py::arg("overwrite") = false,
219  R"(
220  Add all gates of a (typically large) gate type to the set of previously identified word-level structures.
221  The gate types do not have to be part of the target gate types.
222  The input and output pin groups of the gates of these types will be used to guide datapath analysis.
223  For each gate type, the input and output pin groups to be considered for analysis must be specified.
224  An empty pin group vector results in all pin groups of the gate type being considered.
225  Only pin groups larger than ``min_group_size`` will be considered.
226 
227  :param dict[hal_py.GateType,list[hal_py.GatePinGroup]] structures: A dict from gates to a vector of a subset of their pin groups.
228  :param bool overwrite: Set ``True`` to overwrite the existing known word-level structures, ``False`` otherwise. Defaults to ``False``.
229  :returns: The updated dataflow analysis configuration.
230  :rtype: dataflow.Dataflow.Configuration
231  )");
232 
233  py_dataflow_configuration.def(
234  "with_known_groups", py::overload_cast<const std::vector<Module*>&, bool>(&dataflow::Configuration::with_known_groups), py::arg("groups"), py::arg("overwrite") = false, R"(
235  Add modules to the set of previously identified word-level groups.
236  These groups must only contain gates of the target gate types specified for analysis and will otherwise be ignored.
237  The groups will be used to guide dataflow analysis, but will remain unaltered in the process.
238 
239  :param list[hal_py.Module] groups: A list of modules.
240  :param bool overwrite: Set ``True`` to overwrite the existing previously identified word-level groups, ``False`` otherwise. Defaults to ``False``.
241  :returns: The updated dataflow analysis configuration.
242  :rtype: dataflow.Dataflow.Configuration
243  )");
244 
245  py_dataflow_configuration.def("with_known_groups",
246  py::overload_cast<const std::vector<std::vector<Gate*>>&, bool>(&dataflow::Configuration::with_known_groups),
247  py::arg("groups"),
248  py::arg("overwrite") = false,
249  R"(
250  Add lists of gates to the set of previously identified word-level groups.
251  These groups must only contain gates of the target gate types specified for analysis and will otherwise be ignored.
252  The groups will be used to guide dataflow analysis, but will remain unaltered in the process.
253 
254  :param list[list[hal_py.Gate]] groups: A list of groups, each of them given as a list of gates.
255  :param bool overwrite: Set ``True`` to overwrite the existing previously identified word-level groups, ``False`` otherwise. Defaults to ``False``.
256  :returns: The updated dataflow analysis configuration.
257  :rtype: dataflow.Dataflow.Configuration
258  )");
259 
260  py_dataflow_configuration.def(
261  "with_known_groups", py::overload_cast<const std::vector<std::vector<u32>>&, bool>(&dataflow::Configuration::with_known_groups), py::arg("groups"), py::arg("overwrite") = false, R"(
262  Add lists of gate IDs to the set of previously identified word-level groups.
263  These groups must only contain gates of the target gate types specified for analysis and will otherwise be ignored.
264  The groups will be used to guide dataflow analysis, but will remain unaltered in the process.
265 
266  :param list[list[int]] groups: A list of groups, each of them given as a list of gate IDs.
267  :param bool overwrite: Set ``True`` to overwrite the existing previously identified word-level groups, ``False`` otherwise. Defaults to ``False``.
268  :returns: The updated dataflow analysis configuration.
269  :rtype: dataflow.Dataflow.Configuration
270  )");
271 
272  py_dataflow_configuration.def("with_known_groups",
273  py::overload_cast<const std::unordered_map<u32, std::unordered_set<Gate*>>&, bool>(&dataflow::Configuration::with_known_groups),
274  py::arg("groups"),
275  py::arg("overwrite") = false,
276  R"(
277  Add groups from a previous dataflow analysis run to the set of previously identified word-level groups.
278  These groups must only contain gates of the target gate types specified for analysis and will otherwise be ignored.
279  The groups will be used to guide dataflow analysis, but will remain unaltered in the process.
280  The group IDs will be ignored during analysis and the same group may be assigned a new ID.
281 
282  :param dict[int,set[hal_py.Gate]] groups: A dict from group IDs to groups, each of them given as a set of gates.
283  :param bool overwrite: Set ``True`` to overwrite the existing previously identified word-level groups, ``False`` otherwise. Defaults to ``False``.
284  :returns: The updated dataflow analysis configuration.
285  :rtype: dataflow.Dataflow.Configuration
286  )");
287 
288  py_dataflow_configuration.def(
289  "with_gate_types", py::overload_cast<const std::set<const GateType*>&, bool>(&dataflow::Configuration::with_gate_types), py::arg("types"), py::arg("overwrite") = false, R"(
290  Add the gate types to the set of gate types to be grouped by dataflow analysis.
291  Overwrite the existing set of gate types by setting the optional ``overwrite`` flag to ``True``.
292 
293  :param set[hal_py.GateType] types: A set of gate types.
294  :param bool overwrite: Set ``True`` to overwrite existing set of gate types, ``False`` otherwise. Defaults to ``False``.
295  :returns: The updated dataflow analysis configuration.
296  :rtype: dataflow.Dataflow.Configuration
297  )");
298 
299  py_dataflow_configuration.def(
300  "with_gate_types", py::overload_cast<const std::set<GateTypeProperty>&, bool>(&dataflow::Configuration::with_gate_types), py::arg("type_properties"), py::arg("overwrite") = false, R"(
301  Add the gate types featuring the specified properties to the set of gate types to be grouped by dataflow analysis.
302  Overwrite the existing set of gate types by setting the optional ``overwrite`` flag to ``True``.
303 
304  :param set[hal_py.GateTypeProperty] type_properties: A set of gate type properties.
305  :param bool overwrite: Set ``True`` to overwrite existing set of gate types, ``False`` otherwise. Defaults to ``False``.
306  :returns: The updated dataflow analysis configuration.
307  :rtype: dataflow.Dataflow.Configuration
308  )");
309 
310  py_dataflow_configuration.def("with_control_pin_types", &dataflow::Configuration::with_control_pin_types, py::arg("types"), py::arg("overwrite") = false, R"(
311  Set the pin types of the pins to be considered control pins by dataflow analysis.
312  Overwrite the existing set of pin types by setting the optional ``overwrite`` flag to ``True``.
313 
314  :param set[hal_py.PinType] types: A set of pin types.
315  :param bool enable: Set ``True`` to overwrite existing set of pin types, ``False`` otherwise. Defaults to ``False``.
316  :returns: The updated dataflow analysis configuration.
317  :rtype: dataflow.Dataflow.Configuration
318  )");
319 
320  py_dataflow_configuration.def("with_flip_flops", &dataflow::Configuration::with_flip_flops, R"(
321  Use the default detection configuration for flip-flops.
322  Includes all flip-flop types as target gate types and sets ``clock``, ``enable``, ``set``, and ``reset`` pins as control pins.
323  Overwrites any existing gate type and control pin configuration.
324 
325  :returns: The updated dataflow analysis configuration.
326  :rtype: dataflow.Dataflow.Configuration
327  )");
328 
329  py_dataflow_configuration.def("with_stage_identification", &dataflow::Configuration::with_stage_identification, py::arg("enable") = true, R"(
330  Enable stage identification as part of dataflow analysis.
331 
332  :param bool enable: Set ``True`` to enable stage identification, ``False`` otherwise. Defaults to ``True``.
333  :returns: The updated dataflow analysis configuration.
334  :rtype: dataflow.Dataflow.Configuration
335  )");
336 
337  py_dataflow_configuration.def("with_type_consistency", &dataflow::Configuration::with_type_consistency, py::arg("enable") = true, R"(
338  Enable type consistency as part of dataflow analysis when deciding whether two gates are allowed to merge into the same group.
339 
340  :param bool enable: Set ``True`` to enable type consistency inside of a group, ``False`` otherwise. Defaults to ``True``.
341  :returns: The updated dataflow analysis configuration.
342  :rtype: dataflow.Dataflow.Configuration
343  )");
344 
345  m.def(
346  "analyze",
347  [](const dataflow::Configuration& config) -> std::optional<dataflow::Result> {
348  auto res = dataflow::analyze(config);
349  if (res.is_ok())
350  {
351  return res.get();
352  }
353  else
354  {
355  log_error("python_context", "error encountered while analyzing dataflow:\n{}", res.get_error().get());
356  return std::nullopt;
357  }
358  },
359  py::arg("config"),
360  R"(
361  Analyze the gate-level netlist to identify word-level structures such as registers.
362  Reconstructs word-level structures such as registers based on properties such as the control inputs of their flip-flops and common successors/predecessors.
363  Operates on an abstraction of the netlist that contains only flip-flops and connections between two flip-flops only if they are connected through combinational logic.
364 
365  :param dataflow.Dataflow.Configuration config: The dataflow analysis configuration.
366  :returns: The dataflow analysis result on success, ``None`` otherwise.
367  :rtype: dataflow.Dataflow.Result or None
368  )");
369 
370  py::class_<dataflow::Result, RawPtrWrapper<dataflow::Result>> py_dataflow_result(m, "Result", R"(
371  This class holds result of a dataflow analysis run, which contains the identified groups of sequential gates and their interconnections.
372  Each such group is assigned a unique ID by which it can be addressed in many of the member functions of this class.
373  Please note that this ID is not related to any other HAL ID.
374  )");
375 
376  py_dataflow_result.def("get_netlist", &dataflow::Result::get_netlist, R"(
377  Get the netlist on which dataflow analysis has been performed.
378 
379  :returns: The netlist.
380  :rtype: hal_py.Netlist
381  )");
382 
383  py_dataflow_result.def("get_groups", &dataflow::Result::get_groups, R"(
384  Get the groups of sequential gates resulting from dataflow analysis.
385 
386  :returns: A dict from group ID to a set of gates belonging to the respective group.
387  :rtype: dict[int,set[hal_py.Gate]]
388  )");
389 
390  py_dataflow_result.def("get_gates", &dataflow::Result::get_gates, R"(
391  Get all gates contained in any of the groups groups.
392 
393  :returns: A list of gates.
394  :rtype: list[hal_py.Gate]
395  )");
396 
397  py_dataflow_result.def(
398  "get_gates_of_group",
399  [](const dataflow::Result& self, const u32 group_id) -> std::optional<std::unordered_set<Gate*>> {
400  auto res = self.get_gates_of_group(group_id);
401  if (res.is_ok())
402  {
403  return res.get();
404  }
405  else
406  {
407  log_error("python_context", "error encountered while getting gates of group:\n{}", res.get_error().get());
408  return std::nullopt;
409  }
410  },
411  py::arg("group_id"),
412  R"(
413  Get the gates of the specified group of sequential gates.
414 
415  :param int group_id: The ID of the group.
416  :returns: The gates of the group as a set on success, ``None`` otherwise.
417  :rtype: set[hal_py.Gate] or None
418  )");
419 
420  py_dataflow_result.def(
421  "get_group_id_of_gate",
422  [](const dataflow::Result& self, const Gate* gate) -> std::optional<u32> {
423  auto res = self.get_group_id_of_gate(gate);
424  if (res.is_ok())
425  {
426  return res.get();
427  }
428  else
429  {
430  log_error("python_context", "error encountered while getting group ID of gate:\n{}", res.get_error().get());
431  return std::nullopt;
432  }
433  },
434  py::arg("gate"),
435  R"(
436  Get the group ID of the group that contains the given gate.
437 
438  :param hal_py.Gate gate: The gate.
439  :returns: The group ID on success, ``None`` otherwise.
440  :rtype: int or None
441  )");
442 
443  py_dataflow_result.def(
444  "get_group_control_nets",
445  [](const dataflow::Result& self, const u32 group_id, const PinType type) -> std::optional<std::unordered_set<Net*>> {
446  auto res = self.get_group_control_nets(group_id, type);
447  if (res.is_ok())
448  {
449  return res.get();
450  }
451  else
452  {
453  log_error("python_context", "error encountered while getting group control nets:\n{}", res.get_error().get());
454  return std::nullopt;
455  }
456  },
457  py::arg("group_id"),
458  py::arg("type"),
459  R"(
460  Get the control nets of the group with the given group ID that are connected to a pin of the specified type.
461 
462  :param int group_id: The group ID.
463  :param hal_py.PinType type: The pin type.
464  :returns: A set of control nets of the group on success, ``None`` otherwise.
465  :rtype: set[hal_py.Net] or None
466  )");
467 
468  py_dataflow_result.def(
469  "get_gate_control_nets",
470  [](const dataflow::Result& self, const Gate* gate, const PinType type) -> std::optional<std::unordered_set<Net*>> {
471  auto res = self.get_gate_control_nets(gate, type);
472  if (res.is_ok())
473  {
474  return res.get();
475  }
476  else
477  {
478  log_error("python_context", "error encountered while getting gate control nets:\n{}", res.get_error().get());
479  return std::nullopt;
480  }
481  },
482  py::arg("gate"),
483  py::arg("type"),
484  R"(
485  Get the control nets of the given gate that are connected to a pin of the specified type.
486 
487  :param hal_py.Gate gate: The gate.
488  :param hal_py.PinType type: The pin type.
489  :returns: A set of control nets of the gate on success, ``None`` otherwise.
490  :rtype: set[hal_py.Net] or None
491  )");
492 
493  py_dataflow_result.def(
494  "get_group_successors",
495  [](const dataflow::Result& self, const u32 group_id) -> std::optional<std::unordered_set<u32>> {
496  auto res = self.get_group_successors(group_id);
497  if (res.is_ok())
498  {
499  return res.get();
500  }
501  else
502  {
503  log_error("python_context", "error encountered while getting successor groups:\n{}", res.get_error().get());
504  return std::nullopt;
505  }
506  },
507  py::arg("group_id"),
508  R"(
509  Get the successor groups of the group with the given ID.
510 
511  :param int group_id: The group ID.
512  :returns: The successors of the group as a set of group IDs on success, ``None`` otherwise.
513  :rtype: set[int] or None
514  )");
515 
516  py_dataflow_result.def(
517  "get_gate_successors",
518  [](const dataflow::Result& self, const Gate* gate) -> std::optional<std::unordered_set<Gate*>> {
519  auto res = self.get_gate_successors(gate);
520  if (res.is_ok())
521  {
522  return res.get();
523  }
524  else
525  {
526  log_error("python_context", "error encountered while getting successor gates:\n{}", res.get_error().get());
527  return std::nullopt;
528  }
529  },
530  py::arg("gate"),
531  R"(
532  Get the sequential successor gates of the given sequential gate.
533 
534  :param hal_py.Gate gate: The gate.
535  :returns: The successors of the gate as a set of gates on success, ``None`` otherwise.
536  :rtype: set[hal_py.Gate] or None
537  )");
538 
539  py_dataflow_result.def(
540  "get_group_predecessors",
541  [](const dataflow::Result& self, const u32 group_id) -> std::optional<std::unordered_set<u32>> {
542  auto res = self.get_group_predecessors(group_id);
543  if (res.is_ok())
544  {
545  return res.get();
546  }
547  else
548  {
549  log_error("python_context", "error encountered while getting predecessor groups:\n{}", res.get_error().get());
550  return std::nullopt;
551  }
552  },
553  py::arg("group_id"),
554  R"(
555  Get the predecessor groups of the group with the given ID.
556 
557  :param int group_id: The ID of the group.
558  :returns: The predecessors of the group as a set of group IDs on success, ``None`` otherwise.
559  :rtype: set[int] or None
560  )");
561 
562  py_dataflow_result.def(
563  "get_gate_predecessors",
564  [](const dataflow::Result& self, const Gate* gate) -> std::optional<std::unordered_set<Gate*>> {
565  auto res = self.get_gate_predecessors(gate);
566  if (res.is_ok())
567  {
568  return res.get();
569  }
570  else
571  {
572  log_error("python_context", "error encountered while getting predecessor gates:\n{}", res.get_error().get());
573  return std::nullopt;
574  }
575  },
576  py::arg("gate"),
577  R"(
578  Get the sequential predecessor gates of the given sequential gate.
579 
580  :param hal_py.Gate gate: The gate.
581  :returns: The predecessors of the gate as a set of gates on success, ``None`` otherwise.
582  :rtype: set[hal_py.Gate] or None
583  )");
584 
585  py_dataflow_result.def(
586  "write_dot",
587  [](const dataflow::Result& self, const std::filesystem::path& out_path, const std::unordered_set<u32>& group_ids = {}) -> bool {
588  auto res = self.write_dot(out_path, group_ids);
589  if (res.is_ok())
590  {
591  return true;
592  }
593  else
594  {
595  log_error("python_context", "error encountered while writing DOT graph:\n{}", res.get_error().get());
596  return false;
597  }
598  },
599  py::arg("out_path"),
600  py::arg("group_ids") = std::unordered_set<u32>(),
601  R"(
602  Write the dataflow graph as a DOT graph to the specified location.
603 
604  :param pathlib.Path out_path: The output path.
605  :param set[int] group_ids: The group IDs to consider. If no IDs are provided, all groups will be considered. Defaults to an empty set.
606  :returns: ``True`` on success, ``False`` otherwise.
607  :rtype: bool
608  )");
609 
610  py_dataflow_result.def(
611  "write_txt",
612  [](const dataflow::Result& self, const std::filesystem::path& out_path, const std::unordered_set<u32>& group_ids = {}) -> bool {
613  auto res = self.write_txt(out_path, group_ids);
614  if (res.is_ok())
615  {
616  return true;
617  }
618  else
619  {
620  log_error("python_context", "error encountered while writing DOT graph:\n{}", res.get_error().get());
621  return false;
622  }
623  },
624  py::arg("out_path"),
625  py::arg("group_ids") = std::unordered_set<u32>(),
626  R"(
627  Write the groups resulting from dataflow analysis to a `.txt` file.
628 
629  :param pathlib.Path out_path: The output path.
630  :param set[int] group_ids: The group IDs to consider. If no IDs are provided, all groups will be considered. Defaults to an empty set.
631  :returns: ``True`` on success, ``False`` otherwise.
632  :rtype: bool
633  )");
634 
635  py_dataflow_result.def(
636  "create_modules",
637  [](const dataflow::Result& self, const std::unordered_set<u32>& group_ids = {}) -> std::optional<std::unordered_map<u32, Module*>> {
638  auto res = self.create_modules(group_ids);
639  if (res.is_ok())
640  {
641  return res.get();
642  }
643  else
644  {
645  log_error("python_context", "error encountered while creating modules:\n{}", res.get_error().get());
646  return std::nullopt;
647  }
648  },
649  py::arg("group_ids") = std::unordered_set<u32>(),
650  R"(
651  Create modules for the dataflow analysis result.
652 
653  :param set[int] group_ids: The group IDs to consider. If an empty set is provided, all groups will be considered. Defaults to an empty set.
654  :returns: A map from group IDs to Modules on success, ``None`` otherwise.
655  :rtype: dict[int,hal_py.Module] or None
656  )");
657 
658  py_dataflow_result.def(
659  "create_modules",
660  [](const dataflow::Result& self,
661  const std::map<const GateType*, std::string>& module_suffixes,
662  const std::map<std::pair<PinDirection, std::string>, std::string>& pin_prefixes,
663  const std::unordered_set<u32>& group_ids) -> std::optional<std::unordered_map<u32, Module*>> {
664  auto res = self.create_modules(module_suffixes, pin_prefixes, group_ids);
665  if (res.is_ok())
666  {
667  return res.get();
668  }
669  else
670  {
671  log_error("python_context", "error encountered while creating modules:\n{}", res.get_error().get());
672  return std::nullopt;
673  }
674  },
675  py::arg("module_suffixes"),
676  py::arg("pin_prefixes"),
677  py::arg("group_ids"),
678  R"(
679  Create modules for the dataflow analysis result.
680 
681  :param dict[hal_py.GateType,str] module_suffixes: The suffixes to use for modules containing only gates of a specific gate type. Defaults to ``"module"`` for mixed and unspecified gate types.
682  :param dict[tuple(hal_py.PinDirection,str),str] pin_prefixes: The prefixes to use for the module pins that (within the module) only connect to gate pins of a specific name.
683  :param set[int] group_ids: The group IDs to consider. If no IDs are provided, all groups will be considered.
684  :returns: A map from group IDs to Modules on success, ``None`` otherwise.
685  :rtype: dict[int,hal_py.Module] or None
686  )");
687 
688  py_dataflow_result.def(
689  "create_modules",
690  [](const dataflow::Result& self,
691  const std::map<GateTypeProperty, std::string>& module_suffixes,
692  const std::map<std::pair<PinDirection, std::string>, std::string>& pin_prefixes,
693  const std::unordered_set<u32>& group_ids) -> std::optional<std::unordered_map<u32, Module*>> {
694  auto res = self.create_modules(module_suffixes, pin_prefixes, group_ids);
695  if (res.is_ok())
696  {
697  return res.get();
698  }
699  else
700  {
701  log_error("python_context", "error encountered while creating modules:\n{}", res.get_error().get());
702  return std::nullopt;
703  }
704  },
705  py::arg("module_suffixes"),
706  py::arg("pin_prefixes"),
707  py::arg("group_ids"),
708  R"(
709  Create modules for the dataflow analysis result.
710 
711  :param dict[hal_py.GateTypeProperty,str] module_suffixes: The suffixes to use for modules containing only gates of a specific gate type. All gate types featuring the specified gate type property are considered, but the module must still be pure (i.e., all gates must be of the same type) for the suffix to be used. Defaults to ``"module"`` for mixed and unspecified gate types.
712  :param dict[tuple(hal_py.PinDirection,str),str] pin_prefixes: The prefixes to use for the module pins that (within the module) only connect to gate pins of a specific name.
713  :param set[int] group_ids: The group IDs to consider. If no IDs are provided, all groups will be considered.
714  :returns: A map from group IDs to Modules on success, ``None`` otherwise.
715  :rtype: dict[int,hal_py.Module] or None
716  )");
717 
718  py_dataflow_result.def("get_group_list",
720  py::arg("group_ids") = std::unordered_set<u32>(),
721  R"(
722  Get the groups of the dataflow analysis result as a list.
723 
724  :param set[int] group_ids: The group IDs to consider. If no IDs are provided, all groups will be considered. Defaults to an empty set.
725  :returns: A list of groups with each group being a list of gates.
726  :rtype: list[list[hal_py.Gate]]
727  )");
728 
729  py_dataflow_result.def(
730  "merge_groups",
731  [](dataflow::Result& self, const std::vector<u32>& group_ids) -> std::optional<u32> {
732  auto res = self.merge_groups(group_ids);
733  if (res.is_ok())
734  {
735  return res.get();
736  }
737  else
738  {
739  log_error("python_context", "error encountered while merging groups:\n{}", res.get_error().get());
740  return std::nullopt;
741  }
742  },
743  py::arg("group_ids"),
744  R"(
745  Merge multiple groups specified by ID.
746  All specified groups are merged into the first group of the provided vector and are subsequently deleted.
747 
748  :param set[int] group_ids: The group IDs of the groups to merge.
749  :returns: The ID of the group that all other groups have been merged into on success, ``None`` otherwise.
750  :rtype: int or None
751  )");
752 
753  py_dataflow_result.def(
754  "split_group",
755  [](dataflow::Result& self, u32 group_id, const std::vector<std::unordered_set<Gate*>>& new_groups) -> std::optional<std::vector<u32>> {
756  auto res = self.split_group(group_id, new_groups);
757  if (res.is_ok())
758  {
759  return res.get();
760  }
761  else
762  {
763  log_error("python_context", "error encountered while splitting group:\n{}", res.get_error().get());
764  return std::nullopt;
765  }
766  },
767  py::arg("group_id"),
768  py::arg("new_groups"),
769  R"(
770  Split a group into multiple smaller groups specified by sets of gates.
771  All gates of the group to split must be contained in the sets exactly once and all gates in the sets must be contained in the group to split.
772  The group that is being split is deleted in the process.
773 
774  :param int group_id: The group ID of the group to split.
775  :param list[set[hal_py.Gate]] new_groups: A list of groups specified as unordered sets of gates.
776  :returns: The group IDs of the newly created groups in the order of the provided sets.
777  :rtype: list[int]
778  )");
779 
780 #ifndef PYBIND11_MODULE
781  return m.ptr();
782 #endif // PYBIND11_MODULE
783  }
784 } // namespace hal
std::string get_name() const override
Get the name of the plugin.
std::string get_version() const override
Get the version of the plugin.
std::string get_description() const override
Get a short description of the plugin.
Definition: gate.h:58
Result of a dataflow analysis run.
Definition: result.h:57
std::vector< std::vector< Gate * > > get_groups_as_list(const std::unordered_set< u32 > &group_ids={}) const
Get the groups of the dataflow analysis result as a list.
Definition: result.cpp:614
const std::unordered_map< u32, std::unordered_set< Gate * > > & get_groups() const
Get the groups of sequential gates resulting from dataflow analysis.
Definition: result.cpp:104
Netlist * get_netlist() const
Get the netlist on which dataflow analysis has been performed.
Definition: result.cpp:99
std::vector< Gate * > get_gates() const
Get all gates contained in any of the groups groups.
Definition: result.cpp:109
#define log_error(channel,...)
Definition: log.h:78
const Module * module(const Gate *g, const NodeBoxes &boxes)
hal::Result< dataflow::Result > analyze(const Configuration &config)
Analyze the gate-level netlist to identify word-level structures such as registers.
Definition: dataflow.cpp:12
PYBIND11_PLUGIN(hal_py)
PinType
Definition: pin_type.h:36
quint32 u32
PinType type
Configuration of a dataflow analysis run.
Definition: configuration.h:61
Configuration & with_flip_flops()
Use the default detection configuration for flip-flops.
std::vector< std::vector< Net * > > known_net_groups
Groups of nets that have been identified as word-level datapathes beforehand. Defaults to an empty ve...
Definition: configuration.h:92
std::vector< u32 > expected_sizes
Expected group sizes. Groups of these sizes will be prioritized. Defaults to an empty vector.
Definition: configuration.h:82
Configuration & with_type_consistency(bool enable=true)
Enable type consistency as part of dataflow analysis when deciding whether two gates are allowed to m...
std::set< const GateType * > gate_types
The gate types to be grouped by dataflow analysis. Defaults to an empty set.
Definition: configuration.h:97
std::set< PinType > control_pin_types
The pin types of the pins to be considered control pins. Defaults to an empty set.
Configuration & with_gate_types(const std::set< const GateType * > &types, bool overwrite=false)
Add the gate types to the set of gate types to be grouped by dataflow analysis.
Configuration & with_control_pin_types(const std::set< PinType > &types, bool overwrite=false)
Set the pin types of the pins to be considered control pins by dataflow analysis.
Configuration & with_stage_identification(bool enable=true)
Enable stage identification as part of dataflow analysis.
Configuration & with_known_groups(const std::vector< Module * > &groups, bool overwrite=false)
Add modules to the set of previously identified word-level groups.
bool enforce_type_consistency
Enforce gate type consistency inside of a group. Defaults to false.
u32 min_group_size
Minimum size of a group. Smaller groups will be penalized during analysis. Defaults to 8.
Definition: configuration.h:77
Configuration & with_expected_sizes(const std::vector< u32 > &sizes)
Set the expected group sizes. Groups of these sizes will be prioritized.
std::vector< std::vector< Gate * > > known_gate_groups
Groups of gates that have already been identified as word-level groups beforehand....
Definition: configuration.h:87
Configuration & with_min_group_size(u32 size)
Set the minimum size of a group. Smaller groups will be penalized during analysis.
bool enable_stages
Enable stage identification as part of dataflow analysis. Defaults to false.
Configuration & with_known_structures(const std::vector< Module * > &structures, bool overwrite=false)
Add modules to the set of previously identified word-level structures.