2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * (C) 2019 Eddie Hung <eddie@fpgeh.com>
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.
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.
21 #include "kernel/register.h"
22 #include "kernel/celltypes.h"
23 #include "kernel/rtlil.h"
24 #include "kernel/log.h"
27 PRIVATE_NAMESPACE_BEGIN
29 #define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate
30 // to one LUT6 (instead of a LUT5 + LUT2)
32 struct Abc9Pass
: public ScriptPass
34 Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { }
36 void help() YS_OVERRIDE
38 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
40 log(" abc9 [options] [selection]\n");
42 log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n");
43 log("library to a target architecture.\n");
45 log(" -exe <command>\n");
47 log(" use the specified command instead of \"" ABCEXTERNAL
"\" to execute ABC.\n");
49 log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
51 log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
53 log(" -script <file>\n");
54 log(" use the specified ABC script file instead of the default script.\n");
56 log(" if <file> starts with a plus sign (+), then the rest of the filename\n");
57 log(" string is interpreted as the command string to be passed to ABC. The\n");
58 log(" leading plus sign is removed and all commas (,) in the string are\n");
59 log(" replaced with blanks before the string is passed to ABC.\n");
61 log(" if no -script parameter is given, the following scripts are used:\n");
63 log(" for -lut/-luts (only one LUT size):\n");
65 //log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str());
67 log(" for -lut/-luts (different LUT sizes):\n");
69 //log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
72 log(" use different default scripts that are slightly faster (at the cost\n");
73 log(" of output quality):\n");
75 log(" for -lut/-luts:\n");
77 //log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str());
79 log(" -D <picoseconds>\n");
80 log(" set delay target. the string {D} in the default scripts above is\n");
81 log(" replaced by this option when used, and an empty string otherwise\n");
82 log(" (indicating best possible delay).\n");
84 // log(" -S <num>\n");
85 // log(" maximum number of LUT inputs shared.\n");
86 // log(" (replaces {S} in the default scripts above, default: -S 1)\n");
88 log(" -lut <width>\n");
89 log(" generate netlist using luts of (max) the specified width.\n");
91 log(" -lut <w1>:<w2>\n");
92 log(" generate netlist using luts of (max) the specified width <w2>. All\n");
93 log(" luts with width <= <w1> have constant cost. for luts larger than <w1>\n");
94 log(" the area cost doubles with each additional input bit. the delay cost\n");
95 log(" is still constant for all lut widths.\n");
97 log(" -lut <file>\n");
98 log(" pass this file with lut library to ABC.\n");
100 log(" -luts <cost1>,<cost2>,<cost3>,<sizeN>:<cost4-N>,..\n");
101 log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
102 log(" 2, 3, .. inputs.\n");
105 log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n");
106 log(" domains are marked as such and automatically partitioned by ABC.\n");
108 log(" -nocleanup\n");
109 log(" when this option is used, the temporary files created by this pass\n");
110 log(" are not removed. this is useful for debugging.\n");
113 log(" print the temp dir name in log. usually this is suppressed so that the\n");
114 log(" command output is identical across runs.\n");
116 log(" -markgroups\n");
117 log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n");
118 log(" this attribute is a unique integer for each ABC process started. This\n");
119 log(" is useful for debugging the partitioning of clock domains.\n");
121 log(" -box <file>\n");
122 log(" pass this file with box library to ABC. Use with -lut.\n");
124 log("Note that this is a logic optimization pass within Yosys that is calling ABC\n");
125 log("internally. This is not going to \"run ABC on your design\". It will instead run\n");
126 log("ABC on logic snippets extracted from your design. You will not get any useful\n");
127 log("output when passing an ABC script that writes a file. Instead write your full\n");
128 log("design as an XAIGER file with `write_xaiger' and then load that into ABC\n");
129 log("externally if you want to use ABC to convert your design into another format.\n");
131 log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
137 std::stringstream map_cmd
;
138 bool dff_mode
, cleanup
;
140 void clear_flags() YS_OVERRIDE
143 map_cmd
<< "abc9_map";
148 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
150 std::string run_from
, run_to
;
154 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
155 std::string arg
= args
[argidx
];
156 if ((arg
== "-exe" || arg
== "-script" || arg
== "-D" ||
157 /* arg == "-S" || */ arg
== "-lut" || arg
== "-luts" ||
158 arg
== "-box" || arg
== "-W") &&
159 argidx
+1 < args
.size()) {
160 map_cmd
<< " " << arg
<< " " << args
[++argidx
];
163 if (arg
== "-fast" || /* arg == "-dff" || */
164 /* arg == "-nocleanup" || */ arg
== "-showtmp" || arg
== "-markgroups" ||
166 map_cmd
<< " " << arg
;
173 if (arg
== "-nocleanup") {
179 extra_args(args
, argidx
, design
);
181 log_header(design
, "Executing ABC9 pass.\n");
183 run_script(design
, run_from
, run_to
);
186 void script() YS_OVERRIDE
188 run("abc9_ops -prep_holes");
189 run("select -set abc9_holes A:abc9_holes");
190 run("flatten -wb @abc9_holes");
191 run("techmap @abc9_holes");
192 run("scc -set_attr abc9_scc_id {}");
193 run("abc9_ops -break_scc");
196 run("abc9_ops -prep_dff");
197 run("opt -purge @abc9_holes");
198 run("wbflip @abc9_holes");
200 auto selected_modules
= active_design
->selected_modules();
201 active_design
->selection_stack
.emplace_back(false);
203 for (auto mod
: selected_modules
) {
204 if (mod
->get_blackbox_attribute())
207 if (mod
->processes
.size() > 0) {
208 log("Skipping module %s as it contains processes.\n", log_id(mod
));
212 active_design
->selection().select(mod
);
214 std::string tempdir_name
= "/tmp/yosys-abc-XXXXXX";
216 tempdir_name
[0] = tempdir_name
[4] = '_';
217 tempdir_name
= make_temp_dir(tempdir_name
);
219 run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name
.c_str(), tempdir_name
.c_str()),
220 "write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig");
221 run(stringf("%s -tempdir %s", map_cmd
.str().c_str(), tempdir_name
.c_str()),
222 "abc9_map [options] -tempdir <abc-temp-dir>");
226 log("Removing temp directory.\n");
227 remove_directory(tempdir_name
);
230 active_design
->selection().selected_modules
.clear();
233 active_design
->selection_stack
.pop_back();
235 run("abc9_ops -unbreak_scc");
239 PRIVATE_NAMESPACE_END