diff options
author | Clifford Wolf <clifford@clifford.at> | 2015-02-14 12:55:03 +0100 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2015-02-14 12:55:03 +0100 |
commit | dcf2e242406d563254013ea7db4b29b55be96eff (patch) | |
tree | ad242e2b5273a775752a2398171c178df89f9e2a /passes | |
parent | 913c304fe62cb962e32fa0eb024fa4fc3110639c (diff) |
Added $meminit support to "memory" command
Diffstat (limited to 'passes')
-rw-r--r-- | passes/memory/memory_bram.cc | 5 | ||||
-rw-r--r-- | passes/memory/memory_collect.cc | 83 | ||||
-rw-r--r-- | passes/memory/memory_map.cc | 11 |
3 files changed, 69 insertions, 30 deletions
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 8f421402..958cc88b 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -905,6 +905,11 @@ void handle_cell(Cell *cell, const rules_t &rules) { log("Processing %s.%s:\n", log_id(cell->module), log_id(cell)); + if (!SigSpec(cell->getParam("\\INIT")).is_fully_undef()) { + log(" initialized memories are not supported yet."); + return; + } + dict<string, int> match_properties; match_properties["words"] = cell->getParam("\\SIZE").as_int(); match_properties["abits"] = cell->getParam("\\ABITS").as_int(); diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index ccc19620..d0d32f50 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -17,11 +17,8 @@ * */ -#include "kernel/register.h" -#include "kernel/log.h" -#include <sstream> -#include <algorithm> -#include <stdlib.h> +#include "kernel/yosys.h" +#include "kernel/sigtools.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -37,13 +34,16 @@ bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b) void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) { - log("Collecting $memrd and $memwr for memory `%s' in module `%s':\n", + 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; while ((1 << addr_bits) < memory->size) addr_bits++; + Const init_data(State::Sx, memory->size * memory->width); + SigMap sigmap(module); + int wr_ports = 0; RTLIL::SigSpec sig_wr_clk; RTLIL::SigSpec sig_wr_clk_enable; @@ -60,12 +60,11 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) RTLIL::SigSpec sig_rd_addr; RTLIL::SigSpec sig_rd_data; - std::vector<RTLIL::Cell*> del_cells; std::vector<RTLIL::Cell*> memcells; for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if ((cell->type == "$memwr" || cell->type == "$memrd") && memory->name == cell->parameters["\\MEMID"].decode_string()) + if (cell->type.in("$memrd", "$memwr", "$meminit") && memory->name == cell->parameters["\\MEMID"].decode_string()) memcells.push_back(cell); } @@ -73,17 +72,38 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) for (auto cell : memcells) { - if (cell->type == "$memwr" && memory->name == cell->parameters["\\MEMID"].decode_string()) + log(" %s (%s)\n", log_id(cell), log_id(cell->type)); + + if (cell->type == "$meminit") { - wr_ports++; - del_cells.push_back(cell); + SigSpec addr = sigmap(cell->getPort("\\ADDR")); + SigSpec data = sigmap(cell->getPort("\\DATA")); + + if (!addr.is_fully_const()) + log_error("Non-constant address %s in memory initialization %s.\n", log_signal(addr), log_id(cell)); + if (!data.is_fully_const()) + log_error("Non-constant data %s in memory initialization %s.\n", log_signal(data), log_id(cell)); + + int offset = (addr.as_int() - memory->start_offset) * memory->width; - RTLIL::SigSpec clk = cell->getPort("\\CLK"); - RTLIL::SigSpec clk_enable = RTLIL::SigSpec(cell->parameters["\\CLK_ENABLE"]); - RTLIL::SigSpec clk_polarity = RTLIL::SigSpec(cell->parameters["\\CLK_POLARITY"]); - RTLIL::SigSpec addr = cell->getPort("\\ADDR"); - RTLIL::SigSpec data = cell->getPort("\\DATA"); - RTLIL::SigSpec en = cell->getPort("\\EN"); + if (offset < 0 || offset + GetSize(data) > GetSize(init_data)) + log_warning("Address %s in memory initialization %s is out-of-bounds.\n", log_signal(addr), log_id(cell)); + + for (int i = 0; i < GetSize(data); i++) + if (0 <= i+offset && i+offset < GetSize(init_data)) + init_data.bits[i+offset] = data[i].data; + + continue; + } + + if (cell->type == "$memwr") + { + SigSpec clk = sigmap(cell->getPort("\\CLK")); + SigSpec clk_enable = RTLIL::SigSpec(cell->parameters["\\CLK_ENABLE"]); + SigSpec clk_polarity = RTLIL::SigSpec(cell->parameters["\\CLK_POLARITY"]); + SigSpec addr = sigmap(cell->getPort("\\ADDR")); + SigSpec data = sigmap(cell->getPort("\\DATA")); + SigSpec en = sigmap(cell->getPort("\\EN")); clk.extend_u0(1, false); clk_enable.extend_u0(1, false); @@ -98,19 +118,19 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) sig_wr_addr.append(addr); sig_wr_data.append(data); sig_wr_en.append(en); + + wr_ports++; + continue; } - if (cell->type == "$memrd" && memory->name == cell->parameters["\\MEMID"].decode_string()) + if (cell->type == "$memrd") { - rd_ports++; - del_cells.push_back(cell); - - RTLIL::SigSpec clk = cell->getPort("\\CLK"); - RTLIL::SigSpec clk_enable = RTLIL::SigSpec(cell->parameters["\\CLK_ENABLE"]); - RTLIL::SigSpec clk_polarity = RTLIL::SigSpec(cell->parameters["\\CLK_POLARITY"]); - RTLIL::SigSpec transparent = RTLIL::SigSpec(cell->parameters["\\TRANSPARENT"]); - RTLIL::SigSpec addr = cell->getPort("\\ADDR"); - RTLIL::SigSpec data = cell->getPort("\\DATA"); + SigSpec clk = sigmap(cell->getPort("\\CLK")); + SigSpec clk_enable = RTLIL::SigSpec(cell->parameters["\\CLK_ENABLE"]); + SigSpec clk_polarity = RTLIL::SigSpec(cell->parameters["\\CLK_POLARITY"]); + SigSpec transparent = RTLIL::SigSpec(cell->parameters["\\TRANSPARENT"]); + SigSpec addr = sigmap(cell->getPort("\\ADDR")); + SigSpec data = sigmap(cell->getPort("\\DATA")); clk.extend_u0(1, false); clk_enable.extend_u0(1, false); @@ -125,6 +145,9 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) sig_rd_transparent.append(transparent); sig_rd_addr.append(addr); sig_rd_data.append(data); + + rd_ports++; + continue; } } @@ -138,6 +161,10 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) mem->parameters["\\SIZE"] = RTLIL::Const(memory->size); mem->parameters["\\ABITS"] = RTLIL::Const(addr_bits); + while (GetSize(init_data) > 1 && init_data.bits.back() == State::Sx && init_data.bits[GetSize(init_data)-2] == State::Sx) + init_data.bits.pop_back(); + mem->parameters["\\INIT"] = init_data; + log_assert(sig_wr_clk.size() == wr_ports); log_assert(sig_wr_clk_enable.size() == wr_ports && sig_wr_clk_enable.is_fully_const()); log_assert(sig_wr_clk_polarity.size() == wr_ports && sig_wr_clk_polarity.is_fully_const()); @@ -169,7 +196,7 @@ void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) mem->setPort("\\RD_ADDR", sig_rd_addr); mem->setPort("\\RD_DATA", sig_rd_data); - for (auto c : del_cells) + for (auto c : memcells) module->remove(c); } diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index 4fb10a98..18c60ea0 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -80,11 +80,15 @@ struct MemoryMapWorker { std::set<int> static_ports; std::map<int, RTLIL::SigSpec> static_cells_map; + 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"); + init_data.extend_u0(mem_size*mem_width, true); + // delete unused memory cell if (cell->parameters["\\RD_PORTS"].as_int() == 0 && cell->parameters["\\WR_PORTS"].as_int() == 0) { module->remove(cell); @@ -165,7 +169,10 @@ struct MemoryMapWorker w_out_name = genid(cell->name, "", i, "$q"); RTLIL::Wire *w_out = module->addWire(w_out_name, mem_width); - w_out->start_offset = mem_offset; + SigSpec w_init = init_data.extract(i*mem_width, mem_width); + + if (!w_init.is_fully_undef()) + w_out->attributes["\\init"] = w_init.as_const(); data_reg_out.push_back(RTLIL::SigSpec(w_out)); c->setPort("\\Q", data_reg_out.back()); |