diff options
Diffstat (limited to 'passes')
| -rw-r--r-- | passes/cmds/Makefile.inc | 1 | ||||
| -rw-r--r-- | passes/cmds/exec.cc | 203 | ||||
| -rw-r--r-- | passes/fsm/fsm_extract.cc | 6 | ||||
| -rw-r--r-- | passes/techmap/iopadmap.cc | 24 | 
4 files changed, 223 insertions, 11 deletions
| diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index 20b38bf8e..60f20fa6d 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -1,4 +1,5 @@ +OBJS += passes/cmds/exec.o  OBJS += passes/cmds/add.o  OBJS += passes/cmds/delete.o  OBJS += passes/cmds/design.o diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc new file mode 100644 index 000000000..399cb0ebb --- /dev/null +++ b/passes/cmds/exec.cc @@ -0,0 +1,203 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012 - 2020  Claire Wolf <claire@symbioticeda.com> + * + *  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 <cstdio> + +#if defined(_WIN32) +#  define WIFEXITED(x) 1 +#  define WIFSIGNALED(x) 0 +#  define WIFSTOPPED(x) 0 +#  define WEXITSTATUS(x) ((x) & 0xff) +#  define WTERMSIG(x) SIGTERM +#else +#  include <sys/wait.h> +#endif + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct ExecPass : public Pass { +	ExecPass() : Pass("exec", "execute commands in the operating system shell") { } +	void help() YS_OVERRIDE +	{ +		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +		log("\n"); +		log("    exec [options] -- [command]\n"); +		log("\n"); +		log("Execute a command in the operating system shell.  All supplied arguments are\n"); +		log("concatenated and passed as a command to popen(3).  Whitespace is not guaranteed\n"); +		log("to be preserved, even if quoted.  stdin and stderr are not connected, while stdout is\n"); +		log("logged unless the \"-q\" option is specified.\n"); +		log("\n"); +		log("\n"); +		log("    -q\n"); +		log("        Suppress stdout and stderr from subprocess\n"); +		log("\n"); +		log("    -expect-return <int>\n"); +		log("        Generate an error if popen() does not return specified value.\n"); +		log("        May only be specified once; the final specified value is controlling\n"); +		log("        if specified multiple times.\n"); +		log("\n"); +		log("    -expect-stdout <regex>\n"); +		log("        Generate an error if the specified regex does not match any line\n"); +		log("        in subprocess's stdout.  May be specified multiple times.\n"); +		log("\n"); +		log("    -not-expect-stdout <regex>\n"); +		log("        Generate an error if the specified regex matches any line\n"); +		log("        in subprocess's stdout.  May be specified multiple times.\n"); +		log("\n"); +		log("\n"); +		log("    Example: exec -q -expect-return 0 -- echo \"bananapie\" | grep \"nana\"\n"); +		log("\n"); +		log("\n"); +	} +	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE +	{ +		std::string cmd = ""; +		char buf[1024] = {}; +		std::string linebuf = ""; +		bool flag_cmd = false; +		bool flag_quiet = false; +		bool flag_expect_return = false; +		int expect_return_value = 0; +		bool flag_expect_stdout = false; +		struct expect_stdout_elem { +			bool matched; +			bool polarity;	//true: this regex must match at least one line +					//false: this regex must not match any line +			std::string str; +			YS_REGEX_TYPE re; + +			expect_stdout_elem() : matched(false), polarity(true), str(), re(){}; +		}; +		std::vector<expect_stdout_elem> expect_stdout; + +		if(args.size() == 0) +			log_cmd_error("No command provided.\n"); + +		for(size_t argidx = 1; argidx < args.size(); ++argidx) { +			if (flag_cmd) { +				cmd += args[argidx] + (argidx != (args.size() - 1)? " " : ""); +			} else { +				if (args[argidx] == "--") +					flag_cmd = true; +				else if (args[argidx] == "-q") +					flag_quiet = true; +				else if (args[argidx] == "-expect-return") { +					flag_expect_return = true; +					++argidx; +					if (argidx >= args.size()) +						log_cmd_error("No expected return value specified.\n"); + +					expect_return_value = atoi(args[argidx].c_str()); +				} else if (args[argidx] == "-expect-stdout") { +					flag_expect_stdout = true; +					++argidx; +					if (argidx >= args.size()) +						log_cmd_error("No expected regular expression specified.\n"); + +					try{ +						expect_stdout_elem x; +						x.str = args[argidx]; +						x.re = YS_REGEX_COMPILE(args[argidx]); +						expect_stdout.push_back(x); +					} catch (const YS_REGEX_NS::regex_error& e) { +						log_cmd_error("Error in regex expression '%s' !\n", args[argidx].c_str()); +					} +				} else if (args[argidx] == "-not-expect-stdout") { +					flag_expect_stdout = true; +					++argidx; +					if (argidx >= args.size()) +						log_cmd_error("No expected regular expression specified.\n"); + +					try{ +						expect_stdout_elem x; +						x.str = args[argidx]; +						x.re = YS_REGEX_COMPILE(args[argidx]); +						x.polarity = false; +						expect_stdout.push_back(x); +					} catch (const YS_REGEX_NS::regex_error& e) { +						log_cmd_error("Error in regex expression '%s' !\n", args[argidx].c_str()); +					} + +				} else +					log_cmd_error("Unknown option \"%s\" or \"--\" doesn\'t precede command.", args[argidx].c_str()); +			} +		} + +		log_header(design, "Executing command \"%s\".\n", cmd.c_str()); +		log_push(); + +		fflush(stdout); +		bool keep_reading = true; +		int status = 0; +		int retval = 0; + +#ifndef EMSCRIPTEN +		FILE *f = popen(cmd.c_str(), "r"); +		if (f == nullptr) +			log_cmd_error("errno %d after popen() returned NULL.\n", errno); +		while (keep_reading) { +			keep_reading = (fgets(buf, sizeof(buf), f) != nullptr); +			linebuf += buf; +			memset(buf, 0, sizeof(buf)); + +			auto pos = linebuf.find('\n'); +			while (pos != std::string::npos) { +				std::string line = linebuf.substr(0, pos); +				linebuf.erase(0, pos + 1); +				if (!flag_quiet) +					log("%s\n", line.c_str()); + +				if (flag_expect_stdout) +					for(auto &x : expect_stdout) +						if (YS_REGEX_NS::regex_search(line, x.re)) +							x.matched = true; + +				pos = linebuf.find('\n'); +			} +		} +		status = pclose(f); +#endif + +		if(WIFEXITED(status)) { +		    retval = WEXITSTATUS(status); +		} +		else if(WIFSIGNALED(status)) { +		    retval = WTERMSIG(status); +		} +		else if(WIFSTOPPED(status)) { +		    retval = WSTOPSIG(status); +		} + +		if (flag_expect_return && retval != expect_return_value) +			log_cmd_error("Return value %d did not match expected return value %d.\n", retval, expect_return_value); + +		if (flag_expect_stdout) +			for (auto &x : expect_stdout) +				if (x.polarity ^ x.matched) +					log_cmd_error("Command stdout did%s have a line matching given regex \"%s\".\n", (x.polarity? " not" : ""), x.str.c_str()); + +		log_pop(); +	} +} ExecPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc index a85c3bec0..0f7b4d106 100644 --- a/passes/fsm/fsm_extract.cc +++ b/passes/fsm/fsm_extract.cc @@ -422,11 +422,7 @@ struct FsmExtractPass : public Pass {  		log_header(design, "Executing FSM_EXTRACT pass (extracting FSM from design).\n");  		extra_args(args, 1, design); -		CellTypes ct; -		ct.setup_internals(); -		ct.setup_internals_mem(); -		ct.setup_stdcells(); -		ct.setup_stdcells_mem(); +		CellTypes ct(design);  		for (auto &mod_it : design->modules_)  		{ diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index f63012d1a..8b1862237 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -308,7 +308,9 @@ struct IopadmapPass : public Pass {  						{  							log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype.c_str()); -							Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(tinoutpad_celltype)); +							Cell *cell = module->addCell( +								module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), +								RTLIL::escape_id(tinoutpad_celltype));  							cell->setPort(RTLIL::escape_id(tinoutpad_portname_oe), en_sig);  							cell->attributes[ID::keep] = RTLIL::Const(1); @@ -328,7 +330,9 @@ struct IopadmapPass : public Pass {  						} else {  							log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, toutpad_celltype.c_str()); -							Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(toutpad_celltype)); +							Cell *cell = module->addCell( +								module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), +								RTLIL::escape_id(toutpad_celltype));  							cell->setPort(RTLIL::escape_id(toutpad_portname_oe), en_sig);  							cell->setPort(RTLIL::escape_id(toutpad_portname_i), data_sig); @@ -406,7 +410,9 @@ struct IopadmapPass : public Pass {  						SigBit wire_bit(wire, i); -						RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); +						RTLIL::Cell *cell = module->addCell( +							module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), +							RTLIL::escape_id(celltype));  						cell->setPort(RTLIL::escape_id(portname_int), wire_bit);  						if (!portname_pad.empty()) @@ -420,12 +426,16 @@ struct IopadmapPass : public Pass {  				}  				else  				{ -					RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); +					RTLIL::Cell *cell = module->addCell( +						module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), +						RTLIL::escape_id(celltype));  					cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire));  					if (!portname_pad.empty()) {  						RTLIL::Wire *new_wire = NULL; -						new_wire = module->addWire(NEW_ID, wire); +						new_wire = module->addWire( +							module->uniquify(stringf("$iopadmap$%s", log_id(wire))), +							wire);  						module->swap_names(new_wire, wire);  						wire->attributes.clear();  						cell->setPort(RTLIL::escape_id(portname_pad), RTLIL::SigSpec(new_wire)); @@ -446,7 +456,9 @@ struct IopadmapPass : public Pass {  			for (auto &it : rewrite_bits) {  				RTLIL::Wire *wire = it.first; -				RTLIL::Wire *new_wire = module->addWire(NEW_ID, wire); +				RTLIL::Wire *new_wire = module->addWire( +					module->uniquify(stringf("$iopadmap$%s", log_id(wire))), +					wire);  				module->swap_names(new_wire, wire);  				wire->attributes.clear();  				for (int i = 0; i < wire->width; i++) | 
