summaryrefslogtreecommitdiff
path: root/passes/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'passes/cmds')
-rw-r--r--passes/cmds/Makefile.inc4
-rw-r--r--passes/cmds/add.cc4
-rw-r--r--passes/cmds/blackbox.cc81
-rw-r--r--passes/cmds/check.cc89
-rw-r--r--passes/cmds/chformal.cc282
-rw-r--r--passes/cmds/chtype.cc83
-rw-r--r--passes/cmds/connect.cc4
-rw-r--r--passes/cmds/connwrappers.cc6
-rw-r--r--passes/cmds/copy.cc4
-rw-r--r--passes/cmds/cover.cc6
-rw-r--r--passes/cmds/delete.cc4
-rw-r--r--passes/cmds/design.cc142
-rw-r--r--passes/cmds/edgetypes.cc4
-rw-r--r--passes/cmds/logcmd.cc4
-rw-r--r--passes/cmds/ltp.cc185
-rw-r--r--passes/cmds/plugin.cc4
-rw-r--r--passes/cmds/qwp.cc5
-rw-r--r--passes/cmds/rename.cc4
-rw-r--r--passes/cmds/scatter.cc4
-rw-r--r--passes/cmds/scc.cc78
-rw-r--r--passes/cmds/select.cc59
-rw-r--r--passes/cmds/setattr.cc12
-rw-r--r--passes/cmds/setundef.cc263
-rw-r--r--passes/cmds/show.cc36
-rw-r--r--passes/cmds/splice.cc4
-rw-r--r--passes/cmds/splitnets.cc14
-rw-r--r--passes/cmds/stat.cc15
-rw-r--r--passes/cmds/tee.cc5
-rw-r--r--passes/cmds/torder.cc4
-rw-r--r--passes/cmds/trace.cc17
-rw-r--r--passes/cmds/write_file.cc5
31 files changed, 1275 insertions, 156 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 01ada773..44a83b2b 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -25,4 +25,8 @@ OBJS += passes/cmds/plugin.o
OBJS += passes/cmds/check.o
OBJS += passes/cmds/qwp.o
OBJS += passes/cmds/edgetypes.o
+OBJS += passes/cmds/chformal.o
+OBJS += passes/cmds/chtype.o
+OBJS += passes/cmds/blackbox.o
+OBJS += passes/cmds/ltp.o
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index e698926f..cfccca96 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -83,7 +83,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
struct AddPass : public Pass {
AddPass() : Pass("add", "add objects to the design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -106,7 +106,7 @@ struct AddPass : public Pass {
log("selected modules.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string command;
std::string arg_name;
diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc
new file mode 100644
index 00000000..6094f8f1
--- /dev/null
+++ b/passes/cmds/blackbox.cc
@@ -0,0 +1,81 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct BlackboxPass : public Pass {
+ BlackboxPass() : Pass("blackbox", "change type of cells in the design") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" blackbox [options] [selection]\n");
+ log("\n");
+ log("Convert modules into blackbox modules (remove contents and set the blackbox\n");
+ log("module attribute).\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-???") {
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_whole_modules_warn())
+ {
+ pool<Cell*> remove_cells;
+ pool<Wire*> remove_wires;
+
+ for (auto cell : module->cells())
+ remove_cells.insert(cell);
+
+ for (auto wire : module->wires())
+ if (wire->port_id == 0)
+ remove_wires.insert(wire);
+
+ for (auto it = module->memories.begin(); it != module->memories.end(); ++it)
+ delete it->second;
+ module->memories.clear();
+
+ for (auto it = module->processes.begin(); it != module->processes.end(); ++it)
+ delete it->second;
+ module->processes.clear();
+
+ module->new_connections(std::vector<RTLIL::SigSig>());
+
+ for (auto cell : remove_cells)
+ module->remove(cell);
+
+ module->remove(remove_wires);
+
+ module->set_bool_attribute("\\blackbox");
+ }
+ }
+} BlackboxPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index b3622cb1..64697c13 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct CheckPass : public Pass {
CheckPass() : Pass("check", "check for obvious problems in the design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -44,14 +44,18 @@ struct CheckPass : public Pass {
log("When called with -noinit then this command also checks for wires which have\n");
log("the 'init' attribute set.\n");
log("\n");
+ log("When called with -initdrv then this command also checks for wires which have\n");
+ log("the 'init' attribute set and aren't driven by a FF cell type.\n");
+ log("\n");
log("When called with -assert then the command will produce an error if any\n");
log("problems are found in the current design.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
int counter = 0;
bool noinit = false;
+ bool initdrv = false;
bool assert_mode = false;
size_t argidx;
@@ -60,6 +64,10 @@ struct CheckPass : public Pass {
noinit = true;
continue;
}
+ if (args[argidx] == "-initdrv") {
+ initdrv = true;
+ continue;
+ }
if (args[argidx] == "-assert") {
assert_mode = true;
continue;
@@ -70,6 +78,49 @@ struct CheckPass : public Pass {
log_header(design, "Executing CHECK pass (checking for obvious problems).\n");
+ pool<IdString> fftypes;
+ fftypes.insert("$sr");
+ fftypes.insert("$ff");
+ fftypes.insert("$dff");
+ fftypes.insert("$dffe");
+ fftypes.insert("$dffsr");
+ fftypes.insert("$adff");
+ fftypes.insert("$dlatch");
+ fftypes.insert("$dlatchsr");
+ fftypes.insert("$_DFFE_NN_");
+ fftypes.insert("$_DFFE_NP_");
+ fftypes.insert("$_DFFE_PN_");
+ fftypes.insert("$_DFFE_PP_");
+ fftypes.insert("$_DFFSR_NNN_");
+ fftypes.insert("$_DFFSR_NNP_");
+ fftypes.insert("$_DFFSR_NPN_");
+ fftypes.insert("$_DFFSR_NPP_");
+ fftypes.insert("$_DFFSR_PNN_");
+ fftypes.insert("$_DFFSR_PNP_");
+ fftypes.insert("$_DFFSR_PPN_");
+ fftypes.insert("$_DFFSR_PPP_");
+ fftypes.insert("$_DFF_NN0_");
+ fftypes.insert("$_DFF_NN1_");
+ fftypes.insert("$_DFF_NP0_");
+ fftypes.insert("$_DFF_NP1_");
+ fftypes.insert("$_DFF_N_");
+ fftypes.insert("$_DFF_PN0_");
+ fftypes.insert("$_DFF_PN1_");
+ fftypes.insert("$_DFF_PP0_");
+ fftypes.insert("$_DFF_PP1_");
+ fftypes.insert("$_DFF_P_");
+ fftypes.insert("$_DLATCHSR_NNN_");
+ fftypes.insert("$_DLATCHSR_NNP_");
+ fftypes.insert("$_DLATCHSR_NPN_");
+ fftypes.insert("$_DLATCHSR_NPP_");
+ fftypes.insert("$_DLATCHSR_PNN_");
+ fftypes.insert("$_DLATCHSR_PNP_");
+ fftypes.insert("$_DLATCHSR_PPN_");
+ fftypes.insert("$_DLATCHSR_PPP_");
+ fftypes.insert("$_DLATCH_N_");
+ fftypes.insert("$_DLATCH_P_");
+ fftypes.insert("$_FF_");
+
for (auto module : design->selected_whole_modules_warn())
{
if (module->has_processes_warn())
@@ -109,6 +160,8 @@ struct CheckPass : public Pass {
if (bit.wire) wire_drivers_count[bit]++;
}
+ pool<SigBit> init_bits;
+
for (auto wire : module->wires()) {
if (wire->port_input) {
SigSpec sig = sigmap(wire);
@@ -121,9 +174,15 @@ struct CheckPass : public Pass {
if (wire->port_input && !wire->port_output)
for (auto bit : sigmap(wire))
if (bit.wire) wire_drivers_count[bit]++;
- if (noinit && wire->attributes.count("\\init")) {
- log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", log_id(module), log_id(wire));
- counter++;
+ if (wire->attributes.count("\\init")) {
+ Const initval = wire->attributes.at("\\init");
+ for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++)
+ if (initval[i] == State::S0 || initval[i] == State::S1)
+ init_bits.insert(sigmap(SigBit(wire, i)));
+ if (noinit) {
+ log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", log_id(module), log_id(wire));
+ counter++;
+ }
}
}
@@ -150,6 +209,26 @@ struct CheckPass : public Pass {
log_warning("%s", message.c_str());
counter++;
}
+
+ if (initdrv)
+ {
+ for (auto cell : module->cells())
+ {
+ if (fftypes.count(cell->type) == 0)
+ continue;
+
+ for (auto bit : sigmap(cell->getPort("\\Q")))
+ init_bits.erase(bit);
+ }
+
+ SigSpec init_sig(init_bits);
+ init_sig.sort_and_unify();
+
+ for (auto chunk : init_sig.chunks()) {
+ log_warning("Wire %s.%s has 'init' attribute and is not driven by an FF cell.\n", log_id(module), log_signal(chunk));
+ counter++;
+ }
+ }
}
log("found and reported %d problems.\n", counter);
diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc
new file mode 100644
index 00000000..522758ea
--- /dev/null
+++ b/passes/cmds/chformal.cc
@@ -0,0 +1,282 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct ChformalPass : public Pass {
+ ChformalPass() : Pass("chformal", "change formal constraints of the design") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" chformal [types] [mode] [options] [selection]\n");
+ log("\n");
+ log("Make changes to the formal constraints of the design. The [types] options\n");
+ log("the type of constraint to operate on. If none of the folling options is given,\n");
+ log("the command will operate on all constraint types:\n");
+ log("\n");
+ log(" -assert $assert cells, representing assert(...) constraints\n");
+ log(" -assume $assume cells, representing assume(...) constraints\n");
+ log(" -live $live cells, representing assert(s_eventually ...)\n");
+ log(" -fair $fair cells, representing assume(s_eventually ...)\n");
+ log(" -cover $cover cells, representing cover() statements\n");
+ log("\n");
+ log("Exactly one of the following modes must be specified:\n");
+ log("\n");
+ log(" -remove\n");
+ log(" remove the cells and thus constraints from the design\n");
+ log("\n");
+ log(" -early\n");
+ log(" bypass FFs that only delay the activation of a constraint\n");
+ log("\n");
+ log(" -delay <N>\n");
+ log(" delay activation of the constraint by <N> clock cycles\n");
+ log("\n");
+ log(" -skip <N>\n");
+ log(" ignore activation of the constraint in the first <N> clock cycles\n");
+ log("\n");
+ log(" -assert2assume\n");
+ log(" -assume2assert\n");
+ log(" -live2fair\n");
+ log(" -fair2live\n");
+ log(" change the roles of cells as indicated. this options can be combined\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ bool assert2assume = false;
+ bool assume2assert = false;
+ bool live2fair = false;
+ bool fair2live = false;
+
+ pool<IdString> constr_types;
+ char mode = 0;
+ int mode_arg = 0;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-assert") {
+ constr_types.insert("$assert");
+ continue;
+ }
+ if (args[argidx] == "-assume") {
+ constr_types.insert("$assume");
+ continue;
+ }
+ if (args[argidx] == "-live") {
+ constr_types.insert("$live");
+ continue;
+ }
+ if (args[argidx] == "-fair") {
+ constr_types.insert("$fair");
+ continue;
+ }
+ if (args[argidx] == "-cover") {
+ constr_types.insert("$cover");
+ continue;
+ }
+ if (mode == 0 && args[argidx] == "-remove") {
+ mode = 'r';
+ continue;
+ }
+ if (mode == 0 && args[argidx] == "-early") {
+ mode = 'e';
+ continue;
+ }
+ if (mode == 0 && args[argidx] == "-delay" && argidx+1 < args.size()) {
+ mode = 'd';
+ mode_arg = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if (mode == 0 && args[argidx] == "-skip" && argidx+1 < args.size()) {
+ mode = 's';
+ mode_arg = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if ((mode == 0 || mode == 'c') && args[argidx] == "-assert2assume") {
+ assert2assume = true;
+ mode = 'c';
+ continue;
+ }
+ if ((mode == 0 || mode == 'c') && args[argidx] == "-assume2assert") {
+ assume2assert = true;
+ mode = 'c';
+ continue;
+ }
+ if ((mode == 0 || mode == 'c') && args[argidx] == "-live2fair") {
+ live2fair = true;
+ mode = 'c';
+ continue;
+ }
+ if ((mode == 0 || mode == 'c') && args[argidx] == "-fair2live") {
+ fair2live = true;
+ mode = 'c';
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (constr_types.empty()) {
+ constr_types.insert("$assert");
+ constr_types.insert("$assume");
+ constr_types.insert("$live");
+ constr_types.insert("$fair");
+ constr_types.insert("$cover");
+ }
+
+ if (mode == 0)
+ log_cmd_error("Mode option is missing.\n");
+
+ for (auto module : design->selected_modules())
+ {
+ vector<Cell*> constr_cells;
+
+ for (auto cell : module->selected_cells())
+ if (constr_types.count(cell->type))
+ constr_cells.push_back(cell);
+
+ if (mode == 'r')
+ {
+ for (auto cell : constr_cells)
+ module->remove(cell);
+ }
+ else
+ if (mode == 'e')
+ {
+ SigMap sigmap(module);
+ dict<SigBit, pair<SigBit, pair<SigBit, bool>>> ffmap;
+ pool<SigBit> init_zero, init_one;
+
+ for (auto wire : module->wires())
+ {
+ if (wire->attributes.count("\\init") == 0)
+ continue;
+
+ SigSpec initsig = sigmap(wire);
+ Const initval = wire->attributes.at("\\init");
+
+ for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) {
+ if (initval[i] == State::S0)
+ init_zero.insert(initsig[i]);
+ if (initval[i] == State::S1)
+ init_one.insert(initsig[i]);
+ }
+ }
+
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "$ff") {
+ SigSpec D = sigmap(cell->getPort("\\D"));
+ SigSpec Q = sigmap(cell->getPort("\\Q"));
+ for (int i = 0; i < GetSize(D); i++)
+ ffmap[Q[i]] = make_pair(D[i], make_pair(State::Sm, false));
+ }
+ if (cell->type == "$dff") {
+ SigSpec D = sigmap(cell->getPort("\\D"));
+ SigSpec Q = sigmap(cell->getPort("\\Q"));
+ SigSpec C = sigmap(cell->getPort("\\CLK"));
+ bool clockpol = cell->getParam("\\CLK_POLARITY").as_bool();
+ for (int i = 0; i < GetSize(D); i++)
+ ffmap[Q[i]] = make_pair(D[i], make_pair(C, clockpol));
+ }
+ }
+
+ for (auto cell : constr_cells)
+ while (true)
+ {
+ SigSpec A = sigmap(cell->getPort("\\A"));
+ SigSpec EN = sigmap(cell->getPort("\\EN"));
+
+ if (ffmap.count(A) == 0 || ffmap.count(EN) == 0)
+ break;
+
+ if (!init_zero.count(EN)) {
+ if (cell->type == "$cover") break;
+ if (cell->type.in("$assert", "$assume") && !init_one.count(A)) break;
+ }
+
+ const auto &A_map = ffmap.at(A);
+ const auto &EN_map = ffmap.at(EN);
+
+ if (A_map.second != EN_map.second)
+ break;
+
+ cell->setPort("\\A", A_map.first);
+ cell->setPort("\\EN", EN_map.first);
+ }
+ }
+ else
+ if (mode == 'd')
+ {
+ for (auto cell : constr_cells)
+ for (int i = 0; i < mode_arg; i++)
+ {
+ SigSpec orig_a = cell->getPort("\\A");
+ SigSpec orig_en = cell->getPort("\\EN");
+
+ Wire *new_a = module->addWire(NEW_ID);
+ Wire *new_en = module->addWire(NEW_ID);
+ new_en->attributes["\\init"] = State::S0;
+
+ module->addFf(NEW_ID, orig_a, new_a);
+ module->addFf(NEW_ID, orig_en, new_en);
+
+ cell->setPort("\\A", new_a);
+ cell->setPort("\\EN", new_en);
+ }
+ }
+ else
+ if (mode == 's')
+ {
+ SigSpec en = State::S1;
+
+ for (int i = 0; i < mode_arg; i++) {
+ Wire *w = module->addWire(NEW_ID);
+ w->attributes["\\init"] = State::S0;
+ module->addFf(NEW_ID, en, w);
+ en = w;
+ }
+
+ for (auto cell : constr_cells)
+ cell->setPort("\\EN", module->LogicAnd(NEW_ID, en, cell->getPort("\\EN")));
+ }
+ else
+ if (mode == 'c')
+ {
+ for (auto cell : constr_cells)
+ if (assert2assume && cell->type == "$assert")
+ cell->type = "$assume";
+ else if (assume2assert && cell->type == "$assume")
+ cell->type = "$assert";
+ else if (live2fair && cell->type == "$live")
+ cell->type = "$fair";
+ else if (fair2live && cell->type == "$fair")
+ cell->type = "$live";
+ }
+ }
+ }
+} ChformalPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc
new file mode 100644
index 00000000..979aeadd
--- /dev/null
+++ b/passes/cmds/chtype.cc
@@ -0,0 +1,83 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct ChtypePass : public Pass {
+ ChtypePass() : Pass("chtype", "change type of cells in the design") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" chtype [options] [selection]\n");
+ log("\n");
+ log("Change the types of cells in the design.\n");
+ log("\n");
+ log(" -set <type>\n");
+ log(" set the cell type to the given type\n");
+ log("\n");
+ log(" -map <old_type> <new_type>\n");
+ log(" change cells types that match <old_type> to <new_type>\n");
+ log("\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ IdString set_type;
+ dict<IdString, IdString> map_types;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (set_type == IdString() && args[argidx] == "-set" && argidx+1 < args.size()) {
+ set_type = RTLIL::escape_id(args[++argidx]);
+ continue;
+ }
+ if (args[argidx] == "-map" && argidx+2 < args.size()) {
+ IdString old_type = RTLIL::escape_id(args[++argidx]);
+ IdString new_type = RTLIL::escape_id(args[++argidx]);
+ map_types[old_type] = new_type;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ {
+ for (auto cell : module->selected_cells())
+ {
+ if (map_types.count(cell->type)) {
+ cell->type = map_types.at(cell->type);
+ continue;
+ }
+
+ if (set_type != IdString()) {
+ cell->type = set_type;
+ continue;
+ }
+ }
+ }
+ }
+} ChtypePass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc
index 52611cf4..d480b79a 100644
--- a/passes/cmds/connect.cc
+++ b/passes/cmds/connect.cc
@@ -43,7 +43,7 @@ static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap &
struct ConnectPass : public Pass {
ConnectPass() : Pass("connect", "create or remove connections") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -75,7 +75,7 @@ struct ConnectPass : public Pass {
log("This command does not operate on module with processes.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
RTLIL::Module *module = NULL;
for (auto &it : design->modules_) {
diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc
index c9ab226d..5a15cbba 100644
--- a/passes/cmds/connwrappers.cc
+++ b/passes/cmds/connwrappers.cc
@@ -149,8 +149,8 @@ struct ConnwrappersWorker
};
struct ConnwrappersPass : public Pass {
- ConnwrappersPass() : Pass("connwrappers", "replace undef values with defined constants") { }
- virtual void help()
+ ConnwrappersPass() : Pass("connwrappers", "match width of input-output port pairs") { }
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -172,7 +172,7 @@ struct ConnwrappersPass : public Pass {
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)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
ConnwrappersWorker worker;
diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc
index fb863512..acd2dba5 100644
--- a/passes/cmds/copy.cc
+++ b/passes/cmds/copy.cc
@@ -26,7 +26,7 @@ PRIVATE_NAMESPACE_BEGIN
struct CopyPass : public Pass {
CopyPass() : Pass("copy", "copy modules in the design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -36,7 +36,7 @@ struct CopyPass : public Pass {
log("by this command.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
if (args.size() != 3)
log_cmd_error("Invalid number of arguments!\n");
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
index 1475475c..0ec74767 100644
--- a/passes/cmds/cover.cc
+++ b/passes/cmds/cover.cc
@@ -35,7 +35,7 @@ PRIVATE_NAMESPACE_BEGIN
struct CoverPass : public Pass {
CoverPass() : Pass("cover", "print code coverage counters") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -83,7 +83,7 @@ struct CoverPass : public Pass {
log("Coverage counters are only available in Yosys for Linux.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<FILE*> out_files;
std::vector<std::string> patterns;
@@ -128,7 +128,7 @@ struct CoverPass : public Pass {
log("\n");
}
-#if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
+#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
for (auto &it : get_coverage_data()) {
if (!patterns.empty()) {
for (auto &p : patterns)
diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc
index 6d51d30e..f8d91ea4 100644
--- a/passes/cmds/delete.cc
+++ b/passes/cmds/delete.cc
@@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
struct DeletePass : public Pass {
DeletePass() : Pass("delete", "delete objects in the design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -40,7 +40,7 @@ struct DeletePass : public Pass {
log("selected wires, thus 'deleting' module ports.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool flag_input = false;
bool flag_output = false;
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index e900e7b9..172addcc 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -17,10 +17,8 @@
*
*/
-#include "kernel/register.h"
-#include "kernel/celltypes.h"
-#include "kernel/rtlil.h"
-#include "kernel/log.h"
+#include "kernel/yosys.h"
+#include "frontends/ast/ast.h"
YOSYS_NAMESPACE_BEGIN
@@ -29,7 +27,7 @@ std::vector<RTLIL::Design*> pushed_designs;
struct DesignPass : public Pass {
DesignPass() : Pass("design", "save, restore and reset current design") { }
- virtual ~DesignPass() {
+ ~DesignPass() YS_OVERRIDE {
for (auto &it : saved_designs)
delete it.second;
saved_designs.clear();
@@ -37,7 +35,7 @@ struct DesignPass : public Pass {
delete it;
pushed_designs.clear();
}
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -82,13 +80,28 @@ struct DesignPass : public Pass {
log("\n");
log("Copy modules from the current design into the specified one.\n");
log("\n");
+ log("\n");
+ log(" design -import <name> [-as <new_top_name>] [selection]\n");
+ log("\n");
+ log("Import the specified design into the current design. The source design must\n");
+ log("either have a selected top module or the selection must contain exactly one\n");
+ log("module that is then used as top module for this command.\n");
+ log("\n");
+ log("\n");
+ log(" design -reset-vlog\n");
+ log("\n");
+ log("The Verilog front-end remembers defined macros and top-level declarations\n");
+ log("between calls to 'read_verilog'. This command resets this memory.\n");
+ log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool got_mode = false;
bool reset_mode = false;
+ bool reset_vlog_mode = false;
bool push_mode = false;
bool pop_mode = false;
+ bool import_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;
@@ -102,6 +115,11 @@ struct DesignPass : public Pass {
reset_mode = true;
continue;
}
+ if (!got_mode && args[argidx] == "-reset-vlog") {
+ got_mode = true;
+ reset_vlog_mode = true;
+ continue;
+ }
if (!got_mode && args[argidx] == "-push") {
got_mode = true;
push_mode = true;
@@ -146,8 +164,17 @@ struct DesignPass : public Pass {
copy_from_design = design;
continue;
}
- if (copy_from_design != NULL && args[argidx] == "-as" && argidx+1 < args.size()) {
+ if (!got_mode && args[argidx] == "-import" && argidx+1 < args.size()) {
got_mode = true;
+ import_mode = true;
+ if (saved_designs.count(args[++argidx]) == 0)
+ log_cmd_error("No saved design '%s' found!\n", args[argidx].c_str());
+ copy_from_design = saved_designs.at(args[argidx]);
+ copy_to_design = design;
+ as_name = args[argidx];
+ continue;
+ }
+ if (copy_from_design != NULL && args[argidx] == "-as" && argidx+1 < args.size()) {
as_name = args[++argidx];
continue;
}
@@ -156,10 +183,10 @@ struct DesignPass : public Pass {
if (copy_from_design != NULL)
{
- if (copy_from_design != design && argidx == args.size())
+ if (copy_from_design != design && argidx == args.size() && !import_mode)
cmd_error(args, argidx, "Missing selection.");
- RTLIL::Selection sel = design->selection_stack.back();
+ RTLIL::Selection sel;
if (argidx != args.size()) {
handle_extra_select_args(this, args, argidx, args.size(), copy_from_design);
sel = copy_from_design->selection_stack.back();
@@ -175,6 +202,17 @@ struct DesignPass : public Pass {
if (sel.selected_module(it.first))
log_cmd_error("Module %s is only partly selected.\n", RTLIL::id2cstr(it.first));
}
+
+ if (import_mode) {
+ for (auto module : copy_src_modules)
+ {
+ if (module->get_bool_attribute("\\top")) {
+ copy_src_modules.clear();
+ copy_src_modules.push_back(module);
+ break;
+ }
+ }
+ }
}
extra_args(args, argidx, design, false);
@@ -185,6 +223,68 @@ struct DesignPass : public Pass {
if (pop_mode && pushed_designs.empty())
log_cmd_error("No pushed designs.\n");
+ if (import_mode)
+ {
+ std::string prefix = RTLIL::escape_id(as_name);
+
+ pool<Module*> queue;
+ dict<IdString, IdString> done;
+
+ if (copy_to_design->modules_.count(prefix))
+ delete copy_to_design->modules_.at(prefix);
+
+ if (GetSize(copy_src_modules) != 1)
+ log_cmd_error("No top module found in source design.\n");
+
+ for (auto mod : copy_src_modules)
+ {
+ log("Importing %s as %s.\n", log_id(mod), log_id(prefix));
+
+ copy_to_design->modules_[prefix] = mod->clone();
+ copy_to_design->modules_[prefix]->name = prefix;
+ copy_to_design->modules_[prefix]->design = copy_to_design;
+ copy_to_design->modules_[prefix]->attributes.erase("\\top");
+
+ queue.insert(copy_to_design->modules_[prefix]);
+ done[mod->name] = prefix;
+ }
+
+ while (!queue.empty())
+ {
+ pool<Module*> old_queue;
+ old_queue.swap(queue);
+
+ for (auto mod : old_queue)
+ for (auto cell : mod->cells())
+ {
+ Module *fmod = copy_from_design->module(cell->type);
+
+ if (fmod == nullptr)
+ continue;
+
+ if (done.count(cell->type) == 0)
+ {
+ std::string trg_name = prefix + "." + (cell->type.c_str() + (*cell->type.c_str() == '\\'));
+
+ log("Importing %s as %s.\n", log_id(fmod), log_id(trg_name));
+
+ if (copy_to_design->modules_.count(trg_name))
+ delete copy_to_design->modules_.at(trg_name);
+
+ copy_to_design->modules_[trg_name] = fmod->clone();
+ copy_to_design->modules_[trg_name]->name = trg_name;
+ copy_to_design->modules_[trg_name]->design = copy_to_design;
+ copy_to_design->modules_[trg_name]->attributes.erase("\\top");
+
+ queue.insert(copy_to_design->modules_[trg_name]);
+ done[cell->type] = trg_name;
+ }
+
+ cell->type = done.at(cell->type);
+ }
+ }
+ }
+ else
if (copy_to_design != NULL)
{
if (!as_name.empty() && copy_src_modules.size() > 1)
@@ -196,6 +296,7 @@ struct DesignPass : public Pass {
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;
@@ -235,19 +336,34 @@ struct DesignPass : public Pass {
design->selection_stack.push_back(RTLIL::Selection());
}
+ if (reset_mode || reset_vlog_mode || !load_name.empty() || push_mode || pop_mode)
+ {
+ for (auto node : design->verilog_packages)
+ delete node;
+ design->verilog_packages.clear();
+
+ for (auto node : design->verilog_globals)
+ delete node;
+ design->verilog_globals.clear();
+
+ design->verilog_defines.clear();
+ }
+
if (!load_name.empty() || pop_mode)
{
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->add(it.second->clone());
design->selection_stack = saved_design->selection_stack;
design->selection_vars = saved_design->selection_vars;
design->selected_active_module = saved_design->selected_active_module;
+
+ if (pop_mode) {
+ delete saved_design;
+ pushed_designs.pop_back();
+ }
}
}
} DesignPass;
diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc
index 7b75a009..58ed6457 100644
--- a/passes/cmds/edgetypes.cc
+++ b/passes/cmds/edgetypes.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct EdgetypePass : public Pass {
EdgetypePass() : Pass("edgetypes", "list all types of edges in selection") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -35,7 +35,7 @@ struct EdgetypePass : public Pass {
log("is a 4-tuple of source and sink cell type and port name.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc
index 85386f3d..522e1089 100644
--- a/passes/cmds/logcmd.cc
+++ b/passes/cmds/logcmd.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct LogPass : public Pass {
LogPass() : Pass("log", "print text and log files") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -52,7 +52,7 @@ struct LogPass : public Pass {
log(" do not append a newline\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
{
size_t argidx;
bool to_stdout = false;
diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc
new file mode 100644
index 00000000..05701710
--- /dev/null
+++ b/passes/cmds/ltp.cc
@@ -0,0 +1,185 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/celltypes.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct LtpWorker
+{
+ RTLIL::Design *design;
+ RTLIL::Module *module;
+ SigMap sigmap;
+
+ dict<SigBit, tuple<int, SigBit, Cell*>> bits;
+ dict<SigBit, dict<SigBit, Cell*>> bit2bits;
+ dict<SigBit, tuple<SigBit, Cell*>> bit2ff;
+
+ int maxlvl;
+ SigBit maxbit;
+ pool<SigBit> busy;
+
+ LtpWorker(RTLIL::Module *module, bool noff) : design(module->design), module(module), sigmap(module)
+ {
+ CellTypes ff_celltypes;
+
+ if (noff) {
+ ff_celltypes.setup_internals_mem();
+ ff_celltypes.setup_stdcells_mem();
+ }
+
+ for (auto wire : module->selected_wires())
+ for (auto bit : sigmap(wire))
+ bits[bit] = tuple<int, SigBit, Cell*>(-1, State::Sx, nullptr);
+
+ for (auto cell : module->selected_cells())
+ {
+ pool<SigBit> src_bits, dst_bits;
+
+ for (auto &conn : cell->connections())
+ for (auto bit : sigmap(conn.second)) {
+ if (cell->input(conn.first))
+ src_bits.insert(bit);
+ if (cell->output(conn.first))
+ dst_bits.insert(bit);
+ }
+
+ if (noff && ff_celltypes.cell_known(cell->type)) {
+ for (auto s : src_bits)
+ for (auto d : dst_bits) {
+ bit2ff[s] = tuple<SigBit, Cell*>(d, cell);
+ break;
+ }
+ continue;
+ }
+
+ for (auto s : src_bits)
+ for (auto d : dst_bits)
+ bit2bits[s][d] = cell;
+ }
+
+ maxlvl = -1;
+ maxbit = State::Sx;
+ }
+
+ void runner(SigBit bit, int level, SigBit from, Cell *via)
+ {
+ auto &bitinfo = bits.at(bit);
+
+ if (get<0>(bitinfo) >= level)
+ return;
+
+ if (busy.count(bit) > 0) {
+ log_warning("Detected loop at %s in %s\n", log_signal(bit), log_id(module));
+ return;
+ }
+
+ busy.insert(bit);
+ get<0>(bitinfo) = level;
+ get<1>(bitinfo) = from;
+ get<2>(bitinfo) = via;
+
+ if (level > maxlvl) {
+ maxlvl = level;
+ maxbit = bit;
+ }
+
+ if (bit2bits.count(bit)) {
+ for (auto &it : bit2bits.at(bit))
+ runner(it.first, level+1, bit, it.second);
+ }
+
+ busy.erase(bit);
+ }
+
+ void printpath(SigBit bit)
+ {
+ auto &bitinfo = bits.at(bit);
+ if (get<2>(bitinfo)) {
+ printpath(get<1>(bitinfo));
+ log("%5d: %s (via %s)\n", get<0>(bitinfo), log_signal(bit), log_id(get<2>(bitinfo)));
+ } else {
+ log("%5d: %s\n", get<0>(bitinfo), log_signal(bit));
+ }
+ }
+
+ void run()
+ {
+ for (auto &it : bits)
+ if (get<0>(it.second) < 0)
+ runner(it.first, 0, State::Sx, nullptr);
+
+ log("\n");
+ log("Longest topological path in %s (length=%d):\n", log_id(module), maxlvl);
+
+ if (maxlvl >= 0)
+ printpath(maxbit);
+
+ if (bit2ff.count(maxbit))
+ log("%5s: %s (via %s)\n", "ff", log_signal(get<0>(bit2ff.at(maxbit))), log_id(get<1>(bit2ff.at(maxbit))));
+ }
+};
+
+struct LtpPass : public Pass {
+ LtpPass() : Pass("ltp", "print longest topological path") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" ltp [options] [selection]\n");
+ log("\n");
+ log("This command prints the longest topological path in the design. (Only considers\n");
+ log("paths within a single module, so the design must be flattened.)\n");
+ log("\n");
+ log(" -noff\n");
+ log(" automatically exclude FF cell types\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ bool noff = false;
+
+ log_header(design, "Executing LTP pass (find longest path).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-noff") {
+ noff = true;
+ continue;
+ }
+ break;
+ }
+
+ extra_args(args, argidx, design);
+
+ for (Module *module : design->selected_modules())
+ {
+ if (module->has_processes_warn())
+ continue;
+
+ LtpWorker worker(module, noff);
+ worker.run();
+ }
+ }
+} LtpPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc
index 828c671d..aa6d5b6c 100644
--- a/passes/cmds/plugin.cc
+++ b/passes/cmds/plugin.cc
@@ -58,7 +58,7 @@ void load_plugin(std::string, std::vector<std::string>)
struct PluginPass : public Pass {
PluginPass() : Pass("plugin", "load and list loaded plugins") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -76,7 +76,7 @@ struct PluginPass : public Pass {
log(" List loaded plugins\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string plugin_filename;
std::vector<std::string> plugin_aliases;
diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc
index 1b800b6d..1c64a7b7 100644
--- a/passes/cmds/qwp.cc
+++ b/passes/cmds/qwp.cc
@@ -778,7 +778,7 @@ struct QwpWorker
struct QwpPass : public Pass {
QwpPass() : Pass("qwp", "quadratic wirelength placer") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -808,7 +808,7 @@ struct QwpPass : public Pass {
log("dense matrix operations. It is only a toy-placer for small circuits.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
QwpConfig config;
xorshift32_state = 123456789;
@@ -835,6 +835,7 @@ struct QwpPass : public Pass {
}
if (args[argidx] == "-dump" && argidx+1 < args.size()) {
config.dump_file.open(args[++argidx], std::ofstream::trunc);
+ yosys_output_files.insert(args[argidx]);
continue;
}
break;
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index 6a002869..dce576fd 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -54,7 +54,7 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std::
struct RenamePass : public Pass {
RenamePass() : Pass("rename", "rename object in the design") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -81,7 +81,7 @@ struct RenamePass : public Pass {
log("Rename top module.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string pattern_prefix = "_", pattern_suffix = "_";
bool flag_enumerate = false;
diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc
index f083e1f6..7123ba9f 100644
--- a/passes/cmds/scatter.cc
+++ b/passes/cmds/scatter.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct ScatterPass : public Pass {
ScatterPass() : Pass("scatter", "add additional intermediate nets") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -41,7 +41,7 @@ struct ScatterPass : public Pass {
log("Use the opt_clean command to get rid of the additional nets.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
CellTypes ct(design);
extra_args(args, 1, design);
diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc
index bb6d7447..99f4fbae 100644
--- a/passes/cmds/scc.cc
+++ b/passes/cmds/scc.cc
@@ -163,16 +163,8 @@ struct SccWorker
}
for (auto cell : workQueue)
- cellToNextCell[cell] = sigToNextCells.find(cellToNextSig[cell]);
-
- labelCounter = 0;
- cellLabels.clear();
-
- while (workQueue.size() > 0)
{
- RTLIL::Cell *cell = *workQueue.begin();
- log_assert(cellStack.size() == 0);
- cellDepth.clear();
+ cellToNextCell[cell] = sigToNextCells.find(cellToNextSig[cell]);
if (!nofeedbackMode && cellToNextCell[cell].count(cell)) {
log("Found an SCC:");
@@ -183,6 +175,16 @@ struct SccWorker
sccList.push_back(scc);
log("\n");
}
+ }
+
+ labelCounter = 0;
+ cellLabels.clear();
+
+ while (!workQueue.empty())
+ {
+ RTLIL::Cell *cell = *workQueue.begin();
+ log_assert(cellStack.size() == 0);
+ cellDepth.clear();
run(cell, 0, maxDepth);
}
@@ -216,7 +218,7 @@ struct SccWorker
struct SccPass : public Pass {
SccPass() : Pass("scc", "detect strongly connected components (logic loops)") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -244,20 +246,18 @@ struct SccPass : public Pass {
log(" are assumed to be bidirectional 'inout' ports.\n");
log("\n");
log(" -set_attr <name> <value>\n");
- log(" -set_cell_attr <name> <value>\n");
- log(" -set_wire_attr <name> <value>\n");
- log(" set the specified attribute on all cells and/or wires that are part of\n");
- log(" a logic loop. the special token {} in the value is replaced with a\n");
- log(" unique identifier for the logic loop.\n");
+ log(" set the specified attribute on all cells that are part of a logic\n");
+ log(" loop. the special token {} in the value is replaced with a unique\n");
+ log(" identifier for the logic loop.\n");
log("\n");
log(" -select\n");
log(" replace the current selection with a selection of all cells and wires\n");
log(" that are part of a found logic loop\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- std::map<std::string, std::string> setCellAttr, setWireAttr;
+ std::map<std::string, std::string> setAttr;
bool allCellTypes = false;
bool selectMode = false;
bool nofeedbackMode = false;
@@ -285,18 +285,7 @@ struct SccPass : public Pass {
continue;
}
if (args[argidx] == "-set_attr" && argidx+2 < args.size()) {
- setCellAttr[args[argidx+1]] = args[argidx+2];
- setWireAttr[args[argidx+1]] = args[argidx+2];
- argidx += 2;
- continue;
- }
- if (args[argidx] == "-set_cell_attr" && argidx+2 < args.size()) {
- setCellAttr[args[argidx+1]] = args[argidx+2];
- argidx += 2;
- continue;
- }
- if (args[argidx] == "-set_wire_attr" && argidx+2 < args.size()) {
- setWireAttr[args[argidx+1]] = args[argidx+2];
+ setAttr[args[argidx+1]] = args[argidx+2];
argidx += 2;
continue;
}
@@ -309,9 +298,6 @@ struct SccPass : public Pass {
int origSelectPos = design->selection_stack.size() - 1;
extra_args(args, argidx, design);
- if (setCellAttr.size() > 0 || setWireAttr.size() > 0)
- log_cmd_error("The -set*_attr options are not implemented at the moment!\n");
-
RTLIL::Selection newSelection(false);
int scc_counter = 0;
@@ -319,7 +305,33 @@ struct SccPass : public Pass {
if (design->selected(mod_it.second))
{
SccWorker worker(design, mod_it.second, nofeedbackMode, allCellTypes, maxDepth);
- scc_counter += GetSize(worker.sccList);
+
+ if (!setAttr.empty())
+ {
+ for (const auto &cells : worker.sccList)
+ {
+ for (auto attr : setAttr)
+ {
+ IdString attr_name(RTLIL::escape_id(attr.first));
+ string attr_valstr = attr.second;
+ string index = stringf("%d", scc_counter);
+
+ for (size_t pos = 0; (pos = attr_valstr.find("{}", pos)) != string::npos; pos += index.size())
+ attr_valstr.replace(pos, 2, index);
+
+ Const attr_value(attr_valstr);
+
+ for (auto cell : cells)
+ cell->attributes[attr_name] = attr_value;
+ }
+
+ scc_counter++;
+ }
+ }
+ else
+ {
+ scc_counter += GetSize(worker.sccList);
+ }
if (selectMode)
worker.select(newSelection);
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index d2e1a2e2..d97aa2b3 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -760,6 +760,9 @@ static void select_stmt(RTLIL::Design *design, std::string arg)
if (!design->selected_active_module.empty()) {
arg_mod = design->selected_active_module;
arg_memb = arg;
+ } else
+ if (GetSize(arg) >= 2 && arg[0] >= 'a' && arg[0] <= 'z' && arg[1] == ':') {
+ arg_mod = "*", arg_memb = arg;
} else {
size_t pos = arg.find('/');
if (pos == std::string::npos) {
@@ -947,7 +950,7 @@ PRIVATE_NAMESPACE_BEGIN
struct SelectPass : public Pass {
SelectPass() : Pass("select", "modify and view the list of selected objects") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -961,7 +964,7 @@ struct SelectPass : public Pass {
log("list of selected objects.\n");
log("\n");
log("Note that many commands support an optional [selection] argument that can be\n");
- log("used to override the global selection for the command. The syntax of this\n");
+ log("used to YS_OVERRIDE the global selection for the command. The syntax of this\n");
log("optional argument is identical to the syntax of the <selection> argument\n");
log("described here.\n");
log("\n");
@@ -1164,7 +1167,7 @@ struct SelectPass : public Pass {
log(" select */t:SWITCH %%x:+[GATE] */t:SWITCH %%d\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool add_mode = false;
bool del_mode = false;
@@ -1263,6 +1266,7 @@ struct SelectPass : public Pass {
log_cmd_error("Option -read can not be combined with a selection expression.\n");
std::ifstream f(read_file);
+ yosys_input_files.insert(read_file);
if (f.fail())
log_error("Can't open '%s' for reading: %s\n", read_file.c_str(), strerror(errno));
@@ -1331,6 +1335,7 @@ struct SelectPass : public Pass {
FILE *f = NULL;
if (!write_file.empty()) {
f = fopen(write_file.c_str(), "w");
+ yosys_output_files.insert(write_file);
if (f == NULL)
log_error("Can't open '%s' for writing: %s\n", write_file.c_str(), strerror(errno));
}
@@ -1465,7 +1470,7 @@ struct SelectPass : public Pass {
struct CdPass : public Pass {
CdPass() : Pass("cd", "a shortcut for 'select -module <name>'") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1482,17 +1487,53 @@ struct CdPass : public Pass {
log("\n");
log(" cd ..\n");
log("\n");
+ log("Remove trailing substrings that start with '.' in current module name until\n");
+ log("the name of a module in the current design is generated, then switch to that\n");
+ log("module. Otherwise clear the current selection.\n");
+ log("\n");
+ log(" cd\n");
+ log("\n");
log("This is just a shortcut for 'select -clear'.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- if (args.size() != 2)
+ if (args.size() != 1 && args.size() != 2)
log_cmd_error("Invalid number of arguments.\n");
- if (args[1] == "..") {
+ if (args.size() == 1 || args[1] == "/") {
+ design->selection_stack.back() = RTLIL::Selection(true);
+ design->selected_active_module = std::string();
+ return;
+ }
+
+ if (args[1] == "..")
+ {
+ string modname = design->selected_active_module;
+
design->selection_stack.back() = RTLIL::Selection(true);
design->selected_active_module = std::string();
+
+ while (1)
+ {
+ size_t pos = modname.rfind('.');
+
+ if (pos == string::npos)
+ break;
+
+ modname = modname.substr(0, pos);
+ Module *mod = design->module(modname);
+
+ if (mod == nullptr)
+ continue;
+
+ design->selected_active_module = modname;
+ design->selection_stack.back() = RTLIL::Selection();
+ select_filter_active_mod(design, design->selection_stack.back());
+ design->selection_stack.back().optimize(design);
+ return;
+ }
+
return;
}
@@ -1537,7 +1578,7 @@ static void log_matches(const char *title, Module *module, T list)
struct LsPass : public Pass {
LsPass() : Pass("ls", "list modules or objects in modules") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1548,7 +1589,7 @@ struct LsPass : public Pass {
log("When an active module is selected, this prints a list of objects in the module.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx = 1;
extra_args(args, argidx, design);
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index 689e3148..d38a6b3d 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -56,7 +56,7 @@ static void do_setunset(dict<RTLIL::IdString, RTLIL::Const> &attrs, const std::v
struct SetattrPass : public Pass {
SetattrPass() : Pass("setattr", "set/unset attributes on objects") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -69,7 +69,7 @@ struct SetattrPass : public Pass {
log("instead of objects within modules.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<setunset_t> setunset_list;
bool flag_mod = false;
@@ -130,7 +130,7 @@ struct SetattrPass : public Pass {
struct SetparamPass : public Pass {
SetparamPass() : Pass("setparam", "set/unset parameters on objects") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -142,7 +142,7 @@ struct SetparamPass : public Pass {
log("The -type option can be used to change the cell type of the selected cells.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
vector<setunset_t> setunset_list;
string new_cell_type;
@@ -188,7 +188,7 @@ struct SetparamPass : public Pass {
struct ChparamPass : public Pass {
ChparamPass() : Pass("chparam", "re-evaluate modules with new parameters") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -203,7 +203,7 @@ struct ChparamPass : public Pass {
log("List the available parameters of the selected modules.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<setunset_t> setunset_list;
dict<RTLIL::IdString, RTLIL::Const> new_parameters;
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index 26b2eb87..62d940ce 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -23,33 +23,82 @@
#include "kernel/rtlil.h"
#include "kernel/log.h"
+#define MODE_ZERO 0
+#define MODE_ONE 1
+#define MODE_UNDEF 2
+#define MODE_RANDOM 3
+#define MODE_ANYSEQ 4
+#define MODE_ANYCONST 5
+
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+static RTLIL::Wire * add_wire(RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output)
+{
+ RTLIL::Wire *wire = NULL;
+ name = RTLIL::escape_id(name);
+
+ if (module->count_id(name) != 0)
+ {
+ log("Module %s already has such an object %s.\n", module->name.c_str(), name.c_str());
+ name += "$";
+ return add_wire(module, name, width, flag_input, flag_output);
+ }
+ else
+ {
+ wire = module->addWire(name, width);
+ wire->port_input = flag_input;
+ wire->port_output = flag_output;
+
+ if (flag_input || flag_output) {
+ wire->port_id = module->wires_.size();
+ module->fixup_ports();
+ }
+
+ log("Added wire %s to module %s.\n", name.c_str(), module->name.c_str());
+ }
+
+ return wire;
+}
+
struct SetundefWorker
{
int next_bit_mode;
uint32_t next_bit_state;
+ vector<SigSpec*> siglist;
RTLIL::State next_bit()
{
- if (next_bit_mode == 0)
+ if (next_bit_mode == MODE_ZERO)
return RTLIL::State::S0;
- if (next_bit_mode == 1)
+ if (next_bit_mode == MODE_ONE)
return 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);
+ if (next_bit_mode == MODE_UNDEF)
+ return RTLIL::State::Sx;
+
+ if (next_bit_mode == MODE_RANDOM)
+ {
+ // 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;
+ return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
+ }
+
+ log_abort();
}
void operator()(RTLIL::SigSpec &sig)
{
+ if (next_bit_mode == MODE_ANYSEQ || next_bit_mode == MODE_ANYCONST) {
+ siglist.push_back(&sig);
+ return;
+ }
+
for (auto &bit : sig)
if (bit.wire == NULL && bit.data > RTLIL::State::S1)
bit = next_bit();
@@ -58,23 +107,35 @@ struct SetundefWorker
struct SetundefPass : public Pass {
SetundefPass() : Pass("setundef", "replace undef values with defined constants") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" setundef [options] [selection]\n");
log("\n");
- log("This command replaced undef (x) constants with defined (0/1) constants.\n");
+ log("This command replaces undef (x) constants with defined (0/1) constants.\n");
log("\n");
log(" -undriven\n");
log(" also set undriven nets to constant values\n");
log("\n");
+ log(" -expose\n");
+ log(" also expose undriven nets as inputs (use with -undriven)\n");
+ log("\n");
log(" -zero\n");
log(" replace with bits cleared (0)\n");
log("\n");
log(" -one\n");
log(" replace with bits set (1)\n");
log("\n");
+ log(" -undef\n");
+ log(" replace with undef (x) bits, may be used with -undriven\n");
+ log("\n");
+ log(" -anyseq\n");
+ log(" replace with $anyseq drivers (for formal)\n");
+ log("\n");
+ log(" -anyconst\n");
+ log(" replace with $anyconst drivers (for formal)\n");
+ log("\n");
log(" -random <seed>\n");
log(" replace with random bits using the specified integer als seed\n");
log(" value for the random number generator.\n");
@@ -83,13 +144,16 @@ struct SetundefPass : public Pass {
log(" also create/update init values for flip-flops\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool got_value = false;
bool undriven_mode = false;
+ bool expose_mode = false;
bool init_mode = false;
SetundefWorker worker;
+ log_header(design, "Executing SETUNDEF pass (replace undef values with defined constants).\n");
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
@@ -97,14 +161,39 @@ struct SetundefPass : public Pass {
undriven_mode = true;
continue;
}
+ if (args[argidx] == "-expose") {
+ got_value = true;
+ expose_mode = true;
+ continue;
+ }
if (args[argidx] == "-zero") {
got_value = true;
- worker.next_bit_mode = 0;
+ worker.next_bit_mode = MODE_ZERO;
+ worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-one") {
got_value = true;
- worker.next_bit_mode = 1;
+ worker.next_bit_mode = MODE_ONE;
+ worker.next_bit_state = 0;
+ continue;
+ }
+ if (args[argidx] == "-anyseq") {
+ got_value = true;
+ worker.next_bit_mode = MODE_ANYSEQ;
+ worker.next_bit_state = 0;
+ continue;
+ }
+ if (args[argidx] == "-anyconst") {
+ got_value = true;
+ worker.next_bit_mode = MODE_ANYCONST;
+ worker.next_bit_state = 0;
+ continue;
+ }
+ if (args[argidx] == "-undef") {
+ got_value = true;
+ worker.next_bit_mode = MODE_UNDEF;
+ worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-init") {
@@ -113,7 +202,7 @@ struct SetundefPass : public Pass {
}
if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
got_value = true;
- worker.next_bit_mode = 2;
+ worker.next_bit_mode = MODE_RANDOM;
worker.next_bit_state = atoi(args[++argidx].c_str()) + 1;
for (int i = 0; i < 10; i++)
worker.next_bit();
@@ -123,8 +212,13 @@ struct SetundefPass : public Pass {
}
extra_args(args, argidx, design);
+ if (expose_mode && !undriven_mode)
+ log_cmd_error("Option -expose must be used with option -undriven.\n");
if (!got_value)
- log_cmd_error("One of the options -zero, -one, or -random <seed> must be specified.\n");
+ log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, or -random <seed> must be specified.\n");
+
+ if (init_mode && (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST))
+ log_cmd_error("The options -init and -anyseq / -anyconst are exclusive.\n");
for (auto module : design->selected_modules())
{
@@ -133,25 +227,103 @@ struct SetundefPass : public Pass {
if (!module->processes.empty())
log_error("The 'setundef' command can't operate in -undriven mode on modules with processes. Run 'proc' first.\n");
- SigMap sigmap(module);
- SigPool undriven_signals;
+ if (expose_mode)
+ {
+ SigMap sigmap(module);
+ dict<SigBit, bool> wire_drivers;
+ pool<SigBit> used_wires;
+ SigPool undriven_signals;
+
+ for (auto cell : module->cells())
+ for (auto &conn : cell->connections()) {
+ SigSpec sig = sigmap(conn.second);
+ if (cell->input(conn.first))
+ for (auto bit : sig)
+ if (bit.wire)
+ used_wires.insert(bit);
+ if (cell->output(conn.first))
+ for (int i = 0; i < GetSize(sig); i++)
+ if (sig[i].wire)
+ wire_drivers[sig[i]] = true;
+ }
+
+ for (auto wire : module->wires()) {
+ if (wire->port_input) {
+ SigSpec sig = sigmap(wire);
+ for (int i = 0; i < GetSize(sig); i++)
+ wire_drivers[sig[i]] = true;
+ }
+ if (wire->port_output) {
+ SigSpec sig = sigmap(wire);
+ for (auto bit : sig)
+ if (bit.wire)
+ used_wires.insert(bit);
+ }
+ }
+
+ pool<RTLIL::Wire*> undriven_wires;
+ for (auto bit : used_wires)
+ if (!wire_drivers.count(bit))
+ undriven_wires.insert(bit.wire);
+
+ for (auto &it : undriven_wires)
+ undriven_signals.add(sigmap(it));
+
+ for (auto &it : undriven_wires)
+ if (it->port_input)
+ undriven_signals.del(sigmap(it));
+
+ CellTypes ct(design);
+ 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()) {
+ RTLIL::Wire * wire;
+ if (c.wire->width == c.width) {
+ wire = c.wire;
+ wire->port_input = true;
+ } else {
+ string name = c.wire->name.str() + "$[" + std::to_string(c.width + c.offset) + ":" + std::to_string(c.offset) + "]";
+ wire = add_wire(module, name, c.width, true, false);
+ module->connect(RTLIL::SigSig(c, wire));
+ }
+ log("Exposing undriven wire %s as input.\n", wire->name.c_str());
+ }
+ module->fixup_ports();
+ }
+ else
+ {
+ SigMap sigmap(module);
+ SigPool undriven_signals;
- for (auto &it : module->wires_)
- if (!it.second->port_input)
+ for (auto &it : module->wires_)
undriven_signals.add(sigmap(it.second));
- CellTypes ct(design);
- 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()) {
- RTLIL::SigSpec bits;
- for (int i = 0; i < c.width; i++)
- bits.append(worker.next_bit());
- module->connect(RTLIL::SigSig(c, bits));
+ for (auto &it : module->wires_)
+ if (it.second->port_input)
+ undriven_signals.del(sigmap(it.second));
+
+ CellTypes ct(design);
+ 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()) {
+ RTLIL::SigSpec bits;
+ if (worker.next_bit_mode == MODE_ANYSEQ)
+ bits = module->Anyseq(NEW_ID, c.width);
+ else if (worker.next_bit_mode == MODE_ANYCONST)
+ bits = module->Anyconst(NEW_ID, c.width);
+ else
+ for (int i = 0; i < c.width; i++)
+ bits.append(worker.next_bit());
+ module->connect(RTLIL::SigSig(c, bits));
+ }
}
}
@@ -236,6 +408,35 @@ struct SetundefPass : public Pass {
}
module->rewrite_sigspecs(worker);
+
+ if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)
+ {
+ vector<SigSpec*> siglist;
+ siglist.swap(worker.siglist);
+
+ for (auto sigptr : siglist)
+ {
+ SigSpec &sig = *sigptr;
+ int cursor = 0;
+
+ while (cursor < GetSize(sig))
+ {
+ int width = 0;
+ while (cursor+width < GetSize(sig) && sig[cursor+width] == State::Sx)
+ width++;
+
+ if (width > 0) {
+ if (worker.next_bit_mode == MODE_ANYSEQ)
+ sig.replace(cursor, module->Anyseq(NEW_ID, width));
+ else
+ sig.replace(cursor, module->Anyconst(NEW_ID, width));
+ cursor += width;
+ } else {
+ cursor++;
+ }
+ }
+ }
+ }
}
}
} SetundefPass;
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 3a3939a8..a4887324 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -30,6 +30,10 @@
# include <readline/readline.h>
#endif
+#ifdef YOSYS_ENABLE_EDITLINE
+# include <editline/readline.h>
+#endif
+
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -569,7 +573,7 @@ struct ShowWorker
struct ShowPass : public Pass {
ShowPass() : Pass("show", "generate schematics using graphviz") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -580,6 +584,7 @@ struct ShowPass : public Pass {
log("\n");
log(" -viewer <viewer>\n");
log(" Run the specified command with the graphics file as parameter.\n");
+ log(" On Windows, this pauses yosys until the viewer exits.\n");
log("\n");
log(" -format <format>\n");
log(" Generate a graphics file in the specified format. Use 'dot' to just\n");
@@ -641,7 +646,7 @@ struct ShowPass : public Pass {
log(" do not add the module name as graph title to the dot file\n");
log("\n");
log("When no <format> is specified, 'dot' is used. When no <format> and <viewer> is\n");
- log("specified, 'xdot' is used to display the schematic.\n");
+ log("specified, 'xdot' is used to display the schematic (POSIX systems only).\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");
@@ -651,7 +656,7 @@ struct ShowPass : public Pass {
log("the 'show' command is executed.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Generating Graphviz representation of design.\n");
log_push();
@@ -677,6 +682,7 @@ struct ShowPass : public Pass {
bool flag_enum = false;
bool flag_abbreviate = true;
bool flag_notitle = false;
+ bool custom_prefix = false;
RTLIL::IdString colorattr;
size_t argidx;
@@ -693,6 +699,7 @@ struct ShowPass : public Pass {
}
if (arg == "-prefix" && argidx+1 < args.size()) {
prefix = args[++argidx];
+ custom_prefix = true;
continue;
}
if (arg == "-color" && argidx+2 < args.size()) {
@@ -778,6 +785,7 @@ struct ShowPass : public Pass {
for (auto filename : libfiles) {
std::ifstream f;
f.open(filename.c_str());
+ yosys_input_files.insert(filename);
if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design;
@@ -793,6 +801,8 @@ struct ShowPass : public Pass {
log("Writing dot description to `%s'.\n", dot_file.c_str());
FILE *f = fopen(dot_file.c_str(), "w");
+ if (custom_prefix)
+ yosys_output_files.insert(dot_file);
if (f == NULL) {
for (auto lib : libs)
delete lib;
@@ -808,14 +818,30 @@ struct ShowPass : public Pass {
log_cmd_error("Nothing there to show.\n");
if (format != "dot" && !format.empty()) {
- std::string cmd = stringf("dot -T%s '%s' > '%s.new' && mv '%s.new' '%s'", format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str());
+ #ifdef _WIN32
+ // system()/cmd.exe does not understand single quotes on Windows.
+ #define DOT_CMD "dot -T%s \"%s\" > \"%s.new\" && move \"%s.new\" \"%s\""
+ #else
+ #define DOT_CMD "dot -T%s '%s' > '%s.new' && mv '%s.new' '%s'"
+ #endif
+ std::string cmd = stringf(DOT_CMD, format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str());
+ #undef DOT_CMD
log("Exec: %s\n", cmd.c_str());
if (run_command(cmd) != 0)
log_cmd_error("Shell command failed!\n");
}
if (!viewer_exe.empty()) {
- std::string cmd = stringf("%s '%s' &", viewer_exe.c_str(), out_file.c_str());
+ #ifdef _WIN32
+ // system()/cmd.exe does not understand single quotes nor
+ // background tasks on Windows. So we have to pause yosys
+ // until the viewer exits.
+ #define VIEW_CMD "%s \"%s\""
+ #else
+ #define VIEW_CMD "%s '%s' &"
+ #endif
+ std::string cmd = stringf(VIEW_CMD, viewer_exe.c_str(), out_file.c_str());
+ #undef VIEW_CMD
log("Exec: %s\n", cmd.c_str());
if (run_command(cmd) != 0)
log_cmd_error("Shell command failed!\n");
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index 7418ec4d..bafafca4 100644
--- a/passes/cmds/splice.cc
+++ b/passes/cmds/splice.cc
@@ -247,7 +247,7 @@ struct SpliceWorker
struct SplicePass : public Pass {
SplicePass() : Pass("splice", "create explicit splicing cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -288,7 +288,7 @@ struct SplicePass : public Pass {
log("by selected wires are rewired.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool sel_by_cell = false;
bool sel_by_wire = false;
diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc
index 14eeb066..f5a1f17b 100644
--- a/passes/cmds/splitnets.cc
+++ b/passes/cmds/splitnets.cc
@@ -37,14 +37,20 @@ struct SplitnetsWorker
new_wire_name += format.substr(0, 1);
if (width > 1) {
- new_wire_name += stringf("%d", offset+width-1);
+ if (wire->upto)
+ new_wire_name += stringf("%d", wire->start_offset+wire->width-(offset+width)-1);
+ else
+ new_wire_name += stringf("%d", wire->start_offset+offset+width-1);
if (format.size() > 2)
new_wire_name += format.substr(2, 1);
else
new_wire_name += ":";
}
- new_wire_name += stringf("%d", offset);
+ if (wire->upto)
+ new_wire_name += stringf("%d", wire->start_offset+wire->width-offset-1);
+ else
+ new_wire_name += stringf("%d", wire->start_offset+offset);
if (format.size() > 1)
new_wire_name += format.substr(1, 1);
@@ -81,7 +87,7 @@ struct SplitnetsWorker
struct SplitnetsPass : public Pass {
SplitnetsPass() : Pass("splitnets", "split up multi-bit nets") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -103,7 +109,7 @@ struct SplitnetsPass : public Pass {
log(" and split nets so that no driver drives only part of a net.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool flag_ports = false;
bool flag_driver = false;
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 362a0edf..54f4ea81 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -112,7 +112,7 @@ struct statdata_t
"$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")) {
+ "$add", "$sub", "$mul", "$div", "$mod", "$pow", "$alu")) {
int width_a = it.second->hasPort("\\A") ? GetSize(it.second->getPort("\\A")) : 0;
int width_b = it.second->hasPort("\\B") ? GetSize(it.second->getPort("\\B")) : 0;
int width_y = it.second->hasPort("\\Y") ? GetSize(it.second->getPort("\\Y")) : 0;
@@ -142,7 +142,7 @@ struct statdata_t
}
}
- void log_data()
+ void log_data(RTLIL::IdString mod_name, bool top_mod)
{
log(" Number of wires: %6d\n", num_wires);
log(" Number of wire bits: %6d\n", num_wire_bits);
@@ -163,7 +163,7 @@ struct statdata_t
if (area != 0) {
log("\n");
- log(" Chip area for this module: %f\n", area);
+ log(" Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area);
}
}
};
@@ -190,6 +190,7 @@ void read_liberty_cellarea(dict<IdString, double> &cell_area, string liberty_fil
{
std::ifstream f;
f.open(liberty_file.c_str());
+ yosys_input_files.insert(liberty_file);
if (f.fail())
log_cmd_error("Can't open liberty file `%s': %s\n", liberty_file.c_str(), strerror(errno));
LibertyParser libparser(f);
@@ -208,7 +209,7 @@ void read_liberty_cellarea(dict<IdString, double> &cell_area, string liberty_fil
struct StatPass : public Pass {
StatPass() : Pass("stat", "print some statistics") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -230,7 +231,7 @@ struct StatPass : public Pass {
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)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Printing statistics.\n");
@@ -274,7 +275,7 @@ struct StatPass : public Pass {
log("\n");
log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
log("\n");
- data.log_data();
+ data.log_data(mod->name, false);
}
if (top_mod != NULL && GetSize(mod_stat) > 1)
@@ -287,7 +288,7 @@ struct StatPass : public Pass {
statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0);
log("\n");
- data.log_data();
+ data.log_data(top_mod->name, true);
}
log("\n");
diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc
index 3db2dbf0..ff80f385 100644
--- a/passes/cmds/tee.cc
+++ b/passes/cmds/tee.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct TeePass : public Pass {
TeePass() : Pass("tee", "redirect command output to file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -49,7 +49,7 @@ struct TeePass : public Pass {
log(" Add/subract INT from the -v setting for this command.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<FILE*> backup_log_files, files_to_close;
int backup_log_verbose_level = log_verbose_level;
@@ -65,6 +65,7 @@ struct TeePass : public Pass {
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);
+ yosys_input_files.insert(args[argidx]);
if (f == NULL) {
for (auto cf : files_to_close)
fclose(cf);
diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc
index 56223610..3c0eac8d 100644
--- a/passes/cmds/torder.cc
+++ b/passes/cmds/torder.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct TorderPass : public Pass {
TorderPass() : Pass("torder", "print cells in topological order") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -43,7 +43,7 @@ struct TorderPass : public Pass {
log(" are not used in topological sorting. this option deactivates that.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool noautostop = false;
dict<IdString, pool<IdString>> stop_db;
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
index 1a5f873f..f5305cde 100644
--- a/passes/cmds/trace.cc
+++ b/passes/cmds/trace.cc
@@ -25,34 +25,34 @@ PRIVATE_NAMESPACE_BEGIN
struct TraceMonitor : public RTLIL::Monitor
{
- virtual void notify_module_add(RTLIL::Module *module) YS_OVERRIDE
+ void notify_module_add(RTLIL::Module *module) YS_OVERRIDE
{
log("#TRACE# Module add: %s\n", log_id(module));
}
- virtual void notify_module_del(RTLIL::Module *module) YS_OVERRIDE
+ void notify_module_del(RTLIL::Module *module) YS_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) YS_OVERRIDE
+ void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_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) YS_OVERRIDE
+ void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) YS_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) YS_OVERRIDE
+ void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) YS_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) YS_OVERRIDE
+ void notify_blackout(RTLIL::Module *module) YS_OVERRIDE
{
log("#TRACE# Blackout in module %s:\n", log_id(module));
}
@@ -60,7 +60,7 @@ struct TraceMonitor : public RTLIL::Monitor
struct TracePass : public Pass {
TracePass() : Pass("trace", "redirect command output to file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -70,7 +70,7 @@ struct TracePass : public Pass {
log("the design in real time.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -95,4 +95,3 @@ struct TracePass : public Pass {
} TracePass;
PRIVATE_NAMESPACE_END
-
diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc
index b7826593..9613b462 100644
--- a/passes/cmds/write_file.cc
+++ b/passes/cmds/write_file.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct WriteFileFrontend : public Frontend {
WriteFileFrontend() : Frontend("=write_file", "write a text to a file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -44,7 +44,7 @@ struct WriteFileFrontend : public Frontend {
log(" EOT\n");
log("\n");
}
- virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*)
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
{
bool append_mode = false;
std::string output_filename;
@@ -67,6 +67,7 @@ struct WriteFileFrontend : public Frontend {
extra_args(f, filename, args, argidx);
FILE *of = fopen(output_filename.c_str(), append_mode ? "a" : "w");
+ yosys_output_files.insert(output_filename);
char buffer[64 * 1024];
int bytes;