1 /*
2  *  yosys -- Yosys Open SYnthesis Suite
3  *
4  *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
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 SynthPass : public ScriptPass
29 {
SynthPassSynthPass30 	SynthPass() : ScriptPass("synth", "generic synthesis script") { }
31 
helpSynthPass32 	void help() override
33 	{
34 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
35 		log("\n");
36 		log("    synth [options]\n");
37 		log("\n");
38 		log("This command runs the default synthesis script. This command does not operate\n");
39 		log("on partly selected designs.\n");
40 		log("\n");
41 		log("    -top <module>\n");
42 		log("        use the specified module as top module (default='top')\n");
43 		log("\n");
44 		log("    -auto-top\n");
45 		log("        automatically determine the top of the design hierarchy\n");
46 		log("\n");
47 		log("    -flatten\n");
48 		log("        flatten the design before synthesis. this will pass '-auto-top' to\n");
49 		log("        'hierarchy' if no top module is specified.\n");
50 		log("\n");
51 		log("    -encfile <file>\n");
52 		log("        passed to 'fsm_recode' via 'fsm'\n");
53 		log("\n");
54 		log("    -lut <k>\n");
55 		log("        perform synthesis for a k-LUT architecture.\n");
56 		log("\n");
57 		log("    -nofsm\n");
58 		log("        do not run FSM optimization\n");
59 		log("\n");
60 		log("    -noabc\n");
61 		log("        do not run abc (as if yosys was compiled without ABC support)\n");
62 		log("\n");
63 		log("    -noalumacc\n");
64 		log("        do not run 'alumacc' pass. i.e. keep arithmetic operators in\n");
65 		log("        their direct form ($add, $sub, etc.).\n");
66 		log("\n");
67 		log("    -nordff\n");
68 		log("        passed to 'memory'. prohibits merging of FFs into memory read ports\n");
69 		log("\n");
70 		log("    -noshare\n");
71 		log("        do not run SAT-based resource sharing\n");
72 		log("\n");
73 		log("    -run <from_label>[:<to_label>]\n");
74 		log("        only run the commands between the labels (see below). an empty\n");
75 		log("        from label is synonymous to 'begin', and empty to label is\n");
76 		log("        synonymous to the end of the command list.\n");
77 		log("\n");
78 		log("    -abc9\n");
79 		log("        use new ABC9 flow (EXPERIMENTAL)\n");
80 		log("\n");
81 		log("    -flowmap\n");
82 		log("        use FlowMap LUT techmapping instead of ABC\n");
83 		log("\n");
84 		log("\n");
85 		log("The following commands are executed by this synthesis command:\n");
86 		help_script();
87 		log("\n");
88 	}
89 
90 	string top_module, fsm_opts, memory_opts, abc;
91 	bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap;
92 	int lut;
93 
clear_flagsSynthPass94 	void clear_flags() override
95 	{
96 		top_module.clear();
97 		fsm_opts.clear();
98 		memory_opts.clear();
99 
100 		autotop = false;
101 		flatten = false;
102 		lut = 0;
103 		noalumacc = false;
104 		nofsm = false;
105 		noabc = false;
106 		noshare = false;
107 		flowmap = false;
108 		abc = "abc";
109 	}
110 
executeSynthPass111 	void execute(std::vector<std::string> args, RTLIL::Design *design) override
112 	{
113 		string run_from, run_to;
114 		clear_flags();
115 
116 		size_t argidx;
117 		for (argidx = 1; argidx < args.size(); argidx++)
118 		{
119 			if (args[argidx] == "-top" && argidx+1 < args.size()) {
120 				top_module = args[++argidx];
121 				continue;
122 			}
123 			if (args[argidx] == "-encfile" && argidx+1 < args.size()) {
124 				fsm_opts = " -encfile " + args[++argidx];
125 				continue;
126 			}
127 			if (args[argidx] == "-run" && argidx+1 < args.size()) {
128 				size_t pos = args[argidx+1].find(':');
129 				if (pos == std::string::npos) {
130 					run_from = args[++argidx];
131 					run_to = args[argidx];
132 				} else {
133 					run_from = args[++argidx].substr(0, pos);
134 					run_to = args[argidx].substr(pos+1);
135 				}
136 				continue;
137 			}
138 			if (args[argidx] == "-auto-top") {
139 				autotop = true;
140 				continue;
141 			}
142 			if (args[argidx] == "-flatten") {
143 				flatten = true;
144 				continue;
145 			}
146 			if (args[argidx] == "-lut") {
147 				lut = atoi(args[++argidx].c_str());
148 				continue;
149 			}
150 			if (args[argidx] == "-nofsm") {
151 				nofsm = true;
152 				continue;
153 			}
154 			if (args[argidx] == "-noabc") {
155 				noabc = true;
156 				continue;
157 			}
158 			if (args[argidx] == "-noalumacc") {
159 				noalumacc = true;
160 				continue;
161 			}
162 			if (args[argidx] == "-nordff") {
163 				memory_opts += " -nordff";
164 				continue;
165 			}
166 			if (args[argidx] == "-noshare") {
167 				noshare = true;
168 				continue;
169 			}
170 			if (args[argidx] == "-abc9") {
171 				abc = "abc9";
172 				continue;
173 			}
174 			if (args[argidx] == "-flowmap") {
175 				flowmap = true;
176 				continue;
177 			}
178 			break;
179 		}
180 		extra_args(args, argidx, design);
181 
182 		if (!design->full_selection())
183 			log_cmd_error("This command only operates on fully selected designs!\n");
184 
185 		if (abc == "abc9" && !lut)
186 			log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)\n");
187 		if (flowmap && !lut)
188 			log_cmd_error("FlowMap is only supported for FPGA synthesis (using '-lut' option)\n");
189 
190 		log_header(design, "Executing SYNTH pass.\n");
191 		log_push();
192 
193 		run_script(design, run_from, run_to);
194 
195 		log_pop();
196 	}
197 
scriptSynthPass198 	void script() override
199 	{
200 		if (check_label("begin"))
201 		{
202 			if (help_mode) {
203 				run("hierarchy -check [-top <top> | -auto-top]");
204 			} else {
205 				if (top_module.empty()) {
206 					if (flatten || autotop)
207 						run("hierarchy -check -auto-top");
208 					else
209 						run("hierarchy -check");
210 				} else
211 					run(stringf("hierarchy -check -top %s", top_module.c_str()));
212 			}
213 		}
214 
215 		if (check_label("coarse"))
216 		{
217 			run("proc");
218 			if (help_mode || flatten)
219 				run("flatten", "  (if -flatten)");
220 			run("opt_expr");
221 			run("opt_clean");
222 			run("check");
223 			run("opt -nodffe -nosdff");
224 			if (!nofsm)
225 				run("fsm" + fsm_opts, "      (unless -nofsm)");
226 			run("opt");
227 			run("wreduce");
228 			run("peepopt");
229 			run("opt_clean");
230 			if (help_mode)
231 				run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)");
232 			else if (lut)
233 				run(stringf("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", lut));
234 			if (!noalumacc)
235 				run("alumacc", "  (unless -noalumacc)");
236 			if (!noshare)
237 				run("share", "    (unless -noshare)");
238 			run("opt");
239 			run("memory -nomap" + memory_opts);
240 			run("opt_clean");
241 		}
242 
243 		if (check_label("fine"))
244 		{
245 			run("opt -fast -full");
246 			run("memory_map");
247 			run("opt -full");
248 			run("techmap");
249 			if (help_mode)
250 			{
251 				run("techmap -map +/gate2lut.v", "(if -noabc and -lut)");
252 				run("clean; opt_lut", "           (if -noabc and -lut)");
253 				run("flowmap -maxlut K", "        (if -flowmap and -lut)");
254 			}
255 			else if (noabc && lut)
256 			{
257 				run(stringf("techmap -map +/gate2lut.v -D LUT_WIDTH=%d", lut));
258 				run("clean; opt_lut");
259 			}
260 			else if (flowmap)
261 			{
262 				run(stringf("flowmap -maxlut %d", lut));
263 			}
264 			run("opt -fast");
265 
266 			if (!noabc && !flowmap) {
267 		#ifdef YOSYS_ENABLE_ABC
268 				if (help_mode)
269 				{
270 					run(abc + " -fast", "       (unless -noabc, unless -lut)");
271 					run(abc + " -fast -lut k", "(unless -noabc, if -lut)");
272 				}
273 				else
274 				{
275 					if (lut)
276 						run(stringf("%s -fast -lut %d", abc.c_str(), lut));
277 					else
278 						run(abc + " -fast");
279 				}
280 				run("opt -fast", "       (unless -noabc)");
281 		#endif
282 			}
283 		}
284 
285 		if (check_label("check"))
286 		{
287 			run("hierarchy -check");
288 			run("stat");
289 			run("check");
290 		}
291 	}
292 } SynthPass;
293 
294 PRIVATE_NAMESPACE_END
295