Merge pull request #1465 from YosysHQ/dave/ice40_timing_sim
[yosys.git] / passes / techmap / deminout.cc
index ed4e457621379b61bee75c41a3cefc204cc608e3..b976b401b0db72ce755e8f7fee31de636481eb2b 100644 (file)
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
 
 struct DeminoutPass : public Pass {
        DeminoutPass() : Pass("deminout", "demote inout ports to input or output") { }
-       virtual void help()
+       void help() YS_OVERRIDE
        {
                log("\n");
                log("    deminout [options] [selection]\n");
@@ -33,7 +33,7 @@ struct DeminoutPass : public Pass {
                log("\"Demote\" inout ports to input or output ports, if possible.\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
        {
                log_header(design, "Executing DEMINOUT pass (demote inout ports to input or output).\n");
 
@@ -57,7 +57,7 @@ struct DeminoutPass : public Pass {
                        for (auto module : design->selected_modules())
                        {
                                SigMap sigmap(module);
-                               pool<SigBit> bits_written, bits_used, bits_inout;
+                               pool<SigBit> bits_written, bits_used, bits_inout, bits_tribuf;
                                dict<SigBit, int> bits_numports;
 
                                for (auto wire : module->wires())
@@ -82,6 +82,25 @@ struct DeminoutPass : public Pass {
                                        if (cellport_in)
                                                for (auto bit : sigmap(conn.second))
                                                        bits_used.insert(bit);
+
+                                       if (conn.first == ID::Y && cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_TBUF_), ID($tribuf)))
+                                       {
+                                               bool tribuf = cell->type.in(ID($_TBUF_), ID($tribuf));
+
+                                               if (!tribuf) {
+                                                       for (auto &c : cell->connections()) {
+                                                               if (!c.first.in(ID::A, ID::B))
+                                                                       continue;
+                                                               for (auto b : sigmap(c.second))
+                                                                       if (b == State::Sz)
+                                                                               tribuf = true;
+                                                       }
+                                               }
+
+                                               if (tribuf)
+                                                       for (auto bit : sigmap(conn.second))
+                                                               bits_tribuf.insert(bit);
+                                       }
                                }
 
                                for (auto wire : module->selected_wires())
@@ -94,11 +113,17 @@ struct DeminoutPass : public Pass {
                                                {
                                                        if (bits_numports[bit] > 1 || bits_inout.count(bit))
                                                                new_input = true, new_output = true;
-
-                                                       if (bits_written.count(bit))
+                                                       if (bit == State::S0 || bit == State::S1)
+                                                               new_output = true;
+                                                       if (bits_written.count(bit)) {
                                                                new_output = true;
-                                                       else if (bits_used.count(bit))
-                                                               new_input = true;
+                                                               if (bits_tribuf.count(bit))
+                                                                       goto tribuf_bit;
+                                                       } else {
+                                               tribuf_bit:
+                                                               if (bits_used.count(bit))
+                                                                       new_input = true;
+                                                       }
                                                }
 
                                                if (new_input != new_output) {