diff options
Diffstat (limited to 'techlibs/xilinx/synth_xilinx.cc')
-rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 123 |
1 files changed, 84 insertions, 39 deletions
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f13740865..2c5686a35 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -46,7 +46,7 @@ struct SynthXilinxPass : public ScriptPass log(" -top <module>\n"); log(" use the specified module as top module\n"); log("\n"); - log(" -family {xcup|xcu|xc7|xc6v|xc6s}\n"); + log(" -family {xcup|xcu|xc7|xc6v|xc5v|xc6s}\n"); log(" run synthesis for the specified Xilinx architecture\n"); log(" generate the synthesis netlist for the specified family.\n"); log(" default: xc7\n"); @@ -93,6 +93,9 @@ struct SynthXilinxPass : public ScriptPass log(" -noclkbuf\n"); log(" disable automatic clock buffer insertion\n"); log("\n"); + log(" -uram\n"); + log(" infer URAM288s for large memories (xcup only)\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"); @@ -119,7 +122,7 @@ struct SynthXilinxPass : public ScriptPass } std::string top_opt, edif_file, blif_file, family; - bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, abc9; + bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram, abc9; bool flatten_before_abc; int widemux; @@ -143,6 +146,7 @@ struct SynthXilinxPass : public ScriptPass nocarry = false; nowidelut = false; nodsp = false; + uram = false; abc9 = false; flatten_before_abc = false; widemux = 0; @@ -248,11 +252,15 @@ struct SynthXilinxPass : public ScriptPass nodsp = true; continue; } + if (args[argidx] == "-uram") { + uram = true; + continue; + } break; } extra_args(args, argidx, design); - if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6v" && family != "xc6s") + if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6v" && family != "xc5v" && family != "xc6s") log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family.c_str()); if (widemux != 0 && widemux < 2) @@ -274,6 +282,7 @@ struct SynthXilinxPass : public ScriptPass void script() YS_OVERRIDE { + bool do_iopad = iopad || (ise && !noiopad); std::string ff_map_file; if (help_mode) ff_map_file = "+/xilinx/{family}_ff_map.v"; @@ -288,24 +297,7 @@ struct SynthXilinxPass : public ScriptPass else run("read_verilog -lib +/xilinx/cells_sim.v"); - if (help_mode) - run("read_verilog -lib +/xilinx/{family}_cells_xtra.v"); - else if (family == "xc6s") - run("read_verilog -lib +/xilinx/xc6s_cells_xtra.v"); - else if (family == "xc6v") - run("read_verilog -lib +/xilinx/xc6v_cells_xtra.v"); - else if (family == "xc7") - run("read_verilog -lib +/xilinx/xc7_cells_xtra.v"); - else if (family == "xcu" || family == "xcup") - run("read_verilog -lib +/xilinx/xcu_cells_xtra.v"); - - if (help_mode) { - run("read_verilog -lib +/xilinx/{family}_brams_bb.v"); - } else if (family == "xc6s") { - run("read_verilog -lib +/xilinx/xc6s_brams_bb.v"); - } else if (family == "xc6v" || family == "xc7") { - run("read_verilog -lib +/xilinx/xc7_brams_bb.v"); - } + run("read_verilog -lib +/xilinx/cells_xtra.v"); run(stringf("hierarchy -check %s", top_opt.c_str())); } @@ -314,6 +306,8 @@ struct SynthXilinxPass : public ScriptPass run("proc"); if (flatten || help_mode) run("flatten", "(with '-flatten')"); + run("tribuf -logic"); + run("deminout"); run("opt_expr"); run("opt_clean"); run("check"); @@ -341,15 +335,53 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_dsp", "(skip if '-nodsp')")) { if (!nodsp || help_mode) { + run("memory_dff"); // xilinx_dsp will merge registers, reserve memory port registers first // 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 " // Partial multipliers are intentionally - // limited to 18x18 in order to take - // advantage of the (PCOUT << 17) -> PCIN - // dedicated cascade chain capability - "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers - "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller - "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + if (help_mode) + run("techmap -map +/mul2dsp.v -map +/xilinx/{family}_dsp_map.v {options}"); + else if (family == "xc2v" || family == "xc3s" || family == "xc3se" || family == "xc3sa") + run("techmap -map +/mul2dsp.v -map +/xilinx/xc3s_mult_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); + else if (family == "xc3sda") + run("techmap -map +/mul2dsp.v -map +/xilinx/xc3sda_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); + else if (family == "xc6s") + run("techmap -map +/mul2dsp.v -map +/xilinx/xc6s_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); + else if (family == "xc4v") + run("techmap -map +/mul2dsp.v -map +/xilinx/xc4v_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); + else if (family == "xc5v") + run("techmap -map +/mul2dsp.v -map +/xilinx/xc5v_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 " + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + else if (family == "xc6v" || family == "xc7") + run("techmap -map +/mul2dsp.v -map +/xilinx/xc7_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 " + "-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally + // limited to 18x18 in order to take + // advantage of the (PCOUT << 17) -> PCIN + // dedicated cascade chain capability + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); + else if (family == "xcu" || family == "xcup") + run("techmap -map +/mul2dsp.v -map +/xilinx/xcu_dsp_map.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=18 " + "-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally + // limited to 18x18 in order to take + // advantage of the (PCOUT << 17) -> PCIN + // dedicated cascade chain capability + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL27X18"); run("select a:mul2dsp"); run("setattr -unset mul2dsp"); run("opt_expr -fine"); @@ -370,6 +402,20 @@ struct SynthXilinxPass : public ScriptPass run("opt_clean"); } + if (check_label("map_uram", "(only if '-uram')")) { + if (help_mode) { + run("memory_bram -rules +/xilinx/{family}_urams.txt"); + run("techmap -map +/xilinx/{family}_urams_map.v"); + } else if (uram) { + if (family == "xcup") { + run("memory_bram -rules +/xilinx/xcup_urams.txt"); + run("techmap -map +/xilinx/xcup_urams_map.v"); + } else { + log_warning("UltraRAM inference not supported for family %s.\n", family.c_str()); + } + } + } + if (check_label("map_bram", "(skip if '-nobram')")) { if (help_mode) { run("memory_bram -rules +/xilinx/{family}_brams.txt"); @@ -379,8 +425,11 @@ struct SynthXilinxPass : public ScriptPass run("memory_bram -rules +/xilinx/xc6s_brams.txt"); run("techmap -map +/xilinx/xc6s_brams_map.v"); } else if (family == "xc6v" || family == "xc7") { - run("memory_bram -rules +/xilinx/xc7_brams.txt"); + run("memory_bram -rules +/xilinx/xc7_xcu_brams.txt"); run("techmap -map +/xilinx/xc7_brams_map.v"); + } else if (family == "xcu" || family == "xcup") { + run("memory_bram -rules +/xilinx/xc7_xcu_brams.txt"); + run("techmap -map +/xilinx/xcu_brams_map.v"); } else { log_warning("Block RAM inference not yet supported for family %s.\n", family.c_str()); } @@ -457,6 +506,9 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("map_cells")) { + // Needs to be done before logic optimization, so that inverters (OE vs T) are handled. + if (help_mode || do_iopad) + run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(only if '-iopad' or '-ise' and not '-noiopad')"); std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v"; if (widemux > 0) techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); @@ -515,15 +567,8 @@ struct SynthXilinxPass : public ScriptPass } 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 (help_mode || do_iopad) - run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')"); + if (help_mode || !noclkbuf) + run("clkbufmap -buf BUFG O:I ", "(skip if '-noclkbuf')"); if (help_mode || ise) run("extractinv -inv INV O:I", "(only if '-ise')"); } |