HAL  v4.5.0-133-g64838ea8d
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 
3 #include "pybind11/operators.h"
4 #include "pybind11/pybind11.h"
5 #include "pybind11/stl.h"
6 #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(xilinx_toolbox, m)
20  {
21  m.doc() = "A collection of functions specifically designed to operate on Xilinx FPGA netlists.";
22 #else
23  PYBIND11_PLUGIN(xilinx_toolbox)
24  {
25  py::module m("xilinx_toolbox", "A collection of functions specifically designed to operate on Xilinx FPGA netlists.");
26 #endif // ifdef PYBIND11_MODULE
27 
28  py::class_<XilinxToolboxPlugin, RawPtrWrapper<XilinxToolboxPlugin>, BasePluginInterface> py_xilinx_toolbox_plugin(
29  m, "XilinxToolboxPlugin", R"(This class provides an interface to integrate the Xilinx toolbox as a plugin within the HAL framework.)");
30 
31  py_xilinx_toolbox_plugin.def_property_readonly("name", &XilinxToolboxPlugin::get_name, R"(
32  The name of the plugin.
33 
34  :type: str
35  )");
36 
37  py_xilinx_toolbox_plugin.def("get_name", &XilinxToolboxPlugin::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_xilinx_toolbox_plugin.def_property_readonly("version", &XilinxToolboxPlugin::get_version, R"(
45  The version of the plugin.
46 
47  :type: str
48  )");
49 
50  py_xilinx_toolbox_plugin.def("get_version", &XilinxToolboxPlugin::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_xilinx_toolbox_plugin.def_property_readonly("description", &XilinxToolboxPlugin::get_description, R"(
58  The description of the plugin.
59 
60  :type: str
61  )");
62 
63  py_xilinx_toolbox_plugin.def("get_description", &XilinxToolboxPlugin::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_xilinx_toolbox_plugin.def_property_readonly("dependencies", &XilinxToolboxPlugin::get_dependencies, R"(
71  A set of plugin names that this plugin depends on.
72 
73  :type: set[str]
74  )");
75 
76  py_xilinx_toolbox_plugin.def("get_dependencies", &XilinxToolboxPlugin::get_dependencies, R"(
77  Get a set of plugin names that this plugin depends on.
78 
79  :returns: A set of plugin names that this plugin depends on.
80  :rtype: set[str]
81  )");
82 
83  m.def(
84  "split_luts",
85  [](Netlist* nl, const std::vector<Gate*>& gates) -> std::optional<u32> {
86  auto res = xilinx_toolbox::split_luts(nl, gates);
87  if (res.is_ok())
88  {
89  return res.get();
90  }
91  else
92  {
93  log_error("python_context", "{}", res.get_error().get());
94  return std::nullopt;
95  }
96  },
97  py::arg("nl"),
98  py::arg("gates") = std::vector<Gate*>(),
99  R"(
100  Split LUTs with two outputs into two separate LUT gates.
101  Replaces ``LUT6_2`` with a ``LUT6`` and a ``LUT5`` gate if the respective outputs of the ``LUT6_2`` are actually used, i.e., connected to other gates.
102 
103  :param hal_py.Netlist nl: The netlist to operate on.
104  :param list[hal_py.Gate] gates: The gates to consider. Defaults to an empty list, in which case all gates of the netlist are considered.
105  :returns: The number of split ``LUT6_2`` gates on success, ``None`` otherwise.
106  :rtype: int or None
107  )");
108 
109  m.def(
110  "split_shift_registers",
111  [](Netlist* nl, const std::vector<Gate*>& gates) -> std::optional<u32> {
112  auto res = xilinx_toolbox::split_shift_registers(nl, gates);
113  if (res.is_ok())
114  {
115  return res.get();
116  }
117  else
118  {
119  log_error("python_context", "{}", res.get_error().get());
120  return std::nullopt;
121  }
122  },
123  py::arg("nl"),
124  py::arg("gates") = std::vector<Gate*>(),
125  R"(
126  Split shift register primitives and replaces them with equivalent flip-flops chains.
127  Currently only implemented for gate types ``SRL16E`` and ``SRLC32E``.
128  The created flip-flops are assigned to the module of the shift register gate that they replace.
129 
130  :param hal_py.Netlist nl: The netlist to operate on.
131  :param list[hal_py.Gate] gates: The gates to consider. Defaults to an empty list, in which case all gates of the netlist are considered.
132  :returns: The number of split shift registers on success, ``None`` otherwise.
133  :rtype: int or None
134  )");
135 
136  m.def(
137  "remove_no_load_wires",
138  [](Netlist* nl, const std::vector<Net*>& nets) -> std::optional<u32> {
139  auto res = xilinx_toolbox::remove_no_load_wires(nl, nets);
140  if (res.is_ok())
141  {
142  return res.get();
143  }
144  else
145  {
146  log_error("python_context", "{}", res.get_error().get());
147  return std::nullopt;
148  }
149  },
150  py::arg("nl"),
151  py::arg("nets") = std::vector<Net*>(),
152  R"(
153  Remove the "no load wire" nets that Vivado writes for unused output pins.
154  Vivado names such nets ``NLW_<instance>_<pin>_UNCONNECTED`` and only connects them to the output pin they stand in for.
155  A net is removed if its name starts with ``NLW_`` (or has ``NLW_`` right after a ``/`` in a flattened path) and ends with ``_UNCONNECTED``, optionally followed by a bit index such as ``(2)`` or ``[2]``, it has no destinations, and it is not a global output.
156  The output pins that drove the removed nets are left unconnected.
157 
158  :param hal_py.Netlist nl: The netlist to operate on.
159  :param list[hal_py.Net] nets: The nets to consider. Defaults to an empty list, in which case all nets of the netlist are considered.
160  :returns: The number of removed nets on success, ``None`` otherwise.
161  :rtype: int or None
162  )");
163 
164  m.def(
165  "parse_xdc_file",
166  [](Netlist* nl, const std::filesystem::path& xdc_file) -> bool {
167  auto res = xilinx_toolbox::parse_xdc_file(nl, xdc_file);
168  if (res.is_ok())
169  {
170  return true;
171  }
172  else
173  {
174  log_error("python_context", "{}", res.get_error().get());
175  return false;
176  }
177  },
178  py::arg("nl"),
179  py::arg("xdc_file"),
180  R"(
181  Parse an ``.xdc`` file and extract the position LOC and BEL data of each gate.
182  Translates the coordinates extracted from the ``.xdc`` file into integer values.
183 
184  :param hal_py.Netlist nl: The netlist to operate on.
185  :param path xdc_file: The path to the ``.xdc`` file.
186  :returns: ``True`` on success, ``False`` otherwise.
187  :rtype: bool
188  )");
189 
190 #ifndef PYBIND11_MODULE
191  return m.ptr();
192 #endif // PYBIND11_MODULE
193  }
194 } // namespace hal
std::string get_name() const override
Get the name of the plugin.
std::string get_version() const override
Get the version of the plugin.
std::set< std::string > get_dependencies() const override
Get the plugin dependencies.
std::string get_description() const override
Get a short description of the plugin.
#define log_error(channel,...)
Definition: log.h:78
const Module * module(const Gate *g, const NodeBoxes &boxes)
Result< u32 > remove_no_load_wires(Netlist *nl, const std::vector< Net * > &nets={})
Remove the "no load wire" nets that Vivado writes for unused output pins.
Result< std::monostate > parse_xdc_file(Netlist *nl, const std::filesystem::path &xdc_file)
Parse an .xdc file and extract the position LOC and BEL data of each gate.
Definition: xdc_parser.cpp:220
Result< u32 > split_luts(Netlist *nl, const std::vector< Gate * > &gates={})
Split LUTs with two outputs into two separate LUT gates.
Result< u32 > split_shift_registers(Netlist *nl, const std::vector< Gate * > &gates={})
Split shift register primitives and replaces them with equivalent flip-flops chains.
Definition: defines.h:45
PYBIND11_PLUGIN(hal_py)
This file contains all functions related to the HAL plugin API.
This file contains functions specifically designed to preprocess Xilinx FPGA netlists.