Merge pull request #1716 from zeldin/ecp5_fix
[yosys.git] / techlibs / xilinx / synth_xilinx.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * (C) 2019 Eddie Hung <eddie@fpgeh.com>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21 #include "kernel/register.h"
22 #include "kernel/celltypes.h"
23 #include "kernel/rtlil.h"
24 #include "kernel/log.h"
25
26 USING_YOSYS_NAMESPACE
27 PRIVATE_NAMESPACE_BEGIN
28
29 struct SynthXilinxPass : public ScriptPass
30 {
31 SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
32
33 void on_register() YS_OVERRIDE
34 {
35 RTLIL::constpad["synth_xilinx.abc9.xc7.W"] = "300"; // Number with which ABC will map a 6-input gate
36 // to one LUT6 (instead of a LUT5 + LUT2)
37 }
38
39 void help() YS_OVERRIDE
40 {
41 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
42 log("\n");
43 log(" synth_xilinx [options]\n");
44 log("\n");
45 log("This command runs synthesis for Xilinx FPGAs. This command does not operate on\n");
46 log("partly selected designs. At the moment this command creates netlists that are\n");
47 log("compatible with 7-Series Xilinx devices.\n");
48 log("\n");
49 log(" -top <module>\n");
50 log(" use the specified module as top module\n");
51 log("\n");
52 log(" -family <family>\n");
53 log(" run synthesis for the specified Xilinx architecture\n");
54 log(" generate the synthesis netlist for the specified family.\n");
55 log(" supported values:\n");
56 log(" - xcup: Ultrascale Plus\n");
57 log(" - xcu: Ultrascale\n");
58 log(" - xc7: Series 7 (default)\n");
59 log(" - xc6s: Spartan 6\n");
60 log(" - xc6v: Virtex 6\n");
61 log(" - xc5v: Virtex 5 (EXPERIMENTAL)\n");
62 log(" - xc4v: Virtex 4 (EXPERIMENTAL)\n");
63 log(" - xc3sda: Spartan 3A DSP (EXPERIMENTAL)\n");
64 log(" - xc3sa: Spartan 3A (EXPERIMENTAL)\n");
65 log(" - xc3se: Spartan 3E (EXPERIMENTAL)\n");
66 log(" - xc3s: Spartan 3 (EXPERIMENTAL)\n");
67 log(" - xc2vp: Virtex 2 Pro (EXPERIMENTAL)\n");
68 log(" - xc2v: Virtex 2 (EXPERIMENTAL)\n");
69 log(" - xcve: Virtex E, Spartan 2E (EXPERIMENTAL)\n");
70 log(" - xcv: Virtex, Spartan 2 (EXPERIMENTAL)\n");
71 log("\n");
72 log(" -edif <file>\n");
73 log(" write the design to the specified edif file. writing of an output file\n");
74 log(" is omitted if this parameter is not specified.\n");
75 log("\n");
76 log(" -blif <file>\n");
77 log(" write the design to the specified BLIF file. writing of an output file\n");
78 log(" is omitted if this parameter is not specified.\n");
79 log("\n");
80 log(" -vpr\n");
81 log(" generate an output netlist (and BLIF file) suitable for VPR\n");
82 log(" (this feature is experimental and incomplete)\n");
83 log("\n");
84 log(" -ise\n");
85 log(" generate an output netlist suitable for ISE\n");
86 log("\n");
87 log(" -nobram\n");
88 log(" do not use block RAM cells in output netlist\n");
89 log("\n");
90 log(" -nolutram\n");
91 log(" do not use distributed RAM cells in output netlist\n");
92 log("\n");
93 log(" -nosrl\n");
94 log(" do not use distributed SRL cells in output netlist\n");
95 log("\n");
96 log(" -nocarry\n");
97 log(" do not use XORCY/MUXCY/CARRY4 cells in output netlist\n");
98 log("\n");
99 log(" -nowidelut\n");
100 log(" do not use MUXF[5-9] resources to implement LUTs larger than native for the target\n");
101 log("\n");
102 log(" -nodsp\n");
103 log(" do not use DSP48*s to implement multipliers and associated logic\n");
104 log("\n");
105 log(" -noiopad\n");
106 log(" disable I/O buffer insertion (useful for hierarchical or \n");
107 log(" out-of-context flows)\n");
108 log("\n");
109 log(" -noclkbuf\n");
110 log(" disable automatic clock buffer insertion\n");
111 log("\n");
112 log(" -uram\n");
113 log(" infer URAM288s for large memories (xcup only)\n");
114 log("\n");
115 log(" -widemux <int>\n");
116 log(" enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n");
117 log(" above this number of inputs (minimum value 2, recommended value >= 5).\n");
118 log(" default: 0 (no inference)\n");
119 log("\n");
120 log(" -run <from_label>:<to_label>\n");
121 log(" only run the commands between the labels (see below). an empty\n");
122 log(" from label is synonymous to 'begin', and empty to label is\n");
123 log(" synonymous to the end of the command list.\n");
124 log("\n");
125 log(" -flatten\n");
126 log(" flatten design before synthesis\n");
127 log("\n");
128 log(" -dff\n");
129 log(" run 'abc'/'abc9' with -dff option\n");
130 log("\n");
131 log(" -retime\n");
132 log(" run 'abc' with '-D 1' option to enable flip-flop retiming.\n");
133 log(" implies -dff.\n");
134 log("\n");
135 log(" -abc9\n");
136 log(" use new ABC9 flow (EXPERIMENTAL)\n");
137 log("\n");
138 log("\n");
139 log("The following commands are executed by this synthesis command:\n");
140 help_script();
141 log("\n");
142 }
143
144 std::string top_opt, edif_file, blif_file, family;
145 bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram;
146 bool abc9, dff_mode;
147 bool flatten_before_abc;
148 int widemux;
149 int lut_size;
150 int widelut_size;
151
152 void clear_flags() YS_OVERRIDE
153 {
154 top_opt = "-auto-top";
155 edif_file.clear();
156 blif_file.clear();
157 family = "xc7";
158 flatten = false;
159 retime = false;
160 vpr = false;
161 ise = false;
162 noiopad = false;
163 noclkbuf = false;
164 nocarry = false;
165 nobram = false;
166 nolutram = false;
167 nosrl = false;
168 nocarry = false;
169 nowidelut = false;
170 nodsp = false;
171 uram = false;
172 abc9 = false;
173 dff_mode = false;
174 flatten_before_abc = false;
175 widemux = 0;
176 lut_size = 6;
177 }
178
179 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
180 {
181 std::string run_from, run_to;
182 clear_flags();
183
184 size_t argidx;
185 for (argidx = 1; argidx < args.size(); argidx++)
186 {
187 if (args[argidx] == "-top" && argidx+1 < args.size()) {
188 top_opt = "-top " + args[++argidx];
189 continue;
190 }
191 if ((args[argidx] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) {
192 family = args[++argidx];
193 continue;
194 }
195 if (args[argidx] == "-edif" && argidx+1 < args.size()) {
196 edif_file = args[++argidx];
197 continue;
198 }
199 if (args[argidx] == "-blif" && argidx+1 < args.size()) {
200 blif_file = args[++argidx];
201 continue;
202 }
203 if (args[argidx] == "-run" && argidx+1 < args.size()) {
204 size_t pos = args[argidx+1].find(':');
205 if (pos == std::string::npos)
206 break;
207 run_from = args[++argidx].substr(0, pos);
208 run_to = args[argidx].substr(pos+1);
209 continue;
210 }
211 if (args[argidx] == "-flatten") {
212 flatten = true;
213 continue;
214 }
215 if (args[argidx] == "-flatten_before_abc") {
216 flatten_before_abc = true;
217 continue;
218 }
219 if (args[argidx] == "-retime") {
220 dff_mode = true;
221 retime = true;
222 continue;
223 }
224 if (args[argidx] == "-nocarry") {
225 nocarry = true;
226 continue;
227 }
228 if (args[argidx] == "-nowidelut") {
229 nowidelut = true;
230 continue;
231 }
232 if (args[argidx] == "-vpr") {
233 vpr = true;
234 continue;
235 }
236 if (args[argidx] == "-ise") {
237 ise = true;
238 continue;
239 }
240 if (args[argidx] == "-iopad") {
241 continue;
242 }
243 if (args[argidx] == "-noiopad") {
244 noiopad = true;
245 continue;
246 }
247 if (args[argidx] == "-noclkbuf") {
248 noclkbuf = true;
249 continue;
250 }
251 if (args[argidx] == "-nocarry") {
252 nocarry = true;
253 continue;
254 }
255 if (args[argidx] == "-nobram") {
256 nobram = true;
257 continue;
258 }
259 if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") {
260 nolutram = true;
261 continue;
262 }
263 if (args[argidx] == "-nosrl") {
264 nosrl = true;
265 continue;
266 }
267 if (args[argidx] == "-widemux" && argidx+1 < args.size()) {
268 widemux = atoi(args[++argidx].c_str());
269 continue;
270 }
271 if (args[argidx] == "-abc9") {
272 abc9 = true;
273 continue;
274 }
275 if (args[argidx] == "-nodsp") {
276 nodsp = true;
277 continue;
278 }
279 if (args[argidx] == "-uram") {
280 uram = true;
281 continue;
282 }
283 if (args[argidx] == "-dff") {
284 dff_mode = true;
285 continue;
286 }
287 break;
288 }
289 extra_args(args, argidx, design);
290
291 if (family == "xcup" || family == "xcu") {
292 lut_size = 6;
293 widelut_size = 9;
294 } else if (family == "xc7" ||
295 family == "xc6v" ||
296 family == "xc5v" ||
297 family == "xc6s") {
298 lut_size = 6;
299 widelut_size = 8;
300 } else if (family == "xc4v" ||
301 family == "xc3sda" ||
302 family == "xc3sa" ||
303 family == "xc3se" ||
304 family == "xc3s" ||
305 family == "xc2vp" ||
306 family == "xc2v") {
307 lut_size = 4;
308 widelut_size = 8;
309 } else if (family == "xcve" || family == "xcv") {
310 lut_size = 4;
311 widelut_size = 6;
312 } else
313 log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family.c_str());
314
315 if (widemux != 0 && lut_size != 6)
316 log_cmd_error("-widemux is not currently supported for LUT4-based architectures.\n");
317
318 if (lut_size != 6) {
319 log_warning("Shift register inference not yet supported for family %s.\n", family.c_str());
320 nosrl = true;
321 }
322
323 if (widemux != 0 && widemux < 2)
324 log_cmd_error("-widemux value must be 0 or >= 2.\n");
325
326 if (!design->full_selection())
327 log_cmd_error("This command only operates on fully selected designs!\n");
328
329 if (abc9 && retime)
330 log_cmd_error("-retime option not currently compatible with -abc9!\n");
331
332 log_header(design, "Executing SYNTH_XILINX pass.\n");
333 log_push();
334
335 run_script(design, run_from, run_to);
336
337 log_pop();
338 }
339
340 void script() YS_OVERRIDE
341 {
342 std::string lut_size_s = std::to_string(lut_size);
343 if (help_mode)
344 lut_size_s = "[46]";
345 std::string ff_map_file;
346 if (help_mode)
347 ff_map_file = "+/xilinx/{family}_ff_map.v";
348 else if (family == "xc6s")
349 ff_map_file = "+/xilinx/xc6s_ff_map.v";
350 else
351 ff_map_file = "+/xilinx/xc7_ff_map.v";
352
353 if (check_label("begin")) {
354 std::string read_args;
355 if (vpr)
356 read_args += " -D_EXPLICIT_CARRY";
357 read_args += " -lib -specify +/xilinx/cells_sim.v";
358 run("read_verilog" + read_args);
359
360 run("read_verilog -lib +/xilinx/cells_xtra.v");
361
362 run(stringf("hierarchy -check %s", top_opt.c_str()));
363 }
364
365 if (check_label("prepare")) {
366 run("proc");
367 if (flatten || help_mode)
368 run("flatten", "(with '-flatten')");
369 if (active_design)
370 active_design->scratchpad_unset("tribuf.added_something");
371 run("tribuf -logic");
372 if (noiopad && active_design && active_design->scratchpad_get_bool("tribuf.added_something"))
373 log_error("Tristate buffers are unsupported without the '-iopad' option.\n");
374 run("deminout");
375 run("opt_expr");
376 run("opt_clean");
377 run("check");
378 run("opt");
379 if (help_mode)
380 run("wreduce [-keepdc]", "(option for '-widemux')");
381 else
382 run("wreduce" + std::string(widemux > 0 ? " -keepdc" : ""));
383 run("peepopt");
384 run("opt_clean");
385
386 if (widemux > 0 || help_mode)
387 run("muxpack", " ('-widemux' only)");
388
389 // xilinx_srl looks for $shiftx cells for identifying variable-length
390 // shift registers, so attempt to convert $pmux-es to this
391 // Also: wide multiplexer inference benefits from this too
392 if (!(nosrl && widemux == 0) || help_mode) {
393 run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')");
394 run("clean", " (skip if '-nosrl' and '-widemux=0')");
395 }
396
397 run("techmap -map +/cmp2lut.v -D LUT_WIDTH=" + lut_size_s);
398 }
399
400 if (check_label("map_dsp", "(skip if '-nodsp')")) {
401 if (!nodsp || help_mode) {
402 run("memory_dff"); // xilinx_dsp will merge registers, reserve memory port registers first
403 // NB: Xilinx multipliers are signed only
404 if (help_mode)
405 run("techmap -map +/mul2dsp.v -map +/xilinx/{family}_dsp_map.v {options}");
406 else if (family == "xc2v" || family == "xc2vp" || family == "xc3s" || family == "xc3se" || family == "xc3sa")
407 run("techmap -map +/mul2dsp.v -map +/xilinx/xc3s_mult_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
408 "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
409 "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
410 "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
411 else if (family == "xc3sda")
412 run("techmap -map +/mul2dsp.v -map +/xilinx/xc3sda_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
413 "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
414 "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
415 "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
416 else if (family == "xc6s")
417 run("techmap -map +/mul2dsp.v -map +/xilinx/xc6s_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
418 "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
419 "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
420 "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
421 else if (family == "xc4v")
422 run("techmap -map +/mul2dsp.v -map +/xilinx/xc4v_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 "
423 "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
424 "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
425 "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18");
426 else if (family == "xc5v")
427 run("techmap -map +/mul2dsp.v -map +/xilinx/xc5v_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 "
428 "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
429 "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
430 "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
431 else if (family == "xc6v" || family == "xc7")
432 run("techmap -map +/mul2dsp.v -map +/xilinx/xc7_dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 "
433 "-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally
434 // limited to 18x18 in order to take
435 // advantage of the (PCOUT << 17) -> PCIN
436 // dedicated cascade chain capability
437 "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
438 "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
439 "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
440 else if (family == "xcu" || family == "xcup")
441 run("techmap -map +/mul2dsp.v -map +/xilinx/xcu_dsp_map.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=18 "
442 "-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally
443 // limited to 18x18 in order to take
444 // advantage of the (PCOUT << 17) -> PCIN
445 // dedicated cascade chain capability
446 "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers
447 "-D DSP_Y_MINWIDTH=9 " // UG901 suggests small multiplies are those 4x4 and smaller
448 "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL27X18");
449 run("select a:mul2dsp");
450 run("setattr -unset mul2dsp");
451 run("opt_expr -fine");
452 run("wreduce");
453 run("select -clear");
454 if (help_mode)
455 run("xilinx_dsp -family <family>");
456 else
457 run("xilinx_dsp -family " + family);
458 run("chtype -set $mul t:$__soft_mul");
459 }
460 }
461
462 if (check_label("coarse")) {
463 run("alumacc");
464 run("share");
465 run("opt");
466 run("fsm");
467 run("opt -fast");
468 run("memory -nomap");
469 run("opt_clean");
470 }
471
472 if (check_label("map_uram", "(only if '-uram')")) {
473 if (help_mode) {
474 run("memory_bram -rules +/xilinx/{family}_urams.txt");
475 run("techmap -map +/xilinx/{family}_urams_map.v");
476 } else if (uram) {
477 if (family == "xcup") {
478 run("memory_bram -rules +/xilinx/xcup_urams.txt");
479 run("techmap -map +/xilinx/xcup_urams_map.v");
480 } else {
481 log_warning("UltraRAM inference not supported for family %s.\n", family.c_str());
482 }
483 }
484 }
485
486 if (check_label("map_bram", "(skip if '-nobram')")) {
487 if (help_mode) {
488 run("memory_bram -rules +/xilinx/{family}_brams.txt");
489 run("techmap -map +/xilinx/{family}_brams_map.v");
490 } else if (!nobram) {
491 if (family == "xc2v" || family == "xc2vp" || family == "xc3s" || family == "xc3se") {
492 run("memory_bram -rules +/xilinx/xc2v_brams.txt");
493 run("techmap -map +/xilinx/xc2v_brams_map.v");
494 } else if (family == "xc3sa") {
495 // Superset of Virtex 2 primitives — uses common map file.
496 run("memory_bram -rules +/xilinx/xc3sa_brams.txt");
497 run("techmap -map +/xilinx/xc2v_brams_map.v");
498 } else if (family == "xc3sda") {
499 // Supported block RAMs for Spartan 3A DSP are
500 // a subset of Spartan 6's ones.
501 run("memory_bram -rules +/xilinx/xc3sda_brams.txt");
502 run("techmap -map +/xilinx/xc6s_brams_map.v");
503 } else if (family == "xc6s") {
504 run("memory_bram -rules +/xilinx/xc6s_brams.txt");
505 run("techmap -map +/xilinx/xc6s_brams_map.v");
506 } else if (family == "xc6v" || family == "xc7") {
507 run("memory_bram -rules +/xilinx/xc7_xcu_brams.txt");
508 run("techmap -map +/xilinx/xc7_brams_map.v");
509 } else if (family == "xcu" || family == "xcup") {
510 run("memory_bram -rules +/xilinx/xc7_xcu_brams.txt");
511 run("techmap -map +/xilinx/xcu_brams_map.v");
512 } else {
513 log_warning("Block RAM inference not yet supported for family %s.\n", family.c_str());
514 }
515 }
516 }
517
518 if (check_label("map_lutram", "(skip if '-nolutram')")) {
519 if (!nolutram || help_mode) {
520 run("memory_bram -rules +/xilinx/lut" + lut_size_s + "_lutrams.txt");
521 run("techmap -map +/xilinx/lutrams_map.v");
522 }
523 }
524
525 if (check_label("map_ffram")) {
526 // Required for dffsr2dff to work.
527 run("simplemap t:$dff t:$adff t:$mux");
528 // Needs to be done before opt -mux_bool happens.
529 run("dffsr2dff");
530 if (help_mode)
531 run("dff2dffs [-match-init]", "(-match-init for xc6s only)");
532 else if (family == "xc6s")
533 run("dff2dffs -match-init");
534 else
535 run("dff2dffs");
536 if (widemux > 0)
537 run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover
538 // performs less efficiently
539 else
540 run("opt -fast -full");
541 run("memory_map");
542 }
543
544 if (check_label("fine")) {
545 run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
546 if (help_mode)
547 run("muxcover <internal options> ('-widemux' only)");
548 else if (widemux > 0) {
549 constexpr int cost_mux2 = 100;
550 std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2);
551 switch (widemux) {
552 case 2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break;
553 case 3:
554 case 4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break;
555 case 5:
556 case 6:
557 case 7:
558 case 8: muxcover_args += stringf(" -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break;
559 case 9:
560 case 10:
561 case 11:
562 case 12:
563 case 13:
564 case 14:
565 case 15:
566 default: muxcover_args += stringf(" -mux16=%d", cost_mux2*(widemux-1)-1); break;
567 }
568 run("muxcover " + muxcover_args);
569 }
570 run("opt -full");
571
572 if (!nosrl || help_mode)
573 run("xilinx_srl -variable -minlen 3", "(skip if '-nosrl')");
574
575 std::string techmap_args = " -map +/techmap.v -D LUT_SIZE=" + lut_size_s;
576 if (help_mode)
577 techmap_args += " [-map +/xilinx/mux_map.v]";
578 else if (widemux > 0)
579 techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", widemux);
580 if (!nocarry) {
581 techmap_args += " -map +/xilinx/arith_map.v";
582 if (vpr)
583 techmap_args += " -D _EXPLICIT_CARRY";
584 }
585 run("techmap " + techmap_args);
586 run("opt -fast");
587 }
588
589 if (check_label("map_cells")) {
590 // Needs to be done before logic optimization, so that inverters (OE vs T) are handled.
591 if (help_mode || !noiopad)
592 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", "(skip if '-noiopad')");
593 std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v";
594 if (widemux > 0)
595 techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux);
596 run("techmap " + techmap_args);
597 run("clean");
598 }
599
600 if (check_label("map_ffs")) {
601 if (abc9 || help_mode) {
602 run("techmap -map " + ff_map_file, "('-abc9' only)");
603 }
604 }
605
606 if (check_label("map_luts")) {
607 run("opt_expr -mux_undef");
608 if (flatten_before_abc)
609 run("flatten");
610 if (help_mode)
611 run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for 'nowidelut', '-dff', '-retime')");
612 else if (abc9) {
613 if (lut_size != 6)
614 log_error("'synth_xilinx -abc9' not currently supported for LUT4-based devices.\n");
615 if (family != "xc7")
616 log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, "
617 "will use timing for 'xc7' instead.\n", family.c_str());
618 std::string techmap_args = "-map +/xilinx/abc9_map.v -max_iter 1";
619 if (dff_mode)
620 techmap_args += " -D DFF_MODE";
621 run("techmap " + techmap_args);
622 run("read_verilog -icells -lib -specify +/abc9_model.v +/xilinx/abc9_model.v");
623 std::string abc9_opts;
624 auto k = stringf("synth_xilinx.abc9.%s.W", family.c_str());
625 if (active_design->scratchpad.count(k))
626 abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str());
627 else
628 abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k, RTLIL::constpad.at("synth_xilinx.abc9.xc7.W")).c_str());
629 if (nowidelut)
630 abc9_opts += stringf(" -maxlut %d", lut_size);
631 if (dff_mode)
632 abc9_opts += " -dff";
633 run("abc9" + abc9_opts);
634 run("techmap -map +/xilinx/abc9_unmap.v");
635 }
636 else {
637 std::string abc_opts;
638 if (lut_size != 6) {
639 if (nowidelut)
640 abc_opts += " -lut " + lut_size_s;
641 else
642 abc_opts += " -lut " + lut_size_s + ":" + std::to_string(widelut_size);
643 } else {
644 if (nowidelut)
645 abc_opts += " -luts 2:2,3,6:5";
646 else if (widelut_size == 8)
647 abc_opts += " -luts 2:2,3,6:5,10,20";
648 else
649 abc_opts += " -luts 2:2,3,6:5,10,20,40";
650 }
651 if (dff_mode)
652 abc_opts += " -dff";
653 if (retime)
654 abc_opts += " -D 1";
655 run("abc" + abc_opts);
656 }
657 run("clean");
658
659 // This shregmap call infers fixed length shift registers after abc
660 // has performed any necessary retiming
661 if (!nosrl || help_mode)
662 run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')");
663 std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v";
664 if (help_mode || !abc9)
665 techmap_args += stringf(" -map %s", ff_map_file.c_str());
666 techmap_args += " -D LUT_WIDTH=" + lut_size_s;
667 run("techmap " + techmap_args);
668 if (help_mode)
669 run("xilinx_dffopt [-lut4]");
670 else if (lut_size == 4)
671 run("xilinx_dffopt -lut4");
672 else
673 run("xilinx_dffopt");
674 run("opt_lut_ins -tech xilinx");
675 }
676
677 if (check_label("finalize")) {
678 if (help_mode || !noclkbuf)
679 run("clkbufmap -buf BUFG O:I", "(skip if '-noclkbuf')");
680 if (help_mode || ise)
681 run("extractinv -inv INV O:I", "(only if '-ise')");
682 run("clean");
683 }
684
685 if (check_label("check")) {
686 run("hierarchy -check");
687 run("stat -tech xilinx");
688 run("check -noinit");
689 }
690
691 if (check_label("edif")) {
692 if (!edif_file.empty() || help_mode)
693 run(stringf("write_edif -pvector bra %s", edif_file.c_str()));
694 }
695
696 if (check_label("blif")) {
697 if (!blif_file.empty() || help_mode)
698 run(stringf("write_blif %s", edif_file.c_str()));
699 }
700 }
701 } SynthXilinxPass;
702
703 PRIVATE_NAMESPACE_END