Merge remote-tracking branch 'origin/xaig_dff' into eddie/abc9_refactor
[yosys.git] / passes / techmap / abc9.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 #define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate
30 // to one LUT6 (instead of a LUT5 + LUT2)
31
32 struct Abc9Pass : public ScriptPass
33 {
34 Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { }
35
36 void help() YS_OVERRIDE
37 {
38 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
39 log("\n");
40 log(" abc9 [options] [selection]\n");
41 log("\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");
44 log("\n");
45 log(" -exe <command>\n");
46 #ifdef ABCEXTERNAL
47 log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
48 #else
49 log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
50 #endif
51 log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
52 log("\n");
53 log(" -script <file>\n");
54 log(" use the specified ABC script file instead of the default script.\n");
55 log("\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");
60 log("\n");
61 log(" if no -script parameter is given, the following scripts are used:\n");
62 log("\n");
63 log(" for -lut/-luts (only one LUT size):\n");
64 // FIXME
65 //log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str());
66 log("\n");
67 log(" for -lut/-luts (different LUT sizes):\n");
68 // FIXME
69 //log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
70 log("\n");
71 log(" -fast\n");
72 log(" use different default scripts that are slightly faster (at the cost\n");
73 log(" of output quality):\n");
74 log("\n");
75 log(" for -lut/-luts:\n");
76 // FIXME
77 //log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str());
78 log("\n");
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");
83 log("\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");
87 // log("\n");
88 log(" -lut <width>\n");
89 log(" generate netlist using luts of (max) the specified width.\n");
90 log("\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");
96 log("\n");
97 log(" -lut <file>\n");
98 log(" pass this file with lut library to ABC.\n");
99 log("\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");
103 log("\n");
104 log(" -nocleanup\n");
105 log(" when this option is used, the temporary files created by this pass\n");
106 log(" are not removed. this is useful for debugging.\n");
107 log("\n");
108 log(" -showtmp\n");
109 log(" print the temp dir name in log. usually this is suppressed so that the\n");
110 log(" command output is identical across runs.\n");
111 log("\n");
112 log(" -markgroups\n");
113 log(" set a 'abcgroup' attribute on all objects created by ABC. The value of\n");
114 log(" this attribute is a unique integer for each ABC process started. This\n");
115 log(" is useful for debugging the partitioning of clock domains.\n");
116 log("\n");
117 log(" -box <file>\n");
118 log(" pass this file with box library to ABC. Use with -lut.\n");
119 log("\n");
120 log("Note that this is a logic optimization pass within Yosys that is calling ABC\n");
121 log("internally. This is not going to \"run ABC on your design\". It will instead run\n");
122 log("ABC on logic snippets extracted from your design. You will not get any useful\n");
123 log("output when passing an ABC script that writes a file. Instead write your full\n");
124 log("design as an XAIGER file with write_xaiger and then load that into ABC externally\n");
125 log("if you want to use ABC to convert your design into another format.\n");
126 log("\n");
127 log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
128 log("\n");
129 help_script();
130 log("\n");
131 }
132
133 std::stringstream map_cmd;
134 bool cleanup;
135
136 void clear_flags() YS_OVERRIDE
137 {
138 map_cmd.str("");
139 map_cmd << "abc9_map";
140 cleanup = true;
141 }
142
143 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
144 {
145 std::string run_from, run_to;
146 clear_flags();
147
148 size_t argidx;
149 for (argidx = 1; argidx < args.size(); argidx++) {
150 std::string arg = args[argidx];
151 if ((arg == "-exe" || arg == "-script" || arg == "-D" ||
152 /* arg == "-S" || */ arg == "-lut" || arg == "-luts" ||
153 arg == "-clk" || arg == "-box" || arg == "-W") &&
154 argidx+1 < args.size()) {
155 map_cmd << " " << arg << " " << args[++argidx];
156 continue;
157 }
158 if (arg == "-fast"
159 /*|| arg == "-nocleanup"*/ || arg == "-showtmp" || arg == "-markgroups"
160 || arg == "-nomfs") {
161 map_cmd << " " << arg;
162 continue;
163 }
164 if (arg == "-nocleanup") {
165 cleanup = false;
166 continue;
167 }
168 break;
169 }
170 extra_args(args, argidx, design);
171
172 log_header(design, "Executing ABC9 pass.\n");
173
174 run_script(design, run_from, run_to);
175 }
176
177 void script() YS_OVERRIDE
178 {
179 run("abc9_ops -prep_holes");
180 run("select -set abc9_holes A:abc9_holes");
181 run("flatten -wb @abc9_holes");
182 run("techmap @abc9_holes");
183 run("aigmap @abc9_holes");
184 run("select -list @abc9_holes");
185 run("abc9_ops -prep_dff");
186 run("opt -purge @abc9_holes");
187 run("setattr -mod -set whitebox 1 @abc9_holes");
188
189 auto selected_modules = active_design->selected_modules();
190 active_design->selection_stack.emplace_back(false);
191
192 for (auto mod : selected_modules) {
193 if (mod->get_blackbox_attribute())
194 continue;
195
196 if (mod->processes.size() > 0) {
197 log("Skipping module %s as it contains processes.\n", log_id(mod));
198 continue;
199 }
200
201 log_push();
202
203 active_design->selection().select(mod);
204
205 std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
206 if (!cleanup)
207 tempdir_name[0] = tempdir_name[4] = '_';
208 tempdir_name = make_temp_dir(tempdir_name);
209
210 run("scc -set_attr abc9_scc_id {}");
211 run("abc9_ops -break_scc");
212 run("aigmap");
213 run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()),
214 "write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig");
215 run(stringf("%s -tempdir %s", map_cmd.str().c_str(), tempdir_name.c_str()),
216 "abc9_map [options] -tempdir <abc-temp-dir>");
217 run("abc9_ops -unbreak_scc");
218
219 if (cleanup)
220 {
221 log("Removing temp directory.\n");
222 remove_directory(tempdir_name);
223 }
224
225 active_design->selection().selected_modules.clear();
226
227 log_pop();
228 }
229
230 active_design->selection_stack.pop_back();
231 }
232 } Abc9Pass;
233
234 PRIVATE_NAMESPACE_END