dff2dffe: Add option for unmap to only remove DFFE with low CE signal use
authorSylvain Munaut <tnt@246tNt.com>
Thu, 15 Nov 2018 01:48:44 +0000 (02:48 +0100)
committerSylvain Munaut <tnt@246tNt.com>
Tue, 27 Nov 2018 20:50:42 +0000 (21:50 +0100)
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
passes/techmap/dff2dffe.cc

index 3291f5a4a19210ebab725dac20480367f98e9e25..3f5b48c7530ed001f2e4ebd621897dca21e0ae4c 100644 (file)
@@ -263,10 +263,14 @@ struct Dff2dffePass : public Pass {
                log("more feedback paths to $dffe cells. It also works on gate-level cells such as\n");
                log("$_DFF_P_, $_DFF_N_ and $_MUX_.\n");
                log("\n");
-               log("    -unmap\n");
+               log("    -unmap");
                log("        operate in the opposite direction: replace $dffe cells with combinations\n");
                log("        of $dff and $mux cells. the options below are ignore in unmap mode.\n");
                log("\n");
+               log("    -unmap-mince N\n");
+               log("        Same as -unmap but only unmap $dffe where the clock enable port\n");
+               log("        signal is used by less $dffe than the specified number\n");
+               log("\n");
                log("    -direct <internal_gate_type> <external_gate_type>\n");
                log("        map directly to external gate type. <internal_gate_type> can\n");
                log("        be any internal gate-level FF cell (except $_DFFE_??_). the\n");
@@ -289,6 +293,7 @@ struct Dff2dffePass : public Pass {
                log_header(design, "Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
 
                bool unmap_mode = false;
+               int min_ce_use = -1;
                dict<IdString, IdString> direct_dict;
 
                size_t argidx;
@@ -297,6 +302,11 @@ struct Dff2dffePass : public Pass {
                                unmap_mode = true;
                                continue;
                        }
+                       if (args[argidx] == "-unmap-mince" && argidx + 1 < args.size()) {
+                               unmap_mode = true;
+                               min_ce_use = std::stoi(args[++argidx]);
+                               continue;
+                       }
                        if (args[argidx] == "-direct" && argidx + 2 < args.size()) {
                                string direct_from = RTLIL::escape_id(args[++argidx]);
                                string direct_to = RTLIL::escape_id(args[++argidx]);
@@ -343,8 +353,21 @@ struct Dff2dffePass : public Pass {
                        if (!mod->has_processes_warn())
                        {
                                if (unmap_mode) {
+                                       SigMap sigmap(mod);
                                        for (auto cell : mod->selected_cells()) {
                                                if (cell->type == "$dffe") {
+                                                       if (min_ce_use >= 0) {
+                                                               int ce_use = 0;
+                                                               for (auto cell_other : mod->selected_cells()) {
+                                                                       if (cell_other->type != cell->type)
+                                                                               continue;
+                                                                       if (sigmap(cell->getPort("\\EN")) == sigmap(cell_other->getPort("\\EN")))
+                                                                               ce_use++;
+                                                               }
+                                                               if (ce_use >= min_ce_use)
+                                                                       continue;
+                                                       }
+
                                                        RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort("\\D")));
                                                        mod->addDff(NEW_ID, cell->getPort("\\CLK"), tmp, cell->getPort("\\Q"), cell->getParam("\\CLK_POLARITY").as_bool());
                                                        if (cell->getParam("\\EN_POLARITY").as_bool())
@@ -355,6 +378,18 @@ struct Dff2dffePass : public Pass {
                                                        continue;
                                                }
                                                if (cell->type.substr(0, 7) == "$_DFFE_") {
+                                                       if (min_ce_use >= 0) {
+                                                               int ce_use = 0;
+                                                               for (auto cell_other : mod->selected_cells()) {
+                                                                       if (cell_other->type != cell->type)
+                                                                               continue;
+                                                                       if (sigmap(cell->getPort("\\E")) == sigmap(cell_other->getPort("\\E")))
+                                                                               ce_use++;
+                                                               }
+                                                               if (ce_use >= min_ce_use)
+                                                                       continue;
+                                                       }
+
                                                        bool clk_pol = cell->type.substr(7, 1) == "P";
                                                        bool en_pol = cell->type.substr(8, 1) == "P";
                                                        RTLIL::SigSpec tmp = mod->addWire(NEW_ID);