From: Clifford Wolf Date: Fri, 19 Aug 2016 16:38:25 +0000 (+0200) Subject: Optimize memory address port width in wreduce and memory_collect, not verilog front-end X-Git-Tag: yosys-0.7~128 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f6629b9c29838879cec6a94d6cb47afc6fbd2db4;p=yosys.git Optimize memory address port width in wreduce and memory_collect, not verilog front-end --- diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index bee2256e3..115f8d122 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1253,13 +1253,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int mem_width, mem_size, addr_bits; id2ast->meminfo(mem_width, mem_size, addr_bits); + RTLIL::SigSpec addr_sig = children[0]->genRTLIL(); + cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1)); cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1)); - cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits)); + cell->setPort("\\ADDR", addr_sig); cell->setPort("\\DATA", RTLIL::SigSpec(wire)); cell->parameters["\\MEMID"] = RTLIL::Const(str); - cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits); + cell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr_sig)); cell->parameters["\\WIDTH"] = RTLIL::Const(wire->width); cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0); @@ -1290,11 +1292,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) cell->parameters["\\WORDS"] = RTLIL::Const(num_words); } - cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits)); + SigSpec addr_sig = children[0]->genRTLIL(); + + cell->setPort("\\ADDR", addr_sig); cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words)); cell->parameters["\\MEMID"] = RTLIL::Const(str); - cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits); + cell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr_sig)); cell->parameters["\\WIDTH"] = RTLIL::Const(current_module->memories[str]->width); if (type == AST_MEMWR) { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 79dc3b7c8..6ff117a44 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1490,6 +1490,11 @@ skip_dynamic_range_lvalue_expansion:; int mem_width, mem_size, addr_bits; children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); + int addr_width_hint = -1; + bool addr_sign_hint = true; + children[0]->children[0]->children[0]->detectSignWidthWorker(addr_width_hint, addr_sign_hint); + addr_bits = std::max(addr_bits, addr_width_hint); + AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); wire_addr->str = id_addr; current_ast_mod->children.push_back(wire_addr); diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index e068ef905..ab66e3fb8 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -37,8 +37,6 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) log("Collecting $memrd, $memwr and $meminit for memory `%s' in module `%s':\n", memory->name.c_str(), module->name.c_str()); - int addr_bits = 0; - Const init_data(State::Sx, memory->size * memory->width); SigMap sigmap(module); @@ -59,16 +57,28 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) SigSpec sig_rd_data; SigSpec sig_rd_en; + int addr_bits = 0; std::vector memcells; for (auto &cell_it : module->cells_) { Cell *cell = cell_it.second; if (cell->type.in("$memrd", "$memwr", "$meminit") && memory->name == cell->parameters["\\MEMID"].decode_string()) { - addr_bits = max(addr_bits, cell->getParam("\\ABITS").as_int()); + SigSpec addr = sigmap(cell->getPort("\\ADDR")); + for (int i = 0; i < GetSize(addr); i++) + if (addr[i] != State::S0) + addr_bits = std::max(addr_bits, i+1); memcells.push_back(cell); } } + if (memory->start_offset == 0 && addr_bits < 30 && (1 << addr_bits) < memory->size) + memory->size = 1 << addr_bits; + + if (memory->start_offset >= 0) + addr_bits = std::min(addr_bits, ceil_log2(memory->size + memory->start_offset)); + + addr_bits = std::max(addr_bits, 1); + if (memcells.empty()) { log(" no cells found. removing memory.\n"); return nullptr; diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 333541eab..b2f1bea7a 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -385,6 +385,7 @@ struct WreducePass : public Pass { continue; for (auto c : module->selected_cells()) + { if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", "$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) { @@ -396,6 +397,23 @@ struct WreducePass : public Pass { module->connect(sig, Const(0, GetSize(sig))); } } + if (c->type.in("$memrd", "$memwr", "$meminit")) { + IdString memid = c->getParam("\\MEMID").decode_string(); + RTLIL::Memory *mem = module->memories.at(memid); + if (mem->start_offset == 0) { + int cur_addrbits = c->getParam("\\ABITS").as_int(); + int max_addrbits = ceil_log2(mem->size); + if (cur_addrbits > max_addrbits) { + log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n", + cur_addrbits-max_addrbits, cur_addrbits, + c->type == "$memrd" ? "read" : c->type == "$memwr" ? "write" : "init", + log_id(module), log_id(c), log_id(memid)); + c->setParam("\\ABITS", max_addrbits); + c->setPort("\\ADDR", c->getPort("\\ADDR").extract(0, max_addrbits)); + } + } + } + } WreduceWorker worker(&config, module); worker.run();