aboutsummaryrefslogtreecommitdiffstats
path: root/passes/fsm/fsm_opt.cc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-08-09 14:49:51 +0200
committerClifford Wolf <clifford@clifford.at>2014-08-09 14:49:51 +0200
commit2faef8973830e553b1730c07d327c8d76d412e1c (patch)
tree5ad43e1f7d86c4c257a1b111e342ccd2b70e0d87 /passes/fsm/fsm_opt.cc
parent51aa5544fbda97c6b49bfba55696083ba47d4cef (diff)
downloadyosys-2faef8973830e553b1730c07d327c8d76d412e1c.tar.gz
yosys-2faef8973830e553b1730c07d327c8d76d412e1c.tar.bz2
yosys-2faef8973830e553b1730c07d327c8d76d412e1c.zip
Some improvements in fsm_opt and fsm_map for FSM with unreachable states
Diffstat (limited to 'passes/fsm/fsm_opt.cc')
-rw-r--r--passes/fsm/fsm_opt.cc44
1 files changed, 44 insertions, 0 deletions
diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc
index bcaa89bf0..a0e1885ec 100644
--- a/passes/fsm/fsm_opt.cc
+++ b/passes/fsm/fsm_opt.cc
@@ -30,6 +30,48 @@ struct FsmOpt
FsmData fsm_data;
RTLIL::Cell *cell;
RTLIL::Module *module;
+
+ void opt_unreachable_states()
+ {
+ while (1)
+ {
+ std::set<int> unreachable_states;
+ std::vector<FsmData::transition_t> new_transition_table;
+ std::vector<RTLIL::Const> new_state_table;
+ std::map<int, int> old_to_new_state;
+
+ for (int i = 0; i < SIZE(fsm_data.state_table); i++)
+ if (i != fsm_data.reset_state)
+ unreachable_states.insert(i);
+
+ for (auto &trans : fsm_data.transition_table)
+ unreachable_states.erase(trans.state_out);
+
+ if (unreachable_states.empty())
+ break;
+
+ for (int i = 0; i < SIZE(fsm_data.state_table); i++) {
+ if (unreachable_states.count(i)) {
+ log(" Removing unreachable state %s.\n", log_signal(fsm_data.state_table[i]));
+ continue;
+ }
+ old_to_new_state[i] = SIZE(new_state_table);
+ new_state_table.push_back(fsm_data.state_table[i]);
+ }
+
+ for (auto trans : fsm_data.transition_table) {
+ if (unreachable_states.count(trans.state_in))
+ continue;
+ trans.state_in = old_to_new_state.at(trans.state_in);
+ trans.state_out = old_to_new_state.at(trans.state_out);
+ new_transition_table.push_back(trans);
+ }
+
+ new_transition_table.swap(fsm_data.transition_table);
+ new_state_table.swap(fsm_data.state_table);
+ fsm_data.reset_state = old_to_new_state.at(fsm_data.reset_state);
+ }
+ }
bool signal_is_unused(RTLIL::SigSpec sig)
{
@@ -253,6 +295,8 @@ struct FsmOpt
this->cell = cell;
this->module = module;
+ opt_unreachable_states();
+
opt_unused_outputs();
opt_alias_inputs();