mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Added memory_memx pass, "memory -memx", and "prep -memx"
This commit is contained in:
		
							parent
							
								
									f6629b9c29
								
							
						
					
					
						commit
						15ef608453
					
				
					 4 changed files with 121 additions and 4 deletions
				
			
		|  | @ -6,4 +6,5 @@ OBJS += passes/memory/memory_collect.o | ||||||
| OBJS += passes/memory/memory_unpack.o | OBJS += passes/memory/memory_unpack.o | ||||||
| OBJS += passes/memory/memory_bram.o | OBJS += passes/memory/memory_bram.o | ||||||
| OBJS += passes/memory/memory_map.o | OBJS += passes/memory/memory_map.o | ||||||
|  | OBJS += passes/memory/memory_memx.o | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -31,14 +31,15 @@ struct MemoryPass : public Pass { | ||||||
| 	{ | 	{ | ||||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    memory [-nomap] [-nordff] [-bram <bram_rules>] [selection]\n"); | 		log("    memory [-nomap] [-nordff] [-memx] [-bram <bram_rules>] [selection]\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("This pass calls all the other memory_* passes in a useful order:\n"); | 		log("This pass calls all the other memory_* passes in a useful order:\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    memory_dff [-nordff]\n"); | 		log("    memory_dff [-nordff]                (-memx implies -nordff)\n"); | ||||||
| 		log("    opt_clean\n"); | 		log("    opt_clean\n"); | ||||||
| 		log("    memory_share\n"); | 		log("    memory_share\n"); | ||||||
| 		log("    opt_clean\n"); | 		log("    opt_clean\n"); | ||||||
|  | 		log("    memory_memx                         (when called with -memx)\n"); | ||||||
| 		log("    memory_collect\n"); | 		log("    memory_collect\n"); | ||||||
| 		log("    memory_bram -rules <bram_rules>     (when called with -bram)\n"); | 		log("    memory_bram -rules <bram_rules>     (when called with -bram)\n"); | ||||||
| 		log("    memory_map                          (skipped if called with -nomap)\n"); | 		log("    memory_map                          (skipped if called with -nomap)\n"); | ||||||
|  | @ -51,6 +52,7 @@ struct MemoryPass : public Pass { | ||||||
| 	{ | 	{ | ||||||
| 		bool flag_nomap = false; | 		bool flag_nomap = false; | ||||||
| 		bool flag_nordff = false; | 		bool flag_nordff = false; | ||||||
|  | 		bool flag_memx = false; | ||||||
| 		string memory_bram_opts; | 		string memory_bram_opts; | ||||||
| 
 | 
 | ||||||
| 		log_header(design, "Executing MEMORY pass.\n"); | 		log_header(design, "Executing MEMORY pass.\n"); | ||||||
|  | @ -66,6 +68,11 @@ struct MemoryPass : public Pass { | ||||||
| 				flag_nordff = true; | 				flag_nordff = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-memx") { | ||||||
|  | 				flag_nordff = true; | ||||||
|  | 				flag_memx = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			if (argidx+1 < args.size() && args[argidx] == "-bram") { | 			if (argidx+1 < args.size() && args[argidx] == "-bram") { | ||||||
| 				memory_bram_opts += " -rules " + args[++argidx]; | 				memory_bram_opts += " -rules " + args[++argidx]; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -77,6 +84,8 @@ struct MemoryPass : public Pass { | ||||||
| 		Pass::call(design, flag_nordff ? "memory_dff -nordff" : "memory_dff"); | 		Pass::call(design, flag_nordff ? "memory_dff -nordff" : "memory_dff"); | ||||||
| 		Pass::call(design, "opt_clean"); | 		Pass::call(design, "opt_clean"); | ||||||
| 		Pass::call(design, "memory_share"); | 		Pass::call(design, "memory_share"); | ||||||
|  | 		if (flag_memx) | ||||||
|  | 			Pass::call(design, "memory_memx"); | ||||||
| 		Pass::call(design, "opt_clean"); | 		Pass::call(design, "opt_clean"); | ||||||
| 		Pass::call(design, "memory_collect"); | 		Pass::call(design, "memory_collect"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										92
									
								
								passes/memory/memory_memx.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								passes/memory/memory_memx.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||||
|  | @ -53,6 +53,10 @@ struct PrepPass : public ScriptPass | ||||||
| 		log("        passed to 'proc'. uses verilog simulation behavior for verilog if/case\n"); | 		log("        passed to 'proc'. uses verilog simulation behavior for verilog if/case\n"); | ||||||
| 		log("        undef handling. this also prevents 'wreduce' from being run.\n"); | 		log("        undef handling. this also prevents 'wreduce' from being run.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -memx\n"); | ||||||
|  | 		log("        simulate verilog simulation behavior for out-of-bounds memory accesses\n"); | ||||||
|  | 		log("        using the 'memory_memx' pass. This option implies -nordff.\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("    -nordff\n"); | 		log("    -nordff\n"); | ||||||
| 		log("        passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n"); | 		log("        passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | @ -68,7 +72,7 @@ struct PrepPass : public ScriptPass | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	string top_module, fsm_opts, memory_opts; | 	string top_module, fsm_opts, memory_opts; | ||||||
| 	bool autotop, flatten, ifxmode; | 	bool autotop, flatten, ifxmode, memxmode; | ||||||
| 
 | 
 | ||||||
| 	virtual void clear_flags() YS_OVERRIDE | 	virtual void clear_flags() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
|  | @ -78,6 +82,7 @@ struct PrepPass : public ScriptPass | ||||||
| 		autotop = false; | 		autotop = false; | ||||||
| 		flatten = false; | 		flatten = false; | ||||||
| 		ifxmode = false; | 		ifxmode = false; | ||||||
|  | 		memxmode = false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
|  | @ -114,6 +119,11 @@ struct PrepPass : public ScriptPass | ||||||
| 				ifxmode = true; | 				ifxmode = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-memx") { | ||||||
|  | 				memxmode = true; | ||||||
|  | 				memory_opts += " -nordff"; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			if (args[argidx] == "-nordff") { | 			if (args[argidx] == "-nordff") { | ||||||
| 				memory_opts += " -nordff"; | 				memory_opts += " -nordff"; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -153,7 +163,10 @@ struct PrepPass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 		if (check_label("coarse")) | 		if (check_label("coarse")) | ||||||
| 		{ | 		{ | ||||||
| 			run(ifxmode ? "proc -ifx" : "proc"); | 			if (help_mode) | ||||||
|  | 				run("proc [-ifx]"); | ||||||
|  | 			else | ||||||
|  | 				run(ifxmode ? "proc -ifx" : "proc"); | ||||||
| 			if (help_mode || flatten) | 			if (help_mode || flatten) | ||||||
| 				run("flatten", "(if -flatten)"); | 				run("flatten", "(if -flatten)"); | ||||||
| 			run("opt_expr -keepdc"); | 			run("opt_expr -keepdc"); | ||||||
|  | @ -163,6 +176,8 @@ struct PrepPass : public ScriptPass | ||||||
| 			if (!ifxmode) | 			if (!ifxmode) | ||||||
| 				run("wreduce"); | 				run("wreduce"); | ||||||
| 			run("memory_dff" + (help_mode ? " [-nordff]" : memory_opts)); | 			run("memory_dff" + (help_mode ? " [-nordff]" : memory_opts)); | ||||||
|  | 			if (help_mode || memxmode) | ||||||
|  | 				run("memory_memx", "(if -memx)"); | ||||||
| 			run("opt_clean"); | 			run("opt_clean"); | ||||||
| 			run("memory_collect"); | 			run("memory_collect"); | ||||||
| 			run("opt -keepdc -fast"); | 			run("opt -keepdc -fast"); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue