Missing space
[yosys.git] / techlibs / xilinx / synth_xilinx.cc
index 2181923150339f407bc7fcee49c288a3a0672bd7..e822d9b7ef08f8160cc9c2e11a8799ae18935c81 100644 (file)
@@ -63,6 +63,9 @@ struct SynthXilinxPass : public ScriptPass
                log("        generate an output netlist (and BLIF file) suitable for VPR\n");
                log("        (this feature is experimental and incomplete)\n");
                log("\n");
+               log("    -ise\n");
+               log("        generate an output netlist suitable for ISE (enables -iopad)\n");
+               log("\n");
                log("    -nobram\n");
                log("        do not use block RAM cells in output netlist\n");
                log("\n");
@@ -78,6 +81,18 @@ struct SynthXilinxPass : public ScriptPass
                log("    -nowidelut\n");
                log("        do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");
                log("\n");
+               log("    -nodsp\n");
+               log("        do not use DSP48E1s to implement multipliers and associated logic\n");
+               log("\n");
+               log("    -iopad\n");
+               log("        enable I/O buffer insertion (selected automatically by -ise)\n");
+               log("\n");
+               log("    -noiopad\n");
+               log("        disable I/O buffer insertion (only useful with -ise)\n");
+               log("\n");
+               log("    -noclkbuf\n");
+               log("        disable automatic clock buffer insertion\n");
+               log("\n");
                log("    -widemux <int>\n");
                log("        enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n");
                log("        above this number of inputs (minimum value 2, recommended value >= 5).\n");
@@ -104,7 +119,8 @@ struct SynthXilinxPass : public ScriptPass
        }
 
        std::string top_opt, edif_file, blif_file, family;
-       bool flatten, retime, vpr, nobram, nolutram, nosrl, nocarry, nowidelut, abc9;
+       bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, abc9;
+       bool flatten_before_abc;
        int widemux;
 
        void clear_flags() YS_OVERRIDE
@@ -116,13 +132,19 @@ struct SynthXilinxPass : public ScriptPass
                flatten = false;
                retime = false;
                vpr = false;
+               ise = false;
+               iopad = false;
+               noiopad = false;
+               noclkbuf = false;
                nocarry = false;
                nobram = false;
                nolutram = false;
                nosrl = false;
                nocarry = false;
                nowidelut = false;
+               nodsp = false;
                abc9 = false;
+               flatten_before_abc = false;
                widemux = 0;
        }
 
@@ -162,6 +184,10 @@ struct SynthXilinxPass : public ScriptPass
                                flatten = true;
                                continue;
                        }
+                       if (args[argidx] == "-flatten_before_abc") {
+                               flatten_before_abc = true;
+                               continue;
+                       }
                        if (args[argidx] == "-retime") {
                                retime = true;
                                continue;
@@ -178,6 +204,22 @@ struct SynthXilinxPass : public ScriptPass
                                vpr = true;
                                continue;
                        }
+                       if (args[argidx] == "-ise") {
+                               ise = true;
+                               continue;
+                       }
+                       if (args[argidx] == "-iopad") {
+                               iopad = true;
+                               continue;
+                       }
+                       if (args[argidx] == "-noiopad") {
+                               noiopad = true;
+                               continue;
+                       }
+                       if (args[argidx] == "-noclkbuf") {
+                               noclkbuf = true;
+                               continue;
+                       }
                        if (args[argidx] == "-nocarry") {
                                nocarry = true;
                                continue;
@@ -202,6 +244,10 @@ struct SynthXilinxPass : public ScriptPass
                                abc9 = true;
                                continue;
                        }
