aboutsummaryrefslogtreecommitdiffstats
path: root/passes/cmds
diff options
context:
space:
mode:
authorAhmed Irfan <ahmedirfan1983@gmail.com>2014-09-22 11:35:04 +0200
committerAhmed Irfan <ahmedirfan1983@gmail.com>2014-09-22 11:35:04 +0200
commitd3c67ad9b61f602de1100cd264efd227dcacb417 (patch)
tree88c462c53bdab128cd1edbded42483772f82612a /passes/cmds
parentb783dbe148e6d246ebd107c0913de2989ab5af48 (diff)
parent13117bb346dd02d2345f716b4403239aebe3d0e2 (diff)
downloadyosys-d3c67ad9b61f602de1100cd264efd227dcacb417.tar.gz
yosys-d3c67ad9b61f602de1100cd264efd227dcacb417.tar.bz2
yosys-d3c67ad9b61f602de1100cd264efd227dcacb417.zip
Merge branch 'master' of https://github.com/cliffordwolf/yosys into btor
added case for memwr cell that is used in muxes (same cell is used more than one time) corrected bug for xnor and logic_not added pmux cell translation Conflicts: backends/btor/btor.cc
Diffstat (limited to 'passes/cmds')
-rw-r--r--passes/cmds/Makefile.inc6
-rw-r--r--passes/cmds/add.cc23
-rw-r--r--passes/cmds/connect.cc18
-rw-r--r--passes/cmds/connwrappers.cc205
-rw-r--r--passes/cmds/copy.cc9
-rw-r--r--passes/cmds/cover.cc144
-rw-r--r--passes/cmds/delete.cc61
-rw-r--r--passes/cmds/design.cc82
-rw-r--r--passes/cmds/plugin.cc124
-rw-r--r--passes/cmds/rename.cc65
-rw-r--r--passes/cmds/scatter.cc15
-rw-r--r--passes/cmds/scc.cc18
-rw-r--r--passes/cmds/select.cc198
-rw-r--r--passes/cmds/setattr.cc10
-rw-r--r--passes/cmds/setundef.cc70
-rw-r--r--passes/cmds/show.cc139
-rw-r--r--passes/cmds/splice.cc78
-rw-r--r--passes/cmds/splitnets.cc59
-rw-r--r--passes/cmds/stat.cc49
-rw-r--r--passes/cmds/tee.cc88
-rw-r--r--passes/cmds/trace.cc97
-rw-r--r--passes/cmds/write_file.cc76
22 files changed, 1244 insertions, 390 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index f01a1c4b5..eba61d1df 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -15,4 +15,10 @@ OBJS += passes/cmds/copy.o
OBJS += passes/cmds/splice.o
OBJS += passes/cmds/scc.o
OBJS += passes/cmds/log.o
+OBJS += passes/cmds/tee.o
+OBJS += passes/cmds/write_file.o
+OBJS += passes/cmds/connwrappers.o
+OBJS += passes/cmds/cover.o
+OBJS += passes/cmds/trace.o
+OBJS += passes/cmds/plugin.o
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index acee4c46f..e3fde8559 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -28,8 +28,8 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
if (module->count_id(name) != 0)
{
- if (module->wires.count(name) > 0)
- wire = module->wires.at(name);
+ if (module->wires_.count(name) > 0)
+ wire = module->wires_.at(name);
if (wire != NULL && wire->width != width)
wire = NULL;
@@ -47,15 +47,12 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
}
else
{
- wire = new RTLIL::Wire;
- wire->name = name;
- wire->width = width;
+ wire = module->addWire(name, width);
wire->port_input = flag_input;
wire->port_output = flag_output;
- module->add(wire);
if (flag_input || flag_output) {
- wire->port_id = module->wires.size();
+ wire->port_id = module->wires_.size();
module->fixup_ports();
}
@@ -65,20 +62,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 &it : module->cells_)
{
- if (design->modules.count(it.second->type) == 0)
+ if (design->modules_.count(it.second->type) == 0)
continue;
- RTLIL::Module *mod = design->modules.at(it.second->type);
+ RTLIL::Module *mod = design->modules_.at(it.second->type);
if (!design->selected_whole_module(mod->name))
continue;
if (mod->get_bool_attribute("\\blackbox"))
continue;
- if (it.second->connections.count(name) > 0)
+ if (it.second->hasPort(name))
continue;
- it.second->connections[name] = wire;
+ 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());
}
}
@@ -139,7 +136,7 @@ struct AddPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &mod : design->modules)
+ for (auto &mod : design->modules_)
{
RTLIL::Module *module = mod.second;
if (!design->selected_whole_module(module->name))
diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc
index 7da2b9517..30c80f732 100644
--- a/passes/cmds/connect.cc
+++ b/passes/cmds/connect.cc
@@ -27,14 +27,14 @@ static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap &
{
CellTypes ct(design);
- RTLIL::Wire *dummy_wire = module->new_wire(sig.width, NEW_ID);
+ RTLIL::Wire *dummy_wire = module->addWire(NEW_ID, sig.size());
- for (auto &it : module->cells)
- for (auto &port : it.second->connections)
+ for (auto &it : module->cells_)
+ for (auto &port : it.second->connections_)
if (ct.cell_output(it.second->type, port.first))
sigmap(port.second).replace(sig, dummy_wire, &port.second);
- for (auto &conn : module->connections)
+ for (auto &conn : module->connections_)
sigmap(conn.first).replace(sig, dummy_wire, &conn.first);
}
@@ -75,7 +75,7 @@ struct ConnectPass : public Pass {
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
RTLIL::Module *module = NULL;
- for (auto &it : design->modules) {
+ for (auto &it : design->modules_) {
if (!design->selected(it.second))
continue;
if (module != NULL)
@@ -123,7 +123,7 @@ struct ConnectPass : public Pass {
SigMap sigmap;
if (!flag_nomap)
- for (auto &it : module->connections) {
+ for (auto &it : module->connections()) {
std::vector<RTLIL::SigBit> lhs = it.first.to_sigbit_vector();
std::vector<RTLIL::SigBit> rhs = it.first.to_sigbit_vector();
for (size_t i = 0; i < lhs.size(); i++)
@@ -148,7 +148,7 @@ struct ConnectPass : public Pass {
if (!flag_nounset)
unset_drivers(design, module, sigmap, sig_lhs);
- module->connections.push_back(RTLIL::SigSig(sig_lhs, sig_rhs));
+ module->connect(RTLIL::SigSig(sig_lhs, sig_rhs));
}
else
if (!unset_expr.empty())
@@ -169,14 +169,14 @@ struct ConnectPass : public Pass {
if (flag_nounset)
log_cmd_error("Cant use -port together with -nounset.\n");
- if (module->cells.count(RTLIL::escape_id(port_cell)) == 0)
+ if (module->cells_.count(RTLIL::escape_id(port_cell)) == 0)
log_cmd_error("Can't find cell %s.\n", port_cell.c_str());
RTLIL::SigSpec sig;
if (!RTLIL::SigSpec::parse_sel(sig, design, module, port_expr))
log_cmd_error("Failed to parse port expression `%s'.\n", port_expr.c_str());
- module->cells.at(RTLIL::escape_id(port_cell))->connections[RTLIL::escape_id(port_port)] = sigmap(sig);
+ module->cells_.at(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig));
}
else
log_cmd_error("Expected -set, -unset, or -port.\n");
diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc
new file mode 100644
index 000000000..aac117169
--- /dev/null
+++ b/passes/cmds/connwrappers.cc
@@ -0,0 +1,205 @@
+/*
+ * 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/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+struct ConnwrappersWorker
+{
+ struct portdecl_t {
+ // key: celltype, portname;
+ std::string widthparam, signparam;
+ bool is_signed;
+ };
+
+ std::set<RTLIL::IdString> decl_celltypes;
+ std::map<std::pair<RTLIL::IdString, RTLIL::IdString>, portdecl_t> decls;
+
+ void add_port(std::string celltype, std::string portname, std::string widthparam, std::string signparam)
+ {
+ std::pair<std::string, std::string> key(RTLIL::escape_id(celltype), RTLIL::escape_id(portname));
+ decl_celltypes.insert(key.first);
+
+ if (decls.count(key))
+ log_cmd_error("Duplicate port decl: %s %s\n", celltype.c_str(), portname.c_str());
+
+ portdecl_t decl;
+ decl.widthparam = RTLIL::escape_id(widthparam);
+ decl.signparam = RTLIL::escape_id(signparam);
+ decl.is_signed = false;
+ decls[key] = decl;
+ }
+
+ void add_port(std::string celltype, std::string portname, std::string widthparam, bool is_signed)
+ {
+ std::pair<std::string, std::string> key(RTLIL::escape_id(celltype), RTLIL::escape_id(portname));
+ decl_celltypes.insert(key.first);
+
+ if (decls.count(key))
+ log_cmd_error("Duplicate port decl: %s %s\n", celltype.c_str(), portname.c_str());
+
+ portdecl_t decl;
+ decl.widthparam = RTLIL::escape_id(widthparam);
+ decl.is_signed = is_signed;
+ decls[key] = decl;
+ }
+
+ void work(RTLIL::Design *design, RTLIL::Module *module)
+ {
+ std::map<RTLIL::SigBit, std::pair<bool, RTLIL::SigSpec>> extend_map;
+ SigMap sigmap(module);
+
+ for (auto &it : module->cells_)
+ {
+ RTLIL::Cell *cell = it.second;
+
+ if (!decl_celltypes.count(cell->type))
+ continue;
+
+ for (auto &conn : cell->connections())
+ {
+ std::pair<RTLIL::IdString, RTLIL::IdString> key(cell->type, conn.first);
+
+ if (!decls.count(key))
+ continue;
+
+ portdecl_t &decl = decls.at(key);
+
+ if (!cell->parameters.count(decl.widthparam))
+ continue;
+
+ if (!decl.signparam.empty() && !cell->parameters.count(decl.signparam))
+ continue;
+
+ int inner_width = cell->parameters.at(decl.widthparam).as_int();
+ int outer_width = conn.second.size();
+ bool is_signed = decl.signparam.empty() ? decl.is_signed : cell->parameters.at(decl.signparam).as_bool();
+
+ if (inner_width >= outer_width)
+ continue;
+
+ RTLIL::SigSpec sig = sigmap(conn.second);
+ extend_map[sig.extract(inner_width - 1, 1)] = std::pair<bool, RTLIL::SigSpec>(is_signed,
+ sig.extract(inner_width, outer_width - inner_width));
+ }
+ }
+
+ for (auto &it : module->cells_)
+ {
+ RTLIL::Cell *cell = it.second;
+
+ if (!design->selected(module, cell))
+ continue;
+
+ for (auto &conn : cell->connections_)
+ {
+ std::vector<RTLIL::SigBit> sigbits = sigmap(conn.second).to_sigbit_vector();
+ RTLIL::SigSpec old_sig;
+
+ for (size_t i = 0; i < sigbits.size(); i++)
+ {
+ if (!extend_map.count(sigbits[i]))
+ continue;
+
+ bool is_signed = extend_map.at(sigbits[i]).first;
+ RTLIL::SigSpec extend_sig = extend_map.at(sigbits[i]).second;
+
+ int extend_width = 0;
+ RTLIL::SigBit extend_bit = is_signed ? sigbits[i] : RTLIL::SigBit(RTLIL::State::S0);
+ while (extend_width < extend_sig.size() && i + extend_width + 1 < sigbits.size() &&
+ sigbits[i + extend_width + 1] == extend_bit) extend_width++;
+
+ if (extend_width == 0)
+ continue;
+
+ if (old_sig.size() == 0)
+ old_sig = conn.second;
+
+ conn.second.replace(i+1, extend_sig.extract(0, extend_width));
+ i += extend_width;
+ }
+
+ if (old_sig.size())
+ log("Connected extended bits of %s.%s:%s: %s -> %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name),
+ RTLIL::id2cstr(conn.first), log_signal(old_sig), log_signal(conn.second));
+ }
+ }
+ }
+};
+
+struct ConnwrappersPass : public Pass {
+ ConnwrappersPass() : Pass("connwrappers", "replace undef values with defined constants") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" connwrappers [options] [selection]\n");
+ log("\n");
+ log("Wrappers are used in coarse-grain synthesis to wrap cells with smaller ports\n");
+ log("in wrapper cells with a (larger) constant port size. I.e. the upper bits\n");
+ log("of the wrapper outut are signed/unsigned bit extended. This command uses this\n");
+ log("knowlege to rewire the inputs of the driven cells to match the output of\n");
+ log("the driving cell.\n");
+ log("\n");
+ log(" -signed <cell_type> <port_name> <width_param>\n");
+ log(" -unsigned <cell_type> <port_name> <width_param>\n");
+ log(" consider the specified signed/unsigned wrapper output\n");
+ log("\n");
+ log(" -port <cell_type> <port_name> <width_param> <sign_param>\n");
+ log(" use the specified parameter to decide if signed or unsigned\n");
+ log("\n");
+ log("The options -signed, -unsigned, and -port can be specified multiple times.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ ConnwrappersWorker worker;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-signed" && argidx+3 < args.size()) {
+ worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], true);
+ argidx += 3;
+ continue;
+ }
+ if (args[argidx] == "-unsigned" && argidx+3 < args.size()) {
+ worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], false);
+ argidx += 3;
+ continue;
+ }
+ if (args[argidx] == "-port" && argidx+4 < args.size()) {
+ worker.add_port(args[argidx+1], args[argidx+2], args[argidx+3], args[argidx+4]);
+ argidx += 4;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ log_header("Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n");
+
+ for (auto &mod_it : design->modules_)
+ if (design->selected(mod_it.second))
+ worker.work(design, mod_it.second);
+ }
+} ConnwrappersPass;
+
diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc
index 4b1a8db81..be7758200 100644
--- a/passes/cmds/copy.cc
+++ b/passes/cmds/copy.cc
@@ -41,14 +41,15 @@ struct CopyPass : public Pass {
std::string src_name = RTLIL::escape_id(args[1]);
std::string trg_name = RTLIL::escape_id(args[2]);
- if (design->modules.count(src_name) == 0)
+ if (design->modules_.count(src_name) == 0)
log_cmd_error("Can't find source module %s.\n", src_name.c_str());
- if (design->modules.count(trg_name) != 0)
+ if (design->modules_.count(trg_name) != 0)
log_cmd_error("Target module name %s already exists.\n", trg_name.c_str());
- design->modules[trg_name] = design->modules.at(src_name)->clone();
- design->modules[trg_name]->name = trg_name;
+ RTLIL::Module *new_mod = design->module(src_name)->clone();
+ new_mod->name = trg_name;
+ design->add(new_mod);
}
} CopyPass;
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
new file mode 100644
index 000000000..ac72ba53a
--- /dev/null
+++ b/passes/cmds/cover.cc
@@ -0,0 +1,144 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2014 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 <sys/types.h>
+#include <unistd.h>
+#include <fnmatch.h>
+
+#include "kernel/register.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+struct CoverPass : public Pass {
+ CoverPass() : Pass("cover", "print code coverage counters") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" cover [options] [pattern]\n");
+ log("\n");
+ log("Print the code coverage counters collected using the cover() macro in the Yosys\n");
+ log("C++ code. This is useful to figure out what parts of Yosys are utilized by a\n");
+ log("test bench.\n");
+ log("\n");
+ log(" -q\n");
+ log(" Do not print output to the normal destination (console and/or log file)\n");
+ log("\n");
+ log(" -o file\n");
+ log(" Write output to this file, truncate if exists.\n");
+ log("\n");
+ log(" -a file\n");
+ log(" Write output to this file, append if exists.\n");
+ log("\n");
+ log(" -d dir\n");
+ log(" Write output to a newly created file in the specified directory.\n");
+ log("\n");
+ log("When one or more pattern (shell wildcards) are specified, then only counters\n");
+ log("matching at least one pattern are printed.\n");
+ log("\n");
+ log("\n");
+ log("It is also possible to instruct Yosys to print the coverage counters on program\n");
+ log("exit to a file using environment variables:\n");
+ log("\n");
+ log(" YOSYS_COVER_DIR=\"{dir-name}\" yosys {args}\n");
+ log("\n");
+ log(" This will create a file (with an auto-generated name) in this\n");
+ log(" directory and write the coverage counters to it.\n");
+ log("\n");
+ log(" YOSYS_COVER_FILE=\"{file-name}\" yosys {args}\n");
+ log("\n");
+ log(" This will append the coverage counters to the specified file.\n");
+ log("\n");
+ log("\n");
+ log("Hint: Use the following AWK command to consolidate Yosys coverage files:\n");
+ log("\n");
+ log(" gawk '{ p[$3] = $1; c[$3] += $2; } END { for (i in p)\n");
+ log(" printf \"%%-60s %%10d %%s\\n\", p[i], c[i], i; }' {files} | sort -k3\n");
+ log("\n");
+ log("\n");
+ log("Coverage counters are only available in debug builds of Yosys for Linux.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ std::vector<FILE*> out_files;
+ std::vector<std::string> patterns;
+ bool do_log = true;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-q") {
+ do_log = false;
+ continue;
+ }
+ 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];
+ if (args[argidx-1] == "-d") {
+ char filename_buffer[4096];
+ snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid());
+ filename = mkstemps(filename_buffer, 4);
+ }
+ 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());
+ }
+ out_files.push_back(f);
+ continue;
+ }
+ break;
+ }
+ while (argidx < args.size() && args[argidx].substr(0, 1) != "-")
+ patterns.push_back(args[argidx++]);
+ extra_args(args, argidx, design);
+
+ if (do_log) {
+ log_header("Printing code coverage counters.\n");
+ log("\n");
+ }
+
+#ifdef COVER_ACTIVE
+ for (auto &it : get_coverage_data()) {
+ if (!patterns.empty()) {
+ for (auto &p : patterns)
+ if (!fnmatch(p.c_str(), it.first.c_str(), 0))
+ goto pattern_match;
+ continue;
+ }
+ pattern_match:
+ for (auto f : out_files)
+ fprintf(f, "%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str());
+ if (do_log)
+ log("%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str());
+ }
+#else
+ for (auto f : out_files)
+ fclose(f);
+
+ log_cmd_error("Coverage counters are only available in debug builds of Yosys for Linux.\n");
+#endif
+
+ for (auto f : out_files)
+ fclose(f);
+ }
+} CoverPass;
+
diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc
index 1c02752c2..2a91bc9ea 100644
--- a/passes/cmds/delete.cc
+++ b/passes/cmds/delete.cc
@@ -21,21 +21,6 @@
#include "kernel/rtlil.h"
#include "kernel/log.h"
-struct DeleteWireWorker
-{
- RTLIL::Module *module;
- std::set<std::string> *delete_wires_p;
-
- void operator()(RTLIL::SigSpec &sig) {
- sig.optimize();
- for (auto &c : sig.chunks)
- if (c.wire != NULL && delete_wires_p->count(c.wire->name)) {
- c.wire = module->new_wire(c.width, NEW_ID);
- c.offset = 0;
- }
- }
-};
-
struct DeletePass : public Pass {
DeletePass() : Pass("delete", "delete objects in the design") { }
virtual void help()
@@ -79,9 +64,9 @@ struct DeletePass : public Pass {
}
extra_args(args, argidx, design);
- std::vector<std::string> delete_mods;
+ std::vector<RTLIL::IdString> delete_mods;
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
if (design->selected_whole_module(mod_it.first) && !flag_input && !flag_output) {
delete_mods.push_back(mod_it.first);
@@ -94,7 +79,7 @@ struct DeletePass : public Pass {
RTLIL::Module *module = mod_it.second;
if (flag_input || flag_output) {
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (design->selected(module, it.second)) {
if (flag_input)
it.second->port_input = false;
@@ -105,62 +90,52 @@ struct DeletePass : public Pass {
continue;
}
- std::set<std::string> delete_wires;
- std::set<std::string> delete_cells;
- std::set<std::string> delete_procs;
- std::set<std::string> delete_mems;
+ std::set<RTLIL::Wire*> delete_wires;
+ std::set<RTLIL::Cell*> delete_cells;
+ std::set<RTLIL::IdString> delete_procs;
+ std::set<RTLIL::IdString> delete_mems;
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (design->selected(module, it.second))
- delete_wires.insert(it.first);
+ delete_wires.insert(it.second);
for (auto &it : module->memories)
if (design->selected(module, it.second))
delete_mems.insert(it.first);
- for (auto &it : module->cells) {
+ for (auto &it : module->cells_) {
if (design->selected(module, it.second))
- delete_cells.insert(it.first);
+ delete_cells.insert(it.second);
if ((it.second->type == "$memrd" || it.second->type == "$memwr") &&
delete_mems.count(it.second->parameters.at("\\MEMID").decode_string()) != 0)
- delete_cells.insert(it.first);
+ delete_cells.insert(it.second);
}
for (auto &it : module->processes)
if (design->selected(module, it.second))
delete_procs.insert(it.first);
- DeleteWireWorker delete_wire_worker;
- delete_wire_worker.module = module;
- delete_wire_worker.delete_wires_p = &delete_wires;
- module->rewrite_sigspecs(delete_wire_worker);
-
- for (auto &it : delete_wires) {
- delete module->wires.at(it);
- module->wires.erase(it);
- }
-
for (auto &it : delete_mems) {
delete module->memories.at(it);
module->memories.erase(it);
}
- for (auto &it : delete_cells) {
- delete module->cells.at(it);
- module->cells.erase(it);
- }
+ for (auto &it : delete_cells)
+ module->remove(it);
for (auto &it : delete_procs) {
delete module->processes.at(it);
module->processes.erase(it);
}
+ module->remove(delete_wires);
+
module->fixup_ports();
}
for (auto &it : delete_mods) {
- delete design->modules.at(it);
- design->modules.erase(it);
+ delete design->modules_.at(it);
+ design->modules_.erase(it);
}
}
} DeletePass;
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index 80a6c0731..9f800c31f 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -22,13 +22,20 @@
#include "kernel/rtlil.h"
#include "kernel/log.h"
+YOSYS_NAMESPACE_BEGIN
+
+std::map<std::string, RTLIL::Design*> saved_designs;
+std::vector<RTLIL::Design*> pushed_designs;
+
struct DesignPass : public Pass {
DesignPass() : Pass("design", "save, restore and reset current design") { }
- std::map<std::string, RTLIL::Design*> saved_designs;
virtual ~DesignPass() {
for (auto &it : saved_designs)
delete it.second;
saved_designs.clear();
+ for (auto &it : pushed_designs)
+ delete it;
+ pushed_designs.clear();
}
virtual void help()
{
@@ -49,6 +56,16 @@ struct DesignPass : public Pass {
log("Save the current design under the given name and then clear the current design.\n");
log("\n");
log("\n");
+ log(" design -push\n");
+ log("\n");
+ log("Push the current design to the stack and then clear the current design.\n");
+ log("\n");
+ log("\n");
+ log(" design -pop\n");
+ log("\n");
+ log("Reset the current design and pop the last design from the stack.\n");
+ log("\n");
+ log("\n");
log(" design -load <name>\n");
log("\n");
log("Reset the current design and load the design previously saved under the given\n");
@@ -70,6 +87,8 @@ struct DesignPass : public Pass {
{
bool got_mode = false;
bool reset_mode = false;
+ bool push_mode = false;
+ bool pop_mode = false;
RTLIL::Design *copy_from_design = NULL, *copy_to_design = NULL;
std::string save_name, load_name, as_name;
std::vector<RTLIL::Module*> copy_src_modules;
@@ -83,6 +102,16 @@ struct DesignPass : public Pass {
reset_mode = true;
continue;
}
+ if (!got_mode && args[argidx] == "-push") {
+ got_mode = true;
+ push_mode = true;
+ continue;
+ }
+ if (!got_mode && args[argidx] == "-pop") {
+ got_mode = true;
+ pop_mode = true;
+ continue;
+ }
if (!got_mode && args[argidx] == "-save" && argidx+1 < args.size()) {
got_mode = true;
save_name = args[++argidx];
@@ -138,7 +167,7 @@ struct DesignPass : public Pass {
argidx = args.size();
}
- for (auto &it : copy_from_design->modules) {
+ for (auto &it : copy_from_design->modules_) {
if (sel.selected_whole_module(it.first)) {
copy_src_modules.push_back(it.second);
continue;
@@ -151,7 +180,10 @@ struct DesignPass : public Pass {
extra_args(args, argidx, design, false);
if (!got_mode)
- cmd_error(args, argidx, "Missing mode argument (-reset, -save, -load, -copy-from, or -copy-to).");
+ cmd_error(args, argidx, "Missing mode argument.");
+
+ if (pop_mode && pushed_designs.empty())
+ log_cmd_error("No pushed designs.\n");
if (copy_to_design != NULL)
{
@@ -160,21 +192,22 @@ struct DesignPass : public Pass {
for (auto mod : copy_src_modules)
{
- std::string trg_name = as_name.empty() ? mod->name : RTLIL::escape_id(as_name);
+ std::string trg_name = as_name.empty() ? mod->name.str() : RTLIL::escape_id(as_name);
- if (copy_to_design->modules.count(trg_name))
- delete copy_to_design->modules.at(trg_name);
- copy_to_design->modules[trg_name] = mod->clone();
- copy_to_design->modules[trg_name]->name = trg_name;
+ if (copy_to_design->modules_.count(trg_name))
+ delete copy_to_design->modules_.at(trg_name);
+ copy_to_design->modules_[trg_name] = mod->clone();
+ copy_to_design->modules_[trg_name]->name = trg_name;
+ copy_to_design->modules_[trg_name]->design = copy_to_design;
}
}
- if (!save_name.empty())
+ if (!save_name.empty() || push_mode)
{
RTLIL::Design *design_copy = new RTLIL::Design;
- for (auto &it : design->modules)
- design_copy->modules[it.first] = it.second->clone();
+ for (auto &it : design->modules_)
+ design_copy->add(it.second->clone());
design_copy->selection_stack = design->selection_stack;
design_copy->selection_vars = design->selection_vars;
@@ -182,14 +215,18 @@ struct DesignPass : public Pass {
if (saved_designs.count(save_name))
delete saved_designs.at(save_name);
- saved_designs[save_name] = design_copy;
+
+ if (push_mode)
+ pushed_designs.push_back(design_copy);
+ else
+ saved_designs[save_name] = design_copy;
}
- if (reset_mode || !load_name.empty())
+ if (reset_mode || !load_name.empty() || push_mode || pop_mode)
{
- for (auto &it : design->modules)
+ for (auto &it : design->modules_)
delete it.second;
- design->modules.clear();
+ design->modules_.clear();
design->selection_stack.clear();
design->selection_vars.clear();
@@ -198,12 +235,15 @@ struct DesignPass : public Pass {
design->selection_stack.push_back(RTLIL::Selection());
}
- if (!load_name.empty())
+ if (!load_name.empty() || pop_mode)
{
- RTLIL::Design *saved_design = saved_designs.at(load_name);
+ RTLIL::Design *saved_design = pop_mode ? pushed_designs.back() : saved_designs.at(load_name);
+
+ if (pop_mode)
+ pushed_designs.pop_back();
- for (auto &it : saved_design->modules)
- design->modules[it.first] = it.second->clone();
+ for (auto &it : saved_design->modules_)
+ design->add(it.second->clone());
design->selection_stack = saved_design->selection_stack;
design->selection_vars = saved_design->selection_vars;
@@ -211,4 +251,6 @@ struct DesignPass : public Pass {
}
}
} DesignPass;
-
+
+YOSYS_NAMESPACE_END
+
diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc
new file mode 100644
index 000000000..4e8234d16
--- /dev/null
+++ b/passes/cmds/plugin.cc
@@ -0,0 +1,124 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2014 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"
+
+#ifdef YOSYS_ENABLE_PLUGINS
+# include <dlfcn.h>
+#endif
+
+YOSYS_NAMESPACE_BEGIN
+
+std::map<std::string, void*> loaded_plugins;
+std::map<std::string, std::string> loaded_plugin_aliases;
+
+void load_plugin(std::string filename, std::vector<std::string> aliases)
+{
+#ifdef YOSYS_ENABLE_PLUGINS
+ if (filename.find('/') == std::string::npos)
+ filename = "./" + filename;
+
+ if (!loaded_plugins.count(filename)) {
+ void *hdl = dlopen(filename.c_str(), RTLD_LAZY|RTLD_LOCAL);
+ if (hdl == NULL)
+ log_cmd_error("Can't load module `%s': %s\n", filename.c_str(), dlerror());
+ loaded_plugins[filename] = hdl;
+ Pass::init_register();
+ }
+
+ for (auto &alias : aliases)
+ loaded_plugin_aliases[alias] = filename;
+#else
+ log_error("This version of yosys is built without plugin support.\n");
+#endif
+}
+
+struct PluginPass : public Pass {
+ PluginPass() : Pass("plugin", "load and list loaded plugins") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" plugin [options]\n");
+ log("\n");
+ log("Load and list loaded plugins.\n");
+ log("\n");
+ log(" -i <plugin_filename>\n");
+ log(" Load (install) the specified plugin.\n");
+ log("\n");
+ log(" -a <alias_name>\n");
+ log(" Register the specified alias name for the loaded plugin\n");
+ log("\n");
+ log(" -l\n");
+ log(" List loaded plugins\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ std::string plugin_filename;
+ std::vector<std::string> plugin_aliases;
+ bool list_mode = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if ((args[argidx] == "-i") && argidx+1 < args.size() && plugin_filename.empty()) {
+ plugin_filename = args[++argidx];
+ continue;
+ }
+ if ((args[argidx] == "-a") && argidx+1 < args.size()) {
+ plugin_aliases.push_back(args[++argidx]);
+ continue;
+ }
+ if (args[argidx] == "-l") {
+ list_mode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design, false);
+
+ if (!plugin_filename.empty())
+ load_plugin(plugin_filename, plugin_aliases);
+
+ if (list_mode)
+ {
+ log("\n");
+ if (loaded_plugins.empty())
+ log("No plugins loaded.\n");
+ else
+ log("Loaded plugins:\n");
+
+ for (auto &it : loaded_plugins)
+ log(" %s\n", it.first.c_str());
+
+ if (!loaded_plugin_aliases.empty()) {
+ log("\n");
+ int max_alias_len = 1;
+ for (auto &it : loaded_plugin_aliases)
+ max_alias_len = std::max(max_alias_len, SIZE(it.first));
+ for (auto &it : loaded_plugin_aliases)
+ log("Alias: %-*s %s\n", max_alias_len, it.first.c_str(), it.second.c_str());
+ }
+ }
+ }
+} PluginPass;
+
+YOSYS_NAMESPACE_END
+
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index 519dce452..91de364fe 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -29,23 +29,17 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std::
if (module->count_id(to_name))
log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name.c_str(), module->name.c_str());
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (it.first == from_name) {
- RTLIL::Wire *wire = it.second;
- log("Renaming wire %s to %s in module %s.\n", wire->name.c_str(), to_name.c_str(), module->name.c_str());
- module->wires.erase(wire->name);
- wire->name = to_name;
- module->add(wire);
+ log("Renaming wire %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;
}
- for (auto &it : module->cells)
+ for (auto &it : module->cells_)
if (it.first == from_name) {
- RTLIL::Cell *cell = it.second;
- log("Renaming cell %s to %s in module %s.\n", cell->name.c_str(), to_name.c_str(), module->name.c_str());
- module->cells.erase(cell->name);
- cell->name = to_name;
- module->add(cell);
+ 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;
}
@@ -64,10 +58,12 @@ struct RenamePass : public Pass {
log("by this command.\n");
log("\n");
log("\n");
- log(" rename -enumerate [selection]\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");
- log("names.\n");
+ log("names. The -pattern option can be used to set the pattern for the new names.\n");
+ log("The character %% in the pattern is replaced with a integer number. The default\n");
+ log("pattern is '_%%_'.\n");
log("\n");
log(" rename -hide [selection]\n");
log("\n");
@@ -77,6 +73,7 @@ struct RenamePass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
+ std::string pattern_prefix = "_", pattern_suffix = "_";
bool flag_enumerate = false;
bool flag_hide = false;
bool got_mode = false;
@@ -95,6 +92,12 @@ struct RenamePass : public Pass {
got_mode = true;
continue;
}
+ if (arg == "-pattern" && argidx+1 < args.size() && args[argidx+1].find('%') != std::string::npos) {
+ int pos = args[++argidx].find('%');
+ pattern_prefix = args[argidx].substr(0, pos);
+ pattern_suffix = args[argidx].substr(pos+1);
+ continue;
+ }
break;
}
@@ -102,7 +105,7 @@ struct RenamePass : public Pass {
{
extra_args(args, argidx, design);
- for (auto &mod : design->modules)
+ for (auto &mod : design->modules_)
{
int counter = 0;
@@ -111,22 +114,22 @@ struct RenamePass : public Pass {
continue;
std::map<RTLIL::IdString, RTLIL::Wire*> new_wires;
- for (auto &it : module->wires) {
+ for (auto &it : module->wires_) {
if (it.first[0] == '$' && design->selected(module, it.second))
- do it.second->name = stringf("\\_%d_", counter++);
+ do it.second->name = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
while (module->count_id(it.second->name) > 0);
new_wires[it.second->name] = it.second;
}
- module->wires.swap(new_wires);
+ module->wires_.swap(new_wires);
std::map<RTLIL::IdString, RTLIL::Cell*> new_cells;
- for (auto &it : module->cells) {
+ for (auto &it : module->cells_) {
if (it.first[0] == '$' && design->selected(module, it.second))
- do it.second->name = stringf("\\_%d_", counter++);
+ do it.second->name = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
while (module->count_id(it.second->name) > 0);
new_cells[it.second->name] = it.second;
}
- module->cells.swap(new_cells);
+ module->cells_.swap(new_cells);
}
}
else
@@ -134,29 +137,29 @@ struct RenamePass : public Pass {
{
extra_args(args, argidx, design);
- for (auto &mod : design->modules)
+ for (auto &mod : design->modules_)
{
RTLIL::Module *module = mod.second;
if (!design->selected(module))
continue;
std::map<RTLIL::IdString, RTLIL::Wire*> new_wires;
- for (auto &it : module->wires) {
+ for (auto &it : module->wires_) {
if (design->selected(module, it.second))
if (it.first[0] == '\\' && it.second->port_id == 0)
it.second->name = NEW_ID;
new_wires[it.second->name] = it.second;
}
- module->wires.swap(new_wires);
+ module->wires_.swap(new_wires);
std::map<RTLIL::IdString, RTLIL::Cell*> new_cells;
- for (auto &it : module->cells) {
+ for (auto &it : module->cells_) {
if (design->selected(module, it.second))
if (it.first[0] == '\\')
it.second->name = NEW_ID;
new_cells[it.second->name] = it.second;
}
- module->cells.swap(new_cells);
+ module->cells_.swap(new_cells);
}
}
else
@@ -169,19 +172,19 @@ 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);
+ if (design->modules_.count(design->selected_active_module) > 0)
+ rename_in_module(design->modules_.at(design->selected_active_module), from_name, to_name);
}
else
{
- for (auto &mod : design->modules) {
+ for (auto &mod : design->modules_) {
if (mod.first == from_name || RTLIL::unescape_id(mod.first) == from_name) {
to_name = RTLIL::escape_id(to_name);
log("Renaming module %s to %s.\n", mod.first.c_str(), to_name.c_str());
RTLIL::Module *module = mod.second;
- design->modules.erase(module->name);
+ design->modules_.erase(module->name);
module->name = to_name;
- design->modules[module->name] = module;
+ design->modules_[module->name] = module;
goto rename_ok;
}
}
diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc
index e5f78830e..e09c00123 100644
--- a/passes/cmds/scatter.cc
+++ b/passes/cmds/scatter.cc
@@ -43,25 +43,22 @@ struct ScatterPass : public Pass {
CellTypes ct(design);
extra_args(args, 1, design);
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
if (!design->selected(mod_it.second))
continue;
- for (auto &c : mod_it.second->cells)
- for (auto &p : c.second->connections)
+ for (auto &c : mod_it.second->cells_)
+ for (auto &p : c.second->connections_)
{
- RTLIL::Wire *wire = new RTLIL::Wire;
- wire->name = NEW_ID;
- wire->width = p.second.width;
- mod_it.second->add(wire);
+ RTLIL::Wire *wire = mod_it.second->addWire(NEW_ID, p.second.size());
if (ct.cell_output(c.second->type, p.first)) {
RTLIL::SigSig sigsig(p.second, wire);
- mod_it.second->connections.push_back(sigsig);
+ mod_it.second->connect(sigsig);
} else {
RTLIL::SigSig sigsig(wire, p.second);
- mod_it.second->connections.push_back(sigsig);
+ mod_it.second->connect(sigsig);
}
p.second = wire;
diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc
index f8c351a43..5224f5bc9 100644
--- a/passes/cmds/scc.cc
+++ b/passes/cmds/scc.cc
@@ -51,7 +51,7 @@ struct SccWorker
void run(RTLIL::Cell *cell, int depth, int maxDepth)
{
- assert(workQueue.count(cell) > 0);
+ log_assert(workQueue.count(cell) > 0);
workQueue.erase(cell);
cellLabels[cell] = std::pair<int, int>(labelCounter, labelCounter);
@@ -114,11 +114,11 @@ struct SccWorker
SigPool selectedSignals;
SigSet<RTLIL::Cell*> sigToNextCells;
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (design->selected(module, it.second))
selectedSignals.add(sigmap(RTLIL::SigSpec(it.second)));
- for (auto &it : module->cells)
+ for (auto &it : module->cells_)
{
RTLIL::Cell *cell = it.second;
@@ -132,7 +132,7 @@ struct SccWorker
RTLIL::SigSpec inputSignals, outputSignals;
- for (auto &conn : cell->connections)
+ for (auto &conn : cell->connections())
{
bool isInput = true, isOutput = true;
@@ -166,7 +166,7 @@ struct SccWorker
while (workQueue.size() > 0) {
RTLIL::Cell *cell = *workQueue.begin();
- assert(cellStack.size() == 0);
+ log_assert(cellStack.size() == 0);
cellDepth.clear();
run(cell, 0, maxDepth);
}
@@ -191,7 +191,7 @@ struct SccWorker
nextsig.sort_and_unify();
sig = prevsig.extract(nextsig);
- for (auto &chunk : sig.chunks)
+ for (auto &chunk : sig.chunks())
if (chunk.wire != NULL)
sel.selected_members[module->name].insert(chunk.wire->name);
}
@@ -216,7 +216,7 @@ struct SccPass : public Pass {
log("\n");
log(" -all_cell_types\n");
log(" Usually this command only considers internal non-memory cells. With\n");
- log(" this option set, all cells are considered. For unkown cells all ports\n");
+ log(" this option set, all cells are considered. For unknown cells all ports\n");
log(" are assumed to be bidirectional 'inout' ports.\n");
log("\n");
log(" -set_attr <name> <value>\n");
@@ -280,7 +280,7 @@ struct SccPass : public Pass {
RTLIL::Selection newSelection(false);
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
if (design->selected(mod_it.second))
{
SccWorker worker(design, mod_it.second, allCellTypes, maxDepth);
@@ -290,7 +290,7 @@ struct SccPass : public Pass {
}
if (selectMode) {
- assert(origSelectPos >= 0);
+ log_assert(origSelectPos >= 0);
design->selection_stack[origSelectPos] = newSelection;
design->selection_stack[origSelectPos].optimize(design);
}
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index a1a64f145..4c540ca67 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -23,6 +23,7 @@
#include "kernel/log.h"
#include <string.h>
#include <fnmatch.h>
+#include <errno.h>
using RTLIL::id2cstr;
@@ -63,6 +64,8 @@ static bool match_attr_val(const RTLIL::Const &value, std::string pattern, char
if (match_op == '=')
return value == pattern_value;
+ if (match_op == '!')
+ return value != pattern_value;
if (match_op == '<')
return value.as_int() < pattern_value.as_int();
if (match_op == '>')
@@ -82,6 +85,8 @@ static bool match_attr_val(const RTLIL::Const &value, std::string pattern, char
if (match_op == '=')
return value_str == pattern;
+ if (match_op == '!')
+ return value_str != pattern;
if (match_op == '<')
return value_str < pattern;
if (match_op == '>')
@@ -115,9 +120,11 @@ static bool match_attr(const std::map<RTLIL::IdString, RTLIL::Const> &attributes
static bool match_attr(const std::map<RTLIL::IdString, RTLIL::Const> &attributes, std::string match_expr)
{
- size_t pos = match_expr.find_first_of("<=>");
+ size_t pos = match_expr.find_first_of("<!=>");
if (pos != std::string::npos) {
+ if (match_expr.substr(pos, 2) == "!=")
+ return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), '!');
if (match_expr.substr(pos, 2) == "<=")
return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), '[');
if (match_expr.substr(pos, 2) == ">=")
@@ -144,7 +151,7 @@ static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs)
RTLIL::Selection new_sel(false);
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
if (lhs.selected_whole_module(mod_it.first))
continue;
@@ -154,13 +161,13 @@ static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs)
}
RTLIL::Module *mod = mod_it.second;
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (!lhs.selected_member(mod_it.first, it.first))
new_sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->memories)
if (!lhs.selected_member(mod_it.first, it.first))
new_sel.selected_members[mod->name].insert(it.first);
- for (auto &it : mod->cells)
+ for (auto &it : mod->cells_)
if (!lhs.selected_member(mod_it.first, it.first))
new_sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->processes)
@@ -174,13 +181,13 @@ static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs)
static void select_op_submod(RTLIL::Design *design, RTLIL::Selection &lhs)
{
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
if (lhs.selected_whole_module(mod_it.first))
{
- for (auto &cell_it : mod_it.second->cells)
+ for (auto &cell_it : mod_it.second->cells_)
{
- if (design->modules.count(cell_it.second->type) == 0)
+ if (design->modules_.count(cell_it.second->type) == 0)
continue;
lhs.selected_modules.insert(cell_it.second->type);
}
@@ -198,7 +205,7 @@ static void select_op_fullmod(RTLIL::Design *design, RTLIL::Selection &lhs)
static void select_op_alias(RTLIL::Design *design, RTLIL::Selection &lhs)
{
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
if (lhs.selected_whole_module(mod_it.first))
continue;
@@ -208,11 +215,11 @@ static void select_op_alias(RTLIL::Design *design, RTLIL::Selection &lhs)
SigMap sigmap(mod_it.second);
SigPool selected_bits;
- for (auto &it : mod_it.second->wires)
+ for (auto &it : mod_it.second->wires_)
if (lhs.selected_member(mod_it.first, it.first))
selected_bits.add(sigmap(it.second));
- for (auto &it : mod_it.second->wires)
+ for (auto &it : mod_it.second->wires_)
if (!lhs.selected_member(mod_it.first, it.first) && selected_bits.check_any(sigmap(it.second)))
lhs.selected_members[mod_it.first].insert(it.first);
}
@@ -253,7 +260,7 @@ static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const R
if (!rhs.full_selection && rhs.selected_modules.size() == 0 && rhs.selected_members.size() == 0)
return;
lhs.full_selection = false;
- for (auto &it : design->modules)
+ for (auto &it : design->modules_)
lhs.selected_modules.insert(it.first);
}
@@ -264,18 +271,18 @@ static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const R
for (auto &it : rhs.selected_members)
{
- if (design->modules.count(it.first) == 0)
+ if (design->modules_.count(it.first) == 0)
continue;
- RTLIL::Module *mod = design->modules[it.first];
+ RTLIL::Module *mod = design->modules_[it.first];
if (lhs.selected_modules.count(mod->name) > 0)
{
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
lhs.selected_members[mod->name].insert(it.first);
for (auto &it : mod->memories)
lhs.selected_members[mod->name].insert(it.first);
- for (auto &it : mod->cells)
+ for (auto &it : mod->cells_)
lhs.selected_members[mod->name].insert(it.first);
for (auto &it : mod->processes)
lhs.selected_members[mod->name].insert(it.first);
@@ -297,7 +304,7 @@ static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, co
if (lhs.full_selection) {
lhs.full_selection = false;
- for (auto &it : design->modules)
+ for (auto &it : design->modules_)
lhs.selected_modules.insert(it.first);
}
@@ -361,7 +368,7 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v
{
int sel_objects = 0;
bool is_input, is_output;
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
if (lhs.selected_whole_module(mod_it.first) || !lhs.selected_module(mod_it.first))
continue;
@@ -369,11 +376,11 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v
RTLIL::Module *mod = mod_it.second;
std::set<RTLIL::Wire*> selected_wires;
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (lhs.selected_member(mod_it.first, it.first) && limits.count(it.first) == 0)
selected_wires.insert(it.second);
- for (auto &conn : mod->connections)
+ for (auto &conn : mod->connections())
{
std::vector<RTLIL::SigBit> conn_lhs = conn.first.to_sigbit_vector();
std::vector<RTLIL::SigBit> conn_rhs = conn.second.to_sigbit_vector();
@@ -388,8 +395,8 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v
}
}
- for (auto &cell : mod->cells)
- for (auto &conn : cell.second->connections)
+ for (auto &cell : mod->cells_)
+ for (auto &conn : cell.second->connections())
{
char last_mode = '-';
for (auto &rule : rules) {
@@ -408,7 +415,7 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v
include_match:
is_input = mode == 'x' || ct.cell_input(cell.second->type, conn.first);
is_output = mode == 'x' || ct.cell_output(cell.second->type, conn.first);
- for (auto &chunk : conn.second.chunks)
+ for (auto &chunk : conn.second.chunks())
if (chunk.wire != NULL) {
if (max_objects != 0 && selected_wires.count(chunk.wire) > 0 && lhs.selected_members[mod->name].count(cell.first) == 0)
if (mode == 'x' || (mode == 'i' && is_output) || (mode == 'o' && is_input))
@@ -483,7 +490,7 @@ static void select_op_expand(RTLIL::Design *design, std::string arg, char mode)
for (auto i2 : i1.second)
limits.insert(i2);
} else
- log_cmd_error("Selection %s is not defined!\n", RTLIL::id2cstr(str));
+ log_cmd_error("Selection %s is not defined!\n", RTLIL::unescape_id(str).c_str());
} else
limits.insert(RTLIL::escape_id(str));
}
@@ -540,7 +547,7 @@ static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &se
return;
}
- std::vector<std::string> del_list;
+ std::vector<RTLIL::IdString> del_list;
for (auto mod_name : sel.selected_modules)
if (mod_name != design->selected_active_module)
del_list.push_back(mod_name);
@@ -588,6 +595,13 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
select_op_diff(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]);
work_stack.pop_back();
} else
+ if (arg == "%D") {
+ if (work_stack.size() < 2)
+ log_cmd_error("Must have at least two elements on the stack for operator %%d.\n");
+ select_op_diff(design, work_stack[work_stack.size()-1], work_stack[work_stack.size()-2]);
+ work_stack[work_stack.size()-2] = work_stack[work_stack.size()-1];
+ work_stack.pop_back();
+ } else
if (arg == "%i") {
if (work_stack.size() < 2)
log_cmd_error("Must have at least two elements on the stack for operator %%i.\n");
@@ -599,14 +613,19 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
log_cmd_error("Must have at least one element on the stack for operator %%s.\n");
select_op_submod(design, work_stack[work_stack.size()-1]);
} else
+ if (arg == "%c") {
+ if (work_stack.size() < 1)
+ log_cmd_error("Must have at least one element on the stack for operator %%c.\n");
+ work_stack.push_back(work_stack.back());
+ } else
if (arg == "%m") {
if (work_stack.size() < 1)
- log_cmd_error("Must have at least one element on the stack for operator %%s.\n");
+ log_cmd_error("Must have at least one element on the stack for operator %%m.\n");
select_op_fullmod(design, work_stack[work_stack.size()-1]);
} else
if (arg == "%a") {
if (work_stack.size() < 1)
- log_cmd_error("Must have at least one element on the stack for operator %%s.\n");
+ log_cmd_error("Must have at least one element on the stack for operator %%a.\n");
select_op_alias(design, work_stack[work_stack.size()-1]);
} else
if (arg == "%x" || (arg.size() > 2 && arg.substr(0, 2) == "%x" && (arg[2] == ':' || arg[2] == '*' || arg[2] == '.' || ('0' <= arg[2] && arg[2] <= '9')))) {
@@ -635,7 +654,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
if (design->selection_vars.count(set_name) > 0)
work_stack.push_back(design->selection_vars[set_name]);
else
- log_cmd_error("Selection @%s is not defined!\n", RTLIL::id2cstr(set_name));
+ log_cmd_error("Selection @%s is not defined!\n", RTLIL::unescape_id(set_name).c_str());
select_filter_active_mod(design, work_stack.back());
return;
}
@@ -665,7 +684,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
}
sel.full_selection = false;
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
if (arg_mod.substr(0, 2) == "A:") {
if (!match_attr(mod_it.second->attributes, arg_mod.substr(2)))
@@ -681,22 +700,22 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
RTLIL::Module *mod = mod_it.second;
if (arg_memb.substr(0, 2) == "w:") {
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "i:") {
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (it.second->port_input && match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "o:") {
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (it.second->port_output && match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "x:") {
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if ((it.second->port_input || it.second->port_output) && match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
@@ -704,7 +723,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
size_t delim = arg_memb.substr(2).find(':');
if (delim == std::string::npos) {
int width = atoi(arg_memb.substr(2).c_str());
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (it.second->width == width)
sel.selected_members[mod->name].insert(it.first);
} else {
@@ -712,7 +731,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
std::string max_str = arg_memb.substr(2+delim+1);
int min_width = min_str.empty() ? 0 : atoi(min_str.c_str());
int max_width = max_str.empty() ? -1 : atoi(max_str.c_str());
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (min_width <= it.second->width && (it.second->width <= max_width || max_width == -1))
sel.selected_members[mod->name].insert(it.first);
}
@@ -723,12 +742,12 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "c:") {
- for (auto &it : mod->cells)
+ for (auto &it : mod->cells_)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "t:") {
- for (auto &it : mod->cells)
+ for (auto &it : mod->cells_)
if (match_ids(it.second->type, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
@@ -738,13 +757,13 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "a:") {
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (match_attr(it.second->attributes, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->memories)
if (match_attr(it.second->attributes, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
- for (auto &it : mod->cells)
+ for (auto &it : mod->cells_)
if (match_attr(it.second->attributes, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->processes)
@@ -752,19 +771,19 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "r:") {
- for (auto &it : mod->cells)
+ for (auto &it : mod->cells_)
if (match_attr(it.second->parameters, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else {
if (arg_memb.substr(0, 2) == "n:")
arg_memb = arg_memb.substr(2);
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
if (match_ids(it.first, arg_memb))
sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->memories)
if (match_ids(it.first, arg_memb))
sel.selected_members[mod->name].insert(it.first);
- for (auto &it : mod->cells)
+ for (auto &it : mod->cells_)
if (match_ids(it.first, arg_memb))
sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->processes)
@@ -838,6 +857,10 @@ struct SelectPass : public Pass {
log(" selection is non-empty. i.e. produce an error if no object matching\n");
log(" the selection is found.\n");
log("\n");
+ log(" -assert-count N\n");
+ log(" do not modify the current selection. instead assert that the given\n");
+ log(" selection contains exactly N objects.\n");
+ log("\n");
log(" -list\n");
log(" list all objects in the current selection\n");
log("\n");
@@ -951,12 +974,18 @@ struct SelectPass : public Pass {
log(" %%d\n");
log(" pop the top set from the stack and subtract it from the new top\n");
log("\n");
+ log(" %%D\n");
+ log(" like %%d but swap the roles of two top sets on the stack\n");
+ log("\n");
+ log(" %%c\n");
+ log(" create a copy of the top set rom the stack and push it\n");
+ log("\n");
log(" %%x[<num1>|*][.<num2>][:<rule>[:<rule>..]]\n");
log(" expand top set <num1> num times according to the specified rules.\n");
log(" (i.e. select all cells connected to selected wires and select all\n");
log(" wires connected to selected cells) The rules specify which cell\n");
log(" ports to use for this. the syntax for a rule is a '-' for exclusion\n");
- log(" and a '+' for inclusion, followed by an optional comma seperated\n");
+ log(" and a '+' for inclusion, followed by an optional comma separated\n");
log(" list of cell types followed by an optional comma separated list of\n");
log(" cell ports in square brackets. a rule can also be just a cell or wire\n");
log(" name that limits the expansion (is included but does not go beyond).\n");
@@ -996,6 +1025,7 @@ struct SelectPass : public Pass {
bool got_module = false;
bool assert_none = false;
bool assert_any = false;
+ int assert_count = -1;
std::string write_file;
std::string set_name;
std::string sel_str;
@@ -1022,6 +1052,10 @@ struct SelectPass : public Pass {
assert_any = true;
continue;
}
+ if (arg == "-assert-count" && argidx+1 < args.size()) {
+ assert_count = atoi(args[++argidx].c_str());
+ continue;
+ }
if (arg == "-clear") {
clear_mode = true;
continue;
@@ -1044,9 +1078,9 @@ struct SelectPass : public Pass {
}
if (arg == "-module" && argidx+1 < args.size()) {
RTLIL::IdString mod_name = RTLIL::escape_id(args[++argidx]);
- if (design->modules.count(mod_name) == 0)
+ if (design->modules_.count(mod_name) == 0)
log_cmd_error("No such module: %s\n", id2cstr(mod_name));
- design->selected_active_module = mod_name;
+ design->selected_active_module = mod_name.str();
got_module = true;
continue;
}
@@ -1055,7 +1089,7 @@ struct SelectPass : public Pass {
continue;
}
if (arg.size() > 0 && arg[0] == '-')
- log_cmd_error("Unkown option %s.\n", arg.c_str());
+ log_cmd_error("Unknown option %s.\n", arg.c_str());
select_stmt(design, arg);
sel_str += " " + arg;
}
@@ -1066,14 +1100,14 @@ struct SelectPass : public Pass {
if (none_mode && args.size() != 2)
log_cmd_error("Option -none can not be combined with any other options.\n");
- if (add_mode + del_mode + assert_none + assert_any > 1)
- log_cmd_error("Options -add, -del, -assert-none or -assert-any can not be combined.\n");
+ if (add_mode + del_mode + assert_none + assert_any + (assert_count >= 0) > 1)
+ log_cmd_error("Options -add, -del, -assert-none, -assert-any or -assert-count can not be combined.\n");
- if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any))
- log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none or -assert-any.\n");
+ if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any || assert_count >= 0))
+ log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none, -assert-any or -assert-count.\n");
- if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any))
- log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none or -assert-any.\n");
+ if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any || assert_count >= 0))
+ log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none, -assert-any or -assert-count.\n");
if (work_stack.size() == 0 && got_module) {
RTLIL::Selection sel;
@@ -1086,7 +1120,7 @@ struct SelectPass : public Pass {
work_stack.pop_back();
}
- assert(design->selection_stack.size() > 0);
+ log_assert(design->selection_stack.size() > 0);
if (clear_mode) {
design->selection_stack.back() = RTLIL::Selection(true);
@@ -1113,18 +1147,18 @@ struct SelectPass : public Pass {
if (work_stack.size() > 0)
sel = &work_stack.back();
sel->optimize(design);
- for (auto mod_it : design->modules)
+ for (auto mod_it : design->modules_)
{
if (sel->selected_whole_module(mod_it.first) && list_mode)
log("%s\n", id2cstr(mod_it.first));
if (sel->selected_module(mod_it.first)) {
- for (auto &it : mod_it.second->wires)
+ for (auto &it : mod_it.second->wires_)
if (sel->selected_member(mod_it.first, it.first))
LOG_OBJECT("%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))
LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
- for (auto &it : mod_it.second->cells)
+ for (auto &it : mod_it.second->cells_)
if (sel->selected_member(mod_it.first, it.first))
LOG_OBJECT("%s/%s\n", id2cstr(mod_it.first), id2cstr(it.first));
for (auto &it : mod_it.second->processes)
@@ -1176,6 +1210,34 @@ struct SelectPass : public Pass {
return;
}
+ if (assert_count >= 0)
+ {
+ int total_count = 0;
+ if (work_stack.size() == 0)
+ log_cmd_error("No selection to check.\n");
+ RTLIL::Selection *sel = &work_stack.back();
+ sel->optimize(design);
+ 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))
+ total_count++;
+ for (auto &it : mod_it.second->memories)
+ if (sel->selected_member(mod_it.first, it.first))
+ total_count++;
+ for (auto &it : mod_it.second->cells_)
+ if (sel->selected_member(mod_it.first, it.first))
+ total_count++;
+ for (auto &it : mod_it.second->processes)
+ if (sel->selected_member(mod_it.first, it.first))
+ total_count++;
+ }
+ if (assert_count != total_count)
+ log_error("Assertation failed: selection contains %d elements instead of the asserted %d:%s\n",
+ total_count, assert_count, sel_str.c_str());
+ return;
+ }
+
if (!set_name.empty())
{
if (work_stack.size() == 0)
@@ -1237,15 +1299,15 @@ struct CdPass : public Pass {
std::string modname = RTLIL::escape_id(args[1]);
- if (design->modules.count(modname) == 0 && !design->selected_active_module.empty()) {
+ if (design->modules_.count(modname) == 0 && !design->selected_active_module.empty()) {
RTLIL::Module *module = NULL;
- if (design->modules.count(design->selected_active_module) > 0)
- module = design->modules.at(design->selected_active_module);
- if (module != NULL && module->cells.count(modname) > 0)
- modname = module->cells.at(modname)->type;
+ if (design->modules_.count(design->selected_active_module) > 0)
+ module = design->modules_.at(design->selected_active_module);
+ if (module != NULL && module->cells_.count(modname) > 0)
+ modname = module->cells_.at(modname)->type.str();
}
- if (design->modules.count(modname) > 0) {
+ if (design->modules_.count(modname) > 0) {
design->selected_active_module = modname;
design->selection_stack.back() = RTLIL::Selection();
select_filter_active_mod(design, design->selection_stack.back());
@@ -1253,14 +1315,14 @@ struct CdPass : public Pass {
return;
}
- log_cmd_error("No such module `%s' found!\n", RTLIL::id2cstr(modname));
+ log_cmd_error("No such module `%s' found!\n", RTLIL::unescape_id(modname).c_str());
}
} CdPass;
template<typename T>
static int log_matches(const char *title, std::string pattern, T list)
{
- std::vector<std::string> matches;
+ std::vector<RTLIL::IdString> matches;
for (auto &it : list)
if (pattern.empty() || match_ids(it.first, pattern))
@@ -1306,15 +1368,15 @@ struct LsPass : public Pass {
if (design->selected_active_module.empty())
{
- counter += log_matches("modules", pattern, design->modules);
+ counter += log_matches("modules", pattern, design->modules_);
}
else
- if (design->modules.count(design->selected_active_module) > 0)
+ if (design->modules_.count(design->selected_active_module) > 0)
{
- RTLIL::Module *module = design->modules.at(design->selected_active_module);
- counter += log_matches("wires", pattern, module->wires);
+ RTLIL::Module *module = design->modules_.at(design->selected_active_module);
+ counter += log_matches("wires", pattern, module->wires_);
counter += log_matches("memories", pattern, module->memories);
- counter += log_matches("cells", pattern, module->cells);
+ counter += log_matches("cells", pattern, module->cells_);
counter += log_matches("processes", pattern, module->processes);
}
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index 8d98df719..029c0ec79 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -98,7 +98,7 @@ struct SetattrPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &mod : design->modules)
+ for (auto &mod : design->modules_)
{
RTLIL::Module *module = mod.second;
@@ -111,7 +111,7 @@ struct SetattrPass : public Pass {
if (!design->selected(module))
continue;
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (design->selected(module, it.second))
do_setunset(it.second->attributes, setunset_list);
@@ -119,7 +119,7 @@ struct SetattrPass : public Pass {
if (design->selected(module, it.second))
do_setunset(it.second->attributes, setunset_list);
- for (auto &it : module->cells)
+ for (auto &it : module->cells_)
if (design->selected(module, it.second))
do_setunset(it.second->attributes, setunset_list);
@@ -164,14 +164,14 @@ struct SetparamPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &mod : design->modules)
+ for (auto &mod : design->modules_)
{
RTLIL::Module *module = mod.second;
if (!design->selected(module))
continue;
- for (auto &it : module->cells)
+ for (auto &it : module->cells_)
if (design->selected(module, it.second))
do_setunset(it.second->parameters, setunset_list);
}
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index 9d59834c2..c72e64b80 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -23,35 +23,33 @@
#include "kernel/rtlil.h"
#include "kernel/log.h"
-static int next_bit_mode;
-static uint32_t next_bit_state;
-
-static RTLIL::State next_bit()
+struct SetundefWorker
{
- if (next_bit_mode == 0)
- return RTLIL::State::S0;
+ int next_bit_mode;
+ uint32_t next_bit_state;
- if (next_bit_mode == 1)
- return RTLIL::State::S1;
+ RTLIL::State next_bit()
+ {
+ if (next_bit_mode == 0)
+ return RTLIL::State::S0;
- // xorshift32
- next_bit_state ^= next_bit_state << 13;
- next_bit_state ^= next_bit_state >> 17;
- next_bit_state ^= next_bit_state << 5;
- log_assert(next_bit_state != 0);
+ if (next_bit_mode == 1)
+ return RTLIL::State::S1;
- return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
-}
+ // xorshift32
+ next_bit_state ^= next_bit_state << 13;
+ next_bit_state ^= next_bit_state >> 17;
+ next_bit_state ^= next_bit_state << 5;
+ log_assert(next_bit_state != 0);
+
+ return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
+ }
-struct SetundefWorker
-{
void operator()(RTLIL::SigSpec &sig)
{
- sig.expand();
- for (auto &c : sig.chunks)
- if (c.wire == NULL && c.data.bits.at(0) > RTLIL::State::S1)
- c.data.bits.at(0) = next_bit();
- sig.optimize();
+ for (auto &bit : sig)
+ if (bit.wire == NULL && bit.data > RTLIL::State::S1)
+ bit = next_bit();
}
};
@@ -83,6 +81,7 @@ struct SetundefPass : public Pass {
{
bool got_value = false;
bool undriven_mode = false;
+ SetundefWorker worker;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -93,20 +92,20 @@ struct SetundefPass : public Pass {
}
if (args[argidx] == "-zero") {
got_value = true;
- next_bit_mode = 0;
+ worker.next_bit_mode = 0;
continue;
}
if (args[argidx] == "-one") {
got_value = true;
- next_bit_mode = 1;
+ worker.next_bit_mode = 1;
continue;
}
if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
got_value = true;
- next_bit_mode = 2;
- next_bit_state = atoi(args[++argidx].c_str()) + 1;
+ worker.next_bit_mode = 2;
+ worker.next_bit_state = atoi(args[++argidx].c_str()) + 1;
for (int i = 0; i < 10; i++)
- next_bit();
+ worker.next_bit();
continue;
}
break;
@@ -116,7 +115,7 @@ struct SetundefPass : public Pass {
if (!got_value)
log_cmd_error("One of the options -zero, -one, or -random <seed> must be specified.\n");
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
RTLIL::Module *module = mod_it.second;
if (!design->selected(module))
@@ -130,27 +129,26 @@ struct SetundefPass : public Pass {
SigMap sigmap(module);
SigPool undriven_signals;
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (!it.second->port_input)
undriven_signals.add(sigmap(it.second));
CellTypes ct(design);
- for (auto &it : module->cells)
- for (auto &conn : it.second->connections)
+ for (auto &it : module->cells_)
+ for (auto &conn : it.second->connections())
if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first))
undriven_signals.del(sigmap(conn.second));
RTLIL::SigSpec sig = undriven_signals.export_all();
- for (auto &c : sig.chunks) {
+ for (auto &c : sig.chunks()) {
RTLIL::SigSpec bits;
for (int i = 0; i < c.width; i++)
- bits.append(next_bit());
- bits.optimize();
- module->connections.push_back(RTLIL::SigSig(c, bits));
+ bits.append(worker.next_bit());
+ module->connect(RTLIL::SigSig(c, bits));
}
}
- module->rewrite_sigspecs(SetundefWorker());
+ module->rewrite_sigspecs(worker);
}
}
} SetundefPass;
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index fdccb4bcc..2218eded2 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -22,7 +22,10 @@
#include "kernel/log.h"
#include <string.h>
#include <dirent.h>
-#include <readline/readline.h>
+
+#ifdef YOSYS_ENABLE_READLINE
+# include <readline/readline.h>
+#endif
using RTLIL::id2cstr;
@@ -45,6 +48,7 @@ struct ShowWorker
RTLIL::Module *module;
uint32_t currentColor;
bool genWidthLabels;
+ bool genSignedLabels;
bool stretchIO;
bool enumerateIds;
bool abbreviateIds;
@@ -54,7 +58,7 @@ struct ShowWorker
const std::vector<std::pair<std::string, RTLIL::Selection>> &color_selections;
const std::vector<std::pair<std::string, RTLIL::Selection>> &label_selections;
- uint32_t xorshift32(uint32_t x) {
+ static uint32_t xorshift32(uint32_t x) {
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
@@ -78,7 +82,7 @@ struct ShowWorker
std::string nextColor(RTLIL::SigSpec sig, std::string defaultColor)
{
sig.sort_and_unify();
- for (auto &c : sig.chunks) {
+ for (auto &c : sig.chunks()) {
if (c.wire != NULL)
for (auto &s : color_selections)
if (s.second.selected_members.count(module->name) > 0 && s.second.selected_members.at(module->name).count(c.wire->name) > 0)
@@ -87,17 +91,17 @@ struct ShowWorker
return defaultColor;
}
- std::string nextColor(RTLIL::SigSig &conn, std::string defaultColor)
+ std::string nextColor(const RTLIL::SigSig &conn, std::string defaultColor)
{
return nextColor(conn.first, nextColor(conn.second, defaultColor));
}
- std::string nextColor(RTLIL::SigSpec &sig)
+ std::string nextColor(const RTLIL::SigSpec &sig)
{
return nextColor(sig, nextColor());
}
- std::string nextColor(RTLIL::SigSig &conn)
+ std::string nextColor(const RTLIL::SigSig &conn)
{
return nextColor(conn, nextColor());
}
@@ -124,7 +128,7 @@ struct ShowWorker
const char *findLabel(std::string member_name)
{
for (auto &s : label_selections)
- if (s.second.selected_member(module->name, RTLIL::escape_id(member_name)))
+ if (s.second.selected_member(module->name, member_name))
return escape(s.first);
return escape(member_name, true);
}
@@ -171,15 +175,13 @@ struct ShowWorker
std::string gen_signode_simple(RTLIL::SigSpec sig, bool range_check = true)
{
- sig.optimize();
-
- if (sig.chunks.size() == 0) {
+ if (SIZE(sig) == 0) {
fprintf(f, "v%d [ label=\"\" ];\n", single_idx_count);
return stringf("v%d", single_idx_count++);
}
- if (sig.chunks.size() == 1) {
- RTLIL::SigChunk &c = sig.chunks[0];
+ if (sig.is_chunk()) {
+ const RTLIL::SigChunk &c = sig.as_chunk();
if (c.wire != NULL && design->selected_member(module->name, c.wire->name)) {
if (!range_check || c.wire->width == c.width)
return stringf("n%d", id2num(c.wire->name));
@@ -199,13 +201,12 @@ struct ShowWorker
if (net.empty())
{
std::string label_string;
- sig.optimize();
- int pos = sig.width-1;
+ int pos = sig.size()-1;
int idx = single_idx_count++;
- for (int i = int(sig.chunks.size())-1; i >= 0; i--) {
- RTLIL::SigChunk &c = sig.chunks[i];
+ for (int i = int(sig.chunks().size())-1; i >= 0; i--) {
+ const RTLIL::SigChunk &c = sig.chunks().at(i);
net = gen_signode_simple(c, false);
- assert(!net.empty());
+ log_assert(!net.empty());
if (driver) {
label_string += stringf("<s%d> %d:%d - %d:%d |", i, pos, pos-c.width+1, c.offset+c.width-1, c.offset);
net_conn_map[net].in.insert(stringf("x%d:s%d", idx, i));
@@ -225,9 +226,9 @@ struct ShowWorker
if (!port.empty()) {
currentColor = xorshift32(currentColor);
if (driver)
- code += stringf("%s:e -> x%d:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", port.c_str(), idx, nextColor(sig).c_str(), widthLabel(sig.width).c_str());
+ code += stringf("%s:e -> x%d:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", port.c_str(), idx, nextColor(sig).c_str(), widthLabel(sig.size()).c_str());
else
- code += stringf("x%d:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", idx, port.c_str(), nextColor(sig).c_str(), widthLabel(sig.width).c_str());
+ code += stringf("x%d:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", idx, port.c_str(), nextColor(sig).c_str(), widthLabel(sig.size()).c_str());
}
if (node != NULL)
*node = stringf("x%d", idx);
@@ -239,7 +240,7 @@ struct ShowWorker
net_conn_map[net].in.insert(port);
else
net_conn_map[net].out.insert(port);
- net_conn_map[net].bits = sig.width;
+ net_conn_map[net].bits = sig.size();
net_conn_map[net].color = nextColor(sig, net_conn_map[net].color);
}
if (node != NULL)
@@ -299,16 +300,16 @@ struct ShowWorker
dot_id2num_store.clear();
net_conn_map.clear();
- fprintf(f, "digraph \"%s\" {\n", escape(module->name));
+ fprintf(f, "digraph \"%s\" {\n", escape(module->name.str()));
if (!notitle)
- fprintf(f, "label=\"%s\";\n", escape(module->name));
+ fprintf(f, "label=\"%s\";\n", escape(module->name.str()));
fprintf(f, "rankdir=\"LR\";\n");
fprintf(f, "remincross=true;\n");
std::set<std::string> all_sources, all_sinks;
std::map<std::string, std::string> wires_on_demand;
- for (auto &it : module->wires) {
+ for (auto &it : module->wires_) {
if (!design->selected_member(module->name, it.first))
continue;
const char *shape = "diamond";
@@ -316,14 +317,14 @@ struct ShowWorker
shape = "octagon";
if (it.first[0] == '\\') {
fprintf(f, "n%d [ shape=%s, label=\"%s\", %s, fontcolor=\"black\" ];\n",
- id2num(it.first), shape, findLabel(it.first),
+ id2num(it.first), shape, findLabel(it.first.str()),
nextColor(RTLIL::SigSpec(it.second), "color=\"black\"").c_str());
if (it.second->port_input)
all_sources.insert(stringf("n%d", id2num(it.first)));
else if (it.second->port_output)
all_sinks.insert(stringf("n%d", id2num(it.first)));
} else {
- wires_on_demand[stringf("n%d", id2num(it.first))] = it.first;
+ wires_on_demand[stringf("n%d", id2num(it.first))] = it.first.str();
}
}
@@ -340,38 +341,43 @@ struct ShowWorker
fprintf(f, "}\n");
}
- for (auto &it : module->cells)
+ for (auto &it : module->cells_)
{
if (!design->selected_member(module->name, it.first))
continue;
std::vector<RTLIL::IdString> in_ports, out_ports;
- for (auto &conn : it.second->connections) {
+ for (auto &conn : it.second->connections()) {
if (!ct.cell_output(it.second->type, conn.first))
in_ports.push_back(conn.first);
else
out_ports.push_back(conn.first);
}
+ std::sort(in_ports.begin(), in_ports.end(), RTLIL::sort_by_id_str());
+ std::sort(out_ports.begin(), out_ports.end(), RTLIL::sort_by_id_str());
+
std::string label_string = "{{";
for (auto &p : in_ports)
- label_string += stringf("<p%d> %s|", id2num(p), escape(p));
+ label_string += stringf("<p%d> %s%s|", id2num(p), escape(p.str()),
+ genSignedLabels && it.second->hasParam(p.str() + "_SIGNED") &&
+ it.second->getParam(p.str() + "_SIGNED").as_bool() ? "*" : "");
if (label_string[label_string.size()-1] == '|')
label_string = label_string.substr(0, label_string.size()-1);
- label_string += stringf("}|%s\\n%s|{", findLabel(it.first), escape(it.second->type));
+ label_string += stringf("}|%s\\n%s|{", findLabel(it.first.str()), escape(it.second->type.str()));
for (auto &p : out_ports)
- label_string += stringf("<p%d> %s|", id2num(p), escape(p));
+ label_string += stringf("<p%d> %s|", id2num(p), escape(p.str()));
if (label_string[label_string.size()-1] == '|')
label_string = label_string.substr(0, label_string.size()-1);
label_string += "}}";
std::string code;
- for (auto &conn : it.second->connections) {
+ for (auto &conn : it.second->connections()) {
code += gen_portbox(stringf("c%d:p%d", id2num(it.first), id2num(conn.first)),
conn.second, ct.cell_output(it.second->type, conn.first));
}
@@ -383,7 +389,7 @@ struct ShowWorker
else
#endif
fprintf(f, "c%d [ shape=record, label=\"%s\"%s ];\n%s",
- id2num(it.first), label_string.c_str(), findColor(it.first), code.c_str());
+ id2num(it.first), label_string.c_str(), findColor(it.first.str()), code.c_str());
}
for (auto &it : module->processes)
@@ -405,7 +411,7 @@ struct ShowWorker
code += gen_portbox("", sig, false, &node);
fprintf(f, "%s", code.c_str());
net_conn_map[node].out.insert(stringf("p%d", pidx));
- net_conn_map[node].bits = sig.width;
+ net_conn_map[node].bits = sig.size();
net_conn_map[node].color = nextColor(sig, net_conn_map[node].color);
}
@@ -414,25 +420,25 @@ struct ShowWorker
code += gen_portbox("", sig, true, &node);
fprintf(f, "%s", code.c_str());
net_conn_map[node].in.insert(stringf("p%d", pidx));
- net_conn_map[node].bits = sig.width;
+ net_conn_map[node].bits = sig.size();
net_conn_map[node].color = nextColor(sig, net_conn_map[node].color);
}
std::string proc_src = RTLIL::unescape_id(proc->name);
if (proc->attributes.count("\\src") > 0)
proc_src = proc->attributes.at("\\src").decode_string();
- fprintf(f, "p%d [shape=box, style=rounded, label=\"PROC %s\\n%s\"];\n", pidx, findLabel(proc->name), proc_src.c_str());
+ fprintf(f, "p%d [shape=box, style=rounded, label=\"PROC %s\\n%s\"];\n", pidx, findLabel(proc->name.str()), proc_src.c_str());
}
- for (auto &conn : module->connections)
+ for (auto &conn : module->connections())
{
bool found_lhs_wire = false;
- for (auto &c : conn.first.chunks) {
+ for (auto &c : conn.first.chunks()) {
if (c.wire == NULL || design->selected_member(module->name, c.wire->name))
found_lhs_wire = true;
}
bool found_rhs_wire = false;
- for (auto &c : conn.second.chunks) {
+ for (auto &c : conn.second.chunks()) {
if (c.wire == NULL || design->selected_member(module->name, c.wire->name))
found_rhs_wire = true;
}
@@ -446,11 +452,11 @@ struct ShowWorker
if (left_node[0] == 'x' && right_node[0] == 'x') {
currentColor = xorshift32(currentColor);
- fprintf(f, "%s:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", left_node.c_str(), right_node.c_str(), nextColor(conn).c_str(), widthLabel(conn.first.width).c_str());
+ fprintf(f, "%s:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", left_node.c_str(), right_node.c_str(), nextColor(conn).c_str(), widthLabel(conn.first.size()).c_str());
} else {
- net_conn_map[right_node].bits = conn.first.width;
+ net_conn_map[right_node].bits = conn.first.size();
net_conn_map[right_node].color = nextColor(conn, net_conn_map[right_node].color);
- net_conn_map[left_node].bits = conn.first.width;
+ net_conn_map[left_node].bits = conn.first.size();
net_conn_map[left_node].color = nextColor(conn, net_conn_map[left_node].color);
if (left_node[0] == 'x') {
net_conn_map[right_node].in.insert(left_node);
@@ -487,15 +493,15 @@ struct ShowWorker
fprintf(f, "%s:e -> %s:w [%s, %s];\n", it.first.c_str(), it2.c_str(), nextColor(it.second.color).c_str(), widthLabel(it.second.bits).c_str());
}
- fprintf(f, "};\n");
+ fprintf(f, "}\n");
}
- ShowWorker(FILE *f, RTLIL::Design *design, std::vector<RTLIL::Design*> &libs, uint32_t colorSeed,
- bool genWidthLabels, bool stretchIO, bool enumerateIds, bool abbreviateIds, bool notitle,
+ ShowWorker(FILE *f, RTLIL::Design *design, std::vector<RTLIL::Design*> &libs, uint32_t colorSeed, bool genWidthLabels,
+ bool genSignedLabels, bool stretchIO, bool enumerateIds, bool abbreviateIds, bool notitle,
const std::vector<std::pair<std::string, RTLIL::Selection>> &color_selections,
const std::vector<std::pair<std::string, RTLIL::Selection>> &label_selections) :
f(f), design(design), currentColor(colorSeed), genWidthLabels(genWidthLabels),
- stretchIO(stretchIO), enumerateIds(enumerateIds), abbreviateIds(abbreviateIds),
+ genSignedLabels(genSignedLabels), stretchIO(stretchIO), enumerateIds(enumerateIds), abbreviateIds(abbreviateIds),
notitle(notitle), color_selections(color_selections), label_selections(label_selections)
{
ct.setup_internals();
@@ -509,7 +515,7 @@ struct ShowWorker
design->optimize();
page_counter = 0;
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
module = mod_it.second;
if (!design->selected_module(module->name))
@@ -519,7 +525,7 @@ struct ShowWorker
log("Skipping blackbox module %s.\n", id2cstr(module->name));
continue;
} else
- if (module->cells.empty() && module->connections.empty() && module->processes.empty()) {
+ if (module->cells_.empty() && module->connections().empty() && module->processes.empty()) {
log("Skipping empty module %s.\n", id2cstr(module->name));
continue;
} else
@@ -575,6 +581,10 @@ struct ShowPass : public Pass {
log(" -width\n");
log(" annotate busses with a label indicating the width of the bus.\n");
log("\n");
+ log(" -signed\n");
+ log(" mark ports (A, B) that are declarted as signed (using the [AB]_SIGNED\n");
+ log(" cell parameter) with an asterisk next to the port name.\n");
+ log("\n");
log(" -stretch\n");
log(" stretch the graph so all inputs are on the left side and all outputs\n");
log(" (including inout ports) are on the right side.\n");
@@ -591,8 +601,8 @@ 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("When no <format> is specified, SVG is used. When no <format> and <viewer> is\n");
- log("specified, 'yosys-svgviewer' is used to display the schematic.\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.\n");
log("\n");
log("The generated output files are '~/.yosys_show.dot' and '~/.yosys_show.<format>',\n");
log("unless another prefix is specified using -prefix <prefix>.\n");
@@ -613,6 +623,7 @@ struct ShowPass : public Pass {
std::vector<RTLIL::Design*> libs;
uint32_t colorSeed = 0;
bool flag_width = false;
+ bool flag_signed = false;
bool flag_stretch = false;
bool flag_pause = false;
bool flag_enum = false;
@@ -655,6 +666,8 @@ struct ShowPass : public Pass {
}
if (arg == "-colors" && argidx+1 < args.size()) {
colorSeed = atoi(args[++argidx].c_str());
+ for (int i = 0; i < 100; i++)
+ colorSeed = ShowWorker::xorshift32(colorSeed);
continue;
}
if (arg == "-format" && argidx+1 < args.size()) {
@@ -665,6 +678,10 @@ struct ShowPass : public Pass {
flag_width= true;
continue;
}
+ if (arg == "-signed") {
+ flag_signed= true;
+ continue;
+ }
if (arg == "-stretch") {
flag_stretch= true;
continue;
@@ -693,10 +710,10 @@ struct ShowPass : public Pass {
if (format != "ps") {
int modcount = 0;
- for (auto &mod_it : design->modules) {
+ for (auto &mod_it : design->modules_) {
if (mod_it.second->get_bool_attribute("\\blackbox"))
continue;
- if (mod_it.second->cells.empty() && mod_it.second->connections.empty())
+ if (mod_it.second->cells_.empty() && mod_it.second->connections().empty())
continue;
if (design->selected_module(mod_it.first))
modcount++;
@@ -706,13 +723,13 @@ struct ShowPass : public Pass {
}
for (auto filename : libfiles) {
- FILE *f = fopen(filename.c_str(), "rt");
- if (f == NULL)
+ std::ifstream f;
+ f.open(filename.c_str());
+ if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design;
- Frontend::frontend_call(lib, f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
+ Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
libs.push_back(lib);
- fclose(f);
}
if (libs.size() > 0)
@@ -728,7 +745,7 @@ struct ShowPass : public Pass {
delete lib;
log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file.c_str());
}
- ShowWorker worker(f, design, libs, colorSeed, flag_width, flag_stretch, flag_enum, flag_abbeviate, flag_notitle, color_selections, label_selections);
+ ShowWorker worker(f, design, libs, colorSeed, flag_width, flag_signed, flag_stretch, flag_enum, flag_abbeviate, flag_notitle, color_selections, label_selections);
fclose(f);
for (auto lib : libs)
@@ -737,8 +754,8 @@ struct ShowPass : public Pass {
if (worker.page_counter == 0)
log_cmd_error("Nothing there to show.\n");
- if (format != "dot") {
- std::string cmd = stringf("dot -T%s -o '%s' '%s'", format.empty() ? "svg" : format.c_str(), out_file.c_str(), dot_file.c_str());
+ if (format != "dot" && !format.empty()) {
+ std::string cmd = stringf("dot -T%s -o '%s' '%s'", format.c_str(), out_file.c_str(), dot_file.c_str());
log("Exec: %s\n", cmd.c_str());
if (system(cmd.c_str()) != 0)
log_cmd_error("Shell command failed!\n");
@@ -751,13 +768,14 @@ struct ShowPass : public Pass {
log_cmd_error("Shell command failed!\n");
} else
if (format.empty()) {
- std::string cmd = stringf("fuser -s '%s' || '%s' '%s' &", out_file.c_str(), rewrite_yosys_exe("yosys-svgviewer").c_str(), out_file.c_str());
+ std::string cmd = stringf("fuser -s '%s' || xdot '%s' < '%s' &", dot_file.c_str(), dot_file.c_str(), dot_file.c_str());
log("Exec: %s\n", cmd.c_str());
if (system(cmd.c_str()) != 0)
log_cmd_error("Shell command failed!\n");
}
if (flag_pause) {
+ #ifdef YOSYS_ENABLE_READLINE
char *input = NULL;
while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != NULL) {
if (input[strspn(input, " \t\r\n")] == 0)
@@ -768,6 +786,9 @@ struct ShowPass : public Pass {
break;
}
}
+ #else
+ log_cmd_error("This version of yosys is built without readline support => 'show -pause' is not available.\n");
+ #endif
}
log_pop();
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index 6d920dbc5..d03aaf3b5 100644
--- a/passes/cmds/splice.cc
+++ b/passes/cmds/splice.cc
@@ -33,8 +33,8 @@ struct SpliceWorker
bool sel_by_wire;
bool sel_any_bit;
bool no_outputs;
- std::set<std::string> ports;
- std::set<std::string> no_ports;
+ std::set<RTLIL::IdString> ports;
+ std::set<RTLIL::IdString> no_ports;
CellTypes ct;
SigMap sigmap;
@@ -52,7 +52,7 @@ struct SpliceWorker
RTLIL::SigSpec get_sliced_signal(RTLIL::SigSpec sig)
{
- if (sig.width == 0 || sig.is_fully_const())
+ if (sig.size() == 0 || sig.is_fully_const())
return sig;
if (sliced_signals_cache.count(sig))
@@ -69,20 +69,16 @@ struct SpliceWorker
RTLIL::SigSpec new_sig = sig;
- if (sig_a.width != sig.width) {
- RTLIL::Cell *cell = new RTLIL::Cell;
- cell->name = NEW_ID;
- cell->type = "$slice";
+ if (sig_a.size() != sig.size()) {
+ RTLIL::Cell *cell = module->addCell(NEW_ID, "$slice");
cell->parameters["\\OFFSET"] = offset;
- cell->parameters["\\A_WIDTH"] = sig_a.width;
- cell->parameters["\\Y_WIDTH"] = sig.width;
- cell->connections["\\A"] = sig_a;
- cell->connections["\\Y"] = module->new_wire(sig.width, NEW_ID);
- new_sig = cell->connections["\\Y"];
- module->add(cell);
+ cell->parameters["\\A_WIDTH"] = sig_a.size();
+ cell->parameters["\\Y_WIDTH"] = sig.size();
+ cell->setPort("\\A", sig_a);
+ cell->setPort("\\Y", module->addWire(NEW_ID, sig.size()));
+ new_sig = cell->getPort("\\Y");
}
- new_sig.optimize();
sliced_signals_cache[sig] = new_sig;
return new_sig;
@@ -90,7 +86,7 @@ struct SpliceWorker
RTLIL::SigSpec get_spliced_signal(RTLIL::SigSpec sig)
{
- if (sig.width == 0 || sig.is_fully_const())
+ if (sig.size() == 0 || sig.is_fully_const())
return sig;
if (spliced_signals_cache.count(sig))
@@ -131,19 +127,15 @@ struct SpliceWorker
RTLIL::SigSpec new_sig = get_sliced_signal(chunks.front());
for (size_t i = 1; i < chunks.size(); i++) {
RTLIL::SigSpec sig2 = get_sliced_signal(chunks[i]);
- RTLIL::Cell *cell = new RTLIL::Cell;
- cell->name = NEW_ID;
- cell->type = "$concat";
- cell->parameters["\\A_WIDTH"] = new_sig.width;
- cell->parameters["\\B_WIDTH"] = sig2.width;
- cell->connections["\\A"] = new_sig;
- cell->connections["\\B"] = sig2;
- cell->connections["\\Y"] = module->new_wire(new_sig.width + sig2.width, NEW_ID);
- new_sig = cell->connections["\\Y"];
- module->add(cell);
+ RTLIL::Cell *cell = module->addCell(NEW_ID, "$concat");
+ cell->parameters["\\A_WIDTH"] = new_sig.size();
+ cell->parameters["\\B_WIDTH"] = sig2.size();
+ cell->setPort("\\A", new_sig);
+ cell->setPort("\\B", sig2);
+ cell->setPort("\\Y", module->addWire(NEW_ID, new_sig.size() + sig2.size()));
+ new_sig = cell->getPort("\\Y");
}
- new_sig.optimize();
spliced_signals_cache[sig] = new_sig;
log(" Created spliced signal: %s -> %s\n", log_signal(sig), log_signal(new_sig));
@@ -157,7 +149,7 @@ struct SpliceWorker
driven_bits.push_back(RTLIL::State::Sm);
driven_bits.push_back(RTLIL::State::Sm);
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (it.second->port_input) {
RTLIL::SigSpec sig = sigmap(it.second);
driven_chunks.insert(sig);
@@ -166,8 +158,8 @@ struct SpliceWorker
driven_bits.push_back(RTLIL::State::Sm);
}
- for (auto &it : module->cells)
- for (auto &conn : it.second->connections)
+ for (auto &it : module->cells_)
+ for (auto &conn : it.second->connections())
if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first)) {
RTLIL::SigSpec sig = sigmap(conn.second);
driven_chunks.insert(sig);
@@ -183,14 +175,14 @@ struct SpliceWorker
SigPool selected_bits;
if (!sel_by_cell)
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (design->selected(module, it.second))
selected_bits.add(sigmap(it.second));
- for (auto &it : module->cells) {
+ for (auto &it : module->cells_) {
if (!sel_by_wire && !design->selected(module, it.second))
continue;
- for (auto &conn : it.second->connections)
+ for (auto &conn : it.second->connections_)
if (ct.cell_input(it.second->type, conn.first)) {
if (ports.size() > 0 && !ports.count(conn.first))
continue;
@@ -211,7 +203,7 @@ struct SpliceWorker
std::vector<std::pair<RTLIL::Wire*, RTLIL::SigSpec>> rework_wires;
- for (auto &it : module->wires)
+ for (auto &it : module->wires_)
if (!no_outputs && it.second->port_output) {
if (!design->selected(module, it.second))
continue;
@@ -232,15 +224,15 @@ struct SpliceWorker
for (auto &it : rework_wires)
{
- module->wires.erase(it.first->name);
- RTLIL::Wire *new_port = new RTLIL::Wire(*it.first);
- it.first->name = NEW_ID;
+ RTLIL::IdString orig_name = it.first->name;
+ module->rename(it.first, NEW_ID);
+
+ RTLIL::Wire *new_port = module->addWire(orig_name, it.first);
it.first->port_id = 0;
it.first->port_input = false;
it.first->port_output = false;
- module->add(it.first);
- module->add(new_port);
- module->connections.push_back(RTLIL::SigSig(new_port, it.second));
+
+ module->connect(RTLIL::SigSig(new_port, it.second));
}
}
};
@@ -259,12 +251,12 @@ struct SplicePass : public Pass {
log("\n");
log(" -sel_by_cell\n");
log(" only select the cell ports to rewire by the cell. if the selection\n");
- log(" contains a cell, than all cell inputs are rewired, if neccessary.\n");
+ log(" contains a cell, than all cell inputs are rewired, if necessary.\n");
log("\n");
log(" -sel_by_wire\n");
log(" only select the cell ports to rewire by the wire. if the selection\n");
log(" contains a wire, than all cell ports driven by this wire are wired,\n");
- log(" if neccessary.\n");
+ log(" if necessary.\n");
log("\n");
log(" -sel_any_bit\n");
log(" it is sufficient if the driver of any bit of a cell port is selected.\n");
@@ -291,7 +283,7 @@ struct SplicePass : public Pass {
bool sel_by_wire = false;
bool sel_any_bit = false;
bool no_outputs = false;
- std::set<std::string> ports, no_ports;
+ std::set<RTLIL::IdString> ports, no_ports;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@@ -335,7 +327,7 @@ struct SplicePass : public Pass {
log_header("Executing SPLICE pass (creating cells for signal splicing).\n");
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
if (!design->selected(mod_it.second))
continue;
diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc
index da9ef43f9..344b03fc2 100644
--- a/passes/cmds/splitnets.cc
+++ b/passes/cmds/splitnets.cc
@@ -28,33 +28,28 @@ struct SplitnetsWorker
void append_wire(RTLIL::Module *module, RTLIL::Wire *wire, int offset, int width, std::string format)
{
- RTLIL::Wire *new_wire = new RTLIL::Wire;
-
- new_wire->port_id = wire->port_id;
- new_wire->port_input = wire->port_input;
- new_wire->port_output = wire->port_output;
- new_wire->name = wire->name;
- new_wire->width = width;
+ std::string new_wire_name = wire->name.str();
if (format.size() > 0)
- new_wire->name += format.substr(0, 1);
+ new_wire_name += format.substr(0, 1);
if (width > 1) {
- new_wire->name += stringf("%d", offset+width-1);
+ new_wire_name += stringf("%d", offset+width-1);
if (format.size() > 2)
- new_wire->name += format.substr(2, 1);
+ new_wire_name += format.substr(2, 1);
else
- new_wire->name += ":";
+ new_wire_name += ":";
}
- new_wire->name += stringf("%d", offset);
+ new_wire_name += stringf("%d", offset);
if (format.size() > 1)
- new_wire->name += format.substr(1, 1);
+ new_wire_name += format.substr(1, 1);
- while (module->count_id(new_wire->name) > 0)
- new_wire->name = new_wire->name + "_";
- module->add(new_wire);
+ RTLIL::Wire *new_wire = module->addWire(module->uniquify(new_wire_name), width);
+ new_wire->port_id = wire->port_id;
+ new_wire->port_input = wire->port_input;
+ new_wire->port_output = wire->port_output;
std::vector<RTLIL::SigBit> sigvec = RTLIL::SigSpec(new_wire).to_sigbit_vector();
splitmap[wire].insert(splitmap[wire].end(), sigvec.begin(), sigvec.end());
@@ -62,11 +57,9 @@ struct SplitnetsWorker
void operator()(RTLIL::SigSpec &sig)
{
- sig.expand();
- for (auto &c : sig.chunks)
- if (splitmap.count(c.wire) > 0)
- c = splitmap.at(c.wire).at(c.offset);
- sig.optimize();
+ for (auto &bit : sig)
+ if (splitmap.count(bit.wire) > 0)
+ bit = splitmap.at(bit.wire).at(bit.offset);
}
};
@@ -83,7 +76,7 @@ struct SplitnetsPass : public Pass {
log(" -format char1[char2[char3]]\n");
log(" the first char is inserted between the net name and the bit index, the\n");
log(" second char is appended to the netname. e.g. -format () creates net\n");
- log(" names like 'mysignal(42)'. the 3rd character is the range seperation\n");
+ log(" names like 'mysignal(42)'. the 3rd character is the range separation\n");
log(" character when creating multi-bit wires. the default is '[]:'.\n");
log("\n");
log(" -ports\n");
@@ -121,7 +114,7 @@ struct SplitnetsPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &mod_it : design->modules)
+ for (auto &mod_it : design->modules_)
{
RTLIL::Module *module = mod_it.second;
if (!design->selected(module))
@@ -135,16 +128,16 @@ struct SplitnetsPass : public Pass {
std::map<RTLIL::Wire*, std::set<int>> split_wires_at;
- for (auto &c : module->cells)
- for (auto &p : c.second->connections)
+ for (auto &c : module->cells_)
+ for (auto &p : c.second->connections())
{
if (!ct.cell_known(c.second->type))
continue;
if (!ct.cell_output(c.second->type, p.first))
continue;
- RTLIL::SigSpec sig = p.second.optimized();
- for (auto &chunk : sig.chunks) {
+ RTLIL::SigSpec sig = p.second;
+ for (auto &chunk : sig.chunks()) {
if (chunk.wire == NULL)
continue;
if (chunk.wire->port_id == 0 || flag_ports) {
@@ -167,9 +160,9 @@ struct SplitnetsPass : public Pass {
}
else
{
- for (auto &w : module->wires) {
+ for (auto &w : module->wires_) {
RTLIL::Wire *wire = w.second;
- if (wire->width > 1 && (wire->port_id == 0 || flag_ports))
+ if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, w.second))
worker.splitmap[wire] = std::vector<RTLIL::SigBit>();
}
@@ -180,10 +173,10 @@ struct SplitnetsPass : public Pass {
module->rewrite_sigspecs(worker);
- for (auto &it : worker.splitmap) {
- module->wires.erase(it.first->name);
- delete it.first;
- }
+ std::set<RTLIL::Wire*> delete_wires;
+ for (auto &it : worker.splitmap)
+ delete_wires.insert(it.first);
+ module->remove(delete_wires);
module->fixup_ports();
}
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 834770071..19cdaa621 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -63,13 +63,13 @@ namespace
#undef X
}
- statdata_t(RTLIL::Design *design, RTLIL::Module *mod)
+ statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode)
{
#define X(_name) _name = 0;
STAT_INT_MEMBERS
#undef X
- for (auto &it : mod->wires)
+ for (auto &it : mod->wires_)
{
if (!design->selected(mod, it.second))
continue;
@@ -90,11 +90,35 @@ namespace
num_memory_bits += it.second->width * it.second->size;
}
- for (auto &it : mod->cells) {
+ for (auto &it : mod->cells_)
+ {
if (!design->selected(mod, it.second))
continue;
+
+ RTLIL::IdString cell_type = it.second->type;
+
+ if (width_mode)
+ {
+ if (cell_type.in("$not", "$pos", "$neg",
+ "$logic_not", "$logic_and", "$logic_or",
+ "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
+ "$lut", "$and", "$or", "$xor", "$xnor",
+ "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
+ "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
+ "$add", "$sub", "$mul", "$div", "$mod", "$pow")) {
+ int width_a = it.second->hasPort("\\A") ? SIZE(it.second->getPort("\\A")) : 0;
+ int width_b = it.second->hasPort("\\B") ? SIZE(it.second->getPort("\\B")) : 0;
+ int width_y = it.second->hasPort("\\Y") ? SIZE(it.second->getPort("\\Y")) : 0;
+ cell_type = stringf("%s_%d", cell_type.c_str(), std::max<int>({width_a, width_b, width_y}));
+ }
+ else if (cell_type.in("$mux", "$pmux"))
+ cell_type = stringf("%s_%d", cell_type.c_str(), SIZE(it.second->getPort("\\Y")));
+ else if (cell_type.in("$sr", "$dff", "$dffsr", "$adff", "$dlatch", "$dlatchsr"))
+ cell_type = stringf("%s_%d", cell_type.c_str(), SIZE(it.second->getPort("\\Q")));
+ }
+
num_cells++;
- num_cells_by_type[it.second->type]++;
+ num_cells_by_type[cell_type]++;
}
for (auto &it : mod->processes) {
@@ -154,28 +178,37 @@ struct StatPass : public Pass {
log(" selected and a module has the 'top' attribute set, this module is used\n");
log(" default value for this option.\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");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
log_header("Printing statistics.\n");
+ bool width_mode = false;
RTLIL::Module *top_mod = NULL;
std::map<RTLIL::IdString, statdata_t> mod_stat;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
+ if (args[argidx] == "-width") {
+ width_mode = true;
+ continue;
+ }
if (args[argidx] == "-top" && argidx+1 < args.size()) {
- if (design->modules.count(RTLIL::escape_id(args[argidx+1])) == 0)
+ 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());
- top_mod = design->modules.at(RTLIL::escape_id(args[++argidx]));
+ top_mod = design->modules_.at(RTLIL::escape_id(args[++argidx]));
continue;
}
break;
}
extra_args(args, argidx, design);
- for (auto &it : design->modules)
+ for (auto &it : design->modules_)
{
if (!design->selected_module(it.first))
continue;
@@ -184,7 +217,7 @@ struct StatPass : public Pass {
if (it.second->get_bool_attribute("\\top"))
top_mod = it.second;
- statdata_t data(design, it.second);
+ statdata_t data(design, it.second, width_mode);
mod_stat[it.first] = data;
log("\n");
diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc
new file mode 100644
index 000000000..6f80ef72c
--- /dev/null
+++ b/passes/cmds/tee.cc
@@ -0,0 +1,88 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.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/rtlil.h"
+#include "kernel/log.h"
+
+struct TeePass : public Pass {
+ TeePass() : Pass("tee", "redirect command output to file") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" tee [-q] [-o logfile|-a logfile] cmd\n");
+ log("\n");
+ log("Execute the specified command, optionally writing the commands output to the\n");
+ 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("\n");
+ log(" -o logfile\n");
+ log(" Write output to this file, truncate if exists.\n");
+ log("\n");
+ log(" -a logfile\n");
+ log(" Write output to this file, append if exists.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ std::vector<FILE*> backup_log_files, files_to_close;
+ backup_log_files = log_files;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-q" && files_to_close.empty()) {
+ log_files.clear();
+ continue;
+ }
+ if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) {
+ const char *open_mode = args[argidx] == "-o" ? "w" : "a+";
+ FILE *f = fopen(args[++argidx].c_str(), open_mode);
+ if (f == NULL) {
+ for (auto cf : files_to_close)
+ fclose(cf);
+ log_cmd_error("Can't create file %s.\n", args[argidx].c_str());
+ }
+ log_files.push_back(f);
+ files_to_close.push_back(f);
+ continue;
+ }
+ break;
+ }
+
+ try {
+ std::vector<std::string> new_args(args.begin() + argidx, args.end());
+ Pass::call(design, new_args);
+ } catch (log_cmd_error_expection) {
+ for (auto cf : files_to_close)
+ fclose(cf);
+ log_files = backup_log_files;
+ throw log_cmd_error_expection();
+ }
+
+ for (auto cf : files_to_close)
+ fclose(cf);
+ log_files = backup_log_files;
+ }
+} TeePass;
+
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
new file mode 100644
index 000000000..09293a86b
--- /dev/null
+++ b/passes/cmds/trace.cc
@@ -0,0 +1,97 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.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"
+
+PRIVATE_NAMESPACE_BEGIN
+
+struct TraceMonitor : public RTLIL::Monitor
+{
+ virtual void notify_module_add(RTLIL::Module *module) OVERRIDE
+ {
+ log("#TRACE# Module add: %s\n", log_id(module));
+ }
+
+ virtual void notify_module_del(RTLIL::Module *module) OVERRIDE
+ {
+ log("#TRACE# Module delete: %s\n", log_id(module));
+ }
+
+ virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) OVERRIDE
+ {
+ log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", log_id(cell->module), log_id(cell), log_id(port), log_signal(sig), log_signal(old_sig));
+ }
+
+ virtual void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) OVERRIDE
+ {
+ log("#TRACE# Connection in module %s: %s = %s\n", log_id(module), log_signal(sigsig.first), log_signal(sigsig.second));
+ }
+
+ virtual void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) OVERRIDE
+ {
+ log("#TRACE# New connections in module %s:\n", log_id(module));
+ for (auto &sigsig : sigsig_vec)
+ log("## %s = %s\n", log_signal(sigsig.first), log_signal(sigsig.second));
+ }
+
+ virtual void notify_blackout(RTLIL::Module *module) OVERRIDE
+ {
+ log("#TRACE# Blackout in module %s:\n", log_id(module));
+ }
+};
+
+struct TracePass : public Pass {
+ TracePass() : Pass("trace", "redirect command output to file") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" trace cmd\n");
+ log("\n");
+ log("Execute the specified command, logging all changes the command performs on\n");
+ log("the design in real time.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // .. parse options ..
+ break;
+ }
+
+ TraceMonitor monitor;
+ design->monitors.insert(&monitor);
+
+ try {
+ std::vector<std::string> new_args(args.begin() + argidx, args.end());
+ Pass::call(design, new_args);
+ } catch (log_cmd_error_expection) {
+ design->monitors.erase(&monitor);
+ throw log_cmd_error_expection();
+ }
+
+ design->monitors.erase(&monitor);
+ }
+} TracePass;
+
+PRIVATE_NAMESPACE_END
+
diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc
new file mode 100644
index 000000000..813e215ba
--- /dev/null
+++ b/passes/cmds/write_file.cc
@@ -0,0 +1,76 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.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"
+
+struct WriteFileFrontend : public Frontend {
+ WriteFileFrontend() : Frontend("=write_file", "write a text to a file") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" write_file [options] output_file [input_file]\n");
+ log("\n");
+ log("Write the text fron the input file to the output file.\n");
+ log("\n");
+ log(" -a\n");
+ log(" Append to output file (instead of overwriting)\n");
+ log("\n");
+ log("\n");
+ log("Inside a script the input file can also can a here-document:\n");
+ log("\n");
+ log(" write_file hello.txt <<EOT\n");
+ log(" Hello World!\n");
+ log(" EOT\n");
+ log("\n");
+ }
+ virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*)
+ {
+ bool append_mode = false;
+ std::string output_filename;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-a") {
+ append_mode = true;
+ continue;
+ }
+ break;
+ }
+
+ if (argidx < args.size() && args[argidx].rfind("-", 0) != 0)
+ output_filename = args[argidx++];
+ else
+ log_cmd_error("Missing putput filename.\n");
+
+ extra_args(f, filename, args, argidx);
+
+ FILE *of = fopen(output_filename.c_str(), append_mode ? "a" : "w");
+ char buffer[64 * 1024];
+ size_t bytes;
+
+ while (0 < (bytes = f->readsome(buffer, sizeof(buffer))))
+ fwrite(buffer, bytes, 1, of);
+
+ fclose(of);
+ }
+} WriteFileFrontend;
+