9 #include "z3_utils/subgraph_function_generation.h" 
   10 #include "z3_utils/z3_utils.h" 
   17     namespace boolean_influence
 
   21             const std::string probabilistic_function = R
"( 
   26 static unsigned long x=123456789, y=362436069, z=521288629; 
   29 unsigned long xorshf96(void) {           
   46 const int input_size = <INPUT_SIZE>; 
   48 void build_values(bool* values) { 
   49     for (int i = 0; i < input_size; i++) { 
   50         bool random_value = xorshf96() % 2; 
   51         values[i] = random_value; 
   57 int main(int argc, char *argv[]) { 
   58     unsigned long long b     = strtoull(argv[1], 0, 10); 
   59     unsigned long long num   = strtoull(argv[2], 0, 10); 
   60     unsigned long long count = 0; 
   62     bool values[input_size]; 
   63     for (unsigned long long i = 0; i < num; i++) { 
   67         bool r1 = func(values); 
   70         bool r2 = func(values); 
   77     printf("%lld\n", count); 
   82             const std::string deterministic_function = R
"( 
   89 const int input_size = <INPUT_SIZE>; 
   91 void build_values(bool* values, unsigned long long val) { 
   92     for (int idx = 0; idx < input_size; idx++) { 
   93         values[idx] = (val >> idx) & 0x1; 
   99 int main(int argc, char *argv[]) { 
  100     unsigned long long b     = strtoull(argv[1], 0, 10); 
  101     unsigned long long count = 0; 
  103     bool values[input_size]; 
  104     for (unsigned long long i = 0; i < (1 << input_size); i++) { 
  105         build_values(values, i); 
  108         bool r1 = func(values); 
  111         bool r2 = func(values); 
  118     printf("%lld\n", count); 
  124             unsigned long xorshf96(
u64& x, 
u64& y, 
u64& z)
 
  140             Result<std::unordered_map<std::string, double>> get_boolean_influence_internal(
const z3::expr& expr, 
const u32 num_evaluations, 
const bool deterministic)
 
  142                 const auto to_replacement_var = [](
const u32 var_idx) -> std::string { 
return "var_" + std::to_string(var_idx); };
 
  144                 const auto extract_index = [](
const std::string& var) -> Result<u32> {
 
  147                         return ERR(
"variable " + var + 
" does not start with prefix 'var_', so we cannot extract an index.");
 
  152                         return OK(
u32(std::stoul(var.substr(4))));
 
  154                     catch (
const std::invalid_argument& e)
 
  156                         return ERR(
"could not get index from string '" + var + 
"': " + e.what());
 
  158                     catch (
const std::out_of_range& e)
 
  160                         return ERR(
"could not get index from string '" + var + 
"': " + e.what());
 
  164                 const auto to_original_var = [extract_index](
const std::string& replacement_var, 
const std::vector<std::string>& original_vars) -> Result<std::string> {
 
  165                     const auto var_idx_res = extract_index(replacement_var);
 
  166                     if (var_idx_res.is_error())
 
  168                         return ERR_APPEND(var_idx_res.get_error(), 
"unable to reconstruct original variable from replacement variable" + replacement_var + 
": failed to extract index.");
 
  170                     const auto var_idx = var_idx_res.get();
 
  172                     if (var_idx > original_vars.size())
 
  174                         return ERR(
"unable to reconstruct original variable from replacement variable" + replacement_var + 
": extracted index " + std::to_string(var_idx)
 
  175                                    + 
" is bigger than the size of the original vars (" + std::to_string(original_vars.size()) + 
").");
 
  178                     return OK(original_vars.at(var_idx));
 
  181                 std::unordered_map<std::string, double> influences;
 
  185                 std::vector<std::string> input_vars = 
utils::to_vector(z3_utils::get_variable_names(expr));
 
  187                 if (input_vars.empty())
 
  189                     return OK(influences);
 
  192                 if (deterministic && input_vars.size() > 16)
 
  194                     return ERR(
"unable to generate Boolean influence: Cannot evaluate Boolean function deterministically for more than 16 variables but got " + std::to_string(input_vars.size()));
 
  197                 std::vector<std::string> replacement_vars;
 
  199                 z3::expr_vector from_vec(expr.ctx());
 
  200                 z3::expr_vector to_vec(expr.ctx());
 
  202                 for (
u32 var_idx = 0; var_idx < input_vars.size(); var_idx++)
 
  204                     replacement_vars.push_back(to_replacement_var(var_idx));
 
  206                     z3::expr 
from = expr.ctx().bv_const(input_vars.at(var_idx).c_str(), 1);
 
  207                     z3::expr 
to   = expr.ctx().bv_const(to_replacement_var(var_idx).c_str(), 1);
 
  209                     from_vec.push_back(
from);
 
  210                     to_vec.push_back(
to);
 
  213                 auto replaced_e = expr;
 
  214                 replaced_e      = replaced_e.substitute(from_vec, to_vec);
 
  218                 if (directory_res.is_error())
 
  220                     return ERR_APPEND(directory_res.get_error(), 
"unable to generate Boolean influence: could not create temporary directory");
 
  222                 const std::filesystem::path directory = directory_res.get();
 
  223                 std::filesystem::create_directory(directory);
 
  224                 const std::filesystem::path file_path = directory / 
"boolean_func.cpp";
 
  226                 std::string cpp_program = deterministic ? deterministic_function : probabilistic_function;
 
  227                 cpp_program             = 
utils::replace(cpp_program, std::string(
"<C_FUNCTION>"), z3_utils::to_cpp(replaced_e));
 
  228                 cpp_program             = 
utils::replace(cpp_program, std::string(
"<INPUT_SIZE>"), std::to_string(replacement_vars.size()));
 
  231                 std::ofstream ofs(file_path);
 
  234                     return ERR(
"unable to generate Boolean influence: could not open file " + file_path.string() + 
".");
 
  241                 const std::string program_name    = file_path.string().substr(0, file_path.string().size() - 4);
 
  242                 const std::string compile_command = 
"g++ -o " + program_name + 
" " + file_path.string() + 
" -O3";
 
  243                 int res                           = system(compile_command.c_str());
 
  247                 for (
const auto& var : replacement_vars)
 
  249                     const auto idx_res = extract_index(var);
 
  250                     if (idx_res.is_error())
 
  252                         return ERR_APPEND(idx_res.get_error(), 
"unable to generate Boolean influence: failed to extract index from variable " + var + 
".");
 
  254                     const auto idx = idx_res.get();
 
  256                     const std::string num_evaluations_str = deterministic ? 
"" : std::to_string(num_evaluations);
 
  258                     const std::string run_command = program_name + 
" " + std::to_string(idx) + 
" " + num_evaluations_str + 
" 2>&1";
 
  260                     std::array<char, 128> buffer;
 
  263                     FILE* pipe = popen(run_command.c_str(), 
"r");
 
  266                         return ERR(
"unable to generate Boolean influence: error during execution of compiled boolean program");
 
  268                     while (fgets(buffer.data(), 128, pipe) != NULL)
 
  270                         result += buffer.data();
 
  275                     const u32 count            = std::stoi(result);
 
  276                     const u32 real_evaluations = deterministic ? (1 << input_vars.size()) : num_evaluations;
 
  277                     double cv                  = (double)(count) / (double)(real_evaluations);
 
  279                     const auto org_var_res = to_original_var(var, input_vars);
 
  280                     if (org_var_res.is_error())
 
  282                         return ERR_APPEND(org_var_res.get_error(), 
"unable to generate Boolean influence: failed to reconstruct original variable from replacement variable " + var + 
".");
 
  284                     const auto org_var = org_var_res.get();
 
  286                     influences.insert({org_var, cv});
 
  294                 return OK(influences);
 
  297             Result<std::map<Net*, double>> get_boolean_influences_of_subcircuit_internal(
const std::vector<Gate*>& gates, 
const Net* start_net, 
const u32 num_evaluations, 
const bool deterministic)
 
  299                 for (
const auto* gate : gates)
 
  303                         return ERR(
"unable to get Boolean influence for net " + start_net->get_name() + 
" with ID " + std::to_string(start_net->get_id()) + 
": sub circuit gates include gate " 
  304                                    + gate->get_name() + 
" with ID " + std::to_string(gate->get_id()) + 
" that is either not a combinational gate or is a VCC / GND gate.");
 
  309                 auto ctx  = z3::context();
 
  310                 auto func = z3::expr(ctx);
 
  314                     const auto func_res = z3_utils::get_subgraph_z3_function(gates, start_net, ctx);
 
  315                     if (func_res.is_error())
 
  318                                           "unable to get Boolean influence for net " + start_net->get_name() + 
" with ID " + std::to_string(start_net->get_id())
 
  319                                               + 
": failed to build subgraph function");
 
  321                     func = func_res.get();
 
  326                     func = ctx.bv_const(BooleanFunctionNetDecorator(*start_net).get_boolean_variable_name().c_str(), 1);
 
  330                 const auto inf_res = get_boolean_influence_internal(func, num_evaluations, deterministic);
 
  331                 if (inf_res.is_error())
 
  334                                       "unable to get Boolean influence for net " + start_net->get_name() + 
" with ID " + std::to_string(start_net->get_id())
 
  335                                           + 
": failed to get boolean influence for net " + start_net->get_name() + 
" with ID " + std::to_string(start_net->get_id()) + 
".");
 
  337                 const std::unordered_map<std::string, double> var_names_to_inf = inf_res.get();
 
  340                 std::map<Net*, double> nets_to_inf;
 
  342                 Netlist* nl = start_net->get_netlist();
 
  343                 for (
const auto& [var_name, 
inf] : var_names_to_inf)
 
  346                     if (net_res.is_error())
 
  349                                           "unable to get Boolean influence for net " + start_net->get_name() + 
" with ID " + std::to_string(start_net->get_id())
 
  350                                               + 
": failed to reconstruct net from variable " + var_name + 
".");
 
  352                     const auto net = net_res.get();
 
  354                     nets_to_inf.insert({
net, 
inf});
 
  357                 return OK(nets_to_inf);
 
  360             Result<std::map<Net*, double>> get_boolean_influences_of_gate_internal(
const Gate* gate, 
const u32 num_evaluations, 
const bool deterministic)
 
  364                     return ERR(
"unable to get Boolean influence for gate " + gate->get_name() + 
" with ID " + std::to_string(gate->get_id()) + 
": can only handle flip-flops but found gate type " 
  365                                + gate->get_type()->get_name() + 
".");
 
  370                 if (d_pins.size() != 1)
 
  372                     return ERR(
"unable to get Boolean influence for gate " + gate->get_name() + 
" with ID " + std::to_string(gate->get_id())
 
  373                                + 
": can only handle flip-flops with exactly one data port, but found " + std::to_string(d_pins.size()) + 
".");
 
  375                 const GatePin* data_pin = d_pins.front();
 
  376                 const Net* data_net     = gate->get_fan_in_net(data_pin);
 
  378                 if (data_net == 
nullptr)
 
  380                     return ERR(
"unable to get Boolean influence for gate " + gate->get_name() + 
" with ID " + std::to_string(gate->get_id()) + 
": failed to find net at data pin " 
  381                                + data_pin->get_name());
 
  385                 const auto function_gates_res = NetlistTraversalDecorator(*(gate->get_netlist())).get_next_combinational_gates(data_net, 
false);
 
  386                 if (function_gates_res.is_error())
 
  388                     return ERR_APPEND(function_gates_res.get_error(),
 
  389                                       "unable to get Boolean influence for gate " + gate->get_name() + 
" with ID " + std::to_string(gate->get_id()) + 
": failed to get combinational fan-in gates.");
 
  394                 const auto inf_res = get_boolean_influences_of_subcircuit_internal(function_gates, data_net, num_evaluations, deterministic);
 
  395                 if (inf_res.is_error())
 
  398                                       "unable to get Boolean influence for gate " + gate->get_name() + 
" with ID " + std::to_string(gate->get_id()) + 
": failed to get Boolean influence for data net " 
  399                                           + data_net->get_name() + 
" with ID " + std::to_string(data_net->get_id()) + 
".");
 
  409             auto ctx         = z3::context();
 
  410             const auto z3_bf = z3_utils::from_bf(bf, ctx);
 
  417             return get_boolean_influence_internal(expr, num_evaluations, 
false);
 
  422             auto ctx         = z3::context();
 
  423             const auto z3_bf = z3_utils::from_bf(bf, ctx);
 
  430             return get_boolean_influence_internal(expr, 0, 
true);
 
  435             return get_boolean_influences_of_subcircuit_internal(gates, start_net, num_evaluations, 
false);
 
  440             return get_boolean_influences_of_gate_internal(gate, num_evaluations, 
false);
 
  445             return get_boolean_influences_of_subcircuit_internal(gates, start_net, 0, 
true);
 
  450             return get_boolean_influences_of_gate_internal(gate, 0, 
true);
 
  455             std::unordered_map<std::string, double> influences;
 
  458             u64 x = 123456789, y = 362436069, z = 521288629;
 
  460             for (
const auto& var : variables)
 
  463                 for (
unsigned long long i = 0; i < num_evaluations; i++)
 
  465                     std::unordered_map<std::string, BooleanFunction::Value> values;
 
  467                     for (
const auto& var_to_set : variables)
 
  469                         if (var == var_to_set)
 
  474                         BooleanFunction::Value random_value = (xorshf96(x, y, z) % 2) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO;
 
  475                         values.insert({var_to_set, random_value});
 
  479                     values[var]      = BooleanFunction::Value::ONE;
 
  480                     const auto res_1 = bf.
evaluate(values);
 
  481                     if (res_1.is_error())
 
  483                         return ERR_APPEND(res_1.get_error(), 
"unable to evaluate boolean function ");
 
  487                     values[var]      = BooleanFunction::Value::ZERO;
 
  488                     const auto res_2 = bf.
evaluate(values);
 
  489                     if (res_2.is_error())
 
  491                         return ERR_APPEND(res_2.get_error(), 
"unable to evaluate boolean function ");
 
  494                     const auto r1 = res_1.get();
 
  495                     const auto r2 = res_2.get();
 
  502                 double cv = (double)(count) / (double)(num_evaluations);
 
  503                 influences.insert({var, cv});
 
  506             return OK(influences);
 
  511             std::unordered_map<std::string, double> influences;
 
  514             auto ctx   = z3::context();
 
  515             auto z3_bf = z3_utils::from_bf(bf, ctx);
 
  517             u64 x = 123456789, y = 362436069, z = 521288629;
 
  519             for (
const auto& var : variables)
 
  521                 const auto var_expr = ctx.bv_const(var.c_str(), 1);
 
  524                 for (
unsigned long long i = 0; i < num_evaluations; i++)
 
  526                     z3::expr_vector from_vec(ctx);
 
  527                     z3::expr_vector to_vec(ctx);
 
  530                     for (
const auto& var_to_set : variables)
 
  532                         if (var == var_to_set)
 
  537                         const auto var_to_set_expr = ctx.bv_const(var_to_set.c_str(), 1);
 
  539                         auto random_value = (xorshf96(x, y, z) % 2) ? ctx.bv_val(1, 1) : ctx.bv_val(0, 1);
 
  541                         from_vec.push_back(var_to_set_expr);
 
  542                         to_vec.push_back(random_value);
 
  545                     auto z3_bf_substitute = z3_bf.substitute(from_vec, to_vec).simplify();
 
  547                     z3::expr_vector from_vec_var(ctx);
 
  548                     z3::expr_vector to_vec_one(ctx);
 
  549                     z3::expr_vector to_vec_zero(ctx);
 
  551                     from_vec_var.push_back(var_expr);
 
  552                     to_vec_one.push_back(ctx.bv_val(1, 1));
 
  553                     to_vec_zero.push_back(ctx.bv_val(0, 1));
 
  556                     const auto res_1 = z3_bf_substitute.substitute(from_vec_var, to_vec_one).simplify();
 
  557                     if (!res_1.is_numeral())
 
  559                         std::cout << res_1 << std::endl;
 
  560                         return ERR(
"cannot determine boolean influence of variabel " + var + 
": failed to simplify to a constant");
 
  564                     const auto res_2 = z3_bf_substitute.substitute(from_vec_var, to_vec_zero).simplify();
 
  565                     if (!res_2.is_numeral())
 
  567                         std::cout << res_2 << std::endl;
 
  568                         return ERR(
"cannot determine boolean influence of variabel " + var + 
": failed to simplify to a constant");
 
  571                     const auto r1 = res_1.get_numeral_uint64();
 
  572                     const auto r2 = res_2.get_numeral_uint64();
 
  579                 double cv = (double)(count) / (double)(num_evaluations);
 
  580                 influences.insert({var, cv});
 
  583             return OK(influences);
 
  588             std::map<u32, Gate*> matrix_id_to_gate;
 
  589             std::map<Gate*, u32> gate_to_matrix_id;
 
  590             std::vector<std::vector<double>> matrix;
 
  592             std::unordered_map<const Net*, std::set<Gate*>>* cache;
 
  594             u32 matrix_gates = 0;
 
  601                 gate_to_matrix_id[gate]         = matrix_gates;
 
  602                 matrix_id_to_gate[matrix_gates] = gate;
 
  606             u32 status_counter = 0;
 
  607             for (
const auto& [
id, gate] : matrix_id_to_gate)
 
  609                 if (status_counter % 100 == 0)
 
  611                     log_info(
"boolean_influence", 
"status {}/{} processed", status_counter, matrix_id_to_gate.size());
 
  614                 std::vector<double> line_of_matrix;
 
  616                 std::set<u32> gates_to_add;
 
  618                 if (next_seq_gates.is_error())
 
  621                                       "unable to generate ff dependency matrix: failed to generate Boolean influence for gate " + gate->get_name() + 
" with ID " + std::to_string(gate->get_id())
 
  622                                           + 
": failed to get next sequential gates.");
 
  624                 for (
const auto& pred_gate : next_seq_gates.get())
 
  626                     gates_to_add.insert(gate_to_matrix_id[pred_gate]);
 
  628                 std::map<Net*, double> boolean_influence_for_gate;
 
  629                 if (with_boolean_influence)
 
  632                     if (inf_res.is_error())
 
  635                                           "unable to generate ff dependency matrix: failed to generate Boolean influence for gate " + gate->get_name() + 
" with ID " + std::to_string(gate->get_id())
 
  638                     boolean_influence_for_gate = inf_res.get();
 
  641                 for (
u32 i = 0; i < matrix_gates; i++)
 
  643                     if (gates_to_add.find(i) != gates_to_add.end())
 
  645                         if (with_boolean_influence)
 
  647                             double influence = 0.0;
 
  649                             Gate* pred_ff = matrix_id_to_gate[i];
 
  653                                 if (boolean_influence_for_gate.find(output_net) != boolean_influence_for_gate.end())
 
  655                                     influence += boolean_influence_for_gate[output_net];
 
  659                             line_of_matrix.push_back(influence);
 
  663                             line_of_matrix.push_back(1.0);
 
  668                         line_of_matrix.push_back(0.0);
 
  671                 matrix.push_back(line_of_matrix);
 
  674             return OK(std::make_pair(matrix_id_to_gate, matrix));
 
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
 
std::set< std::string > get_variable_names() const
 
Result< Value > evaluate(const std::unordered_map< std::string, Value > &inputs) const
 
Value
represents the type of the node
 
static Result< Net * > get_net_from(const Netlist *netlist, const BooleanFunction &var)
 
const std::vector< Net * > & get_fan_out_nets() const
 
const std::vector< Gate * > & get_gates() const
 
Result< std::set< Gate * > > get_next_sequential_gates(const Net *net, bool successors, const std::set< PinType > &forbidden_pins={}, std::unordered_map< const Net *, std::set< Gate * >> *cache=nullptr) const
 
#define log_info(channel,...)
 
#define ERR_APPEND(prev_error, message)
 
Result< std::map< Net *, double > > get_boolean_influences_of_subcircuit(const std::vector< Gate * > &gates, const Net *start_net, const u32 num_evaluations=32000)
 
Result< std::map< Net *, double > > get_boolean_influences_of_gate(const Gate *gate, const u32 num_evaluations=32000)
 
Result< std::unordered_map< std::string, double > > get_boolean_influence_with_z3_expr(const BooleanFunction &bf, const u32 num_evaluations)
 
Result< std::map< Net *, double > > get_boolean_influences_of_subcircuit_deterministic(const std::vector< Gate * > &gates, const Net *start_net)
 
Result< std::unordered_map< std::string, double > > get_boolean_influence_deterministic(const BooleanFunction &bf)
 
Result< std::unordered_map< std::string, double > > get_boolean_influence(const BooleanFunction &bf, const u32 num_evaluations=32000)
 
Result< std::map< Net *, double > > get_boolean_influences_of_gate_deterministic(const Gate *gate)
 
Result< std::pair< std::map< u32, Gate * >, std::vector< std::vector< double > > > > get_ff_dependency_matrix(const Netlist *netlist, bool with_boolean_influence)
 
Result< std::unordered_map< std::string, double > > get_boolean_influence_with_hal_boolean_function_class(const BooleanFunction &bf, const u32 num_evaluations)
 
void remove(std::filesystem::path file_path)
 
CORE_API T replace(const T &str, const T &search, const T &replace)
 
CORE_API bool starts_with(const T &s, const T &start)
 
Result< std::filesystem::path > get_unique_temp_directory(const std::string &prefix, const u32 max_attmeps)
 
CORE_API std::vector< T > to_vector(const Container< T, Args... > &container)