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.
2 
5 #include "pybind11/operators.h"
6 #include "pybind11/pybind11.h"
7 #include "pybind11/stl.h"
8 #include "pybind11/stl_bind.h"
9 
10 namespace py = pybind11;
11 
12 namespace hal
13 {
14 
15  // the name in PYBIND11_MODULE/PYBIND11_PLUGIN *MUST* match the filename of the output library (without extension),
16  // otherwise you will get "ImportError: dynamic module does not define module export function" when importing the module
17 
18 #ifdef PYBIND11_MODULE
19  PYBIND11_MODULE(bitorder_propagation, m)
20  {
21  m.doc() = "Tool to automatically propagate known bit orders to module pin groups of unknown bit order.";
22 #else
23  PYBIND11_PLUGIN(bitorder_propagation)
24  {
25  py::module m("bitorder_propagation", "Tool to automatically propagate known bit orders to module pin groups of unknown bit order.");
26 #endif // ifdef PYBIND11_MODULE
27 
28  py::class_<BitorderPropagationPlugin, RawPtrWrapper<BitorderPropagationPlugin>, BasePluginInterface> py_bitorder_propagation_plugin(
29  m, "BitorderPropagationPlugin", R"(This class provides an interface to integrate the bit-order propagation as a plugin within the HAL framework.)");
30 
31  py_bitorder_propagation_plugin.def_property_readonly("name", &BitorderPropagationPlugin::get_name, R"(
32  The name of the plugin.
33 
34  :type: str
35  )");
36 
37  py_bitorder_propagation_plugin.def("get_name", &BitorderPropagationPlugin::get_name, R"(
38  Get the name of the plugin.
39 
40  :returns: The name of the plugin.
41  :rtype: str
42  )");
43 
44  py_bitorder_propagation_plugin.def_property_readonly("version", &BitorderPropagationPlugin::get_version, R"(
45  The version of the plugin.
46 
47  :type: str
48  )");
49 
50  py_bitorder_propagation_plugin.def("get_version", &BitorderPropagationPlugin::get_version, R"(
51  Get the version of the plugin.
52 
53  :returns: The version of the plugin.
54  :rtype: str
55  )");
56 
57  py_bitorder_propagation_plugin.def_property_readonly("description", &BitorderPropagationPlugin::get_description, R"(
58  The description of the plugin.
59 
60  :type: str
61  )");
62 
63  py_bitorder_propagation_plugin.def("get_description", &BitorderPropagationPlugin::get_description, R"(
64  Get the description of the plugin.
65 
66  :returns: The description of the plugin.
67  :rtype: str
68  )");
69 
70  py::class_<bitorder_propagation::BitOrder> py_bit_order(m, "BitOrder", R"(
71  The bit order of a single module pin group, i.e., which net of the pin group carries which bit.
72  )");
73 
74  py_bit_order.def(py::init<Module*, PinGroup<ModulePin>*, std::vector<std::pair<Net*, u32>>>(), py::arg("module"), py::arg("pin_group"), py::arg("order"), R"(
75  Construct a bit order for a module pin group.
76 
77  :param hal_py.Module module: The module the pin group belongs to.
78  :param hal_py.ModulePinGroup pin_group: The pin group.
79  :param list[tuple(hal_py.Net,int)] order: The index of each net of the pin group.
80  )");
81 
82  // The getter is built as a cpp_function here rather than handed over directly, because
83  // def_property_readonly builds it itself without passing on any of the attributes that follow,
84  // so a call policy given to the property never reaches the function that does the call.
85  py_bit_order.def_property_readonly("module", py::cpp_function(&bitorder_propagation::BitOrder::get_module, py::is_method(py_bit_order), borrowed()), R"(
86  The module that the pin group belongs to.
87 
88  :type: hal_py.Module
89  )");
90 
91  py_bit_order.def_property_readonly("pin_group", py::cpp_function(&bitorder_propagation::BitOrder::get_pin_group, py::is_method(py_bit_order), borrowed()), R"(
92  The pin group whose bit order this is.
93 
94  :type: hal_py.ModulePinGroup
95  )");
96 
97  py_bit_order.def_property_readonly("order", py::cpp_function(&bitorder_propagation::BitOrder::get_order, py::is_method(py_bit_order), borrowed()), R"(
98  The index of every net, ordered by index.
99 
100  :type: list[tuple(hal_py.Net,int)]
101  )");
102 
103  py_bit_order.def("get_index", &bitorder_propagation::BitOrder::get_index, py::arg("net"), R"(
104  Get the index of the given net.
105 
106  :param hal_py.Net net: The net.
107  :returns: The index of the net, ``None`` if the net is not part of this bit order.
108  :rtype: int or None
109  )");
110 
111  py_bit_order.def("get_net_at", &bitorder_propagation::BitOrder::get_net_at, py::arg("index"), borrowed(), R"(
112  Get the net at the given index.
113 
114  :param int index: The index.
115  :returns: The net at the index, ``None`` if no net carries that index.
116  :rtype: hal_py.Net or None
117  )");
118 
119  py_bit_order.def_property_readonly("size", &bitorder_propagation::BitOrder::get_size, R"(
120  The number of nets that the bit order covers.
121 
122  :type: int
123  )");
124 
125  py_bit_order.def("is_continuous", &bitorder_propagation::BitOrder::is_continuous, R"(
126  Check whether the indices run from 0 without leaving a gap.
127 
128  :returns: ``True`` if the order is continuous, ``False`` otherwise.
129  :rtype: bool
130  )");
131 
132  py_bit_order.def(py::self == py::self);
133  py_bit_order.def(py::self != py::self);
134 
135  py::class_<bitorder_propagation::BitOrderResult> py_bit_order_result(m, "BitOrderResult", R"(
136  The bit orders that are known, which is what a propagation reports: the ones it was given as well as the ones it worked out.
137 
138  Iterating over a result walks the bit orders by module ID and then by pin group ID, so it does not depend on where the modules and pin groups happen to be allocated.
139  )");
140 
141  py_bit_order_result.def(py::init<>(), R"(Construct a result that holds no bit order.)");
142 
143  py_bit_order_result.def(py::init<std::vector<bitorder_propagation::BitOrder>>(), py::arg("bit_orders"), R"(
144  Construct a result from the given bit orders.
145 
146  :param list[bitorder_propagation.BitOrder] bit_orders: The bit orders.
147  )");
148 
149  py_bit_order_result.def("add", &bitorder_propagation::BitOrderResult::add, py::arg("bit_order"), R"(
150  Add a bit order, replacing one that is already known for the same pin group.
151 
152  :param bitorder_propagation.BitOrder bit_order: The bit order.
153  )");
154 
155  py_bit_order_result.def_property_readonly(
156  "bit_orders", py::cpp_function(&bitorder_propagation::BitOrderResult::get_bit_orders, py::is_method(py_bit_order_result), borrowed()), R"(
157  Every bit order, ordered by module ID and pin group ID.
158 
159  :type: list[bitorder_propagation.BitOrder]
160  )");
161 
162  py_bit_order_result.def("get", &bitorder_propagation::BitOrderResult::get, py::arg("module"), py::arg("pin_group"), borrowed(), R"(
163  Get the bit order of the given pin group.
164 
165  :param hal_py.Module module: The module the pin group belongs to.
166  :param hal_py.ModulePinGroup pin_group: The pin group.
167  :returns: The bit order, ``None`` if the pin group has no known bit order.
168  :rtype: bitorder_propagation.BitOrder or None
169  )");
170 
171  py_bit_order_result.def("contains", &bitorder_propagation::BitOrderResult::contains, py::arg("module"), py::arg("pin_group"), R"(
172  Check whether the bit order of the given pin group is known.
173 
174  :param hal_py.Module module: The module the pin group belongs to.
175  :param hal_py.ModulePinGroup pin_group: The pin group.
176  :returns: ``True`` if the bit order is known, ``False`` otherwise.
177  :rtype: bool
178  )");
179 
180  py_bit_order_result.def("__len__", &bitorder_propagation::BitOrderResult::get_size);
181 
182  py_bit_order_result.def(
183  "__iter__", [](const bitorder_propagation::BitOrderResult& self) { return py::make_iterator(self.begin(), self.end()); }, py::keep_alive<0, 1>());
184 
185  m.def(
186  "propagate_module_pingroup_bitorder",
188  const std::set<std::pair<Module*, PinGroup<ModulePin>*>>& dst,
189  const bool enforce_continuous_bitorders = true) -> std::optional<bitorder_propagation::BitOrderResult> {
190  const auto res = bitorder_propagation::propagate_module_pingroup_bitorder(src, dst, enforce_continuous_bitorders);
191  if (res.is_ok())
192  {
193  return res.get();
194  }
195  else
196  {
197  log_error("python_context", "{}", res.get_error().get());
198  return std::nullopt;
199  }
200  },
201  py::arg("src"),
202  py::arg("dst"),
203  py::arg("enforce_continuous_bitorders") = true,
204  R"(
205  Propagate known bit-order information from the given module pin groups to module pin groups of unknown bit order.
206  The known bit-order information is taken from the map from net to index given for each pair of module and pin group in ``src``.
207  After propagation, the algorithm tries to reconstruct valid bit orders from the propagated information.
208 
209  :param bitorder_propagation.BitOrderResult src: The bit orders that are already known.
210  :param set[tuple(hal_py.Module,hal_py.ModulePinGroup)] dst: The pairs of module ID and pin group name with unknown bit order.
211  :param bool enforce_continuous_bitorders: Set ``True`` to only allow for continuous bit orders, ``^`` to also allow bit orders that are not continuous. Defaults to ``True``.
212  :returns: All known bit orders, the new ones as well as the ones already known, on success, ``None`` otherwise.
213  :rtype: bitorder_propagation.BitOrderResult or None
214  )");
215 
216  m.def(
217  "reorder_module_pin_groups",
218  [](const bitorder_propagation::BitOrderResult& ordered_module_pin_groups) -> bool {
219  const auto res = bitorder_propagation::reorder_module_pin_groups(ordered_module_pin_groups);
220  if (res.is_ok())
221  {
222  return true;
223  }
224  else
225  {
226  log_error("python_context", "{}", res.get_error().get());
227  return false;
228  }
229  },
230  py::arg("ordered_module_pin_groups"),
231  R"(
232  Reorder and rename the pins of the pin groups according to the provided bit-order information.
233 
234  :param bitorder_propagation.BitOrderResult ordered_module_pin_groups: The bit orders to apply.
235  :returns: ``True`` on success, ``False`` otherwise.
236  :rtype: bool
237  )");
238 
239  m.def(
240  "propagate_bitorder",
241  [](Netlist* nl, const std::pair<u32, std::string>& src, const std::pair<u32, std::string>& dst) -> std::optional<bitorder_propagation::BitOrderResult> {
242  const auto res = bitorder_propagation::propagate_bitorder(nl, src, dst);
243  if (res.is_ok())
244  {
245  return res.get();
246  }
247  else
248  {
249  log_error("python_context", "{}", res.get_error().get());
250  return std::nullopt;
251  }
252  },
253  py::arg("nl"),
254  py::arg("src"),
255  py::arg("dst"),
256  R"(
257  Propagate known bit-order information from one module pin group to another module pin group of unknown bit order.
258  The known bit-order information is taken from the order of pins in the pin group of ``src``.
259  After propagation, the algorithm tries to reconstruct a valid bit order from the propagated information.
260  The valid bit order is then annotated to the module pin group, i.e., the pins of the respective pin group are renamed and reordered.
261 
262  :param hal_py.netlist nl: The netlist containing the module.
263  :param tuple(int,str) src: The pair of module ID and pin group name with known bit order.
264  :param tuple(int,str) dst: The pair of module ID and pin group name with unknown bit order.
265  :returns: A dict containing all known bit orders (including new and already known ones) on success, ``None`` otherwise.
266  :rtype: dict[tuple(hal_py.Module,hal_py.ModulePinGroup),dict[hal_py.Net,int]] or None
267  )");
268 
269  m.def(
270  "propagate_bitorder",
271  [](const std::pair<Module*, PinGroup<ModulePin>*>& src,
272  const std::pair<Module*, PinGroup<ModulePin>*>& dst) -> std::optional<bitorder_propagation::BitOrderResult> {
273  const auto res = bitorder_propagation::propagate_bitorder(src, dst);
274  if (res.is_ok())
275  {
276  return res.get();
277  }
278  else
279  {
280  log_error("python_context", "{}", res.get_error().get());
281  return std::nullopt;
282  }
283  },
284  py::arg("src"),
285  py::arg("dst"),
286  R"(
287  Propagate known bit-order information from one module pin group to another module pin group of unknown bit order.
288  The known bit-order information is taken from the order of pins in the pin group of ``src``.
289  After propagation, the algorithm tries to reconstruct a valid bit order from the propagated information.
290  The valid bit order is then annotated to the module pin group, i.e., the pins of the respective pin group are renamed and reordered.
291 
292  :param tuple(hal_py.Module,hal_py.ModulePinGroup) src: The pair of module and pin group with known bit order.
293  :param tuple(hal_py.Module,hal_py.ModulePinGroup) dst: The pair of module and pin group with unknown bit order.
294  :returns: A dict containing all known bit orders (including new and already known ones) on success, ``None`` otherwise.
295  :rtype: dict[tuple(hal_py.Module,hal_py.ModulePinGroup),dict[hal_py.Net,int]] or None
296  )");
297 
298  m.def(
299  "propagate_bitorder",
300  [](Netlist* nl,
301  const std::vector<std::pair<u32, std::string>>& src,
302  const std::vector<std::pair<u32, std::string>>& dst) -> std::optional<bitorder_propagation::BitOrderResult> {
303  const auto res = bitorder_propagation::propagate_bitorder(nl, src, dst);
304  if (res.is_ok())
305  {
306  return res.get();
307  }
308  else
309  {
310  log_error("python_context", "{}", res.get_error().get());
311  return std::nullopt;
312  }
313  },
314  py::arg("nl"),
315  py::arg("src"),
316  py::arg("dst"),
317  R"(
318  Propagate known bit-order information from the given module pin groups to module pin groups of unknown bit order.
319  The known bit-order information is taken from the order of pins in the pin groups of ``src``.
320  After propagation, the algorithm tries to reconstruct valid bit orders from the propagated information.
321  The valid bit orders are then annotated to the module pin groups, i.e., the pins of the respective pin groups are renamed and reordered.
322 
323  :param hal_py.netlist nl: The netlist containing the modules.
324  :param list[tuple(int,str)] src: The pairs of module ID and pin group name with known bit order.
325  :param list[tuple(int,str)] dst: The pairs of module ID and pin group name with unknown bit order.
326  :returns: A dict containing all known bit orders (including new and already known ones) on success, ``None`` otherwise.
327  :rtype: dict[tuple(hal_py.Module,hal_py.ModulePinGroup),dict[hal_py.Net,int]] or None
328  )");
329 
330  m.def(
331  "propagate_bitorder",
332  [](const std::vector<std::pair<Module*, PinGroup<ModulePin>*>>& src,
333  const std::vector<std::pair<Module*, PinGroup<ModulePin>*>>& dst) -> std::optional<bitorder_propagation::BitOrderResult> {
334  const auto res = bitorder_propagation::propagate_bitorder(src, dst);
335  if (res.is_ok())
336  {
337  return res.get();
338  }
339  else
340  {
341  log_error("python_context", "{}", res.get_error().get());
342  return std::nullopt;
343  }
344  },
345  py::arg("src"),
346  py::arg("dst"),
347  R"(
348  Propagate known bit-order information from the given module pin groups to module pin groups of unknown bit order.
349  The known bit-order information is taken from the order of pins in the pin groups of ``src``.
350  After propagation, the algorithm tries to reconstruct valid bit orders from the propagated information.
351  The valid bit orders are then annotated to the module pin groups, i.e., the pins of the respective pin groups are renamed and reordered.
352 
353  :param list[tuple(hal_py.Module,hal_py.ModulePinGroup)] src: The pairs of module and pin group with known bit order.
354  :param list[tuple(hal_py.Module,hal_py.ModulePinGroup)] dst: The pairs of module and pin group with unknown bit order.
355  :returns: A dict containing all known bit orders (including new and already known ones) on success, ``None`` otherwise.
356  :rtype: dict[tuple(hal_py.Module,hal_py.ModulePinGroup),dict[hal_py.Net,int]] or None
357  )");
358 
359  m.def(
360  "export_bitorder_propagation_information",
362  const std::set<std::pair<Module*, PinGroup<ModulePin>*>>& dst,
363  const std::string& export_filepath) -> std::optional<std::map<std::pair<Module*, PinGroup<ModulePin>*>, u32>> {
364  const auto res = bitorder_propagation::export_bitorder_propagation_information(src, dst, export_filepath);
365  if (res.is_ok())
366  {
367  return res.get();
368  }
369  else
370  {
371  log_error("python_context", "{}", res.get_error().get());
372  return std::nullopt;
373  }
374  },
375  py::arg("src"),
376  py::arg("dst"),
377  py::arg("export_filepath"),
378  R"(
379  Export collected bitorder information like word composition, known bitorder and connectivity in ``.json`` format to solve with external tools.
380 
381  :param bitorder_propagation.BitOrderResult src: The bit orders that are already known.
382  :param set[tuple(hal_py.Module,hal_py.ModulePinGroup)] dst: The pairs of module ID and pin group name with unknown bit order.
383  :param str export_filepath: The filepath where the ``.json`` file should be written to.
384  :returns: The mapping from each mdoule/pingroup pair to its index on success, ``None`` otherwise.
385  :rtype: dict[tuple(hal_py.Module, hal_py.ModulePinGroup), int] or None
386  )");
387 
388  m.def(
389  "export_bitorder_propagation_information",
390  [](const std::vector<std::pair<Module*, PinGroup<ModulePin>*>>& src,
391  const std::vector<std::pair<Module*, PinGroup<ModulePin>*>>& dst,
392  const std::string& export_filepath) -> std::optional<std::map<std::pair<Module*, PinGroup<ModulePin>*>, u32>> {
393  const auto res = bitorder_propagation::export_bitorder_propagation_information(src, dst, export_filepath);
394  if (res.is_ok())
395  {
396  return res.get();
397  }
398  else
399  {
400  log_error("python_context", "{}", res.get_error().get());
401  return std::nullopt;
402  }
403  },
404  py::arg("src"),
405  py::arg("dst"),
406  py::arg("export_filepath"),
407  R"(
408  Export collected bitorder information like word composition, known bitorder and connectivity in ``.json`` format to solve with external tools.
409 
410  :param tuple(hal_py.Module,hal_py.ModulePinGroup) src: The pair of module and pin group with known bit order.
411  :param tuple(hal_py.Module,hal_py.ModulePinGroup) dst: The pair of module and pin group with unknown bit order.
412  :param str export_filepath: The filepath where the ``.json`` file should be written to.
413  :returns: The mapping from each mdoule/pingroup pair to its index on success, ``None`` otherwise.
414  :rtype: dict[tuple(hal_py.Module, hal_py.ModulePinGroup), int] or None
415  )");
416 
417 #ifndef PYBIND11_MODULE
418  return m.ptr();
419 #endif // PYBIND11_MODULE
420  }
421 } // namespace hal
This file contains functions for bit-order propagation from pin groups of known bit order to pin grou...
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::string get_name() const override
Get the name of the plugin.
Net * get_net_at(u32 index) const
Definition: bit_order.cpp:39
std::optional< u32 > get_index(const Net *net) const
Definition: bit_order.cpp:33
const std::vector< std::pair< Net *, u32 > > & get_order() const
Definition: bit_order.cpp:28
PinGroup< ModulePin > * get_pin_group() const
Definition: bit_order.cpp:23
bool contains(const Module *module, const PinGroup< ModulePin > *pin_group) const
Definition: bit_order.cpp:129
const BitOrder * get(const Module *module, const PinGroup< ModulePin > *pin_group) const
Definition: bit_order.cpp:116
const std::vector< BitOrder > & get_bit_orders() const
Definition: bit_order.cpp:111
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< BitOrderResult > propagate_bitorder(Netlist *nl, const std::pair< u32, std::string > &src, const std::pair< u32, std::string > &dst)
Propagate known bit-order information from one module pin group to another module pin group of unknow...
Result< std::monostate > reorder_module_pin_groups(const BitOrderResult &ordered_module_pin_groups)
Reorder and rename the pins of the pin groups according to the provided bit-order information.
Result< BitOrderResult > propagate_module_pingroup_bitorder(const BitOrderResult &src, const std::set< std::pair< Module *, PinGroup< ModulePin > * >> &dst, const bool enforce_continuous_bitorders=true)
Propagate known bit-order information from the given module pin groups to module pin groups of unknow...
Result< std::map< std::pair< Module *, PinGroup< ModulePin > * >, WordIndex > > export_bitorder_propagation_information(const std::vector< std::pair< Module *, PinGroup< ModulePin > * >> &src, const std::vector< std::pair< Module *, PinGroup< ModulePin > * >> &dst, const std::string &export_filepath)
Export word composition, known bitorder and connectivity in .json format to solve with external tools...
Definition: defines.h:45
PYBIND11_PLUGIN(hal_py)
This file contains all functions related to the HAL plugin API.