HAL
solve_fsm.cpp
Go to the documentation of this file.
1 #include "solve_fsm/solve_fsm.h"
2 
13 #include "hal_core/netlist/net.h"
14 
15 #include <bitset>
16 #include <fstream>
17 #include <deque>
18 
19 namespace hal
20 {
21  namespace solve_fsm
22  {
23  namespace
24  {
25  // generates a list of state flip flop output nets and the corresponding boolean function at their data input
26  Result<std::vector<std::pair<Net*, BooleanFunction>>>
27  generate_state_bfs(Netlist* nl, const std::vector<Gate*>& state_reg, const std::vector<Gate*>& transition_logic, const bool consider_control_inputs)
28  {
29  std::map<Net*, Net*> output_net_to_input_net;
30 
31  for (const auto& ff : state_reg)
32  {
33  const std::vector<GatePin*> d_pins = ff->get_type()->get_pins([](const GatePin* pin) { return pin->get_type() == PinType::data; });
34  if (d_pins.size() != 1)
35  {
36  return ERR("failed to create input - output mapping: currently not supporting flip-flops with multiple or no data inputs, but found " + std::to_string(d_pins.size())
37  + " for gate type " + ff->get_type()->get_name() + ".");
38  }
39 
40  hal::Net* input_net;
41  if (auto res = ff->get_fan_in_net(d_pins.front()); res == nullptr)
42  {
43  return ERR("failed to create input - output mapping: could not get fan-in net at pin " + d_pins.front()->get_name() + " of gate " + std::to_string(ff->get_id()) + ".");
44  }
45  else
46  {
47  input_net = res;
48  }
49 
50  for (const auto& out_net : ff->get_fan_out_nets())
51  {
52  output_net_to_input_net.insert({out_net, input_net});
53  }
54  }
55 
56  std::vector<std::pair<Net*, BooleanFunction>> state_bfs;
57 
58  const std::vector<const Gate*> subgraph_gates = {transition_logic.begin(), transition_logic.end()};
59  const auto nl_dec = SubgraphNetlistDecorator(*nl);
60 
61  for (const auto& ff : state_reg)
62  {
63  const std::vector<GatePin*> d_pins = ff->get_type()->get_pins([](const GatePin* pin) { return pin->get_type() == PinType::data; });
64  const GatePin* d_pin = d_pins.front();
65 
66  const std::vector<GatePin*> state_pins = ff->get_type()->get_pins([](const GatePin* pin) { return pin->get_type() == PinType::state; });
67  const std::vector<GatePin*> neg_state_pins = ff->get_type()->get_pins([](const GatePin* pin) { return pin->get_type() == PinType::neg_state; });
68 
69  Net* data_net = ff->get_fan_in_net(d_pin);
70 
71  BooleanFunction bf;
72  if (consider_control_inputs)
73  {
74  BooleanFunction complete_bf;
75  std::string internal_state_identifier;
76  std::string internal_negated_state_identifier;
77 
78  if (ff->get_type()->has_property(GateTypeProperty::ff))
79  {
80  const FFComponent* ff_component = ff->get_type()->get_component_as<FFComponent>([](const GateTypeComponent* c) { return FFComponent::is_class_of(c); });
81  const StateComponent* state_componenet = ff->get_type()->get_component_as<StateComponent>([](const GateTypeComponent* c) { return StateComponent::is_class_of(c); });
82 
83  complete_bf = ff_component->get_next_state_function();
84  internal_state_identifier = state_componenet->get_state_identifier();
85  internal_negated_state_identifier = state_componenet->get_neg_state_identifier();
86  }
87  else
88  {
89  return ERR("failed to generate boolean functions of state: gate " + ff->get_name() + " with ID " + std::to_string(ff->get_id())
90  + " of state register has an unhandeled type " + ff->get_type()->get_name());
91  }
92 
93  std::cout << complete_bf << std::endl;
94 
95  for (const auto& pin_var : complete_bf.get_variable_names())
96  {
97  // The complete Boolean function of a flip flop will contain the internal state and negated internal state.
98  // We substitute them with the outgoing state / negated state nets.
99  if (pin_var == internal_state_identifier)
100  {
101  if (state_pins.size() != 1)
102  {
103  return ERR("failed to generate boolean functions of state: found " + std::to_string(state_pins.size()) + " state pins at gate " + ff->get_name() + " with ID "
104  + std::to_string(ff->get_id()) + ", but we expect exactly 1.");
105  }
106 
107  complete_bf = complete_bf.substitute(internal_state_identifier, BooleanFunctionNetDecorator(*(ff->get_fan_out_net(state_pins.front()))).get_boolean_variable_name());
108 
109  continue;
110  }
111 
112  if (pin_var == internal_negated_state_identifier)
113  {
114  if (neg_state_pins.size() != 1)
115  {
116  return ERR("failed to generate boolean functions of state: found " + std::to_string(neg_state_pins.size()) + " neg state pins at gate " + ff->get_name()
117  + " with ID " + std::to_string(ff->get_id()) + ", but we expect exactly 1.");
118  }
119 
120  complete_bf =
121  complete_bf.substitute(internal_state_identifier, BooleanFunctionNetDecorator(*(ff->get_fan_out_net(neg_state_pins.front()))).get_boolean_variable_name());
122 
123  continue;
124  }
125 
126  const auto pin_net = ff->get_fan_in_net(pin_var);
127  BooleanFunction pin_bf;
128  if (auto res = nl_dec.get_subgraph_function(subgraph_gates, pin_net); res.is_error())
129  {
130  return ERR_APPEND(res.get_error(),
131  "failed to generate boolean functions of state: could not generate subgraph function for state net " + std::to_string(pin_net->get_id()) + ".");
132  }
133  else
134  {
135  pin_bf = res.get();
136  }
137 
138  if (auto res = BooleanFunctionDecorator(pin_bf).substitute_power_ground_nets(nl); res.is_error())
139  {
140  return ERR_APPEND(res.get_error(),
141  "failed to generate boolean functions of state: could not substitute power and ground nets in boolean funtion of net "
142  + std::to_string(pin_net->get_id()));
143  }
144  else
145  {
146  pin_bf = res.get();
147  }
148 
149  if (auto res = complete_bf.substitute(pin_var, pin_bf); res.is_error())
150  {
151  return ERR_APPEND(res.get_error(),
152  "failed to generate boolean functions of state: could not substitute variable " + pin_var + " in boolean funtion of net "
153  + std::to_string(pin_net->get_id()));
154  }
155  else
156  {
157  complete_bf = res.get();
158  }
159  }
160 
161  std::cout << complete_bf << std::endl;
162 
163  bf = complete_bf;
164  }
165  else
166  {
167  if (auto res = nl_dec.get_subgraph_function(subgraph_gates, data_net); res.is_error())
168  {
169  return ERR_APPEND(res.get_error(),
170  "failed to generate boolean functions of state: could not generate subgraph function for state net " + std::to_string(data_net->get_id()) + ".");
171  }
172  else
173  {
174  bf = res.get();
175  }
176 
177  if (auto res = BooleanFunctionDecorator(bf).substitute_power_ground_nets(nl); res.is_error())
178  {
179  return ERR_APPEND(res.get_error(),
180  "failed to generate boolean functions of state: could not substitute power and ground nets in boolean funtion of net "
181  + std::to_string(data_net->get_id()));
182  }
183  else
184  {
185  bf = res.get();
186  }
187  }
188 
189  bf.simplify();
190 
191  const auto var_names = bf.get_variable_names();
192 
193  // in the transition logic expressions of the next state bits we substitue the output nets of the state flip-flops with their (negated) input net.
194  for (const auto& [out, in] : output_net_to_input_net)
195  {
196  // check whether output net is part of the expression
197  if (var_names.find(BooleanFunctionNetDecorator(*out).get_boolean_variable_name()) == var_names.end())
198  {
199  continue;
200  }
201 
202  auto in_bf = BooleanFunctionNetDecorator(*in).get_boolean_variable();
203 
204  // check for multidriven nets
205  if (out->get_sources().size() != 1)
206  {
207  return ERR("failed to generate boolean functions of state: found multi driven net " + std::to_string(out->get_id()) + ".");
208  }
209 
210  // negate if the output stems from the negated state output
211  const GatePin* src_pin = out->get_sources().front()->get_pin();
212  if (src_pin->get_type() == PinType::neg_state)
213  {
214  in_bf = ~in_bf;
215  }
216 
217  auto res = bf.substitute(BooleanFunctionNetDecorator(*out).get_boolean_variable_name(), in_bf);
218 
219  if (res.is_error())
220  {
221  return ERR("failed to generate boolean functions of state: unable to replace out net " + std::to_string(out->get_id()) + " with in net " + std::to_string(in->get_id())
222  + ".");
223  }
224 
225  bf = res.get();
226  }
227 
228  state_bfs.push_back({data_net, bf});
229  }
230 
231  return OK(state_bfs);
232  }
233 
234  // takes a map of unconditional transitions and reconstructs the conditions under which each condition is taken
235  Result<std::map<u64, std::map<u64, BooleanFunction>>> generate_conditional_transitions(const std::vector<std::pair<Net*, BooleanFunction>>& state_bfs,
236  const std::map<u64, std::set<u64>>& transitions)
237  {
238  // generate all transitions that are reachable from the inital state.
239  std::map<u64, std::map<u64, BooleanFunction>> conditional_transitions;
240 
241  // for all possible and previously found successor states we build the condition to reach them
242  for (const auto& [prev, successors] : transitions)
243  {
244  // this builds a mapping for all the output net variables of the state vector to the current starting state
245  std::map<std::string, BooleanFunction> prev_mapping;
246  for (u32 i = 0; i < state_bfs.size(); i++)
247  {
248  prev_mapping.insert(
249  {BooleanFunctionNetDecorator(*(state_bfs.at(i).first)).get_boolean_variable_name(), ((prev >> i) & 1) ? BooleanFunction::Const(1, 1) : BooleanFunction::Const(0, 1)});
250  }
251 
252  for (const auto& suc : successors)
253  {
254  // this all the boolean functions of incoming data nets to the state vector either vanilla incase the corresponding state bit is 1 in the successor state or negated incase the state bit is 0 in the successor state.
255  BooleanFunction condition;
256 
257  for (u32 i = 0; i < state_bfs.size(); i++)
258  {
259  auto next_state_bit_bf = ((suc >> i) & 1) ? state_bfs.at(i).second : BooleanFunction::Not(state_bfs.at(i).second.clone(), 1).get();
260 
261  if (condition.is_empty())
262  {
263  condition = next_state_bit_bf;
264  }
265  else
266  {
267  condition = BooleanFunction::And(std::move(condition), std::move(next_state_bit_bf), 1).get();
268  }
269  }
270 
271  // replace all the variables of the previous state with their real values for our current state n and simplify.
272  condition = condition.substitute(prev_mapping).get();
273 
274  // we are left with a condition that only includes the inputs to the fsm that needs to be fullfilled to reach the successor state from state n.
275  condition = condition.simplify();
276 
277  conditional_transitions[prev].insert({suc, condition});
278  }
279  }
280 
281  return OK(conditional_transitions);
282  }
283 
284 
285  void open_dot_in_viewer(const std::filesystem::path& out_path)
286  {
287  BasePluginInterface* bpif = plugin_manager::get_plugin_instance("dot_viewer");
288  if (!bpif)
289  {
290  log_info("solve_fsm", "Cannot find 'dot_viewer' plugin, dot graph not displayed.");
291  return;
292  }
293  GuiExtensionInterface* geif = bpif->get_first_extension<GuiExtensionInterface>();
294  if (!geif)
295  {
296  log_info("solve_fsm", "Cannot find dot_viewer GUI interface, dot graph not displayed.");
297  return;
298  }
299  std::vector<PluginParameter> params;
300  params.push_back(PluginParameter(PluginParameter::ExistingFile, "filename", "", out_path.string()));
301  params.push_back(PluginParameter(PluginParameter::String, "plugin", "", "solve_fsm"));
302  params.push_back(PluginParameter(PluginParameter::PushButton, "exec", "", "clicked"));
303  geif->set_parameter(params);
304  log_info("solve_fsm", "Request to display graph '{}' send to dot viewer.", out_path.string());
305  }
306 
307  } // namespace
308 
309  Result<std::map<u64, std::map<u64, BooleanFunction>>>
310  solve_fsm_brute_force(Netlist* nl, const std::vector<Gate*>& state_reg, const std::vector<Gate*>& transition_logic, const std::filesystem::path& graph_path)
311  {
312  const u32 state_size = state_reg.size();
313  if (state_size > 64)
314  {
315  return ERR("failed to solve fsm: Currently only supports fsm with up to 64 state flip-flops but got " + std::to_string(state_size) + ".");
316  }
317 
318  // extract Boolean functions for each state flip-flop
319  const auto state_bfs_res = generate_state_bfs(nl, state_reg, transition_logic, true);
320  if (state_bfs_res.is_error())
321  {
322  return ERR_APPEND(state_bfs_res.get_error(), "failed to solve fsm: unable to generate Boolean functions for state.");
323  }
324  const std::vector<std::pair<Net*, BooleanFunction>> state_bfs = state_bfs_res.get();
325 
326  // bitvector including all the functions to calculate the next state
327  BooleanFunction next_state_vec = state_bfs.front().second;
328  for (u32 i = 1; i < state_reg.size(); i++)
329  {
330  next_state_vec = BooleanFunction::Concat(state_bfs.at(i).second.clone(), std::move(next_state_vec), next_state_vec.size() + 1).get();
331  }
332 
333  std::map<u64, std::set<u64>> all_transitions;
334 
335  for (u64 state = 0; state < (u64(1) << state_size); state++)
336  {
337  // generate state map
338  std::map<std::string, BooleanFunction> var_to_val;
339  for (u32 state_index = 0; state_index < state_size; state_index++)
340  {
341  std::string var = BooleanFunctionNetDecorator(*(state_bfs.at(state_index).first)).get_boolean_variable_name();
342  BooleanFunction val = ((state >> state_index) & 0x1) ? BooleanFunction::Const(1, 1) : BooleanFunction::Const(0, 1);
343  var_to_val.insert({var, val});
344  }
345 
346  const auto sub_res = next_state_vec.substitute(var_to_val);
347  if (sub_res.is_error())
348  {
349  return ERR_APPEND(sub_res.get_error(), "failed to solve fsm: unable to substitute variables in next state vec.");
350  }
351 
352  const auto state_bf = sub_res.get().simplify();
353  const auto inputs = utils::to_vector(state_bf.get_variable_names());
354 
355  // brute force over all external inputs
356  for (u64 input_val = 0; input_val < (u64(1) << inputs.size()); input_val++)
357  {
358  // generate input map
359  std::unordered_map<std::string, std::vector<BooleanFunction::Value>> input_mapping;
360  for (u32 input_index = 0; input_index < inputs.size(); input_index++)
361  {
362  std::string input_var = inputs.at(input_index);
363  BooleanFunction::Value val = ((input_val >> input_index) & 0x1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO;
364  input_mapping.insert({input_var, {val}});
365  }
366 
367  const auto& eval_res = state_bf.evaluate(input_mapping);
368  if (sub_res.is_error())
369  {
370  return ERR_APPEND(sub_res.get_error(), "failed to solve fsm: unable to evaluate next state function.");
371  }
372 
373  const auto eval = eval_res.get();
374 
375  if (eval.front() == BooleanFunction::Value::X)
376  {
377  return ERR("failed to solve fsm: evaluating state function resulted in X state.");
378  }
379 
380  const u64 suc_state = BooleanFunction::to_u64(eval).get();
381  all_transitions[state].insert(suc_state);
382  }
383  }
384 
385  const auto conditional_transitions = generate_conditional_transitions(state_bfs, all_transitions).get();
386 
387  /* DEBUG PRINTING */
388  for (const auto& [org, successors] : conditional_transitions)
389  {
390  std::cout << org << ": " << std::endl;
391  for (const auto& [suc, condition] : successors)
392  {
393  std::cout << "\t" << suc << ": " << condition.to_string() << std::endl;
394  }
395  }
396  /* END DEBUG PRINTING */
397 
398  if (auto graph_res = generate_dot_graph(state_reg, conditional_transitions, graph_path); graph_res.is_error())
399  {
400  return ERR_APPEND(graph_res.get_error(), "failed to solve fsm: unable to generate dot graph.");
401  }
402 
403  return OK(conditional_transitions);
404  }
405 
407  const std::vector<Gate*>& state_reg,
408  const std::vector<Gate*>& transition_logic,
409  const std::map<Gate*, bool>& initial_state,
410  const std::filesystem::path& graph_path,
411  const u32 timeout)
412  {
413  const u32 state_size = state_reg.size();
414  if (state_size > 64)
415  {
416  return ERR("failed to solve fsm: Currently only supports fsm with up to 64 state flip-flops but got " + std::to_string(state_size) + ".");
417  }
418 
419  // extract Boolean functions for each state flip-flop
420  const auto state_bfs_res = generate_state_bfs(nl, state_reg, transition_logic, true);
421  if (state_bfs_res.is_error())
422  {
423  return ERR_APPEND(state_bfs_res.get_error(), "failed to solve fsm: unable to generate Boolean functions for state.");
424  }
425  const std::vector<std::pair<Net*, BooleanFunction>> state_bfs = state_bfs_res.get();
426 
427  BooleanFunction prev_state_vec = BooleanFunctionNetDecorator(*(state_bfs.front().first)).get_boolean_variable();
428  BooleanFunction next_state_vec = state_bfs.front().second;
429  for (u32 i = 1; i < state_reg.size(); i++)
430  {
431  // bitvector representing the previous state
432  prev_state_vec = BooleanFunction::Concat(BooleanFunctionNetDecorator(*(state_bfs.at(i).first)).get_boolean_variable(), std::move(prev_state_vec), i + 1).get();
433 
434  // bitvector including all the functions to calculate the next state
435  next_state_vec = BooleanFunction::Concat(state_bfs.at(i).second.clone(), std::move(next_state_vec), i + 1).get();
436  }
437 
438  // generate initial state
439  u64 initial_state_num = 0;
440  if (!initial_state.empty())
441  {
442  for (const auto& gate : state_reg)
443  {
444  if (initial_state.find(gate) == initial_state.end())
445  {
446  return ERR("failed to solve fsm: Unable to find intial value for gate " + std::to_string(gate->get_id()) + " in the provided initial state map.");
447  }
448 
449  initial_state_num = initial_state_num << 1;
450  initial_state_num += initial_state.at(gate);
451  }
452  }
453 
454  // generate all transitions that are reachable from the inital state.
455  std::map<u64, std::set<u64>> all_transitions;
456 
457  std::deque<u64> q;
458  std::unordered_set<u64> visited;
459 
460  q.push_back(initial_state_num);
461 
462  while (!q.empty())
463  {
464  std::vector<u64> successor_states;
465 
466  u64 n = q.front();
467  q.pop_front();
468 
469  if (visited.find(n) != visited.end())
470  {
471  continue;
472  }
473  visited.insert(n);
474 
475  // generate new transitions and add them to the queue
476  SMT::Solver s;
477 
478  // set prev_state_vec to starting state
479  s = s.with_constraint(SMT::Constraint{prev_state_vec.clone(), BooleanFunction::Const(n, state_size)});
480 
481  while (true)
482  {
483  if (auto res = s.query(SMT::QueryConfig().with_model_generation().with_timeout(timeout)); res.is_error())
484  {
485  return ERR_APPEND(res.get_error(), "failed to solve fsm: failed to querry SMT solver for state " + std::to_string(n) + ".");
486  }
487  else
488  {
489  auto s_res = res.get();
490 
491  if (s_res.is_unsat())
492  {
493  break;
494  }
495 
496  if (s_res.is_unknown())
497  {
498  return ERR("failed to solve fsm: received an unknown solver result for state " + std::to_string(n) + ".");
499  }
500 
501  auto m = s_res.model.value();
502  auto suc = m.evaluate(next_state_vec).get();
503  auto suc_num = 0;
504 
505  // a constant (numeral) successor state
506  if (suc.is_constant())
507  {
508  suc_num = suc.get_constant_value_u64().get();
509  }
510  // a successor state that includes boolean functions (for example in form of input variables)
511  else
512  {
513  // to resolve such a successor state, we simpply set all variables left in the state to zero (which is one possible solution) and continue to search for more valid solutions
514  std::unordered_map<std::string, std::vector<BooleanFunction::Value>> zero_mapping;
515  for (const auto& var : suc.get_variable_names())
516  {
517  zero_mapping.insert({var, {BooleanFunction::Value::ZERO}});
518  }
519 
520  if (auto eval_res = suc.evaluate(zero_mapping); eval_res.is_error())
521  {
522  return ERR_APPEND(eval_res.get_error(), "failed to solve fsm: could not evaluate successor state to constant.");
523  }
524  else
525  {
526  suc_num = BooleanFunction::to_u64(eval_res.get()).get();
527  }
528  }
529 
530  q.push_back(suc_num);
531  all_transitions[n].insert(suc_num);
532  s = s.with_constraint(SMT::Constraint(BooleanFunction::Not(BooleanFunction::Eq(next_state_vec.clone(), BooleanFunction::Const(suc_num, suc.size()), 1).get(), 1).get()));
533  }
534  }
535  }
536 
537  const auto conditional_transitions = generate_conditional_transitions(state_bfs, all_transitions).get();
538 
539  /* DEBUG PRINTING */
540  for (const auto& [org, successors] : conditional_transitions)
541  {
542  std::cout << org << ": " << std::endl;
543  for (const auto& [suc, condition] : successors)
544  {
545  std::cout << "\t" << suc << ": " << condition.to_string() << std::endl;
546  }
547  }
548  /* END DEBUG PRINTING */
549 
550  if (auto graph_res = generate_dot_graph(state_reg, conditional_transitions, graph_path); graph_res.is_error())
551  {
552  return ERR_APPEND(graph_res.get_error(), "failed to solve fsm: unable to generate dot graph.");
553  }
554 
555  return OK(conditional_transitions);
556  }
557 
558 
559  Result<std::string> generate_dot_graph(const std::vector<Gate*>& state_reg,
560  const std::map<u64, std::map<u64, BooleanFunction>>& transitions,
561  const std::filesystem::path& graph_path,
562  const u32 max_condition_length,
563  const u32 base)
564  {
565  std::string graph_str = "digraph {\ncomment=\"created by HAL plugin solve_fsm\"\n";
566 
567  for (const auto& [org, successors] : transitions)
568  {
569  for (const auto& [suc, cond] : successors)
570  {
571  std::string start_name;
572  std::string end_name;
573 
574  switch (base)
575  {
576  case 2:
577  start_name = std::bitset<64>(org).to_string().substr(64 - state_reg.size(), 64);
578  end_name = std::bitset<64>(suc).to_string().substr(64 - state_reg.size(), 64);
579  break;
580  case 10:
581  start_name = std::to_string(org);
582  end_name = std::to_string(suc);
583  break;
584  default:
585  return ERR("failed to generate DOT graph: base " + std::to_string(base) + "not implemented.");
586  }
587 
588  graph_str +=
589  start_name + " -> " + end_name + "[label=\"" + cond.to_string().substr(0, max_condition_length) + "\", weight=\"" + cond.to_string().substr(0, max_condition_length) + "\"];\n";
590  ;
591  }
592  }
593 
594  graph_str += "}";
595 
596  // write to file
597  if (!graph_path.empty())
598  {
599  std::ofstream ofs(graph_path);
600  if (!ofs.is_open())
601  {
602  return ERR("failed to generate DOT graph: could not open file '" + graph_path.string() + "' for writing.");
603  }
604  ofs << graph_str;
605  ofs.close();
606  }
607 
608  open_dot_in_viewer(graph_path);
609 
610  return OK(graph_str);
611  }
612  } // namespace solve_fsm
613 } // namespace hal
static Result< BooleanFunction > Eq(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
static Result< BooleanFunction > Concat(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
BooleanFunction clone() const
Value
represents the type of the node
static BooleanFunction Const(const BooleanFunction::Value &value)
static Result< u64 > to_u64(const std::vector< BooleanFunction::Value > &value)
static Result< BooleanFunction > Not(BooleanFunction &&p0, u16 size)
static Result< BooleanFunction > And(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
BooleanFunction substitute(const std::string &old_variable_name, const std::string &new_variable_name) const
static bool is_class_of(const GateTypeComponent *component)
Definition: net.h:58
Result< SolverResult > query(const QueryConfig &config=QueryConfig()) const
Definition: solver.cpp:401
Solver & with_constraint(const Constraint &constraint)
Definition: solver.cpp:355
static bool is_class_of(const GateTypeComponent *component)
uint64_t u64
Definition: defines.h:42
#define log_info(channel,...)
Definition: log.h:70
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49
#define ERR_APPEND(prev_error, message)
Definition: result.h:57
BasePluginInterface * get_plugin_instance(const std::string &plugin_name, bool initialize, bool silent)
Result< std::string > generate_dot_graph(const std::vector< Gate * > &state_reg, const std::map< u64, std::map< u64, BooleanFunction >> &transitions, const std::filesystem::path &graph_path="", const u32 max_condition_length=128, const u32 base=10)
Definition: solve_fsm.cpp:559
Result< std::map< u64, std::map< u64, BooleanFunction > > > solve_fsm(Netlist *nl, const std::vector< Gate * > &state_reg, const std::vector< Gate * > &transition_logic, const std::map< Gate *, bool > &initial_state={}, const std::filesystem::path &graph_path="", const u32 timeout=600000)
Definition: solve_fsm.cpp:406
Result< std::map< u64, std::map< u64, BooleanFunction > > > solve_fsm_brute_force(Netlist *nl, const std::vector< Gate * > &state_reg, const std::vector< Gate * > &transition_logic, const std::filesystem::path &graph_path="")
Definition: solve_fsm.cpp:310
CORE_API std::vector< T > to_vector(const Container< T, Args... > &container)
Definition: utils.h:513
string graph_path
Definition: test_plugin.py:29
dictionary initial_state
Definition: test_plugin.py:28
n
Definition: test.py:6
quint32 u32
This file contains functions to generate the state transition graph of a given FSM.
QueryConfig & with_model_generation()
Definition: types.cpp:113
QueryConfig & with_timeout(u64 seconds)
Definition: types.cpp:125