diff options
author | Marcelina Kościelnicka <mwk@0x04.net> | 2021-03-12 17:05:39 +0100 |
---|---|---|
committer | Marcelina Kościelnicka <mwk@0x04.net> | 2021-03-15 17:17:29 +0100 |
commit | a55bf6375b38a955de4589a66e4d2992ac7dd621 (patch) | |
tree | 2f9a517b5eb61dfc37a08a818bdd0214546d96ff /passes/proc | |
parent | 3af871f969f7f5bd5201bac17544559671312a6f (diff) | |
download | yosys-a55bf6375b38a955de4589a66e4d2992ac7dd621.tar.gz yosys-a55bf6375b38a955de4589a66e4d2992ac7dd621.tar.bz2 yosys-a55bf6375b38a955de4589a66e4d2992ac7dd621.zip |
proc_arst: Add special-casing of clock signal in conditionals.
The already-existing special case for conditionals on clock has been
remade as follows:
- now triggered for the last remaining edge trigger after all others
have been converted to async reset, not just when there is only one
sync rule in the first place
- does not require all contained assignments to be constant, as opposed
to a reset conditional — merely const-folds the condition
In addition, the code has been refactored a bit; as a bonus, the
priority order of async resets found is now preserved in resulting sync
rule ordering (though this is not yet respected by proc_dff).
Fixes #2656.
Diffstat (limited to 'passes/proc')
-rw-r--r-- | passes/proc/proc_arst.cc | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index 4351321e0..d1bfbc647 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -179,39 +179,67 @@ RTLIL::SigSpec apply_reset(RTLIL::Module *mod, RTLIL::Process *proc, RTLIL::Sync void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map) { -restart_proc_arst: - if (proc->root_case.switches.size() != 1) - return; - - RTLIL::SigSpec root_sig = proc->root_case.switches[0]->signal; + std::vector<RTLIL::SyncRule *> arst_syncs; + std::vector<RTLIL::SyncRule *> edge_syncs; + std::vector<RTLIL::SyncRule *> other_syncs; for (auto &sync : proc->syncs) { - if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) { + if (sync->type == RTLIL::SyncType::ST0 || sync->type == RTLIL::SyncType::ST1) { + arst_syncs.push_back(sync); + } else if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) { + edge_syncs.push_back(sync); + } else { + other_syncs.push_back(sync); + } + } + + bool did_something = false; + + while (proc->root_case.switches.size() == 1) { + RTLIL::SigSpec root_sig = proc->root_case.switches[0]->signal; + + bool found = false; + for (auto it = edge_syncs.begin(); it != edge_syncs.end(); ++it) { + auto sync = *it; bool polarity = sync->type == RTLIL::SyncType::STp; if (check_signal(mod, root_sig, sync->signal, polarity)) { - if (proc->syncs.size() == 1) { - log("Found VHDL-style edge-trigger %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str()); - } else { + if (edge_syncs.size() > 1) { log("Found async reset %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str()); sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0; - } - for (auto &action : sync->actions) { - action.second = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, action.second, action.first); - } - for (auto &memwr : sync->mem_write_actions) { - RTLIL::SigSpec en = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.enable, memwr.enable); - if (!en.is_fully_zero()) { - log_error("Async reset %s causes memory write to %s.\n", - log_signal(sync->signal), log_id(memwr.memid)); + arst_syncs.push_back(sync); + edge_syncs.erase(it); + for (auto &action : sync->actions) { + action.second = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, action.second, action.first); } - apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.address, memwr.address); - apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.data, memwr.data); + for (auto &memwr : sync->mem_write_actions) { + RTLIL::SigSpec en = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.enable, memwr.enable); + if (!en.is_fully_zero()) { + log_error("Async reset %s causes memory write to %s.\n", + log_signal(sync->signal), log_id(memwr.memid)); + } + apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.address, memwr.address); + apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.data, memwr.data); + } + sync->mem_write_actions.clear(); + eliminate_const(mod, &proc->root_case, root_sig, polarity); + } else { + log("Found VHDL-style edge-trigger %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str()); + eliminate_const(mod, &proc->root_case, root_sig, !polarity); } - sync->mem_write_actions.clear(); - eliminate_const(mod, &proc->root_case, root_sig, polarity); - goto restart_proc_arst; + did_something = true; + found = true; + break; } } + if (!found) + break; + } + + if (did_something) { + proc->syncs.clear(); + proc->syncs.insert(proc->syncs.end(), arst_syncs.begin(), arst_syncs.end()); + proc->syncs.insert(proc->syncs.end(), edge_syncs.begin(), edge_syncs.end()); + proc->syncs.insert(proc->syncs.end(), other_syncs.begin(), other_syncs.end()); } } |