HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
candidate_search.cpp
Go to the documentation of this file.
2 
7 #include "hal_core/netlist/net.h"
8 
9 namespace hal
10 {
11  namespace hawkeye
12  {
13  namespace
14  {
15  static std::set<PinType> control_types = {PinType::enable, PinType::clock, PinType::set, PinType::reset};
16 
17  bool continue_through_exit_ep(const Endpoint* exit_ep, const u32 current_depth)
18  {
19  if (exit_ep == nullptr)
20  {
21  return false;
22  }
23 
24  if (exit_ep->get_gate()->get_type()->has_property(GateTypeProperty::ff))
25  {
26  if (current_depth != 0)
27  {
28  return false;
29  }
30  else if (control_types.find(exit_ep->get_pin()->get_type()) != control_types.end())
31  {
32  return false;
33  }
34  }
35 
36  return true;
37  }
38 
39  bool continue_through_entry_ep(const Endpoint* entry_ep, const u32 current_depth)
40  {
41  if (entry_ep == nullptr)
42  {
43  return false;
44  }
45 
46  if (control_types.find(entry_ep->get_pin()->get_type()) != control_types.end())
47  {
48  return false;
49  }
50 
51  const auto* gt = entry_ep->get_gate()->get_type();
52  if (gt->has_property(GateTypeProperty::ram))
53  {
54  return false;
55  }
56 
57  return true;
58  }
59 
60  struct GraphCandidate
61  {
63  std::set<u32> in_reg;
64  std::set<u32> out_reg;
65 
66  bool operator==(const GraphCandidate& rhs) const
67  {
68  return this->size == rhs.size && this->in_reg == rhs.in_reg && this->out_reg == rhs.out_reg;
69  }
70 
71  bool operator<(const GraphCandidate& rhs) const
72  {
73  return this->size > rhs.size || (this->size == rhs.size && this->in_reg > rhs.in_reg) || (this->size == rhs.size && this->in_reg == rhs.in_reg && this->out_reg > rhs.out_reg);
74  }
75  };
76 
77  igraph_error_t get_saturating_neighborhoods(const igraph_t* graph, igraph_vector_int_t* in_set, igraph_vector_int_t* out_set, igraph_integer_t node, igraph_integer_t timeout)
78  {
79  igraph_integer_t no_of_nodes = igraph_vcount(graph);
80  igraph_integer_t i, j, k;
81  igraph_bool_t* added;
82  igraph_vector_int_t current_hood, previous_hood;
83  igraph_vector_int_t* current_hood_p = &current_hood;
84  igraph_vector_int_t* previous_hood_p = &previous_hood;
85  igraph_vector_int_t tmp;
86 
87  if (timeout < 0)
88  {
89  IGRAPH_ERROR("Negative timeout", IGRAPH_EINVAL);
90  }
91 
92  added = IGRAPH_CALLOC(no_of_nodes, igraph_bool_t);
93  IGRAPH_CHECK_OOM(added, "Cannot calculate neighborhood size.");
94  IGRAPH_FINALLY(igraph_free, added);
95 
96  IGRAPH_VECTOR_INT_INIT_FINALLY(current_hood_p, 0);
97  IGRAPH_VECTOR_INT_INIT_FINALLY(previous_hood_p, 0);
98  IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp, 0);
99 
100  IGRAPH_CHECK(igraph_vector_int_init(in_set, 0));
101  IGRAPH_CHECK(igraph_vector_int_init(out_set, 0));
102  igraph_vector_int_clear(in_set);
103  igraph_vector_int_clear(out_set);
104 
105  IGRAPH_CHECK(igraph_vector_int_push_back(current_hood_p, node));
106 
107  igraph_integer_t previous_size, current_size;
108 
109  for (i = 0; i < timeout; i++)
110  {
111  previous_size = igraph_vector_int_size(previous_hood_p);
112  current_size = igraph_vector_int_size(current_hood_p);
113 
114  if (previous_size < current_size)
115  {
116  igraph_vector_int_swap(previous_hood_p, current_hood_p);
117  igraph_vector_int_clear(current_hood_p);
118 
119  memset(added, false, no_of_nodes * sizeof(igraph_bool_t));
120 
121  for (j = 0; j < current_size; j++)
122  {
123  igraph_integer_t actnode = VECTOR(*previous_hood_p)[j];
124  igraph_vector_int_clear(&tmp);
125  // IGRAPH_LOOPS_TWICE and multiple = true keep every neighbor in the result, duplicates are filtered by `added` below
126  IGRAPH_CHECK(igraph_neighbors(graph, &tmp, actnode, IGRAPH_OUT, IGRAPH_LOOPS_TWICE, true));
127 
128  for (k = 0; k < igraph_vector_int_size(&tmp); k++)
129  {
130  igraph_integer_t nei = VECTOR(tmp)[k];
131  if (!added[nei])
132  {
133  added[nei] = true;
134  IGRAPH_CHECK(igraph_vector_int_push_back(current_hood_p, nei));
135  }
136  }
137  }
138  }
139  else
140  {
141  if (previous_size == current_size)
142  {
143  IGRAPH_CHECK(igraph_vector_int_update(in_set, previous_hood_p));
144  IGRAPH_CHECK(igraph_vector_int_update(out_set, current_hood_p));
145  }
146 
147  break;
148  }
149  }
150 
151  igraph_vector_int_destroy(current_hood_p);
152  igraph_vector_int_destroy(previous_hood_p);
153  igraph_vector_int_destroy(&tmp);
154  IGRAPH_FREE(added);
155  IGRAPH_FINALLY_CLEAN(4);
156 
157  return IGRAPH_SUCCESS;
158  }
159 
160  igraph_error_t get_saturating_neighborhoods_scc(const igraph_t* graph,
161  igraph_vector_int_t* in_set,
162  igraph_vector_int_t* out_set,
163  igraph_integer_t node,
164  igraph_integer_t timeout,
165  std::map<std::set<u32>, igraph_vector_int_t*>& cache)
166  {
167  igraph_integer_t no_of_nodes = igraph_vcount(graph);
168  igraph_integer_t i, j, k;
169  igraph_bool_t* added;
170  igraph_vector_int_t current_hood, previous_hood;
171  igraph_vector_int_t current_component, previous_component;
172  igraph_vector_int_t* current_hood_p = &current_hood;
173  igraph_vector_int_t* previous_hood_p = &previous_hood;
174  igraph_vector_int_t* current_component_p = &current_component;
175  igraph_vector_int_t* previous_component_p = &previous_component;
176  igraph_vector_int_t tmp;
177 
178  if (timeout < 0)
179  {
180  IGRAPH_ERROR("Negative timeout", IGRAPH_EINVAL);
181  }
182 
183  added = IGRAPH_CALLOC(no_of_nodes, igraph_bool_t);
184  IGRAPH_CHECK_OOM(added, "Cannot calculate neighborhood size.");
185  IGRAPH_FINALLY(igraph_free, added);
186 
187  IGRAPH_VECTOR_INT_INIT_FINALLY(current_hood_p, 0);
188  IGRAPH_VECTOR_INT_INIT_FINALLY(previous_hood_p, 0);
189  IGRAPH_VECTOR_INT_INIT_FINALLY(current_component_p, 0);
190  IGRAPH_VECTOR_INT_INIT_FINALLY(previous_component_p, 0);
191  IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp, 0);
192 
193  IGRAPH_CHECK(igraph_vector_int_init(in_set, 0));
194  IGRAPH_CHECK(igraph_vector_int_init(out_set, 0));
195  igraph_vector_int_clear(in_set);
196  igraph_vector_int_clear(out_set);
197 
198  IGRAPH_CHECK(igraph_vector_int_push_back(current_hood_p, node));
199  IGRAPH_CHECK(igraph_vector_int_push_back(current_component_p, node));
200 
201  igraph_integer_t previous_size, current_size;
202 
203  for (i = 0; i < timeout; i++)
204  {
205  previous_size = igraph_vector_int_size(previous_component_p);
206  current_size = igraph_vector_int_size(current_component_p);
207  u32 current_hood_size = igraph_vector_int_size(current_hood_p);
208 
209  if (previous_size < current_size || current_size == 1)
210  {
211  // move current objects to previous
212  igraph_vector_int_swap(previous_hood_p, current_hood_p);
213  igraph_vector_int_swap(previous_component_p, current_component_p);
214  igraph_vector_int_clear(current_hood_p);
215  igraph_vector_int_clear(current_component_p);
216 
217  // clear flags of added vertices
218  memset(added, false, no_of_nodes * sizeof(igraph_bool_t));
219 
220  std::set<u32> cache_key;
221  for (j = 0; j < current_hood_size; j++)
222  {
223  igraph_integer_t actnode = VECTOR(*previous_hood_p)[j];
224  igraph_vector_int_clear(&tmp);
225  // IGRAPH_LOOPS_TWICE and multiple = true keep every neighbor in the result, duplicates are filtered by `added` below
226  IGRAPH_CHECK(igraph_neighbors(graph, &tmp, actnode, IGRAPH_OUT, IGRAPH_LOOPS_TWICE, true));
227 
228  for (k = 0; k < igraph_vector_int_size(&tmp); k++)
229  {
230  igraph_integer_t nei = VECTOR(tmp)[k];
231  if (!added[nei])
232  {
233  added[nei] = true;
234  IGRAPH_CHECK(igraph_vector_int_push_back(current_hood_p, nei));
235  cache_key.insert(nei);
236  }
237  }
238  }
239 
240  if (k == 0)
241  {
242  continue;
243  }
244 
245  if (const auto cache_it = cache.find(cache_key); cache_it != cache.end())
246  {
247  IGRAPH_CHECK(igraph_vector_int_update(current_component_p, cache_it->second));
248  }
249  else
250  {
251  igraph_t subgraph;
252  igraph_vs_t subgraph_vertices = igraph_vss_vector(current_hood_p);
253  IGRAPH_FINALLY(igraph_vs_destroy, &subgraph_vertices);
254  igraph_vector_int_t vertex_map;
255  IGRAPH_VECTOR_INT_INIT_FINALLY(&vertex_map, igraph_vector_int_size(current_hood_p));
256  IGRAPH_CHECK(igraph_induced_subgraph_map(graph, &subgraph, subgraph_vertices, IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH, nullptr, &vertex_map));
257  IGRAPH_FINALLY(igraph_destroy, &subgraph);
258 
259  igraph_vector_int_t membership, csize;
260  IGRAPH_VECTOR_INT_INIT_FINALLY(&membership, 0);
261  IGRAPH_VECTOR_INT_INIT_FINALLY(&csize, 0);
262  IGRAPH_CHECK(igraph_connected_components(&subgraph, &membership, &csize, nullptr, IGRAPH_STRONG));
263 
264  u32 max_id = igraph_vector_int_which_max(&csize);
265  u32 num_subgraph_vertices = igraph_vcount(&subgraph);
266  for (i32 i = 0; i < num_subgraph_vertices; i++)
267  {
268  u32 cid = VECTOR(membership)[i];
269  if (cid == max_id)
270  {
271  IGRAPH_CHECK(igraph_vector_int_push_back(current_component_p, VECTOR(vertex_map)[i]));
272  }
273  }
274 
275  igraph_vs_destroy(&subgraph_vertices);
276  igraph_vector_int_destroy(&vertex_map);
277  igraph_vector_int_destroy(&membership);
278  igraph_vector_int_destroy(&csize);
279  igraph_destroy(&subgraph);
280  IGRAPH_FINALLY_CLEAN(5);
281 
282  igraph_vector_int_t* cache_tmp = new igraph_vector_int_t;
283  IGRAPH_CHECK(igraph_vector_int_init(cache_tmp, 0)); // cleanup handled by caller
284  IGRAPH_CHECK(igraph_vector_int_update(cache_tmp, current_component_p));
285  cache[cache_key] = cache_tmp;
286  }
287  }
288  else
289  {
290  if (previous_size == current_size)
291  {
292  IGRAPH_CHECK(igraph_vector_int_update(in_set, previous_component_p));
293  IGRAPH_CHECK(igraph_vector_int_update(out_set, current_component_p));
294  }
295 
296  break;
297  }
298  }
299 
300  igraph_vector_int_destroy(current_hood_p);
301  igraph_vector_int_destroy(previous_hood_p);
302  igraph_vector_int_destroy(current_component_p);
303  igraph_vector_int_destroy(previous_component_p);
304  igraph_vector_int_destroy(&tmp);
305  IGRAPH_FREE(added);
306  IGRAPH_FINALLY_CLEAN(6);
307 
308  return IGRAPH_SUCCESS;
309  }
310  } // namespace
311 
312  Result<std::vector<RegisterCandidate>> detect_candidates(Netlist* nl, const std::vector<DetectionConfiguration>& configs, u32 min_state_size, const std::vector<Gate*>& start_ffs)
313  {
314  if (nl == nullptr)
315  {
316  return ERR("netlist is a nullptr");
317  }
318 
319  log_info("hawkeye", "start detecting state register candidates...");
320  auto start = std::chrono::system_clock::now();
321 
322  const auto nl_dec = NetlistTraversalDecorator(*nl);
323  std::map<Gate*, std::set<Gate*>> ff_map;
324  std::unordered_map<const Net*, std::set<Gate*>> cache = {};
325  const auto start_gates = nl->get_gates([](const Gate* g) { return g->get_type()->has_property(GateTypeProperty::ff); });
326  for (auto* sg : start_gates)
327  {
328  if (const auto res = nl_dec.get_next_matching_gates(
329  sg, true, [](const Gate* g) { return g->get_type()->has_property(GateTypeProperty::ff); }, false, continue_through_exit_ep, continue_through_entry_ep);
330  res.is_ok())
331  {
332  ff_map[sg] = res.get();
333  }
334  else
335  {
336  return ERR(res.get_error());
337  }
338  }
339 
340  auto res = graph_algorithm::NetlistGraph::from_netlist_no_edges(nl, start_gates);
341  if (res.is_error())
342  {
343  return ERR(res.get_error());
344  }
345  auto base_graph = res.get();
346 
347  const auto start_vertices_res = base_graph->get_vertices_from_gates(start_ffs.empty() ? start_gates : start_ffs);
348  if (start_vertices_res.is_error())
349  {
350  return ERR(start_vertices_res.get_error());
351  }
352  auto start_vertices = start_vertices_res.get();
353 
354  std::set<RegisterCandidate> candidates;
355  for (const auto& config : configs)
356  {
357  auto tmp_graph_res = base_graph->copy();
358  if (tmp_graph_res.is_error())
359  {
360  return ERR(tmp_graph_res.get_error());
361  }
362  auto tmp_graph = tmp_graph_res.get();
363 
364  std::map<Gate*, std::set<Gate*>> filtered_map;
365  if (config.control == DetectionConfiguration::Control::CHECK_FF)
366  {
367  filtered_map = std::move(ff_map);
368  if (const auto edge_res = tmp_graph->add_edges(ff_map); edge_res.is_error())
369  {
370  return ERR(edge_res.get_error());
371  }
372  }
373  else if (config.control == DetectionConfiguration::Control::CHECK_TYPE)
374  {
375  std::map<const GateType*, std::set<const GateType*>> allowed_gate_type_map;
376  const auto* gl = nl->get_gate_library();
377  for (const auto& gt_list : config.equivalent_types)
378  {
379  std::set<const GateType*> types;
380  for (const auto& gt_name : gt_list)
381  {
382  types.insert(gl->get_gate_type_by_name(gt_name));
383  }
384 
385  for (const auto* gt : types)
386  {
387  allowed_gate_type_map[gt] = types;
388  }
389  }
390 
391  for (const auto& [src, dsts] : ff_map)
392  {
393  for (auto* dst : dsts)
394  {
395  const auto* src_type = src->get_type();
396  const auto* dst_type = dst->get_type();
397  if (src_type != dst_type)
398  {
399  if (const auto src_it = allowed_gate_type_map.find(src_type); src_it != allowed_gate_type_map.end())
400  {
401  const auto& allowed_gates = std::get<1>(*src_it);
402  if (allowed_gates.find(dst_type) == allowed_gates.end())
403  {
404  continue;
405  }
406  }
407  else
408  {
409  continue;
410  }
411  }
412 
413  filtered_map[src].insert(dst);
414  }
415  }
416  }
417  else if (config.control == DetectionConfiguration::Control::CHECK_NETS)
418  {
419  std::unordered_map<const Gate*, std::map<PinType, const Net*>> control_map;
420  for (const auto* gate : start_gates)
421  {
422  control_map[gate] = std::map<PinType, const Net*>();
423 
424  for (const auto& ep : gate->get_fan_in_endpoints())
425  {
426  if (auto pin_type = ep->get_pin()->get_type(); control_types.find(pin_type) != control_types.end())
427  {
428  control_map[gate][pin_type] = ep->get_net();
429  }
430  }
431  }
432 
433  for (const auto& [src, dsts] : ff_map)
434  {
435  for (auto* dst : dsts)
436  {
437  if (control_map.at(src) != control_map.at(dst))
438  {
439  continue;
440  }
441 
442  filtered_map[src].insert(dst);
443  }
444  }
445  }
446  else if (config.control == DetectionConfiguration::Control::CHECK_PINS)
447  {
448  std::unordered_map<const Gate*, std::set<PinType>> control_map;
449  for (const auto* gate : start_gates)
450  {
451  control_map[gate] = std::set<PinType>();
452 
453  for (const auto& ep : gate->get_fan_in_endpoints())
454  {
455  auto sources = ep->get_net()->get_sources();
456  if (sources.size() != 1)
457  {
458  continue;
459  }
460  if (sources.at(0)->get_gate()->is_gnd_gate() || sources.at(0)->get_gate()->is_vcc_gate())
461  {
462  continue;
463  }
464 
465  if (auto pin_type = ep->get_pin()->get_type(); control_types.find(pin_type) != control_types.end())
466  {
467  control_map[gate].insert(pin_type);
468  }
469  }
470  }
471 
472  for (const auto& [src, dsts] : ff_map)
473  {
474  for (auto* dst : dsts)
475  {
476  // if (src->get_type() != dst->get_type())
477  // {
478  // continue;
479  // }
480 
481  if (control_map.at(src) != control_map.at(dst))
482  {
483  continue;
484  }
485 
486  filtered_map[src].insert(dst);
487  }
488  }
489  }
490 
491  if (const auto edge_res = tmp_graph->add_edges(filtered_map); edge_res.is_error())
492  {
493  return ERR(edge_res.get_error());
494  }
495 
496  igraph_vector_int_t in_set, out_set;
497  if (const auto res = igraph_vector_int_init(&in_set, 0); res != IGRAPH_SUCCESS)
498  {
499  return ERR(igraph_strerror(res));
500  }
501 
502  if (const auto res = igraph_vector_int_init(&out_set, 0); res != IGRAPH_SUCCESS)
503  {
504  igraph_vector_int_destroy(&in_set);
505  return ERR(igraph_strerror(res));
506  }
507 
508  std::set<GraphCandidate> graph_candidates;
509 
510  if (config.components == DetectionConfiguration::Components::NONE)
511  {
512  for (const auto v : start_vertices)
513  {
514  igraph_vector_int_clear(&in_set);
515  igraph_vector_int_clear(&out_set);
516 
517  if (const auto res = get_saturating_neighborhoods(tmp_graph->get_graph(), &in_set, &out_set, v, config.timeout); res != IGRAPH_SUCCESS)
518  {
519  igraph_vector_int_destroy(&in_set);
520  igraph_vector_int_destroy(&out_set);
521  return ERR(igraph_strerror(res));
522  }
523 
524  u32 size = igraph_vector_int_size(&out_set);
525  if (size <= config.min_register_size)
526  {
527  continue;
528  }
529 
530  GraphCandidate c;
531  c.size = size;
532  for (u32 i = 0; i < igraph_vector_int_size(&in_set); i++)
533  {
534  c.in_reg.insert(VECTOR(in_set)[i]);
535  }
536  for (u32 i = 0; i < igraph_vector_int_size(&out_set); i++)
537  {
538  c.out_reg.insert(VECTOR(out_set)[i]);
539  }
540  graph_candidates.insert(c);
541  }
542  }
543  else if (config.components == DetectionConfiguration::Components::CHECK_SCC)
544  {
545  std::map<std::set<u32>, igraph_vector_int_t*> scc_cache;
546 
547  for (const auto v : start_vertices)
548  {
549  igraph_vector_int_clear(&in_set);
550  igraph_vector_int_clear(&out_set);
551 
552  if (const auto res = get_saturating_neighborhoods_scc(tmp_graph->get_graph(), &in_set, &out_set, v, config.timeout, scc_cache); res != IGRAPH_SUCCESS)
553  {
554  igraph_vector_int_destroy(&in_set);
555  igraph_vector_int_destroy(&out_set);
556  for (auto& [_, comp] : scc_cache)
557  {
558  igraph_vector_int_destroy(comp);
559  delete comp;
560  }
561  return ERR(igraph_strerror(res));
562  }
563 
564  u32 size = igraph_vector_int_size(&out_set);
565  if (size <= config.min_register_size)
566  {
567  continue;
568  }
569 
570  GraphCandidate c;
571  c.size = size;
572  for (u32 i = 0; i < igraph_vector_int_size(&in_set); i++)
573  {
574  c.in_reg.insert(VECTOR(in_set)[i]);
575  }
576  for (u32 i = 0; i < igraph_vector_int_size(&out_set); i++)
577  {
578  c.out_reg.insert(VECTOR(out_set)[i]);
579  }
580  graph_candidates.insert(c);
581  }
582 
583  for (auto& [_, comp] : scc_cache)
584  {
585  igraph_vector_int_destroy(comp);
586  delete comp;
587  }
588  }
589 
590  igraph_vector_int_destroy(&in_set);
591  igraph_vector_int_destroy(&out_set);
592 
593  for (const auto& gc : graph_candidates)
594  {
595  std::set<Gate*> out_reg;
596 
597  if (auto out_reg_res = tmp_graph->get_gates_set_from_vertices(gc.out_reg); out_reg_res.is_ok())
598  {
599  out_reg = out_reg_res.get();
600  }
601  else
602  {
603  return ERR(out_reg_res.get_error());
604  }
605 
606  if (gc.in_reg == gc.out_reg)
607  {
608  candidates.insert(RegisterCandidate(out_reg));
609  }
610  else
611  {
612  std::set<Gate*> in_reg;
613  if (auto in_reg_res = tmp_graph->get_gates_set_from_vertices(gc.in_reg); in_reg_res.is_ok())
614  {
615  in_reg = in_reg_res.get();
616  candidates.insert(RegisterCandidate(in_reg, out_reg));
617  }
618  else
619  {
620  return ERR(in_reg_res.get_error());
621  }
622  }
623  }
624  }
625 
626  std::set<const RegisterCandidate*> candidates_to_delete;
627  for (auto outer_it = candidates.begin(); outer_it != candidates.end(); outer_it++)
628  {
629  for (auto inner_it = std::next(outer_it, 1); inner_it != candidates.end(); inner_it++)
630  {
631  if (std::includes(outer_it->get_output_reg().begin(), outer_it->get_output_reg().end(), inner_it->get_output_reg().begin(), inner_it->get_output_reg().end()))
632  {
633  candidates_to_delete.insert(&(*outer_it));
634  break;
635  }
636  }
637 
638  if (outer_it->get_size() < min_state_size)
639  {
640  candidates_to_delete.insert(&(*outer_it));
641  }
642  }
643 
644  for (const auto* c : candidates_to_delete)
645  {
646  candidates.erase(*c);
647  }
648 
649  auto duration_in_seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - start).count();
650  if (candidates.size() == 1)
651  {
652  log_info("hawkeye", "detected {} state register candidate in {} seconds", candidates.size(), duration_in_seconds);
653  }
654  else
655  {
656  log_info("hawkeye", "detected {} state register candidates in {} seconds", candidates.size(), duration_in_seconds);
657  }
658 
659  return OK(std::vector<RegisterCandidate>(candidates.begin(), candidates.end()));
660  }
661  } // namespace hawkeye
662 
663  template<>
664  std::map<hawkeye::DetectionConfiguration::Control, std::string> EnumStrings<hawkeye::DetectionConfiguration::Control>::data = {
669 
670  template<>
671  std::map<hawkeye::DetectionConfiguration::Components, std::string> EnumStrings<hawkeye::DetectionConfiguration::Components>::data = {
674 } // namespace hal
std::set< u32 > out_reg
std::set< u32 > in_reg
u32 size
This file contains the function for HAWKEYE's candidate search as well as a struct for configuring th...
Definition: gate.h:58
GateType * get_type() const
Definition: gate.cpp:125
const std::vector< Gate * > & get_gates() const
Definition: netlist.cpp:204
const GateLibrary * get_gate_library() const
Definition: netlist.cpp:132
static Result< std::unique_ptr< NetlistGraph > > from_netlist_no_edges(Netlist *nl, const std::vector< Gate * > &gates={})
Create an empty directed graph from a netlist.
A register candidate discovered by HAWKEYE.
uint32_t u32
Definition: defines.h:41
int32_t i32
Definition: defines.h:36
#define log_info(channel,...)
Definition: log.h:70
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
Result< std::vector< RegisterCandidate > > detect_candidates(Netlist *nl, const std::vector< DetectionConfiguration > &configs, u32 min_state_size=40, const std::vector< Gate * > &start_ffs={})
Attempt to locate candidates for symmetric cryptographic implementations within a gate-level netlist.
Definition: defines.h:45
This file contains functions related to neighborhoods in graphs.
This file contains the class that holds a netlist graph.
@ CHECK_NETS
If two flip-flops ff1 and ff2 are connected through combinational logic and are controlled through th...
@ CHECK_TYPE
If two flip-flops ff1 and ff2 are connected through combinational logic and are of the same gate type...
@ CHECK_FF
If two flip-flops ff1 and ff2 are connected through combinational logic, an edge is added such that (...
@ CHECK_PINS
If two flip-flops ff1 and ff2 are connected through combinational logic and are controlled through th...
@ CHECK_SCC
Use SCC detection within the currently explored neighborhood of a start flip-flop.
@ NONE
Do not use SCC detection and instead resort to the simple neighborhood discovery algorithm.