X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=passes%2Fproc%2Fproc_arst.cc;h=f016829571451fb8a08a99375a7affe59c9ca5a4;hb=a0e912ba9996536f5eab9989e7119d91b20545f4;hp=e400fcb723fd930c98e364811912969928fdff55;hpb=cf716e1fff53fe4633dce98ebca04fe36c283106;p=yosys.git diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index e400fcb72..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 + * Copyright (C) 2012 Claire Xenia Wolf * * 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,57 +153,99 @@ 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 arst_syncs; + std::vector edge_syncs; + std::vector 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()); } } struct ProcArstPass : public Pass { ProcArstPass() : Pass("proc_arst", "detect asynchronous resets") { } - void help() YS_OVERRIDE + void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -221,7 +263,7 @@ struct ProcArstPass : public Pass { log(" in the 'init' attribute on the net.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + void execute(std::vector args, RTLIL::Design *design) override { std::string global_arst; bool global_arst_neg = false;