log(" fsm [options] [selection]\n");
log("\n");
log("This pass calls all the other fsm_* passes in a useful order. This performs\n");
- log("FSM extraction and optimiziation. It also calls opt_rmunused as needed:\n");
+ log("FSM extraction and optimiziation. It also calls opt_clean as needed:\n");
log("\n");
log(" fsm_detect unless got option -nodetect\n");
log(" fsm_extract\n");
log("\n");
log(" fsm_opt\n");
- log(" opt_rmunused\n");
+ log(" opt_clean\n");
log(" fsm_opt\n");
log("\n");
log(" fsm_expand if got option -expand\n");
- log(" opt_rmunused if got option -expand\n");
+ log(" opt_clean if got option -expand\n");
log(" fsm_opt if got option -expand\n");
log("\n");
log(" fsm_recode unless got option -norecode\n");
Pass::call(design, "fsm_extract");
Pass::call(design, "fsm_opt");
- Pass::call(design, "opt_rmunused");
+ Pass::call(design, "opt_clean");
Pass::call(design, "fsm_opt");
if (flag_expand) {
Pass::call(design, "fsm_expand");
- Pass::call(design, "opt_rmunused");
+ Pass::call(design, "opt_clean");
Pass::call(design, "fsm_opt");
}
log("\n");
log("The generated FSM cell still generates the original state signal with its\n");
log("original encoding. The 'fsm_opt' pass can be used in combination with the\n");
- log("'opt_rmunused' pass to eliminate this signal.\n");
+ log("'opt_clean' pass to eliminate this signal.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
log("\n");
log("This pass optimizes FSM cells. It detects which output signals are actually\n");
log("not used and removes them from the FSM. This pass is usually used in\n");
- log("combination with the 'opt_rmunused' pass (see also 'help fsm').\n");
+ log("combination with the 'opt_clean' pass (see also 'help fsm').\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
OBJS += passes/opt/opt_muxtree.o
OBJS += passes/opt/opt_reduce.o
OBJS += passes/opt/opt_rmdff.o
-OBJS += passes/opt/opt_rmunused.o
+OBJS += passes/opt/opt_clean.o
OBJS += passes/opt/opt_const.o
log(" opt_reduce\n");
log(" opt_share\n");
log(" opt_rmdff\n");
- log(" opt_rmunused\n");
+ log(" opt_clean\n");
log(" opt_const\n");
log(" while [changed design]\n");
log("\n");
Pass::call(design, "opt_reduce");
Pass::call(design, "opt_share");
Pass::call(design, "opt_rmdff");
- Pass::call(design, "opt_rmunused");
+ Pass::call(design, "opt_clean");
Pass::call(design, "opt_const");
if (OPT_DID_SOMETHING == false)
break;
--- /dev/null
+/*
+ * 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 "opt_status.h"
+#include "kernel/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/log.h"
+#include "kernel/celltypes.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <set>
+
+using RTLIL::id2cstr;
+
+static CellTypes ct;
+
+static void rmunused_module_cells(RTLIL::Module *module)
+{
+ SigMap assign_map(module);
+ std::set<RTLIL::Cell*> queue, unused;
+
+ SigSet<RTLIL::Cell*> wire2driver;
+ for (auto &it : module->cells) {
+ RTLIL::Cell *cell = it.second;
+ for (auto &it2 : cell->connections) {
+ if (!ct.cell_input(cell->type, it2.first)) {
+ RTLIL::SigSpec sig = it2.second;
+ assign_map.apply(sig);
+ wire2driver.insert(sig, cell);
+ }
+ }
+ if (cell->type == "$memwr")
+ queue.insert(cell);
+ unused.insert(cell);
+ }
+
+ for (auto &it : module->wires) {
+ RTLIL::Wire *wire = it.second;
+ if (wire->port_output) {
+ std::set<RTLIL::Cell*> cell_list;
+ RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
+ assign_map.apply(sig);
+ wire2driver.find(sig, cell_list);
+ for (auto cell : cell_list)
+ queue.insert(cell);
+ }
+ }
+
+ while (queue.size() > 0)
+ {
+ std::set<RTLIL::Cell*> new_queue;
+ for (auto cell : queue)
+ unused.erase(cell);
+ for (auto cell : queue) {
+ for (auto &it : cell->connections) {
+ if (!ct.cell_output(cell->type, it.first)) {
+ std::set<RTLIL::Cell*> cell_list;
+ RTLIL::SigSpec sig = it.second;
+ assign_map.apply(sig);
+ wire2driver.find(sig, cell_list);
+ for (auto cell : cell_list) {
+ if (unused.count(cell) > 0)
+ new_queue.insert(cell);
+ }
+ }
+ }
+ }
+ queue.swap(new_queue);
+ }
+
+ for (auto cell : unused) {
+ log(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
+ OPT_DID_SOMETHING = true;
+ module->cells.erase(cell->name);
+ delete cell;
+ }
+}
+
+static bool compare_signals(RTLIL::SigSpec &s1, RTLIL::SigSpec &s2)
+{
+ assert(s1.width == 1);
+ assert(s2.width == 1);
+ assert(s1.chunks.size() == 1);
+ assert(s2.chunks.size() == 1);
+
+ RTLIL::Wire *w1 = s1.chunks[0].wire;
+ RTLIL::Wire *w2 = s2.chunks[0].wire;
+
+ if (w1 == NULL || w2 == NULL)
+ return w2 == NULL;
+
+ if (w1->port_input != w2->port_input)
+ return w2->port_input;
+
+ if (w1->name[0] != w2->name[0])
+ return w2->name[0] == '\\';
+
+ if (w1->attributes.size() != w2->attributes.size())
+ return w2->attributes.size() > w1->attributes.size();
+
+ return w2->name < w1->name;
+}
+
+static bool check_public_name(RTLIL::IdString id)
+{
+ if (id[0] == '$')
+ return false;
+#if 0
+ if (id.find(".$") != std::string::npos)
+ return false;
+#endif
+ return true;
+}
+
+static void rmunused_module_signals(RTLIL::Module *module)
+{
+ SigMap assign_map(module);
+ for (auto &it : module->wires) {
+ RTLIL::Wire *wire = it.second;
+ for (int i = 0; i < wire->width; i++) {
+ RTLIL::SigSpec s1 = RTLIL::SigSpec(wire, 1, i), s2 = assign_map(s1);
+ if (!compare_signals(s1, s2))
+ assign_map.add(s1);
+ }
+ }
+
+ module->connections.clear();
+
+ SigPool used_signals;
+ SigPool used_signals_nodrivers;
+ for (auto &it : module->cells) {
+ RTLIL::Cell *cell = it.second;
+ for (auto &it2 : cell->connections) {
+ assign_map.apply(it2.second);
+ used_signals.add(it2.second);
+ if (!ct.cell_output(cell->type, it2.first))
+ used_signals_nodrivers.add(it2.second);
+ }
+ }
+ for (auto &it : module->wires) {
+ RTLIL::Wire *wire = it.second;
+ if (wire->port_id > 0) {
+ RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
+ assign_map.apply(sig);
+ used_signals.add(sig);
+ if (!wire->port_input)
+ used_signals_nodrivers.add(sig);
+ }
+ }
+
+ std::vector<RTLIL::Wire*> del_wires;
+ for (auto &it : module->wires) {
+ RTLIL::Wire *wire = it.second;
+ if (check_public_name(wire->name)) {
+ RTLIL::SigSpec s1 = RTLIL::SigSpec(wire), s2 = s1;
+ assign_map.apply(s2);
+ if (!used_signals.check_any(s2) && wire->port_id == 0) {
+ del_wires.push_back(wire);
+ } else {
+ s1.expand();
+ s2.expand();
+ assert(s1.chunks.size() == s2.chunks.size());
+ RTLIL::SigSig new_conn;
+ for (size_t i = 0; i < s1.chunks.size(); i++)
+ if (s1.chunks[i] != s2.chunks[i]) {
+ new_conn.first.append(s1.chunks[i]);
+ new_conn.second.append(s2.chunks[i]);
+ }
+ if (new_conn.first.width > 0) {
+ new_conn.first.optimize();
+ new_conn.second.optimize();
+ used_signals.add(new_conn.first);
+ used_signals.add(new_conn.second);
+ module->connections.push_back(new_conn);
+ }
+ }
+ } else {
+ if (!used_signals.check_any(RTLIL::SigSpec(wire)))
+ del_wires.push_back(wire);
+ }
+ RTLIL::SigSpec sig = assign_map(RTLIL::SigSpec(wire));
+ if (!used_signals_nodrivers.check_any(sig)) {
+ std::string unused_bits;
+ sig.expand();
+ for (size_t i = 0; i < sig.chunks.size(); i++) {
+ if (sig.chunks[i].wire == NULL)
+ continue;
+ if (!used_signals_nodrivers.check_any(sig)) {
+ if (!unused_bits.empty())
+ unused_bits += " ";
+ unused_bits += stringf("%zd", i);
+ }
+ }
+ if (unused_bits.empty() || wire->port_id != 0)
+ wire->attributes.erase("\\unused_bits");
+ else
+ wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits);
+ } else {
+ wire->attributes.erase("\\unused_bits");
+ }
+ }
+
+ int del_wires_count = 0;
+ for (auto wire : del_wires)
+ if (!used_signals.check_any(RTLIL::SigSpec(wire))) {
+ if (check_public_name(wire->name)) {
+ log(" removing unused non-port wire %s.\n", wire->name.c_str());
+ del_wires_count++;
+ }
+ module->wires.erase(wire->name);
+ delete wire;
+ }
+
+ if (del_wires_count > 0)
+ log(" removed %d unused temporary wires.\n", del_wires_count);
+}
+
+static void rmunused_module(RTLIL::Module *module)
+{
+ log("Finding unused cells or wires in module %s..\n", module->name.c_str());
+
+ rmunused_module_cells(module);
+ rmunused_module_signals(module);
+}
+
+struct OptCleanPass : public Pass {
+ OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" opt_clean [selection]\n");
+ log("\n");
+ log("This pass identifies wires and cells that are unused and removes them. Other\n");
+ log("passes often remove cells but leave the wires in the design or reconnect the\n");
+ log("wires but leave the old cells in the design. This pass can be used to clean up\n");
+ log("after the passes that do the actual work.\n");
+ log("\n");
+ log("This pass only operates on completely selected modules without processes.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header("Executing OPT_CLEAN pass (remove unused cells and wires).\n");
+ log_push();
+
+ extra_args(args, 1, design);
+
+ ct.setup_internals();
+ ct.setup_internals_mem();
+ ct.setup_stdcells();
+ ct.setup_stdcells_mem();
+
+ for (auto &mod_it : design->modules) {
+ if (!design->selected_whole_module(mod_it.first)) {
+ if (design->selected(mod_it.second))
+ log("Skipping module %s as it is only partially selected.\n", id2cstr(mod_it.second->name));
+ continue;
+ }
+ if (mod_it.second->processes.size() > 0) {
+ log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str());
+ } else {
+ rmunused_module(mod_it.second);
+ }
+ }
+
+ ct.clear();
+ log_pop();
+ }
+} OptCleanPass;
+
+++ /dev/null
-/*
- * 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 "opt_status.h"
-#include "kernel/register.h"
-#include "kernel/sigtools.h"
-#include "kernel/log.h"
-#include "kernel/celltypes.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <stdio.h>
-#include <set>
-
-using RTLIL::id2cstr;
-
-static CellTypes ct;
-
-static void rmunused_module_cells(RTLIL::Module *module)
-{
- SigMap assign_map(module);
- std::set<RTLIL::Cell*> queue, unused;
-
- SigSet<RTLIL::Cell*> wire2driver;
- for (auto &it : module->cells) {
- RTLIL::Cell *cell = it.second;
- for (auto &it2 : cell->connections) {
- if (!ct.cell_input(cell->type, it2.first)) {
- RTLIL::SigSpec sig = it2.second;
- assign_map.apply(sig);
- wire2driver.insert(sig, cell);
- }
- }
- if (cell->type == "$memwr")
- queue.insert(cell);
- unused.insert(cell);
- }
-
- for (auto &it : module->wires) {
- RTLIL::Wire *wire = it.second;
- if (wire->port_output) {
- std::set<RTLIL::Cell*> cell_list;
- RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
- assign_map.apply(sig);
- wire2driver.find(sig, cell_list);
- for (auto cell : cell_list)
- queue.insert(cell);
- }
- }
-
- while (queue.size() > 0)
- {
- std::set<RTLIL::Cell*> new_queue;
- for (auto cell : queue)
- unused.erase(cell);
- for (auto cell : queue) {
- for (auto &it : cell->connections) {
- if (!ct.cell_output(cell->type, it.first)) {
- std::set<RTLIL::Cell*> cell_list;
- RTLIL::SigSpec sig = it.second;
- assign_map.apply(sig);
- wire2driver.find(sig, cell_list);
- for (auto cell : cell_list) {
- if (unused.count(cell) > 0)
- new_queue.insert(cell);
- }
- }
- }
- }
- queue.swap(new_queue);
- }
-
- for (auto cell : unused) {
- log(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
- OPT_DID_SOMETHING = true;
- module->cells.erase(cell->name);
- delete cell;
- }
-}
-
-static bool compare_signals(RTLIL::SigSpec &s1, RTLIL::SigSpec &s2)
-{
- assert(s1.width == 1);
- assert(s2.width == 1);
- assert(s1.chunks.size() == 1);
- assert(s2.chunks.size() == 1);
-
- RTLIL::Wire *w1 = s1.chunks[0].wire;
- RTLIL::Wire *w2 = s2.chunks[0].wire;
-
- if (w1 == NULL || w2 == NULL)
- return w2 == NULL;
-
- if (w1->port_input != w2->port_input)
- return w2->port_input;
-
- if (w1->name[0] != w2->name[0])
- return w2->name[0] == '\\';
-
- if (w1->attributes.size() != w2->attributes.size())
- return w2->attributes.size() > w1->attributes.size();
-
- return w2->name < w1->name;
-}
-
-static bool check_public_name(RTLIL::IdString id)
-{
- if (id[0] == '$')
- return false;
-#if 0
- if (id.find(".$") != std::string::npos)
- return false;
-#endif
- return true;
-}
-
-static void rmunused_module_signals(RTLIL::Module *module)
-{
- SigMap assign_map(module);
- for (auto &it : module->wires) {
- RTLIL::Wire *wire = it.second;
- for (int i = 0; i < wire->width; i++) {
- RTLIL::SigSpec s1 = RTLIL::SigSpec(wire, 1, i), s2 = assign_map(s1);
- if (!compare_signals(s1, s2))
- assign_map.add(s1);
- }
- }
-
- module->connections.clear();
-
- SigPool used_signals;
- SigPool used_signals_nodrivers;
- for (auto &it : module->cells) {
- RTLIL::Cell *cell = it.second;
- for (auto &it2 : cell->connections) {
- assign_map.apply(it2.second);
- used_signals.add(it2.second);
- if (!ct.cell_output(cell->type, it2.first))
- used_signals_nodrivers.add(it2.second);
- }
- }
- for (auto &it : module->wires) {
- RTLIL::Wire *wire = it.second;
- if (wire->port_id > 0) {
- RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
- assign_map.apply(sig);
- used_signals.add(sig);
- if (!wire->port_input)
- used_signals_nodrivers.add(sig);
- }
- }
-
- std::vector<RTLIL::Wire*> del_wires;
- for (auto &it : module->wires) {
- RTLIL::Wire *wire = it.second;
- if (check_public_name(wire->name)) {
- RTLIL::SigSpec s1 = RTLIL::SigSpec(wire), s2 = s1;
- assign_map.apply(s2);
- if (!used_signals.check_any(s2) && wire->port_id == 0) {
- del_wires.push_back(wire);
- } else {
- s1.expand();
- s2.expand();
- assert(s1.chunks.size() == s2.chunks.size());
- RTLIL::SigSig new_conn;
- for (size_t i = 0; i < s1.chunks.size(); i++)
- if (s1.chunks[i] != s2.chunks[i]) {
- new_conn.first.append(s1.chunks[i]);
- new_conn.second.append(s2.chunks[i]);
- }
- if (new_conn.first.width > 0) {
- new_conn.first.optimize();
- new_conn.second.optimize();
- used_signals.add(new_conn.first);
- used_signals.add(new_conn.second);
- module->connections.push_back(new_conn);
- }
- }
- } else {
- if (!used_signals.check_any(RTLIL::SigSpec(wire)))
- del_wires.push_back(wire);
- }
- RTLIL::SigSpec sig = assign_map(RTLIL::SigSpec(wire));
- if (!used_signals_nodrivers.check_any(sig)) {
- std::string unused_bits;
- sig.expand();
- for (size_t i = 0; i < sig.chunks.size(); i++) {
- if (sig.chunks[i].wire == NULL)
- continue;
- if (!used_signals_nodrivers.check_any(sig)) {
- if (!unused_bits.empty())
- unused_bits += " ";
- unused_bits += stringf("%zd", i);
- }
- }
- if (unused_bits.empty() || wire->port_id != 0)
- wire->attributes.erase("\\unused_bits");
- else
- wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits);
- } else {
- wire->attributes.erase("\\unused_bits");
- }
- }
-
- int del_wires_count = 0;
- for (auto wire : del_wires)
- if (!used_signals.check_any(RTLIL::SigSpec(wire))) {
- if (check_public_name(wire->name)) {
- log(" removing unused non-port wire %s.\n", wire->name.c_str());
- del_wires_count++;
- }
- module->wires.erase(wire->name);
- delete wire;
- }
-
- if (del_wires_count > 0)
- log(" removed %d unused temporary wires.\n", del_wires_count);
-}
-
-static void rmunused_module(RTLIL::Module *module)
-{
- log("Finding unused cells or wires in module %s..\n", module->name.c_str());
-
- rmunused_module_cells(module);
- rmunused_module_signals(module);
-}
-
-struct OptRmUnusedPass : public Pass {
- OptRmUnusedPass() : Pass("opt_rmunused", "remove unused cells and wires") { }
- virtual void help()
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" opt_rmunused [selection]\n");
- log("\n");
- log("This pass identifies wires and cells that are unused and removes them. Other\n");
- log("passes often remove cells but leave the wires in the design or reconnect the\n");
- log("wires but leave the old cells in the design. This pass can be used to clean up\n");
- log("after the passes that do the actual work.\n");
- log("\n");
- log("This pass only operates on completely selected modules without processes.\n");
- log("\n");
- }
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
- {
- log_header("Executing OPT_RMUNUSED pass (remove unused cells and wires).\n");
- log_push();
-
- extra_args(args, 1, design);
-
- ct.setup_internals();
- ct.setup_internals_mem();
- ct.setup_stdcells();
- ct.setup_stdcells_mem();
-
- for (auto &mod_it : design->modules) {
- if (!design->selected_whole_module(mod_it.first)) {
- if (design->selected(mod_it.second))
- log("Skipping module %s as it is only partially selected.\n", id2cstr(mod_it.second->name));
- continue;
- }
- if (mod_it.second->processes.size() > 0) {
- log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str());
- } else {
- rmunused_module(mod_it.second);
- }
- }
-
- ct.clear();
- log_pop();
- }
-} OptRmUnusedPass;
-
if (opt_name.empty())
{
- Pass::call(design, "opt_rmunused");
+ Pass::call(design, "opt_clean");
log_header("Continuing SUBMOD pass.\n");
std::set<std::string> handled_modules;
}
}
- Pass::call(design, "opt_rmunused");
+ Pass::call(design, "opt_clean");
}
else
{