13 #include <unordered_set>
17 namespace netlist_utils
21 class ShortestPathInternal
25 const std::unordered_set<Gate*>& m_end_gates;
27 std::unordered_map<Gate*, Gate*> m_origin_map;
28 bool (ShortestPathInternal::*m_heureka) (
Gate*)
const;
29 std::unordered_set<Gate*> (ShortestPathInternal::*m_get_next_gates) (
Gate*)
const;
31 bool heureka_single(
Gate* test_gate)
const
33 return (m_end_gate == test_gate);
36 bool heureka_multiple(
Gate* test_gate)
const
38 return (m_end_gates.find(test_gate) != m_end_gates.end());
41 std::unordered_set<Gate*> get_next_gates_forward(
Gate* origin)
const
43 std::unordered_set<Gate*> retval;
46 for (
const Endpoint* ep :
n->get_destinations())
48 retval.insert(ep->get_gate());
54 std::unordered_set<Gate*> get_next_gates_backward(
Gate* origin)
const
56 std::unordered_set<Gate*> retval;
59 for (
const Endpoint* ep :
n->get_sources())
61 retval.insert(ep->get_gate());
68 ShortestPathInternal(
Gate* start_gate,
const std::unordered_set<Gate*>& end_gates,
bool forward=
true)
69 : m_start_gate(start_gate), m_end_gate(
nullptr), m_end_gates(end_gates), m_forward(forward)
71 if (m_end_gates.size() == 1)
73 m_end_gate = *(m_end_gates.begin());
74 m_heureka = &ShortestPathInternal::heureka_single;
77 m_heureka = &ShortestPathInternal::heureka_multiple;
80 m_get_next_gates = &ShortestPathInternal::get_next_gates_forward;
82 m_get_next_gates = &ShortestPathInternal::get_next_gates_backward;
87 if (m_end_gates.empty())
89 log_warning(
"netlist_utils",
"Cannot find shortest path from start gate ID={}, no target given.", m_start_gate->get_id());
90 return std::vector<Gate*>();
92 if ((this->*m_heureka)(m_start_gate))
94 log_warning(
"netlist_utils",
"Cannot find shortest path since start gate ID={} and target are the same.", m_start_gate->get_id());
95 return std::vector<Gate*>();
98 std::vector<Gate*> v0;
99 std::vector<Gate*> v1;
100 v0.push_back(m_start_gate);
101 std::unordered_map<Gate*, Gate*> originMap;
107 for (
Gate* g1 : (this->*m_get_next_gates)(g0))
109 if (originMap.find(g1) != originMap.end())
114 if ((this->*m_heureka)(g1))
117 std::vector<Gate*> retval;
119 while (
g != m_start_gate)
122 auto it = originMap.find(
g);
123 assert(it != originMap.end());
126 retval.push_back(m_start_gate);
128 std::reverse(retval.begin(),retval.end());
137 log_warning(
"netlist_utils",
"It looks like there is no path from start gate ID={} to selected {} target(s).", m_start_gate->get_id(), m_end_gates.size());
138 return std::vector<Gate*>();
148 return ERR(
"could not get subgraph function: net is a 'nullptr'");
157 return ERR(res.get_error());
166 return ERR(res.get_error());
176 if (
auto res = nl->
copy(); res.is_error())
178 log_error(
"netlist_utils",
"error encountered while copying netlist:\n{}", res.get_error().get());
189 std::map<u32, Gate*> matrix_id_to_gate;
190 std::map<Gate*, u32> gate_to_matrix_id;
191 std::vector<std::vector<int>> matrix;
193 u32 matrix_gates = 0;
200 gate_to_matrix_id[gate] = matrix_gates;
201 matrix_id_to_gate[matrix_gates] = gate;
205 for (
const auto& [
id, gate] : matrix_id_to_gate)
207 std::vector<int> line_of_matrix;
209 std::set<u32> gates_to_add;
212 gates_to_add.insert(gate_to_matrix_id[pred_gate]);
215 for (
u32 i = 0; i < matrix_gates; i++)
217 if (gates_to_add.find(i) != gates_to_add.end())
219 line_of_matrix.push_back(1);
223 line_of_matrix.push_back(0);
226 matrix.push_back(line_of_matrix);
229 return std::make_pair(matrix_id_to_gate, matrix);
240 log_error(
"netlist_utils",
"error encountered while copying subgraph netlist:\n{}", res.get_error().get());
245 std::vector<Gate*>
get_next_gates(
const Gate* gate,
bool get_successors,
int depth,
const std::function<
bool(
const Gate*)>& filter)
247 std::vector<Gate*> retval;
248 std::unordered_map<u32, std::vector<Gate*>> cache;
249 std::vector<const Gate*> v0;
251 std::unordered_set<const Gate*> gats_handled;
252 std::unordered_set<const Net*> nets_handled;
253 gats_handled.insert(gate);
255 for (
int round = 0; !depth || round < depth; round++)
257 std::vector<const Gate*> v1;
258 for (
const Gate* g0 : v0)
260 for (
const Net*
n : get_successors ? g0->get_fan_out_nets() : g0->get_fan_in_nets())
262 if (nets_handled.find(
n) != nets_handled.end())
266 nets_handled.insert(
n);
268 for (
const Endpoint* ep : get_successors ?
n->get_destinations() :
n->get_sources())
270 Gate* g1 = ep->get_gate();
271 if (gats_handled.find(g1) != gats_handled.end())
275 gats_handled.insert(g1);
276 if (!filter || filter(g1))
279 retval.push_back(g1);
295 std::vector<Gate*> retval;
296 std::unordered_map<u32, std::vector<Gate*>> cache;
297 std::vector<const Gate*> v0;
298 std::unordered_set<const Gate*> gates_handled;
299 std::unordered_set<const Net*> nets_handled;
300 for (
const Endpoint* ep : (get_successors ?
net->get_destinations() :
net->get_sources()))
302 Gate*
g = ep->get_gate();
303 if (!filter || filter(
g))
306 gates_handled.insert(
g);
307 nets_handled.insert(
net);
312 for (
int round = 1; depth == 0 || round < depth; round++)
314 std::vector<const Gate*> v1;
315 for (
const Gate* g0 : v0)
317 for (
const Net*
n : get_successors ? g0->get_fan_out_nets() : g0->get_fan_in_nets())
319 if (nets_handled.find(
n) != nets_handled.end())
323 nets_handled.insert(
n);
325 for (
const Endpoint* ep : get_successors ?
n->get_destinations() :
n->get_sources())
327 Gate* g1 = ep->get_gate();
328 if (gates_handled.find(g1) != gates_handled.end())
332 gates_handled.insert(g1);
333 if (!filter || filter(g1))
336 retval.push_back(g1);
352 std::unordered_set<Gate*> end_gates;
357 ShortestPathInternal spi(start_gate, end_gates, forward_direction);
358 return spi.get_path();
363 std::unordered_set<Gate*> end_gates_forward;
364 end_gates_forward.insert(end_gate);
365 ShortestPathInternal spi_forward(start_gate, end_gates_forward,
true);
366 std::vector<Gate*> path_forward = spi_forward.get_path();
367 if (!search_both_directions)
369 std::unordered_set<Gate*> start_gates_reverse;
370 start_gates_reverse.insert(start_gate);
371 ShortestPathInternal spi_reverse(end_gate, start_gates_reverse,
false);
372 std::vector<Gate*> path_reverse = spi_reverse.get_path();
373 return (path_reverse.size() < path_forward.size()) ? path_reverse : path_forward;
378 std::vector<Gate*> get_next_sequential_gates_internal(
const Net* start_net,
bool forward, std::unordered_set<u32>& seen, std::unordered_map<
u32, std::vector<Gate*>>& cache)
380 if (
auto it = cache.find(start_net->
get_id()); it != cache.end())
385 if (seen.find(start_net->
get_id()) != seen.end())
390 seen.insert(start_net->
get_id());
392 std::vector<Gate*> found_ffs;
396 auto next_gate = endpoint->get_gate();
400 found_ffs.push_back(next_gate);
404 for (
auto n : forward ? next_gate->get_fan_out_nets() : next_gate->get_fan_in_nets())
406 auto next_gates = get_next_sequential_gates_internal(
n, forward, seen, cache);
407 found_ffs.insert(found_ffs.end(), next_gates.begin(), next_gates.end());
412 std::sort(found_ffs.begin(), found_ffs.end());
413 found_ffs.erase(std::unique(found_ffs.begin(), found_ffs.end()), found_ffs.end());
415 cache.emplace(start_net->
get_id(), found_ffs);
422 std::vector<Gate*> found_ffs;
426 found_ffs.insert(found_ffs.end(), suc.begin(), suc.end());
429 std::sort(found_ffs.begin(), found_ffs.end());
430 found_ffs.erase(std::unique(found_ffs.begin(), found_ffs.end()), found_ffs.end());
437 std::unordered_set<u32> seen;
438 return get_next_sequential_gates_internal(
net, get_successors, seen, cache);
443 std::unordered_map<u32, std::vector<Gate*>> cache;
449 std::unordered_map<u32, std::vector<Gate*>> cache;
456 get_path_internal(
const Net* start_net,
bool forward, std::set<GateTypeProperty> stop_types, std::unordered_set<u32>& seen, std::unordered_map<
u32, std::vector<Gate*>>& cache)
458 if (
auto it = cache.find(start_net->
get_id()); it != cache.end())
463 if (seen.find(start_net->
get_id()) != seen.end())
468 seen.insert(start_net->
get_id());
470 std::vector<Gate*> found_combinational;
474 auto next_gate = endpoint->get_gate();
479 if (stop_types.find(property) != stop_types.end())
487 found_combinational.push_back(next_gate);
489 for (
auto n : forward ? next_gate->get_fan_out_nets() : next_gate->get_fan_in_nets())
491 auto next_gates = get_path_internal(
n, forward, stop_types, seen, cache);
492 found_combinational.insert(found_combinational.end(), next_gates.begin(), next_gates.end());
497 std::sort(found_combinational.begin(), found_combinational.end());
498 found_combinational.erase(std::unique(found_combinational.begin(), found_combinational.end()), found_combinational.end());
500 cache.emplace(start_net->
get_id(), found_combinational);
501 return found_combinational;
505 std::vector<Gate*>
get_path(
const Gate* gate,
bool get_successors, std::set<GateTypeProperty> stop_properties, std::unordered_map<
u32, std::vector<Gate*>>& cache)
507 std::vector<Gate*> found_combinational;
510 auto suc =
get_path(
n, get_successors, stop_properties, cache);
511 found_combinational.insert(found_combinational.end(), suc.begin(), suc.end());
514 std::sort(found_combinational.begin(), found_combinational.end());
515 found_combinational.erase(std::unique(found_combinational.begin(), found_combinational.end()), found_combinational.end());
517 return found_combinational;
520 std::vector<Gate*>
get_path(
const Net*
net,
bool get_successors, std::set<GateTypeProperty> stop_properties, std::unordered_map<
u32, std::vector<Gate*>>& cache)
522 std::unordered_set<u32> seen;
523 return get_path_internal(
net, get_successors, stop_properties, seen, cache);
526 std::vector<Gate*>
get_path(
const Gate* gate,
bool get_successors, std::set<GateTypeProperty> stop_properties)
528 std::unordered_map<u32, std::vector<Gate*>> cache;
529 return get_path(gate, get_successors, stop_properties, cache);
532 std::vector<Gate*>
get_path(
const Net*
net,
bool get_successors, std::set<GateTypeProperty> stop_properties)
534 std::unordered_map<u32, std::vector<Gate*>> cache;
535 return get_path(
net, get_successors, stop_properties, cache);
540 std::vector<Net*> nets;
542 for (
const auto& pin :
pins)
546 log_warning(
"netlist_utils",
"'nullptr' given as pin.");
559 log_warning(
"netlist_utils",
"could not retrieve fan-in net for pin '{}' of gate '{}' with ID {}.", pin->get_name(), gate->
get_name(), gate->
get_id());
570 log_warning(
"netlist_utils",
"could not retrieve fan-out net for pin '{}' of gate '{}' with ID {}.", pin->get_name(), gate->
get_name(), gate->
get_id());
582 for (
const auto& gate :
netlist->get_gates())
593 if (fan_out.size() != 1)
600 if (functions.size() != 1)
606 Endpoint* out_endpoint = *(fan_out.begin());
620 auto sources = ep->get_net()->get_sources();
621 if (sources.size() != 1)
626 if (sources.front()->get_gate()->is_gnd_gate())
630 func = substitution.get();
633 else if (sources.front()->get_gate()->is_vcc_gate())
637 func = substitution.get();
647 if (std::find(in_pins.begin(), in_pins.end(), func_str) != in_pins.end())
652 for (
Endpoint* in_endpoint : fan_in)
654 Net* in_net = in_endpoint->get_net();
656 if (in_endpoint->get_pin()->get_name() == func_str)
661 Gate* dst_gate = dst->get_gate();
662 GatePin* dst_pin = dst->get_pin();
665 return ERR(
"could not completely remove buffers from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to remove destination from output net '"
666 + out_net->
get_name() +
"' with ID " + std::to_string(out_net->
get_id()) +
" of buffer gate '" + gate->
get_name() +
"' with ID "
667 + std::to_string(gate->
get_id()));
671 return ERR(
"could not completely remove buffers from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to add destination to input net '"
672 + in_net->
get_name() +
"' with ID " + std::to_string(in_net->
get_id()) +
" of buffer gate '" + gate->
get_name() +
"' with ID "
673 + std::to_string(gate->
get_id()));
682 return ERR(
"could not completely remove buffers from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to remove destination from input net '"
683 + in_net->
get_name() +
"' with ID " + std::to_string(in_net->
get_id()) +
" of buffer gate '" + gate->
get_name() +
"' with ID "
684 + std::to_string(gate->
get_id()));
694 else if (func_str ==
"0" || func_str ==
"1")
698 const std::vector<Gate*>& gnd_gates =
netlist->get_gnd_gates();
699 const std::vector<Gate*>& vcc_gates =
netlist->get_vcc_gates();
700 if (gnd_gates.empty() || vcc_gates.empty())
704 Net* gnd_net = gnd_gates.front()->get_fan_out_nets().front();
705 Net* vcc_net = vcc_gates.front()->get_fan_out_nets().front();
707 for (
Endpoint* in_endpoint : fan_in)
709 Net* in_net = in_endpoint->get_net();
714 return ERR(
"could not completely remove buffers from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to remove destination from input net '"
715 + in_net->
get_name() +
"' with ID " + std::to_string(in_net->
get_id()) +
" of buffer gate '" + gate->
get_name() +
"' with ID " + std::to_string(gate->
get_id()));
722 Gate* dst_gate = dst->get_gate();
723 GatePin* dst_pin = dst->get_pin();
726 return ERR(
"could not completely remove buffers from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to remove destination from output net '"
727 + out_net->
get_name() +
"' with ID " + std::to_string(out_net->
get_id()) +
" of buffer gate '" + gate->
get_name() +
"' with ID "
728 + std::to_string(gate->
get_id()));
732 return ERR(
"could not completely remove buffers from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to add destination to GND net '"
733 + gnd_net->
get_name() +
"' with ID " + std::to_string(gnd_net->
get_id()));
737 else if (func_str ==
"1")
741 Gate* dst_gate = dst->get_gate();
742 GatePin* dst_pin = dst->get_pin();
745 return ERR(
"could not completely remove buffers from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to remove destination from output net '"
746 + out_net->
get_name() +
"' with ID " + std::to_string(out_net->
get_id()) +
" of buffer gate '" + gate->
get_name() +
"' with ID "
747 + std::to_string(gate->
get_id()));
751 return ERR(
"could not completely remove buffers from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to add destination to VCC net '"
752 + gnd_net->
get_name() +
"' with ID " + std::to_string(gnd_net->
get_id()));
764 return OK(num_gates);
772 const std::vector<Gate*>& gnd_gates =
netlist->get_gnd_gates();
773 if (gnd_gates.empty())
775 return ERR(
"could not completely remove unused LUT endpoints from netlist with ID " + std::to_string(
netlist->get_id()) +
": no GND net available within netlist");
777 Net* gnd_net = gnd_gates.front()->get_fan_out_nets().front();
780 for (
const auto& gate :
netlist->get_gates([](
const Gate*
g) { return g->get_type()->has_property(GateTypeProperty::c_lut); }))
786 if (functions.size() != 1)
791 auto active_pins = functions.begin()->second.get_variable_names();
794 if (fan_in.size() > active_pins.size())
796 for (
const auto& ep : fan_in)
798 if (std::find(active_pins.begin(), active_pins.end(), ep->get_pin()->get_name()) == active_pins.end())
802 if (!ep->get_net()->remove_destination(gate, pin))
804 return ERR(
"could not completely remove unused LUT endpoints from netlist with ID " + std::to_string(
netlist->get_id())
805 +
": failed to remove inactive endpoint from gate '" + gate->
get_name() +
"' with ID " + std::to_string(gate->
get_id()));
809 return ERR(
"could not completely remove unused LUT endpoints from netlist with ID " + std::to_string(
netlist->get_id()) +
": failed to connect inactive input of gate '"
810 + gate->
get_name() +
"' with ID " + std::to_string(gate->
get_id()) +
" to GND net");
825 threshold = gates.size();
829 std::map<Net*, u32> net_count;
830 for (
Gate*
g : gates)
832 for (
Endpoint* pred :
g->get_predecessors())
834 if (pred->get_gate()->is_gnd_gate() || pred->get_gate()->is_vcc_gate())
839 Net* pred_net = pred->get_net();
840 if (
const auto it = net_count.find(pred_net); it != net_count.end())
846 net_count[pred_net] = 1;
852 std::vector<Net*> common_inputs;
853 for (
const auto& [
n, cnt] : net_count)
855 if (cnt >= threshold)
857 common_inputs.push_back(
n);
861 return common_inputs;
872 return ERR(res.get_error());
877 get_gate_chain(
Gate* start_gate,
const std::vector<const GatePin*>& input_pins,
const std::vector<const GatePin*>& output_pins,
const std::function<
bool(
const Gate*)>& filter)
879 if (start_gate ==
nullptr)
881 return ERR(
"could not detect gate chain at start gate: start gate is a 'nullptr'");
885 if (filter && !filter(start_gate))
887 return ERR(
"could not detect gate chain at start gate '" + start_gate->
get_name() +
"' with ID " + std::to_string(start_gate->
get_id())
888 +
": filter evaluates to 'false' for start gate");
891 std::deque<Gate*> gate_chain = {start_gate};
892 std::unordered_set<Gate*> visited_gates = {start_gate};
894 bool found_next_gate;
897 const Gate* current_gate = start_gate;
900 found_next_gate =
false;
903 std::vector<Endpoint*> successors = current_gate->
get_successors([input_pins, output_pins, target_type, filter](
const GatePin* ep_pin,
Endpoint* ep) {
906 if (output_pins.empty() || std::find(output_pins.begin(), output_pins.end(), ep_pin) != output_pins.end())
908 if (input_pins.empty() || std::find(input_pins.begin(), input_pins.end(), ep->get_pin()) != input_pins.end())
910 if (!filter || filter(ep->get_gate()))
920 if (successors.size() > 1)
923 "detected more than one valid successor gate for gate '{}' with ID {} in netlist with ID {}.",
929 else if (!successors.empty())
931 Gate* suc_gate = successors.at(0)->get_gate();
933 if (visited_gates.find(suc_gate) != visited_gates.end())
935 log_debug(
"netlist_utils",
"detected a loop at gate with ID {}.", suc_gate->
get_id());
939 gate_chain.push_back(suc_gate);
940 visited_gates.insert(suc_gate);
941 current_gate = suc_gate;
942 found_next_gate =
true;
944 }
while (found_next_gate);
947 current_gate = start_gate;
950 found_next_gate =
false;
953 std::vector<Endpoint*> predecessors = current_gate->
get_predecessors([input_pins, output_pins, target_type, filter](
const GatePin* ep_pin,
Endpoint* ep) {
956 if (input_pins.empty() || std::find(input_pins.begin(), input_pins.end(), ep_pin) != input_pins.end())
958 if (output_pins.empty() || std::find(output_pins.begin(), output_pins.end(), ep->get_pin()) != output_pins.end())
960 if (!filter || filter(ep->get_gate()))
970 if (predecessors.size() > 1)
973 "detected more than one valid predecessor gate for gate '{}' with ID {} in netlist with ID {}.",
974 current_gate->get_name(),
975 current_gate->get_id(),
976 current_gate->get_netlist()->get_id());
979 else if (!predecessors.empty())
981 Gate* pred_gate = predecessors.at(0)->get_gate();
983 if (visited_gates.find(pred_gate) != visited_gates.end())
985 log_debug(
"netlist_utils",
"detected a loop at gate with ID {}.", pred_gate->get_id());
989 gate_chain.push_front(pred_gate);
990 visited_gates.insert(pred_gate);
991 current_gate = pred_gate;
992 found_next_gate =
true;
993 log_debug(
"netlist_utils",
"found predecessor gate with ID {}.", pred_gate->get_id());
995 }
while (found_next_gate);
997 return OK(std::vector<Gate*>(gate_chain.begin(), gate_chain.end()));
1001 const std::vector<GateType*>& chain_types,
1002 const std::map<
GateType*, std::vector<const GatePin*>>& input_pins,
1003 const std::map<
GateType*, std::vector<const GatePin*>>& output_pins,
1004 const std::function<
bool(
const Gate*)>& filter)
1006 if (start_gate ==
nullptr)
1008 return ERR(
"could not detect gate chain at start gate: start gate is a 'nullptr'");
1010 if (chain_types.size() < 2)
1012 return ERR(
"could not detect gate chain at start gate: 'chain_types' comprises less than two target gate types");
1014 if (start_gate->
get_type() != chain_types.at(0))
1016 return ERR(
"could not detect gate chain at start gate '" + start_gate->
get_name() +
"' with ID " + std::to_string(start_gate->
get_id()) +
": start gate is not of type '"
1017 + chain_types.front()->get_name() +
"'");
1019 if (filter && !filter(start_gate))
1021 return ERR(
"could not detect gate chain at start gate '" + start_gate->
get_name() +
"' with ID " + std::to_string(start_gate->
get_id())
1022 +
": filter evaluates to 'false' for start gate");
1025 std::deque<Gate*> gate_chain = {start_gate};
1026 std::unordered_set<Gate*> visited_gates;
1029 u32 current_index = (last_index + 1) % chain_types.size();
1032 bool found_next_gate;
1033 const Gate* current_gate = start_gate;
1036 found_next_gate =
false;
1039 GateType* target_type = chain_types.at(current_index);
1040 const std::vector<const GatePin*>& inputs = input_pins.at(target_type);
1041 const std::vector<const GatePin*>& outputs = output_pins.at(chain_types.at(last_index));
1042 std::vector<Endpoint*> successors = current_gate->
get_successors([target_type, inputs, outputs, filter](
const GatePin* ep_pin,
Endpoint* ep) {
1045 if (outputs.empty() || std::find(outputs.begin(), outputs.end(), ep_pin) != outputs.end())
1047 if (inputs.empty() || std::find(inputs.begin(), inputs.end(), ep->
get_pin()) != inputs.end())
1049 if (!filter || filter(ep->
get_gate()))
1059 if (successors.size() > 1)
1062 "detected more than one valid successor gate for gate '{}' with ID {} in netlist with ID {}.",
1068 else if (!successors.empty())
1070 Gate* suc_gate = successors.at(0)->get_gate();
1072 if (visited_gates.find(suc_gate) != visited_gates.end())
1074 log_debug(
"netlist_utils",
"detected a loop at gate with ID {}.", suc_gate->
get_id());
1078 gate_chain.push_back(suc_gate);
1079 visited_gates.insert(suc_gate);
1080 current_gate = suc_gate;
1081 last_index = current_index;
1082 current_index = (current_index + 1) % chain_types.size();
1083 found_next_gate =
true;
1085 }
while (found_next_gate);
1088 while (current_index != 0)
1090 gate_chain.pop_back();
1094 current_gate = start_gate;
1096 current_index = chain_types.size() - 1;
1101 found_next_gate =
false;
1104 GateType* target_type = chain_types.at(current_index);
1105 const std::vector<const GatePin*>& inputs = input_pins.at(chain_types.at(last_index));
1106 const std::vector<const GatePin*>& outputs = output_pins.at(target_type);
1110 if (inputs.empty() || std::find(inputs.begin(), inputs.end(), ep_pin) != inputs.end())
1112 if (outputs.empty() || std::find(outputs.begin(), outputs.end(), ep->
get_pin()) != outputs.end())
1114 if (!filter || filter(ep->
get_gate()))
1124 if (predecessors.size() > 1)
1127 "detected more than one valid predecessor gate for gate '{}' with ID {} in netlist with ID {}.",
1133 else if (!predecessors.empty())
1135 Gate* pred_gate = predecessors.at(0)->get_gate();
1137 if (visited_gates.find(pred_gate) != visited_gates.end())
1139 log_debug(
"netlist_utils",
"detected a loop at gate with ID {}.", pred_gate->
get_id());
1143 gate_chain.push_front(pred_gate);
1144 visited_gates.insert(pred_gate);
1145 current_gate = pred_gate;
1146 last_index = current_index;
1147 current_index = (current_index == 0) ? chain_types.size() - 1 : current_index - 1;
1148 found_next_gate =
true;
1150 }
while (found_next_gate);
1153 while (last_index != 0)
1155 gate_chain.pop_front();
1159 return OK(std::vector<Gate*>(gate_chain.begin(), gate_chain.end()));
const std::string & get_name() const
BooleanFunction simplify() const
static std::string to_string(Value value)
static BooleanFunction Const(const BooleanFunction::Value &value)
BooleanFunction substitute(const std::string &old_variable_name, const std::string &new_variable_name) const
GatePin * get_pin() const
Net * get_fan_in_net(const std::string &pin_name) const
const std::vector< Net * > & get_fan_in_nets() const
const std::vector< Endpoint * > & get_fan_out_endpoints() const
GateType * get_type() const
std::vector< Endpoint * > get_predecessors(const std::function< bool(const GatePin *pin, Endpoint *ep)> &filter=nullptr) const
Net * get_fan_out_net(const std::string &pin_name) const
std::vector< Endpoint * > get_successors(const std::function< bool(const GatePin *pin, Endpoint *ep)> &filter=nullptr) const
const std::string & get_name() const
const std::vector< Net * > & get_fan_out_nets() const
const std::vector< Endpoint * > & get_fan_in_endpoints() const
Netlist * get_netlist() const
std::unordered_map< std::string, BooleanFunction > get_boolean_functions(bool only_custom_functions=false) const
std::vector< std::string > get_input_pin_names() const
bool has_property(GateTypeProperty property) const
const std::vector< Gate * > & get_gates() const
Endpoint * add_destination(Gate *gate, const std::string &pin_name)
const std::string & get_name() const
std::vector< Endpoint * > get_destinations(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
bool remove_destination(Gate *gate, const std::string &pin_name)
std::vector< Endpoint * > get_sources(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
const std::vector< Gate * > & get_gates() const
Result< std::unique_ptr< Netlist > > copy() const
Result< Gate * > replace_gate(Gate *gate, GateType *target_type, const std::map< GatePin *, GatePin * > &pin_map)
Result< std::unique_ptr< Netlist > > copy_subgraph_netlist(const std::vector< const Gate * > &subgraph_gates, const bool all_global_io=false) const
Result< BooleanFunction > get_subgraph_function(const std::vector< const Gate * > &subgraph_gates, const Net *subgraph_output, std::map< std::pair< u32, const GatePin * >, BooleanFunction > &cache) const
#define log_error(channel,...)
#define log_debug(channel,...)
#define log_warning(channel,...)
std::vector< Net * > get_common_inputs(const std::vector< Gate * > &gates, u32 threshold)
std::unique_ptr< Netlist > get_partial_netlist(const Netlist *nl, const std::vector< const Gate * > &subgraph_gates)
std::vector< Gate * > get_next_gates(const Gate *gate, bool get_successors, int depth, const std::function< bool(const Gate *)> &filter)
Result< std::vector< Gate * > > get_gate_chain(Gate *start_gate, const std::vector< const GatePin * > &input_pins, const std::vector< const GatePin * > &output_pins, const std::function< bool(const Gate *)> &filter)
Result< std::vector< Gate * > > get_complex_gate_chain(Gate *start_gate, const std::vector< GateType * > &chain_types, const std::map< GateType *, std::vector< const GatePin * >> &input_pins, const std::map< GateType *, std::vector< const GatePin * >> &output_pins, const std::function< bool(const Gate *)> &filter)
std::vector< Gate * > get_path(const Gate *gate, bool get_successors, std::set< GateTypeProperty > stop_properties, std::unordered_map< u32, std::vector< Gate * >> &cache)
std::unique_ptr< Netlist > copy_netlist(const Netlist *nl)
Result< std::monostate > replace_gate(Gate *gate, GateType *target_type, std::map< GatePin *, GatePin * > pin_map)
std::vector< Net * > get_nets_at_pins(Gate *gate, std::vector< GatePin * > pins)
Result< u32 > remove_unused_lut_endpoints(Netlist *netlist)
Result< BooleanFunction > get_subgraph_function(const Net *net, const std::vector< const Gate * > &subgraph_gates, std::map< std::pair< u32, const GatePin * >, BooleanFunction > &cache)
std::vector< Gate * > get_shortest_path(Gate *start_gate, Module *end_module, bool forward_direction)
std::vector< Gate * > get_next_sequential_gates(const Gate *gate, bool get_successors, std::unordered_map< u32, std::vector< Gate * >> &cache)
std::pair< std::map< u32, Gate * >, std::vector< std::vector< int > > > get_ff_dependency_matrix(const Netlist *nl)
Result< u32 > remove_buffers(Netlist *netlist, bool analyze_inputs)
std::vector< PinInformation > pins
This file contains various functions to create and load netlists.