abc9: generate $abc9_holes design instead of <name>$holes
[yosys.git] / techlibs / ice40 / synth_ice40.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/register.h"
21 #include "kernel/celltypes.h"
22 #include "kernel/rtlil.h"
23 #include "kernel/log.h"
24
25 USING_YOSYS_NAMESPACE
26 PRIVATE_NAMESPACE_BEGIN
27
28 struct SynthIce40Pass : public ScriptPass
29 {
30 SynthIce40Pass() : ScriptPass("synth_ice40", "synthesis for iCE40 FPGAs") { }
31
32 void on_register() YS_OVERRIDE
33 {
34 RTLIL::constpad["synth_ice40.abc9.hx.W"] = "250";
35 RTLIL::constpad["synth_ice40.abc9.lp.W"] = "400";
36 RTLIL::constpad["synth_ice40.abc9.u.W"] = "750";
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_ice40 [options]\n");
44 log("\n");
45 log("This command runs synthesis for iCE40 FPGAs.\n");
46 log("\n");
47 log(" -device < hx | lp | u >\n");
48 log(" relevant only for '-abc9' flow, optimise timing for the specified device.\n");
49 log(" default: hx\n");
50 log("\n");
51 log(" -top <module>\n");
52 log(" use the specified module as top module\n");
53 log("\n");
54 log(" -blif <file>\n");
55 log(" write the design to the specified BLIF file. writing of an output file\n");
56 log(" is omitted if this parameter is not specified.\n");
57 log("\n");
58 log(" -edif <file>\n");
59 log(" write the design to the specified EDIF file. writing of an output file\n");
60 log(" is omitted if this parameter is not specified.\n");
61 log("\n");
62 log(" -json <file>\n");
63 log(" write the design to the specified JSON file. writing of an output file\n");
64 log(" is omitted if this parameter is not specified.\n");
65 log("\n");
66 log(" -run <from_label>:<to_label>\n");
67 log(" only run the commands between the labels (see below). an empty\n");
68 log(" from label is synonymous to 'begin', and empty to label is\n");
69 log(" synonymous to the end of the command list.\n");
70 log("\n");
71 log(" -noflatten\n");
72 log(" do not flatten design before synthesis\n");
73 log("\n");
74 log(" -dff\n");
75 log(" run 'abc'/'abc9' with -dff option\n");
76 log("\n");
77 log(" -retime\n");
78 log(" run 'abc' with '-dff -D 1' options\n");
79 log("\n");
80 log(" -nocarry\n");
81 log(" do not use SB_CARRY cells in output netlist\n");
82 log("\n");
83 log(" -nodffe\n");
84 log(" do not use SB_DFFE* cells in output netlist\n");
85 log("\n");
86 log(" -dffe_min_ce_use <min_ce_use>\n");
87 log(" do not use SB_DFFE* cells if the resulting CE line would go to less\n");
88 log(" than min_ce_use SB_DFFE* in output netlist\n");
89 log("\n");
90 log(" -nobram\n");
91 log(" do not use SB_RAM40_4K* cells in output netlist\n");
92 log("\n");
93 log(" -dsp\n");
94 log(" use iCE40 UltraPlus DSP cells for large arithmetic\n");
95 log("\n");
96 log(" -noabc\n");
97 log(" use built-in Yosys LUT techmapping instead of abc\n");
98 log("\n");
99 log(" -abc2\n");
100 log(" run two passes of 'abc' for slightly improved logic density\n");
101 log("\n");
102 log(" -vpr\n");
103 log(" generate an output netlist (and BLIF file) suitable for VPR\n");
104 log(" (this feature is experimental and incomplete)\n");
105 log("\n");
106 log(" -abc9\n");
107 log(" use new ABC9 flow (EXPERIMENTAL)\n");
108 log("\n");
109 log(" -flowmap\n");
110 log(" use FlowMap LUT techmapping instead of abc (EXPERIMENTAL)\n");
111 log("\n");
112 log("\n");
113 log("The following commands are executed by this synthesis command:\n");
114 help_script();
115 log("\n");
116 }
117
118 string top_opt, blif_file, edif_file, json_file, device_opt;
119 bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap;
120 int min_ce_use;
121
122 void clear_flags() YS_OVERRIDE
123 {
124 top_opt = "-auto-top";
125 blif_file = "";
126 edif_file = "";
127 json_file = "";
128 nocarry = false;
129 nodffe = false;
130 min_ce_use = -1;
131 nobram = false;
132 dsp = false;
133 flatten = true;
134 retime = false;
135 noabc = false;
136 abc2 = false;
137 vpr = false;
138 abc9 = false;
139 flowmap = false;
140 device_opt = "hx";
141 }
142
143 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
144 {
145 string run_from, run_to;
146 clear_flags();
147
148 size_t argidx;
149 for (argidx = 1; argidx < args.size(); argidx++)
150 {
151 if (args[argidx] == "-top" && argidx+1 < args.size()) {
152 top_opt = "-top " + args[++argidx];
153 continue;
154 }
155 if (args[argidx] == "-blif" && argidx+1 < args.size()) {
156 blif_file = args[++argidx];
157 continue;
158 }
159 if (args[argidx] == "-edif" && argidx+1 < args.size()) {
160 edif_file = args[++argidx];
161 continue;
162 }
163 if (args[argidx] == "-json" && argidx+1 < args.size()) {
164 json_file = args[++argidx];
165 continue;
166 }
167 if (args[argidx] == "-run" && argidx+1 < args.size()) {
168 size_t pos = args[argidx+1].find(':');
169 if (pos == std::string::npos)
170 break;
171 run_from = args[++argidx].substr(0, pos);
172 run_to = args[argidx].substr(pos+1);
173 continue;
174 }
175 if (args[argidx] == "-flatten") {
176 flatten = true;
177 continue;
178 }
179 if (args[argidx] == "-noflatten") {
180 flatten = false;
181 continue;
182 }
183 if (args[argidx] == "-retime") {
184 retime = true;
185 continue;
186 }
187 if (args[argidx] == "-relut") {
188 // removed, opt_lut is always run
189 continue;
190 }
191 if (args[argidx] == "-nocarry") {
192 nocarry = true;
193 continue;
194 }
195 if (args[argidx] == "-nodffe") {
196 nodffe = true;
197 continue;
198 }
199 if (args[argidx] == "-dffe_min_ce_use" && argidx+1 < args.size()) {
200 min_ce_use = atoi(args[++argidx].c_str());
201 continue;
202 }
203 if (args[argidx] == "-nobram") {
204 nobram = true;
205 continue;
206 }
207 if (args[argidx] == "-dsp") {
208 dsp = true;
209 continue;
210 }
211 if (args[argidx] == "-noabc") {
212 noabc = true;
213 continue;
214 }
215 if (args[argidx] == "-abc2") {
216 abc2 = true;
217 continue;
218 }
219 if (args[argidx] == "-vpr") {
220 vpr = true;
221 continue;
222 }
223 if (args[argidx] == "-abc9") {
224 abc9 = true;
225 continue;
226 }
227 if (args[argidx] == "-dff") {
228 dff = true;
229 continue;
230 }
231 if (args[argidx] == "-device" && argidx+1 < args.size()) {
232 device_opt = args[++argidx];
233 continue;
234 }
235 if (args[argidx] == "-flowmap") {
236 flowmap = true;
237 continue;
238 }
239 break;
240 }
241 extra_args(args, argidx, design);
242
243 if (!design->full_selection())
244 log_cmd_error("This command only operates on fully selected designs!\n");
245 if (device_opt != "hx" && device_opt != "lp" && device_opt !="u")
246 log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str());
247
248 if (abc9 && retime)
249 log_cmd_error("-retime option not currently compatible with -abc9!\n");
250 if (abc9 && noabc)
251 log_cmd_error("-abc9 is incompatible with -noabc!\n");
252 if (abc9 && flowmap)
253 log_cmd_error("-abc9 is incompatible with -flowmap!\n");
254 if (flowmap && noabc)
255 log_cmd_error("-flowmap is incompatible with -noabc!\n");
256
257 log_header(design, "Executing SYNTH_ICE40 pass.\n");
258 log_push();
259
260 run_script(design, run_from, run_to);
261
262 log_pop();
263 }
264
265 void script() YS_OVERRIDE
266 {
267 std::string define;
268 if (device_opt == "lp")
269 define = "-D ICE40_LP";
270 else if (device_opt == "u")
271 define = "-D ICE40_U";
272 else
273 define = "-D ICE40_HX";
274 if (check_label("begin"))
275 {
276 run("read_verilog " + define + " -lib -specify +/ice40/cells_sim.v");
277 run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
278 run("proc");
279 }
280
281 if (check_label("flatten", "(unless -noflatten)"))
282 {
283 if (flatten) {
284 run("flatten");
285 run("tribuf -logic");
286 run("deminout");
287 }
288 }
289
290 if (check_label("coarse"))
291 {
292 run("opt_expr");
293 run("opt_clean");
294 run("check");
295 run("opt");
296 run("wreduce");
297 run("peepopt");
298 run("opt_clean");
299 run("share");
300 run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
301 run("opt_expr");
302 run("opt_clean");
303 if (help_mode || dsp) {
304 run("memory_dff"); // ice40_dsp will merge registers, reserve memory port registers first
305 run("wreduce t:$mul");
306 run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 "
307 "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 "
308 "-D DSP_NAME=$__MUL16X16", "(if -dsp)");
309 run("select a:mul2dsp", " (if -dsp)");
310 run("setattr -unset mul2dsp", " (if -dsp)");
311 run("opt_expr -fine", " (if -dsp)");
312 run("wreduce", " (if -dsp)");
313 run("select -clear", " (if -dsp)");
314 run("ice40_dsp", " (if -dsp)");
315 run("chtype -set $mul t:$__soft_mul", "(if -dsp)");
316 }
317 run("alumacc");
318 run("opt");
319 run("fsm");
320 run("opt -fast");
321 run("memory -nomap");
322 run("opt_clean");
323 }
324
325 if (!nobram && check_label("map_bram", "(skip if -nobram)"))
326 {
327 run("memory_bram -rules +/ice40/brams.txt");
328 run("techmap -map +/ice40/brams_map.v");
329 run("ice40_braminit");
330 }
331
332 if (check_label("map_ffram"))
333 {
334 run("opt -fast -mux_undef -undriven -fine");
335 run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
336 "-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
337 "-attr syn_romstyle=auto -attr syn_romstyle=logic");
338 run("opt -undriven -fine");
339 }
340
341 if (check_label("map_gates"))
342 {
343 if (nocarry)
344 run("techmap");
345 else {
346 run("ice40_wrapcarry");
347 run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
348 }
349 run("opt -fast");
350 if (retime || help_mode)
351 run("abc -dff -D 1", "(only if -retime)");
352 run("ice40_opt");
353 }
354
355 if (check_label("map_ffs"))
356 {
357 if (!nodffe)
358 run("dff2dffe -direct-match $_DFF_*");
359 if (min_ce_use >= 0) {
360 run("opt_merge");
361 run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
362 run("simplemap t:$dff");
363 }
364 if ((abc9 && dff) || help_mode)
365 run("zinit -all", "(-abc9 and -dff only)");
366 run("techmap -map +/ice40/ff_map.v");
367 run("opt_expr -mux_undef");
368 run("simplemap");
369 run("ice40_ffinit");
370 run("ice40_ffssr");
371 run("ice40_opt -full");
372 }
373
374 if (check_label("map_luts"))
375 {
376 if (abc2 || help_mode) {
377 run("abc", " (only if -abc2)");
378 run("ice40_opt", "(only if -abc2)");
379 }
380 run("techmap -map +/ice40/latches_map.v");
381 if (noabc || flowmap || help_mode) {
382 run("simplemap", " (if -noabc or -flowmap)");
383 if (noabc || help_mode)
384 run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
385 if (flowmap || help_mode)
386 run("flowmap -maxlut 4", "(only if -flowmap)");
387 }
388 if (!noabc) {
389 if (abc9) {
390 run("read_verilog " + define + " -icells -lib -specify +/abc9_model.v +/ice40/abc9_model.v");
391 std::string abc9_opts;
392 std::string k = "synth_ice40.abc9.W";
393 if (active_design && active_design->scratchpad.count(k))
394 abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str());
395 else {
396 k = stringf("synth_ice40.abc9.%s.W", device_opt.c_str());
397 abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str());
398 }
399 if (dff)
400 abc9_opts += " -dff";
401 run("abc9 " + abc9_opts);
402 }
403 else
404 run(stringf("abc -dress -lut 4 %s", dff ? "-dff" : ""), "(skip if -noabc)");
405 }
406 run("ice40_wrapcarry -unwrap");
407 run("techmap -map +/ice40/ff_map.v");
408 run("clean");
409 run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
410 }
411
412 if (check_label("map_cells"))
413 {
414 if (help_mode)
415 run("techmap -map +/ice40/cells_map.v", "(skip if -vpr)");
416 else if (!vpr)
417 run("techmap -map +/ice40/cells_map.v");
418 run("clean");
419 }
420
421 if (check_label("check"))
422 {
423 run("autoname");
424 run("hierarchy -check");
425 run("stat");
426 run("check -noinit");
427 }
428
429 if (check_label("blif"))
430 {
431 if (!blif_file.empty() || help_mode) {
432 if (vpr || help_mode) {
433 run(stringf("opt_clean -purge"),
434 " (vpr mode)");
435 run(stringf("write_blif -attr -cname -conn -param %s",
436 help_mode ? "<file-name>" : blif_file.c_str()),
437 " (vpr mode)");
438 }
439 if (!vpr)
440 run(stringf("write_blif -gates -attr -param %s",
441 help_mode ? "<file-name>" : blif_file.c_str()),
442 " (non-vpr mode)");
443 }
444 }
445
446 if (check_label("edif"))
447 {
448 if (!edif_file.empty() || help_mode)
449 run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
450 }
451
452 if (check_label("json"))
453 {
454 if (!json_file.empty() || help_mode)
455 run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
456 }
457 }
458 } SynthIce40Pass;
459
460 PRIVATE_NAMESPACE_END