47 std::string format_value(
const u64 value,
const u32 size,
const u32 base)
51 return std::bitset<64>(value).to_string().substr(64 -
size, 64);
53 return std::to_string(value);
60 std::string format_function(
const BooleanFunction& bf,
const u32 base)
64 if (
const auto res = bf.get_constant_value_u64(); res.is_ok())
66 return format_value(res.get(), bf.size(), base);
69 return bf.to_string();
76 std::string format_element(
const T* element)
78 return "'" + element->get_name() +
"' with ID " + std::to_string(element->get_id());
89 std::string graph_str =
"digraph {\ncomment=\"created by HAL plugin solve_fsm\"\n";
91 const auto format_state = [
this, base](
const u64 state) -> std::string {
96 return std::to_string(
state);
99 if (base != 2 && base != 10)
101 return ERR(
"failed to generate DOT graph: base " + std::to_string(base) +
"not implemented.");
107 std::set<u64> states;
111 for (
const auto& [suc, _] : successors)
117 for (
const auto&
state : states)
119 std::string label = format_state(
state);
123 for (
const auto& [
name, bf] : it->second)
128 if (bf.is_constant())
130 if (
const auto val_res = bf.get_constant_value_u64(); val_res.is_ok())
132 value = (base == 2) ? std::bitset<64>(val_res.get()).
to_string().substr(64 - bf.size(), 64) : std::to_string(val_res.get());
137 value = bf.to_string().substr(0, max_condition_length);
140 label +=
"\\n" +
name +
" = " + value;
144 graph_str += format_state(
state) +
" [label=\"" + label +
"\"];\n";
150 for (
const auto& [suc, cond] : successors)
152 const std::string start_name = format_state(org);
153 const std::string end_name = format_state(suc);
156 start_name +
" -> " + end_name +
"[label=\"" + cond.to_string().substr(0, max_condition_length) +
"\", weight=\"" + cond.to_string().substr(0, max_condition_length) +
"\"];\n";
164 if (!graph_path.empty())
166 std::ofstream ofs(graph_path);
169 return ERR(
"failed to generate DOT graph: could not open file '" + graph_path.string() +
"' for writing.");
176 return OK(graph_str);
180 if (base != 2 && base != 10)
182 return ERR(
"failed to print state transition graph: base " + std::to_string(base) +
" is not implemented.");
186 std::stringstream ss;
188 ss <<
"FSM with " << state_size <<
" state bits and " <<
transitions.size() <<
" reachable states" << std::endl << std::endl;
191 ss <<
"state register (least significant bit first):" << std::endl;
194 ss <<
" bit " << i <<
": " << format_element(
state_register.at(i)) << std::endl;
200 ss <<
"outputs (least significant bit first):" << std::endl;
203 ss <<
" " <<
name <<
":";
204 for (
u32 i = 0; i < nets.size(); i++)
206 ss << (i == 0 ?
" " :
", ") << format_element(nets.at(i));
215 std::set<std::string> variables;
218 for (
const auto& [successor, condition] : successors)
220 const auto vars = condition.get_variable_names();
221 variables.insert(vars.begin(), vars.end());
226 for (
const auto& [
name, bf] : state_outputs)
228 const auto vars = bf.get_variable_names();
229 variables.insert(vars.begin(), vars.end());
233 if (!variables.empty())
235 ss <<
"nets referenced in the Boolean functions below:" << std::endl;
236 for (
const auto& variable : variables)
238 ss <<
" " << variable <<
": ";
241 ss <<
"unknown, the netlist is not available" << std::endl;
247 ss <<
"'" << net_res.get()->get_name() <<
"' with ID " << net_res.get()->get_id() << std::endl;
251 ss <<
"not a net of this netlist" << std::endl;
259 ss <<
"state " << format_value(
state, state_size, base) << std::endl;
263 ss <<
" outputs:" << std::endl;
264 for (
const auto& [
name, bf] : it->second)
266 ss <<
" " <<
name <<
" = " << format_function(bf, base) << std::endl;
270 ss <<
" transitions:" << std::endl;
271 if (successors.empty())
273 ss <<
" none" << std::endl;
275 for (
const auto& [successor, condition] : successors)
277 ss <<
" to " << format_value(successor, state_size, base) <<
" if " << condition.to_string() << std::endl;
291 return ERR_APPEND(res.get_error(),
"failed to write state transition graph to '" + file_path.string() +
"'.");
294 std::ofstream ofs(file_path);
297 return ERR(
"failed to write state transition graph: could not open file '" + file_path.string() +
"' for writing.");
static Result< Net * > get_net_from(const Netlist *netlist, const BooleanFunction &var)
#define ERR_APPEND(prev_error, message)
Result< StateTransitionGraph > solve_fsm(const Configuration &config)
Recover the state transition graph of an FSM from the netlist that implements it.
This file contains the struct that holds the state transition graph of an FSM.
std::vector< std::pair< std::string, std::vector< Net * > > > output_nets
The outputs of the FSM, each given as a name and the nets that make up that output.
Result< std::string > generate_dot_graph(const std::filesystem::path &graph_path="", const u32 max_condition_length=128, const u32 base=10) const
Render the state transition graph in the DOT format.
std::map< u64, std::map< u64, BooleanFunction > > transitions
A map from each state to its successor states, together with the condition under which the respective...
u32 get_state_size() const
Get the number of flip-flops that make up the state register, i.e., the bit-size of a state.
std::vector< Gate * > state_register
The flip-flops that make up the state register, in the order that determines the encoding of a state.
Netlist * netlist
The netlist that implements the FSM.
Result< std::string > to_string(const u32 base=10) const
Render the state transition graph as human-readable text, without truncating anything.
std::map< u64, std::vector< std::pair< std::string, BooleanFunction > > > outputs
A map from each state to the value of every output of the FSM in that state.
Result< std::monostate > write_txt(const std::filesystem::path &file_path, const u32 base=10) const
Write the state transition graph to a text file, without truncating anything.