Introspection: Use GetCmd base class for GetNets Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/design_introspection-plugin/Makefile b/design_introspection-plugin/Makefile index 436000e..c9b43b3 100644 --- a/design_introspection-plugin/Makefile +++ b/design_introspection-plugin/Makefile
@@ -5,7 +5,7 @@ PLUGINS_DIR = $(shell yosys-config --datdir)/plugins NAME = design_introspection -OBJS = $(NAME).o get_nets.o get_ports.o +OBJS = $(NAME).o get_cmd.o get_nets.o get_ports.o $(NAME).so: $(OBJS) $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS)
diff --git a/design_introspection-plugin/get_cmd.cc b/design_introspection-plugin/get_cmd.cc new file mode 100644 index 0000000..b69d016 --- /dev/null +++ b/design_introspection-plugin/get_cmd.cc
@@ -0,0 +1,142 @@ +#include "get_cmd.h" + +USING_YOSYS_NAMESPACE + +void GetCmd::help() { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" get_%ss [-quiet] [-filter filter_expression] " + "<%s_selection> \n", + TypeName().c_str(), TypeName().c_str()); + log("\n"); + log("Get matching %ss\n", TypeName().c_str()); + log("\n"); + log("Print the output to stdout too. This is useful when all Yosys " + "is " + "executed.\n"); + log("\n"); + log(" -filter\n"); + log(" Name and value of attribute to be taken into " + "account.\n"); + log(" e.g. -filter { attr == \"true\" }\n"); + log("\n"); + log(" -quiet\n"); + log(" Don't print the result of the execution to stdout.\n"); + log("\n"); + log(" <selection_pattern>\n"); + log(" Selection of %s names. Default are all %ss in the " + "design.\n", + TypeName().c_str(), TypeName().c_str()); + log("\n"); +} + +void GetCmd::execute(std::vector<std::string> args, RTLIL::Design* design) { + RTLIL::Module* top_module = design->top_module(); + if (top_module == nullptr) { + log_cmd_error("No top module detected\n"); + } + + size_t argidx; + std::vector<std::pair<std::string, std::string>> filters; + bool is_quiet = false; + bool has_filter = false; + + // Parse command arguments + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-quiet") { + is_quiet = true; + continue; + } + + if (arg == "-filter" and argidx + 1 < args.size()) { + std::string filter_arg = args[++argidx]; + + // Remove spaces + filter_arg.erase( + std::remove_if(filter_arg.begin(), filter_arg.end(), isspace), + filter_arg.end()); + + // Parse filters + std::regex filter_attr_regex("(\\w+\\s?==\\s?\\w+)([(||)(&&)]*)"); + std::regex_token_iterator<std::string::iterator> regex_end; + std::regex_token_iterator<std::string::iterator> matches( + filter_arg.begin(), filter_arg.end(), filter_attr_regex, 1); + if (matches == regex_end) { + log_warning( + "Currently -filter switch supports only a single " + "'equal(==)' condition expression, the rest will be " + "ignored\n"); + } + + while (matches != regex_end) { + std::string filter(*matches++); + auto separator = filter.find("=="); + if (separator == std::string::npos) { + log_cmd_error("Incorrect filter expression: %s\n", + args[argidx].c_str()); + } + filters.emplace_back(filter.substr(0, separator), + filter.substr(separator + 2)); + } + size_t filter_cnt = filters.size(); + has_filter = filter_cnt > 0; + if (filter_cnt > 1) { + log_warning( + "Currently -filter switch supports only a single " + "'equal(==)' condition expression, the rest will be " + "ignored\n"); + } + continue; + } + + if (arg.size() > 0 and arg[0] == '-') { + log_cmd_error("Unknown option %s.\n", arg.c_str()); + } + + break; + } + + // Add name of top module to selection string + std::vector<std::string> selection_args; + std::transform(args.begin() + argidx, args.end(), + std::back_inserter(selection_args), [&](std::string& net) { + return RTLIL::unescape_id(top_module->name) + + "/w:" + net; + }); + + // Execute the selection + extra_args(selection_args, 0, design); + if (design->selected_modules().empty()) { + if (!is_quiet) { + log_warning("Specified net not found in design\n"); + } + } + + // Pack the selected nets into Tcl List + Tcl_Interp* interp = yosys_get_tcl_interp(); + Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL); + for (auto module : design->selected_modules()) { + for (auto wire : module->selected_wires()) { + if (has_filter) { + std::pair<std::string, std::string> filter = filters.at(0); + std::string attr_value = wire->get_string_attribute( + RTLIL::IdString(RTLIL::escape_id(filter.first))); + if (attr_value.compare(filter.second)) { + continue; + } + } + if (!is_quiet) { + log("%s ", id2cstr(wire->name)); + } + Tcl_Obj* value_obj = Tcl_NewStringObj(id2cstr(wire->name), -1); + Tcl_ListObjAppendElement(interp, tcl_list, value_obj); + } + } + if (!is_quiet) { + log("\n"); + } + Tcl_SetObjResult(interp, tcl_list); +} +/* void execute(std::vector<std::string> args, RTLIL::Design* design) override; + */
diff --git a/design_introspection-plugin/get_cmd.h b/design_introspection-plugin/get_cmd.h new file mode 100644 index 0000000..6376b05 --- /dev/null +++ b/design_introspection-plugin/get_cmd.h
@@ -0,0 +1,16 @@ +#ifndef _GET_CMD_H_ +#define _GET_CMD_H_ + +#include "kernel/register.h" + +USING_YOSYS_NAMESPACE + +struct GetCmd : public Pass { + GetCmd(const std::string& name, const std::string& description) : Pass(name, description) {} + + void help() override; + void execute(std::vector<std::string> args, RTLIL::Design* design) override; + virtual std::string TypeName() = 0; +}; + +#endif // GET_CMD_H_
diff --git a/design_introspection-plugin/get_nets.cc b/design_introspection-plugin/get_nets.cc index 4b5e4a0..25ce177 100644 --- a/design_introspection-plugin/get_nets.cc +++ b/design_introspection-plugin/get_nets.cc
@@ -1,138 +1,8 @@ #include "get_nets.h" -#include <regex> -#include "kernel/log.h" -#include "kernel/register.h" -#include "kernel/rtlil.h" USING_YOSYS_NAMESPACE -void GetNets::help() { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" get_nets [-quiet] [-filter filter_expression] <net_selection> \n"); - log("\n"); - log("Get matching nets\n"); - log("\n"); - log("Print the output to stdout too. This is useful when all Yosys is " - "executed.\n"); - log("\n"); - log(" -filter\n"); - log(" Name and value of attribute to be taken into account.\n"); - log(" e.g. -filter { attr == \"true\" }\n"); - log("\n"); - log(" -quiet\n"); - log(" Don't print the result of the execution to stdout.\n"); - log("\n"); - log(" <net_selection>\n"); - log(" Selection of net name. Default are all nets in the design.\n"); - log("\n"); +std::string GetNets::TypeName() { + return "net"; } -void GetNets::execute(std::vector<std::string> args, RTLIL::Design* design) { - RTLIL::Module* top_module = design->top_module(); - if (top_module == nullptr) { - log_cmd_error("No top module detected\n"); - } - - size_t argidx; - std::vector<std::pair<std::string, std::string>> filters; - bool is_quiet = false; - bool has_filter = false; - - // Parse command arguments - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-quiet") { - is_quiet = true; - continue; - } - - if (arg == "-filter" and argidx + 1 < args.size()) { - std::string filter_arg = args[++argidx]; - - // Remove spaces - filter_arg.erase( - std::remove_if(filter_arg.begin(), filter_arg.end(), isspace), - filter_arg.end()); - - // Parse filters - std::regex filter_attr_regex("(\\w+\\s?==\\s?\\w+)([(||)(&&)]*)"); - std::regex_token_iterator<std::string::iterator> regex_end; - std::regex_token_iterator<std::string::iterator> matches( - filter_arg.begin(), filter_arg.end(), filter_attr_regex, 1); - if (matches == regex_end) { - log_warning( - "Currently -filter switch supports only a single " - "'equal(==)' condition expression, the rest will be " - "ignored\n"); - } - - while (matches != regex_end) { - std::string filter(*matches++); - auto separator = filter.find("=="); - if (separator == std::string::npos) { - log_cmd_error("Incorrect filter expression: %s\n", - args[argidx].c_str()); - } - filters.emplace_back(filter.substr(0, separator), - filter.substr(separator + 2)); - } - size_t filter_cnt = filters.size(); - has_filter = filter_cnt > 0; - if (filter_cnt > 1) { - log_warning( - "Currently -filter switch supports only a single " - "'equal(==)' condition expression, the rest will be " - "ignored\n"); - } - continue; - } - - if (arg.size() > 0 and arg[0] == '-') { - log_cmd_error("Unknown option %s.\n", arg.c_str()); - } - - break; - } - - // Add name of top module to selection string - std::vector<std::string> selection_args; - std::transform(args.begin() + argidx, args.end(), - std::back_inserter(selection_args), [&](std::string& net) { - return RTLIL::unescape_id(top_module->name) + - "/w:" + net; - }); - - // Execute the selection - extra_args(selection_args, 0, design); - if (design->selected_modules().empty()) { - if (!is_quiet) { - log_warning("Specified net not found in design\n"); - } - } - - // Pack the selected nets into Tcl List - Tcl_Interp* interp = yosys_get_tcl_interp(); - Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL); - for (auto module : design->selected_modules()) { - for (auto wire : module->selected_wires()) { - if (has_filter) { - std::pair<std::string, std::string> filter = filters.at(0); - std::string attr_value = wire->get_string_attribute( - RTLIL::IdString(RTLIL::escape_id(filter.first))); - if (attr_value.compare(filter.second)) { - continue; - } - } - if (!is_quiet) { - log("%s ", id2cstr(wire->name)); - } - Tcl_Obj* value_obj = Tcl_NewStringObj(id2cstr(wire->name), -1); - Tcl_ListObjAppendElement(interp, tcl_list, value_obj); - } - } - if (!is_quiet) { - log("\n"); - } - Tcl_SetObjResult(interp, tcl_list); -}
diff --git a/design_introspection-plugin/get_nets.h b/design_introspection-plugin/get_nets.h index 8b66abe..57b9885 100644 --- a/design_introspection-plugin/get_nets.h +++ b/design_introspection-plugin/get_nets.h
@@ -1,10 +1,14 @@ -#include "kernel/register.h" +#ifndef _GET_NETS_H_ +#define _GET_NETS_H_ + +#include "get_cmd.h" USING_YOSYS_NAMESPACE -struct GetNets : public Pass { - GetNets() : Pass("get_nets", "Print matching nets") {} +struct GetNets : public GetCmd { + GetNets() : GetCmd("get_nets", "Print matching nets") {} - void help() override; - void execute(std::vector<std::string> args, RTLIL::Design* design) override; + std::string TypeName() override; }; + +#endif // GET_NETS_H_