HAL
boolean_function.cpp
Go to the documentation of this file.
2 
3 namespace hal
4 {
6  {
7  py::class_<BooleanFunction> py_boolean_function(m,
8  "BooleanFunction",
9  R"(
10  A BooleanFunction represents a symbolic expression (e.g., ``A & B``) in order to abstract the (semantic) functionality of a single netlist gate (or even a complex subcircuit comprising multiple gates) in a formal manner. To this end, the ``BooleanFunction`` class is able to construct and display arbitrarily-nested expressions, enable symbolic simplification (e.g., simplify ``A & 0`` to ``0``), and translate Boolean functions to the SAT / SMT solver domain to use the solve constraint formulas.
11  )");
12 
13  py::enum_<BooleanFunction::Value> py_boolean_function_value(py_boolean_function, "Value", R"(
14  Represents the logic value that a Boolean function operates on.
15  )");
16 
17  py_boolean_function_value.value("ZERO", BooleanFunction::Value::ZERO, R"(Represents a logical 0.)")
18  .value("ONE", BooleanFunction::Value::ONE, R"(Represents a logical 1.)")
19  .value("Z", BooleanFunction::Value::Z, R"(Represents a high-impedance value.)")
20  .value("X", BooleanFunction::Value::X, R"(Represents an undefined value.)")
21  .export_values();
22 
23  py_boolean_function_value.def(
24  "__str__", [](const BooleanFunction::Value& v) { return BooleanFunction::to_string(v); }, R"(
25  Translates the Boolean function value into its string representation.
26 
27  :returns: The value as a string.
28  :rtype: str
29  )");
30 
31  py_boolean_function.def_static(
32  "to_string",
33  [](const std::vector<BooleanFunction::Value>& value, u8 base = 2) -> std::optional<std::string> {
34  auto res = BooleanFunction::to_string(value, base);
35  if (res.is_ok())
36  {
37  return res.get();
38  }
39  else
40  {
41  log_error("python_context", "{}", res.get_error().get());
42  return std::nullopt;
43  }
44  },
45  py::arg("value"),
46  py::arg("base") = 2,
47  R"(
48  Convert the given bit-vector to its string representation in the given base.
49 
50  :param list[hal_py.BooleanFunction.Value] value: The value as a bit-vector.
51  :param int base: The base that the values should be converted to. Valid values are 2 (default), 8, 10, and 16.
52  :returns: A string representing the values in the given base on success, None otherwise.
53  :rtype: str or None
54  )");
55 
56  py_boolean_function.def_static(
57  "to_u64",
58  [](const std::vector<BooleanFunction::Value>& value) -> std::optional<u64> {
59  auto res = BooleanFunction::to_u64(value);
60  if (res.is_ok())
61  {
62  return res.get();
63  }
64  else
65  {
66  log_error("python_context", "{}", res.get_error().get());
67  return std::nullopt;
68  }
69  },
70  py::arg("value"),
71  R"(
72  Convert the given bit-vector to its unsigned 64-bit integer representation.
73 
74  :param list[hal_py.BooleanFunction.Value] value: The value as a bit-vector.
75  :returns: A 64-bit integer representing the values on success, None otherwise.
76  :rtype: int or None
77  )");
78 
79  py_boolean_function.def(py::init<>(), R"(
80  Constructs an empty / invalid Boolean function.
81  )");
82 
83  py_boolean_function.def_static("Var", &BooleanFunction::Var, py::arg("name"), py::arg("size") = 1, R"(
84  Creates a multi-bit Boolean function of the given bit-size comprising only a variable of the specified name.
85 
86  :param str name: The name of the variable.
87  :param int size: The bit-size. Defaults to 1.
88  :returns: The BooleanFunction.
89  :rtype: hal_py.BooleanFunction
90  )");
91 
92  py_boolean_function.def_static("Const", py::overload_cast<const BooleanFunction::Value&>(&BooleanFunction::Const), py::arg("value"), R"(
93  Creates a constant single-bit Boolean function from a value.
94 
95  :param hal_py.BooleanFunction.Value value: The value.
96  :returns: The Boolean function.
97  :rtype: hal_py.BooleanFunction
98  )");
99 
100  py_boolean_function.def_static("Const", py::overload_cast<const std::vector<BooleanFunction::Value>&>(&BooleanFunction::Const), py::arg("value"), R"(
101  Creates a constant multi-bit Boolean function from a list of values.
102 
103  :param list[hal_py.BooleanFunction.Value] value: The list of values.
104  :returns: The Boolean function.
105  :rtype: hal_py.BooleanFunction
106  )");
107 
108  py_boolean_function.def_static("Const", py::overload_cast<u64, u16>(&BooleanFunction::Const), py::arg("value"), py::arg("size"), R"(
109  Creates a constant multi-bit Boolean function of the given bit-size from an integer value.
110 
111  :param int value: The integer value.
112  :param int size: The bit-size.
113  :returns: The Boolean function.
114  :rtype: hal_py.BooleanFunction
115  )");
116 
117  py_boolean_function.def_static("Index", &BooleanFunction::Index, py::arg("index"), py::arg("size"), R"(
118  Creates an index for a Boolean function of the given bit-size from an integer value.
119 
120  :param int index: The integer value.
121  :param int size: The bit-size.
122  :returns: The Boolean function.
123  :rtype: hal_py.BooleanFunction
124  )");
125 
126  py_boolean_function.def_static(
127  "And",
128  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
129  auto res = BooleanFunction::And(std::move(p0), std::move(p1), size);
130  if (res.is_ok())
131  {
132  return res.get();
133  }
134  else
135  {
136  log_error("python_context", "{}", res.get_error().get());
137  return std::nullopt;
138  }
139  },
140  py::arg("p0"),
141  py::arg("p1"),
142  py::arg("size"),
143  R"(
144  Joins two Boolean functions by applying an AND operation.
145  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
146 
147  :param hal_py.BooleanFunction p0: First Boolean function.
148  :param hal_py.BooleanFunction p1: Second Boolean function.
149  :param int size: Bit-size of the operation.
150  :returns: The joined Boolean function on success, None otherwise.
151  :rtype: hal_py.BooleanFunction or None
152  )");
153 
154  py_boolean_function.def_static(
155  "Or",
156  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
157  auto res = BooleanFunction::Or(std::move(p0), std::move(p1), size);
158  if (res.is_ok())
159  {
160  return res.get();
161  }
162  else
163  {
164  log_error("python_context", "{}", res.get_error().get());
165  return std::nullopt;
166  }
167  },
168  py::arg("p0"),
169  py::arg("p1"),
170  py::arg("size"),
171  R"(
172  Joins two Boolean functions by applying an OR operation.
173  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
174 
175  :param hal_py.BooleanFunction p0: First Boolean function.
176  :param hal_py.BooleanFunction p1: Second Boolean function.
177  :param int size: Bit-size of the operation.
178  :returns: The joined Boolean function on success, None otherwise.
179  :rtype: hal_py.BooleanFunction or None
180  )");
181 
182  py_boolean_function.def_static(
183  "Not",
184  [](BooleanFunction p0, u16 size) -> std::optional<BooleanFunction> {
185  auto res = BooleanFunction::Not(std::move(p0), size);
186  if (res.is_ok())
187  {
188  return res.get();
189  }
190  else
191  {
192  log_error("python_context", "{}", res.get_error().get());
193  return std::nullopt;
194  }
195  },
196  py::arg("p0"),
197  py::arg("size"),
198  R"(
199  Negates the given Boolean function.
200  Requires the Boolean function to be of the specified bit-size and produces a new Boolean function of the same bit-size.
201 
202  :param hal_py.BooleanFunction p0: The Boolean function to negate.
203  :param int size: Bit-size of the operation.
204  :returns: The negated Boolean function on success, None otherwise.
205  :rtype: hal_py.BooleanFunction or None
206  )");
207 
208  py_boolean_function.def_static(
209  "Xor",
210  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
211  auto res = BooleanFunction::Xor(std::move(p0), std::move(p1), size);
212  if (res.is_ok())
213  {
214  return res.get();
215  }
216  else
217  {
218  log_error("python_context", "{}", res.get_error().get());
219  return std::nullopt;
220  }
221  },
222  py::arg("p0"),
223  py::arg("p1"),
224  py::arg("size"),
225  R"(
226  Joins two Boolean functions by applying an XOR operation.
227  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
228 
229  :param hal_py.BooleanFunction p0: First Boolean function.
230  :param hal_py.BooleanFunction p1: Second Boolean function.
231  :param int size: Bit-size of the operation.
232  :returns: The joined Boolean function on success, None otherwise.
233  :rtype: hal_py.BooleanFunction or None
234  )");
235 
236  py_boolean_function.def_static(
237  "Add",
238  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
239  auto res = BooleanFunction::Add(std::move(p0), std::move(p1), size);
240  if (res.is_ok())
241  {
242  return res.get();
243  }
244  else
245  {
246  log_error("python_context", "{}", res.get_error().get());
247  return std::nullopt;
248  }
249  },
250  py::arg("p0"),
251  py::arg("p1"),
252  py::arg("size"),
253  R"(
254  Joins two Boolean functions by applying an ADD operation.
255  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
256 
257  :param hal_py.BooleanFunction p0: First Boolean function.
258  :param hal_py.BooleanFunction p1: Second Boolean function.
259  :param int size: Bit-size of the operation.
260  :returns: The joined Boolean function on success, None otherwise.
261  :rtype: hal_py.BooleanFunction or None
262  )");
263 
264  py_boolean_function.def_static(
265  "Sub",
266  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
267  auto res = BooleanFunction::Sub(std::move(p0), std::move(p1), size);
268  if (res.is_ok())
269  {
270  return res.get();
271  }
272  else
273  {
274  log_error("python_context", "{}", res.get_error().get());
275  return std::nullopt;
276  }
277  },
278  py::arg("p0"),
279  py::arg("p1"),
280  py::arg("size"),
281  R"(
282  Joins two Boolean functions by applying an SUB operation.
283  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
284 
285  :param hal_py.BooleanFunction p0: First Boolean function.
286  :param hal_py.BooleanFunction p1: Second Boolean function.
287  :param int size: Bit-size of the operation.
288  :returns: The joined Boolean function on success, None otherwise.
289  :rtype: hal_py.BooleanFunction or None
290  )");
291 
292  py_boolean_function.def_static(
293  "Mul",
294  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
295  auto res = BooleanFunction::Mul(std::move(p0), std::move(p1), size);
296  if (res.is_ok())
297  {
298  return res.get();
299  }
300  else
301  {
302  log_error("python_context", "{}", res.get_error().get());
303  return std::nullopt;
304  }
305  },
306  py::arg("p0"),
307  py::arg("p1"),
308  py::arg("size"),
309  R"(
310  Joins two Boolean functions by applying an MUL operation.
311  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
312 
313  :param hal_py.BooleanFunction p0: First Boolean function.
314  :param hal_py.BooleanFunction p1: Second Boolean function.
315  :param int size: Bit-size of the operation.
316  :returns: The joined Boolean function on success, None otherwise.
317  :rtype: hal_py.BooleanFunction or None
318  )");
319 
320  py_boolean_function.def_static(
321  "Sdiv",
322  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
323  auto res = BooleanFunction::Sdiv(std::move(p0), std::move(p1), size);
324  if (res.is_ok())
325  {
326  return res.get();
327  }
328  else
329  {
330  log_error("python_context", "{}", res.get_error().get());
331  return std::nullopt;
332  }
333  },
334  py::arg("p0"),
335  py::arg("p1"),
336  py::arg("size"),
337  R"(
338  Joins two Boolean functions by applying an SDIV operation.
339  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
340 
341  :param hal_py.BooleanFunction p0: First Boolean function.
342  :param hal_py.BooleanFunction p1: Second Boolean function.
343  :param int size: Bit-size of the operation.
344  :returns: The joined Boolean function on success, None otherwise.
345  :rtype: hal_py.BooleanFunction or None
346  )");
347 
348  py_boolean_function.def_static(
349  "Udiv",
350  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
351  auto res = BooleanFunction::Udiv(std::move(p0), std::move(p1), size);
352  if (res.is_ok())
353  {
354  return res.get();
355  }
356  else
357  {
358  log_error("python_context", "{}", res.get_error().get());
359  return std::nullopt;
360  }
361  },
362  py::arg("p0"),
363  py::arg("p1"),
364  py::arg("size"),
365  R"(
366  Joins two Boolean functions by applying an UDIV operation.
367  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
368 
369  :param hal_py.BooleanFunction p0: First Boolean function.
370  :param hal_py.BooleanFunction p1: Second Boolean function.
371  :param int size: Bit-size of the operation.
372  :returns: The joined Boolean function on success, None otherwise.
373  :rtype: hal_py.BooleanFunction or None
374  )");
375 
376  py_boolean_function.def_static(
377  "Srem",
378  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
379  auto res = BooleanFunction::Srem(std::move(p0), std::move(p1), size);
380  if (res.is_ok())
381  {
382  return res.get();
383  }
384  else
385  {
386  log_error("python_context", "{}", res.get_error().get());
387  return std::nullopt;
388  }
389  },
390  py::arg("p0"),
391  py::arg("p1"),
392  py::arg("size"),
393  R"(
394  Joins two Boolean functions by applying an SREM operation.
395  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
396 
397  :param hal_py.BooleanFunction p0: First Boolean function.
398  :param hal_py.BooleanFunction p1: Second Boolean function.
399  :param int size: Bit-size of the operation.
400  :returns: The joined Boolean function on success, None otherwise.
401  :rtype: hal_py.BooleanFunction or None
402  )");
403 
404  py_boolean_function.def_static(
405  "Urem",
406  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
407  auto res = BooleanFunction::Urem(std::move(p0), std::move(p1), size);
408  if (res.is_ok())
409  {
410  return res.get();
411  }
412  else
413  {
414  log_error("python_context", "{}", res.get_error().get());
415  return std::nullopt;
416  }
417  },
418  py::arg("p0"),
419  py::arg("p1"),
420  py::arg("size"),
421  R"(
422  Joins two Boolean functions by applying an UREM operation.
423  Requires both Boolean functions to be of the specified bit-size and produces a new Boolean function of the same bit-size.
424 
425  :param hal_py.BooleanFunction p0: First Boolean function.
426  :param hal_py.BooleanFunction p1: Second Boolean function.
427  :param int size: Bit-size of the operation.
428  :returns: The joined Boolean function on success, None otherwise.
429  :rtype: hal_py.BooleanFunction or None
430  )");
431 
432  py_boolean_function.def_static(
433  "Slice",
434  [](BooleanFunction p0, BooleanFunction p1, BooleanFunction p2, u16 size) -> std::optional<BooleanFunction> {
435  auto res = BooleanFunction::Slice(std::move(p0), std::move(p1), std::move(p2), size);
436  if (res.is_ok())
437  {
438  return res.get();
439  }
440  else
441  {
442  log_error("python_context", "{}", res.get_error().get());
443  return std::nullopt;
444  }
445  },
446  py::arg("p0"),
447  py::arg("p1"),
448  py::arg("p2"),
449  py::arg("size"),
450  R"(
451  Returns the slice ``[i:j]`` of a Boolean function specified by a start index ``i`` and an end index ``j`` beginning at 0.
452  Note that slice ``[i:j]`` includes positions ``i`` and ``j`` as well.
453 
454  :param hal_py.BooleanFunction p0: Boolean function to slice.
455  :param hal_py.BooleanFunction p1: Boolean function of type ``Index`` encoding start index ``i``.
456  :param hal_py.BooleanFunction p2: Boolean function of type ``Index`` encoding end index ``j``.
457  :param int size: Bit-size of the resulting Boolean function slice, i.e., ``j - i + 1``.
458  :returns: The Boolean function slice on success, None otherwise.
459  :rtype: hal_py.BooleanFunction or None
460  )");
461 
462  py_boolean_function.def_static(
463  "Concat",
464  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
465  auto res = BooleanFunction::Concat(std::move(p0), std::move(p1), size);
466  if (res.is_ok())
467  {
468  return res.get();
469  }
470  else
471  {
472  log_error("python_context", "{}", res.get_error().get());
473  return std::nullopt;
474  }
475  },
476  py::arg("p0"),
477  py::arg("p1"),
478  py::arg("size"),
479  R"(
480  Concatenates two Boolean functions of bit-sizes ``n`` and ``m`` to form a single Boolean function of bit-size ``n + m``.
481 
482  :param hal_py.BooleanFunction p0: First Boolean function (MSBs).
483  :param hal_py.BooleanFunction p1: Second Boolean function (LSBs).
484  :param int size: Bit-size of the concatenated Boolean function, i.e., ``n + m``.
485  :returns: The concatenated Boolean function on success, None otherwise.
486  :rtype: hal_py.BooleanFunction or None
487  )");
488 
489  py_boolean_function.def_static(
490  "Zext",
491  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
492  auto res = BooleanFunction::Zext(std::move(p0), std::move(p1), size);
493  if (res.is_ok())
494  {
495  return res.get();
496  }
497  else
498  {
499  log_error("python_context", "{}", res.get_error().get());
500  return std::nullopt;
501  }
502  },
503  py::arg("p0"),
504  py::arg("p1"),
505  py::arg("size"),
506  R"(
507  Zero-extends a Boolean function to the specified bit-size.
508 
509  :param hal_py.BooleanFunction p0: Boolean function to extend.
510  :param hal_py.BooleanFunction p1: Boolean function of type ``Index`` encoding the bit-size of the zero-extended result.
511  :param int size: Bit-size of the zero-extended Boolean function.
512  :returns: The zero-extended Boolean function on success, None otherwise.
513  :rtype: hal_py.BooleanFunction or None
514  )");
515 
516  py_boolean_function.def_static(
517  "Sext",
518  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
519  auto res = BooleanFunction::Sext(std::move(p0), std::move(p1), size);
520  if (res.is_ok())
521  {
522  return res.get();
523  }
524  else
525  {
526  log_error("python_context", "{}", res.get_error().get());
527  return std::nullopt;
528  }
529  },
530  py::arg("p0"),
531  py::arg("p1"),
532  py::arg("size"),
533  R"(
534  Sign-extends a Boolean function to the specified bit-size.
535 
536  :param hal_py.BooleanFunction p0: Boolean function to extend.
537  :param hal_py.BooleanFunction p1: Boolean function of type ``Index`` encoding the bit-size of the sign-extended result.
538  :param int size: Bit-size of the sign-extended Boolean function.
539  :returns: The sign-extended Boolean function on success, None otherwise.
540  :rtype: hal_py.BooleanFunction or None
541  )");
542 
543  py_boolean_function.def_static(
544  "Shl",
545  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
546  auto res = BooleanFunction::Shl(std::move(p0), std::move(p1), size);
547  if (res.is_ok())
548  {
549  return res.get();
550  }
551  else
552  {
553  log_error("python_context", "{}", res.get_error().get());
554  return std::nullopt;
555  }
556  },
557  py::arg("p0"),
558  py::arg("p1"),
559  py::arg("size"),
560  R"(
561  Shifts a Boolean function to the left by the specified number of bits.
562 
563  :param hal_py.BooleanFunction p0: Boolean function to shift.
564  :param hal_py.BooleanFunction p1: Boolean function of type ``Index`` encoding the number of bits to shift.
565  :param int size: Bit-size of the shifted Boolean function.
566  :returns: The shifted Boolean function on success, None otherwise.
567  :rtype: hal_py.BooleanFunction or None
568  )");
569 
570  py_boolean_function.def_static(
571  "Lshr",
572  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
573  auto res = BooleanFunction::Lshr(std::move(p0), std::move(p1), size);
574  if (res.is_ok())
575  {
576  return res.get();
577  }
578  else
579  {
580  log_error("python_context", "{}", res.get_error().get());
581  return std::nullopt;
582  }
583  },
584  py::arg("p0"),
585  py::arg("p1"),
586  py::arg("size"),
587  R"(
588  Logically shifts a Boolean function to the right by the specified number of bits.
589 
590  :param hal_py.BooleanFunction p0: Boolean function to shift.
591  :param hal_py.BooleanFunction p1: Boolean function of type ``Index`` encoding the number of bits to shift.
592  :param int size: Bit-size of the shifted Boolean function.
593  :returns: The shifted Boolean function on success, None otherwise.
594  :rtype: hal_py.BooleanFunction or None
595  )");
596 
597  py_boolean_function.def_static(
598  "Ashr",
599  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
600  auto res = BooleanFunction::Ashr(std::move(p0), std::move(p1), size);
601  if (res.is_ok())
602  {
603  return res.get();
604  }
605  else
606  {
607  log_error("python_context", "{}", res.get_error().get());
608  return std::nullopt;
609  }
610  },
611  py::arg("p0"),
612  py::arg("p1"),
613  py::arg("size"),
614  R"(
615  Arithmetically shifts a Boolean function to the right by the specified number of bits.
616 
617  :param hal_py.BooleanFunction p0: Boolean function to shift.
618  :param hal_py.BooleanFunction p1: Boolean function of type ``Index`` encoding the number of bits to shift.
619  :param int size: Bit-size of the shifted Boolean function.
620  :returns: The shifted Boolean function on success, None otherwise.
621  :rtype: hal_py.BooleanFunction or None
622  )");
623 
624  py_boolean_function.def_static(
625  "Rol",
626  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
627  auto res = BooleanFunction::Rol(std::move(p0), std::move(p1), size);
628  if (res.is_ok())
629  {
630  return res.get();
631  }
632  else
633  {
634  log_error("python_context", "{}", res.get_error().get());
635  return std::nullopt;
636  }
637  },
638  py::arg("p0"),
639  py::arg("p1"),
640  py::arg("size"),
641  R"(
642  Rotates a Boolean function to the left by the specified number of bits.
643 
644  :param hal_py.BooleanFunction p0: Boolean function to rotate.
645  :param hal_py.BooleanFunction p1: Boolean function of type ``Index`` encoding the number of bits to rotate.
646  :param int size: Bit-size of the rotated Boolean function.
647  :returns: The rotated Boolean function on success, None otherwise.
648  :rtype: hal_py.BooleanFunction or None
649  )");
650 
651  py_boolean_function.def_static(
652  "Ror",
653  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
654  auto res = BooleanFunction::Ror(std::move(p0), std::move(p1), size);
655  if (res.is_ok())
656  {
657  return res.get();
658  }
659  else
660  {
661  log_error("python_context", "{}", res.get_error().get());
662  return std::nullopt;
663  }
664  },
665  py::arg("p0"),
666  py::arg("p1"),
667  py::arg("size"),
668  R"(
669  Rotates a Boolean function to the right by the specified number of bits.
670 
671  :param hal_py.BooleanFunction p0: Boolean function to rotate.
672  :param hal_py.BooleanFunction p1: Boolean function of type ``Index`` encoding the number of bits to rotate.
673  :param int size: Bit-size of the rotated Boolean function.
674  :returns: The rotated Boolean function on success, None otherwise.
675  :rtype: hal_py.BooleanFunction or None
676  )");
677 
678  py_boolean_function.def_static(
679  "Eq",
680  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
681  auto res = BooleanFunction::Eq(std::move(p0), std::move(p1), size);
682  if (res.is_ok())
683  {
684  return res.get();
685  }
686  else
687  {
688  log_error("python_context", "{}", res.get_error().get());
689  return std::nullopt;
690  }
691  },
692  py::arg("p0"),
693  py::arg("p1"),
694  py::arg("size"),
695  R"(
696  Joins two Boolean functions by an equality check that produces a single-bit result.
697 
698  :param hal_py.BooleanFunction p0: First Boolean function.
699  :param hal_py.BooleanFunction p1: Second Boolean function.
700  :param int size: Bit-size of the operation (always =1).
701  :returns: The joined Boolean function on success, None otherwise.
702  :rtype: hal_py.BooleanFunction or None
703  )");
704 
705  py_boolean_function.def_static(
706  "Sle",
707  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
708  auto res = BooleanFunction::Sle(std::move(p0), std::move(p1), size);
709  if (res.is_ok())
710  {
711  return res.get();
712  }
713  else
714  {
715  log_error("python_context", "{}", res.get_error().get());
716  return std::nullopt;
717  }
718  },
719  py::arg("p0"),
720  py::arg("p1"),
721  py::arg("size"),
722  R"(
723  Joins two Boolean functions by a signed less-than-equal check that produces a single-bit result.
724 
725  :param hal_py.BooleanFunction p0: First Boolean function.
726  :param hal_py.BooleanFunction p1: Second Boolean function.
727  :param int size: Bit-size of the operation (always =1).
728  :returns: The joined Boolean function on success, None otherwise.
729  :rtype: hal_py.BooleanFunction or None
730  )");
731 
732  py_boolean_function.def_static(
733  "Slt",
734  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
735  auto res = BooleanFunction::Slt(std::move(p0), std::move(p1), size);
736  if (res.is_ok())
737  {
738  return res.get();
739  }
740  else
741  {
742  log_error("python_context", "{}", res.get_error().get());
743  return std::nullopt;
744  }
745  },
746  py::arg("p0"),
747  py::arg("p1"),
748  py::arg("size"),
749  R"(
750  Joins two Boolean functions by a signed less-than check that produces a single-bit result.
751 
752  :param hal_py.BooleanFunction p0: First Boolean function.
753  :param hal_py.BooleanFunction p1: Second Boolean function.
754  :param int size: Bit-size of the operation (always =1).
755  :returns: The joined Boolean function on success, None otherwise.
756  :rtype: hal_py.BooleanFunction or None
757  )");
758 
759  py_boolean_function.def_static(
760  "Ule",
761  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
762  auto res = BooleanFunction::Ule(std::move(p0), std::move(p1), size);
763  if (res.is_ok())
764  {
765  return res.get();
766  }
767  else
768  {
769  log_error("python_context", "{}", res.get_error().get());
770  return std::nullopt;
771  }
772  },
773  py::arg("p0"),
774  py::arg("p1"),
775  py::arg("size"),
776  R"(
777  Joins two Boolean functions by an unsigned less-than-equal check that produces a single-bit result.
778 
779  :param hal_py.BooleanFunction p0: First Boolean function.
780  :param hal_py.BooleanFunction p1: Second Boolean function.
781  :param int size: Bit-size of the operation (always =1).
782  :returns: The joined Boolean function on success, None otherwise.
783  :rtype: hal_py.BooleanFunction or None
784  )");
785 
786  py_boolean_function.def_static(
787  "Ult",
788  [](BooleanFunction p0, BooleanFunction p1, u16 size) -> std::optional<BooleanFunction> {
789  auto res = BooleanFunction::Ult(std::move(p0), std::move(p1), size);
790  if (res.is_ok())
791  {
792  return res.get();
793  }
794  else
795  {
796  log_error("python_context", "{}", res.get_error().get());
797  return std::nullopt;
798  }
799  },
800  py::arg("p0"),
801  py::arg("p1"),
802  py::arg("size"),
803  R"(
804  Joins two Boolean functions by an unsigned less-than check that produces a single-bit result.
805 
806  :param hal_py.BooleanFunction p0: First Boolean function.
807  :param hal_py.BooleanFunction p1: Second Boolean function.
808  :param int size: Bit-size of the operation (always =1).
809  :returns: The joined Boolean function on success, None otherwise.
810  :rtype: hal_py.BooleanFunction or None
811  )");
812 
813  py_boolean_function.def_static(
814  "Ite",
815  [](BooleanFunction p0, BooleanFunction p1, BooleanFunction p2, u16 size) -> std::optional<BooleanFunction> {
816  auto res = BooleanFunction::Ite(std::move(p0), std::move(p1), std::move(p2), size);
817  if (res.is_ok())
818  {
819  return res.get();
820  }
821  else
822  {
823  log_error("python_context", "{}", res.get_error().get());
824  return std::nullopt;
825  }
826  },
827  py::arg("p0"),
828  py::arg("p1"),
829  py::arg("p2"),
830  py::arg("size"),
831  R"(
832  Joins three Boolean functions by an if-then-else operation with p0 as the condition, p1 as true-case, and p2 as false-case.
833  Requires ``p1`` to be of bit-size 1 and both Boolean functions ``p1`` and ``p2`` to be of the same bit-size.
834  Produces a new Boolean function of the specified bit-size that must be equal to the size of ``p1`` and ``p2``.
835 
836  :param hal_py.BooleanFunction p0: Boolean function condition.
837  :param hal_py.BooleanFunction p1: Boolean function for ``true``-case.
838  :param hal_py.BooleanFunction p1: Boolean function for ``false``-case.
839  :param int size: Bit-size of the operation, i.e., size of ``p1`` and ``p2``.
840  :returns: The joined Boolean function on success, None otherwise.
841  :rtype: hal_py.BooleanFunction or None
842  )");
843 
844  py_boolean_function.def(py::self & py::self, R"(
845  Joins two Boolean functions by an AND operation.
846  Requires both Boolean functions to be of the same bit-size.
847 
848  **Warning:** fails if the Boolean functions have different bit-sizes.
849 
850  :returns: The joined Boolean Bunction.
851  :rtype: hal_py.BooleanFunction
852  )");
853 
854  py_boolean_function.def(py::self &= py::self, R"(
855  Joins two Boolean functions by an AND operation in-place.
856  Requires both Boolean functions to be of the same bit-size.
857 
858  **Warning:** fails if the Boolean functions have different bit-sizes.
859 
860  :returns: The joined Boolean Bunction.
861  :rtype: hal_py.BooleanFunction
862  )");
863 
864  py_boolean_function.def(py::self | py::self, R"(
865  Joins two Boolean functions by an OR operation.
866  Requires both Boolean functions to be of the same bit-size.
867 
868  **Warning:** fails if the Boolean functions have different bit-sizes.
869 
870  :returns: The joined Boolean Bunction.
871  :rtype: hal_py.BooleanFunction
872  )");
873 
874  py_boolean_function.def(py::self |= py::self, R"(
875  Joins two Boolean functions by an OR operation in-place.
876  Requires both Boolean functions to be of the same bit-size.
877 
878  **Warning:** fails if the Boolean functions have different bit-sizes.
879 
880  :returns: The joined Boolean Bunction.
881  :rtype: hal_py.BooleanFunction
882  )");
883 
884  py_boolean_function.def(~py::self, R"(
885  Negates the Boolean function.
886 
887  :returns: The negated Boolean function.
888  :rtype: hal_py.BooleanFunction
889  )");
890 
891  py_boolean_function.def(py::self ^ py::self, R"(
892  Joins two Boolean functions by an XOR operation.
893  Requires both Boolean functions to be of the same bit-size.
894 
895  **Warning:** fails if the Boolean functions have different bit-sizes.
896 
897  :returns: The joined Boolean Bunction.
898  :rtype: hal_py.BooleanFunction
899  )");
900 
901  py_boolean_function.def(py::self ^= py::self, R"(
902  Joins two Boolean functions by an XOR operation in-place.
903  Requires both Boolean functions to be of the same bit-size.
904 
905  **Warning:** fails if the Boolean functions have different bit-sizes.
906 
907  :returns: The joined Boolean Bunction.
908  :rtype: hal_py.BooleanFunction
909  )");
910 
911  py_boolean_function.def(py::self + py::self, R"(
912  Joins two Boolean functions by an ADD operation.
913  Requires both Boolean functions to be of the same bit-size.
914 
915  **Warning:** fails if the Boolean functions have different bit-sizes.
916 
917  :returns: The joined Boolean Bunction.
918  :rtype: hal_py.BooleanFunction
919  )");
920 
921  py_boolean_function.def(py::self += py::self, R"(
922  Joins two Boolean functions by an ADD operation in-place.
923  Requires both Boolean functions to be of the same bit-size.
924 
925  **Warning:** fails if the Boolean functions have different bit-sizes.
926 
927  :returns: The joined Boolean Bunction.
928  :rtype: hal_py.BooleanFunction
929  )");
930 
931  py_boolean_function.def(py::self - py::self, R"(
932  Joins two Boolean functions by an SUB operation.
933  Requires both Boolean functions to be of the same bit-size.
934 
935  **Warning:** fails if the Boolean functions have different bit-sizes.
936 
937  :returns: The joined Boolean Bunction.
938  :rtype: hal_py.BooleanFunction
939  )");
940 
941  py_boolean_function.def(py::self -= py::self, R"(
942  Joins two Boolean functions by an SUB operation in-place.
943  Requires both Boolean functions to be of the same bit-size.
944 
945  **Warning:** fails if the Boolean functions have different bit-sizes.
946 
947  :returns: The joined Boolean Bunction.
948  :rtype: hal_py.BooleanFunction
949  )");
950 
951  py_boolean_function.def(py::self * py::self, R"(
952  Joins two Boolean functions by an MUL operation.
953  Requires both Boolean functions to be of the same bit-size.
954 
955  **Warning:* fails if the Boolean functions have different bit-sizes.
956 
957  :returns: The joined Boolean Bunction.
958  :rtype: hal_py.BooleanFunction
959  )");
960 
961  py_boolean_function.def(py::self *= py::self, R"(
962  Joins two Boolean functions by an MUL operation in-place.
963  Requires both Boolean functions to be of the same bit-size.
964 
965  **Warning:** fails if the Boolean functions have different bit-sizes.
966 
967  :returns: The joined Boolean Bunction.
968  :rtype: hal_py.BooleanFunction
969  )");
970 
971  py_boolean_function.def(py::self == py::self, R"(
972  Checks whether two Boolean functions are equal.
973 
974  :returns: True if both Boolean functions are equal, False otherwise.
975  :rtype: bool
976  )");
977 
978  py_boolean_function.def(py::self != py::self, R"(
979  Checks whether two Boolean functions are unequal.
980 
981  :returns: True if both Boolean functions are unequal, False otherwise.
982  :rtype: bool
983  )");
984 
985  py_boolean_function.def(py::self < py::self, R"(
986  Checks whether this Boolean function is 'smaller' than the ``other`` Boolean function.
987 
988  :returns: True if this Boolean function is 'smaller', False otherwise.
989  :rtype: bool
990  )");
991 
992  py_boolean_function.def("is_empty", &BooleanFunction::is_empty, R"(
993  Checks whether the Boolean function is empty.
994 
995  :returns: True if the Boolean function is empty, False otherwise.
996  :rtype: bool
997  )");
998 
999  py_boolean_function.def("clone", &BooleanFunction::clone, R"(
1000  Clones the Boolean function.
1001 
1002  :returns: The cloned Boolean function.
1003  :rtype: hal_py.BooleanFunction
1004  )");
1005 
1006  py_boolean_function.def_property_readonly("size", &BooleanFunction::size, R"(
1007  The bit-size of the Boolean function.
1008 
1009  :type: int
1010  )");
1011 
1012  py_boolean_function.def("get_size", &BooleanFunction::size, R"(
1013  Returns the bit-size of the Boolean function.
1014 
1015  :returns: The bit-size of the Boolean function.
1016  :rtype: int
1017  )");
1018 
1019  py_boolean_function.def("is", &BooleanFunction::is, py::arg("type"), R"(
1020  Checks whether the top-level node of the Boolean function is of a specific type.
1021 
1022  :param int type: The type to check for.
1023  :returns: True if the node is of the given type, False otherwise.
1024  :rtype: bool
1025  )");
1026 
1027  py_boolean_function.def("is_variable", &BooleanFunction::is_variable, R"(
1028  Checks whether the top-level node of the Boolean function is of type ``Variable`` and holds a specific variable name.
1029 
1030  :returns: True if the top-level node of the Boolean function is of type Variable, False otherwise.
1031  :rtype: bool
1032  )");
1033 
1034  py_boolean_function.def("has_variable_name", &BooleanFunction::has_variable_name, R"(
1035  Checks whether the top-level node of the Boolean function is of type Variable and holds a specific variable name.
1036 
1037  :param int value: The variable name to check for.
1038  :returns: True if the top-level node of the Boolean function is of type Variable and holds the given variable name, False otherwise.
1039  :rtype: bool
1040  )");
1041 
1042  py_boolean_function.def(
1043  "get_variable_name",
1044  [](const BooleanFunction& self) -> std::optional<std::string> {
1045  auto res = self.get_variable_name();
1046  if (res.is_ok())
1047  {
1048  return res.get();
1049  }
1050  else
1051  {
1052  log_error("python_context", "{}", res.get_error().get());
1053  return std::nullopt;
1054  }
1055  },
1056  R"(
1057  Get the variable name of the top-level node of the Boolean function of type Variable.
1058 
1059  :returns: The variable name on success, None otherwise.
1060  :rtype: str or None
1061  )");
1062 
1063  py_boolean_function.def("is_constant", &BooleanFunction::is_constant, R"(
1064  Checks whether the top-level node of the Boolean function is of type Constant.
1065 
1066  :returns: True if the top-level node of the Boolean function is of type Constant, False otherwise.
1067  :rtype: bool
1068  )");
1069 
1070  py_boolean_function.def("has_constant_value", py::overload_cast<const std::vector<BooleanFunction::Value>&>(&BooleanFunction::has_constant_value, py::const_), R"(
1071  Checks whether the top-level node of the Boolean function is of type Constant and holds a specific value.
1072 
1073  :param list[hal_py.BooleanFunction.Value] value: The constant value to check for.
1074  :returns: True if the top-level node of the Boolean function is of type Constant and holds the given value, False otherwise.
1075  :rtype: bool
1076  )");
1077 
1078  py_boolean_function.def("has_constant_value", py::overload_cast<u64>(&BooleanFunction::has_constant_value, py::const_), R"(
1079  Checks whether the top-level node of the Boolean function is of type Constant and holds a specific value.
1080 
1081  :param int value: The constant value to check for.
1082  :returns: True if the top-level node of the Boolean function is of type Constant and holds the given value, False otherwise.
1083  :rtype: bool
1084  )");
1085 
1086  py_boolean_function.def(
1087  "get_constant_value",
1088  [](const BooleanFunction& self) -> std::optional<std::vector<BooleanFunction::Value>> {
1089  auto res = self.get_constant_value();
1090  if (res.is_ok())
1091  {
1092  return res.get();
1093  }
1094  else
1095  {
1096  log_error("python_context", "{}", res.get_error().get());
1097  return std::nullopt;
1098  }
1099  },
1100  R"(
1101  Get the constant value of the top-level node of the Boolean function of type Constant as a list of ``hal_py.BooleanFunction.Value``.
1102 
1103  :returns: The constant value on success, None otherwise.
1104  :rtype: list[hal_py.BooleanFunction.Value] or None
1105  )");
1106 
1107  py_boolean_function.def(
1108  "get_constant_value_u64",
1109  [](const BooleanFunction& self) -> std::optional<u64> {
1110  auto res = self.get_constant_value_u64();
1111  if (res.is_ok())
1112  {
1113  return res.get();
1114  }
1115  else
1116  {
1117  log_error("python_context", "{}", res.get_error().get());
1118  return std::nullopt;
1119  }
1120  },
1121  R"(
1122  Get the constant value of the top-level node of the Boolean function of type Constant as long as it has a size <= 64-bit.
1123 
1124  :returns: The constant value on success, None otherwise.
1125  :rtype: int or None
1126  )");
1127 
1128  py_boolean_function.def("is_index", &BooleanFunction::is_index, R"(
1129  Checks whether the top-level node of the Boolean function is of type Index.
1130 
1131  :returns: True if the top-level node of the Boolean function is of type Index, False otherwise.
1132  :rtype: bool
1133  )");
1134 
1135  py_boolean_function.def("has_index_value", &BooleanFunction::has_index_value, R"(
1136  Checks whether the top-level node of the Boolean function is of type Index and holds a specific value.
1137 
1138  :param int value: The index value to check for.
1139  :returns: True if the top-level node of the Boolean function is of type Index and holds the given value, False otherwise.
1140  :rtype: bool
1141  )");
1142 
1143  py_boolean_function.def(
1144  "get_index_value",
1145  [](const BooleanFunction& self) -> std::optional<u16> {
1146  auto res = self.get_index_value();
1147  if (res.is_ok())
1148  {
1149  return res.get();
1150  }
1151  else
1152  {
1153  log_error("python_context", "{}", res.get_error().get());
1154  return std::nullopt;
1155  }
1156  },
1157  R"(
1158  Get the index value of the top-level node of the Boolean function of type Index.
1159 
1160  :returns: The index value on success, None otherwise.
1161  :rtype: int or None
1162  )");
1163 
1164  py_boolean_function.def_property_readonly("top_level_node", &BooleanFunction::get_top_level_node, R"(
1165  The top-level node of the Boolean function.
1166 
1167  **Warning:** fails if the Boolean function is empty.
1168 
1169  :type: hal_py.BooleanFunction.Node
1170  )");
1171 
1172  py_boolean_function.def("get_top_level_node", &BooleanFunction::get_top_level_node, R"(
1173  Returns the top-level node of the Boolean function.
1174 
1175  **Warning:** fails if the Boolean function is empty.
1176 
1177  :returns: The top-level node.
1178  :rtype: hal_py.BooleanFunction.Node
1179  )");
1180 
1181  py_boolean_function.def_property_readonly("length", &BooleanFunction::length, R"(
1182  The number of nodes in the Boolean function.
1183 
1184  :type: int
1185  )");
1186 
1187  py_boolean_function.def("get_length", &BooleanFunction::length, R"(
1188  Returns the number of nodes in the Boolean function.
1189 
1190  :returns: The number of nodes.
1191  :rtype: int
1192  )");
1193 
1194  py_boolean_function.def("nodes", &BooleanFunction::get_nodes, R"(
1195  The reverse polish notation list of the Boolean function nodes.
1196 
1197  :type: list[hal_py.BooleanFunction.Node]
1198  )");
1199 
1200  py_boolean_function.def("get_nodes", &BooleanFunction::get_nodes, R"(
1201  Returns the reverse polish notation list of the Boolean function nodes.
1202 
1203  :returns: A list of nodes.
1204  :rtype: list[hal_py.BooleanFunction.Node]
1205  )");
1206 
1207  py_boolean_function.def_property_readonly("parameters", &BooleanFunction::get_parameters, R"(
1208  The parameter list of the top-level node of the Boolean function.
1209 
1210  :type: list[hal_py.BooleanFunction]
1211  )");
1212 
1213  py_boolean_function.def("get_parameters", &BooleanFunction::get_parameters, R"(
1214  Returns the parameter list of the top-level node of the Boolean function.
1215 
1216  :returns: A vector of Boolean functions.
1217  :rtype: list[hal_py.BooleanFunction]
1218  )");
1219 
1220  py_boolean_function.def_property_readonly("variable_names", &BooleanFunction::get_variable_names, R"(
1221  The set of variable names used by the Boolean function.
1222 
1223  :type: set[str]
1224  )");
1225 
1226  py_boolean_function.def("get_variable_names", &BooleanFunction::get_variable_names, R"(
1227  Returns the set of variable names used by the Boolean function.
1228 
1229  :returns: A set of variable names.
1230  :rtype: set[str]
1231  )");
1232 
1233  py_boolean_function.def(
1234  "__str__", [](const BooleanFunction& f) { return f.to_string(); }, R"(
1235  Translates the Boolean function into its string representation.
1236 
1237  :returns: The Boolean function as a string.
1238  :rtype: str
1239  )");
1240 
1241  py_boolean_function.def_static(
1242  "from_string",
1243  [](const std::string& expression) -> BooleanFunction {
1244  auto res = BooleanFunction::from_string(expression);
1245  if (res.is_ok())
1246  {
1247  return res.get();
1248  }
1249  else
1250  {
1251  log_error("python_context", "{}", res.get_error().get());
1252  return BooleanFunction();
1253  }
1254  },
1255  py::arg("expression"),
1256  R"(
1257  Parses a Boolean function from a string expression.
1258 
1259  :param str expression: Boolean function string.
1260  :returns: The Boolean function on success, an empty Boolean function otherwise.
1261  :rtype: hal_py.BooleanFunction
1262  )");
1263 
1264  py_boolean_function.def("simplify", &BooleanFunction::simplify, R"(
1265  Simplifies the Boolean function.
1266 
1267  :returns: The simplified Boolean function.
1268  :rtype: hal_py.BooleanFunction
1269  )");
1270 
1271  py_boolean_function.def(
1272  "substitute", py::overload_cast<const std::string&, const std::string&>(&BooleanFunction::substitute, py::const_), py::arg("old_variable_name"), py::arg("new_variable_name"), R"(
1273  Substitute a variable name with another one, i.e., renames the variable.
1274  The operation is applied to all instances of the variable in the function.
1275 
1276  :param str old_variable_name: The old variable name to substitute.
1277  :param str new_variable_name: The new variable name.
1278  :returns: The resulting Boolean function.
1279  :rtype: hal_py.BooleanFunction
1280  )");
1281 
1282  py_boolean_function.def(
1283  "substitute",
1284  [](const BooleanFunction& self, const std::string& variable_name, const BooleanFunction& function) -> std::optional<BooleanFunction> {
1285  auto res = self.substitute(variable_name, function);
1286  if (res.is_ok())
1287  {
1288  return res.get();
1289  }
1290  else
1291  {
1292  log_error("python_context", "{}", res.get_error().get());
1293  return std::nullopt;
1294  }
1295  },
1296  py::arg("variable_name"),
1297  py::arg("function"),
1298  R"(
1299  Substitute a variable with another Boolean function.
1300  The operation is applied to all instances of the variable in the function.
1301 
1302  :param str variable_name: The variable to substitute.
1303  :param hal_py.BooleanFunction function: The function replace the variable with.
1304  :returns: The resulting Boolean function on success, None otherwise.
1305  :rtype: hal_py.BooleanFunction or None
1306  )");
1307 
1308  py_boolean_function.def("substitute",
1309  py::overload_cast<const std::map<std::string, std::string>&>(&BooleanFunction::substitute, py::const_),
1310  py::arg("substitutions"),
1311  R"(
1312  Substitute multiple variable names with different names at once, i.e., rename the variables.
1313  The operation is applied to all instances of the variable in the function.
1314 
1315  :param dict[str,str] substitutions: A dict from old variable names to new variable names.
1316  :returns: The resulting Boolean function.
1317  :rtype: hal_py.BooleanFunction
1318  )");
1319 
1320  py_boolean_function.def(
1321  "substitute",
1322  [](const BooleanFunction& self, const std::map<std::string, BooleanFunction>& substitutions) -> std::optional<BooleanFunction> {
1323  auto res = self.substitute(substitutions);
1324  if (res.is_ok())
1325  {
1326  return res.get();
1327  }
1328  else
1329  {
1330  log_error("python_context", "{}", res.get_error().get());
1331  return std::nullopt;
1332  }
1333  },
1334  py::arg("substitutions"),
1335  R"(
1336  Substitute multiple variables with other boolean functions at once.
1337  The operation is applied to all instances of the variable in the function.
1338 
1339  :param dict substitutions: A map from the variable names to the function to replace the variable with.
1340  :returns: The resulting Boolean function on success, None otherwise.
1341  :rtype: hal_py.BooleanFunction or None
1342  )");
1343 
1344  py_boolean_function.def(
1345  "evaluate",
1346  [](const BooleanFunction& self, const std::unordered_map<std::string, BooleanFunction::Value>& inputs) -> std::optional<BooleanFunction::Value> {
1347  auto res = self.evaluate(inputs);
1348  if (res.is_ok())
1349  {
1350  return res.get();
1351  }
1352  else
1353  {
1354  log_error("python_context", "{}", res.get_error().get());
1355  return std::nullopt;
1356  }
1357  },
1358  py::arg("inputs"),
1359  R"(
1360  Evaluates a Boolean function comprising only single-bit variables using the given input values.
1361 
1362  :param dict[str,hal_py.BooleanFunction.Value] inputs: A dict from variable name to input value.
1363  :returns: The resulting value on success, None otherwise.
1364  :rtype: hal_py.BooleanFunction.Value or None
1365  )");
1366 
1367  py_boolean_function.def(
1368  "evaluate",
1369  [](const BooleanFunction& self, const std::unordered_map<std::string, std::vector<BooleanFunction::Value>>& inputs) -> std::optional<std::vector<BooleanFunction::Value>> {
1370  auto res = self.evaluate(inputs);
1371  if (res.is_ok())
1372  {
1373  return res.get();
1374  }
1375  else
1376  {
1377  log_error("python_context", "{}", res.get_error().get());
1378  return std::nullopt;
1379  }
1380  },
1381  py::arg("inputs"),
1382  R"(
1383  Evaluates a Boolean function comprising multi-bit variables using the given input values.
1384 
1385  :param dict[str,list[hal_py.BooleanFunction.Value]] inputs: A dict from variable name to a list of input values.
1386  :returns: A vector of values on success, None otherwise.
1387  :rtype: list[hal_py.BooleanFunction.Value] or None
1388  )");
1389 
1390  py_boolean_function.def(
1391  "compute_truth_table",
1392  [](const BooleanFunction& self, const std::vector<std::string>& ordered_variables, bool remove_unknown_variables) -> std::optional<std::vector<std::vector<BooleanFunction::Value>>> {
1393  auto res = self.compute_truth_table(ordered_variables, remove_unknown_variables);
1394  if (res.is_ok())
1395  {
1396  return res.get();
1397  }
1398  else
1399  {
1400  log_error("python_context", "{}", res.get_error().get());
1401  return std::nullopt;
1402  }
1403  },
1404  py::arg("ordered_variables") = std::vector<std::string>(),
1405  py::arg("remove_unknown_variables") = false,
1406  R"(
1407  Computes the truth table outputs for a Boolean function that comprises <= 10 single-bit variables.
1408 
1409  **Warning:** The generation of the truth table is exponential in the number of parameters.
1410 
1411  :param list[str] ordered_variables: A list describing the order of input variables used to generate the truth table. Defaults to an empty list.
1412  :param bool remove_unknown_variables: Set True to remove variables from the truth table that are not present within the Boolean function, False otherwise. Defaults to False.
1413  :returns: A list of values representing the truth table output on success, None otherwise.
1414  :rtype: list[list[hal_py.BooleanFunction.Value]] or None
1415  )");
1416 
1417  py_boolean_function.def(
1418  "get_truth_table_as_string",
1419  [](const BooleanFunction& self, const std::vector<std::string>& ordered_variables, std::string function_name, bool remove_unknown_variables) -> std::optional<std::string> {
1420  auto res = self.get_truth_table_as_string(ordered_variables, function_name, remove_unknown_variables);
1421  if (res.is_ok())
1422  {
1423  return res.get();
1424  }
1425  else
1426  {
1427  log_error("python_context", "{}", res.get_error().get());
1428  return std::nullopt;
1429  }
1430  },
1431  py::arg("ordered_variables") = std::vector<std::string>(),
1432  py::arg("function_name") = std::string(""),
1433  py::arg("remove_unknown_variables") = false,
1434  R"(
1435  Prints the truth table for a Boolean function that comprises <= 10 single-bit variables.
1436 
1437  **Warning:** The generation of the truth table is exponential in the number of parameters.
1438 
1439  :param list[str] ordered_variables: A list describing the order of input variables used to generate the truth table. Defaults to an empty list.
1440  :param str function_name: The name of the Boolean function to be printed as header of the output columns.
1441  :param bool remove_unknown_variables: Set True to remove variables from the truth table that are not present within the Boolean function, False otherwise. Defaults to False.
1442  :returns: A string representing the truth table on success, None otherwise.
1443  :rtype: str or None
1444  )");
1445 
1446  py::class_<BooleanFunction::Node> py_boolean_function_node(py_boolean_function, "Node", R"(
1447  Node refers to an abstract syntax tree node of a Boolean function. A node is an abstract base class for either an operation (e.g., AND, XOR) or an operand (e.g., a signal name variable).
1448  )");
1449 
1450  py_boolean_function_node.def_readwrite("type", &BooleanFunction::Node::type, R"(
1451  The type of the node.
1452 
1453  :type: int
1454  )");
1455 
1456  py_boolean_function_node.def_readwrite("size", &BooleanFunction::Node::size, R"(
1457  The bit-size of the node.
1458 
1459  :type: int
1460  )");
1461 
1462  py_boolean_function_node.def_readwrite("constant", &BooleanFunction::Node::constant, R"(
1463  The (optional) constant value of the node.
1464 
1465  :type: list[hal_py.BooleanFunction.Value]
1466  )");
1467 
1468  py_boolean_function_node.def_readwrite("index", &BooleanFunction::Node::index, R"(
1469  The (optional) index value of the node.
1470 
1471  :type: int
1472  )");
1473 
1474  py_boolean_function_node.def_readwrite("variable", &BooleanFunction::Node::variable, R"(
1475  The (optional) variable name of the node.
1476 
1477  :type: str
1478  )");
1479 
1480  py_boolean_function_node.def_static("Operation", BooleanFunction::Node::Operation, py::arg("type"), py::arg("size"), R"(
1481  Constructs an 'operation' node.
1482 
1483  :param int type: The type of the operation.
1484  :param int size: The bit-size of the operation.
1485  :returns: The node.
1486  :rtype: hal_py.BooleanFunction.Node
1487  )");
1488 
1489  py_boolean_function_node.def_static("Constant", BooleanFunction::Node::Constant, py::arg("value"), R"(
1490  Constructs a 'constant' node.
1491 
1492  :param list[hal_py.BooleanFunction.Value] value: The constant value of the node.
1493  :returns: The node.
1494  :rtype: hal_py.BooleanFunction.Node
1495  )");
1496 
1497  py_boolean_function_node.def_static("Index", BooleanFunction::Node::Index, py::arg("index"), py::arg("size"), R"(
1498  Constructs an 'index' node.
1499 
1500  :param int value: The index value of the node.
1501  :param int size: The bit-size of the node.
1502  :returns: The node.
1503  :rtype: hal_py.BooleanFunction.Node
1504  )");
1505 
1506  py_boolean_function_node.def_static("Variable", BooleanFunction::Node::Variable, py::arg("variable"), py::arg("size"), R"(
1507  Constructs a 'variable' node.
1508 
1509  :param int value: The variable name of the node.
1510  :param int size: The bit-size of the node.
1511  :returns: The node.
1512  :rtype: hal_py.BooleanFunction.Node
1513  )");
1514 
1515  py_boolean_function_node.def(py::self == py::self, R"(
1516  Checks whether two Boolean function nodes are equal.
1517 
1518  :returns: True if both Boolean function nodes are equal, False otherwise.
1519  :rtype: bool
1520  )");
1521 
1522  py_boolean_function_node.def(py::self != py::self, R"(
1523  Checks whether two Boolean function nodes are unequal.
1524 
1525  :returns: True if both Boolean function nodes are unequal, False otherwise.
1526  :rtype: bool
1527  )");
1528 
1529  py_boolean_function_node.def(py::self < py::self, R"(
1530  Checks whether this Boolean function node is 'smaller' than the ``other`` Boolean function node.
1531 
1532  :returns: True if this Boolean function node is 'smaller', False otherwise.
1533  :rtype: bool
1534  )");
1535 
1536  py_boolean_function_node.def("clone", &BooleanFunction::Node::clone, R"(
1537  Clones the Boolean function node.
1538 
1539  :returns: The cloned Boolean function node.
1540  :rtype: hal_py.BooleanFunction.Node
1541  )");
1542 
1543  py_boolean_function_node.def(
1544  "__str__", [](const BooleanFunction::Node& n) { return n.to_string(); }, R"(
1545  Translates the Boolean function node into its string representation.
1546 
1547  :returns: The Boolean function node as a string.
1548  :rtype: str
1549  )");
1550 
1551  py_boolean_function_node.def_property_readonly("arity", &BooleanFunction::Node::get_arity, R"(
1552  The arity of the Boolean function node, i.e., the number of parameters.
1553 
1554  :type: int
1555  )");
1556 
1557  py_boolean_function_node.def("get_arity", &BooleanFunction::Node::get_arity, R"(
1558  Returns the arity of the Boolean function node, i.e., the number of parameters.
1559 
1560  :returns: The arity.
1561  :rtype: int
1562  )");
1563 
1564  py_boolean_function_node.def_static("get_arity_of_type", &BooleanFunction::Node::get_arity_of_type, py::arg("type"), R"(
1565  Returns the arity for a Boolean function node of the given type, i.e., the number of parameters.
1566 
1567  :returns: The arity.
1568  :rtype: int
1569  )");
1570 
1571  py_boolean_function_node.def("is", &BooleanFunction::Node::is, py::arg("type"), R"(
1572  Checks whether the Boolean function node is of a specific type.
1573 
1574  :param int type: The type to check for.
1575  :returns: True if the node is of the given type, False otherwise.
1576  :rtype: bool
1577  )");
1578 
1579  py_boolean_function_node.def("is_constant", &BooleanFunction::Node::is_constant, R"(
1580  Checks whether the Boolean function node is of type Constant.
1581 
1582  :returns: True if the Boolean function node is of type Constant, False otherwise.
1583  :rtype: bool
1584  )");
1585 
1586  py_boolean_function_node.def("has_constant_value", py::overload_cast<const std::vector<BooleanFunction::Value>&>(&BooleanFunction::Node::has_constant_value, py::const_), py::arg("value"), R"(
1587  Checks whether the Boolean function node is of type Constant and holds a specific value.
1588 
1589  :param list[hal_py.BooleanFunction.Value] value: The value to check for.
1590  :returns: True if the Boolean function node is of type Constant and holds the given value, False otherwise.
1591  :rtype: bool
1592  )");
1593 
1594  py_boolean_function_node.def("has_constant_value", py::overload_cast<u64>(&BooleanFunction::Node::has_constant_value, py::const_), py::arg("value"), R"(
1595  Checks whether the Boolean function node is of type Constant and holds a specific value.
1596 
1597  :param int value: The value to check for.
1598  :returns: True if the Boolean function node is of type Constant and holds the given value, False otherwise.
1599  :rtype: bool
1600  )");
1601 
1602  py_boolean_function_node.def(
1603  "get_constant_value",
1604  [](const BooleanFunction::Node& self) -> std::optional<std::vector<BooleanFunction::Value>> {
1605  if (const auto res = self.get_constant_value(); res.is_ok())
1606  {
1607  return res.get();
1608  }
1609  else
1610  {
1611  log_error("python_context", "could not get constant value:\n{}", res.get_error().get());
1612  return std::nullopt;
1613  }
1614  },
1615  R"(
1616  Get the constant value of the node of type ``Constant`` as a list of ``hal_py.BooleanFunction.Value``.
1617 
1618  :returns: The constant value on success, None otherwise.
1619  :rtype: list[hal_py.BooleanFunction.Value] or None
1620  )");
1621 
1622  py_boolean_function_node.def(
1623  "get_constant_value_u64",
1624  [](const BooleanFunction::Node& self) -> std::optional<u64> {
1625  if (const auto res = self.get_constant_value_u64(); res.is_ok())
1626  {
1627  return res.get();
1628  }
1629  else
1630  {
1631  log_error("python_context", "could not get constant value:\n{}", res.get_error().get());
1632  return std::nullopt;
1633  }
1634  },
1635  R"(
1636  Get the constant value of the node of type ``Constant`` as long as it has a size <= 64-bit.
1637 
1638  :returns: The constant value on success, None otherwise.
1639  :rtype: int or None
1640  )");
1641 
1642  py_boolean_function_node.def("is_index", &BooleanFunction::Node::is_index, R"(
1643  Checks whether the Boolean function node is of type Index.
1644 
1645  :returns: True if the Boolean function node is of type Index, False otherwise.
1646  :rtype: bool
1647  )");
1648 
1649  py_boolean_function_node.def("has_index_value", &BooleanFunction::Node::has_index_value, py::arg("value"), R"(
1650  Checks whether the Boolean function node is of type Index and holds a specific value.
1651 
1652  :param int value: The value to check for.
1653  :returns: True if the Boolean function node is of type Index and holds the given value, False otherwise.
1654  :rtype: bool
1655  )");
1656 
1657  py_boolean_function_node.def(
1658  "get_index_value",
1659  [](const BooleanFunction::Node& self) -> std::optional<u64> {
1660  if (const auto res = self.get_index_value(); res.is_ok())
1661  {
1662  return res.get();
1663  }
1664  else
1665  {
1666  log_error("python_context", "could not get index value:\n{}", res.get_error().get());
1667  return std::nullopt;
1668  }
1669  },
1670  R"(
1671  Get the index value of node of type ``Index``.
1672 
1673  :returns: The index value on success, None otherwise.
1674  :rtype: int or None
1675  )");
1676 
1677  py_boolean_function_node.def("is_variable", &BooleanFunction::Node::is_variable, R"(
1678  Checks whether the Boolean function node is of type Variable.
1679 
1680  :returns: True if the Boolean function node is of type Variable, False otherwise.
1681  :rtype: bool
1682  )");
1683 
1684  py_boolean_function_node.def("has_variable_name", &BooleanFunction::Node::has_variable_name, py::arg("variable_name"), R"(
1685  Checks whether the Boolean function node is of type Variable and holds a specific variable name.
1686 
1687  :param str variable_name: The variable name to check for.
1688  :returns: True if the Boolean function node is of type Variable and holds the given variable name, False otherwise.
1689  :rtype: bool
1690  )");
1691 
1692  py_boolean_function_node.def(
1693  "get_variable_name",
1694  [](const BooleanFunction::Node& self) -> std::optional<std::string> {
1695  if (const auto res = self.get_variable_name(); res.is_ok())
1696  {
1697  return res.get();
1698  }
1699  else
1700  {
1701  log_error("python_context", "could not get variable name:\n{}", res.get_error().get());
1702  return std::nullopt;
1703  }
1704  },
1705  R"(
1706  Get the variable name of node of type ``Variable``.
1707 
1708  :returns: The variable name on success, None otherwise.
1709  :rtype: str or None
1710  )");
1711 
1712  py_boolean_function_node.def("is_operation", &BooleanFunction::Node::is_operation, R"(
1713  Checks whether the Boolean function node is an operation node.
1714 
1715  :returns: True if the Boolean function node is an operation node, False otherwise.
1716  :rtype: bool
1717  )");
1718 
1719  py_boolean_function_node.def("is_operand", &BooleanFunction::Node::is_operand, R"(
1720  Checks whether the Boolean function node is an operand node.
1721 
1722  :returns: True if the Boolean function node is an operand node, False otherwise.
1723  :rtype: bool
1724  )");
1725 
1726  py_boolean_function_node.def("is_commutative", &BooleanFunction::Node::is_commutative, R"(
1727  Checks whether the Boolean function node is commutative.
1728 
1729  :returns: True if the Boolean function node is commutative, False otherwise.
1730  :rtype: bool
1731  )");
1732 
1733  py::class_<BooleanFunction::NodeType> py_boolean_function_node_type(py_boolean_function, "NodeType", R"(
1734  Holds all node types available in a Boolean function.
1735  )");
1736 
1737  py_boolean_function_node_type.def_readonly_static("And", &BooleanFunction::NodeType::And);
1738  py_boolean_function_node_type.def_readonly_static("Or", &BooleanFunction::NodeType::Or);
1739  py_boolean_function_node_type.def_readonly_static("Not", &BooleanFunction::NodeType::Not);
1740  py_boolean_function_node_type.def_readonly_static("Xor", &BooleanFunction::NodeType::Xor);
1741 
1742  py_boolean_function_node_type.def_readonly_static("Add", &BooleanFunction::NodeType::Add);
1743  py_boolean_function_node_type.def_readonly_static("Sub", &BooleanFunction::NodeType::Sub);
1744  py_boolean_function_node_type.def_readonly_static("Mul", &BooleanFunction::NodeType::Mul);
1745  py_boolean_function_node_type.def_readonly_static("Sdiv", &BooleanFunction::NodeType::Sdiv);
1746  py_boolean_function_node_type.def_readonly_static("Udiv", &BooleanFunction::NodeType::Udiv);
1747  py_boolean_function_node_type.def_readonly_static("Srem", &BooleanFunction::NodeType::Srem);
1748  py_boolean_function_node_type.def_readonly_static("Urem", &BooleanFunction::NodeType::Urem);
1749 
1750  py_boolean_function_node_type.def_readonly_static("Concat", &BooleanFunction::NodeType::Concat);
1751  py_boolean_function_node_type.def_readonly_static("Slice", &BooleanFunction::NodeType::Slice);
1752  py_boolean_function_node_type.def_readonly_static("Zext", &BooleanFunction::NodeType::Zext);
1753  py_boolean_function_node_type.def_readonly_static("Sext", &BooleanFunction::NodeType::Sext);
1754 
1755  py_boolean_function_node_type.def_readonly_static("Shl", &BooleanFunction::NodeType::Shl);
1756  py_boolean_function_node_type.def_readonly_static("Lshr", &BooleanFunction::NodeType::Lshr);
1757  py_boolean_function_node_type.def_readonly_static("Ashr", &BooleanFunction::NodeType::Ashr);
1758  py_boolean_function_node_type.def_readonly_static("Rol", &BooleanFunction::NodeType::Rol);
1759  py_boolean_function_node_type.def_readonly_static("Ror", &BooleanFunction::NodeType::Ror);
1760 
1761  py_boolean_function_node_type.def_readonly_static("Eq", &BooleanFunction::NodeType::Eq);
1762  py_boolean_function_node_type.def_readonly_static("Sle", &BooleanFunction::NodeType::Sle);
1763  py_boolean_function_node_type.def_readonly_static("Slt", &BooleanFunction::NodeType::Slt);
1764  py_boolean_function_node_type.def_readonly_static("Ule", &BooleanFunction::NodeType::Ule);
1765  py_boolean_function_node_type.def_readonly_static("Ult", &BooleanFunction::NodeType::Ult);
1766  py_boolean_function_node_type.def_readonly_static("Ite", &BooleanFunction::NodeType::Ite);
1767 
1768  py_boolean_function_node_type.def_readonly_static("Constant", &BooleanFunction::NodeType::Constant);
1769  py_boolean_function_node_type.def_readonly_static("Index", &BooleanFunction::NodeType::Index);
1770  py_boolean_function_node_type.def_readonly_static("Variable", &BooleanFunction::NodeType::Variable);
1771  }
1772 } // namespace hal
static Result< BooleanFunction > Slt(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
bool has_index_value(u16 index) const
static Result< BooleanFunction > Ite(BooleanFunction &&p0, BooleanFunction &&p1, BooleanFunction &&p2, u16 size)
static Result< BooleanFunction > Eq(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static BooleanFunction Var(const std::string &name, u16 size=1)
static Result< BooleanFunction > Xor(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
const BooleanFunction::Node & get_top_level_node() const
static Result< BooleanFunction > Add(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
std::set< std::string > get_variable_names() const
static Result< BooleanFunction > Lshr(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
bool has_constant_value(const std::vector< Value > &value) const
static Result< BooleanFunction > Zext(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Mul(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
bool has_variable_name(const std::string &variable_name) const
static Result< BooleanFunction > Ule(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Sub(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Sext(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Udiv(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Concat(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Ult(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static BooleanFunction Index(u16 index, u16 size)
static Result< BooleanFunction > Sle(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > from_string(const std::string &expression)
static Result< BooleanFunction > Slice(BooleanFunction &&p0, BooleanFunction &&p1, BooleanFunction &&p2, u16 size)
const std::vector< BooleanFunction::Node > & get_nodes() const
bool is(u16 type) const
BooleanFunction simplify() const
BooleanFunction clone() const
Value
represents the type of the node
static Result< BooleanFunction > Or(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Urem(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Ror(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Sdiv(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static std::string to_string(Value value)
static BooleanFunction Const(const BooleanFunction::Value &value)
static Result< BooleanFunction > Ashr(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< u64 > to_u64(const std::vector< BooleanFunction::Value > &value)
static Result< BooleanFunction > Not(BooleanFunction &&p0, u16 size)
static Result< BooleanFunction > And(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
std::vector< BooleanFunction > get_parameters() const
BooleanFunction substitute(const std::string &old_variable_name, const std::string &new_variable_name) const
static Result< BooleanFunction > Shl(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Rol(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Srem(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
uint16_t u16
Definition: defines.h:40
uint8_t u8
Definition: defines.h:39
void boolean_function_init(py::module &m)
#define log_error(channel,...)
Definition: log.h:78
const Module * module(const Gate *g, const NodeBoxes &boxes)
n
Definition: test.py:6
std::vector< BooleanFunction::Value > constant
The (optional) constant value of the node.
u16 type
The type of the node.
u16 size
The bit-size of the node.
static u16 get_arity_of_type(u16 type)
static Node Constant(const std::vector< BooleanFunction::Value > value)
bool has_index_value(u16 value) const
std::string variable
The (optional) variable name of the node.
bool has_variable_name(const std::string &variable_name) const
static Node Operation(u16 type, u16 size)
bool has_constant_value(const std::vector< Value > &value) const
static Node Index(u16 index, u16 size)
u16 index
The (optional) index value of the node.
static Node Variable(const std::string variable, u16 size)