iopadmap: Fix z assignment to inout port
authorMarcin Kościelnicki <mwk@0x04.net>
Mon, 30 Mar 2020 13:35:31 +0000 (15:35 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Thu, 2 Apr 2020 16:15:04 +0000 (18:15 +0200)
Fixes #1841.

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

index 8b186223765cd9bc27cdef91272707ac09a6a86b..f754aecb80b7119ae99e627ed9ba70bdd761ebc2 100644 (file)
@@ -229,11 +229,13 @@ struct IopadmapPass : public Pass {
                for (auto module : design->selected_modules())
                {
                        dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits;
+                       pool<SigSig> remove_conns;
 
                        if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
                        {
                                dict<SigBit, Cell *> tbuf_bits;
                                pool<SigBit> driven_bits;
+                               dict<SigBit, SigSig> z_conns;
 
                                // Gather tristate buffers and always-on drivers.
                                for (auto cell : module->cells())
@@ -252,8 +254,10 @@ struct IopadmapPass : public Pass {
                                        for (int i = 0; i < GetSize(conn.first); i++) {
                                                SigBit dstbit = conn.first[i];
                                                SigBit srcbit = conn.second[i];
-                                               if (!srcbit.wire && srcbit.data == State::Sz)
+                                               if (!srcbit.wire && srcbit.data == State::Sz) {
+                                                       z_conns[dstbit] = conn;
                                                        continue;
+                                               }
                                                driven_bits.insert(dstbit);
                                        }
 
@@ -302,6 +306,8 @@ struct IopadmapPass : public Pass {
                                                        // enable.
                                                        en_sig = SigBit(State::S0);
                                                        data_sig = SigBit(State::Sx);
+                                                       if (z_conns.count(wire_bit))
+                                                               remove_conns.insert(z_conns[wire_bit]);
                                                }
 
                                                if (wire->port_input)
@@ -454,6 +460,14 @@ struct IopadmapPass : public Pass {
                                }
                        }
 
+                       if (!remove_conns.empty()) {
+                               std::vector<SigSig> new_conns;
+                               for (auto &conn : module->connections())
+                                       if (!remove_conns.count(conn))
+                                               new_conns.push_back(conn);
+                               module->new_connections(new_conns);
+                       }
+
                        for (auto &it : rewrite_bits) {
                                RTLIL::Wire *wire = it.first;
                                RTLIL::Wire *new_wire = module->addWire(
index 25ea94dfce2082360f8bca8f304585504552dbe0..df029b3a0395df2a171a883eaea904772f6dd221 100644 (file)
@@ -55,13 +55,19 @@ obuf b (.i(i), .o(tmp));
 assign o = tmp;
 endmodule
 
+module k(inout o, o2);
+assign o = 1'bz;
+endmodule
+
 EOT
 
 opt_clean
 tribuf
 simplemap
-iopadmap -bits -inpad ibuf o:i -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io a b c d e f g h i j
+iopadmap -bits -inpad ibuf o:i -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io a b c d e f g h i j k
 opt_clean
+hierarchy -check
+check
 
 select -assert-count 1 a/t:ibuf
 select -assert-count 1 a/t:obuf
@@ -140,6 +146,8 @@ select -assert-count 0 i/t:obuf
 select -assert-count 1 j/t:ibuf
 select -assert-count 1 j/t:obuf
 
+select -assert-count 2 k/t:iobuf
+
 
 # Check that \init attributes get moved from output buffer
 #   to buffer input