21 namespace module_identification
25 std::vector<std::vector<VerifiedCandidate>> filter_out_redundant_const_muls(std::vector<std::vector<VerifiedCandidate>>& candidate_sets)
27 std::set<std::vector<Net*>> found_counter_for_output;
28 for (
const auto& cs : candidate_sets)
30 if (std::find(cs.front().m_types.begin(), cs.front().m_types.end(),
CandidateType::counter) != cs.front().m_types.end())
32 found_counter_for_output.insert(cs.front().m_output_nets);
36 std::vector<std::vector<VerifiedCandidate>> filtered_candidates;
37 for (
const auto& cs : candidate_sets)
42 if (found_counter_for_output.find(cs.front().m_output_nets) != found_counter_for_output.end())
48 filtered_candidates.push_back(cs);
52 std::cout <<
"Left with the following sets: " << std::endl;
53 for (
const auto& cs : filtered_candidates)
55 std::cout <<
enum_to_string(*cs.front().m_types.begin()) <<
": " << cs.size() << std::endl;
56 for (
const auto& o_net : cs.front().m_output_nets)
58 std::cout <<
"\t" << o_net->get_name() << std::endl;
63 return filtered_candidates;
67 u32 calculate_shared_source_regs(
const Netlist* nl,
const std::vector<VerifiedCandidate>& candidates,
const std::vector<std::vector<Gate*>>& registers)
69 u32 shared_input_regs = 0;
70 for (
const auto& c : candidates)
72 std::set<u32> op_regs;
73 for (
const auto& nets : c.m_operands)
76 for (
const auto& n : nets)
78 const auto seq_inputs_res =
79 NetlistTraversalDecorator(*nl).get_next_matching_gates(n,
false, [](
const auto& g) { return g->get_type()->has_property(GateTypeProperty::sequential); });
80 if (seq_inputs_res.is_error())
82 log_error(
"module_identification",
"{}", seq_inputs_res.get_error().get());
84 const auto seq_inputs = seq_inputs_res.get();
86 for (
const auto& si : seq_inputs)
88 for (
u32 reg_idx = 0; reg_idx < registers.size(); reg_idx++)
90 const auto& reg = registers.at(reg_idx);
91 if (std::find(reg.begin(), reg.end(), si) != reg.end())
93 op_regs.insert(reg_idx);
102 std::set<u32> ctrl_regs;
103 for (
const auto& n : c.m_control_signals)
105 const auto seq_inputs_res =
106 NetlistTraversalDecorator(*nl).get_next_matching_gates( n,
false, [](
const auto& g) { return g->get_type()->has_property(GateTypeProperty::sequential); });
107 if (seq_inputs_res.is_error())
109 log_error(
"module_identification",
"{}", seq_inputs_res.get_error().get());
111 const auto seq_inputs = seq_inputs_res.get();
113 for (
const auto& si : seq_inputs)
115 for (
u32 reg_idx = 0; reg_idx < registers.size(); reg_idx++)
117 const auto& reg = registers.at(reg_idx);
118 if (std::find(reg.begin(), reg.end(), si) != reg.end())
120 ctrl_regs.insert(reg_idx);
127 std::vector<u32> intersection;
128 std::set_intersection(op_regs.begin(), op_regs.end(), ctrl_regs.begin(), ctrl_regs.end(), std::back_inserter(intersection));
130 shared_input_regs += intersection.size();
133 return shared_input_regs;
137 u32 calcualte_ignored_input_signals(
const std::vector<VerifiedCandidate>& candidate_set)
139 u32 max_inputs_ignored = 0;
140 std::set<Net*> covered_nets;
141 for (
const auto& c : candidate_set)
144 for (
const auto& op : c.m_operands)
146 for (
const auto&
net : op)
148 if (
net->is_gnd_net() ||
net->is_vcc_net())
152 covered_nets.insert(
net);
157 covered_nets.insert(c.m_control_signals.begin(), c.m_control_signals.end());
160 for (
const auto& c : candidate_set)
163 u32 ignored_inputs = 0;
165 for (
const auto& input_net : all_input_nets)
167 if (input_net->is_gnd_net() || input_net->is_vcc_net())
172 if (covered_nets.find(input_net) == covered_nets.end())
178 max_inputs_ignored = std::max(max_inputs_ignored, ignored_inputs);
181 return max_inputs_ignored;
185 u32 calculate_maximum_io_signals(
const std::vector<VerifiedCandidate>& candidate_set)
187 u32 max_io_signals = 0;
188 for (
const auto& c : candidate_set)
191 std::set<Net*> io_signals;
192 for (
const auto& op : c.m_operands)
194 for (
const auto&
net : op)
196 if (
net->is_gnd_net() ||
net->is_vcc_net())
200 io_signals.insert(
net);
204 io_signals.insert(c.m_output_nets.begin(), c.m_output_nets.end());
206 max_io_signals = std::max(max_io_signals, (
u32)io_signals.size());
209 return max_io_signals;
213 u32 calcualte_ignored_output_signals(
const std::vector<VerifiedCandidate>& candidate_set)
215 u32 max_outputs_ignored = 0;
216 for (
const auto& c : candidate_set)
219 const auto c_outputs = c.m_output_nets.size();
220 const auto outputs_ignored = (c_outputs > all_outputs) ? 0 : all_outputs - c_outputs;
222 if (outputs_ignored > max_outputs_ignored)
224 max_outputs_ignored = outputs_ignored;
228 return max_outputs_ignored;
232 std::vector<std::vector<VerifiedCandidate>> filter_sets_by(
const std::vector<std::vector<VerifiedCandidate>>& candidate_sets,
233 const std::vector<std::vector<Gate*>>& registers,
235 const std::function<
u32(
const std::vector<VerifiedCandidate>&,
const std::vector<std::vector<Gate*>>& registers)>& criteria)
237 std::vector<u32> fitlered_indices;
238 u32 best_criteria_value = minimize ? std::numeric_limits<u32>::max() :
std::numeric_limits<
u32>::min();
239 for (
u32 idx = 0; idx < candidate_sets.size(); idx++)
241 const u32 criteria_val = criteria(candidate_sets.at(idx), registers);
242 const bool new_best = minimize ? (criteria_val < best_criteria_value) : (criteria_val > best_criteria_value);
243 const bool equal = (criteria_val == best_criteria_value);
247 best_criteria_value = criteria_val;
248 fitlered_indices.clear();
249 fitlered_indices.push_back(idx);
255 fitlered_indices.push_back(idx);
259 std::vector<std::vector<VerifiedCandidate>> filtered_candidates;
260 for (
const auto& idx : fitlered_indices)
262 filtered_candidates.push_back(candidate_sets.at(idx));
265 return filtered_candidates;
268 std::vector<VerifiedCandidate> select_best_candidate_set(
const Netlist* nl,
const std::vector<VerifiedCandidate>& candidates,
const std::vector<std::vector<Gate*>>& registers)
271 std::vector<VerifiedCandidate> unique_candidates = candidates;
272 unique_candidates.erase(std::unique(unique_candidates.begin(), unique_candidates.end()), unique_candidates.end());
275 std::cout <<
"Dedupe candidates to a size of " << unique_candidates.size() << std::endl;
279 std::map<std::pair<std::vector<Gate*>, std::vector<Net*>>, std::vector<VerifiedCandidate>> gates_control_to_candidate_sets;
280 for (
const auto& c : unique_candidates)
282 gates_control_to_candidate_sets[{c.m_gates, c.m_control_signals}].push_back(c);
285 std::vector<std::vector<VerifiedCandidate>> candidate_sets;
286 for (
const auto& [_, c_set] : gates_control_to_candidate_sets)
288 candidate_sets.push_back(c_set);
292 std::cout <<
"Sorted candidates into " << candidate_sets.size() <<
" candidate sets" << std::endl;
299 candidate_sets = filter_out_redundant_const_muls(candidate_sets);
301 std::cout <<
"Filtered redundant constant multiplication candidates, left with " << candidate_sets.size() << std::endl;
305 candidate_sets = filter_sets_by(candidate_sets, registers,
true, [](
const auto& c_set,
const auto& _registers) {
307 return calcualte_ignored_input_signals(c_set);
310 std::cout <<
"Left with the following sets: " << std::endl;
311 for (
const auto& cs : candidate_sets)
313 std::cout <<
enum_to_string(*cs.front().m_types.begin()) <<
": " << cs.size() << std::endl;
314 for (
const auto& o_net : cs.front().m_output_nets)
316 std::cout <<
"\t" << o_net->get_name() << std::endl;
319 std::cout <<
"Filtered candidates with ignored input signals, left with " << candidate_sets.size() << std::endl;
323 candidate_sets = filter_sets_by(candidate_sets, registers,
false, [](
const auto& c_set,
const auto& _registers) {
325 return calculate_maximum_io_signals(c_set);
328 std::cout <<
"Filtered candidates with most IO signals, left with " << candidate_sets.size() << std::endl;
332 candidate_sets = filter_sets_by(candidate_sets, registers,
true, [](
const auto& c_set,
const auto& _registers) {
334 return c_set.front().m_control_signals.size();
337 std::cout <<
"Filtered candidates with control signal count, left with " << candidate_sets.size() << std::endl;
341 candidate_sets = filter_sets_by(candidate_sets, registers,
false, [](
const auto& c_set,
const auto& _registers) {
343 return c_set.front().m_gates.size();
346 std::cout <<
"Filtered candidates with candidate gate count, left with " << candidate_sets.size() << std::endl;
350 candidate_sets = filter_sets_by(candidate_sets, registers,
true, [nl](
const auto& c_set,
const auto& r) {
return calculate_shared_source_regs(nl, c_set, r); });
352 std::cout <<
"Filtered candidates with shared source reg count, left with " << candidate_sets.size() << std::endl;
356 candidate_sets = filter_sets_by(candidate_sets, registers,
true, [](
const auto& c_set,
const auto& _registers) {
358 return calcualte_ignored_output_signals(c_set);
361 std::cout <<
"Filtered candidates with ignored output signal count, left with " << candidate_sets.size() << std::endl;
365 candidate_sets = filter_sets_by(candidate_sets, registers,
false, [](
const auto& c_set,
const auto& _registers) {
370 std::cout <<
"Reduced candidates to " << candidate_sets.size() <<
" sets." << std::endl;
374 if (candidate_sets.size() > 1)
376 log_warning(
"module_identification",
"Found {} optimal candidate sets, need to investigate furhter.", candidate_sets.size());
379 return candidate_sets.front();
386 u32 calculate_operand_source_regs(
const Netlist* nl,
const VerifiedCandidate& candidate,
const std::vector<std::vector<Gate*>>& registers)
388 u32 total_source_regs = 0;
389 for (
const auto& nets : candidate.m_operands)
391 std::set<u32> op_regs;
392 for (
const auto& n : nets)
394 const auto seq_inputs_res =
395 NetlistTraversalDecorator(*nl).get_next_matching_gates( n,
false, [](
const auto& g) { return g->get_type()->has_property(GateTypeProperty::sequential); });
396 if (seq_inputs_res.is_error())
398 log_error(
"module_identification",
"{}", seq_inputs_res.get_error().get());
400 const auto seq_inputs = seq_inputs_res.get();
402 for (
const auto& si : seq_inputs)
404 for (
u32 reg_idx = 0; reg_idx < registers.size(); reg_idx++)
406 const auto& reg = registers.at(reg_idx);
407 if (std::find(reg.begin(), reg.end(), si) != reg.end())
409 op_regs.insert(reg_idx);
416 total_source_regs += op_regs.size();
419 return total_source_regs;
422 VerifiedCandidate select_best_sign_extended_comparison_candidate(
const Netlist* nl,
const std::vector<VerifiedCandidate>& candidates)
424 std::set<Net*> unique_nets;
425 for (
const auto& op_nets : candidates.front().m_operands)
427 for (
const auto&
net : op_nets)
429 if (
net->is_gnd_net() ||
net->is_vcc_net())
434 unique_nets.insert(
net);
439 const std::set<const Gate*> candidate_gates = {candidates.front().m_gates.begin(), candidates.front().m_gates.end()};
441 std::map<Net*, std::set<Gate*>> net_to_reachable_gates;
442 std::map<Gate*, u32> gate_to_reach_counter;
444 for (
const auto&
net : unique_nets)
446 const auto reachable_res =
447 NetlistTraversalDecorator(*nl).get_next_matching_gates_until(
net,
true, [&candidate_gates](
const auto& g) { return candidate_gates.find(g) != candidate_gates.end(); });
449 net_to_reachable_gates.insert({
net, reachable_res.get()});
451 for (
const auto& gate : reachable_res.get())
453 gate_to_reach_counter[gate] += 1;
458 std::set<Gate*> core_gates;
459 for (
const auto& [gate, count] : gate_to_reach_counter)
463 core_gates.insert(gate);
467 u32 best_candidate_idx = 0;
468 u32 most_reached_gates = 0;
470 for (
u32 idx = 0; idx < candidates.size(); idx++)
472 const auto& candidate = candidates.at(idx);
475 Net* signed_net =
nullptr;
476 for (
const auto& operand : candidate.m_operands)
478 if (operand[operand.size() - 1] == operand[operand.size() - 2])
480 signed_net = operand[operand.size() - 1];
484 if (signed_net ==
nullptr)
490 std::vector<Gate*> reachable_core_gates;
491 std::set_intersection(
492 net_to_reachable_gates.at(signed_net).begin(), net_to_reachable_gates.at(signed_net).end(), core_gates.begin(), core_gates.end(), std::back_inserter(reachable_core_gates));
494 if (reachable_core_gates.size() > most_reached_gates)
496 most_reached_gates = reachable_core_gates.size();
497 best_candidate_idx = idx;
501 return candidates.at(best_candidate_idx);
504 std::vector<VerifiedCandidate> filter_candidates_by(
const std::vector<VerifiedCandidate>& candidates,
505 const std::vector<std::vector<Gate*>>& registers,
507 const std::function<
u32(
const VerifiedCandidate&,
const std::vector<std::vector<Gate*>>& registers)>& criteria)
509 std::vector<u32> fitlered_indices;
510 u32 best_criteria_value = minimize ? std::numeric_limits<u32>::max() :
std::numeric_limits<
u32>::min();
511 for (
u32 idx = 0; idx < candidates.size(); idx++)
513 const u32 criteria_val = criteria(candidates.at(idx), registers);
514 const bool new_best = minimize ? (criteria_val < best_criteria_value) : (criteria_val > best_criteria_value);
515 const bool equal = (criteria_val == best_criteria_value);
519 best_criteria_value = criteria_val;
520 fitlered_indices.clear();
521 fitlered_indices.push_back(idx);
527 fitlered_indices.push_back(idx);
531 std::vector<VerifiedCandidate> filtered_candidates;
532 for (
const auto& idx : fitlered_indices)
534 filtered_candidates.push_back(candidates.at(idx));
537 return filtered_candidates;
540 std::vector<VerifiedCandidate> select_best_candidates(
const Netlist* nl,
const std::vector<VerifiedCandidate>& candidates,
const std::vector<std::vector<Gate*>>& registers)
542 auto best_candidates = candidates;
547 best_candidates = filter_candidates_by(best_candidates, registers,
true, [](
const auto& c,
const auto& _r) {
550 const auto c_outputs = c.m_output_nets.size();
551 const auto additional_outputs = (c_outputs > all_outputs) ? 0 : all_outputs - c_outputs;
552 return additional_outputs;
556 std::cout <<
"reduced candidate set to size " << best_candidates.size() << std::endl;
562 best_candidates = filter_candidates_by(best_candidates, registers,
false, [](
const auto& c,
const auto& _r) {
564 u32 non_constant_count = 0;
565 for (
const auto& nets : c.m_operands)
567 for (
const auto&
net : nets)
569 non_constant_count = (!
net->is_gnd_net() && !
net->is_vcc_net()) ? non_constant_count + 1 : non_constant_count;
572 return non_constant_count;
576 std::cout <<
"reduced candidate set to size " << best_candidates.size() << std::endl;
584 best_candidates = filter_candidates_by(best_candidates, registers,
true, [](
const auto& c,
const auto& _r) {
586 u32 constant_count = 0;
587 for (
const auto& nets : c.m_operands)
589 for (
const auto&
net : nets)
591 constant_count = (!
net->is_gnd_net() && !
net->is_vcc_net()) ? constant_count : constant_count + 1;
594 return constant_count;
598 std::cout <<
"reduced candidate set to size " << best_candidates.size() << std::endl;
606 best_candidates = filter_candidates_by(best_candidates, registers,
true, [](
const auto& c,
const auto& _r) {
609 std::map<Net*, std::set<u32>> net_to_ops;
610 for (
u32 op_idx = 0; op_idx < c.m_operands.size(); op_idx++)
612 const auto& nets = c.m_operands.at(op_idx);
613 for (
const auto&
net : nets)
615 net_to_ops[
net].insert(op_idx);
619 for (
const auto& [_, ops] : net_to_ops)
630 std::cout <<
"reduced candidate set to size " << best_candidates.size() << std::endl;
638 best_candidates = filter_candidates_by(best_candidates, registers,
true, [nl](
const auto& c,
const auto& r) {
return calculate_operand_source_regs(nl, c, r); });
641 std::cout <<
"reduced candidate set to size " << best_candidates.size() << std::endl;
648 std::vector<VerifiedCandidate> reducable_signed_comparisons;
649 std::vector<std::vector<VerifiedCandidate>::iterator> to_remove;
650 for (
auto it = best_candidates.begin(); it != best_candidates.end(); it++)
654 reducable_signed_comparisons.push_back((*it));
655 to_remove.push_back(it);
658 for (
const auto& elem : to_remove)
660 best_candidates.erase(elem);
662 if (reducable_signed_comparisons.size() > 0)
664 best_candidates.push_back(select_best_sign_extended_comparison_candidate(nl, reducable_signed_comparisons));
667 return best_candidates;
679 Result<i32> get_offset(
const u32& org1,
const u32& org2, std::map<
u32, std::map<u32, i32>>& m, std::set<std::set<u32>>& v)
681 if (v.find({org1, org2}) != v.end())
683 return ERR(
"Already tried to follow that offset.");
686 v.insert({org1, org2});
694 if (m.find(org1) == m.end())
696 return ERR(
"No valid offset to other origins.");
699 if (m.at(org1).find(org2) != m.at(org1).end())
701 return OK(m.at(org1).at(org2));
704 for (
auto& [dst, first_proxy_offset] : m.at(org1))
706 auto second_proxy_offset_res = get_offset(dst, org2, m, v);
707 if (second_proxy_offset_res.is_error())
711 i32 second_proxy_offset = second_proxy_offset_res.get();
713 m[org1][org2] = first_proxy_offset + second_proxy_offset;
714 return OK(first_proxy_offset + second_proxy_offset);
717 return ERR(
"Not able to find a offset connection.");
725 Result<std::map<u32, std::map<u32, i32>>> build_offset_matrix(
const std::map<Net*, std::map<u32, u32>>& indices)
728 std::map<u32, std::map<u32, i32>> origin_offset_matrix;
730 for (
const auto& [
net, org_to_idx] : indices)
732 std::map<u32, u32> all_possible_indices;
735 for (
const auto& [org, idx] : org_to_idx)
737 all_possible_indices[org] = idx;
741 for (
const auto& [org, idx] : org_to_idx)
743 for (
const auto& [already_set_org, already_set_index] : all_possible_indices)
746 if (origin_offset_matrix[org].find(already_set_org) == origin_offset_matrix[org].end())
749 i32 offset = already_set_index - new_index;
751 origin_offset_matrix[org][already_set_org] = offset;
752 origin_offset_matrix[already_set_org][org] = -offset;
758 i32 offset = origin_offset_matrix.at(org).at(already_set_org);
760 if (new_index + offset !=
i32(already_set_index))
762 return ERR(
"unable to build offset matrix: failed to find valid offset for net " +
net->get_name() +
" with ID " + std::to_string(
net->get_id()) +
" between "
763 + std::to_string(org) +
" and " + std::to_string(already_set_org));
770 return OK(origin_offset_matrix);
776 std::vector<Net*> reconstruct_shifted_operand(
const std::vector<std::vector<Net*>>& operands)
778 std::map<Net*, std::map<u32, u32>> indices;
779 for (
u32 op_idx = 0; op_idx < operands.size(); op_idx++)
781 const auto& operand = operands.at(op_idx);
782 std::set<Net*> included_nets;
784 bool found_non_const_net =
false;
785 for (
u32 net_idx = 0; net_idx < operand.size(); net_idx++)
787 const auto&
net = operand.at(net_idx);
790 if (!
net->is_gnd_net() && !
net->is_vcc_net())
792 found_non_const_net =
true;
796 if (included_nets.find(
net) != included_nets.end())
802 if ((
net->is_gnd_net() ||
net->is_vcc_net()) && found_non_const_net)
807 included_nets.insert(
net);
809 indices[
net].insert({op_idx, net_idx});
814 std::map<Net*, i32> consens_bitindices;
816 auto offset_matrix_res = build_offset_matrix(indices);
817 if (offset_matrix_res.is_error())
819 log_error(
"module_identification",
"failed to build offset matrix:\n{}", offset_matrix_res.get_error().get());
822 auto offset_matrix = offset_matrix_res.get();
824 auto base_line = offset_matrix.begin()->first;
826 for (
const auto& [
net, possible_indices] : indices)
829 u32 org = possible_indices.begin()->first;
831 i32 org_index = possible_indices.begin()->second;
832 std::set<std::set<u32>> v;
833 auto offset_res = get_offset(org, base_line, offset_matrix, v);
834 if (offset_res.is_error())
837 "failed to reconstruct shifted operand: failed to find offset for net " +
net->get_name() +
" with ID " + std::to_string(
net->get_id()) +
" bewteen "
838 + std::to_string(org) +
" and " + std::to_string(base_line));
843 i32 offset = offset_res.get();
844 consens_bitindices[
net] = org_index + offset;
849 std::vector<Net*> ordered_nets;
850 for (
const auto& [
net, _] : consens_bitindices)
852 if (
net->is_gnd_net() ||
net->is_vcc_net())
857 ordered_nets.push_back(
net);
860 std::sort(ordered_nets.begin(), ordered_nets.end(), [&consens_bitindices](
const auto& n1,
const auto& n2) { return consens_bitindices.at(n1) < consens_bitindices.at(n2); });
865 Result<std::monostate> reconstruct_operands(VerifiedCandidate& vc,
const std::vector<std::vector<Gate*>>& registers)
868 std::vector<std::vector<Net*>> operands = vc.m_operands;
869 std::vector<std::vector<Net*>> reconstructed_operands;
871 if (vc.m_types.size() != 1)
876 const auto candidate_type = *(vc.m_types.begin());
880 reconstructed_operands = {reconstruct_shifted_operand(operands)};
881 vc.m_operands = reconstructed_operands;
887 Result<VerifiedCandidate> merge_candidate_set(
const Netlist* nl,
const std::vector<VerifiedCandidate>& candidate_set,
const std::vector<std::vector<Gate*>>& registers)
889 std::map<std::map<Net*, BooleanFunction::Value>, std::vector<VerifiedCandidate>> ctrl_to_candidates;
890 std::vector<VerifiedCandidate> filtered_candidates;
893 for (
const auto& vc : candidate_set)
896 if (vc.m_control_signal_mappings.size() == 1)
898 ctrl_to_candidates[vc.m_control_signal_mappings.front()].push_back(vc);
902 filtered_candidates.push_back(vc);
906 for (
const auto& [_, c] : ctrl_to_candidates)
911 auto best_candidate = select_best_candidates(nl, c, registers).front();
913 const auto res = reconstruct_operands(best_candidate, registers);
916 return ERR_APPEND(res.get_error(),
"cannot merge canidate set: failed operand reconstruction");
919 filtered_candidates.push_back(best_candidate);
923 auto candidate = c.front();
924 const auto res = reconstruct_operands(candidate, registers);
927 return ERR_APPEND(res.get_error(),
"cannot merge canidate set: failed operand reconstruction");
930 filtered_candidates.push_back(candidate);
935 std::cout <<
"OPTIMAL CANDIDATE SET [" << filtered_candidates.size() <<
"]: " << std::endl;
936 for (
const auto& c : filtered_candidates)
938 std::cout << c.get_candidate_info() << std::endl;
943 if (merge_res.is_error())
945 return ERR_APPEND(merge_res.get_error(),
"Could not merge candidate set in post processing: failed to merge candidates");
955 if (verified_candidates.empty())
961 "module_identification",
"processing module for carry chain {} with {} verified variants", verified_candidates.front().m_base_gates.front()->get_name(), verified_candidates.size());
964 std::cout <<
"ALL CANDIDATES [" << verified_candidates.size() <<
"]: " << std::endl;
965 for (
const auto& vc : verified_candidates)
967 std::cout << vc.get_candidate_info() << std::endl;
972 std::vector<VerifiedCandidate> unique_verified_candidates;
973 for (
const auto& vc : verified_candidates)
975 bool is_unique =
true;
976 for (
const auto& uvc : unique_verified_candidates)
987 unique_verified_candidates.push_back(vc);
991 log_info(
"module_identification",
"processing module for carry chain with {} unique verified variants", unique_verified_candidates.size());
994 std::cout <<
"ALL UNIQUE CANDIDATES [" << unique_verified_candidates.size() <<
"]: " << std::endl;
995 for (
const auto& vc : unique_verified_candidates)
997 std::cout << vc.get_candidate_info() << std::endl;
1000 const auto best_candidate_set = select_best_candidate_set(nl, unique_verified_candidates, registers);
1002 log_info(
"module_identification",
"selected best candidate set containing {} candidates.", best_candidate_set.size());
1006 std::cout <<
"PRE-MERGE CANDIDATE SET [" << best_candidate_set.size() <<
"]: " << std::endl;
1007 for (
const auto& c : best_candidate_set)
1009 std::cout << c.get_candidate_info() << std::endl;
1013 const auto best_candidate = merge_candidate_set(nl, best_candidate_set, registers);
1015 return best_candidate.get();
This file contains the enumeration and constants for the candidate types used in the module identific...
Represents a verified candidate for module identification.
static hal::Result< VerifiedCandidate > merge(const std::vector< VerifiedCandidate > &candidates)
Merge multiple verified candidates into a single candidate.
#define log_error(channel,...)
#define log_info(channel,...)
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
VerifiedCandidate post_processing(const std::vector< VerifiedCandidate > &verified_candidates, const Netlist *nl, const std::vector< std::vector< Gate * >> &dana_cache)
Performs post-processing on a set of verified candidates to identify the best candidate for module id...
std::vector< Net * > get_input_nets(const std::vector< Gate * > &gates)
Get input nets from a list of gates.
@ signed_less_equal
Signed less-than-or-equal comparison.
@ equal
Equality comparison.
@ counter
Counter operation.
@ constant_multiplication
Constant multiplication operation.
@ signed_less_than
Signed less-than comparison.
@ constant_multiplication_offset
Constant multiplication operation with a constant offset.
std::vector< Net * > get_output_nets(const std::vector< Gate * > &gates, bool only_external_destinations=true)
Get output nets from a list of gates.
std::string enum_to_string(T e)
This file contains helper functions for module identification in the HAL framework.
This file contains the function to perform post-processing on verified candidates to identify the bes...