aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelina Kościelnicka <mwk@0x04.net>2021-03-12 17:05:39 +0100
committerMarcelina Kościelnicka <mwk@0x04.net>2021-03-15 17:17:29 +0100
commita55bf6375b38a955de4589a66e4d2992ac7dd621 (patch)
tree2f9a517b5eb61dfc37a08a818bdd0214546d96ff
parent3af871f969f7f5bd5201bac17544559671312a6f (diff)
downloadyosys-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.
-rw-r--r--passes/proc/proc_arst.cc74
-rw-r--r--tests/proc/bug2656.ys31
2 files changed, 82 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());
}
}
diff --git a/tests/proc/bug2656.ys b/tests/proc/bug2656.ys
new file mode 100644
index 000000000..3fe7cb33b
--- /dev/null
+++ b/tests/proc/bug2656.ys
@@ -0,0 +1,31 @@
+read_verilog <<EOT
+module top (...);
+
+input clk, rst, d1, d2;
+output q1, q2;
+
+always @(posedge clk)
+ if (clk)
+ q1 <= d1;
+
+always @(posedge clk, posedge rst)
+ if (rst)
+ q2 <= 0;
+ else if (clk)
+ q2 <= d2;
+
+endmodule
+EOT
+
+proc
+opt
+
+select -assert-count 1 t:$dff
+select -assert-count 1 w:clk %a %co t:$dff %i
+select -assert-count 1 w:d1 %a %co t:$dff %i
+select -assert-count 1 w:q1 %a %ci t:$dff %i
+select -assert-count 1 t:$adff
+select -assert-count 1 w:clk %a %co t:$adff %i
+select -assert-count 1 w:rst %a %co t:$adff %i
+select -assert-count 1 w:d2 %a %co t:$adff %i
+select -assert-count 1 w:q2 %a %ci t:$adff %i