From b0aab4e3046f1a598314e2563fa84b3a8ddc7fa5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 9 Aug 2016 19:56:55 +0200 Subject: Added "attrmap" command --- passes/techmap/Makefile.inc | 1 + passes/techmap/attrmap.cc | 250 ++++++++++++++++++++++++++++++++++++++++++++ passes/techmap/attrmvcp.cc | 2 + 3 files changed, 253 insertions(+) create mode 100644 passes/techmap/attrmap.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index c07d69fb2..b5024fa96 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -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 index 000000000..648d1bc5a --- /dev/null +++ b/passes/techmap/attrmap.cc @@ -0,0 +1,250 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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> &actions, dict &attributes) +{ + dict 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 \n"); + log(" Match attribute names case-insensitively and set it to the specified\n"); + log(" name.\n"); + log("\n"); + log(" -rename \n"); + log(" Rename attributes as specified\n"); + log("\n"); + log(" -map = =\n"); + log(" Map key/value pairs as indicated.\n"); + log("\n"); + log(" -imap = =\n"); + log(" Like -map, but use case-insensitive match for when\n"); + log(" it is a string value.\n"); + log("\n"); + log(" -remove =\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 args, RTLIL::Design *design) + { + log_header(design, "Executing ATTRMAP pass (move or copy attributes).\n"); + + bool modattr_mode = false; + vector> 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(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(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(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(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 diff --git a/passes/techmap/attrmvcp.cc b/passes/techmap/attrmvcp.cc index 1af6077f5..50eaf61df 100644 --- a/passes/techmap/attrmvcp.cc +++ b/passes/techmap/attrmvcp.cc @@ -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; } -- cgit v1.2.3