21 template<
typename T, T m,
int k>
22 static inline T swapbits(T p)
24 T q = ((p >> k) ^ p) & m;
25 return p ^ q ^ (q << k);
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);
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)
50 bool Gate::operator==(
const Gate& other)
const
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());
60 log_debug(
"gate",
"the gates with IDs {} and {} are not equal due to unequal location data.", m_id, other.
get_id());
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());
72 log_debug(
"gate",
"the gates with IDs {} and {} are not equal due to an unequal Boolean functions.", m_id, other.
get_id());
76 if (!DataContainer::operator==(other))
78 log_debug(
"gate",
"the gates with IDs {} and {} are not equal due to unequal data.", m_id, other.
get_id());
85 bool Gate::operator!=(
const Gate& other)
const
87 return !operator==(other);
90 ssize_t Gate::get_hash()
const
92 return (uintptr_t)
this;
95 u32 Gate::get_id()
const
102 return m_internal_manager->m_netlist;
105 const std::string& Gate::get_name()
const
110 void Gate::set_name(
const std::string&
name)
114 log_error(
"gate",
"gate name cannot be empty.");
121 m_event_handler->notify(GateEvent::event::name_changed,
this);
130 i32 Gate::get_location_x()
const
135 i32 Gate::get_location_y()
const
140 std::pair<i32, i32> Gate::get_location()
const
145 bool Gate::has_location()
const
147 return m_x >= 0 && m_y >= 0;
150 void Gate::set_location_x(
i32 x)
155 m_event_handler->notify(GateEvent::event::location_changed,
this);
159 void Gate::set_location_y(
i32 y)
164 m_event_handler->notify(GateEvent::event::location_changed,
this);
168 void Gate::set_location(
const std::pair<i32, i32>& location)
170 set_location_x(location.first);
171 set_location_y(location.second);
179 std::vector<Module*> Gate::get_modules(
const std::function<
bool(
Module*)>& filter,
bool recursive)
const
181 std::vector<Module*> res;
185 res.push_back(m_module);
189 if (filter(m_module))
191 res.push_back(m_module);
198 res.reserve(res.size() + more.size());
199 res.insert(res.end(), more.begin(), more.end());
211 std::string internal_name =
name;
212 if (internal_name.empty())
214 auto output_pins = m_type->get_output_pins();
215 if (output_pins.empty())
219 internal_name = output_pins.front()->get_name();
222 if (m_type->has_component_of_type(GateTypeComponent::ComponentType::lut))
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())
227 return get_lut_function(lut_pins.front());
231 if (
auto it = m_functions.find(internal_name); it != m_functions.end())
236 auto map = m_type->get_boolean_functions();
237 if (
auto it = map.find(internal_name); it != map.end())
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));
250 auto output_pins = m_type->get_output_pins();
251 if (output_pins.empty())
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());
256 pin = output_pins.front();
259 return get_boolean_function(pin->
get_name());
262 std::unordered_map<std::string, BooleanFunction> Gate::get_boolean_functions(
bool only_custom_functions)
const
264 std::unordered_map<std::string, BooleanFunction> res;
266 if (!only_custom_functions)
268 res = m_type->get_boolean_functions();
271 for (
const auto& it : m_functions)
273 res[it.first] = it.second;
276 if (!only_custom_functions && m_type->has_component_of_type(GateTypeComponent::ComponentType::lut))
278 for (
auto pin : m_type->get_pins([](
const GatePin* pin) { return pin->get_type() == PinType::lut; }))
280 res[pin->
get_name()] = get_lut_function(pin);
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)
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.");
296 if (on_stack.find(output_pin->get_name()) != on_stack.end())
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() +
"'");
301 on_stack.insert(output_pin->get_name());
305 std::map<std::string, BooleanFunction> input_to_bf;
309 const GatePin* pin = this->get_type()->get_pin_by_name(var);
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
317 if (pin_dir == PinDirection::input)
319 if (!use_net_variables)
321 const Net*
const input_net = this->get_fan_in_net(var);
322 if (input_net ==
nullptr)
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 '"
330 input_to_bf.insert({var, net_dec.get_boolean_variable()});
333 else if ((pin_dir == PinDirection::internal) || (pin_dir == PinDirection::output))
335 const auto bf_interal_res = get_resolved_boolean_function_internal(pin, on_stack);
336 if (bf_interal_res.is_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() +
"'");
343 input_to_bf.insert({pin->
get_name(), bf_interal_res.get()});
347 if (
auto substituted = bf.
substitute(input_to_bf); substituted.is_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");
355 bf = substituted.get();
358 on_stack.erase(output_pin->get_name());
363 std::unordered_set<std::string> on_stack;
365 return get_resolved_boolean_function_internal(pin, on_stack);
373 if (lut_component ==
nullptr)
375 return BooleanFunction();
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)
382 return BooleanFunction();
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));
389 std::vector<GatePin*> inputs = m_type->get_input_pins();
391 auto result = BooleanFunction::Const(BooleanFunction::Value::ZERO);
393 if (config_str.empty())
398 if (inputs.size() > 6)
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();
407 config = std::stoull(config_str,
nullptr, 16);
409 catch (std::invalid_argument& ex)
412 "LUT gate '{}' with ID {} in netlist with ID {} has invalid configuration string of '{}', which is not a hex value.",
415 m_internal_manager->m_netlist->get_id(),
417 return BooleanFunction();
419 catch (std::out_of_range& ex)
422 "LUT gate '{}' with ID {} in netlist with ID {} has invalid configuration string of '{}', which has to many hex digits.",
425 m_internal_manager->m_netlist->get_id(),
427 return BooleanFunction();
430 u32 max_config_size = 1 << inputs.size();
434 config = bitreverse(config) >> (64 - max_config_size);
437 auto cache_key = std::make_pair(inputs, config);
438 auto& cache = m_internal_manager->m_lut_function_cache;
440 if (
auto it = cache.find(cache_key); it != cache.end())
455 if (config_size > max_config_size)
458 "LUT gate '{}' with ID {} in netlist with ID {} supports a configuration string of up to {} bits, but '{}' comprises {} bits instead.",
461 m_internal_manager->m_netlist->get_id(),
464 config_str.size() * 4);
465 return BooleanFunction();
468 for (
u32 i = 0; config != 0 && i < max_config_size; i++)
470 u8 bit = (config & 1);
474 auto conjunction = BooleanFunction::Const(1, 1);
475 auto input_values = i;
476 for (
auto input : inputs)
478 if ((input_values & 1) == 1)
480 conjunction &= BooleanFunction::Var(
input->get_name());
484 conjunction &= ~BooleanFunction::Var(
input->get_name());
488 result |= conjunction;
492 auto f = result.simplify();
493 cache[cache_key] = f;
500 if (lut_component !=
nullptr)
504 if (init_component !=
nullptr)
506 auto output_pins = m_type->get_output_pins();
507 if (!output_pins.empty() &&
name == output_pins.front()->get_name())
509 auto input_pin_names = m_type->get_input_pin_names();
513 log_error(
"netlist",
"Boolean function '{} = {}' cannot be added to LUT gate '{}' wiht ID {}.",
name, func.
to_string(), m_name, m_id);
516 auto truth_table = tt.get();
517 if (truth_table.size() > 1)
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);
523 u64 config_value = 0;
526 std::reverse(truth_table[0].begin(), truth_table[0].end());
528 for (
auto v : truth_table[0])
530 if (v == BooleanFunction::X)
533 "Boolean function '{} = {}' cannot be added to LUT gate '{}' with ID {} in netlist with ID {} as its truth table contains undefined values.",
538 m_internal_manager->m_netlist->get_id());
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());
556 m_functions[
name] = func;
557 m_event_handler->notify(GateEvent::event::boolean_function_changed,
this);
561 bool Gate::mark_vcc_gate()
563 return m_internal_manager->m_netlist->mark_vcc_gate(
this);
566 bool Gate::mark_gnd_gate()
568 return m_internal_manager->m_netlist->mark_gnd_gate(
this);
571 bool Gate::unmark_vcc_gate()
573 return m_internal_manager->m_netlist->unmark_vcc_gate(
this);
576 bool Gate::unmark_gnd_gate()
578 return m_internal_manager->m_netlist->unmark_gnd_gate(
this);
581 bool Gate::is_vcc_gate()
const
583 return m_internal_manager->m_netlist->is_vcc_gate(
this);
586 bool Gate::is_gnd_gate()
const
588 return m_internal_manager->m_netlist->is_gnd_gate(
this);
591 const std::vector<Net*>& Gate::get_fan_in_nets()
const
596 std::vector<Net*> Gate::get_fan_in_nets(
const std::function<
bool(
Net*)>& filter)
const
598 std::vector<Net*> res;
605 for (
auto n : m_in_nets)
617 Net* Gate::get_fan_in_net(
const std::string& pin_name)
const
619 auto ep = get_fan_in_endpoint(pin_name);
624 return ep->get_net();
629 auto ep = get_fan_in_endpoint(pin);
634 return ep->get_net();
637 bool Gate::is_fan_in_net(
const Net*
net)
const
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);
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())
653 const std::vector<Endpoint*>& Gate::get_fan_in_endpoints()
const
655 return m_in_endpoints;
658 std::vector<Endpoint*> Gate::get_fan_in_endpoints(
const std::function<
bool(
Endpoint*)>& filter)
const
660 std::vector<Endpoint*> res;
663 res = m_in_endpoints;
667 for (
auto ep : m_in_endpoints)
679 Endpoint* Gate::get_fan_in_endpoint(
const std::string& pin_name)
const
681 const GatePin* pin = m_type->get_pin_by_name(pin_name);
685 "could not get fan-in endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
688 std::to_string(m_id),
692 return get_fan_in_endpoint(pin);
699 log_warning(
"gate",
"could not get fan-in endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, m_id);
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);
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())
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);
721 log_warning(
"gate",
"could not get fan-in endpoint of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
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())
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);
735 const std::vector<Net*>& Gate::get_fan_out_nets()
const
740 std::vector<Net*> Gate::get_fan_out_nets(
const std::function<
bool(
Net*)>& filter)
const
742 std::vector<Net*> res;
749 for (
auto n : m_out_nets)
761 Net* Gate::get_fan_out_net(
const std::string& pin_name)
const
763 auto ep = get_fan_out_endpoint(pin_name);
768 return ep->get_net();
773 auto ep = get_fan_out_endpoint(pin);
778 return ep->get_net();
781 bool Gate::is_fan_out_net(
const Net*
net)
const
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);
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())
797 const std::vector<Endpoint*>& Gate::get_fan_out_endpoints()
const
799 return m_out_endpoints;
802 std::vector<Endpoint*> Gate::get_fan_out_endpoints(
const std::function<
bool(
Endpoint*)>& filter)
const
804 std::vector<Endpoint*> res;
807 res = m_out_endpoints;
811 for (
auto ep : m_out_endpoints)
823 Endpoint* Gate::get_fan_out_endpoint(
const std::string& pin_name)
const
825 const GatePin* pin = m_type->get_pin_by_name(pin_name);
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());
831 return get_fan_out_endpoint(pin);
838 log_warning(
"gate",
"could not get fan-out endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, m_id);
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);
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())
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);
860 log_warning(
"gate",
"could not get fan-out endpoint of gate '{}' with ID {}: 'nullptr' given as net", m_name, m_id);
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())
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);
874 std::vector<Gate*> Gate::get_unique_predecessors(
const std::function<
bool(
const GatePin* pin,
Endpoint*)>& filter)
const
876 std::unordered_set<Gate*> res;
877 auto endpoints = get_predecessors(filter);
878 res.reserve(endpoints.size());
879 for (
auto ep : endpoints)
881 res.insert(ep->get_gate());
883 return std::vector<Gate*>(res.begin(), res.end());
886 std::vector<Endpoint*> Gate::get_predecessors(
const std::function<
bool(
const GatePin* pin,
Endpoint*)>& filter)
const
888 std::vector<Endpoint*> result;
889 for (
auto ep : m_in_endpoints)
891 auto pred_pin = ep->get_pin();
892 auto predecessors = ep->get_net()->get_sources();
895 result.insert(result.end(), predecessors.begin(), predecessors.end());
899 for (
auto pre : predecessors)
901 if (!filter(pred_pin, pre))
905 result.push_back(pre);
916 log_warning(
"gate",
"could not get predecessor endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, std::to_string(m_id));
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));
924 auto predecessors = get_predecessors([pin](
const auto p,
auto) ->
bool {
return *p == *pin; });
925 if (predecessors.size() == 0)
929 if (predecessors.size() > 1)
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());
935 return predecessors[0];
938 Endpoint* Gate::get_predecessor(
const std::string& pin_name)
const
940 const GatePin* pin = m_type->get_pin_by_name(pin_name);
944 "could not get predecessor endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
947 std::to_string(m_id),
951 return get_predecessor(pin);
954 std::vector<Gate*> Gate::get_unique_successors(
const std::function<
bool(
const GatePin* pin,
Endpoint*)>& filter)
const
956 std::unordered_set<Gate*> res;
957 auto endpoints = get_successors(filter);
958 res.reserve(endpoints.size());
959 for (
auto ep : endpoints)
961 res.insert(ep->get_gate());
963 return std::vector<Gate*>(res.begin(), res.end());
966 std::vector<Endpoint*> Gate::get_successors(
const std::function<
bool(
const GatePin* pin,
Endpoint*)>& filter)
const
968 std::vector<Endpoint*> result;
969 for (
auto ep : m_out_endpoints)
971 auto suc_pin = ep->get_pin();
972 auto successors = ep->get_net()->get_destinations();
975 result.insert(result.end(), successors.begin(), successors.end());
979 for (
auto suc : successors)
981 if (!filter(suc_pin, suc))
985 result.push_back(suc);
996 log_warning(
"gate",
"could not get successor endpoint of gate '{}' with ID {}: 'nullptr' given as pin", m_name, std::to_string(m_id));
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));
1004 auto successors = get_successors([pin](
const auto p,
auto) ->
bool {
return *p == *pin; });
1005 if (successors.size() == 0)
1009 if (successors.size() > 1)
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());
1015 return successors[0];
1018 Endpoint* Gate::get_successor(
const std::string& pin_name)
const
1020 const GatePin* pin = m_type->get_pin_by_name(pin_name);
1024 "could not get successor endpoint of pin '{}' at gate '{}' with ID {}: no pin with that name exists for gate type '{}'",
1027 std::to_string(m_id),
1028 m_type->get_name());
1031 return get_successor(pin);
1037 if (init_component ==
nullptr)
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");
1046 std::vector<std::string> init_data;
1047 for (
const std::string&
id : identifiers)
1049 init_data.push_back(std::get<1>(get_data(category,
id)));
1052 return OK(init_data);
1058 if (init_component ==
nullptr)
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");
1067 if (identifiers.size() != init_data.size())
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()));
1074 for (
const std::string&
id : identifiers)
1076 set_data(category,
id,
"bit_vector", init_data.at(i));
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
static std::string to_string(Value value)
BooleanFunction substitute(const std::string &old_variable_name, const std::string &new_variable_name) const
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 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
#define log_error(channel,...)
#define log_debug(channel,...)
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
CORE_API T trim(const T &s, const char *to_remove=" \t\r\n")
CORE_API std::vector< T > to_vector(const Container< T, Args... > &container)