10 namespace module_identification
14 BooleanFunction create_operand(
const std::vector<Net*>& op,
const u32 size = 0)
18 log_error(
"module_identification",
"nets are empty, cannot create bit vector");
19 return BooleanFunction();
23 const auto op_size = (
size == 0) ? op.size() :
size;
24 for (
u32 i = 0; i < op_size; i++)
26 const auto net = op.at(i);
28 BooleanFunction new_bit_bf;
29 if (
net->is_gnd_net())
33 else if (
net->is_vcc_net())
39 new_bit_bf = BooleanFunctionNetDecorator(*net).get_boolean_variable();
44 bf = std::move(new_bit_bf);
49 if (bf_res.is_error())
51 log_error(
"module_identification",
"{}", bf_res.get_error().get());
59 Result<std::pair<bool, u64>> do_probe_testing(
const std::vector<BooleanFunction>& actual_funcitons,
const BooleanFunction& expected_function,
const u32 num_tests)
61 const auto start_probe = std::chrono::steady_clock::now();
63 std::srand(std::time(
nullptr));
64 for (
u32 i = 0; i < num_tests; i++)
66 std::unordered_map<std::string, std::vector<BooleanFunction::Value>> test_mapping;
68 auto variables = expected_function.get_variable_names();
69 u64 mapping = std::rand();
71 for (
auto current_variable : variables)
73 std::vector<BooleanFunction::Value> current_input;
75 test_mapping[current_variable] = current_input;
80 auto expected_result = expected_function.evaluate(test_mapping);
81 if (expected_result.is_error())
83 return ERR_APPEND(expected_result.get_error(),
"failed to evalute boolean function");
86 for (
u32 func_idx = 0; func_idx < expected_function.size(); func_idx++)
88 const auto& actual_funciton = actual_funcitons.at(func_idx);
89 auto actual_result = actual_funciton.evaluate(test_mapping);
90 if (actual_result.is_error())
92 return ERR_APPEND(actual_result.get_error(),
"failed to evalute boolean function");
95 if (actual_result.get()[0] != expected_result.get()[func_idx])
97 return OK({
false, std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_probe).count()});
102 return OK({
true, std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_probe).count()});
106 smt_check(
const std::vector<BooleanFunction>& actual_funcitons, BooleanFunction&& expected_function,
const u32 num_probes, std::map<std::string, std::map<std::string, u64>>& timings)
110 auto probe_res = do_probe_testing(actual_funcitons, expected_function, num_probes);
111 if (probe_res.is_error())
113 return ERR_APPEND(probe_res.get_error(),
"failed selective testing on boolean function");
115 const auto [probe, probe_duration] = probe_res.get();
117 timings[
"Probe"][
"Duration"] += probe_duration;
120 timings[
"Probe"][
"#Successful"] += 1;
124 timings[
"Probe"][
"#Failed"] += 1;
128 const auto start_solver_timing = std::chrono::steady_clock::now();
130 auto config = SMT::QueryConfig();
131 auto solver = SMT::Solver();
133 #ifdef BITWUZLA_LIBRARY
136 config = config.with_solver(s_type).with_call(s_call).without_model_generation();
181 auto actual_funciton = actual_funcitons.at(0).clone();
182 for (
u32 i = 1; i < expected_function.size(); i++)
184 auto bf_res =
BooleanFunction::Concat(actual_funcitons.at(i).clone(), std::move(actual_funciton), actual_funciton.size() + 1);
185 if (bf_res.is_error())
187 return ERR_APPEND(bf_res.get_error(),
"cannot compelete equal check: failed to concatenate output functions");
189 actual_funciton = bf_res.get();
193 auto bf_eq_res =
BooleanFunction::Eq(std::move(actual_funciton), std::move(expected_function), 1);
194 if (bf_eq_res.is_error())
196 return ERR_APPEND(bf_eq_res.get_error(),
"failed to concatenate boolean functions");
198 auto bf_eq = bf_eq_res.get();
202 if (bf_neq_res.is_error())
204 return ERR_APPEND(bf_eq_res.get_error(),
"failed to concatenate boolean functions");
206 auto bf_neq = bf_neq_res.get();
208 auto solver_result_res = solver.with_constraint(SMT::Constraint(std::move(bf_neq))).query(config);
209 if (solver_result_res.is_error())
211 return ERR_APPEND(solver_result_res.get_error(),
"failed solver check for module identification utils");
213 auto solver_result = solver_result_res.get();
215 const u64 solver_duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_solver_timing).count();
217 if (solver_result.is_unsat())
219 timings[
"Unsat_Solver_Query"][
"Duration"] += solver_duration;
220 timings[
"Unsat_Solver_Query"][
"#Amount"] += 1;
223 if (solver_result.is_sat())
225 timings[
"Sat_Solver_Query"][
"Duration"] += solver_duration;
226 timings[
"Sat_Solver_Query"][
"#Amount"] += 1;
229 if (solver_result.is_unknown())
231 timings[
"Unknown_Solver_Query"][
"#Amount"] += 1;
232 timings[
"Unknown_Solver_Query"][
"Duration"] += solver_duration;
235 return OK({solver_result.is_unsat()});
242 Result<VerifiedCandidate> create_verified_candidate(
const FunctionalCandidate& fc,
const CandidateType&
type,
const BooleanFunction& operation)
244 return OK(VerifiedCandidate(fc.m_operands,
246 fc.m_control_signals,
247 {fc.m_control_mapping},
248 {{fc.m_control_mapping, operation.clone()}},
251 fc.m_additional_data,
259 Result<std::pair<bool, BooleanFunction>> check_count_n(
const std::vector<BooleanFunction>& output_functions,
260 BooleanFunction&& bf_i,
261 const std::vector<BooleanFunction::Value>& n_vec,
262 std::map<std::string, std::map<std::string, u64>>& timings)
266 auto increment_vec = n_vec;
268 while (bf_i.size() > increment_vec.size())
271 const auto msb = n_vec.back();
272 increment_vec.push_back(msb);
278 if (bf_add_res.is_error())
280 return ERR_APPEND(bf_add_res.get_error(),
"cannot check for counter: failed to build addition Boolean function");
282 auto bf_add = bf_add_res.get();
285 if (bf_add.size() > output_functions.size())
290 output_functions.
size());
292 if (bf_slice_res.is_error())
294 return ERR_APPEND(bf_add_res.get_error(),
"cannot check for counter: failed to slice Boolean function");
296 bf_add = bf_slice_res.get();
299 auto smt_check_res = smt_check(output_functions, bf_add.clone(), 8, timings);
300 if (smt_check_res.is_error())
302 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
305 return OK({smt_check_res.get(), bf_add});
308 Result<std::pair<bool, BooleanFunction>>
309 check_negation(
const std::vector<BooleanFunction>& output_functions, BooleanFunction&& bf_i, std::map<std::string, std::map<std::string, u64>>& timings)
315 if (bf_inv_res.is_error())
317 return ERR_APPEND(bf_inv_res.get_error(),
"failed to concatenate boolean functions");
319 auto bf_inv = bf_inv_res.get();
323 if (bf_add_res.is_error())
325 return ERR_APPEND(bf_add_res.get_error(),
"failed to concatenate boolean functions");
327 auto bf_add = bf_add_res.get();
343 if (output_functions.size() < bf_add.size())
345 return OK({
false, BooleanFunction()});
347 auto smt_check_res = smt_check(output_functions, bf_add.clone(), 2, timings);
348 if (smt_check_res.is_error())
350 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
353 return OK({smt_check_res.get(), bf_add});
356 Result<VerifiedCandidate> check_sum_helper(FunctionalCandidate& fc,
357 const std::vector<BooleanFunction>& output_functions,
358 const std::vector<std::vector<Net*>>& operands,
359 const std::vector<bool>& subtract,
361 std::map<std::string, std::map<std::string, u64>>& timings)
363 u32 first_op_idx = 0;
364 for (
u32 op_idx = 0; op_idx < operands.size(); op_idx++)
366 if (!subtract.at(op_idx))
368 first_op_idx = op_idx;
373 auto bf_sum = create_operand(operands.at(first_op_idx));
376 for (
u32 op_idx = 0; op_idx < operands.size(); op_idx++)
378 if (op_idx == first_op_idx)
383 auto bf_op = create_operand(operands.at(op_idx));
385 subtract.at(op_idx) ?
BooleanFunction::Sub(std::move(bf_sum), std::move(bf_op), bf_sum.size()) : BooleanFunction::
Add(
std::move(bf_sum),
std::move(bf_op), bf_sum.
size());
386 if (bf_add_res.is_error())
388 return ERR(bf_add_res.get_error().get());
390 bf_sum = bf_add_res.get();
393 auto smt_check_res = smt_check(output_functions, bf_sum.clone(), 2, timings);
394 if (smt_check_res.is_error())
396 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
399 if (smt_check_res.get())
401 const auto op_str = (subtract == std::vector<bool>{
true,
false}) ?
"[-, +]" : (subtract == std::vector<bool>{
true,
false}) ? (
"[+, -]") :
"?";
402 fc.add_additional_data(
"SUM OPERATIONS", op_str);
403 return create_verified_candidate(fc,
type, bf_sum);
406 return OK(VerifiedCandidate());
413 auto bf_a = create_operand(fc.
m_operands.at(0));
414 auto bf_b = create_operand(fc.
m_operands.at(1));
418 if (bf_a.is_empty() || bf_b.is_empty())
420 return ERR(
"bit vectors of boolean function could not be generated, aborting...");
423 if (bf_leq_res.is_error())
425 return ERR_APPEND(bf_leq_res.get_error(),
"failed to concatenate boolean functions");
427 auto bf_leq = bf_leq_res.get();
429 auto leq_check_res = smt_check(output_functions, bf_leq.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"LESS_EQUAL"]);
430 if (leq_check_res.is_error())
432 return ERR_APPEND(leq_check_res.get_error(),
"failed equal check for less equal candidate");
435 if (leq_check_res.get())
443 if (bf_lt_res.is_error())
445 return ERR_APPEND(bf_lt_res.get_error(),
"failed to concatenate boolean functions");
447 auto bf_lt = bf_lt_res.get();
449 auto lt_check_res = smt_check(output_functions, bf_lt.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"LESS_THAN"]);
450 if (lt_check_res.is_error())
452 return ERR_APPEND(lt_check_res.get_error(),
"failed equal check for less than candidate");
455 if (lt_check_res.get())
463 if (bf_sleq_res.is_error())
465 return ERR_APPEND(bf_sleq_res.get_error(),
"failed to concatenate boolean functions");
467 auto bf_sleq = bf_sleq_res.get();
469 auto sleq_check_res = smt_check(output_functions, bf_sleq.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"SIGNED_LESS_EQUAL"]);
470 if (sleq_check_res.is_error())
472 return ERR_APPEND(sleq_check_res.get_error(),
"failed equal check for signed less equal candidate");
475 if (sleq_check_res.get())
483 if (bf_slt_res.is_error())
485 return ERR_APPEND(bf_slt_res.get_error(),
"failed to concatenate boolean functions");
487 auto bf_slt = bf_slt_res.get();
489 auto slt_check_res = smt_check(output_functions, bf_slt.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"SIGNED_LESS_THAN"]);
490 if (slt_check_res.is_error())
492 return ERR_APPEND(slt_check_res.get_error(),
"failed equal check for signed less than candidate");
495 if (slt_check_res.get())
505 auto bf_sum = create_operand(fc.
m_operands.at(0));
508 for (
u32 op_idx = 1; op_idx < fc.
m_operands.size(); op_idx++)
510 auto bf_op = create_operand(fc.
m_operands.at(op_idx));
512 if (bf_add_res.is_error())
514 return ERR_APPEND(bf_add_res.get_error(),
"failed to concatenate boolean functions");
516 bf_sum = bf_add_res.get();
519 auto smt_check_res = smt_check(output_functions, bf_sum.clone(), 8, fc.
m_timings[
"SMT_CHECK"][
"ADD"]);
520 if (smt_check_res.is_error())
522 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
525 if (smt_check_res.get())
527 return create_verified_candidate(fc, CandidateType::addition, bf_sum);
535 auto bf_sum = create_operand(fc.
m_operands.at(0));
538 for (
u32 op_idx = 1; op_idx < fc.
m_operands.size(); op_idx++)
540 auto bf_op = create_operand(fc.
m_operands.at(op_idx));
542 if (bf_add_res.is_error())
544 return ERR_APPEND(bf_add_res.get_error(),
"failed to concatenate boolean functions");
546 bf_sum = bf_add_res.get();
550 auto bf_o = output_functions.at(0);
551 for (
u32 i = 1; i < output_functions.size(); i++)
554 if (bf_res.is_error())
556 return ERR_APPEND(bf_res.get_error(),
"cannot check for counter: failed to build conactenated output function");
561 std::map<std::string, BooleanFunction> eval_mapping;
562 for (
const auto& var : bf_o.get_variable_names())
567 const auto substitution_res = bf_o.substitute(eval_mapping);
568 if (substitution_res.is_error())
570 return ERR_APPEND(substitution_res.get_error(),
"cannot check for constant offset: failed to evaluate output functions for zero input");
572 const auto eval = substitution_res.get().simplify_local();
574 const auto increment_res = eval.get_constant_value();
575 if (increment_res.is_error())
577 return ERR_APPEND(increment_res.get_error(),
"cannot check for constant offset: failed to get constant value of substituted boolean function");
579 const auto increment_vec = increment_res.get();
582 if (!increment.has_constant_value(0))
584 auto bf_sum_plus_offset =
BooleanFunction::Add(bf_sum.clone(), increment.clone(), bf_sum.size());
585 if (bf_sum_plus_offset.is_error())
587 return ERR_APPEND(bf_sum_plus_offset.get_error(),
"failed to build sum boolean functions");
589 bf_sum = bf_sum_plus_offset.get();
597 auto smt_check_res = smt_check(output_functions, bf_sum.clone(), 8, fc.
m_timings[
"SMT_CHECK"][
"ADD"]);
598 if (smt_check_res.is_error())
600 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
603 if (smt_check_res.get())
605 return create_verified_candidate(fc, CandidateType::addition_offset, bf_sum);
618 std::vector<VerifiedCandidate> possible_results;
620 for (
u32 pos = 1; pos < output_functions.size(); pos++)
623 auto bf_a = create_operand(fc.
m_operands.at(0), pos + 1);
624 auto bf_b = create_operand(fc.
m_operands.at(1), pos + 1);
629 if (bf_sum_res.is_error())
631 return ERR_APPEND(bf_sum_res.get_error(),
"failed to concatenate boolean functions");
633 auto bf_sum = bf_sum_res.get();
635 auto smt_check_res = smt_check(output_functions, bf_sum.clone(), 8, fc.
m_timings[
"SMT_CHECK"][
"SUB"]);
636 if (smt_check_res.is_error())
638 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
641 if (smt_check_res.get())
643 if (pos == (output_functions.size() - 1))
645 possible_results.push_back(create_verified_candidate(fc, CandidateType::subtraction, bf_sum).get());
654 auto tmp = std::move(fc.
m_operands.at(0).at(pos - 1));
659 bf_a = create_operand(fc.
m_operands.at(0), pos + 1);
660 bf_b = create_operand(fc.
m_operands.at(1), pos + 1);
664 if (bf_swapped_sum_res.is_error())
666 return ERR_APPEND(bf_swapped_sum_res.get_error(),
"failed to concatenate boolean functions");
668 auto bf_swapped_sum = bf_swapped_sum_res.get();
670 auto smt_check_res_2 = smt_check(output_functions, bf_swapped_sum.clone(), 8, fc.
m_timings[
"SMT_CHECK"][
"SUB"]);
671 if (smt_check_res_2.is_error())
673 return ERR_APPEND(smt_check_res_2.get_error(),
"failed equal check for constant multiplication candidate");
676 if (smt_check_res_2.get())
678 if (pos == (output_functions.size() - 1))
680 possible_results.push_back(create_verified_candidate(fc, CandidateType::subtraction, bf_swapped_sum).get());
688 if (!possible_results.empty())
698 std::sort(possible_results.begin(), possible_results.end(), [®isters](
const auto& vc1,
const auto& vc2) {
699 u32 op_reg_score_1 = 0;
700 u32 op_reg_score_2 = 0;
702 for (const auto& op : vc1.m_operands)
704 op_reg_score_1 += find_neighboring_registers(op, registers).size();
707 for (
const auto& op : vc2.m_operands)
709 op_reg_score_2 += find_neighboring_registers(op, registers).size();
712 return op_reg_score_2 < op_reg_score_1;
715 return OK(possible_results.front());
722 std::map<u32, u32> input_var_count;
723 for (
u32 idx = 0; idx < output_functions.size(); idx++)
725 const auto& func = output_functions.at(idx);
726 input_var_count.insert({idx, func.get_variable_names().
size()});
729 std::map<u32, std::vector<u32>> count_to_indices;
730 for (
const auto& [idx, c] : input_var_count)
732 count_to_indices[c].push_back(idx);
735 u32 overfull_bins = 0;
736 for (
const auto& [c, indices] : count_to_indices)
738 if (indices.size() > 1)
745 if (overfull_bins != 1)
751 if (count_to_indices.rbegin()->second.size() == 1)
755 if (count_to_indices.size() < 2)
760 std::vector<u32> next_bit_candidates = count_to_indices.rbegin()->second;
762 std::vector<BooleanFunction> ordered_output_functions;
763 std::vector<Net*> ordered_output_nets;
764 for (
const auto& [_c, indices] : count_to_indices)
766 if (indices.size() != 1)
771 ordered_output_functions.push_back(output_functions.at(indices.front()).clone());
772 ordered_output_nets.push_back(fc.
m_output_nets.at(indices.front()));
776 auto bf_sum = create_operand(fc.
m_operands.at(0));
777 for (
u32 op_idx = 1; op_idx < fc.
m_operands.size(); op_idx++)
779 auto bf_op = create_operand(fc.
m_operands.at(op_idx));
781 if (bf_add_res.is_error())
783 return ERR_APPEND(bf_add_res.get_error(),
"failed to concatenate boolean functions");
785 bf_sum = bf_add_res.get();
788 const auto initial_size = bf_sum.size();
789 const auto initial_end_index = ordered_output_functions.size();
790 auto initial_i0 = BooleanFunction::Index(0, initial_size);
791 auto initial_i1 = BooleanFunction::Index(initial_end_index - 1, initial_size);
792 auto initial_bf_slice_res = BooleanFunction::Slice(bf_sum.clone(), std::move(initial_i0), std::move(initial_i1), initial_end_index);
793 if (initial_bf_slice_res.is_error())
795 return ERR_APPEND(initial_bf_slice_res.get_error(),
"cannot check addition slice: failed to build sliced boolean function");
797 auto initial_bf_slice = initial_bf_slice_res.get();
799 auto initial_smt_check_res = smt_check(output_functions, std::move(initial_bf_slice), 2, fc.
m_timings[
"SMT_CHECK"][
"ADD_SLICED"]);
800 if (initial_smt_check_res.is_error())
802 return ERR_APPEND(initial_smt_check_res.get_error(),
"failed equal check for sliced add candidate");
805 if (!initial_smt_check_res.get())
810 while (!next_bit_candidates.empty())
812 bool found_valid_idx =
false;
814 for (
const auto& idx : next_bit_candidates)
816 auto tmp = ordered_output_functions;
817 tmp.push_back(output_functions.at(idx).clone());
819 const auto size = bf_sum.size();
820 const auto end_index = tmp.size();
821 auto i0 = BooleanFunction::Index(0,
size);
822 auto i1 = BooleanFunction::Index(end_index - 1,
size);
823 auto bf_slice_res = BooleanFunction::Slice(bf_sum.clone(), std::move(i0), std::move(i1), end_index);
824 if (bf_slice_res.is_error())
826 return ERR_APPEND(bf_slice_res.get_error(),
"cannot check addition slice: failed to build sliced boolean function");
828 auto bf_slice = bf_slice_res.get();
830 auto smt_check_res = smt_check(output_functions, bf_slice.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"ADD_SLICED"]);
831 if (smt_check_res.is_error())
833 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
836 if (smt_check_res.get())
838 found_valid_idx =
true;
841 if (next_bit_candidates.size() == 1)
843 return create_verified_candidate(fc, CandidateType::addition, bf_slice);
851 if (!found_valid_idx)
856 next_bit_candidates.erase(
std::remove(next_bit_candidates.begin(), next_bit_candidates.end(), valid_idx), next_bit_candidates.end());
858 ordered_output_functions.push_back(output_functions.at(valid_idx).clone());
859 ordered_output_nets.push_back(fc.
m_output_nets.at(valid_idx));
873 if (check_add_res.is_error())
875 return check_add_res;
877 if (check_add_res.get().is_verified())
879 return check_add_res;
882 auto check_sub_res =
check_sub(fc, output_functions, registers);
883 if (check_sub_res.is_error())
885 return check_sub_res;
887 if (check_sub_res.get().is_verified())
889 return check_sub_res;
914 if (check_add_res.is_error())
916 return check_add_res;
918 if (check_add_res.get().is_verified())
920 return check_add_res;
928 auto bf_i = create_operand(fc.
m_operands.at(0));
933 config.with_model_generation();
935 #ifdef BITWUZLA_LIBRARY
936 auto s_type = SMT::SolverType::Bitwuzla;
937 auto s_call = SMT::SolverCall::Library;
938 config.with_solver(s_type).with_call(s_call);
941 s = s.with_constraint(
SMT::Constraint(output_functions.front().clone()));
943 auto first_result_res = s.query(config);
944 if (first_result_res.is_error())
946 return ERR_APPEND(first_result_res.get_error(),
"failed smt run on boolean function");
948 auto first_result = first_result_res.get();
950 if (!first_result.is_sat())
955 const auto eval_res = first_result.model.value().evaluate(bf_i);
956 if (eval_res.is_error())
958 return ERR_APPEND(eval_res.get_error(),
"failed to evaluate boolean functions");
960 auto bf_m = eval_res.get();
964 if (bf_eq_res.is_error())
966 return ERR_APPEND(bf_eq_res.get_error(),
"failed to concatenate boolean functions");
968 auto bf_eq = bf_eq_res.get();
972 if (bf_neq_res.is_error())
974 return ERR_APPEND(bf_neq_res.get_error(),
"failed to concatenate boolean functions");
976 auto bf_neq = bf_neq_res.get();
980 auto second_result_res = s.query(config);
981 if (second_result_res.is_error())
983 return ERR_APPEND(second_result_res.get_error(),
"failed smt run on boolean function");
985 auto second_result = second_result_res.get();
987 if (!second_result.is_unsat())
1013 return create_verified_candidate(fc, CandidateType::value_check,
BooleanFunction());
1023 auto bf_sum = create_operand(fc.
m_operands.at(0));
1027 for (
u32 op_idx = 1; op_idx < fc.
m_operands.size(); op_idx++)
1029 auto bf_op = create_operand(fc.
m_operands.at(op_idx));
1031 if (bf_add_res.is_error())
1033 return ERR_APPEND(bf_add_res.get_error(),
"failed to add boolean functions");
1035 bf_sum = bf_add_res.get();
1038 auto smt_check_res = smt_check(output_functions, bf_sum.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"CONST_MULT"]);
1039 if (smt_check_res.is_error())
1041 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
1044 if (smt_check_res.get())
1046 return create_verified_candidate(fc, CandidateType::constant_multiplication, bf_sum);
1061 auto sum_check_res_1 = check_sum_helper(fc, output_functions, fc.
m_operands, {false, true}, CandidateType::constant_multiplication, fc.
m_timings[
"SMT_CHECK"][
"CONST_MULT"]);
1062 if (sum_check_res_1.is_error())
1064 return ERR_APPEND(sum_check_res_1.get_error(),
"failed to execute sum_check_helper in first variant");
1066 if (
const auto c = sum_check_res_1.get(); c.is_verified())
1071 auto sum_check_res_2 = check_sum_helper(fc, output_functions, fc.
m_operands, {true, false}, CandidateType::constant_multiplication, fc.
m_timings[
"SMT_CHECK"][
"CONST_MULT"]);
1072 if (sum_check_res_2.is_error())
1074 return ERR_APPEND(sum_check_res_2.get_error(),
"failed to execute sum_check_helper in first variant");
1076 if (
const auto c = sum_check_res_2.get(); c.is_verified())
1092 auto bf_sum = create_operand(fc.
m_operands.at(0));
1096 for (
u32 op_idx = 1; op_idx < fc.
m_operands.size(); op_idx++)
1098 auto bf_op = create_operand(fc.
m_operands.at(op_idx));
1100 if (bf_add_res.is_error())
1102 return ERR_APPEND(bf_add_res.get_error(),
"failed to add boolean functions");
1104 bf_sum = bf_add_res.get();
1107 auto bf_o = output_functions.at(0);
1108 for (
u32 i = 1; i < output_functions.size(); i++)
1110 auto bf_res = BooleanFunction::Concat(output_functions.at(i).clone(), std::move(bf_o), bf_o.size() + 1);
1111 if (bf_res.is_error())
1113 return ERR_APPEND(bf_res.get_error(),
"cannot check for counter: failed to build conactenated output function");
1115 bf_o = bf_res.get();
1119 std::set<std::string> input_operands = bf_o.get_variable_names();
1120 std::map<std::string, BooleanFunction> eval_mapping;
1121 for (
const auto& operand : input_operands)
1123 eval_mapping.insert({operand, BooleanFunction::Const(0, 1)});
1126 const auto substitution_res = bf_o.substitute(eval_mapping);
1127 if (substitution_res.is_error())
1129 return ERR_APPEND(substitution_res.get_error(),
"cannot check for constant offset: failed to evaluate output functions for zero input");
1131 const auto eval = substitution_res.get().simplify_local();
1133 const auto increment_res = eval.get_constant_value();
1134 if (increment_res.is_error())
1136 return ERR_APPEND(increment_res.get_error(),
"cannot check for constant offset: failed to get constant value of substituted boolean function");
1138 const auto increment_vec = increment_res.get();
1139 const auto increment = BooleanFunction::Const(increment_vec);
1141 if (!increment.has_constant_value(0))
1145 if (bf_inc_res.is_error())
1147 return ERR_APPEND(bf_inc_res.get_error(),
"failed to add increment to boolean function");
1149 bf_sum = bf_inc_res.get();
1157 auto smt_check_res = smt_check(output_functions, bf_sum.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"CONST_MULT"]);
1158 if (smt_check_res.is_error())
1160 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
1163 if (smt_check_res.get())
1165 return create_verified_candidate(fc, CandidateType::constant_multiplication_offset, bf_sum);
1175 auto bf_i = create_operand(fc.
m_operands.at(0));
1176 auto bf_o = output_functions.at(0);
1177 for (
u32 i = 1; i < output_functions.size(); i++)
1179 auto bf_res = BooleanFunction::Concat(output_functions.at(i).clone(), std::move(bf_o), bf_o.size() + 1);
1180 if (bf_res.is_error())
1182 return ERR_APPEND(bf_res.get_error(),
"cannot check for counter: failed to build conactenated output function");
1184 bf_o = bf_res.get();
1188 std::set<std::string> input_operands = bf_i.get_variable_names();
1189 std::map<std::string, BooleanFunction> eval_mapping;
1190 for (
const auto& operand : input_operands)
1192 eval_mapping.insert({operand, BooleanFunction::Const(0, 1)});
1195 const auto substitution_res = bf_o.substitute(eval_mapping);
1196 if (substitution_res.is_error())
1198 return ERR_APPEND(substitution_res.get_error(),
"cannot check for counter: failed to evaluate output functions for zero input");
1200 const auto eval = substitution_res.get().simplify_local();
1202 const auto increment_res = eval.get_constant_value();
1203 if (increment_res.is_error())
1205 return ERR_APPEND(increment_res.get_error(),
"cannot check for counter: failed to get constant value of substituted boolean function");
1207 const auto increment_vec = increment_res.get();
1208 const auto increment = BooleanFunction::Const(increment_vec);
1210 auto counter_check_res = check_count_n(output_functions, bf_i.clone(), increment_vec, fc.
m_timings[
"SMT_CHECK"][
"COUNTER"]);
1211 if (counter_check_res.is_error())
1213 return ERR_APPEND(counter_check_res.get_error(),
"failed to run counter check for value: " + increment.to_string());
1215 auto [is_counter, bf_count] = counter_check_res.get();
1219 return create_verified_candidate(fc, CandidateType::counter, bf_count);
1222 auto check_negation_res = check_negation(output_functions, bf_i.clone(), fc.
m_timings[
"SMT_CHECK"][
"NEGATION"]);
1223 if (check_negation_res.is_error())
1225 return ERR_APPEND(check_negation_res.get_error(),
"failed checknegation during check_counter");
1227 auto [is_negation, bf_neg] = check_negation_res.get();
1230 return create_verified_candidate(fc, CandidateType::negation, bf_neg);
1238 auto bf_i = create_operand(fc.
m_operands.at(0));
1243 if (bf_inv_res.is_error())
1245 return ERR_APPEND(bf_inv_res.get_error(),
"failed to concatenate boolean functions");
1247 auto bf_inv = bf_inv_res.get();
1250 auto bf_neg_res =
BooleanFunction::Add(std::move(bf_inv), BooleanFunction::Const(1, bf_inv.size()), bf_inv.size());
1251 if (bf_neg_res.is_error())
1253 return ERR_APPEND(bf_neg_res.get_error(),
"failed to concatenate boolean functions");
1255 auto bf_neg = bf_neg_res.get();
1258 auto bf_a_msb_res = BooleanFunction::Slice(bf_i.clone(), BooleanFunction::Index(bf_i.size() - 1, bf_i.size()), BooleanFunction::Index(bf_i.size() - 1, bf_i.size()), 1);
1259 if (bf_a_msb_res.is_error())
1261 return ERR_APPEND(bf_a_msb_res.get_error(),
"failed to concatenate boolean functions");
1263 auto bf_a_msb = bf_a_msb_res.get();
1266 auto bf_a_abs_res =
BooleanFunction::Ite(bf_a_msb.clone(), bf_neg.clone(), bf_i.clone(), bf_i.size());
1267 if (bf_a_abs_res.is_error())
1269 return ERR_APPEND(bf_a_abs_res.get_error(),
"failed to concatenate boolean functions");
1271 auto bf_a_abs = bf_a_abs_res.get();
1273 auto smt_check_res = smt_check(output_functions, bf_a_abs.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"ABSOLUTE"]);
1274 if (smt_check_res.is_error())
1276 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
1279 if (smt_check_res.get())
1281 return create_verified_candidate(fc, CandidateType::absolute, bf_a_abs);
1290 std::unordered_map<std::string, BooleanFunction::Value> input_mapping;
1291 std::set<std::string> vars = output_functions[0].get_variable_names();
1294 std::unordered_map<Net*, std::string> net_mapping;
1295 std::vector<Net*> input_nets;
1296 for (std::string cur_name : vars)
1298 Net*
net = BooleanFunctionNetDecorator::get_net_from(nl, cur_name).get();
1299 input_nets.push_back(
net);
1300 net_mapping.insert(std::make_pair<Net*, std::string>(std::move(
net), std::move(cur_name)));
1304 for (std::string cur_var_name : vars)
1306 input_mapping.insert(std::make_pair<std::string, BooleanFunction::Value>(std::move(cur_var_name), BooleanFunction::Value::ZERO));
1308 std::vector<std::vector<Net*>> operands;
1309 operands.push_back(std::vector<Net*>());
1310 operands.push_back(std::vector<Net*>());
1312 std::vector<Net*> unused_inputs;
1313 unused_inputs.insert(unused_inputs.end(), input_nets.begin(), input_nets.end());
1314 for (
Net* cur_input : input_nets)
1316 if (std::find(unused_inputs.begin(), unused_inputs.end(), cur_input) == unused_inputs.end())
1321 auto firstit = std::find(unused_inputs.begin(), unused_inputs.end(), cur_input);
1322 unused_inputs.erase(firstit);
1324 operands.at(0).push_back(cur_input);
1326 input_mapping[net_mapping[cur_input]] = BooleanFunction::Value::ONE;
1327 bool found_b =
false;
1328 for (
Net* cur_b_candidate : unused_inputs)
1330 input_mapping[net_mapping[cur_b_candidate]] = BooleanFunction::Value::ONE;
1334 return ERR_APPEND(res.get_error(),
"failed to evaluate boolean function");
1337 if (res.get() == BooleanFunction::Value::ONE)
1342 operands.at(1).push_back(cur_b_candidate);
1343 auto it = std::find(unused_inputs.begin(), unused_inputs.end(), cur_b_candidate);
1344 unused_inputs.erase(it);
1349 input_mapping[net_mapping[cur_b_candidate]] = BooleanFunction::Value::ZERO;
1352 if (found_b ==
false)
1361 auto bf_a = create_operand(operands.at(0));
1362 auto bf_b = create_operand(operands.at(1));
1364 if (bf_a.is_empty() || bf_b.is_empty())
1366 return ERR(
"bit vectors of boolean function could not be generated, aborting...");
1372 if (bf_eq_res.is_error())
1374 return ERR_APPEND(bf_eq_res.get_error(),
"failed to concatenate boolean functions");
1376 auto bf_eq = bf_eq_res.get();
1378 auto smt_check_res = smt_check(output_functions, bf_eq.clone(), 2, fc.
m_timings[
"SMT_CHECK"][
"EQUAL"]);
1379 if (smt_check_res.is_error())
1381 return ERR_APPEND(smt_check_res.get_error(),
"failed equal check for constant multiplication candidate");
1384 if (smt_check_res.get())
1386 return create_verified_candidate(fc, CandidateType::equal, bf_eq);
1392 Result<VerifiedCandidate> FunctionalCandidate::check(
const std::vector<BooleanFunction>& output_functions,
const std::vector<std::vector<Gate*>>& registers)
1394 switch (m_candidate_type)
1396 case module_identification::CandidateType::equal:
1399 case module_identification::CandidateType::less_equal:
1400 return check_leq(*
this, output_functions);
1402 case module_identification::CandidateType::addition:
1405 case module_identification::CandidateType::addition_offset:
1408 case module_identification::CandidateType::absolute:
1411 case module_identification::CandidateType::value_check:
1414 case module_identification::CandidateType::constant_multiplication:
1417 case module_identification::CandidateType::constant_multiplication_offset:
1420 case module_identification::CandidateType::counter:
1426 return ERR(
"No check function implemented for type" +
enum_to_string(m_candidate_type));
This file contains the enumeration and constants for the candidate types used in the module identific...
static Result< BooleanFunction > Slt(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Eq(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Add(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Ule(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Sub(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Concat(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Ult(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static BooleanFunction Index(u16 index, u16 size)
static Result< BooleanFunction > Sle(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Slice(BooleanFunction &&p0, BooleanFunction &&p1, BooleanFunction &&p2, u16 size)
Value
represents the type of the node
static BooleanFunction Const(const BooleanFunction::Value &value)
static Result< BooleanFunction > Not(BooleanFunction &&p0, u16 size)
Represents a functional candidate derived from structural candidates.
std::vector< Net * > m_output_nets
std::map< std::string, std::map< std::string, std::map< std::string, std::map< std::string, u64 > > > > m_timings
std::vector< Net * > m_input_nets
void add_additional_data(std::string key, std::string value)
Add additional data to the functional candidate.
std::vector< std::vector< Net * > > m_operands
Represents a verified candidate for module identification.
This file contains the class and functions for handling functional candidates within the module ident...
#define log_error(channel,...)
#define ERR_APPEND(prev_error, message)
std::vector< BooleanFunction::Value > Ite(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1, const std::vector< BooleanFunction::Value > &p2)
std::vector< BooleanFunction::Value > Add(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
std::vector< BooleanFunction::Value > Not(const std::vector< BooleanFunction::Value > &p)
std::vector< BooleanFunction::Value > Eq(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
void remove(std::filesystem::path file_path)
Result< VerifiedCandidate > check_equal(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
Result< VerifiedCandidate > check_leq(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
Result< VerifiedCandidate > check_add_sub_offset(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions, const std::vector< std::vector< Gate * >> ®isters)
Result< VerifiedCandidate > check_absolute(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
Result< VerifiedCandidate > check_sub(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions, const std::vector< std::vector< Gate * >> ®isters)
Result< VerifiedCandidate > check_sliced_add(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
Result< VerifiedCandidate > check_constant_multiplication(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
Result< VerifiedCandidate > check_addition(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
Result< VerifiedCandidate > check_add_sub(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions, const std::vector< std::vector< Gate * >> ®isters)
Result< VerifiedCandidate > check_constant_multiplication_offset(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
Result< VerifiedCandidate > check_value_check(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
CandidateType
Enumeration of the different candidate types for module identification.
@ signed_less_equal
Signed less-than-or-equal comparison.
@ less_equal
Less-than-or-equal comparison.
@ less_than
Less-than comparison.
@ signed_less_than
Signed less-than comparison.
Result< VerifiedCandidate > check_counter(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
Result< VerifiedCandidate > check_addition_offset(FunctionalCandidate &fc, const std::vector< BooleanFunction > &output_functions)
std::string enum_to_string(T e)
This file contains helper functions for module identification in the HAL framework.
The result of a module identification run containing the candidates.