Added opt_const -undriven
authorClifford Wolf <clifford@clifford.at>
Thu, 6 Feb 2014 14:49:03 +0000 (15:49 +0100)
committerClifford Wolf <clifford@clifford.at>
Thu, 6 Feb 2014 14:49:03 +0000 (15:49 +0100)
passes/opt/opt.cc
passes/opt/opt_const.cc

index 53c27e0f50de7ff5497b1b9a3e0b28449da98529..8d259f34d97582e6a125321fc3c30487f5bbe585 100644 (file)
@@ -31,7 +31,7 @@ struct OptPass : public Pass {
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
-               log("    opt [-mux_undef] [-mux_bool] [selection]\n");
+               log("    opt [-mux_undef] [-mux_bool] [-undriven] [selection]\n");
                log("\n");
                log("This pass calls all the other opt_* passes in a useful order. This performs\n");
                log("a series of trivial optimizations and cleanups. This pass executes the other\n");
@@ -46,7 +46,7 @@ struct OptPass : public Pass {
                log("        opt_share\n");
                log("        opt_rmdff\n");
                log("        opt_clean\n");
-               log("        opt_const [-mux_undef] [-mux_bool]\n");
+               log("        opt_const [-mux_undef] [-mux_bool] [-undriven]\n");
                log("    while [changed design]\n");
                log("\n");
        }
@@ -67,6 +67,10 @@ struct OptPass : public Pass {
                                opt_const_args += " -mux_bool";
                                continue;
                        }
+                       if (args[argidx] == "-undriven") {
+                               opt_const_args += " -undriven";
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
index 2bb542c29c92d5c54a1becd35659ce76fb23cb7c..34d1a69c1baafcf3771573648aa48832bdfb42f1 100644 (file)
@@ -20,6 +20,7 @@
 #include "opt_status.h"
 #include "kernel/register.h"
 #include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
 #include "kernel/log.h"
 #include <stdlib.h>
 #include <assert.h>
 
 static bool did_something;
 
+void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
+{
+       CellTypes ct(design);
+       SigMap sigmap(module);
+       SigPool driven_signals;
+       SigPool used_signals;
+       SigPool all_signals;
+
+       for (auto &it : module->cells)
+       for (auto &conn : it.second->connections) {
+               if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first))
+                       driven_signals.add(sigmap(conn.second));
+               if (!ct.cell_known(it.second->type) || ct.cell_input(it.second->type, conn.first))
+                       used_signals.add(sigmap(conn.second));
+       }
+
+       for (auto &it : module->wires) {
+               if (it.second->port_input)
+                       driven_signals.add(sigmap(it.second));
+               if (it.second->port_output)
+                       used_signals.add(sigmap(it.second));
+               all_signals.add(sigmap(it.second));
+       }
+
+       all_signals.del(driven_signals);
+       RTLIL::SigSpec undriven_signals = all_signals.export_all();
+
+       for (auto &c : undriven_signals.chunks)
+       {
+               RTLIL::SigSpec sig = c;
+
+               if (c.wire->name[0] == '$')
+                       sig = used_signals.extract(sig);
+               if (sig.width == 0)
+                       continue;
+
+               log("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c));
+               module->connections.push_back(RTLIL::SigSig(c, RTLIL::SigSpec(RTLIL::State::Sx, c.width)));
+               OPT_DID_SOMETHING = true;
+       }
+}
+
 void replace_cell(RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val)
 {
        RTLIL::SigSpec Y = cell->connections[out_port];
        log("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
                        cell->type.c_str(), cell->name.c_str(), info.c_str(),
                        module->name.c_str(), log_signal(Y), log_signal(out_val));
-       OPT_DID_SOMETHING = true;
        // ILANG_BACKEND::dump_cell(stderr, "--> ", cell);
        module->connections.push_back(RTLIL::SigSig(Y, out_val));
        module->cells.erase(cell->name);
        delete cell;
+       OPT_DID_SOMETHING = true;
        did_something = true;
 }
 
@@ -76,6 +119,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                        cell->connections["\\A"] = cell->connections["\\B"];
                        cell->connections["\\B"] = tmp;
                        cell->connections["\\S"] = invert_map.at(assign_map(cell->connections["\\S"]));
+                       OPT_DID_SOMETHING = true;
                        did_something = true;
                        goto next_cell;
                }
@@ -263,6 +307,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                                cell->type = "$not";
                        } else
                                cell->type = "$_INV_";
+                       OPT_DID_SOMETHING = true;
                        did_something = true;
                        goto next_cell;
                }
@@ -280,6 +325,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                                cell->type = "$and";
                        } else
                                cell->type = "$_AND_";
+                       OPT_DID_SOMETHING = true;
                        did_something = true;
                        goto next_cell;
                }
@@ -297,6 +343,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                                cell->type = "$or";
                        } else
                                cell->type = "$_or_";
+                       OPT_DID_SOMETHING = true;
                        did_something = true;
                        goto next_cell;
                }
@@ -342,6 +389,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                                        cell->type = "$mux";
                                        cell->parameters.erase("\\S_WIDTH");
                                }
+                               OPT_DID_SOMETHING = true;
                                did_something = true;
                        }
                }
@@ -452,11 +500,15 @@ struct OptConstPass : public Pass {
                log("    -mux_bool\n");
                log("        replace $mux cells with inverters or buffers when possible\n");
                log("\n");
+               log("    -undriven\n");
+               log("        replace undriven nets with undef (x) constants\n");
+               log("\n");
        }
        virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
        {
                bool mux_undef = false;
                bool mux_bool = false;
+               bool undriven = false;
 
                log_header("Executing OPT_CONST pass (perform const folding).\n");
                log_push();
@@ -471,11 +523,19 @@ struct OptConstPass : public Pass {
                                mux_bool = true;
                                continue;
                        }
+                       if (args[argidx] == "-undriven") {
+                               undriven = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
 
                for (auto &mod_it : design->modules)
+               {
+                       if (undriven)
+                               replace_undriven(design, mod_it.second);
+
                        do {
                                do {
                                        did_something = false;
@@ -483,6 +543,7 @@ struct OptConstPass : public Pass {
                                } while (did_something);
                                replace_const_cells(design, mod_it.second, true, mux_undef, mux_bool);
                        } while (did_something);
+               }
 
                log_pop();
        }