From: Marcelina Koƛcielnicka Date: Thu, 8 Oct 2020 11:33:47 +0000 (+0200) Subject: opt_clean: Better memory handling. X-Git-Tag: working-ls180~247 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7670a89e1fde7d0774695ab81031a90fafdf56b9;p=yosys.git opt_clean: Better memory handling. Previously, `$memwr` and `$meminit` cells were always preserved (along with the memory itself). With this change, they are instead part of the main cell mark-and-sweep pass: a memory (and its `$meminit` and `$memwr` cells) is only preserved iff any associated `$memrd` cell needs to be preserved. --- diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index bd9856e81..883374cf6 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -55,7 +55,7 @@ struct keep_cache_t if (!module->get_bool_attribute(ID::keep)) { bool found_keep = false; for (auto cell : module->cells()) - if (query(cell, true /* ignore_specify_mem */)) { + if (query(cell, true /* ignore_specify */)) { found_keep = true; break; } @@ -70,12 +70,12 @@ struct keep_cache_t return cache[module]; } - bool query(Cell *cell, bool ignore_specify_mem = false) + bool query(Cell *cell, bool ignore_specify = false) { if (cell->type.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) return true; - if (!ignore_specify_mem && cell->type.in(ID($memwr), ID($meminit), ID($specify2), ID($specify3), ID($specrule))) + if (!ignore_specify && cell->type.in(ID($specify2), ID($specify3), ID($specrule))) return true; if (cell->has_keep_attr()) @@ -95,6 +95,8 @@ int count_rm_cells, count_rm_wires; void rmunused_module_cells(Module *module, bool verbose) { SigMap sigmap(module); + dict> mem2cells; + pool mem_unused; pool queue, unused; pool used_raw_bits; dict> wire2driver; @@ -108,6 +110,17 @@ void rmunused_module_cells(Module *module, bool verbose) } } + for (auto &it : module->memories) { + mem_unused.insert(it.first); + } + + for (Cell *cell : module->cells()) { + if (cell->type.in(ID($memwr), ID($meminit))) { + IdString mem_id = cell->getParam(ID::MEMID).decode_string(); + mem2cells[mem_id].insert(cell); + } + } + for (auto &it : module->cells_) { Cell *cell = it.second; for (auto &it2 : cell->connections()) { @@ -145,17 +158,33 @@ void rmunused_module_cells(Module *module, bool verbose) while (!queue.empty()) { pool bits; - for (auto cell : queue) - for (auto &it : cell->connections()) - if (!ct_all.cell_known(cell->type) || ct_all.cell_input(cell->type, it.first)) - for (auto bit : sigmap(it.second)) - bits.insert(bit); + pool mems; + for (auto cell : queue) { + for (auto &it : cell->connections()) + if (!ct_all.cell_known(cell->type) || ct_all.cell_input(cell->type, it.first)) + for (auto bit : sigmap(it.second)) + bits.insert(bit); + + if (cell->type == ID($memrd)) { + IdString mem_id = cell->getParam(ID::MEMID).decode_string(); + if (mem_unused.count(mem_id)) { + mem_unused.erase(mem_id); + mems.insert(mem_id); + } + } + } queue.clear(); + for (auto bit : bits) for (auto c : wire2driver[bit]) if (unused.count(c)) queue.insert(c), unused.erase(c); + + for (auto mem : mems) + for (auto c : mem2cells[mem]) + if (unused.count(c)) + queue.insert(c), unused.erase(c); } unused.sort(RTLIL::sort_by_name_id()); @@ -168,6 +197,14 @@ void rmunused_module_cells(Module *module, bool verbose) count_rm_cells++; } + for (auto it : mem_unused) + { + if (verbose) + log_debug(" removing unused memory `%s'.\n", it.c_str()); + delete module->memories.at(it); + module->memories.erase(it); + } + for (auto &it : module->cells_) { Cell *cell = it.second; for (auto &it2 : cell->connections()) { diff --git a/tests/opt/opt_clean_mem.ys b/tests/opt/opt_clean_mem.ys new file mode 100644 index 000000000..b35b15871 --- /dev/null +++ b/tests/opt/opt_clean_mem.ys @@ -0,0 +1,49 @@ +read_verilog <