Merge pull request #46 from antmicro/set_clock_groups
SDC: Add set_clock_groups command
diff --git a/Makefile b/Makefile
index 72611b4..c397859 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-PLUGIN_LIST := fasm xdc params selection sdc get_count ql-iob
+PLUGIN_LIST := fasm xdc params selection sdc get_count ql-iob design_introspection
PLUGINS := $(foreach plugin,$(PLUGIN_LIST),$(plugin).so)
PLUGINS_INSTALL := $(foreach plugin,$(PLUGIN_LIST),install_$(plugin))
PLUGINS_CLEAN := $(foreach plugin,$(PLUGIN_LIST),clean_$(plugin))
diff --git a/design_introspection-plugin/Makefile b/design_introspection-plugin/Makefile
new file mode 100644
index 0000000..85a605a
--- /dev/null
+++ b/design_introspection-plugin/Makefile
@@ -0,0 +1,9 @@
+NAME = design_introspection
+SOURCES = design_introspection.cc \
+ get_cmd.cc \
+ get_nets.cc \
+ get_ports.cc \
+ get_cells.cc \
+ get_pins.cc
+
+include ../Makefile_plugin.common
diff --git a/design_introspection-plugin/design_introspection.cc b/design_introspection-plugin/design_introspection.cc
new file mode 100644
index 0000000..64fdbbc
--- /dev/null
+++ b/design_introspection-plugin/design_introspection.cc
@@ -0,0 +1,39 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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 "get_nets.h"
+#include "get_ports.h"
+#include "get_cells.h"
+#include "get_pins.h"
+
+USING_YOSYS_NAMESPACE
+
+PRIVATE_NAMESPACE_BEGIN
+
+struct DesignIntrospection {
+ DesignIntrospection(){}
+ GetNets get_nets_cmd;
+ GetPorts get_ports_cmd;
+ GetCells get_cells_cmd;
+ GetPins get_pins_cmd;
+} DesignIntrospection;
+
+
+PRIVATE_NAMESPACE_END
diff --git a/design_introspection-plugin/get_cells.cc b/design_introspection-plugin/get_cells.cc
new file mode 100644
index 0000000..937545d
--- /dev/null
+++ b/design_introspection-plugin/get_cells.cc
@@ -0,0 +1,48 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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 "get_cells.h"
+
+USING_YOSYS_NAMESPACE
+
+std::string GetCells::TypeName() { return "cell"; }
+
+std::string GetCells::SelectionType() { return "c"; }
+
+GetCells::SelectionObjects GetCells::ExtractSelection(RTLIL::Design* design, const CommandArgs& args) {
+ SelectionObjects selected_objects;
+ for (auto module : design->selected_modules()) {
+ for (auto cell : module->selected_cells()) {
+ if (args.filters.size() > 0) {
+ Filter filter = args.filters.at(0);
+ std::string attr_value = cell->get_string_attribute(
+ RTLIL::IdString(RTLIL::escape_id(filter.first)));
+ if (attr_value.compare(filter.second)) {
+ continue;
+ }
+ }
+ std::string object_name(RTLIL::unescape_id(cell->name));
+ selected_objects.push_back(object_name);
+ }
+ }
+ if (selected_objects.size() == 0 and !args.is_quiet) {
+ log_warning("Couldn't find matching cell.\n");
+ }
+ return selected_objects;
+}
diff --git a/design_introspection-plugin/get_cells.h b/design_introspection-plugin/get_cells.h
new file mode 100644
index 0000000..205d50b
--- /dev/null
+++ b/design_introspection-plugin/get_cells.h
@@ -0,0 +1,36 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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.
+ *
+ */
+#ifndef _GET_CELLS_H_
+#define _GET_CELLS_H_
+
+#include "get_cmd.h"
+
+USING_YOSYS_NAMESPACE
+
+struct GetCells : public GetCmd {
+ GetCells() : GetCmd("get_cells", "Print matching cells") {}
+
+ std::string TypeName() override;
+ std::string SelectionType() override;
+ SelectionObjects ExtractSelection(RTLIL::Design* design,
+ const CommandArgs& args) override;
+};
+
+#endif // GET_CELLS_H_
diff --git a/design_introspection-plugin/get_cmd.cc b/design_introspection-plugin/get_cmd.cc
new file mode 100644
index 0000000..4b54ded
--- /dev/null
+++ b/design_introspection-plugin/get_cmd.cc
@@ -0,0 +1,138 @@
+#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));
+}
diff --git a/design_introspection-plugin/get_cmd.h b/design_introspection-plugin/get_cmd.h
new file mode 100644
index 0000000..983a50d
--- /dev/null
+++ b/design_introspection-plugin/get_cmd.h
@@ -0,0 +1,55 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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.
+ *
+ */
+#ifndef _GET_CMD_H_
+#define _GET_CMD_H_
+
+#include "kernel/register.h"
+
+USING_YOSYS_NAMESPACE
+
+struct GetCmd : public Pass {
+ using Filter = std::pair<std::string, std::string>;
+ using Filters = std::vector<Filter>;
+ using SelectionObjects = std::vector<std::string>;
+ struct CommandArgs {
+ Filters filters;
+ bool is_quiet;
+ SelectionObjects selection_objects;
+ };
+
+ 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;
+
+ protected:
+ CommandArgs ParseCommand(const std::vector<std::string>& args);
+ void PackToTcl(const SelectionObjects& objects);
+
+ private:
+ virtual std::string TypeName() = 0;
+ virtual std::string SelectionType() = 0;
+ virtual SelectionObjects ExtractSelection(RTLIL::Design* design, const CommandArgs& args) = 0;
+ virtual void ExecuteSelection(RTLIL::Design* design,
+ const CommandArgs& args);
+};
+
+#endif // GET_CMD_H_
diff --git a/design_introspection-plugin/get_nets.cc b/design_introspection-plugin/get_nets.cc
new file mode 100644
index 0000000..db5d375
--- /dev/null
+++ b/design_introspection-plugin/get_nets.cc
@@ -0,0 +1,49 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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 "get_nets.h"
+
+USING_YOSYS_NAMESPACE
+
+std::string GetNets::TypeName() { return "net"; }
+
+std::string GetNets::SelectionType() { return "w"; }
+
+GetNets::SelectionObjects GetNets::ExtractSelection(RTLIL::Design* design,
+ const CommandArgs& args) {
+ SelectionObjects selected_objects;
+ for (auto module : design->selected_modules()) {
+ for (auto wire : module->selected_wires()) {
+ if (args.filters.size() > 0) {
+ Filter filter = args.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;
+ }
+ }
+ std::string object_name(RTLIL::unescape_id(wire->name));
+ selected_objects.push_back(object_name);
+ }
+ }
+ if (selected_objects.size() == 0 and !args.is_quiet) {
+ log_warning("Couldn't find matching net.\n");
+ }
+ return selected_objects;
+}
diff --git a/design_introspection-plugin/get_nets.h b/design_introspection-plugin/get_nets.h
new file mode 100644
index 0000000..11f7502
--- /dev/null
+++ b/design_introspection-plugin/get_nets.h
@@ -0,0 +1,36 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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.
+ *
+ */
+#ifndef _GET_NETS_H_
+#define _GET_NETS_H_
+
+#include "get_cmd.h"
+
+USING_YOSYS_NAMESPACE
+
+struct GetNets : public GetCmd {
+ GetNets() : GetCmd("get_nets", "Print matching nets") {}
+
+ std::string TypeName() override;
+ std::string SelectionType() override;
+ SelectionObjects ExtractSelection(RTLIL::Design* design,
+ const CommandArgs& args) override;
+};
+
+#endif // GET_NETS_H_
diff --git a/design_introspection-plugin/get_pins.cc b/design_introspection-plugin/get_pins.cc
new file mode 100644
index 0000000..d39f6bc
--- /dev/null
+++ b/design_introspection-plugin/get_pins.cc
@@ -0,0 +1,81 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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 "get_pins.h"
+
+USING_YOSYS_NAMESPACE
+
+std::string GetPins::TypeName() { return "pin"; }
+
+std::string GetPins::SelectionType() { return "c"; }
+
+void GetPins::ExecuteSelection(RTLIL::Design* design, const CommandArgs& args) {
+ (void)design;
+ (void)args;
+}
+
+GetPins::SelectionObjects GetPins::ExtractSelection(RTLIL::Design* design,
+ const CommandArgs& args) {
+ SelectionObjects selected_objects;
+ for (auto obj : args.selection_objects) {
+ size_t port_separator = obj.find_last_of("/");
+ std::string cell = obj.substr(0, port_separator);
+ std::string port = obj.substr(port_separator + 1);
+ SelectionObjects selection{
+ RTLIL::unescape_id(design->top_module()->name) + "/" +
+ SelectionType() + ":" + cell};
+ extra_args(selection, 0, design);
+ ExtractSingleSelection(selected_objects, design, port, args);
+ }
+ if (selected_objects.size() == 0 and !args.is_quiet) {
+ log_warning("Couldn't find matching pin.\n");
+ }
+ return selected_objects;
+}
+
+void GetPins::ExtractSingleSelection(SelectionObjects& objects,
+ RTLIL::Design* design,
+ const std::string& port_name,
+ const CommandArgs& args) {
+ if (design->selected_modules().empty()) {
+ if (!args.is_quiet) {
+ log_warning("Specified %s not found in design\n",
+ TypeName().c_str());
+ }
+ }
+ for (auto module : design->selected_modules()) {
+ for (auto cell : module->selected_cells()) {
+ if (!cell->hasPort(RTLIL::escape_id(port_name))) {
+ continue;
+ }
+ if (args.filters.size() > 0) {
+ Filter filter = args.filters.at(0);
+ std::string attr_value = cell->get_string_attribute(
+ RTLIL::IdString(RTLIL::escape_id(filter.first)));
+ if (attr_value.compare(filter.second)) {
+ continue;
+ }
+ }
+ std::string pin_name(RTLIL::unescape_id(cell->name) + "/" +
+ port_name);
+ objects.push_back(pin_name);
+ }
+ }
+}
+
diff --git a/design_introspection-plugin/get_pins.h b/design_introspection-plugin/get_pins.h
new file mode 100644
index 0000000..f7ebe14
--- /dev/null
+++ b/design_introspection-plugin/get_pins.h
@@ -0,0 +1,43 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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.
+ *
+ */
+#ifndef _GET_PINS_H_
+#define _GET_PINS_H_
+
+#include "get_cmd.h"
+
+USING_YOSYS_NAMESPACE
+
+struct GetPins : public GetCmd {
+ GetPins() : GetCmd("get_pins", "Print matching pins") {}
+
+ private:
+ std::string TypeName() override;
+ std::string SelectionType() override;
+ SelectionObjects ExtractSelection(RTLIL::Design* design,
+ const CommandArgs& args) override;
+ void ExecuteSelection(RTLIL::Design* design,
+ const CommandArgs& args) override;
+ void ExtractSingleSelection(SelectionObjects& objects,
+ RTLIL::Design* design,
+ const std::string& port_name,
+ const CommandArgs& args);
+};
+
+#endif // GET_PINS_H_
diff --git a/design_introspection-plugin/get_ports.cc b/design_introspection-plugin/get_ports.cc
new file mode 100644
index 0000000..ef29b95
--- /dev/null
+++ b/design_introspection-plugin/get_ports.cc
@@ -0,0 +1,57 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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 "get_ports.h"
+
+USING_YOSYS_NAMESPACE
+
+std::string GetPorts::TypeName() { return "port"; }
+
+std::string GetPorts::SelectionType() { return "x"; }
+
+void GetPorts::ExecuteSelection([[gnu::unused]] RTLIL::Design* design,
+ [[gnu::unused]] const CommandArgs& args) {
+}
+
+GetPorts::SelectionObjects GetPorts::ExtractSelection(RTLIL::Design* design,
+ const CommandArgs& args) {
+ std::string port_name = args.selection_objects.at(0);
+ std::string port_str(port_name.size(), '\0');
+ int bit(0);
+ if (!sscanf(port_name.c_str(), "%[^[][%d]", &port_str[0], &bit)) {
+ log_error("Couldn't find port %s\n", port_name.c_str());
+ }
+
+ port_str.resize(strlen(port_str.c_str()));
+ RTLIL::IdString port_id(RTLIL::escape_id(port_str));
+ SelectionObjects objects;
+ if (auto wire = design->top_module()->wire(port_id)) {
+ if (wire->port_input || wire->port_output) {
+ if (bit >= wire->start_offset &&
+ bit < wire->start_offset + wire->width) {
+ objects.push_back(port_name);
+ }
+ }
+ }
+ if (objects.size() == 0 and !args.is_quiet) {
+ log_warning("Couldn't find port matching %s\n", port_name.c_str());
+ }
+ return objects;
+}
+
diff --git a/design_introspection-plugin/get_ports.h b/design_introspection-plugin/get_ports.h
new file mode 100644
index 0000000..89ba49a
--- /dev/null
+++ b/design_introspection-plugin/get_ports.h
@@ -0,0 +1,40 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2020 The Symbiflow Authors
+ *
+ * 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.
+ *
+ */
+#ifndef _GET_PORTS_H_
+#define _GET_PORTS_H_
+
+#include "get_cmd.h"
+
+USING_YOSYS_NAMESPACE
+
+struct GetPorts : public GetCmd {
+ GetPorts() : GetCmd("get_ports", "Print matching ports") {}
+
+ private:
+ std::string TypeName() override;
+ std::string SelectionType() override;
+ /* void execute(std::vector<std::string> args, RTLIL::Design* design) override; */
+ SelectionObjects ExtractSelection(RTLIL::Design* design,
+ const CommandArgs& args) override;
+ void ExecuteSelection(RTLIL::Design* design,
+ const CommandArgs& args) override;
+};
+
+#endif // GET_PORTS_H_
diff --git a/design_introspection-plugin/tests/Makefile b/design_introspection-plugin/tests/Makefile
new file mode 100644
index 0000000..fcca1e9
--- /dev/null
+++ b/design_introspection-plugin/tests/Makefile
@@ -0,0 +1,11 @@
+TESTS = get_nets \
+ get_ports \
+ get_cells \
+ get_pins
+
+include $(shell pwd)/../../Makefile_test.common
+
+get_nets_verify = $(call diff_test,get_nets,txt)
+get_ports_verify = $(call diff_test,get_ports,txt)
+get_cells_verify = $(call diff_test,get_cells,txt)
+get_pins_verify = $(call diff_test,get_pins,txt)
diff --git a/design_introspection-plugin/tests/get_cells/get_cells.golden.txt b/design_introspection-plugin/tests/get_cells/get_cells.golden.txt
new file mode 100644
index 0000000..d33818d
--- /dev/null
+++ b/design_introspection-plugin/tests/get_cells/get_cells.golden.txt
@@ -0,0 +1,15 @@
+
+*inter* cells quiet
+bottom_intermediate_inst.OBUF_8
+
+*inter* cells
+bottom_intermediate_inst.OBUF_8
+
+*inter* cells with invalid filter expression
+bottom_intermediate_inst.OBUF_8
+
+Filtered cells
+OBUFTDS_2
+
+All cells
+{$abc$2135$lut$not$aiger2134$1} {$auto$alumacc.cc:485:replace_alu$1469.slice[0].carry4_1st_full} {$auto$alumacc.cc:485:replace_alu$1469.slice[0].plug} {$auto$alumacc.cc:485:replace_alu$1469.slice[1].carry4_full} {$auto$alumacc.cc:485:replace_alu$1469.slice[1].plug} {$auto$alumacc.cc:485:replace_alu$1469.slice[2].carry4_full} {$auto$alumacc.cc:485:replace_alu$1469.slice[2].plug} {$auto$alumacc.cc:485:replace_alu$1469.slice[3].carry4_full} {$auto$alumacc.cc:485:replace_alu$1469.slice[3].plug} {$auto$alumacc.cc:485:replace_alu$1469.slice[4].carry4_full} {$auto$alumacc.cc:485:replace_alu$1469.slice[4].plug} {$auto$alumacc.cc:485:replace_alu$1469.slice[5].carry4_full} {$auto$alumacc.cc:485:replace_alu$1469.slice[5].plug} {$auto$alumacc.cc:485:replace_alu$1469.slice[6].carry4_part} {$auto$simplemap.cc:420:simplemap_dff$1476} {$auto$simplemap.cc:420:simplemap_dff$1477} {$auto$simplemap.cc:420:simplemap_dff$1478} {$auto$simplemap.cc:420:simplemap_dff$1479} {$auto$simplemap.cc:420:simplemap_dff$1480} {$auto$simplemap.cc:420:simplemap_dff$1481} {$auto$simplemap.cc:420:simplemap_dff$1482} {$auto$simplemap.cc:420:simplemap_dff$1483} {$auto$simplemap.cc:420:simplemap_dff$1484} {$auto$simplemap.cc:420:simplemap_dff$1485} {$auto$simplemap.cc:420:simplemap_dff$1486} {$auto$simplemap.cc:420:simplemap_dff$1487} {$auto$simplemap.cc:420:simplemap_dff$1488} {$auto$simplemap.cc:420:simplemap_dff$1489} {$auto$simplemap.cc:420:simplemap_dff$1490} {$auto$simplemap.cc:420:simplemap_dff$1491} {$auto$simplemap.cc:420:simplemap_dff$1492} {$auto$simplemap.cc:420:simplemap_dff$1493} {$auto$simplemap.cc:420:simplemap_dff$1494} {$auto$simplemap.cc:420:simplemap_dff$1495} {$auto$simplemap.cc:420:simplemap_dff$1496} {$auto$simplemap.cc:420:simplemap_dff$1497} {$auto$simplemap.cc:420:simplemap_dff$1498} {$auto$simplemap.cc:420:simplemap_dff$1499} {$auto$simplemap.cc:420:simplemap_dff$1500} {$auto$simplemap.cc:420:simplemap_dff$1501} {$iopadmap$top.clk} OBUFTDS_2 OBUF_6 OBUF_7 OBUF_OUT bottom_inst.OBUF_10 bottom_inst.OBUF_11 bottom_inst.OBUF_9 bottom_intermediate_inst.OBUF_8
diff --git a/design_introspection-plugin/tests/get_cells/get_cells.tcl b/design_introspection-plugin/tests/get_cells/get_cells.tcl
new file mode 100644
index 0000000..861e6a9
--- /dev/null
+++ b/design_introspection-plugin/tests/get_cells/get_cells.tcl
@@ -0,0 +1,33 @@
+yosys -import
+plugin -i design_introspection
+#Import the commands from the plugins to the tcl interpreter
+yosys -import
+
+read_verilog get_cells.v
+# Some of symbiflow expects eblifs with only one module.
+synth_xilinx -vpr -flatten -abc9 -nosrl -noclkbuf -nodsp
+
+
+set fp [open "get_cells.txt" "w"]
+
+puts "\n*inter* cells quiet"
+puts $fp "\n*inter* cells quiet"
+puts $fp [get_cells -quiet *inter*]
+
+puts "\n*inter* cells"
+puts $fp "\n*inter* cells"
+puts $fp [get_cells *inter*]
+
+puts "\n*inter* cells with invalid filter expression"
+puts $fp "\n*inter* cells with invalid filter expression"
+puts $fp [get_cells -filter {mr_ff != true} *inter* ]
+
+puts "\nFiltered cells"
+puts $fp "\nFiltered cells"
+puts $fp [get_cells -filter {mr_ff == true || async_reg == true && dont_touch == true} ]
+
+puts "\nAll cells"
+puts $fp "\nAll cells"
+puts $fp [get_cells]
+
+close $fp
diff --git a/design_introspection-plugin/tests/get_cells/get_cells.v b/design_introspection-plugin/tests/get_cells/get_cells.v
new file mode 100644
index 0000000..e2af7fc
--- /dev/null
+++ b/design_introspection-plugin/tests/get_cells/get_cells.v
@@ -0,0 +1,77 @@
+module top (
+ (* async_reg = "true", mr_ff = "true", dont_touch = "true" *) input clk,
+ output [3:0] led,
+ inout out_a,
+ output [1:0] out_b,
+ output signal_p,
+ output signal_n
+);
+
+ wire LD6, LD7, LD8, LD9;
+ wire inter_wire, inter_wire_2;
+ localparam BITS = 1;
+ localparam LOG2DELAY = 25;
+
+ reg [BITS+LOG2DELAY-1:0] counter = 0;
+
+ always @(posedge clk) begin
+ counter <= counter + 1;
+ end
+ assign led[1] = inter_wire;
+ assign inter_wire = inter_wire_2;
+ assign {LD9, LD8, LD7, LD6} = counter >> LOG2DELAY;
+ (* async_reg = "true", mr_ff = "true", dont_touch = "true" *)
+ OBUFTDS OBUFTDS_2(
+ .I(LD6),
+ .O(signal_p),
+ .OB(signal_n),
+ .T(1'b1)
+ );
+ (* async_reg = "false", mr_ff = "false", dont_touch = "true" *)
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_6(.I(LD6), .O(led[0]));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_7(.I(LD7), .O(inter_wire_2));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_OUT(.I(LD7), .O(out_a));
+ bottom bottom_inst(.I(LD8), .O(led[2]), .OB(out_b));
+ bottom_intermediate bottom_intermediate_inst(.I(LD9), .O(led[3]));
+endmodule
+
+module bottom_intermediate (
+ input I,
+ output O
+);
+ wire bottom_intermediate_wire;
+ assign O = bottom_intermediate_wire;
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_8(.I(I), .O(bottom_intermediate_wire));
+endmodule
+
+module bottom (
+ input I,
+ output [1:0] OB,
+ output O
+);
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_9(.I(I), .O(O));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_10(.I(I), .O(OB[0]));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_11(.I(I), .O(OB[1]));
+endmodule
+
diff --git a/design_introspection-plugin/tests/get_nets/get_nets.golden.txt b/design_introspection-plugin/tests/get_nets/get_nets.golden.txt
new file mode 100644
index 0000000..24c2e2f
--- /dev/null
+++ b/design_introspection-plugin/tests/get_nets/get_nets.golden.txt
@@ -0,0 +1,10 @@
+*inter* nets quiet
+bottom_intermediate_inst.I bottom_intermediate_inst.O bottom_intermediate_inst.bottom_intermediate_wire inter_wire inter_wire_2
+*inter* nets
+bottom_intermediate_inst.I bottom_intermediate_inst.O bottom_intermediate_inst.bottom_intermediate_wire inter_wire inter_wire_2
+*inter* nets with invalid filter expression
+bottom_intermediate_inst.I bottom_intermediate_inst.O bottom_intermediate_inst.bottom_intermediate_wire inter_wire inter_wire_2
+Filtered nets
+clk
+All nets
+{$abc$2135$aiger2134$38} {$abc$2135$aiger2134$42} {$abc$2135$aiger2134$43} {$abc$2135$aiger2134$48} {$abc$2135$aiger2134$49} {$abc$2135$aiger2134$54} {$abc$2135$aiger2134$55} {$abc$2135$aiger2134$60} {$abc$2135$aiger2134$61} {$abc$2135$aiger2134$66} {$abc$2135$aiger2134$67} {$abc$2135$aiger2134$72} {$abc$2135$aiger2134$73} {$abc$2135$aiger2134$76} {$abc$2135$aiger2134$77} {$abc$2135$aiger2134$78} {$abc$2135$iopadmap$clk} {$auto$alumacc.cc:485:replace_alu$1469.O} LD6 LD7 LD8 LD9 bottom_inst.I bottom_inst.O bottom_inst.OB bottom_intermediate_inst.I bottom_intermediate_inst.O bottom_intermediate_inst.bottom_intermediate_wire clk counter inter_wire inter_wire_2 led out_a out_b signal_n signal_p
diff --git a/design_introspection-plugin/tests/get_nets/get_nets.tcl b/design_introspection-plugin/tests/get_nets/get_nets.tcl
new file mode 100644
index 0000000..c4fe329
--- /dev/null
+++ b/design_introspection-plugin/tests/get_nets/get_nets.tcl
@@ -0,0 +1,33 @@
+yosys -import
+plugin -i design_introspection
+#Import the commands from the plugins to the tcl interpreter
+yosys -import
+
+read_verilog get_nets.v
+# Some of symbiflow expects eblifs with only one module.
+synth_xilinx -vpr -flatten -abc9 -nosrl -noclkbuf -nodsp
+
+
+set fp [open "get_nets.txt" "w"]
+
+puts "\n*inter* nets quiet"
+puts $fp "*inter* nets quiet"
+puts $fp [get_nets -quiet *inter*]
+
+puts "\n*inter* nets"
+puts $fp "*inter* nets"
+puts $fp [get_nets *inter*]
+
+puts "\n*inter* nets with invalid filter expression"
+puts $fp "*inter* nets with invalid filter expression"
+puts $fp [get_nets -filter {mr_ff != true} *inter* ]
+
+puts "\nFiltered nets"
+puts $fp "Filtered nets"
+puts $fp [get_nets -filter {mr_ff == true || async_reg == true && dont_touch == true} ]
+
+puts "\nAll nets"
+puts $fp "All nets"
+puts $fp [get_nets]
+
+close $fp
diff --git a/design_introspection-plugin/tests/get_nets/get_nets.v b/design_introspection-plugin/tests/get_nets/get_nets.v
new file mode 100644
index 0000000..d40055b
--- /dev/null
+++ b/design_introspection-plugin/tests/get_nets/get_nets.v
@@ -0,0 +1,75 @@
+module top (
+ (* async_reg = "true", mr_ff = "true", dont_touch = "true" *) input clk,
+ output [3:0] led,
+ inout out_a,
+ output [1:0] out_b,
+ output signal_p,
+ output signal_n
+);
+
+ wire LD6, LD7, LD8, LD9;
+ wire inter_wire, inter_wire_2;
+ localparam BITS = 1;
+ localparam LOG2DELAY = 25;
+
+ reg [BITS+LOG2DELAY-1:0] counter = 0;
+
+ always @(posedge clk) begin
+ counter <= counter + 1;
+ end
+ assign led[1] = inter_wire;
+ assign inter_wire = inter_wire_2;
+ assign {LD9, LD8, LD7, LD6} = counter >> LOG2DELAY;
+ OBUFTDS OBUFTDS_2(
+ .I(LD6),
+ .O(signal_p),
+ .OB(signal_n),
+ .T(1'b1)
+ );
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_6(.I(LD6), .O(led[0]));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_7(.I(LD7), .O(inter_wire_2));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_OUT(.I(LD7), .O(out_a));
+ bottom bottom_inst(.I(LD8), .O(led[2]), .OB(out_b));
+ bottom_intermediate bottom_intermediate_inst(.I(LD9), .O(led[3]));
+endmodule
+
+module bottom_intermediate (
+ input I,
+ output O
+);
+ wire bottom_intermediate_wire;
+ assign O = bottom_intermediate_wire;
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_8(.I(I), .O(bottom_intermediate_wire));
+endmodule
+
+module bottom (
+ input I,
+ output [1:0] OB,
+ output O
+);
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_9(.I(I), .O(O));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_10(.I(I), .O(OB[0]));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_11(.I(I), .O(OB[1]));
+endmodule
+
diff --git a/design_introspection-plugin/tests/get_pins/get_pins.golden.txt b/design_introspection-plugin/tests/get_pins/get_pins.golden.txt
new file mode 100644
index 0000000..b92d21a
--- /dev/null
+++ b/design_introspection-plugin/tests/get_pins/get_pins.golden.txt
@@ -0,0 +1,12 @@
+
+*inter* pins quiet
+OBUF_6/I
+
+*inter* pins
+OBUF_6/I
+
+*inter* pins with invalid filter expression
+bottom_intermediate_inst.OBUF_8/I
+
+Filtered pins
+OBUF_7/I OBUF_OUT/I
diff --git a/design_introspection-plugin/tests/get_pins/get_pins.tcl b/design_introspection-plugin/tests/get_pins/get_pins.tcl
new file mode 100644
index 0000000..144d453
--- /dev/null
+++ b/design_introspection-plugin/tests/get_pins/get_pins.tcl
@@ -0,0 +1,29 @@
+yosys -import
+plugin -i design_introspection
+#Import the commands from the plugins to the tcl interpreter
+yosys -import
+
+read_verilog get_pins.v
+# Some of symbiflow expects eblifs with only one module.
+synth_xilinx -vpr -flatten -abc9 -nosrl -noclkbuf -nodsp
+
+
+set fp [open "get_pins.txt" "w"]
+
+puts "\n*inter* pins quiet"
+puts $fp "\n*inter* pins quiet"
+puts $fp [get_pins -quiet OBUF_6/I]
+
+puts "\n*inter* pins"
+puts $fp "\n*inter* pins"
+puts $fp [get_pins OBUF_6/I]
+
+puts "\n*inter* pins with invalid filter expression"
+puts $fp "\n*inter* pins with invalid filter expression"
+puts $fp [get_pins -filter {mr_ff != true} *inter*/I ]
+
+puts "\nFiltered pins"
+puts $fp "\nFiltered pins"
+puts $fp [get_pins -filter {dont_touch == true || async_reg == true && mr_ff == true} *OBUF*/I ]
+
+close $fp
diff --git a/design_introspection-plugin/tests/get_pins/get_pins.v b/design_introspection-plugin/tests/get_pins/get_pins.v
new file mode 100644
index 0000000..bf08129
--- /dev/null
+++ b/design_introspection-plugin/tests/get_pins/get_pins.v
@@ -0,0 +1,76 @@
+module top (
+ (* async_reg = "true", mr_ff = "true", dont_touch = "true" *) input clk,
+ output [3:0] led,
+ inout out_a,
+ output [1:0] out_b,
+ output signal_p,
+ output signal_n
+);
+
+ wire LD6, LD7, LD8, LD9;
+ wire inter_wire, inter_wire_2;
+ localparam BITS = 1;
+ localparam LOG2DELAY = 25;
+
+ reg [BITS+LOG2DELAY-1:0] counter = 0;
+
+ always @(posedge clk) begin
+ counter <= counter + 1;
+ end
+ assign led[1] = inter_wire;
+ assign inter_wire = inter_wire_2;
+ assign {LD9, LD8, LD7, LD6} = counter >> LOG2DELAY;
+ OBUFTDS OBUFTDS_2(
+ .I(LD6),
+ .O(signal_p),
+ .OB(signal_n),
+ .T(1'b1)
+ );
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_6((* test_attr = "true" *) .I(LD6), .O(led[0]));
+ (* dont_touch = "true" *) OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_7(.I(LD7), .O(inter_wire_2));
+ (* dont_touch = "true" *) OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_OUT(.I(LD7), .O(out_a));
+ bottom bottom_inst(.I(LD8), .O(led[2]), .OB(out_b));
+ bottom_intermediate bottom_intermediate_inst(.I(LD9), .O(led[3]));
+endmodule
+
+(* async_reg = "true", mr_ff = "false", dont_touch = "true" *)
+module bottom_intermediate (
+ input I,
+ output O
+);
+ wire bottom_intermediate_wire;
+ assign O = bottom_intermediate_wire;
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_8(.I(I), .O(bottom_intermediate_wire));
+endmodule
+
+module bottom (
+ input I,
+ output [1:0] OB,
+ output O
+);
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_9(.I(I), .O(O));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_10(.I(I), .O(OB[0]));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_11(.I(I), .O(OB[1]));
+endmodule
+
diff --git a/design_introspection-plugin/tests/get_ports/get_ports.golden.txt b/design_introspection-plugin/tests/get_ports/get_ports.golden.txt
new file mode 100644
index 0000000..d87ba55
--- /dev/null
+++ b/design_introspection-plugin/tests/get_ports/get_ports.golden.txt
@@ -0,0 +1,6 @@
+signal_p port
+signal_p
+clk port
+clk
+led[0] port
+led[0]
diff --git a/design_introspection-plugin/tests/get_ports/get_ports.tcl b/design_introspection-plugin/tests/get_ports/get_ports.tcl
new file mode 100644
index 0000000..1ac5903
--- /dev/null
+++ b/design_introspection-plugin/tests/get_ports/get_ports.tcl
@@ -0,0 +1,45 @@
+yosys -import
+plugin -i design_introspection
+#Import the commands from the plugins to the tcl interpreter
+yosys -import
+
+read_verilog get_ports.v
+# Some of symbiflow expects eblifs with only one module.
+synth_xilinx -vpr -flatten -abc9 -nosrl -noclkbuf -nodsp
+help get_ports
+
+set fp [open "get_ports.txt" "w"]
+
+puts "\nsignal_p port"
+puts $fp "signal_p port"
+puts $fp [get_ports signal_p]
+
+puts "\nclk port"
+puts $fp "clk port"
+puts $fp [get_ports clk]
+
+puts {\nled[0] port}
+puts $fp {led[0] port}
+puts $fp [get_ports {led[0]}]
+
+#puts "\nsignal_* ports quiet"
+#puts $fp "signal_* ports quiet"
+#puts $fp [get_ports -quiet signal_*]
+#
+#puts "\nsignal_* ports"
+#puts $fp "signal_* ports"
+#puts $fp [get_ports signal_*]
+#
+#puts "\nled ports with filter expression"
+#puts $fp "led ports with filter expression"
+#puts $fp [get_ports -filter {mr_ff != true} led]
+#
+#puts "\nFiltered ports"
+#puts $fp "Filtered ports"
+#puts $fp [get_ports -filter {mr_ff == true || async_reg == true && dont_touch == true} ]
+#
+#puts "\nAll ports"
+#puts $fp "All ports"
+#puts $fp [get_ports]
+
+close $fp
diff --git a/design_introspection-plugin/tests/get_ports/get_ports.v b/design_introspection-plugin/tests/get_ports/get_ports.v
new file mode 100644
index 0000000..d40055b
--- /dev/null
+++ b/design_introspection-plugin/tests/get_ports/get_ports.v
@@ -0,0 +1,75 @@
+module top (
+ (* async_reg = "true", mr_ff = "true", dont_touch = "true" *) input clk,
+ output [3:0] led,
+ inout out_a,
+ output [1:0] out_b,
+ output signal_p,
+ output signal_n
+);
+
+ wire LD6, LD7, LD8, LD9;
+ wire inter_wire, inter_wire_2;
+ localparam BITS = 1;
+ localparam LOG2DELAY = 25;
+
+ reg [BITS+LOG2DELAY-1:0] counter = 0;
+
+ always @(posedge clk) begin
+ counter <= counter + 1;
+ end
+ assign led[1] = inter_wire;
+ assign inter_wire = inter_wire_2;
+ assign {LD9, LD8, LD7, LD6} = counter >> LOG2DELAY;
+ OBUFTDS OBUFTDS_2(
+ .I(LD6),
+ .O(signal_p),
+ .OB(signal_n),
+ .T(1'b1)
+ );
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_6(.I(LD6), .O(led[0]));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_7(.I(LD7), .O(inter_wire_2));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_OUT(.I(LD7), .O(out_a));
+ bottom bottom_inst(.I(LD8), .O(led[2]), .OB(out_b));
+ bottom_intermediate bottom_intermediate_inst(.I(LD9), .O(led[3]));
+endmodule
+
+module bottom_intermediate (
+ input I,
+ output O
+);
+ wire bottom_intermediate_wire;
+ assign O = bottom_intermediate_wire;
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_8(.I(I), .O(bottom_intermediate_wire));
+endmodule
+
+module bottom (
+ input I,
+ output [1:0] OB,
+ output O
+);
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_9(.I(I), .O(O));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_10(.I(I), .O(OB[0]));
+ OBUF #(
+ .IOSTANDARD("LVCMOS33"),
+ .SLEW("SLOW")
+ ) OBUF_11(.I(I), .O(OB[1]));
+endmodule
+
diff --git a/xdc-plugin/tests/counter/counter.tcl b/xdc-plugin/tests/counter/counter.tcl
index b7090c8..be26dde 100644
--- a/xdc-plugin/tests/counter/counter.tcl
+++ b/xdc-plugin/tests/counter/counter.tcl
@@ -1,4 +1,5 @@
yosys -import
+plugin -i design_introspection
plugin -i xdc
#Import the commands from the plugins to the tcl interpreter
yosys -import
diff --git a/xdc-plugin/tests/io_loc_pairs/io_loc_pairs.tcl b/xdc-plugin/tests/io_loc_pairs/io_loc_pairs.tcl
index b7090c8..be26dde 100644
--- a/xdc-plugin/tests/io_loc_pairs/io_loc_pairs.tcl
+++ b/xdc-plugin/tests/io_loc_pairs/io_loc_pairs.tcl
@@ -1,4 +1,5 @@
yosys -import
+plugin -i design_introspection
plugin -i xdc
#Import the commands from the plugins to the tcl interpreter
yosys -import
diff --git a/xdc-plugin/tests/minilitex_ddr_arty/minilitex_ddr_arty.tcl b/xdc-plugin/tests/minilitex_ddr_arty/minilitex_ddr_arty.tcl
index af91ce6..34d7947 100644
--- a/xdc-plugin/tests/minilitex_ddr_arty/minilitex_ddr_arty.tcl
+++ b/xdc-plugin/tests/minilitex_ddr_arty/minilitex_ddr_arty.tcl
@@ -1,4 +1,5 @@
yosys -import
+plugin -i design_introspection
plugin -i xdc
#Import the commands from the plugins to the tcl interpreter
yosys -import
diff --git a/xdc-plugin/tests/package_pins/package_pins.tcl b/xdc-plugin/tests/package_pins/package_pins.tcl
index 66bd21d..2df419a 100644
--- a/xdc-plugin/tests/package_pins/package_pins.tcl
+++ b/xdc-plugin/tests/package_pins/package_pins.tcl
@@ -1,4 +1,5 @@
yosys -import
+plugin -i design_introspection
plugin -i xdc
#Import the commands from the plugins to the tcl interpreter
yosys -import
diff --git a/xdc-plugin/tests/port_indexes/port_indexes.tcl b/xdc-plugin/tests/port_indexes/port_indexes.tcl
index ed35c69..283cce5 100644
--- a/xdc-plugin/tests/port_indexes/port_indexes.tcl
+++ b/xdc-plugin/tests/port_indexes/port_indexes.tcl
@@ -1,4 +1,5 @@
yosys -import
+plugin -i design_introspection
plugin -i xdc
#Import the commands from the plugins to the tcl interpreter
yosys -import
diff --git a/xdc-plugin/xdc.cc b/xdc-plugin/xdc.cc
index 9a8e5e7..a27bdf7 100644
--- a/xdc-plugin/xdc.cc
+++ b/xdc-plugin/xdc.cc
@@ -61,7 +61,8 @@
{"OBUFDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}},
{"OBUFTDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}},
{"IBUF", {"IO_LOC_PAIRS", "IOSTANDARD"}},
- {"IOBUF", {"IO_LOC_PAIRS", "IOSTANDARD", "DRIVE", "SLEW", "IN_TERM"}}
+ {"IOBUF", {"IO_LOC_PAIRS", "IOSTANDARD", "DRIVE", "SLEW", "IN_TERM"}},
+ {"IOBUFDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}}
};
void register_in_tcl_interpreter(const std::string& command) {
@@ -70,57 +71,6 @@
Tcl_Eval(interp, tcl_script.c_str());
}
-struct GetPorts : public Pass {
- GetPorts() : Pass("get_ports", "Print matching ports") {
- register_in_tcl_interpreter(pass_name);
- }
-
- void help() override
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" get_ports <port_name> \n");
- log("\n");
- log("Get matching ports\n");
- log("\n");
- log("Print the output to stdout too. This is useful when all Yosys is executed\n");
- log("\n");
- }
-
- void execute(std::vector<std::string> args, RTLIL::Design* design) override
- {
- if (args.size() < 2) {
- log_cmd_error("No port specified.\n");
- }
- RTLIL::Module* top_module = design->top_module();
- if (top_module == nullptr) {
- log_cmd_error("No top module detected\n");
- }
- // TODO handle more than one port
- port_name = args.at(1);
- std::string port_str(port_name.size(), '\0');
- int bit(0);
- if (!sscanf(port_name.c_str(), "%[^[][%d]", &port_str[0], &bit)) {
- log_error("Couldn't find port %s\n", port_name.c_str());
- }
-
- port_str.resize(strlen(port_str.c_str()));
- RTLIL::IdString port_id(RTLIL::escape_id(port_str));
- if (auto wire = top_module->wire(port_id)) {
- if (isInputPort(wire) || isOutputPort(wire)) {
- if (bit >= wire->start_offset && bit < wire->start_offset + wire->width) {
- Tcl_Interp *interp = yosys_get_tcl_interp();
- Tcl_SetResult(interp, const_cast<char*>(port_name.c_str()), NULL);
- log("Found port %s\n", port_name.c_str());
- return;
- }
- }
- }
- log_error("Couldn't find port %s\n", port_name.c_str());
- }
- std::string port_name;
-};
-
struct GetIOBanks : public Pass {
GetIOBanks(std::function<const BankTilesMap&()> get_bank_tiles)
: Pass("get_iobanks", "Set IO Bank number")
@@ -434,7 +384,6 @@
}
BankTilesMap bank_tiles;
- struct GetPorts GetPorts;
struct GetIOBanks GetIOBanks;
struct SetProperty SetProperty;
} ReadXdc;