aboutsummaryrefslogtreecommitdiffstats
path: root/passes/proc/proc_arst.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/proc/proc_arst.cc')
-rw-r--r--passes/proc/proc_arst.cc110
1 files changed, 76 insertions, 34 deletions
diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc
index 16db461b2..f01682957 100644
--- a/passes/proc/proc_arst.cc
+++ b/passes/proc/proc_arst.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -153,51 +153,93 @@ void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigSpec con
}
}
+RTLIL::SigSpec apply_reset(RTLIL::Module *mod, RTLIL::Process *proc, RTLIL::SyncRule *sync, SigMap &assign_map, RTLIL::SigSpec root_sig, bool polarity, RTLIL::SigSpec sig, RTLIL::SigSpec log_sig) {
+ RTLIL::SigSpec rspec = assign_map(sig);
+ RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size());
+ for (int i = 0; i < GetSize(rspec); i++)
+ if (rspec[i].wire == NULL)
+ rval[i] = rspec[i];
+ RTLIL::SigSpec last_rval;
+ for (int count = 0; rval != last_rval; count++) {
+ last_rval = rval;
+ apply_const(mod, rspec, rval, &proc->root_case, root_sig, polarity, false);
+ assign_map.apply(rval);
+ if (rval.is_fully_const())
+ break;
+ if (count > 100)
+ log_error("Async reset %s yields endless loop at value %s for signal %s.\n",
+ log_signal(sync->signal), log_signal(rval), log_signal(log_sig));
+ rspec = rval;
+ }
+ if (rval.has_marked_bits())
+ log_error("Async reset %s yields non-constant value %s for signal %s.\n",
+ log_signal(sync->signal), log_signal(rval), log_signal(log_sig));
+ return rval;
+}
+
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) {
- RTLIL::SigSpec rspec = assign_map(action.second);
- RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size());
- for (int i = 0; i < GetSize(rspec); i++)
- if (rspec[i].wire == NULL)
- rval[i] = rspec[i];
- RTLIL::SigSpec last_rval;
- for (int count = 0; rval != last_rval; count++) {
- last_rval = rval;
- apply_const(mod, rspec, rval, &proc->root_case, root_sig, polarity, false);
- assign_map.apply(rval);
- if (rval.is_fully_const())
- break;
- if (count > 100)
- log_error("Async reset %s yields endless loop at value %s for signal %s.\n",
- log_signal(sync->signal), log_signal(rval), log_signal(action.first));
- rspec = rval;
+ 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);
+ }
+ 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);
}
- if (rval.has_marked_bits())
- log_error("Async reset %s yields non-constant value %s for signal %s.\n",
- log_signal(sync->signal), log_signal(rval), log_signal(action.first));
- action.second = rval;
+ 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);
}
- 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());
}
}