25 template<
typename T, T m,
int k>
26 inline T swapbits(T p)
28 T q = ((p >> k) ^ p) & m;
29 return p ^ q ^ (q << k);
39 return (pv.size() >= 2 && pv[0] ==
'0' && pv[1] ==
'x') ? pv.substr(2) : pv;
42 void lut_init_write(
hal::DataContainer* dc,
const std::string& key,
const std::string& plain_hex)
44 if (plain_hex.empty())
48 const std::string value =
"0x" + plain_hex;
49 const size_t nbits = plain_hex.size() * 4;
50 if (nbits == 0 || nbits > 64)
56 if (param_res.is_error())
66 static const u64 m0 = 0x5555555555555555LLU;
67 static const u64 m1 = 0x0300c0303030c303LLU;
68 static const u64 m2 = 0x00c0300c03f0003fLLU;
69 static const u64 m3 = 0x00000ffc00003fffLLU;
70 n = ((n >> 1) & m0) | (n & m0) << 1;
71 n = swapbits<u64, m1, 4>(n);
72 n = swapbits<u64, m2, 8>(n);
73 n = swapbits<u64, m3, 20>(n);
74 n = (n >> 34) | (n << 30);
81 Gate::Gate(NetlistInternalManager* mgr, EventHandler* event_handler,
const u32 id, GateType* gt,
const std::string&
name,
i32 x,
i32 y)
82 : m_internal_manager(mgr), m_id(
id), m_name(
name), m_type(gt), m_x(
x), m_y(
y), m_event_handler(event_handler)
87 bool Gate::operator==(
const Gate& other)
const
91 log_debug(
"gate",
"the gates with IDs {} and {} are not equal due to an unequal ID, name, or type.", m_id, other.
get_id());
97 log_debug(
"gate",
"the gates with IDs {} and {} are not equal due to unequal location data.", m_id, other.
get_id());
103 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());
109 log_debug(
"gate",
"the gates with IDs {} and {} are not equal due to an unequal Boolean functions.", m_id, other.
get_id());
113 if (!DataContainer::operator==(other))
115 log_debug(
"gate",
"the gates with IDs {} and {} are not equal due to unequal data.", m_id, other.
get_id());
122 bool Gate::operator!=(
const Gate& other)
const
124 return !operator==(other);
127 ssize_t Gate::get_hash()
const
129 return (uintptr_t)
this;
139 return m_internal_manager->m_netlist;
142 const std::string& Gate::get_name()
const
147 void Gate::set_name(
const std::string&
name)
151 log_error(
"gate",
"gate name cannot be empty.");
158 m_event_handler->notify(GateEvent::event::name_changed,
this);
167 i32 Gate::get_location_x()
const
172 i32 Gate::get_location_y()
const
177 std::pair<i32, i32> Gate::get_location()
const
182 bool Gate::has_location()
const
184 return m_x >= 0 && m_y >= 0;
187 void Gate::set_location_x(
i32 x)
192 m_event_handler->notify(GateEvent::event::location_changed,
this);
196 void Gate::set_location_y(
i32 y)
201 m_event_handler->notify(GateEvent::event::location_changed,
this);
205 void Gate::set_location(
const std::pair<i32, i32>& location)
207 set_location_x(location.first);
208 set_location_y(location.second);
216 std::vector<Module*> Gate::get_modules(
const std::function<
bool(
Module*)>& filter,
bool recursive)
const
218 std::vector<Module*> res;
222 res.push_back(m_module);
226 if (filter(m_module))
228 res.push_back(m_module);
235 res.reserve(res.size() + more.size());
236 res.insert(res.end(), more.begin(), more.end());
248 std::string internal_name =
name;
249 if (internal_name.empty())
251 const auto output_pins = m_type->get_output_pins();
252 if (output_pins.empty())
254 log_warning(
"gate",
"could not get Boolean function of gate '{}' with ID {}: gate type has no output pins", m_name, m_id);
257 internal_name = output_pins.front()->get_name();
259 auto res = get_boolean_function(internal_name,
false,
false);
272 return ERR(
"could not get Boolean function of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": name must not be empty");
274 const std::string& internal_name =
name;
276 if (substitute_nets && !inlined)
278 return ERR(
"could not get Boolean function '" + internal_name +
"' of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": substitute_nets requires inlined=true");
284 if (m_type->has_component_of_type(GateTypeComponent::ComponentType::lut))
286 auto lut_pins = m_type->get_pins([&internal_name](
const GatePin* p) {
return p->
get_type() == PinType::lut && p->
get_name() == internal_name; });
287 if (!lut_pins.empty())
289 return OK(get_lut_function(lut_pins.front()));
292 if (
auto it = m_functions.find(internal_name); it != m_functions.end())
294 return OK(it->second);
296 const auto type_bfs = m_type->get_boolean_functions();
297 if (
auto it = type_bfs.find(internal_name); it != type_bfs.end())
299 return OK(it->second);
301 return ERR(
"could not get Boolean function '" + internal_name +
"' of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": no function with that name exists");
308 const GatePin* pin = m_type->get_pin_by_name(internal_name);
311 std::unordered_set<std::string> on_stack = {internal_name};
312 auto res = get_inlined_boolean_function(get_boolean_function(pin), on_stack);
315 return ERR_APPEND(res.get_error(),
"could not get Boolean function '" + internal_name +
"' of gate '" + m_name +
"' with ID " + std::to_string(m_id));
322 if (
auto it = m_functions.find(internal_name); it != m_functions.end())
328 const auto type_bfs = m_type->get_boolean_functions();
329 if (
auto it = type_bfs.find(internal_name); it != type_bfs.end())
335 return ERR(
"could not get Boolean function '" + internal_name +
"' of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": no function with that name exists");
338 std::unordered_set<std::string> on_stack;
339 auto res = get_inlined_boolean_function(bf, on_stack);
342 return ERR_APPEND(res.get_error(),
"could not get Boolean function '" + internal_name +
"' of gate '" + m_name +
"' with ID " + std::to_string(m_id));
350 std::map<std::string, BooleanFunction> net_subs;
353 if (type_params.count(var))
357 const GatePin* var_pin = m_type->get_pin_by_name(var);
358 if (var_pin ==
nullptr || var_pin->
get_direction() != PinDirection::input)
360 return ERR(
"could not get Boolean function '" + internal_name +
"' of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": variable '" + var
361 +
"' is not a recognized input pin");
363 const Net*
const input_net = get_fan_in_net(var);
364 if (input_net ==
nullptr)
366 return ERR(
"could not get Boolean function '" + internal_name +
"' of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": no fan-in net at pin '" + var +
"'");
370 if (!net_subs.empty())
373 if (sub_res.is_error())
376 "could not get Boolean function '" + internal_name +
"' of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": net substitution failed");
389 auto output_pins = m_type->get_output_pins();
390 if (output_pins.empty())
392 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());
395 pin = output_pins.front();
397 return get_boolean_function(pin->
get_name());
404 return ERR(
"could not get Boolean function of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": given pin is a nullptr");
406 return get_boolean_function(pin->
get_name(), inlined, substitute_nets);
409 bool Gate::has_boolean_function(
const std::string&
name)
const
412 std::string internal_name =
name;
413 if (internal_name.empty())
415 auto output_pins = m_type->get_output_pins();
416 if (output_pins.empty())
420 internal_name = output_pins.front()->get_name();
423 if (m_type->has_component_of_type(GateTypeComponent::ComponentType::lut))
425 if (
const GatePin* pin = m_type->get_pin_by_name(internal_name); pin !=
nullptr && pin->
get_type() == PinType::lut)
431 if (m_functions.find(internal_name) != m_functions.end())
436 const auto& map = m_type->get_boolean_functions();
437 return map.find(internal_name) != map.end();
440 bool Gate::has_boolean_function(
const GatePin* pin)
const
445 return has_boolean_function(std::string());
448 return has_boolean_function(pin->
get_name());
451 std::unordered_map<std::string, BooleanFunction> Gate::get_boolean_functions(
bool only_custom_functions)
const
453 std::unordered_map<std::string, BooleanFunction> result;
454 if (!only_custom_functions)
456 for (
const auto& [fn, _] : m_type->get_boolean_functions())
458 result[fn] = get_boolean_function(fn);
460 if (m_type->has_component_of_type(GateTypeComponent::ComponentType::lut))
462 for (
const auto* p : m_type->get_pins([](
const GatePin* p) { return p->get_type() == PinType::lut; }))
468 for (
const auto& [fn, _] : m_functions)
470 result[fn] = get_boolean_function(fn);
477 std::vector<std::string> names;
478 if (!only_custom_functions)
480 for (
const auto& [fn, _] : m_type->get_boolean_functions())
484 if (m_type->has_component_of_type(GateTypeComponent::ComponentType::lut))
486 for (
const auto* p : m_type->get_pins([](
const GatePin* p) { return p->get_type() == PinType::lut; }))
492 for (
const auto& [fn, _] : m_functions)
497 std::unordered_map<std::string, BooleanFunction> result;
498 for (
const auto& fn : names)
500 auto res = get_boolean_function(fn, inlined, substitute_nets);
503 return ERR_APPEND(res.get_error(),
"could not get Boolean functions of gate '" + m_name +
"' with ID " + std::to_string(m_id));
505 result[fn] = res.get();
512 const auto& type_params = m_type->get_parameters();
513 std::map<std::string, BooleanFunction> subs;
514 bool has_param_subs =
false;
518 const GatePin* var_pin = m_type->get_pin_by_name(var);
519 if (var_pin ==
nullptr)
522 if (type_params.count(var))
524 if (
const auto it = m_parameters.find(var); it != m_parameters.end())
526 const auto& [decl, value] = it->second;
527 if (
auto enc = decl.encode_as_int(value); enc.is_ok())
529 subs[var] = BooleanFunction::Const(enc.get(), decl.get_size());
530 has_param_subs =
true;
538 if (dir == PinDirection::internal || dir == PinDirection::output)
540 if (on_stack.count(var))
542 return ERR(
"could not inline Boolean function of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": circular dependency at variable '" + var +
"'");
544 on_stack.insert(var);
545 auto res = get_inlined_boolean_function(get_boolean_function(var_pin), on_stack);
549 return ERR_APPEND(res.get_error(),
"could not inline Boolean function of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": failed at variable '" + var +
"'");
551 subs[var] = res.get();
559 if (sub_res.is_error())
561 return ERR_APPEND(sub_res.get_error(),
"could not inline Boolean function of gate '" + m_name +
"' with ID " + std::to_string(m_id) +
": substitution failed");
563 bf = has_param_subs ? sub_res.get().
simplify() : sub_res.get();
569 BooleanFunction Gate::get_lut_function(
const GatePin* pin)
const
573 log_error(
"gate",
"could not get LUT function of gate '{}' with ID {}: pin is nullptr.", m_name, m_id);
574 return BooleanFunction();
577 const LUTComponent* lut_component = m_type->get_component_as<LUTComponent>([](
const GateTypeComponent* c) {
return c->get_type() == GateTypeComponent::ComponentType::lut; });
578 if (lut_component ==
nullptr)
580 return BooleanFunction();
583 const LUTComponent::LUTOutputConfig* cfg = lut_component->get_output_pin_config(pin->get_name());
586 return BooleanFunction();
589 const u32 bit_count = cfg->bit_count;
590 const u32 bit_offset = cfg->bit_offset;
594 log_error(
"gate",
"LUT gate '{}' with ID {} in netlist with ID {} has an INIT string longer than 64 bits, which is not supported.", m_name, m_id, m_internal_manager->m_netlist->get_id());
595 return BooleanFunction();
598 std::string config_str = lut_init_read(
this, cfg->init_identifier);
599 if (config_str.empty())
601 return BooleanFunction::Const(BooleanFunction::Value::ZERO);
604 if (cfg->input_pins.empty())
606 log_error(
"gate",
"LUT gate '{}' with ID {}: output pin '{}' has no input_pins configured.", m_name, m_id, pin->get_name());
607 return BooleanFunction();
609 std::vector<GatePin*> inputs;
610 for (
const auto& pname : cfg->input_pins)
612 if (GatePin* p = m_type->get_pin_by_name(pname); p !=
nullptr)
619 auto res = LUTComponent::extract_init_slice(config_str, bit_offset, bit_count);
622 log_error(
"gate",
"LUT gate '{}' with ID {} in netlist with ID {}: {}", m_name, m_id, m_internal_manager->m_netlist->get_id(), res.get_error().get());
623 return BooleanFunction();
625 config_str = res.get();
631 config = std::stoull(config_str,
nullptr, 16);
633 catch (
const std::invalid_argument&)
636 "LUT gate '{}' with ID {} in netlist with ID {} has invalid configuration string of '{}', which is not a hex value.",
639 m_internal_manager->m_netlist->get_id(),
641 return BooleanFunction();
643 catch (
const std::out_of_range&)
646 "LUT gate '{}' with ID {} in netlist with ID {} has invalid configuration string of '{}', which has too many hex digits.",
649 m_internal_manager->m_netlist->get_id(),
651 return BooleanFunction();
654 const u32 max_config_size = bit_count;
656 if (cfg->is_ascending)
658 config = bitreverse(config) >> (64 - max_config_size);
661 auto& cache = m_internal_manager->m_lut_function_cache;
662 const auto cache_key = std::make_pair(inputs, config);
663 if (
const auto it = cache.find(cache_key); it != cache.end())
668 const u32 config_size = (config == 0) ? 0 : (64u -
static_cast<u32>(__builtin_clzll(config)));
669 if (config_size > max_config_size)
672 "LUT gate '{}' with ID {} in netlist with ID {} supports up to {} config bits, but '{}' encodes {} bits.",
675 m_internal_manager->m_netlist->get_id(),
678 config_str.size() * 4);
679 return BooleanFunction();
682 auto result = BooleanFunction::Const(BooleanFunction::Value::ZERO);
683 for (
u32 i = 0; config != 0 && i < max_config_size; i++)
687 auto conjunction = BooleanFunction::Const(1, 1);
688 auto input_values = i;
689 for (
auto input : inputs)
691 conjunction &= ((input_values & 1) == 1) ? BooleanFunction::Var(
input->get_name()) : ~BooleanFunction::Var(
input->get_name());
694 result |= conjunction;
699 auto f = result.simplify();
700 cache[cache_key] = f;
707 if (lut_component !=
nullptr)
711 if (!lut_pins.empty() && output_cfg !=
nullptr)
718 std::vector<std::string> input_pin_names;
725 input_pin_names = m_type->get_input_pin_names();
726 const u32 effective_count = __builtin_ctz(bit_count);
727 if (effective_count < input_pin_names.size())
729 input_pin_names.resize(effective_count);
736 log_error(
"netlist",
"Boolean function '{} = {}' cannot be added to LUT gate '{}' with ID {}.",
name, func.
to_string(), m_name, m_id);
739 auto truth_table = tt.get();
740 if (truth_table.size() > 1)
742 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);
748 std::reverse(truth_table[0].begin(), truth_table[0].end());
752 for (
auto v : truth_table[0])
754 if (v == BooleanFunction::X)
757 "Boolean function '{} = {}' cannot be added to LUT gate '{}' with ID {} in netlist with ID {} as its truth table contains undefined values.",
762 m_internal_manager->m_netlist->get_id());
770 const u32 total_inputs = m_type->get_input_pins().size();
771 std::string existing_str = lut_init_read(
this, key);
772 if (existing_str.empty())
774 existing_str = std::string(
static_cast<size_t>(1u << (total_inputs - 2)),
'0');
777 std::stringstream slice_ss;
778 slice_ss << std::hex << std::setfill('0') << std::setw(static_cast<int>((bit_count + 3) / 4)) << new_bits;
780 auto res = LUTComponent::splice_init_slice(existing_str, slice_ss.str(), bit_offset, bit_count);
783 log_error(
"netlist",
"cannot add Boolean function '{}' to LUT gate '{}' with ID {}: {}.",
name, m_name, m_id, res.get_error().get());
786 lut_init_write(
this, key, res.get());
791 m_functions[
name] = func;
792 m_event_handler->notify(GateEvent::event::boolean_function_changed,
this);
796 bool Gate::mark_vcc_gate()
798 return m_internal_manager->m_netlist->mark_vcc_gate(
this);
801 bool Gate::mark_gnd_gate()
803 return m_internal_manager->m_netlist->mark_gnd_gate(
this);
806 bool Gate::unmark_vcc_gate()
808 return m_internal_manager->m_netlist->unmark_vcc_gate(
this);
811 bool Gate::unmark_gnd_gate()
813 return m_internal_manager->m_netlist->unmark_gnd_gate(
this);
816 bool Gate::is_vcc_gate()
const
818 return m_internal_manager->m_netlist->is_vcc_gate(
this);
821 bool Gate::is_gnd_gate()
const
823 return m_internal_manager->m_netlist->is_gnd_gate(
this);
826 const std::vector<Net*>& Gate::get_fan_in_nets()
const
831 std::vector<Net*> Gate::get_fan_in_nets(
const std::function<
bool(
Net*)>& filter)
const
833 std::vector<Net*> res;
840 for (
auto n : m_in_nets)
852 Net* Gate::get_fan_in_net(
const std::string& pin_name)
const
854 auto ep = get_fan_in_endpoint(pin_name);
859 return ep->get_net();
864 auto ep = get_fan_in_endpoint(pin);
869 return ep->get_net();
872 bool Gate::is_fan_in_net(
const Net*
net)
const
876 log_warning(
"gate",
"could not check whether net is a fan-in of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
880 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())
888 const std::vector<Endpoint*>& Gate::get_fan_in_endpoints()
const
890 return m_in_endpoints;
893 std::vector<Endpoint*> Gate::get_fan_in_endpoints(
const std::function<
bool(
Endpoint*)>& filter)
const
895 std::vector<Endpoint*> res;
898 res = m_in_endpoints;
902 for (
auto ep : m_in_endpoints)
914 Endpoint* Gate::get_fan_in_endpoint(
const std::string& pin_name)
const
916 const GatePin* pin = m_type->get_pin_by_name(pin_name);
920 "could not get fan-in endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
923 std::to_string(m_id),
927 return get_fan_in_endpoint(pin);
934 log_warning(
"gate",
"could not get fan-in endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, m_id);
939 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);
942 auto it = std::find_if(m_in_endpoints.begin(), m_in_endpoints.end(), [pin](
const auto* ep) { return ep->get_pin() == pin; });
943 if (it == m_in_endpoints.end())
945 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);
956 log_warning(
"gate",
"could not get fan-in endpoint of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
960 const auto it = std::find_if(m_in_endpoints.begin(), m_in_endpoints.end(), [
net](
const Endpoint* ep) { return ep->get_net() == net; });
961 if (it == m_in_endpoints.end())
963 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);
970 const std::vector<Net*>& Gate::get_fan_out_nets()
const
975 std::vector<Net*> Gate::get_fan_out_nets(
const std::function<
bool(
Net*)>& filter)
const
977 std::vector<Net*> res;
984 for (
auto n : m_out_nets)
996 Net* Gate::get_fan_out_net(
const std::string& pin_name)
const
998 auto ep = get_fan_out_endpoint(pin_name);
1003 return ep->get_net();
1008 auto ep = get_fan_out_endpoint(pin);
1013 return ep->get_net();
1016 bool Gate::is_fan_out_net(
const Net*
net)
const
1020 log_warning(
"gate",
"could not check whether net is a fan-out of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
1024 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())
1032 const std::vector<Endpoint*>& Gate::get_fan_out_endpoints()
const
1034 return m_out_endpoints;
1037 std::vector<Endpoint*> Gate::get_fan_out_endpoints(
const std::function<
bool(
Endpoint*)>& filter)
const
1039 std::vector<Endpoint*> res;
1042 res = m_out_endpoints;
1046 for (
auto ep : m_out_endpoints)
1058 Endpoint* Gate::get_fan_out_endpoint(
const std::string& pin_name)
const
1060 const GatePin* pin = m_type->get_pin_by_name(pin_name);
1063 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());
1066 return get_fan_out_endpoint(pin);
1073 log_warning(
"gate",
"could not get fan-out endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, m_id);
1078 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);
1081 auto it = std::find_if(m_out_endpoints.begin(), m_out_endpoints.end(), [pin](
const auto* ep) { return ep->get_pin() == pin; });
1082 if (it == m_out_endpoints.end())
1084 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);
1095 log_warning(
"gate",
"could not get fan-out endpoint of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
1099 const auto it = std::find_if(m_out_endpoints.begin(), m_out_endpoints.end(), [
net](
const Endpoint* ep) { return ep->get_net() == net; });
1100 if (it == m_out_endpoints.end())
1102 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);
1109 std::vector<Gate*> Gate::get_unique_predecessors(
const std::function<
bool(
const GatePin* pin,
Endpoint*)>& filter)
const
1111 std::unordered_set<Gate*> res;
1112 auto endpoints = get_predecessors(filter);
1113 res.reserve(endpoints.size());
1114 for (
auto ep : endpoints)
1116 res.insert(ep->get_gate());
1118 return std::vector<Gate*>(res.begin(), res.end());
1121 std::vector<Endpoint*> Gate::get_predecessors(
const std::function<
bool(
const GatePin* pin,
Endpoint*)>& filter)
const
1123 std::vector<Endpoint*> result;
1124 for (
auto ep : m_in_endpoints)
1126 auto pred_pin = ep->get_pin();
1127 auto predecessors = ep->get_net()->get_sources();
1130 result.insert(result.end(), predecessors.begin(), predecessors.end());
1134 for (
auto pre : predecessors)
1136 if (!filter(pred_pin, pre))
1140 result.push_back(pre);
1151 log_warning(
"gate",
"could not get predecessor endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, std::to_string(m_id));
1156 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));
1159 auto predecessors = get_predecessors([pin](
const auto p,
auto) ->
bool {
return *p == *pin; });
1160 if (predecessors.size() == 0)
1164 if (predecessors.size() > 1)
1166 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());
1170 return predecessors[0];
1173 Endpoint* Gate::get_predecessor(
const std::string& pin_name)
const
1175 const GatePin* pin = m_type->get_pin_by_name(pin_name);
1179 "could not get predecessor endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
1182 std::to_string(m_id),
1183 m_type->get_name());
1186 return get_predecessor(pin);
1189 std::vector<Gate*> Gate::get_unique_successors(
const std::function<
bool(
const GatePin* pin,
Endpoint*)>& filter)
const
1191 std::unordered_set<Gate*> res;
1192 auto endpoints = get_successors(filter);
1193 res.reserve(endpoints.size());
1194 for (
auto ep : endpoints)
1196 res.insert(ep->get_gate());
1198 return std::vector<Gate*>(res.begin(), res.end());
1201 std::vector<Endpoint*> Gate::get_successors(
const std::function<
bool(
const GatePin* pin,
Endpoint*)>& filter)
const
1203 std::vector<Endpoint*> result;
1204 for (
auto ep : m_out_endpoints)
1206 auto suc_pin = ep->get_pin();
1207 auto successors = ep->get_net()->get_destinations();
1210 result.insert(result.end(), successors.begin(), successors.end());
1214 for (
auto suc : successors)
1216 if (!filter(suc_pin, suc))
1220 result.push_back(suc);
1231 log_warning(
"gate",
"could not get successor endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, std::to_string(m_id));
1236 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));
1239 auto successors = get_successors([pin](
const auto p,
auto) ->
bool {
return *p == *pin; });
1240 if (successors.size() == 0)
1244 if (successors.size() > 1)
1246 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());
1250 return successors[0];
1253 Endpoint* Gate::get_successor(
const std::string& pin_name)
const
1255 const GatePin* pin = m_type->get_pin_by_name(pin_name);
1259 "could not get successor endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
1262 std::to_string(m_id),
1263 m_type->get_name());
1266 return get_successor(pin);
const std::string & get_name() const
PinDirection get_direction() const
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
BooleanFunction simplify() const
static std::string to_string(Value value)
std::vector< BooleanFunction > get_parameters() const
BooleanFunction substitute(const std::string &old_variable_name, const std::string &new_variable_name) const
BooleanFunction get_boolean_variable() const
Result< std::string > get_parameter_value(const std::string &name) const
bool has_parameter(const Parameter ¶m) const
Result< std::monostate > set_parameter(const Parameter ¶m, const std::string &value)
i32 get_location_x() const
i32 get_location_y() const
GateType * get_type() const
const std::string & get_name() const
std::unordered_map< std::string, BooleanFunction > get_boolean_functions(bool only_custom_functions=false) const
T * get_component_as(const std::function< bool(const GateTypeComponent *)> &filter=nullptr)
const LUTOutputConfig * get_output_pin_config(const std::string &pin_name) const
std::vector< Module * > get_parent_modules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=true) const
#define log_error(channel,...)
#define log_debug(channel,...)
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
T trim(const T &s, const char *to_remove=" \t\r\n")
std::vector< std::string > input_pins
std::string init_identifier
static Result< Parameter > BitVector(const std::string &name, u16 size, const std::string &default_value)