Optimize memory address port width in wreduce and memory_collect, not verilog front-end
authorClifford Wolf <clifford@clifford.at>
Fri, 19 Aug 2016 16:38:25 +0000 (18:38 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 19 Aug 2016 16:38:25 +0000 (18:38 +0200)
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
passes/memory/memory_collect.cc
passes/opt/wreduce.cc

index bee2256e3a3712281bf7ad810d3cc3b0fbba8c70..115f8d1220f3be4a4e0e695a4b85e8f542a10563 100644 (file)
@@ -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) {
index 79dc3b7c86f422ee0522972e280783cc233170f6..6ff117a4450e670989d9af17dfe9370ce5b854d8 100644 (file)
@@ -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);
index e068ef90518ace50b6ea1265de47c66d7e02f315..ab66e3fb8b20460d9419efae0c69bb94a49072a7 100644 (file)
@@ -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<Cell*> 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;
index 333541eabd96bf9ad45610392f9e0cacf2352548..b2f1bea7ac15d1429644b8a1dfc667ea7c151c2c 100644 (file)
@@ -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();