Merge pull request #1916 from YosysHQ/eddie/kernel_makeblackbox
[yosys.git] / techlibs / intel_alm / synth_intel_alm.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Claire Wolf <claire@symbioticeda.com>
5 * Copyright (C) 2019 Dan Ravensloft <dan.ravensloft@gmail.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/celltypes.h"
22 #include "kernel/log.h"
23 #include "kernel/register.h"
24 #include "kernel/rtlil.h"
25
26 USING_YOSYS_NAMESPACE
27 PRIVATE_NAMESPACE_BEGIN
28
29 struct SynthIntelALMPass : public ScriptPass {
30 SynthIntelALMPass() : ScriptPass("synth_intel_alm", "synthesis for ALM-based Intel (Altera) FPGAs.") {}
31
32 void help() YS_OVERRIDE
33 {
34 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
35 log("\n");
36 log(" synth_intel_alm [options]\n");
37 log("\n");
38 log("This command runs synthesis for ALM-based Intel FPGAs.\n");
39 log("\n");
40 log(" -top <module>\n");
41 log(" use the specified module as top module (default='top')\n");
42 log("\n");
43 log(" -family <family>\n");
44 log(" target one of:\n");
45 log(" \"cyclonev\" - Cyclone V (default)\n");
46 log(" \"cyclone10gx\" - Cyclone 10GX\n");
47 log("\n");
48 log(" -quartus\n");
49 log(" output a netlist using Quartus cells instead of MISTRAL_* cells\n");
50 log("\n");
51 log(" -vqm <file>\n");
52 log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
53 log(" output file is omitted if this parameter is not specified. Implies -quartus.\n");
54 log("\n");
55 log(" -run <from_label>:<to_label>\n");
56 log(" only run the commands between the labels (see below). an empty\n");
57 log(" from label is synonymous to 'begin', and empty to label is\n");
58 log(" synonymous to the end of the command list.\n");
59 log("\n");
60 log(" -nolutram\n");
61 log(" do not use LUT RAM cells in output netlist\n");
62 log("\n");
63 log(" -nobram\n");
64 log(" do not use block RAM cells in output netlist\n");
65 log("\n");
66 log(" -noflatten\n");
67 log(" do not flatten design before synthesis\n");
68 log("\n");
69 log("The following commands are executed by this synthesis command:\n");
70 help_script();
71 log("\n");
72 }
73
74 string top_opt, family_opt, bram_type, vout_file;
75 bool flatten, quartus, nolutram, nobram;
76
77 void clear_flags() YS_OVERRIDE
78 {
79 top_opt = "-auto-top";
80 family_opt = "cyclonev";
81 bram_type = "m10k";
82 vout_file = "";
83 flatten = true;
84 quartus = false;
85 nolutram = false;
86 nobram = false;
87 }
88
89 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
90 {
91 string run_from, run_to;
92 clear_flags();
93
94 size_t argidx;
95 for (argidx = 1; argidx < args.size(); argidx++) {
96 if (args[argidx] == "-family" && argidx + 1 < args.size()) {
97 family_opt = args[++argidx];
98 continue;
99 }
100 if (args[argidx] == "-top" && argidx + 1 < args.size()) {
101 top_opt = "-top " + args[++argidx];
102 continue;
103 }
104 if (args[argidx] == "-vqm" && argidx + 1 < args.size()) {
105 quartus = true;
106 vout_file = args[++argidx];
107 continue;
108 }
109 if (args[argidx] == "-run" && argidx + 1 < args.size()) {
110 size_t pos = args[argidx + 1].find(':');
111 if (pos == std::string::npos)
112 break;
113 run_from = args[++argidx].substr(0, pos);
114 run_to = args[argidx].substr(pos + 1);
115 continue;
116 }
117 if (args[argidx] == "-quartus") {
118 quartus = true;
119 continue;
120 }
121 if (args[argidx] == "-nolutram") {
122 nolutram = true;
123 continue;
124 }
125 if (args[argidx] == "-nobram") {
126 nobram = true;
127 continue;
128 }
129 if (args[argidx] == "-noflatten") {
130 flatten = false;
131 continue;
132 }
133 break;
134 }
135 extra_args(args, argidx, design);
136
137 if (!design->full_selection())
138 log_cmd_error("This command only operates on fully selected designs!\n");
139
140 if (family_opt == "cyclonev") {
141 bram_type = "m10k";
142 } else if (family_opt == "cyclone10gx") {
143 bram_type = "m20k";
144 } else {
145 log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str());
146 }
147
148 log_header(design, "Executing SYNTH_INTEL_ALM pass.\n");
149 log_push();
150
151 run_script(design, run_from, run_to);
152
153 log_pop();
154 }
155
156 void script() YS_OVERRIDE
157 {
158 if (help_mode) {
159 family_opt = "<family>";
160 bram_type = "<bram_type>";
161 }
162
163 if (check_label("begin")) {
164 run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str()));
165 run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
166 run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
167
168 // Misc and common cells
169 run("read_verilog -lib +/intel/common/altpll_bb.v");
170 run("read_verilog -lib +/intel_alm/common/megafunction_bb.v");
171 run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
172 }
173
174 if (flatten && check_label("flatten", "(unless -noflatten)")) {
175 run("proc");
176 run("flatten");
177 run("tribuf -logic");
178 run("deminout");
179 }
180
181 if (check_label("coarse")) {
182 run("synth -run coarse -lut 6");
183 run("techmap -map +/intel_alm/common/arith_alm_map.v");
184 }
185
186 if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
187 run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str()));
188 run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
189 }
190
191 if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) {
192 run("memory_bram -rules +/intel_alm/common/lutram_mlab.txt", "(for Cyclone V / Cyclone 10GX)");
193 run("techmap -map +/intel_alm/common/lutram_mlab_map.v", "(for Cyclone V / Cyclone 10GX)");
194 }
195
196 if (check_label("map_ffram")) {
197 run("memory_map");
198 run("opt -full");
199 }
200
201 if (check_label("map_ffs")) {
202 run("dff2dffe -direct-match $_DFF_*");
203 run("zinit");
204 run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v");
205 run("opt -full -undriven -mux_undef");
206 run("clean -purge");
207 }
208
209 if (check_label("map_luts")) {
210 run("read_verilog -icells -specify -lib +/abc9_model.v");
211 run("abc9 -maxlut 6 -W 200");
212 run("techmap -map +/intel_alm/common/alm_map.v");
213 run("opt -fast");
214 run("autoname");
215 run("clean");
216 }
217
218 if (check_label("check")) {
219 run("hierarchy -check");
220 run("stat");
221 run("check");
222 }
223
224 if (check_label("quartus")) {
225 if (quartus || help_mode) {
226 run("setundef -zero");
227 run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q");
228 run("techmap -map +/intel_alm/common/quartus_rename.v");
229 run(stringf("techmap -map +/intel_alm/%s/quartus_rename.v", family_opt.c_str()));
230 }
231 }
232
233 if (check_label("vqm")) {
234 if (!vout_file.empty() || help_mode) {
235 run(stringf("write_verilog -attr2comment -defparam -nohex -decimal %s", help_mode ? "<file-name>" : vout_file.c_str()));
236 }
237 }
238 }
239 } SynthIntelALMPass;
240
241 PRIVATE_NAMESPACE_END