aboutsummaryrefslogtreecommitdiffstats
path: root/passes/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'passes/cmds')
-rw-r--r--passes/cmds/Makefile.inc1
-rw-r--r--passes/cmds/autoname.cc134
-rw-r--r--passes/cmds/check.cc82
3 files changed, 190 insertions, 27 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index cf9663d1d..c7edc30fb 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -5,6 +5,7 @@ OBJS += passes/cmds/design.o
OBJS += passes/cmds/select.o
OBJS += passes/cmds/show.o
OBJS += passes/cmds/rename.o
+OBJS += passes/cmds/autoname.o
OBJS += passes/cmds/connect.o
OBJS += passes/cmds/scatter.o
OBJS += passes/cmds/setundef.o
diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc
new file mode 100644
index 000000000..4614a8153
--- /dev/null
+++ b/passes/cmds/autoname.cc
@@ -0,0 +1,134 @@
+/*
+ * 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"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+int autoname_worker(Module *module)
+{
+ dict<Cell*, pair<int, IdString>> proposed_cell_names;
+ dict<Wire*, pair<int, IdString>> proposed_wire_names;
+ dict<Wire*, int> wire_score;
+ int best_score = -1;
+
+ for (auto cell : module->selected_cells())
+ for (auto &conn : cell->connections())
+ for (auto bit : conn.second)
+ if (bit.wire != nullptr)
+ wire_score[bit.wire]++;
+
+ for (auto cell : module->selected_cells()) {
+ if (cell->name[0] == '$') {
+ for (auto &conn : cell->connections()) {
+ string suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first));
+ for (auto bit : conn.second)
+ if (bit.wire != nullptr && bit.wire->name[0] != '$') {
+ IdString new_name(bit.wire->name.str() + suffix);
+ int score = wire_score.at(bit.wire);
+ if (cell->output(conn.first)) score = 0;
+ score = 10000*score + new_name.size();
+ if (!proposed_cell_names.count(cell) || score < proposed_cell_names.at(cell).first) {
+ if (best_score < 0 || score < best_score)
+ best_score = score;
+ proposed_cell_names[cell] = make_pair(score, new_name);
+ }
+ }
+ }
+ } else {
+ for (auto &conn : cell->connections()) {
+ string suffix = stringf("_%s", log_id(conn.first));
+ for (auto bit : conn.second)
+ if (bit.wire != nullptr && bit.wire->name[0] == '$') {
+ IdString new_name(cell->name.str() + suffix);
+ int score = wire_score.at(bit.wire);
+ if (cell->output(conn.first)) score = 0;
+ score = 10000*score + new_name.size();
+ if (!proposed_wire_names.count(bit.wire) || score < proposed_wire_names.at(bit.wire).first) {
+ if (best_score < 0 || score < best_score)
+ best_score = score;
+ proposed_wire_names[bit.wire] = make_pair(score, new_name);
+ }
+ }
+ }
+ }
+ }
+
+ for (auto &it : proposed_cell_names) {
+ if (best_score*2 < it.second.first)
+ continue;
+ IdString n = module->uniquify(it.second.second);
+ log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n));
+ module->rename(it.first, n);
+ }
+
+ for (auto &it : proposed_wire_names) {
+ if (best_score*2 < it.second.first)
+ continue;
+ IdString n = module->uniquify(it.second.second);
+ log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n));
+ module->rename(it.first, n);
+ }
+
+ return proposed_cell_names.size() + proposed_wire_names.size();
+}
+
+struct AutonamePass : public Pass {
+ AutonamePass() : Pass("autoname", "automatically assign names to objects") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" autoname [selection]\n");
+ log("\n");
+ log("Assign auto-generated public names to objects with private names (the ones\n");
+ log("with $-prefix).\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-foo") {
+ // foo = true;
+ // continue;
+ // }
+ break;
+ }
+
+ log_header(design, "Executing AUTONAME pass.\n");
+
+ for (auto module : design->selected_modules())
+ {
+ int count = 0, iter = 0;
+ while (1) {
+ iter++;
+ int n = autoname_worker(module);
+ if (!n) break;
+ count += n;
+ }
+ if (count > 0)
+ log("Renamed %d objects in module %s (%d iterations).\n", count, log_id(module), iter);
+ }
+ }
+} AutonamePass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index 64697c134..820ecac7b 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -41,14 +41,24 @@ struct CheckPass : public Pass {
log("\n");
log(" - used wires that do not have a driver\n");
log("\n");
- log("When called with -noinit then this command also checks for wires which have\n");
- log("the 'init' attribute set.\n");
+ log("Options:\n");
log("\n");
- log("When called with -initdrv then this command also checks for wires which have\n");
- log("the 'init' attribute set and aren't driven by a FF cell type.\n");
+ log(" -noinit\n");
+ log(" Also check for wires which have the 'init' attribute set.\n");
log("\n");
- log("When called with -assert then the command will produce an error if any\n");
- log("problems are found in the current design.\n");
+ log(" -initdrv\n");
+ log(" Also check for wires that have the 'init' attribute set and are not\n");
+ log(" driven by an FF cell type.\n");
+ log("\n");
+ log(" -mapped\n");
+ log(" Also check for internal cells that have not been mapped to cells of the\n");
+ log(" target architecture.\n");
+ log("\n");
+ log(" -allow-tbuf\n");
+ log(" Modify the -mapped behavior to still allow $_TBUF_ cells.\n");
+ log("\n");
+ log(" -assert\n");
+ log(" Produce a runtime error if any problems are found in the current design.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -56,6 +66,8 @@ struct CheckPass : public Pass {
int counter = 0;
bool noinit = false;
bool initdrv = false;
+ bool mapped = false;
+ bool allow_tbuf = false;
bool assert_mode = false;
size_t argidx;
@@ -68,6 +80,14 @@ struct CheckPass : public Pass {
initdrv = true;
continue;
}
+ if (args[argidx] == "-mapped") {
+ mapped = true;
+ continue;
+ }
+ if (args[argidx] == "-allow-tbuf") {
+ allow_tbuf = true;
+ continue;
+ }
if (args[argidx] == "-assert") {
assert_mode = true;
continue;
@@ -135,29 +155,37 @@ struct CheckPass : public Pass {
TopoSort<string> topo;
for (auto cell : module->cells())
- for (auto &conn : cell->connections()) {
- SigSpec sig = sigmap(conn.second);
- bool logic_cell = yosys_celltypes.cell_evaluable(cell->type);
- if (cell->input(conn.first))
- for (auto bit : sig)
- if (bit.wire) {
+ {
+ if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) {
+ if (allow_tbuf && cell->type == ID($_TBUF_)) goto cell_allowed;
+ log_warning("Cell %s.%s is an unmapped internal cell of type %s.\n", log_id(module), log_id(cell), log_id(cell->type));
+ counter++;
+ cell_allowed:;
+ }
+ for (auto &conn : cell->connections()) {
+ SigSpec sig = sigmap(conn.second);
+ bool logic_cell = yosys_celltypes.cell_evaluable(cell->type);
+ if (cell->input(conn.first))
+ for (auto bit : sig)
+ if (bit.wire) {
+ if (logic_cell)
+ topo.edge(stringf("wire %s", log_signal(bit)),
+ stringf("cell %s (%s)", log_id(cell), log_id(cell->type)));
+ used_wires.insert(bit);
+ }
+ if (cell->output(conn.first))
+ for (int i = 0; i < GetSize(sig); i++) {
if (logic_cell)
- topo.edge(stringf("wire %s", log_signal(bit)),
- stringf("cell %s (%s)", log_id(cell), log_id(cell->type)));
- used_wires.insert(bit);
+ topo.edge(stringf("cell %s (%s)", log_id(cell), log_id(cell->type)),
+ stringf("wire %s", log_signal(sig[i])));
+ if (sig[i].wire)
+ wire_drivers[sig[i]].push_back(stringf("port %s[%d] of cell %s (%s)",
+ log_id(conn.first), i, log_id(cell), log_id(cell->type)));
}
- if (cell->output(conn.first))
- for (int i = 0; i < GetSize(sig); i++) {
- if (logic_cell)
- topo.edge(stringf("cell %s (%s)", log_id(cell), log_id(cell->type)),
- stringf("wire %s", log_signal(sig[i])));
- if (sig[i].wire)
- wire_drivers[sig[i]].push_back(stringf("port %s[%d] of cell %s (%s)",
- log_id(conn.first), i, log_id(cell), log_id(cell->type)));
- }
- if (!cell->input(conn.first) && cell->output(conn.first))
- for (auto bit : sig)
- if (bit.wire) wire_drivers_count[bit]++;
+ if (!cell->input(conn.first) && cell->output(conn.first))
+ for (auto bit : sig)
+ if (bit.wire) wire_drivers_count[bit]++;
+ }
}
pool<SigBit> init_bits;