2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Claire Wolf <claire@symbioticeda.com>
5 * Copyright (C) 2019 Dan Ravensloft <dan.ravensloft@gmail.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/celltypes.h"
22 #include "kernel/log.h"
23 #include "kernel/register.h"
24 #include "kernel/rtlil.h"
27 PRIVATE_NAMESPACE_BEGIN
29 struct SynthIntelALMPass
: public ScriptPass
{
30 SynthIntelALMPass() : ScriptPass("synth_intel_alm", "synthesis for ALM-based Intel (Altera) FPGAs.") {}
32 void help() YS_OVERRIDE
34 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
36 log(" synth_intel_alm [options]\n");
38 log("This command runs synthesis for ALM-based Intel FPGAs.\n");
40 log(" -top <module>\n");
41 log(" use the specified module as top module (default='top')\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");
49 log(" output a netlist using Quartus cells instead of MISTRAL_* cells\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");
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");
61 log(" do not use LUT RAM cells in output netlist\n");
64 log(" do not use block RAM cells in output netlist\n");
67 log(" do not flatten design before synthesis\n");
69 log("The following commands are executed by this synthesis command:\n");
74 string top_opt
, family_opt
, bram_type
, vout_file
;
75 bool flatten
, quartus
, nolutram
, nobram
;
77 void clear_flags() YS_OVERRIDE
79 top_opt
= "-auto-top";
80 family_opt
= "cyclonev";
89 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
91 string run_from
, run_to
;
95 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
96 if (args
[argidx
] == "-family" && argidx
+ 1 < args
.size()) {
97 family_opt
= args
[++argidx
];
100 if (args
[argidx
] == "-top" && argidx
+ 1 < args
.size()) {
101 top_opt
= "-top " + args
[++argidx
];
104 if (args
[argidx
] == "-vqm" && argidx
+ 1 < args
.size()) {
106 vout_file
= args
[++argidx
];
109 if (args
[argidx
] == "-run" && argidx
+ 1 < args
.size()) {
110 size_t pos
= args
[argidx
+ 1].find(':');
111 if (pos
== std::string::npos
)
113 run_from
= args
[++argidx
].substr(0, pos
);
114 run_to
= args
[argidx
].substr(pos
+ 1);
117 if (args
[argidx
] == "-quartus") {
121 if (args
[argidx
] == "-nolutram") {
125 if (args
[argidx
] == "-nobram") {
129 if (args
[argidx
] == "-noflatten") {
135 extra_args(args
, argidx
, design
);
137 if (!design
->full_selection())
138 log_cmd_error("This command only operates on fully selected designs!\n");
140 if (family_opt
== "cyclonev") {
142 } else if (family_opt
== "cyclone10gx") {
145 log_cmd_error("Invalid family specified: '%s'\n", family_opt
.c_str());
148 log_header(design
, "Executing SYNTH_INTEL_ALM pass.\n");
151 run_script(design
, run_from
, run_to
);
156 void script() YS_OVERRIDE
159 family_opt
= "<family>";
160 bram_type
= "<bram_type>";
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 run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt
.c_str()));
169 // Misc and common cells
170 run("read_verilog -lib +/intel/common/altpll_bb.v");
171 run("read_verilog -lib +/intel_alm/common/megafunction_bb.v");
172 run(stringf("hierarchy -check %s", help_mode
? "-top <top>" : top_opt
.c_str()));
175 if (flatten
&& check_label("flatten", "(unless -noflatten)")) {
178 run("tribuf -logic");
182 if (check_label("coarse")) {
183 run("synth -run coarse -lut 6");
184 run("techmap -map +/intel_alm/common/arith_alm_map.v");
187 if (!nobram
&& check_label("map_bram", "(skip if -nobram)")) {
188 run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type
.c_str()));
189 run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type
.c_str()));
192 if (!nolutram
&& check_label("map_lutram", "(skip if -nolutram)")) {
193 run("memory_bram -rules +/intel_alm/common/lutram_mlab.txt", "(for Cyclone V / Cyclone 10GX)");
196 if (check_label("map_ffram")) {
201 if (check_label("map_ffs")) {
202 run("dff2dffe -direct-match $_DFF_*");
203 // As mentioned in common/dff_sim.v, Intel flops power up to zero,
204 // so use `zinit` to add inverters where needed.
206 run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v");
207 run("opt -full -undriven -mux_undef");
211 if (check_label("map_luts")) {
212 run("read_verilog -icells -specify -lib +/abc9_model.v");
213 run("abc9 -maxlut 6 -W 200");
214 run("techmap -map +/intel_alm/common/alm_map.v");
220 if (check_label("check")) {
221 run("hierarchy -check");
226 if (check_label("quartus")) {
227 if (quartus
|| help_mode
) {
228 // Quartus ICEs if you have a wire which has `[]` in its name,
229 // which Yosys produces when building memories out of flops.
230 run("rename -hide w:*[* w:*]*");
231 // VQM mode does not support 'x, so replace those with zero.
232 run("setundef -zero");
233 // VQM mode does not support multi-bit constant assignments
234 // (e.g. 2'b00 is an error), so as a workaround use references
235 // to constant driver cells, which Quartus accepts.
236 run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q");
237 // Rename from Yosys-internal MISTRAL_* cells to Quartus cells.
238 run(stringf("techmap -D %s -map +/intel_alm/common/quartus_rename.v", family_opt
.c_str()));
242 if (check_label("vqm")) {
243 if (!vout_file
.empty() || help_mode
) {
244 run(stringf("write_verilog -attr2comment -defparam -nohex -decimal %s", help_mode
? "<file-name>" : vout_file
.c_str()));
250 PRIVATE_NAMESPACE_END