Refactoring: Renamed RTLIL::Module::cells to cells_
[yosys.git] / backends / verilog / verilog_backend.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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 * A simple and straightforward verilog backend.
21 *
22 * Note that RTLIL processes can't always be mapped easily to a Verilog
23 * process. Therefore this frontend should only be used to export a
24 * Verilog netlist (i.e. after the "proc" pass has converted all processes
25 * to logic networks and registers).
26 *
27 */
28
29 #include "verilog_backend.h"
30 #include "kernel/register.h"
31 #include "kernel/celltypes.h"
32 #include "kernel/log.h"
33 #include <assert.h>
34 #include <string>
35 #include <sstream>
36 #include <set>
37 #include <map>
38
39 namespace {
40
41 bool norename, noattr, attr2comment, noexpr;
42 int auto_name_counter, auto_name_offset, auto_name_digits;
43 std::map<std::string, int> auto_name_map;
44
45 std::set<std::string> reg_wires;
46
47 CellTypes reg_ct;
48 RTLIL::Module *active_module;
49
50 void reset_auto_counter_id(const std::string &id, bool may_rename)
51 {
52 const char *str = id.c_str();
53
54 if (*str == '$' && may_rename && !norename)
55 auto_name_map[id] = auto_name_counter++;
56
57 if (str[0] != '_' && str[1] != 0)
58 return;
59 for (int i = 0; str[i] != 0; i++) {
60 if (str[i] == '_')
61 continue;
62 if (str[i] < '0' || str[i] > '9')
63 return;
64 }
65
66 int num = atoi(str+1);
67 if (num >= auto_name_offset)
68 auto_name_offset = num + 1;
69 }
70
71 void reset_auto_counter(RTLIL::Module *module)
72 {
73 auto_name_map.clear();
74 auto_name_counter = 0;
75 auto_name_offset = 0;
76
77 reset_auto_counter_id(module->name, false);
78
79 for (auto it = module->wires_.begin(); it != module->wires_.end(); it++)
80 reset_auto_counter_id(it->second->name, true);
81
82 for (auto it = module->cells_.begin(); it != module->cells_.end(); it++) {
83 reset_auto_counter_id(it->second->name, true);
84 reset_auto_counter_id(it->second->type, false);
85 }
86
87 for (auto it = module->processes.begin(); it != module->processes.end(); it++)
88 reset_auto_counter_id(it->second->name, false);
89
90 auto_name_digits = 1;
91 for (size_t i = 10; i < auto_name_offset + auto_name_map.size(); i = i*10)
92 auto_name_digits++;
93
94 for (auto it = auto_name_map.begin(); it != auto_name_map.end(); it++)
95 log(" renaming `%s' to `_%0*d_'.\n", it->first.c_str(), auto_name_digits, auto_name_offset + it->second);
96 }
97
98 std::string id(std::string internal_id, bool may_rename = true)
99 {
100 const char *str = internal_id.c_str();
101 bool do_escape = false;
102
103 if (may_rename && auto_name_map.count(internal_id) != 0) {
104 char buffer[100];
105 snprintf(buffer, 100, "_%0*d_", auto_name_digits, auto_name_offset + auto_name_map[internal_id]);
106 return std::string(buffer);
107 }
108
109 if (*str == '\\')
110 str++;
111
112 if ('0' <= *str && *str <= '9')
113 do_escape = true;
114
115 for (int i = 0; str[i]; i++)
116 {
117 if ('0' <= str[i] && str[i] <= '9')
118 continue;
119 if ('a' <= str[i] && str[i] <= 'z')
120 continue;
121 if ('A' <= str[i] && str[i] <= 'Z')
122 continue;
123 if (str[i] == '_')
124 continue;
125 do_escape = true;
126 break;
127 }
128
129 if (do_escape)
130 return "\\" + std::string(str) + " ";
131 return std::string(str);
132 }
133
134 bool is_reg_wire(RTLIL::SigSpec sig, std::string &reg_name)
135 {
136 if (!sig.is_chunk() || sig.as_chunk().wire == NULL)
137 return false;
138
139 RTLIL::SigChunk chunk = sig.as_chunk();
140
141 if (reg_wires.count(chunk.wire->name) == 0)
142 return false;
143
144 reg_name = id(chunk.wire->name);
145 if (sig.size() != chunk.wire->width) {
146 if (sig.size() == 1)
147 reg_name += stringf("[%d]", chunk.wire->start_offset + chunk.offset);
148 else
149 reg_name += stringf("[%d:%d]", chunk.wire->start_offset + chunk.offset + chunk.width - 1,
150 chunk.wire->start_offset + chunk.offset);
151 }
152
153 return true;
154 }
155
156 void dump_const(FILE *f, const RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool set_signed = false)
157 {
158 if (width < 0)
159 width = data.bits.size() - offset;
160 if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
161 if (width == 32 && !no_decimal) {
162 int32_t val = 0;
163 for (int i = offset+width-1; i >= offset; i--) {
164 assert(i < (int)data.bits.size());
165 if (data.bits[i] != RTLIL::S0 && data.bits[i] != RTLIL::S1)
166 goto dump_bits;
167 if (data.bits[i] == RTLIL::S1)
168 val |= 1 << (i - offset);
169 }
170 // fprintf(f, "%s32'sd%u", val < 0 ? "-" : "", abs(val));
171 fprintf(f, "%d", val);
172 } else {
173 dump_bits:
174 fprintf(f, "%d'%sb", width, set_signed ? "s" : "");
175 if (width == 0)
176 fprintf(f, "0");
177 for (int i = offset+width-1; i >= offset; i--) {
178 assert(i < (int)data.bits.size());
179 switch (data.bits[i]) {
180 case RTLIL::S0: fprintf(f, "0"); break;
181 case RTLIL::S1: fprintf(f, "1"); break;
182 case RTLIL::Sx: fprintf(f, "x"); break;
183 case RTLIL::Sz: fprintf(f, "z"); break;
184 case RTLIL::Sa: fprintf(f, "z"); break;
185 case RTLIL::Sm: log_error("Found marker state in final netlist.");
186 }
187 }
188 }
189 } else {
190 fprintf(f, "\"");
191 std::string str = data.decode_string();
192 for (size_t i = 0; i < str.size(); i++) {
193 if (str[i] == '\n')
194 fprintf(f, "\\n");
195 else if (str[i] == '\t')
196 fprintf(f, "\\t");
197 else if (str[i] < 32)
198 fprintf(f, "\\%03o", str[i]);
199 else if (str[i] == '"')
200 fprintf(f, "\\\"");
201 else if (str[i] == '\\')
202 fprintf(f, "\\\\");
203 else
204 fputc(str[i], f);
205 }
206 fprintf(f, "\"");
207 }
208 }
209
210 void dump_sigchunk(FILE *f, const RTLIL::SigChunk &chunk, bool no_decimal = false)
211 {
212 if (chunk.wire == NULL) {
213 dump_const(f, chunk.data, chunk.width, chunk.offset, no_decimal);
214 } else {
215 if (chunk.width == chunk.wire->width && chunk.offset == 0)
216 fprintf(f, "%s", id(chunk.wire->name).c_str());
217 else if (chunk.width == 1)
218 fprintf(f, "%s[%d]", id(chunk.wire->name).c_str(), chunk.offset + chunk.wire->start_offset);
219 else
220 fprintf(f, "%s[%d:%d]", id(chunk.wire->name).c_str(),
221 chunk.offset + chunk.wire->start_offset + chunk.width - 1,
222 chunk.offset + chunk.wire->start_offset);
223 }
224 }
225
226 void dump_sigspec(FILE *f, const RTLIL::SigSpec &sig)
227 {
228 if (sig.is_chunk()) {
229 dump_sigchunk(f, sig.as_chunk());
230 } else {
231 fprintf(f, "{ ");
232 for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) {
233 if (it != sig.chunks().rbegin())
234 fprintf(f, ", ");
235 dump_sigchunk(f, *it, true);
236 }
237 fprintf(f, " }");
238 }
239 }
240
241 void dump_attributes(FILE *f, std::string indent, std::map<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n')
242 {
243 if (noattr)
244 return;
245 for (auto it = attributes.begin(); it != attributes.end(); it++) {
246 fprintf(f, "%s" "%s %s", indent.c_str(), attr2comment ? "/*" : "(*", id(it->first).c_str());
247 fprintf(f, " = ");
248 dump_const(f, it->second);
249 fprintf(f, " %s%c", attr2comment ? "*/" : "*)", term);
250 }
251 }
252
253 void dump_wire(FILE *f, std::string indent, RTLIL::Wire *wire)
254 {
255 dump_attributes(f, indent, wire->attributes);
256 #if 0
257 if (wire->port_input && !wire->port_output)
258 fprintf(f, "%s" "input %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : "");
259 else if (!wire->port_input && wire->port_output)
260 fprintf(f, "%s" "output %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : "");
261 else if (wire->port_input && wire->port_output)
262 fprintf(f, "%s" "inout %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : "");
263 else
264 fprintf(f, "%s" "%s ", indent.c_str(), reg_wires.count(wire->name) ? "reg" : "wire");
265 if (wire->width != 1)
266 fprintf(f, "[%d:%d] ", wire->width - 1 + wire->start_offset, wire->start_offset);
267 fprintf(f, "%s;\n", id(wire->name).c_str());
268 #else
269 // do not use Verilog-2k "outut reg" syntax in verilog export
270 std::string range = "";
271 if (wire->width != 1)
272 range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset);
273 if (wire->port_input && !wire->port_output)
274 fprintf(f, "%s" "input%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
275 if (!wire->port_input && wire->port_output)
276 fprintf(f, "%s" "output%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
277 if (wire->port_input && wire->port_output)
278 fprintf(f, "%s" "inout%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
279 if (reg_wires.count(wire->name))
280 fprintf(f, "%s" "reg%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
281 else if (!wire->port_input && !wire->port_output)
282 fprintf(f, "%s" "wire%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
283 #endif
284 }
285
286 void dump_memory(FILE *f, std::string indent, RTLIL::Memory *memory)
287 {
288 dump_attributes(f, indent, memory->attributes);
289 fprintf(f, "%s" "reg [%d:0] %s [%d:0];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size-1);
290 }
291
292 void dump_cell_expr_port(FILE *f, RTLIL::Cell *cell, std::string port, bool gen_signed = true)
293 {
294 if (gen_signed && cell->parameters.count("\\" + port + "_SIGNED") > 0 && cell->parameters["\\" + port + "_SIGNED"].as_bool()) {
295 fprintf(f, "$signed(");
296 dump_sigspec(f, cell->get("\\" + port));
297 fprintf(f, ")");
298 } else
299 dump_sigspec(f, cell->get("\\" + port));
300 }
301
302 std::string cellname(RTLIL::Cell *cell)
303 {
304 if (!norename && cell->name[0] == '$' && reg_ct.cell_known(cell->type) && cell->has("\\Q"))
305 {
306 RTLIL::SigSpec sig = cell->get("\\Q");
307 if (SIZE(sig) != 1 || sig.is_fully_const())
308 goto no_special_reg_name;
309
310 RTLIL::Wire *wire = sig[0].wire;
311
312 if (wire->name[0] != '\\')
313 goto no_special_reg_name;
314
315 std::string cell_name = wire->name;
316
317 size_t pos = cell_name.find('[');
318 if (pos != std::string::npos)
319 cell_name = cell_name.substr(0, pos) + "_reg" + cell_name.substr(pos);
320 else
321 cell_name = cell_name + "_reg";
322
323 if (wire->width != 1)
324 cell_name += stringf("[%d]", wire->start_offset + sig[0].offset);
325
326 if (active_module && active_module->count_id(cell_name) > 0)
327 goto no_special_reg_name;
328
329 return id(cell_name);
330 }
331 else
332 {
333 no_special_reg_name:
334 return id(cell->name).c_str();
335 }
336 }
337
338 void dump_cell_expr_uniop(FILE *f, std::string indent, RTLIL::Cell *cell, std::string op)
339 {
340 fprintf(f, "%s" "assign ", indent.c_str());
341 dump_sigspec(f, cell->get("\\Y"));
342 fprintf(f, " = %s ", op.c_str());
343 dump_attributes(f, "", cell->attributes, ' ');
344 dump_cell_expr_port(f, cell, "A", true);
345 fprintf(f, ";\n");
346 }
347
348 void dump_cell_expr_binop(FILE *f, std::string indent, RTLIL::Cell *cell, std::string op)
349 {
350 fprintf(f, "%s" "assign ", indent.c_str());
351 dump_sigspec(f, cell->get("\\Y"));
352 fprintf(f, " = ");
353 dump_cell_expr_port(f, cell, "A", true);
354 fprintf(f, " %s ", op.c_str());
355 dump_attributes(f, "", cell->attributes, ' ');
356 dump_cell_expr_port(f, cell, "B", true);
357 fprintf(f, ";\n");
358 }
359
360 bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell)
361 {
362 if (cell->type == "$_INV_") {
363 fprintf(f, "%s" "assign ", indent.c_str());
364 dump_sigspec(f, cell->get("\\Y"));
365 fprintf(f, " = ");
366 fprintf(f, "~");
367 dump_attributes(f, "", cell->attributes, ' ');
368 dump_cell_expr_port(f, cell, "A", false);
369 fprintf(f, ";\n");
370 return true;
371 }
372
373 if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_") {
374 fprintf(f, "%s" "assign ", indent.c_str());
375 dump_sigspec(f, cell->get("\\Y"));
376 fprintf(f, " = ");
377 dump_cell_expr_port(f, cell, "A", false);
378 fprintf(f, " ");
379 if (cell->type == "$_AND_")
380 fprintf(f, "&");
381 if (cell->type == "$_OR_")
382 fprintf(f, "|");
383 if (cell->type == "$_XOR_")
384 fprintf(f, "^");
385 dump_attributes(f, "", cell->attributes, ' ');
386 fprintf(f, " ");
387 dump_cell_expr_port(f, cell, "B", false);
388 fprintf(f, ";\n");
389 return true;
390 }
391
392 if (cell->type == "$_MUX_") {
393 fprintf(f, "%s" "assign ", indent.c_str());
394 dump_sigspec(f, cell->get("\\Y"));
395 fprintf(f, " = ");
396 dump_cell_expr_port(f, cell, "S", false);
397 fprintf(f, " ? ");
398 dump_attributes(f, "", cell->attributes, ' ');
399 dump_cell_expr_port(f, cell, "B", false);
400 fprintf(f, " : ");
401 dump_cell_expr_port(f, cell, "A", false);
402 fprintf(f, ";\n");
403 return true;
404 }
405
406 if (cell->type.substr(0, 6) == "$_DFF_")
407 {
408 std::string reg_name = cellname(cell);
409 bool out_is_reg_wire = is_reg_wire(cell->get("\\Q"), reg_name);
410
411 if (!out_is_reg_wire)
412 fprintf(f, "%s" "reg %s;\n", indent.c_str(), reg_name.c_str());
413
414 dump_attributes(f, indent, cell->attributes);
415 fprintf(f, "%s" "always @(%sedge ", indent.c_str(), cell->type[6] == 'P' ? "pos" : "neg");
416 dump_sigspec(f, cell->get("\\C"));
417 if (cell->type[7] != '_') {
418 fprintf(f, " or %sedge ", cell->type[7] == 'P' ? "pos" : "neg");
419 dump_sigspec(f, cell->get("\\R"));
420 }
421 fprintf(f, ")\n");
422
423 if (cell->type[7] != '_') {
424 fprintf(f, "%s" " if (%s", indent.c_str(), cell->type[7] == 'P' ? "" : "!");
425 dump_sigspec(f, cell->get("\\R"));
426 fprintf(f, ")\n");
427 fprintf(f, "%s" " %s <= %c;\n", indent.c_str(), reg_name.c_str(), cell->type[8]);
428 fprintf(f, "%s" " else\n", indent.c_str());
429 }
430
431 fprintf(f, "%s" " %s <= ", indent.c_str(), reg_name.c_str());
432 dump_cell_expr_port(f, cell, "D", false);
433 fprintf(f, ";\n");
434
435 if (!out_is_reg_wire) {
436 fprintf(f, "%s" "assign ", indent.c_str());
437 dump_sigspec(f, cell->get("\\Q"));
438 fprintf(f, " = %s;\n", reg_name.c_str());
439 }
440
441 return true;
442 }
443
444 if (cell->type.substr(0, 8) == "$_DFFSR_")
445 {
446 char pol_c = cell->type[8], pol_s = cell->type[9], pol_r = cell->type[10];
447
448 std::string reg_name = cellname(cell);
449 bool out_is_reg_wire = is_reg_wire(cell->get("\\Q"), reg_name);
450
451 if (!out_is_reg_wire)
452 fprintf(f, "%s" "reg %s;\n", indent.c_str(), reg_name.c_str());
453
454 dump_attributes(f, indent, cell->attributes);
455 fprintf(f, "%s" "always @(%sedge ", indent.c_str(), pol_c == 'P' ? "pos" : "neg");
456 dump_sigspec(f, cell->get("\\C"));
457 fprintf(f, " or %sedge ", pol_s == 'P' ? "pos" : "neg");
458 dump_sigspec(f, cell->get("\\S"));
459 fprintf(f, " or %sedge ", pol_r == 'P' ? "pos" : "neg");
460 dump_sigspec(f, cell->get("\\R"));
461 fprintf(f, ")\n");
462
463 fprintf(f, "%s" " if (%s", indent.c_str(), pol_r == 'P' ? "" : "!");
464 dump_sigspec(f, cell->get("\\R"));
465 fprintf(f, ")\n");
466 fprintf(f, "%s" " %s <= 0;\n", indent.c_str(), reg_name.c_str());
467
468 fprintf(f, "%s" " else if (%s", indent.c_str(), pol_s == 'P' ? "" : "!");
469 dump_sigspec(f, cell->get("\\S"));
470 fprintf(f, ")\n");
471 fprintf(f, "%s" " %s <= 1;\n", indent.c_str(), reg_name.c_str());
472
473 fprintf(f, "%s" " else\n", indent.c_str());
474 fprintf(f, "%s" " %s <= ", indent.c_str(), reg_name.c_str());
475 dump_cell_expr_port(f, cell, "D", false);
476 fprintf(f, ";\n");
477
478 if (!out_is_reg_wire) {
479 fprintf(f, "%s" "assign ", indent.c_str());
480 dump_sigspec(f, cell->get("\\Q"));
481 fprintf(f, " = %s;\n", reg_name.c_str());
482 }
483
484 return true;
485 }
486
487 #define HANDLE_UNIOP(_type, _operator) \
488 if (cell->type ==_type) { dump_cell_expr_uniop(f, indent, cell, _operator); return true; }
489 #define HANDLE_BINOP(_type, _operator) \
490 if (cell->type ==_type) { dump_cell_expr_binop(f, indent, cell, _operator); return true; }
491
492 HANDLE_UNIOP("$not", "~")
493 HANDLE_UNIOP("$pos", "+")
494 HANDLE_UNIOP("$neg", "-")
495
496 HANDLE_BINOP("$and", "&")
497 HANDLE_BINOP("$or", "|")
498 HANDLE_BINOP("$xor", "^")
499 HANDLE_BINOP("$xnor", "~^")
500
501 HANDLE_UNIOP("$reduce_and", "&")
502 HANDLE_UNIOP("$reduce_or", "|")
503 HANDLE_UNIOP("$reduce_xor", "^")
504 HANDLE_UNIOP("$reduce_xnor", "~^")
505 HANDLE_UNIOP("$reduce_bool", "|")
506
507 HANDLE_BINOP("$shl", "<<")
508 HANDLE_BINOP("$shr", ">>")
509 HANDLE_BINOP("$sshl", "<<<")
510 HANDLE_BINOP("$sshr", ">>>")
511
512 HANDLE_BINOP("$lt", "<")
513 HANDLE_BINOP("$le", "<=")
514 HANDLE_BINOP("$eq", "==")
515 HANDLE_BINOP("$ne", "!=")
516 HANDLE_BINOP("$eqx", "===")
517 HANDLE_BINOP("$nex", "!==")
518 HANDLE_BINOP("$ge", ">=")
519 HANDLE_BINOP("$gt", ">")
520
521 HANDLE_BINOP("$add", "+")
522 HANDLE_BINOP("$sub", "-")
523 HANDLE_BINOP("$mul", "*")
524 HANDLE_BINOP("$div", "/")
525 HANDLE_BINOP("$mod", "%")
526 HANDLE_BINOP("$pow", "**")
527
528 HANDLE_UNIOP("$logic_not", "!")
529 HANDLE_BINOP("$logic_and", "&&")
530 HANDLE_BINOP("$logic_or", "||")
531
532 #undef HANDLE_UNIOP
533 #undef HANDLE_BINOP
534
535 if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$pmux_safe")
536 {
537 int width = cell->parameters["\\WIDTH"].as_int();
538 int s_width = cell->get("\\S").size();
539 std::string func_name = cellname(cell);
540
541 fprintf(f, "%s" "function [%d:0] %s;\n", indent.c_str(), width-1, func_name.c_str());
542 fprintf(f, "%s" " input [%d:0] a;\n", indent.c_str(), width-1);
543 fprintf(f, "%s" " input [%d:0] b;\n", indent.c_str(), s_width*width-1);
544 fprintf(f, "%s" " input [%d:0] s;\n", indent.c_str(), s_width-1);
545
546 dump_attributes(f, indent + " ", cell->attributes);
547 if (!noattr)
548 fprintf(f, "%s" " (* parallel_case *)\n", indent.c_str());
549 fprintf(f, "%s" " casez (s)", indent.c_str());
550 fprintf(f, noattr ? " // synopsys parallel_case\n" : "\n");
551
552 for (int i = 0; i < s_width; i++)
553 {
554 fprintf(f, "%s" " %d'b", indent.c_str(), s_width);
555
556 for (int j = s_width-1; j >= 0; j--)
557 fprintf(f, "%c", j == i ? '1' : cell->type == "$pmux_safe" ? '0' : '?');
558
559 fprintf(f, ":\n");
560 fprintf(f, "%s" " %s = b[%d:%d];\n", indent.c_str(), func_name.c_str(), (i+1)*width-1, i*width);
561 }
562
563 fprintf(f, "%s" " default:\n", indent.c_str());
564 fprintf(f, "%s" " %s = a;\n", indent.c_str(), func_name.c_str());
565
566 fprintf(f, "%s" " endcase\n", indent.c_str());
567 fprintf(f, "%s" "endfunction\n", indent.c_str());
568
569 fprintf(f, "%s" "assign ", indent.c_str());
570 dump_sigspec(f, cell->get("\\Y"));
571 fprintf(f, " = %s(", func_name.c_str());
572 dump_sigspec(f, cell->get("\\A"));
573 fprintf(f, ", ");
574 dump_sigspec(f, cell->get("\\B"));
575 fprintf(f, ", ");
576 dump_sigspec(f, cell->get("\\S"));
577 fprintf(f, ");\n");
578 return true;
579 }
580
581 if (cell->type == "$slice")
582 {
583 fprintf(f, "%s" "assign ", indent.c_str());
584 dump_sigspec(f, cell->get("\\Y"));
585 fprintf(f, " = ");
586 dump_sigspec(f, cell->get("\\A"));
587 fprintf(f, " >> %d;\n", cell->parameters.at("\\OFFSET").as_int());
588 return true;
589 }
590
591 if (cell->type == "$bu0")
592 {
593 fprintf(f, "%s" "assign ", indent.c_str());
594 dump_sigspec(f, cell->get("\\Y"));
595 if (cell->parameters["\\A_SIGNED"].as_bool()) {
596 fprintf(f, " = $signed(");
597 dump_sigspec(f, cell->get("\\A"));
598 fprintf(f, ");\n");
599 } else {
600 fprintf(f, " = { 1'b0, ");
601 dump_sigspec(f, cell->get("\\A"));
602 fprintf(f, " };\n");
603 }
604 return true;
605 }
606
607 if (cell->type == "$concat")
608 {
609 fprintf(f, "%s" "assign ", indent.c_str());
610 dump_sigspec(f, cell->get("\\Y"));
611 fprintf(f, " = { ");
612 dump_sigspec(f, cell->get("\\B"));
613 fprintf(f, " , ");
614 dump_sigspec(f, cell->get("\\A"));
615 fprintf(f, " };\n");
616 return true;
617 }
618
619 if (cell->type == "$dff" || cell->type == "$adff")
620 {
621 RTLIL::SigSpec sig_clk, sig_arst, val_arst;
622 bool pol_clk, pol_arst = false;
623
624 sig_clk = cell->get("\\CLK");
625 pol_clk = cell->parameters["\\CLK_POLARITY"].as_bool();
626
627 if (cell->type == "$adff") {
628 sig_arst = cell->get("\\ARST");
629 pol_arst = cell->parameters["\\ARST_POLARITY"].as_bool();
630 val_arst = RTLIL::SigSpec(cell->parameters["\\ARST_VALUE"]);
631 }
632
633 std::string reg_name = cellname(cell);
634 bool out_is_reg_wire = is_reg_wire(cell->get("\\Q"), reg_name);
635
636 if (!out_is_reg_wire)
637 fprintf(f, "%s" "reg [%d:0] %s;\n", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str());
638
639 fprintf(f, "%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg");
640 dump_sigspec(f, sig_clk);
641 if (cell->type == "$adff") {
642 fprintf(f, " or %sedge ", pol_arst ? "pos" : "neg");
643 dump_sigspec(f, sig_arst);
644 }
645 fprintf(f, ")\n");
646
647 if (cell->type == "$adff") {
648 fprintf(f, "%s" " if (%s", indent.c_str(), pol_arst ? "" : "!");
649 dump_sigspec(f, sig_arst);
650 fprintf(f, ")\n");
651 fprintf(f, "%s" " %s <= ", indent.c_str(), reg_name.c_str());
652 dump_sigspec(f, val_arst);
653 fprintf(f, ";\n");
654 fprintf(f, "%s" " else\n", indent.c_str());
655 }
656
657 fprintf(f, "%s" " %s <= ", indent.c_str(), reg_name.c_str());
658 dump_cell_expr_port(f, cell, "D", false);
659 fprintf(f, ";\n");
660
661 if (!out_is_reg_wire) {
662 fprintf(f, "%s" "assign ", indent.c_str());
663 dump_sigspec(f, cell->get("\\Q"));
664 fprintf(f, " = %s;\n", reg_name.c_str());
665 }
666
667 return true;
668 }
669
670 // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_
671 // FIXME: $sr, $dffsr, $dlatch, $memrd, $memwr, $mem, $fsm
672
673 return false;
674 }
675
676 void dump_cell(FILE *f, std::string indent, RTLIL::Cell *cell)
677 {
678 if (cell->type[0] == '$' && !noexpr) {
679 if (dump_cell_expr(f, indent, cell))
680 return;
681 }
682
683 dump_attributes(f, indent, cell->attributes);
684 fprintf(f, "%s" "%s", indent.c_str(), id(cell->type, false).c_str());
685
686 if (cell->parameters.size() > 0) {
687 fprintf(f, " #(");
688 for (auto it = cell->parameters.begin(); it != cell->parameters.end(); it++) {
689 if (it != cell->parameters.begin())
690 fprintf(f, ",");
691 fprintf(f, "\n%s .%s(", indent.c_str(), id(it->first).c_str());
692 bool is_signed = (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0;
693 dump_const(f, it->second, -1, 0, !is_signed, is_signed);
694 fprintf(f, ")");
695 }
696 fprintf(f, "\n%s" ")", indent.c_str());
697 }
698
699 std::string cell_name = cellname(cell);
700 if (cell_name != id(cell->name))
701 fprintf(f, " %s /* %s */ (", cell_name.c_str(), id(cell->name).c_str());
702 else
703 fprintf(f, " %s (", cell_name.c_str());
704
705 bool first_arg = true;
706 std::set<std::string> numbered_ports;
707 for (int i = 1; true; i++) {
708 char str[16];
709 snprintf(str, 16, "$%d", i);
710 for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) {
711 if (it->first != str)
712 continue;
713 if (!first_arg)
714 fprintf(f, ",");
715 first_arg = false;
716 fprintf(f, "\n%s ", indent.c_str());
717 dump_sigspec(f, it->second);
718 numbered_ports.insert(it->first);
719 goto found_numbered_port;
720 }
721 break;
722 found_numbered_port:;
723 }
724 for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) {
725 if (numbered_ports.count(it->first))
726 continue;
727 if (!first_arg)
728 fprintf(f, ",");
729 first_arg = false;
730 fprintf(f, "\n%s .%s(", indent.c_str(), id(it->first).c_str());
731 if (it->second.size() > 0)
732 dump_sigspec(f, it->second);
733 fprintf(f, ")");
734 }
735 fprintf(f, "\n%s" ");\n", indent.c_str());
736 }
737
738 void dump_conn(FILE *f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
739 {
740 fprintf(f, "%s" "assign ", indent.c_str());
741 dump_sigspec(f, left);
742 fprintf(f, " = ");
743 dump_sigspec(f, right);
744 fprintf(f, ";\n");
745 }
746
747 void dump_proc_switch(FILE *f, std::string indent, RTLIL::SwitchRule *sw);
748
749 void dump_case_body(FILE *f, std::string indent, RTLIL::CaseRule *cs, bool omit_trailing_begin = false)
750 {
751 int number_of_stmts = cs->switches.size() + cs->actions.size();
752
753 if (!omit_trailing_begin && number_of_stmts >= 2)
754 fprintf(f, "%s" "begin\n", indent.c_str());
755
756 for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) {
757 if (it->first.size() == 0)
758 continue;
759 fprintf(f, "%s ", indent.c_str());
760 dump_sigspec(f, it->first);
761 fprintf(f, " = ");
762 dump_sigspec(f, it->second);
763 fprintf(f, ";\n");
764 }
765
766 for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
767 dump_proc_switch(f, indent + " ", *it);
768
769 if (!omit_trailing_begin && number_of_stmts == 0)
770 fprintf(f, "%s /* empty */;\n", indent.c_str());
771
772 if (omit_trailing_begin || number_of_stmts >= 2)
773 fprintf(f, "%s" "end\n", indent.c_str());
774 }
775
776 void dump_proc_switch(FILE *f, std::string indent, RTLIL::SwitchRule *sw)
777 {
778 if (sw->signal.size() == 0) {
779 fprintf(f, "%s" "begin\n", indent.c_str());
780 for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) {
781 if ((*it)->compare.size() == 0)
782 dump_case_body(f, indent + " ", *it);
783 }
784 fprintf(f, "%s" "end\n", indent.c_str());
785 return;
786 }
787
788 fprintf(f, "%s" "casez (", indent.c_str());
789 dump_sigspec(f, sw->signal);
790 fprintf(f, ")\n");
791
792 for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) {
793 fprintf(f, "%s ", indent.c_str());
794 if ((*it)->compare.size() == 0)
795 fprintf(f, "default");
796 else {
797 for (size_t i = 0; i < (*it)->compare.size(); i++) {
798 if (i > 0)
799 fprintf(f, ", ");
800 dump_sigspec(f, (*it)->compare[i]);
801 }
802 }
803 fprintf(f, ":\n");
804 dump_case_body(f, indent + " ", *it);
805 }
806
807 fprintf(f, "%s" "endcase\n", indent.c_str());
808 }
809
810 void case_body_find_regs(RTLIL::CaseRule *cs)
811 {
812 for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
813 for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
814 case_body_find_regs(*it2);
815
816 for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) {
817 for (auto &c : it->first.chunks())
818 if (c.wire != NULL)
819 reg_wires.insert(c.wire->name);
820 }
821 }
822
823 void dump_process(FILE *f, std::string indent, RTLIL::Process *proc, bool find_regs = false)
824 {
825 if (find_regs) {
826 case_body_find_regs(&proc->root_case);
827 for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++)
828 for (auto it2 = (*it)->actions.begin(); it2 != (*it)->actions.end(); it2++) {
829 for (auto &c : it2->first.chunks())
830 if (c.wire != NULL)
831 reg_wires.insert(c.wire->name);
832 }
833 return;
834 }
835
836 fprintf(f, "%s" "always @* begin\n", indent.c_str());
837 dump_case_body(f, indent, &proc->root_case, true);
838
839 std::string backup_indent = indent;
840
841 for (size_t i = 0; i < proc->syncs.size(); i++)
842 {
843 RTLIL::SyncRule *sync = proc->syncs[i];
844 indent = backup_indent;
845
846 if (sync->type == RTLIL::STa) {
847 fprintf(f, "%s" "always @* begin\n", indent.c_str());
848 } else {
849 fprintf(f, "%s" "always @(", indent.c_str());
850 if (sync->type == RTLIL::STp || sync->type == RTLIL::ST1)
851 fprintf(f, "posedge ");
852 if (sync->type == RTLIL::STn || sync->type == RTLIL::ST0)
853 fprintf(f, "negedge ");
854 dump_sigspec(f, sync->signal);
855 fprintf(f, ") begin\n");
856 }
857 std::string ends = indent + "end\n";
858 indent += " ";
859
860 if (sync->type == RTLIL::ST0 || sync->type == RTLIL::ST1) {
861 fprintf(f, "%s" "if (%s", indent.c_str(), sync->type == RTLIL::ST0 ? "!" : "");
862 dump_sigspec(f, sync->signal);
863 fprintf(f, ") begin\n");
864 ends = indent + "end\n" + ends;
865 indent += " ";
866 }
867
868 if (sync->type == RTLIL::STp || sync->type == RTLIL::STn) {
869 for (size_t j = 0; j < proc->syncs.size(); j++) {
870 RTLIL::SyncRule *sync2 = proc->syncs[j];
871 if (sync2->type == RTLIL::ST0 || sync2->type == RTLIL::ST1) {
872 fprintf(f, "%s" "if (%s", indent.c_str(), sync2->type == RTLIL::ST1 ? "!" : "");
873 dump_sigspec(f, sync2->signal);
874 fprintf(f, ") begin\n");
875 ends = indent + "end\n" + ends;
876 indent += " ";
877 }
878 }
879 }
880
881 for (auto it = sync->actions.begin(); it != sync->actions.end(); it++) {
882 if (it->first.size() == 0)
883 continue;
884 fprintf(f, "%s ", indent.c_str());
885 dump_sigspec(f, it->first);
886 fprintf(f, " <= ");
887 dump_sigspec(f, it->second);
888 fprintf(f, ";\n");
889 }
890
891 fprintf(f, "%s", ends.c_str());
892 }
893 }
894
895 void dump_module(FILE *f, std::string indent, RTLIL::Module *module)
896 {
897 reg_wires.clear();
898 reset_auto_counter(module);
899 active_module = module;
900
901 fprintf(f, "\n");
902 for (auto it = module->processes.begin(); it != module->processes.end(); it++)
903 dump_process(f, indent + " ", it->second, true);
904
905 if (!noexpr)
906 {
907 std::set<std::pair<RTLIL::Wire*,int>> reg_bits;
908 for (auto &it : module->cells_)
909 {
910 RTLIL::Cell *cell = it.second;
911 if (!reg_ct.cell_known(cell->type) || !cell->has("\\Q"))
912 continue;
913
914 RTLIL::SigSpec sig = cell->get("\\Q");
915
916 if (sig.is_chunk()) {
917 RTLIL::SigChunk chunk = sig.as_chunk();
918 if (chunk.wire != NULL)
919 for (int i = 0; i < chunk.width; i++)
920 reg_bits.insert(std::pair<RTLIL::Wire*,int>(chunk.wire, chunk.offset+i));
921 }
922 }
923 for (auto &it : module->wires_)
924 {
925 RTLIL::Wire *wire = it.second;
926 for (int i = 0; i < wire->width; i++)
927 if (reg_bits.count(std::pair<RTLIL::Wire*,int>(wire, i)) == 0)
928 goto this_wire_aint_reg;
929 reg_wires.insert(wire->name);
930 this_wire_aint_reg:;
931 }
932 }
933
934 dump_attributes(f, indent, module->attributes);
935 fprintf(f, "%s" "module %s(", indent.c_str(), id(module->name, false).c_str());
936 bool keep_running = true;
937 for (int port_id = 1; keep_running; port_id++) {
938 keep_running = false;
939 for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) {
940 RTLIL::Wire *wire = it->second;
941 if (wire->port_id == port_id) {
942 if (port_id != 1)
943 fprintf(f, ", ");
944 fprintf(f, "%s", id(wire->name).c_str());
945 keep_running = true;
946 continue;
947 }
948 }
949 }
950 fprintf(f, ");\n");
951
952 for (auto it = module->wires_.begin(); it != module->wires_.end(); it++)
953 dump_wire(f, indent + " ", it->second);
954
955 for (auto it = module->memories.begin(); it != module->memories.end(); it++)
956 dump_memory(f, indent + " ", it->second);
957
958 for (auto it = module->cells_.begin(); it != module->cells_.end(); it++)
959 dump_cell(f, indent + " ", it->second);
960
961 for (auto it = module->processes.begin(); it != module->processes.end(); it++)
962 dump_process(f, indent + " ", it->second);
963
964 for (auto it = module->connections().begin(); it != module->connections().end(); it++)
965 dump_conn(f, indent + " ", it->first, it->second);
966
967 fprintf(f, "%s" "endmodule\n", indent.c_str());
968 active_module = NULL;
969 }
970
971 } /* namespace */
972
973 struct VerilogBackend : public Backend {
974 VerilogBackend() : Backend("verilog", "write design to verilog file") { }
975 virtual void help()
976 {
977 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
978 log("\n");
979 log(" write_verilog [options] [filename]\n");
980 log("\n");
981 log("Write the current design to a verilog file.\n");
982 log("\n");
983 log(" -norename\n");
984 log(" without this option all internal object names (the ones with a dollar\n");
985 log(" instead of a backslash prefix) are changed to short names in the\n");
986 log(" format '_<number>_'.\n");
987 log("\n");
988 log(" -noattr\n");
989 log(" with this option no attributes are included in the output\n");
990 log("\n");
991 log(" -attr2comment\n");
992 log(" with this option attributes are included as comments in the output\n");
993 log("\n");
994 log(" -noexpr\n");
995 log(" without this option all internal cells are converted to verilog\n");
996 log(" expressions.\n");
997 log("\n");
998 log(" -blackboxes\n");
999 log(" usually modules with the 'blackbox' attribute are ignored. with\n");
1000 log(" this option set only the modules with the 'blackbox' attribute\n");
1001 log(" are written to the output file.\n");
1002 log("\n");
1003 log(" -selected\n");
1004 log(" only write selected modules. modules must be selected entirely or\n");
1005 log(" not at all.\n");
1006 log("\n");
1007 }
1008 virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
1009 {
1010 log_header("Executing Verilog backend.\n");
1011
1012 norename = false;
1013 noattr = false;
1014 attr2comment = false;
1015 noexpr = false;
1016
1017 bool blackboxes = false;
1018 bool selected = false;
1019
1020 reg_ct.clear();
1021 reg_ct.setup_stdcells_mem();
1022 reg_ct.cell_types.insert("$sr");
1023 reg_ct.cell_types.insert("$dff");
1024 reg_ct.cell_types.insert("$adff");
1025
1026 size_t argidx;
1027 for (argidx = 1; argidx < args.size(); argidx++) {
1028 std::string arg = args[argidx];
1029 if (arg == "-norename") {
1030 norename = true;
1031 continue;
1032 }
1033 if (arg == "-noattr") {
1034 noattr = true;
1035 continue;
1036 }
1037 if (arg == "-attr2comment") {
1038 attr2comment = true;
1039 continue;
1040 }
1041 if (arg == "-noexpr") {
1042 noexpr = true;
1043 continue;
1044 }
1045 if (arg == "-blackboxes") {
1046 blackboxes = true;
1047 continue;
1048 }
1049 if (arg == "-selected") {
1050 selected = true;
1051 continue;
1052 }
1053 break;
1054 }
1055 extra_args(f, filename, args, argidx);
1056
1057 fprintf(f, "/* Generated by %s */\n", yosys_version_str);
1058 for (auto it = design->modules.begin(); it != design->modules.end(); it++) {
1059 if (it->second->get_bool_attribute("\\blackbox") != blackboxes)
1060 continue;
1061 if (selected && !design->selected_whole_module(it->first)) {
1062 if (design->selected_module(it->first))
1063 log_cmd_error("Can't handle partially selected module %s!\n", RTLIL::id2cstr(it->first));
1064 continue;
1065 }
1066 log("Dumping module `%s'.\n", it->first.c_str());
1067 dump_module(f, "", it->second);
1068 }
1069
1070 reg_ct.clear();
1071 }
1072 } VerilogBackend;
1073