mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Added "write_smv" skeleton
This commit is contained in:
		
							parent
							
								
									93685a77c6
								
							
						
					
					
						commit
						ea23bb8aa4
					
				
					 3 changed files with 265 additions and 2 deletions
				
			
		
							
								
								
									
										3
									
								
								backends/smv/Makefile.inc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								backends/smv/Makefile.inc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | 
 | ||||||
|  | OBJS += backends/smv/smv.o | ||||||
|  | 
 | ||||||
							
								
								
									
										258
									
								
								backends/smv/smv.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								backends/smv/smv.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,258 @@ | ||||||
|  | /*
 | ||||||
|  |  *  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/rtlil.h" | ||||||
|  | #include "kernel/register.h" | ||||||
|  | #include "kernel/sigtools.h" | ||||||
|  | #include "kernel/celltypes.h" | ||||||
|  | #include "kernel/log.h" | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | USING_YOSYS_NAMESPACE | ||||||
|  | PRIVATE_NAMESPACE_BEGIN | ||||||
|  | 
 | ||||||
|  | struct SmvWorker | ||||||
|  | { | ||||||
|  | 	CellTypes ct; | ||||||
|  | 	SigMap sigmap; | ||||||
|  | 	RTLIL::Module *module; | ||||||
|  | 	std::ostream &f; | ||||||
|  | 	bool verbose; | ||||||
|  | 
 | ||||||
|  | 	int idcounter; | ||||||
|  | 	dict<IdString, shared_str> idcache; | ||||||
|  | 	pool<shared_str> used_names; | ||||||
|  | 
 | ||||||
|  | 	const char *cid() | ||||||
|  | 	{ | ||||||
|  | 		while (true) { | ||||||
|  | 			shared_str s(stringf("_%d", idcounter++)); | ||||||
|  | 			if (!used_names.count(s)) { | ||||||
|  | 				used_names.insert(s); | ||||||
|  | 				return s.c_str(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const char *cid(IdString id, bool precache = false) | ||||||
|  | 	{ | ||||||
|  | 		if (!idcache.count(id)) | ||||||
|  | 		{ | ||||||
|  | 			string name = log_id(id); | ||||||
|  | 
 | ||||||
|  | 			for (auto &c : name) { | ||||||
|  | 				if (c >= 'a' && c <='z') continue; | ||||||
|  | 				if (c >= 'A' && c <='Z') continue; | ||||||
|  | 				if (c >= '0' && c <='9') continue; | ||||||
|  | 				if (precache) return nullptr; | ||||||
|  | 				c = '_'; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			while (used_names.count(name)) | ||||||
|  | 				name += "_"; | ||||||
|  | 
 | ||||||
|  | 			shared_str s(name); | ||||||
|  | 			used_names.insert(s); | ||||||
|  | 			idcache[id] = s; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return idcache.at(id).c_str(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SmvWorker(RTLIL::Module *module, bool verbose, std::ostream &f) : | ||||||
|  | 			ct(module->design), sigmap(module), module(module), f(f), verbose(verbose), idcounter(0) | ||||||
|  | 	{ | ||||||
|  | 		for (auto mod : module->design->modules()) | ||||||
|  | 			cid(mod->name, true); | ||||||
|  | 
 | ||||||
|  | 		for (auto wire : module->wires()) | ||||||
|  | 			cid(wire->name, true); | ||||||
|  | 
 | ||||||
|  | 		for (auto cell : module->cells()) { | ||||||
|  | 			cid(cell->name, true); | ||||||
|  | 			cid(cell->type, true); | ||||||
|  | 			for (auto &conn : cell->connections()) | ||||||
|  | 				cid(conn.first, true); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	string rvalue(SigSpec sig) | ||||||
|  | 	{ | ||||||
|  | 		string s; | ||||||
|  | 		sigmap.apply(sig); | ||||||
|  | 		for (auto &c : sig.chunks()) { | ||||||
|  | 			if (!s.empty()) | ||||||
|  | 				s += " :: "; | ||||||
|  | 			if (c.wire) { | ||||||
|  | 				s += cid(c.wire->name); | ||||||
|  | 				if (c.offset != 0 || c.width != c.wire->width) | ||||||
|  | 					s += stringf("[%d:%d]", c.offset+c.width-1, c.offset); | ||||||
|  | 			} else { | ||||||
|  | 				s += stringf("0ub%d_", c.width); | ||||||
|  | 				for (int i = c.width-1; i >= 0; i--) | ||||||
|  | 					s += c.data.at(i) == State::S1 ? '1' : '0'; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return s; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	string lvalue(SigSpec sig) | ||||||
|  | 	{ | ||||||
|  | 		if (sig.is_wire()) | ||||||
|  | 			return rvalue(sig); | ||||||
|  | 
 | ||||||
|  | 		log_error("Can not generate lvalue for singal %s. Try running 'splice'.\n", log_signal(sig)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void run() | ||||||
|  | 	{ | ||||||
|  | 		vector<string> assignments; | ||||||
|  | 
 | ||||||
|  | 		f << stringf("MODULE %s\n", cid(module->name)); | ||||||
|  | 		f << stringf("  VAR\n"); | ||||||
|  | 
 | ||||||
|  | 		for (auto wire : module->wires()) | ||||||
|  | 			f << stringf("    %s : unsigned word[%d];\n", cid(wire->name), wire->width); | ||||||
|  | 
 | ||||||
|  | 		for (auto cell : module->cells()) | ||||||
|  | 		{ | ||||||
|  | 			f << stringf("    %s : %s;\n", cid(cell->name), cid(cell->type)); | ||||||
|  | 
 | ||||||
|  | 			for (auto &conn : cell->connections()) | ||||||
|  | 				if (cell->output(conn.first)) | ||||||
|  | 					assignments.push_back(stringf("%s := %s.%s;", lvalue(conn.second).c_str(), cid(cell->name), cid(conn.first))); | ||||||
|  | 				else | ||||||
|  | 					assignments.push_back(stringf("%s.%s := %s;", cid(cell->name), cid(conn.first), rvalue(conn.second).c_str())); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		f << stringf("  ASSIGN\n"); | ||||||
|  | 		for (const string &line : assignments) | ||||||
|  | 			f << stringf("    %s\n", line.c_str()); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SmvBackend : public Backend { | ||||||
|  | 	SmvBackend() : Backend("smv", "write design to SMV file") { } | ||||||
|  | 	virtual void help() | ||||||
|  | 	{ | ||||||
|  | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    write_smv [options] [filename]\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("Write an SMV description of the current design.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -verbose\n"); | ||||||
|  | 		log("        this will print the recursive walk used to export the modules.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -tpl <template_file>\n"); | ||||||
|  | 		log("        use the given template file. the line containing only the token '%%%%'\n"); | ||||||
|  | 		log("        is replaced with the regular output of this command.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("THIS COMMAND IS UNDER CONSTRUCTION\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 	} | ||||||
|  | 	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||||
|  | 	{ | ||||||
|  | 		std::ifstream template_f; | ||||||
|  | 		bool verbose = false; | ||||||
|  | 
 | ||||||
|  | 		log_header("Executing SMV backend.\n"); | ||||||
|  | 
 | ||||||
|  | 		size_t argidx; | ||||||
|  | 		for (argidx = 1; argidx < args.size(); argidx++) | ||||||
|  | 		{ | ||||||
|  | 			if (args[argidx] == "-tpl" && argidx+1 < args.size()) { | ||||||
|  | 				template_f.open(args[++argidx]); | ||||||
|  | 				if (template_f.fail()) | ||||||
|  | 					log_error("Can't open template file `%s'.\n", args[argidx].c_str()); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (args[argidx] == "-verbose") { | ||||||
|  | 				verbose = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		extra_args(f, filename, args, argidx); | ||||||
|  | 
 | ||||||
|  | 		pool<Module*> modules; | ||||||
|  | 
 | ||||||
|  | 		for (auto module : design->modules()) | ||||||
|  | 			if (!module->get_bool_attribute("\\blackbox") && !module->has_memories_warn() && !module->has_processes_warn()) | ||||||
|  | 				modules.insert(module); | ||||||
|  | 
 | ||||||
|  | 		if (template_f.is_open()) | ||||||
|  | 		{ | ||||||
|  | 			std::string line; | ||||||
|  | 			while (std::getline(template_f, line)) | ||||||
|  | 			{ | ||||||
|  | 				int indent = 0; | ||||||
|  | 				while (indent < GetSize(line) && (line[indent] == ' ' || line[indent] == '\t')) | ||||||
|  | 					indent++; | ||||||
|  | 
 | ||||||
|  | 				if (line[indent] == '$') | ||||||
|  | 				{ | ||||||
|  | 					vector<string> stmt = split_tokens(line); | ||||||
|  | 
 | ||||||
|  | 					if (GetSize(stmt) == 1 && stmt[0] == "%%") | ||||||
|  | 						break; | ||||||
|  | 
 | ||||||
|  | 					if (GetSize(stmt) == 2 && stmt[0] == "%module") | ||||||
|  | 					{ | ||||||
|  | 						Module *module = design->module(RTLIL::escape_id(stmt[1])); | ||||||
|  | 
 | ||||||
|  | 						if (module == nullptr) | ||||||
|  | 							log_error("Module '%s' not found.\n", stmt[1].c_str()); | ||||||
|  | 
 | ||||||
|  | 						*f << stringf("-- SMV description generated by %s\n", yosys_version_str); | ||||||
|  | 
 | ||||||
|  | 						log("Creating SMV representation of module %s.\n", log_id(module)); | ||||||
|  | 						SmvWorker worker(module, verbose, *f); | ||||||
|  | 						worker.run(); | ||||||
|  | 
 | ||||||
|  | 						*f << stringf("-- end of yosys output\n"); | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					log_error("Unknown template statement: '%s'", line.c_str() + indent); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				*f << line << std::endl; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		*f << stringf("-- SMV description generated by %s\n", yosys_version_str); | ||||||
|  | 
 | ||||||
|  | 		for (auto module : modules) { | ||||||
|  | 			log("Creating SMV representation of module %s.\n", log_id(module)); | ||||||
|  | 			SmvWorker worker(module, verbose, *f); | ||||||
|  | 			worker.run(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		*f << stringf("-- end of yosys output\n"); | ||||||
|  | 
 | ||||||
|  | 		if (template_f.is_open()) { | ||||||
|  | 			std::string line; | ||||||
|  | 			while (std::getline(template_f, line)) | ||||||
|  | 				*f << line << std::endl; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } SmvBackend; | ||||||
|  | 
 | ||||||
|  | PRIVATE_NAMESPACE_END | ||||||
|  | @ -147,8 +147,10 @@ struct shared_str { | ||||||
| 	shared_str() { } | 	shared_str() { } | ||||||
| 	shared_str(string s) { content = std::shared_ptr<string>(new string(s)); } | 	shared_str(string s) { content = std::shared_ptr<string>(new string(s)); } | ||||||
| 	shared_str(const char *s) { content = std::shared_ptr<string>(new string(s)); } | 	shared_str(const char *s) { content = std::shared_ptr<string>(new string(s)); } | ||||||
| 	const char *c_str() { return content->c_str(); } | 	const char *c_str() const { return content->c_str(); } | ||||||
| 	const string &str() { return *content; } | 	const string &str() const { return *content; } | ||||||
|  | 	bool operator==(const shared_str &other) const { return *content == *other.content; } | ||||||
|  | 	unsigned int hash() const { return hashlib::hash_ops<std::string>::hash(*content); } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| using hashlib::mkhash; | using hashlib::mkhash; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue