Improve opt_expr and opt_clean handling of (partially) undriven and/or unused wires...
authorClifford Wolf <clifford@clifford.at>
Fri, 3 May 2019 12:24:53 +0000 (14:24 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 3 May 2019 12:25:01 +0000 (14:25 +0200)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
passes/opt/opt_clean.cc
passes/opt/opt_expr.cc

index 5d95c4f1afd69bbb4e78f1a1ec920084273b0dba..96118e906e7e44b8fdf3edf5f787cf3756eb03ac 100644 (file)
@@ -274,50 +274,53 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
        std::vector<RTLIL::Wire*> maybe_del_wires;
        for (auto wire : module->wires())
        {
+               SigSpec s1 = SigSpec(wire), s2 = assign_map(s1);
+               log_assert(GetSize(s1) == GetSize(s2));
+
+               bool maybe_del = false;
                if ((!purge_mode && check_public_name(wire->name)) || wire->port_id != 0 || wire->get_bool_attribute("\\keep") || wire->attributes.count("\\init")) {
-                       RTLIL::SigSpec s1 = RTLIL::SigSpec(wire), s2 = s1;
-                       assign_map.apply(s2);
-                       if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep")) {
-                               maybe_del_wires.push_back(wire);
-                       } else {
-                               log_assert(GetSize(s1) == GetSize(s2));
-                               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;
-                                               }
-                                               new_conn.first.append_bit(s1[i]);
-                                               new_conn.second.append_bit(s2[i]);
+                       if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep"))
+                               maybe_del = true;
+               } else {
+                       if (!used_signals.check_any(s2))
+                               maybe_del = true;
+               }
+
+               if (maybe_del) {
+                       maybe_del_wires.push_back(wire);
+               } else {
+                       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 (new_conn.first.size() > 0) {
-                                       if (initval.is_fully_undef())
-                                               wire->attributes.erase("\\init");
-                                       else
-                                               wire->attributes.at("\\init") = initval;
-                                       used_signals.add(new_conn.first);
-                                       used_signals.add(new_conn.second);
-                                       module->connect(new_conn);
+                                       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");
+                               else
+                                       wire->attributes.at("\\init") = initval;
+                               used_signals.add(new_conn.first);
+                               used_signals.add(new_conn.second);
+                               module->connect(new_conn);
                        }
-               } else {
-                       if (!used_signals.check_any(RTLIL::SigSpec(wire)))
-                               maybe_del_wires.push_back(wire);
                }
 
-               RTLIL::SigSpec sig = assign_map(RTLIL::SigSpec(wire));
-               if (!used_signals_nodrivers.check_any(sig)) {
+               if (!used_signals_nodrivers.check_all(s2)) {
                        std::string unused_bits;
-                       for (int i = 0; i < GetSize(sig); i++) {
-                               if (sig[i].wire == NULL)
+                       for (int i = 0; i < GetSize(s2); i++) {
+                               if (s2[i].wire == NULL)
                                        continue;
-                               if (!used_signals_nodrivers.check(sig[i])) {
+                               if (!used_signals_nodrivers.check(s2[i])) {
                                        if (!unused_bits.empty())
                                                unused_bits += " ";
                                        unused_bits += stringf("%d", i);
@@ -336,14 +339,40 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
        pool<RTLIL::Wire*> del_wires;
 
        int del_wires_count = 0;
-       for (auto wire : maybe_del_wires)
-               if (!used_signals.check_any(RTLIL::SigSpec(wire))) {
-                       if (check_public_name(wire->name) && verbose) {
+       for (auto wire : maybe_del_wires) {
+               SigSpec s1 = SigSpec(wire);
+               if (used_signals.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;
+                                       }
+                                       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");
+                               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());
                        }
                        del_wires.insert(wire);
                        del_wires_count++;
                }
+       }
 
        module->remove(del_wires);
        count_rm_wires += del_wires.size();
@@ -496,6 +525,9 @@ struct OptCleanPass : public Pass {
 
                ct_all.setup(design);
 
+               count_rm_cells = 0;
+               count_rm_wires = 0;
+
                for (auto module : design->selected_whole_modules_warn()) {
                        if (module->has_processes_warn())
                                continue;
@@ -561,7 +593,7 @@ struct CleanPass : public Pass {
                for (auto module : design->selected_whole_modules()) {
                        if (module->has_processes())
                                continue;
-                       rmunused_module(module, purge_mode, false, false);
+                       rmunused_module(module, purge_mode, ys_debug(), false);
                }
 
                log_suppressed();
index b445afdc806114cae94d3376cfa5b168961055a4..512ef0cbf2f80a5ea3265516fc72dcc4379dc332 100644 (file)
@@ -61,7 +61,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
                }
                if (wire->port_input)
                        driven_signals.add(sigmap(wire));
-               if (wire->port_output)
+               if (wire->port_output || wire->get_bool_attribute("\\keep"))
                        used_signals.add(sigmap(wire));
                all_signals.add(sigmap(wire));
        }
@@ -88,7 +88,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
                        }
                }
 
-               log_debug("Setting undriven signal in %s to constant: %s = %s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(val));
+               log_debug("Setting undriven signal in %s to constant: %s = %s\n", log_id(module), log_signal(sig), log_signal(val));
                module->connect(sig, val);
                did_something = true;
        }
@@ -104,10 +104,15 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
                                if (SigBit(initval[i]) == sig[i])
                                        initval[i] = State::Sx;
                        }
-                       if (initval.is_fully_undef())
+                       if (initval.is_fully_undef()) {
+                               log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire));
                                wire->attributes.erase("\\init");
-                       else
+                               did_something = true;
+                       } else if (initval != wire->attributes.at("\\init")) {
+                               log_debug("Updating init attribute on %s/%s: %s\n", log_id(module), log_id(wire), log_signal(initval));
                                wire->attributes["\\init"] = initval;
+                               did_something = true;
+                       }
                }
        }
 }