| #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::ExecuteSelection(RTLIL::Design *design, const CommandArgs &args) | |
| { | |
| std::vector<std::string> selection_args; | |
| // Add name of top module to selection string | |
| std::transform(args.selection_objects.begin(), args.selection_objects.end(), std::back_inserter(selection_args), | |
| [&](const std::string &obj) { return RTLIL::unescape_id(design->top_module()->name) + "/" + SelectionType() + ":" + obj; }); | |
| extra_args(selection_args, 0, design); | |
| if (design->selected_modules().empty()) { | |
| if (!args.is_quiet) { | |
| log_warning("Specified %s not found in design\n", TypeName().c_str()); | |
| } | |
| } | |
| } | |
| void GetCmd::PackToTcl(const SelectionObjects &objects) | |
| { | |
| Tcl_Obj *tcl_result; | |
| if (objects.size() == 1) { | |
| tcl_result = Tcl_NewStringObj(objects.at(0).c_str(), -1); | |
| } else { | |
| tcl_result = Tcl_NewListObj(0, NULL); | |
| for (const auto &object : objects) { | |
| Tcl_Obj *value_obj = Tcl_NewStringObj(object.c_str(), -1); | |
| Tcl_ListObjAppendElement(yosys_get_tcl_interp(), tcl_result, value_obj); | |
| } | |
| } | |
| Tcl_SetObjResult(yosys_get_tcl_interp(), tcl_result); | |
| } | |
| GetCmd::CommandArgs GetCmd::ParseCommand(const std::vector<std::string> &args) | |
| { | |
| CommandArgs parsed_args{.filters = Filters(), .is_quiet = false, .selection_objects = SelectionObjects()}; | |
| size_t argidx(0); | |
| for (argidx = 1; argidx < args.size(); argidx++) { | |
| std::string arg = args[argidx]; | |
| if (arg == "-quiet") { | |
| parsed_args.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 | |
| // TODO Add support for multiple condition expression | |
| // Currently only a single == is supported | |
| 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()); | |
| } | |
| parsed_args.filters.emplace_back(filter.substr(0, separator), filter.substr(separator + 2)); | |
| } | |
| if (parsed_args.filters.size() > 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; | |
| } | |
| std::copy(args.begin() + argidx, args.end(), std::back_inserter(parsed_args.selection_objects)); | |
| return parsed_args; | |
| } | |
| void GetCmd::execute(std::vector<std::string> args, RTLIL::Design *design) | |
| { | |
| if (design->top_module() == nullptr) { | |
| log_cmd_error("No top module detected\n"); | |
| } | |
| CommandArgs parsed_args(ParseCommand(args)); | |
| ExecuteSelection(design, parsed_args); | |
| PackToTcl(ExtractSelection(design, parsed_args)); | |
| } |