summaryrefslogtreecommitdiff
path: root/passes/opt/opt_clean.cc
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2018-08-30 20:46:20 +0200
committerRuben Undheim <ruben.undheim@gmail.com>2018-08-30 20:46:20 +0200
commit5033b51947a6ef02cb785b5622e993335efa750a (patch)
tree7bed18c526bd94917fa2f08e3df12209863698a1 /passes/opt/opt_clean.cc
parentfefe0fc0430f4f173a25e674708aa0f4f0854b31 (diff)
New upstream version 0.7+20180830git0b7a184
Diffstat (limited to 'passes/opt/opt_clean.cc')
-rw-r--r--passes/opt/opt_clean.cc107
1 files changed, 95 insertions, 12 deletions
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 6600ffa2..c3b13aca 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"))
+ if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover"))
return true;
if (cell->has_keep_attr())
@@ -91,9 +91,16 @@ void rmunused_module_cells(Module *module, bool verbose)
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 bit : sigmap(it2.second))
+ 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 (keep_cache.query(cell))
queue.insert(cell);
@@ -320,19 +327,89 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
if (!used_signals.check_any(RTLIL::SigSpec(wire))) {
if (check_public_name(wire->name) && verbose) {
log(" removing unused non-port wire %s.\n", wire->name.c_str());
- del_wires_count++;
}
del_wires.insert(wire);
+ del_wires_count++;
}
module->remove(del_wires);
- count_rm_wires += del_wires.size();;
+ count_rm_wires += del_wires.size();
- if (del_wires_count > 0)
+ if (verbose && del_wires_count > 0)
log(" removed %d unused temporary wires.\n", del_wires_count);
}
-void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose)
+bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
+{
+ bool did_something = false;
+ CellTypes fftypes;
+ fftypes.setup_internals_mem();
+
+ SigMap sigmap(module);
+ dict<SigBit, State> qbits;
+
+ for (auto cell : module->cells())
+ if (fftypes.cell_known(cell->type) && cell->hasPort("\\Q"))
+ {
+ SigSpec sig = cell->getPort("\\Q");
+
+ for (int i = 0; i < GetSize(sig); i++)
+ {
+ SigBit bit = sig[i];
+
+ if (bit.wire == nullptr || bit.wire->attributes.count("\\init") == 0)
+ continue;
+
+ Const init = bit.wire->attributes.at("\\init");
+
+ if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz)
+ continue;
+
+ sigmap.add(bit);
+ qbits[bit] = init[i];
+ }
+ }
+
+ for (auto wire : module->wires())
+ {
+ if (!purge_mode && wire->name[0] == '\\')
+ continue;
+
+ if (wire->attributes.count("\\init") == 0)
+ continue;
+
+ Const init = wire->attributes.at("\\init");
+
+ for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++)
+ {
+ if (init[i] == State::Sx || init[i] == State::Sz)
+ continue;
+
+ SigBit wire_bit = SigBit(wire, i);
+ SigBit mapped_wire_bit = sigmap(wire_bit);
+
+ if (wire_bit == mapped_wire_bit)
+ goto next_wire;
+
+ if (qbits.count(sigmap(SigBit(wire, i))) == 0)
+ goto next_wire;
+
+ if (qbits.at(sigmap(SigBit(wire, i))) != init[i])
+ goto next_wire;
+ }
+
+ if (verbose)
+ log(" removing redundant init attribute on %s.\n", log_id(wire));
+
+ wire->attributes.erase("\\init");
+ did_something = true;
+ next_wire:;
+ }
+
+ return did_something;
+}
+
+void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool rminit)
{
if (verbose)
log("Finding unused cells or wires in module %s..\n", module->name.c_str());
@@ -358,11 +435,14 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose)
rmunused_module_cells(module, verbose);
rmunused_module_signals(module, purge_mode, verbose);
+
+ if (rminit && rmunused_module_init(module, purge_mode, verbose))
+ rmunused_module_signals(module, purge_mode, verbose);
}
struct OptCleanPass : public Pass {
OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -379,7 +459,7 @@ struct OptCleanPass : public Pass {
log(" also remove internal nets if they have a public 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
{
bool purge_mode = false;
@@ -406,9 +486,12 @@ struct OptCleanPass : public Pass {
for (auto module : design->selected_whole_modules_warn()) {
if (module->has_processes_warn())
continue;
- rmunused_module(module, purge_mode, true);
+ rmunused_module(module, purge_mode, true, true);
}
+ if (count_rm_cells > 0 || count_rm_wires > 0)
+ log("Removed %d unused cells and %d unused wires.\n", count_rm_cells, count_rm_wires);
+
design->optimize();
design->sort();
design->check();
@@ -422,7 +505,7 @@ struct OptCleanPass : public Pass {
struct CleanPass : public Pass {
CleanPass() : Pass("clean", "remove unused cells and wires") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -437,7 +520,7 @@ struct CleanPass : public Pass {
log("in -purge mode between the commands.\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 purge_mode = false;
@@ -465,7 +548,7 @@ struct CleanPass : public Pass {
for (auto module : design->selected_whole_modules()) {
if (module->has_processes())
continue;
- rmunused_module(module, purge_mode, false);
+ rmunused_module(module, purge_mode, false, false);
}
if (count_rm_cells > 0 || count_rm_wires > 0)