+                       if (args[argidx] == "-nodsp") {
+                               nodsp = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -228,6 +274,14 @@ struct SynthXilinxPass : public ScriptPass
 
        void script() YS_OVERRIDE
        {
+               std::string ff_map_file;
+               if (help_mode)
+                       ff_map_file = "+/xilinx/xc6s_ff_map.v";
+               else if (family == "xc6s")
+                       ff_map_file = "+/xilinx/xc6s_ff_map.v";
+               else
+                       ff_map_file = "+/xilinx/xc7_ff_map.v";
+
                if (check_label("begin")) {
                        if (vpr)
                                run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
@@ -247,10 +301,10 @@ struct SynthXilinxPass : public ScriptPass
                        run(stringf("hierarchy -check %s", top_opt.c_str()));
                }
 
-               if (check_label("coarse")) {
+               if (check_label("prepare")) {
                        run("proc");
-                       if (help_mode || flatten)
-                               run("flatten", "(if -flatten)");
+                       if (flatten || help_mode)
+                               run("flatten", "(with '-flatten')");
                        run("opt_expr");
                        run("opt_clean");
                        run("check");
@@ -265,9 +319,8 @@ struct SynthXilinxPass : public ScriptPass
                        if (widemux > 0 || help_mode)
                                run("muxpack", "    ('-widemux' only)");
 
-                       // shregmap -tech xilinx can cope with $shiftx and $mux
-                       //   cells for identifying variable-length shift registers,
-                       //   so attempt to convert $pmux-es to the former
+                       // xilinx_srl looks for $shiftx cells for identifying variable-length
+                       //   shift registers, so attempt to convert $pmux-es to this
                        // Also: wide multiplexer inference benefits from this too
                        if (!(nosrl && widemux == 0) || help_mode) {
                                run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')");
@@ -275,6 +328,18 @@ struct SynthXilinxPass : public ScriptPass
                        }
 
                        run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
+               }
+
+               if (check_label("map_dsp"), "(skip if '-nodsp')") {
+                       if (!nodsp || help_mode) {
+                               // NB: Xilinx multipliers are signed only
+                               run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
+                               run("xilinx_dsp");
+                               run("chtype -set $mul t:$__soft_mul");
+                       }
+               }
+
+               if (check_label("coarse")) {
                        run("alumacc");
                        run("share");
                        run("opt");
@@ -349,13 +414,8 @@ struct SynthXilinxPass : public ScriptPass
                        }
                        run("opt -full");
 
-                       if (!nosrl || help_mode) {
-                               // shregmap operates on bit-level flops, not word-level,
-                               //   so break those down here
-                               run("simplemap t:$dff t:$dffe", "       (skip if '-nosrl')");
-                               // shregmap with '-tech xilinx' infers variable length shift regs
-                               run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");
-                       }
+                       if (!nosrl || help_mode)
+                               run("xilinx_srl -variable -minlen 3", "(skip if '-nosrl')");
 
                        std::string techmap_args = " -map +/techmap.v";
                        if (help_mode)
@@ -383,10 +443,18 @@ struct SynthXilinxPass : public ScriptPass
                        run("clean");
                }
 
+               if (check_label("map_ffs")) {
+                       if (abc9 || help_mode) {
+                               run("techmap -map " + ff_map_file, "('-abc9' only)");
+                       }
+               }
+
                if (check_label("map_luts")) {
                        run("opt_expr -mux_undef");
+                       if (flatten_before_abc)
+                               run("flatten");
                        if (help_mode)
-                               run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')");
+                               run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut'; option for '-retime')");
                        else if (abc9) {
                                if (family != "xc7")
                                        log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n");
@@ -408,16 +476,30 @@ struct SynthXilinxPass : public ScriptPass
                        // This shregmap call infers fixed length shift registers after abc
                        //   has performed any necessary retiming
                        if (!nosrl || help_mode)
-                               run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')");
-                       std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/ff_map.v";
-                       if (abc9)
+                               run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')");
+                       std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v";
+                       if (help_mode)
+                               techmap_args += " [-map " + ff_map_file + "]";
+                       else if (abc9)
                                techmap_args += " -map +/xilinx/abc_unmap.v";
+                       else
+                               techmap_args += " -map " + ff_map_file;
                        run("techmap " + techmap_args);
-                       run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
-                                       "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
                        run("clean");
                }
 
+               if (check_label("finalize")) {
+                       bool do_iopad = iopad || (ise && !noiopad);
+                       if (help_mode || !noclkbuf) {
+                               if (help_mode || do_iopad)
+                                       run("clkbufmap -buf BUFG O:I -inpad IBUFG O:I", "(skip if '-noclkbuf', '-inpad' passed if '-iopad' or '-ise' and not '-noiopad')");
+                               else
+                                       run("clkbufmap -buf BUFG O:I");
+                       }
+                       if (do_iopad)
+                               run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')");
+               }
+
                if (check_label("check")) {
                        run("hierarchy -check");
                        run("stat -tech xilinx");