HAL
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::monostate> 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\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  return OK({});
316  }
317 
318  return ERR("failed to open file at '" + write_path.string() + "' for writing dataflow graph.");
319  }
320 
321  hal::Result<std::monostate> dataflow::Result::write_txt(const std::filesystem::path& out_path, const std::unordered_set<u32>& group_ids) const
322  {
323  auto write_path = out_path;
324 
325  if (write_path.empty())
326  {
327  return ERR("output path is empty.");
328  }
329 
330  if (std::filesystem::is_directory(write_path))
331  {
332  write_path /= "groups.txt";
333  }
334 
335  if (write_path.extension() != "txt")
336  {
337  log_info("dataflow", "replacing invalid file extension '{}' with '.txt' ...", write_path.extension().string());
338  write_path.replace_extension("txt");
339  }
340 
341  log_info("dataflow", "writing dataflow gate groups to '{}' ...", write_path.string());
342 
343  std::ofstream ofs(write_path, std::ofstream::out);
344  if (ofs)
345  {
346  ofs << "State:";
347  ofs << "\n\n";
348 
349  for (const auto& [group_id, gates] : this->get_groups())
350  {
351  if (!group_ids.empty() && group_ids.find(group_id) == group_ids.end())
352  {
353  continue;
354  }
355 
356  ofs << "ID:" << group_id << ", ";
357  ofs << "Size:" << gates.size() << ", ";
358  ofs << "CLK: {" << utils::join(", ", nets_to_id_set(this->get_group_control_nets(group_id, PinType::clock).get())) << "}, ";
359  ofs << "EN: {" << utils::join(", ", nets_to_id_set(this->get_group_control_nets(group_id, PinType::enable).get())) << "}, ";
360  ofs << "R: {" << utils::join(", ", nets_to_id_set(this->get_group_control_nets(group_id, PinType::reset).get())) << "}, ";
361  ofs << "S: {" << utils::join(", ", nets_to_id_set(this->get_group_control_nets(group_id, PinType::set).get())) << "}" << std::endl;
362 
363  if (auto res = this->get_group_successors(group_id); res.is_ok())
364  {
365  auto unsorted_successors = res.get();
366  ofs << " Successors: {" + utils::join(", ", std::set<u32>(unsorted_successors.begin(), unsorted_successors.end())) << "}" << std::endl;
367  }
368 
369  if (auto res = this->get_group_predecessors(group_id); res.is_ok())
370  {
371  auto unsorted_predecessors = res.get();
372  ofs << " Predecessors: {" + utils::join(", ", std::set<u32>(unsorted_predecessors.begin(), unsorted_predecessors.end())) << "}" << std::endl;
373  }
374 
375  std::unordered_map<u32, std::vector<std::string>> texts;
376  std::unordered_map<u32, u32> text_max_lengths;
377 
378  std::set<u32> gate_ids;
379  for (const auto& gate : gates)
380  {
381  auto name = gate->get_name() + ", ";
382  auto type = "type: " + gate->get_type()->get_name() + ", ";
383  auto id = "id: " + std::to_string(gate->get_id()) + ", ";
384  std::string stages = "RS: ";
385 
386  std::vector<std::string> data = {name, type, id, stages};
387  for (u32 i = 0; i < data.size(); ++i)
388  {
389  text_max_lengths[i] = std::max(text_max_lengths[i], (u32)data[i].size());
390  }
391 
392  u32 gate_id = gate->get_id();
393  texts.emplace(gate_id, data);
394  gate_ids.insert(gate_id);
395  }
396 
397  for (const auto& gate_id : gate_ids)
398  {
399  auto& data = texts[gate_id];
400  for (u32 i = 0; i < data.size(); ++i)
401  {
402  ofs << std::setw(text_max_lengths[i]) << std::left << data[i];
403  }
404  ofs << std::endl;
405  }
406  ofs << "\n";
407  }
408  ofs.close();
409 
410  log_info("dataflow", "successfully written dataflow gate groups to '{}'.", write_path.string());
411  return OK({});
412  }
413 
414  return ERR("failed to open file at '" + write_path.string() + "' for writing dataflow gate groups.");
415  }
416 
418  {
419  return create_modules(std::map<const GateType*, std::string>(), std::map<std::pair<PinDirection, std::string>, std::string>(), group_ids);
420  }
421 
422  hal::Result<std::unordered_map<u32, Module*>> dataflow::Result::create_modules(const std::map<const GateType*, std::string>& module_suffixes,
423  const std::map<std::pair<PinDirection, std::string>, std::string>& pin_prefixes,
424  const std::unordered_set<u32>& group_ids) const
425  {
426  auto* nl = this->get_netlist();
427 
428  // delete all modules that start with DANA
429  std::vector<Module*> modules_to_delete;
430  for (const auto mod : nl->get_modules())
431  {
432  if (utils::starts_with(mod->get_name(), std::string("DANA_")))
433  {
434  modules_to_delete.push_back(mod);
435  }
436  }
437 
438  for (auto* mod : modules_to_delete)
439  {
440  nl->delete_module(mod);
441  }
442  log_info("dataflow", "successfully deleted old DANA modules");
443 
444  // create new modules and try to keep hierarchy if possible
445  std::unordered_map<u32, Module*> group_to_module;
446  for (const auto& [group_id, group] : this->get_groups())
447  {
448  if (!group_ids.empty() && group_ids.find(group_id) == group_ids.end())
449  {
450  continue;
451  }
452 
453  bool gate_hierachy_matches_for_all = true;
454  bool gate_type_matches_for_all = true;
455  bool first_run = true;
456  const GateType* gate_type;
457  auto* reference_module = nl->get_top_module();
458 
459  std::vector<Gate*> gates;
460  for (const auto gate : group)
461  {
462  gates.push_back(gate);
463 
464  if (first_run)
465  {
466  reference_module = gate->get_module();
467  gate_type = gate->get_type();
468  first_run = false;
469  }
470  else if (gate->get_module() != reference_module)
471  {
472  gate_hierachy_matches_for_all = false;
473  }
474 
475  if (gate_type != gate->get_type())
476  {
477  gate_hierachy_matches_for_all = false;
478  }
479  }
480 
481  if (!gate_hierachy_matches_for_all)
482  {
483  reference_module = nl->get_top_module();
484  }
485 
486  std::string suffix;
487  if (const auto it = module_suffixes.find(gate_type); gate_type_matches_for_all && it != module_suffixes.end())
488  {
489  suffix = it->second;
490  }
491  else
492  {
493  suffix = "module";
494  }
495 
496  auto* new_mod = nl->create_module("DANA_" + suffix + "_" + std::to_string(group_id), reference_module, gates);
497  group_to_module[group_id] = new_mod;
498 
499  std::map<const std::pair<PinDirection, std::string>, PinGroup<ModulePin>*> pin_groups;
500  for (auto* pin : new_mod->get_pins())
501  {
502  if (pin->get_direction() == PinDirection::input)
503  {
504  const auto destinations = pin->get_net()->get_destinations([new_mod](const Endpoint* ep) { return ep->get_gate()->get_module() == new_mod; });
505 
506  const auto* first_pin = destinations.front()->get_pin();
507  auto pin_type = first_pin->get_type();
508  auto pin_name = first_pin->get_name();
509  if (std::all_of(destinations.begin(), destinations.end(), [pin_name](const Endpoint* ep) { return ep->get_pin()->get_name() == pin_name; }))
510  {
511  const auto pg_key = std::make_pair(PinDirection::input, pin_name);
512 
513  std::string prefix;
514  if (const auto prefix_it = pin_prefixes.find(pg_key); prefix_it != pin_prefixes.end())
515  {
516  prefix = prefix_it->second;
517  }
518  else
519  {
520  prefix = "i_" + pin_name;
521  }
522 
523  if (const auto pg_it = pin_groups.find(pg_key); pg_it == pin_groups.end())
524  {
525  auto* pin_group = pin->get_group().first;
526  pin_groups[pg_key] = pin_group;
527  new_mod->set_pin_group_name(pin_group, prefix);
528  new_mod->set_pin_group_type(pin_group, pin_type);
529  }
530  else
531  {
532  if (!new_mod->assign_pin_to_group(pg_it->second, pin))
533  {
534  log_warning("dataflow", "Assign pin to group failed.");
535  }
536  }
537 
538  new_mod->set_pin_name(pin, prefix + "(" + std::to_string(pin->get_group().second) + ")");
539  new_mod->set_pin_type(pin, pin_type);
540  }
541  }
542  else if (pin->get_direction() == PinDirection::output)
543  {
544  const auto sources = pin->get_net()->get_sources([new_mod](const Endpoint* ep) { return ep->get_gate()->get_module() == new_mod; });
545 
546  const auto* first_pin = sources.front()->get_pin();
547  auto pin_type = first_pin->get_type();
548  auto pin_name = first_pin->get_name();
549  if (sources.size() == 1)
550  {
551  const auto pg_key = std::make_pair(PinDirection::output, pin_name);
552 
553  std::string prefix;
554  if (const auto prefix_it = pin_prefixes.find(pg_key); prefix_it != pin_prefixes.end())
555  {
556  prefix = prefix_it->second;
557  }
558  else
559  {
560  prefix = "o_" + pin_name;
561  }
562 
563  if (const auto pg_it = pin_groups.find(pg_key); pg_it == pin_groups.end())
564  {
565  auto* pin_group = pin->get_group().first;
566  pin_groups[pg_key] = pin_group;
567  new_mod->set_pin_group_name(pin_group, prefix);
568  new_mod->set_pin_group_type(pin_group, pin_type);
569  }
570  else
571  {
572  if (!new_mod->assign_pin_to_group(pg_it->second, pin))
573  {
574  log_warning("dataflow", "Assign pin to group failed.");
575  }
576  }
577 
578  new_mod->set_pin_name(pin, prefix + "(" + std::to_string(pin->get_group().second) + ")");
579  new_mod->set_pin_type(pin, pin_type);
580  }
581  }
582  }
583 
584  // rename pins if only single pin in pin group (remove "(" and ")")
585  for (const auto* pin_group : new_mod->get_pin_groups())
586  {
587  if (pin_group->size() == 1)
588  {
589  auto* pin = pin_group->get_pins().front();
590  new_mod->set_pin_name(pin, pin_group->get_name());
591  }
592  }
593  }
594  return OK(group_to_module);
595  }
596 
597  hal::Result<std::unordered_map<u32, Module*>> dataflow::Result::create_modules(const std::map<GateTypeProperty, std::string>& module_suffixes,
598  const std::map<std::pair<PinDirection, std::string>, std::string>& pin_prefixes,
599  const std::unordered_set<u32>& group_ids) const
600  {
601  const auto* gl = this->m_netlist->get_gate_library();
602  std::map<const GateType*, std::string> gate_type_suffixes;
603  for (const auto& suffix : module_suffixes)
604  {
605  for (const auto& [_, type] : gl->get_gate_types([suffix](const GateType* gt) { return gt->has_property(suffix.first); }))
606  {
607  gate_type_suffixes[type] = suffix.second;
608  }
609  }
610 
611  return this->create_modules(gate_type_suffixes, pin_prefixes, group_ids);
612  }
613 
614  std::vector<std::vector<Gate*>> dataflow::Result::get_groups_as_list(const std::unordered_set<u32>& group_ids) const
615  {
616  std::vector<std::vector<Gate*>> groups;
617  for (const auto& [group_id, group] : this->get_groups())
618  {
619  if (!group_ids.empty() && group_ids.find(group_id) == group_ids.end())
620  {
621  continue;
622  }
623 
624  std::vector<Gate*> group_vector;
625  for (const auto& gate : group)
626  {
627  group_vector.push_back(gate);
628  }
629  groups.push_back(group_vector);
630  }
631  return groups;
632  }
633 
634  hal::Result<u32> dataflow::Result::merge_groups(const std::vector<u32>& group_ids)
635  {
636  if (group_ids.empty())
637  {
638  return ERR("no group IDs provided.");
639  }
640 
641  if (group_ids.size() < 2)
642  {
643  return ERR("at least two groups are required for merging.");
644  }
645 
646  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())
647  {
648  return ERR("a group with ID " + std::to_string(*it) + " does not exist.");
649  }
650 
651  u32 target_group_id = ++(this->m_last_id);
652 
653  // iterate set to make sure that every ID is contained only once
654  std::unordered_set<u32> group_ids_set(group_ids.begin(), group_ids.end());
655  for (auto group_id : group_ids_set)
656  {
657  // new group
658  auto& gates_at_i = this->m_gates_of_group.at(group_id);
659  this->m_gates_of_group[target_group_id].insert(gates_at_i.begin(), gates_at_i.end());
660  this->m_gates_of_group.erase(group_id);
661 
662  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; });
663 
664  // signals
665  if (const auto signals_it = this->m_group_signals.find(group_id); signals_it != this->m_group_signals.end())
666  {
667  for (auto& signals_of_type : std::get<1>(*signals_it))
668  {
669  auto& signals = std::get<1>(signals_of_type);
670  this->m_group_signals[target_group_id][signals_of_type.first].insert(signals.begin(), signals.end());
671  }
672  this->m_group_signals.erase(signals_it);
673  }
674 
675  // successors / predecessors
676  if (const auto suc_it = this->m_group_successors.find(group_id); suc_it != this->m_group_successors.end())
677  {
678  auto& target_suc_ids = this->m_group_successors[target_group_id];
679  for (auto suc_id : std::get<1>(*suc_it))
680  {
681  auto& pred_ids = this->m_group_predecessors.at(suc_id);
682  pred_ids.insert(target_group_id);
683  target_suc_ids.insert(suc_id);
684  pred_ids.erase(group_id);
685  }
686  }
687 
688  if (const auto pred_it = this->m_group_predecessors.find(group_id); pred_it != this->m_group_predecessors.end())
689  {
690  auto& target_pred_ids = this->m_group_predecessors[target_group_id];
691  for (auto pred_id : std::get<1>(*pred_it))
692  {
693  auto& suc_ids = this->m_group_successors.at(pred_id);
694  suc_ids.insert(target_group_id);
695  target_pred_ids.insert(pred_id);
696  suc_ids.erase(group_id);
697  }
698  }
699 
700  this->m_group_successors.erase(group_id);
701  this->m_group_predecessors.erase(group_id);
702  }
703 
704  return OK(target_group_id);
705  }
706 
707  hal::Result<std::vector<u32>> dataflow::Result::split_group(u32 group_id, const std::vector<std::unordered_set<Gate*>>& new_groups)
708  {
709  if (new_groups.empty())
710  {
711  return ERR("no gates provided to define splits.");
712  }
713 
714  const auto group_it = this->m_gates_of_group.find(group_id);
715  if (group_it == this->m_gates_of_group.end())
716  {
717  return ERR("a group with ID " + std::to_string(group_id) + " does not exist.");
718  }
719 
720  const auto& group_gates = std::get<1>(*group_it);
721 
722  std::unordered_set<const Gate*> seen;
723  for (const auto& gates : new_groups)
724  {
725  for (auto* g : gates)
726  {
727  if (!g)
728  {
729  return ERR("gate is a nullptr.");
730  }
731 
732  if (group_gates.find(g) == group_gates.end())
733  {
734  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) + ".");
735  }
736 
737  if (seen.find(g) != seen.end())
738  {
739  return ERR("gate '" + g->get_name() + "' with ID " + std::to_string(g->get_id()) + " cannot be assigned to two groups after splitting.");
740  }
741  seen.insert(g);
742  }
743  }
744 
745  if (seen.size() != group_gates.size())
746  {
747  return ERR("size of the target group does not match combined size of the split groups.");
748  }
749 
750  this->m_gates_of_group.erase(group_id);
751  this->m_group_successors.erase(group_id);
752  this->m_group_predecessors.erase(group_id);
753  this->m_group_signals.erase(group_id);
754 
755  std::vector<u32> new_group_ids;
756  for (const auto& gates : new_groups)
757  {
758  auto current_id = ++(this->m_last_id);
759 
760  // new group
761  this->m_gates_of_group[current_id] = gates;
762 
763  for (const auto* g : gates)
764  {
765  this->m_parent_group_of_gate.at(g) = current_id;
766 
767  // signals
768  if (const auto signals_it = this->m_gate_signals.find(g); signals_it != this->m_gate_signals.end())
769  {
770  const auto& signals = std::get<1>(*signals_it);
771 
772  for (const auto type : std::vector<PinType>({PinType::clock, PinType::enable, PinType::reset, PinType::set}))
773  {
774  if (const auto nets_it = signals.find(type); nets_it != signals.end())
775  {
776  const auto& nets = std::get<1>(*nets_it);
777  this->m_group_signals[current_id][type].insert(nets.begin(), nets.end());
778  }
779  }
780  }
781  }
782 
783  new_group_ids.push_back(current_id);
784  }
785 
786  // successors / predecessors (can only be inferred once all new groups have been created)
787  for (const auto current_id : new_group_ids)
788  {
789  for (const auto* g : this->m_gates_of_group.at(current_id))
790  {
791  if (const auto suc_it = this->m_gate_successors.find(g); suc_it != this->m_gate_successors.end())
792  {
793  for (const auto* suc_g : std::get<1>(*suc_it))
794  {
795  this->m_group_successors[current_id].insert(this->m_parent_group_of_gate.at(suc_g));
796  }
797  }
798 
799  if (const auto pred_it = this->m_gate_predecessors.find(g); pred_it != this->m_gate_predecessors.end())
800  {
801  for (const auto* pred_g : std::get<1>(*pred_it))
802  {
803  this->m_group_predecessors[current_id].insert(this->m_parent_group_of_gate.at(pred_g));
804  }
805  }
806  }
807  }
808 
809  return OK(new_group_ids);
810  }
811  } // namespace dataflow
812 } // namespace hal
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:193
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:353
PinType get_type() const
Definition: pin_group.h:170
hal::Result< u32 > merge_groups(const std::vector< u32 > &group_ids)
Merge multiple groups specified by ID.
Definition: result.cpp:634
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:707
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:614
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:417
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:321
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
hal::Result< std::monostate > 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
#define log_info(channel,...)
Definition: log.h:70
#define log_warning(channel,...)
Definition: log.h:76
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49
CORE_API bool starts_with(const T &s, const T &start)
Definition: utils.h:167
CORE_API std::string join(const std::string &joiner, const Iterator &begin, const Iterator &end, const Transform &transform)
Definition: utils.h:412
PinType
Definition: pin_type.h:36
quint32 u32
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