HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
utils.cpp
Go to the documentation of this file.
1 // #include "module_identification/utils.h"
11 #include "hal_core/netlist/net.h"
14 #include "hal_core/utilities/log.h"
15 
16 #include <algorithm>
17 #include <numeric>
18 #include <sstream>
19 #include <stdlib.h>
20 
21 namespace hal
22 {
23  namespace module_identification
24  {
25  std::vector<Net*> get_input_nets(const std::vector<Gate*>& gates)
26  {
27  std::set<Net*> in_nets;
28  for (Gate* g : gates)
29  {
30  // input nets: if predecessor is not in passed gates, it's an input net
31  for (Net* n : g->get_fan_in_nets())
32  {
33  if (!(n->is_gnd_net()) && !(n->is_vcc_net()))
34  {
35  if (n->is_global_input_net())
36  {
37  in_nets.insert(n);
38  }
39  else
40  {
41  if (n->get_num_of_sources() > 1)
42  {
43  log_error("module_identification", "Found multi driven net {} with ID {}! This is not handled yet!", n->get_name(), n->get_id());
44  continue;
45  }
46 
47  for (Endpoint* s : n->get_sources())
48  {
49  if (std::find(gates.begin(), gates.end(), s->get_gate()) == gates.end())
50  {
51  in_nets.insert(n);
52  }
53  }
54  }
55  }
56  }
57  }
58  return {in_nets.begin(), in_nets.end()};
59  }
60 
61  std::vector<Net*> get_output_nets(const std::vector<Gate*>& gates, bool only_external_destinations)
62  {
63  std::set<Net*> out_nets;
64  for (Gate* g : gates)
65  {
66  // output nets: if successor is not in passed gates, it's an output net
67  for (Net* n : g->get_fan_out_nets())
68  {
69  if (n->is_global_output_net())
70  {
71  out_nets.insert(n);
72  }
73  else
74  {
75  bool is_output_net;
76  // for this variant we consider a net only an output net if it has ONLY destinations outside the subgraph
77  if (only_external_destinations)
78  {
79  is_output_net = !n->get_destinations().empty();
80  for (Endpoint* d : n->get_destinations())
81  {
82  if (std::find(gates.begin(), gates.end(), d->get_gate()) != gates.end())
83  {
84  is_output_net = false;
85  break;
86  }
87  }
88  }
89  // for this variant we consider a net an output net if it has ANY destination outside the subgraph
90  else
91  {
92  is_output_net = false;
93  for (Endpoint* d : n->get_destinations())
94  {
95  if (std::find(gates.begin(), gates.end(), d->get_gate()) == gates.end())
96  {
97  is_output_net = true;
98  break;
99  }
100  }
101  }
102 
103  if (is_output_net)
104  {
105  out_nets.insert(n);
106  }
107  }
108  }
109  }
110  return {out_nets.begin(), out_nets.end()};
111  }
112 
113  std::set<u32> find_neighboring_registers(const Net* n, const std::vector<std::vector<Gate*>>& registers)
114  {
115  std::set<u32> reg_indices;
116 
117  // std::unordered_map<const Net*, std::unordered_set<Gate*>> cache;
118  const auto seq_inputs_res =
119  NetlistTraversalDecorator(*(n->get_netlist())).get_next_matching_gates(/* cache ,*/ n, false, [](const auto& g) { return g->get_type()->has_property(GateTypeProperty::sequential); });
120  if (seq_inputs_res.is_error())
121  {
122  log_error("module_identification", "{}", seq_inputs_res.get_error().get());
123  }
124  const auto seq_inputs = seq_inputs_res.get();
125 
126  for (const auto& si : seq_inputs)
127  {
128  for (u32 reg_idx = 0; reg_idx < registers.size(); reg_idx++)
129  {
130  const auto& reg = registers.at(reg_idx);
131  if (std::find(reg.begin(), reg.end(), si) != reg.end())
132  {
133  reg_indices.insert(reg_idx);
134  break;
135  }
136  }
137  }
138 
139  return reg_indices;
140  }
141 
142  std::set<u32> find_neighboring_registers(const std::vector<Net*> nets, const std::vector<std::vector<Gate*>>& registers)
143  {
144  std::set<u32> reg_indices;
145 
146  for (const auto& n : nets)
147  {
148  const auto neighbors = find_neighboring_registers(n, registers);
149  reg_indices.insert(neighbors.begin(), neighbors.end());
150  }
151 
152  return reg_indices;
153  }
154 
155  namespace
156  {
157  std::vector<std::vector<u32>> permutations(const std::vector<u32>& initial)
158  {
159  std::vector<u32> p = initial;
160  std::vector<std::vector<u32>> result;
161 
162  std::sort(p.begin(), p.end());
163 
164  do
165  {
166  result.push_back({p.begin(), p.end()});
167  } while (std::next_permutation(p.begin(), p.end()));
168 
169  return result;
170  }
171 
172  u32 calculate_permuation_score(const std::vector<u32>& permutation, const std::vector<std::set<u32>>& neighboring_regs, const std::vector<std::set<u32>>& new_neighboring_regs)
173  {
174  u32 overlap = 0;
175  u32 non_over_lapping = 0;
176  for (u32 op_idx = 0; op_idx < permutation.size(); op_idx++)
177  {
178  const u32 new_op_idx = permutation.at(op_idx);
179 
180  std::vector<u32> intersection;
181  std::set_intersection(neighboring_regs.at(op_idx).begin(),
182  neighboring_regs.at(op_idx).end(),
183  new_neighboring_regs.at(new_op_idx).begin(),
184  new_neighboring_regs.at(new_op_idx).end(),
185  std::back_inserter(intersection));
186 
187  non_over_lapping += new_neighboring_regs.at(new_op_idx).size() - intersection.size();
188  }
189 
190  return non_over_lapping;
191  }
192  } // namespace
193 
194  std::vector<std::vector<Net*>> reorder_commutative_operands(const std::vector<std::vector<Net*>>& operands, const std::vector<std::vector<Gate*>>& registers, const u32 permute_start_index)
195  {
196  if (operands.size() > 6)
197  {
198  log_warning("module_identification", "reconstruction of 6+ commutative operands not yet supported and might take some time");
199  }
200 
201  std::vector<std::vector<Net*>> corrected_operands;
202 
203  // vector of {0, ... , num_operands-1}
204  std::vector<u32> op_indices(operands.size());
205  std::iota(op_indices.begin(), op_indices.end(), 0);
206  auto all_permutations = permutations(op_indices);
207 
208  std::vector<std::set<u32>> neighboring_regs(operands.size(), std::set<u32>{});
209  for (u32 net_idx = 0; net_idx < operands.front().size(); net_idx++)
210  {
211  std::vector<u32> best_permutation;
212 
213  // find neighboring regs for each current operand net
214  std::vector<std::set<u32>> new_neighboring_regs;
215  for (u32 op_idx = 0; op_idx < operands.size(); op_idx++)
216  {
217  new_neighboring_regs.push_back(find_neighboring_registers(operands.at(op_idx).at(net_idx), registers));
218  }
219 
220  if (net_idx < permute_start_index)
221  {
222  best_permutation = op_indices;
223  }
224  else
225  {
226  // sort permutations/operand assigments based on the overlap of neighboring registers they produce and pick the one with the biggest overlap
227  std::sort(all_permutations.begin(), all_permutations.end(), [&neighboring_regs, &new_neighboring_regs](const auto& p1, const auto& p2) {
228  return calculate_permuation_score(p1, neighboring_regs, new_neighboring_regs) < calculate_permuation_score(p2, neighboring_regs, new_neighboring_regs);
229  });
230 
231  best_permutation = all_permutations.front();
232  }
233 
234  for (u32 op_idx = 0; op_idx < best_permutation.size(); op_idx++)
235  {
236  const u32 new_op_idx = best_permutation.at(op_idx);
237 
238  Net* new_net = operands.at(new_op_idx).at(net_idx);
239 
240  if (op_idx >= corrected_operands.size())
241  {
242  corrected_operands.push_back({});
243  }
244  corrected_operands.at(op_idx).push_back(new_net);
245  }
246 
247  for (u32 op_idx = 0; op_idx < operands.size(); op_idx++)
248  {
249  neighboring_regs.at(op_idx).insert(new_neighboring_regs.at(op_idx).begin(), new_neighboring_regs.at(op_idx).end());
250  }
251  }
252 
253  return corrected_operands;
254  }
255 
256  } // namespace module_identification
257 } // namespace hal
u32 size
Definition: gate.h:58
Definition: net.h:58
Netlist * get_netlist() const
Definition: net.cpp:93
Result< std::set< Gate * > > get_next_matching_gates(const Net *net, bool successors, const std::function< bool(const Gate *)> &target_gate_filter, bool continue_on_match=false, const std::function< bool(const Endpoint *, u32 current_depth)> &exit_endpoint_filter=nullptr, const std::function< bool(const Endpoint *, u32 current_depth)> &entry_endpoint_filter=nullptr) const
uint32_t u32
Definition: defines.h:41
#define log_error(channel,...)
Definition: log.h:78
#define log_warning(channel,...)
Definition: log.h:76
std::set< u32 > find_neighboring_registers(const Net *n, const std::vector< std::vector< Gate * >> &registers)
Find neighboring registers connected to a given net.
Definition: utils.cpp:113
std::vector< std::vector< Net * > > reorder_commutative_operands(const std::vector< std::vector< Net * >> &operands, const std::vector< std::vector< Gate * >> &registers, const u32 permute_start_index=0)
Reorder commutative operands based on a permutation cache.
Definition: utils.cpp:194
std::vector< Net * > get_input_nets(const std::vector< Gate * > &gates)
Get input nets from a list of gates.
Definition: utils.cpp:25
std::vector< Net * > get_output_nets(const std::vector< Gate * > &gates, bool only_external_destinations=true)
Get output nets from a list of gates.
Definition: utils.cpp:61
Definition: defines.h:45
This file contains all functions related to the HAL plugin API.