HAL  v4.5.0-133-g64838ea8d
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
result.cpp
Go to the documentation of this file.
2 
9 
10 #include <fstream>
11 
12 namespace hal
13 {
14  namespace dataflow
15  {
16  namespace
17  {
18  std::unordered_set<u32> nets_to_id_set(const std::unordered_set<Net*>& nets)
19  {
20  std::unordered_set<u32> ids;
21  for (const auto* net : nets)
22  {
23  ids.insert(net->get_id());
24  }
25  return ids;
26  }
27  } // namespace
28 
30  {
31  m_netlist = nl;
32 
33  const auto& na = grouping.netlist_abstr;
34  for (const auto* gate : na.target_gates)
35  {
36  auto gate_id = gate->get_id();
37 
38  if (const auto it = na.gate_to_successors.find(gate_id); it != na.gate_to_successors.end())
39  {
40  for (auto suc_gate_id : std::get<1>(*it))
41  {
42  this->m_gate_successors[gate].insert(nl->get_gate_by_id(suc_gate_id));
43  }
44  }
45 
46  if (const auto it = na.gate_to_predecessors.find(gate_id); it != na.gate_to_predecessors.end())
47  {
48  for (auto pred_gate_id : std::get<1>(*it))
49  {
50  this->m_gate_predecessors[gate].insert(nl->get_gate_by_id(pred_gate_id));
51  }
52  }
53 
54  if (const auto it = na.gate_to_control_signals.find(gate_id); it != na.gate_to_control_signals.end())
55  {
56  for (const auto& [type, signals] : std::get<1>(*it))
57  {
58  for (auto signal_net_id : signals)
59  {
60  this->m_gate_signals[gate][type].insert(nl->get_net_by_id(signal_net_id));
61  }
62  }
63  }
64  }
65 
66  for (const auto& [group_id, gate_ids] : grouping.gates_of_group)
67  {
68  std::unordered_set<Gate*> gates;
69  for (const auto gate_id : gate_ids)
70  {
71  auto* gate = m_netlist->get_gate_by_id(gate_id);
72  gates.insert(gate);
73  this->m_parent_group_of_gate[gate] = group_id;
74  }
75  m_gates_of_group[group_id] = gates;
76 
77  for (const auto& [type, signals] : grouping.get_control_signals_of_group(group_id))
78  {
79  for (auto signal_net_id : signals)
80  {
81  this->m_group_signals[group_id][type].insert(m_netlist->get_net_by_id(signal_net_id));
82  }
83  }
84 
85  if (auto suc_ids = grouping.get_successor_groups_of_group(group_id); !suc_ids.empty())
86  {
87  this->m_group_successors[group_id] = suc_ids;
88  }
89 
90  if (auto pred_ids = grouping.get_predecessor_groups_of_group(group_id); !pred_ids.empty())
91  {
92  this->m_group_predecessors[group_id] = pred_ids;
93  }
94 
95  this->m_last_id = std::max(this->m_last_id, group_id);
96  }
97  }
98 
100  {
101  return this->m_netlist;
102  }
103 
104  const std::unordered_map<u32, std::unordered_set<Gate*>>& dataflow::Result::get_groups() const
105  {
106  return this->m_gates_of_group;
107  }
108 
109  std::vector<Gate*> dataflow::Result::get_gates() const
110  {
111  std::vector<Gate*> gates;
112 
113  for (auto& group_gates : m_gates_of_group)
114  {
115  std::transform(std::get<1>(group_gates).begin(), std::get<1>(group_gates).end(), std::back_inserter(gates), [](auto* gate) { return gate; });
116  }
117 
118  return gates;
119  }
120 
122  {
123  if (const auto it = this->m_gates_of_group.find(group_id); it != this->m_gates_of_group.end())
124  {
125  return OK(it->second);
126  }
127  else
128  {
129  return ERR("invalid group ID.");
130  }
131  }
132 
134  {
135  if (!gate)
136  {
137  return ERR("gate is a nullptr.");
138  }
139 
140  if (const auto it = this->m_parent_group_of_gate.find(gate); it != this->m_parent_group_of_gate.end())
141  {
142  return OK(it->second);
143  }
144  else
145  {
146  return ERR("gate is not part of a group.");
147  }
148  }
149 
151  {
152  if (this->m_gates_of_group.find(group_id) == this->m_gates_of_group.end())
153  {
154  return ERR("invalid group ID.");
155  }
156 
157  if (const auto group_it = this->m_group_signals.find(group_id); group_it != this->m_group_signals.end())
158  {
159  const auto& type_map = std::get<1>(*group_it);
160  if (const auto type_it = type_map.find(type); type_it != type_map.end())
161  {
162  return OK(type_it->second);
163  }
164  }
165 
166  return OK({});
167  }
168 
170  {
171  if (this->m_parent_group_of_gate.find(gate) == this->m_parent_group_of_gate.end())
172  {
173  return ERR("gate is not part of a group.");
174  }
175 
176  if (const auto gate_it = this->m_gate_signals.find(gate); gate_it != this->m_gate_signals.end())
177  {
178  const auto& type_map = std::get<1>(*gate_it);
179  if (const auto type_it = type_map.find(type); type_it != type_map.end())
180  {
181  return OK(type_it->second);
182  }
183  }
184 
185  return OK({});
186  }
187 
189  {
190  if (this->m_gates_of_group.find(group_id) == this->m_gates_of_group.end())
191  {
192  return ERR("invalid group ID.");
193  }
194 
195  if (const auto it = this->m_group_successors.find(group_id); it != this->m_group_successors.end())
196  {
197  return OK(it->second);
198  }
199 
200  return OK({});
201  }
202 
204  {
205  if (this->m_parent_group_of_gate.find(gate) == this->m_parent_group_of_gate.end())
206  {
207  return ERR("gate is not part of a group.");
208  }
209 
210  if (const auto it = this->m_gate_successors.find(gate); it != this->m_gate_successors.end())
211  {
212  return OK(it->second);
213  }
214 
215  return OK({});
216  }
217 
219  {
220  if (this->m_gates_of_group.find(group_id) == this->m_gates_of_group.end())
221  {
222  return ERR("invalid group ID.");
223  }
224 
225  if (const auto it = this->m_group_predecessors.find(group_id); it != this->m_group_predecessors.end())
226  {
227  return OK(it->second);
228  }
229 
230  return OK({});
231  }
232 
234  {
235  if (this->m_parent_group_of_gate.find(gate) == this->m_parent_group_of_gate.end())
236  {
237  return ERR("gate is not part of a group.");
238  }
239 
240  if (const auto it = this->m_gate_predecessors.find(gate); it != this->m_gate_predecessors.end())
241  {
242  return OK(it->second);
243  }
244 
245  return OK({});
246  }
247 
248  hal::Result<std::filesystem::path> dataflow::Result::write_dot(const std::filesystem::path& out_path, const std::unordered_set<u32>& group_ids) const
249  {
250  auto write_path = out_path;
251 
252  if (write_path.empty())
253  {
254  return ERR("output path is empty.");
255  }
256 
257  if (std::filesystem::is_directory(write_path))
258  {
259  write_path /= "graph.dot";
260  }
261 
262  if (write_path.extension() != ".dot")
263  {
264  log_info("dataflow", "replacing invalid file extension '{}' with '.dot' ...", write_path.extension().string());
265  write_path.replace_extension("dot");
266  }
267 
268  log_info("dataflow", "writing dataflow graph to '{}' ...", write_path.string());
269 
270  std::ofstream ofs(write_path, std::ofstream::out);
271  if (ofs)
272  {
273  ofs << "digraph {\n\tcomment=\"created by HAL plugin dataflow\"\n\tnode [shape=box fillcolor=white style=filled];\n";
274 
275  // print node
276  for (const auto& [group_id, gates] : this->get_groups())
277  {
278  if (!group_ids.empty() && group_ids.find(group_id) == group_ids.end())
279  {
280  continue;
281  }
282 
283  auto size = gates.size() * 0.1;
284  if (size < 1500)
285  {
286  size = size * 0.02;
287  }
288 
289  ofs << group_id << " [width=" << 0.05 * gates.size() << " label=\"" << gates.size() << " bit (id " << group_id << ")\"];\n";
290  }
291 
292  // print edges
293  for (const auto& [group_id, gates] : this->get_groups())
294  {
295  if (!group_ids.empty() && group_ids.find(group_id) == group_ids.end())
296  {
297  continue;
298  }
299 
300  auto sucs = this->get_group_successors(group_id).get();
301  for (auto suc_id : sucs)
302  {
303  if (!group_ids.empty() && group_ids.find(suc_id) == group_ids.end())
304  {
305  continue;
306  }
307  ofs << group_id << " -> " << suc_id << ";\n";
308  }
309  }
310 
311  ofs << "}";
312  ofs.close();
313 
314  log_info("dataflow", "successfully written dataflow graph to '{}'.", write_path.string());
315 
316  return OK({write_path});
317  }
318 
319  return ERR("failed to open file at '" + write_path.string() + "' for writing dataflow graph.");
320  }
321 
322  hal::Result<std::monostate> dataflow::Result::write_txt(const std::filesystem::path& out_path, const std::unordered_set<u32>& group_ids) const
323  {
324  auto write_path = out_path;
325 
326  if (write_path.empty())
327  {
328  return ERR("output path is empty.");
329  }
330 
331  if (std::filesystem::is_directory(write_path))
332  {
333  write_path /= "groups.txt";
334  }
335 
336  if (write_path.extension() != ".txt")
337  {
338  log_info("dataflow", "replacing invalid file extension '{}' with '.txt' ...", write_path.extension().string());
339  write_path.replace_extension("txt");
340  }
341 
342  log_info("dataflow", "writing dataflow gate groups to '{}' ...", write_path.string());
343 
344  std::ofstream ofs(write_path, std::ofstream::out);
345  if (ofs)
346  {
347  ofs << "State:";
348  ofs << "\n\n";
349 
350  for (const auto& [group_id, gates] : this->get_groups())
351  {
352  if (!group_ids.empty() && group_ids.find(group_id) == group_ids.end())
353  {
354  continue;
355  }
356 
357  ofs << "ID:" << group_id << ", ";
358  ofs << "Size:" << gates.size() << ", ";
359  ofs << "CLK: {" << utils::join(", ", nets_to_id_set(this->get_group_control_nets(group_id, PinType::clock).get())) << "}, ";
360  ofs << "EN: {" << utils::join(", ", nets_to_id_set(this->get_group_control_nets(group_id, PinType::enable).get())) << "}, ";
361  ofs << "R: {" << utils::join(", ", nets_to_id_set(this->get_group_control_nets(group_id, PinType::reset).get())) << "}, ";
362  ofs << "S: {" << utils::join(", ", nets_to_id_set(this->get_group_control_nets(group_id, PinType::set).get())) << "}" << std::endl;
363 
364  if (auto res = this->get_group_successors(group_id); res.is_ok())
365  {
366  auto unsorted_successors = res.get();
367  ofs << " Successors: {" + utils::join(", ", std::set<u32>(unsorted_successors.begin(), unsorted_successors.end())) << "}" << std::endl;
368  }
369 
370  if (auto res = this->get_group_predecessors(group_id); res.is_ok())
371  {
372  auto unsorted_predecessors = res.get();
373  ofs << " Predecessors: {" + utils::join(", ", std::set<u32>(unsorted_predecessors.begin(), unsorted_predecessors.end())) << "}" << std::endl;
374  }
375 
376  std::unordered_map<u32, std::vector<std::string>> texts;
377  std::unordered_map<u32, u32> text_max_lengths;
378 
379  std::set<u32> gate_ids;
380  for (const auto& gate : gates)
381  {
382  auto name = gate->get_name() + ", ";
383  auto type = "type: " + gate->get_type()->get_name() + ", ";
384  auto id = "id: " + std::to_string(gate->get_id()) + ", ";
385  std::string stages = "RS: ";
386 
387  std::vector<std::string> data = {name, type, id, stages};
388  for (u32 i = 0; i < data.size(); ++i)
389  {
390  text_max_lengths[i] = std::max(text_max_lengths[i], (u32)data[i].size());
391  }
392 
393  u32 gate_id = gate->get_id();
394  texts.emplace(gate_id, data);
395  gate_ids.insert(gate_id);
396  }
397 
398  for (const auto& gate_id : gate_ids)
399  {
400  auto& data = texts[gate_id];
401  for (u32 i = 0; i < data.size(); ++i)
402  {
403  ofs << std::setw(text_max_lengths[i]) << std::left << data[i];
404  }
405  ofs << std::endl;
406  }
407  ofs << "\n";
408  }
409  ofs.close();
410 
411  log_info("dataflow", "successfully written dataflow gate groups to '{}'.", write_path.string());
412  return OK({});
413  }
414 
415  return ERR("failed to open file at '" + write_path.string() + "' for writing dataflow gate groups.");
416  }
417 
419  {
420  return create_modules(std::map<const GateType*, std::string>(), std::map<std::pair<PinDirection, std::string>, std::string>(), group_ids);
421  }
422 
423  hal::Result<std::unordered_map<u32, Module*>> dataflow::Result::create_modules(const std::map<const GateType*, std::string>& module_suffixes,
424  const std::map<std::pair<PinDirection, std::string>, std::string>& pin_prefixes,
425  const std::unordered_set<u32>& group_ids) const
426  {
427  auto* nl = this->get_netlist();
428 
429  // delete all modules that start with DANA
430  std::vector<Module*> modules_to_delete;
431  for (const auto mod : nl->get_modules())
432  {
433  if (utils::starts_with(mod->get_name(), std::string("DANA_")))
434  {
435  modules_to_delete.push_back(mod);
436  }
437  }
438 
439  for (auto* mod : modules_to_delete)
440  {
441  nl->delete_module(mod);
442  }
443  log_info("dataflow", "successfully deleted old DANA modules");
444 
445  // create new modules and try to keep hierarchy if possible
446  std::unordered_map<u32, Module*> group_to_module;
447  for (const auto& [group_id, group] : this->get_groups())
448  {
449  if (!group_ids.empty() && group_ids.find(group_id) == group_ids.end())
450  {
451  continue;
452  }
453 
454  bool gate_hierachy_matches_for_all = true;
455  bool gate_type_matches_for_all = true;
456  bool first_run = true;
457  const GateType* gate_type;
458  auto* reference_module = nl->get_top_module();
459 
460  std::vector<Gate*> gates;
461  for (const auto gate : group)
462  {
463  gates.push_back(gate);
464 
465  if (first_run)
466  {
467  reference_module = gate->get_module();
468  gate_type = gate->get_type();
469  first_run = false;
470  }
471  else if (gate->get_module() != reference_module)
472  {
473  gate_hierachy_matches_for_all = false;
474  }
475 
476  if (gate_type != gate->get_type())
477  {
478  gate_hierachy_matches_for_all = false;
479  }
480  }
481 
482  if (!gate_hierachy_matches_for_all)
483  {
484  reference_module = nl->get_top_module();
485  }
486 
487  std::string suffix;
488  if (const auto it = module_suffixes.find(gate_type); gate_type_matches_for_all && it != module_suffixes.end())
489  {
490  suffix = it->second;
491  }
492  else
493  {
494  suffix = "module";
495  }
496 
497  auto* new_mod = nl->create_module("DANA_" + suffix + "_" + std::to_string(group_id), reference_module, gates);
498  group_to_module[group_id] = new_mod;
499 
500  std::map<const std::pair<PinDirection, std::string>, PinGroup<ModulePin>*> pin_groups;
501  for (auto* pin : new_mod->get_pins())
502  {
503  if (pin->get_direction() == PinDirection::input)
504  {
505  const auto destinations = pin->get_net()->get_destinations([new_mod](const Endpoint* ep) { return ep->get_gate()->get_module() == new_mod; });
506 
507  const auto* first_pin = destinations.front()->get_pin();
508  auto pin_type = first_pin->get_type();
509  auto pin_name = first_pin->get_name();
510  if (std::all_of(destinations.begin(), destinations.end(), [pin_name](const Endpoint* ep) { return ep->get_pin()->get_name() == pin_name; }))
511  {
512  const auto pg_key = std::make_pair(PinDirection::input, pin_name);
513 
514  std::string prefix;
515  if (const auto prefix_it = pin_prefixes.find(pg_key); prefix_it != pin_prefixes.end())
516  {
517  prefix = prefix_it->second;
518  }
519  else
520  {
521  prefix = "i_" + pin_name;
522  }
523 
524  if (const auto pg_it = pin_groups.find(pg_key); pg_it == pin_groups.end())
525  {
526  auto pin_group = new_mod->create_pin_group(prefix, {pin}, PinDirection::input, pin_type, false, 0, true, true);
527  pin_groups[pg_key] = pin_group.get();
528  }
529  else
530  {
531  if (!new_mod->assign_pin_to_group(pg_it->second, pin))
532  {
533  log_warning("dataflow", "Assign pin to group failed.");
534  }
535  }
536 
537  new_mod->set_pin_name(pin, prefix + "(" + std::to_string(pin->get_group().second) + ")");
538  new_mod->set_pin_type(pin, pin_type);
539  }
540  }
541  else if (pin->get_direction() == PinDirection::output)
542  {
543  const auto sources = pin->get_net()->get_sources([new_mod](const Endpoint* ep) { return ep->get_gate()->get_module() == new_mod; });
544 
545  const auto* first_pin = sources.front()->get_pin();
546  auto pin_type = first_pin->get_type();
547  auto pin_name = first_pin->get_name();
548  if (sources.size() == 1)
549  {
550  const auto pg_key = std::make_pair(PinDirection::output, pin_name);
551 
552  std::string prefix;
553  if (const auto prefix_it = pin_prefixes.find(pg_key); prefix_it != pin_prefixes.end())
554  {
555  prefix = prefix_it->second;
556  }
557  else
558  {
559  prefix = "o_" + pin_name;
560  }
561 
562  if (const auto pg_it = pin_groups.find(pg_key); pg_it == pin_groups.end())
563  {
564  auto pin_group = new_mod->create_pin_group(prefix, {pin}, PinDirection::output, pin_type, false, 0, true, true);
565  pin_groups[pg_key] = pin_group.get();
566  }
567  else
568  {
569  if (!new_mod->assign_pin_to_group(pg_it->second, pin))
570  {
571  log_warning("dataflow", "Assign pin to group failed.");
572  }
573  }
574 
575  new_mod->set_pin_name(pin, prefix + "(" + std::to_string(pin->get_group().second) + ")");
576  new_mod->set_pin_type(pin, pin_type);
577  }
578  }
579  }
580 
581  // rename pins if only single pin in pin group (remove "(" and ")")
582  for (const auto* pin_group : new_mod->get_pin_groups())
583  {
584  if (pin_group->size() == 1)
585  {
586  auto* pin = pin_group->get_pins().front();
587  new_mod->set_pin_name(pin, pin_group->get_name());
588  }
589  }
590  }
591  return OK(group_to_module);
592  }
593 
594  hal::Result<std::unordered_map<u32, Module*>> dataflow::Result::create_modules(const std::map<GateTypeProperty, std::string>& module_suffixes,
595  const std::map<std::pair<PinDirection, std::string>, std::string>& pin_prefixes,
596  const std::unordered_set<u32>& group_ids) const
597  {
598  const auto* gl = this->m_netlist->get_gate_library();
599  std::map<const GateType*, std::string> gate_type_suffixes;
600  for (const auto& suffix : module_suffixes)
601  {
602  for (const auto& [_, type] : gl->get_gate_types([suffix](const GateType* gt) { return gt->has_property(suffix.first); }))
603  {
604  gate_type_suffixes[type] = suffix.second;
605  }
606  }
607 
608  return this->create_modules(gate_type_suffixes, pin_prefixes, group_ids);
609  }
610 
611  std::vector<std::vector<Gate*>> dataflow::Result::get_groups_as_list(const std::unordered_set<u32>& group_ids) const
612  {
613  std::vector<std::vector<Gate*>> groups;
614  for (const auto& [group_id, group] : this->get_groups())
615  {
616  if (!group_ids.empty() && group_ids.find(group_id) == group_ids.end())
617  {
618  continue;
619  }
620 
621  std::vector<Gate*> group_vector;
622  for (const auto& gate : group)
623  {
624  group_vector.push_back(gate);
625  }
626  groups.push_back(group_vector);
627  }
628  return groups;
629  }
630 
631  hal::Result<u32> dataflow::Result::merge_groups(const std::vector<u32>& group_ids)
632  {
633  if (group_ids.empty())
634  {
635  return ERR("no group IDs provided.");
636  }
637 
638  if (group_ids.size() < 2)
639  {
640  return ERR("at least two groups are required for merging.");
641  }
642 
643  if (const auto it = std::find_if(group_ids.begin(), group_ids.end(), [this](u32 id) { return this->m_gates_of_group.find(id) == this->m_gates_of_group.end(); }); it != group_ids.end())
644  {
645  return ERR("a group with ID " + std::to_string(*it) + " does not exist.");
646  }
647 
648  u32 target_group_id = ++(this->m_last_id);
649 
650  // iterate set to make sure that every ID is contained only once
651  std::unordered_set<u32> group_ids_set(group_ids.begin(), group_ids.end());
652  for (auto group_id : group_ids_set)
653  {
654  // new group
655  auto& gates_at_i = this->m_gates_of_group.at(group_id);
656  this->m_gates_of_group[target_group_id].insert(gates_at_i.begin(), gates_at_i.end());
657  this->m_gates_of_group.erase(group_id);
658 
659  std::for_each(gates_at_i.begin(), gates_at_i.end(), [this, target_group_id](const Gate* g) { this->m_parent_group_of_gate.at(g) = target_group_id; });
660 
661  // signals
662  if (const auto signals_it = this->m_group_signals.find(group_id); signals_it != this->m_group_signals.end())
663  {
664  for (auto& signals_of_type : std::get<1>(*signals_it))
665  {
666  auto& signals = std::get<1>(signals_of_type);
667  this->m_group_signals[target_group_id][signals_of_type.first].insert(signals.begin(), signals.end());
668  }
669  this->m_group_signals.erase(signals_it);
670  }
671 
672  // successors / predecessors
673  if (const auto suc_it = this->m_group_successors.find(group_id); suc_it != this->m_group_successors.end())
674  {
675  auto& target_suc_ids = this->m_group_successors[target_group_id];
676  for (auto suc_id : std::get<1>(*suc_it))
677  {
678  auto& pred_ids = this->m_group_predecessors.at(suc_id);
679  pred_ids.insert(target_group_id);
680  target_suc_ids.insert(suc_id);
681  pred_ids.erase(group_id);
682  }
683  }
684 
685  if (const auto pred_it = this->m_group_predecessors.find(group_id); pred_it != this->m_group_predecessors.end())
686  {
687  auto& target_pred_ids = this->m_group_predecessors[target_group_id];
688  for (auto pred_id : std::get<1>(*pred_it))
689  {
690  auto& suc_ids = this->m_group_successors.at(pred_id);
691  suc_ids.insert(target_group_id);
692  target_pred_ids.insert(pred_id);
693  suc_ids.erase(group_id);
694  }
695  }
696 
697  this->m_group_successors.erase(group_id);
698  this->m_group_predecessors.erase(group_id);
699  }
700 
701  return OK(target_group_id);
702  }
703 
704  hal::Result<std::vector<u32>> dataflow::Result::split_group(u32 group_id, const std::vector<std::unordered_set<Gate*>>& new_groups)
705  {
706  if (new_groups.empty())
707  {
708  return ERR("no gates provided to define splits.");
709  }
710 
711  const auto group_it = this->m_gates_of_group.find(group_id);
712  if (group_it == this->m_gates_of_group.end())
713  {
714  return ERR("a group with ID " + std::to_string(group_id) + " does not exist.");
715  }
716 
717  const auto& group_gates = std::get<1>(*group_it);
718 
719  std::unordered_set<const Gate*> seen;
720  for (const auto& gates : new_groups)
721  {
722  for (auto* g : gates)
723  {
724  if (!g)
725  {
726  return ERR("gate is a nullptr.");
727  }
728 
729  if (group_gates.find(g) == group_gates.end())
730  {
731  return ERR("gate '" + g->get_name() + "' with ID " + std::to_string(g->get_id()) + " does not belong to group with ID " + std::to_string(group_id) + ".");
732  }
733 
734  if (seen.find(g) != seen.end())
735  {
736  return ERR("gate '" + g->get_name() + "' with ID " + std::to_string(g->get_id()) + " cannot be assigned to two groups after splitting.");
737  }
738  seen.insert(g);
739  }
740  }
741 
742  if (seen.size() != group_gates.size())
743  {
744  return ERR("size of the target group does not match combined size of the split groups.");
745  }
746 
747  this->m_gates_of_group.erase(group_id);
748  this->m_group_successors.erase(group_id);
749  this->m_group_predecessors.erase(group_id);
750  this->m_group_signals.erase(group_id);
751 
752  std::vector<u32> new_group_ids;
753  for (const auto& gates : new_groups)
754  {
755  auto current_id = ++(this->m_last_id);
756 
757  // new group
758  this->m_gates_of_group[current_id] = gates;
759 
760  for (const auto* g : gates)
761  {
762  this->m_parent_group_of_gate.at(g) = current_id;
763 
764  // signals
765  if (const auto signals_it = this->m_gate_signals.find(g); signals_it != this->m_gate_signals.end())
766  {
767  const auto& signals = std::get<1>(*signals_it);
768 
769  for (const auto type : std::vector<PinType>({PinType::clock, PinType::enable, PinType::reset, PinType::set}))
770  {
771  if (const auto nets_it = signals.find(type); nets_it != signals.end())
772  {
773  const auto& nets = std::get<1>(*nets_it);
774  this->m_group_signals[current_id][type].insert(nets.begin(), nets.end());
775  }
776  }
777  }
778  }
779 
780  new_group_ids.push_back(current_id);
781  }
782 
783  // successors / predecessors (can only be inferred once all new groups have been created)
784  for (const auto current_id : new_group_ids)
785  {
786  for (const auto* g : this->m_gates_of_group.at(current_id))
787  {
788  if (const auto suc_it = this->m_gate_successors.find(g); suc_it != this->m_gate_successors.end())
789  {
790  for (const auto* suc_g : std::get<1>(*suc_it))
791  {
792  this->m_group_successors[current_id].insert(this->m_parent_group_of_gate.at(suc_g));
793  }
794  }
795 
796  if (const auto pred_it = this->m_gate_predecessors.find(g); pred_it != this->m_gate_predecessors.end())
797  {
798  for (const auto* pred_g : std::get<1>(*pred_it))
799  {
800  this->m_group_predecessors[current_id].insert(this->m_parent_group_of_gate.at(pred_g));
801  }
802  }
803  }
804  }
805 
806  return OK(new_group_ids);
807  }
808  } // namespace dataflow
809 } // namespace hal
u32 size
Gate * get_gate() const
Definition: endpoint.cpp:23
Definition: gate.h:58
Gate * get_gate_by_id(const u32 gate_id) const
Definition: netlist.cpp:195
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:355
PinType get_type() const
Definition: pin_group.h:173
hal::Result< u32 > merge_groups(const std::vector< u32 > &group_ids)
Merge multiple groups specified by ID.
Definition: result.cpp:631
hal::Result< std::unordered_set< Gate * > > get_gates_of_group(const u32 group_id) const
Get the gates of the specified group of sequential gates.
Definition: result.cpp:121
hal::Result< std::unordered_set< u32 > > get_group_predecessors(const u32 group_id) const
Get the predecessor groups of the group with the given ID.
Definition: result.cpp:218
hal::Result< std::vector< u32 > > split_group(u32 group_id, const std::vector< std::unordered_set< Gate * >> &new_groups)
Split a group into multiple smaller groups specified by sets of gates.
Definition: result.cpp:704
std::vector< std::vector< Gate * > > get_groups_as_list(const std::unordered_set< u32 > &group_ids={}) const
Get the groups of the dataflow analysis result as a list.
Definition: result.cpp:611
hal::Result< std::filesystem::path > write_dot(const std::filesystem::path &out_path, const std::unordered_set< u32 > &group_ids={}) const
Write the dataflow graph as a DOT graph to the specified location.
Definition: result.cpp:248
hal::Result< std::unordered_map< u32, Module * > > create_modules(const std::unordered_set< u32 > &group_ids={}) const
Create modules for the dataflow analysis result.
Definition: result.cpp:418
hal::Result< std::monostate > write_txt(const std::filesystem::path &out_path, const std::unordered_set< u32 > &group_ids={}) const
Write the groups resulting from dataflow analysis to a .txt file.
Definition: result.cpp:322
hal::Result< std::unordered_set< Net * > > get_group_control_nets(const u32 group_id, const PinType type) const
Get the control nets of the group with the given group ID that are connected to a pin of the specifie...
Definition: result.cpp:150
hal::Result< std::unordered_set< Gate * > > get_gate_successors(const Gate *gate) const
Get the sequential successor gates of the given sequential gate.
Definition: result.cpp:203
const std::unordered_map< u32, std::unordered_set< Gate * > > & get_groups() const
Get the groups of sequential gates resulting from dataflow analysis.
Definition: result.cpp:104
hal::Result< u32 > get_group_id_of_gate(const Gate *gate) const
Get the group ID of the group that contains the given gate.
Definition: result.cpp:133
hal::Result< std::unordered_set< Net * > > get_gate_control_nets(const Gate *gate, const PinType type) const
Get the control nets of the given gate that are connected to a pin of the specified type.
Definition: result.cpp:169
Result(Netlist *nl, const Grouping &grouping)
Definition: result.cpp:29
Netlist * get_netlist() const
Get the netlist on which dataflow analysis has been performed.
Definition: result.cpp:99
hal::Result< std::unordered_set< u32 > > get_group_successors(const u32 group_id) const
Get the successor groups of the group with the given ID.
Definition: result.cpp:188
hal::Result< std::unordered_set< Gate * > > get_gate_predecessors(const Gate *gate) const
Get the sequential predecessor gates of the given sequential gate.
Definition: result.cpp:233
std::vector< Gate * > get_gates() const
Get all gates contained in any of the groups groups.
Definition: result.cpp:109
uint32_t u32
Definition: defines.h:41
#define log_info(channel,...)
Definition: log.h:70
#define log_warning(channel,...)
Definition: log.h:76
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
std::string join(const std::string &joiner, const Iterator &begin, const Iterator &end, const Transform &transform)
Definition: utils.h:458
bool starts_with(const T &s, const T &start)
Definition: utils.h:213
Definition: defines.h:45
PinType
Definition: pin_type.h:36
PinType type
Net * net
std::string name
i32 id
This file contains the struct that holds all information on the result of a dataflow analysis run.
Grouping used during dataflow analysis.
Definition: grouping.h:55
std::unordered_map< u32, std::unordered_set< u32 > > gates_of_group
Definition: grouping.h:89
const NetlistAbstraction & netlist_abstr
Definition: grouping.h:79
std::unordered_set< u32 > get_predecessor_groups_of_group(u32 group_id) const
Get the predecessor groups of a group.
Definition: grouping.cpp:204
std::unordered_set< u32 > get_successor_groups_of_group(u32 group_id) const
Get the successor groups of a group.
Definition: grouping.cpp:173
std::map< PinType, std::unordered_set< u32 > > get_control_signals_of_group(u32 group_id) const
Get the control signals of a group as a map from the control pin type to the connected net IDs.
Definition: grouping.cpp:109