summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2015-02-13 14:34:51 +0100
committerClifford Wolf <clifford@clifford.at>2015-02-13 14:34:51 +0100
commit04cb947d6a35b3773e694651971f28cbf83952e9 (patch)
tree368761c1738878d40cb171a024f065f768b89b13
parentcd919abdf1177ddd5148fbf236201ce5e649ead0 (diff)
Added "check" command
-rw-r--r--passes/cmds/Makefile.inc1
-rw-r--r--passes/cmds/check.cc126
-rw-r--r--techlibs/common/synth.cc4
3 files changed, 131 insertions, 0 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 0e62abbc..e4b40c41 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -21,4 +21,5 @@ OBJS += passes/cmds/connwrappers.o
OBJS += passes/cmds/cover.o
OBJS += passes/cmds/trace.o
OBJS += passes/cmds/plugin.o
+OBJS += passes/cmds/check.o
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
new file mode 100644
index 00000000..39a732ff
--- /dev/null
+++ b/passes/cmds/check.cc
@@ -0,0 +1,126 @@
+/*
+ * 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"
+#include "kernel/celltypes.h"
+#include "kernel/utils.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct CheckPass : public Pass {
+ CheckPass() : Pass("check", "check for obvious problems in the design") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" check [selection]\n");
+ log("\n");
+ log("This pass identifies the following problems in the current design:\n");
+ log("\n");
+ log(" - combinatorical loops\n");
+ log("\n");
+ log(" - two or more conflicting drivers for one wire\n");
+ log("\n");
+ log(" - used wires that do not have a driver\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ int counter = 0;
+
+ log_header("Executing CHECK pass (checking for obvious problems).\n");
+
+ extra_args(args, 1, design);
+
+ for (auto module : design->selected_whole_modules_warn())
+ {
+ if (module->has_processes_warn())
+ continue;
+
+ log("checking module %s..\n", log_id(module));
+
+ SigMap sigmap(module);
+ dict<SigBit, vector<string>> wire_drivers;
+ pool<SigBit> used_wires;
+ 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 (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("cell %s (%s)", log_id(cell), log_id(cell->type)),
+ stringf("wire %s", log_signal(sig[i])));
+ 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)));
+ }
+ }
+
+ for (auto wire : module->wires()) {
+ if (wire->port_input) {
+ SigSpec sig = sigmap(wire);
+ for (int i = 0; i < GetSize(sig); i++)
+ wire_drivers[sig[i]].push_back(stringf("module input %s[%d]", log_id(wire), i));
+ }
+ if (wire->port_output)
+ for (auto bit : sigmap(wire)) used_wires.insert(bit);
+ }
+
+ for (auto it : wire_drivers)
+ if (GetSize(it.second) > 1) {
+ string message = stringf("multiple conflicting drivers for %s.%s:\n", log_id(module), log_signal(it.first));
+ for (auto str : it.second)
+ message += stringf(" %s\n", str.c_str());
+ log_warning("%s", message.c_str());
+ counter++;
+ }
+
+ for (auto bit : used_wires)
+ if (!wire_drivers.count(bit)) {
+ log_warning("Wire %s.%s is used but has no driver.\n", log_id(module), log_signal(bit));
+ counter++;
+ }
+
+ topo.sort();
+ for (auto &loop : topo.loops) {
+ string message = stringf("found logic loop in module %s:\n", log_id(module));
+ for (auto &str : loop)
+ message += stringf(" %s\n", str.c_str());
+ log_warning("%s", message.c_str());
+ counter++;
+ }
+ }
+
+ log("found and reported %d problems.\n", counter);
+ }
+} CheckPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc
index 69ef5bc5..a50db53e 100644
--- a/techlibs/common/synth.cc
+++ b/techlibs/common/synth.cc
@@ -71,6 +71,8 @@ struct SynthPass : public Pass {
log("\n");
log(" coarse:\n");
log(" proc\n");
+ log(" opt_clean\n");
+ log(" check\n");
log(" opt\n");
log(" wreduce\n");
log(" alumacc\n");
@@ -150,6 +152,8 @@ struct SynthPass : public Pass {
if (check_label(active, run_from, run_to, "coarse"))
{
Pass::call(design, "proc");
+ Pass::call(design, "opt_clean");
+ Pass::call(design, "check");
Pass::call(design, "opt");
Pass::call(design, "wreduce");
Pass::call(design, "alumacc");