Various fixes for memories with offsets
authorClifford Wolf <clifford@clifford.at>
Sat, 14 Feb 2015 13:21:15 +0000 (14:21 +0100)
committerClifford Wolf <clifford@clifford.at>
Sat, 14 Feb 2015 13:21:15 +0000 (14:21 +0100)
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
passes/memory/memory_collect.cc
passes/memory/memory_map.cc
tests/simple/memory.v

index 7a78743b9ccaa77278f69bf497243875b8d1a81b..4b3310501ce73e29be5484bad80c6a2420e58244 100644 (file)
@@ -1214,9 +1214,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                        RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_DATA", current_module->memories[str]->width);
                        wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
 
-                       int addr_bits = 1;
-                       while ((1 << addr_bits) < current_module->memories[str]->size)
-                               addr_bits++;
+                       int mem_width, mem_size, addr_bits;
+                       id2ast->meminfo(mem_width, mem_size, addr_bits);
 
                        cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
                        cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
@@ -1243,9 +1242,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                        RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? "$memwr" : "$meminit");
                        cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
 
-                       int addr_bits = 1;
-                       while ((1 << addr_bits) < current_module->memories[str]->size)
-                               addr_bits++;
+                       int mem_width, mem_size, addr_bits;
+                       id2ast->meminfo(mem_width, mem_size, addr_bits);
 
                        cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits));
                        cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width));
index 10b65100015b2eef155420c78d541fc533f85475..095649729ebe705eec8ccce31b10b799d39394c3 100644 (file)
@@ -1421,6 +1421,7 @@ skip_dynamic_range_lvalue_expansion:;
                if (current_always->type != AST_INITIAL)
                        wrnode->children.push_back(new AstNode(AST_IDENTIFIER));
                wrnode->str = children[0]->str;
+               wrnode->id2ast = children[0]->id2ast;
                wrnode->children[0]->str = id_addr;
                wrnode->children[1]->str = id_data;
                if (current_always->type != AST_INITIAL)
index d0d32f504d3b116df4680e8637133707d45fa812..96d0ada03fa3b050506de269dd1435364c9252f8 100644 (file)
@@ -38,8 +38,6 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory)
                        memory->name.c_str(), module->name.c_str());
 
        int addr_bits = 0;
-       while ((1 << addr_bits) < memory->size)
-               addr_bits++;
 
        Const init_data(State::Sx, memory->size * memory->width);
        SigMap sigmap(module);
@@ -64,8 +62,15 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory)
 
        for (auto &cell_it : module->cells_) {
                RTLIL::Cell *cell = cell_it.second;
-               if (cell->type.in("$memrd", "$memwr", "$meminit") && memory->name == cell->parameters["\\MEMID"].decode_string())
+               if (cell->type.in("$memrd", "$memwr", "$meminit") && memory->name == cell->parameters["\\MEMID"].decode_string()) {
+                       addr_bits = std::max(addr_bits, cell->getParam("\\ABITS").as_int());
                        memcells.push_back(cell);
+               }
+       }
+
+       if (memcells.empty()) {
+               log("  no cells found. removing memory.\n");
+               return;
        }
 
        std::sort(memcells.begin(), memcells.end(), memcells_cmp);
index 18c60ea074b052d033f2914779f966ba417abd79..41c4a7b124cee77a08928fa497e0aeb457bc4bb4 100644 (file)
@@ -83,7 +83,7 @@ struct MemoryMapWorker
 
                int mem_size = cell->parameters["\\SIZE"].as_int();
                int mem_width = cell->parameters["\\WIDTH"].as_int();
-               // int mem_offset = cell->parameters["\\OFFSET"].as_int();
+               int mem_offset = cell->parameters["\\OFFSET"].as_int();
                int mem_abits = cell->parameters["\\ABITS"].as_int();
 
                SigSpec init_data = cell->getParam("\\INIT");
@@ -114,7 +114,7 @@ struct MemoryMapWorker
                                        // FIXME: Actually we should check for wr_en.is_fully_const() also and
                                        // create a $adff cell with this ports wr_en input as reset pin when wr_en
                                        // is not a simple static 1.
-                                       static_cells_map[wr_addr.as_int()] = wr_data;
+                                       static_cells_map[wr_addr.as_int() - mem_offset] = wr_data;
                                        static_ports.insert(i);
                                        continue;
                                }
@@ -187,6 +187,9 @@ struct MemoryMapWorker
                {
                        RTLIL::SigSpec rd_addr = cell->getPort("\\RD_ADDR").extract(i*mem_abits, mem_abits);
 
+                       if (mem_offset)
+                               rd_addr = module->Sub(NEW_ID, rd_addr, SigSpec(mem_offset, GetSize(rd_addr)));
+
                        std::vector<RTLIL::SigSpec> rd_signals;
                        rd_signals.push_back(cell->getPort("\\RD_DATA").extract(i*mem_width, mem_width));
 
@@ -263,6 +266,10 @@ struct MemoryMapWorker
                                RTLIL::SigSpec wr_addr = cell->getPort("\\WR_ADDR").extract(j*mem_abits, mem_abits);
                                RTLIL::SigSpec wr_data = cell->getPort("\\WR_DATA").extract(j*mem_width, mem_width);
                                RTLIL::SigSpec wr_en = cell->getPort("\\WR_EN").extract(j*mem_width, mem_width);
+
+                               if (mem_offset)
+                                       wr_addr = module->Sub(NEW_ID, wr_addr, SigSpec(mem_offset, GetSize(wr_addr)));
+
                                RTLIL::Wire *w_seladdr = addr_decode(wr_addr, RTLIL::SigSpec(i, mem_abits));
 
                                int wr_offset = 0;
index 23e93ac91a38acb391ee4962c6ea7bd8a6168b74..67f89cd75639f8f852f54ebb5379aa5052df9c89 100644 (file)
@@ -213,7 +213,7 @@ module memtest09 (
     input a_wen, b_wen,
     output reg [3:0] a_dout, b_dout
 );
-    reg [3:0] memory [0:35];
+    reg [3:0] memory [10:35];
 
     always @(posedge clk) begin
         if (a_wen)
@@ -222,7 +222,7 @@ module memtest09 (
     end
 
     always @(posedge clk) begin
-        if (b_wen && (10 + a_addr != 20 + b_addr))
+        if (b_wen && (10 + a_addr != 20 + b_addr || !a_wen))
             memory[20 + b_addr] <= b_din;
         b_dout <= memory[20 + b_addr];
     end