HAL
netlist_internal_manager.cpp
Go to the documentation of this file.
2 
9 #include "hal_core/netlist/net.h"
12 #include "hal_core/utilities/log.h"
13 
14 namespace hal
15 {
16  NetlistInternalManager::NetlistInternalManager(Netlist* nl, EventHandler* eh)
17  {
18  m_netlist = nl;
19  m_event_handler = eh;
20  assert(nl != nullptr);
21  assert(eh != nullptr);
22  }
23 
24  //######################################################################
25  //### netlist ###
26  //######################################################################
27 
28  Result<std::unique_ptr<Netlist>> NetlistInternalManager::copy_netlist(const Netlist* nl) const
29  {
30  std::unique_ptr<Netlist> c_netlist = netlist_factory::create_netlist(nl->m_gate_library);
31  if (c_netlist == nullptr)
32  {
33  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to create netlist");
34  }
35 
36  c_netlist->enable_automatic_net_checks(false);
37 
38  // manager, netlist_id, and top_module are set in the constructor
39 
40  // copy design name, device name, input filename
41  c_netlist->set_design_name(nl->get_design_name());
42  c_netlist->set_device_name(nl->get_device_name());
43  c_netlist->set_input_filename(nl->get_input_filename());
44 
45  // copy nets
46  for (const Net* net : nl->m_nets)
47  {
48  Net* c_net = c_netlist->create_net(net->m_id, net->m_name);
49  if (c_net == nullptr)
50  {
51  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to create copied net '" + net->m_name + "' with ID " + std::to_string(net->m_id));
52  }
53  c_net->m_data = net->m_data;
54  }
55 
56  // copy gates
57  for (const Gate* gate : nl->m_gates)
58  {
59  Gate* c_gate = c_netlist->create_gate(gate->m_id, gate->m_type, gate->m_name, gate->m_x, gate->m_y);
60  if (c_gate == nullptr)
61  {
62  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to create copied gate '" + gate->m_name + "' with ID " + std::to_string(gate->m_id));
63  }
64 
65  for (const auto& [name, func] : gate->get_boolean_functions(true))
66  {
67  c_gate->add_boolean_function(name, func);
68  }
69 
70  for (const Endpoint* in_point : gate->get_fan_in_endpoints())
71  {
72  const auto net_id = in_point->get_net()->m_id;
73  auto c_net = c_netlist->get_net_by_id(net_id);
74  if (c_net == nullptr)
75  {
76  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to get copied net by ID " + std::to_string(net_id));
77  }
78 
79  if (!c_net->add_destination(c_gate, in_point->get_pin()))
80  {
81  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to add destination to copied net '" + c_net->m_name + "' with ID "
82  + std::to_string(c_net->m_id));
83  }
84  }
85 
86  for (const Endpoint* out_point : gate->get_fan_out_endpoints())
87  {
88  const auto net_id = out_point->get_net()->m_id;
89  auto c_net = c_netlist->get_net_by_id(net_id);
90  if (c_net == nullptr)
91  {
92  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to get copied net by ID " + std::to_string(net_id));
93  }
94 
95  if (!c_net->add_source(c_gate, out_point->get_pin()))
96  {
97  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to add source to copied net '" + c_net->m_name + "' with ID "
98  + std::to_string(c_net->m_id));
99  }
100  }
101 
102  c_gate->m_data = gate->m_data;
103  }
104 
105  // copy modules
106  for (const Module* module : nl->m_modules)
107  {
108  // ignore top module, since this is already created by the constructor
109  if (module->m_id == 1)
110  {
111  c_netlist->m_top_module->m_data = module->get_data_map();
112  c_netlist->m_top_module->m_type = module->m_type;
113  continue;
114  }
115 
116  std::vector<Gate*> c_gates;
117  for (const Gate* gate : module->m_gates)
118  {
119  // find gates of module in the copied netlist by id
120  Gate* c_gate = c_netlist->get_gate_by_id(gate->m_id);
121  if (c_gate == nullptr)
122  {
123  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to get copied gate by ID " + std::to_string(gate->m_id));
124  }
125  c_gates.push_back(c_gate);
126  }
127 
128  // create all modules with the top module as parent module and update later
129  Module* c_module = c_netlist->create_module(module->m_id, module->m_name, c_netlist->m_top_module, c_gates);
130  if (c_module == nullptr)
131  {
132  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to create copied module '" + module->m_name + "' with ID " + std::to_string(module->m_id));
133  }
134 
135  c_module->m_data = module->m_data;
136  c_module->m_type = module->m_type;
137  }
138 
139  // update parent_module in modules
140  for (const Module* module : nl->m_modules)
141  {
142  // ignore top_module
143  if (module->m_parent == nullptr)
144  {
145  continue;
146  }
147 
148  // find parent and child module in the copied netlist by id
149  const u32 module_id = module->m_id;
150  const u32 parent_id = module->m_parent->m_id;
151  Module* c_module = c_netlist->get_module_by_id(module_id);
152  Module* c_parent = c_netlist->get_module_by_id(parent_id);
153 
154  if (!c_module->set_parent_module(c_parent))
155  {
156  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to set copied module '" + c_parent->m_name + "' with ID " + std::to_string(module->m_id)
157  + " as parent module of '" + c_module->m_name + "' with ID " + std::to_string(c_module->m_id));
158  }
159  }
160 
161  // copy groupings
162  for (const Grouping* grouping : nl->m_groupings)
163  {
164  Grouping* c_grouping = c_netlist->create_grouping(grouping->m_id, grouping->m_name);
165  if (c_grouping == nullptr)
166  {
167  return ERR("could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to create copied grouping '" + grouping->m_name + "' with ID "
168  + std::to_string(grouping->m_id));
169  }
170 
171  for (const Module* module : grouping->m_modules)
172  {
173  const u32 module_id = module->m_id;
174  c_grouping->assign_module_by_id(module_id);
175  }
176 
177  for (const Net* net : grouping->m_nets)
178  {
179  const u32 net_id = net->m_id;
180  c_grouping->assign_net_by_id(net_id);
181  }
182 
183  for (const Gate* gate : grouping->m_gates)
184  {
185  const u32 gate_id = gate->m_id;
186  c_grouping->assign_gate_by_id(gate_id);
187  }
188  }
189 
190  // mark globals
191  for (const Net* global_input_net : nl->m_global_input_nets)
192  {
193  Net* c_global_input_net = c_netlist->get_net_by_id(global_input_net->m_id);
194  c_netlist->mark_global_input_net(c_global_input_net);
195  }
196  for (const Net* global_output_net : nl->m_global_output_nets)
197  {
198  Net* c_global_output_net = c_netlist->get_net_by_id(global_output_net->m_id);
199  c_netlist->mark_global_output_net(c_global_output_net);
200  }
201  for (const Gate* gnd_gate : nl->m_gnd_gates)
202  {
203  Gate* c_gnd_gate = c_netlist->get_gate_by_id(gnd_gate->m_id);
204  c_netlist->mark_gnd_gate(c_gnd_gate);
205  }
206  for (const Gate* vcc_gate : nl->m_vcc_gates)
207  {
208  Gate* c_vcc_gate = c_netlist->get_gate_by_id(vcc_gate->m_id);
209  c_netlist->mark_vcc_gate(c_vcc_gate);
210  }
211 
212  c_netlist->m_design_name = nl->m_design_name;
213  c_netlist->m_device_name = nl->m_device_name;
214  c_netlist->m_file_name = nl->m_file_name;
215 
216  // update ids last, after all the creation
217  c_netlist->m_next_gate_id = nl->m_next_gate_id;
218  c_netlist->m_used_gate_ids = nl->m_used_gate_ids;
219  c_netlist->m_free_gate_ids = nl->m_free_gate_ids;
220 
221  c_netlist->m_next_net_id = nl->m_next_net_id;
222  c_netlist->m_used_net_ids = nl->m_used_net_ids;
223  c_netlist->m_free_net_ids = nl->m_free_net_ids;
224 
225  c_netlist->m_next_module_id = nl->m_next_module_id;
226  c_netlist->m_used_module_ids = nl->m_used_module_ids;
227  c_netlist->m_free_module_ids = nl->m_free_module_ids;
228 
229  c_netlist->m_next_grouping_id = nl->m_next_grouping_id;
230  c_netlist->m_used_grouping_ids = nl->m_used_grouping_ids;
231  c_netlist->m_free_grouping_ids = nl->m_free_grouping_ids;
232 
233  // copy module port names
234  for (Module* module : nl->m_modules)
235  {
236  Module* c_module = c_netlist->get_module_by_id(module->m_id);
237  c_module->update_nets();
238 
239  for (const std::unique_ptr<PinGroup<ModulePin>>& pin_group : module->m_pin_groups)
240  {
241  std::vector<ModulePin*> c_pins;
242  for (ModulePin* pin : pin_group->get_pins())
243  {
244  if (const auto res = c_module->create_pin(pin->get_id(), pin->get_name(), c_netlist->get_net_by_id(pin->get_net()->m_id), PinType::none, false); res.is_error())
245  {
246  return ERR_APPEND(res.get_error(),
247  "could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to create copied module pin '" + pin->get_name() + "' of module '"
248  + c_module->m_name + "' with ID " + std::to_string(c_module->m_id));
249  }
250  else
251  {
252  c_pins.push_back(res.get());
253  }
254  }
255 
256  if (const auto res = c_module->create_pin_group(
257  pin_group->get_id(), pin_group->get_name(), c_pins, pin_group->get_direction(), pin_group->get_type(), pin_group->is_ascending(), pin_group->get_start_index());
258  res.is_error())
259  {
260  return ERR_APPEND(res.get_error(),
261  "could not copy netlist with ID " + std::to_string(nl->get_id()) + ": failed to create copied module pin group '" + pin_group->get_name() + "' of module '"
262  + c_module->m_name + "' with ID " + std::to_string(c_module->m_id));
263  }
264  }
265 
266  c_module->m_next_input_index = module->m_next_input_index;
267  c_module->m_next_inout_index = module->m_next_inout_index;
268  c_module->m_next_output_index = module->m_next_output_index;
269  }
270 
271  c_netlist->enable_automatic_net_checks(true);
272  return OK(std::move(c_netlist));
273  }
274 
275  //######################################################################
276  //### gates ###
277  //######################################################################
278 
279  Gate* NetlistInternalManager::create_gate(const u32 id, GateType* gt, const std::string& name, i32 x, i32 y)
280  {
281  if (id == 0)
282  {
283  log_error("gate", "ID 0 represents an invalid gate ID.");
284  return nullptr;
285  }
286  if (m_netlist->m_used_gate_ids.find(id) != m_netlist->m_used_gate_ids.end())
287  {
288  log_error("gate", "gate ID {} is already taken in netlist with ID {}.", id, m_netlist->m_netlist_id);
289  return nullptr;
290  }
291  if (gt == nullptr)
292  {
293  log_error("gate", "nullptr given for gate type.", id);
294  return nullptr;
295  }
296  if (this->is_gate_type_invalid(gt))
297  {
298  log_error("gate", "gate type '{}' with ID {} is invalid.", gt->get_name(), gt->get_id());
299  return nullptr;
300  }
301  if (utils::trim(name).empty())
302  {
303  log_error("gate", "gate name cannot be empty.");
304  return nullptr;
305  }
306 
307  auto new_gate = std::unique_ptr<Gate>(new Gate(this, m_event_handler, id, gt, name, x, y));
308 
309  auto free_id_it = m_netlist->m_free_gate_ids.find(id);
310  if (free_id_it != m_netlist->m_free_gate_ids.end())
311  {
312  m_netlist->m_free_gate_ids.erase(free_id_it);
313  }
314 
315  m_netlist->m_used_gate_ids.insert(id);
316 
317  // add gate to top module
318  new_gate->m_module = m_netlist->m_top_module;
319 
320  auto raw = new_gate.get();
321 
322  m_netlist->m_gates_map[id] = std::move(new_gate);
323  m_netlist->m_gates_set.insert(raw);
324  m_netlist->m_gates.push_back(raw);
325 
326  m_netlist->m_top_module->m_gates_map[id] = raw;
327  m_netlist->m_top_module->m_gates.push_back(raw);
328 
329  // notify
330  m_event_handler->notify(ModuleEvent::event::gate_assigned, m_netlist->m_top_module, id);
331  m_event_handler->notify(GateEvent::event::created, raw);
332 
333  return raw;
334  }
335 
336  bool NetlistInternalManager::delete_gate(Gate* gate)
337  {
338  if (!m_netlist->is_gate_in_netlist(gate))
339  {
340  return false;
341  }
342 
343  for (auto ep : gate->get_fan_out_endpoints())
344  {
345  if (!net_remove_source(ep->get_net(), ep))
346  {
347  return false;
348  }
349  }
350 
351  for (auto ep : gate->get_fan_in_endpoints())
352  {
353  if (!net_remove_destination(ep->get_net(), ep))
354  {
355  return false;
356  }
357  }
358 
359  // remove from grouping
360  if (Grouping* g = gate->get_grouping(); g != nullptr)
361  {
362  g->remove_gate(gate);
363  }
364 
365  // check global_gnd and global_vcc gates
366  m_netlist->unmark_gnd_gate(gate);
367  m_netlist->unmark_vcc_gate(gate);
368 
369  // remove gate from modules
370  gate->m_module->m_gates_map.erase(gate->m_module->m_gates_map.find(gate->get_id()));
371  utils::unordered_vector_erase(gate->m_module->m_gates, gate);
372 
373  auto it = m_netlist->m_gates_map.find(gate->get_id());
374  auto ptr = std::move(it->second);
375  m_netlist->m_gates_map.erase(it);
376  m_netlist->m_gates_set.erase(gate);
377  utils::unordered_vector_erase(m_netlist->m_gates, gate);
378 
379  // free ids
380  m_netlist->m_free_gate_ids.insert(gate->get_id());
381  m_netlist->m_used_gate_ids.erase(gate->get_id());
382 
383  m_event_handler->notify(ModuleEvent::event::gate_removed, gate->m_module, gate->get_id());
384  m_event_handler->notify(GateEvent::event::removed, gate);
385 
386  return true;
387  }
388 
389  bool NetlistInternalManager::is_gate_type_invalid(GateType* gt) const
390  {
391  return !m_netlist->m_gate_library->contains_gate_type(gt);
392  }
393 
394  //######################################################################
395  //### nets ###
396  //######################################################################
397 
398  Net* NetlistInternalManager::create_net(const u32 id, const std::string& name)
399  {
400  if (id == 0)
401  {
402  log_error("net", "ID 0 represents an invalid net ID.");
403  return nullptr;
404  }
405  if (m_netlist->m_used_net_ids.find(id) != m_netlist->m_used_net_ids.end())
406  {
407  log_error("net", "net ID {} is already taken in netlist with ID {}.", id, m_netlist->m_netlist_id);
408  return nullptr;
409  }
410  if (utils::trim(name).empty())
411  {
412  log_error("net", "net name cannot be empty.");
413  return nullptr;
414  }
415 
416  auto new_net = std::unique_ptr<Net>(new Net(this, m_event_handler, id, name));
417 
418  auto free_id_it = m_netlist->m_free_net_ids.find(id);
419  if (free_id_it != m_netlist->m_free_net_ids.end())
420  {
421  m_netlist->m_free_net_ids.erase(free_id_it);
422  }
423 
424  m_netlist->m_used_net_ids.insert(id);
425 
426  // add net to netlist
427  auto raw = new_net.get();
428  m_netlist->m_nets_map[id] = std::move(new_net);
429  m_netlist->m_nets_set.insert(raw);
430  m_netlist->m_nets.push_back(raw);
431 
432  // notify
433  m_event_handler->notify(NetEvent::event::created, raw);
434 
435  return raw;
436  }
437 
438  bool NetlistInternalManager::delete_net(Net* net)
439  {
440  if (!m_netlist->is_net_in_netlist(net))
441  {
442  return false;
443  }
444 
445  auto dsts = net->m_destinations_raw;
446  for (auto dst : dsts)
447  {
448  if (!this->net_remove_destination(net, dst))
449  {
450  return false;
451  }
452  }
453 
454  auto srcs = net->m_sources_raw;
455  for (auto src : srcs)
456  {
457  if (!this->net_remove_source(net, src))
458  {
459  return false;
460  }
461  }
462 
463  // remove from grouping
464  if (Grouping* g = net->get_grouping(); g != nullptr)
465  {
466  g->remove_net(net);
467  }
468 
469  // check global_input and global_output gates
470  m_netlist->unmark_global_input_net(net);
471  m_netlist->unmark_global_output_net(net);
472 
473  // remove net from netlist
474  auto it = m_netlist->m_nets_map.find(net->get_id());
475  auto ptr = std::move(it->second);
476  m_netlist->m_nets_map.erase(it);
477  m_netlist->m_nets_set.erase(net);
478  utils::unordered_vector_erase(m_netlist->m_nets, net);
479 
480  m_netlist->m_free_net_ids.insert(net->get_id());
481  m_netlist->m_used_net_ids.erase(net->get_id());
482 
483  m_event_handler->notify(NetEvent::event::removed, net);
484 
485  return true;
486  }
487 
488  Endpoint* NetlistInternalManager::net_add_source(Net* net, Gate* gate, GatePin* pin)
489  {
490  if (!m_netlist->is_net_in_netlist(net) || !m_netlist->is_gate_in_netlist(gate) || pin == nullptr)
491  {
492  return nullptr;
493  }
494 
495  if (net->is_a_source(gate, pin))
496  {
497  log_error("net",
498  "pin '{}' of gate '{}' with ID {} is already a source of net '{}' with ID {} in netlist with ID {}.",
499  pin->get_name(),
500  gate->get_name(),
501  gate->get_id(),
502  net->get_name(),
503  net->get_id(),
504  m_netlist->m_netlist_id);
505  return nullptr;
506  }
507 
508  // check whether pin is valid for this gate
509  auto output_pins = gate->get_type()->get_output_pins();
510 
511  if ((std::find(output_pins.begin(), output_pins.end(), pin) == output_pins.end()))
512  {
513  log_error("net", "gate '{}' with ID {} has no output pin called '{}' in netlist with ID {}.", gate->get_name(), gate->get_id(), pin->get_name(), m_netlist->m_netlist_id);
514  return nullptr;
515  }
516 
517  // check whether src has already an assigned net
518  if (auto fan_out_net = gate->get_fan_out_net(pin); fan_out_net != nullptr)
519  {
520  log_error("net",
521  "gate '{}' with ID {} is already connected to net '{}' with ID {} at output pin '{}', cannot assign new net '{}' with ID {} in netlist with ID {}.",
522  gate->get_name(),
523  gate->get_id(),
524  fan_out_net->get_name(),
525  fan_out_net->get_id(),
526  pin->get_name(),
527  net->get_name(),
528  net->get_id(),
529  m_netlist->m_netlist_id);
530  return nullptr;
531  }
532 
533  auto new_endpoint = std::unique_ptr<Endpoint>(new Endpoint(gate, pin, net, false));
534  auto new_endpoint_raw = new_endpoint.get();
535  net->m_sources.push_back(std::move(new_endpoint));
536  net->m_sources_raw.push_back(new_endpoint_raw);
537  gate->m_out_endpoints.push_back(new_endpoint_raw);
538  gate->m_out_nets.push_back(net);
539 
540  // update internal nets and port nets
541  if (m_net_checks_enabled)
542  {
543  if (const auto res = gate->get_module()->check_net(net, true); res.is_error())
544  {
545  log_error("net", "{}", res.get_error().get());
546  return nullptr;
547  }
548 
549  for (Endpoint* ep : net->get_destinations())
550  {
551  if (const auto res = ep->get_gate()->get_module()->check_net(net, true); res.is_error())
552  {
553  log_error("net", "{}", res.get_error().get());
554  return nullptr;
555  }
556  }
557  }
558 
559  m_event_handler->notify(NetEvent::event::src_added, net, gate->get_id());
560 
561  return new_endpoint_raw;
562  }
563 
564  bool NetlistInternalManager::net_remove_source(Net* net, Endpoint* ep)
565  {
566  auto gate = ep->get_gate();
567 
568  if (!m_netlist->is_net_in_netlist(net) || !m_netlist->is_gate_in_netlist(gate) || !net->is_a_source(ep))
569  {
570  return false;
571  }
572 
573  bool removed = false;
574  for (u32 i = 0; i < net->m_sources.size(); ++i)
575  {
576  if (net->m_sources_raw[i] == ep)
577  {
578  utils::unordered_vector_erase(gate->m_out_endpoints, ep);
579  utils::unordered_vector_erase(gate->m_out_nets, net);
580  net->m_sources[i] = std::move(net->m_sources.back());
581  net->m_sources.pop_back();
582  net->m_sources_raw[i] = net->m_sources_raw.back();
583  net->m_sources_raw.pop_back();
584  m_event_handler->notify(NetEvent::event::src_removed, net, gate->get_id());
585  removed = true;
586  break;
587  }
588  }
589 
590  if (!removed)
591  {
592  log_warning("net",
593  "output pin '{}' of gate '{}' with ID {} is not a source of net '{}' with ID {} in netlist with ID {}",
594  ep->get_pin()->get_name(),
595  gate->get_name(),
596  gate->get_id(),
597  net->get_name(),
598  net->get_id(),
599  m_netlist->m_netlist_id);
600  }
601  else
602  {
603  // update internal nets and port nets
604  if (m_net_checks_enabled)
605  {
606  if (const auto res = gate->get_module()->check_net(net, true); res.is_error())
607  {
608  log_error("net", "{}", res.get_error().get());
609  return false;
610  }
611 
612  for (Endpoint* dst : net->get_destinations())
613  {
614  if (const auto res = dst->get_gate()->get_module()->check_net(net, true); res.is_error())
615  {
616  log_error("net", "{}", res.get_error().get());
617  return false;
618  }
619  }
620  }
621  }
622 
623  return true;
624  }
625 
626  Endpoint* NetlistInternalManager::net_add_destination(Net* net, Gate* gate, GatePin* pin)
627  {
628  if (!m_netlist->is_net_in_netlist(net) || !m_netlist->is_gate_in_netlist(gate) || pin == nullptr)
629  {
630  return nullptr;
631  }
632 
633  if (net->is_a_destination(gate, pin))
634  {
635  log_error("net",
636  "pin '{}' of gate '{}' with ID {} is already a destination of net '{}' with ID {} in netlist with ID {}.",
637  pin->get_name(),
638  gate->get_name(),
639  gate->get_id(),
640  net->get_name(),
641  net->get_id(),
642  m_netlist->m_netlist_id);
643  return nullptr;
644  }
645 
646  // check whether pin is valid for this gate
647  auto input_pins = gate->get_type()->get_input_pins();
648 
649  if ((std::find(input_pins.begin(), input_pins.end(), pin) == input_pins.end()))
650  {
651  log_error("net", "gate '{}' with ID {} has no input pin called '{}' in netlist with ID {}.", gate->get_name(), gate->get_id(), pin->get_name(), m_netlist->m_netlist_id);
652  return nullptr;
653  }
654 
655  // check whether dst has already an assigned net
656  if (auto fan_in_net = gate->get_fan_in_net(pin); fan_in_net != nullptr)
657  {
658  log_error("net",
659  "gate '{}' with ID {} is already connected to net '{}' with ID {} at input pin '{}', cannot assign new net '{}' with ID {} in netlist with ID {}.",
660  gate->get_name(),
661  gate->get_id(),
662  fan_in_net->get_name(),
663  fan_in_net->get_id(),
664  pin->get_name(),
665  net->get_name(),
666  net->get_id(),
667  m_netlist->m_netlist_id);
668  return nullptr;
669  }
670 
671  std::unique_ptr<Endpoint> new_endpoint = std::unique_ptr<Endpoint>(new Endpoint(gate, pin, net, true));
672  Endpoint* new_endpoint_raw = new_endpoint.get();
673  net->m_destinations.push_back(std::move(new_endpoint));
674  net->m_destinations_raw.push_back(new_endpoint_raw);
675  gate->m_in_endpoints.push_back(new_endpoint_raw);
676  gate->m_in_nets.push_back(net);
677 
678  // update internal nets and port nets
679  if (m_net_checks_enabled)
680  {
681  if (const auto res = gate->get_module()->check_net(net, true); res.is_error())
682  {
683  log_error("net", "{}", res.get_error().get());
684  return nullptr;
685  }
686 
687  for (Endpoint* ep : net->get_sources())
688  {
689  if (const auto res = ep->get_gate()->get_module()->check_net(net, true); res.is_error())
690  {
691  log_error("net", "{}", res.get_error().get());
692  return nullptr;
693  }
694  }
695  }
696 
697  m_event_handler->notify(NetEvent::event::dst_added, net, gate->get_id());
698 
699  return new_endpoint_raw;
700  }
701 
702  bool NetlistInternalManager::net_remove_destination(Net* net, Endpoint* ep)
703  {
704  auto gate = ep->get_gate();
705  if (!m_netlist->is_net_in_netlist(net) || !m_netlist->is_gate_in_netlist(gate) || !net->is_a_destination(ep))
706  {
707  return false;
708  }
709 
710  bool removed = false;
711  for (u32 i = 0; i < net->m_destinations.size(); ++i)
712  {
713  if (net->m_destinations_raw[i] == ep)
714  {
715  utils::unordered_vector_erase(gate->m_in_endpoints, ep);
716  utils::unordered_vector_erase(gate->m_in_nets, net);
717  net->m_destinations[i] = std::move(net->m_destinations.back());
718  net->m_destinations.pop_back();
719  net->m_destinations_raw[i] = net->m_destinations_raw.back();
720  net->m_destinations_raw.pop_back();
721  m_event_handler->notify(NetEvent::event::dst_removed, net, gate->get_id());
722  removed = true;
723  break;
724  }
725  }
726 
727  if (!removed)
728  {
729  log_warning("net",
730  "input pin '{}' of gate '{}' with ID {} is not a destination of net '{}' with ID {} in netlist with ID {}",
731  ep->get_pin()->get_name(),
732  gate->get_name(),
733  gate->get_id(),
734  net->get_name(),
735  net->get_id(),
736  m_netlist->m_netlist_id);
737  }
738  else
739  { // update internal nets and port nets
740  if (m_net_checks_enabled)
741  {
742  if (const auto res = gate->get_module()->check_net(net, true); res.is_error())
743  {
744  log_error("net", "{}", res.get_error().get());
745  return false;
746  }
747 
748  for (Endpoint* src : net->get_sources())
749  {
750  if (const auto res = src->get_gate()->get_module()->check_net(net, true); res.is_error())
751  {
752  log_error("net", "{}", res.get_error().get());
753  return false;
754  }
755  }
756  }
757  }
758 
759  return true;
760  }
761 
762  //######################################################################
763  //### modules ###
764  //######################################################################
765 
766  Module* NetlistInternalManager::create_module(const u32 id, Module* parent, const std::string& name)
767  {
768  if (id == 0)
769  {
770  log_error("module", "ID 0 represents an invalid module ID.");
771  return nullptr;
772  }
773  if (m_netlist->m_used_module_ids.find(id) != m_netlist->m_used_module_ids.end())
774  {
775  log_error("module", "module ID {} is already taken in netlist with ID {}.", id, m_netlist->m_netlist_id);
776  return nullptr;
777  }
778  if (utils::trim(name).empty())
779  {
780  log_error("module", "module name cannot be empty.");
781  return nullptr;
782  }
783  if (parent == nullptr && m_netlist->m_top_module != nullptr)
784  {
785  log_error("module", "parent module cannot not be nullptr.");
786  return nullptr;
787  }
788  if (parent != nullptr && m_netlist != parent->get_netlist())
789  {
790  log_error("module", "parent module must belong to netlist with ID {}.", m_netlist->m_netlist_id);
791  return nullptr;
792  }
793 
794  auto m = std::unique_ptr<Module>(new Module(this, m_event_handler, id, parent, name));
795 
796  auto free_id_it = m_netlist->m_free_module_ids.find(id);
797  if (free_id_it != m_netlist->m_free_module_ids.end())
798  {
799  m_netlist->m_free_module_ids.erase(free_id_it);
800  }
801 
802  m_netlist->m_used_module_ids.insert(id);
803 
804  auto raw = m.get();
805  m_netlist->m_modules_map[id] = std::move(m);
806  m_netlist->m_modules_set.insert(raw);
807  m_netlist->m_modules.push_back(raw);
808 
809  if (parent != nullptr)
810  {
811  parent->m_submodules_map[id] = raw;
812  parent->m_submodules.push_back(raw);
813  }
814 
815  m_event_handler->notify(ModuleEvent::event::created, raw);
816 
817  if (parent != nullptr)
818  {
819  m_event_handler->notify(ModuleEvent::event::submodule_added, parent, id);
820  }
821 
822  return raw;
823  }
824 
825  bool NetlistInternalManager::delete_module(Module* to_remove)
826  {
827  if (!m_netlist->is_module_in_netlist(to_remove))
828  {
829  return false;
830  }
831 
832  if (to_remove == m_netlist->m_top_module)
833  {
834  return false;
835  }
836 
837  // at this point parent is guaranteed to be not null
838 
839  // remove from grouping
840  if (Grouping* g = to_remove->get_grouping(); g != nullptr)
841  {
842  g->remove_module(to_remove);
843  }
844 
845  // move gates and nets to parent, work on a copy since assign_gate will modify m_gates
846  std::vector<Gate*> gates_copy = to_remove->m_gates;
847  to_remove->m_parent->assign_gates(gates_copy);
848 
849  // move all submodules to parent
850  for (auto sm : to_remove->m_submodules)
851  {
852  to_remove->m_parent->m_submodules_map[sm->get_id()] = sm;
853  to_remove->m_parent->m_submodules.push_back(sm);
854 
855  m_event_handler->notify(ModuleEvent::event::submodule_removed, sm->get_parent_module(), sm->get_id());
856 
857  sm->m_parent = to_remove->m_parent;
858 
859  m_event_handler->notify(ModuleEvent::event::parent_changed, sm, 0);
860  m_event_handler->notify(ModuleEvent::event::submodule_added, to_remove->m_parent, sm->get_id());
861  }
862 
863  // remove module from parent
864  to_remove->m_parent->m_submodules_map.erase(to_remove->get_id());
865  utils::unordered_vector_erase(to_remove->m_parent->m_submodules, to_remove);
866  m_event_handler->notify(ModuleEvent::event::submodule_removed, to_remove->m_parent, to_remove->get_id());
867 
868  auto it = m_netlist->m_modules_map.find(to_remove->get_id());
869  auto ptr = std::move(it->second);
870  m_netlist->m_modules_map.erase(it);
871  m_netlist->m_modules_set.erase(to_remove);
872  utils::unordered_vector_erase(m_netlist->m_modules, to_remove);
873 
874  m_netlist->m_free_module_ids.insert(to_remove->get_id());
875  m_netlist->m_used_module_ids.erase(to_remove->get_id());
876 
877  m_event_handler->notify(ModuleEvent::event::removed, to_remove);
878  return true;
879  }
880 
881  bool NetlistInternalManager::module_assign_gate(Module* m, Gate* g)
882  {
883  return module_assign_gates(m, {g});
884  }
885 
886  bool NetlistInternalManager::module_assign_gates(Module* module, const std::vector<Gate*>& gates)
887  {
888  // check all gates for validity
889  if (module == nullptr)
890  {
891  log_error("module", "module cannot be a nullptr.");
892  return false;
893  }
894 
895  std::map<Module*, u32> prev_modules;
896 
897  for (const Gate* g : gates)
898  {
899  if (g == nullptr)
900  {
901  log_error("module", "gate cannot be a nullptr.");
902  return false;
903  }
904 
905  Module* prev_mod = g->m_module;
906 
907  if (prev_mod == module)
908  {
909  log_error("module",
910  "gate '{}' with ID {} is already contained in module '{}' with ID {} in netlist with ID {}.",
911  g->get_name(),
912  g->get_id(),
913  module->get_name(),
914  module->get_id(),
915  m_netlist->m_netlist_id);
916  return false;
917  }
918 
919  if (auto it = prev_modules.find(prev_mod); it == prev_modules.end())
920  {
921  prev_modules[prev_mod] = 1;
922  }
923  else
924  {
925  std::get<1>(*it)++;
926  }
927  }
928 
929  m_event_handler->notify(ModuleEvent::event::gates_assign_begin, module, gates.size());
930  for (const auto& [prev_mod, num_gates] : prev_modules)
931  {
932  m_event_handler->notify(ModuleEvent::event::gates_remove_begin, prev_mod, num_gates);
933  }
934  prev_modules.clear();
935 
936  // re-assign gates
937  std::unordered_map<Module*, std::unordered_set<Net*>> nets_to_check;
938  for (Gate* g : gates)
939  {
940  // remove gate from old module
941  Module* prev_mod = g->m_module;
942  const auto it = prev_mod->m_gates_map.find(g->get_id());
943  assert(it != prev_mod->m_gates_map.end());
944  prev_mod->m_gates_map.erase(it);
945 
946  utils::unordered_vector_erase(prev_mod->m_gates, g);
947 
948  // move gate to new module
949  module->m_gates_map[g->get_id()] = g;
950  module->m_gates.push_back(g);
951  g->m_module = module;
952 
953  // collect affected nets
954  std::vector<Net*> fan_in = g->get_fan_in_nets();
955  nets_to_check[prev_mod].insert(fan_in.begin(), fan_in.end());
956  nets_to_check[module].insert(fan_in.begin(), fan_in.end());
957 
958  std::vector<Net*> fan_out = g->get_fan_out_nets();
959  nets_to_check[prev_mod].insert(fan_out.begin(), fan_out.end());
960  nets_to_check[module].insert(fan_out.begin(), fan_out.end());
961  m_event_handler->notify(ModuleEvent::event::gate_removed, prev_mod, g->get_id());
962  m_event_handler->notify(ModuleEvent::event::gate_assigned, module, g->get_id());
963 
964  if (auto prev_mod_it = prev_modules.find(prev_mod); prev_mod_it == prev_modules.end())
965  {
966  prev_modules[prev_mod] = 1;
967  }
968  else
969  {
970  std::get<1>(*prev_mod_it)++;
971  }
972  }
973 
974  if (m_net_checks_enabled)
975  {
976  for (const auto& [affected_module, nets] : nets_to_check)
977  {
978  for (Net* net : nets)
979  {
980  if (const auto res = affected_module->check_net(net, true); res.is_error())
981  {
982  log_error("module", "{}", res.get_error().get());
983  return false;
984  }
985  }
986  }
987  }
988 
989  m_event_handler->notify(ModuleEvent::event::gates_assign_end, module, gates.size());
990  for (const auto& [prev_mod, num_gates] : prev_modules)
991  {
992  m_event_handler->notify(ModuleEvent::event::gates_remove_end, prev_mod, num_gates);
993  }
994 
995  return true;
996  }
997 
998  bool NetlistInternalManager::module_check_net(Module* module, Net* net, bool recursive)
999  {
1000  if (const auto res = module->check_net(net, recursive); res.is_error())
1001  {
1002  return false;
1003  }
1004  return true;
1005  }
1006 
1007  //######################################################################
1008  //### groupings ###
1009  //######################################################################
1010 
1011  Grouping* NetlistInternalManager::create_grouping(u32 id, const std::string name)
1012  {
1013  if (id == 0)
1014  {
1015  log_error("grouping", "ID 0 represents an invalid grouping ID.");
1016  return nullptr;
1017  }
1018  if (m_netlist->m_used_grouping_ids.find(id) != m_netlist->m_used_grouping_ids.end())
1019  {
1020  log_error("grouping", "grouping ID {} is already taken in netlist with ID {}.", id, m_netlist->m_netlist_id);
1021  return nullptr;
1022  }
1023  if (utils::trim(name).empty())
1024  {
1025  log_error("grouping", "grouping name cannot be empty.");
1026  return nullptr;
1027  }
1028 
1029  auto new_grouping = std::unique_ptr<Grouping>(new Grouping(this, m_event_handler, id, name));
1030 
1031  auto free_id_it = m_netlist->m_free_grouping_ids.find(id);
1032  if (free_id_it != m_netlist->m_free_grouping_ids.end())
1033  {
1034  m_netlist->m_free_grouping_ids.erase(free_id_it);
1035  }
1036 
1037  m_netlist->m_used_grouping_ids.insert(id);
1038 
1039  auto raw = new_grouping.get();
1040 
1041  m_netlist->m_groupings_map[id] = std::move(new_grouping);
1042  m_netlist->m_groupings_set.insert(raw);
1043  m_netlist->m_groupings.push_back(raw);
1044 
1045  // notify
1046  m_event_handler->notify(GroupingEvent::event::created, raw);
1047 
1048  return raw;
1049  }
1050 
1051  bool NetlistInternalManager::delete_grouping(Grouping* grouping)
1052  {
1053  if (!m_netlist->is_grouping_in_netlist(grouping))
1054  {
1055  return false;
1056  }
1057 
1058  for (Gate* gate : grouping->get_gates())
1059  {
1060  gate->m_grouping = nullptr;
1061  }
1062 
1063  for (Net* net : grouping->get_nets())
1064  {
1065  net->m_grouping = nullptr;
1066  }
1067 
1068  for (Module* module : grouping->get_modules())
1069  {
1070  module->m_grouping = nullptr;
1071  }
1072 
1073  auto it = m_netlist->m_groupings_map.find(grouping->get_id());
1074  auto ptr = std::move(it->second);
1075  m_netlist->m_groupings_map.erase(it);
1076  m_netlist->m_groupings_set.erase(grouping);
1077  utils::unordered_vector_erase(m_netlist->m_groupings, grouping);
1078 
1079  // free ids
1080  m_netlist->m_free_grouping_ids.insert(grouping->get_id());
1081  m_netlist->m_used_grouping_ids.erase(grouping->get_id());
1082 
1083  // notify
1084  m_event_handler->notify(GroupingEvent::event::removed, grouping);
1085 
1086  return true;
1087  }
1088 
1089  bool NetlistInternalManager::grouping_assign_gate(Grouping* grouping, Gate* gate, bool force)
1090  {
1091  if (gate == nullptr || gate->get_grouping() == grouping)
1092  {
1093  return false;
1094  }
1095 
1096  u32 gate_id = gate->get_id();
1097 
1098  if (Grouping* other = gate->get_grouping(); other != nullptr)
1099  {
1100  if (force)
1101  {
1102  other->remove_gate(gate);
1103  }
1104  else
1105  {
1106  log_error("grouping",
1107  "gate '{}' with ID {} is already part of another grouping called '{}' with ID {} in netlist with ID {}.",
1108  gate->get_name(),
1109  gate_id,
1110  other->get_name(),
1111  other->get_id(),
1112  m_netlist->m_netlist_id);
1113  return false;
1114  }
1115  }
1116 
1117  grouping->m_gates.push_back(gate);
1118  grouping->m_gates_map.emplace(gate_id, gate);
1119  gate->m_grouping = grouping;
1120 
1121  m_event_handler->notify(GroupingEvent::event::gate_assigned, grouping, gate_id);
1122 
1123  return true;
1124  }
1125 
1126  bool NetlistInternalManager::grouping_remove_gate(Grouping* grouping, Gate* gate)
1127  {
1128  if (gate == nullptr)
1129  {
1130  return false;
1131  }
1132 
1133  u32 gate_id = gate->get_id();
1134 
1135  if (!grouping->contains_gate(gate))
1136  {
1137  log_error("grouping",
1138  "gate '{}' with ID {} is not part of grouping '{}' with ID {} in netlist with ID {}.",
1139  gate->get_name(),
1140  gate_id,
1141  grouping->get_name(),
1142  grouping->get_id(),
1143  m_netlist->m_netlist_id);
1144  return false;
1145  }
1146 
1147  auto vec_it = std::find(grouping->m_gates.begin(), grouping->m_gates.end(), gate);
1148 
1149  *vec_it = grouping->m_gates.back();
1150  grouping->m_gates.pop_back();
1151  grouping->m_gates_map.erase(gate_id);
1152  gate->m_grouping = nullptr;
1153 
1154  m_event_handler->notify(GroupingEvent::event::gate_removed, grouping, gate_id);
1155 
1156  return true;
1157  }
1158 
1159  bool NetlistInternalManager::grouping_assign_net(Grouping* grouping, Net* net, bool force)
1160  {
1161  if (net == nullptr || net->get_grouping() == grouping)
1162  {
1163  return false;
1164  }
1165 
1166  u32 net_id = net->get_id();
1167 
1168  if (Grouping* other = net->get_grouping(); other != nullptr)
1169  {
1170  if (force)
1171  {
1172  other->remove_net(net);
1173  }
1174  else
1175  {
1176  log_error("grouping",
1177  "net '{}' with ID {} is already part of another grouping called '{}' with ID {} in netlist with ID {}.",
1178  net->get_name(),
1179  net_id,
1180  other->get_name(),
1181  other->get_id(),
1182  m_netlist->m_netlist_id);
1183  return false;
1184  }
1185  }
1186 
1187  grouping->m_nets.push_back(net);
1188  grouping->m_nets_map.emplace(net_id, net);
1189  net->m_grouping = grouping;
1190 
1191  m_event_handler->notify(GroupingEvent::event::net_assigned, grouping, net_id);
1192 
1193  return true;
1194  }
1195 
1196  bool NetlistInternalManager::grouping_remove_net(Grouping* grouping, Net* net)
1197  {
1198  if (net == nullptr)
1199  {
1200  return false;
1201  }
1202 
1203  u32 net_id = net->get_id();
1204 
1205  if (!grouping->contains_net(net))
1206  {
1207  log_error("grouping",
1208  "net '{}' with ID {} is not part of grouping '{}' with ID {} in netlist with ID {}.",
1209  net->get_name(),
1210  net_id,
1211  grouping->get_name(),
1212  grouping->get_id(),
1213  m_netlist->m_netlist_id);
1214  return false;
1215  }
1216 
1217  auto vec_it = std::find(grouping->m_nets.begin(), grouping->m_nets.end(), net);
1218 
1219  *vec_it = grouping->m_nets.back();
1220  grouping->m_nets.pop_back();
1221  grouping->m_nets_map.erase(net_id);
1222  net->m_grouping = nullptr;
1223 
1224  m_event_handler->notify(GroupingEvent::event::net_removed, grouping, net_id);
1225 
1226  return true;
1227  }
1228 
1229  bool NetlistInternalManager::grouping_assign_module(Grouping* grouping, Module* module, bool force)
1230  {
1231  if (module == nullptr || module->get_grouping() == grouping)
1232  {
1233  return false;
1234  }
1235 
1236  u32 module_id = module->get_id();
1237 
1238  if (Grouping* other = module->get_grouping(); other != nullptr)
1239  {
1240  if (force)
1241  {
1242  other->remove_module(module);
1243  }
1244  else
1245  {
1246  log_error("grouping",
1247  "module '{}' with ID {} is already part of another grouping called '{}' with ID {} in netlist with ID {}.",
1248  module->get_name(),
1249  module_id,
1250  other->get_name(),
1251  other->get_id(),
1252  m_netlist->m_netlist_id);
1253  return false;
1254  }
1255  }
1256 
1257  grouping->m_modules.push_back(module);
1258  grouping->m_modules_map.emplace(module_id, module);
1259  module->m_grouping = grouping;
1260 
1261  m_event_handler->notify(GroupingEvent::event::module_assigned, grouping, module_id);
1262 
1263  return true;
1264  }
1265 
1266  bool NetlistInternalManager::grouping_remove_module(Grouping* grouping, Module* module)
1267  {
1268  if (module == nullptr)
1269  {
1270  return false;
1271  }
1272 
1273  u32 module_id = module->get_id();
1274 
1275  if (!grouping->contains_module(module))
1276  {
1277  log_error("grouping",
1278  "module '{}' with ID {} is not part of grouping '{}' with ID {} in netlist with ID {}.",
1279  module->get_name(),
1280  module_id,
1281  grouping->get_name(),
1282  grouping->get_id(),
1283  m_netlist->m_netlist_id);
1284  return false;
1285  }
1286 
1287  auto vec_it = std::find(grouping->m_modules.begin(), grouping->m_modules.end(), module);
1288 
1289  *vec_it = grouping->m_modules.back();
1290  grouping->m_modules.pop_back();
1291  grouping->m_modules_map.erase(module_id);
1292  module->m_grouping = nullptr;
1293 
1294  m_event_handler->notify(GroupingEvent::event::module_removed, grouping, module_id);
1295 
1296  return true;
1297  }
1298 
1299  //######################################################################
1300  //### caches ###
1301  //######################################################################
1302 
1303  void NetlistInternalManager::clear_caches()
1304  {
1305  m_lut_function_cache.clear();
1306  }
1307 } // namespace hal
const std::map< std::tuple< std::string, std::string >, std::tuple< std::string, std::string > > & get_data_map() const
std::map< std::tuple< std::string, std::string >, std::tuple< std::string, std::string > > m_data
NETLIST_API void notify(NetlistEvent::event ev, Netlist *netlist, u32 associated_data=0xFFFFFFFF)
@ removed
no associated_data
@ created
no associated_data
bool contains_gate_type(GateType *gate_type) const
@ net_assigned
associated_data = id of inserted net
@ module_removed
associated_data = id of removed module
@ gate_assigned
associated_data = id of inserted gate
@ module_assigned
associated_data = id of inserted module
@ gate_removed
associated_data = id of removed gate
@ removed
no associated_data
@ net_removed
associated_data = id of removed net
@ created
no associated_data
@ gates_remove_end
associated_data = number of removed gates
@ gate_assigned
associated_data = id of inserted gate
@ gate_removed
associated_data = id of removed gate
@ submodule_removed
associated_data = id of removed module
@ gates_assign_begin
associated_data = number of gates to assign
@ gates_assign_end
associated_data = number of assigned gates
@ gates_remove_begin
associated_data = number of gates to remove
@ submodule_added
associated_data = id of added module
@ removed
no associated_data
@ parent_changed
no associated_data
@ created
no associated_data
std::string get_name() const
Definition: module.cpp:87
Grouping * get_grouping() const
Definition: module.cpp:120
u32 get_id() const
Definition: module.cpp:82
@ src_added
associated_data = id of src gate
@ dst_removed
associated_data = id of dst gate
@ src_removed
associated_data = id of src gate
@ dst_added
associated_data = id of dst gate
@ removed
no associated_data
@ created
no associated_data
bool is_gate_in_netlist(const Gate *gate) const
Definition: netlist.cpp:188
bool is_module_in_netlist(const Module *module) const
Definition: netlist.cpp:647
bool unmark_gnd_gate(Gate *gate)
Definition: netlist.cpp:277
bool is_grouping_in_netlist(const Grouping *grouping) const
Definition: netlist.cpp:686
bool unmark_vcc_gate(Gate *gate)
Definition: netlist.cpp:260
bool is_net_in_netlist(const Net *net) const
Definition: netlist.cpp:348
bool unmark_global_output_net(Net *net)
Definition: netlist.cpp:478
bool unmark_global_input_net(Net *net)
Definition: netlist.cpp:447
int32_t i32
Definition: defines.h:36
#define log_error(channel,...)
Definition: log.h:78
#define log_warning(channel,...)
Definition: log.h:76
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49
#define ERR_APPEND(prev_error, message)
Definition: result.h:57
const Module * module(const Gate *g, const NodeBoxes &boxes)
std::unique_ptr< Netlist > create_netlist(const GateLibrary *gate_library)
Create a new empty netlist using the specified gate library.
CORE_API T trim(const T &s, const char *to_remove=" \t\r\n")
Definition: utils.h:358
CORE_API bool unordered_vector_erase(std::vector< T > &vec, T element)
Definition: utils.h:58
quint32 u32
Net * net
std::string name
i32 id
This file contains various functions to create and load netlists.