Added "attrmap" command
authorClifford Wolf <clifford@clifford.at>
Tue, 9 Aug 2016 17:56:55 +0000 (19:56 +0200)
committerClifford Wolf <clifford@clifford.at>
Tue, 9 Aug 2016 17:56:55 +0000 (19:56 +0200)
passes/techmap/Makefile.inc
passes/techmap/attrmap.cc [new file with mode: 0644]
passes/techmap/attrmvcp.cc

index c07d69fb2971f7a1803e8f3906b6c26dcaca368e..b5024fa969f30b949c13f40c68d4702b9cc07a51 100644 (file)
@@ -30,6 +30,7 @@ OBJS += passes/techmap/shregmap.o
 OBJS += passes/techmap/deminout.o
 OBJS += passes/techmap/insbuf.o
 OBJS += passes/techmap/attrmvcp.o
+OBJS += passes/techmap/attrmap.o
 endif
 
 GENFILES += passes/techmap/techmap.inc
diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc
new file mode 100644 (file)
index 0000000..648d1bc
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2012  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"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+Const make_value(string &value)
+{
+       if (GetSize(value) >= 2 && value.front() == '"' && value.back() == '"')
+               return Const(value.substr(1, GetSize(value)-2));
+
+       SigSpec sig;
+       SigSpec::parse(sig, nullptr, value);
+       return sig.as_const();
+}
+
+bool match_name(string &name, IdString &id, bool ignore_case=false)
+{
+       string str1 = RTLIL::escape_id(name);
+       string str2 = id.str();
+
+       if (ignore_case)
+               return !strcasecmp(str1.c_str(), str2.c_str());
+
+       return str1 == str2;
+}
+
+bool match_value(string &value, Const &val, bool ignore_case=false)
+{
+       if (ignore_case && ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) && GetSize(value) && value.front() == '"' && value.back() == '"') {
+               string str1 = value.substr(1, GetSize(value)-2);
+               string str2 = val.decode_string();
+               return !strcasecmp(str1.c_str(), str2.c_str());
+       }
+
+       return make_value(value) == val;
+}
+
+struct AttrmapAction {
+       virtual ~AttrmapAction() { }
+       virtual bool apply(IdString &id, Const &val) = 0;
+};
+
+struct AttrmapTocase : AttrmapAction {
+       string name;
+       virtual bool apply(IdString &id, Const&) {
+               if (match_name(name, id, true))
+                       id = RTLIL::escape_id(name);
+               return true;
+       }
+};
+
+struct AttrmapRename : AttrmapAction {
+       string old_name, new_name;
+       virtual bool apply(IdString &id, Const&) {
+               if (match_name(old_name, id))
+                       id = RTLIL::escape_id(new_name);
+               return true;
+       }
+};
+
+struct AttrmapMap : AttrmapAction {
+       bool imap;
+       string old_name, new_name;
+       string old_value, new_value;
+       virtual bool apply(IdString &id, Const &val) {
+               if (match_name(old_name, id) && match_value(old_value, val, true)) {
+                       id = RTLIL::escape_id(new_name);
+                       val = make_value(new_value);
+               }
+               return true;
+       }
+};
+
+struct AttrmapRemove : AttrmapAction {
+       string name, value;
+       virtual bool apply(IdString &id, Const &val) {
+               return !(match_name(name, id) && match_value(value, val));
+       }
+};
+
+void attrmap_apply(string objname, vector<std::unique_ptr<AttrmapAction>> &actions, dict<RTLIL::IdString, RTLIL::Const> &attributes)
+{
+       dict<RTLIL::IdString, RTLIL::Const> new_attributes;
+
+       for (auto attr : attributes)
+       {
+               auto new_attr = attr;
+               for (auto &action : actions)
+                       if (!action->apply(new_attr.first, new_attr.second))
+                               goto delete_this_attr;
+
+               if (new_attr != attr)
+                       log("Changed attribute on %s: %s=%s -> %s=%s\n", objname.c_str(),
+                                       log_id(attr.first), log_const(attr.second), log_id(new_attr.first), log_const(new_attr.second));
+
+               new_attributes[new_attr.first] = new_attr.second;
+
+               if (0)
+       delete_this_attr:
+                       log("Removed attribute on %s: %s=%s\n", objname.c_str(), log_id(attr.first), log_const(attr.second));
+       }
+
+       attributes.swap(new_attributes);
+}
+
+struct AttrmapPass : public Pass {
+       AttrmapPass() : Pass("attrmap", "renaming attributes") { }
+       virtual void help()
+       {
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+               log("\n");
+               log("    attrmap [options] [selection]\n");
+               log("\n");
+               log("This command renames attributes and/or mapps key/value pairs to\n");
+               log("other key/value pairs.\n");
+               log("\n");
+               log("    -tocase <name>\n");
+               log("        Match attribute names case-insensitively and set it to the specified\n");
+               log("        name.\n");
+               log("\n");
+               log("    -rename <old_name> <new_name>\n");
+               log("        Rename attributes as specified\n");
+               log("\n");
+               log("    -map <old_name>=<old_value> <new_name>=<new_value>\n");
+               log("        Map key/value pairs as indicated.\n");
+               log("\n");
+               log("    -imap <old_name>=<old_value> <new_name>=<new_value>\n");
+               log("        Like -map, but use case-insensitive match for <old_value> when\n");
+               log("        it is a string value.\n");
+               log("\n");
+               log("    -remove <name>=<value>\n");
+               log("        Remove attributes matching this pattern.\n");
+               log("\n");
+               log("    -modattr\n");
+               log("        Operate on module attributes instead of attributes on wires and cells.\n");
+               log("\n");
+               log("For example, mapping Xilinx-style \"keep\" attributes to Yosys-style:\n");
+               log("\n");
+               log("    attrmap -tocase keep -imap keep=\"true\" keep=1 \\\n");
+               log("            -imap keep=\"false\" keep=0 -remove keep=0\n");
+               log("\n");
+       }
+       virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+       {
+               log_header(design, "Executing ATTRMAP pass (move or copy attributes).\n");
+
+               bool modattr_mode = false;
+               vector<std::unique_ptr<AttrmapAction>> actions;
+
+               size_t argidx;
+               for (argidx = 1; argidx < args.size(); argidx++)
+               {
+                       std::string arg = args[argidx];
+                       if (arg == "-tocase" && argidx+1 < args.size()) {
+                               auto action = new AttrmapTocase;
+                               action->name = args[++argidx];
+                               actions.push_back(std::move(std::unique_ptr<AttrmapAction>(action)));
+                               continue;
+                       }
+                       if (arg == "-rename" && argidx+2 < args.size()) {
+                               auto action = new AttrmapRename;
+                               action->old_name = args[++argidx];
+                               action->new_name = args[++argidx];
+                               actions.push_back(std::move(std::unique_ptr<AttrmapAction>(action)));
+                               continue;
+                       }
+                       if ((arg == "-map" || arg == "-imap") && argidx+2 < args.size()) {
+                               string arg1 = args[++argidx];
+                               string arg2 = args[++argidx];
+                               string val1, val2;
+                               size_t p = arg1.find("=");
+                               if (p != string::npos) {
+                                       val1 = arg1.substr(p+1);
+                                       arg1 = arg1.substr(0, p);
+                               }
+                               p = arg2.find("=");
+                               if (p != string::npos) {
+                                       val2 = arg2.substr(p+1);
+                                       arg2 = arg2.substr(0, p);
+                               }
+                               auto action = new AttrmapMap;
+                               action->imap = (arg == "-map");
+                               action->old_name = arg1;
+                               action->new_name = arg2;
+                               action->old_value = val1;
+                               action->new_value = val2;
+                               actions.push_back(std::move(std::unique_ptr<AttrmapAction>(action)));
+                               continue;
+                       }
+                       if (arg == "-remove" && argidx+1 < args.size()) {
+                               string arg1 = args[++argidx], val1;
+                               size_t p = arg1.find("=");
+                               if (p != string::npos) {
+                                       val1 = arg1.substr(p+1);
+                                       arg1 = arg1.substr(0, p);
+                               }
+                               auto action = new AttrmapRemove;
+                               action->name = arg1;
+                               action->value = val1;
+                               actions.push_back(std::move(std::unique_ptr<AttrmapAction>(action)));
+                               continue;
+                       }
+                       if (arg == "-modattr") {
+                               modattr_mode = true;
+                               continue;
+                       }
+                       break;
+               }
+               extra_args(args, argidx, design);
+
+               if (modattr_mode)
+               {
+                       for (auto module : design->selected_whole_modules())
+                               attrmap_apply(stringf("%s", log_id(module)), actions, module->attributes);
+               }
+               else
+               {
+                       for (auto module : design->selected_modules())
+                       {
+                               for (auto wire : module->selected_wires())
+                                       attrmap_apply(stringf("%s.%s", log_id(module), log_id(wire)), actions, wire->attributes);
+
+                               for (auto cell : module->selected_cells())
+                                       attrmap_apply(stringf("%s.%s", log_id(module), log_id(cell)), actions, cell->attributes);
+                       }
+               }
+       }
+} AttrmapPass;
+
+PRIVATE_NAMESPACE_END
index 1af6077f54f6ffd84d78980773c8c7e0415e25bb..50eaf61dff46262ece4450327d2dab9f64ce7965 100644 (file)
@@ -119,6 +119,8 @@ struct AttrmvcpPass : public Pass {
                                        for (auto bit : sigmap(wire))
                                                if (net2cells.count(bit))
                                                        for (auto cell : net2cells.at(bit)) {
+                                                               log("Moving attribute %s=%s from %s.%s to %s.%s.\n", log_id(attr.first), log_const(attr.second),
+                                                                               log_id(module), log_id(wire), log_id(module), log_id(cell));
                                                                cell->attributes[attr.first] = attr.second;
                                                                did_something = true;
                                                        }