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