From d245e2bae59d18eb641aa6b324eef1bbbfa13c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Sat, 6 Mar 2021 11:05:57 +0100 Subject: proc_clean: Fix empty case removal conditions. Fixes #2639. --- passes/proc/proc_clean.cc | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'passes/proc') diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 5e78b7316..54d5a81ff 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -76,22 +76,33 @@ void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did } else { - bool all_fully_def = true; for (auto cs : sw->cases) - { if (max_depth != 0) proc_clean_case(cs, did_something, count, max_depth-1); - int size = 0; - for (auto cmp : cs->compare) + + bool is_parallel_case = sw->get_bool_attribute(ID::parallel_case); + bool is_full_case = sw->get_bool_attribute(ID::full_case); + + // Empty case removal. The rules are: + // + // - for full_case: only remove cases if *all* cases are empty + // - for parallel_case but not full_case: remove any empty case + // - for non-parallel and non-full case: remove the final case if it's empty + + if (is_full_case) + { + bool all_empty = true; + for (auto cs : sw->cases) + if (!cs->empty()) + all_empty = false; + if (all_empty) { - size += cmp.size(); - if (!cmp.is_fully_def()) - all_fully_def = false; + for (auto cs : sw->cases) + delete cs; + sw->cases.clear(); } - if (sw->signal.size() != size) - all_fully_def = false; } - if (all_fully_def) + else if (is_parallel_case) { for (auto cs = sw->cases.begin(); cs != sw->cases.end();) { -- cgit v1.2.3 From 760284033d6f255790d44bfcda0d1625a0c7bc87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Sat, 6 Mar 2021 03:59:03 +0100 Subject: proc_dff: Fix emitted FF when a register is not assigned in async reset Fixes #2619. --- passes/proc/proc_dff.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'passes/proc') diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc index e320a72a6..2b6ca8449 100644 --- a/passes/proc/proc_dff.cc +++ b/passes/proc/proc_dff.cc @@ -328,6 +328,10 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce) ce.assign_map.apply(sig); if (rstval == sig) { + if (sync_level->type == RTLIL::SyncType::ST1) + insig = mod->Mux(NEW_ID, insig, sig, sync_level->signal); + else + insig = mod->Mux(NEW_ID, sig, insig, sync_level->signal); rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size()); sync_level = NULL; } -- cgit v1.2.3 From 4e03865d5bf3fafe0bd3735c88431675d53d2663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Tue, 23 Feb 2021 00:21:46 +0100 Subject: Add support for memory writes in processes. --- passes/proc/Makefile.inc | 1 + passes/proc/proc.cc | 2 + passes/proc/proc_arst.cc | 54 ++++++++++++++-------- passes/proc/proc_clean.cc | 2 +- passes/proc/proc_dlatch.cc | 7 +-- passes/proc/proc_init.cc | 11 +---- passes/proc/proc_memwr.cc | 111 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 passes/proc/proc_memwr.cc (limited to 'passes/proc') diff --git a/passes/proc/Makefile.inc b/passes/proc/Makefile.inc index 4b56979f8..50244bf33 100644 --- a/passes/proc/Makefile.inc +++ b/passes/proc/Makefile.inc @@ -8,3 +8,4 @@ OBJS += passes/proc/proc_arst.o OBJS += passes/proc/proc_mux.o OBJS += passes/proc/proc_dlatch.o OBJS += passes/proc/proc_dff.o +OBJS += passes/proc/proc_memwr.o diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc index 09cf0af82..2151b0ce7 100644 --- a/passes/proc/proc.cc +++ b/passes/proc/proc.cc @@ -43,6 +43,7 @@ struct ProcPass : public Pass { log(" proc_mux\n"); log(" proc_dlatch\n"); log(" proc_dff\n"); + log(" proc_memwr\n"); log(" proc_clean\n"); log("\n"); log("This replaces the processes in the design with multiplexers,\n"); @@ -102,6 +103,7 @@ struct ProcPass : public Pass { Pass::call(design, ifxmode ? "proc_mux -ifx" : "proc_mux"); Pass::call(design, "proc_dlatch"); Pass::call(design, "proc_dff"); + Pass::call(design, "proc_memwr"); Pass::call(design, "proc_clean"); log_pop(); diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index 16db461b2..4351321e0 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -153,6 +153,30 @@ 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: @@ -172,28 +196,18 @@ restart_proc_arst: 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; + 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)); } - 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; + 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); goto restart_proc_arst; } diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 54d5a81ff..9e0b671f4 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -161,7 +161,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool for (size_t j = 0; j < proc->syncs[i]->actions.size(); j++) if (proc->syncs[i]->actions[j].first.size() == 0) proc->syncs[i]->actions.erase(proc->syncs[i]->actions.begin() + (j--)); - if (proc->syncs[i]->actions.size() == 0) { + if (proc->syncs[i]->actions.size() == 0 && proc->syncs[i]->mem_write_actions.size() == 0) { delete proc->syncs[i]; proc->syncs.erase(proc->syncs.begin() + (i--)); } diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc index 7b8c05b21..03d072cf4 100644 --- a/passes/proc/proc_dlatch.cc +++ b/passes/proc/proc_dlatch.cc @@ -342,7 +342,6 @@ struct proc_dlatch_db_t void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) { - std::vector new_syncs; RTLIL::SigSig latches_bits, nolatches_bits; dict latches_out_in; dict latches_hold; @@ -351,7 +350,6 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) for (auto sr : proc->syncs) { if (sr->type != RTLIL::SyncType::STa) { - new_syncs.push_back(sr); continue; } @@ -373,8 +371,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) for (int i = 0; i < GetSize(ss.first); i++) latches_out_in[ss.first[i]] = ss.second[i]; } - - delete sr; + sr->actions.clear(); } latches_out_in.sort(); @@ -441,8 +438,6 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) offset += width; } - - new_syncs.swap(proc->syncs); } struct ProcDlatchPass : public Pass { diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index eb323038d..b705251dd 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -71,17 +71,8 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc) offset += lhs_c.width; } } + sync->actions.clear(); } - - if (found_init) { - std::vector new_syncs; - for (auto &sync : proc->syncs) - if (sync->type == RTLIL::SyncType::STi) - delete sync; - else - new_syncs.push_back(sync); - proc->syncs.swap(new_syncs); - } } struct ProcInitPass : public Pass { diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc new file mode 100644 index 000000000..f898979d8 --- /dev/null +++ b/passes/proc/proc_memwr.cc @@ -0,0 +1,111 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2021 Marcelina Kościelnicka + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/ffinit.h" +#include "kernel/consteval.h" +#include "kernel/log.h" +#include +#include +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &next_priority) +{ + for (auto sr : proc->syncs) + { + for (auto memwr : sr->mem_write_actions) { + RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr)); + cell->attributes = memwr.attributes; + cell->setParam(ID::MEMID, Const(memwr.memid.str())); + cell->setParam(ID::ABITS, GetSize(memwr.address)); + cell->setParam(ID::WIDTH, GetSize(memwr.data)); + cell->setParam(ID::PRIORITY, next_priority[memwr.memid]++); + cell->setPort(ID::ADDR, memwr.address); + cell->setPort(ID::DATA, memwr.data); + SigSpec enable = memwr.enable; + for (auto sr2 : proc->syncs) { + if (sr2->type == RTLIL::SyncType::ST0) { + log_assert(sr2->mem_write_actions.empty()); + enable = mod->Mux(NEW_ID, Const(State::S0, GetSize(enable)), enable, sr2->signal); + } else if (sr2->type == RTLIL::SyncType::ST1) { + log_assert(sr2->mem_write_actions.empty()); + enable = mod->Mux(NEW_ID, enable, Const(State::S0, GetSize(enable)), sr2->signal); + } + } + cell->setPort(ID::EN, enable); + if (sr->type == RTLIL::SyncType::STa) { + cell->setPort(ID::CLK, State::Sx); + cell->setParam(ID::CLK_ENABLE, State::S0); + cell->setParam(ID::CLK_POLARITY, State::Sx); + } else if (sr->type == RTLIL::SyncType::STp) { + cell->setPort(ID::CLK, sr->signal); + cell->setParam(ID::CLK_ENABLE, State::S1); + cell->setParam(ID::CLK_POLARITY, State::S1); + } else if (sr->type == RTLIL::SyncType::STn) { + cell->setPort(ID::CLK, sr->signal); + cell->setParam(ID::CLK_ENABLE, State::S1); + cell->setParam(ID::CLK_POLARITY, State::S0); + } else { + log_error("process memory write with unsupported sync type in %s.%s", log_id(mod), log_id(proc)); + } + } + sr->mem_write_actions.clear(); + } +} + +struct ProcMemWrPass : public Pass { + ProcMemWrPass() : Pass("proc_memwr", "extract memory writes from processes") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" proc_memwr [selection]\n"); + log("\n"); + log("This pass converts memory writes in processes into $memwr cells.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing PROC_MEMWR pass (convert process memory writes to cells).\n"); + + extra_args(args, 1, design); + + for (auto module : design->selected_modules()) { + dict next_priority; + for (auto cell : module->cells()) { + if (cell->type == ID($memwr)) { + IdString memid = cell->parameters.at(ID::MEMID).decode_string(); + int priority = cell->parameters.at(ID::PRIORITY).as_int(); + if (priority >= next_priority[memid]) + next_priority[memid] = priority + 1; + } + } + for (auto &proc_it : module->processes) + if (design->selected(module, proc_it.second)) + proc_memwr(module, proc_it.second, next_priority); + } + } +} ProcMemWrPass; + +PRIVATE_NAMESPACE_END + -- cgit v1.2.3 From a55bf6375b38a955de4589a66e4d2992ac7dd621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Fri, 12 Mar 2021 17:05:39 +0100 Subject: proc_arst: Add special-casing of clock signal in conditionals. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- passes/proc/proc_arst.cc | 74 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 23 deletions(-) (limited to 'passes/proc') 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 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) { - 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()); } } -- cgit v1.2.3 From 72787f52fc31954e4b7dc3dc34d86705fc4e9dd1 Mon Sep 17 00:00:00 2001 From: Claire Xenia Wolf Date: Tue, 8 Jun 2021 00:39:36 +0200 Subject: Fixing old e-mail addresses and deadnames s/((Claire|Xen|Xenia|Clifford)\s+)+(Wolf|Xen)\s+<(claire|clifford)@(symbioticeda.com|clifford.at|yosyshq.com)>/Claire Xenia Wolf /gi; s/((Nina|Nak|N\.)\s+)+Engelhardt\s+/N. Engelhardt /gi; s/((David)\s+)+Shah\s+<(dave|david)@(symbioticeda.com|yosyshq.com|ds0.me)>/David Shah /gi; s/((Miodrag)\s+)+Milanovic\s+<(miodrag|micko)@(symbioticeda.com|yosyshq.com)>/Miodrag Milanovic /gi; s,https?://www.clifford.at/yosys/,http://yosyshq.net/yosys/,g; --- passes/proc/proc.cc | 2 +- passes/proc/proc_arst.cc | 2 +- passes/proc/proc_clean.cc | 2 +- passes/proc/proc_dff.cc | 2 +- passes/proc/proc_dlatch.cc | 2 +- passes/proc/proc_init.cc | 2 +- passes/proc/proc_mux.cc | 2 +- passes/proc/proc_rmdead.cc | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'passes/proc') diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc index 2151b0ce7..2dfc30e87 100644 --- a/passes/proc/proc.cc +++ b/passes/proc/proc.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 diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index d1bfbc647..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 diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 9e0b671f4..76d4cf51b 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.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 diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc index 2b6ca8449..da2a14c82 100644 --- a/passes/proc/proc_dff.cc +++ b/passes/proc/proc_dff.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 diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc index 03d072cf4..8340e1431 100644 --- a/passes/proc/proc_dlatch.cc +++ b/passes/proc/proc_dlatch.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 diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index b705251dd..841bce400 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.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 diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index d20f34534..b209057fe 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.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 diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index ee91637ca..d49fd7ed3 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.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 -- cgit v1.2.3 From 009940f56ca71cc8655a13a514371eb5757b96ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Sun, 11 Jul 2021 23:57:53 +0200 Subject: rtlil: Make Process handling more uniform with Cell and Wire. - add a backlink to module from Process - make constructor and destructor protected, expose Module functions to add and remove processes --- passes/proc/proc_clean.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'passes/proc') diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 76d4cf51b..45872907b 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -209,7 +209,7 @@ struct ProcCleanPass : public Pass { extra_args(args, argidx, design); for (auto mod : design->modules()) { - std::vector delme; + std::vector delme; if (!design->selected(mod)) continue; for (auto &proc_it : mod->processes) { @@ -220,12 +220,11 @@ struct ProcCleanPass : public Pass { proc_it.second->root_case.actions.size() == 0) { if (!quiet) log("Removing empty process `%s.%s'.\n", log_id(mod), proc_it.second->name.c_str()); - delme.push_back(proc_it.first); + delme.push_back(proc_it.second); } } - for (auto &id : delme) { - delete mod->processes[id]; - mod->processes.erase(id); + for (auto proc : delme) { + mod->remove(proc); } } -- cgit v1.2.3 From 88f20fa4dd6ec534cb30c4663d53e1f4d90ac07b Mon Sep 17 00:00:00 2001 From: Rupert Swarbrick Date: Wed, 14 Jul 2021 10:19:07 +0100 Subject: Delete unused found_init variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spotted during compilation: passes/proc/proc_init.cc: In function ‘void {anonymous}::proc_init(Yosys::RTLIL::Module*, Yosys::SigMap&, Yosys::RTLIL::Process*)’: passes/proc/proc_init.cc:31:7: warning: variable ‘found_init’ set but not used [-Wunused-but-set-variable] --- passes/proc/proc_init.cc | 3 --- 1 file changed, 3 deletions(-) (limited to 'passes/proc') diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index 841bce400..4da20c395 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -28,12 +28,9 @@ PRIVATE_NAMESPACE_BEGIN void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc) { - bool found_init = false; - for (auto &sync : proc->syncs) if (sync->type == RTLIL::SyncType::STi) { - found_init = true; log("Found init rule in `%s.%s'.\n", mod->name.c_str(), proc->name.c_str()); for (auto &action : sync->actions) -- cgit v1.2.3 From a0e912ba9996536f5eab9989e7119d91b20545f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Tue, 27 Jul 2021 15:43:36 +0200 Subject: proc: Run opt_expr at the end --- passes/proc/proc.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'passes/proc') diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc index 2dfc30e87..d7aac57b6 100644 --- a/passes/proc/proc.cc +++ b/passes/proc/proc.cc @@ -45,6 +45,7 @@ struct ProcPass : public Pass { log(" proc_dff\n"); log(" proc_memwr\n"); log(" proc_clean\n"); + log(" opt_expr -keepdc\n"); log("\n"); log("This replaces the processes in the design with multiplexers,\n"); log("flip-flops and latches.\n"); @@ -61,12 +62,16 @@ struct ProcPass : public Pass { log(" This option is passed through to proc_mux. proc_rmdead is not\n"); log(" executed in -ifx mode.\n"); log("\n"); + log(" -noopt\n"); + log(" Will omit the opt_expr pass.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { std::string global_arst; bool ifxmode = false; bool nomux = false; + bool noopt = false; log_header(design, "Executing PROC pass (convert processes to netlists).\n"); log_push(); @@ -86,6 +91,10 @@ struct ProcPass : public Pass { ifxmode = true; continue; } + if (args[argidx] == "-noopt") { + noopt = true; + continue; + } break; } extra_args(args, argidx, design); @@ -105,6 +114,8 @@ struct ProcPass : public Pass { Pass::call(design, "proc_dff"); Pass::call(design, "proc_memwr"); Pass::call(design, "proc_clean"); + if (!noopt) + Pass::call(design, "opt_expr -keepdc"); log_pop(); } -- cgit v1.2.3 From c016f6a4236fb970196f35c2afb0f2c7c237a77f Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Wed, 28 Jul 2021 17:34:24 -0400 Subject: proc_rmdead: use explicit pattern set when there are no wildcards If width of a case expression was large, explicit patterns could cause the existing logic to take an extremely long time, or exhaust the maximum size of the underlying set. For cases where all of the patterns are fully defined and there are no constants in the case expression, this change uses a simple set to track which patterns have been seen. --- passes/proc/proc_rmdead.cc | 65 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) (limited to 'passes/proc') diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index d49fd7ed3..2ec11415a 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.cc @@ -28,9 +28,62 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter) +static bool can_use_fully_defined_pool(RTLIL::SwitchRule *sw) +{ + if (!GetSize(sw->signal)) + return false; + + for (const RTLIL::SigBit &bit : sw->signal) + if (bit.wire == NULL) + return false; + + for (const RTLIL::CaseRule *cas : sw->cases) + for (const RTLIL::SigSpec &sig : cas->compare) + if (!sig.is_fully_def()) + return false; + + return true; +} + +// This replicates the necessary parts of BitPatternPool's interface, but rather +// than storing remaining patterns, this explicitly stores which fully-defined +// constants have already been matched. +struct FullyDefinedPool +{ + FullyDefinedPool(const RTLIL::SigSpec &signal) + : max_patterns{signal.size() >= 32 ? 0ul : 1ul << signal.size()} + {} + + bool take(RTLIL::SigSpec sig) + { + if (default_reached || patterns.count(sig)) + return false; + patterns.insert(sig); + return true; + } + + void take_all() + { + default_reached = true; + } + + bool empty() + { + return default_reached || + (max_patterns && max_patterns == patterns.size()); + } + + pool patterns; + bool default_reached = false; + size_t max_patterns; +}; + +void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter); + +template +static void proc_rmdead_impl(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter) { - BitPatternPool pool(sw->signal); + Pool pool(sw->signal); for (size_t i = 0; i < sw->cases.size(); i++) { @@ -68,6 +121,14 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter) } } +void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter) +{ + if (can_use_fully_defined_pool(sw)) + proc_rmdead_impl(sw, counter, full_case_counter); + else + proc_rmdead_impl(sw, counter, full_case_counter); +} + struct ProcRmdeadPass : public Pass { ProcRmdeadPass() : Pass("proc_rmdead", "eliminate dead trees in decision trees") { } void help() override -- cgit v1.2.3 From 24027b5446ffa9d47e00e2ab8bc773fdebc246bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Thu, 27 May 2021 20:55:09 +0200 Subject: proc_memwr: Use the v2 memwr cell. --- passes/proc/proc_memwr.cc | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'passes/proc') diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc index f898979d8..cf10bd4b2 100644 --- a/passes/proc/proc_memwr.cc +++ b/passes/proc/proc_memwr.cc @@ -29,17 +29,26 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &next_priority) +void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &next_port_id) { for (auto sr : proc->syncs) { + std::vector prev_port_ids; for (auto memwr : sr->mem_write_actions) { - RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr)); + int port_id = next_port_id[memwr.memid]++; + Const priority_mask(State::S0, port_id); + for (int i = 0; i < GetSize(prev_port_ids); i++) + if (memwr.priority_mask[i] == State::S1) + priority_mask[prev_port_ids[i]] = State::S1; + prev_port_ids.push_back(port_id); + + RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr_v2)); cell->attributes = memwr.attributes; cell->setParam(ID::MEMID, Const(memwr.memid.str())); cell->setParam(ID::ABITS, GetSize(memwr.address)); cell->setParam(ID::WIDTH, GetSize(memwr.data)); - cell->setParam(ID::PRIORITY, next_priority[memwr.memid]++); + cell->setParam(ID::PORTID, port_id); + cell->setParam(ID::PRIORITY_MASK, priority_mask); cell->setPort(ID::ADDR, memwr.address); cell->setPort(ID::DATA, memwr.data); SigSpec enable = memwr.enable; @@ -91,18 +100,19 @@ struct ProcMemWrPass : public Pass { extra_args(args, 1, design); for (auto module : design->selected_modules()) { - dict next_priority; + dict next_port_id; for (auto cell : module->cells()) { - if (cell->type == ID($memwr)) { + if (cell->type.in(ID($memwr), ID($memwr_v2))) { + bool is_compat = cell->type == ID($memwr); IdString memid = cell->parameters.at(ID::MEMID).decode_string(); - int priority = cell->parameters.at(ID::PRIORITY).as_int(); - if (priority >= next_priority[memid]) - next_priority[memid] = priority + 1; + int port_id = cell->parameters.at(is_compat ? ID::PRIORITY : ID::PORTID).as_int(); + if (port_id >= next_port_id[memid]) + next_port_id[memid] = port_id + 1; } } for (auto &proc_it : module->processes) if (design->selected(module, proc_it.second)) - proc_memwr(module, proc_it.second, next_priority); + proc_memwr(module, proc_it.second, next_port_id); } } } ProcMemWrPass; -- cgit v1.2.3 From faacc7ad897437a8169af9dbbab6818f88c7b1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Sat, 14 Aug 2021 14:23:12 +0200 Subject: proc_prune: Make assign removal and promotion per-bit, remember promoted bits. Fixes #2962. --- passes/proc/proc_prune.cc | 65 ++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 40 deletions(-) (limited to 'passes/proc') diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc index bd122b91f..9f1080ef6 100644 --- a/passes/proc/proc_prune.cc +++ b/passes/proc/proc_prune.cc @@ -67,51 +67,36 @@ struct PruneWorker } for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ) { RTLIL::SigSpec lhs = sigmap(it->first); - bool redundant = true; - for (auto &bit : lhs) { + RTLIL::SigSpec rhs = sigmap(it->second); + SigSpec new_lhs, new_rhs; + SigSpec conn_lhs, conn_rhs; + for (int i = 0; i < GetSize(lhs); i++) { + SigBit bit = lhs[i]; if (bit.wire && !assigned[bit]) { - redundant = false; - break; - } - } - bool remove = false; - if (redundant) { - removed_count++; - remove = true; - } else { - if (root) { - bool promotable = true; - for (auto &bit : lhs) { - if (bit.wire && affected[bit] && !assigned[bit]) { - promotable = false; - break; - } - } - if (promotable) { - RTLIL::SigSpec rhs = sigmap(it->second); - RTLIL::SigSig conn; - for (int i = 0; i < GetSize(lhs); i++) { - RTLIL::SigBit lhs_bit = lhs[i]; - if (lhs_bit.wire && !assigned[lhs_bit]) { - conn.first.append(lhs_bit); - conn.second.append(rhs.extract(i)); - } - } - promoted_count++; - module->connect(conn); - remove = true; + if (!affected[bit] && root) { + conn_lhs.append(bit); + conn_rhs.append(rhs[i]); + } else { + new_lhs.append(bit); + new_rhs.append(rhs[i]); } + assigned.insert(bit); + affected.insert(bit); } - for (auto &bit : lhs) - if (bit.wire) - assigned.insert(bit); - for (auto &bit : lhs) - if (bit.wire) - affected.insert(bit); } - if (remove) + if (GetSize(conn_lhs)) { + promoted_count++; + module->connect(conn_lhs, conn_rhs); + } + if (GetSize(new_lhs) == 0) { + if (GetSize(conn_lhs) == 0) + removed_count++; cs->actions.erase((it++).base() - 1); - else it++; + } else { + it->first = new_lhs; + it->second = new_rhs; + it++; + } } return assigned; } -- cgit v1.2.3 From 8d881826ebeafa524b1ed5e12ebbedb6d6b2a867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Sat, 2 Oct 2021 02:34:13 +0200 Subject: proc_dff: Emit $aldff. --- passes/proc/proc_dff.cc | 39 +++++++-------------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) (limited to 'passes/proc') diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc index da2a14c82..234671df5 100644 --- a/passes/proc/proc_dff.cc +++ b/passes/proc/proc_dff.cc @@ -143,48 +143,23 @@ void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative"); } -void gen_dffsr(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_out, +void gen_aldff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_out, bool clk_polarity, bool set_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec set, RTLIL::Process *proc) { std::stringstream sstr; sstr << "$procdff$" << (autoidx++); - RTLIL::SigSpec sig_set_inv = mod->addWire(NEW_ID, sig_in.size()); - RTLIL::SigSpec sig_sr_set = mod->addWire(NEW_ID, sig_in.size()); - RTLIL::SigSpec sig_sr_clr = mod->addWire(NEW_ID, sig_in.size()); - - RTLIL::Cell *inv_set = mod->addCell(NEW_ID, ID($not)); - inv_set->parameters[ID::A_SIGNED] = RTLIL::Const(0); - inv_set->parameters[ID::A_WIDTH] = RTLIL::Const(sig_in.size()); - inv_set->parameters[ID::Y_WIDTH] = RTLIL::Const(sig_in.size()); - inv_set->setPort(ID::A, sig_set); - inv_set->setPort(ID::Y, sig_set_inv); - - RTLIL::Cell *mux_sr_set = mod->addCell(NEW_ID, ID($mux)); - mux_sr_set->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size()); - mux_sr_set->setPort(set_polarity ? ID::A : ID::B, RTLIL::Const(0, sig_in.size())); - mux_sr_set->setPort(set_polarity ? ID::B : ID::A, sig_set); - mux_sr_set->setPort(ID::Y, sig_sr_set); - mux_sr_set->setPort(ID::S, set); - - RTLIL::Cell *mux_sr_clr = mod->addCell(NEW_ID, ID($mux)); - mux_sr_clr->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size()); - mux_sr_clr->setPort(set_polarity ? ID::A : ID::B, RTLIL::Const(0, sig_in.size())); - mux_sr_clr->setPort(set_polarity ? ID::B : ID::A, sig_set_inv); - mux_sr_clr->setPort(ID::Y, sig_sr_clr); - mux_sr_clr->setPort(ID::S, set); - - RTLIL::Cell *cell = mod->addCell(sstr.str(), ID($dffsr)); + RTLIL::Cell *cell = mod->addCell(sstr.str(), ID($aldff)); cell->attributes = proc->attributes; + cell->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size()); + cell->parameters[ID::ALOAD_POLARITY] = RTLIL::Const(set_polarity, 1); cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity, 1); - cell->parameters[ID::SET_POLARITY] = RTLIL::Const(true, 1); - cell->parameters[ID::CLR_POLARITY] = RTLIL::Const(true, 1); cell->setPort(ID::D, sig_in); cell->setPort(ID::Q, sig_out); + cell->setPort(ID::AD, sig_set); cell->setPort(ID::CLK, clk); - cell->setPort(ID::SET, sig_sr_set); - cell->setPort(ID::CLR, sig_sr_clr); + cell->setPort(ID::ALOAD, set); log(" created %s cell `%s' with %s edge clock and %s level non-const reset.\n", cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative", set_polarity ? "positive" : "negative"); @@ -355,7 +330,7 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce) else if (!rstval.is_fully_const() && !ce.eval(rstval)) { log_warning("Async reset value `%s' is not constant!\n", log_signal(rstval)); - gen_dffsr(mod, insig, rstval, sig_q, + gen_aldff(mod, insig, rstval, sig_q, sync_edge->type == RTLIL::SyncType::STp, sync_level && sync_level->type == RTLIL::SyncType::ST1, sync_edge->signal, sync_level->signal, proc); -- cgit v1.2.3