aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/xilinx/synth_xilinx.cc
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/xilinx/synth_xilinx.cc')
-rw-r--r--techlibs/xilinx/synth_xilinx.cc123
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')");
}