Added "abc -luts" option, Improved Xilinx logic mapping
authorClifford Wolf <clifford@clifford.at>
Mon, 1 Feb 2016 11:40:32 +0000 (12:40 +0100)
committerClifford Wolf <clifford@clifford.at>
Mon, 1 Feb 2016 11:40:32 +0000 (12:40 +0100)
passes/techmap/abc.cc
techlibs/xilinx/synth_xilinx.cc

index 5c5148590010e16f13f7a3f0f3a4d7eba86d9fb5..7da266026004d8ca31eeabca0d898641a0f4fb98 100644 (file)
@@ -592,7 +592,7 @@ struct abc_output_filter
 };
 
 void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
-               std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, int lut_mode2, bool dff_mode, std::string clk_str,
+               std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
                bool keepff, std::string delay_target, bool fast_mode, const std::vector<RTLIL::Cell*> &cells, bool show_tempdir)
 {
        module = current_module;
@@ -626,7 +626,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                if (!constr_file.empty())
                        abc_script += stringf("read_constr -v %s; ", constr_file.c_str());
        } else
-       if (lut_mode)
+       if (!lut_costs.empty())
                abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
        else
                abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str());
@@ -642,7 +642,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                                        abc_script += script_file[i];
                } else
                        abc_script += stringf("source %s", script_file.c_str());
-       } else if (lut_mode)
+       } else if (!lut_costs.empty())
                abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
        else if (!liberty_file.empty())
                abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR);
@@ -868,15 +868,13 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                        fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_"));
                fclose(f);
 
-               if (lut_mode) {
+               if (!lut_costs.empty()) {
                        buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
                        f = fopen(buffer.c_str(), "wt");
                        if (f == NULL)
                                log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
-                       for (int i = 0; i < lut_mode; i++)
-                               fprintf(f, "%d 1.00 1.00\n", i+1);
-                       for (int i = lut_mode; i < lut_mode2; i++)
-                               fprintf(f, "%d %d.00 1.00\n", i+1, 2 << (i - lut_mode));
+                       for (int i = 0; i < GetSize(lut_costs); i++)
+                               fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i));
                        fclose(f);
                }
 
@@ -894,7 +892,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                if (ifs.fail())
                        log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
 
-               bool builtin_lib = liberty_file.empty() && script_file.empty() && !lut_mode;
+               bool builtin_lib = liberty_file.empty() && script_file.empty() && lut_costs.empty();
                RTLIL::Design *mapped_design = new RTLIL::Design;
                parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_");
 
@@ -1238,6 +1236,10 @@ struct AbcPass : public Pass {
                log("        the area cost doubles with each additional input bit. the delay cost\n");
                log("        is still constant for all lut widths.\n");
                log("\n");
+               log("    -luts <cost1>,<cost2>,<cost3>,<sizeN>:<cost4-N>,..\n");
+               log("        generate netlist using luts. Use the specified costs for luts with 1,\n");
+               log("        2, 3, .. inputs.\n");
+               log("\n");
                // log("    -mux4, -mux8, -mux16\n");
                // log("        try to extract 4-input, 8-input, and/or 16-input muxes\n");
                // log("        (ignored when used with -liberty or -lut)\n");
@@ -1291,7 +1293,7 @@ struct AbcPass : public Pass {
                std::string script_file, liberty_file, constr_file, clk_str, delay_target;
                bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
                bool show_tempdir = false;
-               int lut_mode = 0, lut_mode2 = 0;
+               vector<int> lut_costs;
                markgroups = false;
 
                map_mux4 = false;
@@ -1341,6 +1343,7 @@ struct AbcPass : public Pass {
                        if (arg == "-lut" && argidx+1 < args.size()) {
                                string arg = args[++argidx];
                                size_t pos = arg.find_first_of(':');
+                               int lut_mode = 0, lut_mode2 = 0;
                                if (pos != string::npos) {
                                        lut_mode = atoi(arg.substr(0, pos).c_str());
                                        lut_mode2 = atoi(arg.substr(pos+1).c_str());
@@ -1348,6 +1351,27 @@ struct AbcPass : public Pass {
                                        lut_mode = atoi(arg.c_str());
                                        lut_mode2 = lut_mode;
                                }
+                               lut_costs.clear();
+                               for (int i = 0; i < lut_mode; i++)
+                                       lut_costs.push_back(1);
+                               for (int i = lut_mode; i < lut_mode2; i++)
+                                       lut_costs.push_back(2 << (i - lut_mode));
+                               continue;
+                       }
+                       if (arg == "-luts" && argidx+1 < args.size()) {
+                               lut_costs.clear();
+                               for (auto &tok : split_tokens(args[++argidx], ",")) {
+                                       auto parts = split_tokens(tok, ":");
+                                       if (GetSize(parts) == 0 && !lut_costs.empty())
+                                               lut_costs.push_back(lut_costs.back());
+                                       else if (GetSize(parts) == 1)
+                                               lut_costs.push_back(atoi(parts.at(0).c_str()));
+                                       else if (GetSize(parts) == 2)
+                                               while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
+                                                       lut_costs.push_back(atoi(parts.at(1).c_str()));
+                                       else
+                                               log_cmd_error("Invalid -luts syntax.\n");
+                               }
                                continue;
                        }
                        if (arg == "-mux4") {
@@ -1414,7 +1438,7 @@ struct AbcPass : public Pass {
                }
                extra_args(args, argidx, design);
 
-               if (lut_mode != 0 && !liberty_file.empty())
+               if (!lut_costs.empty() && !liberty_file.empty())
                        log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n");
                if (!constr_file.empty() && liberty_file.empty())
                        log_cmd_error("Got -constr but no -liberty!\n");
@@ -1423,7 +1447,7 @@ struct AbcPass : public Pass {
                        if (mod->processes.size() > 0)
                                log("Skipping module %s as it contains processes.\n", log_id(mod));
                        else if (!dff_mode || !clk_str.empty())
-                               abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, lut_mode2, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir);
+                               abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir);
                        else
                        {
                                assign_map.set(mod);
@@ -1567,7 +1591,7 @@ struct AbcPass : public Pass {
                                        clk_sig = assign_map(std::get<1>(it.first));
                                        en_polarity = std::get<2>(it.first);
                                        en_sig = assign_map(std::get<3>(it.first));
-                                       abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, lut_mode2,
+                                       abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs,
                                                        !clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir);
                                        assign_map.set(mod);
                                }
index fbcc96014df4f8099beea3bf5a9e568d561ce2c6..6358a266b9a4473422728e3fc265ec83f9ac4c86 100644 (file)
@@ -97,7 +97,7 @@ struct SynthXilinxPass : public Pass {
                log("        opt -fast\n");
                log("\n");
                log("    map_luts:\n");
-               log("        abc -lut 5:8 [-dff]\n");
+               log("        abc -luts 2:2,3,6:5,10,20 [-dff]\n");
                log("        clean\n");
                log("\n");
                log("    map_cells:\n");
@@ -204,7 +204,7 @@ struct SynthXilinxPass : public Pass {
 
                if (check_label(active, run_from, run_to, "map_luts"))
                {
-                       Pass::call(design, "abc -lut 6:8" + string(retime ? " -dff" : ""));
+                       Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
                        Pass::call(design, "clean");
                }