From e9368a1d7e13bc691f86f25cd80981110b937cab Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 14 Feb 2015 14:21:15 +0100 Subject: [PATCH] Various fixes for memories with offsets --- frontends/ast/genrtlil.cc | 10 ++++------ frontends/ast/simplify.cc | 1 + passes/memory/memory_collect.cc | 11 ++++++++--- passes/memory/memory_map.cc | 11 +++++++++-- tests/simple/memory.v | 4 ++-- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 7a78743b9..4b3310501 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -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)); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 10b651000..095649729 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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) diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index d0d32f504..96d0ada03 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -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); diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index 18c60ea07..41c4a7b12 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -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 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; diff --git a/tests/simple/memory.v b/tests/simple/memory.v index 23e93ac91..67f89cd75 100644 --- a/tests/simple/memory.v +++ b/tests/simple/memory.v @@ -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 -- 2.30.2