Fix dffmux peepopt init handling
authorClifford Wolf <clifford@clifford.at>
Wed, 16 Oct 2019 09:40:32 +0000 (11:40 +0200)
committerClifford Wolf <clifford@clifford.at>
Wed, 16 Oct 2019 09:40:32 +0000 (11:40 +0200)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
passes/pmgen/peepopt.cc
passes/pmgen/peepopt_dffmux.pmg

index 72b02127a63c4c5a07125bf4971422b6973867d2..2230145df943e0d2917c99b0c083bcb3f820b92f 100644 (file)
@@ -24,8 +24,11 @@ USING_YOSYS_NAMESPACE
 PRIVATE_NAMESPACE_BEGIN
 
 bool did_something;
+dict<SigBit, State> initbits;
+pool<SigBit> rminitbits;
 
 #include "passes/pmgen/peepopt_pm.h"
+#include "generate.h"
 
 struct PeepoptPass : public Pass {
        PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { }
@@ -40,27 +43,86 @@ struct PeepoptPass : public Pass {
        }
        void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
        {
+               std::string genmode;
+
                log_header(design, "Executing PEEPOPT pass (run peephole optimizers).\n");
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++)
                {
-                       // if (args[argidx] == "-singleton") {
-                       //      singleton_mode = true;
-                       //      continue;
-                       // }
+                       if (args[argidx] == "-generate" && argidx+1 < args.size()) {
+                               genmode = args[++argidx];
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
 
-               for (auto module : design->selected_modules()) {
+               if (!genmode.empty())
+               {
+                       initbits.clear();
+                       rminitbits.clear();
+
+                       if (genmode == "shiftmul")
+                               GENERATE_PATTERN(peepopt_pm, shiftmul);
+                       else if (genmode == "muldiv")
+                               GENERATE_PATTERN(peepopt_pm, muldiv);
+                       else if (genmode == "dffmux")
+                               GENERATE_PATTERN(peepopt_pm, dffmux);
+                       else
+                               log_abort();
+                       return;
+               }
+
+               for (auto module : design->selected_modules())
+               {
                        did_something = true;
-                       while (did_something) {
+
+                       while (did_something)
+                       {
                                did_something = false;
-                               peepopt_pm pm(module, module->selected_cells());
+                               initbits.clear();
+                               rminitbits.clear();
+
+                               peepopt_pm pm(module);
+
+                               for (auto w : module->wires()) {
+                                       auto it = w->attributes.find(ID(init));
+                                       if (it != w->attributes.end()) {
+                                               SigSpec sig = pm.sigmap(w);
+                                               Const val = it->second;
+                                               int len = std::min(GetSize(sig), GetSize(val));
+                                               for (int i = 0; i < len; i++) {
+                                                       if (sig[i].wire == nullptr)
+                                                               continue;
+                                                       if (val[i] != State::S0 && val[i] != State::S1)
+                                                               continue;
+                                                       initbits[sig[i]] = val[i];
+                                               }
+                                       }
+                               }
+
+                               pm.setup(module->selected_cells());
+
                                pm.run_shiftmul();
                                pm.run_muldiv();
                                pm.run_dffmux();
+
+                               for (auto w : module->wires()) {
+                                       auto it = w->attributes.find(ID(init));
+                                       if (it != w->attributes.end()) {
+                                               SigSpec sig = pm.sigmap(w);
+                                               Const &val = it->second;
+                                               int len = std::min(GetSize(sig), GetSize(val));
+                                               for (int i = 0; i < len; i++) {
+                                                       if (rminitbits.count(sig[i]))
+                                                               val[i] = State::Sx;
+                                               }
+                                       }
+                               }
+
+                               initbits.clear();
+                               rminitbits.clear();
                        }
                }
        }
index 15c8dc22f461607842cacfa4bf5dacb2054bc832..0069b0570443ad3b910e38c10fd957382510cdea 100644 (file)
@@ -60,12 +60,13 @@ code
        SigSpec Q = port(dff, \Q);
        int width = GetSize(D);
 
-       SigSpec &dffD = dff->connections_.at(\D);
-       SigSpec &dffQ = dff->connections_.at(\Q);
-       Const init;
-       for (const auto &b : Q) {
-               auto it = b.wire->attributes.find(\init);
-               init.bits.push_back(it == b.wire->attributes.end() ? State::Sx : it->second[b.offset]);
+       SigSpec dffD = dff->getPort(\D);
+       SigSpec dffQ = dff->getPort(\Q);
+
+       Const initval;
+       for (auto b : Q) {
+               auto it = initbits.find(b);
+               initval.bits.push_back(it == initbits.end() ? State::Sx : it->second);
        }
 
        auto cmpx = [=](State lhs, State rhs) {
@@ -76,56 +77,68 @@ code
 
        int i = width-1;
        while (i > 1) {
-               // log_dump(i, D[i], D[i-1], rst[i], rst[i-1], init[i], init[i-1]);
                if (D[i] != D[i-1])
                        break;
                if (!cmpx(rst[i], rst[i-1]))
                        break;
-               if (!cmpx(init[i], init[i-1]))
+               if (!cmpx(initval[i], initval[i-1]))
                        break;
-               if (!cmpx(rst[i], init[i]))
+               if (!cmpx(rst[i], initval[i]))
                        break;
+               rminitbits.insert(Q[i]);
                module->connect(Q[i], Q[i-1]);
                i--;
        }
        if (i < width-1) {
                did_something = true;
                if (cemux) {
-                       SigSpec &ceA = cemux->connections_.at(\A);
-                       SigSpec &ceB = cemux->connections_.at(\B);
-                       SigSpec &ceY = cemux->connections_.at(\Y);
+                       SigSpec ceA = cemux->getPort(\A);
+                       SigSpec ceB = cemux->getPort(\B);
+                       SigSpec ceY = cemux->getPort(\Y);
                        ceA.remove(i, width-1-i);
                        ceB.remove(i, width-1-i);
                        ceY.remove(i, width-1-i);
+                       cemux->setPort(\A, ceA);
+                       cemux->setPort(\B, ceB);
+                       cemux->setPort(\Y, ceY);
                        cemux->fixup_parameters();
+                       blacklist(cemux);
                }
                if (rstmux) {
-                       SigSpec &rstA = rstmux->connections_.at(\A);
-                       SigSpec &rstB = rstmux->connections_.at(\B);
-                       SigSpec &rstY = rstmux->connections_.at(\Y);
+                       SigSpec rstA = rstmux->getPort(\A);
+                       SigSpec rstB = rstmux->getPort(\B);
+                       SigSpec rstY = rstmux->getPort(\Y);
                        rstA.remove(i, width-1-i);
                        rstB.remove(i, width-1-i);
                        rstY.remove(i, width-1-i);
+                       rstmux->setPort(\A, rstA);
+                       rstmux->setPort(\B, rstB);
+                       rstmux->setPort(\Y, rstY);
                        rstmux->fixup_parameters();
+                       blacklist(rstmux);
                }
                dffD.remove(i, width-1-i);
                dffQ.remove(i, width-1-i);
+               dff->setPort(\D, dffD);
+               dff->setPort(\Q, dffQ);
                dff->fixup_parameters();
+               blacklist(dff);
 
                log("dffcemux pattern in %s: dff=%s, cemux=%s, rstmux=%s; removed top %d bits.\n", log_id(module), log_id(dff), log_id(cemux, "n/a"), log_id(rstmux, "n/a"), width-1-i);
                width = i+1;
        }
        if (cemux) {
-               SigSpec &ceA = cemux->connections_.at(\A);
-               SigSpec &ceB = cemux->connections_.at(\B);
-               SigSpec &ceY = cemux->connections_.at(\Y);
+               SigSpec ceA = cemux->getPort(\A);
+               SigSpec ceB = cemux->getPort(\B);
+               SigSpec ceY = cemux->getPort(\Y);
 
                int count = 0;
                for (int i = width-1; i >= 0; i--) {
                        if (D[i].wire)
                                continue;
-                       if (cmpx(rst[i], D[i].data) && cmpx(init[i], D[i].data)) {
+                       if (cmpx(rst[i], D[i].data) && cmpx(initval[i], D[i].data)) {
                                count++;
+                               rminitbits.insert(Q[i]);
                                module->connect(Q[i], D[i]);
                                ceA.remove(i);
                                ceB.remove(i);
@@ -134,10 +147,21 @@ code
                                dffQ.remove(i);
                        }
                }
-               if (count > 0) {
+               if (count > 0)
+               {
                        did_something = true;
+
+                       cemux->setPort(\A, ceA);
+                       cemux->setPort(\B, ceB);
+                       cemux->setPort(\Y, ceY);
                        cemux->fixup_parameters();
+                       blacklist(cemux);
+
+                       dff->setPort(\D, dffD);
+                       dff->setPort(\Q, dffQ);
                        dff->fixup_parameters();
+                       blacklist(dff);
+
                        log("dffcemux pattern in %s: dff=%s, cemux=%s, rstmux=%s; removed %d constant bits.\n", log_id(module), log_id(dff), log_id(cemux), log_id(rstmux, "n/a"), count);
                }
        }