diff options
author | Clifford Wolf <clifford@clifford.at> | 2016-08-19 19:48:26 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2016-08-19 19:48:26 +0200 |
commit | 15ef6084533809894dd0b5200a65497047c2ccf8 (patch) | |
tree | 63be8604471ff08a682c31b9cc182d93f1eb4973 /passes/memory | |
parent | f6629b9c29838879cec6a94d6cb47afc6fbd2db4 (diff) | |
download | yosys-15ef6084533809894dd0b5200a65497047c2ccf8.tar.gz yosys-15ef6084533809894dd0b5200a65497047c2ccf8.tar.bz2 yosys-15ef6084533809894dd0b5200a65497047c2ccf8.zip |
Added memory_memx pass, "memory -memx", and "prep -memx"
Diffstat (limited to 'passes/memory')
-rw-r--r-- | passes/memory/Makefile.inc | 1 | ||||
-rw-r--r-- | passes/memory/memory.cc | 13 | ||||
-rw-r--r-- | passes/memory/memory_memx.cc | 92 |
3 files changed, 104 insertions, 2 deletions
diff --git a/passes/memory/Makefile.inc b/passes/memory/Makefile.inc index aeff225d8..ad359c01b 100644 --- a/passes/memory/Makefile.inc +++ b/passes/memory/Makefile.inc @@ -6,4 +6,5 @@ OBJS += passes/memory/memory_collect.o OBJS += passes/memory/memory_unpack.o OBJS += passes/memory/memory_bram.o OBJS += passes/memory/memory_map.o +OBJS += passes/memory/memory_memx.o diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc index e3c627607..947d598be 100644 --- a/passes/memory/memory.cc +++ b/passes/memory/memory.cc @@ -31,14 +31,15 @@ struct MemoryPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" memory [-nomap] [-nordff] [-bram <bram_rules>] [selection]\n"); + log(" memory [-nomap] [-nordff] [-memx] [-bram <bram_rules>] [selection]\n"); log("\n"); log("This pass calls all the other memory_* passes in a useful order:\n"); log("\n"); - log(" memory_dff [-nordff]\n"); + log(" memory_dff [-nordff] (-memx implies -nordff)\n"); log(" opt_clean\n"); log(" memory_share\n"); log(" opt_clean\n"); + log(" memory_memx (when called with -memx)\n"); log(" memory_collect\n"); log(" memory_bram -rules <bram_rules> (when called with -bram)\n"); log(" memory_map (skipped if called with -nomap)\n"); @@ -51,6 +52,7 @@ struct MemoryPass : public Pass { { bool flag_nomap = false; bool flag_nordff = false; + bool flag_memx = false; string memory_bram_opts; log_header(design, "Executing MEMORY pass.\n"); @@ -66,6 +68,11 @@ struct MemoryPass : public Pass { flag_nordff = true; continue; } + if (args[argidx] == "-memx") { + flag_nordff = true; + flag_memx = true; + continue; + } if (argidx+1 < args.size() && args[argidx] == "-bram") { memory_bram_opts += " -rules " + args[++argidx]; continue; @@ -77,6 +84,8 @@ struct MemoryPass : public Pass { Pass::call(design, flag_nordff ? "memory_dff -nordff" : "memory_dff"); Pass::call(design, "opt_clean"); Pass::call(design, "memory_share"); + if (flag_memx) + Pass::call(design, "memory_memx"); Pass::call(design, "opt_clean"); Pass::call(design, "memory_collect"); diff --git a/passes/memory/memory_memx.cc b/passes/memory/memory_memx.cc new file mode 100644 index 000000000..2b02e2490 --- /dev/null +++ b/passes/memory/memory_memx.cc @@ -0,0 +1,92 @@ +/* + * 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 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/log.h" +#include <sstream> +#include <set> +#include <stdlib.h> + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct MemoryMemxPass : public Pass { + MemoryMemxPass() : Pass("memory_memx", "emulate vlog sim behavior for mem ports") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" memory_memx [selection]\n"); + log("\n"); + log("This pass adds additional circuitry that emulates the Verilog simulation\n"); + log("behavior for out-of-bounds memory reads and writes.\n"); + log("\n"); + } + virtual void execute(std::vector<std::string> args, RTLIL::Design *design) { + log_header(design, "Executing MEMORY_MEMX pass (converting $mem cells to logic and flip-flops).\n"); + extra_args(args, 1, design); + + for (auto module : design->selected_modules()) + { + vector<Cell*> mem_port_cells; + + for (auto cell : module->selected_cells()) + if (cell->type.in("$memrd", "$memwr")) + mem_port_cells.push_back(cell); + + for (auto cell : mem_port_cells) + { + IdString memid = cell->getParam("\\MEMID").decode_string(); + RTLIL::Memory *mem = module->memories.at(memid); + + int lowest_addr = mem->start_offset; + int highest_addr = mem->start_offset + mem->size - 1; + + SigSpec addr = cell->getPort("\\ADDR"); + addr.extend_u0(32); + + SigSpec addr_ok = module->Nex(NEW_ID, module->ReduceXor(NEW_ID, addr), module->ReduceXor(NEW_ID, {addr, State::S1})); + if (lowest_addr != 0) + addr_ok = module->LogicAnd(NEW_ID, addr_ok, module->Ge(NEW_ID, addr, lowest_addr)); + addr_ok = module->LogicAnd(NEW_ID, addr_ok, module->Le(NEW_ID, addr, highest_addr)); + + if (cell->type == "$memrd") + { + if (cell->getParam("\\CLK_ENABLE").as_bool()) + log_error("Cell %s.%s (%s) has an enabled clock. Clocked $memrd cells are not supported by memory_memx!\n", + log_id(module), log_id(cell), log_id(cell->type)); + + SigSpec rdata = cell->getPort("\\DATA"); + Wire *raw_rdata = module->addWire(NEW_ID, GetSize(rdata)); + module->addMux(NEW_ID, SigSpec(State::Sx, GetSize(rdata)), raw_rdata, addr_ok, rdata); + cell->setPort("\\DATA", raw_rdata); + } + + if (cell->type == "$memwr") + { + SigSpec en = cell->getPort("\\EN"); + en = module->And(NEW_ID, en, addr_ok.repeat(GetSize(en))); + cell->setPort("\\EN", en); + } + } + } + } +} MemoryMemxPass; + +PRIVATE_NAMESPACE_END |