aboutsummaryrefslogtreecommitdiffstats
path: root/passes/opt
diff options
context:
space:
mode:
Diffstat (limited to 'passes/opt')
-rw-r--r--passes/opt/opt_clean.cc171
1 files changed, 90 insertions, 81 deletions
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 9f6212526..6ca6ac820 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -64,7 +64,7 @@ struct keep_cache_t
bool query(Cell *cell)
{
- if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover"))
+ if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3", "$specrule"))
return true;
if (cell->has_keep_attr())
@@ -85,22 +85,34 @@ void rmunused_module_cells(Module *module, bool verbose)
{
SigMap sigmap(module);
pool<Cell*> queue, unused;
+ pool<SigBit> used_raw_bits;
dict<SigBit, pool<Cell*>> wire2driver;
+ dict<SigBit, vector<string>> driver_driver_logs;
+
+ SigMap raw_sigmap;
+ for (auto &it : module->connections_) {
+ for (int i = 0; i < GetSize(it.second); i++) {
+ if (it.second[i].wire != nullptr)
+ raw_sigmap.add(it.first[i], it.second[i]);
+ }
+ }
for (auto &it : module->cells_) {
Cell *cell = it.second;
for (auto &it2 : cell->connections()) {
- if (!ct_all.cell_known(cell->type) || ct_all.cell_output(cell->type, it2.first))
- for (auto raw_bit : it2.second) {
- if (raw_bit.wire == nullptr)
- continue;
- auto bit = sigmap(raw_bit);
- if (bit.wire == nullptr)
- log_warning("Driver-driver conflict for %s between cell %s.%s and constant %s in %s: Resolved using constant.\n",
- log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module));
- if (bit.wire != nullptr)
- wire2driver[bit].insert(cell);
- }
+ if (ct_all.cell_known(cell->type) && !ct_all.cell_output(cell->type, it2.first))
+ continue;
+ for (auto raw_bit : it2.second) {
+ if (raw_bit.wire == nullptr)
+ continue;
+ auto bit = sigmap(raw_bit);
+ if (bit.wire == nullptr)
+ driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict "
+ "for %s between cell %s.%s and constant %s in %s: Resolved using constant.",
+ log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module)));
+ if (bit.wire != nullptr)
+ wire2driver[bit].insert(cell);
+ }
}
if (keep_cache.query(cell))
queue.insert(cell);
@@ -114,6 +126,8 @@ void rmunused_module_cells(Module *module, bool verbose)
for (auto bit : sigmap(wire))
for (auto c : wire2driver[bit])
queue.insert(c), unused.erase(c);
+ for (auto raw_bit : SigSpec(wire))
+ used_raw_bits.insert(raw_sigmap(raw_bit));
}
}
@@ -142,6 +156,22 @@ void rmunused_module_cells(Module *module, bool verbose)
module->remove(cell);
count_rm_cells++;
}
+
+ for (auto &it : module->cells_) {
+ Cell *cell = it.second;
+ for (auto &it2 : cell->connections()) {
+ if (ct_all.cell_known(cell->type) && !ct_all.cell_input(cell->type, it2.first))
+ continue;
+ for (auto raw_bit : raw_sigmap(it2.second))
+ used_raw_bits.insert(raw_bit);
+ }
+ }
+
+ for (auto it : driver_driver_logs) {
+ if (used_raw_bits.count(it.first))
+ for (auto msg : it.second)
+ log_warning("%s\n", msg.c_str());
+ }
}
int count_nontrivial_wire_attrs(RTLIL::Wire *w)
@@ -276,7 +306,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
}
}
- std::vector<RTLIL::Wire*> maybe_del_wires;
+ pool<RTLIL::Wire*> del_wires_queue;
for (auto wire : module->wires())
{
SigSpec s1 = SigSpec(wire), s2 = assign_map(s1);
@@ -290,22 +320,32 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
if (initval.is_fully_undef())
wire->attributes.erase("\\init");
- bool maybe_del = false;
+ if (GetSize(wire) == 0) {
+ // delete zero-width wires
+ goto delete_this_wire;
+ } else
if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) {
- /* do not delete anything with "keep" or module ports or initialized wires */
+ // do not delete anything with "keep" or module ports or initialized wires
} else
if (!purge_mode && check_public_name(wire->name)) {
- /* do not get rid of public names unless in purge mode */
- } else {
- if (!raw_used_signals_noaliases.check_any(s1))
- maybe_del = true;
- if (!used_signals_nodrivers.check_any(s2))
- maybe_del = true;
+ // do not get rid of public names unless in purge mode
+ } else
+ if (!raw_used_signals_noaliases.check_any(s1)) {
+ // delete wires that aren't used by anything directly
+ goto delete_this_wire;
+ } else
+ if (!used_signals_nodrivers.check_any(s2)) {
+ // delete wires that aren't used by anything indirectly, even though other wires may alias it
+ goto delete_this_wire;
}
- if (maybe_del) {
- maybe_del_wires.push_back(wire);
- } else {
+ if (0)
+ {
+ delete_this_wire:
+ del_wires_queue.insert(wire);
+ }
+ else
+ {
RTLIL::SigSig new_conn;
for (int i = 0; i < GetSize(s1); i++)
if (s1[i] != s2[i]) {
@@ -325,72 +365,41 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
used_signals.add(new_conn.second);
module->connect(new_conn);
}
- }
- if (!used_signals_nodrivers.check_all(s2)) {
- std::string unused_bits;
- for (int i = 0; i < GetSize(s2); i++) {
- if (s2[i].wire == NULL)
- continue;
- if (!used_signals_nodrivers.check(s2[i])) {
- if (!unused_bits.empty())
- unused_bits += " ";
- unused_bits += stringf("%d", 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");
- }
- }
-
-
- pool<RTLIL::Wire*> del_wires;
-
- int del_wires_count = 0;
- for (auto wire : maybe_del_wires) {
- SigSpec s1 = SigSpec(wire);
- if (used_signals_nodrivers.check_any(s1)) {
- SigSpec s2 = assign_map(s1);
- Const initval;
- if (wire->attributes.count("\\init"))
- initval = wire->attributes.at("\\init");
- if (GetSize(initval) != GetSize(wire))
- initval.bits.resize(GetSize(wire), State::Sx);
- RTLIL::SigSig new_conn;
- for (int i = 0; i < GetSize(s1); i++)
- if (s1[i] != s2[i]) {
- if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) {
- s2[i] = initval[i];
- initval[i] = State::Sx;
+ if (!used_signals_nodrivers.check_all(s2)) {
+ std::string unused_bits;
+ for (int i = 0; i < GetSize(s2); i++) {
+ if (s2[i].wire == NULL)
+ continue;
+ if (!used_signals_nodrivers.check(s2[i])) {
+ if (!unused_bits.empty())
+ unused_bits += " ";
+ unused_bits += stringf("%d", i);
}
- new_conn.first.append_bit(s1[i]);
- new_conn.second.append_bit(s2[i]);
}
- if (new_conn.first.size() > 0) {
- if (initval.is_fully_undef())
- wire->attributes.erase("\\init");
+ if (unused_bits.empty() || wire->port_id != 0)
+ wire->attributes.erase("\\unused_bits");
else
- wire->attributes.at("\\init") = initval;
- module->connect(new_conn);
- }
- } else {
- if (ys_debug() || (check_public_name(wire->name) && verbose)) {
- log_debug(" removing unused non-port wire %s.\n", wire->name.c_str());
+ wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits);
+ } else {
+ wire->attributes.erase("\\unused_bits");
}
- del_wires.insert(wire);
- del_wires_count++;
}
}
- module->remove(del_wires);
- count_rm_wires += del_wires.size();
+ int del_temp_wires_count = 0;
+ for (auto wire : del_wires_queue) {
+ if (ys_debug() || (check_public_name(wire->name) && verbose))
+ log_debug(" removing unused non-port wire %s.\n", wire->name.c_str());
+ else
+ del_temp_wires_count++;
+ }
+
+ module->remove(del_wires_queue);
+ count_rm_wires += GetSize(del_wires_queue);
- if (verbose && del_wires_count > 0)
- log_debug(" removed %d unused temporary wires.\n", del_wires_count);
+ if (verbose && del_temp_wires_count)
+ log_debug(" removed %d unused temporary wires.\n", del_temp_wires_count);
}
bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)