24 Result<std::vector<std::pair<Net*, BooleanFunction>>>
25 generate_state_bfs(Netlist* nl,
const std::vector<Gate*>& state_reg,
const std::vector<Gate*>& transition_logic,
const bool consider_control_inputs)
27 std::map<Net*, Net*> output_net_to_input_net;
29 for (
const auto& ff : state_reg)
31 const std::vector<GatePin*> d_pins =
ff->get_type()->get_pins([](
const GatePin* pin) {
return pin->get_type() ==
PinType::data; });
32 if (d_pins.size() != 1)
34 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())
35 +
" for gate type " +
ff->get_type()->get_name() +
".");
39 if (
auto res =
ff->get_fan_in_net(d_pins.front()); res ==
nullptr)
41 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()) +
".");
48 for (
const auto& out_net :
ff->get_fan_out_nets())
50 output_net_to_input_net.insert({out_net, input_net});
54 std::vector<std::pair<Net*, BooleanFunction>> state_bfs;
56 const std::vector<const Gate*> subgraph_gates = {transition_logic.begin(), transition_logic.end()};
57 const auto nl_dec = SubgraphNetlistDecorator(*nl);
59 for (
const auto& ff : state_reg)
61 const std::vector<GatePin*> d_pins =
ff->get_type()->get_pins([](
const GatePin* pin) {
return pin->get_type() ==
PinType::data; });
62 const GatePin* d_pin = d_pins.front();
64 const std::vector<GatePin*> state_pins =
ff->get_type()->get_pins([](
const GatePin* pin) {
return pin->get_type() ==
PinType::state; });
65 const std::vector<GatePin*> neg_state_pins =
ff->get_type()->get_pins([](
const GatePin* pin) {
return pin->get_type() ==
PinType::neg_state; });
67 Net* data_net =
ff->get_fan_in_net(d_pin);
70 if (consider_control_inputs)
72 BooleanFunction complete_bf;
73 std::string internal_state_identifier;
74 std::string internal_negated_state_identifier;
78 const FFComponent* ff_component =
ff->get_type()->get_component_as<FFComponent>([](
const GateTypeComponent* c) {
return FFComponent::is_class_of(c); });
79 const StateComponent* state_componenet =
ff->get_type()->get_component_as<StateComponent>([](
const GateTypeComponent* c) {
return StateComponent::is_class_of(c); });
81 complete_bf = ff_component->get_next_state_function();
82 internal_state_identifier = state_componenet->get_state_identifier();
83 internal_negated_state_identifier = state_componenet->get_neg_state_identifier();
87 return ERR(
"failed to generate boolean functions of state: gate " +
ff->get_name() +
" with ID " + std::to_string(
ff->get_id())
88 +
" of state register has an unhandeled type " +
ff->get_type()->get_name());
91 std::cout << complete_bf << std::endl;
93 for (
const auto& pin_var : complete_bf.get_variable_names())
97 if (pin_var == internal_state_identifier)
99 if (state_pins.size() != 1)
101 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 "
102 + std::to_string(
ff->get_id()) +
", but we expect exactly 1.");
105 complete_bf = complete_bf.substitute(internal_state_identifier, BooleanFunctionNetDecorator(*(
ff->get_fan_out_net(state_pins.front()))).get_boolean_variable_name());
110 if (pin_var == internal_negated_state_identifier)
112 if (neg_state_pins.size() != 1)
114 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()
115 +
" with ID " + std::to_string(
ff->get_id()) +
", but we expect exactly 1.");
119 complete_bf.substitute(internal_state_identifier, BooleanFunctionNetDecorator(*(
ff->get_fan_out_net(neg_state_pins.front()))).get_boolean_variable_name());
124 const auto pin_net =
ff->get_fan_in_net(pin_var);
125 BooleanFunction pin_bf;
126 if (
auto res = nl_dec.get_subgraph_function(subgraph_gates, pin_net); res.is_error())
129 "failed to generate boolean functions of state: could not generate subgraph function for state net " + std::to_string(pin_net->get_id()) +
".");
136 if (
auto res = BooleanFunctionDecorator(pin_bf).substitute_power_ground_nets(nl); res.is_error())
139 "failed to generate boolean functions of state: could not substitute power and ground nets in boolean funtion of net "
140 + std::to_string(pin_net->get_id()));
147 if (
auto res = complete_bf.substitute(pin_var, pin_bf); res.is_error())
150 "failed to generate boolean functions of state: could not substitute variable " + pin_var +
" in boolean funtion of net "
151 + std::to_string(pin_net->get_id()));
155 complete_bf = res.get();
159 std::cout << complete_bf << std::endl;
165 if (
auto res = nl_dec.get_subgraph_function(subgraph_gates, data_net); res.is_error())
168 "failed to generate boolean functions of state: could not generate subgraph function for state net " + std::to_string(data_net->get_id()) +
".");
175 if (
auto res = BooleanFunctionDecorator(bf).substitute_power_ground_nets(nl); res.is_error())
178 "failed to generate boolean functions of state: could not substitute power and ground nets in boolean funtion of net "
179 + std::to_string(data_net->get_id()));
189 const auto var_names = bf.get_variable_names();
192 for (
const auto& [out, in] : output_net_to_input_net)
195 if (var_names.find(BooleanFunctionNetDecorator(*out).get_boolean_variable_name()) == var_names.end())
200 auto in_bf = BooleanFunctionNetDecorator(*in).get_boolean_variable();
203 if (out->get_sources().size() != 1)
205 return ERR(
"failed to generate boolean functions of state: found multi driven net " + std::to_string(out->get_id()) +
".");
209 const GatePin* src_pin = out->get_sources().front()->get_pin();
215 auto res = bf.substitute(BooleanFunctionNetDecorator(*out).get_boolean_variable_name(), in_bf);
219 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())
226 state_bfs.push_back({data_net, bf});
229 return OK(state_bfs);
233 Result<std::map<u64, std::map<u64, BooleanFunction>>> generate_conditional_transitions(
const std::vector<std::pair<Net*, BooleanFunction>>& state_bfs,
234 const std::map<
u64, std::set<u64>>& transitions)
237 std::map<u64, std::map<u64, BooleanFunction>> conditional_transitions;
240 for (
const auto& [prev, successors] : transitions)
243 std::map<std::string, BooleanFunction> prev_mapping;
244 for (
u32 i = 0; i < state_bfs.size(); i++)
247 {BooleanFunctionNetDecorator(*(state_bfs.at(i).first)).get_boolean_variable_name(), ((prev >> i) & 1) ?
BooleanFunction::Const(1, 1) : BooleanFunction::Const(0, 1)});
250 for (
const auto& suc : successors)
253 BooleanFunction condition;
255 for (
u32 i = 0; i < state_bfs.size(); i++)
257 auto next_state_bit_bf = ((suc >> i) & 1) ? state_bfs.at(i).second :
BooleanFunction::Not(state_bfs.at(i).second.clone(), 1).get();
259 if (condition.is_empty())
261 condition = next_state_bit_bf;
270 condition = condition.substitute(prev_mapping).get();
273 condition = condition.simplify();
275 conditional_transitions[prev].insert({suc, condition});
279 return OK(conditional_transitions);
284 Result<std::map<u64, std::map<u64, BooleanFunction>>>
287 const u32 state_size = state_reg.size();
290 return ERR(
"failed to solve fsm: Currently only supports fsm with up to 64 state flip-flops but got " + std::to_string(state_size) +
".");
294 const auto state_bfs_res = generate_state_bfs(nl, state_reg, transition_logic,
true);
295 if (state_bfs_res.is_error())
297 return ERR_APPEND(state_bfs_res.get_error(),
"failed to solve fsm: unable to generate Boolean functions for state.");
299 const std::vector<std::pair<Net*, BooleanFunction>> state_bfs = state_bfs_res.get();
303 for (
u32 i = 1; i < state_reg.size(); i++)
305 next_state_vec =
BooleanFunction::Concat(state_bfs.at(i).second.clone(), std::move(next_state_vec), next_state_vec.
size() + 1).get();
308 std::map<u64, std::set<u64>> all_transitions;
313 std::map<std::string, BooleanFunction> var_to_val;
314 for (
u32 state_index = 0; state_index < state_size; state_index++)
318 var_to_val.insert({var, val});
321 const auto sub_res = next_state_vec.
substitute(var_to_val);
322 if (sub_res.is_error())
324 return ERR_APPEND(sub_res.get_error(),
"failed to solve fsm: unable to substitute variables in next state vec.");
327 const auto state_bf = sub_res.get().simplify();
331 for (
u64 input_val = 0; input_val < (
u64(1) << inputs.size()); input_val++)
334 std::unordered_map<std::string, std::vector<BooleanFunction::Value>> input_mapping;
335 for (
u32 input_index = 0; input_index < inputs.size(); input_index++)
337 std::string input_var = inputs.at(input_index);
338 BooleanFunction::Value val = ((input_val >> input_index) & 0x1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO;
339 input_mapping.insert({input_var, {val}});
342 const auto& eval_res = state_bf.evaluate(input_mapping);
343 if (sub_res.is_error())
345 return ERR_APPEND(sub_res.get_error(),
"failed to solve fsm: unable to evaluate next state function.");
348 const auto eval = eval_res.get();
350 if (eval.front() == BooleanFunction::Value::X)
352 return ERR(
"failed to solve fsm: evaluating state function resulted in X state.");
356 all_transitions[
state].insert(suc_state);
360 const auto conditional_transitions = generate_conditional_transitions(state_bfs, all_transitions).get();
363 for (
const auto& [org, successors] : conditional_transitions)
365 std::cout << org <<
": " << std::endl;
366 for (
const auto& [suc, condition] : successors)
368 std::cout <<
"\t" << suc <<
": " << condition.to_string() << std::endl;
375 return ERR_APPEND(graph_res.get_error(),
"failed to solve fsm: unable to generate dot graph.");
378 return OK(conditional_transitions);
382 const std::vector<Gate*>& state_reg,
383 const std::vector<Gate*>& transition_logic,
388 const u32 state_size = state_reg.size();
391 return ERR(
"failed to solve fsm: Currently only supports fsm with up to 64 state flip-flops but got " + std::to_string(state_size) +
".");
395 const auto state_bfs_res = generate_state_bfs(nl, state_reg, transition_logic,
true);
396 if (state_bfs_res.is_error())
398 return ERR_APPEND(state_bfs_res.get_error(),
"failed to solve fsm: unable to generate Boolean functions for state.");
400 const std::vector<std::pair<Net*, BooleanFunction>> state_bfs = state_bfs_res.get();
404 for (
u32 i = 1; i < state_reg.size(); i++)
410 next_state_vec =
BooleanFunction::Concat(state_bfs.at(i).second.clone(), std::move(next_state_vec), i + 1).get();
414 u64 initial_state_num = 0;
417 for (
const auto& gate : state_reg)
421 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.");
424 initial_state_num = initial_state_num << 1;
430 std::map<u64, std::set<u64>> all_transitions;
433 std::unordered_set<u64> visited;
435 q.push_back(initial_state_num);
439 std::vector<u64> successor_states;
444 if (visited.find(
n) != visited.end())
460 return ERR_APPEND(res.get_error(),
"failed to solve fsm: failed to querry SMT solver for state " + std::to_string(
n) +
".");
464 auto s_res = res.get();
466 if (s_res.is_unsat())
471 if (s_res.is_unknown())
473 return ERR(
"failed to solve fsm: received an unknown solver result for state " + std::to_string(
n) +
".");
476 auto m = s_res.model.value();
477 auto suc = m.evaluate(next_state_vec).get();
481 if (suc.is_constant())
483 suc_num = suc.get_constant_value_u64().get();
489 std::unordered_map<std::string, std::vector<BooleanFunction::Value>> zero_mapping;
490 for (
const auto& var : suc.get_variable_names())
492 zero_mapping.insert({var, {BooleanFunction::Value::ZERO}});
495 if (
auto eval_res = suc.evaluate(zero_mapping); eval_res.is_error())
497 return ERR_APPEND(eval_res.get_error(),
"failed to solve fsm: could not evaluate successor state to constant.");
505 q.push_back(suc_num);
506 all_transitions[
n].insert(suc_num);
512 const auto conditional_transitions = generate_conditional_transitions(state_bfs, all_transitions).get();
515 for (
const auto& [org, successors] : conditional_transitions)
517 std::cout << org <<
": " << std::endl;
518 for (
const auto& [suc, condition] : successors)
520 std::cout <<
"\t" << suc <<
": " << condition.to_string() << std::endl;
527 return ERR_APPEND(graph_res.get_error(),
"failed to solve fsm: unable to generate dot graph.");
530 return OK(conditional_transitions);
534 const std::map<
u64, std::map<u64, BooleanFunction>>& transitions,
536 const u32 max_condition_length,
539 std::string graph_str =
"digraph {\n";
541 for (
const auto& [org, successors] : transitions)
543 for (
const auto& [suc, cond] : successors)
545 std::string start_name;
546 std::string end_name;
551 start_name = std::bitset<64>(org).to_string().substr(64 - state_reg.size(), 64);
552 end_name = std::bitset<64>(suc).to_string().substr(64 - state_reg.size(), 64);
555 start_name = std::to_string(org);
556 end_name = std::to_string(suc);
559 return ERR(
"failed to generate DOT graph: base " + std::to_string(base) +
"not implemented.");
563 start_name +
" -> " + end_name +
"[label=\"" + cond.to_string().substr(0, max_condition_length) +
"\", weight=\"" + cond.to_string().substr(0, max_condition_length) +
"\"];\n";
576 return ERR(
"failed to generate DOT graph: could not open file '" +
graph_path.string() +
"' for writing.");
582 return OK(graph_str);
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
std::string get_boolean_variable_name() const
BooleanFunction get_boolean_variable() const
static bool is_class_of(const GateTypeComponent *component)
Result< SolverResult > query(const QueryConfig &config=QueryConfig()) const
Solver & with_constraint(const Constraint &constraint)
static bool is_class_of(const GateTypeComponent *component)
#define ERR_APPEND(prev_error, message)
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)
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)
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="")
CORE_API std::vector< T > to_vector(const Container< T, Args... > &container)
This file contains functions to generate the state transition graph of a given FSM.
QueryConfig & with_model_generation()
QueryConfig & with_timeout(u64 seconds)