diff options
author | Clifford Wolf <clifford@clifford.at> | 2013-10-30 00:47:58 +0100 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2013-10-30 00:47:58 +0100 |
commit | b8bfa020fa346a9c0afb79f8666c862280f169f1 (patch) | |
tree | 3ed770ea6fa65ae4291520a03a38bccecf34c28a /passes/fsm | |
parent | 888c43210b4be97a65c99781734cd8cdd6363191 (diff) | |
download | yosys-b8bfa020fa346a9c0afb79f8666c862280f169f1.tar.gz yosys-b8bfa020fa346a9c0afb79f8666c862280f169f1.tar.bz2 yosys-b8bfa020fa346a9c0afb79f8666c862280f169f1.zip |
Added detection for endless recursion in fsm_detect pass
Diffstat (limited to 'passes/fsm')
-rw-r--r-- | passes/fsm/fsm_detect.cc | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index e1cef9438..6cd428a87 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -31,7 +31,7 @@ static SigSet<sig2driver_entry_t> sig2driver, sig2user; static std::set<RTLIL::Cell*> muxtree_cells; static SigPool sig_at_port; -static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig) +static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, SigPool &recursion_monitor) { if (sig_at_port.check_any(assign_map(sig))) return false; @@ -39,6 +39,14 @@ static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig) if (sig.is_fully_const() || old_sig == sig) return true; + if (recursion_monitor.check_any(sig)) { + log("Warning: logic loop in mux tree at signal %s in module %s.\n", + log_signal(sig), RTLIL::id2cstr(module->name)); + return false; + } + + recursion_monitor.add(sig); + std::set<sig2driver_entry_t> cellport_list; sig2driver.find(sig, cellport_list); for (auto &cellport : cellport_list) { @@ -46,14 +54,16 @@ static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig) return false; RTLIL::SigSpec sig_a = assign_map(cellport.first->connections["\\A"]); RTLIL::SigSpec sig_b = assign_map(cellport.first->connections["\\B"]); - if (!check_state_mux_tree(old_sig, sig_a)) + if (!check_state_mux_tree(old_sig, sig_a, recursion_monitor)) return false; for (int i = 0; i < sig_b.width; i += sig_a.width) - if (!check_state_mux_tree(old_sig, sig_b.extract(i, sig_a.width))) + if (!check_state_mux_tree(old_sig, sig_b.extract(i, sig_a.width), recursion_monitor)) return false; muxtree_cells.insert(cellport.first); } + recursion_monitor.del(sig); + return true; } @@ -98,9 +108,10 @@ static void detect_fsm(RTLIL::Wire *wire) if ((cellport.first->type != "$dff" && cellport.first->type != "$adff") || cellport.second != "\\Q") continue; muxtree_cells.clear(); + SigPool recursion_monitor; RTLIL::SigSpec sig_q = assign_map(cellport.first->connections["\\Q"]); RTLIL::SigSpec sig_d = assign_map(cellport.first->connections["\\D"]); - if (sig_q == RTLIL::SigSpec(wire) && check_state_mux_tree(sig_q, sig_d) && check_state_users(sig_q)) { + if (sig_q == RTLIL::SigSpec(wire) && check_state_mux_tree(sig_q, sig_d, recursion_monitor) && check_state_users(sig_q)) { log("Found FSM state register %s in module %s.\n", wire->name.c_str(), module->name.c_str()); wire->attributes["\\fsm_encoding"] = RTLIL::Const("auto"); return; |