2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 * A simple and straightforward verilog backend.
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).
29 #include "verilog_backend.h"
30 #include "kernel/register.h"
31 #include "kernel/celltypes.h"
32 #include "kernel/log.h"
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
;
45 std::set
<std::string
> reg_wires
;
48 RTLIL::Module
*active_module
;
50 void reset_auto_counter_id(const std::string
&id
, bool may_rename
)
52 const char *str
= id
.c_str();
54 if (*str
== '$' && may_rename
&& !norename
)
55 auto_name_map
[id
] = auto_name_counter
++;
57 if (str
[0] != '_' && str
[1] != 0)
59 for (int i
= 0; str
[i
] != 0; i
++) {
62 if (str
[i
] < '0' || str
[i
] > '9')
66 int num
= atoi(str
+1);
67 if (num
>= auto_name_offset
)
68 auto_name_offset
= num
+ 1;
71 void reset_auto_counter(RTLIL::Module
*module
)
73 auto_name_map
.clear();
74 auto_name_counter
= 0;
77 reset_auto_counter_id(module
->name
, false);
79 for (auto it
= module
->wires_
.begin(); it
!= module
->wires_
.end(); it
++)
80 reset_auto_counter_id(it
->second
->name
, true);
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);
87 for (auto it
= module
->processes
.begin(); it
!= module
->processes
.end(); it
++)
88 reset_auto_counter_id(it
->second
->name
, false);
91 for (size_t i
= 10; i
< auto_name_offset
+ auto_name_map
.size(); i
= i
*10)
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
);
98 std::string
id(std::string internal_id
, bool may_rename
= true)
100 const char *str
= internal_id
.c_str();
101 bool do_escape
= false;
103 if (may_rename
&& auto_name_map
.count(internal_id
) != 0) {
105 snprintf(buffer
, 100, "_%0*d_", auto_name_digits
, auto_name_offset
+ auto_name_map
[internal_id
]);
106 return std::string(buffer
);
112 if ('0' <= *str
&& *str
<= '9')
115 for (int i
= 0; str
[i
]; i
++)
117 if ('0' <= str
[i
] && str
[i
] <= '9')
119 if ('a' <= str
[i
] && str
[i
] <= 'z')
121 if ('A' <= str
[i
] && str
[i
] <= 'Z')
130 return "\\" + std::string(str
) + " ";
131 return std::string(str
);
134 bool is_reg_wire(RTLIL::SigSpec sig
, std::string
®_name
)
136 if (!sig
.is_chunk() || sig
.as_chunk().wire
== NULL
)
139 RTLIL::SigChunk chunk
= sig
.as_chunk();
141 if (reg_wires
.count(chunk
.wire
->name
) == 0)
144 reg_name
= id(chunk
.wire
->name
);
145 if (sig
.size() != chunk
.wire
->width
) {
147 reg_name
+= stringf("[%d]", chunk
.wire
->start_offset
+ chunk
.offset
);
149 reg_name
+= stringf("[%d:%d]", chunk
.wire
->start_offset
+ chunk
.offset
+ chunk
.width
- 1,
150 chunk
.wire
->start_offset
+ chunk
.offset
);
156 void dump_const(FILE *f
, const RTLIL::Const
&data
, int width
= -1, int offset
= 0, bool no_decimal
= false, bool set_signed
= false)
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
) {
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
)
167 if (data
.bits
[i
] == RTLIL::S1
)
168 val
|= 1 << (i
- offset
);
170 // fprintf(f, "%s32'sd%u", val < 0 ? "-" : "", abs(val));
171 fprintf(f
, "%d", val
);
174 fprintf(f
, "%d'%sb", width
, set_signed
? "s" : "");
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.");
191 std::string str
= data
.decode_string();
192 for (size_t i
= 0; i
< str
.size(); i
++) {
195 else if (str
[i
] == '\t')
197 else if (str
[i
] < 32)
198 fprintf(f
, "\\%03o", str
[i
]);
199 else if (str
[i
] == '"')
201 else if (str
[i
] == '\\')
210 void dump_sigchunk(FILE *f
, const RTLIL::SigChunk
&chunk
, bool no_decimal
= false)
212 if (chunk
.wire
== NULL
) {
213 dump_const(f
, chunk
.data
, chunk
.width
, chunk
.offset
, no_decimal
);
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
);
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
);
226 void dump_sigspec(FILE *f
, const RTLIL::SigSpec
&sig
)
228 if (sig
.is_chunk()) {
229 dump_sigchunk(f
, sig
.as_chunk());
232 for (auto it
= sig
.chunks().rbegin(); it
!= sig
.chunks().rend(); it
++) {
233 if (it
!= sig
.chunks().rbegin())
235 dump_sigchunk(f
, *it
, true);
241 void dump_attributes(FILE *f
, std::string indent
, std::map
<RTLIL::IdString
, RTLIL::Const
> &attributes
, char term
= '\n')
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());
248 dump_const(f
, it
->second
);
249 fprintf(f
, " %s%c", attr2comment
? "*/" : "*)", term
);
253 void dump_wire(FILE *f
, std::string indent
, RTLIL::Wire
*wire
)
255 dump_attributes(f
, indent
, wire
->attributes
);
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 " : "");
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());
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());
286 void dump_memory(FILE *f
, std::string indent
, RTLIL::Memory
*memory
)
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);
292 void dump_cell_expr_port(FILE *f
, RTLIL::Cell
*cell
, std::string port
, bool gen_signed
= true)
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
));
299 dump_sigspec(f
, cell
->get("\\" + port
));
302 std::string
cellname(RTLIL::Cell
*cell
)
304 if (!norename
&& cell
->name
[0] == '$' && reg_ct
.cell_known(cell
->type
) && cell
->has("\\Q"))
306 RTLIL::SigSpec sig
= cell
->get("\\Q");
307 if (SIZE(sig
) != 1 || sig
.is_fully_const())
308 goto no_special_reg_name
;
310 RTLIL::Wire
*wire
= sig
[0].wire
;
312 if (wire
->name
[0] != '\\')
313 goto no_special_reg_name
;
315 std::string cell_name
= wire
->name
;
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
);
321 cell_name
= cell_name
+ "_reg";
323 if (wire
->width
!= 1)
324 cell_name
+= stringf("[%d]", wire
->start_offset
+ sig
[0].offset
);
326 if (active_module
&& active_module
->count_id(cell_name
) > 0)
327 goto no_special_reg_name
;
329 return id(cell_name
);
334 return id(cell
->name
).c_str();
338 void dump_cell_expr_uniop(FILE *f
, std::string indent
, RTLIL::Cell
*cell
, std::string op
)
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);
348 void dump_cell_expr_binop(FILE *f
, std::string indent
, RTLIL::Cell
*cell
, std::string op
)
350 fprintf(f
, "%s" "assign ", indent
.c_str());
351 dump_sigspec(f
, cell
->get("\\Y"));
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);
360 bool dump_cell_expr(FILE *f
, std::string indent
, RTLIL::Cell
*cell
)
362 if (cell
->type
== "$_INV_") {
363 fprintf(f
, "%s" "assign ", indent
.c_str());
364 dump_sigspec(f
, cell
->get("\\Y"));
367 dump_attributes(f
, "", cell
->attributes
, ' ');
368 dump_cell_expr_port(f
, cell
, "A", false);
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"));
377 dump_cell_expr_port(f
, cell
, "A", false);
379 if (cell
->type
== "$_AND_")
381 if (cell
->type
== "$_OR_")
383 if (cell
->type
== "$_XOR_")
385 dump_attributes(f
, "", cell
->attributes
, ' ');
387 dump_cell_expr_port(f
, cell
, "B", false);
392 if (cell
->type
== "$_MUX_") {
393 fprintf(f
, "%s" "assign ", indent
.c_str());
394 dump_sigspec(f
, cell
->get("\\Y"));
396 dump_cell_expr_port(f
, cell
, "S", false);
398 dump_attributes(f
, "", cell
->attributes
, ' ');
399 dump_cell_expr_port(f
, cell
, "B", false);
401 dump_cell_expr_port(f
, cell
, "A", false);
406 if (cell
->type
.substr(0, 6) == "$_DFF_")
408 std::string reg_name
= cellname(cell
);
409 bool out_is_reg_wire
= is_reg_wire(cell
->get("\\Q"), reg_name
);
411 if (!out_is_reg_wire
)
412 fprintf(f
, "%s" "reg %s;\n", indent
.c_str(), reg_name
.c_str());
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"));
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"));
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());
431 fprintf(f
, "%s" " %s <= ", indent
.c_str(), reg_name
.c_str());
432 dump_cell_expr_port(f
, cell
, "D", false);
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());
444 if (cell
->type
.substr(0, 8) == "$_DFFSR_")
446 char pol_c
= cell
->type
[8], pol_s
= cell
->type
[9], pol_r
= cell
->type
[10];
448 std::string reg_name
= cellname(cell
);
449 bool out_is_reg_wire
= is_reg_wire(cell
->get("\\Q"), reg_name
);
451 if (!out_is_reg_wire
)
452 fprintf(f
, "%s" "reg %s;\n", indent
.c_str(), reg_name
.c_str());
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"));
463 fprintf(f
, "%s" " if (%s", indent
.c_str(), pol_r
== 'P' ? "" : "!");
464 dump_sigspec(f
, cell
->get("\\R"));
466 fprintf(f
, "%s" " %s <= 0;\n", indent
.c_str(), reg_name
.c_str());
468 fprintf(f
, "%s" " else if (%s", indent
.c_str(), pol_s
== 'P' ? "" : "!");
469 dump_sigspec(f
, cell
->get("\\S"));
471 fprintf(f
, "%s" " %s <= 1;\n", indent
.c_str(), reg_name
.c_str());
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);
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());
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; }
492 HANDLE_UNIOP("$not", "~")
493 HANDLE_UNIOP("$pos", "+")
494 HANDLE_UNIOP("$neg", "-")
496 HANDLE_BINOP("$and", "&")
497 HANDLE_BINOP("$or", "|")
498 HANDLE_BINOP("$xor", "^")
499 HANDLE_BINOP("$xnor", "~^")
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", "|")
507 HANDLE_BINOP("$shl", "<<")
508 HANDLE_BINOP("$shr", ">>")
509 HANDLE_BINOP("$sshl", "<<<")
510 HANDLE_BINOP("$sshr", ">>>")
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", ">")
521 HANDLE_BINOP("$add", "+")
522 HANDLE_BINOP("$sub", "-")
523 HANDLE_BINOP("$mul", "*")
524 HANDLE_BINOP("$div", "/")
525 HANDLE_BINOP("$mod", "%")
526 HANDLE_BINOP("$pow", "**")
528 HANDLE_UNIOP("$logic_not", "!")
529 HANDLE_BINOP("$logic_and", "&&")
530 HANDLE_BINOP("$logic_or", "||")
535 if (cell
->type
== "$mux" || cell
->type
== "$pmux" || cell
->type
== "$pmux_safe")
537 int width
= cell
->parameters
["\\WIDTH"].as_int();
538 int s_width
= cell
->get("\\S").size();
539 std::string func_name
= cellname(cell
);
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);
546 dump_attributes(f
, indent
+ " ", cell
->attributes
);
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");
552 for (int i
= 0; i
< s_width
; i
++)
554 fprintf(f
, "%s" " %d'b", indent
.c_str(), s_width
);
556 for (int j
= s_width
-1; j
>= 0; j
--)
557 fprintf(f
, "%c", j
== i
? '1' : cell
->type
== "$pmux_safe" ? '0' : '?');
560 fprintf(f
, "%s" " %s = b[%d:%d];\n", indent
.c_str(), func_name
.c_str(), (i
+1)*width
-1, i
*width
);
563 fprintf(f
, "%s" " default:\n", indent
.c_str());
564 fprintf(f
, "%s" " %s = a;\n", indent
.c_str(), func_name
.c_str());
566 fprintf(f
, "%s" " endcase\n", indent
.c_str());
567 fprintf(f
, "%s" "endfunction\n", indent
.c_str());
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"));
574 dump_sigspec(f
, cell
->get("\\B"));
576 dump_sigspec(f
, cell
->get("\\S"));
581 if (cell
->type
== "$slice")
583 fprintf(f
, "%s" "assign ", indent
.c_str());
584 dump_sigspec(f
, cell
->get("\\Y"));
586 dump_sigspec(f
, cell
->get("\\A"));
587 fprintf(f
, " >> %d;\n", cell
->parameters
.at("\\OFFSET").as_int());
591 if (cell
->type
== "$bu0")
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"));
600 fprintf(f
, " = { 1'b0, ");
601 dump_sigspec(f
, cell
->get("\\A"));
607 if (cell
->type
== "$concat")
609 fprintf(f
, "%s" "assign ", indent
.c_str());
610 dump_sigspec(f
, cell
->get("\\Y"));
612 dump_sigspec(f
, cell
->get("\\B"));
614 dump_sigspec(f
, cell
->get("\\A"));
619 if (cell
->type
== "$dff" || cell
->type
== "$adff")
621 RTLIL::SigSpec sig_clk
, sig_arst
, val_arst
;
622 bool pol_clk
, pol_arst
= false;
624 sig_clk
= cell
->get("\\CLK");
625 pol_clk
= cell
->parameters
["\\CLK_POLARITY"].as_bool();
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"]);
633 std::string reg_name
= cellname(cell
);
634 bool out_is_reg_wire
= is_reg_wire(cell
->get("\\Q"), reg_name
);
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());
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
);
647 if (cell
->type
== "$adff") {
648 fprintf(f
, "%s" " if (%s", indent
.c_str(), pol_arst
? "" : "!");
649 dump_sigspec(f
, sig_arst
);
651 fprintf(f
, "%s" " %s <= ", indent
.c_str(), reg_name
.c_str());
652 dump_sigspec(f
, val_arst
);
654 fprintf(f
, "%s" " else\n", indent
.c_str());
657 fprintf(f
, "%s" " %s <= ", indent
.c_str(), reg_name
.c_str());
658 dump_cell_expr_port(f
, cell
, "D", false);
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());
670 // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_
671 // FIXME: $sr, $dffsr, $dlatch, $memrd, $memwr, $mem, $fsm
676 void dump_cell(FILE *f
, std::string indent
, RTLIL::Cell
*cell
)
678 if (cell
->type
[0] == '$' && !noexpr
) {
679 if (dump_cell_expr(f
, indent
, cell
))
683 dump_attributes(f
, indent
, cell
->attributes
);
684 fprintf(f
, "%s" "%s", indent
.c_str(), id(cell
->type
, false).c_str());
686 if (cell
->parameters
.size() > 0) {
688 for (auto it
= cell
->parameters
.begin(); it
!= cell
->parameters
.end(); it
++) {
689 if (it
!= cell
->parameters
.begin())
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
);
696 fprintf(f
, "\n%s" ")", indent
.c_str());
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());
703 fprintf(f
, " %s (", cell_name
.c_str());
705 bool first_arg
= true;
706 std::set
<std::string
> numbered_ports
;
707 for (int i
= 1; true; i
++) {
709 snprintf(str
, 16, "$%d", i
);
710 for (auto it
= cell
->connections().begin(); it
!= cell
->connections().end(); it
++) {
711 if (it
->first
!= str
)
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
;
722 found_numbered_port
:;
724 for (auto it
= cell
->connections().begin(); it
!= cell
->connections().end(); it
++) {
725 if (numbered_ports
.count(it
->first
))
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
);
735 fprintf(f
, "\n%s" ");\n", indent
.c_str());
738 void dump_conn(FILE *f
, std::string indent
, const RTLIL::SigSpec
&left
, const RTLIL::SigSpec
&right
)
740 fprintf(f
, "%s" "assign ", indent
.c_str());
741 dump_sigspec(f
, left
);
743 dump_sigspec(f
, right
);
747 void dump_proc_switch(FILE *f
, std::string indent
, RTLIL::SwitchRule
*sw
);
749 void dump_case_body(FILE *f
, std::string indent
, RTLIL::CaseRule
*cs
, bool omit_trailing_begin
= false)
751 int number_of_stmts
= cs
->switches
.size() + cs
->actions
.size();
753 if (!omit_trailing_begin
&& number_of_stmts
>= 2)
754 fprintf(f
, "%s" "begin\n", indent
.c_str());
756 for (auto it
= cs
->actions
.begin(); it
!= cs
->actions
.end(); it
++) {
757 if (it
->first
.size() == 0)
759 fprintf(f
, "%s ", indent
.c_str());
760 dump_sigspec(f
, it
->first
);
762 dump_sigspec(f
, it
->second
);
766 for (auto it
= cs
->switches
.begin(); it
!= cs
->switches
.end(); it
++)
767 dump_proc_switch(f
, indent
+ " ", *it
);
769 if (!omit_trailing_begin
&& number_of_stmts
== 0)
770 fprintf(f
, "%s /* empty */;\n", indent
.c_str());
772 if (omit_trailing_begin
|| number_of_stmts
>= 2)
773 fprintf(f
, "%s" "end\n", indent
.c_str());
776 void dump_proc_switch(FILE *f
, std::string indent
, RTLIL::SwitchRule
*sw
)
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
);
784 fprintf(f
, "%s" "end\n", indent
.c_str());
788 fprintf(f
, "%s" "casez (", indent
.c_str());
789 dump_sigspec(f
, sw
->signal
);
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");
797 for (size_t i
= 0; i
< (*it
)->compare
.size(); i
++) {
800 dump_sigspec(f
, (*it
)->compare
[i
]);
804 dump_case_body(f
, indent
+ " ", *it
);
807 fprintf(f
, "%s" "endcase\n", indent
.c_str());
810 void case_body_find_regs(RTLIL::CaseRule
*cs
)
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
);
816 for (auto it
= cs
->actions
.begin(); it
!= cs
->actions
.end(); it
++) {
817 for (auto &c
: it
->first
.chunks())
819 reg_wires
.insert(c
.wire
->name
);
823 void dump_process(FILE *f
, std::string indent
, RTLIL::Process
*proc
, bool find_regs
= false)
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())
831 reg_wires
.insert(c
.wire
->name
);
836 fprintf(f
, "%s" "always @* begin\n", indent
.c_str());
837 dump_case_body(f
, indent
, &proc
->root_case
, true);
839 std::string backup_indent
= indent
;
841 for (size_t i
= 0; i
< proc
->syncs
.size(); i
++)
843 RTLIL::SyncRule
*sync
= proc
->syncs
[i
];
844 indent
= backup_indent
;
846 if (sync
->type
== RTLIL::STa
) {
847 fprintf(f
, "%s" "always @* begin\n", indent
.c_str());
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");
857 std::string ends
= indent
+ "end\n";
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
;
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
;
881 for (auto it
= sync
->actions
.begin(); it
!= sync
->actions
.end(); it
++) {
882 if (it
->first
.size() == 0)
884 fprintf(f
, "%s ", indent
.c_str());
885 dump_sigspec(f
, it
->first
);
887 dump_sigspec(f
, it
->second
);
891 fprintf(f
, "%s", ends
.c_str());
895 void dump_module(FILE *f
, std::string indent
, RTLIL::Module
*module
)
898 reset_auto_counter(module
);
899 active_module
= module
;
902 for (auto it
= module
->processes
.begin(); it
!= module
->processes
.end(); it
++)
903 dump_process(f
, indent
+ " ", it
->second
, true);
907 std::set
<std::pair
<RTLIL::Wire
*,int>> reg_bits
;
908 for (auto &it
: module
->cells_
)
910 RTLIL::Cell
*cell
= it
.second
;
911 if (!reg_ct
.cell_known(cell
->type
) || !cell
->has("\\Q"))
914 RTLIL::SigSpec sig
= cell
->get("\\Q");
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
));
923 for (auto &it
: module
->wires_
)
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
);
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
) {
944 fprintf(f
, "%s", id(wire
->name
).c_str());
952 for (auto it
= module
->wires_
.begin(); it
!= module
->wires_
.end(); it
++)
953 dump_wire(f
, indent
+ " ", it
->second
);
955 for (auto it
= module
->memories
.begin(); it
!= module
->memories
.end(); it
++)
956 dump_memory(f
, indent
+ " ", it
->second
);
958 for (auto it
= module
->cells_
.begin(); it
!= module
->cells_
.end(); it
++)
959 dump_cell(f
, indent
+ " ", it
->second
);
961 for (auto it
= module
->processes
.begin(); it
!= module
->processes
.end(); it
++)
962 dump_process(f
, indent
+ " ", it
->second
);
964 for (auto it
= module
->connections().begin(); it
!= module
->connections().end(); it
++)
965 dump_conn(f
, indent
+ " ", it
->first
, it
->second
);
967 fprintf(f
, "%s" "endmodule\n", indent
.c_str());
968 active_module
= NULL
;
973 struct VerilogBackend
: public Backend
{
974 VerilogBackend() : Backend("verilog", "write design to verilog file") { }
977 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
979 log(" write_verilog [options] [filename]\n");
981 log("Write the current design to a verilog file.\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");
989 log(" with this option no attributes are included in the output\n");
991 log(" -attr2comment\n");
992 log(" with this option attributes are included as comments in the output\n");
995 log(" without this option all internal cells are converted to verilog\n");
996 log(" expressions.\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");
1003 log(" -selected\n");
1004 log(" only write selected modules. modules must be selected entirely or\n");
1005 log(" not at all.\n");
1008 virtual void execute(FILE *&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
)
1010 log_header("Executing Verilog backend.\n");
1014 attr2comment
= false;
1017 bool blackboxes
= false;
1018 bool selected
= false;
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");
1027 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
1028 std::string arg
= args
[argidx
];
1029 if (arg
== "-norename") {
1033 if (arg
== "-noattr") {
1037 if (arg
== "-attr2comment") {
1038 attr2comment
= true;
1041 if (arg
== "-noexpr") {
1045 if (arg
== "-blackboxes") {
1049 if (arg
== "-selected") {
1055 extra_args(f
, filename
, args
, argidx
);
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
)
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
));
1066 log("Dumping module `%s'.\n", it
->first
.c_str());
1067 dump_module(f
, "", it
->second
);