summaryrefslogtreecommitdiff
path: root/passes/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'passes/cmds')
-rw-r--r--passes/cmds/Makefile.inc2
-rw-r--r--passes/cmds/add.cc2
-rw-r--r--passes/cmds/blackbox.cc2
-rw-r--r--passes/cmds/bugpoint.cc371
-rw-r--r--passes/cmds/chformal.cc4
-rw-r--r--passes/cmds/connect.cc6
-rw-r--r--passes/cmds/cover.cc10
-rw-r--r--passes/cmds/plugin.cc50
-rw-r--r--passes/cmds/qwp.cc2
-rw-r--r--passes/cmds/rename.cc148
-rw-r--r--passes/cmds/select.cc60
-rw-r--r--passes/cmds/setattr.cc39
-rw-r--r--passes/cmds/setundef.cc140
-rw-r--r--passes/cmds/show.cc27
-rw-r--r--passes/cmds/stat.cc76
-rw-r--r--passes/cmds/tee.cc9
-rw-r--r--passes/cmds/trace.cc34
-rw-r--r--passes/cmds/write_file.cc2
18 files changed, 923 insertions, 61 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 44a83b2b..c8067a8b 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -29,4 +29,4 @@ OBJS += passes/cmds/chformal.o
OBJS += passes/cmds/chtype.o
OBJS += passes/cmds/blackbox.o
OBJS += passes/cmds/ltp.o
-
+OBJS += passes/cmds/bugpoint.o
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index cfccca96..af6f7043 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -71,7 +71,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
RTLIL::Module *mod = design->modules_.at(it.second->type);
if (!design->selected_whole_module(mod->name))
continue;
- if (mod->get_bool_attribute("\\blackbox"))
+ if (mod->get_blackbox_attribute())
continue;
if (it.second->hasPort(name))
continue;
diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc
index 6094f8f1..d09ed872 100644
--- a/passes/cmds/blackbox.cc
+++ b/passes/cmds/blackbox.cc
@@ -23,7 +23,7 @@ USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct BlackboxPass : public Pass {
- BlackboxPass() : Pass("blackbox", "change type of cells in the design") { }
+ BlackboxPass() : Pass("blackbox", "convert modules into blackbox modules") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
new file mode 100644
index 00000000..038ab7c7
--- /dev/null
+++ b/passes/cmds/bugpoint.cc
@@ -0,0 +1,371 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 whitequark <whitequark@whitequark.org>
+ *
+ * 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 "backends/ilang/ilang_backend.h"
+
+USING_YOSYS_NAMESPACE
+using namespace ILANG_BACKEND;
+PRIVATE_NAMESPACE_BEGIN
+
+struct BugpointPass : public Pass {
+ BugpointPass() : Pass("bugpoint", "minimize testcases") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" bugpoint [options]\n");
+ log("\n");
+ log("This command minimizes testcases that crash Yosys. It removes an arbitrary part\n");
+ log("of the design and recursively invokes Yosys with a given script, repeating these\n");
+ log("steps while it can find a smaller design that still causes a crash. Once this\n");
+ log("command finishes, it replaces the current design with the smallest testcase it\n");
+ log("was able to produce.\n");
+ log("\n");
+ log("It is possible to specify the kinds of design part that will be removed. If none\n");
+ log("are specified, all parts of design will be removed.\n");
+ log("\n");
+ log(" -yosys <filename>\n");
+ log(" use this Yosys binary. if not specified, `yosys` is used.\n");
+ log("\n");
+ log(" -script <filename>\n");
+ log(" use this script to crash Yosys. required.\n");
+ log("\n");
+ log(" -grep <string>\n");
+ log(" only consider crashes that place this string in the log file.\n");
+ log("\n");
+ log(" -fast\n");
+ log(" run `clean -purge` after each minimization step. converges faster, but\n");
+ log(" produces larger testcases, and may fail to produce any testcase at all if\n");
+ log(" the crash is related to dangling wires.\n");
+ log("\n");
+ log(" -clean\n");
+ log(" run `clean -purge` before checking testcase and after finishing. produces\n");
+ log(" smaller and more useful testcases, but may fail to produce any testcase\n");
+ log(" at all if the crash is related to dangling wires.\n");
+ log("\n");
+ log(" -modules\n");
+ log(" try to remove modules.\n");
+ log("\n");
+ log(" -ports\n");
+ log(" try to remove module ports.\n");
+ log("\n");
+ log(" -cells\n");
+ log(" try to remove cells.\n");
+ log("\n");
+ log(" -connections\n");
+ log(" try to reconnect ports to 'x.\n");
+ log("\n");
+ }
+
+ bool run_yosys(RTLIL::Design *design, string yosys_cmd, string script)
+ {
+ design->sort();
+
+ std::ofstream f("bugpoint-case.il");
+ ILANG_BACKEND::dump_design(f, design, /*only_selected=*/false, /*flag_m=*/true, /*flag_n=*/false);
+ f.close();
+
+ string yosys_cmdline = stringf("%s -qq -L bugpoint-case.log -s %s bugpoint-case.il", yosys_cmd.c_str(), script.c_str());
+ return run_command(yosys_cmdline) == 0;
+ }
+
+ bool check_logfile(string grep)
+ {
+ if (grep.empty())
+ return true;
+
+ std::ifstream f("bugpoint-case.log");
+ while (!f.eof())
+ {
+ string line;
+ getline(f, line);
+ if (line.find(grep) != std::string::npos)
+ return true;
+ }
+ return false;
+ }
+
+ RTLIL::Design *clean_design(RTLIL::Design *design, bool do_clean = true, bool do_delete = false)
+ {
+ if (!do_clean)
+ return design;
+
+ RTLIL::Design *design_copy = new RTLIL::Design;
+ for (auto &it : design->modules_)
+ design_copy->add(it.second->clone());
+ Pass::call(design_copy, "clean -purge");
+
+ if (do_delete)
+ delete design;
+ return design_copy;
+ }
+
+ RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections)
+ {
+ RTLIL::Design *design_copy = new RTLIL::Design;
+ for (auto &it : design->modules_)
+ design_copy->add(it.second->clone());
+
+ int index = 0;
+ if (modules)
+ {
+ for (auto &it : design_copy->modules_)
+ {
+ if (it.second->get_blackbox_attribute())
+ continue;
+
+ if (index++ == seed)
+ {
+ log("Trying to remove module %s.\n", it.first.c_str());
+ design_copy->remove(it.second);
+ return design_copy;
+ }
+ }
+ }
+ if (ports)
+ {
+ for (auto mod : design_copy->modules())
+ {
+ if (mod->get_blackbox_attribute())
+ continue;
+
+ for (auto wire : mod->wires())
+ {
+ if (!stage2 && wire->get_bool_attribute("$bugpoint"))
+ continue;
+
+ if (wire->port_input || wire->port_output)
+ {
+ if (index++ == seed)
+ {
+ log("Trying to remove module port %s.\n", log_signal(wire));
+ wire->port_input = wire->port_output = false;
+ mod->fixup_ports();
+ return design_copy;
+ }
+ }
+ }
+ }
+ }
+ if (cells)
+ {
+ for (auto mod : design_copy->modules())
+ {
+ if (mod->get_blackbox_attribute())
+ continue;
+
+ for (auto &it : mod->cells_)
+ {
+ if (index++ == seed)
+ {
+ log("Trying to remove cell %s.%s.\n", mod->name.c_str(), it.first.c_str());
+ mod->remove(it.second);
+ return design_copy;
+ }
+ }
+ }
+ }
+ if (connections)
+ {
+ for (auto mod : design_copy->modules())
+ {
+ if (mod->get_blackbox_attribute())
+ continue;
+
+ for (auto cell : mod->cells())
+ {
+ for (auto it : cell->connections_)
+ {
+ RTLIL::SigSpec port = cell->getPort(it.first);
+ bool is_undef = port.is_fully_undef();
+ bool is_port = port.is_wire() && (port.as_wire()->port_input || port.as_wire()->port_output);
+
+ if(is_undef || (!stage2 && is_port))
+ continue;
+
+ if (index++ == seed)
+ {
+ log("Trying to remove cell port %s.%s.%s.\n", mod->name.c_str(), cell->name.c_str(), it.first.c_str());
+ RTLIL::SigSpec port_x(State::Sx, port.size());
+ cell->unsetPort(it.first);
+ cell->setPort(it.first, port_x);
+ return design_copy;
+ }
+
+ if (!stage2 && (cell->input(it.first) || cell->output(it.first)) && index++ == seed)
+ {
+ log("Trying to expose cell port %s.%s.%s as module port.\n", mod->name.c_str(), cell->name.c_str(), it.first.c_str());
+ RTLIL::Wire *wire = mod->addWire(NEW_ID, port.size());
+ wire->set_bool_attribute("$bugpoint");
+ wire->port_input = cell->input(it.first);
+ wire->port_output = cell->output(it.first);
+ cell->unsetPort(it.first);
+ cell->setPort(it.first, wire);
+ mod->fixup_ports();
+ return design_copy;
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ string yosys_cmd = "yosys", script, grep;
+ bool fast = false, clean = false;
+ bool modules = false, ports = false, cells = false, connections = false, has_part = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-yosys" && argidx + 1 < args.size()) {
+ yosys_cmd = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-script" && argidx + 1 < args.size()) {
+ script = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-grep" && argidx + 1 < args.size()) {
+ grep = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-fast") {
+ fast = true;
+ continue;
+ }
+ if (args[argidx] == "-clean") {
+ clean = true;
+ continue;
+ }
+ if (args[argidx] == "-modules") {
+ modules = true;
+ has_part = true;
+ continue;
+ }
+ if (args[argidx] == "-ports") {
+ ports = true;
+ has_part = true;
+ continue;
+ }
+ if (args[argidx] == "-cells") {
+ cells = true;
+ has_part = true;
+ continue;
+ }
+ if (args[argidx] == "-connections") {
+ connections = true;
+ has_part = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (script.empty())
+ log_cmd_error("Missing -script option.\n");
+
+ if (!has_part)
+ {
+ modules = true;
+ ports = true;
+ cells = true;
+ connections = true;
+ }
+
+ if (!design->full_selection())
+ log_cmd_error("This command only operates on fully selected designs!\n");
+
+ RTLIL::Design *crashing_design = clean_design(design, clean);
+ if (run_yosys(crashing_design, yosys_cmd, script))
+ log_cmd_error("The provided script file and Yosys binary do not crash on this design!\n");
+ if (!check_logfile(grep))
+ log_cmd_error("The provided grep string is not found in the log file!\n");
+
+ int seed = 0;
+ bool found_something = false, stage2 = false;
+ while (true)
+ {
+ if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections))
+ {
+ simplified = clean_design(simplified, fast, /*do_delete=*/true);
+
+ bool crashes;
+ if (clean)
+ {
+ RTLIL::Design *testcase = clean_design(simplified);
+ crashes = !run_yosys(testcase, yosys_cmd, script);
+ delete testcase;
+ }
+ else
+ {
+ crashes = !run_yosys(simplified, yosys_cmd, script);
+ }
+
+ if (crashes && check_logfile(grep))
+ {
+ log("Testcase crashes.\n");
+ if (crashing_design != design)
+ delete crashing_design;
+ crashing_design = simplified;
+ found_something = true;
+ }
+ else
+ {
+ log("Testcase does not crash.\n");
+ delete simplified;
+ seed++;
+ }
+ }
+ else
+ {
+ seed = 0;
+ if (found_something)
+ found_something = false;
+ else
+ {
+ if (!stage2)
+ {
+ log("Demoting introduced module ports.\n");
+ stage2 = true;
+ }
+ else
+ {
+ log("Simplifications exhausted.\n");
+ break;
+ }
+ }
+ }
+ }
+
+ if (crashing_design != design)
+ {
+ Pass::call(design, "design -reset");
+ crashing_design = clean_design(crashing_design, clean, /*do_delete=*/true);
+ for (auto &it : crashing_design->modules_)
+ design->add(it.second->clone());
+ delete crashing_design;
+ }
+ }
+} BugpointPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc
index 522758ea..7e32da65 100644
--- a/passes/cmds/chformal.cc
+++ b/passes/cmds/chformal.cc
@@ -32,7 +32,7 @@ struct ChformalPass : public Pass {
log(" chformal [types] [mode] [options] [selection]\n");
log("\n");
log("Make changes to the formal constraints of the design. The [types] options\n");
- log("the type of constraint to operate on. If none of the folling options is given,\n");
+ log("the type of constraint to operate on. If none of the following options are given,\n");
log("the command will operate on all constraint types:\n");
log("\n");
log(" -assert $assert cells, representing assert(...) constraints\n");
@@ -59,7 +59,7 @@ struct ChformalPass : public Pass {
log(" -assume2assert\n");
log(" -live2fair\n");
log(" -fair2live\n");
- log(" change the roles of cells as indicated. this options can be combined\n");
+ log(" change the roles of cells as indicated. these options can be combined\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc
index d480b79a..f93bada2 100644
--- a/passes/cmds/connect.cc
+++ b/passes/cmds/connect.cc
@@ -137,7 +137,7 @@ struct ConnectPass : public Pass {
if (!set_lhs.empty())
{
if (!unset_expr.empty() || !port_cell.empty())
- log_cmd_error("Cant use -set together with -unset and/or -port.\n");
+ log_cmd_error("Can't use -set together with -unset and/or -port.\n");
RTLIL::SigSpec sig_lhs, sig_rhs;
if (!RTLIL::SigSpec::parse_sel(sig_lhs, design, module, set_lhs))
@@ -157,7 +157,7 @@ struct ConnectPass : public Pass {
if (!unset_expr.empty())
{
if (!port_cell.empty() || flag_nounset)
- log_cmd_error("Cant use -unset together with -port and/or -nounset.\n");
+ log_cmd_error("Can't use -unset together with -port and/or -nounset.\n");
RTLIL::SigSpec sig;
if (!RTLIL::SigSpec::parse_sel(sig, design, module, unset_expr))
@@ -170,7 +170,7 @@ struct ConnectPass : public Pass {
if (!port_cell.empty())
{
if (flag_nounset)
- log_cmd_error("Cant use -port together with -nounset.\n");
+ log_cmd_error("Can't use -port together with -nounset.\n");
if (module->cells_.count(RTLIL::escape_id(port_cell)) == 0)
log_cmd_error("Can't find cell %s.\n", port_cell.c_str());
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
index 5f0042a6..0d137ca4 100644
--- a/passes/cmds/cover.cc
+++ b/passes/cmds/cover.cc
@@ -98,21 +98,23 @@ struct CoverPass : public Pass {
}
if ((args[argidx] == "-o" || args[argidx] == "-a" || args[argidx] == "-d") && argidx+1 < args.size()) {
const char *open_mode = args[argidx] == "-a" ? "a+" : "w";
- std::string filename = args[++argidx];
+ const std::string &filename = args[++argidx];
+ FILE *f = nullptr;
if (args[argidx-1] == "-d") {
#ifdef _WIN32
log_cmd_error("The 'cover -d' option is not supported on win32.\n");
#else
char filename_buffer[4096];
snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid());
- filename = mkstemps(filename_buffer, 4);
+ f = fdopen(mkstemps(filename_buffer, 4), "w");
#endif
+ } else {
+ f = fopen(filename.c_str(), open_mode);
}
- FILE *f = fopen(filename.c_str(), open_mode);
if (f == NULL) {
for (auto f : out_files)
fclose(f);
- log_cmd_error("Can't create file %s.\n", args[argidx].c_str());
+ log_cmd_error("Can't create file %s%s.\n", args[argidx-1] == "-d" ? "in directory " : "", args[argidx].c_str());
}
out_files.push_back(f);
continue;
diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc
index aa6d5b6c..4c16b56c 100644
--- a/passes/cmds/plugin.cc
+++ b/passes/cmds/plugin.cc
@@ -23,9 +23,18 @@
# include <dlfcn.h>
#endif
+#ifdef WITH_PYTHON
+# include <boost/algorithm/string/predicate.hpp>
+# include <Python.h>
+# include <boost/filesystem.hpp>
+#endif
+
YOSYS_NAMESPACE_BEGIN
std::map<std::string, void*> loaded_plugins;
+#ifdef WITH_PYTHON
+std::map<std::string, void*> loaded_python_plugins;
+#endif
std::map<std::string, std::string> loaded_plugin_aliases;
#ifdef YOSYS_ENABLE_PLUGINS
@@ -36,7 +45,35 @@ void load_plugin(std::string filename, std::vector<std::string> aliases)
if (filename.find('/') == std::string::npos)
filename = "./" + filename;
+ #ifdef WITH_PYTHON
+ if (!loaded_plugins.count(filename) && !loaded_python_plugins.count(filename)) {
+ #else
if (!loaded_plugins.count(filename)) {
+ #endif
+
+ #ifdef WITH_PYTHON
+
+ boost::filesystem::path full_path(filename);
+
+ if(strcmp(full_path.extension().c_str(), ".py") == 0)
+ {
+ std::string path(full_path.parent_path().c_str());
+ filename = full_path.filename().c_str();
+ filename = filename.substr(0,filename.size()-3);
+ PyRun_SimpleString(("sys.path.insert(0,\""+path+"\")").c_str());
+ PyErr_Print();
+ PyObject *module_p = PyImport_ImportModule(filename.c_str());
+ if(module_p == NULL)
+ {
+ PyErr_Print();
+ log_cmd_error("Can't load python module `%s'\n", full_path.filename().c_str());
+ return;
+ }
+ loaded_python_plugins[orig_filename] = module_p;
+ Pass::init_register();
+ } else {
+ #endif
+
void *hdl = dlopen(filename.c_str(), RTLD_LAZY|RTLD_LOCAL);
if (hdl == NULL && orig_filename.find('/') == std::string::npos)
hdl = dlopen((proc_share_dirname() + "plugins/" + orig_filename + ".so").c_str(), RTLD_LAZY|RTLD_LOCAL);
@@ -44,6 +81,10 @@ void load_plugin(std::string filename, std::vector<std::string> aliases)
log_cmd_error("Can't load module `%s': %s\n", filename.c_str(), dlerror());
loaded_plugins[orig_filename] = hdl;
Pass::init_register();
+
+ #ifdef WITH_PYTHON
+ }
+ #endif
}
for (auto &alias : aliases)
@@ -107,7 +148,11 @@ struct PluginPass : public Pass {
if (list_mode)
{
log("\n");
+#ifdef WITH_PYTHON
+ if (loaded_plugins.empty() and loaded_python_plugins.empty())
+#else
if (loaded_plugins.empty())
+#endif
log("No plugins loaded.\n");
else
log("Loaded plugins:\n");
@@ -115,6 +160,11 @@ struct PluginPass : public Pass {
for (auto &it : loaded_plugins)
log(" %s\n", it.first.c_str());
+#ifdef WITH_PYTHON
+ for (auto &it : loaded_python_plugins)
+ log(" %s\n", it.first.c_str());
+#endif
+
if (!loaded_plugin_aliases.empty()) {
log("\n");
int max_alias_len = 1;
diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc
index 1c64a7b7..adbe89e3 100644
--- a/passes/cmds/qwp.cc
+++ b/passes/cmds/qwp.cc
@@ -291,7 +291,7 @@ struct QwpWorker
// gaussian elimination
for (int i = 0; i < N; i++)
{
- if (config.verbose && ((i+1) % (N/15)) == 0)
+ if (config.verbose && N > 15 && ((i+1) % (N/15)) == 0)
log("> Solved %d%%: %d/%d\n", (100*(i+1))/N, i+1, N);
// find best row
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index dce576fd..9b1830b7 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -24,7 +24,7 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-static void rename_in_module(RTLIL::Module *module, std::string from_name, std::string to_name)
+static void rename_in_module(RTLIL::Module *module, std::string from_name, std::string to_name, bool flag_output)
{
from_name = RTLIL::escape_id(from_name);
to_name = RTLIL::escape_id(to_name);
@@ -37,13 +37,18 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std::
Wire *w = it.second;
log("Renaming wire %s to %s in module %s.\n", log_id(w), log_id(to_name), log_id(module));
module->rename(w, to_name);
- if (w->port_id)
+ if (w->port_id || flag_output) {
+ if (flag_output)
+ w->port_output = true;
module->fixup_ports();
+ }
return;
}
for (auto &it : module->cells_)
if (it.first == from_name) {
+ if (flag_output)
+ log_cmd_error("Called with -output but the specified object is a cell.\n");
log("Renaming cell %s to %s in module %s.\n", log_id(it.second), log_id(to_name), log_id(module));
module->rename(it.second, to_name);
return;
@@ -52,6 +57,51 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std::
log_cmd_error("Object `%s' not found!\n", from_name.c_str());
}
+static std::string derive_name_from_src(const std::string &src, int counter)
+{
+ std::string src_base = src.substr(0, src.find('|'));
+ if (src_base.empty())
+ return stringf("$%d", counter);
+ else
+ return stringf("\\%s$%d", src_base.c_str(), counter);
+}
+
+static IdString derive_name_from_wire(const RTLIL::Cell &cell)
+{
+ // Find output
+ const SigSpec *output = nullptr;
+ int num_outputs = 0;
+ for (auto &connection : cell.connections()) {
+ if (cell.output(connection.first)) {
+ output = &connection.second;
+ num_outputs++;
+ }
+ }
+
+ if (num_outputs != 1) // Skip cells thad drive multiple outputs
+ return cell.name;
+
+ std::string name = "";
+ for (auto &chunk : output->chunks()) {
+ // Skip cells that drive privately named wires
+ if (!chunk.wire || chunk.wire->name.str()[0] == '$')
+ return cell.name;
+
+ if (name != "")
+ name += "$";
+
+ name += chunk.wire->name.str();
+ if (chunk.wire->width != chunk.width) {
+ name += "[";
+ if (chunk.width != 1)
+ name += std::to_string(chunk.offset + chunk.width) + ":";
+ name += std::to_string(chunk.offset) + "]";
+ }
+ }
+
+ return name + cell.type.str();
+}
+
struct RenamePass : public Pass {
RenamePass() : Pass("rename", "rename object in the design") { }
void help() YS_OVERRIDE
@@ -64,6 +114,25 @@ struct RenamePass : public Pass {
log("by this command.\n");
log("\n");
log("\n");
+ log("\n");
+ log(" rename -output old_name new_name\n");
+ log("\n");
+ log("Like above, but also make the wire an output. This will fail if the object is\n");
+ log("not a wire.\n");
+ log("\n");
+ log("\n");
+ log(" rename -src [selection]\n");
+ log("\n");
+ log("Assign names auto-generated from the src attribute to all selected wires and\n");
+ log("cells with private names.\n");
+ log("\n");
+ log("\n");
+ log(" rename -wire [selection]\n");
+ log("\n");
+ log("Assign auto-generated names based on the wires they drive to all selected\n");
+ log("cells with private names. Ignores cells driving privatly named wires.\n");
+ log("\n");
+ log("\n");
log(" rename -enumerate [-pattern <pattern>] [selection]\n");
log("\n");
log("Assign short auto-generated names to all selected wires and cells with private\n");
@@ -71,11 +140,13 @@ struct RenamePass : public Pass {
log("The character %% in the pattern is replaced with a integer number. The default\n");
log("pattern is '_%%_'.\n");
log("\n");
+ log("\n");
log(" rename -hide [selection]\n");
log("\n");
log("Assign private names (the ones with $-prefix) to all selected wires and cells\n");
log("with public names. This ignores all selected ports.\n");
log("\n");
+ log("\n");
log(" rename -top new_name\n");
log("\n");
log("Rename top module.\n");
@@ -84,15 +155,33 @@ struct RenamePass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string pattern_prefix = "_", pattern_suffix = "_";
+ bool flag_src = false;
+ bool flag_wire = false;
bool flag_enumerate = false;
bool flag_hide = false;
bool flag_top = false;
+ bool flag_output = false;
bool got_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
+ if (arg == "-src" && !got_mode) {
+ flag_src = true;
+ got_mode = true;
+ continue;
+ }
+ if (arg == "-output" && !got_mode) {
+ flag_output = true;
+ got_mode = true;
+ continue;
+ }
+ if (arg == "-wire" && !got_mode) {
+ flag_wire = true;
+ got_mode = true;
+ continue;
+ }
if (arg == "-enumerate" && !got_mode) {
flag_enumerate = true;
got_mode = true;
@@ -117,6 +206,57 @@ struct RenamePass : public Pass {
break;
}
+ if (flag_src)
+ {
+ extra_args(args, argidx, design);
+
+ for (auto &mod : design->modules_)
+ {
+ int counter = 0;
+
+ RTLIL::Module *module = mod.second;
+ if (!design->selected(module))
+ continue;
+
+ dict<RTLIL::IdString, RTLIL::Wire*> new_wires;
+ for (auto &it : module->wires_) {
+ if (it.first[0] == '$' && design->selected(module, it.second))
+ it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++);
+ new_wires[it.second->name] = it.second;
+ }
+ module->wires_.swap(new_wires);
+ module->fixup_ports();
+
+ dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
+ for (auto &it : module->cells_) {
+ if (it.first[0] == '$' && design->selected(module, it.second))
+ it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++);
+ new_cells[it.second->name] = it.second;
+ }
+ module->cells_.swap(new_cells);
+ }
+ }
+ else
+ if (flag_wire)
+ {
+ extra_args(args, argidx, design);
+
+ for (auto &mod : design->modules_)
+ {
+ RTLIL::Module *module = mod.second;
+ if (!design->selected(module))
+ continue;
+
+ dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
+ for (auto &it : module->cells_) {
+ if (it.first[0] == '$' && design->selected(module, it.second))
+ it.second->name = derive_name_from_wire(*it.second);
+ new_cells[it.second->name] = it.second;
+ }
+ module->cells_.swap(new_cells);
+ }
+ }
+ else
if (flag_enumerate)
{
extra_args(args, argidx, design);
@@ -206,10 +346,12 @@ struct RenamePass : public Pass {
if (!design->selected_active_module.empty())
{
if (design->modules_.count(design->selected_active_module) > 0)
- rename_in_module(design->modules_.at(design->selected_active_module), from_name, to_name);
+ rename_in_module(design->modules_.at(design->selected_active_module), from_name, to_name, flag_output);
}
else
{
+ if (flag_output)
+ log_cmd_error("Mode -output requires that there is an active module selected.\n");
for (auto &mod : design->modules_) {
if (mod.first == from_name || RTLIL::unescape_id(mod.first) == from_name) {
to_name = RTLIL::escape_id(to_name);
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index d97aa2b3..b5e8ef1a 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -896,6 +896,29 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
select_filter_active_mod(design, work_stack.back());
}
+static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::Selection *sel)
+{
+ std::string desc = "Selection contains:\n";
+ for (auto mod_it : design->modules_)
+ {
+ if (sel->selected_module(mod_it.first)) {
+ for (auto &it : mod_it.second->wires_)
+ if (sel->selected_member(mod_it.first, it.first))
+ desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
+ for (auto &it : mod_it.second->memories)
+ if (sel->selected_member(mod_it.first, it.first))
+ desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
+ for (auto &it : mod_it.second->cells_)
+ if (sel->selected_member(mod_it.first, it.first))
+ desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
+ for (auto &it : mod_it.second->processes)
+ if (sel->selected_member(mod_it.first, it.first))
+ desc += stringf("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
+ }
+ }
+ return desc;
+}
+
PRIVATE_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN
@@ -964,7 +987,7 @@ struct SelectPass : public Pass {
log("list of selected objects.\n");
log("\n");
log("Note that many commands support an optional [selection] argument that can be\n");
- log("used to YS_OVERRIDE the global selection for the command. The syntax of this\n");
+ log("used to override the global selection for the command. The syntax of this\n");
log("optional argument is identical to the syntax of the <selection> argument\n");
log("described here.\n");
log("\n");
@@ -1394,7 +1417,12 @@ struct SelectPass : public Pass {
log_cmd_error("No selection to check.\n");
work_stack.back().optimize(design);
if (!work_stack.back().empty())
- log_error("Assertion failed: selection is not empty:%s\n", sel_str.c_str());
+ {
+ RTLIL::Selection *sel = &work_stack.back();
+ sel->optimize(design);
+ std::string desc = describe_selection_for_assert(design, sel);
+ log_error("Assertion failed: selection is not empty:%s\n%s", sel_str.c_str(), desc.c_str());
+ }
return;
}
@@ -1404,7 +1432,12 @@ struct SelectPass : public Pass {
log_cmd_error("No selection to check.\n");
work_stack.back().optimize(design);
if (work_stack.back().empty())
- log_error("Assertion failed: selection is empty:%s\n", sel_str.c_str());
+ {
+ RTLIL::Selection *sel = &work_stack.back();
+ sel->optimize(design);
+ std::string desc = describe_selection_for_assert(design, sel);
+ log_error("Assertion failed: selection is empty:%s\n%s", sel_str.c_str(), desc.c_str());
+ }
return;
}
@@ -1431,14 +1464,23 @@ struct SelectPass : public Pass {
total_count++;
}
if (assert_count >= 0 && assert_count != total_count)
- log_error("Assertion failed: selection contains %d elements instead of the asserted %d:%s\n",
- total_count, assert_count, sel_str.c_str());
+ {
+ std::string desc = describe_selection_for_assert(design, sel);
+ log_error("Assertion failed: selection contains %d elements instead of the asserted %d:%s\n%s",
+ total_count, assert_count, sel_str.c_str(), desc.c_str());
+ }
if (assert_max >= 0 && assert_max < total_count)
- log_error("Assertion failed: selection contains %d elements, more than the maximum number %d:%s\n",
- total_count, assert_max, sel_str.c_str());
+ {
+ std::string desc = describe_selection_for_assert(design, sel);
+ log_error("Assertion failed: selection contains %d elements, more than the maximum number %d:%s\n%s",
+ total_count, assert_max, sel_str.c_str(), desc.c_str());
+ }
if (assert_min >= 0 && assert_min > total_count)
- log_error("Assertion failed: selection contains %d elements, less than the minimum number %d:%s\n",
- total_count, assert_min, sel_str.c_str());
+ {
+ std::string desc = describe_selection_for_assert(design, sel);
+ log_error("Assertion failed: selection contains %d elements, less than the minimum number %d:%s\n%s",
+ total_count, assert_min, sel_str.c_str(), desc.c_str());
+ }
return;
}
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index d38a6b3d..b9fcc3e7 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -128,6 +128,45 @@ struct SetattrPass : public Pass {
}
} SetattrPass;
+struct WbflipPass : public Pass {
+ WbflipPass() : Pass("wbflip", "flip the whitebox attribute") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" wbflip [selection]\n");
+ log("\n");
+ log("Flip the whitebox attribute on selected cells. I.e. if it's set, unset it, and\n");
+ log("vice-versa. Blackbox cells are not effected by this command.\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++)
+ {
+ std::string arg = args[argidx];
+ // if (arg == "-mod") {
+ // flag_mod = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (Module *module : design->modules())
+ {
+ if (!design->selected(module))
+ continue;
+
+ if (module->get_bool_attribute("\\blackbox"))
+ continue;
+
+ module->set_bool_attribute("\\whitebox", !module->get_bool_attribute("\\whitebox"));
+ }
+ }
+} WbflipPass;
+
struct SetparamPass : public Pass {
SetparamPass() : Pass("setparam", "set/unset parameters on objects") { }
void help() YS_OVERRIDE
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index a1dfa9b5..3eedc86b 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -137,12 +137,15 @@ struct SetundefPass : public Pass {
log(" replace with $anyconst drivers (for formal)\n");
log("\n");
log(" -random <seed>\n");
- log(" replace with random bits using the specified integer als seed\n");
+ log(" replace with random bits using the specified integer as seed\n");
log(" value for the random number generator.\n");
log("\n");
log(" -init\n");
log(" also create/update init values for flip-flops\n");
log("\n");
+ log(" -params\n");
+ log(" replace undef in cell parameters\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
@@ -150,6 +153,7 @@ struct SetundefPass : public Pass {
bool undriven_mode = false;
bool expose_mode = false;
bool init_mode = false;
+ bool params_mode = false;
SetundefWorker worker;
log_header(design, "Executing SETUNDEF pass (replace undef values with defined constants).\n");
@@ -199,6 +203,10 @@ struct SetundefPass : public Pass {
init_mode = true;
continue;
}
+ if (args[argidx] == "-params") {
+ params_mode = true;
+ continue;
+ }
if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
got_value = true;
worker.next_bit_mode = MODE_RANDOM;
@@ -228,6 +236,18 @@ struct SetundefPass : public Pass {
for (auto module : design->selected_modules())
{
+ if (params_mode)
+ {
+ for (auto *cell : module->selected_cells()) {
+ for (auto &parameter : cell->parameters) {
+ for (auto &bit : parameter.second.bits) {
+ if (bit > RTLIL::State::S1)
+ bit = worker.next_bit();
+ }
+ }
+ }
+ }
+
if (undriven_mode)
{
if (!module->processes.empty())
@@ -373,44 +393,112 @@ struct SetundefPass : public Pass {
ffbits.insert(bit);
}
- for (auto wire : module->wires())
+ auto process_initwires = [&]()
{
- if (!wire->attributes.count("\\init"))
- continue;
+ dict<Wire*, int> wire_weights;
+
+ for (auto wire : initwires)
+ {
+ int weight = 0;
- for (auto bit : sigmap(wire))
- ffbits.erase(bit);
+ for (auto bit : sigmap(wire))
+ weight += ffbits.count(bit) ? +1 : -1;
- initwires.insert(wire);
- }
+ wire_weights[wire] = weight;
+ }
+
+ initwires.sort([&](Wire *a, Wire *b) { return wire_weights.at(a) > wire_weights.at(b); });
+
+ for (auto wire : initwires)
+ {
+ Const &initval = wire->attributes["\\init"];
+ initval.bits.resize(GetSize(wire), State::Sx);
+
+ for (int i = 0; i < GetSize(wire); i++) {
+ SigBit bit = sigmap(SigBit(wire, i));
+ if (initval[i] == State::Sx && ffbits.count(bit)) {
+ initval[i] = worker.next_bit();
+ ffbits.erase(bit);
+ }
+ }
+
+ if (initval.is_fully_undef())
+ wire->attributes.erase("\\init");
+ }
+
+ initwires.clear();
+ };
for (int wire_types = 0; wire_types < 2; wire_types++)
- for (auto wire : module->wires())
+ {
+ // prioritize wires that already have an init attribute
+ if (!ffbits.empty())
{
- if (wire->name[0] == (wire_types ? '\\' : '$'))
- next_wire:
- continue;
+ for (auto wire : module->wires())
+ {
+ if (wire->name[0] == (wire_types ? '\\' : '$'))
+ continue;
- for (auto bit : sigmap(wire))
- if (!ffbits.count(bit))
- goto next_wire;
+ if (!wire->attributes.count("\\init"))
+ continue;
- for (auto bit : sigmap(wire))
- ffbits.erase(bit);
+ Const &initval = wire->attributes["\\init"];
+ initval.bits.resize(GetSize(wire), State::Sx);
+
+ if (initval.is_fully_undef()) {
+ wire->attributes.erase("\\init");
+ continue;
+ }
+
+ for (int i = 0; i < GetSize(wire); i++)
+ if (initval[i] != State::Sx)
+ ffbits.erase(sigmap(SigBit(wire, i)));
- initwires.insert(wire);
+ initwires.insert(wire);
+ }
+
+ process_initwires();
}
- for (auto wire : initwires)
- {
- Const &initval = wire->attributes["\\init"];
+ // next consider wires that completely contain bits to be initialized
+ if (!ffbits.empty())
+ {
+ for (auto wire : module->wires())
+ {
+ if (wire->name[0] == (wire_types ? '\\' : '$'))
+ continue;
+
+ for (auto bit : sigmap(wire))
+ if (!ffbits.count(bit))
+ goto next_wire;
- for (int i = 0; i < GetSize(wire); i++)
- if (GetSize(initval) <= i)
- initval.bits.push_back(worker.next_bit());
- else if (initval.bits[i] == State::Sx)
- initval.bits[i] = worker.next_bit();
+ initwires.insert(wire);
+
+ next_wire:
+ continue;
+ }
+
+ process_initwires();
+ }
+
+ // finally use whatever wire we can find.
+ if (!ffbits.empty())
+ {
+ for (auto wire : module->wires())
+ {
+ if (wire->name[0] == (wire_types ? '\\' : '$'))
+ continue;
+
+ for (auto bit : sigmap(wire))
+ if (ffbits.count(bit))
+ initwires.insert(wire);
+ }
+
+ process_initwires();
+ }
}
+
+ log_assert(ffbits.empty());
}
module->rewrite_sigspecs(worker);
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 58acd302..cf729215 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -237,15 +237,34 @@ struct ShowWorker
int idx = single_idx_count++;
for (int rep, i = int(sig.chunks().size())-1; i >= 0; i -= rep) {
const RTLIL::SigChunk &c = sig.chunks().at(i);
- net = gen_signode_simple(c, false);
- log_assert(!net.empty());
+ if (!driver && c.wire == nullptr) {
+ RTLIL::State s1 = c.data.front();
+ for (auto s2 : c.data)
+ if (s1 != s2)
+ goto not_const_stream;
+ net.clear();
+ } else {
+ not_const_stream:
+ net = gen_signode_simple(c, false);
+ log_assert(!net.empty());
+ }
for (rep = 1; i-rep >= 0 && c == sig.chunks().at(i-rep); rep++) {}
std::string repinfo = rep > 1 ? stringf("%dx ", rep) : "";
if (driver) {
+ log_assert(!net.empty());
label_string += stringf("<s%d> %d:%d - %s%d:%d |", i, pos, pos-c.width+1, repinfo.c_str(), c.offset+c.width-1, c.offset);
net_conn_map[net].in.insert(stringf("x%d:s%d", idx, i));
net_conn_map[net].bits = rep*c.width;
net_conn_map[net].color = nextColor(c, net_conn_map[net].color);
+ } else
+ if (net.empty()) {
+ log_assert(rep == 1);
+ label_string += stringf("%c -&gt; %d:%d |",
+ c.data.front() == State::S0 ? '0' :
+ c.data.front() == State::S1 ? '1' :
+ c.data.front() == State::Sx ? 'X' :
+ c.data.front() == State::Sz ? 'Z' : '?',
+ pos, pos-rep*c.width+1);
} else {
label_string += stringf("<s%d> %s%d:%d - %d:%d |", i, repinfo.c_str(), c.offset+c.width-1, c.offset, pos, pos-rep*c.width+1);
net_conn_map[net].out.insert(stringf("x%d:s%d", idx, i));
@@ -555,7 +574,7 @@ struct ShowWorker
if (!design->selected_module(module->name))
continue;
if (design->selected_whole_module(module->name)) {
- if (module->get_bool_attribute("\\blackbox")) {
+ if (module->get_blackbox_attribute()) {
// log("Skipping blackbox module %s.\n", id2cstr(module->name));
continue;
} else
@@ -771,7 +790,7 @@ struct ShowPass : public Pass {
if (format != "ps" && format != "dot") {
int modcount = 0;
for (auto &mod_it : design->modules_) {
- if (mod_it.second->get_bool_attribute("\\blackbox"))
+ if (mod_it.second->get_blackbox_attribute())
continue;
if (mod_it.second->cells_.empty() && mod_it.second->connections().empty())
continue;
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 54f4ea81..27c5fb60 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -37,7 +37,9 @@ struct statdata_t
STAT_INT_MEMBERS
#undef X
double area;
+ string tech;
+ std::map<RTLIL::IdString, int> techinfo;
std::map<RTLIL::IdString, int, RTLIL::sort_by_id_str> num_cells_by_type;
std::set<RTLIL::IdString> unknown_cell_area;
@@ -70,8 +72,10 @@ struct statdata_t
#undef X
}
- statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode, const dict<IdString, double> &cell_area)
+ statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode, const dict<IdString, double> &cell_area, string techname)
{
+ tech = techname;
+
#define X(_name) _name = 0;
STAT_NUMERIC_MEMBERS
#undef X
@@ -153,7 +157,8 @@ struct statdata_t
log(" Number of processes: %6d\n", num_processes);
log(" Number of cells: %6d\n", num_cells);
for (auto &it : num_cells_by_type)
- log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second);
+ if (it.second)
+ log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second);
if (!unknown_cell_area.empty()) {
log("\n");
@@ -165,6 +170,59 @@ struct statdata_t
log("\n");
log(" Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area);
}
+
+ if (tech == "xilinx")
+ {
+ int lut6_cnt = num_cells_by_type["\\LUT6"];
+ int lut5_cnt = num_cells_by_type["\\LUT5"];
+ int lut4_cnt = num_cells_by_type["\\LUT4"];
+ int lut3_cnt = num_cells_by_type["\\LUT3"];
+ int lut2_cnt = num_cells_by_type["\\LUT2"];
+ int lut1_cnt = num_cells_by_type["\\LUT1"];
+ int lc_cnt = 0;
+
+ lc_cnt += lut6_cnt;
+
+ lc_cnt += lut5_cnt;
+ if (lut1_cnt) {
+ int cnt = std::min(lut5_cnt, lut1_cnt);
+ lut5_cnt -= cnt;
+ lut1_cnt -= cnt;
+ }
+
+ lc_cnt += lut4_cnt;
+ if (lut1_cnt) {
+ int cnt = std::min(lut4_cnt, lut1_cnt);
+ lut4_cnt -= cnt;
+ lut1_cnt -= cnt;
+ }
+ if (lut2_cnt) {
+ int cnt = std::min(lut4_cnt, lut2_cnt);
+ lut4_cnt -= cnt;
+ lut2_cnt -= cnt;
+ }
+
+ lc_cnt += lut3_cnt;
+ if (lut1_cnt) {
+ int cnt = std::min(lut3_cnt, lut1_cnt);
+ lut3_cnt -= cnt;
+ lut1_cnt -= cnt;
+ }
+ if (lut2_cnt) {
+ int cnt = std::min(lut3_cnt, lut2_cnt);
+ lut3_cnt -= cnt;
+ lut2_cnt -= cnt;
+ }
+ if (lut3_cnt) {
+ int cnt = (lut3_cnt + 1) / 2;
+ lut3_cnt -= cnt;
+ }
+
+ lc_cnt += (lut2_cnt + lut1_cnt + 1) / 2;
+
+ log("\n");
+ log(" Estimated number of LCs: %10d\n", lc_cnt);
+ }
}
};
@@ -226,6 +284,10 @@ struct StatPass : public Pass {
log(" -liberty <liberty_file>\n");
log(" use cell area information from the provided liberty file\n");
log("\n");
+ log(" -tech <technology>\n");
+ log(" print area estemate for the specified technology. Currently supported\n");
+ log(" values for <technology>: xilinx\n");
+ log("\n");
log(" -width\n");
log(" annotate internal cell types with their word width.\n");
log(" e.g. $add_8 for an 8 bit wide $add cell.\n");
@@ -239,6 +301,7 @@ struct StatPass : public Pass {
RTLIL::Module *top_mod = NULL;
std::map<RTLIL::IdString, statdata_t> mod_stat;
dict<IdString, double> cell_area;
+ string techname;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -253,6 +316,10 @@ struct StatPass : public Pass {
read_liberty_cellarea(cell_area, liberty_file);
continue;
}
+ if (args[argidx] == "-tech" && argidx+1 < args.size()) {
+ techname = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-top" && argidx+1 < args.size()) {
if (design->modules_.count(RTLIL::escape_id(args[argidx+1])) == 0)
log_cmd_error("Can't find module %s.\n", args[argidx+1].c_str());
@@ -263,13 +330,16 @@ struct StatPass : public Pass {
}
extra_args(args, argidx, design);
+ if (techname != "" && techname != "xilinx")
+ log_cmd_error("Unsupported technology: '%s'\n", techname.c_str());
+
for (auto mod : design->selected_modules())
{
if (!top_mod && design->full_selection())
if (mod->get_bool_attribute("\\top"))
top_mod = mod;
- statdata_t data(design, mod, width_mode, cell_area);
+ statdata_t data(design, mod, width_mode, cell_area, techname);
mod_stat[mod->name] = data;
log("\n");
diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc
index ff80f385..1a44bdae 100644
--- a/passes/cmds/tee.cc
+++ b/passes/cmds/tee.cc
@@ -37,7 +37,7 @@ struct TeePass : public Pass {
log("specified logfile(s).\n");
log("\n");
log(" -q\n");
- log(" Do not print output to the normal destination (console and/or log file)\n");
+ log(" Do not print output to the normal destination (console and/or log file).\n");
log("\n");
log(" -o logfile\n");
log(" Write output to this file, truncate if exists.\n");
@@ -46,13 +46,15 @@ struct TeePass : public Pass {
log(" Write output to this file, append if exists.\n");
log("\n");
log(" +INT, -INT\n");
- log(" Add/subract INT from the -v setting for this command.\n");
+ log(" Add/subtract INT from the -v setting for this command.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<FILE*> backup_log_files, files_to_close;
+ std::vector<std::ostream*> backup_log_streams;
int backup_log_verbose_level = log_verbose_level;
+ backup_log_streams = log_streams;
backup_log_files = log_files;
size_t argidx;
@@ -60,6 +62,7 @@ struct TeePass : public Pass {
{
if (args[argidx] == "-q" && files_to_close.empty()) {
log_files.clear();
+ log_streams.clear();
continue;
}
if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) {
@@ -89,6 +92,7 @@ struct TeePass : public Pass {
for (auto cf : files_to_close)
fclose(cf);
log_files = backup_log_files;
+ log_streams = backup_log_streams;
throw;
}
@@ -97,6 +101,7 @@ struct TeePass : public Pass {
log_verbose_level = backup_log_verbose_level;
log_files = backup_log_files;
+ log_streams = backup_log_streams;
}
} TeePass;
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
index f5305cde..cf3e46ac 100644
--- a/passes/cmds/trace.cc
+++ b/passes/cmds/trace.cc
@@ -94,4 +94,38 @@ struct TracePass : public Pass {
}
} TracePass;
+struct DebugPass : public Pass {
+ DebugPass() : Pass("debug", "run command with debug log messages enabled") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" debug cmd\n");
+ log("\n");
+ log("Execute the specified command with debug log messages enabled\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++)
+ {
+ // .. parse options ..
+ break;
+ }
+
+ log_force_debug++;
+
+ try {
+ std::vector<std::string> new_args(args.begin() + argidx, args.end());
+ Pass::call(design, new_args);
+ } catch (...) {
+ log_force_debug--;
+ throw;
+ }
+
+ log_force_debug--;
+ }
+} DebugPass;
+
PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc
index 9613b462..64a762d7 100644
--- a/passes/cmds/write_file.cc
+++ b/passes/cmds/write_file.cc
@@ -62,7 +62,7 @@ struct WriteFileFrontend : public Frontend {
if (argidx < args.size() && args[argidx].rfind("-", 0) != 0)
output_filename = args[argidx++];
else
- log_cmd_error("Missing putput filename.\n");
+ log_cmd_error("Missing output filename.\n");
extra_args(f, filename, args, argidx);