HAL
gate.cpp
Go to the documentation of this file.
2 
11 #include "hal_core/netlist/net.h"
15 #include "hal_core/utilities/log.h"
16 
17 #include <assert.h>
18 #include <iomanip>
19 #include <sstream>
20 
21 template<typename T, T m, int k>
22 static inline T swapbits(T p)
23 {
24  T q = ((p >> k) ^ p) & m;
25  return p ^ q ^ (q << k);
26 }
27 
28 static u64 bitreverse(u64 n)
29 {
30  static const u64 m0 = 0x5555555555555555LLU;
31  static const u64 m1 = 0x0300c0303030c303LLU;
32  static const u64 m2 = 0x00c0300c03f0003fLLU;
33  static const u64 m3 = 0x00000ffc00003fffLLU;
34  n = ((n >> 1) & m0) | (n & m0) << 1;
35  n = swapbits<u64, m1, 4>(n);
36  n = swapbits<u64, m2, 8>(n);
37  n = swapbits<u64, m3, 20>(n);
38  n = (n >> 34) | (n << 30);
39  return n;
40 }
41 
42 namespace hal
43 {
44  Gate::Gate(NetlistInternalManager* mgr, EventHandler* event_handler, const u32 id, GateType* gt, const std::string& name, i32 x, i32 y)
45  : m_internal_manager(mgr), m_id(id), m_name(name), m_type(gt), m_x(x), m_y(y), m_event_handler(event_handler)
46  {
47  ;
48  }
49 
50  bool Gate::operator==(const Gate& other) const
51  {
52  if (m_id != other.get_id() || m_name != other.get_name() || m_type != other.get_type())
53  {
54  log_debug("gate", "the gates with IDs {} and {} are not equal due to an unequal ID, name, or type.", m_id, other.get_id());
55  return false;
56  }
57 
58  if (m_x != other.get_location_x() || m_y != other.get_location_y())
59  {
60  log_debug("gate", "the gates with IDs {} and {} are not equal due to unequal location data.", m_id, other.get_id());
61  return false;
62  }
63 
64  if (is_gnd_gate() != other.is_gnd_gate() || is_vcc_gate() != other.is_vcc_gate())
65  {
66  log_debug("gate", "the gates with IDs {} and {} are not equal as one is a GND or VCC gate and the other is not.", m_id, other.get_id());
67  return false;
68  }
69 
70  if (m_functions != other.get_boolean_functions(true))
71  {
72  log_debug("gate", "the gates with IDs {} and {} are not equal due to an unequal Boolean functions.", m_id, other.get_id());
73  return false;
74  }
75 
76  if (!DataContainer::operator==(other))
77  {
78  log_debug("gate", "the gates with IDs {} and {} are not equal due to unequal data.", m_id, other.get_id());
79  return false;
80  }
81 
82  return true;
83  }
84 
85  bool Gate::operator!=(const Gate& other) const
86  {
87  return !operator==(other);
88  }
89 
90  ssize_t Gate::get_hash() const
91  {
92  return (uintptr_t)this;
93  }
94 
95  u32 Gate::get_id() const
96  {
97  return m_id;
98  }
99 
100  Netlist* Gate::get_netlist() const
101  {
102  return m_internal_manager->m_netlist;
103  }
104 
105  const std::string& Gate::get_name() const
106  {
107  return m_name;
108  }
109 
110  void Gate::set_name(const std::string& name)
111  {
112  if (utils::trim(name).empty())
113  {
114  log_error("gate", "gate name cannot be empty.");
115  return;
116  }
117 
118  if (name != m_name)
119  {
120  m_name = name;
121  m_event_handler->notify(GateEvent::event::name_changed, this);
122  }
123  }
124 
125  GateType* Gate::get_type() const
126  {
127  return m_type;
128  }
129 
130  i32 Gate::get_location_x() const
131  {
132  return m_x;
133  }
134 
135  i32 Gate::get_location_y() const
136  {
137  return m_y;
138  }
139 
140  std::pair<i32, i32> Gate::get_location() const
141  {
142  return {m_x, m_y};
143  }
144 
145  bool Gate::has_location() const
146  {
147  return m_x >= 0 && m_y >= 0;
148  }
149 
150  void Gate::set_location_x(i32 x)
151  {
152  if (x != m_x)
153  {
154  m_x = x;
155  m_event_handler->notify(GateEvent::event::location_changed, this);
156  }
157  }
158 
159  void Gate::set_location_y(i32 y)
160  {
161  if (y != m_y)
162  {
163  m_y = y;
164  m_event_handler->notify(GateEvent::event::location_changed, this);
165  }
166  }
167 
168  void Gate::set_location(const std::pair<i32, i32>& location)
169  {
170  set_location_x(location.first);
171  set_location_y(location.second);
172  }
173 
174  Module* Gate::get_module() const
175  {
176  return m_module;
177  }
178 
179  std::vector<Module*> Gate::get_modules(const std::function<bool(Module*)>& filter, bool recursive) const
180  {
181  std::vector<Module*> res;
182 
183  if (!filter)
184  {
185  res.push_back(m_module);
186  }
187  else
188  {
189  if (filter(m_module))
190  {
191  res.push_back(m_module);
192  }
193  }
194 
195  if (recursive)
196  {
197  std::vector<Module*> more = m_module->get_parent_modules(filter, true);
198  res.reserve(res.size() + more.size());
199  res.insert(res.end(), more.begin(), more.end());
200  }
201  return res;
202  }
203 
204  Grouping* Gate::get_grouping() const
205  {
206  return m_grouping;
207  }
208 
209  BooleanFunction Gate::get_boolean_function(const std::string& name) const
210  {
211  std::string internal_name = name;
212  if (internal_name.empty())
213  {
214  auto output_pins = m_type->get_output_pins();
215  if (output_pins.empty())
216  {
217  return BooleanFunction();
218  }
219  internal_name = output_pins.front()->get_name();
220  }
221 
222  if (m_type->has_component_of_type(GateTypeComponent::ComponentType::lut))
223  {
224  auto lut_pins = m_type->get_pins([internal_name](const GatePin* pin) { return pin->get_type() == PinType::lut && pin->get_name() == internal_name; });
225  if (!lut_pins.empty())
226  {
227  return get_lut_function(lut_pins.front());
228  }
229  }
230 
231  if (auto it = m_functions.find(internal_name); it != m_functions.end())
232  {
233  return it->second;
234  }
235 
236  auto map = m_type->get_boolean_functions();
237  if (auto it = map.find(internal_name); it != map.end())
238  {
239  return it->second;
240  }
241 
242  log_warning("gate", "could not get Boolean function '{}' of gate '{}' with ID {}: no function with that name exists", internal_name, m_name, std::to_string(m_id));
243  return BooleanFunction();
244  }
245 
246  BooleanFunction Gate::get_boolean_function(const GatePin* pin) const
247  {
248  if (pin == nullptr)
249  {
250  auto output_pins = m_type->get_output_pins();
251  if (output_pins.empty())
252  {
253  log_warning("gate", "could not get Boolean function of gate '{}' with ID {}: gate type '{}' with ID {} has no output pins", m_name, m_id, m_type->get_name(), m_type->get_id());
254  return BooleanFunction();
255  }
256  pin = output_pins.front();
257  }
258 
259  return get_boolean_function(pin->get_name());
260  }
261 
262  std::unordered_map<std::string, BooleanFunction> Gate::get_boolean_functions(bool only_custom_functions) const
263  {
264  std::unordered_map<std::string, BooleanFunction> res;
265 
266  if (!only_custom_functions)
267  {
268  res = m_type->get_boolean_functions();
269  }
270 
271  for (const auto& it : m_functions)
272  {
273  res[it.first] = it.second;
274  }
275 
276  if (!only_custom_functions && m_type->has_component_of_type(GateTypeComponent::ComponentType::lut))
277  {
278  for (auto pin : m_type->get_pins([](const GatePin* pin) { return pin->get_type() == PinType::lut; }))
279  {
280  res[pin->get_name()] = get_lut_function(pin);
281  }
282  }
283 
284  return res;
285  }
286 
287  Result<BooleanFunction> Gate::get_resolved_boolean_function(const GatePin* pin, const bool use_net_variables) const
288  {
289  const std::function<Result<BooleanFunction>(const GatePin*, std::unordered_set<std::string>&)> get_resolved_boolean_function_internal =
290  [this, &get_resolved_boolean_function_internal, use_net_variables](const GatePin* output_pin, std::unordered_set<std::string>& on_stack) -> Result<BooleanFunction> {
291  if (output_pin == nullptr)
292  {
293  return ERR("could not get resolved Boolean function of gate '" + this->get_name() + "' with ID " + std::to_string(this->get_id()) + ": given output pin is null.");
294  }
295 
296  if (on_stack.find(output_pin->get_name()) != on_stack.end())
297  {
298  return ERR("could not get resolved Boolean function of gate '" + this->get_name() + "' with ID " + std::to_string(this->get_id())
299  + ": boolean functions of gate contain an endless recursion including pin '" + output_pin->get_name() + "'");
300  }
301  on_stack.insert(output_pin->get_name());
302 
303  BooleanFunction bf = this->get_boolean_function(output_pin);
304 
305  std::map<std::string, BooleanFunction> input_to_bf;
306  std::vector<std::string> input_vars = utils::to_vector(bf.get_variable_names());
307  for (const auto& var : bf.get_variable_names())
308  {
309  const GatePin* pin = this->get_type()->get_pin_by_name(var);
310  if (pin == nullptr)
311  {
312  return ERR("could not get resolved Boolean function of gate '" + this->get_name() + "' with ID " + std::to_string(this->get_id()) + ": failed to get input pin '" + var
313  + "' by name");
314  }
315 
316  const PinDirection pin_dir = pin->get_direction();
317  if (pin_dir == PinDirection::input)
318  {
319  if (!use_net_variables)
320  {
321  const Net* const input_net = this->get_fan_in_net(var);
322  if (input_net == nullptr)
323  {
324  // if no net is connected, the input pin name cannot be replaced
325  return ERR("could not get resolved Boolean function of gate '" + this->get_name() + "' with ID " + std::to_string(this->get_id()) + ": failed to get fan-in net at pin '"
326  + pin->get_name() + "'");
327  }
328 
329  const auto net_dec = BooleanFunctionNetDecorator(*input_net);
330  input_to_bf.insert({var, net_dec.get_boolean_variable()});
331  }
332  }
333  else if ((pin_dir == PinDirection::internal) || (pin_dir == PinDirection::output))
334  {
335  const auto bf_interal_res = get_resolved_boolean_function_internal(pin, on_stack);
336  if (bf_interal_res.is_error())
337  {
338  return ERR_APPEND(bf_interal_res.get_error(),
339  "could not get resolved Boolean function of gate '" + this->get_name() + "' with ID " + std::to_string(this->get_id())
340  + ": failed to get Boolean function at output pin '" + pin->get_name() + "'");
341  }
342 
343  input_to_bf.insert({pin->get_name(), bf_interal_res.get()});
344  }
345  }
346 
347  if (auto substituted = bf.substitute(input_to_bf); substituted.is_error())
348  {
349  return ERR_APPEND(substituted.get_error(),
350  "could not get resolved Boolean function of gate '" + this->get_name() + "' with ID " + std::to_string(this->get_id())
351  + ": failed to substitute variable inputs with other Boolean functions");
352  }
353  else
354  {
355  bf = substituted.get();
356  }
357 
358  on_stack.erase(output_pin->get_name());
359 
360  return OK(bf);
361  };
362 
363  std::unordered_set<std::string> on_stack;
364 
365  return get_resolved_boolean_function_internal(pin, on_stack);
366  }
367 
368  BooleanFunction Gate::get_lut_function(const GatePin* pin) const
369  {
370  UNUSED(pin);
371 
372  LUTComponent* lut_component = m_type->get_component_as<LUTComponent>([](const GateTypeComponent* component) { return component->get_type() == GateTypeComponent::ComponentType::lut; });
373  if (lut_component == nullptr)
374  {
375  return BooleanFunction();
376  }
377 
378  InitComponent* init_component =
379  lut_component->get_component_as<InitComponent>([](const GateTypeComponent* component) { return component->get_type() == GateTypeComponent::ComponentType::init; });
380  if (init_component == nullptr)
381  {
382  return BooleanFunction();
383  }
384 
385  const std::string& category = init_component->get_init_category();
386  const std::string& key = init_component->get_init_identifiers().front();
387  std::string config_str = std::get<1>(get_data(category, key));
388  auto is_ascending = lut_component->is_init_ascending();
389  std::vector<GatePin*> inputs = m_type->get_input_pins();
390 
391  auto result = BooleanFunction::Const(BooleanFunction::Value::ZERO);
392 
393  if (config_str.empty())
394  {
395  return result;
396  }
397 
398  if (inputs.size() > 6)
399  {
400  log_error("gate", "LUT gate '{}' with ID {} in netlist with ID {} has more than six input pins, which is currently not supported.", m_name, m_id, m_internal_manager->m_netlist->get_id());
401  return BooleanFunction();
402  }
403 
404  u64 config = 0;
405  try
406  {
407  config = std::stoull(config_str, nullptr, 16);
408  }
409  catch (std::invalid_argument& ex)
410  {
411  log_error("gate",
412  "LUT gate '{}' with ID {} in netlist with ID {} has invalid configuration string of '{}', which is not a hex value.",
413  m_name,
414  m_id,
415  m_internal_manager->m_netlist->get_id(),
416  config_str);
417  return BooleanFunction();
418  }
419  catch (std::out_of_range& ex)
420  {
421  log_error("gate",
422  "LUT gate '{}' with ID {} in netlist with ID {} has invalid configuration string of '{}', which has to many hex digits.",
423  m_name,
424  m_id,
425  m_internal_manager->m_netlist->get_id(),
426  config_str);
427  return BooleanFunction();
428  }
429 
430  u32 max_config_size = 1 << inputs.size();
431 
432  if (is_ascending)
433  {
434  config = bitreverse(config) >> (64 - max_config_size);
435  }
436 
437  auto cache_key = std::make_pair(inputs, config);
438  auto& cache = m_internal_manager->m_lut_function_cache;
439 
440  if (auto it = cache.find(cache_key); it != cache.end())
441  {
442  return it->second;
443  }
444 
445  u32 config_size = 0;
446  {
447  u64 tmp = config;
448  while (tmp != 0)
449  {
450  config_size++;
451  tmp >>= 1;
452  }
453  }
454 
455  if (config_size > max_config_size)
456  {
457  log_error("gate",
458  "LUT gate '{}' with ID {} in netlist with ID {} supports a configuration string of up to {} bits, but '{}' comprises {} bits instead.",
459  m_name,
460  m_id,
461  m_internal_manager->m_netlist->get_id(),
462  max_config_size,
463  config_str,
464  config_str.size() * 4);
465  return BooleanFunction();
466  }
467 
468  for (u32 i = 0; config != 0 && i < max_config_size; i++)
469  {
470  u8 bit = (config & 1);
471  config >>= 1;
472  if (bit == 1)
473  {
474  auto conjunction = BooleanFunction::Const(1, 1);
475  auto input_values = i;
476  for (auto input : inputs)
477  {
478  if ((input_values & 1) == 1)
479  {
480  conjunction &= BooleanFunction::Var(input->get_name());
481  }
482  else
483  {
484  conjunction &= ~BooleanFunction::Var(input->get_name());
485  }
486  input_values >>= 1;
487  }
488  result |= conjunction;
489  }
490  }
491 
492  auto f = result.simplify();
493  cache[cache_key] = f;
494  return f;
495  }
496 
497  bool Gate::add_boolean_function(const std::string& name, const BooleanFunction& func)
498  {
499  LUTComponent* lut_component = m_type->get_component_as<LUTComponent>([](const GateTypeComponent* component) { return component->get_type() == GateTypeComponent::ComponentType::lut; });
500  if (lut_component != nullptr)
501  {
502  InitComponent* init_component =
503  lut_component->get_component_as<InitComponent>([](const GateTypeComponent* component) { return component->get_type() == GateTypeComponent::ComponentType::init; });
504  if (init_component != nullptr)
505  {
506  auto output_pins = m_type->get_output_pins();
507  if (!output_pins.empty() && name == output_pins.front()->get_name())
508  {
509  auto input_pin_names = m_type->get_input_pin_names();
510  auto tt = func.compute_truth_table(input_pin_names);
511  if (tt.is_error())
512  {
513  log_error("netlist", "Boolean function '{} = {}' cannot be added to LUT gate '{}' wiht ID {}.", name, func.to_string(), m_name, m_id);
514  return false;
515  }
516  auto truth_table = tt.get();
517  if (truth_table.size() > 1)
518  {
519  log_error("netlist", "Boolean function '{} = {}' cannot be added to LUT gate '{}' with ID {} (= function is > 1-bit in output size). ", name, func.to_string(), m_name, m_id);
520  return false;
521  }
522 
523  u64 config_value = 0;
524  if (!lut_component->is_init_ascending())
525  {
526  std::reverse(truth_table[0].begin(), truth_table[0].end());
527  }
528  for (auto v : truth_table[0])
529  {
530  if (v == BooleanFunction::X)
531  {
532  log_error("netlist",
533  "Boolean function '{} = {}' cannot be added to LUT gate '{}' with ID {} in netlist with ID {} as its truth table contains undefined values.",
534  name,
535  func.to_string(),
536  m_name,
537  m_id,
538  m_internal_manager->m_netlist->get_id());
539  return false;
540  }
541  config_value <<= 1;
542  config_value |= v;
543  }
544 
545  const std::string& category = init_component->get_init_category();
546  const std::string& key = init_component->get_init_identifiers().front();
547 
548  std::stringstream stream;
549  u32 init_len = 1 << (input_pin_names.size() - 2);
550  stream << std::hex << std::setfill('0') << std::setw(init_len) << config_value;
551  set_data(category, key, "bit_vector", stream.str());
552  }
553  }
554  }
555 
556  m_functions[name] = func;
557  m_event_handler->notify(GateEvent::event::boolean_function_changed, this);
558  return true;
559  }
560 
561  bool Gate::mark_vcc_gate()
562  {
563  return m_internal_manager->m_netlist->mark_vcc_gate(this);
564  }
565 
566  bool Gate::mark_gnd_gate()
567  {
568  return m_internal_manager->m_netlist->mark_gnd_gate(this);
569  }
570 
571  bool Gate::unmark_vcc_gate()
572  {
573  return m_internal_manager->m_netlist->unmark_vcc_gate(this);
574  }
575 
576  bool Gate::unmark_gnd_gate()
577  {
578  return m_internal_manager->m_netlist->unmark_gnd_gate(this);
579  }
580 
581  bool Gate::is_vcc_gate() const
582  {
583  return m_internal_manager->m_netlist->is_vcc_gate(this);
584  }
585 
586  bool Gate::is_gnd_gate() const
587  {
588  return m_internal_manager->m_netlist->is_gnd_gate(this);
589  }
590 
591  const std::vector<Net*>& Gate::get_fan_in_nets() const
592  {
593  return m_in_nets;
594  }
595 
596  std::vector<Net*> Gate::get_fan_in_nets(const std::function<bool(Net*)>& filter) const
597  {
598  std::vector<Net*> res;
599  if (!filter)
600  {
601  res = m_in_nets;
602  }
603  else
604  {
605  for (auto n : m_in_nets)
606  {
607  if (!filter(n))
608  {
609  continue;
610  }
611  res.push_back(n);
612  }
613  }
614  return res;
615  }
616 
617  Net* Gate::get_fan_in_net(const std::string& pin_name) const
618  {
619  auto ep = get_fan_in_endpoint(pin_name);
620  if (ep == nullptr)
621  {
622  return nullptr;
623  }
624  return ep->get_net();
625  }
626 
627  Net* Gate::get_fan_in_net(const GatePin* pin) const
628  {
629  auto ep = get_fan_in_endpoint(pin);
630  if (ep == nullptr)
631  {
632  return nullptr;
633  }
634  return ep->get_net();
635  }
636 
637  bool Gate::is_fan_in_net(const Net* net) const
638  {
639  if (net == nullptr)
640  {
641  log_warning("gate", "could not check whether net is a fan-in of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
642  return false;
643  }
644 
645  if (const auto it = std::find_if(m_in_endpoints.begin(), m_in_endpoints.end(), [net](const Endpoint* ep) { return ep->get_net() == net; }); it != m_in_endpoints.end())
646  {
647  return true;
648  }
649 
650  return false;
651  }
652 
653  const std::vector<Endpoint*>& Gate::get_fan_in_endpoints() const
654  {
655  return m_in_endpoints;
656  }
657 
658  std::vector<Endpoint*> Gate::get_fan_in_endpoints(const std::function<bool(Endpoint*)>& filter) const
659  {
660  std::vector<Endpoint*> res;
661  if (!filter)
662  {
663  res = m_in_endpoints;
664  }
665  else
666  {
667  for (auto ep : m_in_endpoints)
668  {
669  if (!filter(ep))
670  {
671  continue;
672  }
673  res.push_back(ep);
674  }
675  }
676  return res;
677  }
678 
679  Endpoint* Gate::get_fan_in_endpoint(const std::string& pin_name) const
680  {
681  const GatePin* pin = m_type->get_pin_by_name(pin_name);
682  if (pin == nullptr)
683  {
684  log_warning("gate",
685  "could not get fan-in endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
686  pin_name,
687  m_name,
688  std::to_string(m_id),
689  m_type->get_name());
690  return nullptr;
691  }
692  return get_fan_in_endpoint(pin);
693  }
694 
695  Endpoint* Gate::get_fan_in_endpoint(const GatePin* pin) const
696  {
697  if (pin == nullptr)
698  {
699  log_warning("gate", "could not get fan-in endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, m_id);
700  return nullptr;
701  }
702  if (PinDirection direction = pin->get_direction(); direction != PinDirection::input && direction != PinDirection::inout)
703  {
704  log_warning("gate", "could not get fan-in endpoint of pin '{}' at gate '{}' with ID {}: pin is not an input pin", pin->get_name(), m_name, m_id);
705  return nullptr;
706  }
707  auto it = std::find_if(m_in_endpoints.begin(), m_in_endpoints.end(), [&pin](auto& ep) { return *ep->get_pin() == *pin; });
708  if (it == m_in_endpoints.end())
709  {
710  log_debug("gate", "could not get fan-in endpoint of pin '{}' at gate '{}' with ID {}: no net is connected to pin", pin->get_name(), m_name, m_id);
711  return nullptr;
712  }
713 
714  return *it;
715  }
716 
717  Endpoint* Gate::get_fan_in_endpoint(const Net* net) const
718  {
719  if (net == nullptr)
720  {
721  log_warning("gate", "could not get fan-in endpoint of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
722  return nullptr;
723  }
724 
725  const auto it = std::find_if(m_in_endpoints.begin(), m_in_endpoints.end(), [net](const Endpoint* ep) { return ep->get_net() == net; });
726  if (it == m_in_endpoints.end())
727  {
728  log_warning("gate", "could not get fan-in endpoint of net '{}' with ID {} at gate '{}' with ID {}: net is not an input net", net->get_name(), net->get_id(), m_name, m_id);
729  return nullptr;
730  }
731 
732  return *it;
733  }
734 
735  const std::vector<Net*>& Gate::get_fan_out_nets() const
736  {
737  return m_out_nets;
738  }
739 
740  std::vector<Net*> Gate::get_fan_out_nets(const std::function<bool(Net*)>& filter) const
741  {
742  std::vector<Net*> res;
743  if (!filter)
744  {
745  res = m_out_nets;
746  }
747  else
748  {
749  for (auto n : m_out_nets)
750  {
751  if (!filter(n))
752  {
753  continue;
754  }
755  res.push_back(n);
756  }
757  }
758  return res;
759  }
760 
761  Net* Gate::get_fan_out_net(const std::string& pin_name) const
762  {
763  auto ep = get_fan_out_endpoint(pin_name);
764  if (ep == nullptr)
765  {
766  return nullptr;
767  }
768  return ep->get_net();
769  }
770 
771  Net* Gate::get_fan_out_net(const GatePin* pin) const
772  {
773  auto ep = get_fan_out_endpoint(pin);
774  if (ep == nullptr)
775  {
776  return nullptr;
777  }
778  return ep->get_net();
779  }
780 
781  bool Gate::is_fan_out_net(const Net* net) const
782  {
783  if (net == nullptr)
784  {
785  log_warning("gate", "could not check whether net is a fan-out of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
786  return false;
787  }
788 
789  if (const auto it = std::find_if(m_out_endpoints.begin(), m_out_endpoints.end(), [net](const Endpoint* ep) { return ep->get_net() == net; }); it != m_out_endpoints.end())
790  {
791  return true;
792  }
793 
794  return false;
795  }
796 
797  const std::vector<Endpoint*>& Gate::get_fan_out_endpoints() const
798  {
799  return m_out_endpoints;
800  }
801 
802  std::vector<Endpoint*> Gate::get_fan_out_endpoints(const std::function<bool(Endpoint*)>& filter) const
803  {
804  std::vector<Endpoint*> res;
805  if (!filter)
806  {
807  res = m_out_endpoints;
808  }
809  else
810  {
811  for (auto ep : m_out_endpoints)
812  {
813  if (!filter(ep))
814  {
815  continue;
816  }
817  res.push_back(ep);
818  }
819  }
820  return res;
821  }
822 
823  Endpoint* Gate::get_fan_out_endpoint(const std::string& pin_name) const
824  {
825  const GatePin* pin = m_type->get_pin_by_name(pin_name);
826  if (pin == nullptr)
827  {
828  log_warning("gate", "could not get fan-out endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'", pin_name, m_name, m_id, m_type->get_name());
829  return nullptr;
830  }
831  return get_fan_out_endpoint(pin);
832  }
833 
834  Endpoint* Gate::get_fan_out_endpoint(const GatePin* pin) const
835  {
836  if (pin == nullptr)
837  {
838  log_warning("gate", "could not get fan-out endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, m_id);
839  return nullptr;
840  }
841  if (PinDirection direction = pin->get_direction(); direction != PinDirection::output && direction != PinDirection::inout)
842  {
843  log_warning("gate", "could not get fan-out endpoint of pin '{}' at gate '{}' with ID {}: pin is not an output pin", pin->get_name(), m_name, m_id);
844  return nullptr;
845  }
846  auto it = std::find_if(m_out_endpoints.begin(), m_out_endpoints.end(), [&pin](auto& ep) { return *ep->get_pin() == *pin; });
847  if (it == m_out_endpoints.end())
848  {
849  log_debug("gate", "could not get fan-out endpoint of pin '{}' at gate '{}' with ID {}: no net is connected to pin", pin->get_name(), m_name, m_id);
850  return nullptr;
851  }
852 
853  return *it;
854  }
855 
856  Endpoint* Gate::get_fan_out_endpoint(const Net* net) const
857  {
858  if (net == nullptr)
859  {
860  log_warning("gate", "could not get fan-out endpoint of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
861  return nullptr;
862  }
863 
864  const auto it = std::find_if(m_out_endpoints.begin(), m_out_endpoints.end(), [net](const Endpoint* ep) { return ep->get_net() == net; });
865  if (it == m_out_endpoints.end())
866  {
867  log_warning("gate", "could not get fan-out endpoint of net '{}' with ID {} at gate '{}' with ID {}: net is not an output net", net->get_name(), net->get_id(), m_name, m_id);
868  return nullptr;
869  }
870 
871  return *it;
872  }
873 
874  std::vector<Gate*> Gate::get_unique_predecessors(const std::function<bool(const GatePin* pin, Endpoint*)>& filter) const
875  {
876  std::unordered_set<Gate*> res;
877  auto endpoints = get_predecessors(filter);
878  res.reserve(endpoints.size());
879  for (auto ep : endpoints)
880  {
881  res.insert(ep->get_gate());
882  }
883  return std::vector<Gate*>(res.begin(), res.end());
884  }
885 
886  std::vector<Endpoint*> Gate::get_predecessors(const std::function<bool(const GatePin* pin, Endpoint*)>& filter) const
887  {
888  std::vector<Endpoint*> result;
889  for (auto ep : m_in_endpoints)
890  {
891  auto pred_pin = ep->get_pin();
892  auto predecessors = ep->get_net()->get_sources();
893  if (!filter)
894  {
895  result.insert(result.end(), predecessors.begin(), predecessors.end());
896  }
897  else
898  {
899  for (auto pre : predecessors)
900  {
901  if (!filter(pred_pin, pre))
902  {
903  continue;
904  }
905  result.push_back(pre);
906  }
907  }
908  }
909  return result;
910  }
911 
912  Endpoint* Gate::get_predecessor(const GatePin* pin) const
913  {
914  if (pin == nullptr)
915  {
916  log_warning("gate", "could not get predecessor endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, std::to_string(m_id));
917  return nullptr;
918  }
919  if (auto direction = pin->get_direction(); direction != PinDirection::input && direction != PinDirection::inout)
920  {
921  log_warning("gate", "could not get predecessor endpoint of pin '{}' at gate '{}' with ID {}: pin is not an input pin", pin->get_name(), m_name, std::to_string(m_id));
922  return nullptr;
923  }
924  auto predecessors = get_predecessors([pin](const auto p, auto) -> bool { return *p == *pin; });
925  if (predecessors.size() == 0)
926  {
927  return nullptr;
928  }
929  if (predecessors.size() > 1)
930  {
931  log_warning("gate", "gate '{}' with ID {} has multiple predecessors at input pin '{}' in netlist with ID {}.", m_name, m_id, pin->get_name(), m_internal_manager->m_netlist->get_id());
932  return nullptr;
933  }
934 
935  return predecessors[0];
936  }
937 
938  Endpoint* Gate::get_predecessor(const std::string& pin_name) const
939  {
940  const GatePin* pin = m_type->get_pin_by_name(pin_name);
941  if (pin == nullptr)
942  {
943  log_warning("gate",
944  "could not get predecessor endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
945  pin_name,
946  m_name,
947  std::to_string(m_id),
948  m_type->get_name());
949  return nullptr;
950  }
951  return get_predecessor(pin);
952  }
953 
954  std::vector<Gate*> Gate::get_unique_successors(const std::function<bool(const GatePin* pin, Endpoint*)>& filter) const
955  {
956  std::unordered_set<Gate*> res;
957  auto endpoints = get_successors(filter);
958  res.reserve(endpoints.size());
959  for (auto ep : endpoints)
960  {
961  res.insert(ep->get_gate());
962  }
963  return std::vector<Gate*>(res.begin(), res.end());
964  }
965 
966  std::vector<Endpoint*> Gate::get_successors(const std::function<bool(const GatePin* pin, Endpoint*)>& filter) const
967  {
968  std::vector<Endpoint*> result;
969  for (auto ep : m_out_endpoints)
970  {
971  auto suc_pin = ep->get_pin();
972  auto successors = ep->get_net()->get_destinations();
973  if (!filter)
974  {
975  result.insert(result.end(), successors.begin(), successors.end());
976  }
977  else
978  {
979  for (auto suc : successors)
980  {
981  if (!filter(suc_pin, suc))
982  {
983  continue;
984  }
985  result.push_back(suc);
986  }
987  }
988  }
989  return result;
990  }
991 
992  Endpoint* Gate::get_successor(const GatePin* pin) const
993  {
994  if (pin == nullptr)
995  {
996  log_warning("gate", "could not get successor endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, std::to_string(m_id));
997  return nullptr;
998  }
999  if (auto direction = pin->get_direction(); direction != PinDirection::output && direction != PinDirection::inout)
1000  {
1001  log_warning("gate", "could not get successor endpoint of pin '{}' at gate '{}' with ID {}: pin is not an output pin", pin->get_name(), m_name, std::to_string(m_id));
1002  return nullptr;
1003  }
1004  auto successors = get_successors([pin](const auto p, auto) -> bool { return *p == *pin; });
1005  if (successors.size() == 0)
1006  {
1007  return nullptr;
1008  }
1009  if (successors.size() > 1)
1010  {
1011  log_warning("gate", "gate '{}' with ID {} has multiple successor at output pin '{}' in netlist with ID {}.", m_name, m_id, pin->get_name(), m_internal_manager->m_netlist->get_id());
1012  return nullptr;
1013  }
1014 
1015  return successors[0];
1016  }
1017 
1018  Endpoint* Gate::get_successor(const std::string& pin_name) const
1019  {
1020  const GatePin* pin = m_type->get_pin_by_name(pin_name);
1021  if (pin == nullptr)
1022  {
1023  log_warning("gate",
1024  "could not get successor endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
1025  pin_name,
1026  m_name,
1027  std::to_string(m_id),
1028  m_type->get_name());
1029  return nullptr;
1030  }
1031  return get_successor(pin);
1032  }
1033 
1034  Result<std::vector<std::string>> Gate::get_init_data() const
1035  {
1036  InitComponent* init_component = m_type->get_component_as<InitComponent>([](const GateTypeComponent* c) { return c->get_type() == GateTypeComponent::ComponentType::init; });
1037  if (init_component == nullptr)
1038  {
1039  return ERR("could not get INIT data for gate '" + m_name + "' with ID '" + std::to_string(m_id) + "': type '" + m_type->get_name() + "' with ID " + std::to_string(m_type->get_id())
1040  + "' cannot hold INIT data");
1041  }
1042 
1043  const std::string& category = init_component->get_init_category();
1044  const std::vector<std::string>& identifiers = init_component->get_init_identifiers();
1045 
1046  std::vector<std::string> init_data;
1047  for (const std::string& id : identifiers)
1048  {
1049  init_data.push_back(std::get<1>(get_data(category, id)));
1050  }
1051 
1052  return OK(init_data);
1053  }
1054 
1055  Result<std::monostate> Gate::set_init_data(const std::vector<std::string>& init_data)
1056  {
1057  InitComponent* init_component = m_type->get_component_as<InitComponent>([](const GateTypeComponent* c) { return c->get_type() == GateTypeComponent::ComponentType::init; });
1058  if (init_component == nullptr)
1059  {
1060  return ERR("could not set INIT data for gate '" + m_name + "' with ID '" + std::to_string(m_id) + "': type '" + m_type->get_name() + "' with ID " + std::to_string(m_type->get_id())
1061  + "' cannot hold INIT data");
1062  }
1063 
1064  const std::string& category = init_component->get_init_category();
1065  const std::vector<std::string>& identifiers = init_component->get_init_identifiers();
1066 
1067  if (identifiers.size() != init_data.size())
1068  {
1069  return ERR("could not set INIT data for gate '" + m_name + "' with ID '" + std::to_string(m_id) + "': provided INIT data has size " + std::to_string(init_data.size())
1070  + " and must be of size " + std::to_string(identifiers.size()));
1071  }
1072 
1073  u32 i = 0;
1074  for (const std::string& id : identifiers)
1075  {
1076  set_data(category, id, "bit_vector", init_data.at(i));
1077  i++;
1078  }
1079 
1080  return OK({});
1081  }
1082 } // namespace hal
const std::string & get_name() const
Definition: base_pin.h:108
PinType get_type() const
Definition: base_pin.h:148
PinDirection get_direction() const
Definition: base_pin.h:128
std::set< std::string > get_variable_names() const
Result< std::vector< std::vector< Value > > > compute_truth_table(const std::vector< std::string > &ordered_variables={}, bool remove_unknown_variables=false) const
static std::string to_string(Value value)
BooleanFunction substitute(const std::string &old_variable_name, const std::string &new_variable_name) const
Definition: gate.h:58
i32 get_location_x() const
Definition: gate.cpp:130
i32 get_location_y() const
Definition: gate.cpp:135
GateType * get_type() const
Definition: gate.cpp:125
const std::string & get_name() const
Definition: gate.cpp:105
bool is_vcc_gate() const
Definition: gate.cpp:581
bool is_gnd_gate() const
Definition: gate.cpp:586
std::unordered_map< std::string, BooleanFunction > get_boolean_functions(bool only_custom_functions=false) const
Definition: gate.cpp:262
u32 get_id() const
Definition: gate.cpp:95
T * get_component_as(const std::function< bool(const GateTypeComponent *)> &filter=nullptr)
const std::string & get_init_category() const
const std::vector< std::string > & get_init_identifiers() const
bool is_init_ascending() const
std::vector< Module * > get_parent_modules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=true) const
Definition: module.cpp:130
Definition: net.h:58
uint64_t u64
Definition: defines.h:42
uint8_t u8
Definition: defines.h:39
#define UNUSED(expr)
Definition: defines.h:49
int32_t i32
Definition: defines.h:36
#define log_error(channel,...)
Definition: log.h:78
#define log_debug(channel,...)
Definition: log.h:74
#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
CORE_API T trim(const T &s, const char *to_remove=" \t\r\n")
Definition: utils.h:358
CORE_API std::vector< T > to_vector(const Container< T, Args... > &container)
Definition: utils.h:513
PinDirection
Definition: pin_direction.h:36
n
Definition: test.py:6
quint32 u32
Net * net
PinDirection direction
std::string name
i32 id