18 namespace module_identification
34 std::vector<std::unique_ptr<BaseCandidate>> find_carry_chains(
const Netlist* nl)
36 std::vector<std::vector<Gate*>> carry_chains;
39 std::vector<Gate*> carry_gates = nl->get_gates([](
const Gate* g) {
return g->get_type()->has_property(
GateTypeProperty::c_carry); });
40 std::set<Gate*> carry_gates_set = std::set<Gate*>(carry_gates.begin(), carry_gates.end());
43 while (!carry_gates_set.empty())
45 Gate* current_gate = *carry_gates_set.begin();
46 const GateType* carry_type = current_gate->get_type();
49 auto chain_res = NetlistTraversalDecorator(*nl).get_gate_chain(current_gate, {carry_type->get_pin_by_name(
"CI")}, {carry_type->get_pin_by_name(
"CO(3)")});
50 if (chain_res.is_error())
52 return std::vector<std::unique_ptr<BaseCandidate>>();
54 std::vector<Gate*> carry_chain = chain_res.get();
57 for (Gate* g : carry_chain)
59 carry_gates_set.erase(g);
63 if (carry_chain.size() >= 2)
65 log_debug(
"module_identification",
"\tcarry_gate: {}", carry_chain.front()->get_name());
66 carry_chains.push_back(carry_chain);
71 std::vector<std::vector<Gate*>> filtered_carry_chains;
72 for (
u32 i = 0; i < carry_chains.size(); i++)
74 auto& c_test = carry_chains.at(i);
75 std::set<Gate*> test_set = {c_test.begin(), c_test.end()};
78 for (
u32 j = 0; j < carry_chains.size(); j++)
85 auto& c_other = carry_chains.at(j);
86 std::set<Gate*> other_set = {c_other.begin(), c_other.end()};
88 if (std::includes(other_set.begin(), other_set.end(), test_set.begin(), test_set.end()))
97 filtered_carry_chains.push_back(c_test);
101 std::vector<std::unique_ptr<BaseCandidate>> base_candidates;
102 for (
const auto& carry_chain : filtered_carry_chains)
104 std::unique_ptr<BaseCandidate> base_candidate = std::make_unique<BaseCandidate>(carry_chain);
105 base_candidates.push_back(std::move(base_candidate));
108 return base_candidates;
121 std::vector<std::unique_ptr<StructuralCandidate>> build_structural_candidates(BaseCandidate* base_candidate)
123 std::vector<std::unique_ptr<StructuralCandidate>> candidates;
125 std::vector<Gate*> carry_chain = base_candidate->m_gates;
127 Gate* first_carry = carry_chain.front();
132 return std::vector<std::unique_ptr<StructuralCandidate>>();
134 log_debug(
"module_identification",
"\tcarry_chain: {}", first_carry->get_name());
138 std::unordered_set<Gate*> big_candidate_gates = {carry_chain.begin(), carry_chain.end()};
139 std::unordered_map<const Net*, std::unordered_set<Gate*>> cache;
141 for (
const auto& gate : carry_chain)
145 bool add_gate =
true;
173 for (
const auto& gate_to_add : gates)
175 big_candidate_gates.insert(gate_to_add);
179 if (big_candidate_gates.size() < (carry_chain.size() * 128))
183 std::unique_ptr<StructuralCandidate> candidate_big = std::make_unique<StructuralCandidate>(base_candidate, gate_vec);
184 log_debug(
"module_identification",
"big_candidate is {} big", candidate_big->m_gates.size());
185 candidates.push_back(std::move(candidate_big));
189 log_debug(
"module_identification",
"big_candidate is too big with {} gates", big_candidate_gates.size());
194 std::vector<Gate*> candidate_gates(carry_chain);
196 std::unique_ptr<StructuralCandidate> first_candidate = std::make_unique<StructuralCandidate>(base_candidate, candidate_gates);
197 if (first_candidate ==
nullptr)
199 log_error(
"module_identification",
"nullptr candidate after creation");
201 candidates.push_back(std::move(first_candidate));
204 for (
const auto& gate : carry_chain)
206 for (
const auto& pred_endp : gate->get_predecessors())
208 auto pred_gate = pred_endp->get_gate();
210 if (pred_gate->is_gnd_gate() || pred_gate->is_vcc_gate())
232 candidate_gates.push_back(pred_gate);
237 std::unique_ptr<StructuralCandidate> candidate_all_gates_infront_level_1 = std::make_unique<StructuralCandidate>(base_candidate, candidate_gates);
238 if (candidate_all_gates_infront_level_1 ==
nullptr)
240 log_error(
"module_identification",
"nullptr candidate after creation");
242 candidates.push_back(std::move(candidate_all_gates_infront_level_1));
245 std::vector<Gate*> si_di0_candidate_gates(carry_chain);
246 std::vector<std::string> allowed_pins_si_di0 = {
"S(0)",
"S(1)",
"S(2)",
"S(3)",
"DI(0)"};
248 for (
const auto& gate : carry_chain)
250 for (
const auto& pin : allowed_pins_si_di0)
252 const auto& pred_endp = gate->get_predecessor(pin);
253 if (pred_endp ==
nullptr)
257 auto pred_gate = pred_endp->get_gate();
258 if (pred_gate->is_gnd_gate() || pred_gate->is_vcc_gate())
265 log_error(
"module_identification",
"\tfound IO gate, but why?");
281 si_di0_candidate_gates.push_back(pred_gate);
285 std::unique_ptr<StructuralCandidate> candidate_gates_infront_of_si_di0 = std::make_unique<StructuralCandidate>(base_candidate, si_di0_candidate_gates);
286 if (candidate_gates_infront_of_si_di0 ==
nullptr)
288 log_error(
"module_identification",
"nullptr candidate after creation");
290 candidates.push_back(std::move(candidate_gates_infront_of_si_di0));
294 std::vector<Gate*> si_di_candidate_gates(carry_chain);
295 std::vector<std::string> allowed_pins_si_di = {
"S(0)",
"S(1)",
"S(2)",
"S(3)",
"DI(0)",
"DI(1)",
"DI(2)",
"DI(3)"};
297 for (
const auto& gate : carry_chain)
299 for (
const auto& pin : allowed_pins_si_di)
301 const auto& pred_endp = gate->get_predecessor(pin);
302 if (pred_endp ==
nullptr)
306 auto pred_gate = pred_endp->get_gate();
307 if (pred_gate->is_gnd_gate() || pred_gate->is_vcc_gate())
314 log_error(
"module_identification",
"\tfound IO gate, but why?");
329 si_di_candidate_gates.push_back(pred_gate);
333 std::unique_ptr<StructuralCandidate> candidate_gates_infront_of_si_di = std::make_unique<StructuralCandidate>(base_candidate, si_di_candidate_gates);
334 if (candidate_gates_infront_of_si_di ==
nullptr)
336 log_error(
"module_identification",
"nullptr candidate after creation");
338 candidates.push_back(std::move(candidate_gates_infront_of_si_di));
341 std::vector<Gate*> si_candidate_gates(carry_chain);
343 std::vector<std::string> allowed_pins_si = {
"S(0)",
"S(1)",
"S(2)",
"S(3)"};
344 for (
const auto& gate : carry_chain)
346 for (
const auto& pin : allowed_pins_si)
348 const auto& pred_endp = gate->get_predecessor(pin);
349 if (pred_endp ==
nullptr)
353 auto pred_gate = pred_endp->get_gate();
354 if (pred_gate->is_gnd_gate() || pred_gate->is_vcc_gate())
361 log_error(
"module_identification",
"\tfound IO gate, but why?");
377 si_candidate_gates.push_back(pred_gate);
382 std::vector<Gate*> candidate_gates_infront_of_si_gates;
383 for (
const auto& g : si_candidate_gates)
385 candidate_gates_infront_of_si_gates.push_back(g);
387 std::unique_ptr<StructuralCandidate> candidate_gates_infront_of_si = std::make_unique<StructuralCandidate>(base_candidate, candidate_gates_infront_of_si_gates);
389 candidates.push_back(std::move(candidate_gates_infront_of_si));
391 std::vector<std::unique_ptr<StructuralCandidate>> candidates_to_add;
394 for (
const auto& cand : candidates)
398 log_error(
"module_identification",
"nullptr candidate");
402 if (cand->m_gates.empty())
404 log_error(
"module_identification",
"candidate has no gates");
407 std::set<Gate*> additional_layer_gates;
409 for (
const auto& gate : cand->m_gates)
416 for (
const auto& pred_endp : gate->get_predecessors())
418 if (pred_endp ==
nullptr)
423 auto pred_gate = pred_endp->get_gate();
425 if (pred_gate ==
nullptr)
430 if (pred_gate->is_gnd_gate() || pred_gate->is_vcc_gate())
452 additional_layer_gates.insert(pred_gate);
456 std::vector<Gate*> all_gates(cand->m_gates);
457 for (
const auto& g : additional_layer_gates)
459 all_gates.push_back(g);
461 std::unique_ptr<StructuralCandidate> additional_gate_candidate = std::make_unique<StructuralCandidate>(base_candidate, all_gates);
462 candidates_to_add.push_back(std::move(additional_gate_candidate));
465 for (
auto& candidate_to_add : candidates_to_add)
467 candidates.push_back(std::move(candidate_to_add));
470 std::vector<std::unique_ptr<StructuralCandidate>> inv_candidates_to_add;
473 for (
const auto& cand : candidates)
477 log_error(
"module_identification",
"nullptr candidate");
481 if (cand->m_gates.empty())
483 log_error(
"module_identification",
"candidate has no gates");
486 std::set<Gate*> additional_layer_gates;
488 for (
const auto& gate : cand->m_gates)
495 for (
const auto& pred_endp : gate->get_predecessors())
497 if (pred_endp ==
nullptr)
502 auto pred_gate = pred_endp->get_gate();
504 if (pred_gate ==
nullptr)
511 additional_layer_gates.insert(pred_gate);
515 std::vector<Gate*> all_gates(cand->m_gates);
516 for (
const auto& g : additional_layer_gates)
518 all_gates.push_back(g);
520 std::unique_ptr<StructuralCandidate> additional_gate_candidate = std::make_unique<StructuralCandidate>(base_candidate, all_gates);
521 inv_candidates_to_add.push_back(std::move(additional_gate_candidate));
524 for (
auto& candidate_to_add : inv_candidates_to_add)
526 candidates.push_back(std::move(candidate_to_add));
532 std::vector<std::unique_ptr<StructuralCandidate>> new_candidates;
533 for (
const auto& c : candidates)
535 for (
const auto& in_net : carry_chain.front()->get_fan_in_nets())
537 if (in_net->is_gnd_net() || in_net->is_vcc_net())
542 for (
const auto& dst : in_net->get_destinations())
544 if (dst->get_gate() == carry_chain.front())
549 if (dst->get_gate() ==
nullptr)
555 bool is_single_input_lut = dst->get_gate()->get_type()->has_property(
GateTypeProperty::c_lut) && (dst->get_gate()->get_boolean_functions().size() == 1)
556 && (dst->get_gate()->get_boolean_functions().begin()->second.get_variable_names().size() == 1);
558 if (!is_inverter && !is_single_input_lut)
563 std::unique_ptr<StructuralCandidate> new_candidate = std::make_unique<StructuralCandidate>(base_candidate, c->m_gates);
564 new_candidate->m_gates.emplace_back(dst->get_gate());
565 new_candidates.emplace_back(std::move(new_candidate));
569 for (
auto& nc : new_candidates)
571 candidates.push_back(std::move(nc));
596 std::vector<std::unique_ptr<StructuralCandidate>> new_candidates;
597 for (
const auto& c : candidates)
599 std::set<Gate*> additional_gates;
603 for (
const auto& input : all_inputs)
605 for (
const auto& dest :
input->get_destinations())
607 if (dest->get_gate() ==
nullptr)
612 if (c_gates.find(dest->get_gate()) != c_gates.end())
617 if (additional_gates.find(dest->get_gate()) != additional_gates.end())
622 const auto gate_inputs = dest->get_gate()->get_fan_in_nets();
625 for (
auto& gi : gate_inputs)
627 if (all_inputs.find(gi) == all_inputs.end())
636 additional_gates.insert(dest->get_gate());
648 auto total_gates = c->m_gates;
649 total_gates.insert(total_gates.end(), additional_gates.begin(), additional_gates.end());
650 new_candidates.push_back(std::make_unique<StructuralCandidate>(base_candidate, total_gates));
652 for (
auto& nc : new_candidates)
654 candidates.push_back(std::move(nc));
658 std::set<std::set<Gate*>> all_sets;
659 u32 old_size = candidates.size();
660 std::vector<std::unique_ptr<StructuralCandidate>> candidates_to_return;
662 for (
auto& cand : candidates)
664 std::set<Gate*> set_gates = {cand->m_gates.begin(), cand->m_gates.end()};
665 if (all_sets.find(set_gates) == all_sets.end())
667 all_sets.insert(set_gates);
668 candidates_to_return.push_back(std::move(cand));
672 return candidates_to_return;
678 std::vector<std::pair<std::unique_ptr<BaseCandidate>, std::vector<std::unique_ptr<StructuralCandidate>>>> base_to_structural_candidates;
680 auto base_candidates = find_carry_chains(nl);
682 log_info(
"module_identification",
"found {} carry chains, building structural variants now...", base_candidates.size());
684 for (
auto& base_candidate : base_candidates)
686 std::vector<std::unique_ptr<StructuralCandidate>> structural_candidates = build_structural_candidates(base_candidate.get());
687 base_to_structural_candidates.push_back({std::move(base_candidate), std::move(structural_candidates)});
690 return base_to_structural_candidates;
This file contains the definition of the BaseCandidate class, which represents a base candidate in th...
#define log_error(channel,...)
#define log_debug(channel,...)
#define log_info(channel,...)
std::vector< std::pair< std::unique_ptr< BaseCandidate >, std::vector< std::unique_ptr< StructuralCandidate > > > > generate_structural_candidates(const Netlist *nl)
Generate structural candidates for a given netlist.
std::vector< Net * > get_input_nets(const std::vector< Gate * > &gates)
Get input nets from a list of gates.
@ xilinx_unisim
Xilinx Unisim FPGA architecture.
std::vector< Gate * > get_next_gates(const Gate *gate, bool get_successors, int depth=0, const std::function< bool(const Gate *)> &filter=nullptr)
std::set< T > to_set(const Container< T, Args... > &container)
bool is_subset(const T1 &subset, const T2 &superset)
std::vector< T > to_vector(const Container< T, Args... > &container)
This file contains helper functions for module identification in the HAL framework.
This file contains the class for defining and managing structural candidates within the module identi...
This file contains the function to generate structural candidates for Xilinx Unisim libraries.