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/add.cc95
-rw-r--r--passes/cmds/logger.cc201
-rw-r--r--passes/cmds/show.cc19
4 files changed, 289 insertions, 27 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 07a5d3ddc..20b38bf8e 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -33,3 +33,4 @@ OBJS += passes/cmds/blackbox.o
OBJS += passes/cmds/ltp.o
OBJS += passes/cmds/bugpoint.o
OBJS += passes/cmds/scratchpad.o
+OBJS += passes/cmds/logger.o
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index dd05ac81f..7b76f3d4a 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -22,26 +22,61 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+static bool is_formal_celltype(const std::string &celltype)
+{
+ if(celltype == "assert" || celltype == "assume" || celltype == "live" || celltype == "fair" || celltype == "cover")
+ return true;
+ else
+ return false;
+}
+
+static void add_formal(RTLIL::Module *module, const std::string &celltype, const std::string &name, const std::string &enable_name)
+{
+ std::string escaped_name = RTLIL::escape_id(name);
+ std::string escaped_enable_name = (enable_name != "") ? RTLIL::escape_id(enable_name) : "";
+ RTLIL::Wire *wire = module->wire(escaped_name);
+ log_assert(is_formal_celltype(celltype));
+
+ if (wire == nullptr) {
+ log_error("Could not find wire with name \"%s\".\n", name.c_str());
+ }
+ else {
+ RTLIL::Cell *formal_cell = module->addCell(NEW_ID, "$" + celltype);
+ formal_cell->setPort(ID(A), wire);
+ if(enable_name == "") {
+ formal_cell->setPort(ID(EN), State::S1);
+ log("Added $%s cell for wire \"%s.%s\"\n", celltype.c_str(), module->name.str().c_str(), name.c_str());
+ }
+ else {
+ RTLIL::Wire *enable_wire = module->wire(escaped_enable_name);
+ if(enable_wire == nullptr)
+ log_error("Could not find enable wire with name \"%s\".\n", enable_name.c_str());
+
+ formal_cell->setPort(ID(EN), enable_wire);
+ log("Added $%s cell for wire \"%s.%s\" enabled by wire \"%s.%s\".\n", celltype.c_str(), module->name.str().c_str(), name.c_str(), module->name.str().c_str(), enable_name.c_str());
+ }
+ }
+}
+
static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output, bool flag_global)
{
- RTLIL::Wire *wire = NULL;
+ RTLIL::Wire *wire = nullptr;
name = RTLIL::escape_id(name);
if (module->count_id(name) != 0)
{
- if (module->wires_.count(name) > 0)
- wire = module->wires_.at(name);
+ wire = module->wire(name);
- if (wire != NULL && wire->width != width)
- wire = NULL;
+ if (wire != nullptr && wire->width != width)
+ wire = nullptr;
- if (wire != NULL && wire->port_input != flag_input)
- wire = NULL;
+ if (wire != nullptr && wire->port_input != flag_input)
+ wire = nullptr;
- if (wire != NULL && wire->port_output != flag_output)
- wire = NULL;
+ if (wire != nullptr && wire->port_output != flag_output)
+ wire = nullptr;
- if (wire == NULL)
+ if (wire == nullptr)
log_cmd_error("Found incompatible object with same name in module %s!\n", module->name.c_str());
log("Module %s already has such an object.\n", module->name.c_str());
@@ -53,7 +88,6 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
wire->port_output = flag_output;
if (flag_input || flag_output) {
- wire->port_id = module->wires_.size();
module->fixup_ports();
}
@@ -63,21 +97,20 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
if (!flag_global)
return;
- for (auto &it : module->cells_)
+ for (auto cell : module->cells())
{
- if (design->modules_.count(it.second->type) == 0)
+ RTLIL::Module *mod = design->module(cell->type);
+ if (mod == nullptr)
continue;
-
- RTLIL::Module *mod = design->modules_.at(it.second->type);
if (!design->selected_whole_module(mod->name))
continue;
if (mod->get_blackbox_attribute())
continue;
- if (it.second->hasPort(name))
+ if (cell->hasPort(name))
continue;
- it.second->setPort(name, wire);
- log("Added connection %s to cell %s.%s (%s).\n", name.c_str(), module->name.c_str(), it.first.c_str(), it.second->type.c_str());
+ cell->setPort(name, wire);
+ log("Added connection %s to cell %s.%s (%s).\n", name.c_str(), module->name.c_str(), cell->name.c_str(), cell->type.c_str());
}
}
@@ -106,6 +139,12 @@ struct AddPass : public Pass {
log("selected modules.\n");
log("\n");
log("\n");
+ log(" add {-assert|-assume|-live|-fair|-cover} <name1> [-if <name2>]\n");
+ log("\n");
+ log("Add an $assert, $assume, etc. cell connected to a wire named name1, with its\n");
+ log("enable signal optionally connected to a wire named name2 (default: 1'b1).\n");
+ log("\n");
+ log("\n");
log(" add -mod <name[s]>\n");
log("\n");
log("Add module[s] with the specified name[s].\n");
@@ -115,6 +154,7 @@ struct AddPass : public Pass {
{
std::string command;
std::string arg_name;
+ std::string enable_name = "";
bool arg_flag_input = false;
bool arg_flag_output = false;
bool arg_flag_global = false;
@@ -144,6 +184,17 @@ struct AddPass : public Pass {
argidx++;
break;
}
+ if (arg.length() > 0 && arg[0] == '-' && is_formal_celltype(arg.substr(1))) {
+ if (argidx + 1 >= args.size())
+ break;
+ command = arg.substr(1);
+ arg_name = args[++argidx];
+ if (argidx + 2 < args.size() && args[argidx + 1] == "-if") {
+ enable_name = args[argidx + 2];
+ argidx += 2;
+ }
+ continue;
+ }
break;
}
@@ -155,15 +206,17 @@ struct AddPass : public Pass {
extra_args(args, argidx, design);
- for (auto &mod : design->modules_)
+ for (auto module : design->modules())
{
- RTLIL::Module *module = mod.second;
+ log_assert(module != nullptr);
if (!design->selected_whole_module(module->name))
continue;
if (module->get_bool_attribute("\\blackbox"))
continue;
- if (command == "wire")
+ if (is_formal_celltype(command))
+ add_formal(module, command, arg_name, enable_name);
+ else if (command == "wire")
add_wire(design, module, arg_name, arg_width, arg_flag_input, arg_flag_output, arg_flag_global);
}
}
diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc
new file mode 100644
index 000000000..bd1038a7e
--- /dev/null
+++ b/passes/cmds/logger.cc
@@ -0,0 +1,201 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Miodrag Milanovic <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/register.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct LoggerPass : public Pass {
+ LoggerPass() : Pass("logger", "set logger properties") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" logger [options]\n");
+ log("\n");
+ log("This command sets global logger properties, also available using command line\n");
+ log("options.\n");
+ log("\n");
+ log(" -[no]time\n");
+ log(" enable/disable display of timestamp in log output.\n");
+ log("\n");
+ log(" -[no]stderr\n");
+ log(" enable/disable logging errors to stderr.\n");
+ log("\n");
+ log(" -warn regex\n");
+ log(" print a warning for all log messages matching the regex.\n");
+ log("\n");
+ log(" -nowarn regex\n");
+ log(" if a warning message matches the regex, it is printed as regular\n");
+ log(" message instead.\n");
+ log("\n");
+ log(" -werror regex\n");
+ log(" if a warning message matches the regex, it is printed as error\n");
+ log(" message instead and the tool terminates with a nonzero return code.\n");
+ log("\n");
+ log(" -[no]debug\n");
+ log(" globally enable/disable debug log messages.\n");
+ log("\n");
+ log(" -experimental <feature>\n");
+ log(" do not print warnings for the specified experimental feature\n");
+ log("\n");
+ log(" -expect <type> <regex> <expected_count>\n");
+ log(" expect log,warning or error to appear. In case of error return code is 0.\n");
+ log("\n");
+ log(" -expect-no-warnings\n");
+ log(" gives error in case there is at least one warning that is not expected.\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] == "-time") {
+ log_time = true;
+ log("Enabled timestamp in logs.\n");
+ continue;
+ }
+ if (args[argidx] == "-notime") {
+ log_time = false;
+ log("Disabled timestamp in logs.\n");
+ continue;
+ }
+ if (args[argidx] == "-stderr") {
+ log_error_stderr = true;
+ log("Enabled loggint errors to stderr.\n");
+ continue;
+ }
+ if (args[argidx] == "-nostderr") {
+ log_error_stderr = false;
+ log("Disabled loggint errors to stderr.\n");
+ continue;
+ }
+ if (args[argidx] == "-warn" && argidx+1 < args.size()) {
+ std::string pattern = args[++argidx];
+ if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2);
+ try {
+ log("Added regex '%s' for warnings to warn list.\n", pattern.c_str());
+ log_warn_regexes.push_back(std::regex(pattern,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::egrep));
+ }
+ catch (const std::regex_error& e) {
+ log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str());
+ }
+ continue;
+ }
+ if (args[argidx] == "-nowarn" && argidx+1 < args.size()) {
+ std::string pattern = args[++argidx];
+ if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2);
+ try {
+ log("Added regex '%s' for warnings to nowarn list.\n", pattern.c_str());
+ log_nowarn_regexes.push_back(std::regex(pattern,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::egrep));
+ }
+ catch (const std::regex_error& e) {
+ log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str());
+ }
+ continue;
+ }
+ if (args[argidx] == "-werror" && argidx+1 < args.size()) {
+ std::string pattern = args[++argidx];
+ if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2);
+ try {
+ log("Added regex '%s' for warnings to werror list.\n", pattern.c_str());
+ log_werror_regexes.push_back(std::regex(pattern,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::egrep));
+ }
+ catch (const std::regex_error& e) {
+ log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str());
+ }
+ continue;
+ }
+ if (args[argidx] == "-debug") {
+ log_force_debug = 1;
+ log("Enabled debug log messages.\n");
+ continue;
+ }
+ if (args[argidx] == "-nodebug") {
+ log_force_debug = 0;
+ log("Disabled debug log messages.\n");
+ continue;
+ }
+ if (args[argidx] == "-experimental" && argidx+1 < args.size()) {
+ std::string value = args[++argidx];
+ log("Added '%s' experimental ignore list.\n", value.c_str());
+ log_experimentals_ignored.insert(value);
+ continue;
+ }
+ if (args[argidx] == "-expect" && argidx+3 < args.size()) {
+ std::string type = args[++argidx];
+ if (type!="error" && type!="warning" && type!="log")
+ log_cmd_error("Expect command require type to be 'log', 'warning' or 'error' !\n");
+ if (type=="error" && log_expect_error.size()>0)
+ log_cmd_error("Only single error message can be expected !\n");
+ std::string pattern = args[++argidx];
+ if (pattern.front() == '\"' && pattern.back() == '\"') pattern = pattern.substr(1, pattern.size() - 2);
+ int count = atoi(args[++argidx].c_str());
+ if (count<=0)
+ log_cmd_error("Number of expected messages must be higher then 0 !\n");
+ if (type=="error" && count!=1)
+ log_cmd_error("Expected error message occurrences must be 1 !\n");
+ log("Added regex '%s' for warnings to expected %s list.\n", pattern.c_str(), type.c_str());
+ try {
+ if (type=="error")
+ log_expect_error.push_back(std::make_pair(std::regex(pattern,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::egrep), LogExpectedItem(pattern, count)));
+ else if (type=="warning")
+ log_expect_warning.push_back(std::make_pair(std::regex(pattern,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::egrep), LogExpectedItem(pattern, count)));
+ else
+ log_expect_log.push_back(std::make_pair(std::regex(pattern,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::egrep), LogExpectedItem(pattern, count)));
+ }
+ catch (const std::regex_error& e) {
+ log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str());
+ }
+ continue;
+ }
+ if (args[argidx] == "-expect-no-warnings") {
+ log_expect_no_warnings = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design, false);
+ }
+} LoggerPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index eeef24bde..e0d428811 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -668,6 +668,10 @@ struct ShowPass : public Pass {
log(" -notitle\n");
log(" do not add the module name as graph title to the dot file\n");
log("\n");
+ log(" -nobg\n");
+ log(" don't run viewer in the background, IE wait for the viewer tool to\n");
+ log(" exit before returning\n");
+ log("\n");
log("When no <format> is specified, 'dot' is used. When no <format> and <viewer> is\n");
log("specified, 'xdot' is used to display the schematic (POSIX systems only).\n");
log("\n");
@@ -706,6 +710,7 @@ struct ShowPass : public Pass {
bool flag_abbreviate = true;
bool flag_notitle = false;
bool custom_prefix = false;
+ std::string background = "&";
RTLIL::IdString colorattr;
size_t argidx;
@@ -787,6 +792,10 @@ struct ShowPass : public Pass {
flag_notitle = true;
continue;
}
+ if (arg == "-nobg") {
+ background= "";
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -859,21 +868,19 @@ struct ShowPass : public Pass {
// system()/cmd.exe does not understand single quotes nor
// background tasks on Windows. So we have to pause yosys
// until the viewer exits.
- #define VIEW_CMD "%s \"%s\""
+ std::string cmd = stringf("%s \"%s\"", viewer_exe.c_str(), out_file.c_str());
#else
- #define VIEW_CMD "%s '%s' &"
+ std::string cmd = stringf("%s '%s' %s", viewer_exe.c_str(), out_file.c_str(), background.c_str());
#endif
- std::string cmd = stringf(VIEW_CMD, viewer_exe.c_str(), out_file.c_str());
- #undef VIEW_CMD
log("Exec: %s\n", cmd.c_str());
if (run_command(cmd) != 0)
log_cmd_error("Shell command failed!\n");
} else
if (format.empty()) {
#ifdef __APPLE__
- std::string cmd = stringf("ps -fu %d | grep -q '[ ]%s' || xdot '%s' &", getuid(), dot_file.c_str(), dot_file.c_str());
+ std::string cmd = stringf("ps -fu %d | grep -q '[ ]%s' || xdot '%s' %s", getuid(), dot_file.c_str(), dot_file.c_str(), background.c_str());
#else
- std::string cmd = stringf("{ test -f '%s.pid' && fuser -s '%s.pid' 2> /dev/null; } || ( echo $$ >&3; exec xdot '%s'; ) 3> '%s.pid' &", dot_file.c_str(), dot_file.c_str(), dot_file.c_str(), dot_file.c_str());
+ std::string cmd = stringf("{ test -f '%s.pid' && fuser -s '%s.pid' 2> /dev/null; } || ( echo $$ >&3; exec xdot '%s'; ) 3> '%s.pid' %s", dot_file.c_str(), dot_file.c_str(), dot_file.c_str(), dot_file.c_str(), background.c_str());
#endif
log("Exec: %s\n", cmd.c_str());
if (run_command(cmd) != 0)