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