5 #include "pybind11/operators.h"
6 #include "pybind11/pybind11.h"
7 #include "pybind11/stl.h"
8 #include "pybind11/stl_bind.h"
18 #ifdef PYBIND11_MODULE
19 PYBIND11_MODULE(netlist_preprocessing, m)
21 m.doc() =
"hal NetlistPreprocessingPlugin python bindings";
25 py::module m(
"netlist_preprocessing",
"hal NetlistPreprocessingPlugin python bindings");
28 py::class_<NetlistPreprocessingPlugin, RawPtrWrapper<NetlistPreprocessingPlugin>,
BasePluginInterface> py_netlist_preprocessing(m,
"NetlistPreprocessingPlugin");
30 The name of the plugin.
36 Get the name of the plugin.
38 :returns: Plugin name.
43 The version of the plugin.
49 Get the version of the plugin.
51 :returns: Plugin version.
56 The description of the plugin.
62 Get the description of the plugin.
64 :returns: The description of the plugin.
69 A set of plugin names that this plugin depends on.
75 Get a set of plugin names that this plugin depends on.
77 :returns: A set of plugin names that this plugin depends on.
82 "remove_unused_lut_inputs",
83 [](
Netlist* nl,
const std::vector<Gate*>& gates) -> std::optional<u32> {
91 log_error(
"python_context",
"{}", res.get_error().get());
96 py::arg(
"gates") = std::vector<Gate*>(),
98 Removes all LUT fan-in endpoints that do not correspond to a variable within the Boolean function that determines the output of a gate.
100 :param hal_py.Netlist nl: The netlist to operate on.
101 :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.
102 :returns: The number of removed LUT endpoints on success, ``None`` otherwise.
103 :rtype: int or ``None``
108 [](
Netlist* nl,
const std::vector<Gate*>& gates) -> std::optional<u32> {
116 log_error(
"python_context",
"{}", res.get_error().get());
121 py::arg(
"gates") = std::vector<Gate*>(),
123 Removes buffer gates from the netlist and connect their fan-in to their fan-out nets.
124 Considers all combinational gates and takes their inputs into account.
125 For example, a 2-input AND gate with one input being connected to constant ``1`` will also be removed.
127 :param hal_py.Netlist nl: The netlist to operate on.
128 :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.
129 :returns: The number of removed buffers on success, ``None`` otherwise.
130 :rtype: int or ``None``
134 "remove_redundant_gates",
135 [](
Netlist* nl,
const std::function<
bool(
const Gate*)>& filter =
nullptr,
const std::vector<Gate*>& gates = {}) -> std::optional<u32> {
143 log_error(
"python_context",
"{}", res.get_error().get());
148 py::arg(
"filter") =
nullptr,
149 py::arg(
"gates") = std::vector<Gate*>(),
151 Removes redundant gates from the netlist, i.e., gates that are functionally equivalent and are connected to the same input nets.
152 Only gates contained in ``gates`` are removed, the equivalent gate that is kept in their stead may lie outside of ``gates``.
154 :param hal_py.Netlist nl: The netlist to operate on.
155 :param lambda filter: Optional filter to fine-tune which gates are being replaced. Default to a ``None``.
156 :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.
157 :returns: The number of removed gates on success, ``None`` otherwise.
158 :rtype: int or ``None``
162 "remove_redundant_loops",
163 [](
Netlist* nl) -> std::optional<u32> {
171 log_error(
"python_context",
"{}", res.get_error().get());
177 Removes redundant sequential feedback loops.
178 Sometimes flip-flops and some of their combinational fan-in form a feedback loop where the flip-flop input depends on its own output.
179 For optimization, some synthesizers create multiple equivalent instances of these feedback loops.
180 To simplify structural analysis, this function removes the redundant flip-flop gate of the loop from the netlist.
181 Other preprocessing functions can then take care of the remaining combination gates of the loop.
183 :param hal_py.Netlist nl: The netlist to operate on.
184 :returns: The number of removed gates on success, ``None`` otherwise.
185 :rtype: int or ``None``
189 "remove_redundant_logic_trees",
190 [](
Netlist* nl) -> std::optional<u32> {
198 log_error(
"python_context",
"{}", res.get_error().get());
204 Removes redundant logic trees made up of combinational gates.
205 If two trees compute the exact same function even if implemented with different gates we will disconnect one of the trees and afterwards clean up all dangling gates and nets.
207 :param hal_py.Netlist nl: The netlist to operate on.
208 :returns: The number of removed gates on success, ``None`` otherwise.
209 :rtype: int or ``None``
213 "remove_unconnected_gates",
214 [](
Netlist* nl,
const std::vector<Gate*>& gates) -> std::optional<u32> {
222 log_error(
"python_context",
"{}", res.get_error().get());
227 py::arg(
"gates") = std::vector<Gate*>(),
229 Removes gates for which all fan-out nets do not have a destination and are not global output nets.
230 The removal is repeated until no further gates can be removed, but gates outside of ``gates`` are never removed, even if they become unconnected in the process.
232 :param hal_py.Netlist nl: The netlist to operate on.
233 :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.
234 :returns: The number of removed gates on success, ``None`` otherwise.
235 :rtype: int or ``None``
239 "remove_unconnected_nets",
240 [](
Netlist* nl) -> std::optional<u32> {
248 log_error(
"python_context",
"{}", res.get_error().get());
254 Removes nets who have neither a source, nor a destination.
256 :param hal_py.Netlist nl: The netlist to operate on.
257 :returns: The number of removed nets on success, ``None`` otherwise.
258 :rtype: int or ``None``
262 "remove_unconnected_looped",
263 [](
Netlist* nl) -> std::optional<u32> {
271 log_error(
"python_context",
"{}", res.get_error().get());
277 Calls remove_unconnected_gates / remove_unconnected_nets until there are no further changes.
279 :param hal_py.Netlist nl: The netlist to operate on.
280 :returns: The number of removed nets and gates on success, ``None`` otherwise.
281 :rtype: int or ``None``
285 "manual_mux_optimizations",
294 log_error(
"python_context",
"{}", res.get_error().get());
299 py::arg(
"mux_inv_gl"),
301 Apply manually implemented optimizations to the netlist centered around muxes.
302 Currently implemented optimizations include:
304 - removing inverters in case there are inverter gates in front of and behind every data input and output of the mux
305 - optimizing and therefore unifying possible inverters preceding the select signals by resynthesizing
307 :param hal_py.Netlist nl: The netlist to operate on.
308 :param hal_py.GateLibrary mux_inv_gl: A gate library only containing mux and inverter gates used for resynthesis.
309 :returns: The difference in the total number of gates caused by these optimizations.
310 :rtype: int or ``None``
314 "propagate_constants",
315 [](
Netlist* nl,
const std::vector<Gate*>& gates) -> std::optional<u32> {
323 log_error(
"python_context",
"{}", res.get_error().get());
328 py::arg(
"gates") = std::vector<Gate*>(),
330 Builds for all gate output nets the Boolean function and substitutes all variables connected to vcc/gnd nets with the respective boolean value.
331 If the function simplifies to a static boolean constant cut the connection to the nets destinations and directly connect it to vcc/gnd.
332 The propagation is repeated until no further gates can be substituted, but gates outside of ``gates`` are never substituted, even if they become constant in the process.
334 :param hal_py.Netlist nl: The netlist to operate on.
335 :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.
336 :returns: The number of rerouted nets on success, ``None`` otherwise.
337 :rtype: int or ``None``
341 "remove_consecutive_inverters",
342 [](
Netlist* nl,
const std::vector<Gate*>& gates) -> std::optional<u32> {
350 log_error(
"python_context",
"{}", res.get_error().get());
355 py::arg(
"gates") = std::vector<Gate*>(),
357 Removes two consecutive inverters and reconnects the input of the first inverter to the output of the second one.
358 If the first inverter has additional successors, only the second inverter is deleted.
359 Both inverters must be contained in ``gates`` for the pair to be considered, even if only the second one ends up being deleted.
361 :param hal_py.Netlist nl: The netlist to operate on.
362 :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.
363 :returns: The number of removed inverter gates on success, ``None`` otherwise.
364 :rtype: int or ``None``
368 "simplify_lut_inits",
369 [](
Netlist* nl,
const std::vector<Gate*>& gates) -> std::optional<u32> {
377 log_error(
"python_context",
"{}", res.get_error().get());
382 py::arg(
"gates") = std::vector<Gate*>(),
384 Replaces pins connected to GND/VCC with constants and simplifies the boolean function of a LUT by recomputing the INIT string.
386 :param hal_py.Netlist nl: The netlist to operate on.
387 :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.
388 :returns: The number of simplified INIT strings on success, ``None`` otherwise.
389 :rtype: int or ``None``
393 "reconstruct_indexed_ff_identifiers",
394 [](
Netlist* nl) -> std::optional<u32> {
402 log_error(
"python_context",
"{}", res.get_error().get());
408 Tries to reconstruct a name and index for each flip flop that was part of a multi-bit wire in the verilog code.
409 This is NOT a general netlist reverse engineering algorithm and ONLY works on synthesized netlists with names annotated by the synthesizer.
410 This function mainly focuses netlists synthesized with yosys since yosys names the output wires of the flip flops but not the gate it self.
411 We try to reconstruct name and index for each flip flop based on the name of its output nets.
413 :param hal_py.Netlist nl: The netlist to operate on.
414 :returns: The number of reconstructed names on success, ``None`` otherwise.
415 :rtype: int or ``None``
419 "reconstruct_top_module_pin_groups",
420 [](
Netlist* nl) -> std::optional<u32> {
428 log_error(
"python_context",
"{}", res.get_error().get());
434 Tries to reconstruct top module pin groups via indexed pin names.
436 :param hal_py.Netlist nl: The netlist to operate on.
437 :returns: The number of reconstructed pin groups on success, ``None`` otherwise.
438 :rtype: int or ``None``
443 [](
Netlist* nl,
const std::filesystem::path& def_file) ->
bool {
451 log_error(
"python_context",
"{}", res.get_error().get());
458 Parses a design exchange format file and extracts the coordinates of a placed design for each component/gate.
459 The extracted coordinates get annotated to the gates.
461 :param hal_py.Netlist nl: The netlist to operate on.
462 :param pathlib.Path def_file: The path to the def file
463 :returns: ``True`` on success, ``False`` otherwise.
468 "create_multi_bit_gate_modules",
469 [](
Netlist* nl,
const std::map<std::string, std::map<std::string, std::vector<std::string>>>& concatenated_pin_groups) -> std::vector<Module*> {
477 log_error(
"python_context",
"{}", res.get_error().get());
482 py::arg(
"concatenated_pin_groups"),
485 Create modules from large gates like RAMs and DSPs with the option to concatenate multiple gate pin groups into larger consecutive pin groups.
487 :param hal_py.Netlist nl: The netlist to operate on.
488 :param dict[str,dict[str,list[str]]] concatenated_pin_groups: A dict from gate type name to a dict from the name of the resulting pin group to the names of the pin groups it is concatenated from.
489 :returns: The created modules on success, an empty list otherwise.
490 :rtype: list[hal_py.Module]
494 "create_nets_at_unconnected_pins",
495 [](
Netlist* nl,
const std::vector<Gate*>& gates) -> std::vector<Net*> {
503 log_error(
"python_context",
"{}", res.get_error().get());
508 py::arg(
"gates") = std::vector<Gate*>(),
511 Create a new net for every unconnected output pin of every gate of the netlist.
512 The new nets are named ``HAL_UNCONNECTED_<net_id>``.
514 :param hal_py.Netlist nl: The netlist to operate on.
515 :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.
516 :returns: The created nets on success, an empty list otherwise.
517 :rtype: list[hal_py.Net]
522 [](
Netlist* nl,
const std::vector<Gate*>& ffs = {},
GateType* inverter_type =
nullptr) -> std::optional<u32> {
530 log_error(
"python_context",
"{}", res.get_error().get());
535 py::arg(
"ffs") = std::vector<Gate*>(),
536 py::arg(
"inverter_type") =
nullptr,
538 Iterates all flip-flops of the netlist or specified by the user.
539 If a flip-flop has a ``state`` and a ``neg_state`` output, a new inverter gate is created and connected to the ``state`` output net as an additional destination.
540 Finally, the ``neg_state`` output net is disconnected from the ``neg_state`` pin and re-connected to the new inverter gate's output.
541 The new inverter gate is assigned to the module of the respective flip-flop.
543 :param hal_py.Netlist nl: The netlist to operate on.
544 :param list[hal_py.Gate] ffs: The flip-flops to operate on. Defaults to an empty vector, in which case all flip-flops of the netlist are considered.
545 :param hal_py.GateType inverter_type: The inverter gate type to use. Defaults to a ``None``, in which case the first inverter type found in the gate library is used.
546 :returns: The number of rerouted ``neg_state`` outputs on success, ``None`` otherwise.
547 :rtype: int or ``None``
550 #ifndef PYBIND11_MODULE
std::string get_name() const override
Get the name of the plugin.
std::string get_description() const override
Get a short description of the plugin.
std::string get_version() const override
Get the version of the plugin.
std::set< std::string > get_dependencies() const override
Get the plugin dependencies.
#define log_error(channel,...)
const Module * module(const Gate *g, const NodeBoxes &boxes)
Result< std::monostate > parse_def_file(Netlist *nl, const std::filesystem::path &def_file)
Result< u32 > manual_mux_optimizations(Netlist *nl, GateLibrary *mux_inv_gl)
Result< u32 > propagate_constants(Netlist *nl, const std::vector< Gate * > &gates={})
Result< std::vector< Net * > > create_nets_at_unconnected_pins(Netlist *nl, const std::vector< Gate * > &gates={})
Result< u32 > remove_unconnected_gates(Netlist *nl, const std::vector< Gate * > &gates={})
Result< u32 > remove_redundant_loops(Netlist *nl)
Result< u32 > remove_redundant_logic_trees(Netlist *nl)
Result< u32 > remove_redundant_gates(Netlist *nl, const std::function< bool(const Gate *)> &filter=nullptr, const std::vector< Gate * > &gates={})
Result< u32 > reconstruct_top_module_pin_groups(Netlist *nl)
Result< u32 > simplify_lut_inits(Netlist *nl, const std::vector< Gate * > &gates={})
Result< u32 > remove_buffers(Netlist *nl, const std::vector< Gate * > &gates={})
Result< u32 > remove_unused_lut_inputs(Netlist *nl, const std::vector< Gate * > &gates={})
Result< u32 > remove_unconnected_looped(Netlist *nl)
Result< u32 > remove_unconnected_nets(Netlist *nl)
Result< u32 > reconstruct_indexed_ff_identifiers(Netlist *nl)
Result< u32 > remove_consecutive_inverters(Netlist *nl, const std::vector< Gate * > &gates={})
Result< std::vector< Module * > > create_multi_bit_gate_modules(Netlist *nl, const std::map< std::string, std::map< std::string, std::vector< std::string >>> &concatenated_pin_groups)
Result< u32 > unify_ff_outputs(Netlist *nl, const std::vector< Gate * > &ffs={}, GateType *inverter_type=nullptr)
This file contains all functions related to the HAL plugin API.