9 namespace module_identification
16 Result<std::vector<std::pair<Net*, Net*>>> create_net_pair_sorting_by_influence(CandidateContext& ctx,
const Net* output_net,
const std::map<Net*, BooleanFunction::Value>& initial_mapping)
18 const Netlist* nl = output_net->get_netlist();
20 auto to_use_control_mapping = initial_mapping;
22 std::vector<std::pair<Net*, Net*>> result;
25 const auto res = ctx.get_boolean_influence(output_net, to_use_control_mapping);
28 return ERR_APPEND(res.get_error(),
"failed to create boolean influence");
30 const auto influence_mapping = res.get();
33 std::vector<std::pair<Net*, double>> influence_vector;
34 for (std::pair<std::string, double> cur_pair : influence_mapping)
37 influence_vector.push_back(std::make_pair(cur_net, cur_pair.second));
41 if ((influence_vector.size() % 2) != 0)
47 std::sort(influence_vector.begin(), influence_vector.end(), [](
const std::pair<Net*, double>& a,
const std::pair<Net*, double>& b) { return a.second > b.second; });
49 const u32 upper_bound = std::min((
u32)influence_vector.size(), (
u32)10);
50 for (
u32 i = 0; i < upper_bound; i += 2)
52 to_use_control_mapping[influence_vector[i].first] = BooleanFunction::Value::ZERO;
53 to_use_control_mapping[influence_vector[i + 1].first] = BooleanFunction::Value::ZERO;
55 result.push_back(std::make_pair(influence_vector[i].first, influence_vector[i + 1].first));
58 if (influence_vector.size() <= 10)
64 std::reverse(result.begin(), result.end());
73 std::vector<FunctionalCandidate> result;
76 return OK(std::vector<FunctionalCandidate>());
81 new_candidate.m_output_nets = {cur_out_net};
83 result.push_back(new_candidate);
90 std::vector<FunctionalCandidate> candidates;
92 if (var_names_res.is_error())
94 return ERR_APPEND(var_names_res.get_error(),
"cannot check whether to discard equal candidate: failed to retrieve variable names from context");
96 const auto& var_names = var_names_res.get();
98 if (var_names.size() % 2 == 0)
102 return OK(candidates);
113 return ERR_APPEND(res.get_error(),
"cannot find control signals via Boolean influence: failed Boolean influence calculation");
115 std::unordered_map<std::string, double> influence_mapping = res.get();
117 std::vector<std::pair<Net*, double>> influence_vector;
118 for (std::pair<std::string, double> cur_pair : influence_mapping)
121 influence_vector.push_back(std::make_pair(cur_net, cur_pair.second));
125 std::sort(influence_vector.begin(), influence_vector.end(), [](
const std::pair<Net*, double>& a,
const std::pair<Net*, double>& b) { return a.second > b.second; });
128 for (
u32 num_control_signals = 0; num_control_signals < max_control_signals; num_control_signals++)
131 std::vector<Net*> control_signals;
132 for (
u32 net_idx = 0; net_idx < num_control_signals + 1; net_idx++)
134 control_signals.push_back(influence_vector[net_idx].first);
138 candidates.push_back(new_candidate);
141 return OK(candidates);
152 return ERR_APPEND(res.get_error(), (
"failed to get boolean influence for net " + candidate.
m_output_nets[0]->get_name()));
154 auto influences = res.get();
157 std::vector<std::pair<Net*, double>> influence_vector;
158 for (
const auto& cur_pair : influences)
161 influence_vector.push_back(std::make_pair(cur_net, cur_pair.second));
164 if (influence_vector.size() < 3)
166 return OK(new_candidates);
170 std::sort(influence_vector.begin(), influence_vector.end(), [](
const std::pair<Net*, double>& a,
const std::pair<Net*, double>& b) { return a.second > b.second; });
173 if ((influence_vector[0].second * 0.75 < influence_vector[1].second))
175 return OK(new_candidates);
179 new_candidate.m_sign_nets.push_back(influence_vector[0].first);
182 for (
u32 net_idx = 1; net_idx < (influence_vector.size() - 1); net_idx++)
184 new_candidate.m_sign_nets.push_back(influence_vector[net_idx].first);
186 if ((influence_vector[net_idx].second * 0.75) > influence_vector[net_idx + 1].second)
193 if (new_candidate.m_sign_nets.size() > 6)
195 return OK(new_candidates);
199 if (((influence_vector.size() - new_candidate.m_sign_nets.size()) % 2) != 0)
201 return OK(new_candidates);
204 new_candidates.push_back(new_candidate);
206 return OK(new_candidates);
216 if (e.get_sort().bv_size() > 64)
221 return e.get_numeral_uint64() == val;
235 input_mapping.insert({
net, BooleanFunction::Value::ZERO});
239 if (input_nets_res.is_error())
241 return ERR_APPEND(input_nets_res.get_error(),
"cannot create net pair sorting: failed to retrieve variable nets");
243 const auto input_nets = input_nets_res.get();
245 if ((input_nets.size() % 2) != 0)
252 auto input_pair_res = create_net_pair_sorting_by_influence(ctx, new_candidate.
m_output_nets[0], input_mapping);
253 if (input_pair_res.is_error())
255 return ERR_APPEND(input_pair_res.get_error(),
"failed to create sorting of net pairs for LEQ");
257 const auto input_pairs = input_pair_res.get();
259 if (input_pairs.empty())
266 for (
const auto& n : input_nets)
268 input_mapping.insert({n, BooleanFunction::Value::ZERO});
272 auto to_append_operands = new_candidate.
m_operands;
277 for (
const std::pair<Net*, Net*>& cur_bit : input_pairs)
279 input_mapping[cur_bit.first] = BooleanFunction::Value::ONE;
280 bool found_first =
false;
282 if (first_res.is_error())
284 return ERR_APPEND(first_res.get_error(),
"failed to evaluate boolean functions");
292 input_mapping[cur_bit.first] = BooleanFunction::Value::ZERO;
293 input_mapping[cur_bit.second] = BooleanFunction::Value::ONE;
298 return ERR_APPEND(res.get_error(),
"failed to evaluate boolean functions");
301 input_mapping[cur_bit.second] = BooleanFunction::Value::ZERO;
311 new_candidate.
m_operands.at(0).push_back(cur_bit.second);
312 new_candidate.
m_operands.at(1).push_back(cur_bit.first);
317 new_candidate.
m_operands.at(0).push_back(cur_bit.first);
318 new_candidate.
m_operands.at(1).push_back(cur_bit.second);
322 std::vector<FunctionalCandidate> result;
323 result.push_back(new_candidate);
326 for (
u32 msb_idx = 1; msb_idx < candidate.
m_sign_nets.size(); msb_idx++)
328 std::vector<Net*> extension_side;
329 std::vector<Net*> not_extended_side;
338 extension_side.push_back(candidate.
m_sign_nets.at(msb_idx));
339 not_extended_side.push_back(candidate.
m_sign_nets.at(idx));
342 extension_side.push_back(candidate.
m_sign_nets.at(msb_idx));
343 not_extended_side.push_back(candidate.
m_sign_nets.at(0));
350 new_candidate_left.m_operands[0].insert(new_candidate_left.m_operands[0].end(), extension_side.begin(), extension_side.end());
351 new_candidate_left.m_operands[1].insert(new_candidate_left.m_operands[1].end(), not_extended_side.begin(), not_extended_side.end());
352 new_candidate_right.m_operands[0].insert(new_candidate_right.m_operands[0].end(), not_extended_side.begin(), not_extended_side.end());
353 new_candidate_right.m_operands[1].insert(new_candidate_right.m_operands[1].end(), extension_side.begin(), extension_side.end());
355 result.push_back(new_candidate_left);
356 result.push_back(new_candidate_right);
367 std::vector<std::vector<Net*>> combinations(
const std::vector<Net*>& candidates,
const u32 k)
369 std::vector<std::vector<Net*>> res;
370 std::vector<Net*> tmp;
371 std::string bitmask(k, 1);
372 bitmask.resize(candidates.size(), 0);
376 for (
u32 i = 0; i < candidates.size(); ++i)
380 tmp.push_back(candidates[i]);
386 }
while (std::prev_permutation(bitmask.begin(), bitmask.end()));
390 std::map<Net*, BooleanFunction::Value> generate_control_mapping(
const std::vector<Net*>& ctrl_signlas,
u32 val)
392 std::map<Net*, BooleanFunction::Value> substitution_map;
394 for (
u32 idx = 0; idx < ctrl_signlas.size(); idx++)
396 const u32 val_i = (val >> idx) & 0x1;
397 substitution_map[ctrl_signlas.at(idx)] = val_i ? BooleanFunction::Value::ONE :
BooleanFunction::ZERO;
400 return substitution_map;
403 std::vector<std::pair<std::map<u32, std::vector<Net*>>, std::vector<Net*>>>
404 generate_control_input_splits(
const std::pair<std::map<
u32, std::vector<Net*>>, std::vector<Net*>>& initial,
const u32 threshold,
const u32 max_control_signals,
const u32 max_depth)
406 const auto& [count_to_vars, ctrl_vars] = initial;
408 if (ctrl_vars.size() > max_control_signals)
413 for (
const auto& [count, vars] : count_to_vars)
415 if (vars.size() > threshold)
418 const u32 excess = vars.size() - threshold;
419 if (excess > max_control_signals)
431 const auto combs = combinations(vars, excess);
434 std::vector<std::pair<std::map<u32, std::vector<Net*>>, std::vector<Net*>>> tmp;
435 for (
const auto& c : combs)
437 auto new_result = initial;
439 for (
const auto& ctrl_sig : c)
441 auto& c_vars = new_result.first.at(count);
442 c_vars.erase(
std::remove(c_vars.begin(), c_vars.end(), ctrl_sig), c_vars.end());
443 new_result.second.push_back(ctrl_sig);
448 tmp.push_back(new_result);
452 std::vector<std::pair<std::map<u32, std::vector<Net*>>, std::vector<Net*>>> result;
453 for (
const auto& t : tmp)
455 for (
const auto&
split : generate_control_input_splits(t, threshold, max_control_signals, max_depth - 1))
457 result.push_back(
split);
473 std::vector<FunctionalCandidate> new_candidates;
478 std::map<u32, u32> size_to_occurence;
480 std::vector<u32> size_list;
483 size_list.push_back(vars.size());
484 sizes.insert(vars.size());
485 size_to_occurence[vars.size()] += 1;
498 std::sort(size_list.begin(), size_list.end());
503 log_warning(
"module_identification",
"unable to identify control signals: found empty size list");
507 const u32 upper_bound = (sizes.size() == 1) ? *(size_list.begin()) : std::min({*(size_list.rbegin()), *std::next(size_list.rbegin(), 1)});
510 const u32 upper_bound_alt = (sizes.size() == 2) ? *(size_list.begin()) : std::min({*std::next(size_list.rbegin(), 1), *std::next(size_list.rbegin(), 2)});
513 const u32 max_bins_including_control = 2;
515 threshold = std::min({
u32(6), threshold});
516 threshold_alt = std::min({
u32(6), threshold_alt});
521 u32 ctrl_signals = control_input_splits.empty() ? 0 : control_input_splits.front().second.size();
522 u32 future_candidate_size = control_input_splits.size() * (1 << ctrl_signals);
526 if (future_candidate_size > 32000)
528 control_input_splits.clear();
534 if (threshold_alt != threshold)
536 auto control_input_splits_alt =
543 u32 ctrl_signals_alt = control_input_splits_alt.empty() ? 0 : control_input_splits_alt.front().second.size();
544 u32 future_candidate_size_alt = control_input_splits_alt.size() * (1 << ctrl_signals_alt);
548 if (future_candidate_size_alt > 32000)
550 control_input_splits_alt.clear();
553 for (
const auto&
split : control_input_splits_alt)
556 control_input_splits.push_back(
split);
581 bool added_vanilla_candidate =
false;
582 for (
const auto& [_variable_count, ctrl_vars] : control_input_splits)
593 for (
const auto& cv : ctrl_vars)
595 new_candidate.m_control_signals.push_back(cv);
598 new_candidates.push_back(new_candidate);
600 if (ctrl_vars.empty())
602 added_vanilla_candidate =
true;
607 && !added_vanilla_candidate)
610 pass_through_candidate.m_control_signals.clear();
611 for (
const auto& [ctrl_val, _] : pass_through_candidate.m_control_mapping)
613 pass_through_candidate.m_control_signals.push_back(ctrl_val);
615 new_candidates.push_back(pass_through_candidate);
620 log_error(
"module_identification",
"More than 5 control signals are currently not implemented!");
621 new_candidates = {candidate};
624 return OK(new_candidates);
630 std::vector<FunctionalCandidate> new_candidates;
635 new_candidate.m_control_signals.erase(
std::remove(new_candidate.m_control_signals.begin(), new_candidate.m_control_signals.end(), ctrl_signal), new_candidate.m_control_signals.end());
636 new_candidate.m_ctrl_to_operand_net = ctrl_signal;
638 new_candidates.push_back(new_candidate);
641 return OK(new_candidates);
647 std::vector<FunctionalCandidate> new_candidates;
650 for (
u32 val = 0; val < max_val; val++)
653 new_candidate.m_max_control_signals = 0;
660 new_candidate.m_control_mapping = generate_control_mapping(candidate.
m_control_signals, val);
662 new_candidates.push_back(new_candidate);
665 return OK(new_candidates);
670 std::vector<Net*> order_by_influence(
const std::vector<Net*>& nets,
CandidateContext& ctx,
const std::map<hal::Net*, hal::BooleanFunction::Value>& ctrl_mapping)
672 std::vector<Net*> reordered_nets = nets;
673 std::map<Net*, double> output_net_to_influence_score;
674 for (
const auto& n : reordered_nets)
677 if (influences_res.is_error())
679 log_error(influences_res.get_error().get());
682 const auto& influences = influences_res.get();
684 if (influences.empty())
690 double influence_score = 0;
691 for (
const auto& [_, inf] : influences)
693 influence_score += inf;
696 output_net_to_influence_score.insert({n, influence_score});
699 std::sort(reordered_nets.begin(), reordered_nets.end(), [&output_net_to_influence_score](
const auto& n1,
const auto& n2) {
700 return output_net_to_influence_score.at(n1) < output_net_to_influence_score.at(n2);
703 return reordered_nets;
706 std::vector<std::vector<Net*>> permutations(
const std::vector<Net*>& nets)
708 std::vector<Net*> initial = nets;
709 std::vector<std::vector<Net*>> result;
711 std::sort(initial.begin(), initial.end());
715 result.push_back({initial.begin(), initial.end()});
716 }
while (std::next_permutation(initial.begin(), initial.end()));
721 std::vector<std::vector<Net*>> reorder_overfull_input_bins(
const std::map<
u32, std::vector<Net*>>& initial,
const u32 max_overfull_bins)
723 std::vector<std::vector<Net*>> results;
724 std::vector<Net*> singleton_bins_before;
725 std::vector<Net*> singleton_bins_after;
726 std::vector<Net*> to_permute;
727 std::vector<std::vector<Net*>> overfull_bins;
729 for (
auto it = initial.rbegin(); it != initial.rend(); it++)
731 const auto nets = it->second;
732 if (nets.size() != 1)
736 if (!singleton_bins_after.empty())
741 to_permute.insert(to_permute.end(), nets.begin(), nets.end());
742 overfull_bins.push_back(nets);
746 if (to_permute.empty())
748 singleton_bins_before.push_back(nets.front());
752 singleton_bins_after.push_back(nets.front());
758 if (overfull_bins.size() > max_overfull_bins)
766 if (to_permute.size() <= 5)
768 std::sort(to_permute.begin(), to_permute.end());
772 std::vector<Net*> tmp;
773 tmp.insert(tmp.end(), singleton_bins_before.begin(), singleton_bins_before.end());
774 tmp.insert(tmp.end(), to_permute.begin(), to_permute.end());
775 tmp.insert(tmp.end(), singleton_bins_after.begin(), singleton_bins_after.end());
777 results.push_back(tmp);
778 }
while (std::next_permutation(to_permute.begin(), to_permute.end()));
783 std::set<u32> overfull_sizes;
784 for (
const auto& bin : overfull_bins)
786 overfull_sizes.insert(
bin.size());
789 if (overfull_sizes.size() != 1)
796 const u32 bin_size = *overfull_sizes.begin();
805 std::vector<std::vector<std::vector<Net*>>> isolated_permuted_bins = {{}};
806 std::vector<std::vector<std::vector<Net*>>> new_isolated_permuted_bins;
807 for (
auto bin : overfull_bins)
809 std::sort(
bin.begin(),
bin.end());
812 for (
const auto& bin_set : isolated_permuted_bins)
814 auto new_bin_set = bin_set;
815 new_bin_set.push_back(bin);
816 new_isolated_permuted_bins.push_back(new_bin_set);
818 if (new_isolated_permuted_bins.size() > 1000)
825 }
while (std::next_permutation(
bin.begin(),
bin.end()));
827 isolated_permuted_bins = new_isolated_permuted_bins;
828 new_isolated_permuted_bins.clear();
831 for (
const auto& bin_set : isolated_permuted_bins)
833 std::vector<Net*> input_operand;
834 input_operand.insert(input_operand.end(), singleton_bins_before.begin(), singleton_bins_before.end());
835 for (
u32 idx = 0; idx < bin_set.front().
size(); idx++)
837 for (
const auto& bin : bin_set)
839 input_operand.push_back(
bin.at(idx));
842 input_operand.insert(input_operand.end(), singleton_bins_after.begin(), singleton_bins_after.end());
843 results.push_back(input_operand);
850 std::vector<std::vector<Net*>>
851 reorder_overfull_output_bins(CandidateContext& ctx,
const std::map<hal::Net*, hal::BooleanFunction::Value>& ctrl_mapping,
const std::map<
u32, std::vector<Net*>>& initial)
853 std::vector<std::vector<Net*>> prev_results;
854 std::vector<std::vector<Net*>> next_results;
856 std::vector<std::vector<Net*>> bins;
858 for (
auto it = initial.rbegin(); it != initial.rend(); it++)
860 bins.push_back(it->second);
863 for (
const auto& bin : bins)
866 const auto perm = (
bin.size() < 4) ? permutations(bin) : std::vector<std::vector<Net*>>{order_by_influence(bin, ctx, ctrl_mapping)};
874 if (prev_results.empty())
880 for (
const auto& pr : prev_results)
882 for (
const auto& p : perm)
884 std::vector<Net*> tmp = pr;
885 tmp.insert(tmp.end(), p.begin(), p.end());
886 next_results.push_back(tmp);
891 prev_results = next_results;
892 next_results.clear();
913 std::vector<std::set<hal::Net*>> variable_nets;
918 if (variable_nets_res.is_error())
920 return ERR_APPEND(variable_nets_res.get_error(),
921 "cannot update input output stats: failed to retrieve input variable nets for net " + n->get_name() +
" with ID " + std::to_string(n->get_id()));
924 variable_nets.push_back(variable_nets_res.get());
928 std::map<Net*, Net*> single_input_to_output;
932 if (variable_nets.at(o_idx).size() == 1)
934 const auto single_net = *(variable_nets.at(o_idx).begin());
937 if (single_input_to_output.find(single_net) != single_input_to_output.end())
942 single_input_to_output.insert({single_net, n});
947 std::map<Net*, u32> input_nets_to_influenced_outputs;
950 for (
const auto& input_net : variable_nets.at(o_idx))
957 if (single_input_to_output.find(input_net) != single_input_to_output.end())
972 input_nets_to_influenced_outputs[input_net] += 1;
977 std::map<u32, std::vector<Net*>> influence_count_to_input_nets;
978 for (
const auto& [var, count] : input_nets_to_influenced_outputs)
980 influence_count_to_input_nets[count].push_back(var);
983 u32 max_bin_size = 0;
984 for (
const auto& [_, nets] : influence_count_to_input_nets)
986 if (nets.size() > max_bin_size)
988 max_bin_size = nets.size();
993 if (max_bin_size > 12)
1002 std::map<Net*, u32> output_net_to_input_count;
1006 output_net_to_input_count.insert({n,
u32(variable_nets.at(o_idx).size())});
1009 std::map<u32, std::vector<Net*>> input_count_to_output_nets;
1010 for (
const auto& [n, c] : output_net_to_input_count)
1021 input_count_to_output_nets[c].push_back(n);
1024 new_candidate.m_influence_count_to_input_nets = influence_count_to_input_nets;
1025 new_candidate.m_input_count_to_output_nets = input_count_to_output_nets;
1026 new_candidate.m_single_input_to_output = single_input_to_output;
1028 return OK({new_candidate});
1034 std::vector<FunctionalCandidate> new_candidates;
1038 return OK(std::vector<FunctionalCandidate>());
1042 std::sort(single_input_outputs.begin(), single_input_outputs.end());
1047 new_candidate.m_permuted_single_pairs = single_input_outputs;
1049 new_candidates.push_back(new_candidate);
1050 }
while (std::next_permutation(single_input_outputs.begin(), single_input_outputs.end()));
1052 return OK(new_candidates);
1058 std::vector<FunctionalCandidate> new_candidates;
1061 u32 input_count = 0;
1064 input_count += nets.size();
1081 u32 max_variables = 0;
1084 if (nets.size() > max_variables)
1086 max_variables = nets.size();
1093 bool reached_maximum_variable_count =
false;
1094 std::vector<std::vector<Net*>> operands;
1097 const auto& [count, nets] = *it;
1098 if (nets.size() == max_variables)
1100 reached_maximum_variable_count =
true;
1103 const u32 max_idx = reached_maximum_variable_count ? nets.size() : max_variables;
1104 for (
u32 idx = 0; idx < max_idx; idx++)
1106 if (operands.size() <= idx)
1108 operands.push_back({});
1111 if (idx >= nets.size())
1113 operands.at(idx).push_back(candidate.
m_gates.front()->get_netlist()->get_gnd_nets().front());
1117 operands.at(idx).push_back(nets.at(idx));
1126 bool is_valid = (operands.size() >= 2) && (operands.size() <= candidate.
m_max_operands);
1130 for (
const auto& op : operands)
1132 u32 non_const_nets = 0;
1133 for (
const auto&
net : op)
1135 if (!(
net->is_gnd_net() ||
net->is_vcc_net()))
1141 if (non_const_nets < 2)
1161 new_candidate.m_operands = operands;
1163 new_candidates.push_back(new_candidate);
1172 std::vector<std::vector<Net*>> operands;
1176 const auto& [count, nets] = *it;
1177 for (
u32 idx = 0; idx < nets.size(); idx++)
1182 return OK(std::vector<FunctionalCandidate>());
1185 if (operands.size() <= idx)
1187 operands.push_back({});
1190 operands.at(idx).push_back(nets.at(idx));
1194 bool is_valid = (operands.size() >= 2) && (operands.size() <= candidate.
m_max_operands);
1197 return OK(std::vector<FunctionalCandidate>());
1203 for (
u32 op_idx = 0; op_idx < operands.size(); op_idx++)
1205 auto val = (op_idx == 0) ? in_net : candidate.
m_gates.front()->get_netlist()->get_gnd_nets().front();
1206 operands.at(op_idx).insert(operands.at(op_idx).begin(), val);
1212 for (
const auto& op : operands)
1214 u32 non_const_nets = 0;
1215 for (
const auto&
net : op)
1217 if (!(
net->is_gnd_net() ||
net->is_vcc_net()))
1223 if (non_const_nets < 2)
1225 return OK(std::vector<FunctionalCandidate>());
1230 new_candidate.m_operands = operands;
1232 new_candidates.push_back(new_candidate);
1238 for (
const auto& nets : reorderings)
1241 if (nets.empty() || nets.size() == 1)
1247 new_candidate.m_operands.push_back({});
1250 new_candidate.m_operands.front().push_back(in_net);
1253 for (
const auto& n : nets)
1255 new_candidate.m_operands.front().push_back(n);
1258 new_candidates.push_back(new_candidate);
1279 for (
const auto& nets : reorderings)
1287 bool found_missmatch =
false;
1292 found_missmatch =
true;
1297 if (found_missmatch)
1303 new_candidate.m_operands.push_back({});
1304 for (
const auto& n : nets)
1306 new_candidate.m_operands.front().push_back(n);
1309 new_candidates.push_back(new_candidate);
1317 for (
const auto& nets : reorderings)
1320 if (nets.empty() || nets.size() == 1)
1326 new_candidate.m_operands.push_back({});
1329 new_candidate.m_operands.front().push_back(in_net);
1332 for (
const auto& n : nets)
1334 new_candidate.m_operands.front().push_back(n);
1337 if (new_candidate.m_operands.front().size() >= new_candidate.m_output_nets.size())
1342 if (new_candidate.m_ctrl_to_operand_net !=
nullptr)
1344 new_candidate.m_operands.front().push_back(new_candidate.m_ctrl_to_operand_net);
1347 new_candidates.push_back(new_candidate);
1352 for (
const auto& nc : new_candidates)
1354 for (
const auto& net_set : nc.m_operands)
1356 for (
const auto&
net : net_set)
1358 if (
net->is_gnd_net() ||
net->is_vcc_net())
1363 if (
const auto it = std::find(nc.m_input_nets.begin(), nc.m_input_nets.end(),
net); it == nc.m_input_nets.end())
1365 std::cout <<
"ERROR! Found net " <<
net->get_name() <<
" - " <<
net->get_id() <<
" in variable set that is not part of the input nets!" << std::endl;
1371 return OK(new_candidates);
1377 std::vector<FunctionalCandidate> new_candidates;
1380 const std::vector<std::vector<Net*>> reorderings = reorder_overfull_output_bins(ctx, candidate.
m_control_mapping, new_candidate.m_input_count_to_output_nets);
1383 for (
const auto& nets : reorderings)
1391 reordered_candidate.m_output_nets = {nets.rbegin(), nets.rend()};
1393 new_candidates.push_back(reordered_candidate);
1396 return OK(std::move(new_candidates));
1402 std::vector<FunctionalCandidate> new_candidates;
1403 auto new_candidate = candidate;
1407 const auto& [input_net, output_net] = *it;
1408 new_candidate.
m_output_nets.insert(new_candidate.m_output_nets.begin(), output_net);
1413 return OK(std::vector<FunctionalCandidate>());
1416 new_candidates.push_back(new_candidate);
1418 return OK(new_candidates);
1425 std::map<std::string, BooleanFunction::Value> zero_eval_mapping;
1432 zero_eval_mapping.insert({var_name, val});
1436 zero_eval_mapping.insert({var_name, BooleanFunction::Value::ZERO});
1441 u32 non_zero_count = 0;
1444 const auto eval_res = ctx.
evaluate(o_net, {}, zero_eval_mapping);
1445 if (eval_res.is_error())
1447 return ERR_APPEND(eval_res.get_error(),
"cannot check for early abort: failed to evaluate Boolean function");
1450 if (eval_res.get().front() != BooleanFunction::Value::ZERO)
1455 if (non_zero_count != 0)
1465 std::map<std::string, BooleanFunction::Value> zero_eval_mapping;
1472 zero_eval_mapping.insert({var_name, val});
1476 zero_eval_mapping.insert({var_name, BooleanFunction::Value::ZERO});
1480 u32 non_zero_count = 0;
1483 const auto eval_res = ctx.
evaluate(o_net, {}, zero_eval_mapping);
1484 if (eval_res.is_error())
1486 return ERR_APPEND(eval_res.get_error(),
"cannot check for early abort: failed to evaluate Boolean function");
1489 if (eval_res.get().front() != BooleanFunction::Value::ZERO)
1494 if (non_zero_count != 0)
1505 return OK({candidate});
1515 return OK({candidate});
1520 std::vector<std::vector<std::vector<Net*>>> generate_operand_permutations(
const std::vector<std::vector<Net*>>& operands,
const u32 bit_position)
1522 std::vector<Net*> sign_bit_signals;
1523 std::vector<u32> op_indices;
1525 for (
u32 op_idx = 0; op_idx < operands.size(); op_idx++)
1527 const auto& op = operands.at(op_idx);
1528 if (bit_position < op.size())
1530 sign_bit_signals.push_back(op.at(bit_position));
1531 op_indices.push_back(op_idx);
1535 if (op_indices.size() == 1)
1540 std::vector<std::vector<std::vector<Net*>>> permuted_operands;
1544 std::vector<std::vector<Net*>> ops = operands;
1546 for (
u32 i = 0; i < op_indices.size(); i++)
1548 const auto op_idx = op_indices.at(i);
1550 ops.at(op_idx).at(bit_position) = sign_bit_signals.at(i);
1553 permuted_operands.push_back(ops);
1555 }
while (std::next_permutation(op_indices.begin(), op_indices.end()));
1560 return permuted_operands;
1566 std::vector<Net*> sign_extend_operand(
const std::vector<Net*>& operand,
const u32 new_size, Net* sign_net =
nullptr)
1568 std::vector<Net*> new_operand;
1570 auto sn = sign_net ==
nullptr ? operand.back() : sign_net;
1572 for (
u32 idx = 0; idx < new_size; idx++)
1574 if (idx < operand.size())
1576 new_operand.push_back(operand.at(idx));
1580 new_operand.push_back(sn);
1587 std::vector<Net*> zero_extend_operand(
const std::vector<Net*>& operand,
const u32 new_size,
const Netlist* nl)
1589 std::vector<Net*> new_operand;
1591 for (
u32 idx = 0; idx < new_size; idx++)
1593 if (idx < operand.size())
1595 new_operand.push_back(operand.at(idx));
1599 new_operand.push_back(nl->get_gnd_nets().front());
1606 std::vector<Net*> apply_extension(
const std::vector<Net*>& op,
const u32 size,
const u32 extension_type, Net* sign_net,
const Netlist* nl)
1608 std::vector<Net*> new_op = op;
1610 switch (extension_type)
1614 new_op = zero_extend_operand(new_op,
size, nl);
1618 new_op = sign_extend_operand(new_op,
size);
1622 new_op = sign_extend_operand(new_op,
size - 1, sign_net);
1623 new_op = zero_extend_operand(new_op,
size, nl);
1626 if ((op.size() ==
size) && (op.back() == sign_net))
1632 new_op = zero_extend_operand(new_op,
size, nl);
1643 std::vector<FunctionalCandidate> new_candidates;
1645 std::set<u32> sign_bit_positions;
1648 sign_bit_positions.insert(op.size() - 1);
1651 std::vector<std::vector<std::vector<Net*>>> permuted_operands = {candidate.
m_operands};
1653 for (
const auto& sbp : sign_bit_positions)
1655 std::vector<std::vector<std::vector<Net*>>> new_permuted_operands;
1656 for (
const auto& permuted_op : permuted_operands)
1658 const auto new_temp = generate_operand_permutations(permuted_op, sbp);
1659 new_permuted_operands.insert(new_permuted_operands.end(), new_temp.begin(), new_temp.end());
1661 permuted_operands = new_permuted_operands;
1664 for (
const auto& op_set : permuted_operands)
1667 permuted_candidate.m_operands = op_set;
1668 new_candidates.push_back(permuted_candidate);
1671 return OK(new_candidates);
1676 std::vector<std::vector<u32>> combinations_with_repetittions(
const std::vector<u32>& v,
const std::vector<u32>& stack,
const u32 k)
1683 std::vector<std::vector<u32>> result;
1684 for (
u32 i = 0; i < v.size(); i++)
1686 auto new_stack = stack;
1687 new_stack.push_back(v.at(i));
1689 const auto new_combinations = combinations_with_repetittions(v, new_stack, k - 1);
1690 result.insert(result.end(), new_combinations.begin(), new_combinations.end());
1700 std::vector<FunctionalCandidate> new_candidates;
1702 std::vector<u32> possible_extensions;
1706 possible_extensions = {0, 1, 2};
1712 possible_extensions = {0, 1, 2};
1716 possible_extensions = {0, 1};
1720 possible_extensions = {};
1725 possible_extensions = {0, 1, 2};
1728 std::vector<std::vector<u32>> extension_sets;
1733 extension_sets = combinations_with_repetittions(possible_extensions, {}, candidate.
m_operands.size());
1737 for (
const auto& pe : possible_extensions)
1739 extension_sets.push_back(std::vector<u32>(candidate.
m_operands.size(), pe));
1743 if (extension_sets.empty())
1746 return OK({new_candidate});
1749 std::set<u32> operand_lengths;
1752 operand_lengths.insert(op.size());
1757 const std::set<u32> possible_output_sizes = {
1763 for (
const auto& ex_s : extension_sets)
1765 for (
const auto& out_size : possible_output_sizes)
1768 for (
u32 op_idx = 0; op_idx < new_candidate.m_operands.size(); op_idx++)
1774 auto sign_net = candidate.
m_operands.front().back();
1775 new_candidate.m_operands.at(op_idx) = apply_extension(new_candidate.m_operands.at(op_idx), out_size, ex_s.at(op_idx), sign_net, ctx.
m_netlist);
1779 auto sign_net = new_candidate.m_operands.at(op_idx).back();
1780 new_candidate.m_operands.at(op_idx) = apply_extension(new_candidate.m_operands.at(op_idx), out_size, ex_s.at(op_idx), sign_net, ctx.
m_netlist);
1785 bool is_unique =
true;
1786 for (
const auto& nc : new_candidates)
1788 if (nc.m_operands == new_candidate.m_operands)
1797 new_candidates.push_back(new_candidate);
1802 return OK(new_candidates);
1808 std::vector<FunctionalCandidate> new_candidates;
1809 new_candidates.emplace_back(candidate);
1812 if (candidate.
m_output_nets.size() != extended_output_nets.size())
1814 const u32 difference = extended_output_nets.size() - candidate.
m_output_nets.size();
1815 const u32 threshold = 3;
1816 if (difference <= threshold)
1819 new_candidate.m_output_nets = extended_output_nets;
1821 new_candidates.push_back(std::move(new_candidate));
1825 return OK(new_candidates);
1833 std::vector<FunctionalCandidate> new_candidates;
1839 new_candidates.emplace_back(new_candidate);
1846 if (filtered_output_nets.size() == 1)
1849 new_candidates.push_back(new_candidate);
1853 return OK(new_candidates);
1859 std::vector<FunctionalCandidate> new_candidates;
1866 new_candidate.
m_operands.front().push_back(n);
1869 new_candidates.emplace_back(new_candidate);
1871 return OK(new_candidates);
1880 for (
const auto& n : shift_vals)
1886 const u32 n_abs = abs(n);
1887 if (n_abs < candidate.
m_operands.at(0).size())
1890 std::vector<Net*> new_operand;
1891 for (
u32 idx = 0; idx < new_operands.at(0).
size() - n_abs; idx++)
1893 new_operand.push_back(new_operands.at(0).at(idx + n_abs));
1895 new_operands.push_back(new_operand);
1901 std::vector<Net*> new_operand;
1902 for (
u32 i = 0; i < (
u32)n; i++)
1904 new_operand.push_back(candidate.
m_gates.front()->get_netlist()->get_gnd_nets().front());
1906 for (
const auto&
net : new_operands.at(0))
1908 new_operand.push_back(
net);
1910 new_operands.push_back(new_operand);
1915 new_candidate.m_operands = new_operands;
1917 return new_candidate;
1924 std::vector<FunctionalCandidate> new_candidates;
1943 static const std::map<std::vector<std::vector<u32>>, std::vector<std::vector<i32>>> finger_print_library = {{{{0, 4, 5}, {1, 6}, {2, 7}}, {{-5, -4}}},
1944 {{{0, 3, 5}, {1, 4, 6}, {2, 7}}, {{-5, -3}}},
1945 {{{0, 2, 5}, {1, 3, 6}, {4, 7}}, {{-5, -2}}},
1946 {{{0, 1, 5}, {2, 6}, {3, 7}}, {{-5, -1}}},
1947 {{{0, 5}, {1, 6}, {2, 7}}, {{-5}, {-5, 1}, {-5, 2}, {-5, 3}, {-5, 4}, {-5, 5}}},
1948 {{{0, 3, 4}, {1, 5}, {2, 6}}, {{-4, -3}}},
1949 {{{0, 2, 4}, {1, 3, 5}, {6}}, {{-4, -2}}},
1950 {{{0, 1, 4}, {2, 5}, {3, 6}}, {{-4, -1}}},
1951 {{{0, 4}, {1, 5}, {2, 6}}, {{-4}, {-4, 1}, {-4, 2}, {-4, 3}, {-4, 4}, {-4, 5}}},
1952 {{{0, 2, 3}, {1, 4}, {5}}, {{-3, -2}}},
1953 {{{0, 1, 3}, {2, 4}, {5}}, {{-3, -1}}},
1954 {{{0, 3}, {1, 4}, {2, 5}}, {{-3}, {-3, 1}, {-3, 2}, {-3, 3}, {-3, 4}, {-3, 5}}},
1955 {{{0, 1, 2}, {3}, {4}}, {{-2, -1}}},
1956 {{{0, 2}, {1, 3}, {4}}, {{-2}, {-2, 1}, {-2, 2}, {-2, 3}, {-2, 4}, {-2, 5}}},
1957 {{{0, 1}, {2}, {3}}, {{-1}, {-1, 1}, {-1, 2}, {-1, 3}, {-1, 4}, {-1, 5}}},
1959 {{{0}, {1, 2}, {3}}, {{2}, {2, 3}, {2, 4}, {2, 5}}},
1960 {{{0}, {1, 3}, {2, 4}}, {{3}, {3, 4}, {3, 5}}},
1961 {{{0}, {1, 4}, {2, 5}}, {{4}, {4, 5}}},
1962 {{{0}, {1, 5}, {2, 6}}, {{5}}}};
1965 std::vector<std::set<hal::Net*>> variable_nets;
1970 if (variable_nets_res.is_error())
1972 return ERR_APPEND(variable_nets_res.get_error(),
1973 "cannot update input output stats: failed to retrieve input variable nets for net " + n->get_name() +
" with ID " + std::to_string(n->get_id()));
1976 variable_nets.push_back(variable_nets_res.get());
1980 std::map<Net*, u32> input_nets_to_influenced_outputs;
1983 if (variable_nets.size() <= 1)
1988 for (
const auto& input_net : variable_nets.at(o_idx))
1990 input_nets_to_influenced_outputs[input_net] += 1;
1995 std::map<u32, std::vector<Net*>> influence_count_to_input_nets;
1996 for (
const auto& [var, count] : input_nets_to_influenced_outputs)
1998 influence_count_to_input_nets[count].push_back(var);
2001 if (influence_count_to_input_nets.size() < 3)
2003 return OK(new_candidates);
2008 std::vector<std::vector<u32>> finger_print;
2009 auto rit = influence_count_to_input_nets.rbegin();
2010 for (
u32 i = 0; i < 3; i++, rit++)
2012 const auto& [cnt, nets] = *rit;
2014 std::vector<u32> net_indices;
2015 for (
const auto& n : nets)
2017 const auto& op = candidate.
m_operands.front();
2018 const auto f_it = std::find(op.begin(), op.end(), n);
2019 if (f_it == op.end())
2024 const u32 index = f_it - op.begin();
2025 net_indices.push_back(
index);
2028 std::sort(net_indices.begin(), net_indices.end());
2029 finger_print.push_back(net_indices);
2053 if (
const auto fpl_it = finger_print_library.find(finger_print); fpl_it != finger_print_library.end())
2055 for (
const auto& offsets : fpl_it->second)
2058 new_candidate_nm.add_additional_data(
"OPERAND_SHIFTS",
utils::join(
", ", offsets));
2059 new_candidates.push_back(new_candidate_nm);
2063 return OK(new_candidates);
2070 std::vector<FunctionalCandidate> new_candidates;
2077 static const std::vector<std::vector<i32>> all_possible_offsets = {{1}, {2}, {3}, {-2}, {-3}};
2079 for (
const auto& offsets : all_possible_offsets)
2082 new_candidate_nm.add_additional_data(
"OPERAND_SHIFTS",
utils::join(
", ", offsets));
2083 new_candidates.push_back(new_candidate_nm);
2086 return OK(new_candidates);
2090 u32 max_control_signal,
2093 const std::vector<std::vector<Gate*>>& registers)
2096 std::vector<FunctionalCandidate> candidates;
2101 switch (candidate_type)
2137 new_candidate.m_operands = reordered_operands;
2138 return OK({fc, new_candidate});
2159 new_candidate.m_operands = reordered_operands;
2160 return OK({fc, new_candidate});
2232 return ERR(
"no preprocessing available for candidate type" +
enum_to_string(candidate_type));
2238 std::cout <<
"------------------------" << std::endl;
2239 std::cout <<
"Building candidates for carry " << gates.front()->get_name() <<
" and type: " << candidate_type << std::endl;
2240 std::cout <<
"------------------------" << std::endl;
2243 for (
u32 op_idx = 0; op_idx < operations.size(); op_idx++)
2246 std::cout <<
"------------------------" << std::endl;
2247 std::cout <<
"Excecuting operation " << sc->
m_gates.front()->get_name() <<
" / " << sc->
m_gates.front()->get_id() <<
": " << op_idx << std::endl;
2248 std::cout <<
"------------------------" << std::endl;
2250 std::vector<FunctionalCandidate> new_candidates;
2251 for (
const auto& current_candidate : candidates)
2253 auto resulting_candidates_res = operations.at(op_idx)(ctx, current_candidate);
2254 if (resulting_candidates_res.is_error())
2256 return ERR_APPEND(resulting_candidates_res.get_error(), (
"failed functional candidate creation in operation with index " + std::to_string(op_idx)));
2258 auto resulting_candidates = resulting_candidates_res.get();
2260 for (
auto& rc : resulting_candidates)
2262 new_candidates.push_back(rc);
2267 std::cout <<
"------------------------" << std::endl;
2268 std::cout <<
"New Candidates: " << sc->
m_gates.front()->get_name() <<
" / " << sc->
m_gates.front()->get_id() <<
": " << new_candidates.size() << std::endl;
2269 std::cout <<
"------------------------" << std::endl;
2272 candidates = new_candidates;
2274 if (candidates.empty())
2281 std::cout <<
"------------------------" << std::endl;
2282 std::cout <<
"Candidates for type " << sc->
m_gates.front()->get_name() <<
" / " << sc->
m_gates.front()->get_id() <<
": " << candidate_type << std::endl;
2283 std::cout <<
"Total Candidates: " << candidates.size() << std::endl;
2284 std::cout <<
"------------------------" << std::endl;
2287 return OK(candidates);
This file contains the definition of the BaseCandidate class, which represents a base candidate in th...
This file contains the enumeration and constants for the candidate types used in the module identific...
bool has_constant_value(const std::vector< Value > &value) const
Value
represents the type of the node
static Result< Net * > get_net_from(const Netlist *netlist, const BooleanFunction &var)
std::string get_boolean_variable_name() const
Represents a functional candidate derived from structural candidates.
static hal::Result< std::vector< FunctionalCandidate > > discard_equal_candidate(CandidateContext &ctx, const FunctionalCandidate &candidate)
Discard equal candidates based on their number of input signals.
static hal::Result< std::vector< FunctionalCandidate > > create_input_extension_variants(CandidateContext &ctx, const FunctionalCandidate &candidate)
Create input extension variants for an adder, subtractor, or counter.
std::vector< Gate * > m_gates
std::vector< std::pair< Net *, Net * > > m_permuted_single_pairs
std::map< Net *, Net * > m_single_input_to_output
std::vector< Net * > m_output_nets
static hal::Result< std::vector< FunctionalCandidate > > build_input_operand(CandidateContext &ctx, const FunctionalCandidate &candidate)
Build an input operand for a functional candidate by including all external input signals of the cand...
static hal::Result< std::vector< FunctionalCandidate > > add_single_input_signals(CandidateContext &ctx, const FunctionalCandidate &candidate)
Add single input signals for an adder, subtractor, or counter.
static hal::Result< std::vector< FunctionalCandidate > > add_selected_shifted_operand(CandidateContext &ctx, const FunctionalCandidate &candidate)
Add shifted operands to the functional candidate based on its input output stats.
static hal::Result< std::vector< FunctionalCandidate > > trim_to_single_output_net(CandidateContext &ctx, const FunctionalCandidate &candidate)
Trim a functional candidate to a single output net.
std::map< u32, std::vector< Net * > > m_influence_count_to_input_nets
static hal::Result< std::vector< FunctionalCandidate > > add_all_shifted_operand(CandidateContext &ctx, const FunctionalCandidate &candidate)
Add all possible variations of possible shifted operands to the functional candidate.
static hal::Result< std::vector< FunctionalCandidate > > realize_control_signals(CandidateContext &ctx, const FunctionalCandidate &candidate)
Realize control signals for an adder, subtractor, or counter by setting the control signals to concre...
static hal::Result< std::vector< FunctionalCandidate > > permute_single_input_signals(CandidateContext &ctx, const FunctionalCandidate &candidate)
Permute single input signals for an adder, subtractor, or counter.
static hal::Result< std::vector< FunctionalCandidate > > create_sign_bit_variants(CandidateContext &ctx, const FunctionalCandidate &candidate)
Create sign bit variants for an adder, subtractor, or counter.
std::vector< Net * > m_input_nets
static hal::Result< std::vector< FunctionalCandidate > > check_output_size(CandidateContext &ctx, const FunctionalCandidate &candidate)
Check the output size of a functional candidate.
static hal::Result< std::vector< FunctionalCandidate > > find_control_signals(CandidateContext &ctx, const FunctionalCandidate &candidate)
Find control signals for a functional candidate.
static hal::Result< std::vector< FunctionalCandidate > > update_input_output_stats(CandidateContext &ctx, const FunctionalCandidate &candidate)
Update input and output statistics for an adder, subtractor, or counter.
static hal::Result< std::vector< FunctionalCandidate > > create_sign_extension_variants(CandidateContext &ctx, const FunctionalCandidate &candidate)
Create sign extension variants of a functional candidate.
std::vector< Net * > m_control_signals
static hal::Result< std::vector< FunctionalCandidate > > create_candidates(StructuralCandidate *sc, u32 max_control_signal, CandidateContext &ctx, module_identification::CandidateType candidate_type, const std::vector< std::vector< Gate * >> ®isters)
Create functional candidates from a structural candidate.
static hal::Result< std::vector< FunctionalCandidate > > identify_control_signals(CandidateContext &ctx, const FunctionalCandidate &candidate)
Identify control signals for an adder, subtractor, or counter.
std::map< u32, std::vector< Net * > > m_input_count_to_output_nets
static hal::Result< std::vector< FunctionalCandidate > > order_input_operands(CandidateContext &ctx, const FunctionalCandidate &candidate)
Order input operands for a functional candidate.
static FunctionalCandidate add_n_shifted_operands(const FunctionalCandidate &candidate, const std::vector< i32 > &shift_vals)
Add n shifted operands for constant multiplication.
static hal::Result< std::vector< FunctionalCandidate > > order_output_signals(CandidateContext &ctx, const FunctionalCandidate &candidate)
Order output signals for an adder, subtractor, or counter.
std::map< Net *, BooleanFunction::Value > m_control_mapping
static hal::Result< std::vector< FunctionalCandidate > > build_input_operands(CandidateContext &ctx, const FunctionalCandidate &candidate)
Build input operands for an adder, subtractor, or counter.
static hal::Result< std::vector< FunctionalCandidate > > early_abort(CandidateContext &ctx, const FunctionalCandidate &candidate)
Early abort process for a functional candidate.
u32 m_max_control_signals
std::vector< Net * > m_sign_nets
module_identification::CandidateType m_candidate_type
static hal::Result< std::vector< FunctionalCandidate > > create_operand_control_variations(CandidateContext &ctx, const FunctionalCandidate &candidate)
Create operand control variations for absolute functional candidates.
FunctionalCandidate(StructuralCandidate *sc, u32 max_control_signal, module_identification::CandidateType candidate_type)
Constructor for FunctionalCandidate.
Net * m_ctrl_to_operand_net
static hal::Result< std::vector< FunctionalCandidate > > create_output_net_variant(CandidateContext &ctx, const FunctionalCandidate &candidate)
Create output net variants for an adder, subtractor, or counter.
std::vector< std::vector< Net * > > m_operands
A class representing a structural candidate for module identification.
std::vector< Gate * > m_gates
Vector of gates that form the structural candidate.
This file contains the class and functions for handling functional candidates within the module ident...
#define log_error(channel,...)
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
void remove(std::filesystem::path file_path)
bool has_constant_value(const z3::expr &e, const u64 &val)
std::vector< std::vector< Net * > > reorder_commutative_operands(const std::vector< std::vector< Net * >> &operands, const std::vector< std::vector< Gate * >> ®isters, const u32 permute_start_index=0)
Reorder commutative operands based on a permutation cache.
const std::map< CandidateType, u32 > candidate_type_max_operands
A mapping of candidate types to their maximum number of operands.
CandidateType
Enumeration of the different candidate types for module identification.
@ addition
Addition operation.
@ addition_offset
Addition operation with a constant offset.
@ equal
Equality comparison.
@ less_equal
Less-than-or-equal comparison.
@ counter
Counter operation.
@ value_check
Value check against a constant operation.
@ absolute
Absolute value operation.
@ constant_multiplication
Constant multiplication operation.
@ 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 join(const std::string &joiner, const Iterator &begin, const Iterator &end, const Transform &transform)
std::vector< T > split(const T &s, const char delim, bool obey_brackets=false)
std::string enum_to_string(T e)
This file contains helper functions for module identification in the HAL framework.
QTextStream & bin(QTextStream &stream)
This struct manages the context of a candidate during module identification, including caches for all...
hal::Result< const std::set< Net * > > get_variable_nets(const Net *n, const std::map< Net *, BooleanFunction::Value > &ctrl_mapping)
Retrieves the variable nets for a given net and control mapping.
hal::Result< std::unordered_map< std::string, double > > get_boolean_influence(const Net *n, const std::map< Net *, BooleanFunction::Value > &ctrl_mapping)
Retrieves the boolean influence for a given net and control mapping.
const Netlist * m_netlist
The netlist associated with the candidate context.
hal::Result< const BooleanFunction > get_boolean_function(const Net *n, const std::map< Net *, BooleanFunction::Value > &ctrl_mapping)
Retrieves a boolean function for a given net and control mapping.
hal::Result< std::vector< BooleanFunction::Value > > evaluate(const Net *n, const std::map< Net *, BooleanFunction::Value > &ctrl_mapping, const std::map< std::string, BooleanFunction::Value > &eval_mapping)
Evaluates the boolean function for a given net, control mapping, and evaluation mapping.
hal::Result< const std::set< std::string > > get_variable_names(const Net *n, const std::map< Net *, BooleanFunction::Value > &ctrl_mapping)
Retrieves the variable names for a given net and control mapping.
The result of a module identification run containing the candidates.