Added "dff2dffe -direct" for direct gate mapping
authorClifford Wolf <clifford@clifford.at>
Wed, 24 Dec 2014 10:39:15 +0000 (11:39 +0100)
committerClifford Wolf <clifford@clifford.at>
Wed, 24 Dec 2014 10:39:15 +0000 (11:39 +0100)
passes/techmap/dff2dffe.cc

index 03abde6f9f561c60896563cd999c4e336bbc5d78..3390071568eae6ddb4cdbd963089044fb7dafcbf 100644 (file)
@@ -31,6 +31,8 @@ struct Dff2dffeWorker
        SigMap sigmap;
        CellTypes ct;
 
+       RTLIL::IdString direct_to;
+
        typedef std::pair<RTLIL::Cell*, int> cell_int_t;
        std::map<RTLIL::SigBit, cell_int_t> bit2mux;
        std::vector<RTLIL::Cell*> dff_cells;
@@ -39,7 +41,9 @@ struct Dff2dffeWorker
        typedef std::map<RTLIL::SigBit, bool> pattern_t;
        typedef std::set<pattern_t> patterns_t;
 
-       Dff2dffeWorker(RTLIL::Module *module) : module(module), sigmap(module), ct(module->design)
+
+       Dff2dffeWorker(RTLIL::Module *module, RTLIL::IdString direct_from, RTLIL::IdString direct_to) :
+                       module(module), sigmap(module), ct(module->design), direct_to(direct_to)
        {
                for (auto wire : module->wires()) {
                        if (wire->port_output)
@@ -53,8 +57,13 @@ struct Dff2dffeWorker
                                for (int i = 0; i < GetSize(sig_y); i++)
                                        bit2mux[sig_y[i]] = cell_int_t(cell, i);
                        }
-                       if (cell->type == "$dff" || cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
-                               dff_cells.push_back(cell);
+                       if (direct_to.empty()) {
+                               if (cell->type == "$dff" || cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
+                                       dff_cells.push_back(cell);
+                       } else {
+                               if (cell->type == direct_from)
+                                       dff_cells.push_back(cell);
+                       }
                        for (auto conn : cell->connections()) {
                                if (ct.cell_output(cell->type, conn.first))
                                        continue;
@@ -197,6 +206,11 @@ struct Dff2dffeWorker
                                new_sig_d.append(sig_d[i]);
                                new_sig_q.append(sig_q[i]);
                        }
+                       if (!direct_to.empty()) {
+                               log("  converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_to), log_signal(new_sig_d), log_signal(new_sig_q));
+                               dff_cell->setPort("\\E", make_patterns_logic(it.first, true));
+                               dff_cell->type = direct_to;
+                       } else
                        if (dff_cell->type == "$dff") {
                                RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first, false),
                                                new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true);
@@ -208,6 +222,9 @@ struct Dff2dffeWorker
                        }
                }
 
+               if (!direct_to.empty())
+                       return;
+
                if (remaining_indices.empty()) {
                        log("  removing now obsolete cell %s.\n", log_id(dff_cell));
                        module->remove(dff_cell);
@@ -246,7 +263,16 @@ struct Dff2dffePass : public Pass {
                log("\n");
                log("    -unmap\n");
                log("        operate in the opposite direction: replace $dffe cells with combinations\n");
-               log("        of $dff and $mux cells\n");
+               log("        of $dff and $mux cells. the options below are ignore in unmap mode.\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");
+               log("        <external_gate_type> is the cell type name for a cell with an\n");
+               log("        identical interface to the <internal_gate_type>, except it\n");
+               log("        also has an high-active enable port 'E'.\n");
+               log("          Usually <external_gate_type> is an intemediate cell type\n");
+               log("        that is then translated to the final type using 'techmap'.\n");
                log("\n");
        }
        virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
@@ -254,6 +280,7 @@ struct Dff2dffePass : public Pass {
                log_header("Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
 
                bool unmap_mode = false;
+               RTLIL::IdString direct_from, direct_to;
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++) {
@@ -261,6 +288,11 @@ struct Dff2dffePass : public Pass {
                                unmap_mode = true;
                                continue;
                        }
+                       if (args[argidx] == "-direct" && argidx + 2 < args.size()) {
+                               direct_from = RTLIL::escape_id(args[++argidx]);
+                               direct_to = RTLIL::escape_id(args[++argidx]);
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -296,7 +328,7 @@ struct Dff2dffePass : public Pass {
                                        continue;
                                }
 
-                               Dff2dffeWorker worker(mod);
+                               Dff2dffeWorker worker(mod, direct_from, direct_to);
                                worker.run();
                        }
        }