mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Added connwrappers command
This commit is contained in:
		
							parent
							
								
									4bd25edcd4
								
							
						
					
					
						commit
						0dadfed46d
					
				
					 2 changed files with 206 additions and 0 deletions
				
			
		|  | @ -15,4 +15,5 @@ OBJS += passes/cmds/copy.o | |||
| OBJS += passes/cmds/splice.o | ||||
| OBJS += passes/cmds/scc.o | ||||
| OBJS += passes/cmds/log.o | ||||
| OBJS += passes/cmds/connwrappers.o | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										205
									
								
								passes/cmds/connwrappers.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								passes/cmds/connwrappers.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,205 @@ | |||
| /*
 | ||||
|  *  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/sigtools.h" | ||||
| #include "kernel/rtlil.h" | ||||
| #include "kernel/log.h" | ||||
| 
 | ||||
| struct ConnwrappersWorker | ||||
| { | ||||
| 	struct portdecl_t { | ||||
| 		// key: celltype, portname;
 | ||||
| 		std::string widthparam, signparam; | ||||
| 		bool is_signed; | ||||
| 	}; | ||||
| 
 | ||||
| 	std::set<std::string> decl_celltypes; | ||||
| 	std::map<std::pair<std::string, std::string>, portdecl_t> decls; | ||||
| 
 | ||||
| 	void add_port(std::string celltype, std::string portname, std::string widthparam, std::string signparam) | ||||
| 	{ | ||||
| 		std::pair<std::string, std::string> key(RTLIL::escape_id(celltype), RTLIL::escape_id(portname)); | ||||
| 		decl_celltypes.insert(key.first); | ||||
| 
 | ||||
| 		if (decls.count(key)) | ||||
| 			log_cmd_error("Duplicate port decl: %s %s\n", celltype.c_str(), portname.c_str()); | ||||
| 
 | ||||
| 		portdecl_t decl; | ||||
| 		decl.widthparam = RTLIL::escape_id(widthparam); | ||||
| 		decl.signparam = RTLIL::escape_id(signparam); | ||||
| 		decl.is_signed = false; | ||||
| 		decls[key] = decl; | ||||
| 	} | ||||
| 
 | ||||
| 	void add_port(std::string celltype, std::string portname, std::string widthparam, bool is_signed) | ||||
| 	{ | ||||
| 		std::pair<std::string, std::string> key(RTLIL::escape_id(celltype), RTLIL::escape_id(portname)); | ||||
| 		decl_celltypes.insert(key.first); | ||||
| 
 | ||||
| 		if (decls.count(key)) | ||||
| 			log_cmd_error("Duplicate port decl: %s %s\n", celltype.c_str(), portname.c_str()); | ||||
| 
 | ||||
| 		portdecl_t decl; | ||||
| 		decl.widthparam = RTLIL::escape_id(widthparam); | ||||
| 		decl.is_signed = is_signed; | ||||
| 		decls[key] = decl; | ||||
| 	} | ||||
| 
 | ||||
| 	void work(RTLIL::Design *design, RTLIL::Module *module) | ||||
| 	{ | ||||
| 		std::map<RTLIL::SigBit, std::pair<bool, RTLIL::SigSpec>> extend_map; | ||||
| 		SigMap sigmap(module); | ||||
| 
 | ||||
| 		for (auto &it : module->cells) | ||||
| 		{ | ||||
| 			RTLIL::Cell *cell = it.second; | ||||
| 
 | ||||
| 			if (!decl_celltypes.count(cell->type)) | ||||
| 				continue; | ||||
| 
 | ||||
| 			for (auto &conn : cell->connections) | ||||
| 			{ | ||||
| 				std::pair<std::string, std::string> key(cell->type, conn.first); | ||||
| 
 | ||||
| 				if (!decls.count(key)) | ||||
| 					continue; | ||||
| 
 | ||||
| 				portdecl_t &decl = decls.at(key); | ||||
| 
 | ||||
| 				if (!cell->parameters.count(decl.widthparam)) | ||||
| 					continue; | ||||
| 
 | ||||
| 				if (!decl.signparam.empty() && !cell->parameters.count(decl.signparam)) | ||||
| 					continue; | ||||
| 
 | ||||
| 				int inner_width = cell->parameters.at(decl.widthparam).as_int(); | ||||
| 				int outer_width = conn.second.width; | ||||
| 				bool is_signed = decl.signparam.empty() ? decl.is_signed : cell->parameters.at(decl.signparam).as_bool(); | ||||
| 
 | ||||
| 				if (inner_width >= outer_width) | ||||
| 					continue; | ||||
| 
 | ||||
| 				RTLIL::SigSpec sig = sigmap(conn.second); | ||||
| 				extend_map[sig.extract(inner_width - 1, 1)] = std::pair<bool, RTLIL::SigSpec>(is_signed, | ||||
| 						sig.extract(inner_width, outer_width - inner_width)); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto &it : module->cells) | ||||
| 		{ | ||||
| 			RTLIL::Cell *cell = it.second; | ||||
| 
 | ||||
| 			if (!design->selected(module, cell)) | ||||
| 				continue; | ||||
| 
 | ||||
| 			for (auto &conn : cell->connections) | ||||
| 			{ | ||||
| 				std::vector<RTLIL::SigBit> sigbits = sigmap(conn.second).to_sigbit_vector(); | ||||
| 				RTLIL::SigSpec old_sig; | ||||
| 
 | ||||
| 				for (size_t i = 0; i < sigbits.size(); i++) | ||||
| 				{ | ||||
| 					if (!extend_map.count(sigbits[i])) | ||||
| 						continue; | ||||
| 
 | ||||
| 					bool is_signed = extend_map.at(sigbits[i]).first; | ||||
| 					RTLIL::SigSpec extend_sig = extend_map.at(sigbits[i]).second; | ||||
| 
 | ||||
| 					int extend_width = 0; | ||||
| 					RTLIL::SigBit extend_bit = is_signed ? sigbits[i] : RTLIL::SigBit(RTLIL::State::S0); | ||||
| 					while (extend_width < extend_sig.width && i + extend_width + 1 < sigbits.size() && | ||||
| 							sigbits[i + extend_width + 1] == extend_bit) extend_width++; | ||||
| 
 | ||||
| 					if (extend_width == 0) | ||||
| 						continue; | ||||
| 
 | ||||
| 					if (old_sig.width == 0) | ||||
| 						old_sig = conn.second; | ||||
| 
 | ||||
| 					conn.second.replace(i+1, extend_sig.extract(0, extend_width)); | ||||
| 					i += extend_width; | ||||
| 				} | ||||
| 
 | ||||
| 				if (old_sig.width) | ||||
| 					log("Connected extended bits of %s.%s:%s: %s -> %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), | ||||
| 							RTLIL::id2cstr(conn.first), log_signal(old_sig), log_signal(conn.second)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| struct ConnwrappersPass : public Pass { | ||||
| 	ConnwrappersPass() : Pass("connwrappers", "replace undef values with defined constants") { } | ||||
| 	virtual void help() | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    connwrappers [options] [selection]\n"); | ||||
| 		log("\n"); | ||||
| 		log("Wrappers are used in coarse-grain synthesis to wrap cells with smaller ports\n"); | ||||
| 		log("in wrapper cells with a (larger) constant port size. I.e. the upper bits\n"); | ||||
| 		log("of the wrapper outut are signed/unsigned bit extended. This command uses this\n"); | ||||
| 		log("knowlege to rewire the inputs of the driven cells to match the output of\n"); | ||||
| 		log("the driving cell.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -signed <cell_type> <port_name> <width_param>\n"); | ||||
| 		log("    -unsigned <cell_type> <port_name> <width_param>\n"); | ||||
| 		log("        consider the specified signed/unsigned wrapper output\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -port <cell_type> <port_name> <width_param> <sign_param>\n"); | ||||
| 		log("        use the specified parameter to decide if signed or unsigned\n"); | ||||
| 		log("\n"); | ||||
| 		log("The options -signed, -unsigned, and -port can be specified multiple times.\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		ConnwrappersWorker worker; | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
| 		{ | ||||
| 			if (args[argidx] == "-signed" && argidx+3 < args.size()) { | ||||
| 				worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], true); | ||||
| 				argidx += 3; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-unsigned" && argidx+3 < args.size()) { | ||||
| 				worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], false); | ||||
| 				argidx += 3; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-port" && argidx+4 < args.size()) { | ||||
| 				worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], args[argidx+4]); | ||||
| 				argidx += 4; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		log_header("Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n"); | ||||
| 
 | ||||
| 		for (auto &mod_it : design->modules) | ||||
| 			if (design->selected(mod_it.second)) | ||||
| 				worker.work(design, mod_it.second); | ||||
| 	} | ||||
| } ConnwrappersPass; | ||||
|   | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue