| /* |
| * yosys -- Yosys Open SYnthesis Suite |
| * |
| * Copyright (C) 2014 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/yosys.h" |
| |
| #ifdef YOSYS_ENABLE_PLUGINS |
| # include <dlfcn.h> |
| #endif |
| |
| #ifdef WITH_PYTHON |
| # include <boost/algorithm/string/predicate.hpp> |
| # include <Python.h> |
| # include <boost/filesystem.hpp> |
| #endif |
| |
| YOSYS_NAMESPACE_BEGIN |
| |
| std::map<std::string, void*> loaded_plugins; |
| #ifdef WITH_PYTHON |
| std::map<std::string, void*> loaded_python_plugins; |
| #endif |
| std::map<std::string, std::string> loaded_plugin_aliases; |
| |
| #ifdef YOSYS_ENABLE_PLUGINS |
| void load_plugin(std::string filename, std::vector<std::string> aliases) |
| { |
| std::string orig_filename = filename; |
| |
| if (filename.find('/') == std::string::npos) |
| filename = "./" + filename; |
| |
| #ifdef WITH_PYTHON |
| if (!loaded_plugins.count(filename) && !loaded_python_plugins.count(filename)) { |
| #else |
| if (!loaded_plugins.count(filename)) { |
| #endif |
| |
| #ifdef WITH_PYTHON |
| |
| boost::filesystem::path full_path(filename); |
| |
| if(strcmp(full_path.extension().c_str(), ".py") == 0) |
| { |
| std::string path(full_path.parent_path().c_str()); |
| filename = full_path.filename().c_str(); |
| filename = filename.substr(0,filename.size()-3); |
| PyRun_SimpleString(("sys.path.insert(0,\""+path+"\")").c_str()); |
| PyErr_Print(); |
| PyObject *module_p = PyImport_ImportModule(filename.c_str()); |
| if(module_p == NULL) |
| { |
| PyErr_Print(); |
| log_cmd_error("Can't load python module `%s'\n", full_path.filename().c_str()); |
| return; |
| } |
| loaded_python_plugins[orig_filename] = module_p; |
| Pass::init_register(); |
| } else { |
| #endif |
| |
| void *hdl = dlopen(filename.c_str(), RTLD_LAZY|RTLD_LOCAL); |
| if (hdl == NULL && orig_filename.find('/') == std::string::npos) |
| hdl = dlopen((proc_share_dirname() + "plugins/" + orig_filename + ".so").c_str(), RTLD_LAZY|RTLD_LOCAL); |
| if (hdl == NULL) |
| log_cmd_error("Can't load module `%s': %s\n", filename.c_str(), dlerror()); |
| loaded_plugins[orig_filename] = hdl; |
| Pass::init_register(); |
| |
| #ifdef WITH_PYTHON |
| } |
| #endif |
| } |
| |
| for (auto &alias : aliases) |
| loaded_plugin_aliases[alias] = orig_filename; |
| } |
| #else |
| void load_plugin(std::string, std::vector<std::string>) |
| { |
| log_error("This version of yosys is built without plugin support.\n"); |
| } |
| #endif |
| |
| struct PluginPass : public Pass { |
| PluginPass() : Pass("plugin", "load and list loaded plugins") { } |
| void help() YS_OVERRIDE |
| { |
| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| |
| log("\n"); |
| log(" plugin [options]\n"); |
| log("\n"); |
| log("Load and list loaded plugins.\n"); |
| log("\n"); |
| log(" -i <plugin_filename>\n"); |
| log(" Load (install) the specified plugin.\n"); |
| log("\n"); |
| log(" -a <alias_name>\n"); |
| log(" Register the specified alias name for the loaded plugin\n"); |
| log("\n"); |
| log(" -l\n"); |
| log(" List loaded plugins\n"); |
| log("\n"); |
| } |
| void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE |
| { |
| std::string plugin_filename; |
| std::vector<std::string> plugin_aliases; |
| bool list_mode = false; |
| |
| size_t argidx; |
| for (argidx = 1; argidx < args.size(); argidx++) |
| { |
| if ((args[argidx] == "-i") && argidx+1 < args.size() && plugin_filename.empty()) { |
| plugin_filename = args[++argidx]; |
| continue; |
| } |
| if ((args[argidx] == "-a") && argidx+1 < args.size()) { |
| plugin_aliases.push_back(args[++argidx]); |
| continue; |
| } |
| if (args[argidx] == "-l") { |
| list_mode = true; |
| continue; |
| } |
| break; |
| } |
| extra_args(args, argidx, design, false); |
| |
| if (!plugin_filename.empty()) |
| load_plugin(plugin_filename, plugin_aliases); |
| |
| if (list_mode) |
| { |
| log("\n"); |
| #ifdef WITH_PYTHON |
| if (loaded_plugins.empty() and loaded_python_plugins.empty()) |
| #else |
| if (loaded_plugins.empty()) |
| #endif |
| log("No plugins loaded.\n"); |
| else |
| log("Loaded plugins:\n"); |
| |
| for (auto &it : loaded_plugins) |
| log(" %s\n", it.first.c_str()); |
| |
| #ifdef WITH_PYTHON |
| for (auto &it : loaded_python_plugins) |
| log(" %s\n", it.first.c_str()); |
| #endif |
| |
| if (!loaded_plugin_aliases.empty()) { |
| log("\n"); |
| int max_alias_len = 1; |
| for (auto &it : loaded_plugin_aliases) |
| max_alias_len = max(max_alias_len, GetSize(it.first)); |
| for (auto &it : loaded_plugin_aliases) |
| log("Alias: %-*s %s\n", max_alias_len, it.first.c_str(), it.second.c_str()); |
| } |
| } |
| } |
| } PluginPass; |
| |
| YOSYS_NAMESPACE_END |
| |