HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
subgraph_function_generation.cpp
Go to the documentation of this file.
2 
8 #include "z3_utils/z3_utils.h"
9 
10 #include <queue>
11 
12 namespace hal
13 {
14  namespace z3_utils
15  {
16  namespace
17  {
18  Result<z3::expr> get_function_of_net(const std::vector<Gate*>& subgraph_gates,
19  const Net* net,
20  z3::context& ctx,
21  std::map<u32, z3::expr>& net_cache,
22  std::map<std::pair<u32, const GatePin*>, BooleanFunction>& gate_cache)
23  {
24  if (const auto it = net_cache.find(net->get_id()); it != net_cache.end())
25  {
26  return OK(it->second);
27  }
28 
29  const std::vector<Endpoint*> sources = net->get_sources();
30 
31  // net is multi driven
32  if (sources.size() > 1)
33  {
34  return ERR("cannot get Boolean z3 function of net " + net->get_name() + " with ID " + std::to_string(net->get_id()) + ": net is multi driven.");
35  }
36 
37  // net has no source
38  if (sources.empty())
39  {
40  z3::expr ret = ctx.bv_const(BooleanFunctionNetDecorator(*net).get_boolean_variable_name().c_str(), 1);
41  net_cache.insert({net->get_id(), ret});
42  return OK(ret);
43  }
44 
45  const Endpoint* src_ep = sources.front();
46 
47  if (src_ep->get_gate() == nullptr)
48  {
49  return ERR("cannot get Boolean z3 function of net " + net->get_name() + " with ID " + std::to_string(net->get_id()) + ": net source is null.");
50  }
51 
52  const Gate* src = src_ep->get_gate();
53 
54  // source is not in subgraph gates
55  if (std::find(subgraph_gates.begin(), subgraph_gates.end(), src) == subgraph_gates.end())
56  {
57  z3::expr ret = ctx.bv_const(BooleanFunctionNetDecorator(*net).get_boolean_variable_name().c_str(), 1);
58  net_cache.insert({net->get_id(), ret});
59  return OK(ret);
60  }
61 
62  BooleanFunction bf;
63  if (const auto it = gate_cache.find({src->get_id(), src_ep->get_pin()}); it == gate_cache.end())
64  {
65  const auto bf_res = src->get_resolved_boolean_function(src_ep->get_pin());
66  if (bf_res.is_error())
67  {
68  return ERR_APPEND(bf_res.get_error(),
69  "cannot get Boolean z3 function of net " + net->get_name() + " with ID " + std::to_string(net->get_id()) + ": failed to get function of gate.");
70  }
71  bf = bf_res.get();
72 
73  gate_cache.insert({{src->get_id(), src_ep->get_pin()}, bf});
74  }
75  else
76  {
77  bf = it->second;
78  }
79 
80  std::map<std::string, z3::expr> input_to_expr;
81 
82  for (const std::string& in_net_str : bf.get_variable_names())
83  {
84  const auto in_net_res = BooleanFunctionNetDecorator::get_net_from(src->get_netlist(), in_net_str);
85  if (in_net_res.is_error())
86  {
87  return ERR_APPEND(in_net_res.get_error(),
88  "cannot get Boolean z3 function of net " + net->get_name() + " with ID " + std::to_string(net->get_id()) + ": failed to reconstruct input net from variable "
89  + in_net_str + ".");
90  }
91  const auto in_net = in_net_res.get();
92 
93  const auto in_bf_res = get_function_of_net(subgraph_gates, in_net, ctx, net_cache, gate_cache);
94  if (in_bf_res.is_error())
95  {
96  // NOTE since this can lead to a deep recursion we do not append the error and instead only propagate it.
97  return in_bf_res;
98  }
99  const auto in_bf = in_bf_res.get();
100 
101  input_to_expr.insert({in_net_str, in_bf});
102  }
103 
104  z3::expr ret = z3_utils::from_bf(bf, ctx, input_to_expr).simplify();
105  net_cache.insert({net->get_id(), ret});
106 
107  return OK(ret);
108  }
109 
110  Result<z3::expr> get_subgraph_z3_function_internal(const std::vector<Gate*>& subgraph_gates,
111  const Net* net,
112  z3::context& ctx,
113  std::map<u32, z3::expr>& net_cache,
114  std::map<std::pair<u32, const GatePin*>, BooleanFunction>& gate_cache)
115  {
116  // check validity of subgraph_gates
117  if (subgraph_gates.empty())
118  {
119  return ERR("could not get subgraph z3 function of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": subgraph contains no gates");
120  }
121  else if (std::any_of(subgraph_gates.begin(), subgraph_gates.end(), [](const Gate* g) { return g == nullptr; }))
122  {
123  return ERR("could not get subgraph z3 function of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": subgraph contains a gate that is a 'nullptr'");
124  }
125  else if (net == nullptr)
126  {
127  return ERR("could not get subgraph z3 function: net is a 'nullptr'");
128  }
129  else if (net->get_num_of_sources() > 1)
130  {
131  return ERR("could not get subgraph z3 function of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": net has more than one source");
132  }
133  else if (net->is_global_input_net())
134  {
135  const auto net_dec = BooleanFunctionNetDecorator(*net);
136  return OK(ctx.bv_const(net_dec.get_boolean_variable_name().c_str(), 1));
137  }
138  else if (net->get_num_of_sources() == 0)
139  {
140  return ERR("could not get subgraph function of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": net has no sources");
141  }
142 
143  return get_function_of_net(subgraph_gates, net, ctx, net_cache, gate_cache);
144  }
145 
146  } // namespace
147 
148  Result<z3::expr> get_subgraph_z3_function(const std::vector<Gate*>& subgraph_gates, const Net* subgraph_output, z3::context& ctx)
149  {
150  std::map<u32, z3::expr> net_cache;
151  std::map<std::pair<u32, const GatePin*>, BooleanFunction> gate_cache;
152 
153  return get_subgraph_z3_function_internal(subgraph_gates, subgraph_output, ctx, net_cache, gate_cache);
154  }
155 
156  Result<std::vector<z3::expr>> get_subgraph_z3_functions(const std::vector<Gate*>& subgraph_gates, const std::vector<Net*>& subgraph_outputs, z3::context& ctx)
157  {
158  std::map<u32, z3::expr> net_cache;
159  std::map<std::pair<u32, const GatePin*>, BooleanFunction> gate_cache;
160 
161  std::vector<z3::expr> results;
162 
163  for (const auto& net : subgraph_outputs)
164  {
165  const auto res = get_subgraph_z3_function_internal(subgraph_gates, net, ctx, net_cache, gate_cache);
166  if (res.is_error())
167  {
168  return ERR_APPEND(res.get_error(),
169  "unable to generate subgraph functions: failed to generate function for net " + net->get_name() + " with ID " + std::to_string(net->get_id()) + ".");
170  }
171 
172  results.push_back(res.get());
173  }
174 
175  return OK(results);
176  }
177 
178  } // namespace z3_utils
179 } // namespace hal
static Result< Net * > get_net_from(const Netlist *netlist, const BooleanFunction &var)
Definition: net.h:58
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
#define ERR_APPEND(prev_error, message)
Definition: result.h:64
z3::expr from_bf(const BooleanFunction &bf, z3::context &ctx, const std::map< std::string, z3::expr > &var2expr={})
Definition: z3_utils.cpp:15
Result< z3::expr > get_subgraph_z3_function(const std::vector< Gate * > &subgraph_gates, const Net *subgraph_output, z3::context &ctx)
Get the z3 expression representation of a combined Boolean function of a subgraph of combinational ga...
Result< std::vector< z3::expr > > get_subgraph_z3_functions(const std::vector< Gate * > &subgraph_gates, const std::vector< Net * > &subgraph_outputs, z3::context &ctx)
Get the z3 expression representations of combined Boolean functions of a subgraph of combinational ga...
Definition: defines.h:45
Net * net