opt_clean: Make the init attribute follow the FF's Q.
authorMarcelina Kościelnicka <mwk@0x04.net>
Sat, 21 Aug 2021 21:36:00 +0000 (23:36 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Sun, 22 Aug 2021 13:38:29 +0000 (15:38 +0200)
Previously, opt_clean would reconnect all ports (including FF Q ports)
to a "canonical" SigBit chosen by complex rules, but would leave the
init attribute on the old wire.  This change applies the same
canonicalization rules to the init attributes, ensuring that init moves
to wherever the Q port moved.

Part of another jab at #2920.

passes/opt/opt_clean.cc
tests/techmap/iopadmap.ys

index 08e9d6b791c622f4ebccf01e6a9d1c87264d1007..cb2c261c44ebc638c79861d961d9ce55cf24a534 100644 (file)
@@ -339,6 +339,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
                                used_signals_nodrivers.add(it2.second);
                }
        }
+       dict<RTLIL::SigBit, RTLIL::State> init_bits;
        for (auto &it : module->wires_) {
                RTLIL::Wire *wire = it.second;
                if (wire->port_id > 0) {
@@ -354,6 +355,29 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
                        assign_map.apply(sig);
                        used_signals.add(sig);
                }
+               auto it2 = wire->attributes.find(ID::init);
+               if (it2 != wire->attributes.end()) {
+                       RTLIL::Const &val = it2->second;
+                       SigSpec sig = assign_map(wire);
+                       for (int i = 0; i < GetSize(val) && i < GetSize(sig); i++)
+                               if (val.bits[i] != State::Sx)
+                                       init_bits[sig[i]] = val.bits[i];
+                       wire->attributes.erase(it2);
+               }
+       }
+
+       for (auto wire : module->wires()) {
+               bool found = false;
+               Const val(State::Sx, wire->width);
+               for (int i = 0; i < wire->width; i++) {
+                       auto it = init_bits.find(RTLIL::SigBit(wire, i));
+                       if (it != init_bits.end()) {
+                               val.bits[i] = it->second;
+                               found = true;
+                       }
+               }
+               if (found)
+                       wire->attributes[ID::init] = val;
        }
 
        pool<RTLIL::Wire*> del_wires_queue;
index df029b3a0395df2a171a883eaea904772f6dd221..f8e6bc37400f5def949fde335b0781646128b50d 100644 (file)
@@ -169,7 +169,7 @@ sub s2(.i(i[1]), .o(w[1]));
 assign o = oe ? w : 2'bz;
 endmodule
 
-module c(input i, oe, (* init=2'b00 *) inout io, output o1, o2);
+module c(input i, oe, (* init=1'b0 *) inout io, output o1, o2);
 assign io = oe ? i : 1'bz;
 assign {o1,o2} = {io,io};
 endmodule
@@ -182,5 +182,5 @@ select -assert-count 1 a/c:s %co a/a:init=1'b1 %i
 select -assert-count 1 a/a:init
 select -assert-count 1 b/c:s* %co %a b/a:init=2'b1x %i
 select -assert-count 1 b/a:init
-select -assert-count 1 c/t:iobuf %co c/a:init=2'b00 %i
+select -assert-count 1 c/t:iobuf %co c/a:init=1'b0 %i
 select -assert-count 1 c/a:init