HAL  v4.5.0-131-gda71a6012
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
netlist_utils.cpp
Go to the documentation of this file.
2 
3 namespace hal
4 {
5  namespace
6  {
9  void warn_deprecated(const std::string& name, const std::string& use_instead)
10  {
11  static std::set<std::string> warned;
12  if (warned.insert(name).second)
13  {
14  log_warning("python_context", "hal_py.NetlistUtils.{} is deprecated and will be removed in a future version, use {} instead.", name, use_instead);
15  }
16  }
17  } // namespace
18 
20  {
21  auto py_netlist_utils = m.def_submodule("NetlistUtils", R"(
22  HAL Netlist Utility functions.
23  )");
24 
25  py_netlist_utils.def(
26  "get_subgraph_function",
27  [](const Net* net, const std::vector<const Gate*>& subgraph_gates) -> BooleanFunction {
28  warn_deprecated("get_subgraph_function", "hal_py.SubgraphNetlistDecorator.get_subgraph_function");
29  auto res = netlist_utils::get_subgraph_function(net, subgraph_gates);
30  if (res.is_ok())
31  {
32  return res.get();
33  }
34  else
35  {
36  log_error("python_context", "error encountered while getting subgraph function:\n{}", res.get_error().get());
37  return BooleanFunction();
38  }
39  },
40  py::arg("net"),
41  py::arg("subgraph_gates"),
42  R"(
43  Get the combined Boolean function of a subgraph of combinational gates starting at the source of the given net.
44  The variables of the resulting Boolean function are made up of the IDs of the nets that influence the output ('net_[ID]').
45 
46  :param hal_py.Net net: The output net for which to generate the Boolean function.
47  :param list[hal_py.Gate] subgraph_gates: The gates making up the subgraph.
48  :returns: The combined Boolean function of the subgraph on success, an empty Boolean function otherwise.
49  :rtype: hal_py.BooleanFunction
50  )");
51 
52  py_netlist_utils.def(
53  "copy_netlist", [](const Netlist* nl) {
54  warn_deprecated("copy_netlist", "hal_py.Netlist.copy"); return std::shared_ptr<Netlist>(netlist_utils::copy_netlist(nl)); }, py::arg("nl"), R"(
55  Get a deep copy of an entire netlist including all of its gates, nets, modules, and groupings.
56 
57  :param hal_py.Netlist nl: The netlist to copy.
58  :returns: The deep copy of the netlist.
59  :rtype: hal_py.Netlist
60  )");
61 
62  py_netlist_utils.def("get_ff_dependency_matrix", [](const Netlist* nl) {
63  warn_deprecated("get_ff_dependency_matrix", "boolean_influence.get_ff_dependency_matrix");
65  }, py::arg("nl"), borrowed(), R"(
66  Get the FF dependency matrix of a netlist.
67 
68  :param hal_py.Netlist nl: The netlist to extract the dependency matrix from.
69  :returns: A pair consisting of a dict from the original gate IDs to the ones in the matrix, and the FF dependency matrix itself.
70  :rtype: tuple(dict[int,hal_py.Gate], list[list[int]])
71  )");
72 
73  py_netlist_utils.def("get_next_gates", [](const Gate* a0, bool a1, int a2, const std::function<bool(const Gate*)>& a3) {
74  warn_deprecated("get_next_gates", "hal_py.NetlistTraversalDecorator.get_next_matching_gates_until_depth");
75  return netlist_utils::get_next_gates(a0, a1, a2, a3);
76  },
77  py::arg("gate"),
78  py::arg("get_successors"),
79  py::arg("depth") = 0,
80  py::arg("filter") = nullptr, borrowed(),
81  R"(
82  Find predecessors or successors of a gate. If depth is set to 1 only direct predecessors/successors will be returned.
83  Higher number of depth causes as many steps of recursive calls.
84  If depth is set to 0 there is no limitation and the loop continues until no more predecessors/succesors are found.
85  If a filter function is given, the recursion stops whenever the filter function evaluates to ``False``.
86  Only gates matching the filter will be added to the result vector.
87  The result will not include the provided gate itself.
88 
89  :param hal_py.Gate gate: The initial gate.
90  :param bool get_successors: ``True`` to return successors, ``False`` for Predecessors.
91  :param int depth: Depth of recursion.
92  :param lambda filter: User-defined filter function.
93  :returns: List of predecessor/successor gates.
94  :rtype: list[hal_py.Gate]
95  )");
96 
97  py_netlist_utils.def("get_next_gates", [](const Net* a0, bool a1, int a2, const std::function<bool(const Gate*)>& a3) {
98  warn_deprecated("get_next_gates", "hal_py.NetlistTraversalDecorator.get_next_matching_gates_until_depth");
99  return netlist_utils::get_next_gates(a0, a1, a2, a3);
100  },
101  py::arg("net"),
102  py::arg("get_successors"),
103  py::arg("depth") = 0,
104  py::arg("filter") = nullptr, borrowed(),
105  R"(
106  Find predecessors or successors of a net. If depth is set to 1 only direct predecessors/successors will be returned.
107  Higher number of depth causes as many steps of recursive calls.
108  If depth is set to 0 there is no limitation and the loop continues until no more predecessors/succesors are found.
109  If a filter function is given, the recursion stops whenever the filter function evaluates to ``False``.
110  Only gates matching the filter will be added to the result vector.
111 
112  :param hal_py.Net net: The initial net.
113  :param bool get_successors: ``True`` to return successors, ``False`` for Predecessors.
114  :param int depth: Depth of recursion.
115  :param lambda filter: User-defined filter function.
116  :returns: List of predecessor/successor gates.
117  :rtype: list[hal_py.Gate]
118  )");
119 
120  py_netlist_utils.def("get_next_sequential_gates", [](const Gate* a0, bool a1, std::unordered_map<u32, std::vector<Gate*>>& a2) {
121  warn_deprecated("get_next_sequential_gates", "hal_py.NetlistTraversalDecorator.get_next_sequential_gates");
122  return netlist_utils::get_next_sequential_gates(a0, a1, a2);
123  },
124  py::arg("gate"),
125  py::arg("get_successors"),
126  py::arg("cache"), borrowed(),
127  R"(
128  Find all sequential predecessors or successors of a gate.
129  Traverses combinational logic of all input or output nets until sequential gates are found.
130  The result may include the provided gate itself.
131  The use of the this cached version is recommended in case of extensive usage to improve performance.
132  The cache will be filled by this function and should initially be provided empty.
133  Different caches for different values of get_successors shall be used.
134 
135  :param hal_py.Gate gate: The initial gate.
136  :param bool get_successors: If ``True``, sequential successors are returned, otherwise sequential predecessors are returned.
137  :param dict[int, list[hal_py.Gate]] cache: The cache.
138  :returns: All sequential successors or predecessors of the gate.
139  :rtype: list[hal_py.Gate]
140  )");
141 
142  py_netlist_utils.def("get_next_sequential_gates", [](const Gate* a0, bool a1) {
143  warn_deprecated("get_next_sequential_gates", "hal_py.NetlistTraversalDecorator.get_next_sequential_gates");
145  }, py::arg("gate"), py::arg("get_successors"), borrowed(), R"(
146  Find all sequential predecessors or successors of a gate.
147  Traverses combinational logic of all input or output nets until sequential gates are found.
148  The result may include the provided gate itself.
149 
150  :param hal_py.Gate gate: The initial gate.
151  :param bool get_successors: If ``True``, sequential successors are returned, otherwise sequential predecessors are returned.
152  :returns: All sequential successors or predecessors of the gate.
153  :rtype: list[hal_py.Gate]
154  )");
155 
156  py_netlist_utils.def("get_next_sequential_gates", [](const Net* a0, bool a1, std::unordered_map<u32, std::vector<Gate*>>& a2) {
157  warn_deprecated("get_next_sequential_gates", "hal_py.NetlistTraversalDecorator.get_next_sequential_gates");
158  return netlist_utils::get_next_sequential_gates(a0, a1, a2);
159  },
160  py::arg("net"),
161  py::arg("get_successors"),
162  py::arg("cache"), borrowed(),
163  R"(
164  Find all sequential predecessors or successors of a net.
165  Traverses combinational logic of all input or output nets until sequential gates are found.
166  The use of the cache is recommended in case of extensive usage of this function.
167  The cache will be filled by this function and should initially be provided empty.
168  Different caches for different values of get_successors shall be used.
169 
170  :param hal_py.Net net: The initial net.
171  :param bool get_successors: If ``True``, sequential successors are returned, otherwise sequential predecessors are returned.
172  :param dict[int, list[hal_py.Gate]] cache: The cache.
173  :returns: All sequential successors or predecessors of the net.
174  :rtype: list[hal_py.Net]
175  )");
176 
177  py_netlist_utils.def("get_next_sequential_gates", [](const Net* a0, bool a1) {
178  warn_deprecated("get_next_sequential_gates", "hal_py.NetlistTraversalDecorator.get_next_sequential_gates");
180  }, py::arg("net"), py::arg("get_successors"), borrowed(), R"(
181  Find all sequential predecessors or successors of a net.
182  Traverses combinational logic of all input or output nets until sequential gates are found.
183 
184  :param hal_py.Net net: The initial net.
185  :param bool get_successors: If ``True``, sequential successors are returned, otherwise sequential predecessors are returned.
186  :returns: All sequential successors or predecessors of the net.
187  :rtype: list[hal_py.Net]
188  )");
189 
190  py_netlist_utils.def("get_path", [](const Gate* a0, bool a1, std::set<GateTypeProperty> a2, std::unordered_map<u32, std::vector<Gate*>>& a3) {
191  warn_deprecated("get_path", "hal_py.NetlistTraversalDecorator.get_gates with the negated condition and TraversalStop.at_mismatch");
192  return netlist_utils::get_path(a0, a1, a2, a3);
193  },
194  py::arg("gate"),
195  py::arg("get_successors"),
196  py::arg("stop_properties"),
197  py::arg("cache"), borrowed(),
198  R"(
199  Find all gates on the predecessor or successor path of a gate.
200  Traverses all input or output nets until gates of the specified base types are found.
201  The result may include the provided gate itself.
202  The use of the this cached version is recommended in case of extensive usage to improve performance.
203  The cache will be filled by this function and should initially be provided empty.
204  Different caches for different values of get_successors shall be used.
205 
206  :param hal_py.Gate gate: The initial gate.
207  :param bool get_successors: If ``True``, the successor path is returned, otherwise the predecessor path is returned.
208  :param set[hal_py.GateTypeProperty] stop_properties: Stop recursion when reaching a gate of a type with one of the specified properties.
209  :param dict[int, list[hal_py.Gate]] cache: The cache.
210  :returns: All gates on the predecessor or successor path of the gate.
211  :rtype: list[hal_py.Gate]
212  )");
213 
214  py_netlist_utils.def(
215  "get_path", [](const Gate* a0, bool a1, std::set<GateTypeProperty> a2) {
216  warn_deprecated("get_path", "hal_py.NetlistTraversalDecorator.get_gates with the negated condition and TraversalStop.at_mismatch");
217  return netlist_utils::get_path(a0, a1, a2);
218  }, py::arg("gate"), py::arg("get_successors"), py::arg("stop_properties"), borrowed(), R"(
219  Find all gates on the predeccessor or successor path of a gate.
220  Traverses all input or output nets until gates of the specified base types are found.
221  The result may include the provided gate itself.
222 
223  :param hal_py.Gate gate: The initial gate.
224  :param bool get_successors: If ``True``, the successor path is returned, otherwise the predecessor path is returned.
225  :param set[hal_py.GateTypeProperty] stop_properties: Stop recursion when reaching a gate of a type with one of the specified properties.
226  :returns: All gates on the predecessor or successor path of the gate.
227  :rtype: list[hal_py.Gate]
228  )");
229 
230  py_netlist_utils.def("get_path", [](const Net* a0, bool a1, std::set<GateTypeProperty> a2, std::unordered_map<u32, std::vector<Gate*>>& a3) {
231  warn_deprecated("get_path", "hal_py.NetlistTraversalDecorator.get_gates with the negated condition and TraversalStop.at_mismatch");
232  return netlist_utils::get_path(a0, a1, a2, a3);
233  },
234  py::arg("net"),
235  py::arg("get_successors"),
236  py::arg("stop_properties"),
237  py::arg("cache"), borrowed(),
238  R"(
239  Find all gates on the predecessor or successor path of a net.
240  Traverses all input or output nets until gates of the specified base types are found.
241  The use of the this cached version is recommended in case of extensive usage to improve performance.
242  The cache will be filled by this function and should initially be provided empty.
243  Different caches for different values of get_successors shall be used.
244 
245  :param hal_py.Net net: The initial net.
246  :param bool get_successors: If ``True``, the successor path is returned, otherwise the predecessor path is returned.
247  :param set[hal_py.GateTypeProperty] stop_properties: Stop recursion when reaching a gate of a type with one of the specified properties.
248  :param dict[int, list[hal_py.Gate]] cache: The cache.
249  :returns: All gates on the predecessor or successor path of the net.
250  :rtype: list[hal_py.Net]
251  )");
252  py_netlist_utils.def(
253  "get_path", [](const Net* a0, bool a1, std::set<GateTypeProperty> a2) {
254  warn_deprecated("get_path", "hal_py.NetlistTraversalDecorator.get_gates with the negated condition and TraversalStop.at_mismatch");
255  return netlist_utils::get_path(a0, a1, a2);
256  }, py::arg("net"), py::arg("get_successors"), py::arg("stop_properties"), borrowed(), R"(
257  Find all gates on the predecessor or successor path of a net.
258  Traverses all input or output nets until gates of the specified base types are found.
259 
260  :param hal_py.Net net: The initial net.
261  :param bool get_successors: If ``True``, the successor path is returned, otherwise the predecessor path is returned.
262  :param set[hal_py.GateTypeProperty] stop_properties: Stop recursion when reaching a gate of a type with one of the specified properties.
263  :returns: All gates on the predecessor or successor path of the net.
264  :rtype: list[hal_py.Net]
265  )");
266 
267  py_netlist_utils.def("get_nets_at_pins", [](Gate* gate, std::vector<GatePin*> pins) {
268  warn_deprecated("get_nets_at_pins", "hal_py.Gate.get_fan_in_net or get_fan_out_net per pin");
270  }, py::arg("gate"), py::arg("pins"), borrowed(), R"(
271  Get the nets that are connected to a subset of pins of the specified gate.
272 
273  :param hal_py.Gate gate: The gate.
274  :param list[hal_py.GatePin] pins: The targeted pins.
275  :returns: A list of nets connected to the pins.
276  :rtype: list[hal_py.Net]
277  )");
278 
279  py_netlist_utils.def(
280  "remove_buffers",
281  [](Netlist* netlist, bool analyze_inputs = false) -> i32 {
282  warn_deprecated("remove_buffers", "netlist_preprocessing.remove_buffers");
283  auto res = netlist_utils::remove_buffers(netlist, analyze_inputs);
284  if (res.is_ok())
285  {
286  return (i32)res.get();
287  }
288  else
289  {
290  log_error("python_context", "error encountered while removing buffer gates from netlist:\n{}", res.get_error().get());
291  return -1;
292  }
293  },
294  py::arg("netlist"),
295  py::arg("analyze_inputs") = false,
296  R"(
297  Remove all buffer gates from the netlist and connect their fan-in to their fan-out nets.
298  If enabled, analyzes every gate's inputs and removes fixed '0' or '1' inputs from the Boolean function.
299 
300  :param hal_py.Netlist netlist: The target netlist.
301  :param bool analyze_inputs: Set ``True`` to dynamically analyze the inputs, ``False`` otherwise.
302  :returns: The number of removed buffers on success, -1 otherwise.
303  :rtype: int
304  )");
305 
306  py_netlist_utils.def(
307  "remove_unused_lut_endpoints",
308  [](Netlist* netlist) -> i32 {
309  warn_deprecated("remove_unused_lut_endpoints", "netlist_preprocessing.remove_unused_lut_inputs");
310  auto res = netlist_utils::remove_unused_lut_endpoints(netlist);
311  if (res.is_ok())
312  {
313  return (i32)res.get();
314  }
315  else
316  {
317  log_error("python_context", "error encountered while removing unused LUT endpoints from netlist:\n{}", res.get_error().get());
318  return -1;
319  }
320  },
321  py::arg("netlist"),
322  R"(
323  Remove all LUT fan-in endpoints that are not present within the Boolean function of the output of a gate.
324 
325  :param hal_py.Netlist netlist: The target netlist.
326  :returns: The number of removed endpionts on success, -1 otherwise.
327  :rtype: int
328  )");
329 
330  py_netlist_utils.def("get_common_inputs", [](const std::vector<Gate*>& gates, u32 threshold) {
331  warn_deprecated("get_common_inputs", "hal_py.NetlistTraversalDecorator.get_common_inputs");
332  return netlist_utils::get_common_inputs(gates, threshold);
333  }, py::arg("gates"), py::arg("threshold") = 0, borrowed(), R"(
334  Returns all nets that are considered to be common inputs to the provided gates.
335  A threshold value can be provided to specify the number of gates a net must be connected to in order to be classified as a common input.
336  If the theshold value is set to 0, a net must be input to all gates to be considered a common input.
337 
338  :param list[hal_py.Gate] gates: The gates.
339  :param int threshold: The threshold value, defaults to 0.
340  :returns: The common input nets.
341  :rtype: list[hal_py.Net]
342  )");
343 
344  py_netlist_utils.def(
345  "replace_gate",
346  [](Gate* gate, GateType* target_type, std::map<GatePin*, GatePin*> pin_map) -> i32 {
347  warn_deprecated("replace_gate", "hal_py.NetlistModificationDecorator.replace_gate");
348  auto res = netlist_utils::replace_gate(gate, target_type, pin_map);
349  if (res.is_ok())
350  {
351  return true;
352  }
353  else
354  {
355  log_error("python_context", "error encountered while replacing gate:\n{}", res.get_error().get());
356  return false;
357  }
358  },
359  py::arg("gate"),
360  py::arg("target_type"),
361  py::arg("pin_map"),
362  R"(
363  Replace the given gate with a gate of the specified gate type.
364  A dict from old to new pins must be provided in order to correctly connect the gates inputs and outputs.
365  A pin can be omitted if no connection at that pin is desired.
366 
367  :param hal_py.Gate gate: The gate to be replaced.
368  :param hal_py.GateType target_type: The gate type of the replacement gate.
369  :param dict[hal_py.GatePin,hal_py.GatePin] pin_map: A dict from old to new pins.
370  :returns: ``True`` on success, ``False`` otherwise.
371  :rtype: bool
372  )");
373 
374 
375 
376 
377 
378  py_netlist_utils.def("get_shortest_path", [](Gate* a0, Gate* a1, bool a2) {
379  warn_deprecated("get_shortest_path", "hal_py.NetlistTraversalDecorator.get_shortest_path");
380  return netlist_utils::get_shortest_path(a0, a1, a2);
381  }, py::arg("start_gate"), py::arg("end_gate"), py::arg("search_both_directions") = false, borrowed(), R"(
382  Find the shortest path (i.e., the result set with the lowest number of gates) that connects the start gate with the end gate.
383  The gate where the search started from will be the first in the result vector, the end gate will be the last.
384  If there is no such path an empty vector is returned. If there is more than one path with the same length only the first one is returned.
385 
386  :param hal_py.Gate start_gate: The gate to start from.
387  :param hal_py.Gate end_gate: The gate to connect to.
388  :param bool search_both_directions: ``True`` to additionally check whether a shorter path from end to start exists, ``False`` otherwise.
389  :returns: A list of gates that connect the start with end gate (possibly in reverse order).
390  :rtype: list[hal_py.Gate]
391  )");
392 
393  py_netlist_utils.def("get_shortest_path", [](Gate* a0, Module* a1, bool a2) {
394  warn_deprecated("get_shortest_path", "hal_py.NetlistTraversalDecorator.get_shortest_path");
395  return netlist_utils::get_shortest_path(a0, a1, a2);
396  }, py::arg("start_gate"), py::arg("end_module"), py::arg("forward_direction"), borrowed(), R"(
397  Find the shortest path (i.e., the result set with the lowest number of gates) that connects the start gate with any gate from the given module.
398  The gate where the search started from will be the first in the result vector, the end gate will be the last.
399  If there is no such path an empty vector is returned. If there is more than one path with the same length only the first one is returned.
400 
401  :param hal_py.Gate start_gate: The gate to start from.
402  :param hal_py.Module end_module: The module to connect to.
403  :param bool forward_direction: ``True`` to search along the fan-out nets of the start gate, ``False`` to search along its fan-in nets.
404  :returns: A list of gates that connect the start with end gate (possibly in reverse order).
405  :rtype: list[hal_py.Gate]
406  )");
407 
408  py_netlist_utils.def("get_shortest_path", [](Module* a0, Module* a1) {
409  warn_deprecated("get_shortest_path", "hal_py.NetlistTraversalDecorator.get_shortest_path");
410  return netlist_utils::get_shortest_path(a0, a1);
411  }, py::arg("start_module"), py::arg("end_module"), borrowed(), R"(
412  Find the shortest path (i.e., the result set with the lowest number of gates) that connects the start module with the target module.
413  There might be more than one connection thus a list of connecting gate lists is returned.
414 
415  :param hal_py.Module start_module: The module to start from.
416  :param hal_py.Module end_module: The module to connect to.
417  :returns: A list of connecting lists with gates that connect the start with end gate.
418  :rtype: list[list[hal_py.Gate]]
419  )");
420  }
421 } // namespace hal
Definition: gate.h:58
Definition: net.h:58
uint32_t u32
Definition: defines.h:41
int32_t i32
Definition: defines.h:36
void netlist_utils_init(py::module &m)
#define log_error(channel,...)
Definition: log.h:78
#define log_warning(channel,...)
Definition: log.h:76
const Module * module(const Gate *g, const NodeBoxes &boxes)
Result< u32 > remove_unused_lut_endpoints(Netlist *netlist)
std::vector< Gate * > get_path(const Gate *gate, bool get_successors, std::set< GateTypeProperty > stop_properties, std::unordered_map< u32, std::vector< Gate * >> &cache)
std::vector< Gate * > get_next_gates(const Gate *gate, bool get_successors, int depth=0, const std::function< bool(const Gate *)> &filter=nullptr)
Result< BooleanFunction > get_subgraph_function(const Net *net, const std::vector< const Gate * > &subgraph_gates, std::map< std::pair< u32, const GatePin * >, BooleanFunction > &cache)
Result< u32 > remove_buffers(Netlist *netlist, bool analyze_inputs=false)
std::unique_ptr< Netlist > copy_netlist(const Netlist *nl)
std::vector< Gate * > get_next_sequential_gates(const Gate *gate, bool get_successors, std::unordered_map< u32, std::vector< Gate * >> &cache)
std::vector< Gate * > get_shortest_path(Gate *start_gate, Gate *end_gate, bool search_both_directions=false)
Result< std::monostate > replace_gate(Gate *gate, GateType *target_type, std::map< GatePin *, GatePin * > pin_map)
std::vector< Net * > get_nets_at_pins(Gate *gate, std::vector< GatePin * > pins)
std::vector< Net * > get_common_inputs(const std::vector< Gate * > &gates, u32 threshold=0)
std::pair< std::map< u32, Gate * >, std::vector< std::vector< int > > > get_ff_dependency_matrix(const Netlist *nl)
Definition: defines.h:45
std::vector< PinInformation > pins
Net * net
std::string name