diff options
Diffstat (limited to 'passes/memory/memory_unpack.cc')
-rw-r--r-- | passes/memory/memory_unpack.cc | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc index e650facb4..a0fc31b5e 100644 --- a/passes/memory/memory_unpack.cc +++ b/passes/memory/memory_unpack.cc @@ -2,11 +2,11 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> - * + * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -57,6 +57,7 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) cell->parameters["\\CLK_POLARITY"] = RTLIL::SigSpec(memory->parameters.at("\\RD_CLK_POLARITY")).extract(i, 1).as_const(); cell->parameters["\\TRANSPARENT"] = RTLIL::SigSpec(memory->parameters.at("\\RD_TRANSPARENT")).extract(i, 1).as_const(); cell->setPort("\\CLK", memory->getPort("\\RD_CLK").extract(i, 1)); + cell->setPort("\\EN", memory->getPort("\\RD_EN").extract(i, 1)); cell->setPort("\\ADDR", memory->getPort("\\RD_ADDR").extract(i*abits, abits)); cell->setPort("\\DATA", memory->getPort("\\RD_DATA").extract(i*mem->width, mem->width)); } @@ -76,6 +77,41 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) cell->setPort("\\DATA", memory->getPort("\\WR_DATA").extract(i*mem->width, mem->width)); } + Const initval = memory->parameters.at("\\INIT"); + RTLIL::Cell *last_init_cell = nullptr; + SigSpec last_init_data; + int last_init_addr=0; + + for (int i = 0; i < GetSize(initval) && i/mem->width < (1 << abits); i += mem->width) { + Const val = initval.extract(i, mem->width, State::Sx); + for (auto bit : val.bits) + if (bit != State::Sx) + goto found_non_undef_initval; + continue; + found_non_undef_initval: + if (last_init_cell && last_init_addr+1 == i/mem->width) { + last_init_cell->parameters["\\WORDS"] = last_init_cell->parameters["\\WORDS"].as_int() + 1; + last_init_data.append(val); + last_init_addr++; + } else { + if (last_init_cell) + last_init_cell->setPort("\\DATA", last_init_data); + RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit"); + cell->parameters["\\MEMID"] = mem_name.str(); + cell->parameters["\\ABITS"] = memory->parameters.at("\\ABITS"); + cell->parameters["\\WIDTH"] = memory->parameters.at("\\WIDTH"); + cell->parameters["\\WORDS"] = 1; + cell->parameters["\\PRIORITY"] = i/mem->width; + cell->setPort("\\ADDR", SigSpec(i/mem->width, abits)); + last_init_cell = cell; + last_init_addr = i/mem->width; + last_init_data = val; + } + } + + if (last_init_cell) + last_init_cell->setPort("\\DATA", last_init_data); + module->remove(memory); } @@ -102,12 +138,12 @@ struct MemoryUnpackPass : public Pass { log("\n"); } virtual void execute(std::vector<std::string> args, RTLIL::Design *design) { - log_header("Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n"); + log_header(design, "Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n"); extra_args(args, 1, design); for (auto &mod_it : design->modules_) if (design->selected(mod_it.second)) handle_module(design, mod_it.second); } } MemoryUnpackPass; - + PRIVATE_NAMESPACE_END |